diff --git a/AGENTS.md b/AGENTS.md index cea217a8..89301c65 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -221,6 +221,8 @@ | `handler: "nav"` | `handler: "navigate"` | | `handler: "setLocalState"` | `handler: "setState"` + `target: "local"` | | `navigate` + `replace: true` (URL만 변경 시) | `handler: "replaceUrl"` | +| `navigate` `params.path: "back"` (동작 키워드로 착각) | `handler: "navigateBack"` — path 는 주소로 해석되어 조용히 `/back` 으로 이동한다 | +| `navigate` `params.url` / `href` / `to` 로 목적지 전달 | `params.path` (또는 액션 `target`) — 엔진은 이 둘만 읽는다. 다른 이름은 무시되어 목적지가 `undefined` 가 되고, 예외도 404 도 없이 버튼만 동작하지 않는다 | | apiCall `params.target` (params 내부) | `target` 은 액션 top-level. params 내부 위치 시 URL 미해석 | | apiCall `params.onSuccess` / `params.onError` (params 내부) | 액션 top-level. params 내부면 무시됨 | | `refetchDataSource` `params.id` | `params.dataSourceId` 사용 | @@ -313,6 +315,30 @@ Icon 은 `` 글리프라 박스 크기가 곧 `font-size` 다. `w-N h-N` 은 정규식 location 은 프리픽스 location 보다 먼저 매칭되므로, 정적 최적화 블록(`location ~* \.(js|css|json)$`)이 있는 서버에서는 확장자 붙은 동적 응답이 `try_files ... /index.php` 폴백 기회 없이 404 가 된다. 서버측 `AssetUrl` 과 프론트측 `assetUrl.ts` 는 동일 규칙을 공유하므로 한쪽만 바꾸면 그 자산만 404 가 된다. 상세: [routing.md](docs/backend/routing.md) "정적 확장자로 끝나는 동적 엔드포인트", [api/README.md](docs/backend/api/README.md) "자산 URL 이중 모드". +### 목록 컨텍스트 왕복 (list context round-trip) + +페이지네이션 목록 화면과 그에 딸린 상세·형제 상세·작성/수정 폼·확인 모달은 하나의 목록 클러스터다. 이 클러스터 안에서의 이동은 URL 목록 상태(`page`/`search`/`category`/`filters[*]`/정렬/`per_page`)를 손실 없이 보존해야 한다. + +| 금지 | 올바른 사용 | +|------|------------| +| 클러스터 내 navigate 에 `mergeQuery` 누락 | `"params": { "path": "…", "mergeQuery": true, "query": {} }` | +| 이전글/다음글 등 형제 상세 이동만 규약에서 누락 | 목록 진입 / 목록 복귀 / 형제 이동 / 폼 취소 / 삭제 후 복귀 전 leg 동일 적용 | +| 현재 값을 그대로 다시 넘기는 키 열거 (`{"del": "{{query.del ?? ''}}"}`) | `mergeQuery` 가 이미 전부 나른다 — 열거는 중복이자 누락 위험 | +| 덮어쓸 키만 남기지 않고 필터 키 전부 재열거 | 값을 바꿔야 하는 키만 남긴다 (페이지 되돌림은 `{"page": ""}`) | +| 새로고침 버튼에 `mergeQuery: false` | 새로고침은 보던 목록을 다시 부르는 것 — 병합 유지 | +| `mergeQuery` 를 표현식으로 분기 (`"{{cond}}"`) | boolean 리터럴 고정 — 분기마다 보존 여부가 갈리면 한쪽이 조용히 상태를 떨군다 | +| `"path": "/board/{slug}/write?parent_id={{id}}"` (인라인 쿼리스트링) | 인라인 쿼리는 병합 시 버려진다 → `query` 객체로 옮긴다 | +| `mergeQuery: true` + `query` 키 생략 | 의도를 드러내도록 `"query": {}` 를 함께 둔다 | +| `"query": []` (배열 리터럴) | `"query": {}` — 동작은 같아 조용히 통과하지만, 나중에 덮어쓸 키를 넣으면 그 값이 버려진다 | +| 목적지가 표현식이라 판정 불가한 이동을 무표시로 둠 (`"{{_global.shopBase}}/products"`) | 클러스터 내 이동이면 `mergeQuery: true`, 밖으로 나가는 이동이면 예외 주석으로 의도를 명시 | +| 의도적 리셋(검색·필터 초기화 / 탭 전환 / 프리셋 적용)에 `mergeQuery: true` | 리셋은 병합하지 않는다 — 병합하면 초기화 버튼이 아무 일도 하지 않는다 | +| 탭 전환(`onTabChange`)이나 겹치지 않는 다른 목록으로의 이동에 `mergeQuery: true` | 목록 정체성이 다르면 승계하지 않는다 — 남의 검색어·페이지가 얹혀 빈 화면이 열린다 | +| 면제 주석은 "병합하지 않는다" 인데 코드는 `mergeQuery: true` | 주석과 코드를 일치시킨다 (주석은 사실이 아니라 선언일 뿐) | +| 검색 실행·페이지 이동 액션에서 `query` 키를 비움 | 값을 바꾸는 액션은 그 값을 직접 넘긴다 (`{"page": "{{$args[0]}}"}`) — 병합만으로는 새 값이 전달되지 않는다 | +| `path` 없이 `query` 만 바꾸는 액션에 `mergeQuery` 누락 (탭 전환 `{"tab": …}`, 항목 선택 `{"id": …, "mode": "view"}`) | `path` 생략은 "현재 주소에 작용" 이라 목록 화면 자신이 대상 — `mergeQuery: true` 없으면 지금 걸린 목록 상태가 통째로 날아간다 | + +의도적 리셋(검색 초기화 / 필터 초기화 / 탭 전환 / 프리셋 적용 / 다른 목록으로의 이동)은 예외다. 그 경우 액션 노드 `comment` 에 `audit:allow layout-list-context-navigate-merge-query <사유>` 를 남겨 의도를 코드에 기록한다. 상세: [actions-handlers-navigation.md "목록 컨텍스트 왕복 규약"](docs/frontend/actions-handlers-navigation.md) + ### 중첩 리소스 스코프 / 계층 무결성 | 금지 | 올바른 사용 | diff --git a/CHANGELOG.md b/CHANGELOG.md index 7760347c..4d8950ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ ### Fixed +- 목록 표의 각 칸에 넣은 날짜·숫자 서식이 적용되지 않아 값이 비어 보이던 문제를 수정했습니다. 같은 서식을 일반 화면에서 쓰면 정상이었지만 목록 표의 칸 안에서는 값이 사라지거나(날짜 서식) 서식이 빠진 원래 값이 그대로 나왔습니다(숫자·대문자 서식). 목록 표와 카드 목록, 펼침 영역 등 반복해서 그려지는 모든 자리에서 서식이 정상 적용됩니다. (#87 @glitter-gim 님께서 제보해주셨습니다.) +- 목록 화면에서 글이나 항목을 열어 보고 돌아올 때 보고 있던 페이지·검색어·필터가 사라지던 문제를 화면 엔진 차원에서 함께 수정했습니다. '현재 주소의 조건을 유지한다'고 지정해도 덧붙일 값이 없으면 유지가 아예 동작하지 않아 조건이 통째로 사라지던 동작을 바로잡았습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 데이터베이스 연결이 일시적으로 끊기거나 확장 설치가 중간에 실패한 직후 확장 목록을 다시 만들면, 설치된 모듈·플러그인 정보가 통째로 비워지면서 게시판·쇼핑몰 등 모든 확장 화면이 500 오류를 내던 문제를 수정했습니다. 이제 확장 폴더가 그대로 남아 있는데 목록만 비어 있으면 기존 정보를 지우지 않고 보존하며, 왜 갱신하지 않았는지 로그에 남깁니다. - 확장 목록이 손상된 상태에서 복구 명령을 실행하면 목록은 되살아나지만 확장 기능 연결이 비어 있는 채로 남아, 명령을 두 번 실행해야 완전히 복구되던 문제를 수정했습니다. 이제 한 번 실행으로 모두 복구됩니다. - 데이터베이스 계정 설정이 잘못되었을 때 아무 설명 없이 빈 화면만 뜨던 문제를 수정했습니다. 이전에는 최고 권한 계정을 쓰거나 사용자명이 비어 있으면 사이트 기능이 통째로 동작을 멈추면서도 화면에는 아무 안내가 없어 원인을 알 수 없었습니다. 이제 무엇이 잘못되었고 어떻게 고쳐야 하는지 설명하는 전용 안내 화면이 나타납니다. 서버 관리 명령은 평소대로 실행되므로 이 상태에서도 설정을 고칠 수 있습니다. diff --git a/docs/backend/activity-log.md b/docs/backend/activity-log.md index ad8207db..29368d9f 100644 --- a/docs/backend/activity-log.md +++ b/docs/backend/activity-log.md @@ -300,7 +300,7 @@ $this->logActivity('schedule.auto_run', [ 번들 일본어 언어팩(`lang-packs/_bundled/g7-core-ja/backend/ja/activity_log.php`)도 함께 동기화한다. ```text -audit 룰: activity-log-listener-i18n-coverage (코어/모듈/플러그인 ActivityLog 리스너 전 영역 자동 검출) +정적 검사: 코어/모듈/플러그인 ActivityLog 리스너 전 영역에서 키 누락 자동 검출 ``` --- diff --git a/docs/backend/api-documentation.md b/docs/backend/api-documentation.md index ca8f302d..bba14dc4 100644 --- a/docs/backend/api-documentation.md +++ b/docs/backend/api-documentation.md @@ -308,7 +308,7 @@ php artisan api:docgen --scope=core --dry-run 같은 원리로 `is_default` / `status=active` 같은 승격·활성 플래그를 샘플에 붙이지 않는다. 샘플 레코드를 만들기 전에 "이 조합이 전역 설정을 읽는 쿼리에 걸리는가" 를 확인한다. -자동 차단: audit 룰 `apidoc-sample-no-global-active-language-pack` (severity: error). +자동 차단: 정적 검사 대상 (위반 시 차단). ### 설명 백필 커맨드 (`api:docgen-backfill-*`) @@ -338,12 +338,12 @@ php artisan api:docgen-backfill-fields - 트리거: `app/Http/Controllers/**`, `routes/api.php`, `app/Http/Requests/**`, `app/Http/Resources/**` (+ 확장 대응 경로) 편집. - 절차: 코드 변경 → `api:docgen --scope=...` 재실행 → `@generated` 블록 갱신 → 신규 TODO 서술 채움. -- 검증: `api:docgen --check` 로 drift 0 확인. audit 룰 `api-doc-coverage` 가 변경셋에 대응 문서 - 동반 여부를 검사한다. severity 는 **대상별**로 부여된다 — 문서가 완비된 대상은 `error`(문서 - 미동반 변경 차단), 진행 중 대상은 `warn`. 코어(`docs/backend/api/`)는 2026-07-08 완료로 - `error` 승격됨. 즉 코어 API 표면(`routes/api.php`·`app/Http/{Controllers,Requests,Resources}/**`)을 - 변경하면서 코어 API 문서를 함께 갱신하지 않으면 세션 종료 시 차단된다. 나머지 확장은 문서 완비 - 시 순차 승격된다(룰의 `ENFORCED_TARGETS`). +- 검증: `api:docgen --check` 로 drift 0 확인. 정적 검사가 변경셋에 대응 문서 + 동반 여부를 검사한다. 강제 수준은 **대상별**로 다르다 — 문서가 완비된 대상은 차단, 진행 중 + 대상은 경고에 그친다. 코어(`docs/backend/api/`)는 2026-07-08 문서 완비로 차단 대상이 됐다. + 즉 코어 API 표면(`routes/api.php`·`app/Http/{Controllers,Requests,Resources}/**`)을 + 변경하면서 코어 API 문서를 함께 갱신하지 않으면 그 변경은 통과하지 못한다. 나머지 확장은 문서 + 완비 시 순차로 차단 대상에 편입된다. --- diff --git a/docs/backend/middleware.md b/docs/backend/middleware.md index 7226597e..90373c20 100644 --- a/docs/backend/middleware.md +++ b/docs/backend/middleware.md @@ -159,7 +159,7 @@ target 이 `/` 로 시작하면 **URI 패턴**(`$request->path()` 매칭), 아 | 확장 SP 에서 `aliasMiddleware()` 직접 호출 | `getMiddleware()` 선언 | | 확장 라우트 파일에서 자기 `Http\Middleware\` FQCN 을 `->middleware(Foo::class)` 로 부착 | `getMiddleware()` 선언 | -자동 차단: audit 룰 `extension-middleware-declarative-registration`, `extension-route-middleware-alias-reference`, `extension-middleware-gate-cache-coverage` (모두 error). 서드파티 확장의 구방식은 Laravel 공식 API 라 런타임 차단은 없고 문서로 안내한다. +자동 차단: 위 규율은 모두 정적 검사 대상 (위반 시 차단). 서드파티 확장의 구방식은 Laravel 공식 API 라 런타임 차단은 없고 문서로 안내한다. --- diff --git a/docs/backend/notification-system.md b/docs/backend/notification-system.md index 69c9d3e8..4c9b0b0f 100644 --- a/docs/backend/notification-system.md +++ b/docs/backend/notification-system.md @@ -379,7 +379,7 @@ public function getNotificationDefinitions(): array ### 금지 사항 -- 모듈/플러그인 측에 별도 `*NotificationDefinitionSeeder.php` 파일을 두면 안 됩니다. 동일 데이터를 두 곳에서 유지하면 SSoT 가 깨지며, audit 룰 `notification-seeder-orphan` 이 차단합니다. +- 모듈/플러그인 측에 별도 `*NotificationDefinitionSeeder.php` 파일을 두면 안 됩니다. 동일 데이터를 두 곳에서 유지하면 SSoT 가 깨지며, 정적 검사가 차단합니다. - 코어는 `database/seeders/NotificationDefinitionSeeder.php` 가 fresh install 진입점으로 유지되지만, 데이터 자체는 `config/core.php` 가 SSoT 입니다 (시더는 config 를 읽기만 함). --- diff --git a/docs/backend/routing.md b/docs/backend/routing.md index eeefee81..dfdcd0ff 100644 --- a/docs/backend/routing.md +++ b/docs/backend/routing.md @@ -141,7 +141,7 @@ URL 을 만드는 쪽도 문자열로 직접 조립하지 않는다. 서버는 ` `resources/js/core/support/assetUrl.ts` 를 경유해야 현재 모드에 맞는 형태가 나온다. 두 구현은 동일 규칙을 공유하므로 한쪽만 바꾸면 서버가 만든 URL 과 클라이언트가 만든 URL 이 어긋나 그 자산만 404 가 된다. -자동 차단: audit 룰 `dynamic-route-static-extension` (error). 면제는 인라인 주석 +자동 차단: 정적 검사 대상 (위반 시 차단). 면제는 인라인 주석 `// audit:allow dynamic-route-static-extension reason: ...`. 두 형태는 모두 영구 유지한다 — 확장자 형태를 제거하면 URL 을 하드코딩한 서드파티 확장이 깨진다. diff --git a/docs/backend/seo-system.md b/docs/backend/seo-system.md index 07d7b52a..a18c2ff3 100644 --- a/docs/backend/seo-system.md +++ b/docs/backend/seo-system.md @@ -535,7 +535,7 @@ $viewData = HookManager::applyFilters('core.seo.filter_view_data', $viewData, [ ### 도메인 스키마 ownership — seoOgDefaults / seoTwitterDefaults / seoStructuredData -모듈/플러그인은 `AbstractModule` / `AbstractPlugin` 의 다음 메서드를 오버라이드하여 자기 도메인의 OG/Twitter/JSON-LD 를 owned 한다. 레이아웃 JSON 직접 선언은 페이지별 override 가 꼭 필요할 때만 사용 (도메인 스키마는 모듈로 이전 — `seo-domain-schema-in-layout` audit 룰이 자동 차단). +모듈/플러그인은 `AbstractModule` / `AbstractPlugin` 의 다음 메서드를 오버라이드하여 자기 도메인의 OG/Twitter/JSON-LD 를 owned 한다. 레이아웃 JSON 직접 선언은 페이지별 override 가 꼭 필요할 때만 사용 (도메인 스키마는 모듈로 이전 — `seo-domain-schema-in-layout` 정적 검사가 자동 차단). ```php class EcommerceModule extends AbstractModule diff --git a/docs/backend/service-repository.md b/docs/backend/service-repository.md index 3fdb5587..8c862c64 100644 --- a/docs/backend/service-repository.md +++ b/docs/backend/service-repository.md @@ -1095,7 +1095,7 @@ public function findOrFail(string $slug, int $id, ?int $postId = null): Comment | --- | --- | | 방어 위치 | Repository where 절 (SSoT) + Service 가 상위 ID 를 전달 | | 파라미터 형태 | **선택 파라미터**(`?int $postId = null`) — 필수화는 Interface breaking 이라 이 확장에 의존하는 확장을 전부 흔든다 | -| 전달 누락 방지 | 컨트롤러가 라우트 파라미터를 실제로 소비하는지 audit 룰 `controller-unused-route-param` (warn) 이 감시 | +| 전달 누락 방지 | 컨트롤러가 라우트 파라미터를 실제로 소비하는지 정적 검사가 감시 (경고) | | 응답 코드 | 조회 실패이므로 404. 요청 본문 배열 항목의 스코프 위반은 422 (validation.md "배열 항목의 상위 스코프") | | 공통 추상화 | 도입하지 않는다 — 모듈마다 상위 키와 조회 경로가 다르고(`board_id`+`post_id` / `product_id` / `page_id` / `order_id`), 코어 표면이 늘면 확장 버전 제약 동기화가 연쇄된다 | diff --git a/docs/backend/settings-multilingual-enrichment.md b/docs/backend/settings-multilingual-enrichment.md index 5337a6fd..54a57be2 100644 --- a/docs/backend/settings-multilingual-enrichment.md +++ b/docs/backend/settings-multilingual-enrichment.md @@ -7,7 +7,7 @@ 2. helper: localize_catalog_field($field, $langKey) — 단일 함수 호출 3. 모듈/플러그인 Service 가 자기 빌드 메서드 안에서 직접 호출 4. lang key segment 는 settings JSON 의 식별자(id/code/key) 와 동일 -5. audit 룰 settings-multilingual-enrichment-coverage 가 호출 누락 검출 (warning) +5. 정적 검사가 호출 누락 검출 (경고) ``` ## 사용법 @@ -108,9 +108,9 @@ helper 동작: 운영자가 admin UI 에서 ja 라벨을 직접 입력했다면 보존. 입력 안한 locale 만 lang pack 으로 채움. -## audit 룰 +## 정적 검사 -`settings-multilingual-enrichment-coverage` (severity: warning): +경고 수준으로 다음을 검출한다: - `{modules|plugins}/_bundled/*/config/settings/defaults.json` 에 다국어 카탈로그 entry 발견 - 같은 확장의 `src/Services/*.php` 안에 `localize_catalog_field` 호출 없음 diff --git a/docs/backend/translatable-seeders.md b/docs/backend/translatable-seeders.md index d8b13b06..c655427d 100644 --- a/docs/backend/translatable-seeders.md +++ b/docs/backend/translatable-seeders.md @@ -6,7 +6,7 @@ 1. 다국어 JSON 컬럼(name 등)을 시드하는 확장 entity 시더는 TranslatableSeederInterface 구현 필수 2. App\Concerns\Seeder\HasTranslatableSeeder trait 사용 → resolveTranslatedDefaults() 가 활성 lang pack 머지 자동 처리 3. 시더는 getDefaults() 에 ko/en 만 정의, ja 등은 lang pack seed/{entity}.json 자동 빌드 (build-language-pack-ja.cjs) -4. audit 룰 seeder-translation-filter 가 누락 검출 (error severity) +4. 정적 검사가 누락 검출 (위반 시 차단) 5. 코어 시더(NotificationDefinitionSeeder 등)는 별도 LoadsConfigSeedWithLangPackFilter trait 패턴 (config 기반) ``` @@ -14,7 +14,7 @@ 활성 언어팩의 `seed/{entity}.json` 파일을 entity 시더가 머지하는 인프라가 7.0.0-beta.4 부터 정식화되었으나, 시더가 직접 `HookManager::applyFilters()` 를 호출하는 패턴이라 누락 시 회귀가 발생했다. (예: 7.0.0-beta.4 직전 `ShippingCarrierSeeder` 에서 ja 라벨 fallback 회귀) -7.0.0-beta.5 부터 `TranslatableSeederInterface` + `HasTranslatableSeeder` trait 로 컴파일 타임 / audit 단계에서 강제하도록 인프라화. +7.0.0-beta.5 부터 `TranslatableSeederInterface` + `HasTranslatableSeeder` trait 로 컴파일 타임 / 정적 검사 단계에서 강제하도록 인프라화. ## 인터페이스 @@ -82,9 +82,9 @@ class ShippingCarrierSeeder extends Seeder implements TranslatableSeederInterfac - `getMatchKey()` 가 반환하는 키 조합이 시드 항목의 식별자로 사용된다. - `getDefaults()` 가 ko 기준 다국어 필드를 반환한다. -## audit 룰 +## 정적 검사 -`seeder-translation-filter` (severity: error): +다음을 차단한다: - 코어 시더 (NotificationDefinitionSeeder/IdentityMessageDefinitionSeeder) — `applyFilters('seed.X.translations', ...)` 발화 필수 - ModuleManager/PluginManager — `sync*Definitions/*Messages` 본문에 `applyFilters` 발화 필수 - 확장 entity 시더 (`(modules|plugins)/_bundled//database/seeders/Seeder.php`) — 다국어 JSON 컬럼 시드 시 `TranslatableSeederInterface` 구현 + `HasTranslatableSeeder` trait 사용 필수 @@ -99,7 +99,7 @@ class ShippingCarrierSeeder extends Seeder implements TranslatableSeederInterfac - **확장 entity 시더** (BoardType/ShippingCarrier 등): 시더 자체가 데이터 SSoT → `TranslatableSeederInterface` + `HasTranslatableSeeder` - **코어 시더** (NotificationDefinition/IdentityMessageDefinition/Permission/Role/Menu): `config/core.php` 가 데이터 SSoT → 시더는 `LoadsConfigSeedWithLangPackFilter` trait 의 `loadConfigSeed(, )` 호출 -두 패턴 모두 `seed.{X}.translations` 필터를 발화하므로 audit 룰 통과는 동일. +두 패턴 모두 `seed.{X}.translations` 필터를 발화하므로 정적 검사 결과는 동일. ## 참고 diff --git a/docs/backend/validation.md b/docs/backend/validation.md index 6ab0beee..ac160315 100644 --- a/docs/backend/validation.md +++ b/docs/backend/validation.md @@ -533,7 +533,7 @@ class TestMailRequest extends FormRequest 'allowed_extensions' => ['exclude_if:use_file_upload,false', 'sometimes', 'required', 'array', 'min:1'], ``` -자동 차단: `formrequest-store-update-conditional-symmetry`(error), `formrequest-sometimes-array-min-inert`(warning). +자동 차단: 정적 검사 대상. store/update 사이의 조건부 검증 비대칭은 차단되고, `sometimes` + `array` + `min` 조합이 무효화되는 형태는 경고로 보고된다. --- @@ -1060,7 +1060,7 @@ Rule::exists("board_{$slug}_posts", 'id'), | Service 2차 방어 | 검증을 우회하는 경로(시더 / 훅 / 기존 오염 데이터)를 위해 재귀 함수에 방문 ID 가드를 둔다. 무한 루프 대신 유한 실패 + 로그 | | 코어 Rule 재사용 | `App\Rules\NotCircularParent` 는 `App\Models\Menu` 하드코딩이다. 다른 모델에는 모듈 로컬 Rule 을 신설한다 (코어 시그니처 변경 = 확장 버전 제약 연쇄) | -자동 차단: audit 룰 `parent-id-requires-cycle-rule` (error). +자동 차단: 정적 검사 대상 (위반 시 차단). --- @@ -1153,7 +1153,7 @@ FormRequest 책임). ### 자동 검증 -audit 룰 `formrequest-direct-data-access` 가 FormRequest 내 DB facade / Model +정적 검사가 FormRequest 내 DB facade / Model 정적 호출 / 영속 메서드(`save`/`saveQuietly`/`forceDelete`) 직접 호출을 자동 차단한다. `Rule::exists(Model::class, ...)` 같은 validation rule helper 는 면제. diff --git a/docs/database-guide.md b/docs/database-guide.md index f93d1e2e..92ae1124 100644 --- a/docs/database-guide.md +++ b/docs/database-guide.md @@ -190,7 +190,7 @@ public function up(): void #### `->change()` 패턴의 멱등성 -`->change()` 는 이미 존재하는 컬럼의 타입/제약 변경이므로 컬럼 부재 fatal 위험은 없다. 단, MariaDB/MySQL 의 일부 ALTER 가 비-멱등인 경우 (예: enum 값 추가 후 재실행) 가 있으므로 마이그레이션 작성자가 의도 검증 필요. audit rule `migration-idempotency-guard` 는 `->change()` 라인을 자동 제외하므로 false positive 미발생. +`->change()` 는 이미 존재하는 컬럼의 타입/제약 변경이므로 컬럼 부재 fatal 위험은 없다. 단, MariaDB/MySQL 의 일부 ALTER 가 비-멱등인 경우 (예: enum 값 추가 후 재실행) 가 있으므로 마이그레이션 작성자가 의도 검증 필요. 정적 검사는 `->change()` 라인을 자동 제외하므로 false positive 미발생. #### 검증 절차 diff --git a/docs/extension/cache-driver.md b/docs/extension/cache-driver.md index 361ebe71..9ef59c41 100644 --- a/docs/extension/cache-driver.md +++ b/docs/extension/cache-driver.md @@ -152,7 +152,7 @@ public function register(): void } ``` -audit 룰 `extension-no-global-cache-rebind` 가 자동 차단한다. 면제 표지 불허. +정적 검사가 자동 차단한다. 면제 표지 불허. ### 표준 패턴 — contextual binding diff --git a/docs/extension/changelog-rules.md b/docs/extension/changelog-rules.md index 8bf6fe68..1c48d9b1 100644 --- a/docs/extension/changelog-rules.md +++ b/docs/extension/changelog-rules.md @@ -292,10 +292,12 @@ setState(selectedX) → apiCall(changelog) ### 자동 검증 -- `host-lang-change-requires-changelog` (warn) — 변경셋에 호스트 lang 파일이 있는데 그 호스트 CHANGELOG 가 없으면 경고 -- `lang-duplicate-array-key` (error) — 같은 레벨 중복 키 차단. 뒤 선언이 앞을 덮어 앞 블록 전용 키가 런타임에 소실되고 원문 키가 노출되는 것을 막는다. 정정은 항상 **두 블록 병합** (한쪽만 삭제하면 그쪽 키가 사라진다) +정적 검사가 다음 두 가지를 본다. -언어팩 패키지(`lang-packs/_bundled/**`)는 별도 룰(`lang-pack-*`)이 담당하므로 본 절의 대상이 아니다. +- 변경셋에 호스트 lang 파일이 있는데 그 호스트 CHANGELOG 가 없으면 경고한다. +- 같은 레벨의 중복 배열 키는 차단한다. 뒤 선언이 앞을 덮어 앞 블록 전용 키가 런타임에 소실되고 원문 키가 노출되기 때문이다. 정정은 항상 **두 블록 병합** — 한쪽만 삭제하면 그쪽 키가 사라진다. + +언어팩 패키지(`lang-packs/_bundled/**`)는 별도 검사가 담당하므로 본 절의 대상이 아니다. --- diff --git a/docs/extension/editor-spec.md b/docs/extension/editor-spec.md index 1abeee75..aef85104 100644 --- a/docs/extension/editor-spec.md +++ b/docs/extension/editor-spec.md @@ -75,15 +75,15 @@ editor-spec.json 이 커지면(코어 admin 템플릿은 단일 파일 18,000줄 - `icon-picker` — 아이콘 prop(예 `iconName`/`triggerIcon`)을 카탈로그 그리드에서 검색·선택한다. **카탈로그는 템플릿 소유**(라이브러리 종속) — Font Awesome 등 아이콘셋을 쓰는 템플릿이 `G7Core.layoutEditor.registerWidget('icon-picker', ...)` 로 자기 위젯을 등록한다(코어는 위젯명만 디스패치, 아이콘 라이브러리 토큰 0). 프리뷰 폴백은 `preview.html`(코어 비해석) → `preview.className` → raw value 순. 카탈로그 미공급 시 자유 텍스트 입력으로 디그레이드. - `options-list` — `Select`/`RadioGroup` 등의 정적 `options` 배열(value/label 행)을 추가/삭제/이동 편집한다. 값이 `{{바인딩}}` 이면 "바인딩됨(코드 편집)" 디그레이드(덮어쓰기 차단). 데이터소스 바인딩(dataProps `options`)과 직교 공존(위 "선택지 직교 완화"). - `array-items` / `array-group` / `array-cell-tree` / `number-list` — 정적 배열 prop 편집(탭/차트 데이터/카드 컬럼 등). `nodeEditor` 슬롯 또는 propControl 로 결선한다(아래 "데이터 정의 빌트인" 참조). -- `i18n-text` vs `text` — **표시 텍스트**(사용자가 화면에서 읽는 라벨/메시지/플레이스홀더)는 `i18n-text` 를 쓴다. `i18n-text` 는 평문 입력 시 `createCustomKey` 로 다국어 키를 자동 생성해 `$t:custom.*` 로 치환하고(미리보기에 raw 키 미노출), 🌐 펼침으로 ko/en/ja 동시 편집을 제공하며, `{{바인딩}}` 값이면 읽기전용 디그레이드한다(공통 위젯 `I18nTextField`). **비-표시값**(URL/id/수치/색/통화코드/separator 등)만 `text` 를 쓴다. 표시 텍스트에 `text` 를 쓰면 raw `$t:` 노출·다국어 누락 회귀가 발생한다(audit `editor-array-label-field-i18n` 가 배열 라벨 필드의 `text` 사용을 차단). +- `i18n-text` vs `text` — **표시 텍스트**(사용자가 화면에서 읽는 라벨/메시지/플레이스홀더)는 `i18n-text` 를 쓴다. `i18n-text` 는 평문 입력 시 `createCustomKey` 로 다국어 키를 자동 생성해 `$t:custom.*` 로 치환하고(미리보기에 raw 키 미노출), 🌐 펼침으로 ko/en/ja 동시 편집을 제공하며, `{{바인딩}}` 값이면 읽기전용 디그레이드한다(공통 위젯 `I18nTextField`). **비-표시값**(URL/id/수치/색/통화코드/separator 등)만 `text` 를 쓴다. 표시 텍스트에 `text` 를 쓰면 raw `$t:` 노출·다국어 누락 회귀가 발생한다(정적 검사가 배열 라벨 필드의 `text` 사용을 차단). ### componentCapabilities — 컴포넌트별 편집 역량 컴포넌트별로 `propControls`(속성 탭 컨트롤 화이트리스트 — `controls.json` 의 `apply.type==="propValue"` 컨트롤 참조, 비-스타일 prop 편집) / `dataProps`(데이터 연결 선언 — 아래) / `styleControls`(스타일 탭 컨트롤 화이트리스트) / `advanced`(고급 속성) / `events`(액션 편집 이벤트 — 미선언 시 동작 탭 숨김) / `flexEditor`(`container`/`item`/`auto` — 정렬 박스 편집 역할) / `visibilityCondition`(표시조건 탭 허용 여부) / `nodeEditor`·`canvasOverlay`(구조 에디터 일반 슬롯 `{kind,params}` — 종류별 고정 키 금지, kind 핸들러 레지스트리 디스패치)을 선언한다. -**데이터 연결(`dataProps`)**: "데이터를 바라보는 prop"(컬렉션의 `data`/`items`/`options` 배열, 입력 `value`·텍스트 등 단일값)을 데이터소스/상태에 바인딩하는 선언이다. 각 항목은 `{propKey, shape:'scalar'|'array', label?, itemFields?, required?, sources?}`. [속성] 탭 최상단 "데이터 연결" 영역이 각 항목을 검색형 바인딩 행으로 렌더하고, 선택 시 `{{.}}` 가 `node.props[propKey]` 에 기입된다(런타임 동일). 데이터 prop 은 **항상 바인딩 모드**(정적↔바인딩 토글 없음). **구조/수치 prop**(열 수·간격·페이지크기·크기)·**enum 선택**(variant/position)·**boolean config**(required/disabled)는 dataProps 비대상 — `propControls` 정적 편집이다. `dataProps` 와 `propControls` 는 직교한다(한 prop 은 한쪽만). `shape: 'array'` 면 `itemFields`(항목 객체 주요 필드)를 권장한다(검색 피커 항목 미리보기). `shape: 'object'` 는 컴포넌트가 객체 1건을 통째로 바라보는 prop(예 ProductCard.product, Avatar.author)용이다. 후보 풀은 편집기 샘플 데이터(data_sources `sampleData` shape + `sampleGlobal`) 가 SSoT 다(런타임 응답 추측 금지). audit `editor-datapropspec-shape-valid` 가 스키마를 가드한다. +**데이터 연결(`dataProps`)**: "데이터를 바라보는 prop"(컬렉션의 `data`/`items`/`options` 배열, 입력 `value`·텍스트 등 단일값)을 데이터소스/상태에 바인딩하는 선언이다. 각 항목은 `{propKey, shape:'scalar'|'array', label?, itemFields?, required?, sources?}`. [속성] 탭 최상단 "데이터 연결" 영역이 각 항목을 검색형 바인딩 행으로 렌더하고, 선택 시 `{{.}}` 가 `node.props[propKey]` 에 기입된다(런타임 동일). 데이터 prop 은 **항상 바인딩 모드**(정적↔바인딩 토글 없음). **구조/수치 prop**(열 수·간격·페이지크기·크기)·**enum 선택**(variant/position)·**boolean config**(required/disabled)는 dataProps 비대상 — `propControls` 정적 편집이다. `dataProps` 와 `propControls` 는 직교한다(한 prop 은 한쪽만). `shape: 'array'` 면 `itemFields`(항목 객체 주요 필드)를 권장한다(검색 피커 항목 미리보기). `shape: 'object'` 는 컴포넌트가 객체 1건을 통째로 바라보는 prop(예 ProductCard.product, Avatar.author)용이다. 후보 풀은 편집기 샘플 데이터(data_sources `sampleData` shape + `sampleGlobal`) 가 SSoT 다(런타임 응답 추측 금지). 정적 검사가 스키마를 가드한다. -**선택지(options) 직교 완화**: 선택 컴포넌트(Select/RadioGroup/TagInput/SearchableDropdown 등)의 `options` 배열은 정적 목록 직접 편집(propControls `selectOptions` → `apply.propKey: "options"`)과 데이터소스 바인딩(dataProps `options` array)을 **둘 다** 노출한다 — 같은 `options` prop 에 정적·동적 두 입력을 모두 제공한다(부록6 "한 prop 은 한쪽만" 규칙의 명시적 완화). audit 룰의 propControls 비교는 controlKey 문자열 기준이라 `selectOptions`(controlKey) ≠ `options`(dataProps propKey)로 자동 통과한다. +**선택지(options) 직교 완화**: 선택 컴포넌트(Select/RadioGroup/TagInput/SearchableDropdown 등)의 `options` 배열은 정적 목록 직접 편집(propControls `selectOptions` → `apply.propKey: "options"`)과 데이터소스 바인딩(dataProps `options` array)을 **둘 다** 노출한다 — 같은 `options` prop 에 정적·동적 두 입력을 모두 제공한다(부록6 "한 prop 은 한쪽만" 규칙의 명시적 완화). 정적 검사의 propControls 비교는 controlKey 문자열 기준이라 `selectOptions`(controlKey) ≠ `options`(dataProps propKey)로 자동 통과한다. **반복(iteration) 데이터 연결**: `node.iteration.source`(반복 렌더링의 배열 소스)는 `props` 가 아니라 **노드 최상위 구조 키**라 컴포넌트 capability(`dataProps`)와 무관하다. iteration 은 Div/Span/Button/Li 등 거의 모든 컴포넌트에 붙을 수 있으므로, 편집기는 `dataProps` 선언 여부와 별개로 **iteration 을 가진 모든 노드**에 [속성] 탭 최상단 "반복 데이터 연결" 공용 영역(`IterationBindingSection`)을 노출한다(항상 array shape 바인딩). `item_var`/`index_var` 는 안쪽 자식 바인딩과 연동되어 읽기전용 힌트로만 표시한다(변경은 코드 편집). @@ -102,7 +102,7 @@ editor-spec.json 이 커지면(코어 admin 템플릿은 단일 파일 18,000줄 **역할 식별 (이름 가정 금지)**: 코어는 컴포넌트 **이름**(`name==="Table"`)으로 표/목록/배열을 식별하지 않는다. 어떤 컴포넌트든 capability 의 `nodeEditor.kind`/`canvasOverlay.kind`/`dataProps`/`flexEditor` **역할 선언**으로 편집 동작을 결정한다. 따라서 `div`-그리드로 만든 표도 `nodeEditor:{kind:"table",params:{...역할 매핑}}` 만 선언하면 표 에디터가 붙고, 커스텀 목록 컴포넌트도 `nodeEditor:{kind:"children"}` 으로 목록 에디터가 붙는다. `params` 의 역할 매핑(rowContainer/row/cell 등)은 컴포넌트 이름이 아니라 그 컴포넌트가 어떤 자식 구조를 쓰는지를 적는다. -**데이터 정의 빌트인(옵션/배열/차트 수동 데이터)**: 정적으로 편집 가능한 "데이터 정의" 표면(Select.options, TabNavigation.tabs, BarChart.labels+datasets, DonutChart.data, CardGrid.cardColumns, DynamicFieldList.columns, SocialLoginButtons.providers 등)은 모두 `nodeEditor`(array/array-group/array-cell-tree) 또는 `propControls`(options-list) 로 편집 가능하게 선언한다. 전 draggable 컴포넌트는 데이터 표면을 가지면 편집 슬롯을 보유하거나(누락 0), 보유하지 않으면 비대상 allowlist(flat scalar / 표시 텍스트 / 레이아웃 / 런타임 scalar 바인딩전용)에 등록되어야 한다 — audit `editor-all-draggable-data-editable` 가 둘 다 아닌 draggable 을 차단한다. +**데이터 정의 빌트인(옵션/배열/차트 수동 데이터)**: 정적으로 편집 가능한 "데이터 정의" 표면(Select.options, TabNavigation.tabs, BarChart.labels+datasets, DonutChart.data, CardGrid.cardColumns, DynamicFieldList.columns, SocialLoginButtons.providers 등)은 모두 `nodeEditor`(array/array-group/array-cell-tree) 또는 `propControls`(options-list) 로 편집 가능하게 선언한다. 전 draggable 컴포넌트는 데이터 표면을 가지면 편집 슬롯을 보유하거나(누락 0), 보유하지 않으면 비대상 allowlist(flat scalar / 표시 텍스트 / 레이아웃 / 런타임 scalar 바인딩전용)에 등록되어야 한다 — 정적 검사가 둘 다 아닌 draggable 을 차단한다. **코어 제공 속성(요소 ID) + opt-out**: 코어는 모든 draggable 컴포넌트의 [속성] 탭 최상단에 "요소 ID" 컨트롤을 일괄 제공한다(값 = 표준 `node.props.id`, 강제 DOM 주입 없음 — 컴포넌트 passthrough 책임). 기존 `elemId`(→id) 같은 템플릿 propControl 은 코어로 이전(중복 선언 금지 — 코어 우선). 인라인 루트가 없는 컴포넌트(서드파티 모달/Portal)는 capability 에 `"coreProps": false` 로 opt-out 한다. `"coreProps": ["id"]` 처럼 부분집합 선언도 가능(미선언 = 코어 기본 전체). 코어 id 컨트롤은 `{{바인딩}}` 값이면 "바인딩됨(코드 편집)" 디그레이드, HTML 안전 문자만 허용(한글·공백 자동 제거). 컴포넌트 측 id passthrough 규약은 `docs/frontend/components-types.md` "요소 id 패스스루" 참조. @@ -178,7 +178,7 @@ editor-spec.json 이 커지면(코어 admin 템플릿은 단일 파일 18,000줄 `stateLabels` 가 상태값(`_global`/`query` 등) 명칭을 editor-spec 카탈로그에서 다는 것과 달리, **data_source 의 친화 명칭은 그 소스를 선언한 레이아웃 JSON 의 `data_sources[]` 항목에 `label_key` 로 직접 단다**(`$t:` 다국어 키 — 예 `"label_key": "$t:editor.data_source.products"`). 데이터 연결(`dataProps`) 검색 피커가 data_source 후보를 표시할 때 현재 로케일의 친화 명칭으로 보여 주며, 미지정 시 소스 id 로 폴백한다. 명칭 키는 편집 대상 템플릿의 편집기 i18n(`lang/partial/{locale}/editor.json` 의 `data_source.`)에 정의한다 — 언어팩으로 로케일이 동적 추가되면 자동 대응한다. -`label_key` 는 레이아웃 편집기의 **데이터 소스 편집기**(툴바 `⚙데이터` → `DataSourcesPanel`)가 관리한다. 번들 템플릿의 모든 레이아웃은 모든 data_source 에 `label_key` 를 보유해야 하며(누락 0), audit `data-source-label-key-coverage` 가 신규 레이아웃의 누락·비-`$t:` 값을 차단한다. +`label_key` 는 레이아웃 편집기의 **데이터 소스 편집기**(툴바 `⚙데이터` → `DataSourcesPanel`)가 관리한다. 번들 템플릿의 모든 레이아웃은 모든 data_source 에 `label_key` 를 보유해야 하며(누락 0), 정적 검사가 신규 레이아웃의 누락·비-`$t:` 값을 차단한다. ### darkMode — 다크 모드 표현 (소형, manifest 인라인 권장) diff --git a/docs/extension/hooks.md b/docs/extension/hooks.md index a7ec6362..1b3e8268 100644 --- a/docs/extension/hooks.md +++ b/docs/extension/hooks.md @@ -230,7 +230,7 @@ class ProductCacheInvalidationListener implements HookListenerInterface ### Listener 데이터 접근 규정 -Listener 는 thin orchestrator 로 동작하며 영속/도메인 책임은 Service / Repository 가 갖는다. 다음 패턴은 audit 가 차단한다. +Listener 는 thin orchestrator 로 동작하며 영속/도메인 책임은 Service / Repository 가 갖는다. 다음 패턴은 정적 검사가 차단한다. | ❌ 금지 | ✅ 올바른 사용 | |--------|---------------| @@ -282,7 +282,7 @@ $products = $this->productRepository->findByIdsKeyed($ids); #### 면제 (allowlist) -다음과 같은 의도된 예외는 인라인 주석으로 명시한다 (audit 가 해당 라인을 건너뜀). +다음과 같은 의도된 예외는 인라인 주석으로 명시한다 (정적 검사가 해당 라인을 건너뜀). ```php // audit:allow listener-direct-db-facade reason: 동적 modelClass dispatch (description resolver 의 unified ID→name 변환) diff --git a/docs/extension/language-packs.md b/docs/extension/language-packs.md index de83a609..4f6354be 100644 --- a/docs/extension/language-packs.md +++ b/docs/extension/language-packs.md @@ -69,7 +69,7 @@ lang/ - `core.<영역>.*` — 향후 코어 UI 추가 시 호스팅 템플릿/모듈/플러그인의 lang JSON 은 root 에 `core` 키를 정의하지 않는다. -audit 룰 `core-frontend-i18n-location` 이 정적으로 차단한다. +정적 검사가 차단한다. ### 런타임 병합 흐름 diff --git a/docs/extension/module-assets.md b/docs/extension/module-assets.md index 0e09158b..98413cd7 100644 --- a/docs/extension/module-assets.md +++ b/docs/extension/module-assets.md @@ -410,7 +410,7 @@ GET /api/plugins/bundle.css?v={version} ### 병합 규율 -| 규율 | 내용 | audit 룰 | +| 규율 | 내용 | 정적 검사 | |------|------|---------| | priority 순서 | manifest `loading.priority` 오름차순만. 확장 이름 하드코딩 금지 | (선언형) | | `\n;\n` 구분자 | IIFE 사이는 `\n;\n`(JS)/`\n`(CSS). 미사용 시 ASI 붕괴 → 전체 파싱 에러 | `extension-bundle-concat-separator` | diff --git a/docs/extension/plugin-development.md b/docs/extension/plugin-development.md index b166c436..6f4c07bc 100644 --- a/docs/extension/plugin-development.md +++ b/docs/extension/plugin-development.md @@ -392,10 +392,10 @@ class FooPluginServiceProvider extends BasePluginServiceProvider ### 금지 사항 -- **글로벌 `CacheInterface` / `StorageInterface` 바인딩 재정의 금지** — `$this->app->singleton(CacheInterface::class, ...)` 또는 `app()->bind(StorageInterface::class, ...)` 는 코어/타 확장 도메인을 누수시킨다. audit 룰 `extension-no-global-cache-rebind` 가 자동 차단한다. +- **글로벌 `CacheInterface` / `StorageInterface` 바인딩 재정의 금지** — `$this->app->singleton(CacheInterface::class, ...)` 또는 `app()->bind(StorageInterface::class, ...)` 는 코어/타 확장 도메인을 누수시킨다. 정적 검사가 자동 차단한다. - **인라인 contextual binding 복제 금지** — `$this->app->when([X::class])->needs(StorageInterface::class)->give(...)` 패턴을 직접 작성하지 말고 `$storageServices` 배열에 등록한다. - **Listener 의 동적 인스턴스 생성에서 `app(CacheInterface::class)` 직접 호출 금지** — `app()->makeWith(MyService::class, [...])` 로 컨테이너 해석에 위임해야 contextual binding 이 적용된다. -- **HTTP Kernel 미들웨어 그룹 직접 조작 금지** — SP `boot()` 에서 `HttpKernel::append/prepend/pushMiddlewareToGroup()` / `aliasMiddleware()`, 또는 라우트 파일에서 자기 `Http\Middleware\` FQCN 을 `->middleware(Foo::class)` 로 부착하지 않는다. 대신 `Plugin::getMiddleware()` 로 미들웨어와 부착 대상(targets)을 선언하면 코어 self-gate 게이트가 요청 시점에 실행한다. audit 룰 `extension-middleware-declarative-registration` / `extension-route-middleware-alias-reference` 가 자동 차단한다. 상세: [docs/backend/middleware.md "확장 미들웨어 선언 (self-gate)"](../backend/middleware.md#확장-미들웨어-선언-self-gate). +- **HTTP Kernel 미들웨어 그룹 직접 조작 금지** — SP `boot()` 에서 `HttpKernel::append/prepend/pushMiddlewareToGroup()` / `aliasMiddleware()`, 또는 라우트 파일에서 자기 `Http\Middleware\` FQCN 을 `->middleware(Foo::class)` 로 부착하지 않는다. 대신 `Plugin::getMiddleware()` 로 미들웨어와 부착 대상(targets)을 선언하면 코어 self-gate 게이트가 요청 시점에 실행한다. 정적 검사가 자동 차단한다. 상세: [docs/backend/middleware.md "확장 미들웨어 선언 (self-gate)"](../backend/middleware.md#확장-미들웨어-선언-self-gate). 상세: [cache-driver.md `## 확장에서 cache 바인딩`](cache-driver.md) diff --git a/docs/extension/upgrade-step-guide.md b/docs/extension/upgrade-step-guide.md index 88fb39cb..6516f936 100644 --- a/docs/extension/upgrade-step-guide.md +++ b/docs/extension/upgrade-step-guide.md @@ -431,7 +431,7 @@ Call to undefined method App\Services\CoreUpdateService::ensureWritableDirectori beta.4 의 `Upgrade_7_0_0_beta_4` step 이 `app(CoreUpdateService::class)->ensureWritableDirectories(...)` 를 호출했으나, 부모 메모리의 stale beta.3 `CoreUpdateService` 인스턴스에는 `ensureWritableDirectories` 가 없어 fatal. 디스크는 이미 beta.4 였음에도 PHP autoloader 가 beta.3 인스턴스를 재사용한 결과. -#### 자동 검출 — `upgrade-step-vone-safety` audit rule (manual-only) +#### 자동 검출 — V-1 안전 정적 검사 (리뷰 경고) `upgrades/Upgrade_*.php` 안의 `app(\w+Service::class)` / `app(\w+Manager::class)` / `app(\w+Repository::class)` 패턴은 PR review reviewer 에게 manual-only 경고를 발행한다. 자동 차단은 아니지만, 매치된 위치를 보고 "이 메서드가 이전 버전 디스크에 존재했는가" 를 reviewer 가 수동 판정한다. 면제: `// audit:allow upgrade-step-vone-safety reason: ...` 인라인 주석. @@ -650,7 +650,7 @@ $pluginResult = app(PluginManager::class)->resyncAllActiveDeclarativeArtifacts() 3. 확장 작성자는 자신의 `module.php` / `plugin.php` 에 declaration override (필요 확장만) 4. manifest(`module.json` / `plugin.json`) 변경 불필요 — declaration 은 PHP 클래스 메서드 -**자동 정합성 검증**: 정적 audit 도구가 새 declaration 메서드 추가 시 sync 묶음에 누락 없이 반영되는지 검증. 누락 시 빌드/커밋 단계에서 차단된다. +**자동 정합성 검증**: 정적 검사가 새 declaration 메서드 추가 시 sync 묶음에 누락 없이 반영되는지 검증. 누락 시 빌드/커밋 단계에서 차단된다. ### 권한 정상화 실패 노출 @@ -670,7 +670,7 @@ spawn 자식 (경로 B) 은 디스크의 *최신* 코드/시더/카탈로그를 - **코어**: 7.0.0-beta.5 부터 신규 step 의무 (beta.2~4 는 legacy 호환 유지) - **번들 모듈/플러그인**: `module.json` / `plugin.json` 의 `g7_version` 제약 최소 버전이 `7.0.0-beta.5` 이상이면 *그 확장의 현재 version 부터* 신규 step 의무. 그 미만이면 legacy (가드 미발동) -- **외부 확장 (`modules/{not _bundled}` / `plugins/{not _bundled}`)**: 런타임 가드는 동일하게 발화 (manifest g7_version 판정), audit 만 적용 제외 (사용자 수정 코드 PR 차단 부적합) +- **외부 확장 (`modules/{not _bundled}` / `plugins/{not _bundled}`)**: 런타임 가드는 동일하게 발화 (manifest g7_version 판정), 정적 검사만 적용 제외 (사용자 수정 코드 PR 차단 부적합) - **번들 템플릿/언어팩**: upgrade step 시스템 자체가 부재 — 미래 도입 시 동일 규약 자동 상속 ### 확장 작성자의 적용 트리거 @@ -785,10 +785,10 @@ final public function run(UpgradeContext $context): void - **raw JSON 만 read** (Applier) — 시더 클래스 `Database\Seeders\*` 참조 금지 (fresh-load invariant) - **idempotent** — `Schema::hasColumn` / `where->exists()` 가드 동반 -- **V-1 안전 강화** — `app(*Service|*Manager|*Repository::class)` 호출 금지 (audit `upgrade-step-data-snapshot` 가 error 로 차단) +- **V-1 안전 강화** — `app(*Service|*Manager|*Repository::class)` 호출 금지 (정적 검사가 차단) - **버전 격리** — 다른 버전 namespace `App\Upgrades\Data\V{other}\*` 참조 금지 - **로컬 헬퍼 + Illuminate 파사드만 사용** — 신규 도입 클래스 / 미래 변경 가능 클래스 의존 회피 -- **공용 헬퍼 사용 시 신중** — `FilePermissionHelper::copyDirectory` 처럼 V-1 안전 검증된 헬퍼만 허용 (audit 룰이 미허용 호출은 차단) +- **공용 헬퍼 사용 시 신중** — `FilePermissionHelper::copyDirectory` 처럼 V-1 안전 검증된 헬퍼만 허용 (정적 검사가 미허용 호출은 차단) ### 강제 메커니즘 @@ -797,7 +797,7 @@ final public function run(UpgradeContext $context): void | 런타임 | 코어 | `CoreUpdateService::runUpgradeSteps()` 의 instance 검증 | 버전 ≥ beta.5 인데 `AbstractUpgradeStep` 미상속 → `CoreUpdateOperationException` throw → update 전체 중단 → 백업 복원 | | 런타임 | 모듈 | `ModuleManager::runUpgradeSteps()` 내 `ExtensionUpgradeGuardHelper` 호출 | manifest g7_version 기반 since-version 판정 → 미상속 시 `RuntimeException` throw | | 런타임 | 플러그인 | `PluginManager::runUpgradeSteps()` 내 `ExtensionUpgradeGuardHelper` 호출 | 동일 패턴 (식별자만 다름) | -| PR 시점 | 코어 + 번들 모듈/플러그인 | audit rule `upgrade-step-data-snapshot` (severity: error) | namespace 불일치 / Seeders use / app() 호출 / 다른 버전 참조 / 공용 디렉토리 사용 자동 차단. 확장 경로는 manifest g7_version 기반 since-version 으로 검사 범위 결정 | +| PR 시점 | 코어 + 번들 모듈/플러그인 | 정적 검사 (위반 시 차단) | namespace 불일치 / Seeders use / app() 호출 / 다른 버전 참조 / 공용 디렉토리 사용 자동 차단. 확장 경로는 manifest g7_version 기반 since-version 으로 검사 범위 결정 | 면제: `// audit:allow upgrade-step-data-snapshot reason: ...` 인라인 주석. legacy 미들 케이스 또는 임시 우회 시. @@ -831,7 +831,7 @@ final public function run(UpgradeContext $context): void 4. `04_IdentityPermissionPivotMerge.php` — IDV 권한 rename 충돌 경로 피벗 병합 5. `05_RecoverPublicStorageSymlink.php` — public/storage symlink 복구 -beta.4 까지 출시본의 박제된 핫픽스 모든 동작이 본 격리 구조로 100% 보존되며, 미래 버전이 이 디렉토리를 *수정하지 않는 한* (수정은 audit error) beta.1 → beta.7 같은 멀티 점프에서도 동일한 결과를 보장한다. +beta.4 까지 출시본의 박제된 핫픽스 모든 동작이 본 격리 구조로 100% 보존되며, 미래 버전이 이 디렉토리를 *수정하지 않는 한* (수정은 정적 검사 차단 대상) beta.1 → beta.7 같은 멀티 점프에서도 동일한 결과를 보장한다. --- diff --git a/docs/frontend/actions-handlers-navigation.md b/docs/frontend/actions-handlers-navigation.md index 087e4f8c..06c286aa 100644 --- a/docs/frontend/actions-handlers-navigation.md +++ b/docs/frontend/actions-handlers-navigation.md @@ -33,7 +33,7 @@ | 필드 | 타입 | 기본값 | 설명 | |------|------|--------|------| -| `path` | string | - | 이동할 경로 | +| `path` | string | - | 이동할 경로. 목적지는 이 필드(없으면 액션 노드의 `target`)로만 정해진다 — `url` / `href` / `to` 같은 다른 이름으로 적으면 읽히지 않아 목적지가 `undefined` 가 되고, 예외도 404 도 없이 버튼만 동작하지 않는다 | | `query` | object | - | 쿼리 파라미터 객체 | | `mergeQuery` | boolean | false | 기존 쿼리 파라미터와 병합 | | `replace` | boolean | false | URL만 변경 (페이지 리로드 없음) | @@ -169,6 +169,65 @@ } ``` +`params` 형태별 결과는 다음과 같다. `replaceUrl` 도 동일하다. + +| `params` 형태 | 결과 | +| --- | --- | +| `mergeQuery: true` + `query: {}` | 현재 URL 쿼리 **전부 유지** | +| `mergeQuery: true` + `query: {k: v}` | 유지 + `k` 만 덮어씀 (빈 문자열이면 `k` 제거) | +| `mergeQuery: true` + `query` 키 없음 | 전부 유지 (engine-v1.54.2+. 그 이전에는 병합이 no-op 이 되어 **전부 소실**) | +| `query: {k: v}` (mergeQuery 없음) | `k` 외 **전부 소실** | +| `query` 키 자체가 없음 | 쿼리 **전부 소실** | + +### 목록 컨텍스트 왕복 규약 + +페이지네이션 목록 화면과 그에 딸린 **상세 · 형제 상세(이전글/다음글) · 작성/수정 폼 · 확인 모달**은 하나의 목록 클러스터다. 이 클러스터 안에서의 이동은 URL 목록 상태(`page`/`search`/`category`/`filters[*]`/정렬/`per_page`)를 손실 없이 보존해야 한다. + +```json +"params": { "path": "…", "mergeQuery": true, "query": {} } +``` + +지켜야 할 점: + +- **모든 leg 에 동일 적용한다.** 목록 진입 / 목록 복귀 / 형제 상세 이동 / 폼 취소 / 삭제 후 복귀 중 하나만 빠져도 그 지점에서 상태가 끊기고, 이후 '목록' 버튼은 복원할 상태가 없어 1페이지로 되돌아간다. 공개 이슈 #75 가 정확히 이 형태였다 — 행 클릭과 '목록' 버튼에는 규약이 적용됐지만 이전글/다음글만 누락됐다. +- **현재 값을 그대로 다시 넘기는 키는 열거하지 않는다.** `{"del": "{{query.del ?? ''}}"}` 같은 열거는 `mergeQuery` 가 이미 나르므로 중복이고, 나머지 키를 빠뜨리게 만드는 원인이 된다. 값을 **바꿔야** 하는 키만 남긴다. +- **페이지를 되돌려야 하면 `{"page": ""}`** 를 쓴다(빈 문자열 = 파라미터 제거 = 1페이지). 새 검색을 실행하는 버튼이 여기 해당한다. +- **새로고침 버튼도 병합 대상이다.** 새로고침은 보던 목록을 다시 부르는 동작이지 조건을 지우는 동작이 아니다. +- **`mergeQuery` 는 boolean 리터럴로 고정한다.** `"{{cond}}"` 처럼 분기시키면 한쪽 분기에서만 상태가 조용히 사라진다. +- **`path` 에 인라인 쿼리스트링을 붙이지 않는다.** `buildMergedQueryPath` 가 `?` 이후를 잘라내므로 `"/board/{{slug}}/write?parent_id={{id}}"` 의 `parent_id` 는 병합 시 사라진다. `query` 객체로 옮긴다. +- **목적지가 표현식이면 의도를 명시한다.** `"{{route.id ? '/board/' + route.slug + '/' + route.id : '/board/' + route.slug}}"` 같은 취소 버튼은 문자열 리터럴로 목적지가 드러나므로 룰이 클러스터 소속을 판정한다. 그러나 `"{{_global.shopBase}}/products"` / `"{{notification.url}}"` 처럼 경로 전체가 런타임 값이면 정적으로는 알 수 없다. 클러스터 내 이동이면 `mergeQuery: true` 를, 밖으로 나가는 이동이면 아래 면제 주석을 남긴다. +- **`path` 를 생략한 액션도 병합 대상이다.** `path` 없이 `query` 만 주면 "현재 주소를 유지한 채 쿼리만 바꾼다" 는 뜻이라 목록 화면 자신에게 작용한다. 그런데 `mergeQuery` 가 없으면 위 표의 마지막 두 행대로 쿼리가 통째로 대체되므로, 상세 화면의 탭 전환(`{"tab": "reviews"}`)이나 좌우 분할 목록의 항목 선택(`{"id": …, "mode": "view"}`) 한 번에 방금 건 검색어·정렬·페이지가 사라진다. 목적지 문자열이 없어 경로 기반 판정이 닿지 않는 자리라 눈에 잘 띄지 않는다. +- **병합은 값을 나르지 않는다.** `mergeQuery` 는 "지금 URL 에 있는 값을 이어받는다" 는 뜻이지 "새 값을 만든다" 가 아니다. 검색 실행·페이지 이동처럼 값을 **바꾸는** 액션은 그 값을 `query` 에 직접 담아야 한다 (`{"page": "{{$args[0]}}"}`). `query: {}` 로 비우면 페이지 버튼이 아무 동작도 하지 않는다. + +의도적 리셋은 예외다 — 검색 초기화 / 필터 초기화 / 탭 전환 / 프리셋 적용 / **다른 목록으로의 이동**이 여기 해당한다. 이때는 액션 노드 `comment` 에 다음을 남겨 의도를 코드에 기록한다. + +리셋 자리에 `mergeQuery: true` 를 넣으면 그 버튼은 화면상 아무 일도 하지 않는다 — 조건을 비우려고 이동하는데 병합이 방금 비운 조건을 URL 에서 되돌려놓기 때문이다. 면제 주석은 선언일 뿐 사실이 아니므로, "병합하지 않는다" 고 적어 두고 `mergeQuery: true` 를 함께 두는 자기모순이 생기지 않도록 주석과 params 를 함께 확인한다. + +탭 전환은 특히 실수하기 쉽다. `/admin/templates/user` 와 `/admin/templates/admin` 처럼 탭마다 라우트가 갈리는 화면은 탭 각각이 자기 검색어·페이지를 갖는 **별개의 목록**이다. 여기에 병합을 붙이면 `?search=…&page=3` 상태에서 다른 탭으로 넘어갈 때 남의 검색어로 걸러진 3페이지(대개 빈 화면)가 열린다. 마찬가지로 프리셋 적용은 조건 세트를 통째로 갈아끼우는 동작이므로, 병합하면 프리셋이 열거하지 않은 직전 조건이 화면에 보이지 않는 채 URL 에 남는다. + +앞선 액션이 `setState` 로 로컬 필터를 비웠다면 **URL 쪽 같은 키도 함께 비워야 한다**. `mergeQuery` 는 그 키를 URL 에서 그대로 이어받으므로, 비우지 않으면 입력창은 비어 보이는데 조회는 옛 조건으로 걸리는 어긋남이 생긴다 (`{"search_keyword": ""}` — 빈 문자열 = 파라미터 제거). + +```json +{ + "comment": "audit:allow layout-list-context-navigate-merge-query 검색 초기화 — 조건을 전부 비우는 것이 목적", + "handler": "navigate", + "params": { "path": "/board/{{route.slug}}", "mergeQuery": false } +} +``` + +자동 차단: 정적 검사 대상 (위반 시 차단). 목록 라우트는 저장소에서 자동 도출하므로 화이트리스트를 관리할 필요가 없다. 도출 근거는 두 가지다. + +1. `query` 에 `page` 키가 등장하는 navigate 목적지 +2. 화면이 실제로 페이지네이션 UI(`onPageChange` 액션 / `Pagination` 컴포넌트)를 갖고 있는지 — partial 을 따라 전파한다 +3. 데이터소스 params 가 URL 에서 페이지를 읽는지 (`"page": "{{query.page}}"`) — 페이저를 같은 파일에 그리지 않는 목록까지 포함 +4. 데이터소스 params 가 URL 에서 목록 필터를 읽는지 (`search`/`category`/`sort`/`status`/`filters`) — **페이지가 URL 이 아니라 클라이언트 상태(무한스크롤)로 관리되는 목록**도 필터는 URL 에 있으므로 그 목록의 새로고침·왕복이 필터를 보존해야 한다 + +두 번째 근거가 없으면 "이미 규약을 적용한 화면일수록 감시 대상이 된다" 는 순환이 생겨, 아직 고치지 않은 화면이 오히려 탐지에서 빠진다. 네 번째 근거가 없으면 무한스크롤 목록의 검색어가 새로고침에서 조용히 사라지는 결함이 빠진다. + +정적 검사는 반대 방향도 본다 — 탭 전환(`onTabChange`)에 `mergeQuery: true` 를 붙이거나, 자기 클러스터와 상하 관계가 전혀 없는 다른 목록 라우트로 나가면서 병합하면 위반으로 잡는다. "병합 누락"만 보면 이 방향이 통째로 사각지대가 된다. + +한계 — 정적 검사는 레이아웃 JSON 만 스캔한다. navigate leg 이 컴포넌트 코드(`.tsx`)에 있으면(예: `ProductCard` 의 카드 클릭) 룰의 시야 밖이다. 목록 항목으로 렌더되는 컴포넌트가 상세로 이동할 때는 컴포넌트가 직접 `mergeQuery` 를 실어야 한다(`ProductCard` 의 `preserveListQuery` prop 참조). + ### 배열 쿼리 파라미터 > **버전**: engine-v1.10.0+ diff --git a/docs/frontend/components-types.md b/docs/frontend/components-types.md index 60da7342..961daf02 100644 --- a/docs/frontend/components-types.md +++ b/docs/frontend/components-types.md @@ -175,7 +175,7 @@ export const Foo = ({ /* 도메인 prop */, editorAttrs }: FooProps) => ( - 사용자 페이지(비편집)에서는 `editorAttrs` 미주입 → `{...editorAttrs}` 가 no-op → DOM 구조/속성 불변 (프리뷰 ↔ 사용자 페이지 패리티 유지). - `editorAttrs` 만 spread 하므로 도메인 prop 누출/HTML 동명 prop 타입 충돌이 없다. (`React.HTMLAttributes` 상속 + `{...rest}` 방식은 도메인 prop 누출 위험으로 채택 안 함.) -- 자동 검출: audit 룰 `editor-attrs-passthrough` (nesting.draggable 의 composite/layout 컴포넌트가 `editorAttrs` 미수신 시 error). 의도적 면제는 파일 헤더 `// editor-attrs:allow <사유>`. +- 자동 검출: 정적 검사가 nesting.draggable 의 composite/layout 컴포넌트가 `editorAttrs` 를 받지 않으면 차단한다. 의도적 면제는 파일 헤더 `// editor-attrs:allow <사유>`. ### 요소 id 패스스루 (코어 일괄 ID) diff --git a/docs/frontend/components.md b/docs/frontend/components.md index 66f184cc..ad643981 100644 --- a/docs/frontend/components.md +++ b/docs/frontend/components.md @@ -142,7 +142,7 @@ import { Icon, IconName } from '../basic/Icon'; ### 레이아웃 편집기 capability 선언 의무 -새 draggable 컴포넌트(레이아웃 편집기 팔레트/캔버스에 노출)는 위 4개 파일에 더해 호스트 템플릿 `editor-spec/componentCapabilities.json` 에 capability 를 선언해야 편집기에서 "편집 불가(no-editable)"가 되지 않는다. 표시 텍스트/아이콘/select/목록·배열·표 데이터 prop 별로 `propControls`(속성 탭) / `dataProps`(데이터 연결) / `nodeEditor`·`canvasOverlay`(구조 에디터) / `styleControls`(스타일 탭) / `events`(동작 탭) 를 선언한다. 데이터 표면을 가진 컴포넌트가 편집 슬롯도 비대상 allowlist 도 없으면 audit `editor-all-draggable-data-editable` 가 차단한다. composite/layout 컴포넌트는 `editorAttrs` spread + `id` 패스스루도 필요하다. +새 draggable 컴포넌트(레이아웃 편집기 팔레트/캔버스에 노출)는 위 4개 파일에 더해 호스트 템플릿 `editor-spec/componentCapabilities.json` 에 capability 를 선언해야 편집기에서 "편집 불가(no-editable)"가 되지 않는다. 표시 텍스트/아이콘/select/목록·배열·표 데이터 prop 별로 `propControls`(속성 탭) / `dataProps`(데이터 연결) / `nodeEditor`·`canvasOverlay`(구조 에디터) / `styleControls`(스타일 탭) / `events`(동작 탭) 를 선언한다. 데이터 표면을 가진 컴포넌트가 편집 슬롯도 비대상 allowlist 도 없으면 정적 검사가 차단한다. composite/layout 컴포넌트는 `editorAttrs` spread + `id` 패스스루도 필요하다. 상세: [editor-spec.md "componentCapabilities"](../extension/editor-spec.md) · [components-types.md "편집기 attribute 패스스루"](components-types.md) diff --git a/docs/frontend/data-sources.md b/docs/frontend/data-sources.md index 659fead6..c14f731a 100644 --- a/docs/frontend/data-sources.md +++ b/docs/frontend/data-sources.md @@ -84,7 +84,7 @@ | 필드 | 타입 | 필수 | 기본값 | 설명 | |------|------|------|--------|------| | `id` | string | ✅ | - | 데이터 소스 고유 ID (컴포넌트에서 `{{id.data}}` 형태로 참조) | -| `label_key` | string | ❌ | - | 친화 명칭 `$t:` 다국어 키 (예 `$t:editor.data_source.products`). 레이아웃 편집기 데이터 연결 검색 피커가 현재 로케일 명칭으로 표시. 미지정 시 `id` 폴백. 번들 템플릿은 전 data_source 보유 의무(audit `data-source-label-key-coverage`) | +| `label_key` | string | ❌ | - | 친화 명칭 `$t:` 다국어 키 (예 `$t:editor.data_source.products`). 레이아웃 편집기 데이터 연결 검색 피커가 현재 로케일 명칭으로 표시. 미지정 시 `id` 폴백. 번들 템플릿은 전 data_source 보유 의무(정적 검사) | | `type` | string | ✅ | - | 데이터 소스 타입 (`api`, `static`, `route_params`, `query_params`, `websocket`) | | `endpoint` | string | ✅* | - | API 엔드포인트 (type이 `api`일 때 필수) | | `method` | string | ❌ | `GET` | HTTP 메서드 (`GET`, `POST`, `PUT`, `PATCH`, `DELETE`) | diff --git a/docs/testing-guide.md b/docs/testing-guide.md index bffed930..c57b6cf4 100644 --- a/docs/testing-guide.md +++ b/docs/testing-guide.md @@ -339,7 +339,7 @@ public function test_pg_payment_member_with_mileage_to_jeju(): void { ... } TypeScript 테스트는 `// @scenario` / `// @effects` 주석 동일 사용. -audit rule `test-scenario-coverage` 가 매니페스트 cross product 와 effects 항목을 테스트 docblock 마킹과 대조하여 누락을 검출 (자동 차단). +정적 검사가 매니페스트 cross product 와 effects 항목을 테스트 docblock 마킹과 대조하여 누락을 검출한다 (자동 차단). ### cross product 폭발 관리 diff --git a/docs/testing/e2e-testing.md b/docs/testing/e2e-testing.md index 392a24ce..8e0b90a0 100644 --- a/docs/testing/e2e-testing.md +++ b/docs/testing/e2e-testing.md @@ -230,7 +230,7 @@ test('unauthenticated_401 × no_token', async ({ page }) => { }); ``` -`audit-branch.cjs` 의 `test-scenario-coverage` 룰이 매니페스트 axes ↔ docblock 매칭을 자동 검증. +정적 검사가 매니페스트 axes ↔ docblock 매칭을 자동 검증. ## §8. 회귀 테스트 4단계 diff --git a/modules/_bundled/gnuboard7-hello_module/CHANGELOG.md b/modules/_bundled/gnuboard7-hello_module/CHANGELOG.md index ff042df5..fdf30e2e 100644 --- a/modules/_bundled/gnuboard7-hello_module/CHANGELOG.md +++ b/modules/_bundled/gnuboard7-hello_module/CHANGELOG.md @@ -6,6 +6,10 @@ ## [0.1.0] - 2026-07-01 +### Fixed + +- 메모 목록에서 작성·수정 화면에 다녀오면 보고 있던 페이지가 사라지고 1페이지로 되돌아가던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) + ### Changed - 메모 관리 화면의 콘텐츠 카드 외형을 sirsoft-admin_basic 표준 시맨틱 (.admin-card) 과 정합 — 다른 관리자 화면과 같은 결로 통일. diff --git a/modules/_bundled/gnuboard7-hello_module/resources/layouts/admin/admin_memo_form.json b/modules/_bundled/gnuboard7-hello_module/resources/layouts/admin/admin_memo_form.json index 1fc5b16b..d11ecf7e 100644 --- a/modules/_bundled/gnuboard7-hello_module/resources/layouts/admin/admin_memo_form.json +++ b/modules/_bundled/gnuboard7-hello_module/resources/layouts/admin/admin_memo_form.json @@ -142,7 +142,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/memos" + "path": "/admin/memos", + "mergeQuery": true, + "query": {} } } ], @@ -183,7 +185,9 @@ { "handler": "navigate", "params": { - "path": "/admin/memos" + "path": "/admin/memos", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/gnuboard7-hello_module/resources/layouts/admin/admin_memo_list.json b/modules/_bundled/gnuboard7-hello_module/resources/layouts/admin/admin_memo_list.json index 2bdf6986..1a33695d 100644 --- a/modules/_bundled/gnuboard7-hello_module/resources/layouts/admin/admin_memo_list.json +++ b/modules/_bundled/gnuboard7-hello_module/resources/layouts/admin/admin_memo_list.json @@ -75,7 +75,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/memos/create" + "path": "/admin/memos/create", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-board/CHANGELOG.md b/modules/_bundled/sirsoft-board/CHANGELOG.md index 4fedbc04..6bc3063b 100644 --- a/modules/_bundled/sirsoft-board/CHANGELOG.md +++ b/modules/_bundled/sirsoft-board/CHANGELOG.md @@ -18,6 +18,8 @@ ### Fixed +- 관리자 게시글 목록에서 글을 열어 이전글·다음글로 넘어가거나 수정 후 돌아올 때 보고 있던 페이지·검색어·분류가 사라지던 문제를 수정했습니다. 목록 ↔ 상세 ↔ 이전/다음 글 ↔ 작성·수정 폼 어디로 오가든 목록 상태가 유지되며, 신고 관리와 게시판 목록도 동일하게 개선됐습니다. 새로고침 버튼도 걸어 둔 검색·필터를 지운 채 새로 부르지 않고 보고 있던 목록을 그대로 다시 부릅니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 게시글 목록에서 뒤쪽 페이지를 보던 중 검색하거나 게시 상태를 바꾸면 그 페이지 번호가 그대로 유지돼 결과가 없는 빈 화면이 열리던 문제를 수정했습니다. 검색과 상태 변경은 1페이지부터 보여주며, 사용자가 고른 표시 개수와 정렬은 그대로 유지됩니다. 검색창에서 엔터를 치는 경우와 검색 버튼을 누르는 경우가 서로 다르게 동작하던 것도 함께 맞췄습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 첨부파일을 사용하지 않는 게시판을 아무것도 바꾸지 않고 저장해도 "허용 파일 확장자를 최소 1개 이상 입력하세요" 오류가 나며 저장이 막히던 문제를 수정했습니다. 첨부를 쓰지 않는 게시판에서는 허용 확장자를 비워 두어도 정상적으로 저장됩니다. 게시판 환경설정의 기본값도 동일하게 동작합니다. (#78 @jiwonpapa 님께서 제보해주셨습니다.) - 새 글 표시 기간을 "0시간"(새 글 표시 안 함)으로 저장할 수 없던 문제를 수정했습니다. 0은 원래 새 글 배지를 끄는 값으로 동작하도록 되어 있었으나 저장 단계에서 막혀 있었습니다. - 게시판 환경설정에서 제목·댓글 최소 길이를 0(제한 없음)으로 저장할 수 없던 문제를 수정했습니다. 내용 최소 길이는 0이 허용되어 같은 화면에서 항목마다 동작이 달랐습니다. diff --git a/modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts b/modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts new file mode 100644 index 00000000..0caa96e3 --- /dev/null +++ b/modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts @@ -0,0 +1,347 @@ +/** + * @file admin-list-context-round-trip.test.ts + * @description 관리자 게시판 목록 컨텍스트 왕복 시 URL 목록 상태 보존 회귀 (#75) + * + * 결함: 목록(`/admin/board/{slug}`) 에서 상세로 들어간 뒤 이전글/다음글/폼취소/삭제후복귀를 + * 거치면 navigate 가 `mergeQuery` 없이 실행되어 page/search/category/filters 가 URL 에서 + * 사라졌다. 그 뒤 '목록' 버튼은 복원할 상태가 없어 1페이지로 되돌아간다. + * + * 검증 방식 2단: + * 1. 실 레이아웃 JSON 전수 분석 — 클러스터 내 navigate 가 모두 `mergeQuery: true` 인지 + * 2. 실 액션을 엔진에 태워 실행(`triggerAction`) — 선언이 실제 목적지 URL 로 이어지는지 + * 손으로 쓴 조각이 아니라 실 레이아웃 JSON 을 읽는다. 실파일이 규약을 어기면 red 여야 한다. + * 선언만 검사하면 "JSON 에 리터럴이 적혀 있다" 까지만 고정되고 병합 결과는 미검증으로 남는다. + * + * @scenario leg=row_click|prev|next|form_cancel|delete_return + * @effects navigation_preserves_list_query + * + * @vitest-environment jsdom + */ + +import { describe, it, expect, afterEach } from 'vitest'; +import fs from 'fs'; +import path from 'path'; + +import { + createLayoutTest, + createMockComponentRegistryWithBasics, +} from '@core/template-engine/__tests__/utils/layoutTestUtils'; + +const LAYOUTS_ROOT = path.resolve(__dirname, '../../../layouts/admin'); + +/** + * 레이아웃 파일 → 그 화면이 속한 목록 클러스터. + * + * 클러스터는 파일 단위로 다르다. 예를 들어 게시판 목록(`/admin/boards`)에서 특정 게시판의 + * 글 목록(`/admin/board/{slug}`)으로 가는 것은 왕복이 아니라 **다른 목록으로의 진입**이므로 + * 병합 대상이 아니다. 확장 전체에 하나의 목록 목록을 적용하면 이런 이동까지 위반으로 잡힌다. + */ +const CLUSTER_FILES: Array<[string, string]> = [ + ['admin_board_posts_index.json', '/admin/board/*'], + ['admin_board_post_detail.json', '/admin/board/*'], + ['admin_board_post_form.json', '/admin/board/*'], + ['partials/admin_board_post_detail/_post_card_content.json', '/admin/board/*'], + ['partials/admin_board_post_detail/_reply_card_content.json', '/admin/board/*'], + ['admin_board_index.json', '/admin/boards'], + ['admin_board_form.json', '/admin/boards'], + ['admin_board_reports_index.json', '/admin/boards/reports'], + ['admin_board_reports_detail.json', '/admin/boards/reports'], + ['partials/admin_board_reports_detail/_card_report_info.json', '/admin/boards/reports'], +]; + +type NavAction = { + handler: string; + comment?: string; + params: { path?: string; mergeQuery?: unknown; query?: unknown }; +}; + +/** + * JSON 트리에서 navigate/replaceUrl 액션을 모두 수집합니다. + * + * @param node 순회 시작 노드 + * @returns 액션 목록 + */ +function collectNavActions(node: unknown): NavAction[] { + const out: NavAction[] = []; + const walk = (n: unknown): void => { + if (Array.isArray(n)) { + n.forEach(walk); + return; + } + if (!n || typeof n !== 'object') return; + const obj = n as Record; + if ( + (obj.handler === 'navigate' || obj.handler === 'replaceUrl') && + obj.params && + typeof obj.params === 'object' + ) { + out.push(obj as unknown as NavAction); + } + Object.values(obj).forEach(walk); + }; + walk(node); + return out; +} + +/** + * 목적지 경로를 비교용 표준형(`{{expr}}` → `*`)으로 바꿉니다. + * + * @param raw 원본 경로 + * @returns 표준형 경로 (판정 불가 시 null) + */ +function normalizePath(raw: unknown): string | null { + if (typeof raw !== 'string' || raw === '') return null; + const p = raw.replace(/\{\{[^}]*\}\}/g, '*').split('?')[0].replace(/\/+$/, ''); + return p.startsWith('/') ? p : null; +} + +/** + * 경로가 목록 라우트와 같은 클러스터인지 판정합니다. + * + * @param dest 표준형 목적지 + * @param list 표준형 목록 라우트 + * @returns 같은 클러스터 여부 + */ +function inFamily(dest: string, list: string): boolean { + return dest === list || dest.startsWith(`${list}/`); +} + +/** + * 레이아웃 파일을 읽어 파싱합니다. + * + * @param rel 레이아웃 루트 기준 상대 경로 + * @returns 파싱된 JSON + */ +function readLayout(rel: string): unknown { + return JSON.parse(fs.readFileSync(path.join(LAYOUTS_ROOT, rel), 'utf8')); +} + +describe('#75 관리자 게시판 목록 컨텍스트 왕복 — mergeQuery 전수', () => { + it.each(CLUSTER_FILES)('%s (클러스터 %s) 내 navigate 는 모두 mergeQuery: true', (rel, list) => { + const offenders = collectNavActions(readLayout(rel)) + .filter((a) => { + if (typeof a.comment === 'string' && a.comment.includes('audit:allow')) return false; + const dest = normalizePath(a.params.path); + if (!dest) return a.params.mergeQuery !== undefined && a.params.mergeQuery !== true; + if (!inFamily(dest, list)) return false; + return a.params.mergeQuery !== true; + }) + .map((a) => `${a.params.path} (mergeQuery=${JSON.stringify(a.params.mergeQuery)})`); + + expect(offenders, `목록 상태를 떨구는 navigate: \n ${offenders.join('\n ')}`).toEqual([]); + }); +}); + +describe('#75 개별 leg 고정', () => { + /** + * 특정 목적지로 가는 첫 navigate 액션을 찾습니다. + * + * @param rel 레이아웃 상대 경로 + * @param destPath 목적지 경로(원문 그대로) + * @returns 액션 + */ + const leg = (rel: string, destPath: string): NavAction => { + const hit = collectNavActions(readLayout(rel)).find((a) => a.params.path === destPath); + if (!hit) throw new Error(`${rel} 에서 "${destPath}" navigate 를 찾지 못했습니다.`); + return hit; + }; + + it('상세 이전글 leg 이 목록 상태를 승계한다', () => { + const a = leg( + 'partials/admin_board_post_detail/_post_card_content.json', + '/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.prev?.id}}' + ); + expect(a.params.mergeQuery).toBe(true); + }); + + it('상세 다음글 leg 이 목록 상태를 승계한다', () => { + const a = leg( + 'partials/admin_board_post_detail/_post_card_content.json', + '/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.next?.id}}' + ); + expect(a.params.mergeQuery).toBe(true); + }); + + it("상세 '목록' 버튼이 목록 상태를 복원한다", () => { + const a = leg('admin_board_post_detail.json', '/admin/board/{{route.slug}}'); + expect(a.params.mergeQuery).toBe(true); + }); + + it('목록 행 클릭이 목록 상태를 상세로 나른다', () => { + const a = leg('admin_board_posts_index.json', '/admin/board/{{row.slug}}/post/{{row.id}}'); + expect(a.params.mergeQuery).toBe(true); + }); + + it('삭제 확인 후 복귀 navigate 의 mergeQuery 가 분기 표현식이 아니다', () => { + const dynamic = collectNavActions(readLayout('admin_board_post_detail.json')).filter( + (a) => 'mergeQuery' in a.params && typeof a.params.mergeQuery !== 'boolean' + ); + expect(dynamic.map((a) => a.params.path)).toEqual([]); + }); +}); + +// --------------------------------------------------------------------------- +// 실행 검증 — 실 액션을 엔진에 태워 목적지 URL 을 확인한다 +// --------------------------------------------------------------------------- + +/** + * 실 JSON 액션을 현재 URL 상태에서 실행하고 목적지를 돌려줍니다. + * + * @param action 실 레이아웃 JSON 에서 뽑은 navigate 액션 + * @returns navigate 목적지 경로 + */ +async function runNav(action: NavAction): Promise { + const utils = createLayoutTest( + { + version: '1.0.0', + layout_name: 'nav_action_probe', + data_sources: [], + components: [{ type: 'basic', name: 'Div', props: { 'data-testid': 'probe' } }], + } as never, + { componentRegistry: createMockComponentRegistryWithBasics() as never, locale: 'ko' } + ); + await utils.render(); + await utils.triggerAction({ type: 'click', ...action } as never); + const dest = utils.getNavigationHistory()[0]; + utils.cleanup(); + return dest; +} + +/** + * 목적지 URL 의 쿼리스트링을 파싱합니다. + * + * @param dest navigate 목적지 + * @returns URLSearchParams + */ +function queryOf(dest: string): URLSearchParams { + return new URLSearchParams(dest.includes('?') ? dest.slice(dest.indexOf('?')) : ''); +} + +/** + * 특정 목적지로 가는 첫 navigate 액션을 찾습니다. + * + * @param rel 레이아웃 상대 경로 + * @param destPath 목적지 경로(원문 그대로) + * @returns 액션 + */ +function navLeg(rel: string, destPath: string): NavAction { + const hit = collectNavActions(readLayout(rel)).find((a) => a.params.path === destPath); + if (!hit) throw new Error(`${rel} 에서 "${destPath}" navigate 를 찾지 못했습니다.`); + return hit; +} + +describe('#75 관리자 게시판 목록 컨텍스트 왕복 — 실행 결과 URL', () => { + afterEach(() => { + window.history.replaceState({}, '', '/'); + }); + + const legs: Array<[string, string]> = [ + ['이전글', '/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.prev?.id}}'], + ['다음글', '/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.next?.id}}'], + ]; + + it.each(legs)('%s leg 실행 시 page/search/category 가 모두 살아남는다', async (_label, destPath) => { + window.history.replaceState({}, '', '/admin/board/free/post/45?page=2&search=테스트&category=공지'); + + const q = queryOf(await runNav(navLeg('partials/admin_board_post_detail/_post_card_content.json', destPath))); + + expect(q.get('page')).toBe('2'); + expect(q.get('search')).toBe('테스트'); + expect(q.get('category')).toBe('공지'); + }); + + it("상세 '목록' 버튼 실행 시 목록 상태가 그대로 복귀된다", async () => { + window.history.replaceState({}, '', '/admin/board/free/post/45?page=2&search=테스트'); + + const q = queryOf(await runNav(navLeg('admin_board_post_detail.json', '/admin/board/{{route.slug}}'))); + + expect(q.get('page')).toBe('2'); + expect(q.get('search')).toBe('테스트'); + }); + + it('검색 실행(Enter) 은 page 를 떨구고 표시 개수는 유지한다', async () => { + window.history.replaceState({}, '', '/admin/board/free?page=5&per_page=30&sort_by=created_at'); + + const action = collectNavActions(readLayout('admin_board_posts_index.json')).find( + (a) => (a as unknown as { type?: string }).type === 'keypress' + ); + expect(action, 'admin_board_posts_index.json 에 검색 Enter navigate 가 없습니다.').toBeTruthy(); + + const q = queryOf(await runNav(action as NavAction)); + + // page 는 새 검색이므로 1페이지로 되돌린다(파라미터 제거). 되돌리지 않으면 결과의 5페이지로 가 빈 화면이 열린다. + expect(q.get('page')).toBeNull(); + expect(q.get('per_page')).toBe('30'); + expect(q.get('sort_by')).toBe('created_at'); + }); + + it('이전글 → 목록 순서로 이어가도 목록 페이지가 복원된다', async () => { + window.history.replaceState({}, '', '/admin/board/free/post/45?page=2&search=테스트'); + + // ① 이전글로 이동 → 이동 결과를 실제 URL 로 반영 (다음 leg 의 mergeQuery 입력) + const afterPrev = await runNav( + navLeg( + 'partials/admin_board_post_detail/_post_card_content.json', + '/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.prev?.id}}' + ) + ); + window.history.replaceState({}, '', afterPrev); + + // ② 그 상태에서 '목록' 복귀 + const q = queryOf(await runNav(navLeg('admin_board_post_detail.json', '/admin/board/{{route.slug}}'))); + + expect(q.get('page')).toBe('2'); + expect(q.get('search')).toBe('테스트'); + }); +}); + +// --------------------------------------------------------------------------- +// 검색·필터 변경 시 page 되돌림 (#75) +// +// mergeQuery 는 현재 페이지까지 함께 나른다. 그래서 목록을 좁히는 조건(검색어·카테고리·상태)을 +// 바꾸는 액션은 page 를 명시적으로 되돌려야 한다. 되돌리지 않으면 5페이지를 보던 중 검색했을 때 +// 결과의 5페이지로 이동해 빈 화면이 열린다. 한 화면 안에서 진입점마다 갈리면(버튼은 되돌리고 +// Enter 는 안 되돌림) 같은 기능이 다르게 동작한다. +// --------------------------------------------------------------------------- + +/** 목록을 좁히는 조건 키 — 바뀌면 결과 건수가 달라지므로 page 를 되돌려야 한다. */ +const NARROWING_KEY = /^(filters\[\d+\]\[value\]|search|search_keyword|category|status|target_status|type)$/; + +/** page 되돌림으로 인정하는 값 — `""`(파라미터 제거) 또는 1. */ +function isPageReset(value: unknown): boolean { + return value === '' || value === 1 || value === '1'; +} + +describe('#75 검색·필터 액션은 page 를 되돌린다 — 전수', () => { + it.each([['admin_board_posts_index.json'], ['admin_board_reports_index.json']])( + '%s 의 조건 변경 navigate 는 모두 page 를 되돌린다', + (rel) => { + const offenders = collectNavActions(readLayout(rel)) + .filter((a) => { + const q = a.params.query; + if (!q || typeof q !== 'object' || Array.isArray(q)) return false; + const keys = Object.keys(q as Record); + if (!keys.some((k) => NARROWING_KEY.test(k))) return false; + return !isPageReset((q as Record).page); + }) + .map((a) => `${a.params.path} → ${JSON.stringify(a.params.query)}`); + + expect(offenders, `조건을 바꾸면서 page 를 그대로 두는 navigate: \n ${offenders.join('\n ')}`).toEqual( + [] + ); + } + ); + + // mergeQuery 가 이미 현재 정렬을 나르므로, 검색 액션이 정렬을 다시 적어 보낼 필요가 없다. + // 열거가 남아 있으면 다음 편집자가 "여기에 적힌 값이 정렬의 근거" 로 오해한다 (기본값은 데이터소스가 정한다). + it('신고 목록 검색 액션은 정렬 키를 다시 적어 보내지 않는다', () => { + const search = (readLayout('admin_board_reports_index.json') as { + named_actions: { searchBoardReports: NavAction }; + }).named_actions.searchBoardReports; + + const keys = Object.keys(search.params.query as Record); + + expect(keys).not.toContain('sort_by'); + expect(keys).not.toContain('sort_order'); + }); +}); diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_form.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_form.json index d7c7abff..c828cb38 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_form.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_form.json @@ -325,7 +325,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/boards" + "path": "/admin/boards", + "mergeQuery": true, + "query": {} } } ] @@ -357,7 +359,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/boards" + "path": "/admin/boards", + "mergeQuery": true, + "query": {} } } ] diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_index.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_index.json index 9f70763d..76caecc7 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_index.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_index.json @@ -69,11 +69,13 @@ }, "actions": [ { + "comment": "새로고침은 보고 있던 목록을 그대로 다시 부르는 것이다 — 페이지/검색을 유지한다 (#75).", "type": "click", "handler": "navigate", "params": { "path": "/admin/boards", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], @@ -102,7 +104,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/boards/create" + "path": "/admin/boards/create", + "mergeQuery": true, + "query": {} } } ], @@ -341,8 +345,8 @@ "handler": "navigate", "params": { "path": "/admin/boards/{{row.slug}}/edit", - "mergeQuery": false, - "query": [] + "mergeQuery": true, + "query": {} } }, "manage_posts": { @@ -638,10 +642,15 @@ "target": "copy_confirm_modal" }, { + "comment": "복사 생성 폼으로 이동 — copy_id 는 query 로 넘긴다. mergeQuery 는 path 의 인라인 쿼리스트링을 버리므로 path 에 붙여두면 사라진다 (#75).", "type": "click", "handler": "navigate", "params": { - "path": "/admin/boards/create?copy_id={{_global.modal_data.id}}" + "path": "/admin/boards/create", + "mergeQuery": true, + "query": { + "copy_id": "{{_global.modal_data.id}}" + } } } ] diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_post_detail.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_post_detail.json index 59546aa2..f0553df0 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_post_detail.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_post_detail.json @@ -120,7 +120,8 @@ "handler": "navigate", "params": { "path": "/admin/board/{{route.slug}}/post/{{route?.id}}", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], @@ -147,7 +148,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}" + "path": "/admin/board/{{route.slug}}", + "mergeQuery": true, + "query": {} } } ], @@ -377,10 +380,12 @@ "if": "{{_global.modal_data?.type === 'comment'}}" }, { + "comment": "삭제 후 복귀 — 게시글이면 목록으로, 답변이면 원글 상세로 돌아간다. 어느 쪽이든 목록 클러스터 안이므로 목록 상태를 유지한다. 종전에는 mergeQuery 가 분기 표현식이라 답변 삭제 경로에서만 페이지/검색이 조용히 사라졌다 (#75).", "handler": "navigate", "params": { "path": "{{_global.modal_data?.type === 'post' ? '/admin/board/' + route.slug : '/admin/board/' + route.slug + '/post/' + route.id}}", - "mergeQuery": "{{_global.modal_data?.type === 'post'}}" + "mergeQuery": true, + "query": {} }, "if": "{{_global.modal_data?.type !== 'comment'}}" }, diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_post_form.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_post_form.json index 24456356..0cdf2fc9 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_post_form.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_post_form.json @@ -139,7 +139,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "{{route?.id ? '/admin/board/' + route.slug + '/post/' + route.id : '/admin/board/' + route.slug}}" + "path": "{{route?.id ? '/admin/board/' + route.slug + '/post/' + route.id : '/admin/board/' + route.slug}}", + "mergeQuery": true, + "query": {} } } ], @@ -206,7 +208,9 @@ { "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}/post/{{route?.id ?? result?.data?.id}}" + "path": "/admin/board/{{route.slug}}/post/{{route?.id ?? result?.data?.id}}", + "mergeQuery": true, + "query": {} } } ], @@ -430,7 +434,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "{{route?.id ? '/admin/board/' + route.slug + '/post/' + route.id : '/admin/board/' + route.slug}}" + "path": "{{route?.id ? '/admin/board/' + route.slug + '/post/' + route.id : '/admin/board/' + route.slug}}", + "mergeQuery": true, + "query": {} } } ], @@ -498,7 +504,9 @@ { "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}/post/{{route?.id ?? result?.data?.id}}" + "path": "/admin/board/{{route.slug}}/post/{{route?.id ?? result?.data?.id}}", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_posts_index.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_posts_index.json index 1b519ebe..a77b2db0 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_posts_index.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_posts_index.json @@ -148,11 +148,13 @@ }, "actions": [ { + "comment": "새로고침은 보고 있던 목록을 그대로 다시 부르는 것이다 — 페이지/검색/필터를 유지한다 (#75).", "type": "click", "handler": "navigate", "params": { "path": "/admin/board/{{route.slug}}", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], @@ -180,7 +182,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}/create" + "path": "/admin/board/{{route.slug}}/create", + "mergeQuery": true, + "query": {} } } ], @@ -273,11 +277,13 @@ { "type": "keypress", "key": "Enter", + "comment": "검색 실행 — 검색 버튼과 동일하게 page 는 1페이지로 되돌린다. 되돌리지 않으면 5페이지를 보던 중 검색 시 결과의 5페이지로 가 빈 화면이 열린다 (#75).", "handler": "navigate", "params": { "path": "/admin/board/{{route.slug}}", "mergeQuery": true, "query": { + "page": "", "filters[0][field]": "{{_local.searchField || 'all'}}", "filters[0][value]": "{{$event.target.value}}", "filters[0][operator]": "like" @@ -498,12 +504,14 @@ "actions": [ { "type": "change", + "comment": "상태 필터 변경 — 카테고리 필터와 동일하게 page 를 1페이지로 되돌린다. 되돌리지 않으면 뒤쪽 페이지에서 필터를 바꿀 때 빈 화면이 열린다 (#75).", "handler": "navigate", "params": { "path": "/admin/board/{{route.slug}}", "mergeQuery": true, "query": { - "status": "{{$event.target.value}}" + "status": "{{$event.target.value}}", + "page": 1 } } } @@ -556,6 +564,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 초기화 버튼 — 목록 상태를 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "type": "click", "handler": "navigate", "params": { @@ -589,11 +598,13 @@ "actions": [ { "type": "click", + "comment": "검색 실행 — 열거한 검색 조건만 덮어쓰고 정렬/페이지당 개수 등 나머지 목록 상태는 유지한다. page 는 새 검색이므로 1페이지로 되돌린다 (#75).", "handler": "navigate", "params": { "path": "/admin/board/{{route.slug}}", - "mergeQuery": false, + "mergeQuery": true, "query": { + "page": "", "filters[0][field]": "{{_local.searchField || 'all'}}", "filters[0][value]": "{{_local.searchQuery || ''}}", "filters[0][operator]": "like", @@ -835,7 +846,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/board/{{row.slug}}/post/{{row.id}}" + "path": "/admin/board/{{row.slug}}/post/{{row.id}}", + "mergeQuery": true, + "query": {} } } ] @@ -1127,7 +1140,7 @@ "params": { "path": "/admin/board/{{route.slug}}", "mergeQuery": true, - "query": [] + "query": {} } }, { diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_reports_detail.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_reports_detail.json index 65a7564a..a349d7f9 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_reports_detail.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_reports_detail.json @@ -105,7 +105,8 @@ "handler": "navigate", "params": { "path": "/admin/boards/reports/{{route.id}}", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], @@ -132,7 +133,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/boards/reports" + "path": "/admin/boards/reports", + "mergeQuery": true, + "query": {} } } ], @@ -338,7 +341,8 @@ "handler": "navigate", "params": { "path": "/admin/boards/reports/{{route.id}}", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_reports_index.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_reports_index.json index 517c3bd2..90d8a56d 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_reports_index.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_reports_index.json @@ -66,11 +66,13 @@ ], "named_actions": { "searchBoardReports": { + "comment": "검색 실행 — 열거한 검색 조건만 덮어쓰고 페이지당 개수 등 나머지 목록 상태는 유지한다. page 는 새 검색이므로 1페이지로 되돌린다 (#75).", "handler": "navigate", "params": { "path": "/admin/boards/reports", - "mergeQuery": false, + "mergeQuery": true, "query": { + "page": "", "filters[0][field]": "{{_local.searchField || 'all'}}", "filters[0][value]": "{{_local.searchQuery || ''}}", "filters[0][operator]": "like", @@ -78,9 +80,7 @@ "type": "{{((_global.typeFilter ?? query['type[]'] ?? []) || []).length > 0 ? (_global.typeFilter ?? query['type[]']) : null}}", "target_status": "{{((_global.targetStatusFilter ?? query['target_status[]'] ?? []) || []).length > 0 ? (_global.targetStatusFilter ?? query['target_status[]']) : null}}", "reported_at_from": "{{_global.dateFrom !== undefined ? _global.dateFrom : (query.reported_at_from || '')}}", - "reported_at_to": "{{_global.dateTo !== undefined ? _global.dateTo : (query.reported_at_to || '')}}", - "sort_by": "{{query.sort_by || 'last_reported_at'}}", - "sort_order": "{{query.sort_order || 'desc'}}" + "reported_at_to": "{{_global.dateTo !== undefined ? _global.dateTo : (query.reported_at_to || '')}}" } } } @@ -120,11 +120,13 @@ }, "actions": [ { + "comment": "새로고침은 보고 있던 목록을 그대로 다시 부르는 것이다 — 페이지/검색/필터를 유지한다 (#75).", "type": "click", "handler": "navigate", "params": { "path": "/admin/boards/reports", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], @@ -1244,6 +1246,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 초기화 버튼 — 목록 상태를 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "type": "click", "handler": "navigate", "params": { @@ -2202,7 +2205,9 @@ "view": { "handler": "navigate", "params": { - "path": "/admin/boards/reports/{{$args[1]?.id}}" + "path": "/admin/boards/reports/{{$args[1]?.id}}", + "mergeQuery": true, + "query": {} } }, "go_to_board": { diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_settings.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_settings.json index d0f09a00..e6b0877b 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_settings.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/admin_board_settings.json @@ -347,6 +347,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 탭 전환 — 탭마다 다루는 대상이 달라 이전 탭의 목록 상태를 물려받으면 오히려 잘못된 화면이 된다.", "handler": "navigate", "params": { "path": "/admin/boards/settings", diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_post_card_content.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_post_card_content.json index debe17aa..7e70ae62 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_post_card_content.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_post_card_content.json @@ -155,10 +155,15 @@ "if": "{{post?.data?.board?.use_reply && !post?.data?.is_notice && (post?.data?.depth ?? 0) < (post?.data?.board?.max_reply_depth ?? 1) && post?.data?.status !== 'blinded' && post?.data?.status !== 'deleted' && !post?.data?.deleted_at}}", "actions": [ { + "comment": "답변 작성 폼으로 이동 — parent_id 는 query 로 넘긴다. mergeQuery 는 path 의 인라인 쿼리스트링을 버리므로 path 에 붙여두면 사라진다 (#75).", "type": "click", "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}/create?parent_id={{post?.data?.id}}" + "path": "/admin/board/{{route.slug}}/create", + "mergeQuery": true, + "query": { + "parent_id": "{{post?.data?.id}}" + } } } ], @@ -261,7 +266,9 @@ "edit": { "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}/{{post?.data?.id}}/edit" + "path": "/admin/board/{{route.slug}}/{{post?.data?.id}}/edit", + "mergeQuery": true, + "query": {} } }, "blind": { @@ -1166,7 +1173,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.prev?.id}}" + "path": "/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.prev?.id}}", + "mergeQuery": true, + "query": {} } } ], @@ -1228,7 +1237,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.next?.id}}" + "path": "/admin/board/{{route.slug}}/post/{{post?.data?.navigation?.next?.id}}", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_reply_card_content.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_reply_card_content.json index 1df8d3b7..0cdf8d82 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_reply_card_content.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_detail/_reply_card_content.json @@ -154,7 +154,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/board/{{route.slug}}/post/{{item.id}}" + "path": "/admin/board/{{route.slug}}/post/{{item.id}}", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_report_policy.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_report_policy.json index c4c748c0..093f4ac2 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_report_policy.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_report_policy.json @@ -766,7 +766,7 @@ "params": { "actions": [ { "handler": "setState", "params": { "target": "global", "activeBoardSettingsTab": "notification_definitions" } }, - { "handler": "replaceUrl", "params": { "query": { "tab": "notification_definitions" } } } + { "comment": "audit:allow layout-list-context-navigate-merge-query 다른 탭으로 넘어가는 이동이다 — 알림 정의 탭은 자기 검색어와 페이지를 따로 갖는 별개의 목록이라 신고 정책 탭의 조건을 물려주지 않는다.", "handler": "replaceUrl", "params": { "query": { "tab": "notification_definitions" } } } ] } } @@ -915,7 +915,7 @@ "params": { "actions": [ { "handler": "setState", "params": { "target": "global", "activeBoardSettingsTab": "notification_definitions" } }, - { "handler": "replaceUrl", "params": { "query": { "tab": "notification_definitions" } } } + { "comment": "audit:allow layout-list-context-navigate-merge-query 다른 탭으로 넘어가는 이동이다 — 알림 정의 탭은 자기 검색어와 페이지를 따로 갖는 별개의 목록이라 신고 정책 탭의 조건을 물려주지 않는다.", "handler": "replaceUrl", "params": { "query": { "tab": "notification_definitions" } } } ] } } diff --git a/modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-admin-list-context-round-trip.spec.ts b/modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-admin-list-context-round-trip.spec.ts new file mode 100644 index 00000000..1755f644 --- /dev/null +++ b/modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-admin-list-context-round-trip.spec.ts @@ -0,0 +1,79 @@ +/** + * 관리자 게시글 목록 컨텍스트 왕복 — 목록 상태(page/검색)가 상세·폼을 거쳐도 살아남는지 (공개 이슈 #75). + * + * 결함: 목록 클러스터(목록 ↔ 상세 ↔ 작성/수정 폼) 안의 이동에 `mergeQuery` 가 빠져 있어, + * 2페이지에서 글을 열었다가 목록으로 돌아오면 1페이지로 되돌아갔다. 특히 폼 '취소' 버튼은 + * 목적지가 삼항 표현식이라 정적 검사에서도 오래 빠져 있었다 — 저장 leg 만 고쳐지고 취소 leg 는 + * 남아 "저장하면 2페이지 유지 / 취소하면 1페이지 리셋" 비대칭이 생겼다. + * + * 단위/정적: + * - modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts + * 가 실 JSON 의 액션 params 를 전수 고정 + * - audit 룰 layout-list-context-navigate-merge-query 가 표현식 경로까지 판정해 재발 차단 + * 이 spec 은 브라우저 수준(실제 주소창 URL)을 담당한다. + * + * 시드 의존: 샘플 시드의 자유게시판(`free`, 30건) — 관리자 목록 15건/페이지이므로 2페이지가 존재한다. + * + * @scenario board-list-context-round-trip + * @axes leg=enter leg=back + * @effects list_return_preserves_query + */ +import { test, expect, authenticatePage } from '../../fixtures/board-auth'; + +const SLUG = 'free'; +const LIST_URL = `/admin/board/${SLUG}`; + +/** + * 현재 URL 의 쿼리 파라미터를 돌려줍니다. + * + * @param url 페이지 URL + * @returns 쿼리 파라미터 + */ +function queryOf(url: string): URLSearchParams { + return new URL(url).searchParams; +} + +test.describe('관리자 게시글 목록 컨텍스트 왕복 (#75)', () => { + // @scenario leg=enter + // @effects list_return_preserves_query + test('2페이지에서 글 제목을 누르면 상세 URL 에 page 가 실린다', async ({ page, boardManageToken }) => { + await authenticatePage(page, boardManageToken); + await page.goto(`${LIST_URL}?page=2`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + // 제목 Span 이 이동 액션을 갖는다 (행 전체가 아니라 제목만 클릭 대상). + await page.locator('tbody tr span.cursor-pointer').first().click(); + await page.waitForURL(new RegExp(`/admin/board/${SLUG}/post/\\d+`), { timeout: 30_000 }); + + expect(queryOf(page.url()).get('page')).toBe('2'); + }); + + // @scenario leg=back + // @effects list_return_preserves_query + test('상세에서 목록으로 돌아오면 2페이지가 복원된다', async ({ page, boardManageToken }) => { + await authenticatePage(page, boardManageToken); + await page.goto(`${LIST_URL}?page=2`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + await page.locator('tbody tr span.cursor-pointer').first().click(); + await page.waitForURL(new RegExp(`/admin/board/${SLUG}/post/\\d+`), { timeout: 30_000 }); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#back_button').click(); + await page.waitForURL(new RegExp(`/admin/board/${SLUG}\\?`), { timeout: 30_000 }); + + expect(queryOf(page.url()).get('page')).toBe('2'); + }); + + // @scenario leg=back + // @effects list_return_preserves_query + test('작성 폼에서 취소하면 보고 있던 페이지로 돌아온다', async ({ page, boardManageToken }) => { + await authenticatePage(page, boardManageToken); + await page.goto(`${LIST_URL}/create?page=2`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#header_cancel_button').click(); + await page.waitForURL(new RegExp(`/admin/board/${SLUG}\\?`), { timeout: 30_000 }); + + expect(queryOf(page.url()).get('page')).toBe('2'); + }); +}); diff --git a/modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts b/modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts new file mode 100644 index 00000000..6eb9b588 --- /dev/null +++ b/modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts @@ -0,0 +1,156 @@ +/** + * 목록 컨텍스트 왕복 — 이전글/다음글 leg 의 URL 목록 상태 보존 (공개 이슈 #75). + * + * 결함: 목록에서 상세로 들어갈 때는 `mergeQuery: true` 로 page/search/category 가 상세 URL 에 + * 실렸지만, 상세의 이전글/다음글 버튼은 규약에서 누락돼 `del` 하나만 남기고 나머지를 전부 + * 떨궜다. 그 뒤 '목록' 버튼은 복원할 상태가 없어 1페이지로 되돌아갔다. + * + * 이 spec 은 시드 의존을 최소화한다 — 샘플 시드의 자유게시판(`free`, 28건/3페이지)만 있으면 + * 돌아간다. 별도 전용 게시판(navtest) 시드를 요구하는 board-post-navigation.spec.ts 와 달리 + * skip 없이 실행된다. + * + * 단위/렌더링: + * - templates/_bundled/sirsoft-basic/src/__tests__/layouts/board-post-navigation-list-return.test.tsx + * 가 실 `_navigation.json` 의 액션 params 로 mergeQuery 왕복을 고정 + * - .claude/scripts/audit/rules/layout-list-context-navigate-merge-query.cjs 가 전 저장소 재발 차단 + * 이 spec 은 브라우저 수준(실제 URL + 목록 API 요청 파라미터)을 담당한다. + * + * @scenario board-list-context-round-trip + * @axes leg=enter leg=back leg=prev leg=next + * @effects navigation_preserves_list_query, + * list_return_preserves_query + */ +import { test, expect } from '@playwright/test'; + +const BOARD_SLUG = 'free'; +const LIST_URL = `/board/${BOARD_SLUG}`; + +/** + * 현재 URL 의 쿼리 파라미터를 돌려줍니다. + * + * @param url 페이지 URL + * @returns 쿼리 파라미터 + */ +function queryOf(url: string): URLSearchParams { + return new URL(url).searchParams; +} + +/** + * 목록의 게시글 행 로케이터. + * + * basic 형 목록의 행은 `` 가 아니라 navigate 액션이 달린 Button 이며, 접근성 이름이 + * "번호 제목 … 작성일 조회수" 형태다. 페이지네이션 버튼("페이지 1")과 구분하기 위해 + * 번호로 시작하는 이름만 고른다. + * + * @param page Playwright 페이지 + * @returns 행 로케이터 + */ +function postRows(page: import('@playwright/test').Page) { + return page.getByRole('button', { name: /^\d+\s+\S/ }); +} + +/** + * 목록 2페이지로 진입해 첫 글 상세까지 들어갑니다. + * + * @param page Playwright 페이지 + * @returns 진입한 상세 URL + */ +async function enterDetailFromPage2(page: import('@playwright/test').Page): Promise { + await page.goto(`${LIST_URL}?page=2`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await postRows(page).first().click(); + await page.waitForURL(new RegExp(`/board/${BOARD_SLUG}/\\d+`), { timeout: 30_000 }); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + return page.url(); +} + +test.describe('목록 컨텍스트 왕복 — 이전글/다음글 (#75)', () => { + // @scenario leg=enter + // @effects list_return_preserves_query + test('목록 2페이지에서 상세로 들어가면 page 가 상세 URL 에 실린다', async ({ page }) => { + const detailUrl = await enterDetailFromPage2(page); + + expect(detailUrl).toContain(`/board/${BOARD_SLUG}/`); + expect(queryOf(detailUrl).get('page')).toBe('2'); + }); + + // @scenario leg=prev + // @effects navigation_preserves_list_query + test('이전글로 이동해도 page 가 유지된다', async ({ page }) => { + await enterDetailFromPage2(page); + + const prev = page.getByRole('button', { name: /(이전글|Previous)(?!\s*page)/i }).first(); + await prev.click(); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + expect(queryOf(page.url()).get('page')).toBe('2'); + }); + + // @scenario leg=next + // @effects navigation_preserves_list_query + test('다음글로 이동해도 page 가 유지된다', async ({ page }) => { + await enterDetailFromPage2(page); + + const next = page.getByRole('button', { name: /(다음글|Next)(?!\s*page)/i }).first(); + await next.click(); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + expect(queryOf(page.url()).get('page')).toBe('2'); + }); + + // @scenario leg=prev, leg=back + // @effects navigation_preserves_list_query, list_return_preserves_query + test('이전글 3회 연속 후 목록으로 돌아가도 2페이지가 복원된다', async ({ page }) => { + await enterDetailFromPage2(page); + + for (let i = 0; i < 3; i++) { + const prev = page.getByRole('button', { name: /(이전글|Previous)(?!\s*page)/i }).first(); + if (!(await prev.isVisible().catch(() => false))) break; + await prev.click(); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + expect(queryOf(page.url()).get('page'), `${i + 1}회차 이전글 이동에서 page 소실`).toBe('2'); + } + + // 목록 복귀 — 목록 API 가 실제로 2페이지를 요청해야 한다. + // 직전 이동 직후에는 상세가 다시 렌더되며 버튼이 교체되므로, 버튼이 안정된 뒤 클릭한다. + const listButton = page.getByRole('button', { name: /(목록|Back to List)$/i }).first(); + await expect(listButton).toBeVisible({ timeout: 30_000 }); + + const [listRequest] = await Promise.all([ + page.waitForRequest( + (req) => req.url().includes('/posts') && req.url().includes('page=2'), + { timeout: 30_000 } + ), + listButton.click(), + ]); + + expect(listRequest.url()).toContain('page=2'); + await page.waitForURL(new RegExp(`/board/${BOARD_SLUG}\\?`), { timeout: 30_000 }); + expect(queryOf(page.url()).get('page')).toBe('2'); + }); + + // @scenario leg=prev + // @effects navigation_preserves_list_query + test('검색어가 걸린 상태에서도 이전글 이동이 검색어를 유지한다', async ({ page }) => { + await page.goto(`${LIST_URL}?page=1&search=맛집`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + const row = postRows(page).first(); + if (!(await row.isVisible().catch(() => false))) { + test.skip(true, '검색 결과가 없어 이 축을 실행할 수 없습니다.'); + return; + } + await row.click(); + await page.waitForURL(new RegExp(`/board/${BOARD_SLUG}/\\d+`), { timeout: 30_000 }); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + expect(queryOf(page.url()).get('search')).toBe('맛집'); + + const prev = page.getByRole('button', { name: /(이전글|Previous)(?!\s*page)/i }).first(); + if (await prev.isVisible().catch(() => false)) { + await prev.click(); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + expect(queryOf(page.url()).get('search')).toBe('맛집'); + } + }); +}); diff --git a/modules/_bundled/sirsoft-board/tests/scenarios/board-list-context-round-trip.yaml b/modules/_bundled/sirsoft-board/tests/scenarios/board-list-context-round-trip.yaml new file mode 100644 index 00000000..f171fa49 --- /dev/null +++ b/modules/_bundled/sirsoft-board/tests/scenarios/board-list-context-round-trip.yaml @@ -0,0 +1,46 @@ +feature: 목록 컨텍스트 왕복 시 URL 목록 상태 보존 + +description: | + 페이지네이션 목록 화면과 그에 딸린 상세·형제 상세(이전글/다음글)·작성/수정 폼·확인 모달은 + 하나의 "목록 클러스터" 다. 이 클러스터 안에서의 모든 이동은 URL 에 실린 목록 상태 + (page / search / category / filters[*] / 정렬 / per_page)를 손실 없이 이어받아야 한다. + + 공개 이슈 #75 (@jiwonpapa) 는 이 규약의 **부분 적용**이 원인이었다. + - 45-1 에서 목록 진입(enter)·목록 복귀(back) leg 에는 mergeQuery:true 가 적용됐다. + - 그러나 같은 화면의 이전글/다음글(prev/next) leg 은 누락돼 `del` 하나만 남기고 + page/search/category 를 전부 떨궜다. + - 그 뒤 '목록' 버튼은 복원할 상태가 없어 1페이지로 되돌아갔다. + + 따라서 변별 축은 글 유형이 아니라 **이동 leg** 이다. post_kind 와는 직교하지 않는다 — + 답글·공지 상세에는 prev/next leg 자체가 존재하지 않으며, 그 부재는 + board-post-navigation.yaml 의 navigation_null_for_reply / navigation_null_for_notice 가 담당한다. + + 수정 범위는 게시판에 한정되지 않는다. 동일 결함이 관리자 게시판·이커머스·페이지·회원· + 마이페이지 등 9개 확장에 걸쳐 있었고, 전 저장소를 한 번에 교정했다. 재발은 audit 룰 + `layout-list-context-navigate-merge-query` (error) 가 차단한다. + +axes: + # 목록 클러스터 안에서 발생하는 이동 leg. 하나라도 빠지면 그 지점에서 상태가 끊긴다. + leg: [enter, back, prev, next] # 목록→상세 / 상세→목록 / 이전글 / 다음글 + +effects: + - navigation_preserves_list_query # 형제 상세(prev/next) 이동이 목록 상태를 승계 + - list_return_preserves_query # 목록 복귀가 상세 URL 의 목록 상태를 그대로 복원 + +test_files: + - modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts + - modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-admin-list-context-round-trip.spec.ts + - templates/_bundled/sirsoft-basic/src/__tests__/layouts/board-post-navigation-list-return.test.tsx + - modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts + - modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts + - modules/_bundled/sirsoft-page/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts + - templates/_bundled/sirsoft-admin_basic/src/__tests__/layouts/admin-list-context-round-trip.test.ts + - .claude/scripts/audit/__tests__/layout-list-context-navigate-merge-query.test.cjs + +validation: + note: | + leg 4종은 E2E(board-list-context-round-trip.spec.ts)가 실제 브라우저 URL 과 목록 API 요청 + 파라미터로 실측한다. 확장별 레이아웃 테스트는 실 JSON 의 액션 params 를 읽어 클러스터 내 + navigate 가 전부 mergeQuery:true 인지 전수 고정하고, audit 룰 테스트가 저장소 전체 잔여 + 위반 0건을 회귀로 못박는다. 엔진 게이트(mergeQuery:true + query 생략) 는 + ActionDispatcher.test.ts 가 navigate/replaceUrl 양쪽에서 검증한다. diff --git a/modules/_bundled/sirsoft-board/tests/scenarios/board-post-navigation.yaml b/modules/_bundled/sirsoft-board/tests/scenarios/board-post-navigation.yaml index 8b5823c0..f1879fb9 100644 --- a/modules/_bundled/sirsoft-board/tests/scenarios/board-post-navigation.yaml +++ b/modules/_bundled/sirsoft-board/tests/scenarios/board-post-navigation.yaml @@ -28,6 +28,9 @@ axes: # navigation 결과를 가르는 핵심 변별 축은 글 유형(post_kind). # 카테고리 유무·목록 위치·비밀/블라인드 변종은 effects 와 개별 테스트 메서드로 커버한다. post_kind: [original, reply, notice] # 원글(정상 순회) / 답글(미노출) / 공지(미노출) + # 목록 상태 보존(#75)의 변별 축은 "어느 leg 으로 이동했는가" 이며 post_kind 와 직교하지 않는다 + # (답글·공지에는 이전/다음 leg 자체가 없다). 별도 기능으로 분리한다 → + # tests/scenarios/board-list-context-round-trip.yaml effects: - navigation_limited_to_same_category # 47-1: 동일 카테고리 글만 prev/next @@ -38,12 +41,14 @@ effects: - navigation_blinded_excluded # 47-2: 블라인드 제외 (기존 유지) - navigation_boundary_null # 47-3: 첫/마지막 글 prev/next null - list_return_preserves_query # 45-1: 행 클릭→상세→목록 복귀 시 query 보존 + - navigation_preserves_list_query # 75: 이전글/다음글 leg 도 목록 상태(page/search/category)를 승계 test_files: - modules/_bundled/sirsoft-board/tests/Feature/User/PostNavigationTest.php - modules/_bundled/sirsoft-board/tests/Feature/User/PostNavigationApiTest.php - templates/_bundled/sirsoft-basic/src/__tests__/layouts/board-post-navigation-list-return.test.tsx - modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-post-navigation.spec.ts + - modules/_bundled/sirsoft-board/tests/Playwright/specs/user/board-list-context-round-trip.spec.ts validation: note: | diff --git a/modules/_bundled/sirsoft-ecommerce/CHANGELOG.md b/modules/_bundled/sirsoft-ecommerce/CHANGELOG.md index 6d1070e1..73fe64b1 100644 --- a/modules/_bundled/sirsoft-ecommerce/CHANGELOG.md +++ b/modules/_bundled/sirsoft-ecommerce/CHANGELOG.md @@ -18,6 +18,14 @@ ### Fixed +- 휴대폰으로 관리자 주문 목록을 볼 때 왼쪽 위 '뒤로' 버튼을 누르면 이전 화면이 아니라 빈 페이지로 넘어가던 문제를 수정했습니다. +- 관리자 주문·상품·쿠폰·배송정책·리뷰·마일리지 목록에서 상세나 등록/수정 화면에 다녀오면 걸어 둔 필터와 페이지가 사라지던 문제를 수정했습니다. 필터를 여러 개 건 상태에서 주문 하나를 확인하고 돌아와도 조건이 그대로 유지됩니다. 정렬·표시 개수를 바꾸거나 새로고침해도 걸어 둔 조건은 그대로입니다. 반대로 초기화 버튼과 프리셋 적용은 종전처럼 조건을 새로 세팅합니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 브랜드·상품 공통정보·상품 고시정보 목록에서 검색어(브랜드는 정렬 포함)를 걸어 둔 채 새로고침 버튼을 누르면 걸어 둔 검색이 풀려 전체 목록으로 돌아가던 문제를 수정했습니다. 이제 새로고침은 보던 조건 그대로 다시 불러옵니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 주문 목록에서 '이 주문자의 주문 검색'을 실행하면 검색창은 비어 보이는데 직전 검색어가 계속 적용돼 결과가 어긋나던 문제를 수정했습니다. 비회원 주문자명으로 검색할 때 회원 지정 조건이 함께 걸려 결과가 비어 보이던 문제도 함께 해소되며, 주문 상세의 주문자 카드에서 같은 검색을 실행할 때도 동일하게 적용됩니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 브랜드 관리에서 브랜드명으로 검색하면 결과가 항상 비어 있던 문제를 수정했습니다. 이제 브랜드명·slug·웹사이트 주소 중 하나만 일치해도 검색됩니다. +- 관리자 상품 등록/수정 화면의 배송 정보에서 '배송정책 등록' 버튼을 눌러도 아무 반응이 없던 문제를 수정했습니다. 이제 배송정책 등록 화면으로 이동합니다. +- 관리자 브랜드·상품 카테고리·상품 공통정보·상품 고시정보 목록에서 왼쪽 목록의 항목을 고르면 걸어 둔 검색어(브랜드는 정렬 포함)가 사라지던 문제를 수정했습니다. 항목 선택은 선택 상태만 주소에 기록하고 목록 조건은 그대로 둡니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 쿠폰 목록에서 '등록' 으로 들어가거나 상품을 새로 저장한 직후, 보고 있던 목록의 조건이 사라져 취소·복귀 시 1페이지로 돌아가던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 상품을 장바구니에 담거나 바로 구매할 때, 표시 언어(로케일)나 관리자의 옵션 이름 수정과 무관하게 선택한 옵션이 정확히 담기도록 개선했습니다. 특정 상황에서 "해당 옵션 조합을 찾을 수 없습니다" 오류로 담기가 실패하던 문제가 해소됩니다. - 오류 안내가 뜨기는 하지만 내용이 비어 있던 문제를 수정했습니다. 서버가 알려 준 실패 사유가 그대로 표시됩니다. - 헤더에서 통화나 배송 국가를 바꿀 때 저장에 실패해도 아무 안내 없이 넘어가던 문제를 수정했습니다. 실패하면 그 이유가 화면에 표시됩니다. diff --git a/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts new file mode 100644 index 00000000..f0672f66 --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts @@ -0,0 +1,344 @@ +/** + * @file admin-list-context-round-trip.test.ts + * @description 관리자 이커머스 목록 컨텍스트 왕복 시 URL 목록 상태 보존 회귀 (#75) + * + * 결함: 주문/상품/쿠폰/배송정책/리뷰/마일리지 목록에서 상세·폼으로 들어갔다 돌아오면 + * navigate 가 `mergeQuery` 없이 실행되어 page 와 필터 20여 종이 URL 에서 사라졌다. + * 필터를 여러 개 건 상태일수록 손실이 크다. + * + * 검증 방식 2단: + * 1. 실 레이아웃 JSON 전수 분석 — 클러스터 내 navigate 가 모두 `mergeQuery: true` 인지 + * 2. 실 액션을 엔진에 태워 실행(`triggerAction`) — 선언이 실제 목적지 URL 로 이어지는지 + * 손으로 쓴 조각이 아니라 실파일을 읽는다. 선언만 검사하면 "JSON 에 리터럴이 적혀 있다" + * 까지만 고정되고 병합 결과는 미검증으로 남는다. + * + * @scenario leg=row_click|detail_return|form_cancel|filter_apply + * @effects navigation_preserves_list_query + * + * @vitest-environment jsdom + */ + +import { describe, it, expect, afterEach } from 'vitest'; +import fs from 'fs'; +import path from 'path'; + +import { + createLayoutTest, + createMockComponentRegistryWithBasics, +} from '@core/template-engine/__tests__/utils/layoutTestUtils'; + +const LAYOUTS_ROOT = path.resolve(__dirname, '../../../layouts/admin'); + +/** 이 확장이 소유한 페이지네이션 목록 라우트 */ +const LIST_ROUTES = [ + '/admin/ecommerce/orders', + '/admin/ecommerce/products', + '/admin/ecommerce/reviews', + '/admin/ecommerce/promotion-coupons', + '/admin/ecommerce/shipping-policies', + '/admin/ecommerce/mileage-transactions', +]; + +/** 목록 클러스터에 속하는 레이아웃 파일 */ +const CLUSTER_FILES = [ + 'admin_ecommerce_order_detail.json', + 'admin_ecommerce_order_index.json', + 'admin_ecommerce_order_list.json', + 'admin_ecommerce_product_form.json', + 'admin_ecommerce_product_list.json', + 'admin_ecommerce_product_review_index.json', + 'admin_ecommerce_promotion_coupon_form.json', + 'admin_ecommerce_promotion_coupon_list.json', + 'admin_ecommerce_shipping_policy_form.json', + 'admin_ecommerce_shipping_policy_list.json', + 'partials/admin_ecommerce_mileage_transaction_index/_filters.json', + 'partials/admin_ecommerce_mileage_transaction_index/_transactions_table.json', + 'partials/admin_ecommerce_order_detail/_partial_order_info.json', + 'partials/admin_ecommerce_order_list/_partial_filter_section.json', + 'partials/admin_ecommerce_order_list/_partial_order_datagrid.json', + 'partials/admin_ecommerce_order_list/_partial_preset_section.json', + 'partials/admin_ecommerce_product_form/_modal_delete_confirm.json', + 'partials/admin_ecommerce_product_list/_partial_filter_section.json', + 'partials/admin_ecommerce_product_list/_partial_product_datagrid.json', + 'partials/admin_ecommerce_promotion_coupon_list/_partial_coupon_datagrid.json', + 'partials/admin_ecommerce_promotion_coupon_list/_partial_filter_section.json', + 'partials/admin_ecommerce_shipping_policy_list/_modal_copy.json', + 'partials/admin_ecommerce_shipping_policy_list/_partial_datagrid.json', + 'partials/admin_ecommerce_shipping_policy_list/_partial_filter.json', +]; + +/** + * 목적지 경로(`path`)가 없는 선택형 navigate/replaceUrl 을 가진 목록 화면. + * + * `path` 를 생략한 액션은 "현재 URL 을 유지한 채 쿼리만 바꾼다" 는 뜻이라 목록 화면 + * 자신에게 작용한다. 그런데 `mergeQuery` 가 없으면 엔진이 대체 분기로 가 쿼리를 + * **통째로** 새 값으로 바꿔치므로, 방금 건 검색어·정렬이 항목 선택 한 번에 사라진다. + * 목적지가 문자열로 안 적혀 있어 경로 기반 검사(`normalizePath`)의 사각지대다. + */ +const SELF_QUERY_FILES = [ + 'partials/admin_ecommerce_brand_index/_panel_brand_list.json', + 'partials/admin_ecommerce_category_index/_panel_category_list.json', + 'partials/admin_ecommerce_product_common_info_index/_panel_list.json', + 'partials/admin_ecommerce_product_notice_index/_panel_list.json', +]; + +type NavAction = { + handler: string; + comment?: string; + params: { path?: string; mergeQuery?: unknown; query?: unknown }; +}; + +/** + * JSON 트리에서 navigate/replaceUrl 액션을 모두 수집합니다. + * + * @param node 순회 시작 노드 + * @returns 액션 목록 + */ +function collectNavActions(node: unknown): NavAction[] { + const out: NavAction[] = []; + const walk = (n: unknown): void => { + if (Array.isArray(n)) { + n.forEach(walk); + return; + } + if (!n || typeof n !== 'object') return; + const obj = n as Record; + if ( + (obj.handler === 'navigate' || obj.handler === 'replaceUrl') && + obj.params && + typeof obj.params === 'object' + ) { + out.push(obj as unknown as NavAction); + } + Object.values(obj).forEach(walk); + }; + walk(node); + return out; +} + +/** + * 목적지 경로를 비교용 표준형(`{{expr}}` → `*`)으로 바꿉니다. + * + * @param raw 원본 경로 + * @returns 표준형 경로 (판정 불가 시 null) + */ +function normalizePath(raw: unknown): string | null { + if (typeof raw !== 'string' || raw === '') return null; + const p = raw.replace(/\{\{[^}]*\}\}/g, '*').split('?')[0].replace(/\/+$/, ''); + return p.startsWith('/') ? p : null; +} + +/** + * 경로가 목록 라우트와 같은 클러스터인지 판정합니다. + * + * @param dest 표준형 목적지 + * @param list 표준형 목록 라우트 + * @returns 같은 클러스터 여부 + */ +function inFamily(dest: string, list: string): boolean { + return dest === list || dest.startsWith(`${list}/`); +} + +/** + * 레이아웃 파일을 읽어 파싱합니다. + * + * @param rel 레이아웃 루트 기준 상대 경로 + * @returns 파싱된 JSON + */ +function readLayout(rel: string): unknown { + return JSON.parse(fs.readFileSync(path.join(LAYOUTS_ROOT, rel), 'utf8')); +} + +describe('#75 관리자 이커머스 목록 컨텍스트 왕복 — mergeQuery 전수', () => { + it.each(CLUSTER_FILES)('%s 의 클러스터 내 navigate 는 모두 mergeQuery: true', (rel) => { + const offenders = collectNavActions(readLayout(rel)) + .filter((a) => { + if (typeof a.comment === 'string' && a.comment.includes('audit:allow')) return false; + const dest = normalizePath(a.params.path); + if (!dest) return false; + if (!LIST_ROUTES.some((l) => inFamily(dest, l))) return false; + return a.params.mergeQuery !== true; + }) + .map((a) => `${a.params.path} (mergeQuery=${JSON.stringify(a.params.mergeQuery)})`); + + expect(offenders, `목록 상태를 떨구는 navigate: \n ${offenders.join('\n ')}`).toEqual([]); + }); +}); + +describe('#75 목적지가 자기 자신인 액션도 목록 상태를 유지한다', () => { + it.each(SELF_QUERY_FILES)('%s 의 path 없는 navigate/replaceUrl 은 mergeQuery: true', (rel) => { + const offenders = collectNavActions(readLayout(rel)) + .filter((a) => { + if (typeof a.comment === 'string' && a.comment.includes('audit:allow')) return false; + if (normalizePath(a.params.path) !== null) return false; + return a.params.mergeQuery !== true; + }) + .map((a) => `${a.handler} query=${JSON.stringify(a.params.query)}`); + + expect( + offenders, + `현재 URL 의 검색어·정렬을 통째로 덮어쓰는 액션: \n ${offenders.join('\n ')}` + ).toEqual([]); + }); + + it('브랜드를 선택해도 걸어둔 검색어와 정렬이 URL 에 남는다', async () => { + window.history.replaceState({}, '', '/admin/ecommerce/brands?search=나이키&sort=name_desc'); + + const action = collectNavActions( + readLayout('partials/admin_ecommerce_brand_index/_panel_brand_list.json') + ).find((a) => a.handler === 'replaceUrl' && normalizePath(a.params.path) === null); + expect(action, '브랜드 선택 replaceUrl 을 찾지 못했습니다.').toBeTruthy(); + + await runAction(action as NavAction); + const q = new URLSearchParams(window.location.search); + + expect(q.get('search')).toBe('나이키'); + expect(q.get('sort')).toBe('name_desc'); + expect(q.get('mode')).toBe('view'); + }); +}); + +describe('#75 주문자명 검색은 회원 지정 필터를 함께 비운다', () => { + /** + * `orderer_uuid`(회원 지정)와 `search_field=orderer_name`(이름 문자열)은 서로 배타적이다. + * `mergeQuery: true` 가 붙은 뒤로는 이전 화면의 `orderer_uuid` 가 살아남으므로, + * 이름 검색을 걸면 두 조건이 AND 로 겹쳐 결과가 비어 보인다. 이름 검색을 실행하는 + * 모든 leg 이 `orderer_uuid` 를 명시적으로 비워야 한다. + */ + const ORDERER_SEARCH_LEGS: Array<[string, string]> = [ + ['목록 데이터그리드', 'partials/admin_ecommerce_order_list/_partial_order_datagrid.json'], + ['주문 상세 주문자 카드', 'partials/admin_ecommerce_order_detail/_partial_order_info.json'], + ]; + + it.each(ORDERER_SEARCH_LEGS)('%s 의 주문자명 검색이 orderer_uuid 를 비운다', (_label, rel) => { + const actions = collectNavActions(readLayout(rel)).filter( + (a) => + a.params.query !== null && + typeof a.params.query === 'object' && + (a.params.query as Record).search_field === 'orderer_name' + ); + + expect(actions.length, '주문자명 검색 navigate 를 찾지 못했습니다.').toBeGreaterThan(0); + actions.forEach((a) => { + const query = a.params.query as Record; + expect(Object.keys(query)).toContain('orderer_uuid'); + expect(query.orderer_uuid).toBe(''); + }); + }); +}); + +describe('#75 주문 목록 ↔ 상세 왕복 leg 고정', () => { + it('주문 행 클릭이 필터/페이지를 상세로 나른다', () => { + const actions = collectNavActions( + readLayout('partials/admin_ecommerce_order_list/_partial_order_datagrid.json') + ).filter((a) => String(a.params.path ?? '').startsWith('/admin/ecommerce/orders/{{')); + + expect(actions.length).toBeGreaterThan(0); + actions.forEach((a) => expect(a.params.mergeQuery).toBe(true)); + }); + + it("주문 상세 '목록' 버튼이 필터/페이지를 복원한다", () => { + const a = collectNavActions(readLayout('admin_ecommerce_order_detail.json')).find( + (x) => x.params.path === '/admin/ecommerce/orders' + ); + expect(a, "주문 상세의 '목록' navigate 를 찾지 못했습니다.").toBeTruthy(); + expect(a?.params.mergeQuery).toBe(true); + }); +}); + +// --------------------------------------------------------------------------- +// 실행 검증 — 실 액션을 엔진에 태워 목적지 URL 을 확인한다 +// --------------------------------------------------------------------------- + +/** + * 실 JSON 액션을 현재 URL 상태에서 실행하고 목적지를 돌려줍니다. + * + * @param action 실 레이아웃 JSON 에서 뽑은 navigate 액션 + * @returns navigate 목적지 경로 + */ +async function runNav(action: NavAction): Promise { + return (await runAction(action)) as string; +} + +/** + * 실 JSON 액션을 현재 URL 상태에서 실행합니다. + * + * `navigate` 는 목적지가 navigation history 에 쌓이지만 `replaceUrl` 은 주소만 바꾸므로 + * 히스토리가 비어 있다. 결과 확인은 호출 측이 목적으로 나눠서 한다 — + * navigate 는 반환값, replaceUrl 은 `window.location`. + * + * @param action 실 레이아웃 JSON 에서 뽑은 navigate/replaceUrl 액션 + * @returns navigate 목적지 경로 (replaceUrl 이면 undefined) + */ +async function runAction(action: NavAction): Promise { + const utils = createLayoutTest( + { + version: '1.0.0', + layout_name: 'nav_action_probe', + data_sources: [], + components: [{ type: 'basic', name: 'Div', props: { 'data-testid': 'probe' } }], + } as never, + { componentRegistry: createMockComponentRegistryWithBasics() as never, locale: 'ko' } + ); + await utils.render(); + await utils.triggerAction({ type: 'click', ...action } as never); + const dest = utils.getNavigationHistory()[0]; + utils.cleanup(); + return dest; +} + +/** + * 목적지 URL 의 쿼리스트링을 파싱합니다. + * + * @param dest navigate 목적지 + * @returns URLSearchParams + */ +function queryOf(dest: string): URLSearchParams { + return new URLSearchParams(dest.includes('?') ? dest.slice(dest.indexOf('?')) : ''); +} + +describe('#75 주문 목록 ↔ 상세 왕복 — 실행 결과 URL', () => { + afterEach(() => { + window.history.replaceState({}, '', '/'); + }); + + /** 필터를 여러 개 건 목록 URL — 이 화면이 손실 폭이 가장 크다 */ + const LIST_URL = + '/admin/ecommerce/orders?page=2&per_page=20&search_field=orderer_name&search=홍길동&order_status=confirmed'; + + it('주문 행 클릭이 필터 전부를 상세 URL 로 나른다', async () => { + window.history.replaceState({}, '', LIST_URL); + + const action = collectNavActions( + readLayout('partials/admin_ecommerce_order_list/_partial_order_datagrid.json') + ).find((a) => String(a.params.path ?? '').startsWith('/admin/ecommerce/orders/{{')); + expect(action, '주문 행 클릭 navigate 를 찾지 못했습니다.').toBeTruthy(); + + const q = queryOf(await runNav(action as NavAction)); + + expect(q.get('page')).toBe('2'); + expect(q.get('per_page')).toBe('20'); + expect(q.get('search_field')).toBe('orderer_name'); + expect(q.get('search')).toBe('홍길동'); + expect(q.get('order_status')).toBe('confirmed'); + }); + + it("주문 상세 '목록' 버튼이 필터 전부를 목록으로 복원한다", async () => { + window.history.replaceState( + {}, + '', + '/admin/ecommerce/orders/1024?page=2&per_page=20&search=홍길동&order_status=confirmed' + ); + + const action = collectNavActions(readLayout('admin_ecommerce_order_detail.json')).find( + (x) => x.params.path === '/admin/ecommerce/orders' + ); + + const q = queryOf(await runNav(action as NavAction)); + + expect(q.get('page')).toBe('2'); + expect(q.get('per_page')).toBe('20'); + expect(q.get('search')).toBe('홍길동'); + expect(q.get('order_status')).toBe('confirmed'); + }); +}); diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_brand_index.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_brand_index.json index 4119496f..b4cccb93 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_brand_index.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_brand_index.json @@ -144,7 +144,8 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/brands", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_detail.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_detail.json index f761b46e..502515b3 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_detail.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_detail.json @@ -318,7 +318,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/orders" + "path": "/admin/ecommerce/orders", + "mergeQuery": true, + "query": {} } } ] diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_index.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_index.json index be202cd3..54ec969e 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_index.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_index.json @@ -185,7 +185,8 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ] diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_list.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_list.json index 0b9feb6c..cc101ce3 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_list.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_order_list.json @@ -380,11 +380,9 @@ ], "actions": [ { + "comment": "브라우저 히스토리 뒤로가기 — navigate 는 path 를 주소로 해석하므로 \"back\" 을 주면 /back 으로 이동한다", "type": "click", - "handler": "navigate", - "params": { - "path": "back" - } + "handler": "navigateBack" } ] }, @@ -444,11 +442,13 @@ ], "actions": [ { + "comment": "새로고침은 보고 있던 목록을 그대로 다시 부르는 것이다 — 페이지와 걸어둔 필터 20여 종을 유지한다 (#75).", "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ] diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_common_info_index.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_common_info_index.json index 400f6e9e..61a216c5 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_common_info_index.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_common_info_index.json @@ -122,7 +122,8 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/common-info", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_form.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_form.json index aeb8a5fd..d9c82e68 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_form.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_form.json @@ -882,7 +882,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/products" + "path": "/admin/ecommerce/products", + "mergeQuery": true, + "query": {} } } ] @@ -1053,10 +1055,13 @@ } }, { + "comment": "신규 저장 후 편집 화면으로 전환 — 같은 목록 클러스터 안의 이동이므로 목록 상태를 유지한다 (#75).", "handler": "navigate", "if": "{{!route.itemCode}}", "params": { - "path": "{{'/admin/ecommerce/products/' + result.data.id + '/edit'}}" + "path": "{{'/admin/ecommerce/products/' + result.data.id + '/edit'}}", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_list.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_list.json index f65b2063..0b08c040 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_list.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_list.json @@ -424,7 +424,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/products/create" + "path": "/admin/ecommerce/products/create", + "mergeQuery": true, + "query": {} } } ] diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_notice_index.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_notice_index.json index 122631a9..3d63e633 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_notice_index.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_notice_index.json @@ -134,7 +134,8 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/product-notices", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_review_index.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_review_index.json index 09aa1afe..dc6c827b 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_review_index.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_product_review_index.json @@ -177,10 +177,13 @@ ], "actions": [ { + "comment": "새로고침은 보고 있던 목록을 그대로 다시 부르는 것이다 — 페이지/검색/필터를 유지한다 (#75).", "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", + "mergeQuery": true, + "query": {}, "replace": true } } @@ -406,12 +409,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "rating": "", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -438,12 +441,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "rating": "5", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -470,12 +473,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "rating": "4", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -502,12 +505,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "rating": "3", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -534,12 +537,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "rating": "2", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -566,12 +569,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "rating": "1", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -625,12 +628,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "reply_status": "", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -657,12 +660,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "reply_status": "replied", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -689,12 +692,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "reply_status": "not_replied", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -748,12 +751,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "photo": "", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -780,12 +783,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "photo": "photo", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -812,12 +815,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "photo": "normal", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -871,12 +874,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "status": "", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -903,12 +906,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "status": "visible", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -935,12 +938,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "status": "hidden", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -1282,7 +1285,7 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, + "mergeQuery": true, "query": { "search_field": "{{_local.filter.searchField !== 'product_name' ? _local.filter.searchField : ''}}", "search_keyword": "{{_local.filter.searchKeyword ?? ''}}", @@ -1296,6 +1299,7 @@ "per_page": "{{query.per_page || 20}}", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -1335,6 +1339,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", @@ -1511,12 +1516,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "sort": "{{$event.target.value}}", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -1554,12 +1559,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "per_page": "{{$event.target.value}}", "page": 1 }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } @@ -2908,11 +2913,11 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/reviews", - "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, + "replace": true, "transition_overlay_target": "review_datagrid__body" } } diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_promotion_coupon_form.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_promotion_coupon_form.json index 3392d26f..9d3be329 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_promotion_coupon_form.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_promotion_coupon_form.json @@ -170,7 +170,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/promotion-coupons" + "path": "/admin/ecommerce/promotion-coupons", + "mergeQuery": true, + "query": {} } } ] @@ -230,7 +232,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/promotion-coupons" + "path": "/admin/ecommerce/promotion-coupons", + "mergeQuery": true, + "query": {} } } ] @@ -300,7 +304,9 @@ { "handler": "navigate", "params": { - "path": "/admin/ecommerce/promotion-coupons" + "path": "/admin/ecommerce/promotion-coupons", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_promotion_coupon_list.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_promotion_coupon_list.json index 14fdc846..a7714a3b 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_promotion_coupon_list.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_promotion_coupon_list.json @@ -223,7 +223,7 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/promotion-coupons", - "replace": true, + "mergeQuery": true, "query": { "search_field": "{{_local.filter.searchField !== 'all' ? _local.filter.searchField : ''}}", "search_keyword": "{{_local.filter.searchKeyword}}", @@ -244,6 +244,7 @@ "created_by": "{{_local.filter.createdBy}}", "page": 1 }, + "replace": true, "transition_overlay_target": "pc_data_table__body" } } @@ -340,10 +341,13 @@ ], "actions": [ { + "comment": "쿠폰 등록 폼 진입 — 폼에서 취소하고 돌아왔을 때 보던 목록으로 복귀하려면 진입 시점에 목록 상태를 넘겨야 한다 (#75).", "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/promotion-coupon-create" + "path": "/admin/ecommerce/promotion-coupon-create", + "mergeQuery": true, + "query": {} } } ] diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_settings.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_settings.json index cd42f434..ec7d4d4b 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_settings.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_settings.json @@ -348,6 +348,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 탭 전환 — 탭마다 다루는 대상이 달라 이전 탭의 목록 상태를 물려받으면 오히려 잘못된 화면이 된다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/settings", diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_shipping_policy_form.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_shipping_policy_form.json index 63b8372b..bf07790e 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_shipping_policy_form.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_shipping_policy_form.json @@ -329,7 +329,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/shipping-policies" + "path": "/admin/ecommerce/shipping-policies", + "mergeQuery": true, + "query": {} } } ] @@ -406,7 +408,9 @@ { "handler": "navigate", "params": { - "path": "/admin/ecommerce/shipping-policies" + "path": "/admin/ecommerce/shipping-policies", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_shipping_policy_list.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_shipping_policy_list.json index 6ecf75af..008b36ea 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_shipping_policy_list.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/admin_ecommerce_shipping_policy_list.json @@ -107,7 +107,7 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/shipping-policies", - "replace": true, + "mergeQuery": true, "query": { "page": 1, "search": "{{_local.filter.search || undefined}}", @@ -116,6 +116,7 @@ "countries[]": "{{_local.filter.countries?.length > 0 ? _local.filter.countries : undefined}}", "is_active": "{{_local.filter.is_active || undefined}}" }, + "replace": true, "transition_overlay_target": "shipping_policy_datagrid__body" } } @@ -188,7 +189,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/shipping-policies/create" + "path": "/admin/ecommerce/shipping-policies/create", + "mergeQuery": true, + "query": {} } } ] @@ -268,13 +271,13 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/shipping-policies", - "replace": true, "mergeQuery": true, "query": { "sort_by": "{{$event.target.value.split('_').slice(0, -1).join('_')}}", "sort_order": "{{$event.target.value.split('_').pop()}}", "page": 1 }, + "replace": true, "transition_overlay_target": "shipping_policy_datagrid__body" } } @@ -312,12 +315,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/shipping-policies", - "replace": true, "mergeQuery": true, "query": { "per_page": "{{$event.target.value}}", "page": 1 }, + "replace": true, "transition_overlay_target": "shipping_policy_datagrid__body" } } diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_brand_index/_panel_brand_list.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_brand_index/_panel_brand_list.json index 80450c41..edce0470 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_brand_index/_panel_brand_list.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_brand_index/_panel_brand_list.json @@ -139,6 +139,7 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/brands", + "mergeQuery": true, "query": { "search": "{{query.search}}", "sort": "{{$event.target.value}}" @@ -196,8 +197,10 @@ } }, { + "comment": "선택 상태만 주소에 기록한다 — 왼쪽 목록에 걸어둔 검색어·정렬은 그대로 둔다. 병합하지 않으면 항목을 고르는 순간 목록이 초기화된다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "id": "{{$args[0].id}}", "mode": "view" diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_category_index/_panel_category_list.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_category_index/_panel_category_list.json index 35ac5ee3..c81e35c9 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_category_index/_panel_category_list.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_category_index/_panel_category_list.json @@ -89,8 +89,10 @@ } }, { + "comment": "선택 상태만 주소에 기록한다 — 왼쪽 목록에 걸어둔 조건은 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "id": "{{$args[0]?.id}}", "mode": "view" diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_mileage_transaction_index/_filters.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_mileage_transaction_index/_filters.json index 15cbbf58..5fce754c 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_mileage_transaction_index/_filters.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_mileage_transaction_index/_filters.json @@ -456,11 +456,13 @@ "text": "$t:sirsoft-ecommerce.admin.mileage_transactions.search.submit", "actions": [ { + "comment": "검색 실행 — 열거한 검색 조건만 덮어쓰고 나머지 목록 상태는 유지한다 (#75).", "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/mileage-transactions", "replace": true, + "mergeQuery": true, "query": { "search_field": "{{_local.filter.searchField ?? 'member'}}", "search_keyword": "{{_local.filter.searchKeyword ?? ''}}", @@ -514,10 +516,12 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/mileage-transactions", "replace": true, + "mergeQuery": false, "transition_overlay_target": "mileage_transactions_datagrid__body" } } diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_mileage_transaction_index/_transactions_table.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_mileage_transaction_index/_transactions_table.json index a523b8f2..7e97e4d9 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_mileage_transaction_index/_transactions_table.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_mileage_transaction_index/_transactions_table.json @@ -135,12 +135,13 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/mileage-transactions", - "replace": true, + "mergeQuery": true, "query": { "search_field": "member_id", "search_keyword": "{{row.user_id}}", "page": 1 }, + "replace": true, "transition_overlay_target": "mileage_transactions_datagrid__body" } } @@ -581,11 +582,11 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/mileage-transactions", - "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, + "replace": true, "transition_overlay_target": "mileage_transactions_datagrid__body" } }, @@ -595,12 +596,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/mileage-transactions", - "replace": true, "mergeQuery": true, "query": { "sort": "{{$args[0]}}", "page": 1 }, + "replace": true, "transition_overlay_target": "mileage_transactions_datagrid__body" } }, diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_detail/_partial_order_info.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_detail/_partial_order_info.json index dc42ac1e..f3cdd2ef 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_detail/_partial_order_info.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_detail/_partial_order_info.json @@ -1296,12 +1296,15 @@ } }, "search_by_orderer": { + "comment": "주문자명으로 검색 — 회원 지정 필터(orderer_uuid)를 함께 비우지 않으면 이름 검색과 회원 필터가 겹쳐 결과가 비어 보인다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", + "mergeQuery": true, "query": { "search_field": "orderer_name", "search_keyword": "{{order.data?.orderer_name}}", + "orderer_uuid": "", "page": 1 }, "transition_overlay_target": "order_product_datagrid__body" diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_filter_section.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_filter_section.json index 427732a6..7825311f 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_filter_section.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_filter_section.json @@ -2093,6 +2093,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 프리셋 적용 — 프리셋은 조건 세트를 통째로 갈아끼우는 것이므로 병합하면 직전 조건(배송정책·회원구분 등 여기 열거되지 않은 필터)이 화면에 보이지 않는 채로 남는다. 같은 화면의 _partial_preset_section.json 과 동일 규약.", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", @@ -2640,6 +2641,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_order_datagrid.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_order_datagrid.json index 1a4c52e3..bc0fed8d 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_order_datagrid.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_order_datagrid.json @@ -100,12 +100,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", - "replace": true, "mergeQuery": true, "query": { "sort_by": "{{$event.target.value.split('_').slice(0,-1).join('_')}}", "sort_order": "{{$event.target.value.split('_').pop()}}" - } + }, + "replace": true } } ] @@ -155,12 +155,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", - "replace": true, "mergeQuery": true, "query": { "per_page": "{{$event.target.value}}", "page": 1 }, + "replace": true, "transition_overlay_target": "order_datagrid__body" } } @@ -266,7 +266,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/orders/{{row.order_number}}" + "path": "/admin/ecommerce/orders/{{row.order_number}}", + "mergeQuery": true, + "query": {} } } ] @@ -597,11 +599,15 @@ } }, { + "comment": "이 주문자의 주문만 보기 — 앞선 setState 가 검색어를 비우므로 URL 의 검색 조건도 함께 비운다. 비우지 않으면 화면 입력창은 빈 채로 이전 검색어가 계속 적용된다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", + "mergeQuery": true, "query": { "orderer_uuid": "{{row.user?.uuid}}", + "search_field": "", + "search_keyword": "", "page": 1 }, "transition_overlay_target": "order_datagrid__body" @@ -617,16 +623,20 @@ "params": { "target": "_local", "filter.searchField": "orderer_name", - "filter.searchKeyword": "{{row.address?.orderer_name || row.user?.name}}" + "filter.searchKeyword": "{{row.address?.orderer_name || row.user?.name}}", + "filter.ordererUuid": "" } }, { + "comment": "비회원 주문자명으로 검색 — 회원 지정 필터(orderer_uuid)를 함께 비우지 않으면 이름 검색과 회원 필터가 겹쳐 결과가 비어 보인다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", + "mergeQuery": true, "query": { "search_field": "orderer_name", "search_keyword": "{{row.address?.orderer_name || row.user?.name}}", + "orderer_uuid": "", "page": 1 }, "transition_overlay_target": "order_datagrid__body" @@ -762,11 +772,11 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", - "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, + "replace": true, "transition_overlay_target": "order_datagrid__body" } }, @@ -778,7 +788,9 @@ "view_detail": { "handler": "navigate", "params": { - "path": "/admin/ecommerce/orders/{{$args[1].order_number}}" + "path": "/admin/ecommerce/orders/{{$args[1].order_number}}", + "mergeQuery": true, + "query": {} } } } diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_preset_section.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_preset_section.json index 0d359830..bddeb820 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_preset_section.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_order_list/_partial_preset_section.json @@ -86,6 +86,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 프리셋 적용 — 프리셋은 조건 세트를 통째로 갈아끼우는 것이므로 병합하면 직전 프리셋의 조건(기간·상태 등)이 남는다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", @@ -136,6 +137,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 프리셋 적용 — 프리셋은 조건 세트를 통째로 갈아끼우는 것이므로 병합하면 직전 프리셋의 조건(기간·상태 등)이 남는다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", @@ -188,6 +190,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 저장된 프리셋 적용 — 저장해 둔 조건 세트를 통째로 적용하는 것이 목적이므로 병합하면 직전 조건이 섞인다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", @@ -244,6 +247,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 저장된 프리셋 적용 — 저장해 둔 조건 세트를 통째로 적용하는 것이 목적이므로 병합하면 직전 조건이 섞인다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_common_info_index/_panel_list.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_common_info_index/_panel_list.json index b6eb0ca3..37547398 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_common_info_index/_panel_list.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_common_info_index/_panel_list.json @@ -241,8 +241,10 @@ } }, { + "comment": "선택 상태만 주소에 기록한다 — 왼쪽 목록에 걸어둔 검색어는 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "id": "{{item.id}}", "mode": "view" diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_modal_delete_confirm.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_modal_delete_confirm.json index 5d946687..bced563a 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_modal_delete_confirm.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_modal_delete_confirm.json @@ -271,7 +271,9 @@ { "handler": "navigate", "params": { - "path": "/admin/ecommerce/products" + "path": "/admin/ecommerce/products", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_partial_shipping.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_partial_shipping.json index 5e66652e..ebf68064 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_partial_shipping.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_partial_shipping.json @@ -588,10 +588,11 @@ "text": "$t:sirsoft-ecommerce.admin.product.buttons.create_shipping_policy", "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 상품 폼에서 배송정책 목록 클러스터로 나가는 이동이다 — 상품 목록의 페이지·필터를 물려주지 않는다.", "type": "click", "handler": "navigate", "params": { - "url": "/admin/ecommerce/shipping-policies/create" + "path": "/admin/ecommerce/shipping-policies/create" } } ] diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_partial_shopping_integration.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_partial_shopping_integration.json index a4caa3de..b52a80aa 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_partial_shopping_integration.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_form/_partial_shopping_integration.json @@ -189,10 +189,11 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 상품 폼에서 채널 연동 설정 화면으로 나가는 이동이다 — 상품 목록의 페이지·필터를 물려주지 않는다.", "type": "click", "handler": "navigate", "params": { - "url": "/admin/ecommerce/integrations/naver" + "path": "/admin/ecommerce/integrations/naver" } } ], @@ -546,10 +547,11 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 상품 폼에서 채널 연동 설정 화면으로 나가는 이동이다 — 상품 목록의 페이지·필터를 물려주지 않는다.", "type": "click", "handler": "navigate", "params": { - "url": "/admin/ecommerce/integrations/facebook" + "path": "/admin/ecommerce/integrations/facebook" } } ], @@ -903,10 +905,11 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 상품 폼에서 채널 연동 설정 화면으로 나가는 이동이다 — 상품 목록의 페이지·필터를 물려주지 않는다.", "type": "click", "handler": "navigate", "params": { - "url": "/admin/ecommerce/integrations/google" + "path": "/admin/ecommerce/integrations/google" } } ], diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_list/_partial_filter_section.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_list/_partial_filter_section.json index 060c276a..6843a1c6 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_list/_partial_filter_section.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_list/_partial_filter_section.json @@ -1702,6 +1702,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 프리셋 적용 — 프리셋은 조건 세트를 통째로 갈아끼우는 것이므로 병합하면 직전 조건이 섞인다. 주문 목록의 프리셋 규약과 동일.", "handler": "navigate", "params": { "path": "/admin/ecommerce/products", @@ -2287,6 +2288,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/products", diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_list/_partial_product_datagrid.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_list/_partial_product_datagrid.json index ce2472ae..c905a9e1 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_list/_partial_product_datagrid.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_list/_partial_product_datagrid.json @@ -1565,7 +1565,9 @@ "edit": { "handler": "navigate", "params": { - "path": "/admin/ecommerce/products/{{$args[1].product_code ?? $args[1].id}}/edit" + "path": "/admin/ecommerce/products/{{$args[1].product_code ?? $args[1].id}}/edit", + "mergeQuery": true, + "query": {} } }, "copy": { diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_notice_index/_panel_list.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_notice_index/_panel_list.json index 82e6d313..914d0ea6 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_notice_index/_panel_list.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_product_notice_index/_panel_list.json @@ -215,8 +215,10 @@ } }, { + "comment": "선택 상태만 주소에 기록한다 — 왼쪽 목록에 걸어둔 검색어는 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "id": "{{template.id}}", "mode": "view" diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_promotion_coupon_list/_partial_coupon_datagrid.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_promotion_coupon_list/_partial_coupon_datagrid.json index f496797d..b2e125f9 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_promotion_coupon_list/_partial_coupon_datagrid.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_promotion_coupon_list/_partial_coupon_datagrid.json @@ -163,13 +163,13 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/promotion-coupons", - "replace": true, "mergeQuery": true, "query": { "sort_by": "{{$event.target.value.split('_').slice(0, -1).join('_')}}", "sort_order": "{{$event.target.value.split('_').pop()}}", "page": 1 }, + "replace": true, "transition_overlay_target": "pc_data_table__body" } } @@ -207,12 +207,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/promotion-coupons", - "replace": true, "mergeQuery": true, "query": { "per_page": "{{$event.target.value}}", "page": 1 }, + "replace": true, "transition_overlay_target": "pc_data_table__body" } } @@ -311,7 +311,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/ecommerce/promotion-coupons/{{row.id}}/edit" + "path": "/admin/ecommerce/promotion-coupons/{{row.id}}/edit", + "mergeQuery": true, + "query": {} } } ] @@ -563,11 +565,12 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/promotion-coupons", - "replace": true, + "mergeQuery": true, "query": { "created_by": "{{row.created_by}}", "page": 1 }, + "replace": true, "transition_overlay_target": "pc_data_table__body" } } @@ -588,11 +591,11 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/promotion-coupons", - "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, + "replace": true, "transition_overlay_target": "pc_data_table__body" } }, @@ -611,7 +614,9 @@ "edit": { "handler": "navigate", "params": { - "path": "/admin/ecommerce/promotion-coupons/{{$args[1].id}}/edit" + "path": "/admin/ecommerce/promotion-coupons/{{$args[1].id}}/edit", + "mergeQuery": true, + "query": {} } }, "issue_history": { @@ -817,7 +822,9 @@ "edit": { "handler": "navigate", "params": { - "path": "/admin/ecommerce/promotion-coupons/{{coupon.id}}/edit" + "path": "/admin/ecommerce/promotion-coupons/{{coupon.id}}/edit", + "mergeQuery": true, + "query": {} } }, "issue_history": { diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_promotion_coupon_list/_partial_filter_section.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_promotion_coupon_list/_partial_filter_section.json index 97da23b8..d0587c97 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_promotion_coupon_list/_partial_filter_section.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_promotion_coupon_list/_partial_filter_section.json @@ -2241,9 +2241,11 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/promotion-coupons", + "mergeQuery": false, "replace": true } } @@ -2366,9 +2368,11 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/promotion-coupons", + "mergeQuery": false, "replace": true } } diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_identity_policies.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_identity_policies.json index 84e9792b..d62033f9 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_identity_policies.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_identity_policies.json @@ -308,11 +308,13 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/settings", "replace": true, + "mergeQuery": false, "query": { "tab": "identity_policies" }, diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_mileage_notification_card.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_mileage_notification_card.json index 3c3dee0f..aaf3e3dc 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_mileage_notification_card.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_mileage_notification_card.json @@ -255,6 +255,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 탭 전환 — 탭마다 다루는 대상이 달라 이전 탭의 목록 상태를 물려받으면 오히려 잘못된 화면이 된다.", "handler": "navigate", "params": { "path": "/admin/ecommerce/settings", diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_modal_copy.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_modal_copy.json index e7081569..6a6d8ff5 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_modal_copy.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_modal_copy.json @@ -247,6 +247,7 @@ "handler": "navigate", "params": { "path": "/admin/ecommerce/shipping-policies/create", + "mergeQuery": true, "query": { "copy_id": "{{_global.targetPolicy?.id}}" } diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_partial_datagrid.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_partial_datagrid.json index fd2256fc..bb33be43 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_partial_datagrid.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_partial_datagrid.json @@ -346,7 +346,9 @@ "edit": { "handler": "navigate", "params": { - "path": "/admin/ecommerce/shipping-policies/{{$args[1].id}}/edit" + "path": "/admin/ecommerce/shipping-policies/{{$args[1].id}}/edit", + "mergeQuery": true, + "query": {} } }, "copy": { diff --git a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_partial_filter.json b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_partial_filter.json index cfd30bdd..1a5c1a23 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_partial_filter.json +++ b/modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_shipping_policy_list/_partial_filter.json @@ -1098,9 +1098,11 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { - "path": "/admin/ecommerce/shipping-policies" + "path": "/admin/ecommerce/shipping-policies", + "mergeQuery": false } } ] diff --git a/modules/_bundled/sirsoft-ecommerce/src/Repositories/BrandRepository.php b/modules/_bundled/sirsoft-ecommerce/src/Repositories/BrandRepository.php index f9b9de35..b484aa41 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Repositories/BrandRepository.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Repositories/BrandRepository.php @@ -3,6 +3,8 @@ namespace Modules\Sirsoft\Ecommerce\Repositories; use App\Helpers\PermissionHelper; +use App\Search\Engines\DatabaseFulltextEngine; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; use Modules\Sirsoft\Ecommerce\Models\Brand; use Modules\Sirsoft\Ecommerce\Repositories\Contracts\BrandRepositoryInterface; @@ -34,39 +36,21 @@ class BrandRepository implements BrandRepositoryInterface $query->where('is_active', $filters['is_active']); } - // 검색 키워드가 있으면 Scout 사용 + // 검색 키워드 — 이름(FULLTEXT) / slug / website 중 하나만 맞아도 나와야 한다. + // + // Scout 의 `search()->query(fn)` 로는 이 형태를 만들 수 없다. 그 콜백은 검색 엔진이 + // 이미 맞힌 결과를 **좁히는** 자리라, slug·website 를 OR 로 덧붙여도 실제로는 AND 로 + // 걸린다. 이름만 일치하고 slug·website 에는 키워드가 없는 브랜드(대부분)가 전부 + // 걸러져 검색 결과가 항상 비었다. 같은 함정을 이미 겪은 페이지 검색과 동일하게 + // whereFulltext 헬퍼로 한 쿼리 안에서 OR 로 묶는다. if (! empty($filters['search'])) { $keyword = $filters['search']; - return Brand::search($keyword) - ->query(function ($query) use ($filters, $keyword, $with) { - // 권한 스코프 필터링 - PermissionHelper::applyPermissionScope($query, 'sirsoft-ecommerce.brands.read'); - - // 상품 수 조회 - $query->withCount('products'); - - // 활성 상태 필터 - if (isset($filters['is_active'])) { - $query->where('is_active', $filters['is_active']); - } - - // FULLTEXT 외 필드 OR 조건 (slug, website) - $query->where(function ($q) use ($keyword) { - $q->orWhere('slug', 'like', "%{$keyword}%") - ->orWhere('website', 'like', "%{$keyword}%"); - }); - - // 정렬 처리 - $locale = $filters['locale'] ?? app()->getLocale(); - $this->applySorting($query, $filters, $locale); - - // Eager loading - if (! empty($with)) { - $query->with($with); - } - }) - ->get(); + $query->where(function ($q) use ($keyword) { + DatabaseFulltextEngine::whereFulltext($q, 'name', $keyword, 'and'); + $q->orWhere('slug', 'like', "%{$keyword}%") + ->orWhere('website', 'like', "%{$keyword}%"); + }); } // 정렬 처리 @@ -88,7 +72,7 @@ class BrandRepository implements BrandRepositoryInterface { $query = $this->model->newQuery(); - if (!empty($with)) { + if (! empty($with)) { $query->with($with); } @@ -113,6 +97,7 @@ class BrandRepository implements BrandRepositoryInterface { $brand = $this->findById($id); $brand->update($data); + return $brand->fresh(); } @@ -122,6 +107,7 @@ class BrandRepository implements BrandRepositoryInterface public function delete(int $id): bool { $brand = $this->findById($id); + return $brand->delete(); } @@ -131,6 +117,7 @@ class BrandRepository implements BrandRepositoryInterface public function getProductCount(int $id): int { $brand = $this->findById($id); + return $brand->products()->count(); } @@ -151,10 +138,9 @@ class BrandRepository implements BrandRepositoryInterface /** * 정렬 조건을 쿼리에 적용합니다. * - * @param \Illuminate\Database\Eloquent\Builder $query Eloquent 쿼리 빌더 - * @param array $filters 필터 배열 - * @param string $locale 로케일 - * @return void + * @param Builder $query Eloquent 쿼리 빌더 + * @param array $filters 필터 배열 + * @param string $locale 로케일 */ private function applySorting($query, array $filters, string $locale): void { @@ -190,4 +176,4 @@ class BrandRepository implements BrandRepositoryInterface $query->orderBy("name->{$locale}")->orderBy('id'); } } -} \ No newline at end of file +} diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/admin/order-admin-list-context-round-trip.spec.ts b/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/admin/order-admin-list-context-round-trip.spec.ts new file mode 100644 index 00000000..5f2b6f81 --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/admin/order-admin-list-context-round-trip.spec.ts @@ -0,0 +1,73 @@ +/** + * 관리자 주문 목록 컨텍스트 왕복 — 걸어 둔 필터·페이지가 상세를 다녀와도 살아남는지 (공개 이슈 #75). + * + * 결함: 주문 목록에서 주문 하나를 열었다가 '목록' 으로 돌아오면 걸어 둔 필터와 페이지가 전부 사라져 + * 1페이지 무필터 상태로 되돌아갔다. 필터를 여러 개 걸어 두고 주문을 하나씩 확인하는 실제 운영 흐름에서 + * 가장 아프게 드러나는 형태다. + * + * 표식으로 `page` 와 `per_page` 를 쓴다 — 시드 주문 105건이므로 2페이지가 항상 존재한다. + * + * 커버 범위: 이 spec 은 **복귀 leg**(상세 → 목록)를 브라우저 수준에서 실측한다. 진입 leg 는 + * `resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts` 가 실 JSON 의 액션 params 로 + * 고정하고 audit 룰 layout-list-context-navigate-merge-query 가 재발을 차단한다. + * + * @scenario order-admin-list-context-round-trip + * @axes leg=back + * @effects list_return_preserves_query + */ +import { test, expect, authenticatePage } from '../../fixtures/ecommerce-auth'; + +const LIST_URL = '/admin/ecommerce/orders'; +const LIST_STATE = 'page=2&per_page=10'; + +/** + * 현재 URL 의 쿼리 파라미터를 돌려줍니다. + * + * @param url 페이지 URL + * @returns 쿼리 파라미터 + */ +function queryOf(url: string): URLSearchParams { + return new URL(url).searchParams; +} + +test.describe('관리자 주문 목록 컨텍스트 왕복 (#75)', () => { + // @scenario leg=back + // @effects list_return_preserves_query + test('주문 상세에서 목록으로 돌아오면 페이지와 표시 개수가 복원된다', async ({ page, ordersReadToken }) => { + await authenticatePage(page, ordersReadToken); + await page.goto(`${LIST_URL}?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + // 목록에서 상세로 들어간 직후와 동일한 URL 상태 (진입 leg 가 mergeQuery 로 만들어 주는 형태) + const orderNumber = await page.evaluate(async () => { + const res = await fetch('/api/modules/sirsoft-ecommerce/admin/orders?per_page=10', { + headers: { + Authorization: `Bearer ${localStorage.getItem('auth_token')}`, + Accept: 'application/json', + }, + }); + const json = await res.json(); + // 응답 봉투 형태에 의존하지 않도록 order_number 를 가진 첫 객체를 찾는다. + const stack: unknown[] = [json]; + while (stack.length > 0) { + const node = stack.pop(); + if (!node || typeof node !== 'object') continue; + const rec = node as Record; + if (typeof rec.order_number === 'string') return rec.order_number; + stack.push(...Object.values(rec)); + } + return null; + }); + expect(orderNumber, '주문 시드가 없어 왕복을 검증할 수 없습니다.').not.toBeNull(); + + await page.goto(`${LIST_URL}/${orderNumber}?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#list_button').click(); + await page.waitForURL(/\/admin\/ecommerce\/orders\?/, { timeout: 30_000 }); + + const q = queryOf(page.url()); + expect(q.get('page')).toBe('2'); + expect(q.get('per_page')).toBe('10'); + }); +}); diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Repositories/BrandRepositorySearchTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Repositories/BrandRepositorySearchTest.php new file mode 100644 index 00000000..81fd05b3 --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Repositories/BrandRepositorySearchTest.php @@ -0,0 +1,147 @@ +repository = new BrandRepository(new Brand); + } + + /** + * 테스트용 브랜드를 만듭니다. + * + * @param array $name 로케일별 이름 + * @param string $slug slug + * @param string|null $website 웹사이트 주소 + * @return Brand 생성된 브랜드 + */ + private function makeBrand(array $name, string $slug, ?string $website = null): Brand + { + return Brand::create([ + 'name' => $name, + 'slug' => $slug, + 'website' => $website, + 'is_active' => true, + 'sort_order' => 1, + ]); + } + + /** + * 이름 검색은 결과 행이 아니라 실행된 SQL 형태로 단언한다. + * + * InnoDB FULLTEXT 색인은 커밋 이후에만 보이므로, 트랜잭션 안에서 만든 행은 MATCH 로 + * 잡히지 않는다 (코어 DatabaseFulltextEngineTest 도 같은 이유로 SQL 을 단언한다). + * 이번 결함의 본질은 "이름 조건이 slug·website 와 OR 로 묶이는가" 이므로 그 형태를 고정한다. + */ + public function test_search_combines_name_slug_website_with_or(): void + { + $this->makeBrand(['ko' => '나이키', 'en' => 'Nike'], 'nike', 'https://www.nike.com'); + + DB::enableQueryLog(); + $this->repository->getAll(['search' => '나이키']); + $log = DB::getQueryLog(); + DB::disableQueryLog(); + + $sql = collect($log)->pluck('query')->implode(' | '); + + $this->assertStringContainsString( + 'match(`name`) against', + strtolower($sql), + '이름에 대한 FULLTEXT 조건이 쿼리에 없습니다.' + ); + $this->assertMatchesRegularExpression( + '/against\(\? in boolean mode\)\s+or\s+`slug`\s+like\s+\?\s+or\s+`website`\s+like\s+\?/i', + strtolower($sql), + '이름·slug·website 가 OR 로 묶이지 않았습니다 — 좁히는 AND 로 걸리면 이름만 일치하는 브랜드가 전부 사라집니다.' + ); + } + + public function test_search_finds_brand_by_slug(): void + { + // Given: 이름은 한글, slug 는 영문 + $puma = $this->makeBrand(['ko' => '퓨마', 'en' => 'Puma'], 'puma-korea', 'https://www.puma.com'); + + // When: slug 조각으로 검색 + $result = $this->repository->getAll(['search' => 'puma-korea']); + + // Then: slug 가 맞았으므로 나와야 한다 + $this->assertCount(1, $result, 'slug 가 일치하는 브랜드가 검색되지 않았습니다.'); + $this->assertSame($puma->id, $result->first()->id); + } + + public function test_search_finds_brand_by_website(): void + { + // Given: 이름·slug 와 무관한 도메인 + $zara = $this->makeBrand(['ko' => '자라', 'en' => 'ZARA'], 'zara', 'https://shop.inditex-group.com'); + + // When: 도메인 조각으로 검색 + $result = $this->repository->getAll(['search' => 'inditex-group']); + + // Then: website 가 맞았으므로 나와야 한다 + $this->assertCount(1, $result, 'website 가 일치하는 브랜드가 검색되지 않았습니다.'); + $this->assertSame($zara->id, $result->first()->id); + } + + public function test_search_excludes_unrelated_brands(): void + { + // Given: 서로 겹치지 않는 두 브랜드 + $this->makeBrand(['ko' => '나이키', 'en' => 'Nike'], 'nike', 'https://www.nike.com'); + $this->makeBrand(['ko' => '아디다스', 'en' => 'Adidas'], 'adidas', 'https://www.adidas.com'); + + // When: 한쪽만 가리키는 키워드로 검색 + $result = $this->repository->getAll(['search' => 'adidas']); + + // Then: 나머지는 섞이지 않는다 + $this->assertCount(1, $result); + $this->assertSame('adidas', $result->first()->slug); + } + + public function test_search_respects_active_filter(): void + { + // Given: 같은 키워드를 가진 활성/비활성 브랜드 + $active = $this->makeBrand(['ko' => '나이키', 'en' => 'Nike'], 'nike-korea', null); + $inactive = $this->makeBrand(['ko' => '나이키 키즈', 'en' => 'Nike Kids'], 'nike-kids', null); + $inactive->update(['is_active' => false]); + + // When: 활성만 요청 + $result = $this->repository->getAll(['search' => 'nike-korea', 'is_active' => true]); + + // Then: 검색과 필터가 함께 적용된다 + $this->assertCount(1, $result); + $this->assertSame($active->id, $result->first()->id); + } + + public function test_search_keeps_active_filter_and_keyword_grouped(): void + { + // Given: 비활성 브랜드가 키워드를 담고 있다 + $this->makeBrand(['ko' => '나이키', 'en' => 'Nike'], 'nike-korea', null) + ->update(['is_active' => false]); + + // When: 활성만 요청 + $result = $this->repository->getAll(['search' => 'nike-korea', 'is_active' => true]); + + // Then: OR 그룹이 괄호로 묶여야 활성 조건이 무력화되지 않는다 + $this->assertCount(0, $result, 'is_active 조건이 OR 로 흡수돼 비활성 브랜드가 새어 나왔습니다.'); + } +} diff --git a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/order-admin-list-context-round-trip.yaml b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/order-admin-list-context-round-trip.yaml new file mode 100644 index 00000000..c3a3855a --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/order-admin-list-context-round-trip.yaml @@ -0,0 +1,31 @@ +feature: 관리자 주문 목록 컨텍스트 왕복 + +description: | + 관리자 주문 목록과 그에 딸린 주문 상세는 하나의 "목록 클러스터" 다. 이 안에서의 이동은 URL 목록 + 상태(page / per_page / 검색 / 상태 필터 / 기간)를 손실 없이 이어받아야 한다 (공개 이슈 #75). + + 운영 흐름상 이 도메인이 가장 아프다 — 필터를 여러 개 걸어 두고 주문을 하나씩 열어 확인하는데, + 복귀할 때마다 1페이지 무필터로 되돌아가면 걸어 둔 조건을 매번 다시 만들어야 한다. + + 반대로 **초기화 버튼과 프리셋 적용은 병합하지 않는다**. 프리셋은 조건 세트를 통째로 갈아끼우는 + 동작이라 병합하면 직전 프리셋의 기간·상태가 남아 엉뚱한 결과가 나온다. 이 구분은 액션 노드의 + `audit:allow layout-list-context-navigate-merge-query` 주석으로 코드에 기록돼 있고, + 룰이 "주석은 병합하지 않겠다는데 코드는 mergeQuery: true" 인 자기모순을 검출한다. + +axes: + # 목록 클러스터 안에서 발생하는 이동 leg + leg: [back] # 주문 상세 → 목록 + +effects: + - list_return_preserves_query # 복귀 이동이 URL 목록 상태를 그대로 복원 + +test_files: + - modules/_bundled/sirsoft-ecommerce/tests/Playwright/specs/admin/order-admin-list-context-round-trip.spec.ts + - modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts + - .claude/scripts/audit/__tests__/layout-list-context-navigate-merge-query.test.cjs + +validation: + note: | + 진입 leg(목록 행 → 상세)와 필터/프리셋/초기화의 병합 여부는 레이아웃 테스트가 실 JSON 의 액션 + params 로 전수 고정한다. 브라우저 spec 은 진입이 만들어 내는 URL 상태를 재현한 뒤 복귀 leg 를 + 실측한다. 재발 차단은 audit 룰 `layout-list-context-navigate-merge-query` (error) 가 담당한다. diff --git a/modules/_bundled/sirsoft-page/CHANGELOG.md b/modules/_bundled/sirsoft-page/CHANGELOG.md index a9af21bd..9081b877 100644 --- a/modules/_bundled/sirsoft-page/CHANGELOG.md +++ b/modules/_bundled/sirsoft-page/CHANGELOG.md @@ -18,6 +18,7 @@ ### Fixed +- 관리자 페이지 목록에서 상세나 수정 화면에 다녀오면 보고 있던 페이지와 검색 조건이 사라지고 1페이지로 되돌아가던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 페이지 활동 로그에서 "제목"·"내용" 변경 항목의 이름이 비어 보이던 문제를 수정했습니다. - 다른 페이지의 주소로 특정 페이지의 이전 버전 내용을 열람할 수 있던 문제를 수정했습니다. - 다른 페이지에 속한 버전으로 복원을 시도하면 "복원에 실패했습니다" 라는 서버 오류가 나던 문제를 수정했습니다. 이제 열람과 동일하게 "찾을 수 없음" 으로 안내합니다. diff --git a/modules/_bundled/sirsoft-page/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts b/modules/_bundled/sirsoft-page/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts new file mode 100644 index 00000000..b5f13d80 --- /dev/null +++ b/modules/_bundled/sirsoft-page/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts @@ -0,0 +1,212 @@ +/** + * @file admin-list-context-round-trip.test.ts + * @description 관리자 페이지 목록 컨텍스트 왕복 시 URL 목록 상태 보존 회귀 (#75) + * + * 결함: 페이지 목록(`/admin/pages`) 에서 상세·수정 폼으로 들어갔다 돌아오면 navigate 가 + * `mergeQuery` 없이 실행되어 page/검색 필터가 URL 에서 사라지고 1페이지로 되돌아갔다. + * + * 검증 방식 2단: + * 1. 실 레이아웃 JSON 전수 분석 — 클러스터 내 navigate 가 모두 `mergeQuery: true` 인지 + * 2. 실 액션을 엔진에 태워 실행(`triggerAction`) — 선언이 실제 목적지 URL 로 이어지는지 + * 선언만 검사하면 "JSON 에 리터럴이 적혀 있다" 까지만 고정되고 병합 결과는 미검증으로 남는다. + * + * @scenario leg=row_click|detail_return|form_cancel + * @effects navigation_preserves_list_query + * + * @vitest-environment jsdom + */ + +import { describe, it, expect, afterEach } from 'vitest'; +import fs from 'fs'; +import path from 'path'; + +import { + createLayoutTest, + createMockComponentRegistryWithBasics, +} from '@core/template-engine/__tests__/utils/layoutTestUtils'; + +const LAYOUTS_ROOT = path.resolve(__dirname, '../../../layouts/admin'); + +/** 이 확장이 소유한 페이지네이션 목록 라우트 */ +const LIST_ROUTES = ['/admin/pages']; + +/** 목록 클러스터에 속하는 레이아웃 파일 */ +const CLUSTER_FILES = ['admin_page_list.json', 'admin_page_detail.json', 'admin_page_form.json']; + +type NavAction = { + handler: string; + comment?: string; + params: { path?: string; mergeQuery?: unknown; query?: unknown }; +}; + +/** + * JSON 트리에서 navigate/replaceUrl 액션을 모두 수집합니다. + * + * @param node 순회 시작 노드 + * @returns 액션 목록 + */ +function collectNavActions(node: unknown): NavAction[] { + const out: NavAction[] = []; + const walk = (n: unknown): void => { + if (Array.isArray(n)) { + n.forEach(walk); + return; + } + if (!n || typeof n !== 'object') return; + const obj = n as Record; + if ( + (obj.handler === 'navigate' || obj.handler === 'replaceUrl') && + obj.params && + typeof obj.params === 'object' + ) { + out.push(obj as unknown as NavAction); + } + Object.values(obj).forEach(walk); + }; + walk(node); + return out; +} + +/** + * 목적지 경로를 비교용 표준형(`{{expr}}` → `*`)으로 바꿉니다. + * + * @param raw 원본 경로 + * @returns 표준형 경로 (판정 불가 시 null) + */ +function normalizePath(raw: unknown): string | null { + if (typeof raw !== 'string' || raw === '') return null; + const p = raw.replace(/\{\{[^}]*\}\}/g, '*').split('?')[0].replace(/\/+$/, ''); + return p.startsWith('/') ? p : null; +} + +/** + * 경로가 목록 라우트와 같은 클러스터인지 판정합니다. + * + * @param dest 표준형 목적지 + * @param list 표준형 목록 라우트 + * @returns 같은 클러스터 여부 + */ +function inFamily(dest: string, list: string): boolean { + return dest === list || dest.startsWith(`${list}/`); +} + +/** + * 레이아웃 파일을 읽어 파싱합니다. + * + * @param rel 레이아웃 루트 기준 상대 경로 + * @returns 파싱된 JSON + */ +function readLayout(rel: string): unknown { + return JSON.parse(fs.readFileSync(path.join(LAYOUTS_ROOT, rel), 'utf8')); +} + +describe('#75 관리자 페이지 목록 컨텍스트 왕복 — mergeQuery 전수', () => { + it.each(CLUSTER_FILES)('%s 의 클러스터 내 navigate 는 모두 mergeQuery: true', (rel) => { + const offenders = collectNavActions(readLayout(rel)) + .filter((a) => { + if (typeof a.comment === 'string' && a.comment.includes('audit:allow')) return false; + const dest = normalizePath(a.params.path); + if (!dest) return false; + if (!LIST_ROUTES.some((l) => inFamily(dest, l))) return false; + return a.params.mergeQuery !== true; + }) + .map((a) => `${a.params.path} (mergeQuery=${JSON.stringify(a.params.mergeQuery)})`); + + expect(offenders, `목록 상태를 떨구는 navigate: \n ${offenders.join('\n ')}`).toEqual([]); + }); + + it("페이지 상세의 '목록' 버튼이 목록 상태를 복원한다", () => { + const backs = collectNavActions(readLayout('admin_page_detail.json')).filter( + (a) => a.params.path === '/admin/pages' + ); + expect(backs.length).toBeGreaterThan(0); + backs.forEach((a) => expect(a.params.mergeQuery).toBe(true)); + }); +}); + +// --------------------------------------------------------------------------- +// 실행 검증 — 실 액션을 엔진에 태워 목적지 URL 을 확인한다 +// --------------------------------------------------------------------------- + +/** + * 실 JSON 액션을 현재 URL 상태에서 실행하고 목적지를 돌려줍니다. + * + * @param action 실 레이아웃 JSON 에서 뽑은 navigate 액션 + * @returns navigate 목적지 경로 + */ +async function runNav(action: NavAction): Promise { + const utils = createLayoutTest( + { + version: '1.0.0', + layout_name: 'nav_action_probe', + data_sources: [], + components: [{ type: 'basic', name: 'Div', props: { 'data-testid': 'probe' } }], + } as never, + { componentRegistry: createMockComponentRegistryWithBasics() as never, locale: 'ko' } + ); + await utils.render(); + await utils.triggerAction({ type: 'click', ...action } as never); + const dest = utils.getNavigationHistory()[0]; + utils.cleanup(); + return dest; +} + +/** + * 목적지 URL 의 쿼리스트링을 파싱합니다. + * + * @param dest navigate 목적지 + * @returns URLSearchParams + */ +function queryOf(dest: string): URLSearchParams { + return new URLSearchParams(dest.includes('?') ? dest.slice(dest.indexOf('?')) : ''); +} + +/** + * 실 JSON 에서 목적지 경로가 일치하는 navigate 액션을 찾습니다. + * + * @param json 레이아웃 JSON + * @param destPath 목적지 경로 (원문 그대로) + * @returns 액션 + */ +function findNavAction(json: unknown, destPath: string): NavAction { + const action = collectNavActions(json).find((a) => a.params.path === destPath); + expect(action, `navigate 액션(${destPath})을 실 JSON 에서 찾지 못함`).toBeTruthy(); + return action as NavAction; +} + +describe('#75 관리자 페이지 목록 컨텍스트 왕복 — 실행 결과 URL', () => { + afterEach(() => { + window.history.replaceState({}, '', '/'); + }); + + it('목록 행 클릭이 목록 상태를 상세 URL 로 나른다', async () => { + window.history.replaceState({}, '', '/admin/pages?page=3&per_page=2&sort_by=title'); + + const q = queryOf(await runNav(findNavAction(readLayout('admin_page_list.json'), '/admin/pages/{{$args[1].id}}'))); + + expect(q.get('page')).toBe('3'); + expect(q.get('per_page')).toBe('2'); + expect(q.get('sort_by')).toBe('title'); + }); + + it("상세의 '목록' 버튼이 상세 URL 의 목록 상태를 목록으로 복귀시킨다", async () => { + window.history.replaceState({}, '', '/admin/pages/7?page=3&per_page=2&sort_by=title'); + + const q = queryOf(await runNav(findNavAction(readLayout('admin_page_detail.json'), '/admin/pages'))); + + expect(q.get('page')).toBe('3'); + expect(q.get('per_page')).toBe('2'); + expect(q.get('sort_by')).toBe('title'); + }); + + it('상세 → 수정 이동에서도 목록 상태가 이어진다', async () => { + window.history.replaceState({}, '', '/admin/pages/7?page=3&per_page=2'); + + const q = queryOf( + await runNav(findNavAction(readLayout('admin_page_detail.json'), '/admin/pages/{{route?.id}}/edit')) + ); + + expect(q.get('page')).toBe('3'); + expect(q.get('per_page')).toBe('2'); + }); +}); diff --git a/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_detail.json b/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_detail.json index 990e9324..e6347add 100644 --- a/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_detail.json +++ b/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_detail.json @@ -158,7 +158,9 @@ { "handler": "navigate", "params": { - "path": "/admin/pages" + "path": "/admin/pages", + "mergeQuery": true, + "query": {} } } ], @@ -655,7 +657,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/pages" + "path": "/admin/pages", + "mergeQuery": true, + "query": {} } } ], @@ -691,7 +695,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/pages/{{route?.id}}/edit" + "path": "/admin/pages/{{route?.id}}/edit", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_form.json b/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_form.json index 3731b629..58699421 100644 --- a/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_form.json +++ b/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_form.json @@ -963,7 +963,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "{{route?.id ? '/admin/pages/' + route.id : '/admin/pages'}}" + "path": "{{route?.id ? '/admin/pages/' + route.id : '/admin/pages'}}", + "mergeQuery": true, + "query": {} } } ], @@ -1058,7 +1060,9 @@ { "handler": "navigate", "params": { - "path": "/admin/pages/{{route?.id ?? response.data.id}}" + "path": "/admin/pages/{{route?.id ?? response.data.id}}", + "mergeQuery": true, + "query": {} } } ], diff --git a/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_list.json b/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_list.json index 33dc05d0..b78d66c7 100644 --- a/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_list.json +++ b/modules/_bundled/sirsoft-page/resources/layouts/admin/admin_page_list.json @@ -111,7 +111,8 @@ "handler": "navigate", "params": { "path": "/admin/pages", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], @@ -139,7 +140,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/pages/create" + "path": "/admin/pages/create", + "mergeQuery": true, + "query": {} } } ], @@ -828,13 +831,17 @@ "view": { "handler": "navigate", "params": { - "path": "/admin/pages/{{$args[1].id}}" + "path": "/admin/pages/{{$args[1].id}}", + "mergeQuery": true, + "query": {} } }, "edit": { "handler": "navigate", "params": { - "path": "/admin/pages/{{$args[1].id}}/edit" + "path": "/admin/pages/{{$args[1].id}}/edit", + "mergeQuery": true, + "query": {} } }, "delete": { @@ -968,7 +975,7 @@ "params": { "path": "/admin/pages", "mergeQuery": true, - "query": [] + "query": {} } }, { @@ -1129,7 +1136,7 @@ "params": { "path": "/admin/pages", "mergeQuery": true, - "query": [] + "query": {} } }, { diff --git a/modules/_bundled/sirsoft-page/tests/Playwright/specs/admin/page-admin-list-context-round-trip.spec.ts b/modules/_bundled/sirsoft-page/tests/Playwright/specs/admin/page-admin-list-context-round-trip.spec.ts new file mode 100644 index 00000000..7ba063b4 --- /dev/null +++ b/modules/_bundled/sirsoft-page/tests/Playwright/specs/admin/page-admin-list-context-round-trip.spec.ts @@ -0,0 +1,106 @@ +/** + * 관리자 페이지 목록 컨텍스트 왕복 — 목록 상태가 상세·폼을 거쳐도 살아남는지 (공개 이슈 #75). + * + * 결함: 목록 → 상세 → 목록, 목록 → 등록/수정 폼 → 취소 경로에 `mergeQuery` 가 빠져 있어 표시 개수· + * 필터 같은 목록 상태가 이동 한 번에 사라졌다. 취소 버튼은 목적지가 삼항 표현식이라 정적 검사에서도 + * 오래 빠져 있던 자리다. + * + * 표시 개수(`per_page`)를 표식으로 쓴다 — 시드 건수와 무관하게 항상 URL 에 실리는 목록 상태다. + * + * 커버 범위: 이 spec 은 **복귀 leg**(상세 → 목록, 폼 취소 → 목록)를 브라우저 수준에서 실측한다. + * 진입 leg(목록 행 → 상세)는 행 끝 ⋯ 메뉴가 포털로 렌더되어 로케이터가 불안정하므로, + * `resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts` 가 실 JSON 의 액션 params 로 + * 고정하고 audit 룰이 재발을 차단한다. 복귀 leg 는 진입으로 만들어진 URL 상태를 그대로 재현해 검증한다. + * + * @scenario page-admin-list-context-round-trip + * @axes leg=back leg=cancel + * @effects list_return_preserves_query + */ +import { test, expect, authenticatePage } from '../../fixtures/page-auth'; + +const LIST_URL = '/admin/pages'; +const LIST_STATE = 'per_page=10'; + +/** + * 현재 URL 의 쿼리 파라미터를 돌려줍니다. + * + * @param url 페이지 URL + * @returns 쿼리 파라미터 + */ +function queryOf(url: string): URLSearchParams { + return new URL(url).searchParams; +} + +/** + * 목록의 첫 페이지 id 를 조회합니다. + * + * 브라우저 컨텍스트에서 조회해 화면과 같은 토큰·권한을 그대로 쓴다. + * + * @param page Playwright 페이지 + * @returns 페이지 id + */ +async function firstPageId(page: import('@playwright/test').Page): Promise { + const id = await page.evaluate(async () => { + const res = await fetch('/api/modules/sirsoft-page/admin/pages?per_page=1', { + headers: { + Authorization: `Bearer ${localStorage.getItem('auth_token')}`, + Accept: 'application/json', + }, + }); + const json = await res.json(); + const rows = json?.data?.data ?? json?.data ?? []; + return Array.isArray(rows) && rows.length > 0 ? rows[0].id : null; + }); + expect(id, '페이지 시드가 없어 왕복을 검증할 수 없습니다.').not.toBeNull(); + return id as number; +} + +test.describe('관리자 페이지 목록 컨텍스트 왕복 (#75)', () => { + // @scenario leg=back + // @effects list_return_preserves_query + test('상세에서 목록으로 돌아오면 목록 상태가 복원된다', async ({ page, pageManageToken }) => { + await authenticatePage(page, pageManageToken); + await page.goto(`${LIST_URL}?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + const id = await firstPageId(page); + // 목록에서 상세로 들어간 직후와 동일한 URL 상태 (진입 leg 가 mergeQuery 로 만들어 주는 형태) + await page.goto(`${LIST_URL}/${id}?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#header_back_button').click(); + await page.waitForURL(/\/admin\/pages\?/, { timeout: 30_000 }); + + expect(queryOf(page.url()).get('per_page')).toBe('10'); + }); + + // @scenario leg=cancel + // @effects list_return_preserves_query + test('등록 폼에서 취소하면 목록 상태가 유지된 채 목록으로 돌아온다', async ({ page, pageManageToken }) => { + await authenticatePage(page, pageManageToken); + await page.goto(`${LIST_URL}/create?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#footer_cancel_button').click(); + await page.waitForURL(/\/admin\/pages\?/, { timeout: 30_000 }); + + expect(queryOf(page.url()).get('per_page')).toBe('10'); + }); + + // @scenario leg=cancel + // @effects list_return_preserves_query + test('수정 폼에서 취소하면 그 페이지 상세로 돌아오며 목록 상태가 살아 있다', async ({ page, pageManageToken }) => { + await authenticatePage(page, pageManageToken); + await page.goto(`${LIST_URL}?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + const id = await firstPageId(page); + await page.goto(`${LIST_URL}/${id}/edit?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#footer_cancel_button').click(); + await page.waitForURL(new RegExp(`/admin/pages/${id}\\?`), { timeout: 30_000 }); + + expect(queryOf(page.url()).get('per_page')).toBe('10'); + }); +}); diff --git a/modules/_bundled/sirsoft-page/tests/scenarios/page-admin-list-context-round-trip.yaml b/modules/_bundled/sirsoft-page/tests/scenarios/page-admin-list-context-round-trip.yaml new file mode 100644 index 00000000..2e741f63 --- /dev/null +++ b/modules/_bundled/sirsoft-page/tests/scenarios/page-admin-list-context-round-trip.yaml @@ -0,0 +1,29 @@ +feature: 관리자 페이지 목록 컨텍스트 왕복 + +description: | + 관리자 페이지 목록과 그에 딸린 상세·등록/수정 폼은 하나의 "목록 클러스터" 다. 이 안에서의 이동은 + URL 목록 상태(page / per_page / 정렬 / 필터)를 손실 없이 이어받아야 한다 (공개 이슈 #75). + + 이 모듈에서 특히 오래 남아 있던 자리는 **폼 취소 leg** 이다. 저장 leg 는 목적지가 고정 경로라 + 일찍 교정됐지만, 취소 버튼은 목적지가 삼항 표현식(`route?.id ? '/admin/pages/' + id : '/admin/pages'`) + 이라 정적 검사에서 판정 자체가 포기돼 "저장하면 유지 / 취소하면 리셋" 비대칭이 남았다. + audit 룰이 표현식 안의 문자열 리터럴로 클러스터를 판정하도록 승격되면서 검출 대상이 됐다. + +axes: + # 목록 클러스터 안에서 발생하는 이동 leg + leg: [back, cancel] # 상세→목록 / 폼 취소→직전 화면 + +effects: + - list_return_preserves_query # 복귀 이동이 URL 목록 상태를 그대로 복원 + +test_files: + - modules/_bundled/sirsoft-page/tests/Playwright/specs/admin/page-admin-list-context-round-trip.spec.ts + - modules/_bundled/sirsoft-page/resources/js/__tests__/layouts/admin-list-context-round-trip.test.ts + - .claude/scripts/audit/__tests__/layout-list-context-navigate-merge-query.test.cjs + +validation: + note: | + 진입 leg(목록 행 → 상세)는 행 끝 액션 메뉴가 포털로 렌더돼 브라우저 로케이터가 불안정하므로 + 레이아웃 테스트가 실 JSON 의 액션 params 로 고정한다. 브라우저 spec 은 진입이 만들어 내는 URL 상태를 + 그대로 재현한 뒤 복귀 leg 를 실측한다. 재발 차단은 audit 룰 + `layout-list-context-navigate-merge-query` (error) 가 담당한다. diff --git a/plugins/_bundled/sirsoft-gdpr/resources/layouts/admin/gdpr_consent_log.json b/plugins/_bundled/sirsoft-gdpr/resources/layouts/admin/gdpr_consent_log.json index 27f1600d..99096059 100644 --- a/plugins/_bundled/sirsoft-gdpr/resources/layouts/admin/gdpr_consent_log.json +++ b/plugins/_bundled/sirsoft-gdpr/resources/layouts/admin/gdpr_consent_log.json @@ -132,6 +132,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 검색/필터 조건과 페이지를 모두 비우는 의도적 리셋이므로 병합하지 않는다", "handler": "navigate", "params": { "path": "/admin/plugins/sirsoft-gdpr/consent-log", diff --git a/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md b/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md index f1231e96..0437ee69 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixed +- 관리자 주문 목록에서 주문번호를 눌러 상세로 들어갈 때 걸어 둔 필터와 페이지가 사라지던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 주문 목록에서 '이 주문자의 주문 검색'을 실행하면 검색창은 비어 보이는데 직전 검색어가 계속 적용돼 결과가 어긋나던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 해외결제(CBT) 연결 진단을 실행했을 때 결과 안내가 실제 문장 대신 내부 식별자로 표시되던 문제를 수정했습니다. ## [1.0.1] - 2026-07-16 diff --git a/plugins/_bundled/sirsoft-pay_kginicis/resources/extensions/admin_order_list_test_badge.json b/plugins/_bundled/sirsoft-pay_kginicis/resources/extensions/admin_order_list_test_badge.json index 8b521d85..555f4f84 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/resources/extensions/admin_order_list_test_badge.json +++ b/plugins/_bundled/sirsoft-pay_kginicis/resources/extensions/admin_order_list_test_badge.json @@ -52,7 +52,7 @@ "props": { "className": "font-medium text-blue-600 dark:text-blue-400 cursor-pointer hover:underline" }, "text": "{{row.order_number}}", "actions": [ - { "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders/{{row.order_number}}" } } + { "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders/{{row.order_number}}", "mergeQuery": true, "query": {} } } ] } ] @@ -178,14 +178,14 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "_local", "filter.ordererUuid": "{{row.user?.uuid}}", "filter.searchField": "all", "filter.searchKeyword": "", "ordererSearchResults": "{{[{ uuid: row.user?.uuid, name: row.user?.name || row.address?.orderer_name, email: row.user?.email || '' }]}}" } }, - { "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "query": { "orderer_uuid": "{{row.user?.uuid}}", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } + { "comment": "이 주문자의 주문만 보기 — 앞선 setState 가 검색어를 비우므로 URL 의 검색 조건도 함께 비운다. 비우지 않으면 화면 입력창은 빈 채로 이전 검색어가 계속 적용된다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "mergeQuery": true, "query": { "orderer_uuid": "{{row.user?.uuid}}", "search_field": "", "search_keyword": "", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } ] }, "search_by_orderer_guest": { "handler": "sequence", "actions": [ - { "handler": "setState", "params": { "target": "_local", "filter.searchField": "orderer_name", "filter.searchKeyword": "{{row.address?.orderer_name || row.user?.name}}" } }, - { "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "query": { "search_field": "orderer_name", "search_keyword": "{{row.address?.orderer_name || row.user?.name}}", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } + { "handler": "setState", "params": { "target": "_local", "filter.searchField": "orderer_name", "filter.searchKeyword": "{{row.address?.orderer_name || row.user?.name}}", "filter.ordererUuid": "" } }, + { "comment": "비회원 주문자명으로 검색 — 회원 지정 필터(orderer_uuid)를 함께 비우지 않으면 이름 검색과 회원 필터가 겹쳐 결과가 비어 보인다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "mergeQuery": true, "query": { "search_field": "orderer_name", "search_keyword": "{{row.address?.orderer_name || row.user?.name}}", "orderer_uuid": "", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } ] } } diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md b/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md index abae0cf1..869ce5d6 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixed +- 관리자 주문 목록에서 주문번호를 눌러 상세로 들어갈 때 걸어 둔 필터와 페이지가 사라지던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 주문 목록에서 '이 주문자의 주문 검색'을 실행하면 검색창은 비어 보이는데 직전 검색어가 계속 적용돼 결과가 어긋나던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 오류 안내가 뜨기는 하지만 내용이 비어 있던 문제를 수정했습니다. 설정 저장에 실패하면 서버가 알려 준 사유가 그대로 표시됩니다. - 설정 화면의 연동 점검 결과 아이콘이 의도한 크기보다 크거나 작게 보이던 문제를 수정했습니다. diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/resources/extensions/admin_order_list_test_badge.json b/plugins/_bundled/sirsoft-pay_nhnkcp/resources/extensions/admin_order_list_test_badge.json index 501d1908..f1a2689f 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/resources/extensions/admin_order_list_test_badge.json +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/resources/extensions/admin_order_list_test_badge.json @@ -73,7 +73,7 @@ "props": { "className": "font-medium text-blue-600 dark:text-blue-400 cursor-pointer hover:underline" }, "text": "{{row.order_number}}", "actions": [ - { "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders/{{row.order_number}}" } } + { "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders/{{row.order_number}}", "mergeQuery": true, "query": {} } } ] } ] @@ -199,14 +199,14 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "_local", "filter.ordererUuid": "{{row.user?.uuid}}", "filter.searchField": "all", "filter.searchKeyword": "", "ordererSearchResults": "{{[{ uuid: row.user?.uuid, name: row.user?.name || row.address?.orderer_name, email: row.user?.email || '' }]}}" } }, - { "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "query": { "orderer_uuid": "{{row.user?.uuid}}", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } + { "comment": "이 주문자의 주문만 보기 — 앞선 setState 가 검색어를 비우므로 URL 의 검색 조건도 함께 비운다. 비우지 않으면 화면 입력창은 빈 채로 이전 검색어가 계속 적용된다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "mergeQuery": true, "query": { "orderer_uuid": "{{row.user?.uuid}}", "search_field": "", "search_keyword": "", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } ] }, "search_by_orderer_guest": { "handler": "sequence", "actions": [ - { "handler": "setState", "params": { "target": "_local", "filter.searchField": "orderer_name", "filter.searchKeyword": "{{row.address?.orderer_name || row.user?.name}}" } }, - { "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "query": { "search_field": "orderer_name", "search_keyword": "{{row.address?.orderer_name || row.user?.name}}", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } + { "handler": "setState", "params": { "target": "_local", "filter.searchField": "orderer_name", "filter.searchKeyword": "{{row.address?.orderer_name || row.user?.name}}", "filter.ordererUuid": "" } }, + { "comment": "비회원 주문자명으로 검색 — 회원 지정 필터(orderer_uuid)를 함께 비우지 않으면 이름 검색과 회원 필터가 겹쳐 결과가 비어 보인다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "mergeQuery": true, "query": { "search_field": "orderer_name", "search_keyword": "{{row.address?.orderer_name || row.user?.name}}", "orderer_uuid": "", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } ] } } diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/CHANGELOG.md b/plugins/_bundled/sirsoft-pay_nicepayments/CHANGELOG.md index 117f5b55..1bc36e63 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-pay_nicepayments/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixed +- 관리자 주문 목록에서 주문번호를 눌러 상세로 들어갈 때 걸어 둔 필터와 페이지가 사라지던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 주문 목록에서 '이 주문자의 주문 검색'을 실행하면 검색창은 비어 보이는데 직전 검색어가 계속 적용돼 결과가 어긋나던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 오류 안내가 뜨기는 하지만 내용이 비어 있던 문제를 수정했습니다. 설정 저장에 실패하면 서버가 알려 준 사유가 그대로 표시됩니다. - 설정 화면의 아이콘이 의도한 크기보다 크거나 작게 보이던 문제를 수정했습니다. diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/resources/extensions/admin_order_list_test_badge.json b/plugins/_bundled/sirsoft-pay_nicepayments/resources/extensions/admin_order_list_test_badge.json index 15aaa8bd..bcefd210 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/resources/extensions/admin_order_list_test_badge.json +++ b/plugins/_bundled/sirsoft-pay_nicepayments/resources/extensions/admin_order_list_test_badge.json @@ -51,7 +51,7 @@ "props": { "className": "font-medium text-blue-600 dark:text-blue-400 cursor-pointer hover:underline" }, "text": "{{row.order_number}}", "actions": [ - { "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders/{{row.order_number}}" } } + { "type": "click", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders/{{row.order_number}}", "mergeQuery": true, "query": {} } } ] } ] @@ -177,14 +177,14 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "_local", "filter.ordererUuid": "{{row.user?.uuid}}", "filter.searchField": "all", "filter.searchKeyword": "", "ordererSearchResults": "{{[{ uuid: row.user?.uuid, name: row.user?.name || row.address?.orderer_name, email: row.user?.email || '' }]}}" } }, - { "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "query": { "orderer_uuid": "{{row.user?.uuid}}", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } + { "comment": "이 주문자의 주문만 보기 — 앞선 setState 가 검색어를 비우므로 URL 의 검색 조건도 함께 비운다. 비우지 않으면 화면 입력창은 빈 채로 이전 검색어가 계속 적용된다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "mergeQuery": true, "query": { "orderer_uuid": "{{row.user?.uuid}}", "search_field": "", "search_keyword": "", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } ] }, "search_by_orderer_guest": { "handler": "sequence", "actions": [ - { "handler": "setState", "params": { "target": "_local", "filter.searchField": "orderer_name", "filter.searchKeyword": "{{row.address?.orderer_name || row.user?.name}}" } }, - { "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "query": { "search_field": "orderer_name", "search_keyword": "{{row.address?.orderer_name || row.user?.name}}", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } + { "handler": "setState", "params": { "target": "_local", "filter.searchField": "orderer_name", "filter.searchKeyword": "{{row.address?.orderer_name || row.user?.name}}", "filter.ordererUuid": "" } }, + { "comment": "비회원 주문자명으로 검색 — 회원 지정 필터(orderer_uuid)를 함께 비우지 않으면 이름 검색과 회원 필터가 겹쳐 결과가 비어 보인다 (#75).", "handler": "navigate", "params": { "path": "/admin/ecommerce/orders", "mergeQuery": true, "query": { "search_field": "orderer_name", "search_keyword": "{{row.address?.orderer_name || row.user?.name}}", "orderer_uuid": "", "page": 1 }, "transition_overlay_target": "order_datagrid__body" } } ] } } diff --git a/public/build/core/template-engine.min.js b/public/build/core/template-engine.min.js index d708b2d0..8415f566 100644 --- a/public/build/core/template-engine.min.js +++ b/public/build/core/template-engine.min.js @@ -1,20 +1,20 @@ -var Qx=Object.defineProperty;var Zx=(Vt,Wa,Ya)=>Wa in Vt?Qx(Vt,Wa,{enumerable:!0,configurable:!0,writable:!0,value:Ya}):Vt[Wa]=Ya;var $=(Vt,Wa,Ya)=>Zx(Vt,typeof Wa!="symbol"?Wa+"":Wa,Ya);(function(Vt){"use strict";function Wa(o,e){for(var a=0;ar[i]})}}}return Object.freeze(Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}))}function Ya(o){return o&&o.__esModule&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o}var Gu={exports:{}},Ke={};var Lg;function OS(){if(Lg)return Ke;Lg=1;var o=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),l=Symbol.for("react.consumer"),u=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),f=Symbol.for("react.suspense"),g=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),b=Symbol.for("react.activity"),v=Symbol.iterator;function S(x){return x===null||typeof x!="object"?null:(x=v&&x[v]||x["@@iterator"],typeof x=="function"?x:null)}var E={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},A=Object.assign,T={};function L(x,K,re){this.props=x,this.context=K,this.refs=T,this.updater=re||E}L.prototype.isReactComponent={},L.prototype.setState=function(x,K){if(typeof x!="object"&&typeof x!="function"&&x!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,x,K,"setState")},L.prototype.forceUpdate=function(x){this.updater.enqueueForceUpdate(this,x,"forceUpdate")};function M(){}M.prototype=L.prototype;function R(x,K,re){this.props=x,this.context=K,this.refs=T,this.updater=re||E}var D=R.prototype=new M;D.constructor=R,A(D,L.prototype),D.isPureReactComponent=!0;var U=Array.isArray;function j(){}var P={H:null,A:null,T:null,S:null},X=Object.prototype.hasOwnProperty;function ge(x,K,re){var de=re.ref;return{$$typeof:o,type:x,key:K,ref:de!==void 0?de:null,props:re}}function Ee(x,K){return ge(x.type,K,x.props)}function Ce(x){return typeof x=="object"&&x!==null&&x.$$typeof===o}function $e(x){var K={"=":"=0",":":"=2"};return"$"+x.replace(/[=:]/g,function(re){return K[re]})}var Pe=/\/+/g;function Xe(x,K){return typeof x=="object"&&x!==null&&x.key!=null?$e(""+x.key):K.toString(36)}function ht(x){switch(x.status){case"fulfilled":return x.value;case"rejected":throw x.reason;default:switch(typeof x.status=="string"?x.then(j,j):(x.status="pending",x.then(function(K){x.status==="pending"&&(x.status="fulfilled",x.value=K)},function(K){x.status==="pending"&&(x.status="rejected",x.reason=K)})),x.status){case"fulfilled":return x.value;case"rejected":throw x.reason}}throw x}function Q(x,K,re,de,se){var me=typeof x;(me==="undefined"||me==="boolean")&&(x=null);var Ne=!1;if(x===null)Ne=!0;else switch(me){case"bigint":case"string":case"number":Ne=!0;break;case"object":switch(x.$$typeof){case o:case e:Ne=!0;break;case m:return Ne=x._init,Q(Ne(x._payload),K,re,de,se)}}if(Ne)return se=se(x),Ne=de===""?"."+Xe(x,0):de,U(se)?(re="",Ne!=null&&(re=Ne.replace(Pe,"$&/")+"/"),Q(se,K,re,"",function(Ae){return Ae})):se!=null&&(Ce(se)&&(se=Ee(se,re+(se.key==null||x&&x.key===se.key?"":(""+se.key).replace(Pe,"$&/")+"/")+Ne)),K.push(se)),1;Ne=0;var ve=de===""?".":de+":";if(U(x))for(var He=0;He>>1,he=Q[te];if(0>>1;tei(re,ye))dei(se,re)?(Q[te]=se,Q[de]=ye,te=de):(Q[te]=re,Q[K]=ye,te=K);else if(dei(se,ye))Q[te]=se,Q[de]=ye,te=de;else break e}}return fe}function i(Q,fe){var ye=Q.sortIndex-fe.sortIndex;return ye!==0?ye:Q.id-fe.id}if(o.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var l=performance;o.unstable_now=function(){return l.now()}}else{var u=Date,d=u.now();o.unstable_now=function(){return u.now()-d}}var f=[],g=[],m=1,b=null,v=3,S=!1,E=!1,A=!1,T=!1,L=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,R=typeof setImmediate<"u"?setImmediate:null;function D(Q){for(var fe=a(g);fe!==null;){if(fe.callback===null)r(g);else if(fe.startTime<=Q)r(g),fe.sortIndex=fe.expirationTime,e(f,fe);else break;fe=a(g)}}function U(Q){if(A=!1,D(Q),!E)if(a(f)!==null)E=!0,j||(j=!0,$e());else{var fe=a(g);fe!==null&&ht(U,fe.startTime-Q)}}var j=!1,P=-1,X=5,ge=-1;function Ee(){return T?!0:!(o.unstable_now()-geQ&&Ee());){var te=b.callback;if(typeof te=="function"){b.callback=null,v=b.priorityLevel;var he=te(b.expirationTime<=Q);if(Q=o.unstable_now(),typeof he=="function"){b.callback=he,D(Q),fe=!0;break t}b===a(f)&&r(f),D(Q)}else r(f);b=a(f)}if(b!==null)fe=!0;else{var x=a(g);x!==null&&ht(U,x.startTime-Q),fe=!1}}break e}finally{b=null,v=ye,S=!1}fe=void 0}}finally{fe?$e():j=!1}}}var $e;if(typeof R=="function")$e=function(){R(Ce)};else if(typeof MessageChannel<"u"){var Pe=new MessageChannel,Xe=Pe.port2;Pe.port1.onmessage=Ce,$e=function(){Xe.postMessage(null)}}else $e=function(){L(Ce,0)};function ht(Q,fe){P=L(function(){Q(o.unstable_now())},fe)}o.unstable_IdlePriority=5,o.unstable_ImmediatePriority=1,o.unstable_LowPriority=4,o.unstable_NormalPriority=3,o.unstable_Profiling=null,o.unstable_UserBlockingPriority=2,o.unstable_cancelCallback=function(Q){Q.callback=null},o.unstable_forceFrameRate=function(Q){0>Q||125te?(Q.sortIndex=ye,e(g,Q),a(f)===null&&Q===a(g)&&(A?(M(P),P=-1):A=!0,ht(U,ye-te))):(Q.sortIndex=he,e(f,Q),E||S||(E=!0,j||(j=!0,$e()))),Q},o.unstable_shouldYield=Ee,o.unstable_wrapCallback=function(Q){var fe=v;return function(){var ye=v;v=fe;try{return Q.apply(this,arguments)}finally{v=ye}}}})(Wu)),Wu}var Ng;function MS(){return Ng||(Ng=1,Ku.exports=LS()),Ku.exports}var Yu={exports:{}},mn={};var Ig;function $S(){if(Ig)return mn;Ig=1;var o=Vu();function e(f){var g="https://react.dev/errors/"+f;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(o)}catch(e){console.error(e)}}return o(),Yu.exports=$S(),Yu.exports}var jg;function NS(){if(jg)return Gs;jg=1;var o=MS(),e=Vu(),a=zg();function r(t){var n="https://react.dev/errors/"+t;if(1he||(t.current=te[he],te[he]=null,he--)}function re(t,n){he++,te[he]=t.current,t.current=n}var de=x(null),se=x(null),me=x(null),Ne=x(null);function ve(t,n){switch(re(me,n),re(se,t),re(de,null),n.nodeType){case 9:case 11:t=(t=n.documentElement)&&(t=t.namespaceURI)?Jv(t):0;break;default:if(t=n.tagName,n=n.namespaceURI)n=Jv(n),t=Qv(n,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}K(de),re(de,t)}function He(){K(de),K(se),K(me)}function Ae(t){t.memoizedState!==null&&re(Ne,t);var n=de.current,s=Qv(n,t.type);n!==s&&(re(se,t),re(de,s))}function Et(t){se.current===t&&(K(de),K(se)),Ne.current===t&&(K(Ne),Sl._currentValue=ye)}var Rt,_t;function ft(t){if(Rt===void 0)try{throw Error()}catch(s){var n=s.stack.trim().match(/\n( *(at )?)/);Rt=n&&n[1]||"",_t=-1Wa in Ft?Qx(Ft,Wa,{enumerable:!0,configurable:!0,writable:!0,value:Ya}):Ft[Wa]=Ya;var $=(Ft,Wa,Ya)=>Zx(Ft,typeof Wa!="symbol"?Wa+"":Wa,Ya);(function(Ft){"use strict";function Wa(o,e){for(var a=0;ar[i]})}}}return Object.freeze(Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}))}function Ya(o){return o&&o.__esModule&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o}var Vu={exports:{}},Ke={};var Mg;function OS(){if(Mg)return Ke;Mg=1;var o=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),l=Symbol.for("react.consumer"),u=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),f=Symbol.for("react.suspense"),g=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),b=Symbol.for("react.activity"),v=Symbol.iterator;function S(x){return x===null||typeof x!="object"?null:(x=v&&x[v]||x["@@iterator"],typeof x=="function"?x:null)}var E={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},A=Object.assign,T={};function L(x,K,re){this.props=x,this.context=K,this.refs=T,this.updater=re||E}L.prototype.isReactComponent={},L.prototype.setState=function(x,K){if(typeof x!="object"&&typeof x!="function"&&x!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,x,K,"setState")},L.prototype.forceUpdate=function(x){this.updater.enqueueForceUpdate(this,x,"forceUpdate")};function M(){}M.prototype=L.prototype;function R(x,K,re){this.props=x,this.context=K,this.refs=T,this.updater=re||E}var D=R.prototype=new M;D.constructor=R,A(D,L.prototype),D.isPureReactComponent=!0;var U=Array.isArray;function j(){}var P={H:null,A:null,T:null,S:null},X=Object.prototype.hasOwnProperty;function ge(x,K,re){var de=re.ref;return{$$typeof:o,type:x,key:K,ref:de!==void 0?de:null,props:re}}function Ee(x,K){return ge(x.type,K,x.props)}function Ce(x){return typeof x=="object"&&x!==null&&x.$$typeof===o}function $e(x){var K={"=":"=0",":":"=2"};return"$"+x.replace(/[=:]/g,function(re){return K[re]})}var Pe=/\/+/g;function Xe(x,K){return typeof x=="object"&&x!==null&&x.key!=null?$e(""+x.key):K.toString(36)}function ht(x){switch(x.status){case"fulfilled":return x.value;case"rejected":throw x.reason;default:switch(typeof x.status=="string"?x.then(j,j):(x.status="pending",x.then(function(K){x.status==="pending"&&(x.status="fulfilled",x.value=K)},function(K){x.status==="pending"&&(x.status="rejected",x.reason=K)})),x.status){case"fulfilled":return x.value;case"rejected":throw x.reason}}throw x}function Q(x,K,re,de,ie){var me=typeof x;(me==="undefined"||me==="boolean")&&(x=null);var Ne=!1;if(x===null)Ne=!0;else switch(me){case"bigint":case"string":case"number":Ne=!0;break;case"object":switch(x.$$typeof){case o:case e:Ne=!0;break;case m:return Ne=x._init,Q(Ne(x._payload),K,re,de,ie)}}if(Ne)return ie=ie(x),Ne=de===""?"."+Xe(x,0):de,U(ie)?(re="",Ne!=null&&(re=Ne.replace(Pe,"$&/")+"/"),Q(ie,K,re,"",function(Ae){return Ae})):ie!=null&&(Ce(ie)&&(ie=Ee(ie,re+(ie.key==null||x&&x.key===ie.key?"":(""+ie.key).replace(Pe,"$&/")+"/")+Ne)),K.push(ie)),1;Ne=0;var Se=de===""?".":de+":";if(U(x))for(var He=0;He>>1,he=Q[te];if(0>>1;tei(re,ye))dei(ie,re)?(Q[te]=ie,Q[de]=ye,te=de):(Q[te]=re,Q[K]=ye,te=K);else if(dei(ie,ye))Q[te]=ie,Q[de]=ye,te=de;else break e}}return fe}function i(Q,fe){var ye=Q.sortIndex-fe.sortIndex;return ye!==0?ye:Q.id-fe.id}if(o.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var l=performance;o.unstable_now=function(){return l.now()}}else{var u=Date,d=u.now();o.unstable_now=function(){return u.now()-d}}var f=[],g=[],m=1,b=null,v=3,S=!1,E=!1,A=!1,T=!1,L=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,R=typeof setImmediate<"u"?setImmediate:null;function D(Q){for(var fe=a(g);fe!==null;){if(fe.callback===null)r(g);else if(fe.startTime<=Q)r(g),fe.sortIndex=fe.expirationTime,e(f,fe);else break;fe=a(g)}}function U(Q){if(A=!1,D(Q),!E)if(a(f)!==null)E=!0,j||(j=!0,$e());else{var fe=a(g);fe!==null&&ht(U,fe.startTime-Q)}}var j=!1,P=-1,X=5,ge=-1;function Ee(){return T?!0:!(o.unstable_now()-geQ&&Ee());){var te=b.callback;if(typeof te=="function"){b.callback=null,v=b.priorityLevel;var he=te(b.expirationTime<=Q);if(Q=o.unstable_now(),typeof he=="function"){b.callback=he,D(Q),fe=!0;break t}b===a(f)&&r(f),D(Q)}else r(f);b=a(f)}if(b!==null)fe=!0;else{var x=a(g);x!==null&&ht(U,x.startTime-Q),fe=!1}}break e}finally{b=null,v=ye,S=!1}fe=void 0}}finally{fe?$e():j=!1}}}var $e;if(typeof R=="function")$e=function(){R(Ce)};else if(typeof MessageChannel<"u"){var Pe=new MessageChannel,Xe=Pe.port2;Pe.port1.onmessage=Ce,$e=function(){Xe.postMessage(null)}}else $e=function(){L(Ce,0)};function ht(Q,fe){P=L(function(){Q(o.unstable_now())},fe)}o.unstable_IdlePriority=5,o.unstable_ImmediatePriority=1,o.unstable_LowPriority=4,o.unstable_NormalPriority=3,o.unstable_Profiling=null,o.unstable_UserBlockingPriority=2,o.unstable_cancelCallback=function(Q){Q.callback=null},o.unstable_forceFrameRate=function(Q){0>Q||125te?(Q.sortIndex=ye,e(g,Q),a(f)===null&&Q===a(g)&&(A?(M(P),P=-1):A=!0,ht(U,ye-te))):(Q.sortIndex=he,e(f,Q),E||S||(E=!0,j||(j=!0,$e()))),Q},o.unstable_shouldYield=Ee,o.unstable_wrapCallback=function(Q){var fe=v;return function(){var ye=v;v=fe;try{return Q.apply(this,arguments)}finally{v=ye}}}})(Yu)),Yu}var Ig;function MS(){return Ig||(Ig=1,Wu.exports=LS()),Wu.exports}var Xu={exports:{}},mn={};var Hg;function $S(){if(Hg)return mn;Hg=1;var o=Fu();function e(f){var g="https://react.dev/errors/"+f;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(o)}catch(e){console.error(e)}}return o(),Xu.exports=$S(),Xu.exports}var Ug;function NS(){if(Ug)return Vs;Ug=1;var o=MS(),e=Fu(),a=jg();function r(t){var n="https://react.dev/errors/"+t;if(1he||(t.current=te[he],te[he]=null,he--)}function re(t,n){he++,te[he]=t.current,t.current=n}var de=x(null),ie=x(null),me=x(null),Ne=x(null);function Se(t,n){switch(re(me,n),re(ie,t),re(de,null),n.nodeType){case 9:case 11:t=(t=n.documentElement)&&(t=t.namespaceURI)?Jv(t):0;break;default:if(t=n.tagName,n=n.namespaceURI)n=Jv(n),t=Qv(n,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}K(de),re(de,t)}function He(){K(de),K(ie),K(me)}function Ae(t){t.memoizedState!==null&&re(Ne,t);var n=de.current,s=Qv(n,t.type);n!==s&&(re(ie,t),re(de,s))}function Et(t){ie.current===t&&(K(de),K(ie)),Ne.current===t&&(K(Ne),wl._currentValue=ye)}var kt,_t;function ft(t){if(kt===void 0)try{throw Error()}catch(s){var n=s.stack.trim().match(/\n( *(at )?)/);kt=n&&n[1]||"",_t=-1)":-1h||z[c]!==Y[h]){var ae=` `+z[c].replace(" at new "," at ");return t.displayName&&ae.includes("")&&(ae=ae.replace("",t.displayName)),ae}while(1<=c&&0<=h);break}}}finally{un=!1,Error.prepareStackTrace=s}return(s=t?t.displayName||t.name:"")?ft(s):""}function ja(t,n){switch(t.tag){case 26:case 27:case 5:return ft(t.type);case 16:return ft("Lazy");case 13:return t.child!==n&&n!==null?ft("Suspense Fallback"):ft("Suspense");case 19:return ft("SuspenseList");case 0:case 15:return gt(t.type,!1);case 11:return gt(t.type.render,!1);case 1:return gt(t.type,!0);case 31:return ft("Activity");default:return""}}function kn(t){try{var n="",s=null;do n+=ja(t,s),s=t,t=t.return;while(t);return n}catch(c){return` Error generating stack: `+c.message+` -`+c.stack}}var Dn=Object.prototype.hasOwnProperty,jt=o.unstable_scheduleCallback,On=o.unstable_cancelCallback,ea=o.unstable_shouldYield,Ua=o.unstable_requestPaint,Ft=o.unstable_now,Dr=o.unstable_getCurrentPriorityLevel,er=o.unstable_ImmediatePriority,bn=o.unstable_UserBlockingPriority,en=o.unstable_NormalPriority,et=o.unstable_LowPriority,ta=o.unstable_IdlePriority,En=o.log,tr=o.unstable_setDisableYieldValue,Ea=null,tn=null;function _n(t){if(typeof En=="function"&&tr(t),tn&&typeof tn.setStrictMode=="function")try{tn.setStrictMode(Ea,t)}catch{}}var q=Math.clz32?Math.clz32:Z,ce=Math.log,le=Math.LN2;function Z(t){return t>>>=0,t===0?32:31-(ce(t)/le|0)|0}var be=256,Se=262144,Re=4194304;function xe(t){var n=t&42;if(n!==0)return n;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&261888;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function je(t,n,s){var c=t.pendingLanes;if(c===0)return 0;var h=0,p=t.suspendedLanes,w=t.pingedLanes;t=t.warmLanes;var k=c&134217727;return k!==0?(c=k&~p,c!==0?h=xe(c):(w&=k,w!==0?h=xe(w):s||(s=k&~t,s!==0&&(h=xe(s))))):(k=c&~p,k!==0?h=xe(k):w!==0?h=xe(w):s||(s=c&~t,s!==0&&(h=xe(s)))),h===0?0:n!==0&&n!==h&&(n&p)===0&&(p=h&-h,s=n&-n,p>=s||p===32&&(s&4194048)!==0)?n:h}function ze(t,n){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&n)===0}function Le(t,n){switch(t){case 1:case 2:case 4:case 8:case 64:return n+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ke(){var t=Re;return Re<<=1,(Re&62914560)===0&&(Re=4194304),t}function We(t){for(var n=[],s=0;31>s;s++)n.push(t);return n}function Fe(t,n){t.pendingLanes|=n,n!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function _e(t,n,s,c,h,p){var w=t.pendingLanes;t.pendingLanes=s,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=s,t.entangledLanes&=s,t.errorRecoveryDisabledLanes&=s,t.shellSuspendCounter=0;var k=t.entanglements,z=t.expirationTimes,Y=t.hiddenUpdates;for(s=w&~s;0"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var bf=/[\n"\\]/g;function $n(t){return t.replace(bf,function(n){return"\\"+n.charCodeAt(0).toString(16)+" "})}function us(t,n,s,c,h,p,w,k){t.name="",w!=null&&typeof w!="function"&&typeof w!="symbol"&&typeof w!="boolean"?t.type=w:t.removeAttribute("type"),n!=null?w==="number"?(n===0&&t.value===""||t.value!=n)&&(t.value=""+Sn(n)):t.value!==""+Sn(n)&&(t.value=""+Sn(n)):w!=="submit"&&w!=="reset"||t.removeAttribute("value"),n!=null?ar(t,w,Sn(n)):s!=null?ar(t,w,Sn(s)):c!=null&&t.removeAttribute("value"),h==null&&p!=null&&(t.defaultChecked=!!p),h!=null&&(t.checked=h&&typeof h!="function"&&typeof h!="symbol"),k!=null&&typeof k!="function"&&typeof k!="symbol"&&typeof k!="boolean"?t.name=""+Sn(k):t.removeAttribute("name")}function vi(t,n,s,c,h,p,w,k){if(p!=null&&typeof p!="function"&&typeof p!="symbol"&&typeof p!="boolean"&&(t.type=p),n!=null||s!=null){if(!(p!=="submit"&&p!=="reset"||n!=null)){ko(t);return}s=s!=null?""+Sn(s):"",n=n!=null?""+Sn(n):s,k||n===t.value||(t.value=n),t.defaultValue=n}c=c??h,c=typeof c!="function"&&typeof c!="symbol"&&!!c,t.checked=k?t.checked:!!c,t.defaultChecked=!!c,w!=null&&typeof w!="function"&&typeof w!="symbol"&&typeof w!="boolean"&&(t.name=w),ko(t)}function ar(t,n,s){n==="number"&&Nr(t.ownerDocument)===t||t.defaultValue===""+s||(t.defaultValue=""+s)}function Ir(t,n,s,c){if(t=t.options,n){n={};for(var h=0;h"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),$o=!1;if(xa)try{var wi={};Object.defineProperty(wi,"passive",{get:function(){$o=!0}}),window.addEventListener("test",wi,wi),window.removeEventListener("test",wi,wi)}catch{$o=!1}var qa=null,No=null,fs=null;function Dc(){if(fs)return fs;var t,n=No,s=n.length,c,h="value"in qa?qa.value:qa.textContent,p=h.length;for(t=0;t=ne),Ve=" ",ot=!1;function pt(t,n){switch(t){case"keyup":return O.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Nt(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Ra=!1;function If(t,n){switch(t){case"compositionend":return Nt(n);case"keypress":return n.which!==32?null:(ot=!0,Ve);case"textInput":return t=n.data,t===Ve&&ot?null:t;default:return null}}function Hc(t,n){if(Ra)return t==="compositionend"||!I&&pt(t,n)?(t=Dc(),fs=No=qa=null,Ra=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1=n)return{node:s,offset:n-t};t=c}e:{for(;s;){if(s.nextSibling){s=s.nextSibling;break e}s=s.parentNode}s=void 0}s=py(s)}}function yy(t,n){return t&&n?t===n?!0:t&&t.nodeType===3?!1:n&&n.nodeType===3?yy(t,n.parentNode):"contains"in t?t.contains(n):t.compareDocumentPosition?!!(t.compareDocumentPosition(n)&16):!1:!1}function by(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var n=Nr(t.document);n instanceof t.HTMLIFrameElement;){try{var s=typeof n.contentWindow.location.href=="string"}catch{s=!1}if(s)t=n.contentWindow;else break;n=Nr(t.document)}return n}function Bf(t){var n=t&&t.nodeName&&t.nodeName.toLowerCase();return n&&(n==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||n==="textarea"||t.contentEditable==="true")}var OA=xa&&"documentMode"in document&&11>=document.documentMode,ms=null,Pf=null,Vo=null,qf=!1;function vy(t,n,s){var c=s.window===s?s.document:s.nodeType===9?s:s.ownerDocument;qf||ms==null||ms!==Nr(c)||(c=ms,"selectionStart"in c&&Bf(c)?c={start:c.selectionStart,end:c.selectionEnd}:(c=(c.ownerDocument&&c.ownerDocument.defaultView||window).getSelection(),c={anchorNode:c.anchorNode,anchorOffset:c.anchorOffset,focusNode:c.focusNode,focusOffset:c.focusOffset}),Vo&&Go(Vo,c)||(Vo=c,c=ku(Pf,"onSelect"),0>=w,h-=w,Ga=1<<32-q(n)+h|s<Qe?(rt=Ie,Ie=null):rt=Ie.sibling;var yt=J(V,Ie,W[Qe],oe);if(yt===null){Ie===null&&(Ie=rt);break}t&&Ie&&yt.alternate===null&&n(V,Ie),G=p(yt,G,Qe),mt===null?qe=yt:mt.sibling=yt,mt=yt,Ie=rt}if(Qe===W.length)return s(V,Ie),lt&&or(V,Qe),qe;if(Ie===null){for(;QeQe?(rt=Ie,Ie=null):rt=Ie.sibling;var li=J(V,Ie,yt.value,oe);if(li===null){Ie===null&&(Ie=rt);break}t&&Ie&&li.alternate===null&&n(V,Ie),G=p(li,G,Qe),mt===null?qe=li:mt.sibling=li,mt=li,Ie=rt}if(yt.done)return s(V,Ie),lt&&or(V,Qe),qe;if(Ie===null){for(;!yt.done;Qe++,yt=W.next())yt=ue(V,yt.value,oe),yt!==null&&(G=p(yt,G,Qe),mt===null?qe=yt:mt.sibling=yt,mt=yt);return lt&&or(V,Qe),qe}for(Ie=c(Ie);!yt.done;Qe++,yt=W.next())yt=ee(Ie,V,Qe,yt.value,oe),yt!==null&&(t&&yt.alternate!==null&&Ie.delete(yt.key===null?Qe:yt.key),G=p(yt,G,Qe),mt===null?qe=yt:mt.sibling=yt,mt=yt);return t&&Ie.forEach(function(Jx){return n(V,Jx)}),lt&&or(V,Qe),qe}function Tt(V,G,W,oe){if(typeof W=="object"&&W!==null&&W.type===A&&W.key===null&&(W=W.props.children),typeof W=="object"&&W!==null){switch(W.$$typeof){case S:e:{for(var qe=W.key;G!==null;){if(G.key===qe){if(qe=W.type,qe===A){if(G.tag===7){s(V,G.sibling),oe=h(G,W.props.children),oe.return=V,V=oe;break e}}else if(G.elementType===qe||typeof qe=="object"&&qe!==null&&qe.$$typeof===X&&Hi(qe)===G.type){s(V,G.sibling),oe=h(G,W.props),Jo(oe,W),oe.return=V,V=oe;break e}s(V,G);break}else n(V,G);G=G.sibling}W.type===A?(oe=Li(W.props.children,V.mode,oe,W.key),oe.return=V,V=oe):(oe=Fc(W.type,W.key,W.props,null,V.mode,oe),Jo(oe,W),oe.return=V,V=oe)}return w(V);case E:e:{for(qe=W.key;G!==null;){if(G.key===qe)if(G.tag===4&&G.stateNode.containerInfo===W.containerInfo&&G.stateNode.implementation===W.implementation){s(V,G.sibling),oe=h(G,W.children||[]),oe.return=V,V=oe;break e}else{s(V,G);break}else n(V,G);G=G.sibling}oe=Xf(W,V.mode,oe),oe.return=V,V=oe}return w(V);case X:return W=Hi(W),Tt(V,G,W,oe)}if(ht(W))return De(V,G,W,oe);if($e(W)){if(qe=$e(W),typeof qe!="function")throw Error(r(150));return W=qe.call(W),Ge(V,G,W,oe)}if(typeof W.then=="function")return Tt(V,G,Zc(W),oe);if(W.$$typeof===R)return Tt(V,G,Yc(V,W),oe);eu(V,W)}return typeof W=="string"&&W!==""||typeof W=="number"||typeof W=="bigint"?(W=""+W,G!==null&&G.tag===6?(s(V,G.sibling),oe=h(G,W),oe.return=V,V=oe):(s(V,G),oe=Yf(W,V.mode,oe),oe.return=V,V=oe),w(V)):s(V,G)}return function(V,G,W,oe){try{Xo=0;var qe=Tt(V,G,W,oe);return Ts=null,qe}catch(Ie){if(Ie===xs||Ie===Jc)throw Ie;var mt=Vn(29,Ie,null,V.mode);return mt.lanes=oe,mt.return=V,mt}}}var ji=Py(!0),qy=Py(!1),Vr=!1;function lh(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function ch(t,n){t=t.updateQueue,n.updateQueue===t&&(n.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Fr(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Kr(t,n,s){var c=t.updateQueue;if(c===null)return null;if(c=c.shared,(vt&2)!==0){var h=c.pending;return h===null?n.next=n:(n.next=h.next,h.next=n),c.pending=n,n=Vc(t),xy(t,null,s),n}return Gc(t,c,n,s),Vc(t)}function Qo(t,n,s){if(n=n.updateQueue,n!==null&&(n=n.shared,(s&4194048)!==0)){var c=n.lanes;c&=t.pendingLanes,s|=c,n.lanes=s,Ue(t,s)}}function uh(t,n){var s=t.updateQueue,c=t.alternate;if(c!==null&&(c=c.updateQueue,s===c)){var h=null,p=null;if(s=s.firstBaseUpdate,s!==null){do{var w={lane:s.lane,tag:s.tag,payload:s.payload,callback:null,next:null};p===null?h=p=w:p=p.next=w,s=s.next}while(s!==null);p===null?h=p=n:p=p.next=n}else h=p=n;s={baseState:c.baseState,firstBaseUpdate:h,lastBaseUpdate:p,shared:c.shared,callbacks:c.callbacks},t.updateQueue=s;return}t=s.lastBaseUpdate,t===null?s.firstBaseUpdate=n:t.next=n,s.lastBaseUpdate=n}var dh=!1;function Zo(){if(dh){var t=As;if(t!==null)throw t}}function el(t,n,s,c){dh=!1;var h=t.updateQueue;Vr=!1;var p=h.firstBaseUpdate,w=h.lastBaseUpdate,k=h.shared.pending;if(k!==null){h.shared.pending=null;var z=k,Y=z.next;z.next=null,w===null?p=Y:w.next=Y,w=z;var ae=t.alternate;ae!==null&&(ae=ae.updateQueue,k=ae.lastBaseUpdate,k!==w&&(k===null?ae.firstBaseUpdate=Y:k.next=Y,ae.lastBaseUpdate=z))}if(p!==null){var ue=h.baseState;w=0,ae=Y=z=null,k=p;do{var J=k.lane&-536870913,ee=J!==k.lane;if(ee?(at&J)===J:(c&J)===J){J!==0&&J===_s&&(dh=!0),ae!==null&&(ae=ae.next={lane:0,tag:k.tag,payload:k.payload,callback:null,next:null});e:{var De=t,Ge=k;J=n;var Tt=s;switch(Ge.tag){case 1:if(De=Ge.payload,typeof De=="function"){ue=De.call(Tt,ue,J);break e}ue=De;break e;case 3:De.flags=De.flags&-65537|128;case 0:if(De=Ge.payload,J=typeof De=="function"?De.call(Tt,ue,J):De,J==null)break e;ue=b({},ue,J);break e;case 2:Vr=!0}}J=k.callback,J!==null&&(t.flags|=64,ee&&(t.flags|=8192),ee=h.callbacks,ee===null?h.callbacks=[J]:ee.push(J))}else ee={lane:J,tag:k.tag,payload:k.payload,callback:k.callback,next:null},ae===null?(Y=ae=ee,z=ue):ae=ae.next=ee,w|=J;if(k=k.next,k===null){if(k=h.shared.pending,k===null)break;ee=k,k=ee.next,ee.next=null,h.lastBaseUpdate=ee,h.shared.pending=null}}while(!0);ae===null&&(z=ue),h.baseState=z,h.firstBaseUpdate=Y,h.lastBaseUpdate=ae,p===null&&(h.shared.lanes=0),Qr|=w,t.lanes=w,t.memoizedState=ue}}function Gy(t,n){if(typeof t!="function")throw Error(r(191,t));t.call(n)}function Vy(t,n){var s=t.callbacks;if(s!==null)for(t.callbacks=null,t=0;tp?p:8;var w=Q.T,k={};Q.T=k,Dh(t,!1,n,s);try{var z=h(),Y=Q.S;if(Y!==null&&Y(k,z),z!==null&&typeof z=="object"&&typeof z.then=="function"){var ae=UA(z,c);al(t,n,ae,Xn(t))}else al(t,n,c,Xn(t))}catch(ue){al(t,n,{then:function(){},status:"rejected",reason:ue},Xn())}finally{fe.p=p,w!==null&&k.types!==null&&(w.types=k.types),Q.T=w}}function FA(){}function Rh(t,n,s,c){if(t.tag!==5)throw Error(r(476));var h=Eb(t).queue;Cb(t,h,n,ye,s===null?FA:function(){return _b(t),s(c)})}function Eb(t){var n=t.memoizedState;if(n!==null)return n;n={memoizedState:ye,baseState:ye,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:dr,lastRenderedState:ye},next:null};var s={};return n.next={memoizedState:s,baseState:s,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:dr,lastRenderedState:s},next:null},t.memoizedState=n,t=t.alternate,t!==null&&(t.memoizedState=n),n}function _b(t){var n=Eb(t);n.next===null&&(n=t.alternate.memoizedState),al(t,n.next.queue,{},Xn())}function kh(){return hn(Sl)}function Ab(){return Gt().memoizedState}function xb(){return Gt().memoizedState}function KA(t){for(var n=t.return;n!==null;){switch(n.tag){case 24:case 3:var s=Xn();t=Fr(s);var c=Kr(n,t,s);c!==null&&(jn(c,n,s),Qo(c,n,s)),n={cache:rh()},t.payload=n;return}n=n.return}}function WA(t,n,s){var c=Xn();s={lane:c,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null},uu(t)?Rb(n,s):(s=Kf(t,n,s,c),s!==null&&(jn(s,t,c),kb(s,n,c)))}function Tb(t,n,s){var c=Xn();al(t,n,s,c)}function al(t,n,s,c){var h={lane:c,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null};if(uu(t))Rb(n,h);else{var p=t.alternate;if(t.lanes===0&&(p===null||p.lanes===0)&&(p=n.lastRenderedReducer,p!==null))try{var w=n.lastRenderedState,k=p(w,s);if(h.hasEagerState=!0,h.eagerState=k,Gn(k,w))return Gc(t,n,h,0),kt===null&&qc(),!1}catch{}if(s=Kf(t,n,h,c),s!==null)return jn(s,t,c),kb(s,n,c),!0}return!1}function Dh(t,n,s,c){if(c={lane:2,revertLane:lg(),gesture:null,action:c,hasEagerState:!1,eagerState:null,next:null},uu(t)){if(n)throw Error(r(479))}else n=Kf(t,s,c,2),n!==null&&jn(n,t,2)}function uu(t){var n=t.alternate;return t===Je||n!==null&&n===Je}function Rb(t,n){ks=au=!0;var s=t.pending;s===null?n.next=n:(n.next=s.next,s.next=n),t.pending=n}function kb(t,n,s){if((s&4194048)!==0){var c=n.lanes;c&=t.pendingLanes,s|=c,n.lanes=s,Ue(t,s)}}var rl={readContext:hn,use:su,useCallback:Ut,useContext:Ut,useEffect:Ut,useImperativeHandle:Ut,useLayoutEffect:Ut,useInsertionEffect:Ut,useMemo:Ut,useReducer:Ut,useRef:Ut,useState:Ut,useDebugValue:Ut,useDeferredValue:Ut,useTransition:Ut,useSyncExternalStore:Ut,useId:Ut,useHostTransitionStatus:Ut,useFormState:Ut,useActionState:Ut,useOptimistic:Ut,useMemoCache:Ut,useCacheRefresh:Ut};rl.useEffectEvent=Ut;var Db={readContext:hn,use:su,useCallback:function(t,n){return An().memoizedState=[t,n===void 0?null:n],t},useContext:hn,useEffect:hb,useImperativeHandle:function(t,n,s){s=s!=null?s.concat([t]):null,lu(4194308,4,yb.bind(null,n,t),s)},useLayoutEffect:function(t,n){return lu(4194308,4,t,n)},useInsertionEffect:function(t,n){lu(4,2,t,n)},useMemo:function(t,n){var s=An();n=n===void 0?null:n;var c=t();if(Ui){_n(!0);try{t()}finally{_n(!1)}}return s.memoizedState=[c,n],c},useReducer:function(t,n,s){var c=An();if(s!==void 0){var h=s(n);if(Ui){_n(!0);try{s(n)}finally{_n(!1)}}}else h=n;return c.memoizedState=c.baseState=h,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:h},c.queue=t,t=t.dispatch=WA.bind(null,Je,t),[c.memoizedState,t]},useRef:function(t){var n=An();return t={current:t},n.memoizedState=t},useState:function(t){t=Eh(t);var n=t.queue,s=Tb.bind(null,Je,n);return n.dispatch=s,[t.memoizedState,s]},useDebugValue:xh,useDeferredValue:function(t,n){var s=An();return Th(s,t,n)},useTransition:function(){var t=Eh(!1);return t=Cb.bind(null,Je,t.queue,!0,!1),An().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,n,s){var c=Je,h=An();if(lt){if(s===void 0)throw Error(r(407));s=s()}else{if(s=n(),kt===null)throw Error(r(349));(at&127)!==0||Jy(c,n,s)}h.memoizedState=s;var p={value:s,getSnapshot:n};return h.queue=p,hb(Zy.bind(null,c,p,t),[t]),c.flags|=2048,Os(9,{destroy:void 0},Qy.bind(null,c,p,s,n),null),s},useId:function(){var t=An(),n=kt.identifierPrefix;if(lt){var s=Va,c=Ga;s=(c&~(1<<32-q(c)-1)).toString(32)+s,n="_"+n+"R_"+s,s=ru++,0<\/script>",p=p.removeChild(p.firstChild);break;case"select":p=typeof c.is=="string"?w.createElement("select",{is:c.is}):w.createElement("select"),c.multiple?p.multiple=!0:c.size&&(p.size=c.size);break;default:p=typeof c.is=="string"?w.createElement(h,{is:c.is}):w.createElement(h)}}p[an]=n,p[vn]=c;e:for(w=n.child;w!==null;){if(w.tag===5||w.tag===6)p.appendChild(w.stateNode);else if(w.tag!==4&&w.tag!==27&&w.child!==null){w.child.return=w,w=w.child;continue}if(w===n)break e;for(;w.sibling===null;){if(w.return===null||w.return===n)break e;w=w.return}w.sibling.return=w.return,w=w.sibling}n.stateNode=p;e:switch(pn(p,h,c),h){case"button":case"input":case"select":case"textarea":c=!!c.autoFocus;break e;case"img":c=!0;break e;default:c=!1}c&&hr(n)}}return Lt(n),Gh(n,n.type,t===null?null:t.memoizedProps,n.pendingProps,s),null;case 6:if(t&&n.stateNode!=null)t.memoizedProps!==c&&hr(n);else{if(typeof c!="string"&&n.stateNode===null)throw Error(r(166));if(t=me.current,Cs(n)){if(t=n.stateNode,s=n.memoizedProps,c=null,h=fn,h!==null)switch(h.tag){case 27:case 5:c=h.memoizedProps}t[an]=n,t=!!(t.nodeValue===s||c!==null&&c.suppressHydrationWarning===!0||Yv(t.nodeValue,s)),t||qr(n,!0)}else t=Du(t).createTextNode(c),t[an]=n,n.stateNode=t}return Lt(n),null;case 31:if(s=n.memoizedState,t===null||t.memoizedState!==null){if(c=Cs(n),s!==null){if(t===null){if(!c)throw Error(r(318));if(t=n.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(r(557));t[an]=n}else Mi(),(n.flags&128)===0&&(n.memoizedState=null),n.flags|=4;Lt(n),t=!1}else s=eh(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=s),t=!0;if(!t)return n.flags&256?(Kn(n),n):(Kn(n),null);if((n.flags&128)!==0)throw Error(r(558))}return Lt(n),null;case 13:if(c=n.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(h=Cs(n),c!==null&&c.dehydrated!==null){if(t===null){if(!h)throw Error(r(318));if(h=n.memoizedState,h=h!==null?h.dehydrated:null,!h)throw Error(r(317));h[an]=n}else Mi(),(n.flags&128)===0&&(n.memoizedState=null),n.flags|=4;Lt(n),h=!1}else h=eh(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=h),h=!0;if(!h)return n.flags&256?(Kn(n),n):(Kn(n),null)}return Kn(n),(n.flags&128)!==0?(n.lanes=s,n):(s=c!==null,t=t!==null&&t.memoizedState!==null,s&&(c=n.child,h=null,c.alternate!==null&&c.alternate.memoizedState!==null&&c.alternate.memoizedState.cachePool!==null&&(h=c.alternate.memoizedState.cachePool.pool),p=null,c.memoizedState!==null&&c.memoizedState.cachePool!==null&&(p=c.memoizedState.cachePool.pool),p!==h&&(c.flags|=2048)),s!==t&&s&&(n.child.flags|=8192),pu(n,n.updateQueue),Lt(n),null);case 4:return He(),t===null&&fg(n.stateNode.containerInfo),Lt(n),null;case 10:return cr(n.type),Lt(n),null;case 19:if(K(qt),c=n.memoizedState,c===null)return Lt(n),null;if(h=(n.flags&128)!==0,p=c.rendering,p===null)if(h)sl(c,!1);else{if(Bt!==0||t!==null&&(t.flags&128)!==0)for(t=n.child;t!==null;){if(p=nu(t),p!==null){for(n.flags|=128,sl(c,!1),t=p.updateQueue,n.updateQueue=t,pu(n,t),n.subtreeFlags=0,t=s,s=n.child;s!==null;)Ty(s,t),s=s.sibling;return re(qt,qt.current&1|2),lt&&or(n,c.treeForkCount),n.child}t=t.sibling}c.tail!==null&&Ft()>Su&&(n.flags|=128,h=!0,sl(c,!1),n.lanes=4194304)}else{if(!h)if(t=nu(p),t!==null){if(n.flags|=128,h=!0,t=t.updateQueue,n.updateQueue=t,pu(n,t),sl(c,!0),c.tail===null&&c.tailMode==="hidden"&&!p.alternate&&!lt)return Lt(n),null}else 2*Ft()-c.renderingStartTime>Su&&s!==536870912&&(n.flags|=128,h=!0,sl(c,!1),n.lanes=4194304);c.isBackwards?(p.sibling=n.child,n.child=p):(t=c.last,t!==null?t.sibling=p:n.child=p,c.last=p)}return c.tail!==null?(t=c.tail,c.rendering=t,c.tail=t.sibling,c.renderingStartTime=Ft(),t.sibling=null,s=qt.current,re(qt,h?s&1|2:s&1),lt&&or(n,c.treeForkCount),t):(Lt(n),null);case 22:case 23:return Kn(n),hh(),c=n.memoizedState!==null,t!==null?t.memoizedState!==null!==c&&(n.flags|=8192):c&&(n.flags|=8192),c?(s&536870912)!==0&&(n.flags&128)===0&&(Lt(n),n.subtreeFlags&6&&(n.flags|=8192)):Lt(n),s=n.updateQueue,s!==null&&pu(n,s.retryQueue),s=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(s=t.memoizedState.cachePool.pool),c=null,n.memoizedState!==null&&n.memoizedState.cachePool!==null&&(c=n.memoizedState.cachePool.pool),c!==s&&(n.flags|=2048),t!==null&&K(Ii),null;case 24:return s=null,t!==null&&(s=t.memoizedState.cache),n.memoizedState.cache!==s&&(n.flags|=2048),cr(Yt),Lt(n),null;case 25:return null;case 30:return null}throw Error(r(156,n.tag))}function ZA(t,n){switch(Qf(n),n.tag){case 1:return t=n.flags,t&65536?(n.flags=t&-65537|128,n):null;case 3:return cr(Yt),He(),t=n.flags,(t&65536)!==0&&(t&128)===0?(n.flags=t&-65537|128,n):null;case 26:case 27:case 5:return Et(n),null;case 31:if(n.memoizedState!==null){if(Kn(n),n.alternate===null)throw Error(r(340));Mi()}return t=n.flags,t&65536?(n.flags=t&-65537|128,n):null;case 13:if(Kn(n),t=n.memoizedState,t!==null&&t.dehydrated!==null){if(n.alternate===null)throw Error(r(340));Mi()}return t=n.flags,t&65536?(n.flags=t&-65537|128,n):null;case 19:return K(qt),null;case 4:return He(),null;case 10:return cr(n.type),null;case 22:case 23:return Kn(n),hh(),t!==null&&K(Ii),t=n.flags,t&65536?(n.flags=t&-65537|128,n):null;case 24:return cr(Yt),null;case 25:return null;default:return null}}function ev(t,n){switch(Qf(n),n.tag){case 3:cr(Yt),He();break;case 26:case 27:case 5:Et(n);break;case 4:He();break;case 31:n.memoizedState!==null&&Kn(n);break;case 13:Kn(n);break;case 19:K(qt);break;case 10:cr(n.type);break;case 22:case 23:Kn(n),hh(),t!==null&&K(Ii);break;case 24:cr(Yt)}}function ol(t,n){try{var s=n.updateQueue,c=s!==null?s.lastEffect:null;if(c!==null){var h=c.next;s=h;do{if((s.tag&t)===t){c=void 0;var p=s.create,w=s.inst;c=p(),w.destroy=c}s=s.next}while(s!==h)}}catch(k){Ct(n,n.return,k)}}function Xr(t,n,s){try{var c=n.updateQueue,h=c!==null?c.lastEffect:null;if(h!==null){var p=h.next;c=p;do{if((c.tag&t)===t){var w=c.inst,k=w.destroy;if(k!==void 0){w.destroy=void 0,h=n;var z=s,Y=k;try{Y()}catch(ae){Ct(h,z,ae)}}}c=c.next}while(c!==p)}}catch(ae){Ct(n,n.return,ae)}}function tv(t){var n=t.updateQueue;if(n!==null){var s=t.stateNode;try{Vy(n,s)}catch(c){Ct(t,t.return,c)}}}function nv(t,n,s){s.props=Bi(t.type,t.memoizedProps),s.state=t.memoizedState;try{s.componentWillUnmount()}catch(c){Ct(t,n,c)}}function ll(t,n){try{var s=t.ref;if(s!==null){switch(t.tag){case 26:case 27:case 5:var c=t.stateNode;break;case 30:c=t.stateNode;break;default:c=t.stateNode}typeof s=="function"?t.refCleanup=s(c):s.current=c}}catch(h){Ct(t,n,h)}}function Fa(t,n){var s=t.ref,c=t.refCleanup;if(s!==null)if(typeof c=="function")try{c()}catch(h){Ct(t,n,h)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof s=="function")try{s(null)}catch(h){Ct(t,n,h)}else s.current=null}function av(t){var n=t.type,s=t.memoizedProps,c=t.stateNode;try{e:switch(n){case"button":case"input":case"select":case"textarea":s.autoFocus&&c.focus();break e;case"img":s.src?c.src=s.src:s.srcSet&&(c.srcset=s.srcSet)}}catch(h){Ct(t,t.return,h)}}function Vh(t,n,s){try{var c=t.stateNode;wx(c,t.type,s,n),c[vn]=n}catch(h){Ct(t,t.return,h)}}function rv(t){return t.tag===5||t.tag===3||t.tag===26||t.tag===27&&ai(t.type)||t.tag===4}function Fh(t){e:for(;;){for(;t.sibling===null;){if(t.return===null||rv(t.return))return null;t=t.return}for(t.sibling.return=t.return,t=t.sibling;t.tag!==5&&t.tag!==6&&t.tag!==18;){if(t.tag===27&&ai(t.type)||t.flags&2||t.child===null||t.tag===4)continue e;t.child.return=t,t=t.child}if(!(t.flags&2))return t.stateNode}}function Kh(t,n,s){var c=t.tag;if(c===5||c===6)t=t.stateNode,n?(s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s).insertBefore(t,n):(n=s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s,n.appendChild(t),s=s._reactRootContainer,s!=null||n.onclick!==null||(n.onclick=Aa));else if(c!==4&&(c===27&&ai(t.type)&&(s=t.stateNode,n=null),t=t.child,t!==null))for(Kh(t,n,s),t=t.sibling;t!==null;)Kh(t,n,s),t=t.sibling}function mu(t,n,s){var c=t.tag;if(c===5||c===6)t=t.stateNode,n?s.insertBefore(t,n):s.appendChild(t);else if(c!==4&&(c===27&&ai(t.type)&&(s=t.stateNode),t=t.child,t!==null))for(mu(t,n,s),t=t.sibling;t!==null;)mu(t,n,s),t=t.sibling}function iv(t){var n=t.stateNode,s=t.memoizedProps;try{for(var c=t.type,h=n.attributes;h.length;)n.removeAttributeNode(h[0]);pn(n,c,s),n[an]=t,n[vn]=s}catch(p){Ct(t,t.return,p)}}var gr=!1,Qt=!1,Wh=!1,sv=typeof WeakSet=="function"?WeakSet:Set,cn=null;function ex(t,n){if(t=t.containerInfo,pg=Hu,t=by(t),Bf(t)){if("selectionStart"in t)var s={start:t.selectionStart,end:t.selectionEnd};else e:{s=(s=t.ownerDocument)&&s.defaultView||window;var c=s.getSelection&&s.getSelection();if(c&&c.rangeCount!==0){s=c.anchorNode;var h=c.anchorOffset,p=c.focusNode;c=c.focusOffset;try{s.nodeType,p.nodeType}catch{s=null;break e}var w=0,k=-1,z=-1,Y=0,ae=0,ue=t,J=null;t:for(;;){for(var ee;ue!==s||h!==0&&ue.nodeType!==3||(k=w+h),ue!==p||c!==0&&ue.nodeType!==3||(z=w+c),ue.nodeType===3&&(w+=ue.nodeValue.length),(ee=ue.firstChild)!==null;)J=ue,ue=ee;for(;;){if(ue===t)break t;if(J===s&&++Y===h&&(k=w),J===p&&++ae===c&&(z=w),(ee=ue.nextSibling)!==null)break;ue=J,J=ue.parentNode}ue=ee}s=k===-1||z===-1?null:{start:k,end:z}}else s=null}s=s||{start:0,end:0}}else s=null;for(mg={focusedElem:t,selectionRange:s},Hu=!1,cn=n;cn!==null;)if(n=cn,t=n.child,(n.subtreeFlags&1028)!==0&&t!==null)t.return=n,cn=t;else for(;cn!==null;){switch(n=cn,p=n.alternate,t=n.flags,n.tag){case 0:if((t&4)!==0&&(t=n.updateQueue,t=t!==null?t.events:null,t!==null))for(s=0;s title"))),pn(p,c,s),p[an]=t,Wt(p),c=p;break e;case"link":var w=fS("link","href",h).get(c+(s.href||""));if(w){for(var k=0;kTt&&(w=Tt,Tt=Ge,Ge=w);var V=my(k,Ge),G=my(k,Tt);if(V&&G&&(ee.rangeCount!==1||ee.anchorNode!==V.node||ee.anchorOffset!==V.offset||ee.focusNode!==G.node||ee.focusOffset!==G.offset)){var W=ue.createRange();W.setStart(V.node,V.offset),ee.removeAllRanges(),Ge>Tt?(ee.addRange(W),ee.extend(G.node,G.offset)):(W.setEnd(G.node,G.offset),ee.addRange(W))}}}}for(ue=[],ee=k;ee=ee.parentNode;)ee.nodeType===1&&ue.push({element:ee,left:ee.scrollLeft,top:ee.scrollTop});for(typeof k.focus=="function"&&k.focus(),k=0;ks?32:s,Q.T=null,s=tg,tg=null;var p=ei,w=vr;if(sn=0,Is=ei=null,vr=0,(vt&6)!==0)throw Error(r(331));var k=vt;if(vt|=4,yv(p.current),gv(p,p.current,w,s),vt=k,gl(0,!1),tn&&typeof tn.onPostCommitFiberRoot=="function")try{tn.onPostCommitFiberRoot(Ea,p)}catch{}return!0}finally{fe.p=h,Q.T=c,Nv(t,n)}}function Hv(t,n,s){n=ra(s,n),n=$h(t.stateNode,n,2),t=Kr(t,n,2),t!==null&&(Fe(t,2),Ka(t))}function Ct(t,n,s){if(t.tag===3)Hv(t,t,s);else for(;n!==null;){if(n.tag===3){Hv(n,t,s);break}else if(n.tag===1){var c=n.stateNode;if(typeof n.type.getDerivedStateFromError=="function"||typeof c.componentDidCatch=="function"&&(Zr===null||!Zr.has(c))){t=ra(s,t),s=zb(2),c=Kr(n,s,2),c!==null&&(jb(s,c,n,t),Fe(c,2),Ka(c));break}}n=n.return}}function ig(t,n,s){var c=t.pingCache;if(c===null){c=t.pingCache=new ax;var h=new Set;c.set(n,h)}else h=c.get(n),h===void 0&&(h=new Set,c.set(n,h));h.has(s)||(Jh=!0,h.add(s),t=lx.bind(null,t,n,s),n.then(t,t))}function lx(t,n,s){var c=t.pingCache;c!==null&&c.delete(n),t.pingedLanes|=t.suspendedLanes&s,t.warmLanes&=~s,kt===t&&(at&s)===s&&(Bt===4||Bt===3&&(at&62914560)===at&&300>Ft()-vu?(vt&2)===0&&Hs(t,0):Qh|=s,Ns===at&&(Ns=0)),Ka(t)}function zv(t,n){n===0&&(n=ke()),t=Oi(t,n),t!==null&&(Fe(t,n),Ka(t))}function cx(t){var n=t.memoizedState,s=0;n!==null&&(s=n.retryLane),zv(t,s)}function ux(t,n){var s=0;switch(t.tag){case 31:case 13:var c=t.stateNode,h=t.memoizedState;h!==null&&(s=h.retryLane);break;case 19:c=t.stateNode;break;case 22:c=t.stateNode._retryCache;break;default:throw Error(r(314))}c!==null&&c.delete(n),zv(t,s)}function dx(t,n){return jt(t,n)}var xu=null,js=null,sg=!1,Tu=!1,og=!1,ni=0;function Ka(t){t!==js&&t.next===null&&(js===null?xu=js=t:js=js.next=t),Tu=!0,sg||(sg=!0,hx())}function gl(t,n){if(!og&&Tu){og=!0;do for(var s=!1,c=xu;c!==null;){if(t!==0){var h=c.pendingLanes;if(h===0)var p=0;else{var w=c.suspendedLanes,k=c.pingedLanes;p=(1<<31-q(42|t)+1)-1,p&=h&~(w&~k),p=p&201326741?p&201326741|1:p?p|2:0}p!==0&&(s=!0,Pv(c,p))}else p=at,p=je(c,c===kt?p:0,c.cancelPendingCommit!==null||c.timeoutHandle!==-1),(p&3)===0||ze(c,p)||(s=!0,Pv(c,p));c=c.next}while(s);og=!1}}function fx(){jv()}function jv(){Tu=sg=!1;var t=0;ni!==0&&Ex()&&(t=ni);for(var n=Ft(),s=null,c=xu;c!==null;){var h=c.next,p=Uv(c,n);p===0?(c.next=null,s===null?xu=h:s.next=h,h===null&&(js=s)):(s=c,(t!==0||(p&3)!==0)&&(Tu=!0)),c=h}sn!==0&&sn!==5||gl(t),ni!==0&&(ni=0)}function Uv(t,n){for(var s=t.suspendedLanes,c=t.pingedLanes,h=t.expirationTimes,p=t.pendingLanes&-62914561;0k)break;var ae=z.transferSize,ue=z.initiatorType;ae&&Xv(ue)&&(z=z.responseEnd,w+=ae*(z"u"?null:document;function lS(t,n,s){var c=Us;if(c&&typeof n=="string"&&n){var h=$n(n);h='link[rel="'+t+'"][href="'+h+'"]',typeof s=="string"&&(h+='[crossorigin="'+s+'"]'),oS.has(h)||(oS.add(h),t={rel:t,crossOrigin:s,href:n},c.querySelector(h)===null&&(n=c.createElement("link"),pn(n,"link",t),Wt(n),c.head.appendChild(n)))}}function Lx(t){Sr.D(t),lS("dns-prefetch",t,null)}function Mx(t,n){Sr.C(t,n),lS("preconnect",t,n)}function $x(t,n,s){Sr.L(t,n,s);var c=Us;if(c&&t&&n){var h='link[rel="preload"][as="'+$n(n)+'"]';n==="image"&&s&&s.imageSrcSet?(h+='[imagesrcset="'+$n(s.imageSrcSet)+'"]',typeof s.imageSizes=="string"&&(h+='[imagesizes="'+$n(s.imageSizes)+'"]')):h+='[href="'+$n(t)+'"]';var p=h;switch(n){case"style":p=Bs(t);break;case"script":p=Ps(t)}ua.has(p)||(t=b({rel:"preload",href:n==="image"&&s&&s.imageSrcSet?void 0:t,as:n},s),ua.set(p,t),c.querySelector(h)!==null||n==="style"&&c.querySelector(bl(p))||n==="script"&&c.querySelector(vl(p))||(n=c.createElement("link"),pn(n,"link",t),Wt(n),c.head.appendChild(n)))}}function Nx(t,n){Sr.m(t,n);var s=Us;if(s&&t){var c=n&&typeof n.as=="string"?n.as:"script",h='link[rel="modulepreload"][as="'+$n(c)+'"][href="'+$n(t)+'"]',p=h;switch(c){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":p=Ps(t)}if(!ua.has(p)&&(t=b({rel:"modulepreload",href:t},n),ua.set(p,t),s.querySelector(h)===null)){switch(c){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(s.querySelector(vl(p)))return}c=s.createElement("link"),pn(c,"link",t),Wt(c),s.head.appendChild(c)}}}function Ix(t,n,s){Sr.S(t,n,s);var c=Us;if(c&&t){var h=Mr(c).hoistableStyles,p=Bs(t);n=n||"default";var w=h.get(p);if(!w){var k={loading:0,preload:null};if(w=c.querySelector(bl(p)))k.loading=5;else{t=b({rel:"stylesheet",href:t,"data-precedence":n},s),(s=ua.get(p))&&Eg(t,s);var z=w=c.createElement("link");Wt(z),pn(z,"link",t),z._p=new Promise(function(Y,ae){z.onload=Y,z.onerror=ae}),z.addEventListener("load",function(){k.loading|=1}),z.addEventListener("error",function(){k.loading|=2}),k.loading|=4,Lu(w,n,c)}w={type:"stylesheet",instance:w,count:1,state:k},h.set(p,w)}}}function Hx(t,n){Sr.X(t,n);var s=Us;if(s&&t){var c=Mr(s).hoistableScripts,h=Ps(t),p=c.get(h);p||(p=s.querySelector(vl(h)),p||(t=b({src:t,async:!0},n),(n=ua.get(h))&&_g(t,n),p=s.createElement("script"),Wt(p),pn(p,"link",t),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},c.set(h,p))}}function zx(t,n){Sr.M(t,n);var s=Us;if(s&&t){var c=Mr(s).hoistableScripts,h=Ps(t),p=c.get(h);p||(p=s.querySelector(vl(h)),p||(t=b({src:t,async:!0,type:"module"},n),(n=ua.get(h))&&_g(t,n),p=s.createElement("script"),Wt(p),pn(p,"link",t),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},c.set(h,p))}}function cS(t,n,s,c){var h=(h=me.current)?Ou(h):null;if(!h)throw Error(r(446));switch(t){case"meta":case"title":return null;case"style":return typeof s.precedence=="string"&&typeof s.href=="string"?(n=Bs(s.href),s=Mr(h).hoistableStyles,c=s.get(n),c||(c={type:"style",instance:null,count:0,state:null},s.set(n,c)),c):{type:"void",instance:null,count:0,state:null};case"link":if(s.rel==="stylesheet"&&typeof s.href=="string"&&typeof s.precedence=="string"){t=Bs(s.href);var p=Mr(h).hoistableStyles,w=p.get(t);if(w||(h=h.ownerDocument||h,w={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},p.set(t,w),(p=h.querySelector(bl(t)))&&!p._p&&(w.instance=p,w.state.loading=5),ua.has(t)||(s={rel:"preload",as:"style",href:s.href,crossOrigin:s.crossOrigin,integrity:s.integrity,media:s.media,hrefLang:s.hrefLang,referrerPolicy:s.referrerPolicy},ua.set(t,s),p||jx(h,t,s,w.state))),n&&c===null)throw Error(r(528,""));return w}if(n&&c!==null)throw Error(r(529,""));return null;case"script":return n=s.async,s=s.src,typeof s=="string"&&n&&typeof n!="function"&&typeof n!="symbol"?(n=Ps(s),s=Mr(h).hoistableScripts,c=s.get(n),c||(c={type:"script",instance:null,count:0,state:null},s.set(n,c)),c):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,t))}}function Bs(t){return'href="'+$n(t)+'"'}function bl(t){return'link[rel="stylesheet"]['+t+"]"}function uS(t){return b({},t,{"data-precedence":t.precedence,precedence:null})}function jx(t,n,s,c){t.querySelector('link[rel="preload"][as="style"]['+n+"]")?c.loading=1:(n=t.createElement("link"),c.preload=n,n.addEventListener("load",function(){return c.loading|=1}),n.addEventListener("error",function(){return c.loading|=2}),pn(n,"link",s),Wt(n),t.head.appendChild(n))}function Ps(t){return'[src="'+$n(t)+'"]'}function vl(t){return"script[async]"+t}function dS(t,n,s){if(n.count++,n.instance===null)switch(n.type){case"style":var c=t.querySelector('style[data-href~="'+$n(s.href)+'"]');if(c)return n.instance=c,Wt(c),c;var h=b({},s,{"data-href":s.href,"data-precedence":s.precedence,href:null,precedence:null});return c=(t.ownerDocument||t).createElement("style"),Wt(c),pn(c,"style",h),Lu(c,s.precedence,t),n.instance=c;case"stylesheet":h=Bs(s.href);var p=t.querySelector(bl(h));if(p)return n.state.loading|=4,n.instance=p,Wt(p),p;c=uS(s),(h=ua.get(h))&&Eg(c,h),p=(t.ownerDocument||t).createElement("link"),Wt(p);var w=p;return w._p=new Promise(function(k,z){w.onload=k,w.onerror=z}),pn(p,"link",c),n.state.loading|=4,Lu(p,s.precedence,t),n.instance=p;case"script":return p=Ps(s.src),(h=t.querySelector(vl(p)))?(n.instance=h,Wt(h),h):(c=s,(h=ua.get(p))&&(c=b({},s),_g(c,h)),t=t.ownerDocument||t,h=t.createElement("script"),Wt(h),pn(h,"link",c),t.head.appendChild(h),n.instance=h);case"void":return null;default:throw Error(r(443,n.type))}else n.type==="stylesheet"&&(n.state.loading&4)===0&&(c=n.instance,n.state.loading|=4,Lu(c,s.precedence,t));return n.instance}function Lu(t,n,s){for(var c=s.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),h=c.length?c[c.length-1]:null,p=h,w=0;w title"):null)}function Ux(t,n,s){if(s===1||n.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof n.precedence!="string"||typeof n.href!="string"||n.href==="")break;return!0;case"link":if(typeof n.rel!="string"||typeof n.href!="string"||n.href===""||n.onLoad||n.onError)break;return n.rel==="stylesheet"?(t=n.disabled,typeof n.precedence=="string"&&t==null):!0;case"script":if(n.async&&typeof n.async!="function"&&typeof n.async!="symbol"&&!n.onLoad&&!n.onError&&n.src&&typeof n.src=="string")return!0}return!1}function gS(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function Bx(t,n,s,c){if(s.type==="stylesheet"&&(typeof c.media!="string"||matchMedia(c.media).matches!==!1)&&(s.state.loading&4)===0){if(s.instance===null){var h=Bs(c.href),p=n.querySelector(bl(h));if(p){n=p._p,n!==null&&typeof n=="object"&&typeof n.then=="function"&&(t.count++,t=$u.bind(t),n.then(t,t)),s.state.loading|=4,s.instance=p,Wt(p);return}p=n.ownerDocument||n,c=uS(c),(h=ua.get(h))&&Eg(c,h),p=p.createElement("link"),Wt(p);var w=p;w._p=new Promise(function(k,z){w.onload=k,w.onerror=z}),pn(p,"link",c),s.instance=p}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(s,n),(n=s.state.preload)&&(s.state.loading&3)===0&&(t.count++,s=$u.bind(t),n.addEventListener("load",s),n.addEventListener("error",s))}}var Ag=0;function Px(t,n){return t.stylesheets&&t.count===0&&Iu(t,t.stylesheets),0Ag?50:800)+n);return t.unsuspend=s,function(){t.unsuspend=null,clearTimeout(c),clearTimeout(h)}}:null}function $u(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Iu(this,this.stylesheets);else if(this.unsuspend){var t=this.unsuspend;this.unsuspend=null,t()}}}var Nu=null;function Iu(t,n){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Nu=new Map,n.forEach(qx,t),Nu=null,$u.call(t))}function qx(t,n){if(!(n.state.loading&4)){var s=Nu.get(t);if(s)var c=s.get(null);else{s=new Map,Nu.set(t,s);for(var h=t.querySelectorAll("link[data-precedence],style[data-precedence]"),p=0;p"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(o)}catch(e){console.error(e)}}return o(),Fu.exports=NS(),Fu.exports}var Xu=IS();const Ju=Ya(Xu),Vs=[],HS=50;let Qu=!1;function Bg(){try{return window.G7Core?.devTools}catch{return}}function Gi(o,e,a){const r=Bg();if(Qu&&r?.isEnabled?.()){r.trackLog?.(o,e,a);return}Qu||(o==="error"||o==="warn")&&Vs.length{a.isDebugEnabled()&&console.log(e,...r),Gi("log",o,r)},warn:(...r)=>{a.isDebugEnabled()&&console.warn(e,...r),Gi("warn",o,r)},error:(...r)=>{a.isDebugEnabled()&&console.error(e,...r),Gi("error",o,r)}}}Fs.getInstance();const Vi=ct("networkResilience"),Pg=2,qg=300,Gg=2e3,zS=15e3;function Vg(o){return o?.name==="AbortError"}function jS(o){return Vg(o)?!1:o instanceof TypeError}let _l=!1,Fg=!1;function ed(){return _l}function US(){typeof window>"u"||Fg||(Fg=!0,window.addEventListener("pagehide",()=>{_l=!0}),window.addEventListener("pageshow",o=>{o.persisted&&(_l=!1)}),window.addEventListener("beforeunload",()=>{_l=!0}))}function Kg(o,e,a){const r=Math.min(e*Math.pow(2,o),a),i=r*.25*(Math.random()*2-1);return Math.max(0,Math.round(r+i))}function Wg(o){return new Promise(e=>setTimeout(e,o))}async function Al(o,e={}){const{retries:a=Pg,baseDelayMs:r=qg,maxDelayMs:i=Gg,timeoutMs:l=zS,label:u=o,init:d}=e,f=a+1;let g;for(let m=0;m0?new AbortController:null;try{const E={...d};if(S){const T=d?.signal;T&&(T.aborted?S.abort():T.addEventListener("abort",()=>S.abort(),{once:!0})),E.signal=S.signal,v=setTimeout(()=>{b=!0,S.abort()},l)}return await fetch(o,E)}catch(E){if(g=E,Vg(E)&&!b||!(b||jS(E)))throw E;if(ed())throw Vi.warn(`Document unloading, aborting retries: ${u}`),E;if(m===f-1)throw Vi.warn(`All ${f} attempts failed: ${u}`,E),E;const L=Kg(m,r,i);Vi.warn(`Network failure (attempt ${m+1}/${f}), retrying in ${L}ms: ${u}`),await Wg(L)}finally{v!==void 0&&clearTimeout(v)}}throw g}async function Yg(o,e={},a={}){const{retries:r=Pg,baseDelayMs:i=qg,maxDelayMs:l=Gg,label:u=o}=a,d=r+1;for(let f=0;f{const i=document.createElement("script");i.src=o,i.async=!1;for(const[l,u]of Object.entries(e))l==="id"?i.id=u:i.setAttribute(l,u);i.onload=()=>a(),i.onerror=()=>r(new Error(`Failed to load script: ${o}`)),document.head.appendChild(i)})}const Xg="extension",Fi="extensionless",PS="file";function qS(){const o=globalThis?.G7Config;if(globalThis?.__g7AssetUrlMode===Fi)return Fi;const a=o?.assetUrlMode;return a===Fi||a===Xg?a:o?.settings?.general?.asset_url_mode===Fi?Fi:Xg}function Jg(){return qS()===Fi}function La(o,e,a,r){const i=o.replace(/\/+$/,""),l=e.replace(/^\.+/,""),u=Jg()?i:`${i}.${l}`,d=[];return r&&d.push(r.replace(/^[?&]+/,"")),a!=null&&a!==""&&d.push(`v=${a}`),d.length>0?`${u}?${d.join("&")}`:u}function wr(o){if(!o||!Jg())return o;const e=globalThis?.location?.origin,a=e&&o.startsWith(e)?o.slice(e.length):o;if(!a.startsWith("/api/"))return o;const[r,i]=GS(a),l=r.match(/^\/api\/(modules|plugins)\/bundle\.(js|css)$/);if(l)return Qg(`/api/${l[1]}/bundle/${l[2]}`,i);const u=r.match(/^\/api\/(templates|modules|plugins)\/assets\/([^/]+)\/(.+)$/);if(u){const[,f,g,m]=u,b=`${PS}=${encodeURIComponent(decodeURIComponent(m))}`;return`/api/${f}/assets/${g}?${b}${i?`&${i}`:""}`}const d=r.match(/^(\/api\/.+)\.(json|js|css)$/);return d?Qg(d[1],i):o}function GS(o){const e=o.indexOf("?");return e===-1?[o,""]:[o.slice(0,e),o.slice(e+1)]}function Qg(o,e){return e?`${o}?${e}`:o}const Ma=ct("ComponentRegistry");class on extends Error{constructor(a,r,i){super(a);$(this,"code");$(this,"details");this.code=r,this.details=i,this.name="ComponentRegistryError"}}const Pn=class Pn{constructor(){$(this,"registry",{});$(this,"manifest",null);$(this,"loadingState","idle");$(this,"error",null);$(this,"templateId",null);$(this,"templateType",null)}static getInstance(){return Pn.instance||(Pn.instance=new Pn),Pn.instance}static createIsolatedInstance(){return new Pn}static resetInstance(){Pn.instance=null}async loadComponents(e,a){if(this.loadingState==="loading")throw new on("Components are already being loaded","LOADING_IN_PROGRESS");if(this.loadingState==="loaded"&&this.templateId===e&&this.templateType===a){Ma.log("Components already loaded for template:",e,a);return}this.loadingState="loading",this.templateId=e,this.templateType=a,this.error=null;try{await this.loadManifest(),await this.loadComponentBundle(),this.loadingState="loaded",Ma.log("Successfully loaded components:",Object.keys(this.registry).length)}catch(r){throw this.loadingState="error",this.error=r instanceof Error?r:new Error(String(r)),new on(`Failed to load components: ${this.error.message}`,"LOAD_FAILED",{originalError:this.error})}}async loadManifest(){try{if(!this.templateId)throw new on("Template ID not set","TEMPLATE_ID_NOT_SET");const e=`${this.templateId}:${this.templateType}`;if(Pn.manifestCache.has(e)){this.manifest=Pn.manifestCache.get(e),Ma.log("Manifest loaded from cache:",this.manifest.templateId);return}const a=La(`/api/templates/${this.templateId}/components`,"json"),r=await Al(a,{label:"components.json"});if(!r.ok)throw new on(`Failed to fetch manifest: ${r.status} ${r.statusText}`,"MANIFEST_FETCH_FAILED",{status:r.status,statusText:r.statusText});const i=await r.json();this.validateManifest(i),this.manifest=i,Pn.manifestCache.set(e,i),Ma.log("Manifest loaded and cached:",i.templateId)}catch(e){throw e instanceof on?e:new on("Failed to load component manifest","MANIFEST_LOAD_FAILED",{originalError:e})}}validateManifest(e){if(!e.version)throw new on("Manifest missing required field: version","MANIFEST_INVALID",{field:"version"});if(!e.templateId)throw new on("Manifest missing required field: templateId","MANIFEST_INVALID",{field:"templateId"});if(!e.components||typeof e.components!="object")throw new on("Manifest missing required field: components","MANIFEST_INVALID",{field:"components"});const a=["basic","composite","layout"];for(const r of a){if(!Array.isArray(e.components[r]))throw new on(`Manifest field 'components.${r}' must be an array`,"MANIFEST_INVALID",{field:`components.${r}`,value:e.components[r]});e.components[r].forEach((i,l)=>{if(!i.name||typeof i.name!="string")throw new on(`Invalid component metadata at ${r}[${l}]: missing or invalid 'name'`,"MANIFEST_INVALID",{type:r,index:l,metadata:i});if(!i.type||typeof i.type!="string")throw new on(`Invalid component metadata at ${r}[${l}]: missing or invalid 'type'`,"MANIFEST_INVALID",{type:r,index:l,metadata:i})})}Ma.log("Manifest validation passed")}async loadComponentBundle(){try{if(!this.templateId)throw new on("Template ID not set","TEMPLATE_ID_NOT_SET");const e=this.getGlobalVariableName(),a=window[e];if(!a||typeof a!="object")throw new on(`Component bundle not loaded. Expected global variable: ${e}. Ensure admin.blade.php includes the IIFE bundle script.`,"BUNDLE_NOT_LOADED",{expectedVariable:e});await this.registerComponentsFromManifest(a),Ma.log("Component bundle loaded from global variable:",e)}catch(e){throw e instanceof on?e:new on("Failed to load component bundle","BUNDLE_LOAD_FAILED",{originalError:e})}}getGlobalVariableName(){if(!this.templateId)throw new on("Template ID not set","TEMPLATE_ID_NOT_SET");return this.templateId.split(/[-_]/).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join("")}async registerComponentsFromManifest(e){if(!this.manifest)throw new on("Manifest not loaded","MANIFEST_NOT_LOADED");const a=["basic","composite","layout"];for(const r of a){const i=this.manifest.components[r]||[];for(const l of i){const u=l.name,d=e[u];if(!d){Ma.warn(`Component '${u}' not found in bundle`);continue}this.registerComponent(u,d,l)}}}registerComponent(e,a,r){this.registry[e]&&Ma.warn(`Component '${e}' already registered, overwriting`);const i=Ye.memo(a);this.registry[e]={component:i,metadata:r},Ma.log(`[ComponentRegistry] Registered component: ${e} (${r.type})`)}getComponent(e){const a=this.registry[e];return a?a.component:null}getMetadata(e){const a=this.registry[e];return a?a.metadata:null}hasComponent(e){return e in this.registry}getComponentsByType(e){return Object.entries(this.registry).filter(([a,r])=>r.metadata.type===e).map(([a,r])=>a)}getAllComponents(){return Object.keys(this.registry)}getComponentMap(){const e={};for(const[a,r]of Object.entries(this.registry))e[a]=r.component;return e}getLoadingState(){return this.loadingState}getError(){return this.error}getTemplateId(){return this.templateId}getManifest(){return this.manifest}clear(){this.registry={},this.manifest=null,this.loadingState="idle",this.error=null,this.templateId=null,this.templateType=null,Ma.log("Registry cleared")}};$(Pn,"instance",null),$(Pn,"manifestCache",new Map);let da=Pn;const Zg=ct("TranslationEngine");class td extends Error{constructor(a,r,i){super(a);$(this,"key");$(this,"locale");this.key=r,this.locale=i,this.name="TranslationError"}}const Rn=class Rn{constructor(e={}){$(this,"cache",new Map);$(this,"translations",new Map);$(this,"options");$(this,"cacheVersion",0);this.options={defaultLocale:e.defaultLocale||"ko",fallbackLocale:e.fallbackLocale||"en",cacheTTL:e.cacheTTL||3e5}}static getInstance(e={}){return Rn.instance||(Rn.instance=new Rn(e)),Rn.instance}static resetInstance(){Rn.instance=null}setCacheVersion(e){this.cacheVersion!==e&&(Zg.log("Cache version updated:",this.cacheVersion,"->",e),this.cacheVersion=e,this.cache.clear())}getCacheVersion(){return this.cacheVersion}async loadTranslations(e,a,r="/api",i=!1){const l=`${e}:${a}`;if(!i){const u=this.getFromCache(l);if(u)return this.translations.set(l,u),u}try{const u=[];i&&u.push(`_=${Date.now()}`);const d=La(`${r}/templates/${e}/lang/${a}`,"json",this.cacheVersion>0?this.cacheVersion:null,u.length>0?u.join("&"):void 0),f=await fetch(d);if(!f.ok)throw new td(`Failed to load translations: ${f.statusText}`,void 0,a);const m=await f.json();return this.saveToCache(l,m),this.translations.set(l,m),m}catch(u){throw new td(`Failed to fetch translations for ${a}: ${u instanceof Error?u.message:String(u)}`,void 0,a)}}resolveTranslations(e,a,r){let i=e;const l=5;let u=0;for(;u"="+this.translate(m,a,void 0,r)),i===d)break;u++}return i.replace(Rn.TRANSLATION_PATTERN,(d,f,g)=>{const{cleanedParams:m,trailing:b}=this.separateTrailingText(g);return this.translate(f,a,m,r)+b})}translate(e,a,r,i){const l=this.getTranslation(e,a),u=r&&this.cleanParamsStr(r);if(u){const d=this.parseParams(u,i);return this.replaceParams(l,d)}return l}getTranslation(e,a){const{templateId:r,locale:i}=a,l=`${r}:${i}`,u=this.translations.get(l);if(u){const d=this.getNestedValue(u,e);if(d!==null)return d}if(i!==this.options.fallbackLocale){const d=`${r}:${this.options.fallbackLocale}`,f=this.translations.get(d);if(f){const g=this.getNestedValue(f,e);if(g!==null)return g}}return e}getNestedValue(e,a){const r=a.split(".");let i=e;for(const l of r){if(i==null||typeof i!="object")return null;i=i[l]}return typeof i=="string"?i:null}setTranslationValue(e,a,r,i){const l=`${e}:${a}`,u=this.translations.get(l)??{},d=r.split(".");let f=u;for(let g=0;g(l.push(f),`__PLACEHOLDER_${l.length-1}__`)).matchAll(Rn.PARAM_PATTERN);for(const f of d){const[,g,m]=f,b=m.replace(/__PLACEHOLDER_(\d+)__/g,(v,S)=>l[parseInt(S,10)]);r[g.trim()]=this.resolveParamValue(b.trim(),a)}return r}resolveParamValue(e,a){if(e.startsWith("{{")&&e.endsWith("}}")){const r=e.slice(2,-2).trim();if(/[|&()[\]!?:+\-*/%<>=\s]/.test(r)&&a)try{const u=new Function(...Object.keys(a),`return ${r}`)(...Object.values(a));return String(u??"")}catch(l){return Zg.error("Expression evaluation failed:",r,l),""}else{const l=this.getNestedDataValue(a,r);return String(l??"")}}return e}separateTrailingText(e){if(!e)return{cleanedParams:void 0,trailing:""};if(e.trimEnd().endsWith("}}"))return{cleanedParams:e,trailing:""};if(!(e.startsWith("|")?e.slice(1):e).includes("="))return{cleanedParams:void 0,trailing:e};const r=e.match(/(\s+[^\p{L}\w=|&\s][^\p{L}\w=]*\s*)$/u);return r?{cleanedParams:e.slice(0,-r[1].length),trailing:r[1]}:{cleanedParams:e,trailing:""}}cleanParamsStr(e){return this.separateTrailingText(e).cleanedParams||""}getNestedDataValue(e,a){if(!e)return;const r=a.split(".");let i=e;for(const l of r){if(i==null)return;i=i[l]}return i}replaceParams(e,a){let r=e;for(const[i,l]of Object.entries(a)){const u=new RegExp(`\\{\\{${i}\\}\\}`,"g");r=r.replace(u,String(l));const d=new RegExp(`\\{${i}\\}`,"g");r=r.replace(d,String(l))}return r}getFromCache(e){const a=this.cache.get(e);return a?Date.now()-a.timestamp>this.options.cacheTTL?(this.cache.delete(e),null):a.data:null}saveToCache(e,a){this.cache.set(e,{data:a,timestamp:Date.now()})}clearCache(){this.cache.clear(),this.translations.clear()}pruneCache(){const e=Date.now(),a=[];for(const[r,i]of this.cache.entries())e-i.timestamp>this.options.cacheTTL&&a.push(r);for(const r of a)this.cache.delete(r)}getCacheStats(){const e=Date.now();let a=0;for(const r of this.cache.values())e-r.timestamp>this.options.cacheTTL&&a++;return{size:this.cache.size,expired:a}}};$(Rn,"instance",null),$(Rn,"TRANSLATION_PATTERN",/\$t:(?:defer:)?([a-zA-Z0-9._-]+)(\|(?:(?!\$t:).)+)?/g),$(Rn,"NESTED_TRANSLATION_PARAM_PATTERN",/=(\$t:([a-zA-Z0-9._-]+))(?=[|&\s]|$)/g),$(Rn,"PARAM_PATTERN",/([^=|&]+)=([^|&]+)/g);let Cr=Rn,nd=null;function VS(o){return nd||(nd=new Cr(o)),nd}const ep=Object.freeze(Object.defineProperty({__proto__:null,TranslationEngine:Cr,TranslationError:td,getTranslationEngine:VS},Symbol.toStringTag,{value:"Module"})),Ki=ct("PipeRegistry");function tp(o,e){const a=o.getFullYear(),r=String(o.getMonth()+1).padStart(2,"0"),i=String(o.getDate()).padStart(2,"0"),l=String(o.getHours()).padStart(2,"0"),u=String(o.getMinutes()).padStart(2,"0"),d=String(o.getSeconds()).padStart(2,"0");return e.replace("YYYY",String(a)).replace("YY",String(a).slice(-2)).replace("MM",r).replace("M",String(o.getMonth()+1)).replace("DD",i).replace("D",String(o.getDate())).replace("HH",l).replace("H",String(o.getHours())).replace("mm",u).replace("m",String(o.getMinutes())).replace("ss",d).replace("s",String(o.getSeconds()))}function FS(o,e="ko"){const r=new Date().getTime()-o.getTime(),i=Math.floor(r/1e3),l=Math.floor(i/60),u=Math.floor(l/60),d=Math.floor(u/24),f=Math.floor(d/7),g=Math.floor(d/30),m=Math.floor(d/365);return e==="ko"?i<60?"방금 전":l<60?`${l}분 전`:u<24?`${u}시간 전`:d<7?`${d}일 전`:f<4?`${f}주 전`:g<12?`${g}개월 전`:`${m}년 전`:i<60?"just now":l<60?`${l} minute${l===1?"":"s"} ago`:u<24?`${u} hour${u===1?"":"s"} ago`:d<7?`${d} day${d===1?"":"s"} ago`:f<4?`${f} week${f===1?"":"s"} ago`:g<12?`${g} month${g===1?"":"s"} ago`:`${m} year${m===1?"":"s"} ago`}function ad(o){if(o==null)return null;if(o instanceof Date)return o;if(typeof o=="number")return new Date(o);if(typeof o=="string"){const e=new Date(o);return isNaN(e.getTime())?null:e}return null}const Ks={date:{fn:(o,e="YYYY-MM-DD")=>{const a=ad(o);return a?tp(a,e):""},description:"날짜 포맷 (기본: YYYY-MM-DD)"},datetime:{fn:(o,e="YYYY-MM-DD HH:mm")=>{const a=ad(o);return a?tp(a,e):""},description:"날짜+시간 포맷 (기본: YYYY-MM-DD HH:mm)"},relativeTime:{fn:(o,e="ko")=>{const a=ad(o);return a?FS(a,e):""},description:'상대 시간 표시 (예: "3분 전")'},number:{fn:(o,e)=>{const a=Number(o);if(isNaN(a))return String(o??"");const r={};return e!==void 0&&(r.minimumFractionDigits=e,r.maximumFractionDigits=e),a.toLocaleString(void 0,r)},description:"숫자 포맷 (천단위 구분, 선택적 소수점)"},truncate:{fn:(o,e=100,a="...")=>typeof o!="string"?String(o??""):o.length<=e?o:o.slice(0,e)+a,description:'문자열 자르기 (기본: 100자, 접미사: "...")'},uppercase:{fn:o=>typeof o!="string"?String(o??""):o.toUpperCase(),description:"대문자 변환"},lowercase:{fn:o=>typeof o!="string"?String(o??""):o.toLowerCase(),description:"소문자 변환"},stripHtml:{fn:o=>typeof o!="string"?String(o??""):o.replace(/<[^>]*>/g,""),description:"HTML 태그 제거"},default:{fn:(o,e="")=>o==null||o===""?e:o,description:"기본값 설정 (null, undefined, 빈문자열 시)"},fallback:{fn:(o,e)=>o??e,description:"폴백 값 설정 (null, undefined 시만)"},first:{fn:o=>{if(Array.isArray(o))return o[0]},description:"배열의 첫 번째 요소"},last:{fn:o=>{if(Array.isArray(o))return o[o.length-1]},description:"배열의 마지막 요소"},join:{fn:(o,e=", ")=>Array.isArray(o)?o.join(e):"",description:'배열을 문자열로 결합 (기본 구분자: ", ")'},length:{fn:o=>Array.isArray(o)||typeof o=="string"?o.length:0,description:"배열/문자열 길이"},filterBy:{fn:(o,e,a)=>Array.isArray(o)?Array.isArray(e)?o.filter(r=>{const i=a?r?.[a]:r;return e.includes(i)}):o:[],description:"배열 필터링 (allowList에 포함된 항목만 반환)"},keys:{fn:o=>o==null||typeof o!="object"?[]:Object.keys(o),description:"객체의 키 배열"},values:{fn:o=>o==null||typeof o!="object"?[]:Object.values(o),description:"객체의 값 배열"},json:{fn:(o,e)=>{try{return JSON.stringify(o,null,e)}catch{return""}},description:"JSON 문자열로 변환"},localized:{fn:(o,e)=>o==null?"":typeof o=="string"?o:typeof o!="object"?String(o):o[e||"ko"]||o.ko||o.en||Object.values(o)[0]||"",description:"다국어 객체에서 로케일에 맞는 값 추출"}},Wi=new Map,pi=class pi{static getInstance(){return pi.instance||(pi.instance=new pi),pi.instance}register(e,a,r){if(Ks[e]){Ki.warn(`[PipeRegistry] 내장 파이프를 덮어쓸 수 없습니다: ${e}`);return}Wi.set(e,{fn:a,description:r}),Ki.log(`[PipeRegistry] 커스텀 파이프 등록됨: ${e}`)}unregister(e){if(Ks[e])return Ki.warn(`[PipeRegistry] 내장 파이프는 해제할 수 없습니다: ${e}`),!1;const a=Wi.delete(e);return a&&Ki.log(`[PipeRegistry] 커스텀 파이프 해제됨: ${e}`),a}get(e){const a=Ks[e];return a?a.fn:Wi.get(e)?.fn}has(e){return!!Ks[e]||Wi.has(e)}execute(e,a,r=[]){const i=this.get(e);if(!i)return Ki.warn(`[PipeRegistry] 알 수 없는 파이프: ${e}`),a;try{return i(a,...r)}catch(l){return Ki.error(`[PipeRegistry] 파이프 실행 오류 (${e}):`,l),a}}list(){const e=[];for(const[a,r]of Object.entries(Ks))e.push({name:a,description:r.description,type:"built-in"});for(const[a,r]of Wi.entries())e.push({name:a,description:r.description,type:"custom"});return e.sort((a,r)=>a.name.localeCompare(r.name))}clearCustomPipes(){Wi.clear()}};$(pi,"instance",null);let xl=pi;xl.getInstance();function KS(o){const e=o.trim(),a=e.indexOf("(");if(a===-1)return{name:e,args:[]};const r=e.slice(0,a).trim(),i=e.slice(a+1,-1);if(!i.trim())return{name:r,args:[]};const l=[];let u="",d=null,f=0;for(let g=0;g0?i[g-1]:"")==="\\"){u+=m;continue}if((m==='"'||m==="'")&&!d){d=m;continue}if(m===d){d=null;continue}if(d){u+=m;continue}if(m==="("||m==="["||m==="{"){f++,u+=m;continue}if(m===")"||m==="]"||m==="}"){f--,u+=m;continue}if(m===","&&f===0){l.push(np(u.trim())),u="";continue}u+=m}return u.trim()&&l.push(np(u.trim())),{name:r,args:l}}function np(o){if(o==="null")return null;if(o==="undefined")return;if(o==="true")return!0;if(o==="false")return!1;const e=Number(o);return!isNaN(e)&&o!==""?e:o}function WS(o){const e=[];let a="",r=null,i=0;for(let l=0;l0?o[l-1]:"",f=l0?o[r-1]:"",u=r=2&&o.charCodeAt(0)===64976&&o.charCodeAt(o.length-1)===64977}function ip(o){return o.includes(Tl)}function sp(o){return o.slice(1,-1)}function Xs(o){if(typeof o=="string")return Ys(o);if(Array.isArray(o))return o.map(Xs);if(o&&typeof o=="object"){const e={};for(const[a,r]of Object.entries(o))e[a]=Xs(r);return e}return o}const Js=ct("DataBindingEngine");function Rl(){try{return window.G7Core?.devTools}catch{return}}class rd extends Error{constructor(a,r,i){super(a);$(this,"path");$(this,"context");this.path=r,this.context=i,this.name="DataBindingError"}}const Sa=class Sa{constructor(e){$(this,"cache",new Map);$(this,"expressionFnCache",new Map);$(this,"renderCycleCache",new Map);$(this,"currentRenderCycleId",0);$(this,"defaultOptions",{defaultValue:void 0,nullSafe:!0,detectCircular:!0,maxDepth:10});e&&(this.defaultOptions={...this.defaultOptions,...e})}startRenderCycle(){this.currentRenderCycleId++,this.renderCycleCache.clear()}isRenderCycleCacheActive(){return this.currentRenderCycleId>0}getFromRenderCycleCache(e){if(this.isRenderCycleCacheActive())return this.renderCycleCache.get(e)}saveToRenderCycleCache(e,a){this.isRenderCycleCacheActive()&&this.renderCycleCache.set(e,a)}resolveBindings(e,a,r,i){const l={...this.defaultOptions,...r},u=Rl(),d=a._computed&&!a.$computed?{...a,$computed:a._computed}:a;return e.replace(Sa.BINDING_PATTERN,(f,g)=>{const m=g.trim();let b=!1,v=m;if(m.startsWith(Er)&&(b=!0,v=m.slice(Er.length)),ap(v)){const R=u?.isEnabled()?performance.now():0;try{const[D,U]=WS(v);let j,P=!1;const X=/[?:|&!+\-*/<>=()]/.test(D)||/\[['"]/.test(D),ge=D.startsWith("_global")||D.startsWith("_local")||D.startsWith("_isolated")||D.startsWith("$parent");if(l.skipCache)X?j=this.evaluateExpression(D,d):j=this.resolvePath(D,d,l);else if(X){const $e=this.getFromRenderCycleCache(`expr:${D}`);$e!==void 0?(j=$e,P=!0):(j=this.evaluateExpression(D,d),this.saveToRenderCycleCache(`expr:${D}`,j))}else if(ge){const $e=this.getFromRenderCycleCache(D);$e!==void 0?(j=$e,P=!0):(j=this.resolvePath(D,d,l),this.saveToRenderCycleCache(D,j))}else{const $e=this.getFromCache(D);$e!==void 0?(j=$e,P=!0):(j=this.resolvePath(D,d,l),this.saveToCache(D,j))}const Ee=YS(j,U);if(u?.isEnabled()){const $e=performance.now()-R;u.trackExpressionEval({expression:`{{${m}}}`,result:this.sanitizeResultForTracking(Ee),resultType:this.getResultType(Ee),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:P,duration:$e,method:"resolveBindings",skipCache:l.skipCache})}const Ce=this.formatValue(Ee);return b?Ys(Ce):Ce}catch(D){return Js.error("Pipe expression evaluation failed:",v,D),f}}if(/[?:&!+\-*/<>=()]/.test(v)||/\|\|/.test(v)||/\[['"]/.test(v)){const R=u?.isEnabled()?performance.now():0;try{let D,U=!1;if(l.skipCache)D=this.evaluateExpression(v,d);else{const P=`expr:${v}`,X=this.getFromRenderCycleCache(P);X!==void 0?(D=X,U=!0):(D=this.evaluateExpression(v,d),this.saveToRenderCycleCache(P,D))}if(u?.isEnabled()){const P=performance.now()-R;u.trackExpressionEval({expression:`{{${m}}}`,result:this.sanitizeResultForTracking(D),resultType:this.getResultType(D),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:U,duration:P,method:"resolveBindings",skipCache:l.skipCache})}const j=this.formatValue(D);return b?Ys(j):j}catch(D){return Js.error("Expression evaluation failed:",v,D),f}}if(l.skipCache){const R=u?.isEnabled()?performance.now():0,D=this.resolvePath(v,d,l);if(u?.isEnabled()){const j=performance.now()-R;u.trackExpressionEval({expression:`{{${m}}}`,result:this.sanitizeResultForTracking(D),resultType:this.getResultType(D),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!1,duration:j,method:"resolveBindings",skipCache:!0})}const U=this.formatValue(D);return b?Ys(U):U}const E=v.startsWith("_global")||v.startsWith("_local")||v.startsWith("_isolated")||v.startsWith("$parent"),A=u?.isEnabled()?performance.now():0;let T,L=!1;if(E){const R=this.getFromRenderCycleCache(v);R!==void 0?(T=R,L=!0):(T=this.resolvePath(v,d,l),this.saveToRenderCycleCache(v,T))}else{const R=this.getFromCache(v);R!==void 0?(T=R,L=!0):(T=this.resolvePath(v,d,l),this.saveToCache(v,T))}if(u?.isEnabled()){const R=performance.now()-A;u.trackExpressionEval({expression:`{{${m}}}`,result:this.sanitizeResultForTracking(T),resultType:this.getResultType(T),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:L,duration:R,method:"resolveBindings",skipCache:l.skipCache})}const M=this.formatValue(T);return b?Ys(M):M})}resolve(e,a,r,i){const l={...this.defaultOptions,...r},u=Rl(),d=u?.isEnabled()?performance.now():0;if(l.skipCache){const b=this.resolvePath(e,a,l);return u?.isEnabled()&&u.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(b),resultType:this.getResultType(b),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!1,duration:performance.now()-d,method:"resolve",skipCache:!0}),b}const f=e.startsWith("_global")||e.startsWith("_local")||e.startsWith("_isolated")||e.startsWith("$parent");let g=!1;if(f){const b=this.getFromRenderCycleCache(e);if(b!==void 0)return g=!0,u?.isEnabled()&&u.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(b),resultType:this.getResultType(b),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!0,duration:performance.now()-d,method:"resolve",skipCache:l.skipCache}),b}else{const b=this.getFromCache(e);if(b!==void 0)return g=!0,u?.isEnabled()&&u.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(b),resultType:this.getResultType(b),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!0,duration:performance.now()-d,method:"resolve",skipCache:l.skipCache}),b}const m=this.resolvePath(e,a,l);return f?this.saveToRenderCycleCache(e,m):this.saveToCache(e,m),u?.isEnabled()&&u.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(m),resultType:this.getResultType(m),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:g,duration:performance.now()-d,method:"resolve",skipCache:l.skipCache}),m}resolvePath(e,a,r,i=0,l=new WeakSet){if(r.maxDepth&&i>r.maxDepth){if(r.detectCircular)throw new rd(`Maximum depth exceeded (${r.maxDepth}). Possible circular reference.`,e,a);return r.defaultValue}const u=this.parsePath(e);let d=a;for(let f=0;fSa.CACHE_EXPIRY){this.cache.delete(e),r?.isEnabled()&&r.recordCacheMiss();return}return r?.isEnabled()&&r.recordCacheHit(),a.value}saveToCache(e,a){this.cache.set(e,{value:a,timestamp:Date.now()})}isActionDefinition(e){return typeof e.handler!="string"?!1:e.params!==void 0||Array.isArray(e.actions)||typeof e.target=="string"||e.onSuccess!==void 0||e.onError!==void 0}extractSingleBinding(e){if(!e.startsWith("{{")||!e.endsWith("}}")||e.length<5)return null;const a=e.slice(2,-2);let r=0;for(let i=0;i0)r--;else if(a[i+1]==="}")return null}}return a}resolveObject(e,a,r){if(this.isSwitchExpression(e)){const d=e;return this.resolveSwitch(d,a,r)}if(this.isActionDefinition(e))return{...e};if("iteration"in e)return{...e};const i={},u=[...["cellChildren","expandChildren","expandContext","render"],...r?.skipBindingKeys||[]];for(const[d,f]of Object.entries(e)){if(u.includes(d)){i[d]=f;continue}if(typeof f=="string"){const g=this.extractSingleBinding(f);if(g!==null){const m=g.trim();let b=!1,v=m;m.startsWith(Er)&&(b=!0,v=m.slice(Er.length));const E=/[?:|&!+\-*/<>=()]/.test(v)||/\[['"]/.test(v)?this.evaluateExpression(v,a,r):this.resolve(v,a,r);i[d]=b&&E!=null?Xs(E):E}else i[d]=this.resolveBindings(f,a,r)}else Array.isArray(f)?i[d]=f.map(g=>typeof g=="string"?this.resolveBindings(g,a,r):typeof g=="object"&&g!==null?this.resolveObject(g,a,r):g):f&&typeof f=="object"?i[d]=this.resolveObject(f,a,r):i[d]=f}return i}clearCache(){this.cache.clear(),this.expressionFnCache.clear()}invalidateCacheByKeys(e){for(const a of this.cache.keys())for(const r of e)if(a===r||a.startsWith(`${r}.`)||a.startsWith(`${r}[`)){this.cache.delete(a);break}}pruneCache(){const e=Date.now();for(const[a,r]of this.cache.entries())e-r.timestamp>Sa.CACHE_EXPIRY&&this.cache.delete(a)}getCacheStats(){const e=Date.now();let a=0;for(const r of this.cache.values())e-r.timestamp>Sa.CACHE_EXPIRY&&a++;return{size:this.cache.size,expired:a}}evaluateExpression(e,a,r){const i=Rl(),l=i?.isEnabled()?performance.now():0;i?.isEnabled()&&i.trackBindingEval();try{let u=this.preprocessOptionalChaining(e);u=this.preprocessTranslationTokens(u);const d=this.extractVariablesFromExpression(u),f={...a};for(const D of d)D in f||(f[D]=void 0);a._computed&&!f.$computed&&(f.$computed=a._computed);let g=a.$templateId,m=a.$locale;if(typeof window<"u"&&(!g||!m)){const D=window.__templateApp?.getConfig?.();g??(g=D?.templateId),m??(m=D?.locale)}const b=m||"ko";f.$localized=(D,U)=>{if(D==null&&!U)return"";if(typeof D=="string")return D;if(D&&typeof D=="object"&&D[b])return D[b];if(U&&typeof U=="string"){const j=f.$t?f.$t(U):U;if(j&&j!==U)return j}return D&&typeof D=="object"?D.ko||D.en||Object.values(D)[0]||"":D==null?"":String(D)};const v=typeof window<"u"?window.G7Core:void 0;f.$uuid=()=>v?.uuid?v.uuid():typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,D=>{const U=Math.random()*16|0;return(D==="x"?U:U&3|8).toString(16)});const S={templateId:g||"",locale:b};f.$t=D=>{if(!D||typeof D!="string")return"";try{return Cr.getInstance().translate(D,S)}catch(U){return Js.warn("$t() translation failed for key:",D,U),D}},f.$get=(D,U,j=void 0)=>{if(D==null)return j;const P=Array.isArray(U)?U:[U];if(P.length===0)return D;let X=D;for(const ge of P){if(X==null||ge==null)return j;X=X[ge]}return X??j};const E=Object.keys(f),A=Object.values(f),T=`${u}|${E.join(",")}`;let L=this.expressionFnCache.get(T);const M=!!L;L||(L=new Function(...E,`return (${u});`),this.expressionFnCache.set(T,L));const R=L(...A);if(i?.isEnabled()){const D=performance.now()-l;i.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(R),resultType:this.getResultType(R),componentId:r?.componentId,componentName:r?.componentName,propName:r?.propName,fromCache:M,duration:D,method:"evaluateExpression",skipCache:r?.skipCache})}return R}catch(u){throw new Error(`Failed to evaluate expression "${e}": ${u instanceof Error?u.message:String(u)}`)}}getResultType(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}sanitizeResultForTracking(e){if(e==null||typeof e!="object")return e;try{if(Array.isArray(e))return e.length>10?`[Array(${e.length})]`:e.slice(0,10);const a=Object.keys(e);return a.length>20?`{Object(${a.length} keys)}`:(JSON.stringify(e),e)}catch{return"[Complex Object]"}}preprocessTranslationTokens(e){return e=e.replace(/(['"])(\$t:([a-zA-Z_][a-zA-Z0-9_.\-]*))\1/g,(a,r,i,l)=>`$t('${l}')`),e.replace(/(?(a.push(l),`__STRING_LITERAL_${a.length-1}__`));const i=[];return r=r.replace(/\$t:[a-zA-Z_][a-zA-Z0-9_.\-]*(?:\|[^'"\s,)]+)?/g,l=>(i.push(l),`__TRANSLATION_TOKEN_${i.length-1}__`)),r=r.replace(/([a-zA-Z_$][a-zA-Z0-9_$]*)\.(?!\?)/g,"$1?."),r=r.replace(/__TRANSLATION_TOKEN_(\d+)__/g,(l,u)=>i[parseInt(u,10)]),r=r.replace(/__STRING_LITERAL_(\d+)__/g,(l,u)=>a[parseInt(u,10)]),r}extractVariablesFromExpression(e){const a=new Set(["true","false","null","undefined","NaN","Infinity","if","else","for","while","do","switch","case","break","continue","return","function","class","const","let","var","new","delete","typeof","instanceof","this","super","import","export","default","try","catch","finally","throw","Math","Date","JSON","Array","Object","String","Number","Boolean","RegExp","Set","Map","WeakSet","WeakMap","Symbol","Promise","BigInt","Error","parseInt","parseFloat","isNaN","isFinite","encodeURI","decodeURI","encodeURIComponent","decodeURIComponent"]),r=/(?{a!==null&&clearTimeout(a),a=setTimeout(()=>{o(...r)},e)})}class QS{constructor(){$(this,"subscribers",new Set);$(this,"currentWidth",1024);$(this,"debouncedHandler",null);$(this,"isInitialized",!1);this.initialize()}initialize(){typeof window>"u"||(this.currentWidth=window.innerWidth,this.isInitialized=!0,this.debouncedHandler=JS(()=>{this.currentWidth=window.innerWidth,this.notifySubscribers()},150),window.addEventListener("resize",this.debouncedHandler))}notifySubscribers(){this.subscribers.forEach(e=>{e(this.currentWidth)})}subscribe(e){return this.subscribers.add(e),e(this.currentWidth),()=>{this.subscribers.delete(e)}}getWidth(){return this.currentWidth}parseRange(e){if(Dl.has(e))return Dl.get(e)??null;let a=null;if(kl[e])a={...kl[e]};else{const r=e.match(/^(-?\d*)-(-?\d*)$/);if(r){const[,i,l]=r,u=i===""?0:parseInt(i,10),d=l===""?1/0:parseInt(l,10);!isNaN(u)&&!isNaN(d)&&u<=d&&(a={min:u,max:d})}}return Dl.set(e,a),a}getMatchingKey(e,a){const r=[];for(const i of Object.keys(e)){const l=this.parseRange(i);l&&a>=l.min&&a<=l.max&&r.push({key:i,range:l,isPreset:!!kl[i]})}return r.length===0?null:(r.sort((i,l)=>{if(i.isPreset!==l.isPreset)return i.isPreset?1:-1;const u=i.range.max-i.range.min,d=l.range.max-l.range.min;return u-d}),r[0].key)}matches(e){const a=this.parseRange(e);return a?this.currentWidth>=a.min&&this.currentWidth<=a.max:!1}clearSubscribers(){this.subscribers.clear()}destroy(){this.debouncedHandler&&typeof window<"u"&&window.removeEventListener("resize",this.debouncedHandler),this.clearSubscribers(),Dl.clear()}_setWidthForTesting(e){this.currentWidth=e,this.notifySubscribers()}}const ci=new QS,Ol=ct("ConditionEvaluator");function ZS(o){switch(o){case"true":return{value:!0};case"false":return{value:!1};case"null":return{value:null};case"undefined":return{value:void 0};default:return}}function ew(o){return/[?:|&!+\-*/<>=()]/.test(o)}function tw(o){if(!o.startsWith("{{")||!o.endsWith("}}"))return null;const e=o.slice(2,-2);let a=null,r=0;for(let i=0;i0?e[i-1]:"")!=="\\"&&((l==='"'||l==="'")&&!a?a=l:l===a&&(a=null),!a&&(l==="{"&&r++,l==="}"&&r--,r<0)))return null}return r===0?e.trim():null}function nw(o,e,a){if(!o)return!0;try{const r=tw(o);let i;if(r!==null){const l=ZS(r);l!==void 0?i=l.value:ew(r)?i=a.evaluateExpression(r,e):i=a.resolve(r,e,{skipCache:!0})}else i=a.resolveBindings(o,e,{skipCache:!0});if(typeof i=="string"){const l=i.toLowerCase().trim();if(l==="false"||l==="0"||l===""||l==="null"||l==="undefined")return!1}return!!i}catch(r){return Ol.warn(`evaluateStringCondition: 조건 평가 실패: ${o}`,r),!1}}function Ll(o,e,a){if(typeof o=="string")return nw(o,e,a);if("and"in o){if(!Array.isArray(o.and)||o.and.length===0)return Ol.warn("evaluateConditionExpression: AND 그룹이 비어있습니다"),!0;for(const r of o.and)if(!Ll(r,e,a))return!1;return!0}if("or"in o){if(!Array.isArray(o.or)||o.or.length===0)return Ol.warn("evaluateConditionExpression: OR 그룹이 비어있습니다"),!1;for(const r of o.or)if(Ll(r,e,a))return!0;return!1}return Ol.warn("evaluateConditionExpression: 알 수 없는 조건 형식",o),!1}function op(o,e,a){if(!Array.isArray(o)||o.length===0)return{matched:!1,branchIndex:-1};for(let r=0;r=()[\]{}]/.test(o)}function up(o){if(!o.startsWith("{{")||!o.endsWith("}}"))return null;const e=o.slice(2,-2);let a=null,r=0;for(let i=0;i0?e[i-1]:"")!=="\\"&&((l==='"'||l==="'")&&!a?a=l:l===a&&(a=null),!a&&(l==="{"&&r++,l==="}"&&r--,r<0)))return null}return r===0?e.trim():null}function sd(o,e,a){let r=o;if(o.startsWith("{{")&&o.endsWith("}}")&&(r=o.slice(2,-2).trim()),id(r))try{return a.evaluateExpression(r,e)}catch(i){Xa.warn(`resolveIterationSource: 표현식 평가 실패: ${o}`,i);return}return a.resolve(r,e,{skipCache:!0})}function sw(o,e){const a={...o};if(e?.parentDataContext)for(const[r,i]of Object.entries(e.parentDataContext))r in a||(a[r]=i);if(e?.state){const r=a._local||{};a._local={...r,...e.state}}return e?.isolatedContext?.state&&(a._isolated=e.isolatedContext.state),a}function od(o,e,a,r){if(!e||!Array.isArray(e)||e.length===0)return o;const i=r?.actionDispatcher??Zp(),l={...o,actions:e},u=i.bindActionsToProps(l,a,r?.componentContext);return delete u.actions,u}function dp(o,e,a,r){if(typeof o=="boolean")return o;if(!o)return!0;try{const i=up(o);let l;if(i!==null){const u=iw.get(i);u!==void 0?l=u:id(i)?l=a.evaluateExpression(i,e):l=a.resolve(i,e,{skipCache:!0})}else l=a.resolveBindings(o,e,{skipCache:!0});if(typeof l=="string"){const u=l.toLowerCase().trim();if(u==="false"||u==="0"||u===""||u==="null"||u==="undefined")return!1}return!!l}catch(i){return Xa.warn(`evaluateIfCondition: 조건 평가 실패 (컴포넌트: ${r||"unknown"}):`,i),!1}}function Yi(o,e,a,r){if(o.if!==void 0)return dp(o.if,e,a,r);if(o.condition!==void 0)return dp(o.condition,e,a,r);if(o.conditions===void 0)return!0;const i=o.conditions;try{return aw(i)?Ll(i,e,a):rw(i)?op(i,e,a).matched:(Xa.warn(`evaluateRenderCondition: 알 수 없는 conditions 형식 (컴포넌트: ${r||"unknown"})`),!0)}catch(l){return Xa.warn(`evaluateRenderCondition: conditions 평가 실패 (컴포넌트: ${r||"unknown"}):`,l),!1}}function fp(o){if(!o.responsive)return o;const e=ci.getWidth(),a=ci.getMatchingKey(o.responsive,e);if(!a)return o;const r=o.responsive[a];return{...o,props:{...o.props,...r.props},children:r.children??o.children,text:r.text??o.text,if:r.if??o.if,iteration:r.iteration??o.iteration}}function Qs(o,e,a,r,i){if(!o||o.length===0)return[];const l=i?.bindingEngine??new wn,u=i?.translationEngine??Cr.getInstance(),d=i?.translationContext??{templateId:"",locale:"ko"},f=sw(e,i?.componentContext),g=(v,S)=>{if(typeof v=="string"){if(rp(v))return sp(v);if(ip(v)){const A=[],T=v.replace(new RegExp(`${Tl}([^${Ws}]*)${Ws}`,"g"),(M,R)=>(A.push(R),`${_r}${A.length-1}${_r}`));let L=T;return/\$t:[a-zA-Z0-9._-]+/.test(T)&&(L=u.resolveTranslations(T,d,S)),L.replace(new RegExp(`${_r}(\\d+)${_r}`,"g"),(M,R)=>A[parseInt(R)])}if(v.startsWith("$t:defer:")){const A="$t:"+v.slice(9);return u.resolveTranslations(A,d,S)}if(v.startsWith("$t:"))return u.resolveTranslations(v,d,S);const E=up(v);if(E!==null){let A=!1,T=E;E.startsWith(Er)&&(A=!0,T=E.slice(Er.length));let L;if(id(T))try{L=l.evaluateExpression(T,S)}catch(M){Xa.warn("renderItemChildren: 표현식 평가 실패:",M);return}else L=l.resolve(T,S,{skipCache:!0});return!A&&typeof L=="string"&&/\$t:[a-zA-Z0-9._-]+/.test(L)&&(L=u.resolveTranslations(L,d,S)),A&&L!=null?Xs(L):L}if(v.includes("{{")){const A=l.resolveBindings(v,S,{skipCache:!0});return typeof A=="string"&&/\$t:[a-zA-Z0-9._-]+/.test(A)?u.resolveTranslations(A,d,S):A}return v}if(Array.isArray(v))return v.map(E=>g(E,S));if(v&&typeof v=="object"){const E={};for(const[A,T]of Object.entries(v))E[A]=g(T,S);return E}return v},m=(v,S)=>{if(!v)return{};const E={};for(const[A,T]of Object.entries(v))E[A]=g(T,S);return E},b=(v,S,E)=>{const A=fp(v),T=A.iteration;if(!T)return[];const L=sd(T.source,E,l);if(!Array.isArray(L))return Xa.warn(`renderItemChildren: iteration.source가 배열이 아닙니다: ${T.source}`),[];const M=lp();if(M?.isEnabled()){const D=`${S}-iteration`;M.trackIteration(D,T.source,T.item_var,T.index_var,L.length)}const R=a[A.name];return R?L.flatMap((D,U)=>{const j={...E,[T.item_var]:D,[`${T.item_var}_index`]:U,...T.index_var?{[T.index_var]:U}:{}},P=Yi({if:A.if,condition:A.condition,conditions:A.conditions},j,l,A.id);if(A.if&&M?.isEnabled()){const Xe=`${S}-iter-${U}-if`;M.trackIfCondition(Xe,A.if,P,A.name)}if(!P)return[];const X=A.id?String(g(A.id,j)):void 0,ge=`${S}-iter-${U}`,Ee=i?.getRemountKey?i.getRemountKey(X,ge):ge,Ce=m(A.props,j),$e=od(Ce,A.actions,j,{actionDispatcher:i?.actionDispatcher,componentContext:i?.componentContext});let Pe=null;return A.text!==void 0?Pe=g(A.text,j):A.children&&A.children.length>0&&(Pe=Qs(A.children,j,a,Ee,i)),M?.isEnabled()&&M.trackRender(A.name),[Ye.createElement(R,{key:Ee,...$e},Pe)]}):(Xa.warn(`renderItemChildren: 컴포넌트를 찾을 수 없습니다: ${A.name}`),[])};return o.flatMap((v,S)=>{const E=fp(v),A=E.id?String(g(E.id,f)):void 0,T=r?`${r}-${A||S}`:A||`child-${S}`,L=i?.getRemountKey?i.getRemountKey(A,T):T;if(E.iteration)return b(E,L,f);const M=Yi({if:E.if,condition:E.condition,conditions:E.conditions},f,l,E.id),R=lp();if(E.if&&R?.isEnabled()){const X=`${L}-if`;R.trackIfCondition(X,E.if,M,E.name)}if(!M)return[];const D=a[E.name];if(!D)return Xa.warn(`renderItemChildren: 컴포넌트를 찾을 수 없습니다: ${E.name}`),[];const U=m(E.props,f),j=od(U,E.actions,f,{actionDispatcher:i?.actionDispatcher,componentContext:i?.componentContext});let P=null;return E.text!==void 0?P=g(E.text,f):E.children&&E.children.length>0&&(P=Qs(E.children,f,a,L,i)),R?.isEnabled()&&R.trackRender(E.name),[Ye.createElement(D,{key:L,...j},P)]})}function Xi(o,e,a,r){let i,l;return a instanceof wn?(i=a,l=r):(i=cp,l=a),i.resolveBindings(o,e,l)}function ow(o,e,a,r){const i=a??cp,l={skipCache:!0,...r};let u;try{u=i.resolveBindings(o.key,e,{skipCache:l.skipCache})?.toString()?.trim()??""}catch(g){Xa.warn("resolveClassMap: key 평가 실패:",o.key,g),u=""}let d="";u&&o.variants&&u in o.variants?d=o.variants[u]:o.default&&(d=o.default);const f=[];return o.base?.trim()&&f.push(o.base.trim()),d?.trim()&&f.push(d.trim()),f.join(" ")}function hp(o,e){return function(){return o.apply(e,arguments)}}const{toString:lw}=Object.prototype,{getPrototypeOf:Ml}=Object,{iterator:$l,toStringTag:gp}=Symbol,Nl=(o=>e=>{const a=lw.call(e);return o[a]||(o[a]=a.slice(8,-1).toLowerCase())})(Object.create(null)),fa=o=>(o=o.toLowerCase(),e=>Nl(e)===o),Il=o=>e=>typeof e===o,{isArray:Ji}=Array,Qi=Il("undefined");function Zs(o){return o!==null&&!Qi(o)&&o.constructor!==null&&!Qi(o.constructor)&&xn(o.constructor.isBuffer)&&o.constructor.isBuffer(o)}const pp=fa("ArrayBuffer");function cw(o){let e;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?e=ArrayBuffer.isView(o):e=o&&o.buffer&&pp(o.buffer),e}const uw=Il("string"),xn=Il("function"),mp=Il("number"),eo=o=>o!==null&&typeof o=="object",dw=o=>o===!0||o===!1,Hl=o=>{if(Nl(o)!=="object")return!1;const e=Ml(o);return(e===null||e===Object.prototype||Object.getPrototypeOf(e)===null)&&!(gp in o)&&!($l in o)},fw=o=>{if(!eo(o)||Zs(o))return!1;try{return Object.keys(o).length===0&&Object.getPrototypeOf(o)===Object.prototype}catch{return!1}},hw=fa("Date"),gw=fa("File"),pw=o=>!!(o&&typeof o.uri<"u"),mw=o=>o&&typeof o.getParts<"u",yw=fa("Blob"),bw=fa("FileList"),vw=o=>eo(o)&&xn(o.pipe);function Sw(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}}const yp=Sw(),bp=typeof yp.FormData<"u"?yp.FormData:void 0,ww=o=>{if(!o)return!1;if(bp&&o instanceof bp)return!0;const e=Ml(o);if(!e||e===Object.prototype||!xn(o.append))return!1;const a=Nl(o);return a==="formdata"||a==="object"&&xn(o.toString)&&o.toString()==="[object FormData]"},Cw=fa("URLSearchParams"),[Ew,_w,Aw,xw]=["ReadableStream","Request","Response","Headers"].map(fa),Tw=o=>o.trim?o.trim():o.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function to(o,e,{allOwnKeys:a=!1}={}){if(o===null||typeof o>"u")return;let r,i;if(typeof o!="object"&&(o=[o]),Ji(o))for(r=0,i=o.length;r0;)if(i=a[r],e===i.toLowerCase())return i;return null}const ui=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,Sp=o=>!Qi(o)&&o!==ui;function ld(...o){const{caseless:e,skipUndefined:a}=Sp(this)&&this||{},r={},i=(l,u)=>{if(u==="__proto__"||u==="constructor"||u==="prototype")return;const d=e&&vp(r,u)||u,f=cd(r,d)?r[d]:void 0;Hl(f)&&Hl(l)?r[d]=ld(f,l):Hl(l)?r[d]=ld({},l):Ji(l)?r[d]=l.slice():(!a||!Qi(l))&&(r[d]=l)};for(let l=0,u=o.length;l(to(e,(i,l)=>{a&&xn(i)?Object.defineProperty(o,l,{__proto__:null,value:hp(i,a),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(o,l,{__proto__:null,value:i,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:r}),o),kw=o=>(o.charCodeAt(0)===65279&&(o=o.slice(1)),o),Dw=(o,e,a,r)=>{o.prototype=Object.create(e.prototype,r),Object.defineProperty(o.prototype,"constructor",{__proto__:null,value:o,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(o,"super",{__proto__:null,value:e.prototype}),a&&Object.assign(o.prototype,a)},Ow=(o,e,a,r)=>{let i,l,u;const d={};if(e=e||{},o==null)return e;do{for(i=Object.getOwnPropertyNames(o),l=i.length;l-- >0;)u=i[l],(!r||r(u,o,e))&&!d[u]&&(e[u]=o[u],d[u]=!0);o=a!==!1&&Ml(o)}while(o&&(!a||a(o,e))&&o!==Object.prototype);return e},Lw=(o,e,a)=>{o=String(o),(a===void 0||a>o.length)&&(a=o.length),a-=e.length;const r=o.indexOf(e,a);return r!==-1&&r===a},Mw=o=>{if(!o)return null;if(Ji(o))return o;let e=o.length;if(!mp(e))return null;const a=new Array(e);for(;e-- >0;)a[e]=o[e];return a},$w=(o=>e=>o&&e instanceof o)(typeof Uint8Array<"u"&&Ml(Uint8Array)),Nw=(o,e)=>{const r=(o&&o[$l]).call(o);let i;for(;(i=r.next())&&!i.done;){const l=i.value;e.call(o,l[0],l[1])}},Iw=(o,e)=>{let a;const r=[];for(;(a=o.exec(e))!==null;)r.push(a);return r},Hw=fa("HTMLFormElement"),zw=o=>o.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(a,r,i){return r.toUpperCase()+i}),cd=(({hasOwnProperty:o})=>(e,a)=>o.call(e,a))(Object.prototype),jw=fa("RegExp"),wp=(o,e)=>{const a=Object.getOwnPropertyDescriptors(o),r={};to(a,(i,l)=>{let u;(u=e(i,l,o))!==!1&&(r[l]=u||i)}),Object.defineProperties(o,r)},Uw=o=>{wp(o,(e,a)=>{if(xn(o)&&["arguments","caller","callee"].includes(a))return!1;const r=o[a];if(xn(r)){if(e.enumerable=!1,"writable"in e){e.writable=!1;return}e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+a+"'")})}})},Bw=(o,e)=>{const a={},r=i=>{i.forEach(l=>{a[l]=!0})};return Ji(o)?r(o):r(String(o).split(e)),a},Pw=()=>{},qw=(o,e)=>o!=null&&Number.isFinite(o=+o)?o:e;function Gw(o){return!!(o&&xn(o.append)&&o[gp]==="FormData"&&o[$l])}const Vw=o=>{const e=new WeakSet,a=r=>{if(eo(r)){if(e.has(r))return;if(Zs(r))return r;if(!("toJSON"in r)){e.add(r);const i=Ji(r)?[]:{};return to(r,(l,u)=>{const d=a(l);!Qi(d)&&(i[u]=d)}),e.delete(r),i}}return r};return a(o)},Fw=fa("AsyncFunction"),Kw=o=>o&&(eo(o)||xn(o))&&xn(o.then)&&xn(o.catch),Cp=((o,e)=>o?setImmediate:e?((a,r)=>(ui.addEventListener("message",({source:i,data:l})=>{i===ui&&l===a&&r.length&&r.shift()()},!1),i=>{r.push(i),ui.postMessage(a,"*")}))(`axios@${Math.random()}`,[]):a=>setTimeout(a))(typeof setImmediate=="function",xn(ui.postMessage)),Ww=typeof queueMicrotask<"u"?queueMicrotask.bind(ui):typeof process<"u"&&process.nextTick||Cp,F={isArray:Ji,isArrayBuffer:pp,isBuffer:Zs,isFormData:ww,isArrayBufferView:cw,isString:uw,isNumber:mp,isBoolean:dw,isObject:eo,isPlainObject:Hl,isEmptyObject:fw,isReadableStream:Ew,isRequest:_w,isResponse:Aw,isHeaders:xw,isUndefined:Qi,isDate:hw,isFile:gw,isReactNativeBlob:pw,isReactNative:mw,isBlob:yw,isRegExp:jw,isFunction:xn,isStream:vw,isURLSearchParams:Cw,isTypedArray:$w,isFileList:bw,forEach:to,merge:ld,extend:Rw,trim:Tw,stripBOM:kw,inherits:Dw,toFlatObject:Ow,kindOf:Nl,kindOfTest:fa,endsWith:Lw,toArray:Mw,forEachEntry:Nw,matchAll:Iw,isHTMLForm:Hw,hasOwnProperty:cd,hasOwnProp:cd,reduceDescriptors:wp,freezeMethods:Uw,toObjectSet:Bw,toCamelCase:zw,noop:Pw,toFiniteNumber:qw,findKey:vp,global:ui,isContextDefined:Sp,isSpecCompliantForm:Gw,toJSONObject:Vw,isAsyncFn:Fw,isThenable:Kw,setImmediate:Cp,asap:Ww,isIterable:o=>o!=null&&xn(o[$l])},Yw=F.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),Xw=o=>{const e={};let a,r,i;return o&&o.split(` -`).forEach(function(u){i=u.indexOf(":"),a=u.substring(0,i).trim().toLowerCase(),r=u.substring(i+1).trim(),!(!a||e[a]&&Yw[a])&&(a==="set-cookie"?e[a]?e[a].push(r):e[a]=[r]:e[a]=e[a]?e[a]+", "+r:r)}),e};function Jw(o){let e=0,a=o.length;for(;ee;){const r=o.charCodeAt(a-1);if(r!==9&&r!==32)break;a-=1}return e===0&&a===o.length?o:o.slice(e,a)}const Qw=new RegExp("[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+","g"),Zw=new RegExp("[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+","g");function ud(o,e){return F.isArray(o)?o.map(a=>ud(a,e)):Jw(String(o).replace(e,""))}const e0=o=>ud(o,Qw),t0=o=>ud(o,Zw);function Ep(o){const e=Object.create(null);return F.forEach(o.toJSON(),(a,r)=>{e[r]=t0(a)}),e}const _p=Symbol("internals");function no(o){return o&&String(o).trim().toLowerCase()}function zl(o){return o===!1||o==null?o:F.isArray(o)?o.map(zl):e0(String(o))}function n0(o){const e=Object.create(null),a=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=a.exec(o);)e[r[1]]=r[2];return e}const a0=o=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(o.trim());function dd(o,e,a,r,i){if(F.isFunction(r))return r.call(this,e,a);if(i&&(e=a),!!F.isString(e)){if(F.isString(r))return e.indexOf(r)!==-1;if(F.isRegExp(r))return r.test(e)}}function r0(o){return o.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(e,a,r)=>a.toUpperCase()+r)}function i0(o,e){const a=F.toCamelCase(" "+e);["get","set","has"].forEach(r=>{Object.defineProperty(o,r+a,{__proto__:null,value:function(i,l,u){return this[r].call(this,e,i,l,u)},configurable:!0})})}let Cn=class{constructor(e){e&&this.set(e)}set(e,a,r){const i=this;function l(d,f,g){const m=no(f);if(!m)throw new Error("header name must be a non-empty string");const b=F.findKey(i,m);(!b||i[b]===void 0||g===!0||g===void 0&&i[b]!==!1)&&(i[b||f]=zl(d))}const u=(d,f)=>F.forEach(d,(g,m)=>l(g,m,f));if(F.isPlainObject(e)||e instanceof this.constructor)u(e,a);else if(F.isString(e)&&(e=e.trim())&&!a0(e))u(Xw(e),a);else if(F.isObject(e)&&F.isIterable(e)){let d={},f,g;for(const m of e){if(!F.isArray(m))throw TypeError("Object iterator must return a key-value pair");d[g=m[0]]=(f=d[g])?F.isArray(f)?[...f,m[1]]:[f,m[1]]:m[1]}u(d,a)}else e!=null&&l(a,e,r);return this}get(e,a){if(e=no(e),e){const r=F.findKey(this,e);if(r){const i=this[r];if(!a)return i;if(a===!0)return n0(i);if(F.isFunction(a))return a.call(this,i,r);if(F.isRegExp(a))return a.exec(i);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,a){if(e=no(e),e){const r=F.findKey(this,e);return!!(r&&this[r]!==void 0&&(!a||dd(this,this[r],r,a)))}return!1}delete(e,a){const r=this;let i=!1;function l(u){if(u=no(u),u){const d=F.findKey(r,u);d&&(!a||dd(r,r[d],d,a))&&(delete r[d],i=!0)}}return F.isArray(e)?e.forEach(l):l(e),i}clear(e){const a=Object.keys(this);let r=a.length,i=!1;for(;r--;){const l=a[r];(!e||dd(this,this[l],l,e,!0))&&(delete this[l],i=!0)}return i}normalize(e){const a=this,r={};return F.forEach(this,(i,l)=>{const u=F.findKey(r,l);if(u){a[u]=zl(i),delete a[l];return}const d=e?r0(l):String(l).trim();d!==l&&delete a[l],a[d]=zl(i),r[d]=!0}),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const a=Object.create(null);return F.forEach(this,(r,i)=>{r!=null&&r!==!1&&(a[i]=e&&F.isArray(r)?r.join(", "):r)}),a}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([e,a])=>e+": "+a).join(` -`)}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(e){return e instanceof this?e:new this(e)}static concat(e,...a){const r=new this(e);return a.forEach(i=>r.set(i)),r}static accessor(e){const r=(this[_p]=this[_p]={accessors:{}}).accessors,i=this.prototype;function l(u){const d=no(u);r[d]||(i0(i,u),r[d]=!0)}return F.isArray(e)?e.forEach(l):l(e),this}};Cn.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),F.reduceDescriptors(Cn.prototype,({value:o},e)=>{let a=e[0].toUpperCase()+e.slice(1);return{get:()=>o,set(r){this[a]=r}}}),F.freezeMethods(Cn);const s0="[REDACTED ****]";function o0(o){if(F.hasOwnProp(o,"toJSON"))return!0;let e=Object.getPrototypeOf(o);for(;e&&e!==Object.prototype;){if(F.hasOwnProp(e,"toJSON"))return!0;e=Object.getPrototypeOf(e)}return!1}function l0(o,e){const a=new Set(e.map(l=>String(l).toLowerCase())),r=[],i=l=>{if(l===null||typeof l!="object"||F.isBuffer(l))return l;if(r.indexOf(l)!==-1)return;l instanceof Cn&&(l=l.toJSON()),r.push(l);let u;if(F.isArray(l))u=[],l.forEach((d,f)=>{const g=i(d);F.isUndefined(g)||(u[f]=g)});else{if(!F.isPlainObject(l)&&o0(l))return r.pop(),l;u=Object.create(null);for(const[d,f]of Object.entries(l)){const g=a.has(d.toLowerCase())?s0:i(f);F.isUndefined(g)||(u[d]=g)}}return r.pop(),u};return i(o)}let Oe=class RS extends Error{static from(e,a,r,i,l,u){const d=new RS(e.message,a||e.code,r,i,l);return d.cause=e,d.name=e.name,e.status!=null&&d.status==null&&(d.status=e.status),u&&Object.assign(d,u),d}constructor(e,a,r,i,l){super(e),Object.defineProperty(this,"message",{__proto__:null,value:e,enumerable:!0,writable:!0,configurable:!0}),this.name="AxiosError",this.isAxiosError=!0,a&&(this.code=a),r&&(this.config=r),i&&(this.request=i),l&&(this.response=l,this.status=l.status)}toJSON(){const e=this.config,a=e&&F.hasOwnProp(e,"redact")?e.redact:void 0,r=F.isArray(a)&&a.length>0?l0(e,a):F.toJSONObject(e);return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:r,code:this.code,status:this.status}}};Oe.ERR_BAD_OPTION_VALUE="ERR_BAD_OPTION_VALUE",Oe.ERR_BAD_OPTION="ERR_BAD_OPTION",Oe.ECONNABORTED="ECONNABORTED",Oe.ETIMEDOUT="ETIMEDOUT",Oe.ECONNREFUSED="ECONNREFUSED",Oe.ERR_NETWORK="ERR_NETWORK",Oe.ERR_FR_TOO_MANY_REDIRECTS="ERR_FR_TOO_MANY_REDIRECTS",Oe.ERR_DEPRECATED="ERR_DEPRECATED",Oe.ERR_BAD_RESPONSE="ERR_BAD_RESPONSE",Oe.ERR_BAD_REQUEST="ERR_BAD_REQUEST",Oe.ERR_CANCELED="ERR_CANCELED",Oe.ERR_NOT_SUPPORT="ERR_NOT_SUPPORT",Oe.ERR_INVALID_URL="ERR_INVALID_URL",Oe.ERR_FORM_DATA_DEPTH_EXCEEDED="ERR_FORM_DATA_DEPTH_EXCEEDED";const c0=null;function fd(o){return F.isPlainObject(o)||F.isArray(o)}function Ap(o){return F.endsWith(o,"[]")?o.slice(0,-2):o}function hd(o,e,a){return o?o.concat(e).map(function(i,l){return i=Ap(i),!a&&l?"["+i+"]":i}).join(a?".":""):e}function u0(o){return F.isArray(o)&&!o.some(fd)}const d0=F.toFlatObject(F,{},null,function(e){return/^is[A-Z]/.test(e)});function jl(o,e,a){if(!F.isObject(o))throw new TypeError("target must be an object");e=e||new FormData,a=F.toFlatObject(a,{metaTokens:!0,dots:!1,indexes:!1},!1,function(T,L){return!F.isUndefined(L[T])});const r=a.metaTokens,i=a.visitor||b,l=a.dots,u=a.indexes,d=a.Blob||typeof Blob<"u"&&Blob,f=a.maxDepth===void 0?100:a.maxDepth,g=d&&F.isSpecCompliantForm(e);if(!F.isFunction(i))throw new TypeError("visitor must be a function");function m(A){if(A===null)return"";if(F.isDate(A))return A.toISOString();if(F.isBoolean(A))return A.toString();if(!g&&F.isBlob(A))throw new Oe("Blob is not supported. Use a Buffer instead.");return F.isArrayBuffer(A)||F.isTypedArray(A)?g&&typeof Blob=="function"?new Blob([A]):Buffer.from(A):A}function b(A,T,L){let M=A;if(F.isReactNative(e)&&F.isReactNativeBlob(A))return e.append(hd(L,T,l),m(A)),!1;if(A&&!L&&typeof A=="object"){if(F.endsWith(T,"{}"))T=r?T:T.slice(0,-2),A=JSON.stringify(A);else if(F.isArray(A)&&u0(A)||(F.isFileList(A)||F.endsWith(T,"[]"))&&(M=F.toArray(A)))return T=Ap(T),M.forEach(function(D,U){!(F.isUndefined(D)||D===null)&&e.append(u===!0?hd([T],U,l):u===null?T:T+"[]",m(D))}),!1}return fd(A)?!0:(e.append(hd(L,T,l),m(A)),!1)}const v=[],S=Object.assign(d0,{defaultVisitor:b,convertValue:m,isVisitable:fd});function E(A,T,L=0){if(!F.isUndefined(A)){if(L>f)throw new Oe("Object is too deeply nested ("+L+" levels). Max depth: "+f,Oe.ERR_FORM_DATA_DEPTH_EXCEEDED);if(v.indexOf(A)!==-1)throw Error("Circular reference detected in "+T.join("."));v.push(A),F.forEach(A,function(R,D){(!(F.isUndefined(R)||R===null)&&i.call(e,R,F.isString(D)?D.trim():D,T,S))===!0&&E(R,T?T.concat(D):[D],L+1)}),v.pop()}}if(!F.isObject(o))throw new TypeError("data must be an object");return E(o),e}function xp(o){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+"};return encodeURIComponent(o).replace(/[!'()~]|%20/g,function(r){return e[r]})}function gd(o,e){this._pairs=[],o&&jl(o,this,e)}const Tp=gd.prototype;Tp.append=function(e,a){this._pairs.push([e,a])},Tp.toString=function(e){const a=e?function(r){return e.call(this,r,xp)}:xp;return this._pairs.map(function(i){return a(i[0])+"="+a(i[1])},"").join("&")};function f0(o){return encodeURIComponent(o).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function Rp(o,e,a){if(!e)return o;const r=a&&a.encode||f0,i=F.isFunction(a)?{serialize:a}:a,l=i&&i.serialize;let u;if(l?u=l(e,i):u=F.isURLSearchParams(e)?e.toString():new gd(e,i).toString(r),u){const d=o.indexOf("#");d!==-1&&(o=o.slice(0,d)),o+=(o.indexOf("?")===-1?"?":"&")+u}return o}class kp{constructor(){this.handlers=[]}use(e,a,r){return this.handlers.push({fulfilled:e,rejected:a,synchronous:r?r.synchronous:!1,runWhen:r?r.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){F.forEach(this.handlers,function(r){r!==null&&e(r)})}}const pd={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1,legacyInterceptorReqResOrdering:!0},h0={isBrowser:!0,classes:{URLSearchParams:typeof URLSearchParams<"u"?URLSearchParams:gd,FormData:typeof FormData<"u"?FormData:null,Blob:typeof Blob<"u"?Blob:null},protocols:["http","https","file","blob","url","data"]},md=typeof window<"u"&&typeof document<"u",yd=typeof navigator=="object"&&navigator||void 0,g0=md&&(!yd||["ReactNative","NativeScript","NS"].indexOf(yd.product)<0),p0=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function",m0=md&&window.location.href||"http://localhost",yn={...Object.freeze(Object.defineProperty({__proto__:null,hasBrowserEnv:md,hasStandardBrowserEnv:g0,hasStandardBrowserWebWorkerEnv:p0,navigator:yd,origin:m0},Symbol.toStringTag,{value:"Module"})),...h0};function y0(o,e){return jl(o,new yn.classes.URLSearchParams,{visitor:function(a,r,i,l){return yn.isNode&&F.isBuffer(a)?(this.append(r,a.toString("base64")),!1):l.defaultVisitor.apply(this,arguments)},...e})}function b0(o){return F.matchAll(/\w+|\[(\w*)]/g,o).map(e=>e[0]==="[]"?"":e[1]||e[0])}function v0(o){const e={},a=Object.keys(o);let r;const i=a.length;let l;for(r=0;r=a.length;return u=!u&&F.isArray(i)?i.length:u,f?(F.hasOwnProp(i,u)?i[u]=F.isArray(i[u])?i[u].concat(r):[i[u],r]:i[u]=r,!d):((!F.hasOwnProp(i,u)||!F.isObject(i[u]))&&(i[u]=[]),e(a,r,i[u],l)&&F.isArray(i[u])&&(i[u]=v0(i[u])),!d)}if(F.isFormData(o)&&F.isFunction(o.entries)){const a={};return F.forEachEntry(o,(r,i)=>{e(b0(r),i,a,0)}),a}return null}const Zi=(o,e)=>o!=null&&F.hasOwnProp(o,e)?o[e]:void 0;function S0(o,e,a){if(F.isString(o))try{return(e||JSON.parse)(o),F.trim(o)}catch(r){if(r.name!=="SyntaxError")throw r}return(a||JSON.stringify)(o)}const ao={transitional:pd,adapter:["xhr","http","fetch"],transformRequest:[function(e,a){const r=a.getContentType()||"",i=r.indexOf("application/json")>-1,l=F.isObject(e);if(l&&F.isHTMLForm(e)&&(e=new FormData(e)),F.isFormData(e))return i?JSON.stringify(Dp(e)):e;if(F.isArrayBuffer(e)||F.isBuffer(e)||F.isStream(e)||F.isFile(e)||F.isBlob(e)||F.isReadableStream(e))return e;if(F.isArrayBufferView(e))return e.buffer;if(F.isURLSearchParams(e))return a.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let d;if(l){const f=Zi(this,"formSerializer");if(r.indexOf("application/x-www-form-urlencoded")>-1)return y0(e,f).toString();if((d=F.isFileList(e))||r.indexOf("multipart/form-data")>-1){const g=Zi(this,"env"),m=g&&g.FormData;return jl(d?{"files[]":e}:e,m&&new m,f)}}return l||i?(a.setContentType("application/json",!1),S0(e)):e}],transformResponse:[function(e){const a=Zi(this,"transitional")||ao.transitional,r=a&&a.forcedJSONParsing,i=Zi(this,"responseType"),l=i==="json";if(F.isResponse(e)||F.isReadableStream(e))return e;if(e&&F.isString(e)&&(r&&!i||l)){const d=!(a&&a.silentJSONParsing)&&l;try{return JSON.parse(e,Zi(this,"parseReviver"))}catch(f){if(d)throw f.name==="SyntaxError"?Oe.from(f,Oe.ERR_BAD_RESPONSE,this,null,Zi(this,"response")):f}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:yn.classes.FormData,Blob:yn.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};F.forEach(["delete","get","head","post","put","patch","query"],o=>{ao.headers[o]={}});function bd(o,e){const a=this||ao,r=e||a,i=Cn.from(r.headers);let l=r.data;return F.forEach(o,function(d){l=d.call(a,l,i.normalize(),e?e.status:void 0)}),i.normalize(),l}function Op(o){return!!(o&&o.__CANCEL__)}let ro=class extends Oe{constructor(e,a,r){super(e??"canceled",Oe.ERR_CANCELED,a,r),this.name="CanceledError",this.__CANCEL__=!0}};function Lp(o,e,a){const r=a.config.validateStatus;!a.status||!r||r(a.status)?o(a):e(new Oe("Request failed with status code "+a.status,a.status>=400&&a.status<500?Oe.ERR_BAD_REQUEST:Oe.ERR_BAD_RESPONSE,a.config,a.request,a))}function w0(o){const e=/^([-+\w]{1,25}):(?:\/\/)?/.exec(o);return e&&e[1]||""}function C0(o,e){o=o||10;const a=new Array(o),r=new Array(o);let i=0,l=0,u;return e=e!==void 0?e:1e3,function(f){const g=Date.now(),m=r[l];u||(u=g),a[i]=f,r[i]=g;let b=l,v=0;for(;b!==i;)v+=a[b++],b=b%o;if(i=(i+1)%o,i===l&&(l=(l+1)%o),g-u{a=m,i=null,l&&(clearTimeout(l),l=null),o(...g)};return[(...g)=>{const m=Date.now(),b=m-a;b>=r?u(g,m):(i=g,l||(l=setTimeout(()=>{l=null,u(i)},r-b)))},()=>i&&u(i)]}const Ul=(o,e,a=3)=>{let r=0;const i=C0(50,250);return E0(l=>{if(!l||typeof l.loaded!="number")return;const u=l.loaded,d=l.lengthComputable?l.total:void 0,f=d!=null?Math.min(u,d):u,g=Math.max(0,f-r),m=i(g);r=Math.max(r,f);const b={loaded:f,total:d,progress:d?f/d:void 0,bytes:g,rate:m||void 0,estimated:m&&d?(d-f)/m:void 0,event:l,lengthComputable:d!=null,[e?"download":"upload"]:!0};o(b)},a)},Mp=(o,e)=>{const a=o!=null;return[r=>e[0]({lengthComputable:a,total:o,loaded:r}),e[1]]},$p=o=>(...e)=>F.asap(()=>o(...e)),_0=yn.hasStandardBrowserEnv?((o,e)=>a=>(a=new URL(a,yn.origin),o.protocol===a.protocol&&o.host===a.host&&(e||o.port===a.port)))(new URL(yn.origin),yn.navigator&&/(msie|trident)/i.test(yn.navigator.userAgent)):()=>!0,A0=yn.hasStandardBrowserEnv?{write(o,e,a,r,i,l,u){if(typeof document>"u")return;const d=[`${o}=${encodeURIComponent(e)}`];F.isNumber(a)&&d.push(`expires=${new Date(a).toUTCString()}`),F.isString(r)&&d.push(`path=${r}`),F.isString(i)&&d.push(`domain=${i}`),l===!0&&d.push("secure"),F.isString(u)&&d.push(`SameSite=${u}`),document.cookie=d.join("; ")},read(o){if(typeof document>"u")return null;const e=document.cookie.split(";");for(let a=0;ao instanceof Cn?{...o}:o;function di(o,e){e=e||{};const a=Object.create(null);Object.defineProperty(a,"hasOwnProperty",{__proto__:null,value:Object.prototype.hasOwnProperty,enumerable:!1,writable:!0,configurable:!0});function r(g,m,b,v){return F.isPlainObject(g)&&F.isPlainObject(m)?F.merge.call({caseless:v},g,m):F.isPlainObject(m)?F.merge({},m):F.isArray(m)?m.slice():m}function i(g,m,b,v){if(F.isUndefined(m)){if(!F.isUndefined(g))return r(void 0,g,b,v)}else return r(g,m,b,v)}function l(g,m){if(!F.isUndefined(m))return r(void 0,m)}function u(g,m){if(F.isUndefined(m)){if(!F.isUndefined(g))return r(void 0,g)}else return r(void 0,m)}function d(g,m,b){if(F.hasOwnProp(e,b))return r(g,m);if(F.hasOwnProp(o,b))return r(void 0,g)}const f={url:l,method:l,data:l,baseURL:u,transformRequest:u,transformResponse:u,paramsSerializer:u,timeout:u,timeoutMessage:u,withCredentials:u,withXSRFToken:u,adapter:u,responseType:u,xsrfCookieName:u,xsrfHeaderName:u,onUploadProgress:u,onDownloadProgress:u,decompress:u,maxContentLength:u,maxBodyLength:u,beforeRedirect:u,transport:u,httpAgent:u,httpsAgent:u,cancelToken:u,socketPath:u,allowedSocketPaths:u,responseEncoding:u,validateStatus:d,headers:(g,m,b)=>i(Ip(g),Ip(m),b,!0)};return F.forEach(Object.keys({...o,...e}),function(m){if(m==="__proto__"||m==="constructor"||m==="prototype")return;const b=F.hasOwnProp(f,m)?f[m]:i,v=F.hasOwnProp(o,m)?o[m]:void 0,S=F.hasOwnProp(e,m)?e[m]:void 0,E=b(v,S,m);F.isUndefined(E)&&b!==d||(a[m]=E)}),a}const R0=["content-type","content-length"];function k0(o,e,a){if(a!=="content-only"){o.set(e);return}Object.entries(e).forEach(([r,i])=>{R0.includes(r.toLowerCase())&&o.set(r,i)})}const D0=o=>encodeURIComponent(o).replace(/%([0-9A-F]{2})/gi,(e,a)=>String.fromCharCode(parseInt(a,16))),Hp=o=>{const e=di({},o),a=v=>F.hasOwnProp(e,v)?e[v]:void 0,r=a("data");let i=a("withXSRFToken");const l=a("xsrfHeaderName"),u=a("xsrfCookieName");let d=a("headers");const f=a("auth"),g=a("baseURL"),m=a("allowAbsoluteUrls"),b=a("url");if(e.headers=d=Cn.from(d),e.url=Rp(Np(g,b,m),o.params,o.paramsSerializer),f&&d.set("Authorization","Basic "+btoa((f.username||"")+":"+(f.password?D0(f.password):""))),F.isFormData(r)&&(yn.hasStandardBrowserEnv||yn.hasStandardBrowserWebWorkerEnv?d.setContentType(void 0):F.isFunction(r.getHeaders)&&k0(d,r.getHeaders(),a("formDataHeaderPolicy"))),yn.hasStandardBrowserEnv&&(F.isFunction(i)&&(i=i(e)),i===!0||i==null&&_0(e.url))){const S=l&&u&&A0.read(u);S&&d.set(l,S)}return e},O0=typeof XMLHttpRequest<"u"&&function(o){return new Promise(function(a,r){const i=Hp(o);let l=i.data;const u=Cn.from(i.headers).normalize();let{responseType:d,onUploadProgress:f,onDownloadProgress:g}=i,m,b,v,S,E;function A(){S&&S(),E&&E(),i.cancelToken&&i.cancelToken.unsubscribe(m),i.signal&&i.signal.removeEventListener("abort",m)}let T=new XMLHttpRequest;T.open(i.method.toUpperCase(),i.url,!0),T.timeout=i.timeout;function L(){if(!T)return;const R=Cn.from("getAllResponseHeaders"in T&&T.getAllResponseHeaders()),U={data:!d||d==="text"||d==="json"?T.responseText:T.response,status:T.status,statusText:T.statusText,headers:R,config:o,request:T};Lp(function(P){a(P),A()},function(P){r(P),A()},U),T=null}"onloadend"in T?T.onloadend=L:T.onreadystatechange=function(){!T||T.readyState!==4||T.status===0&&!(T.responseURL&&T.responseURL.startsWith("file:"))||setTimeout(L)},T.onabort=function(){T&&(r(new Oe("Request aborted",Oe.ECONNABORTED,o,T)),A(),T=null)},T.onerror=function(D){const U=D&&D.message?D.message:"Network Error",j=new Oe(U,Oe.ERR_NETWORK,o,T);j.event=D||null,r(j),A(),T=null},T.ontimeout=function(){let D=i.timeout?"timeout of "+i.timeout+"ms exceeded":"timeout exceeded";const U=i.transitional||pd;i.timeoutErrorMessage&&(D=i.timeoutErrorMessage),r(new Oe(D,U.clarifyTimeoutError?Oe.ETIMEDOUT:Oe.ECONNABORTED,o,T)),A(),T=null},l===void 0&&u.setContentType(null),"setRequestHeader"in T&&F.forEach(Ep(u),function(D,U){T.setRequestHeader(U,D)}),F.isUndefined(i.withCredentials)||(T.withCredentials=!!i.withCredentials),d&&d!=="json"&&(T.responseType=i.responseType),g&&([v,E]=Ul(g,!0),T.addEventListener("progress",v)),f&&T.upload&&([b,S]=Ul(f),T.upload.addEventListener("progress",b),T.upload.addEventListener("loadend",S)),(i.cancelToken||i.signal)&&(m=R=>{T&&(r(!R||R.type?new ro(null,o,T):R),T.abort(),A(),T=null)},i.cancelToken&&i.cancelToken.subscribe(m),i.signal&&(i.signal.aborted?m():i.signal.addEventListener("abort",m)));const M=w0(i.url);if(M&&!yn.protocols.includes(M)){r(new Oe("Unsupported protocol "+M+":",Oe.ERR_BAD_REQUEST,o));return}T.send(l||null)})},L0=(o,e)=>{if(o=o?o.filter(Boolean):[],!e&&!o.length)return;const a=new AbortController;let r=!1;const i=function(f){if(!r){r=!0,u();const g=f instanceof Error?f:this.reason;a.abort(g instanceof Oe?g:new ro(g instanceof Error?g.message:g))}};let l=e&&setTimeout(()=>{l=null,i(new Oe(`timeout of ${e}ms exceeded`,Oe.ETIMEDOUT))},e);const u=()=>{o&&(l&&clearTimeout(l),l=null,o.forEach(f=>{f.unsubscribe?f.unsubscribe(i):f.removeEventListener("abort",i)}),o=null)};o.forEach(f=>f.addEventListener("abort",i));const{signal:d}=a;return d.unsubscribe=()=>F.asap(u),d},M0=function*(o,e){let a=o.byteLength;if(a{const i=$0(o,e);let l=0,u,d=f=>{u||(u=!0,r&&r(f))};return new ReadableStream({async pull(f){try{const{done:g,value:m}=await i.next();if(g){d(),f.close();return}let b=m.byteLength;if(a){let v=l+=b;a(v)}f.enqueue(new Uint8Array(m))}catch(g){throw d(g),g}},cancel(f){return d(f),i.return()}},{highWaterMark:2})};function I0(o){if(!o||typeof o!="string"||!o.startsWith("data:"))return 0;const e=o.indexOf(",");if(e<0)return 0;const a=o.slice(5,e),r=o.slice(e+1);if(/;base64/i.test(a)){let u=r.length;const d=r.length;for(let S=0;S=48&&E<=57||E>=65&&E<=70||E>=97&&E<=102)&&(A>=48&&A<=57||A>=65&&A<=70||A>=97&&A<=102)&&(u-=2,S+=2)}let f=0,g=d-1;const m=S=>S>=2&&r.charCodeAt(S-2)===37&&r.charCodeAt(S-1)===51&&(r.charCodeAt(S)===68||r.charCodeAt(S)===100);g>=0&&(r.charCodeAt(g)===61?(f++,g--):m(g)&&(f++,g-=3)),f===1&&g>=0&&(r.charCodeAt(g)===61||m(g))&&f++;const v=Math.floor(u/4)*3-(f||0);return v>0?v:0}if(typeof Buffer<"u"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(r,"utf8");let l=0;for(let u=0,d=r.length;u=55296&&f<=56319&&u+1=56320&&g<=57343?(l+=4,u++):l+=3}else l+=3}return l}const vd="1.16.1",jp=64*1024,{isFunction:Bl}=F,Up=(o,...e)=>{try{return!!o(...e)}catch{return!1}},H0=o=>{const e=F.global!==void 0&&F.global!==null?F.global:globalThis,{ReadableStream:a,TextEncoder:r}=e;o=F.merge.call({skipUndefined:!0},{Request:e.Request,Response:e.Response},o);const{fetch:i,Request:l,Response:u}=o,d=i?Bl(i):typeof fetch=="function",f=Bl(l),g=Bl(u);if(!d)return!1;const m=d&&Bl(a),b=d&&(typeof r=="function"?(L=>M=>L.encode(M))(new r):async L=>new Uint8Array(await new l(L).arrayBuffer())),v=f&&m&&Up(()=>{let L=!1;const M=new l(yn.origin,{body:new a,method:"POST",get duplex(){return L=!0,"half"}}),R=M.headers.has("Content-Type");return M.body!=null&&M.body.cancel(),L&&!R}),S=g&&m&&Up(()=>F.isReadableStream(new u("").body)),E={stream:S&&(L=>L.body)};d&&["text","arrayBuffer","blob","formData","stream"].forEach(L=>{!E[L]&&(E[L]=(M,R)=>{let D=M&&M[L];if(D)return D.call(M);throw new Oe(`Response type '${L}' is not supported`,Oe.ERR_NOT_SUPPORT,R)})});const A=async L=>{if(L==null)return 0;if(F.isBlob(L))return L.size;if(F.isSpecCompliantForm(L))return(await new l(yn.origin,{method:"POST",body:L}).arrayBuffer()).byteLength;if(F.isArrayBufferView(L)||F.isArrayBuffer(L))return L.byteLength;if(F.isURLSearchParams(L)&&(L=L+""),F.isString(L))return(await b(L)).byteLength},T=async(L,M)=>{const R=F.toFiniteNumber(L.getContentLength());return R??A(M)};return async L=>{let{url:M,method:R,data:D,signal:U,cancelToken:j,timeout:P,onDownloadProgress:X,onUploadProgress:ge,responseType:Ee,headers:Ce,withCredentials:$e="same-origin",fetchOptions:Pe,maxContentLength:Xe,maxBodyLength:ht}=Hp(L);const Q=F.isNumber(Xe)&&Xe>-1,fe=F.isNumber(ht)&&ht>-1;let ye=i||fetch;Ee=Ee?(Ee+"").toLowerCase():"text";let te=L0([U,j&&j.toAbortSignal()],P),he=null;const x=te&&te.unsubscribe&&(()=>{te.unsubscribe()});let K;try{if(Q&&typeof M=="string"&&M.startsWith("data:")&&I0(M)>Xe)throw new Oe("maxContentLength size of "+Xe+" exceeded",Oe.ERR_BAD_RESPONSE,L,he);if(fe&&R!=="get"&&R!=="head"){const ve=await T(Ce,D);if(typeof ve=="number"&&isFinite(ve)&&ve>ht)throw new Oe("Request body larger than maxBodyLength limit",Oe.ERR_BAD_REQUEST,L,he)}if(ge&&v&&R!=="get"&&R!=="head"&&(K=await T(Ce,D))!==0){let ve=new l(M,{method:"POST",body:D,duplex:"half"}),He;if(F.isFormData(D)&&(He=ve.headers.get("content-type"))&&Ce.setContentType(He),ve.body){const[Ae,Et]=Mp(K,Ul($p(ge)));D=zp(ve.body,jp,Ae,Et)}}F.isString($e)||($e=$e?"include":"omit");const re=f&&"credentials"in l.prototype;if(F.isFormData(D)){const ve=Ce.getContentType();ve&&/^multipart\/form-data/i.test(ve)&&!/boundary=/i.test(ve)&&Ce.delete("content-type")}Ce.set("User-Agent","axios/"+vd,!1);const de={...Pe,signal:te,method:R.toUpperCase(),headers:Ep(Ce.normalize()),body:D,duplex:"half",credentials:re?$e:void 0};he=f&&new l(M,de);let se=await(f?ye(he,Pe):ye(M,de));if(Q){const ve=F.toFiniteNumber(se.headers.get("content-length"));if(ve!=null&&ve>Xe)throw new Oe("maxContentLength size of "+Xe+" exceeded",Oe.ERR_BAD_RESPONSE,L,he)}const me=S&&(Ee==="stream"||Ee==="response");if(S&&se.body&&(X||Q||me&&x)){const ve={};["status","statusText","headers"].forEach(ft=>{ve[ft]=se[ft]});const He=F.toFiniteNumber(se.headers.get("content-length")),[Ae,Et]=X&&Mp(He,Ul($p(X),!0))||[];let Rt=0;const _t=ft=>{if(Q&&(Rt=ft,Rt>Xe))throw new Oe("maxContentLength size of "+Xe+" exceeded",Oe.ERR_BAD_RESPONSE,L,he);Ae&&Ae(ft)};se=new u(zp(se.body,jp,_t,()=>{Et&&Et(),x&&x()}),ve)}Ee=Ee||"text";let Ne=await E[F.findKey(E,Ee)||"text"](se,L);if(Q&&!S&&!me){let ve;if(Ne!=null&&(typeof Ne.byteLength=="number"?ve=Ne.byteLength:typeof Ne.size=="number"?ve=Ne.size:typeof Ne=="string"&&(ve=typeof r=="function"?new r().encode(Ne).byteLength:Ne.length)),typeof ve=="number"&&ve>Xe)throw new Oe("maxContentLength size of "+Xe+" exceeded",Oe.ERR_BAD_RESPONSE,L,he)}return!me&&x&&x(),await new Promise((ve,He)=>{Lp(ve,He,{data:Ne,headers:Cn.from(se.headers),status:se.status,statusText:se.statusText,config:L,request:he})})}catch(re){if(x&&x(),te&&te.aborted&&te.reason instanceof Oe){const de=te.reason;throw de.config=L,he&&(de.request=he),re!==de&&(de.cause=re),de}throw re&&re.name==="TypeError"&&/Load failed|fetch/i.test(re.message)?Object.assign(new Oe("Network Error",Oe.ERR_NETWORK,L,he,re&&re.response),{cause:re.cause||re}):Oe.from(re,re&&re.code,L,he,re&&re.response)}}},z0=new Map,Bp=o=>{let e=o&&o.env||{};const{fetch:a,Request:r,Response:i}=e,l=[r,i,a];let u=l.length,d=u,f,g,m=z0;for(;d--;)f=l[d],g=m.get(f),g===void 0&&m.set(f,g=d?new Map:H0(e)),m=g;return g};Bp();const Sd={http:c0,xhr:O0,fetch:{get:Bp}};F.forEach(Sd,(o,e)=>{if(o){try{Object.defineProperty(o,"name",{__proto__:null,value:e})}catch{}Object.defineProperty(o,"adapterName",{__proto__:null,value:e})}});const Pp=o=>`- ${o}`,j0=o=>F.isFunction(o)||o===null||o===!1;function U0(o,e){o=F.isArray(o)?o:[o];const{length:a}=o;let r,i;const l={};for(let u=0;u`adapter ${f} `+(g===!1?"is not supported by the environment":"is not available in the build"));let d=a?u.length>1?`since : +`+c.stack}}var Dn=Object.prototype.hasOwnProperty,jt=o.unstable_scheduleCallback,On=o.unstable_cancelCallback,ea=o.unstable_shouldYield,Ua=o.unstable_requestPaint,Kt=o.unstable_now,Dr=o.unstable_getCurrentPriorityLevel,er=o.unstable_ImmediatePriority,bn=o.unstable_UserBlockingPriority,tn=o.unstable_NormalPriority,et=o.unstable_LowPriority,ta=o.unstable_IdlePriority,En=o.log,tr=o.unstable_setDisableYieldValue,Ea=null,nn=null;function _n(t){if(typeof En=="function"&&tr(t),nn&&typeof nn.setStrictMode=="function")try{nn.setStrictMode(Ea,t)}catch{}}var q=Math.clz32?Math.clz32:Z,ce=Math.log,le=Math.LN2;function Z(t){return t>>>=0,t===0?32:31-(ce(t)/le|0)|0}var be=256,ve=262144,Re=4194304;function xe(t){var n=t&42;if(n!==0)return n;switch(t&-t){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return t&261888;case 262144:case 524288:case 1048576:case 2097152:return t&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return t&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return t}}function je(t,n,s){var c=t.pendingLanes;if(c===0)return 0;var h=0,p=t.suspendedLanes,w=t.pingedLanes;t=t.warmLanes;var k=c&134217727;return k!==0?(c=k&~p,c!==0?h=xe(c):(w&=k,w!==0?h=xe(w):s||(s=k&~t,s!==0&&(h=xe(s))))):(k=c&~p,k!==0?h=xe(k):w!==0?h=xe(w):s||(s=c&~t,s!==0&&(h=xe(s)))),h===0?0:n!==0&&n!==h&&(n&p)===0&&(p=h&-h,s=n&-n,p>=s||p===32&&(s&4194048)!==0)?n:h}function ze(t,n){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&n)===0}function Le(t,n){switch(t){case 1:case 2:case 4:case 8:case 64:return n+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return n+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function ke(){var t=Re;return Re<<=1,(Re&62914560)===0&&(Re=4194304),t}function We(t){for(var n=[],s=0;31>s;s++)n.push(t);return n}function Fe(t,n){t.pendingLanes|=n,n!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function _e(t,n,s,c,h,p){var w=t.pendingLanes;t.pendingLanes=s,t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0,t.expiredLanes&=s,t.entangledLanes&=s,t.errorRecoveryDisabledLanes&=s,t.shellSuspendCounter=0;var k=t.entanglements,z=t.expirationTimes,Y=t.hiddenUpdates;for(s=w&~s;0"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var vf=/[\n"\\]/g;function $n(t){return t.replace(vf,function(n){return"\\"+n.charCodeAt(0).toString(16)+" "})}function ds(t,n,s,c,h,p,w,k){t.name="",w!=null&&typeof w!="function"&&typeof w!="symbol"&&typeof w!="boolean"?t.type=w:t.removeAttribute("type"),n!=null?w==="number"?(n===0&&t.value===""||t.value!=n)&&(t.value=""+Sn(n)):t.value!==""+Sn(n)&&(t.value=""+Sn(n)):w!=="submit"&&w!=="reset"||t.removeAttribute("value"),n!=null?ar(t,w,Sn(n)):s!=null?ar(t,w,Sn(s)):c!=null&&t.removeAttribute("value"),h==null&&p!=null&&(t.defaultChecked=!!p),h!=null&&(t.checked=h&&typeof h!="function"&&typeof h!="symbol"),k!=null&&typeof k!="function"&&typeof k!="symbol"&&typeof k!="boolean"?t.name=""+Sn(k):t.removeAttribute("name")}function Si(t,n,s,c,h,p,w,k){if(p!=null&&typeof p!="function"&&typeof p!="symbol"&&typeof p!="boolean"&&(t.type=p),n!=null||s!=null){if(!(p!=="submit"&&p!=="reset"||n!=null)){Do(t);return}s=s!=null?""+Sn(s):"",n=n!=null?""+Sn(n):s,k||n===t.value||(t.value=n),t.defaultValue=n}c=c??h,c=typeof c!="function"&&typeof c!="symbol"&&!!c,t.checked=k?t.checked:!!c,t.defaultChecked=!!c,w!=null&&typeof w!="function"&&typeof w!="symbol"&&typeof w!="boolean"&&(t.name=w),Do(t)}function ar(t,n,s){n==="number"&&Nr(t.ownerDocument)===t||t.defaultValue===""+s||(t.defaultValue=""+s)}function Ir(t,n,s,c){if(t=t.options,n){n={};for(var h=0;h"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),No=!1;if(xa)try{var Ci={};Object.defineProperty(Ci,"passive",{get:function(){No=!0}}),window.addEventListener("test",Ci,Ci),window.removeEventListener("test",Ci,Ci)}catch{No=!1}var qa=null,Io=null,hs=null;function Oc(){if(hs)return hs;var t,n=Io,s=n.length,c,h="value"in qa?qa.value:qa.textContent,p=h.length;for(t=0;t=ne),Ve=" ",ot=!1;function pt(t,n){switch(t){case"keyup":return O.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Nt(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Ra=!1;function Hf(t,n){switch(t){case"compositionend":return Nt(n);case"keypress":return n.which!==32?null:(ot=!0,Ve);case"textInput":return t=n.data,t===Ve&&ot?null:t;default:return null}}function zc(t,n){if(Ra)return t==="compositionend"||!I&&pt(t,n)?(t=Oc(),hs=Io=qa=null,Ra=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1=n)return{node:s,offset:n-t};t=c}e:{for(;s;){if(s.nextSibling){s=s.nextSibling;break e}s=s.parentNode}s=void 0}s=py(s)}}function yy(t,n){return t&&n?t===n?!0:t&&t.nodeType===3?!1:n&&n.nodeType===3?yy(t,n.parentNode):"contains"in t?t.contains(n):t.compareDocumentPosition?!!(t.compareDocumentPosition(n)&16):!1:!1}function by(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var n=Nr(t.document);n instanceof t.HTMLIFrameElement;){try{var s=typeof n.contentWindow.location.href=="string"}catch{s=!1}if(s)t=n.contentWindow;else break;n=Nr(t.document)}return n}function Pf(t){var n=t&&t.nodeName&&t.nodeName.toLowerCase();return n&&(n==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||n==="textarea"||t.contentEditable==="true")}var OA=xa&&"documentMode"in document&&11>=document.documentMode,ys=null,qf=null,Fo=null,Gf=!1;function vy(t,n,s){var c=s.window===s?s.document:s.nodeType===9?s:s.ownerDocument;Gf||ys==null||ys!==Nr(c)||(c=ys,"selectionStart"in c&&Pf(c)?c={start:c.selectionStart,end:c.selectionEnd}:(c=(c.ownerDocument&&c.ownerDocument.defaultView||window).getSelection(),c={anchorNode:c.anchorNode,anchorOffset:c.anchorOffset,focusNode:c.focusNode,focusOffset:c.focusOffset}),Fo&&Vo(Fo,c)||(Fo=c,c=Du(qf,"onSelect"),0>=w,h-=w,Ga=1<<32-q(n)+h|s<Qe?(rt=Ie,Ie=null):rt=Ie.sibling;var yt=J(V,Ie,W[Qe],oe);if(yt===null){Ie===null&&(Ie=rt);break}t&&Ie&&yt.alternate===null&&n(V,Ie),G=p(yt,G,Qe),mt===null?qe=yt:mt.sibling=yt,mt=yt,Ie=rt}if(Qe===W.length)return s(V,Ie),lt&&or(V,Qe),qe;if(Ie===null){for(;QeQe?(rt=Ie,Ie=null):rt=Ie.sibling;var li=J(V,Ie,yt.value,oe);if(li===null){Ie===null&&(Ie=rt);break}t&&Ie&&li.alternate===null&&n(V,Ie),G=p(li,G,Qe),mt===null?qe=li:mt.sibling=li,mt=li,Ie=rt}if(yt.done)return s(V,Ie),lt&&or(V,Qe),qe;if(Ie===null){for(;!yt.done;Qe++,yt=W.next())yt=ue(V,yt.value,oe),yt!==null&&(G=p(yt,G,Qe),mt===null?qe=yt:mt.sibling=yt,mt=yt);return lt&&or(V,Qe),qe}for(Ie=c(Ie);!yt.done;Qe++,yt=W.next())yt=ee(Ie,V,Qe,yt.value,oe),yt!==null&&(t&&yt.alternate!==null&&Ie.delete(yt.key===null?Qe:yt.key),G=p(yt,G,Qe),mt===null?qe=yt:mt.sibling=yt,mt=yt);return t&&Ie.forEach(function(Jx){return n(V,Jx)}),lt&&or(V,Qe),qe}function Rt(V,G,W,oe){if(typeof W=="object"&&W!==null&&W.type===A&&W.key===null&&(W=W.props.children),typeof W=="object"&&W!==null){switch(W.$$typeof){case S:e:{for(var qe=W.key;G!==null;){if(G.key===qe){if(qe=W.type,qe===A){if(G.tag===7){s(V,G.sibling),oe=h(G,W.props.children),oe.return=V,V=oe;break e}}else if(G.elementType===qe||typeof qe=="object"&&qe!==null&&qe.$$typeof===X&&zi(qe)===G.type){s(V,G.sibling),oe=h(G,W.props),Qo(oe,W),oe.return=V,V=oe;break e}s(V,G);break}else n(V,G);G=G.sibling}W.type===A?(oe=Mi(W.props.children,V.mode,oe,W.key),oe.return=V,V=oe):(oe=Kc(W.type,W.key,W.props,null,V.mode,oe),Qo(oe,W),oe.return=V,V=oe)}return w(V);case E:e:{for(qe=W.key;G!==null;){if(G.key===qe)if(G.tag===4&&G.stateNode.containerInfo===W.containerInfo&&G.stateNode.implementation===W.implementation){s(V,G.sibling),oe=h(G,W.children||[]),oe.return=V,V=oe;break e}else{s(V,G);break}else n(V,G);G=G.sibling}oe=Jf(W,V.mode,oe),oe.return=V,V=oe}return w(V);case X:return W=zi(W),Rt(V,G,W,oe)}if(ht(W))return De(V,G,W,oe);if($e(W)){if(qe=$e(W),typeof qe!="function")throw Error(r(150));return W=qe.call(W),Ge(V,G,W,oe)}if(typeof W.then=="function")return Rt(V,G,eu(W),oe);if(W.$$typeof===R)return Rt(V,G,Xc(V,W),oe);tu(V,W)}return typeof W=="string"&&W!==""||typeof W=="number"||typeof W=="bigint"?(W=""+W,G!==null&&G.tag===6?(s(V,G.sibling),oe=h(G,W),oe.return=V,V=oe):(s(V,G),oe=Xf(W,V.mode,oe),oe.return=V,V=oe),w(V)):s(V,G)}return function(V,G,W,oe){try{Jo=0;var qe=Rt(V,G,W,oe);return Rs=null,qe}catch(Ie){if(Ie===Ts||Ie===Qc)throw Ie;var mt=Vn(29,Ie,null,V.mode);return mt.lanes=oe,mt.return=V,mt}}}var Ui=Py(!0),qy=Py(!1),Vr=!1;function ch(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function uh(t,n){t=t.updateQueue,n.updateQueue===t&&(n.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Fr(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Kr(t,n,s){var c=t.updateQueue;if(c===null)return null;if(c=c.shared,(vt&2)!==0){var h=c.pending;return h===null?n.next=n:(n.next=h.next,h.next=n),c.pending=n,n=Fc(t),xy(t,null,s),n}return Vc(t,c,n,s),Fc(t)}function Zo(t,n,s){if(n=n.updateQueue,n!==null&&(n=n.shared,(s&4194048)!==0)){var c=n.lanes;c&=t.pendingLanes,s|=c,n.lanes=s,Ue(t,s)}}function dh(t,n){var s=t.updateQueue,c=t.alternate;if(c!==null&&(c=c.updateQueue,s===c)){var h=null,p=null;if(s=s.firstBaseUpdate,s!==null){do{var w={lane:s.lane,tag:s.tag,payload:s.payload,callback:null,next:null};p===null?h=p=w:p=p.next=w,s=s.next}while(s!==null);p===null?h=p=n:p=p.next=n}else h=p=n;s={baseState:c.baseState,firstBaseUpdate:h,lastBaseUpdate:p,shared:c.shared,callbacks:c.callbacks},t.updateQueue=s;return}t=s.lastBaseUpdate,t===null?s.firstBaseUpdate=n:t.next=n,s.lastBaseUpdate=n}var fh=!1;function el(){if(fh){var t=xs;if(t!==null)throw t}}function tl(t,n,s,c){fh=!1;var h=t.updateQueue;Vr=!1;var p=h.firstBaseUpdate,w=h.lastBaseUpdate,k=h.shared.pending;if(k!==null){h.shared.pending=null;var z=k,Y=z.next;z.next=null,w===null?p=Y:w.next=Y,w=z;var ae=t.alternate;ae!==null&&(ae=ae.updateQueue,k=ae.lastBaseUpdate,k!==w&&(k===null?ae.firstBaseUpdate=Y:k.next=Y,ae.lastBaseUpdate=z))}if(p!==null){var ue=h.baseState;w=0,ae=Y=z=null,k=p;do{var J=k.lane&-536870913,ee=J!==k.lane;if(ee?(at&J)===J:(c&J)===J){J!==0&&J===As&&(fh=!0),ae!==null&&(ae=ae.next={lane:0,tag:k.tag,payload:k.payload,callback:null,next:null});e:{var De=t,Ge=k;J=n;var Rt=s;switch(Ge.tag){case 1:if(De=Ge.payload,typeof De=="function"){ue=De.call(Rt,ue,J);break e}ue=De;break e;case 3:De.flags=De.flags&-65537|128;case 0:if(De=Ge.payload,J=typeof De=="function"?De.call(Rt,ue,J):De,J==null)break e;ue=b({},ue,J);break e;case 2:Vr=!0}}J=k.callback,J!==null&&(t.flags|=64,ee&&(t.flags|=8192),ee=h.callbacks,ee===null?h.callbacks=[J]:ee.push(J))}else ee={lane:J,tag:k.tag,payload:k.payload,callback:k.callback,next:null},ae===null?(Y=ae=ee,z=ue):ae=ae.next=ee,w|=J;if(k=k.next,k===null){if(k=h.shared.pending,k===null)break;ee=k,k=ee.next,ee.next=null,h.lastBaseUpdate=ee,h.shared.pending=null}}while(!0);ae===null&&(z=ue),h.baseState=z,h.firstBaseUpdate=Y,h.lastBaseUpdate=ae,p===null&&(h.shared.lanes=0),Qr|=w,t.lanes=w,t.memoizedState=ue}}function Gy(t,n){if(typeof t!="function")throw Error(r(191,t));t.call(n)}function Vy(t,n){var s=t.callbacks;if(s!==null)for(t.callbacks=null,t=0;tp?p:8;var w=Q.T,k={};Q.T=k,Oh(t,!1,n,s);try{var z=h(),Y=Q.S;if(Y!==null&&Y(k,z),z!==null&&typeof z=="object"&&typeof z.then=="function"){var ae=UA(z,c);rl(t,n,ae,Xn(t))}else rl(t,n,c,Xn(t))}catch(ue){rl(t,n,{then:function(){},status:"rejected",reason:ue},Xn())}finally{fe.p=p,w!==null&&k.types!==null&&(w.types=k.types),Q.T=w}}function FA(){}function kh(t,n,s,c){if(t.tag!==5)throw Error(r(476));var h=Eb(t).queue;Cb(t,h,n,ye,s===null?FA:function(){return _b(t),s(c)})}function Eb(t){var n=t.memoizedState;if(n!==null)return n;n={memoizedState:ye,baseState:ye,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:dr,lastRenderedState:ye},next:null};var s={};return n.next={memoizedState:s,baseState:s,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:dr,lastRenderedState:s},next:null},t.memoizedState=n,t=t.alternate,t!==null&&(t.memoizedState=n),n}function _b(t){var n=Eb(t);n.next===null&&(n=t.alternate.memoizedState),rl(t,n.next.queue,{},Xn())}function Dh(){return hn(wl)}function Ab(){return Vt().memoizedState}function xb(){return Vt().memoizedState}function KA(t){for(var n=t.return;n!==null;){switch(n.tag){case 24:case 3:var s=Xn();t=Fr(s);var c=Kr(n,t,s);c!==null&&(jn(c,n,s),Zo(c,n,s)),n={cache:ih()},t.payload=n;return}n=n.return}}function WA(t,n,s){var c=Xn();s={lane:c,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null},du(t)?Rb(n,s):(s=Wf(t,n,s,c),s!==null&&(jn(s,t,c),kb(s,n,c)))}function Tb(t,n,s){var c=Xn();rl(t,n,s,c)}function rl(t,n,s,c){var h={lane:c,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null};if(du(t))Rb(n,h);else{var p=t.alternate;if(t.lanes===0&&(p===null||p.lanes===0)&&(p=n.lastRenderedReducer,p!==null))try{var w=n.lastRenderedState,k=p(w,s);if(h.hasEagerState=!0,h.eagerState=k,Gn(k,w))return Vc(t,n,h,0),Dt===null&&Gc(),!1}catch{}if(s=Wf(t,n,h,c),s!==null)return jn(s,t,c),kb(s,n,c),!0}return!1}function Oh(t,n,s,c){if(c={lane:2,revertLane:cg(),gesture:null,action:c,hasEagerState:!1,eagerState:null,next:null},du(t)){if(n)throw Error(r(479))}else n=Wf(t,s,c,2),n!==null&&jn(n,t,2)}function du(t){var n=t.alternate;return t===Je||n!==null&&n===Je}function Rb(t,n){Ds=ru=!0;var s=t.pending;s===null?n.next=n:(n.next=s.next,s.next=n),t.pending=n}function kb(t,n,s){if((s&4194048)!==0){var c=n.lanes;c&=t.pendingLanes,s|=c,n.lanes=s,Ue(t,s)}}var il={readContext:hn,use:ou,useCallback:Ut,useContext:Ut,useEffect:Ut,useImperativeHandle:Ut,useLayoutEffect:Ut,useInsertionEffect:Ut,useMemo:Ut,useReducer:Ut,useRef:Ut,useState:Ut,useDebugValue:Ut,useDeferredValue:Ut,useTransition:Ut,useSyncExternalStore:Ut,useId:Ut,useHostTransitionStatus:Ut,useFormState:Ut,useActionState:Ut,useOptimistic:Ut,useMemoCache:Ut,useCacheRefresh:Ut};il.useEffectEvent=Ut;var Db={readContext:hn,use:ou,useCallback:function(t,n){return An().memoizedState=[t,n===void 0?null:n],t},useContext:hn,useEffect:hb,useImperativeHandle:function(t,n,s){s=s!=null?s.concat([t]):null,cu(4194308,4,yb.bind(null,n,t),s)},useLayoutEffect:function(t,n){return cu(4194308,4,t,n)},useInsertionEffect:function(t,n){cu(4,2,t,n)},useMemo:function(t,n){var s=An();n=n===void 0?null:n;var c=t();if(Bi){_n(!0);try{t()}finally{_n(!1)}}return s.memoizedState=[c,n],c},useReducer:function(t,n,s){var c=An();if(s!==void 0){var h=s(n);if(Bi){_n(!0);try{s(n)}finally{_n(!1)}}}else h=n;return c.memoizedState=c.baseState=h,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:h},c.queue=t,t=t.dispatch=WA.bind(null,Je,t),[c.memoizedState,t]},useRef:function(t){var n=An();return t={current:t},n.memoizedState=t},useState:function(t){t=_h(t);var n=t.queue,s=Tb.bind(null,Je,n);return n.dispatch=s,[t.memoizedState,s]},useDebugValue:Th,useDeferredValue:function(t,n){var s=An();return Rh(s,t,n)},useTransition:function(){var t=_h(!1);return t=Cb.bind(null,Je,t.queue,!0,!1),An().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,n,s){var c=Je,h=An();if(lt){if(s===void 0)throw Error(r(407));s=s()}else{if(s=n(),Dt===null)throw Error(r(349));(at&127)!==0||Jy(c,n,s)}h.memoizedState=s;var p={value:s,getSnapshot:n};return h.queue=p,hb(Zy.bind(null,c,p,t),[t]),c.flags|=2048,Ls(9,{destroy:void 0},Qy.bind(null,c,p,s,n),null),s},useId:function(){var t=An(),n=Dt.identifierPrefix;if(lt){var s=Va,c=Ga;s=(c&~(1<<32-q(c)-1)).toString(32)+s,n="_"+n+"R_"+s,s=iu++,0<\/script>",p=p.removeChild(p.firstChild);break;case"select":p=typeof c.is=="string"?w.createElement("select",{is:c.is}):w.createElement("select"),c.multiple?p.multiple=!0:c.size&&(p.size=c.size);break;default:p=typeof c.is=="string"?w.createElement(h,{is:c.is}):w.createElement(h)}}p[an]=n,p[vn]=c;e:for(w=n.child;w!==null;){if(w.tag===5||w.tag===6)p.appendChild(w.stateNode);else if(w.tag!==4&&w.tag!==27&&w.child!==null){w.child.return=w,w=w.child;continue}if(w===n)break e;for(;w.sibling===null;){if(w.return===null||w.return===n)break e;w=w.return}w.sibling.return=w.return,w=w.sibling}n.stateNode=p;e:switch(pn(p,h,c),h){case"button":case"input":case"select":case"textarea":c=!!c.autoFocus;break e;case"img":c=!0;break e;default:c=!1}c&&hr(n)}}return Lt(n),Vh(n,n.type,t===null?null:t.memoizedProps,n.pendingProps,s),null;case 6:if(t&&n.stateNode!=null)t.memoizedProps!==c&&hr(n);else{if(typeof c!="string"&&n.stateNode===null)throw Error(r(166));if(t=me.current,Es(n)){if(t=n.stateNode,s=n.memoizedProps,c=null,h=fn,h!==null)switch(h.tag){case 27:case 5:c=h.memoizedProps}t[an]=n,t=!!(t.nodeValue===s||c!==null&&c.suppressHydrationWarning===!0||Yv(t.nodeValue,s)),t||qr(n,!0)}else t=Ou(t).createTextNode(c),t[an]=n,n.stateNode=t}return Lt(n),null;case 31:if(s=n.memoizedState,t===null||t.memoizedState!==null){if(c=Es(n),s!==null){if(t===null){if(!c)throw Error(r(318));if(t=n.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(r(557));t[an]=n}else $i(),(n.flags&128)===0&&(n.memoizedState=null),n.flags|=4;Lt(n),t=!1}else s=th(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=s),t=!0;if(!t)return n.flags&256?(Kn(n),n):(Kn(n),null);if((n.flags&128)!==0)throw Error(r(558))}return Lt(n),null;case 13:if(c=n.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(h=Es(n),c!==null&&c.dehydrated!==null){if(t===null){if(!h)throw Error(r(318));if(h=n.memoizedState,h=h!==null?h.dehydrated:null,!h)throw Error(r(317));h[an]=n}else $i(),(n.flags&128)===0&&(n.memoizedState=null),n.flags|=4;Lt(n),h=!1}else h=th(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=h),h=!0;if(!h)return n.flags&256?(Kn(n),n):(Kn(n),null)}return Kn(n),(n.flags&128)!==0?(n.lanes=s,n):(s=c!==null,t=t!==null&&t.memoizedState!==null,s&&(c=n.child,h=null,c.alternate!==null&&c.alternate.memoizedState!==null&&c.alternate.memoizedState.cachePool!==null&&(h=c.alternate.memoizedState.cachePool.pool),p=null,c.memoizedState!==null&&c.memoizedState.cachePool!==null&&(p=c.memoizedState.cachePool.pool),p!==h&&(c.flags|=2048)),s!==t&&s&&(n.child.flags|=8192),mu(n,n.updateQueue),Lt(n),null);case 4:return He(),t===null&&hg(n.stateNode.containerInfo),Lt(n),null;case 10:return cr(n.type),Lt(n),null;case 19:if(K(Gt),c=n.memoizedState,c===null)return Lt(n),null;if(h=(n.flags&128)!==0,p=c.rendering,p===null)if(h)ol(c,!1);else{if(Bt!==0||t!==null&&(t.flags&128)!==0)for(t=n.child;t!==null;){if(p=au(t),p!==null){for(n.flags|=128,ol(c,!1),t=p.updateQueue,n.updateQueue=t,mu(n,t),n.subtreeFlags=0,t=s,s=n.child;s!==null;)Ty(s,t),s=s.sibling;return re(Gt,Gt.current&1|2),lt&&or(n,c.treeForkCount),n.child}t=t.sibling}c.tail!==null&&Kt()>wu&&(n.flags|=128,h=!0,ol(c,!1),n.lanes=4194304)}else{if(!h)if(t=au(p),t!==null){if(n.flags|=128,h=!0,t=t.updateQueue,n.updateQueue=t,mu(n,t),ol(c,!0),c.tail===null&&c.tailMode==="hidden"&&!p.alternate&&!lt)return Lt(n),null}else 2*Kt()-c.renderingStartTime>wu&&s!==536870912&&(n.flags|=128,h=!0,ol(c,!1),n.lanes=4194304);c.isBackwards?(p.sibling=n.child,n.child=p):(t=c.last,t!==null?t.sibling=p:n.child=p,c.last=p)}return c.tail!==null?(t=c.tail,c.rendering=t,c.tail=t.sibling,c.renderingStartTime=Kt(),t.sibling=null,s=Gt.current,re(Gt,h?s&1|2:s&1),lt&&or(n,c.treeForkCount),t):(Lt(n),null);case 22:case 23:return Kn(n),gh(),c=n.memoizedState!==null,t!==null?t.memoizedState!==null!==c&&(n.flags|=8192):c&&(n.flags|=8192),c?(s&536870912)!==0&&(n.flags&128)===0&&(Lt(n),n.subtreeFlags&6&&(n.flags|=8192)):Lt(n),s=n.updateQueue,s!==null&&mu(n,s.retryQueue),s=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(s=t.memoizedState.cachePool.pool),c=null,n.memoizedState!==null&&n.memoizedState.cachePool!==null&&(c=n.memoizedState.cachePool.pool),c!==s&&(n.flags|=2048),t!==null&&K(Hi),null;case 24:return s=null,t!==null&&(s=t.memoizedState.cache),n.memoizedState.cache!==s&&(n.flags|=2048),cr(Xt),Lt(n),null;case 25:return null;case 30:return null}throw Error(r(156,n.tag))}function ZA(t,n){switch(Zf(n),n.tag){case 1:return t=n.flags,t&65536?(n.flags=t&-65537|128,n):null;case 3:return cr(Xt),He(),t=n.flags,(t&65536)!==0&&(t&128)===0?(n.flags=t&-65537|128,n):null;case 26:case 27:case 5:return Et(n),null;case 31:if(n.memoizedState!==null){if(Kn(n),n.alternate===null)throw Error(r(340));$i()}return t=n.flags,t&65536?(n.flags=t&-65537|128,n):null;case 13:if(Kn(n),t=n.memoizedState,t!==null&&t.dehydrated!==null){if(n.alternate===null)throw Error(r(340));$i()}return t=n.flags,t&65536?(n.flags=t&-65537|128,n):null;case 19:return K(Gt),null;case 4:return He(),null;case 10:return cr(n.type),null;case 22:case 23:return Kn(n),gh(),t!==null&&K(Hi),t=n.flags,t&65536?(n.flags=t&-65537|128,n):null;case 24:return cr(Xt),null;case 25:return null;default:return null}}function ev(t,n){switch(Zf(n),n.tag){case 3:cr(Xt),He();break;case 26:case 27:case 5:Et(n);break;case 4:He();break;case 31:n.memoizedState!==null&&Kn(n);break;case 13:Kn(n);break;case 19:K(Gt);break;case 10:cr(n.type);break;case 22:case 23:Kn(n),gh(),t!==null&&K(Hi);break;case 24:cr(Xt)}}function ll(t,n){try{var s=n.updateQueue,c=s!==null?s.lastEffect:null;if(c!==null){var h=c.next;s=h;do{if((s.tag&t)===t){c=void 0;var p=s.create,w=s.inst;c=p(),w.destroy=c}s=s.next}while(s!==h)}}catch(k){Ct(n,n.return,k)}}function Xr(t,n,s){try{var c=n.updateQueue,h=c!==null?c.lastEffect:null;if(h!==null){var p=h.next;c=p;do{if((c.tag&t)===t){var w=c.inst,k=w.destroy;if(k!==void 0){w.destroy=void 0,h=n;var z=s,Y=k;try{Y()}catch(ae){Ct(h,z,ae)}}}c=c.next}while(c!==p)}}catch(ae){Ct(n,n.return,ae)}}function tv(t){var n=t.updateQueue;if(n!==null){var s=t.stateNode;try{Vy(n,s)}catch(c){Ct(t,t.return,c)}}}function nv(t,n,s){s.props=Pi(t.type,t.memoizedProps),s.state=t.memoizedState;try{s.componentWillUnmount()}catch(c){Ct(t,n,c)}}function cl(t,n){try{var s=t.ref;if(s!==null){switch(t.tag){case 26:case 27:case 5:var c=t.stateNode;break;case 30:c=t.stateNode;break;default:c=t.stateNode}typeof s=="function"?t.refCleanup=s(c):s.current=c}}catch(h){Ct(t,n,h)}}function Fa(t,n){var s=t.ref,c=t.refCleanup;if(s!==null)if(typeof c=="function")try{c()}catch(h){Ct(t,n,h)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof s=="function")try{s(null)}catch(h){Ct(t,n,h)}else s.current=null}function av(t){var n=t.type,s=t.memoizedProps,c=t.stateNode;try{e:switch(n){case"button":case"input":case"select":case"textarea":s.autoFocus&&c.focus();break e;case"img":s.src?c.src=s.src:s.srcSet&&(c.srcset=s.srcSet)}}catch(h){Ct(t,t.return,h)}}function Fh(t,n,s){try{var c=t.stateNode;wx(c,t.type,s,n),c[vn]=n}catch(h){Ct(t,t.return,h)}}function rv(t){return t.tag===5||t.tag===3||t.tag===26||t.tag===27&&ai(t.type)||t.tag===4}function Kh(t){e:for(;;){for(;t.sibling===null;){if(t.return===null||rv(t.return))return null;t=t.return}for(t.sibling.return=t.return,t=t.sibling;t.tag!==5&&t.tag!==6&&t.tag!==18;){if(t.tag===27&&ai(t.type)||t.flags&2||t.child===null||t.tag===4)continue e;t.child.return=t,t=t.child}if(!(t.flags&2))return t.stateNode}}function Wh(t,n,s){var c=t.tag;if(c===5||c===6)t=t.stateNode,n?(s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s).insertBefore(t,n):(n=s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s,n.appendChild(t),s=s._reactRootContainer,s!=null||n.onclick!==null||(n.onclick=Aa));else if(c!==4&&(c===27&&ai(t.type)&&(s=t.stateNode,n=null),t=t.child,t!==null))for(Wh(t,n,s),t=t.sibling;t!==null;)Wh(t,n,s),t=t.sibling}function yu(t,n,s){var c=t.tag;if(c===5||c===6)t=t.stateNode,n?s.insertBefore(t,n):s.appendChild(t);else if(c!==4&&(c===27&&ai(t.type)&&(s=t.stateNode),t=t.child,t!==null))for(yu(t,n,s),t=t.sibling;t!==null;)yu(t,n,s),t=t.sibling}function iv(t){var n=t.stateNode,s=t.memoizedProps;try{for(var c=t.type,h=n.attributes;h.length;)n.removeAttributeNode(h[0]);pn(n,c,s),n[an]=t,n[vn]=s}catch(p){Ct(t,t.return,p)}}var gr=!1,Zt=!1,Yh=!1,sv=typeof WeakSet=="function"?WeakSet:Set,cn=null;function ex(t,n){if(t=t.containerInfo,mg=zu,t=by(t),Pf(t)){if("selectionStart"in t)var s={start:t.selectionStart,end:t.selectionEnd};else e:{s=(s=t.ownerDocument)&&s.defaultView||window;var c=s.getSelection&&s.getSelection();if(c&&c.rangeCount!==0){s=c.anchorNode;var h=c.anchorOffset,p=c.focusNode;c=c.focusOffset;try{s.nodeType,p.nodeType}catch{s=null;break e}var w=0,k=-1,z=-1,Y=0,ae=0,ue=t,J=null;t:for(;;){for(var ee;ue!==s||h!==0&&ue.nodeType!==3||(k=w+h),ue!==p||c!==0&&ue.nodeType!==3||(z=w+c),ue.nodeType===3&&(w+=ue.nodeValue.length),(ee=ue.firstChild)!==null;)J=ue,ue=ee;for(;;){if(ue===t)break t;if(J===s&&++Y===h&&(k=w),J===p&&++ae===c&&(z=w),(ee=ue.nextSibling)!==null)break;ue=J,J=ue.parentNode}ue=ee}s=k===-1||z===-1?null:{start:k,end:z}}else s=null}s=s||{start:0,end:0}}else s=null;for(yg={focusedElem:t,selectionRange:s},zu=!1,cn=n;cn!==null;)if(n=cn,t=n.child,(n.subtreeFlags&1028)!==0&&t!==null)t.return=n,cn=t;else for(;cn!==null;){switch(n=cn,p=n.alternate,t=n.flags,n.tag){case 0:if((t&4)!==0&&(t=n.updateQueue,t=t!==null?t.events:null,t!==null))for(s=0;s title"))),pn(p,c,s),p[an]=t,Yt(p),c=p;break e;case"link":var w=fS("link","href",h).get(c+(s.href||""));if(w){for(var k=0;kRt&&(w=Rt,Rt=Ge,Ge=w);var V=my(k,Ge),G=my(k,Rt);if(V&&G&&(ee.rangeCount!==1||ee.anchorNode!==V.node||ee.anchorOffset!==V.offset||ee.focusNode!==G.node||ee.focusOffset!==G.offset)){var W=ue.createRange();W.setStart(V.node,V.offset),ee.removeAllRanges(),Ge>Rt?(ee.addRange(W),ee.extend(G.node,G.offset)):(W.setEnd(G.node,G.offset),ee.addRange(W))}}}}for(ue=[],ee=k;ee=ee.parentNode;)ee.nodeType===1&&ue.push({element:ee,left:ee.scrollLeft,top:ee.scrollTop});for(typeof k.focus=="function"&&k.focus(),k=0;ks?32:s,Q.T=null,s=ng,ng=null;var p=ei,w=vr;if(sn=0,Hs=ei=null,vr=0,(vt&6)!==0)throw Error(r(331));var k=vt;if(vt|=4,yv(p.current),gv(p,p.current,w,s),vt=k,pl(0,!1),nn&&typeof nn.onPostCommitFiberRoot=="function")try{nn.onPostCommitFiberRoot(Ea,p)}catch{}return!0}finally{fe.p=h,Q.T=c,Nv(t,n)}}function Hv(t,n,s){n=ra(s,n),n=Nh(t.stateNode,n,2),t=Kr(t,n,2),t!==null&&(Fe(t,2),Ka(t))}function Ct(t,n,s){if(t.tag===3)Hv(t,t,s);else for(;n!==null;){if(n.tag===3){Hv(n,t,s);break}else if(n.tag===1){var c=n.stateNode;if(typeof n.type.getDerivedStateFromError=="function"||typeof c.componentDidCatch=="function"&&(Zr===null||!Zr.has(c))){t=ra(s,t),s=zb(2),c=Kr(n,s,2),c!==null&&(jb(s,c,n,t),Fe(c,2),Ka(c));break}}n=n.return}}function sg(t,n,s){var c=t.pingCache;if(c===null){c=t.pingCache=new ax;var h=new Set;c.set(n,h)}else h=c.get(n),h===void 0&&(h=new Set,c.set(n,h));h.has(s)||(Qh=!0,h.add(s),t=lx.bind(null,t,n,s),n.then(t,t))}function lx(t,n,s){var c=t.pingCache;c!==null&&c.delete(n),t.pingedLanes|=t.suspendedLanes&s,t.warmLanes&=~s,Dt===t&&(at&s)===s&&(Bt===4||Bt===3&&(at&62914560)===at&&300>Kt()-Su?(vt&2)===0&&zs(t,0):Zh|=s,Is===at&&(Is=0)),Ka(t)}function zv(t,n){n===0&&(n=ke()),t=Li(t,n),t!==null&&(Fe(t,n),Ka(t))}function cx(t){var n=t.memoizedState,s=0;n!==null&&(s=n.retryLane),zv(t,s)}function ux(t,n){var s=0;switch(t.tag){case 31:case 13:var c=t.stateNode,h=t.memoizedState;h!==null&&(s=h.retryLane);break;case 19:c=t.stateNode;break;case 22:c=t.stateNode._retryCache;break;default:throw Error(r(314))}c!==null&&c.delete(n),zv(t,s)}function dx(t,n){return jt(t,n)}var Tu=null,Us=null,og=!1,Ru=!1,lg=!1,ni=0;function Ka(t){t!==Us&&t.next===null&&(Us===null?Tu=Us=t:Us=Us.next=t),Ru=!0,og||(og=!0,hx())}function pl(t,n){if(!lg&&Ru){lg=!0;do for(var s=!1,c=Tu;c!==null;){if(t!==0){var h=c.pendingLanes;if(h===0)var p=0;else{var w=c.suspendedLanes,k=c.pingedLanes;p=(1<<31-q(42|t)+1)-1,p&=h&~(w&~k),p=p&201326741?p&201326741|1:p?p|2:0}p!==0&&(s=!0,Pv(c,p))}else p=at,p=je(c,c===Dt?p:0,c.cancelPendingCommit!==null||c.timeoutHandle!==-1),(p&3)===0||ze(c,p)||(s=!0,Pv(c,p));c=c.next}while(s);lg=!1}}function fx(){jv()}function jv(){Ru=og=!1;var t=0;ni!==0&&Ex()&&(t=ni);for(var n=Kt(),s=null,c=Tu;c!==null;){var h=c.next,p=Uv(c,n);p===0?(c.next=null,s===null?Tu=h:s.next=h,h===null&&(Us=s)):(s=c,(t!==0||(p&3)!==0)&&(Ru=!0)),c=h}sn!==0&&sn!==5||pl(t),ni!==0&&(ni=0)}function Uv(t,n){for(var s=t.suspendedLanes,c=t.pingedLanes,h=t.expirationTimes,p=t.pendingLanes&-62914561;0k)break;var ae=z.transferSize,ue=z.initiatorType;ae&&Xv(ue)&&(z=z.responseEnd,w+=ae*(z"u"?null:document;function lS(t,n,s){var c=Bs;if(c&&typeof n=="string"&&n){var h=$n(n);h='link[rel="'+t+'"][href="'+h+'"]',typeof s=="string"&&(h+='[crossorigin="'+s+'"]'),oS.has(h)||(oS.add(h),t={rel:t,crossOrigin:s,href:n},c.querySelector(h)===null&&(n=c.createElement("link"),pn(n,"link",t),Yt(n),c.head.appendChild(n)))}}function Lx(t){Sr.D(t),lS("dns-prefetch",t,null)}function Mx(t,n){Sr.C(t,n),lS("preconnect",t,n)}function $x(t,n,s){Sr.L(t,n,s);var c=Bs;if(c&&t&&n){var h='link[rel="preload"][as="'+$n(n)+'"]';n==="image"&&s&&s.imageSrcSet?(h+='[imagesrcset="'+$n(s.imageSrcSet)+'"]',typeof s.imageSizes=="string"&&(h+='[imagesizes="'+$n(s.imageSizes)+'"]')):h+='[href="'+$n(t)+'"]';var p=h;switch(n){case"style":p=Ps(t);break;case"script":p=qs(t)}ua.has(p)||(t=b({rel:"preload",href:n==="image"&&s&&s.imageSrcSet?void 0:t,as:n},s),ua.set(p,t),c.querySelector(h)!==null||n==="style"&&c.querySelector(vl(p))||n==="script"&&c.querySelector(Sl(p))||(n=c.createElement("link"),pn(n,"link",t),Yt(n),c.head.appendChild(n)))}}function Nx(t,n){Sr.m(t,n);var s=Bs;if(s&&t){var c=n&&typeof n.as=="string"?n.as:"script",h='link[rel="modulepreload"][as="'+$n(c)+'"][href="'+$n(t)+'"]',p=h;switch(c){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":p=qs(t)}if(!ua.has(p)&&(t=b({rel:"modulepreload",href:t},n),ua.set(p,t),s.querySelector(h)===null)){switch(c){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(s.querySelector(Sl(p)))return}c=s.createElement("link"),pn(c,"link",t),Yt(c),s.head.appendChild(c)}}}function Ix(t,n,s){Sr.S(t,n,s);var c=Bs;if(c&&t){var h=Mr(c).hoistableStyles,p=Ps(t);n=n||"default";var w=h.get(p);if(!w){var k={loading:0,preload:null};if(w=c.querySelector(vl(p)))k.loading=5;else{t=b({rel:"stylesheet",href:t,"data-precedence":n},s),(s=ua.get(p))&&_g(t,s);var z=w=c.createElement("link");Yt(z),pn(z,"link",t),z._p=new Promise(function(Y,ae){z.onload=Y,z.onerror=ae}),z.addEventListener("load",function(){k.loading|=1}),z.addEventListener("error",function(){k.loading|=2}),k.loading|=4,Mu(w,n,c)}w={type:"stylesheet",instance:w,count:1,state:k},h.set(p,w)}}}function Hx(t,n){Sr.X(t,n);var s=Bs;if(s&&t){var c=Mr(s).hoistableScripts,h=qs(t),p=c.get(h);p||(p=s.querySelector(Sl(h)),p||(t=b({src:t,async:!0},n),(n=ua.get(h))&&Ag(t,n),p=s.createElement("script"),Yt(p),pn(p,"link",t),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},c.set(h,p))}}function zx(t,n){Sr.M(t,n);var s=Bs;if(s&&t){var c=Mr(s).hoistableScripts,h=qs(t),p=c.get(h);p||(p=s.querySelector(Sl(h)),p||(t=b({src:t,async:!0,type:"module"},n),(n=ua.get(h))&&Ag(t,n),p=s.createElement("script"),Yt(p),pn(p,"link",t),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},c.set(h,p))}}function cS(t,n,s,c){var h=(h=me.current)?Lu(h):null;if(!h)throw Error(r(446));switch(t){case"meta":case"title":return null;case"style":return typeof s.precedence=="string"&&typeof s.href=="string"?(n=Ps(s.href),s=Mr(h).hoistableStyles,c=s.get(n),c||(c={type:"style",instance:null,count:0,state:null},s.set(n,c)),c):{type:"void",instance:null,count:0,state:null};case"link":if(s.rel==="stylesheet"&&typeof s.href=="string"&&typeof s.precedence=="string"){t=Ps(s.href);var p=Mr(h).hoistableStyles,w=p.get(t);if(w||(h=h.ownerDocument||h,w={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},p.set(t,w),(p=h.querySelector(vl(t)))&&!p._p&&(w.instance=p,w.state.loading=5),ua.has(t)||(s={rel:"preload",as:"style",href:s.href,crossOrigin:s.crossOrigin,integrity:s.integrity,media:s.media,hrefLang:s.hrefLang,referrerPolicy:s.referrerPolicy},ua.set(t,s),p||jx(h,t,s,w.state))),n&&c===null)throw Error(r(528,""));return w}if(n&&c!==null)throw Error(r(529,""));return null;case"script":return n=s.async,s=s.src,typeof s=="string"&&n&&typeof n!="function"&&typeof n!="symbol"?(n=qs(s),s=Mr(h).hoistableScripts,c=s.get(n),c||(c={type:"script",instance:null,count:0,state:null},s.set(n,c)),c):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,t))}}function Ps(t){return'href="'+$n(t)+'"'}function vl(t){return'link[rel="stylesheet"]['+t+"]"}function uS(t){return b({},t,{"data-precedence":t.precedence,precedence:null})}function jx(t,n,s,c){t.querySelector('link[rel="preload"][as="style"]['+n+"]")?c.loading=1:(n=t.createElement("link"),c.preload=n,n.addEventListener("load",function(){return c.loading|=1}),n.addEventListener("error",function(){return c.loading|=2}),pn(n,"link",s),Yt(n),t.head.appendChild(n))}function qs(t){return'[src="'+$n(t)+'"]'}function Sl(t){return"script[async]"+t}function dS(t,n,s){if(n.count++,n.instance===null)switch(n.type){case"style":var c=t.querySelector('style[data-href~="'+$n(s.href)+'"]');if(c)return n.instance=c,Yt(c),c;var h=b({},s,{"data-href":s.href,"data-precedence":s.precedence,href:null,precedence:null});return c=(t.ownerDocument||t).createElement("style"),Yt(c),pn(c,"style",h),Mu(c,s.precedence,t),n.instance=c;case"stylesheet":h=Ps(s.href);var p=t.querySelector(vl(h));if(p)return n.state.loading|=4,n.instance=p,Yt(p),p;c=uS(s),(h=ua.get(h))&&_g(c,h),p=(t.ownerDocument||t).createElement("link"),Yt(p);var w=p;return w._p=new Promise(function(k,z){w.onload=k,w.onerror=z}),pn(p,"link",c),n.state.loading|=4,Mu(p,s.precedence,t),n.instance=p;case"script":return p=qs(s.src),(h=t.querySelector(Sl(p)))?(n.instance=h,Yt(h),h):(c=s,(h=ua.get(p))&&(c=b({},s),Ag(c,h)),t=t.ownerDocument||t,h=t.createElement("script"),Yt(h),pn(h,"link",c),t.head.appendChild(h),n.instance=h);case"void":return null;default:throw Error(r(443,n.type))}else n.type==="stylesheet"&&(n.state.loading&4)===0&&(c=n.instance,n.state.loading|=4,Mu(c,s.precedence,t));return n.instance}function Mu(t,n,s){for(var c=s.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),h=c.length?c[c.length-1]:null,p=h,w=0;w title"):null)}function Ux(t,n,s){if(s===1||n.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof n.precedence!="string"||typeof n.href!="string"||n.href==="")break;return!0;case"link":if(typeof n.rel!="string"||typeof n.href!="string"||n.href===""||n.onLoad||n.onError)break;return n.rel==="stylesheet"?(t=n.disabled,typeof n.precedence=="string"&&t==null):!0;case"script":if(n.async&&typeof n.async!="function"&&typeof n.async!="symbol"&&!n.onLoad&&!n.onError&&n.src&&typeof n.src=="string")return!0}return!1}function gS(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function Bx(t,n,s,c){if(s.type==="stylesheet"&&(typeof c.media!="string"||matchMedia(c.media).matches!==!1)&&(s.state.loading&4)===0){if(s.instance===null){var h=Ps(c.href),p=n.querySelector(vl(h));if(p){n=p._p,n!==null&&typeof n=="object"&&typeof n.then=="function"&&(t.count++,t=Nu.bind(t),n.then(t,t)),s.state.loading|=4,s.instance=p,Yt(p);return}p=n.ownerDocument||n,c=uS(c),(h=ua.get(h))&&_g(c,h),p=p.createElement("link"),Yt(p);var w=p;w._p=new Promise(function(k,z){w.onload=k,w.onerror=z}),pn(p,"link",c),s.instance=p}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(s,n),(n=s.state.preload)&&(s.state.loading&3)===0&&(t.count++,s=Nu.bind(t),n.addEventListener("load",s),n.addEventListener("error",s))}}var xg=0;function Px(t,n){return t.stylesheets&&t.count===0&&Hu(t,t.stylesheets),0xg?50:800)+n);return t.unsuspend=s,function(){t.unsuspend=null,clearTimeout(c),clearTimeout(h)}}:null}function Nu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Hu(this,this.stylesheets);else if(this.unsuspend){var t=this.unsuspend;this.unsuspend=null,t()}}}var Iu=null;function Hu(t,n){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Iu=new Map,n.forEach(qx,t),Iu=null,Nu.call(t))}function qx(t,n){if(!(n.state.loading&4)){var s=Iu.get(t);if(s)var c=s.get(null);else{s=new Map,Iu.set(t,s);for(var h=t.querySelectorAll("link[data-precedence],style[data-precedence]"),p=0;p"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(o)}catch(e){console.error(e)}}return o(),Ku.exports=NS(),Ku.exports}var Ju=IS();const Qu=Ya(Ju),Fs=[],HS=50;let Zu=!1;function Pg(){try{return window.G7Core?.devTools}catch{return}}function Vi(o,e,a){const r=Pg();if(Zu&&r?.isEnabled?.()){r.trackLog?.(o,e,a);return}Zu||(o==="error"||o==="warn")&&Fs.length{a.isDebugEnabled()&&console.log(e,...r),Vi("log",o,r)},warn:(...r)=>{a.isDebugEnabled()&&console.warn(e,...r),Vi("warn",o,r)},error:(...r)=>{a.isDebugEnabled()&&console.error(e,...r),Vi("error",o,r)}}}Ks.getInstance();const Fi=ct("networkResilience"),qg=2,Gg=300,Vg=2e3,zS=15e3;function Fg(o){return o?.name==="AbortError"}function jS(o){return Fg(o)?!1:o instanceof TypeError}let Al=!1,Kg=!1;function td(){return Al}function US(){typeof window>"u"||Kg||(Kg=!0,window.addEventListener("pagehide",()=>{Al=!0}),window.addEventListener("pageshow",o=>{o.persisted&&(Al=!1)}),window.addEventListener("beforeunload",()=>{Al=!0}))}function Wg(o,e,a){const r=Math.min(e*Math.pow(2,o),a),i=r*.25*(Math.random()*2-1);return Math.max(0,Math.round(r+i))}function Yg(o){return new Promise(e=>setTimeout(e,o))}async function xl(o,e={}){const{retries:a=qg,baseDelayMs:r=Gg,maxDelayMs:i=Vg,timeoutMs:l=zS,label:u=o,init:d}=e,f=a+1;let g;for(let m=0;m0?new AbortController:null;try{const E={...d};if(S){const T=d?.signal;T&&(T.aborted?S.abort():T.addEventListener("abort",()=>S.abort(),{once:!0})),E.signal=S.signal,v=setTimeout(()=>{b=!0,S.abort()},l)}return await fetch(o,E)}catch(E){if(g=E,Fg(E)&&!b||!(b||jS(E)))throw E;if(td())throw Fi.warn(`Document unloading, aborting retries: ${u}`),E;if(m===f-1)throw Fi.warn(`All ${f} attempts failed: ${u}`,E),E;const L=Wg(m,r,i);Fi.warn(`Network failure (attempt ${m+1}/${f}), retrying in ${L}ms: ${u}`),await Yg(L)}finally{v!==void 0&&clearTimeout(v)}}throw g}async function Xg(o,e={},a={}){const{retries:r=qg,baseDelayMs:i=Gg,maxDelayMs:l=Vg,label:u=o}=a,d=r+1;for(let f=0;f{const i=document.createElement("script");i.src=o,i.async=!1;for(const[l,u]of Object.entries(e))l==="id"?i.id=u:i.setAttribute(l,u);i.onload=()=>a(),i.onerror=()=>r(new Error(`Failed to load script: ${o}`)),document.head.appendChild(i)})}const Jg="extension",Ki="extensionless",PS="file";function qS(){const o=globalThis?.G7Config;if(globalThis?.__g7AssetUrlMode===Ki)return Ki;const a=o?.assetUrlMode;return a===Ki||a===Jg?a:o?.settings?.general?.asset_url_mode===Ki?Ki:Jg}function Qg(){return qS()===Ki}function La(o,e,a,r){const i=o.replace(/\/+$/,""),l=e.replace(/^\.+/,""),u=Qg()?i:`${i}.${l}`,d=[];return r&&d.push(r.replace(/^[?&]+/,"")),a!=null&&a!==""&&d.push(`v=${a}`),d.length>0?`${u}?${d.join("&")}`:u}function wr(o){if(!o||!Qg())return o;const e=globalThis?.location?.origin,a=e&&o.startsWith(e)?o.slice(e.length):o;if(!a.startsWith("/api/"))return o;const[r,i]=GS(a),l=r.match(/^\/api\/(modules|plugins)\/bundle\.(js|css)$/);if(l)return Zg(`/api/${l[1]}/bundle/${l[2]}`,i);const u=r.match(/^\/api\/(templates|modules|plugins)\/assets\/([^/]+)\/(.+)$/);if(u){const[,f,g,m]=u,b=`${PS}=${encodeURIComponent(decodeURIComponent(m))}`;return`/api/${f}/assets/${g}?${b}${i?`&${i}`:""}`}const d=r.match(/^(\/api\/.+)\.(json|js|css)$/);return d?Zg(d[1],i):o}function GS(o){const e=o.indexOf("?");return e===-1?[o,""]:[o.slice(0,e),o.slice(e+1)]}function Zg(o,e){return e?`${o}?${e}`:o}const Ma=ct("ComponentRegistry");class on extends Error{constructor(a,r,i){super(a);$(this,"code");$(this,"details");this.code=r,this.details=i,this.name="ComponentRegistryError"}}const Pn=class Pn{constructor(){$(this,"registry",{});$(this,"manifest",null);$(this,"loadingState","idle");$(this,"error",null);$(this,"templateId",null);$(this,"templateType",null)}static getInstance(){return Pn.instance||(Pn.instance=new Pn),Pn.instance}static createIsolatedInstance(){return new Pn}static resetInstance(){Pn.instance=null}async loadComponents(e,a){if(this.loadingState==="loading")throw new on("Components are already being loaded","LOADING_IN_PROGRESS");if(this.loadingState==="loaded"&&this.templateId===e&&this.templateType===a){Ma.log("Components already loaded for template:",e,a);return}this.loadingState="loading",this.templateId=e,this.templateType=a,this.error=null;try{await this.loadManifest(),await this.loadComponentBundle(),this.loadingState="loaded",Ma.log("Successfully loaded components:",Object.keys(this.registry).length)}catch(r){throw this.loadingState="error",this.error=r instanceof Error?r:new Error(String(r)),new on(`Failed to load components: ${this.error.message}`,"LOAD_FAILED",{originalError:this.error})}}async loadManifest(){try{if(!this.templateId)throw new on("Template ID not set","TEMPLATE_ID_NOT_SET");const e=`${this.templateId}:${this.templateType}`;if(Pn.manifestCache.has(e)){this.manifest=Pn.manifestCache.get(e),Ma.log("Manifest loaded from cache:",this.manifest.templateId);return}const a=La(`/api/templates/${this.templateId}/components`,"json"),r=await xl(a,{label:"components.json"});if(!r.ok)throw new on(`Failed to fetch manifest: ${r.status} ${r.statusText}`,"MANIFEST_FETCH_FAILED",{status:r.status,statusText:r.statusText});const i=await r.json();this.validateManifest(i),this.manifest=i,Pn.manifestCache.set(e,i),Ma.log("Manifest loaded and cached:",i.templateId)}catch(e){throw e instanceof on?e:new on("Failed to load component manifest","MANIFEST_LOAD_FAILED",{originalError:e})}}validateManifest(e){if(!e.version)throw new on("Manifest missing required field: version","MANIFEST_INVALID",{field:"version"});if(!e.templateId)throw new on("Manifest missing required field: templateId","MANIFEST_INVALID",{field:"templateId"});if(!e.components||typeof e.components!="object")throw new on("Manifest missing required field: components","MANIFEST_INVALID",{field:"components"});const a=["basic","composite","layout"];for(const r of a){if(!Array.isArray(e.components[r]))throw new on(`Manifest field 'components.${r}' must be an array`,"MANIFEST_INVALID",{field:`components.${r}`,value:e.components[r]});e.components[r].forEach((i,l)=>{if(!i.name||typeof i.name!="string")throw new on(`Invalid component metadata at ${r}[${l}]: missing or invalid 'name'`,"MANIFEST_INVALID",{type:r,index:l,metadata:i});if(!i.type||typeof i.type!="string")throw new on(`Invalid component metadata at ${r}[${l}]: missing or invalid 'type'`,"MANIFEST_INVALID",{type:r,index:l,metadata:i})})}Ma.log("Manifest validation passed")}async loadComponentBundle(){try{if(!this.templateId)throw new on("Template ID not set","TEMPLATE_ID_NOT_SET");const e=this.getGlobalVariableName(),a=window[e];if(!a||typeof a!="object")throw new on(`Component bundle not loaded. Expected global variable: ${e}. Ensure admin.blade.php includes the IIFE bundle script.`,"BUNDLE_NOT_LOADED",{expectedVariable:e});await this.registerComponentsFromManifest(a),Ma.log("Component bundle loaded from global variable:",e)}catch(e){throw e instanceof on?e:new on("Failed to load component bundle","BUNDLE_LOAD_FAILED",{originalError:e})}}getGlobalVariableName(){if(!this.templateId)throw new on("Template ID not set","TEMPLATE_ID_NOT_SET");return this.templateId.split(/[-_]/).map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join("")}async registerComponentsFromManifest(e){if(!this.manifest)throw new on("Manifest not loaded","MANIFEST_NOT_LOADED");const a=["basic","composite","layout"];for(const r of a){const i=this.manifest.components[r]||[];for(const l of i){const u=l.name,d=e[u];if(!d){Ma.warn(`Component '${u}' not found in bundle`);continue}this.registerComponent(u,d,l)}}}registerComponent(e,a,r){this.registry[e]&&Ma.warn(`Component '${e}' already registered, overwriting`);const i=Ye.memo(a);this.registry[e]={component:i,metadata:r},Ma.log(`[ComponentRegistry] Registered component: ${e} (${r.type})`)}getComponent(e){const a=this.registry[e];return a?a.component:null}getMetadata(e){const a=this.registry[e];return a?a.metadata:null}hasComponent(e){return e in this.registry}getComponentsByType(e){return Object.entries(this.registry).filter(([a,r])=>r.metadata.type===e).map(([a,r])=>a)}getAllComponents(){return Object.keys(this.registry)}getComponentMap(){const e={};for(const[a,r]of Object.entries(this.registry))e[a]=r.component;return e}getLoadingState(){return this.loadingState}getError(){return this.error}getTemplateId(){return this.templateId}getManifest(){return this.manifest}clear(){this.registry={},this.manifest=null,this.loadingState="idle",this.error=null,this.templateId=null,this.templateType=null,Ma.log("Registry cleared")}};$(Pn,"instance",null),$(Pn,"manifestCache",new Map);let da=Pn;const ep=ct("TranslationEngine");class nd extends Error{constructor(a,r,i){super(a);$(this,"key");$(this,"locale");this.key=r,this.locale=i,this.name="TranslationError"}}const Rn=class Rn{constructor(e={}){$(this,"cache",new Map);$(this,"translations",new Map);$(this,"options");$(this,"cacheVersion",0);this.options={defaultLocale:e.defaultLocale||"ko",fallbackLocale:e.fallbackLocale||"en",cacheTTL:e.cacheTTL||3e5}}static getInstance(e={}){return Rn.instance||(Rn.instance=new Rn(e)),Rn.instance}static resetInstance(){Rn.instance=null}setCacheVersion(e){this.cacheVersion!==e&&(ep.log("Cache version updated:",this.cacheVersion,"->",e),this.cacheVersion=e,this.cache.clear())}getCacheVersion(){return this.cacheVersion}async loadTranslations(e,a,r="/api",i=!1){const l=`${e}:${a}`;if(!i){const u=this.getFromCache(l);if(u)return this.translations.set(l,u),u}try{const u=[];i&&u.push(`_=${Date.now()}`);const d=La(`${r}/templates/${e}/lang/${a}`,"json",this.cacheVersion>0?this.cacheVersion:null,u.length>0?u.join("&"):void 0),f=await fetch(d);if(!f.ok)throw new nd(`Failed to load translations: ${f.statusText}`,void 0,a);const m=await f.json();return this.saveToCache(l,m),this.translations.set(l,m),m}catch(u){throw new nd(`Failed to fetch translations for ${a}: ${u instanceof Error?u.message:String(u)}`,void 0,a)}}resolveTranslations(e,a,r){let i=e;const l=5;let u=0;for(;u"="+this.translate(m,a,void 0,r)),i===d)break;u++}return i.replace(Rn.TRANSLATION_PATTERN,(d,f,g)=>{const{cleanedParams:m,trailing:b}=this.separateTrailingText(g);return this.translate(f,a,m,r)+b})}translate(e,a,r,i){const l=this.getTranslation(e,a),u=r&&this.cleanParamsStr(r);if(u){const d=this.parseParams(u,i);return this.replaceParams(l,d)}return l}getTranslation(e,a){const{templateId:r,locale:i}=a,l=`${r}:${i}`,u=this.translations.get(l);if(u){const d=this.getNestedValue(u,e);if(d!==null)return d}if(i!==this.options.fallbackLocale){const d=`${r}:${this.options.fallbackLocale}`,f=this.translations.get(d);if(f){const g=this.getNestedValue(f,e);if(g!==null)return g}}return e}getNestedValue(e,a){const r=a.split(".");let i=e;for(const l of r){if(i==null||typeof i!="object")return null;i=i[l]}return typeof i=="string"?i:null}setTranslationValue(e,a,r,i){const l=`${e}:${a}`,u=this.translations.get(l)??{},d=r.split(".");let f=u;for(let g=0;g(l.push(f),`__PLACEHOLDER_${l.length-1}__`)).matchAll(Rn.PARAM_PATTERN);for(const f of d){const[,g,m]=f,b=m.replace(/__PLACEHOLDER_(\d+)__/g,(v,S)=>l[parseInt(S,10)]);r[g.trim()]=this.resolveParamValue(b.trim(),a)}return r}resolveParamValue(e,a){if(e.startsWith("{{")&&e.endsWith("}}")){const r=e.slice(2,-2).trim();if(/[|&()[\]!?:+\-*/%<>=\s]/.test(r)&&a)try{const u=new Function(...Object.keys(a),`return ${r}`)(...Object.values(a));return String(u??"")}catch(l){return ep.error("Expression evaluation failed:",r,l),""}else{const l=this.getNestedDataValue(a,r);return String(l??"")}}return e}separateTrailingText(e){if(!e)return{cleanedParams:void 0,trailing:""};if(e.trimEnd().endsWith("}}"))return{cleanedParams:e,trailing:""};if(!(e.startsWith("|")?e.slice(1):e).includes("="))return{cleanedParams:void 0,trailing:e};const r=e.match(/(\s+[^\p{L}\w=|&\s][^\p{L}\w=]*\s*)$/u);return r?{cleanedParams:e.slice(0,-r[1].length),trailing:r[1]}:{cleanedParams:e,trailing:""}}cleanParamsStr(e){return this.separateTrailingText(e).cleanedParams||""}getNestedDataValue(e,a){if(!e)return;const r=a.split(".");let i=e;for(const l of r){if(i==null)return;i=i[l]}return i}replaceParams(e,a){let r=e;for(const[i,l]of Object.entries(a)){const u=new RegExp(`\\{\\{${i}\\}\\}`,"g");r=r.replace(u,String(l));const d=new RegExp(`\\{${i}\\}`,"g");r=r.replace(d,String(l))}return r}getFromCache(e){const a=this.cache.get(e);return a?Date.now()-a.timestamp>this.options.cacheTTL?(this.cache.delete(e),null):a.data:null}saveToCache(e,a){this.cache.set(e,{data:a,timestamp:Date.now()})}clearCache(){this.cache.clear(),this.translations.clear()}pruneCache(){const e=Date.now(),a=[];for(const[r,i]of this.cache.entries())e-i.timestamp>this.options.cacheTTL&&a.push(r);for(const r of a)this.cache.delete(r)}getCacheStats(){const e=Date.now();let a=0;for(const r of this.cache.values())e-r.timestamp>this.options.cacheTTL&&a++;return{size:this.cache.size,expired:a}}};$(Rn,"instance",null),$(Rn,"TRANSLATION_PATTERN",/\$t:(?:defer:)?([a-zA-Z0-9._-]+)(\|(?:(?!\$t:).)+)?/g),$(Rn,"NESTED_TRANSLATION_PARAM_PATTERN",/=(\$t:([a-zA-Z0-9._-]+))(?=[|&\s]|$)/g),$(Rn,"PARAM_PATTERN",/([^=|&]+)=([^|&]+)/g);let Cr=Rn,ad=null;function VS(o){return ad||(ad=new Cr(o)),ad}const tp=Object.freeze(Object.defineProperty({__proto__:null,TranslationEngine:Cr,TranslationError:nd,getTranslationEngine:VS},Symbol.toStringTag,{value:"Module"})),Wi=ct("PipeRegistry");function np(o,e){const a=o.getFullYear(),r=String(o.getMonth()+1).padStart(2,"0"),i=String(o.getDate()).padStart(2,"0"),l=String(o.getHours()).padStart(2,"0"),u=String(o.getMinutes()).padStart(2,"0"),d=String(o.getSeconds()).padStart(2,"0");return e.replace("YYYY",String(a)).replace("YY",String(a).slice(-2)).replace("MM",r).replace("M",String(o.getMonth()+1)).replace("DD",i).replace("D",String(o.getDate())).replace("HH",l).replace("H",String(o.getHours())).replace("mm",u).replace("m",String(o.getMinutes())).replace("ss",d).replace("s",String(o.getSeconds()))}function FS(o,e="ko"){const r=new Date().getTime()-o.getTime(),i=Math.floor(r/1e3),l=Math.floor(i/60),u=Math.floor(l/60),d=Math.floor(u/24),f=Math.floor(d/7),g=Math.floor(d/30),m=Math.floor(d/365);return e==="ko"?i<60?"방금 전":l<60?`${l}분 전`:u<24?`${u}시간 전`:d<7?`${d}일 전`:f<4?`${f}주 전`:g<12?`${g}개월 전`:`${m}년 전`:i<60?"just now":l<60?`${l} minute${l===1?"":"s"} ago`:u<24?`${u} hour${u===1?"":"s"} ago`:d<7?`${d} day${d===1?"":"s"} ago`:f<4?`${f} week${f===1?"":"s"} ago`:g<12?`${g} month${g===1?"":"s"} ago`:`${m} year${m===1?"":"s"} ago`}function rd(o){if(o==null)return null;if(o instanceof Date)return o;if(typeof o=="number")return new Date(o);if(typeof o=="string"){const e=new Date(o);return isNaN(e.getTime())?null:e}return null}const Ws={date:{fn:(o,e="YYYY-MM-DD")=>{const a=rd(o);return a?np(a,e):""},description:"날짜 포맷 (기본: YYYY-MM-DD)"},datetime:{fn:(o,e="YYYY-MM-DD HH:mm")=>{const a=rd(o);return a?np(a,e):""},description:"날짜+시간 포맷 (기본: YYYY-MM-DD HH:mm)"},relativeTime:{fn:(o,e="ko")=>{const a=rd(o);return a?FS(a,e):""},description:'상대 시간 표시 (예: "3분 전")'},number:{fn:(o,e)=>{const a=Number(o);if(isNaN(a))return String(o??"");const r={};return e!==void 0&&(r.minimumFractionDigits=e,r.maximumFractionDigits=e),a.toLocaleString(void 0,r)},description:"숫자 포맷 (천단위 구분, 선택적 소수점)"},truncate:{fn:(o,e=100,a="...")=>typeof o!="string"?String(o??""):o.length<=e?o:o.slice(0,e)+a,description:'문자열 자르기 (기본: 100자, 접미사: "...")'},uppercase:{fn:o=>typeof o!="string"?String(o??""):o.toUpperCase(),description:"대문자 변환"},lowercase:{fn:o=>typeof o!="string"?String(o??""):o.toLowerCase(),description:"소문자 변환"},stripHtml:{fn:o=>typeof o!="string"?String(o??""):o.replace(/<[^>]*>/g,""),description:"HTML 태그 제거"},default:{fn:(o,e="")=>o==null||o===""?e:o,description:"기본값 설정 (null, undefined, 빈문자열 시)"},fallback:{fn:(o,e)=>o??e,description:"폴백 값 설정 (null, undefined 시만)"},first:{fn:o=>{if(Array.isArray(o))return o[0]},description:"배열의 첫 번째 요소"},last:{fn:o=>{if(Array.isArray(o))return o[o.length-1]},description:"배열의 마지막 요소"},join:{fn:(o,e=", ")=>Array.isArray(o)?o.join(e):"",description:'배열을 문자열로 결합 (기본 구분자: ", ")'},length:{fn:o=>Array.isArray(o)||typeof o=="string"?o.length:0,description:"배열/문자열 길이"},filterBy:{fn:(o,e,a)=>Array.isArray(o)?Array.isArray(e)?o.filter(r=>{const i=a?r?.[a]:r;return e.includes(i)}):o:[],description:"배열 필터링 (allowList에 포함된 항목만 반환)"},keys:{fn:o=>o==null||typeof o!="object"?[]:Object.keys(o),description:"객체의 키 배열"},values:{fn:o=>o==null||typeof o!="object"?[]:Object.values(o),description:"객체의 값 배열"},json:{fn:(o,e)=>{try{return JSON.stringify(o,null,e)}catch{return""}},description:"JSON 문자열로 변환"},localized:{fn:(o,e)=>o==null?"":typeof o=="string"?o:typeof o!="object"?String(o):o[e||"ko"]||o.ko||o.en||Object.values(o)[0]||"",description:"다국어 객체에서 로케일에 맞는 값 추출"}},Yi=new Map,mi=class mi{static getInstance(){return mi.instance||(mi.instance=new mi),mi.instance}register(e,a,r){if(Ws[e]){Wi.warn(`[PipeRegistry] 내장 파이프를 덮어쓸 수 없습니다: ${e}`);return}Yi.set(e,{fn:a,description:r}),Wi.log(`[PipeRegistry] 커스텀 파이프 등록됨: ${e}`)}unregister(e){if(Ws[e])return Wi.warn(`[PipeRegistry] 내장 파이프는 해제할 수 없습니다: ${e}`),!1;const a=Yi.delete(e);return a&&Wi.log(`[PipeRegistry] 커스텀 파이프 해제됨: ${e}`),a}get(e){const a=Ws[e];return a?a.fn:Yi.get(e)?.fn}has(e){return!!Ws[e]||Yi.has(e)}execute(e,a,r=[]){const i=this.get(e);if(!i)return Wi.warn(`[PipeRegistry] 알 수 없는 파이프: ${e}`),a;try{return i(a,...r)}catch(l){return Wi.error(`[PipeRegistry] 파이프 실행 오류 (${e}):`,l),a}}list(){const e=[];for(const[a,r]of Object.entries(Ws))e.push({name:a,description:r.description,type:"built-in"});for(const[a,r]of Yi.entries())e.push({name:a,description:r.description,type:"custom"});return e.sort((a,r)=>a.name.localeCompare(r.name))}clearCustomPipes(){Yi.clear()}};$(mi,"instance",null);let Tl=mi;Tl.getInstance();function KS(o){const e=o.trim(),a=e.indexOf("(");if(a===-1)return{name:e,args:[]};const r=e.slice(0,a).trim(),i=e.slice(a+1,-1);if(!i.trim())return{name:r,args:[]};const l=[];let u="",d=null,f=0;for(let g=0;g0?i[g-1]:"")==="\\"){u+=m;continue}if((m==='"'||m==="'")&&!d){d=m;continue}if(m===d){d=null;continue}if(d){u+=m;continue}if(m==="("||m==="["||m==="{"){f++,u+=m;continue}if(m===")"||m==="]"||m==="}"){f--,u+=m;continue}if(m===","&&f===0){l.push(ap(u.trim())),u="";continue}u+=m}return u.trim()&&l.push(ap(u.trim())),{name:r,args:l}}function ap(o){if(o==="null")return null;if(o==="undefined")return;if(o==="true")return!0;if(o==="false")return!1;const e=Number(o);return!isNaN(e)&&o!==""?e:o}function WS(o){const e=[];let a="",r=null,i=0;for(let l=0;l0?o[l-1]:"",f=l0?o[r-1]:"",u=r=2&&o.charCodeAt(0)===64976&&o.charCodeAt(o.length-1)===64977}function ip(o){return o.includes(Rl)}function sp(o){return o.slice(1,-1)}function Js(o){if(typeof o=="string")return Xs(o);if(Array.isArray(o))return o.map(Js);if(o&&typeof o=="object"){const e={};for(const[a,r]of Object.entries(o))e[a]=Js(r);return e}return o}const Qs=ct("DataBindingEngine");function kl(){try{return window.G7Core?.devTools}catch{return}}class id extends Error{constructor(a,r,i){super(a);$(this,"path");$(this,"context");this.path=r,this.context=i,this.name="DataBindingError"}}const Sa=class Sa{constructor(e){$(this,"cache",new Map);$(this,"expressionFnCache",new Map);$(this,"renderCycleCache",new Map);$(this,"currentRenderCycleId",0);$(this,"defaultOptions",{defaultValue:void 0,nullSafe:!0,detectCircular:!0,maxDepth:10});e&&(this.defaultOptions={...this.defaultOptions,...e})}startRenderCycle(){this.currentRenderCycleId++,this.renderCycleCache.clear()}isRenderCycleCacheActive(){return this.currentRenderCycleId>0}getFromRenderCycleCache(e){if(this.isRenderCycleCacheActive())return this.renderCycleCache.get(e)}saveToRenderCycleCache(e,a){this.isRenderCycleCacheActive()&&this.renderCycleCache.set(e,a)}resolveBindings(e,a,r,i){const l={...this.defaultOptions,...r},u=kl(),d=a._computed&&!a.$computed?{...a,$computed:a._computed}:a;return e.replace(Sa.BINDING_PATTERN,(f,g)=>{const m=g.trim();let b=!1,v=m;if(m.startsWith(Er)&&(b=!0,v=m.slice(Er.length)),ci(v)){const R=u?.isEnabled()?performance.now():0;try{const[D,U]=WS(v);let j,P=!1;const X=/[?:|&!+\-*/<>=()]/.test(D)||/\[['"]/.test(D),ge=D.startsWith("_global")||D.startsWith("_local")||D.startsWith("_isolated")||D.startsWith("$parent");if(l.skipCache)X?j=this.evaluateExpression(D,d):j=this.resolvePath(D,d,l);else if(X){const $e=this.getFromRenderCycleCache(`expr:${D}`);$e!==void 0?(j=$e,P=!0):(j=this.evaluateExpression(D,d),this.saveToRenderCycleCache(`expr:${D}`,j))}else if(ge){const $e=this.getFromRenderCycleCache(D);$e!==void 0?(j=$e,P=!0):(j=this.resolvePath(D,d,l),this.saveToRenderCycleCache(D,j))}else{const $e=this.getFromCache(D);$e!==void 0?(j=$e,P=!0):(j=this.resolvePath(D,d,l),this.saveToCache(D,j))}const Ee=YS(j,U);if(u?.isEnabled()){const $e=performance.now()-R;u.trackExpressionEval({expression:`{{${m}}}`,result:this.sanitizeResultForTracking(Ee),resultType:this.getResultType(Ee),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:P,duration:$e,method:"resolveBindings",skipCache:l.skipCache})}const Ce=this.formatValue(Ee);return b?Xs(Ce):Ce}catch(D){return Qs.error("Pipe expression evaluation failed:",v,D),f}}if(/[?:&!+\-*/<>=()]/.test(v)||/\|\|/.test(v)||/\[['"]/.test(v)){const R=u?.isEnabled()?performance.now():0;try{let D,U=!1;if(l.skipCache)D=this.evaluateExpression(v,d);else{const P=`expr:${v}`,X=this.getFromRenderCycleCache(P);X!==void 0?(D=X,U=!0):(D=this.evaluateExpression(v,d),this.saveToRenderCycleCache(P,D))}if(u?.isEnabled()){const P=performance.now()-R;u.trackExpressionEval({expression:`{{${m}}}`,result:this.sanitizeResultForTracking(D),resultType:this.getResultType(D),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:U,duration:P,method:"resolveBindings",skipCache:l.skipCache})}const j=this.formatValue(D);return b?Xs(j):j}catch(D){return Qs.error("Expression evaluation failed:",v,D),f}}if(l.skipCache){const R=u?.isEnabled()?performance.now():0,D=this.resolvePath(v,d,l);if(u?.isEnabled()){const j=performance.now()-R;u.trackExpressionEval({expression:`{{${m}}}`,result:this.sanitizeResultForTracking(D),resultType:this.getResultType(D),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!1,duration:j,method:"resolveBindings",skipCache:!0})}const U=this.formatValue(D);return b?Xs(U):U}const E=v.startsWith("_global")||v.startsWith("_local")||v.startsWith("_isolated")||v.startsWith("$parent"),A=u?.isEnabled()?performance.now():0;let T,L=!1;if(E){const R=this.getFromRenderCycleCache(v);R!==void 0?(T=R,L=!0):(T=this.resolvePath(v,d,l),this.saveToRenderCycleCache(v,T))}else{const R=this.getFromCache(v);R!==void 0?(T=R,L=!0):(T=this.resolvePath(v,d,l),this.saveToCache(v,T))}if(u?.isEnabled()){const R=performance.now()-A;u.trackExpressionEval({expression:`{{${m}}}`,result:this.sanitizeResultForTracking(T),resultType:this.getResultType(T),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:L,duration:R,method:"resolveBindings",skipCache:l.skipCache})}const M=this.formatValue(T);return b?Xs(M):M})}resolve(e,a,r,i){const l={...this.defaultOptions,...r},u=kl(),d=u?.isEnabled()?performance.now():0;if(l.skipCache){const b=this.resolvePath(e,a,l);return u?.isEnabled()&&u.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(b),resultType:this.getResultType(b),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!1,duration:performance.now()-d,method:"resolve",skipCache:!0}),b}const f=e.startsWith("_global")||e.startsWith("_local")||e.startsWith("_isolated")||e.startsWith("$parent");let g=!1;if(f){const b=this.getFromRenderCycleCache(e);if(b!==void 0)return g=!0,u?.isEnabled()&&u.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(b),resultType:this.getResultType(b),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!0,duration:performance.now()-d,method:"resolve",skipCache:l.skipCache}),b}else{const b=this.getFromCache(e);if(b!==void 0)return g=!0,u?.isEnabled()&&u.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(b),resultType:this.getResultType(b),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!0,duration:performance.now()-d,method:"resolve",skipCache:l.skipCache}),b}const m=this.resolvePath(e,a,l);return f?this.saveToRenderCycleCache(e,m):this.saveToCache(e,m),u?.isEnabled()&&u.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(m),resultType:this.getResultType(m),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:g,duration:performance.now()-d,method:"resolve",skipCache:l.skipCache}),m}resolvePath(e,a,r,i=0,l=new WeakSet){if(r.maxDepth&&i>r.maxDepth){if(r.detectCircular)throw new id(`Maximum depth exceeded (${r.maxDepth}). Possible circular reference.`,e,a);return r.defaultValue}const u=this.parsePath(e);let d=a;for(let f=0;fSa.CACHE_EXPIRY){this.cache.delete(e),r?.isEnabled()&&r.recordCacheMiss();return}return r?.isEnabled()&&r.recordCacheHit(),a.value}saveToCache(e,a){this.cache.set(e,{value:a,timestamp:Date.now()})}isActionDefinition(e){return typeof e.handler!="string"?!1:e.params!==void 0||Array.isArray(e.actions)||typeof e.target=="string"||e.onSuccess!==void 0||e.onError!==void 0}extractSingleBinding(e){if(!e.startsWith("{{")||!e.endsWith("}}")||e.length<5)return null;const a=e.slice(2,-2);let r=0;for(let i=0;i0)r--;else if(a[i+1]==="}")return null}}return a}resolveObject(e,a,r){if(this.isSwitchExpression(e)){const d=e;return this.resolveSwitch(d,a,r)}if(this.isActionDefinition(e))return{...e};if("iteration"in e)return{...e};const i={},u=[...["cellChildren","expandChildren","expandContext","render"],...r?.skipBindingKeys||[]];for(const[d,f]of Object.entries(e)){if(u.includes(d)){i[d]=f;continue}if(typeof f=="string"){const g=this.extractSingleBinding(f);if(g!==null){const m=g.trim();let b=!1,v=m;m.startsWith(Er)&&(b=!0,v=m.slice(Er.length));const S=/[?:|&!+\-*/<>=()]/.test(v)||/\[['"]/.test(v),E=ci(v)?this.resolveBindings(`{{${v}}}`,a,r):S?this.evaluateExpression(v,a,r):this.resolve(v,a,r);i[d]=b&&E!=null?Js(E):E}else i[d]=this.resolveBindings(f,a,r)}else Array.isArray(f)?i[d]=f.map(g=>typeof g=="string"?this.resolveBindings(g,a,r):typeof g=="object"&&g!==null?this.resolveObject(g,a,r):g):f&&typeof f=="object"?i[d]=this.resolveObject(f,a,r):i[d]=f}return i}clearCache(){this.cache.clear(),this.expressionFnCache.clear()}invalidateCacheByKeys(e){for(const a of this.cache.keys())for(const r of e)if(a===r||a.startsWith(`${r}.`)||a.startsWith(`${r}[`)){this.cache.delete(a);break}}pruneCache(){const e=Date.now();for(const[a,r]of this.cache.entries())e-r.timestamp>Sa.CACHE_EXPIRY&&this.cache.delete(a)}getCacheStats(){const e=Date.now();let a=0;for(const r of this.cache.values())e-r.timestamp>Sa.CACHE_EXPIRY&&a++;return{size:this.cache.size,expired:a}}evaluateExpression(e,a,r){const i=kl(),l=i?.isEnabled()?performance.now():0;i?.isEnabled()&&i.trackBindingEval();try{let u=this.preprocessOptionalChaining(e);u=this.preprocessTranslationTokens(u);const d=this.extractVariablesFromExpression(u),f={...a};for(const D of d)D in f||(f[D]=void 0);a._computed&&!f.$computed&&(f.$computed=a._computed);let g=a.$templateId,m=a.$locale;if(typeof window<"u"&&(!g||!m)){const D=window.__templateApp?.getConfig?.();g??(g=D?.templateId),m??(m=D?.locale)}const b=m||"ko";f.$localized=(D,U)=>{if(D==null&&!U)return"";if(typeof D=="string")return D;if(D&&typeof D=="object"&&D[b])return D[b];if(U&&typeof U=="string"){const j=f.$t?f.$t(U):U;if(j&&j!==U)return j}return D&&typeof D=="object"?D.ko||D.en||Object.values(D)[0]||"":D==null?"":String(D)};const v=typeof window<"u"?window.G7Core:void 0;f.$uuid=()=>v?.uuid?v.uuid():typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,D=>{const U=Math.random()*16|0;return(D==="x"?U:U&3|8).toString(16)});const S={templateId:g||"",locale:b};f.$t=D=>{if(!D||typeof D!="string")return"";try{return Cr.getInstance().translate(D,S)}catch(U){return Qs.warn("$t() translation failed for key:",D,U),D}},f.$get=(D,U,j=void 0)=>{if(D==null)return j;const P=Array.isArray(U)?U:[U];if(P.length===0)return D;let X=D;for(const ge of P){if(X==null||ge==null)return j;X=X[ge]}return X??j};const E=Object.keys(f),A=Object.values(f),T=`${u}|${E.join(",")}`;let L=this.expressionFnCache.get(T);const M=!!L;L||(L=new Function(...E,`return (${u});`),this.expressionFnCache.set(T,L));const R=L(...A);if(i?.isEnabled()){const D=performance.now()-l;i.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(R),resultType:this.getResultType(R),componentId:r?.componentId,componentName:r?.componentName,propName:r?.propName,fromCache:M,duration:D,method:"evaluateExpression",skipCache:r?.skipCache})}return R}catch(u){throw new Error(`Failed to evaluate expression "${e}": ${u instanceof Error?u.message:String(u)}`)}}getResultType(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}sanitizeResultForTracking(e){if(e==null||typeof e!="object")return e;try{if(Array.isArray(e))return e.length>10?`[Array(${e.length})]`:e.slice(0,10);const a=Object.keys(e);return a.length>20?`{Object(${a.length} keys)}`:(JSON.stringify(e),e)}catch{return"[Complex Object]"}}preprocessTranslationTokens(e){return e=e.replace(/(['"])(\$t:([a-zA-Z_][a-zA-Z0-9_.\-]*))\1/g,(a,r,i,l)=>`$t('${l}')`),e.replace(/(?(a.push(l),`__STRING_LITERAL_${a.length-1}__`));const i=[];return r=r.replace(/\$t:[a-zA-Z_][a-zA-Z0-9_.\-]*(?:\|[^'"\s,)]+)?/g,l=>(i.push(l),`__TRANSLATION_TOKEN_${i.length-1}__`)),r=r.replace(/([a-zA-Z_$][a-zA-Z0-9_$]*)\.(?!\?)/g,"$1?."),r=r.replace(/__TRANSLATION_TOKEN_(\d+)__/g,(l,u)=>i[parseInt(u,10)]),r=r.replace(/__STRING_LITERAL_(\d+)__/g,(l,u)=>a[parseInt(u,10)]),r}extractVariablesFromExpression(e){const a=new Set(["true","false","null","undefined","NaN","Infinity","if","else","for","while","do","switch","case","break","continue","return","function","class","const","let","var","new","delete","typeof","instanceof","this","super","import","export","default","try","catch","finally","throw","Math","Date","JSON","Array","Object","String","Number","Boolean","RegExp","Set","Map","WeakSet","WeakMap","Symbol","Promise","BigInt","Error","parseInt","parseFloat","isNaN","isFinite","encodeURI","decodeURI","encodeURIComponent","decodeURIComponent"]),r=/(?{a!==null&&clearTimeout(a),a=setTimeout(()=>{o(...r)},e)})}class QS{constructor(){$(this,"subscribers",new Set);$(this,"currentWidth",1024);$(this,"debouncedHandler",null);$(this,"isInitialized",!1);this.initialize()}initialize(){typeof window>"u"||(this.currentWidth=window.innerWidth,this.isInitialized=!0,this.debouncedHandler=JS(()=>{this.currentWidth=window.innerWidth,this.notifySubscribers()},150),window.addEventListener("resize",this.debouncedHandler))}notifySubscribers(){this.subscribers.forEach(e=>{e(this.currentWidth)})}subscribe(e){return this.subscribers.add(e),e(this.currentWidth),()=>{this.subscribers.delete(e)}}getWidth(){return this.currentWidth}parseRange(e){if(Ol.has(e))return Ol.get(e)??null;let a=null;if(Dl[e])a={...Dl[e]};else{const r=e.match(/^(-?\d*)-(-?\d*)$/);if(r){const[,i,l]=r,u=i===""?0:parseInt(i,10),d=l===""?1/0:parseInt(l,10);!isNaN(u)&&!isNaN(d)&&u<=d&&(a={min:u,max:d})}}return Ol.set(e,a),a}getMatchingKey(e,a){const r=[];for(const i of Object.keys(e)){const l=this.parseRange(i);l&&a>=l.min&&a<=l.max&&r.push({key:i,range:l,isPreset:!!Dl[i]})}return r.length===0?null:(r.sort((i,l)=>{if(i.isPreset!==l.isPreset)return i.isPreset?1:-1;const u=i.range.max-i.range.min,d=l.range.max-l.range.min;return u-d}),r[0].key)}matches(e){const a=this.parseRange(e);return a?this.currentWidth>=a.min&&this.currentWidth<=a.max:!1}clearSubscribers(){this.subscribers.clear()}destroy(){this.debouncedHandler&&typeof window<"u"&&window.removeEventListener("resize",this.debouncedHandler),this.clearSubscribers(),Ol.clear()}_setWidthForTesting(e){this.currentWidth=e,this.notifySubscribers()}}const ui=new QS,Ll=ct("ConditionEvaluator");function ZS(o){switch(o){case"true":return{value:!0};case"false":return{value:!1};case"null":return{value:null};case"undefined":return{value:void 0};default:return}}function ew(o){return/[?:|&!+\-*/<>=()]/.test(o)}function tw(o){if(!o.startsWith("{{")||!o.endsWith("}}"))return null;const e=o.slice(2,-2);let a=null,r=0;for(let i=0;i0?e[i-1]:"")!=="\\"&&((l==='"'||l==="'")&&!a?a=l:l===a&&(a=null),!a&&(l==="{"&&r++,l==="}"&&r--,r<0)))return null}return r===0?e.trim():null}function nw(o,e,a){if(!o)return!0;try{const r=tw(o);let i;if(r!==null){const l=ZS(r);l!==void 0?i=l.value:ci(r)?i=a.resolveBindings(`{{${r}}}`,e,{skipCache:!0}):ew(r)?i=a.evaluateExpression(r,e):i=a.resolve(r,e,{skipCache:!0})}else i=a.resolveBindings(o,e,{skipCache:!0});if(typeof i=="string"){const l=i.toLowerCase().trim();if(l==="false"||l==="0"||l===""||l==="null"||l==="undefined")return!1}return!!i}catch(r){return Ll.warn(`evaluateStringCondition: 조건 평가 실패: ${o}`,r),!1}}function Ml(o,e,a){if(typeof o=="string")return nw(o,e,a);if("and"in o){if(!Array.isArray(o.and)||o.and.length===0)return Ll.warn("evaluateConditionExpression: AND 그룹이 비어있습니다"),!0;for(const r of o.and)if(!Ml(r,e,a))return!1;return!0}if("or"in o){if(!Array.isArray(o.or)||o.or.length===0)return Ll.warn("evaluateConditionExpression: OR 그룹이 비어있습니다"),!1;for(const r of o.or)if(Ml(r,e,a))return!0;return!1}return Ll.warn("evaluateConditionExpression: 알 수 없는 조건 형식",o),!1}function op(o,e,a){if(!Array.isArray(o)||o.length===0)return{matched:!1,branchIndex:-1};for(let r=0;r=()[\]{}]/.test(o)}function up(o){if(!o.startsWith("{{")||!o.endsWith("}}"))return null;const e=o.slice(2,-2);let a=null,r=0;for(let i=0;i0?e[i-1]:"")!=="\\"&&((l==='"'||l==="'")&&!a?a=l:l===a&&(a=null),!a&&(l==="{"&&r++,l==="}"&&r--,r<0)))return null}return r===0?e.trim():null}function od(o,e,a){let r=o;if(o.startsWith("{{")&&o.endsWith("}}")&&(r=o.slice(2,-2).trim()),sd(r))try{return a.evaluateExpression(r,e)}catch(i){Xa.warn(`resolveIterationSource: 표현식 평가 실패: ${o}`,i);return}return a.resolve(r,e,{skipCache:!0})}function sw(o,e){const a={...o};if(e?.parentDataContext)for(const[r,i]of Object.entries(e.parentDataContext))r in a||(a[r]=i);if(e?.state){const r=a._local||{};a._local={...r,...e.state}}return e?.isolatedContext?.state&&(a._isolated=e.isolatedContext.state),a}function ld(o,e,a,r){if(!e||!Array.isArray(e)||e.length===0)return o;const i=r?.actionDispatcher??Zp(),l={...o,actions:e},u=i.bindActionsToProps(l,a,r?.componentContext);return delete u.actions,u}function dp(o,e,a,r){if(typeof o=="boolean")return o;if(!o)return!0;try{const i=up(o);let l;if(i!==null){const u=iw.get(i);u!==void 0?l=u:ci(i)?l=a.resolveBindings(`{{${i}}}`,e,{skipCache:!0}):sd(i)?l=a.evaluateExpression(i,e):l=a.resolve(i,e,{skipCache:!0})}else l=a.resolveBindings(o,e,{skipCache:!0});if(typeof l=="string"){const u=l.toLowerCase().trim();if(u==="false"||u==="0"||u===""||u==="null"||u==="undefined")return!1}return!!l}catch(i){return Xa.warn(`evaluateIfCondition: 조건 평가 실패 (컴포넌트: ${r||"unknown"}):`,i),!1}}function Xi(o,e,a,r){if(o.if!==void 0)return dp(o.if,e,a,r);if(o.condition!==void 0)return dp(o.condition,e,a,r);if(o.conditions===void 0)return!0;const i=o.conditions;try{return aw(i)?Ml(i,e,a):rw(i)?op(i,e,a).matched:(Xa.warn(`evaluateRenderCondition: 알 수 없는 conditions 형식 (컴포넌트: ${r||"unknown"})`),!0)}catch(l){return Xa.warn(`evaluateRenderCondition: conditions 평가 실패 (컴포넌트: ${r||"unknown"}):`,l),!1}}function fp(o){if(!o.responsive)return o;const e=ui.getWidth(),a=ui.getMatchingKey(o.responsive,e);if(!a)return o;const r=o.responsive[a];return{...o,props:{...o.props,...r.props},children:r.children??o.children,text:r.text??o.text,if:r.if??o.if,iteration:r.iteration??o.iteration}}function Zs(o,e,a,r,i){if(!o||o.length===0)return[];const l=i?.bindingEngine??new wn,u=i?.translationEngine??Cr.getInstance(),d=i?.translationContext??{templateId:"",locale:"ko"},f=sw(e,i?.componentContext),g=(v,S)=>{if(typeof v=="string"){if(rp(v))return sp(v);if(ip(v)){const A=[],T=v.replace(new RegExp(`${Rl}([^${Ys}]*)${Ys}`,"g"),(M,R)=>(A.push(R),`${_r}${A.length-1}${_r}`));let L=T;return/\$t:[a-zA-Z0-9._-]+/.test(T)&&(L=u.resolveTranslations(T,d,S)),L.replace(new RegExp(`${_r}(\\d+)${_r}`,"g"),(M,R)=>A[parseInt(R)])}if(v.startsWith("$t:defer:")){const A="$t:"+v.slice(9);return u.resolveTranslations(A,d,S)}if(v.startsWith("$t:"))return u.resolveTranslations(v,d,S);const E=up(v);if(E!==null){let A=!1,T=E;E.startsWith(Er)&&(A=!0,T=E.slice(Er.length));let L;if(ci(T))L=l.resolveBindings(`{{${T}}}`,S,{skipCache:!0});else if(sd(T))try{L=l.evaluateExpression(T,S)}catch(M){Xa.warn("renderItemChildren: 표현식 평가 실패:",M);return}else L=l.resolve(T,S,{skipCache:!0});return!A&&typeof L=="string"&&/\$t:[a-zA-Z0-9._-]+/.test(L)&&(L=u.resolveTranslations(L,d,S)),A&&L!=null?Js(L):L}if(v.includes("{{")){const A=l.resolveBindings(v,S,{skipCache:!0});return typeof A=="string"&&/\$t:[a-zA-Z0-9._-]+/.test(A)?u.resolveTranslations(A,d,S):A}return v}if(Array.isArray(v))return v.map(E=>g(E,S));if(v&&typeof v=="object"){const E={};for(const[A,T]of Object.entries(v))E[A]=g(T,S);return E}return v},m=(v,S)=>{if(!v)return{};const E={};for(const[A,T]of Object.entries(v))E[A]=g(T,S);return E},b=(v,S,E)=>{const A=fp(v),T=A.iteration;if(!T)return[];const L=od(T.source,E,l);if(!Array.isArray(L))return Xa.warn(`renderItemChildren: iteration.source가 배열이 아닙니다: ${T.source}`),[];const M=lp();if(M?.isEnabled()){const D=`${S}-iteration`;M.trackIteration(D,T.source,T.item_var,T.index_var,L.length)}const R=a[A.name];return R?L.flatMap((D,U)=>{const j={...E,[T.item_var]:D,[`${T.item_var}_index`]:U,...T.index_var?{[T.index_var]:U}:{}},P=Xi({if:A.if,condition:A.condition,conditions:A.conditions},j,l,A.id);if(A.if&&M?.isEnabled()){const Xe=`${S}-iter-${U}-if`;M.trackIfCondition(Xe,A.if,P,A.name)}if(!P)return[];const X=A.id?String(g(A.id,j)):void 0,ge=`${S}-iter-${U}`,Ee=i?.getRemountKey?i.getRemountKey(X,ge):ge,Ce=m(A.props,j),$e=ld(Ce,A.actions,j,{actionDispatcher:i?.actionDispatcher,componentContext:i?.componentContext});let Pe=null;return A.text!==void 0?Pe=g(A.text,j):A.children&&A.children.length>0&&(Pe=Zs(A.children,j,a,Ee,i)),M?.isEnabled()&&M.trackRender(A.name),[Ye.createElement(R,{key:Ee,...$e},Pe)]}):(Xa.warn(`renderItemChildren: 컴포넌트를 찾을 수 없습니다: ${A.name}`),[])};return o.flatMap((v,S)=>{const E=fp(v),A=E.id?String(g(E.id,f)):void 0,T=r?`${r}-${A||S}`:A||`child-${S}`,L=i?.getRemountKey?i.getRemountKey(A,T):T;if(E.iteration)return b(E,L,f);const M=Xi({if:E.if,condition:E.condition,conditions:E.conditions},f,l,E.id),R=lp();if(E.if&&R?.isEnabled()){const X=`${L}-if`;R.trackIfCondition(X,E.if,M,E.name)}if(!M)return[];const D=a[E.name];if(!D)return Xa.warn(`renderItemChildren: 컴포넌트를 찾을 수 없습니다: ${E.name}`),[];const U=m(E.props,f),j=ld(U,E.actions,f,{actionDispatcher:i?.actionDispatcher,componentContext:i?.componentContext});let P=null;return E.text!==void 0?P=g(E.text,f):E.children&&E.children.length>0&&(P=Zs(E.children,f,a,L,i)),R?.isEnabled()&&R.trackRender(E.name),[Ye.createElement(D,{key:L,...j},P)]})}function Ji(o,e,a,r){let i,l;return a instanceof wn?(i=a,l=r):(i=cp,l=a),i.resolveBindings(o,e,l)}function ow(o,e,a,r){const i=a??cp,l={skipCache:!0,...r};let u;try{u=i.resolveBindings(o.key,e,{skipCache:l.skipCache})?.toString()?.trim()??""}catch(g){Xa.warn("resolveClassMap: key 평가 실패:",o.key,g),u=""}let d="";u&&o.variants&&u in o.variants?d=o.variants[u]:o.default&&(d=o.default);const f=[];return o.base?.trim()&&f.push(o.base.trim()),d?.trim()&&f.push(d.trim()),f.join(" ")}function hp(o,e){return function(){return o.apply(e,arguments)}}const{toString:lw}=Object.prototype,{getPrototypeOf:$l}=Object,{iterator:Nl,toStringTag:gp}=Symbol,Il=(o=>e=>{const a=lw.call(e);return o[a]||(o[a]=a.slice(8,-1).toLowerCase())})(Object.create(null)),fa=o=>(o=o.toLowerCase(),e=>Il(e)===o),Hl=o=>e=>typeof e===o,{isArray:Qi}=Array,Zi=Hl("undefined");function eo(o){return o!==null&&!Zi(o)&&o.constructor!==null&&!Zi(o.constructor)&&xn(o.constructor.isBuffer)&&o.constructor.isBuffer(o)}const pp=fa("ArrayBuffer");function cw(o){let e;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?e=ArrayBuffer.isView(o):e=o&&o.buffer&&pp(o.buffer),e}const uw=Hl("string"),xn=Hl("function"),mp=Hl("number"),to=o=>o!==null&&typeof o=="object",dw=o=>o===!0||o===!1,zl=o=>{if(Il(o)!=="object")return!1;const e=$l(o);return(e===null||e===Object.prototype||Object.getPrototypeOf(e)===null)&&!(gp in o)&&!(Nl in o)},fw=o=>{if(!to(o)||eo(o))return!1;try{return Object.keys(o).length===0&&Object.getPrototypeOf(o)===Object.prototype}catch{return!1}},hw=fa("Date"),gw=fa("File"),pw=o=>!!(o&&typeof o.uri<"u"),mw=o=>o&&typeof o.getParts<"u",yw=fa("Blob"),bw=fa("FileList"),vw=o=>to(o)&&xn(o.pipe);function Sw(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}}const yp=Sw(),bp=typeof yp.FormData<"u"?yp.FormData:void 0,ww=o=>{if(!o)return!1;if(bp&&o instanceof bp)return!0;const e=$l(o);if(!e||e===Object.prototype||!xn(o.append))return!1;const a=Il(o);return a==="formdata"||a==="object"&&xn(o.toString)&&o.toString()==="[object FormData]"},Cw=fa("URLSearchParams"),[Ew,_w,Aw,xw]=["ReadableStream","Request","Response","Headers"].map(fa),Tw=o=>o.trim?o.trim():o.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function no(o,e,{allOwnKeys:a=!1}={}){if(o===null||typeof o>"u")return;let r,i;if(typeof o!="object"&&(o=[o]),Qi(o))for(r=0,i=o.length;r0;)if(i=a[r],e===i.toLowerCase())return i;return null}const di=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,Sp=o=>!Zi(o)&&o!==di;function cd(...o){const{caseless:e,skipUndefined:a}=Sp(this)&&this||{},r={},i=(l,u)=>{if(u==="__proto__"||u==="constructor"||u==="prototype")return;const d=e&&vp(r,u)||u,f=ud(r,d)?r[d]:void 0;zl(f)&&zl(l)?r[d]=cd(f,l):zl(l)?r[d]=cd({},l):Qi(l)?r[d]=l.slice():(!a||!Zi(l))&&(r[d]=l)};for(let l=0,u=o.length;l(no(e,(i,l)=>{a&&xn(i)?Object.defineProperty(o,l,{__proto__:null,value:hp(i,a),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(o,l,{__proto__:null,value:i,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:r}),o),kw=o=>(o.charCodeAt(0)===65279&&(o=o.slice(1)),o),Dw=(o,e,a,r)=>{o.prototype=Object.create(e.prototype,r),Object.defineProperty(o.prototype,"constructor",{__proto__:null,value:o,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(o,"super",{__proto__:null,value:e.prototype}),a&&Object.assign(o.prototype,a)},Ow=(o,e,a,r)=>{let i,l,u;const d={};if(e=e||{},o==null)return e;do{for(i=Object.getOwnPropertyNames(o),l=i.length;l-- >0;)u=i[l],(!r||r(u,o,e))&&!d[u]&&(e[u]=o[u],d[u]=!0);o=a!==!1&&$l(o)}while(o&&(!a||a(o,e))&&o!==Object.prototype);return e},Lw=(o,e,a)=>{o=String(o),(a===void 0||a>o.length)&&(a=o.length),a-=e.length;const r=o.indexOf(e,a);return r!==-1&&r===a},Mw=o=>{if(!o)return null;if(Qi(o))return o;let e=o.length;if(!mp(e))return null;const a=new Array(e);for(;e-- >0;)a[e]=o[e];return a},$w=(o=>e=>o&&e instanceof o)(typeof Uint8Array<"u"&&$l(Uint8Array)),Nw=(o,e)=>{const r=(o&&o[Nl]).call(o);let i;for(;(i=r.next())&&!i.done;){const l=i.value;e.call(o,l[0],l[1])}},Iw=(o,e)=>{let a;const r=[];for(;(a=o.exec(e))!==null;)r.push(a);return r},Hw=fa("HTMLFormElement"),zw=o=>o.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(a,r,i){return r.toUpperCase()+i}),ud=(({hasOwnProperty:o})=>(e,a)=>o.call(e,a))(Object.prototype),jw=fa("RegExp"),wp=(o,e)=>{const a=Object.getOwnPropertyDescriptors(o),r={};no(a,(i,l)=>{let u;(u=e(i,l,o))!==!1&&(r[l]=u||i)}),Object.defineProperties(o,r)},Uw=o=>{wp(o,(e,a)=>{if(xn(o)&&["arguments","caller","callee"].includes(a))return!1;const r=o[a];if(xn(r)){if(e.enumerable=!1,"writable"in e){e.writable=!1;return}e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+a+"'")})}})},Bw=(o,e)=>{const a={},r=i=>{i.forEach(l=>{a[l]=!0})};return Qi(o)?r(o):r(String(o).split(e)),a},Pw=()=>{},qw=(o,e)=>o!=null&&Number.isFinite(o=+o)?o:e;function Gw(o){return!!(o&&xn(o.append)&&o[gp]==="FormData"&&o[Nl])}const Vw=o=>{const e=new WeakSet,a=r=>{if(to(r)){if(e.has(r))return;if(eo(r))return r;if(!("toJSON"in r)){e.add(r);const i=Qi(r)?[]:{};return no(r,(l,u)=>{const d=a(l);!Zi(d)&&(i[u]=d)}),e.delete(r),i}}return r};return a(o)},Fw=fa("AsyncFunction"),Kw=o=>o&&(to(o)||xn(o))&&xn(o.then)&&xn(o.catch),Cp=((o,e)=>o?setImmediate:e?((a,r)=>(di.addEventListener("message",({source:i,data:l})=>{i===di&&l===a&&r.length&&r.shift()()},!1),i=>{r.push(i),di.postMessage(a,"*")}))(`axios@${Math.random()}`,[]):a=>setTimeout(a))(typeof setImmediate=="function",xn(di.postMessage)),Ww=typeof queueMicrotask<"u"?queueMicrotask.bind(di):typeof process<"u"&&process.nextTick||Cp,F={isArray:Qi,isArrayBuffer:pp,isBuffer:eo,isFormData:ww,isArrayBufferView:cw,isString:uw,isNumber:mp,isBoolean:dw,isObject:to,isPlainObject:zl,isEmptyObject:fw,isReadableStream:Ew,isRequest:_w,isResponse:Aw,isHeaders:xw,isUndefined:Zi,isDate:hw,isFile:gw,isReactNativeBlob:pw,isReactNative:mw,isBlob:yw,isRegExp:jw,isFunction:xn,isStream:vw,isURLSearchParams:Cw,isTypedArray:$w,isFileList:bw,forEach:no,merge:cd,extend:Rw,trim:Tw,stripBOM:kw,inherits:Dw,toFlatObject:Ow,kindOf:Il,kindOfTest:fa,endsWith:Lw,toArray:Mw,forEachEntry:Nw,matchAll:Iw,isHTMLForm:Hw,hasOwnProperty:ud,hasOwnProp:ud,reduceDescriptors:wp,freezeMethods:Uw,toObjectSet:Bw,toCamelCase:zw,noop:Pw,toFiniteNumber:qw,findKey:vp,global:di,isContextDefined:Sp,isSpecCompliantForm:Gw,toJSONObject:Vw,isAsyncFn:Fw,isThenable:Kw,setImmediate:Cp,asap:Ww,isIterable:o=>o!=null&&xn(o[Nl])},Yw=F.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),Xw=o=>{const e={};let a,r,i;return o&&o.split(` +`).forEach(function(u){i=u.indexOf(":"),a=u.substring(0,i).trim().toLowerCase(),r=u.substring(i+1).trim(),!(!a||e[a]&&Yw[a])&&(a==="set-cookie"?e[a]?e[a].push(r):e[a]=[r]:e[a]=e[a]?e[a]+", "+r:r)}),e};function Jw(o){let e=0,a=o.length;for(;ee;){const r=o.charCodeAt(a-1);if(r!==9&&r!==32)break;a-=1}return e===0&&a===o.length?o:o.slice(e,a)}const Qw=new RegExp("[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+","g"),Zw=new RegExp("[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+","g");function dd(o,e){return F.isArray(o)?o.map(a=>dd(a,e)):Jw(String(o).replace(e,""))}const e0=o=>dd(o,Qw),t0=o=>dd(o,Zw);function Ep(o){const e=Object.create(null);return F.forEach(o.toJSON(),(a,r)=>{e[r]=t0(a)}),e}const _p=Symbol("internals");function ao(o){return o&&String(o).trim().toLowerCase()}function jl(o){return o===!1||o==null?o:F.isArray(o)?o.map(jl):e0(String(o))}function n0(o){const e=Object.create(null),a=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let r;for(;r=a.exec(o);)e[r[1]]=r[2];return e}const a0=o=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(o.trim());function fd(o,e,a,r,i){if(F.isFunction(r))return r.call(this,e,a);if(i&&(e=a),!!F.isString(e)){if(F.isString(r))return e.indexOf(r)!==-1;if(F.isRegExp(r))return r.test(e)}}function r0(o){return o.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(e,a,r)=>a.toUpperCase()+r)}function i0(o,e){const a=F.toCamelCase(" "+e);["get","set","has"].forEach(r=>{Object.defineProperty(o,r+a,{__proto__:null,value:function(i,l,u){return this[r].call(this,e,i,l,u)},configurable:!0})})}let Cn=class{constructor(e){e&&this.set(e)}set(e,a,r){const i=this;function l(d,f,g){const m=ao(f);if(!m)throw new Error("header name must be a non-empty string");const b=F.findKey(i,m);(!b||i[b]===void 0||g===!0||g===void 0&&i[b]!==!1)&&(i[b||f]=jl(d))}const u=(d,f)=>F.forEach(d,(g,m)=>l(g,m,f));if(F.isPlainObject(e)||e instanceof this.constructor)u(e,a);else if(F.isString(e)&&(e=e.trim())&&!a0(e))u(Xw(e),a);else if(F.isObject(e)&&F.isIterable(e)){let d={},f,g;for(const m of e){if(!F.isArray(m))throw TypeError("Object iterator must return a key-value pair");d[g=m[0]]=(f=d[g])?F.isArray(f)?[...f,m[1]]:[f,m[1]]:m[1]}u(d,a)}else e!=null&&l(a,e,r);return this}get(e,a){if(e=ao(e),e){const r=F.findKey(this,e);if(r){const i=this[r];if(!a)return i;if(a===!0)return n0(i);if(F.isFunction(a))return a.call(this,i,r);if(F.isRegExp(a))return a.exec(i);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,a){if(e=ao(e),e){const r=F.findKey(this,e);return!!(r&&this[r]!==void 0&&(!a||fd(this,this[r],r,a)))}return!1}delete(e,a){const r=this;let i=!1;function l(u){if(u=ao(u),u){const d=F.findKey(r,u);d&&(!a||fd(r,r[d],d,a))&&(delete r[d],i=!0)}}return F.isArray(e)?e.forEach(l):l(e),i}clear(e){const a=Object.keys(this);let r=a.length,i=!1;for(;r--;){const l=a[r];(!e||fd(this,this[l],l,e,!0))&&(delete this[l],i=!0)}return i}normalize(e){const a=this,r={};return F.forEach(this,(i,l)=>{const u=F.findKey(r,l);if(u){a[u]=jl(i),delete a[l];return}const d=e?r0(l):String(l).trim();d!==l&&delete a[l],a[d]=jl(i),r[d]=!0}),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const a=Object.create(null);return F.forEach(this,(r,i)=>{r!=null&&r!==!1&&(a[i]=e&&F.isArray(r)?r.join(", "):r)}),a}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([e,a])=>e+": "+a).join(` +`)}getSetCookie(){return this.get("set-cookie")||[]}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(e){return e instanceof this?e:new this(e)}static concat(e,...a){const r=new this(e);return a.forEach(i=>r.set(i)),r}static accessor(e){const r=(this[_p]=this[_p]={accessors:{}}).accessors,i=this.prototype;function l(u){const d=ao(u);r[d]||(i0(i,u),r[d]=!0)}return F.isArray(e)?e.forEach(l):l(e),this}};Cn.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),F.reduceDescriptors(Cn.prototype,({value:o},e)=>{let a=e[0].toUpperCase()+e.slice(1);return{get:()=>o,set(r){this[a]=r}}}),F.freezeMethods(Cn);const s0="[REDACTED ****]";function o0(o){if(F.hasOwnProp(o,"toJSON"))return!0;let e=Object.getPrototypeOf(o);for(;e&&e!==Object.prototype;){if(F.hasOwnProp(e,"toJSON"))return!0;e=Object.getPrototypeOf(e)}return!1}function l0(o,e){const a=new Set(e.map(l=>String(l).toLowerCase())),r=[],i=l=>{if(l===null||typeof l!="object"||F.isBuffer(l))return l;if(r.indexOf(l)!==-1)return;l instanceof Cn&&(l=l.toJSON()),r.push(l);let u;if(F.isArray(l))u=[],l.forEach((d,f)=>{const g=i(d);F.isUndefined(g)||(u[f]=g)});else{if(!F.isPlainObject(l)&&o0(l))return r.pop(),l;u=Object.create(null);for(const[d,f]of Object.entries(l)){const g=a.has(d.toLowerCase())?s0:i(f);F.isUndefined(g)||(u[d]=g)}}return r.pop(),u};return i(o)}let Oe=class RS extends Error{static from(e,a,r,i,l,u){const d=new RS(e.message,a||e.code,r,i,l);return d.cause=e,d.name=e.name,e.status!=null&&d.status==null&&(d.status=e.status),u&&Object.assign(d,u),d}constructor(e,a,r,i,l){super(e),Object.defineProperty(this,"message",{__proto__:null,value:e,enumerable:!0,writable:!0,configurable:!0}),this.name="AxiosError",this.isAxiosError=!0,a&&(this.code=a),r&&(this.config=r),i&&(this.request=i),l&&(this.response=l,this.status=l.status)}toJSON(){const e=this.config,a=e&&F.hasOwnProp(e,"redact")?e.redact:void 0,r=F.isArray(a)&&a.length>0?l0(e,a):F.toJSONObject(e);return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:r,code:this.code,status:this.status}}};Oe.ERR_BAD_OPTION_VALUE="ERR_BAD_OPTION_VALUE",Oe.ERR_BAD_OPTION="ERR_BAD_OPTION",Oe.ECONNABORTED="ECONNABORTED",Oe.ETIMEDOUT="ETIMEDOUT",Oe.ECONNREFUSED="ECONNREFUSED",Oe.ERR_NETWORK="ERR_NETWORK",Oe.ERR_FR_TOO_MANY_REDIRECTS="ERR_FR_TOO_MANY_REDIRECTS",Oe.ERR_DEPRECATED="ERR_DEPRECATED",Oe.ERR_BAD_RESPONSE="ERR_BAD_RESPONSE",Oe.ERR_BAD_REQUEST="ERR_BAD_REQUEST",Oe.ERR_CANCELED="ERR_CANCELED",Oe.ERR_NOT_SUPPORT="ERR_NOT_SUPPORT",Oe.ERR_INVALID_URL="ERR_INVALID_URL",Oe.ERR_FORM_DATA_DEPTH_EXCEEDED="ERR_FORM_DATA_DEPTH_EXCEEDED";const c0=null;function hd(o){return F.isPlainObject(o)||F.isArray(o)}function Ap(o){return F.endsWith(o,"[]")?o.slice(0,-2):o}function gd(o,e,a){return o?o.concat(e).map(function(i,l){return i=Ap(i),!a&&l?"["+i+"]":i}).join(a?".":""):e}function u0(o){return F.isArray(o)&&!o.some(hd)}const d0=F.toFlatObject(F,{},null,function(e){return/^is[A-Z]/.test(e)});function Ul(o,e,a){if(!F.isObject(o))throw new TypeError("target must be an object");e=e||new FormData,a=F.toFlatObject(a,{metaTokens:!0,dots:!1,indexes:!1},!1,function(T,L){return!F.isUndefined(L[T])});const r=a.metaTokens,i=a.visitor||b,l=a.dots,u=a.indexes,d=a.Blob||typeof Blob<"u"&&Blob,f=a.maxDepth===void 0?100:a.maxDepth,g=d&&F.isSpecCompliantForm(e);if(!F.isFunction(i))throw new TypeError("visitor must be a function");function m(A){if(A===null)return"";if(F.isDate(A))return A.toISOString();if(F.isBoolean(A))return A.toString();if(!g&&F.isBlob(A))throw new Oe("Blob is not supported. Use a Buffer instead.");return F.isArrayBuffer(A)||F.isTypedArray(A)?g&&typeof Blob=="function"?new Blob([A]):Buffer.from(A):A}function b(A,T,L){let M=A;if(F.isReactNative(e)&&F.isReactNativeBlob(A))return e.append(gd(L,T,l),m(A)),!1;if(A&&!L&&typeof A=="object"){if(F.endsWith(T,"{}"))T=r?T:T.slice(0,-2),A=JSON.stringify(A);else if(F.isArray(A)&&u0(A)||(F.isFileList(A)||F.endsWith(T,"[]"))&&(M=F.toArray(A)))return T=Ap(T),M.forEach(function(D,U){!(F.isUndefined(D)||D===null)&&e.append(u===!0?gd([T],U,l):u===null?T:T+"[]",m(D))}),!1}return hd(A)?!0:(e.append(gd(L,T,l),m(A)),!1)}const v=[],S=Object.assign(d0,{defaultVisitor:b,convertValue:m,isVisitable:hd});function E(A,T,L=0){if(!F.isUndefined(A)){if(L>f)throw new Oe("Object is too deeply nested ("+L+" levels). Max depth: "+f,Oe.ERR_FORM_DATA_DEPTH_EXCEEDED);if(v.indexOf(A)!==-1)throw Error("Circular reference detected in "+T.join("."));v.push(A),F.forEach(A,function(R,D){(!(F.isUndefined(R)||R===null)&&i.call(e,R,F.isString(D)?D.trim():D,T,S))===!0&&E(R,T?T.concat(D):[D],L+1)}),v.pop()}}if(!F.isObject(o))throw new TypeError("data must be an object");return E(o),e}function xp(o){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+"};return encodeURIComponent(o).replace(/[!'()~]|%20/g,function(r){return e[r]})}function pd(o,e){this._pairs=[],o&&Ul(o,this,e)}const Tp=pd.prototype;Tp.append=function(e,a){this._pairs.push([e,a])},Tp.toString=function(e){const a=e?function(r){return e.call(this,r,xp)}:xp;return this._pairs.map(function(i){return a(i[0])+"="+a(i[1])},"").join("&")};function f0(o){return encodeURIComponent(o).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function Rp(o,e,a){if(!e)return o;const r=a&&a.encode||f0,i=F.isFunction(a)?{serialize:a}:a,l=i&&i.serialize;let u;if(l?u=l(e,i):u=F.isURLSearchParams(e)?e.toString():new pd(e,i).toString(r),u){const d=o.indexOf("#");d!==-1&&(o=o.slice(0,d)),o+=(o.indexOf("?")===-1?"?":"&")+u}return o}class kp{constructor(){this.handlers=[]}use(e,a,r){return this.handlers.push({fulfilled:e,rejected:a,synchronous:r?r.synchronous:!1,runWhen:r?r.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){F.forEach(this.handlers,function(r){r!==null&&e(r)})}}const md={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1,legacyInterceptorReqResOrdering:!0},h0={isBrowser:!0,classes:{URLSearchParams:typeof URLSearchParams<"u"?URLSearchParams:pd,FormData:typeof FormData<"u"?FormData:null,Blob:typeof Blob<"u"?Blob:null},protocols:["http","https","file","blob","url","data"]},yd=typeof window<"u"&&typeof document<"u",bd=typeof navigator=="object"&&navigator||void 0,g0=yd&&(!bd||["ReactNative","NativeScript","NS"].indexOf(bd.product)<0),p0=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function",m0=yd&&window.location.href||"http://localhost",yn={...Object.freeze(Object.defineProperty({__proto__:null,hasBrowserEnv:yd,hasStandardBrowserEnv:g0,hasStandardBrowserWebWorkerEnv:p0,navigator:bd,origin:m0},Symbol.toStringTag,{value:"Module"})),...h0};function y0(o,e){return Ul(o,new yn.classes.URLSearchParams,{visitor:function(a,r,i,l){return yn.isNode&&F.isBuffer(a)?(this.append(r,a.toString("base64")),!1):l.defaultVisitor.apply(this,arguments)},...e})}function b0(o){return F.matchAll(/\w+|\[(\w*)]/g,o).map(e=>e[0]==="[]"?"":e[1]||e[0])}function v0(o){const e={},a=Object.keys(o);let r;const i=a.length;let l;for(r=0;r=a.length;return u=!u&&F.isArray(i)?i.length:u,f?(F.hasOwnProp(i,u)?i[u]=F.isArray(i[u])?i[u].concat(r):[i[u],r]:i[u]=r,!d):((!F.hasOwnProp(i,u)||!F.isObject(i[u]))&&(i[u]=[]),e(a,r,i[u],l)&&F.isArray(i[u])&&(i[u]=v0(i[u])),!d)}if(F.isFormData(o)&&F.isFunction(o.entries)){const a={};return F.forEachEntry(o,(r,i)=>{e(b0(r),i,a,0)}),a}return null}const es=(o,e)=>o!=null&&F.hasOwnProp(o,e)?o[e]:void 0;function S0(o,e,a){if(F.isString(o))try{return(e||JSON.parse)(o),F.trim(o)}catch(r){if(r.name!=="SyntaxError")throw r}return(a||JSON.stringify)(o)}const ro={transitional:md,adapter:["xhr","http","fetch"],transformRequest:[function(e,a){const r=a.getContentType()||"",i=r.indexOf("application/json")>-1,l=F.isObject(e);if(l&&F.isHTMLForm(e)&&(e=new FormData(e)),F.isFormData(e))return i?JSON.stringify(Dp(e)):e;if(F.isArrayBuffer(e)||F.isBuffer(e)||F.isStream(e)||F.isFile(e)||F.isBlob(e)||F.isReadableStream(e))return e;if(F.isArrayBufferView(e))return e.buffer;if(F.isURLSearchParams(e))return a.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let d;if(l){const f=es(this,"formSerializer");if(r.indexOf("application/x-www-form-urlencoded")>-1)return y0(e,f).toString();if((d=F.isFileList(e))||r.indexOf("multipart/form-data")>-1){const g=es(this,"env"),m=g&&g.FormData;return Ul(d?{"files[]":e}:e,m&&new m,f)}}return l||i?(a.setContentType("application/json",!1),S0(e)):e}],transformResponse:[function(e){const a=es(this,"transitional")||ro.transitional,r=a&&a.forcedJSONParsing,i=es(this,"responseType"),l=i==="json";if(F.isResponse(e)||F.isReadableStream(e))return e;if(e&&F.isString(e)&&(r&&!i||l)){const d=!(a&&a.silentJSONParsing)&&l;try{return JSON.parse(e,es(this,"parseReviver"))}catch(f){if(d)throw f.name==="SyntaxError"?Oe.from(f,Oe.ERR_BAD_RESPONSE,this,null,es(this,"response")):f}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:yn.classes.FormData,Blob:yn.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};F.forEach(["delete","get","head","post","put","patch","query"],o=>{ro.headers[o]={}});function vd(o,e){const a=this||ro,r=e||a,i=Cn.from(r.headers);let l=r.data;return F.forEach(o,function(d){l=d.call(a,l,i.normalize(),e?e.status:void 0)}),i.normalize(),l}function Op(o){return!!(o&&o.__CANCEL__)}let io=class extends Oe{constructor(e,a,r){super(e??"canceled",Oe.ERR_CANCELED,a,r),this.name="CanceledError",this.__CANCEL__=!0}};function Lp(o,e,a){const r=a.config.validateStatus;!a.status||!r||r(a.status)?o(a):e(new Oe("Request failed with status code "+a.status,a.status>=400&&a.status<500?Oe.ERR_BAD_REQUEST:Oe.ERR_BAD_RESPONSE,a.config,a.request,a))}function w0(o){const e=/^([-+\w]{1,25}):(?:\/\/)?/.exec(o);return e&&e[1]||""}function C0(o,e){o=o||10;const a=new Array(o),r=new Array(o);let i=0,l=0,u;return e=e!==void 0?e:1e3,function(f){const g=Date.now(),m=r[l];u||(u=g),a[i]=f,r[i]=g;let b=l,v=0;for(;b!==i;)v+=a[b++],b=b%o;if(i=(i+1)%o,i===l&&(l=(l+1)%o),g-u{a=m,i=null,l&&(clearTimeout(l),l=null),o(...g)};return[(...g)=>{const m=Date.now(),b=m-a;b>=r?u(g,m):(i=g,l||(l=setTimeout(()=>{l=null,u(i)},r-b)))},()=>i&&u(i)]}const Bl=(o,e,a=3)=>{let r=0;const i=C0(50,250);return E0(l=>{if(!l||typeof l.loaded!="number")return;const u=l.loaded,d=l.lengthComputable?l.total:void 0,f=d!=null?Math.min(u,d):u,g=Math.max(0,f-r),m=i(g);r=Math.max(r,f);const b={loaded:f,total:d,progress:d?f/d:void 0,bytes:g,rate:m||void 0,estimated:m&&d?(d-f)/m:void 0,event:l,lengthComputable:d!=null,[e?"download":"upload"]:!0};o(b)},a)},Mp=(o,e)=>{const a=o!=null;return[r=>e[0]({lengthComputable:a,total:o,loaded:r}),e[1]]},$p=o=>(...e)=>F.asap(()=>o(...e)),_0=yn.hasStandardBrowserEnv?((o,e)=>a=>(a=new URL(a,yn.origin),o.protocol===a.protocol&&o.host===a.host&&(e||o.port===a.port)))(new URL(yn.origin),yn.navigator&&/(msie|trident)/i.test(yn.navigator.userAgent)):()=>!0,A0=yn.hasStandardBrowserEnv?{write(o,e,a,r,i,l,u){if(typeof document>"u")return;const d=[`${o}=${encodeURIComponent(e)}`];F.isNumber(a)&&d.push(`expires=${new Date(a).toUTCString()}`),F.isString(r)&&d.push(`path=${r}`),F.isString(i)&&d.push(`domain=${i}`),l===!0&&d.push("secure"),F.isString(u)&&d.push(`SameSite=${u}`),document.cookie=d.join("; ")},read(o){if(typeof document>"u")return null;const e=document.cookie.split(";");for(let a=0;ao instanceof Cn?{...o}:o;function fi(o,e){e=e||{};const a=Object.create(null);Object.defineProperty(a,"hasOwnProperty",{__proto__:null,value:Object.prototype.hasOwnProperty,enumerable:!1,writable:!0,configurable:!0});function r(g,m,b,v){return F.isPlainObject(g)&&F.isPlainObject(m)?F.merge.call({caseless:v},g,m):F.isPlainObject(m)?F.merge({},m):F.isArray(m)?m.slice():m}function i(g,m,b,v){if(F.isUndefined(m)){if(!F.isUndefined(g))return r(void 0,g,b,v)}else return r(g,m,b,v)}function l(g,m){if(!F.isUndefined(m))return r(void 0,m)}function u(g,m){if(F.isUndefined(m)){if(!F.isUndefined(g))return r(void 0,g)}else return r(void 0,m)}function d(g,m,b){if(F.hasOwnProp(e,b))return r(g,m);if(F.hasOwnProp(o,b))return r(void 0,g)}const f={url:l,method:l,data:l,baseURL:u,transformRequest:u,transformResponse:u,paramsSerializer:u,timeout:u,timeoutMessage:u,withCredentials:u,withXSRFToken:u,adapter:u,responseType:u,xsrfCookieName:u,xsrfHeaderName:u,onUploadProgress:u,onDownloadProgress:u,decompress:u,maxContentLength:u,maxBodyLength:u,beforeRedirect:u,transport:u,httpAgent:u,httpsAgent:u,cancelToken:u,socketPath:u,allowedSocketPaths:u,responseEncoding:u,validateStatus:d,headers:(g,m,b)=>i(Ip(g),Ip(m),b,!0)};return F.forEach(Object.keys({...o,...e}),function(m){if(m==="__proto__"||m==="constructor"||m==="prototype")return;const b=F.hasOwnProp(f,m)?f[m]:i,v=F.hasOwnProp(o,m)?o[m]:void 0,S=F.hasOwnProp(e,m)?e[m]:void 0,E=b(v,S,m);F.isUndefined(E)&&b!==d||(a[m]=E)}),a}const R0=["content-type","content-length"];function k0(o,e,a){if(a!=="content-only"){o.set(e);return}Object.entries(e).forEach(([r,i])=>{R0.includes(r.toLowerCase())&&o.set(r,i)})}const D0=o=>encodeURIComponent(o).replace(/%([0-9A-F]{2})/gi,(e,a)=>String.fromCharCode(parseInt(a,16))),Hp=o=>{const e=fi({},o),a=v=>F.hasOwnProp(e,v)?e[v]:void 0,r=a("data");let i=a("withXSRFToken");const l=a("xsrfHeaderName"),u=a("xsrfCookieName");let d=a("headers");const f=a("auth"),g=a("baseURL"),m=a("allowAbsoluteUrls"),b=a("url");if(e.headers=d=Cn.from(d),e.url=Rp(Np(g,b,m),o.params,o.paramsSerializer),f&&d.set("Authorization","Basic "+btoa((f.username||"")+":"+(f.password?D0(f.password):""))),F.isFormData(r)&&(yn.hasStandardBrowserEnv||yn.hasStandardBrowserWebWorkerEnv?d.setContentType(void 0):F.isFunction(r.getHeaders)&&k0(d,r.getHeaders(),a("formDataHeaderPolicy"))),yn.hasStandardBrowserEnv&&(F.isFunction(i)&&(i=i(e)),i===!0||i==null&&_0(e.url))){const S=l&&u&&A0.read(u);S&&d.set(l,S)}return e},O0=typeof XMLHttpRequest<"u"&&function(o){return new Promise(function(a,r){const i=Hp(o);let l=i.data;const u=Cn.from(i.headers).normalize();let{responseType:d,onUploadProgress:f,onDownloadProgress:g}=i,m,b,v,S,E;function A(){S&&S(),E&&E(),i.cancelToken&&i.cancelToken.unsubscribe(m),i.signal&&i.signal.removeEventListener("abort",m)}let T=new XMLHttpRequest;T.open(i.method.toUpperCase(),i.url,!0),T.timeout=i.timeout;function L(){if(!T)return;const R=Cn.from("getAllResponseHeaders"in T&&T.getAllResponseHeaders()),U={data:!d||d==="text"||d==="json"?T.responseText:T.response,status:T.status,statusText:T.statusText,headers:R,config:o,request:T};Lp(function(P){a(P),A()},function(P){r(P),A()},U),T=null}"onloadend"in T?T.onloadend=L:T.onreadystatechange=function(){!T||T.readyState!==4||T.status===0&&!(T.responseURL&&T.responseURL.startsWith("file:"))||setTimeout(L)},T.onabort=function(){T&&(r(new Oe("Request aborted",Oe.ECONNABORTED,o,T)),A(),T=null)},T.onerror=function(D){const U=D&&D.message?D.message:"Network Error",j=new Oe(U,Oe.ERR_NETWORK,o,T);j.event=D||null,r(j),A(),T=null},T.ontimeout=function(){let D=i.timeout?"timeout of "+i.timeout+"ms exceeded":"timeout exceeded";const U=i.transitional||md;i.timeoutErrorMessage&&(D=i.timeoutErrorMessage),r(new Oe(D,U.clarifyTimeoutError?Oe.ETIMEDOUT:Oe.ECONNABORTED,o,T)),A(),T=null},l===void 0&&u.setContentType(null),"setRequestHeader"in T&&F.forEach(Ep(u),function(D,U){T.setRequestHeader(U,D)}),F.isUndefined(i.withCredentials)||(T.withCredentials=!!i.withCredentials),d&&d!=="json"&&(T.responseType=i.responseType),g&&([v,E]=Bl(g,!0),T.addEventListener("progress",v)),f&&T.upload&&([b,S]=Bl(f),T.upload.addEventListener("progress",b),T.upload.addEventListener("loadend",S)),(i.cancelToken||i.signal)&&(m=R=>{T&&(r(!R||R.type?new io(null,o,T):R),T.abort(),A(),T=null)},i.cancelToken&&i.cancelToken.subscribe(m),i.signal&&(i.signal.aborted?m():i.signal.addEventListener("abort",m)));const M=w0(i.url);if(M&&!yn.protocols.includes(M)){r(new Oe("Unsupported protocol "+M+":",Oe.ERR_BAD_REQUEST,o));return}T.send(l||null)})},L0=(o,e)=>{if(o=o?o.filter(Boolean):[],!e&&!o.length)return;const a=new AbortController;let r=!1;const i=function(f){if(!r){r=!0,u();const g=f instanceof Error?f:this.reason;a.abort(g instanceof Oe?g:new io(g instanceof Error?g.message:g))}};let l=e&&setTimeout(()=>{l=null,i(new Oe(`timeout of ${e}ms exceeded`,Oe.ETIMEDOUT))},e);const u=()=>{o&&(l&&clearTimeout(l),l=null,o.forEach(f=>{f.unsubscribe?f.unsubscribe(i):f.removeEventListener("abort",i)}),o=null)};o.forEach(f=>f.addEventListener("abort",i));const{signal:d}=a;return d.unsubscribe=()=>F.asap(u),d},M0=function*(o,e){let a=o.byteLength;if(a{const i=$0(o,e);let l=0,u,d=f=>{u||(u=!0,r&&r(f))};return new ReadableStream({async pull(f){try{const{done:g,value:m}=await i.next();if(g){d(),f.close();return}let b=m.byteLength;if(a){let v=l+=b;a(v)}f.enqueue(new Uint8Array(m))}catch(g){throw d(g),g}},cancel(f){return d(f),i.return()}},{highWaterMark:2})};function I0(o){if(!o||typeof o!="string"||!o.startsWith("data:"))return 0;const e=o.indexOf(",");if(e<0)return 0;const a=o.slice(5,e),r=o.slice(e+1);if(/;base64/i.test(a)){let u=r.length;const d=r.length;for(let S=0;S=48&&E<=57||E>=65&&E<=70||E>=97&&E<=102)&&(A>=48&&A<=57||A>=65&&A<=70||A>=97&&A<=102)&&(u-=2,S+=2)}let f=0,g=d-1;const m=S=>S>=2&&r.charCodeAt(S-2)===37&&r.charCodeAt(S-1)===51&&(r.charCodeAt(S)===68||r.charCodeAt(S)===100);g>=0&&(r.charCodeAt(g)===61?(f++,g--):m(g)&&(f++,g-=3)),f===1&&g>=0&&(r.charCodeAt(g)===61||m(g))&&f++;const v=Math.floor(u/4)*3-(f||0);return v>0?v:0}if(typeof Buffer<"u"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(r,"utf8");let l=0;for(let u=0,d=r.length;u=55296&&f<=56319&&u+1=56320&&g<=57343?(l+=4,u++):l+=3}else l+=3}return l}const Sd="1.16.1",jp=64*1024,{isFunction:Pl}=F,Up=(o,...e)=>{try{return!!o(...e)}catch{return!1}},H0=o=>{const e=F.global!==void 0&&F.global!==null?F.global:globalThis,{ReadableStream:a,TextEncoder:r}=e;o=F.merge.call({skipUndefined:!0},{Request:e.Request,Response:e.Response},o);const{fetch:i,Request:l,Response:u}=o,d=i?Pl(i):typeof fetch=="function",f=Pl(l),g=Pl(u);if(!d)return!1;const m=d&&Pl(a),b=d&&(typeof r=="function"?(L=>M=>L.encode(M))(new r):async L=>new Uint8Array(await new l(L).arrayBuffer())),v=f&&m&&Up(()=>{let L=!1;const M=new l(yn.origin,{body:new a,method:"POST",get duplex(){return L=!0,"half"}}),R=M.headers.has("Content-Type");return M.body!=null&&M.body.cancel(),L&&!R}),S=g&&m&&Up(()=>F.isReadableStream(new u("").body)),E={stream:S&&(L=>L.body)};d&&["text","arrayBuffer","blob","formData","stream"].forEach(L=>{!E[L]&&(E[L]=(M,R)=>{let D=M&&M[L];if(D)return D.call(M);throw new Oe(`Response type '${L}' is not supported`,Oe.ERR_NOT_SUPPORT,R)})});const A=async L=>{if(L==null)return 0;if(F.isBlob(L))return L.size;if(F.isSpecCompliantForm(L))return(await new l(yn.origin,{method:"POST",body:L}).arrayBuffer()).byteLength;if(F.isArrayBufferView(L)||F.isArrayBuffer(L))return L.byteLength;if(F.isURLSearchParams(L)&&(L=L+""),F.isString(L))return(await b(L)).byteLength},T=async(L,M)=>{const R=F.toFiniteNumber(L.getContentLength());return R??A(M)};return async L=>{let{url:M,method:R,data:D,signal:U,cancelToken:j,timeout:P,onDownloadProgress:X,onUploadProgress:ge,responseType:Ee,headers:Ce,withCredentials:$e="same-origin",fetchOptions:Pe,maxContentLength:Xe,maxBodyLength:ht}=Hp(L);const Q=F.isNumber(Xe)&&Xe>-1,fe=F.isNumber(ht)&&ht>-1;let ye=i||fetch;Ee=Ee?(Ee+"").toLowerCase():"text";let te=L0([U,j&&j.toAbortSignal()],P),he=null;const x=te&&te.unsubscribe&&(()=>{te.unsubscribe()});let K;try{if(Q&&typeof M=="string"&&M.startsWith("data:")&&I0(M)>Xe)throw new Oe("maxContentLength size of "+Xe+" exceeded",Oe.ERR_BAD_RESPONSE,L,he);if(fe&&R!=="get"&&R!=="head"){const Se=await T(Ce,D);if(typeof Se=="number"&&isFinite(Se)&&Se>ht)throw new Oe("Request body larger than maxBodyLength limit",Oe.ERR_BAD_REQUEST,L,he)}if(ge&&v&&R!=="get"&&R!=="head"&&(K=await T(Ce,D))!==0){let Se=new l(M,{method:"POST",body:D,duplex:"half"}),He;if(F.isFormData(D)&&(He=Se.headers.get("content-type"))&&Ce.setContentType(He),Se.body){const[Ae,Et]=Mp(K,Bl($p(ge)));D=zp(Se.body,jp,Ae,Et)}}F.isString($e)||($e=$e?"include":"omit");const re=f&&"credentials"in l.prototype;if(F.isFormData(D)){const Se=Ce.getContentType();Se&&/^multipart\/form-data/i.test(Se)&&!/boundary=/i.test(Se)&&Ce.delete("content-type")}Ce.set("User-Agent","axios/"+Sd,!1);const de={...Pe,signal:te,method:R.toUpperCase(),headers:Ep(Ce.normalize()),body:D,duplex:"half",credentials:re?$e:void 0};he=f&&new l(M,de);let ie=await(f?ye(he,Pe):ye(M,de));if(Q){const Se=F.toFiniteNumber(ie.headers.get("content-length"));if(Se!=null&&Se>Xe)throw new Oe("maxContentLength size of "+Xe+" exceeded",Oe.ERR_BAD_RESPONSE,L,he)}const me=S&&(Ee==="stream"||Ee==="response");if(S&&ie.body&&(X||Q||me&&x)){const Se={};["status","statusText","headers"].forEach(ft=>{Se[ft]=ie[ft]});const He=F.toFiniteNumber(ie.headers.get("content-length")),[Ae,Et]=X&&Mp(He,Bl($p(X),!0))||[];let kt=0;const _t=ft=>{if(Q&&(kt=ft,kt>Xe))throw new Oe("maxContentLength size of "+Xe+" exceeded",Oe.ERR_BAD_RESPONSE,L,he);Ae&&Ae(ft)};ie=new u(zp(ie.body,jp,_t,()=>{Et&&Et(),x&&x()}),Se)}Ee=Ee||"text";let Ne=await E[F.findKey(E,Ee)||"text"](ie,L);if(Q&&!S&&!me){let Se;if(Ne!=null&&(typeof Ne.byteLength=="number"?Se=Ne.byteLength:typeof Ne.size=="number"?Se=Ne.size:typeof Ne=="string"&&(Se=typeof r=="function"?new r().encode(Ne).byteLength:Ne.length)),typeof Se=="number"&&Se>Xe)throw new Oe("maxContentLength size of "+Xe+" exceeded",Oe.ERR_BAD_RESPONSE,L,he)}return!me&&x&&x(),await new Promise((Se,He)=>{Lp(Se,He,{data:Ne,headers:Cn.from(ie.headers),status:ie.status,statusText:ie.statusText,config:L,request:he})})}catch(re){if(x&&x(),te&&te.aborted&&te.reason instanceof Oe){const de=te.reason;throw de.config=L,he&&(de.request=he),re!==de&&(de.cause=re),de}throw re&&re.name==="TypeError"&&/Load failed|fetch/i.test(re.message)?Object.assign(new Oe("Network Error",Oe.ERR_NETWORK,L,he,re&&re.response),{cause:re.cause||re}):Oe.from(re,re&&re.code,L,he,re&&re.response)}}},z0=new Map,Bp=o=>{let e=o&&o.env||{};const{fetch:a,Request:r,Response:i}=e,l=[r,i,a];let u=l.length,d=u,f,g,m=z0;for(;d--;)f=l[d],g=m.get(f),g===void 0&&m.set(f,g=d?new Map:H0(e)),m=g;return g};Bp();const wd={http:c0,xhr:O0,fetch:{get:Bp}};F.forEach(wd,(o,e)=>{if(o){try{Object.defineProperty(o,"name",{__proto__:null,value:e})}catch{}Object.defineProperty(o,"adapterName",{__proto__:null,value:e})}});const Pp=o=>`- ${o}`,j0=o=>F.isFunction(o)||o===null||o===!1;function U0(o,e){o=F.isArray(o)?o:[o];const{length:a}=o;let r,i;const l={};for(let u=0;u`adapter ${f} `+(g===!1?"is not supported by the environment":"is not available in the build"));let d=a?u.length>1?`since : `+u.map(Pp).join(` -`):" "+Pp(u[0]):"as no adapter specified";throw new Oe("There is no suitable adapter to dispatch the request "+d,"ERR_NOT_SUPPORT")}return i}const qp={getAdapter:U0,adapters:Sd};function wd(o){if(o.cancelToken&&o.cancelToken.throwIfRequested(),o.signal&&o.signal.aborted)throw new ro(null,o)}function Gp(o){return wd(o),o.headers=Cn.from(o.headers),o.data=bd.call(o,o.transformRequest),["post","put","patch"].indexOf(o.method)!==-1&&o.headers.setContentType("application/x-www-form-urlencoded",!1),qp.getAdapter(o.adapter||ao.adapter,o)(o).then(function(r){wd(o),o.response=r;try{r.data=bd.call(o,o.transformResponse,r)}finally{delete o.response}return r.headers=Cn.from(r.headers),r},function(r){if(!Op(r)&&(wd(o),r&&r.response)){o.response=r.response;try{r.response.data=bd.call(o,o.transformResponse,r.response)}finally{delete o.response}r.response.headers=Cn.from(r.response.headers)}return Promise.reject(r)})}const Pl={};["object","boolean","number","function","string","symbol"].forEach((o,e)=>{Pl[o]=function(r){return typeof r===o||"a"+(e<1?"n ":" ")+o}});const Vp={};Pl.transitional=function(e,a,r){function i(l,u){return"[Axios v"+vd+"] Transitional option '"+l+"'"+u+(r?". "+r:"")}return(l,u,d)=>{if(e===!1)throw new Oe(i(u," has been removed"+(a?" in "+a:"")),Oe.ERR_DEPRECATED);return a&&!Vp[u]&&(Vp[u]=!0,console.warn(i(u," has been deprecated since v"+a+" and will be removed in the near future"))),e?e(l,u,d):!0}},Pl.spelling=function(e){return(a,r)=>(console.warn(`${r} is likely a misspelling of ${e}`),!0)};function B0(o,e,a){if(typeof o!="object")throw new Oe("options must be an object",Oe.ERR_BAD_OPTION_VALUE);const r=Object.keys(o);let i=r.length;for(;i-- >0;){const l=r[i],u=Object.prototype.hasOwnProperty.call(e,l)?e[l]:void 0;if(u){const d=o[l],f=d===void 0||u(d,l,o);if(f!==!0)throw new Oe("option "+l+" must be "+f,Oe.ERR_BAD_OPTION_VALUE);continue}if(a!==!0)throw new Oe("Unknown option "+l,Oe.ERR_BAD_OPTION)}}const ql={assertOptions:B0,validators:Pl},Jn=ql.validators;let fi=class{constructor(e){this.defaults=e||{},this.interceptors={request:new kp,response:new kp}}async request(e,a){try{return await this._request(e,a)}catch(r){if(r instanceof Error){let i={};Error.captureStackTrace?Error.captureStackTrace(i):i=new Error;const l=(()=>{if(!i.stack)return"";const u=i.stack.indexOf(` +`):" "+Pp(u[0]):"as no adapter specified";throw new Oe("There is no suitable adapter to dispatch the request "+d,"ERR_NOT_SUPPORT")}return i}const qp={getAdapter:U0,adapters:wd};function Cd(o){if(o.cancelToken&&o.cancelToken.throwIfRequested(),o.signal&&o.signal.aborted)throw new io(null,o)}function Gp(o){return Cd(o),o.headers=Cn.from(o.headers),o.data=vd.call(o,o.transformRequest),["post","put","patch"].indexOf(o.method)!==-1&&o.headers.setContentType("application/x-www-form-urlencoded",!1),qp.getAdapter(o.adapter||ro.adapter,o)(o).then(function(r){Cd(o),o.response=r;try{r.data=vd.call(o,o.transformResponse,r)}finally{delete o.response}return r.headers=Cn.from(r.headers),r},function(r){if(!Op(r)&&(Cd(o),r&&r.response)){o.response=r.response;try{r.response.data=vd.call(o,o.transformResponse,r.response)}finally{delete o.response}r.response.headers=Cn.from(r.response.headers)}return Promise.reject(r)})}const ql={};["object","boolean","number","function","string","symbol"].forEach((o,e)=>{ql[o]=function(r){return typeof r===o||"a"+(e<1?"n ":" ")+o}});const Vp={};ql.transitional=function(e,a,r){function i(l,u){return"[Axios v"+Sd+"] Transitional option '"+l+"'"+u+(r?". "+r:"")}return(l,u,d)=>{if(e===!1)throw new Oe(i(u," has been removed"+(a?" in "+a:"")),Oe.ERR_DEPRECATED);return a&&!Vp[u]&&(Vp[u]=!0,console.warn(i(u," has been deprecated since v"+a+" and will be removed in the near future"))),e?e(l,u,d):!0}},ql.spelling=function(e){return(a,r)=>(console.warn(`${r} is likely a misspelling of ${e}`),!0)};function B0(o,e,a){if(typeof o!="object")throw new Oe("options must be an object",Oe.ERR_BAD_OPTION_VALUE);const r=Object.keys(o);let i=r.length;for(;i-- >0;){const l=r[i],u=Object.prototype.hasOwnProperty.call(e,l)?e[l]:void 0;if(u){const d=o[l],f=d===void 0||u(d,l,o);if(f!==!0)throw new Oe("option "+l+" must be "+f,Oe.ERR_BAD_OPTION_VALUE);continue}if(a!==!0)throw new Oe("Unknown option "+l,Oe.ERR_BAD_OPTION)}}const Gl={assertOptions:B0,validators:ql},Jn=Gl.validators;let hi=class{constructor(e){this.defaults=e||{},this.interceptors={request:new kp,response:new kp}}async request(e,a){try{return await this._request(e,a)}catch(r){if(r instanceof Error){let i={};Error.captureStackTrace?Error.captureStackTrace(i):i=new Error;const l=(()=>{if(!i.stack)return"";const u=i.stack.indexOf(` `);return u===-1?"":i.stack.slice(u+1)})();try{if(!r.stack)r.stack=l;else if(l){const u=l.indexOf(` `),d=u===-1?-1:l.indexOf(` `,u+1),f=d===-1?"":l.slice(d+1);String(r.stack).endsWith(f)||(r.stack+=` -`+l)}}catch{}}throw r}}_request(e,a){typeof e=="string"?(a=a||{},a.url=e):a=e||{},a=di(this.defaults,a);const{transitional:r,paramsSerializer:i,headers:l}=a;r!==void 0&&ql.assertOptions(r,{silentJSONParsing:Jn.transitional(Jn.boolean),forcedJSONParsing:Jn.transitional(Jn.boolean),clarifyTimeoutError:Jn.transitional(Jn.boolean),legacyInterceptorReqResOrdering:Jn.transitional(Jn.boolean)},!1),i!=null&&(F.isFunction(i)?a.paramsSerializer={serialize:i}:ql.assertOptions(i,{encode:Jn.function,serialize:Jn.function},!0)),a.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?a.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:a.allowAbsoluteUrls=!0),ql.assertOptions(a,{baseUrl:Jn.spelling("baseURL"),withXsrfToken:Jn.spelling("withXSRFToken")},!0),a.method=(a.method||this.defaults.method||"get").toLowerCase();let u=l&&F.merge(l.common,l[a.method]);l&&F.forEach(["delete","get","head","post","put","patch","query","common"],E=>{delete l[E]}),a.headers=Cn.concat(u,l);const d=[];let f=!0;this.interceptors.request.forEach(function(A){if(typeof A.runWhen=="function"&&A.runWhen(a)===!1)return;f=f&&A.synchronous;const T=a.transitional||pd;T&&T.legacyInterceptorReqResOrdering?d.unshift(A.fulfilled,A.rejected):d.push(A.fulfilled,A.rejected)});const g=[];this.interceptors.response.forEach(function(A){g.push(A.fulfilled,A.rejected)});let m,b=0,v;if(!f){const E=[Gp.bind(this),void 0];for(E.unshift(...d),E.push(...g),v=E.length,m=Promise.resolve(a);b{if(!r._listeners)return;let l=r._listeners.length;for(;l-- >0;)r._listeners[l](i);r._listeners=null}),this.promise.then=i=>{let l;const u=new Promise(d=>{r.subscribe(d),l=d}).then(i);return u.cancel=function(){r.unsubscribe(l)},u},e(function(l,u,d){r.reason||(r.reason=new ro(l,u,d),a(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){if(this.reason){e(this.reason);return}this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const a=this._listeners.indexOf(e);a!==-1&&this._listeners.splice(a,1)}toAbortSignal(){const e=new AbortController,a=r=>{e.abort(r)};return this.subscribe(a),e.signal.unsubscribe=()=>this.unsubscribe(a),e.signal}static source(){let e;return{token:new kS(function(i){e=i}),cancel:e}}};function q0(o){return function(a){return o.apply(null,a)}}function G0(o){return F.isObject(o)&&o.isAxiosError===!0}const Cd={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(Cd).forEach(([o,e])=>{Cd[e]=o});function Fp(o){const e=new fi(o),a=hp(fi.prototype.request,e);return F.extend(a,fi.prototype,e,{allOwnKeys:!0}),F.extend(a,e,null,{allOwnKeys:!0}),a.create=function(i){return Fp(di(o,i))},a}const Pt=Fp(ao);Pt.Axios=fi,Pt.CanceledError=ro,Pt.CancelToken=P0,Pt.isCancel=Op,Pt.VERSION=vd,Pt.toFormData=jl,Pt.AxiosError=Oe,Pt.Cancel=Pt.CanceledError,Pt.all=function(e){return Promise.all(e)},Pt.spread=q0,Pt.isAxiosError=G0,Pt.mergeConfig=di,Pt.AxiosHeaders=Cn,Pt.formToJSON=o=>Dp(F.isHTMLForm(o)?new FormData(o):o),Pt.getAdapter=qp.getAdapter,Pt.HttpStatusCode=Cd,Pt.default=Pt;const{Axios:sT,AxiosError:oT,CanceledError:lT,isCancel:cT,CancelToken:uT,VERSION:dT,all:fT,Cancel:hT,isAxiosError:gT,spread:pT,toFormData:mT,AxiosHeaders:yT,HttpStatusCode:bT,formToJSON:vT,getAdapter:ST,mergeConfig:wT,create:CT}=Pt,Ed="g7.identity.redirectStash",Gl=ct("IdentityGuardInterceptor");class St{static setLauncher(e){this.launcher=e}static hasLauncher(){return this.launcher!==null}static markDomainNoticeShown(){this.domainNoticeShown=!0}static consumeDomainNoticeShown(){const e=this.domainNoticeShown;return this.domainNoticeShown=!1,e}static resolveDeferred(e){const a=this.deferredResolver;if(!a){Gl.warn("IdentityGuardInterceptor.resolveDeferred 호출됐지만 대기 중인 launcher 가 없습니다. 모달이 launcher 외부에서 열렸는지 확인하세요.");return}this.deferredResolver=null,a(e)}static createDeferred(){if(this.deferredResolver){const e=this.deferredResolver;this.deferredResolver=null,e({status:"cancelled"})}return new Promise(e=>{this.deferredResolver=e})}static isIdentityRequired(e,a){return e===428&&typeof a=="object"&&a!==null&&a.error_code==="identity_verification_required"}static async handle(e,a,r){this.domainNoticeShown=!1;const i=this.launcher??F0,u=!!(r&&(r.email||r.phone))?{...e.verification,target:r}:e.verification,d=await i(u);if(d.status!=="verified")return null;const f=u.return_request;if(!f)return null;const g=V0(f.url,d.token);return fetch(g,{method:f.method,headers:a?.headers??{Accept:"application/json","Content-Type":"application/json"},body:a?.body,credentials:a?.credentials??"same-origin"})}static redirectExternally(e){const a=e.redirect_url;if(!a)return Gl.error("redirectExternally 호출 시 verification.redirect_url 이 없습니다. payload:",e),Promise.resolve({status:"failed",failureCode:"MISSING_REDIRECT_URL",reason:"verification.redirect_url is required for external_redirect flow"});if(typeof window<"u"){const r={return_url:window.location.href,payload:e,stashed_at:Date.now()};try{window.sessionStorage?.setItem(Ed,JSON.stringify(r))}catch(i){Gl.warn("sessionStorage 접근 실패 — stash 없이 redirect 합니다.",i)}window.location.href=a}return new Promise(()=>{})}static reset(){if(this.deferredResolver){const e=this.deferredResolver;this.deferredResolver=null;try{e({status:"cancelled"})}catch{}}this.launcher=null,this.domainNoticeShown=!1}}$(St,"launcher",null),$(St,"deferredResolver",null),$(St,"domainNoticeShown",!1);function V0(o,e){if(!e)return o;try{const a=typeof window<"u"?window.location.origin:"http://localhost",r=new URL(o,a);return r.searchParams.set("verification_token",e),/^https?:\/\//i.test(o)?r.toString():`${r.pathname}${r.search}${r.hash}`}catch{const a=o.includes("?")?"&":"?";return`${o}${a}verification_token=${encodeURIComponent(e)}`}}const F0=async o=>{if(typeof window>"u")return{status:"cancelled"};if(o.render_hint==="external_redirect"||o.redirect_url)return St.redirectExternally(o);const e=window.G7Core;if(!e?.dispatch)return console.error("[IdentityGuardInterceptor] defaultLauncher: G7Core 가 초기화되지 않아 본인인증 흐름을 시작할 수 없습니다."),{status:"failed",failureCode:"G7_NOT_READY"};try{await e.dispatch({handler:"toast",params:{message:"본인 확인이 필요합니다.",variant:"warning"}})}catch{}const a=window.location.href,r={return_url:a,payload:o,stashed_at:Date.now()};try{window.sessionStorage?.setItem(Ed,JSON.stringify(r))}catch{}const i=`/identity/challenge?return=${encodeURIComponent(a)}`;try{await e.dispatch({handler:"navigate",params:{path:i}})}catch(l){Gl.warn("navigate 실패 — window.location 으로 폴백",l),window.location.href=i}return new Promise(()=>{})},K0=ct("ApiClient");function _d(){return typeof window<"u"&&window.__G7_DEVTOOLS__?window.__G7_DEVTOOLS__:null}class W0{constructor(e={}){$(this,"client");$(this,"config");$(this,"TOKEN_KEY","auth_token");this.config={baseURL:e.baseURL||"/api",timeout:e.timeout||3e4,onTokenExpired:e.onTokenExpired,onUnauthorized:e.onUnauthorized,onError:e.onError},this.client=Pt.create({baseURL:this.config.baseURL,timeout:this.config.timeout,headers:{"Content-Type":"application/json",Accept:"application/json"},paramsSerializer:{serialize:a=>{const r=[];for(const[i,l]of Object.entries(a))if(l!=null)if(Array.isArray(l)){const u=i.endsWith("[]")?i:`${i}[]`;for(const d of l)r.push(`${encodeURIComponent(u)}=${encodeURIComponent(String(d))}`)}else r.push(`${encodeURIComponent(i)}=${encodeURIComponent(String(l))}`);return r.join("&")}}}),this.setupInterceptors()}setToken(e){typeof window<"u"&&localStorage.setItem(this.TOKEN_KEY,e)}getToken(){return typeof window<"u"?localStorage.getItem(this.TOKEN_KEY):null}removeToken(){typeof window<"u"&&localStorage.removeItem(this.TOKEN_KEY)}setupInterceptors(){this.client.interceptors.request.use(e=>{e.url?.startsWith("/api")&&e.baseURL==="/api"&&(e.baseURL="");const a=this.getToken();if(a&&e.headers&&(e.headers.Authorization=`Bearer ${a}`),typeof window<"u"&&e.headers){const i=localStorage.getItem("g7_locale");i&&(e.headers["Accept-Language"]=i)}const r=_d();if(r?.isEnabled()){const i=this.buildFullUrl(e),l=(e.method||"GET").toUpperCase(),u=r.trackRequest(i,l,{requestBody:e.data});e._devToolsRequestId=u}return e},e=>Promise.reject(e)),this.client.interceptors.response.use(e=>{const a=e.config,r=a._devToolsRequestId;if(r){const i=_d();i?.isEnabled()&&i.completeRequest(r,e.status,e.data),a._devToolsRequestId=null}return e},async e=>{const a=e.config,r=a?.url||"",l=["/auth/","/layouts/"].some(u=>r.includes(u));if(e.response?.status===401&&!a?._retry&&!l){if(a._retry=!0,await ha.getInstance().refreshToken()){const f=this.getToken();return f&&(a.headers.Authorization=`Bearer ${f}`),a._devToolsRequestId=null,this.client(a)}return this.completeDevToolsRequest(a,e),this.removeToken(),this.config.onUnauthorized&&this.config.onUnauthorized(),Promise.reject(e)}if(e.response?.status===401&&l)return this.completeDevToolsRequest(a,e),Promise.reject(e);if(St.isIdentityRequired(e.response?.status,e.response?.data)){this.completeDevToolsRequest(a,e);const u={},d=a?.headers??{};for(const[v,S]of Object.entries(d))typeof S=="string"&&(u[v]=S);let f;a?.data!==void 0&&a?.data!==null&&(f=typeof a.data=="string"?a.data:JSON.stringify(a.data),u["Content-Type"]=u["Content-Type"]??"application/json");const g=a?.identity_target,m=await St.handle(e.response.data,{headers:u,body:f,credentials:"same-origin"},g);if(!m)return Promise.reject(e);let b=null;try{b=await m.json()}catch{b=null}return m.ok?{...e.response,status:m.status,data:b}:Promise.reject(Object.assign(new Error("replay failed"),{response:{status:m.status,data:b}}))}return e.response?.status===403?(this.completeDevToolsRequest(a,e),this.callOnError(e),Promise.reject(e)):(this.completeDevToolsRequest(a,e),e.response&&this.callOnError(e),Promise.reject(e))})}async get(e,a){return(await this.client.get(e,a)).data}async post(e,a,r){return(await this.client.post(e,a,r)).data}async put(e,a,r){return(await this.client.put(e,a,r)).data}async patch(e,a,r){return(await this.client.patch(e,a,r)).data}async delete(e,a){return(await this.client.delete(e,a)).data}getInstance(){return this.client}setOnUnauthorized(e){this.config.onUnauthorized=e}setOnError(e){this.config.onError=e}completeDevToolsRequest(e,a){if(!e?._devToolsRequestId)return;const r=_d();if(!r?.isEnabled())return;const i=e._devToolsRequestId;e._devToolsRequestId=null,a.response?r.completeRequest(i,a.response.status,a.response.data):a.request?r.failRequest(i,a.message||"Network error"):r.failRequest(i,a.message||"Request error")}buildFullUrl(e){let a=e.url||"";if(e.baseURL&&!a.startsWith("http")&&(a=`${e.baseURL}${a.startsWith("/")?"":"/"}${a}`),e.params&&typeof e.params=="object"){const r=e.params,i=[];for(const[l,u]of Object.entries(r))if(u!=null)if(Array.isArray(u)){const d=l.endsWith("[]")?l:`${l}[]`;for(const f of u)i.push(`${encodeURIComponent(d)}=${encodeURIComponent(String(f))}`)}else i.push(`${encodeURIComponent(l)}=${encodeURIComponent(String(u))}`);i.length>0&&(a+=(a.includes("?")?"&":"?")+i.join("&"))}return a}callOnError(e){if(!this.config.onError)return;const a={status:e.response?.status||0,message:e.response?.data?.message||e.message||"Unknown error",data:e.response?.data,statusText:e.response?.statusText};try{this.config.onError(a)}catch(r){K0.error("Error in onError handler:",r)}}}let Ad=null;function $a(){return Ad||(Ad=new W0),Ad}const io=ct("AuthManager");function es(o,e,a,r){try{window.G7Core?.devTools?.trackAuthEvent?.(o,e,a,r)}catch{}}const Vl={admin:{type:"admin",loginPath:"/admin/login",defaultPath:"/admin",userEndpoint:"/admin/auth/user",loginEndpoint:"/auth/admin/login",logoutEndpoint:"/admin/auth/logout",refreshEndpoint:"/admin/auth/refresh"},user:{type:"user",loginPath:"/login",defaultPath:"/",userEndpoint:"/auth/user",loginEndpoint:"/auth/login",logoutEndpoint:"/auth/logout",refreshEndpoint:"/auth/refresh"}},wa=class wa{constructor(){$(this,"state");$(this,"config");$(this,"isRefreshing",!1);$(this,"refreshPromise",null);$(this,"eventHandlers",new Map);this.state={isAuthenticated:!1,user:null,type:null},this.config=new Map,this.config.set("admin",Vl.admin),this.config.set("user",Vl.user)}static getInstance(){return wa.instance||(wa.instance=new wa),wa.instance}on(e,a){this.eventHandlers.has(e)||this.eventHandlers.set(e,[]),this.eventHandlers.get(e).push(a)}emit(e,...a){const r=this.eventHandlers.get(e);r&&r.forEach(i=>i(...a))}isAuthenticated(){return this.state.isAuthenticated}getUser(){return this.state.user}getAuthType(){return this.state.type}async checkAuth(e){const a=$a();if(!a.getToken())return this.clearState(),!1;const i=this.config.get(e);if(!i)return io.error(`Unknown auth type: ${e}`),!1;try{const l=await a.get(i.userEndpoint);return l.success&&l.data?(this.state={isAuthenticated:!0,user:l.data,type:e},this.emit("authStateChange",this.state),!0):(this.clearState(),!1)}catch(l){return l.response?.status===401&&await this.refreshToken()?this.checkAuth(e):(this.clearState(),!1)}}async preloadAuth(e){try{return await this.checkAuth(e)}catch(a){return io.warn(`Preload auth failed for type ${e}:`,a),!1}}async login(e,a,r){const i=$a();if(!this.config.get(e))throw new Error(`Unknown auth type: ${e}`);const u=e==="admin"?Vl.admin.loginEndpoint:Vl.user.loginEndpoint;try{const d=r?.headers?{headers:r.headers}:void 0,f=await i.post(u,a,d);if(f.success&&f.data){i.setToken(f.data.token);const g=f.data.user.language,m=localStorage.getItem(wa.LOCALE_STORAGE_KEY),b=g&&g!==m;if(g)try{localStorage.setItem(wa.LOCALE_STORAGE_KEY,g)}catch(v){io.warn("Failed to save user language to localStorage:",v)}return this.state={isAuthenticated:!0,user:f.data.user,type:e},this.emit("login",this.state),this.emit("authStateChange",this.state),es("login",!0,void 0,{userId:f.data.user.uuid,email:f.data.user.email,type:e}),b&&window.__templateApp&&window.__templateApp.changeLocale(g),f.data.user}throw new Error("Login failed")}catch(d){this.clearState();const f=d.response?.data?.message,g=new Error(f||d.message||"Login failed");throw g.response=d.response,g.status=d.response?.status,es("login",!1,g.message,{type:e,status:d.response?.status}),g}}async logout(){const e=$a(),a=this.state.type?this.config.get(this.state.type):null;try{a&&await e.post(a.logoutEndpoint)}catch(r){io.warn("Logout API call failed:",r)}finally{e.removeToken();const r={...this.state};if(this.clearState(),this.emit("logout",r),this.emit("authStateChange",this.state),es("logout",!0,void 0,{previousType:r.type}),a&&r.type){const i=window.location.pathname+window.location.search;window.location.href=this.getLoginRedirectUrl(r.type,i)}}}async refreshToken(){if(this.isRefreshing&&this.refreshPromise)return this.refreshPromise;this.isRefreshing=!0,this.refreshPromise=this.doRefreshToken();try{return await this.refreshPromise}finally{this.isRefreshing=!1,this.refreshPromise=null}}async doRefreshToken(){const e=this.state.type;if(!e)return!1;const a=this.config.get(e);if(!a)return!1;const r=$a();try{const i=await r.post(a.refreshEndpoint);return i.success&&i.data?.token?(r.setToken(i.data.token),this.emit("tokenRefreshed"),es("token-refresh",!0,void 0,{type:e}),!0):(es("token-refresh",!1,"No token in response",{type:e}),!1)}catch(i){return io.error("Token refresh failed:",i),es("token-refresh",!1,i instanceof Error?i.message:"Unknown error",{type:e}),!1}}getLoginRedirectUrl(e,a,r){const i=this.config.get(e);if(!i)return"/login";const l=encodeURIComponent(a);let u=`${i.loginPath}?redirect=${l}`;return r&&(u+=`&reason=${encodeURIComponent(r)}`),u}updateConfig(e,a){if(a.loginPath!==void 0){const i=a.loginPath;if(!i.startsWith("/")||i.startsWith("//"))throw new Error(`AuthManager.updateConfig: loginPath must be a same-origin path starting with '/' (got: ${i})`)}const r=this.config.get(e);r&&this.config.set(e,{...r,...a})}getRedirectUrl(e){const r=this.config.get(e)?.defaultPath||"/",l=new URLSearchParams(window.location.search).get("redirect");if(l)try{const u=decodeURIComponent(l);if(u.startsWith("/"))return u}catch{}return r}getConfig(e){return this.config.get(e)}clearState(){this.state={isAuthenticated:!1,user:null,type:null}}static resetInstance(){wa.instance=null}};$(wa,"instance"),$(wa,"LOCALE_STORAGE_KEY","g7_locale");let ha=wa;const Kp={401:{handler:"navigate",params:{path:"{{auth.loginPath}}"}},403:{handler:"toast",params:{type:"error",message:"{{error.message}}"}},404:{handler:"toast",params:{type:"error",message:"{{error.message}}"}},422:{handler:"toast",params:{type:"error",message:"{{error.message}}"}},default:{handler:"toast",params:{type:"error",message:"{{error.message}}"}}},Ja={findHandler(o,e){if(o){if(o[e])return o[e];if(o[String(e)])return o[String(e)];if(o.default)return o.default}},normalizeOnError(o){return o?Array.isArray(o)?o:[o]:[]},injectErrorCode(o,e,a){if(o.handler!=="showErrorPage"||o.params?.errorCode!==void 0)return o;const r=typeof e=="string"?parseInt(e,10):e,i=isNaN(r)?a:r;return i===void 0?o:{...o,params:{...o.params,errorCode:i}}}},ga=ct("ErrorHandlingResolver"),kr=class kr{constructor(){$(this,"templateErrorHandling",null);$(this,"layoutErrorHandling",null);$(this,"executeAction",null)}static getInstance(){return kr.instance||(kr.instance=new kr),kr.instance}static resetInstance(){kr.instance=null}setTemplateConfig(e){this.templateErrorHandling=e,ga.log("Template config set:",e)}setLayoutConfig(e){this.layoutErrorHandling=e,ga.log("Layout config set:",e)}setActionExecutor(e){this.executeAction=e}resolve(e,a={}){const{errorHandling:r,onError:i}=a;ga.log("Resolving error:",e,{hasActionErrorHandling:!!r,hasActionOnError:!!i,hasLayoutConfig:!!this.layoutErrorHandling,hasTemplateConfig:!!this.templateErrorHandling});let l=Ja.findHandler(r,e);if(l){const u=this.getMatchedKey(r,e);return{handler:Ja.injectErrorCode(l,u,e),level:"action",matchedKey:u}}if(i){const u=Ja.normalizeOnError(i);if(u.length>0)return{handler:u.length===1?u[0]:{handler:"sequence",actions:u},level:"action",matchedKey:"onError"}}if(l=Ja.findHandler(this.layoutErrorHandling||void 0,e),l){const u=this.getMatchedKey(this.layoutErrorHandling,e);return{handler:Ja.injectErrorCode(l,u,e),level:"layout",matchedKey:u}}if(l=Ja.findHandler(this.templateErrorHandling||void 0,e),l){const u=this.getMatchedKey(this.templateErrorHandling,e);return{handler:Ja.injectErrorCode(l,u,e),level:"template",matchedKey:u}}if(l=Ja.findHandler(Kp,e),l){const u=this.getMatchedKey(Kp,e);return{handler:Ja.injectErrorCode(l,u,e),level:"system",matchedKey:u}}return{handler:null,level:null,matchedKey:null}}async execute(e,a){if(!this.executeAction){ga.error("Action executor is not set");return}ga.log("Executing handler:",e.handler,{errorContext:a});try{return await this.executeAction(e,{error:a})}catch(r){throw ga.error("Failed to execute handler:",r),r}}async resolveAndExecute(e,a,r={}){const i=this.resolve(e,r);if(ga.log("Resolve result:",{errorCode:e,handler:i.handler?.handler,level:i.level,matchedKey:i.matchedKey}),!i.handler)return ga.warn("No handler found for error:",e),{handled:!1};try{return{handled:!0,result:await this.execute(i.handler,a)}}catch(l){return ga.error("Handler execution failed:",l),{handled:!1}}}getMatchedKey(e,a){return e[a]?a:e[String(a)]?String(a):"default"}clearLayoutConfig(){this.layoutErrorHandling=null,ga.log("Layout config cleared")}clearAllConfig(){this.templateErrorHandling=null,this.layoutErrorHandling=null,ga.log("All config cleared")}getConfigStatus(){return{hasTemplate:this.templateErrorHandling!==null,hasLayout:this.layoutErrorHandling!==null,hasExecutor:this.executeAction!==null}}};$(kr,"instance",null);let xd=kr;function pa(){return xd.getInstance()}var Td={exports:{}},so={};var Wp;function Y0(){if(Wp)return so;Wp=1;var o=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function a(r,i,l){var u=null;if(l!==void 0&&(u=""+l),i.key!==void 0&&(u=""+i.key),"key"in i){l={};for(var d in i)d!=="key"&&(l[d]=i[d])}else l=i;return i=l.ref,{$$typeof:o,type:r,key:u,ref:i!==void 0?i:null,props:l}}return so.Fragment=e,so.jsx=a,so.jsxs=a,so}var Yp;function X0(){return Yp||(Yp=1,Td.exports=Y0()),Td.exports}var ut=X0();const J0=Wa({__proto__:null,default:Ya(ut)},[ut]),Rd=ct("ParentContextProvider"),Xp=N.createContext(null);let Fl=null;function kd(){Fl?(Rd.log("[triggerModalParentUpdate] 모달 부모 컨텍스트 업데이트 트리거"),Fl()):Rd.warn("[triggerModalParentUpdate] Provider가 아직 마운트되지 않음")}const Jp=({children:o})=>{const[e,a]=N.useState(0),r=N.useRef(!0),i=N.useCallback(()=>{const u=window.__g7LayoutContextStack||[];return u[u.length-1]?.dataContext},[]);N.useEffect(()=>(r.current=!0,Fl=()=>{r.current&&(a(u=>u+1),Rd.log("[ParentContextProvider] 버전 업데이트됨"))},()=>{r.current=!1,Fl=null}),[]);const l={version:e,getParentDataContext:i};return ut.jsx(Xp.Provider,{value:l,children:o})};function Q0(){return N.useContext(Xp)}const H=ct("ActionDispatcher"),Qp=new Set(["navigate","navigateBack","navigateForward","replaceUrl","refresh","logout"]),Z0=new Set(["redirect"]);function Un(){try{return window.G7Core?.devTools}catch{return}}class It extends Error{constructor(a,r,i){super(a);$(this,"action");$(this,"originalError");$(this,"unknownHandler",!1);this.action=r,this.originalError=i,this.name="ActionError"}}const cs=class cs{constructor(e={},a,r){$(this,"bindingEngine");$(this,"translationEngine");$(this,"translationContext");$(this,"customHandlers",new Map);$(this,"defaultContext");$(this,"globalStateUpdater");$(this,"errorHandlingSetup",!1);$(this,"debounceTimers",new Map);$(this,"pendingDebounceFlushers",new Map);$(this,"debounceAccumulatedValues",new Map);$(this,"globalHeaders",[]);$(this,"namedActions",{});$(this,"previewMode",!1);$(this,"intervals",new Map);this.bindingEngine=new wn,this.translationEngine=a,this.translationContext=r,this.defaultContext=e,this.registerDefaultHandlers(),this.setupErrorHandling()}setGlobalHeaders(e){this.globalHeaders=e||[]}setNamedActions(e){this.namedActions=e||{};const a=Un();a?.isEnabled?.()&&a.setNamedActionDefinitions?.(this.namedActions),H.log("[setNamedActions] registered:",Object.keys(this.namedActions))}getNamedActions(){return this.namedActions}setPreviewMode(e){this.previewMode=e,H.log("Preview mode:",e?"enabled":"disabled")}isPreviewMode(){return this.previewMode}static getPreviewSuppressedHandlers(){return Qp}static getPreviewSuppressedLayoutFeatures(){return Z0}resolveActionRef(e){if(!e.actionRef)return e;const a=this.namedActions[e.actionRef];if(!a)return H.warn(`[resolveActionRef] named action not found: "${e.actionRef}"`),e;const r=Un();r?.isEnabled?.()&&r.trackNamedActionRef?.({actionRefName:e.actionRef,resolvedHandler:a.handler,timestamp:Date.now()});const{actionRef:i,type:l,key:u,event:d,...f}=e,g={...a,...Object.fromEntries(Object.entries(f).filter(([,m])=>m!==void 0)),type:l??a.type};return u!==void 0&&(g.key=u),d!==void 0&&(g.event=d),g}matchesPattern(e,a){if(a==="*")return!0;const r=a.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${r}$`).test(e)}getMatchingGlobalHeaders(e,a){const r={};for(const i of this.globalHeaders)this.matchesPattern(e,i.pattern)&&Object.entries(i.headers).forEach(([l,u])=>{const d=Xi(u,a,{skipCache:!0});d!=null&&d!==""&&(r[l]=String(d))});return r}setupErrorHandling(){if(this.errorHandlingSetup)return;pa().setActionExecutor(async(a,r)=>{const i={type:"click",handler:a.handler,target:a.target,params:a.params,actions:a.actions},l={data:{...this.defaultContext.data,error:r.error}};return await this.dispatchAction(i,l)}),this.errorHandlingSetup=!0}registerDefaultHandlers(){this.registerHandler("refetchDataSource",async(a,r)=>{const i=a.params?.dataSourceId,l=a.params?.sync;if(!i){H.warn("refetchDataSource: dataSourceId is required");return}if(typeof window<"u"&&window.G7Core?.dataSource?.refetch){const u=window.G7Core?.state?.get?.()||{},d={...r.state?._global,...u},f=window.G7Core?.state?.getLocal?.()||{},g=r.data?._local||r.state||{},m={...f,...g},b=r.isolatedContext?.state;H.log("[refetchDataSource] localStateOverride:",m),await window.G7Core.dataSource.refetch(i,{...l?{sync:!0}:{},...d?{globalStateOverride:d}:{},...m?{localStateOverride:m}:{},...b?{isolatedStateOverride:b}:{}})}else H.warn("refetchDataSource: G7Core.dataSource.refetch is not available")}),this.registerHandler("appendDataSource",async(a,r)=>{const{dataSourceId:i,dataPath:l,newData:u}=a.params||{};if(!i){H.warn("appendDataSource: dataSourceId is required");return}if(u===void 0){H.warn("appendDataSource: newData is required");return}if(typeof window<"u"&&window.G7Core?.dataSource?.updateData){if(!Array.isArray(u)){H.warn("appendDataSource: newData must be an array, got:",typeof u,u);return}await window.G7Core.dataSource.updateData(i,l||null,u,"append")}else H.warn("appendDataSource: G7Core.dataSource.updateData is not available")}),this.registerHandler("updateDataSource",async(a,r)=>{const{dataSourceId:i,data:l,merge:u=!1}=a.params||{};if(!i){H.warn("updateDataSource: dataSourceId is required");return}if(l===void 0){H.warn("updateDataSource: data is required");return}typeof window<"u"&&window.G7Core?.dataSource?.set?(H.log(`[updateDataSource] Updating dataSource '${i}' with:`,l),window.G7Core.dataSource.set(i,l,{merge:u})):H.warn("updateDataSource: G7Core.dataSource.set is not available")}),this.registerHandler("scrollIntoView",async(a,r)=>{const{selector:i,behavior:l="smooth",block:u="nearest",inline:d="nearest",waitForElement:f=!1,timeout:g=2e3,delay:m=0,retryCount:b=0,retryInterval:v=50,scrollContainer:S}=a.params||{};if(!i){H.warn("scrollIntoView: selector is required");return}if(typeof window>"u"||typeof document>"u"){H.warn("scrollIntoView: window/document is not available");return}let E=null;if(f){if(E=await new Promise(A=>{const T=document.querySelector(i);if(T){A(T);return}const L=setTimeout(()=>{M.disconnect(),A(null)},g),M=new MutationObserver(()=>{const R=document.querySelector(i);R&&(clearTimeout(L),M.disconnect(),A(R))});M.observe(document.body,{childList:!0,subtree:!0})}),!E){H.warn(`scrollIntoView: element not found for selector "${i}" after ${g}ms timeout`);return}}else{m>0&&await new Promise(T=>setTimeout(T,m)),E=document.querySelector(i);let A=0;for(;!E&&AsetTimeout(T,v)),E=document.querySelector(i),A++;if(!E){H.warn(`scrollIntoView: element not found for selector "${i}" after ${A+1} attempts`);return}}if(S){const A=document.querySelector(S);if(!A){H.warn(`scrollIntoView: container not found for selector "${S}"`);return}const T=E.getBoundingClientRect(),L=A.getBoundingClientRect(),M=T.top-L.top+A.scrollTop,R=M+T.height;let D;switch(u){case"start":D=M;break;case"center":D=M-A.clientHeight/2+T.height/2;break;case"end":D=R-A.clientHeight;break;default:const U=T.topL.bottom;if(U)D=M;else if(j)D=R-A.clientHeight;else return;break}A.scrollTo({top:Math.max(0,D),behavior:l});return}E.scrollIntoView({behavior:l,block:u,inline:d})}),this.registerHandler("reloadExtensions",async(a,r)=>{if(typeof window>"u"){H.warn("reloadExtensions: window is not available");return}const i=window.__templateApp;if(!i){H.warn("reloadExtensions: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState()}catch(d){throw H.error("reloadExtensions: reloadExtensionState failed",d),d}else H.warn("reloadExtensions: TemplateApp.reloadExtensionState unavailable");const{moduleInfo:l,pluginInfo:u}=a.params||{};if(l)try{await this.executeAction({handler:"reloadModuleHandlers",params:a.params},r)}catch(d){H.error("reloadExtensions: reloadModuleHandlers failed",d)}if(u)try{await this.executeAction({handler:"reloadPluginHandlers",params:a.params},r)}catch(d){H.error("reloadExtensions: reloadPluginHandlers failed",d)}H.log("reloadExtensions: done")}),this.registerHandler("reloadRoutes",async(a,r)=>{if(typeof window>"u"){H.warn("reloadRoutes: window is not available");return}const i=window.__templateApp;if(!i){H.warn("reloadRoutes: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState(),H.log("reloadRoutes: delegated to reloadExtensionState")}catch(l){throw H.error("reloadRoutes: Failed to reload routes",l),l}else{const l=i.getRouter?.();l&&(await l.loadRoutes(),H.log("reloadRoutes: Routes reloaded (legacy fallback)"))}}),this.registerHandler("refresh",async(a,r)=>{if(typeof window>"u"){H.warn("refresh: window is not available");return}const i=Number(a.params?.delayMs??0);i>0&&await new Promise(l=>setTimeout(l,i)),window.location.reload()}),this.registerHandler("remount",async(a,r)=>{const{componentId:i}=a.params||{};if(!i){H.warn("remount: componentId parameter is required");return}if(!this.globalStateUpdater){H.warn("remount: globalStateUpdater is not set");return}const d=(window.G7Core?.state?.get()||{})._global?._remountKeys||{},f=d[i]||0;this.globalStateUpdater({_remountKeys:{...d,[i]:f+1}}),H.log(`remount: ${i} key incremented to ${f+1}`)}),this.registerHandler("reloadTranslations",async(a,r)=>{if(typeof window>"u"){H.warn("reloadTranslations: window is not available");return}const i=window.__templateApp;if(!i){H.warn("reloadTranslations: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState(),H.log("reloadTranslations: delegated to reloadExtensionState")}catch(l){throw H.error("reloadTranslations: Failed to reload translations",l),l}}),this.registerHandler("reloadModuleHandlers",async(a,r)=>{if(typeof window>"u"){H.warn("reloadModuleHandlers: window is not available");return}const{moduleInfo:i,action:l}=a.params||{};if(!i){H.warn("reloadModuleHandlers: moduleInfo is required");return}const u=i.data||i;if(!u.identifier){H.warn("reloadModuleHandlers: moduleInfo with identifier is required");return}if(!l||l!=="add"&&l!=="remove"){H.warn('reloadModuleHandlers: action must be "add" or "remove"');return}const d=window.G7Config;if(!d){H.warn("reloadModuleHandlers: G7Config not available");return}const f=u.identifier;try{if(l==="add"){if(u.assets&&(d.moduleAssets=d.moduleAssets||{},d.moduleAssets[f]=u.assets,H.log(`reloadModuleHandlers: Added assets for ${f}`),u.assets.js)){const g=u.assets.js,m=`module-${f}`;if(document.getElementById(m)){H.warn(`reloadModuleHandlers: Script ${m} already loaded`);return}const b=document.createElement("script");if(b.id=m,b.src=g,b.async=!0,await new Promise((v,S)=>{b.onload=()=>{H.log(`reloadModuleHandlers: Script loaded successfully for ${f}`),v()},b.onerror=()=>{H.error(`reloadModuleHandlers: Failed to load script for ${f}`),S(new Error(`Failed to load module script: ${g}`))},document.head.appendChild(b)}),u.assets.css){const v=u.assets.css,S=`module-css-${f}`;if(!document.getElementById(S)){const E=document.createElement("link");E.id=S,E.rel="stylesheet",E.href=v,document.head.appendChild(E),H.log(`reloadModuleHandlers: CSS loaded for ${f}`)}}}}else if(l==="remove"){d.moduleAssets&&d.moduleAssets[f]&&(delete d.moduleAssets[f],H.log(`reloadModuleHandlers: Removed assets for ${f}`));const g=`module-${f}`,m=document.getElementById(g);m&&(m.remove(),H.log(`reloadModuleHandlers: Removed script for ${f}`));const b=`module-css-${f}`,v=document.getElementById(b);v&&(v.remove(),H.log(`reloadModuleHandlers: Removed CSS for ${f}`))}}catch(g){throw H.error(`reloadModuleHandlers: Failed to ${l} module assets`,g),g}}),this.registerHandler("reloadPluginHandlers",async(a,r)=>{if(typeof window>"u"){H.warn("reloadPluginHandlers: window is not available");return}const{pluginInfo:i,action:l}=a.params||{};if(!i){H.warn("reloadPluginHandlers: pluginInfo is required");return}const u=i.data||i;if(!u.identifier){H.warn("reloadPluginHandlers: pluginInfo with identifier is required");return}if(!l||l!=="add"&&l!=="remove"){H.warn('reloadPluginHandlers: action must be "add" or "remove"');return}const d=window.G7Config;if(!d){H.warn("reloadPluginHandlers: G7Config not available");return}const f=u.identifier;try{if(l==="add"){if(u.assets&&(d.pluginAssets=d.pluginAssets||{},d.pluginAssets[f]=u.assets,H.log(`reloadPluginHandlers: Added assets for ${f}`),u.assets.js)){const g=u.assets.js,m=`plugin-${f}`;if(document.getElementById(m)){H.warn(`reloadPluginHandlers: Script ${m} already loaded`);return}const b=document.createElement("script");if(b.id=m,b.src=g,b.async=!0,await new Promise((v,S)=>{b.onload=()=>{H.log(`reloadPluginHandlers: Script loaded successfully for ${f}`),v()},b.onerror=()=>{H.error(`reloadPluginHandlers: Failed to load script for ${f}`),S(new Error(`Failed to load plugin script: ${g}`))},document.head.appendChild(b)}),u.assets.css){const v=u.assets.css,S=`plugin-css-${f}`;if(!document.getElementById(S)){const E=document.createElement("link");E.id=S,E.rel="stylesheet",E.href=v,document.head.appendChild(E),H.log(`reloadPluginHandlers: CSS loaded for ${f}`)}}}}else if(l==="remove"){d.pluginAssets&&d.pluginAssets[f]&&(delete d.pluginAssets[f],H.log(`reloadPluginHandlers: Removed assets for ${f}`));const g=`plugin-${f}`,m=document.getElementById(g);m&&(m.remove(),H.log(`reloadPluginHandlers: Removed script for ${f}`));const b=`plugin-css-${f}`,v=document.getElementById(b);v&&(v.remove(),H.log(`reloadPluginHandlers: Removed CSS for ${f}`))}}catch(g){throw H.error(`reloadPluginHandlers: Failed to ${l} plugin assets`,g),g}});let e=!1;this.registerHandler("showErrorPage",async(a,r)=>{if(e){H.log("showErrorPage: Already active, skipping duplicate call");return}if(e=!0,typeof window>"u"){e=!1,H.warn("showErrorPage: window is not available");return}const i=window.__templateApp;if(!i){e=!1,H.warn("showErrorPage: TemplateApp not initialized");return}const l=i.getErrorPageHandler?.();if(!l){e=!1,H.warn("showErrorPage: ErrorPageHandler not available");return}const u=a.params?.errorCode||500,d=a.params?.target||"content";let f=a.params?.containerId;f||(f=d==="full"?"app":"main_content"),H.log("showErrorPage:",{errorCode:u,target:d,containerId:f});const g=(m,b=6e4)=>new Promise((v,S)=>{const E=document.getElementById(m);if(E){v(E);return}H.log(`showErrorPage: Waiting for container #${m}...`);let A;const T=new MutationObserver((L,M)=>{const R=document.getElementById(m);R&&(H.log(`showErrorPage: Container #${m} found`),M.disconnect(),clearTimeout(A),v(R))});T.observe(document.body,{childList:!0,subtree:!0}),A=setTimeout(()=>{T.disconnect(),S(new Error(`Container #${m} not found within ${b}ms`))},b)});try{await g(f);const m=pa(),b=m.layoutErrorHandling;m.clearLayoutConfig();try{await l.renderError(u,f)||H.warn(`showErrorPage: Failed to render error page for code ${u}`)}finally{m.setLayoutConfig(b)}}catch(m){throw H.error("showErrorPage: Error rendering error page:",m),m}finally{e=!1}}),this.registerHandler("emitEvent",async(a,r)=>{const i=a.params?.event,l=a.params?.data;if(!i){H.warn("emitEvent: event parameter is required");return}if(typeof window>"u"){H.warn("emitEvent: window is not available");return}const u=window.G7Core;if(!u?.componentEvent?.emit){H.warn("emitEvent: G7Core.componentEvent is not available");return}try{H.log(`emitEvent: Emitting "${i}"`,l);const d={...l,_context:{data:r.data,state:r.state}},f=await u.componentEvent.emit(i,d);if(!f||f.length===0?H.warn(`emitEvent: No listeners found for "${i}"`):H.log(`emitEvent: Event "${i}" completed with ${f.length} listener(s)`,f),this.globalStateUpdater){const g=(u?.state?.get()||{})._local||{},m={event:i,success:!0,data:f.length===1?f[0]:f,listeners:f.length};this.globalStateUpdater({_local:{...g,_eventResult:m}});const b=r.state&&typeof r.state=="object"&&!Array.isArray(r.state)?r.state:g;window.__g7SequenceLocalSync={...b,_eventResult:m}}}catch(d){if(H.error(`emitEvent: Event "${i}" failed`,d),this.globalStateUpdater){const f=u?.state?.get()||{};this.globalStateUpdater({_local:{...f._local,_eventResult:{event:i,success:!1,error:d instanceof Error?d.message:String(d)}}})}throw d}}),this.registerHandler("updateProductField",async(a,r)=>{const{productId:i,field:l,value:u}=a.params||{};if(!i||!l){H.warn("updateProductField: productId and field are required");return}if(typeof window>"u"){H.warn("updateProductField: window is not available");return}const d=window.G7Core;if(!d?.state?.get||!this.globalStateUpdater){H.warn("updateProductField: G7Core.state or globalStateUpdater is not available");return}try{const f=d.state.get()||{},m=(f.products?.data?.data||[]).map(v=>v.id===i?{...v,[l]:u,_modified:!0}:v),b=new Set(f._local?.modifiedProductIds||[]);b.add(i),this.globalStateUpdater({products:{...f.products,data:{...f.products?.data,data:m}},_local:{...f._local,modifiedProductIds:Array.from(b)}}),H.log(`updateProductField: Updated product ${i}, field: ${l}, value:`,u)}catch(f){throw H.error("updateProductField: Error updating product field",f),f}}),this.registerHandler("updateOptionField",async(a,r)=>{const{productId:i,optionId:l,field:u,value:d}=a.params||{};if(!i||!l||!u){H.warn("updateOptionField: productId, optionId and field are required");return}if(typeof window>"u"){H.warn("updateOptionField: window is not available");return}const f=window.G7Core;if(!f?.state?.get||!this.globalStateUpdater){H.warn("updateOptionField: G7Core.state or globalStateUpdater is not available");return}try{const g=f.state.get()||{},b=(g.products?.data?.data||[]).map(S=>{if(S.id===i&&S.options){const E=S.options.map(A=>A.id===l?{...A,[u]:d,_modified:!0}:A);return{...S,options:E,_modified:!0}}return S}),v=new Set(g._local?.modifiedProductIds||[]);v.add(i),this.globalStateUpdater({products:{...g.products,data:{...g.products?.data,data:b}},_local:{...g._local,modifiedProductIds:Array.from(v)}}),H.log(`updateOptionField: Updated product ${i} option ${l}, field: ${u}, value:`,d)}catch(g){throw H.error("updateOptionField: Error updating option field",g),g}}),this.registerHandler("setLocale",async(a,r)=>{const i=a.target;if(!i||typeof i!="string"){H.warn("setLocale: Invalid locale:",i);return}const l=window.__templateApp;if(l&&typeof l.changeLocale=="function")try{await l.changeLocale(i),H.log("setLocale: Locale changed to",i)}catch(u){H.error("setLocale: Failed to change locale:",u),window.location.reload()}else{H.warn("setLocale: TemplateApp not found, falling back to page reload");try{localStorage.setItem("g7_locale",i)}catch{}window.location.reload()}}),this.registerHandler("suppress",async()=>{H.log("suppress: Error intentionally suppressed")}),this.registerBuiltInHandlerMetadata()}registerBuiltInHandlerMetadata(){const e=Un();if(!e?.isEnabled())return;const a=[{name:"refetchDataSource",description:"데이터 소스를 다시 fetch합니다"},{name:"appendDataSource",description:"데이터 소스에 새 데이터를 병합합니다 (무한 스크롤용)"},{name:"updateDataSource",description:"API 응답으로 데이터 소스를 직접 업데이트합니다 (refetch 대체)"},{name:"reloadRoutes",description:"라우트를 다시 로드합니다"},{name:"refresh",description:"현재 페이지를 새로고침합니다"},{name:"remount",description:"컴포넌트를 리마운트합니다"},{name:"reloadTranslations",description:"다국어 파일을 다시 로드합니다"},{name:"showErrorPage",description:"에러 페이지를 표시합니다"},{name:"emitEvent",description:"이벤트를 발생시킵니다"},{name:"updateProductField",description:"상품 필드를 인라인 수정합니다"},{name:"updateOptionField",description:"상품 옵션 필드를 인라인 수정합니다"},{name:"setLocale",description:"언어를 변경합니다 (DB 저장 + UI 리렌더링)"}];for(const r of a)e.trackHandlerRegistration(r.name,"built-in",r.description)}createHandler(e,a,r){H.log("createHandler called for:",e.handler,e.type);const i=window.__g7DevTools,l=Date.now(),u=r?.state?{...r.state}:null,d=`handler_${e.handler}_${l}`;return async f=>{if(H.log("Handler invoked for:",e.handler,"event:",f.type),i?.isEnabled?.()&&u){const m=window.G7Core?.state?.getLocal?.()??r?.state??{},b=Date.now()-l;for(const v of Object.keys(u)){const S=u[v],E=m[v];S!==E&&b>100&&(i.trackStaleClosureWarning?.({type:"event-handler-stale",location:`createHandler(${e.handler})`,capturedPath:`_local.${v}`,capturedValue:S,capturedAt:l,currentValue:E,actionId:d,stackTrace:new Error().stack}),H.warn(`[Stale Closure] _local.${v} changed after handler creation:`,`captured="${S}" → current="${E}" (${b}ms ago)`))}}try{f.type!=="change"&&f.preventDefault();let g={};if(f.type==="submit"&&f.target instanceof HTMLFormElement){const v=f.target;new FormData(v).forEach((E,A)=>{g[A]=E})}const m={...this.defaultContext,data:{...a,form:g,_local:r?.state||{},$event:f},event:f,...r&&{state:r.state,setState:r.setState},isolatedContext:r?.isolatedContext};if(e.confirm){let v=this.resolveValue(e.confirm,m.data);if(this.translationEngine&&this.translationContext&&v.startsWith("$t:")&&(v=this.translationEngine.resolveTranslations(v,this.translationContext,m.data)),!confirm(v))return}const b=window.__g7ActionContext;window.__g7ActionContext={...r,data:m.data};try{await this.executeAction(e,m)}finally{window.__g7ActionContext=b}}catch(g){if(H.error("Action execution failed:",g),e.onError){const m=g instanceof It&&g.originalError?g.originalError:g,b={...this.defaultContext,data:{...a,error:m,_local:r?.state||{},$event:f},event:f,...r&&{state:r.state,setState:r.setState}},v=Array.isArray(e.onError)?e.onError:[e.onError];for(const S of v)await this.executeAction(S,b)}}}}generateActionId(e,a){const r=e.handler,i=a||"no-target",l=Date.now(),u=Math.random().toString(36).substring(2,9);return`${r}_${i.replace(/[^a-zA-Z0-9]/g,"_")}_${l}_${u}`}async executeAction(e,a){if(e=this.resolveActionRef(e),typeof e.handler=="string"&&e.handler.includes("{{")){const f=this.evaluateExpression(e.handler,a.data);e={...e,handler:f==null?"":String(f)}}const r=Un(),i=r?.isEnabled()?`action_${Date.now()}_${Math.random().toString(36).substring(2,11)}`:void 0,l=performance.now();let u;if(i&&r&&r.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),context:this.sanitizeForDevTools({hasState:!!a.state,hasSetState:!!a.setState,dataKeys:a.data?Object.keys(a.data):[]}),startTime:l,status:"started"}),e.if!==void 0)try{const f=this.resolveValue(e.if,a.data),g=f===!0||f==="true"||f&&f!=="false"&&f!=="0"&&f!==!1;if(H.log("[executeAction] if condition result:",e.handler,g),!g)return i&&r&&r.logAction({id:i,type:e.handler,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"success",result:{skipped:!0,reason:"if condition false"}}),{success:!0,data:void 0}}catch(f){return H.error("[executeAction] if condition error:",e.handler,f),i&&r&&r.logAction({id:i,type:e.handler,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"error",error:{name:"ConditionEvaluationError",message:f instanceof Error?f.message:String(f),stack:f instanceof Error?f.stack:void 0}}),{success:!0,data:void 0}}let d;try{const f=this.resolveParams(e.params,a.data);i&&(u=this.sanitizeForDevTools(f));const g=e.target?this.resolveValue(e.target,a.data):void 0;if(e.handler==="apiCall"&&a.setState){d=this.generateActionId(e,g);const b=a.state?.loadingActions||{};a.setState({loadingActions:{...b,[d]:!0}})}if(this.previewMode&&Qp.has(e.handler))return H.warn(`Preview mode: "${e.handler}" suppressed`,g||f),i&&r&&r.logAction({id:i,type:e.handler,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"skipped",metadata:{reason:"preview_mode_suppressed"}}),{success:!0,data:void 0};let m;switch(e.handler){case"ensureIdentityVerified":m=await this.handleEnsureIdentityVerified(f);break;case"resolveIdentityChallenge":m=this.handleResolveIdentityChallenge(f);break;case"navigate":const b=f.path||g;m=await this.handleNavigate(b,f,a);break;case"navigateBack":m=await this.handleNavigateBack();break;case"navigateForward":m=await this.handleNavigateForward();break;case"openWindow":{const E=f.path||g;m=await this.handleOpenWindow(E,f);break}case"replaceUrl":{const E=f.path||g||window.location.pathname;m=await this.handleReplaceUrl(E,f);break}case"apiCall":if(e.onSuccess&&r?.isEnabled()&&i){const E=window.G7Core,A={};if(E?.state?.get){const T=E.state.get();A._global=T}a.state&&(A._local=a.state),r.registerStateCaptureForHandler?.(i,["_global","_local"],A)}const v=e.auth_mode??(e.auth_required?"required":"none"),S=e.identity_target?this.resolveParams(e.identity_target,a.data):void 0;m=await this.handleApiCall(g,f,a,v,S);break;case"login":m=await this.handleLogin(g,f,a);break;case"logout":m=await this.handleLogout(g,a);break;case"setState":H.log("[executeAction] setState resolvedParams:",f),m=await this.handleSetState(e.render!==void 0?{...f,__render:e.render}:f,a);break;case"setError":m=await this.handleSetError(g,f,a);break;case"openModal":m=await this.handleOpenModal(g,a);break;case"closeModal":m=await this.handleCloseModal(a);break;case"showAlert":m=await this.handleShowAlert(g,a);break;case"toast":m=await this.handleToast(f,a);break;case"switch":m=await this.handleSwitch(e,a);break;case"conditions":m=await this.handleConditions(e,a);break;case"sequence":m=await this.handleSequence(e,a);break;case"parallel":m=await this.handleParallel(e,a);break;case"startInterval":m=this.handleStartInterval(f,a);break;case"stopInterval":m=this.handleStopInterval(f);break;case"loadScript":m=await this.handleLoadScript(f,e,a);break;case"callExternal":m=await this.handleCallExternal(f,e,a);break;case"callExternalEmbed":m=await this.handleCallExternalEmbed(f,e,a);break;case"saveToLocalStorage":m=await this.handleSaveToLocalStorage(f,a);break;case"loadFromLocalStorage":m=await this.handleLoadFromLocalStorage(f,a);break;default:m=await this.handleCustomAction({...e,target:g,params:f},a);break}if(e.resultTo&&m!==void 0){const{target:b,key:v,merge:S}=e.resultTo,E=this.resolveValue(v,a.data),A=S==="replace"?"replace":S==="shallow"?"shallow":"deep";if(b==="_local"&&a.setState){const T=this.buildNestedUpdate(E,m),L=A!=="deep"?{...T,__mergeMode:A}:T;a.setState(L),H.log(`[resultTo] Saved to _local.${E} (merge=${A}):`,m)}else if(b==="_local"&&this.globalStateUpdater){const M=(window.G7Core?.state?.get()||{})._local||{},R=this.buildNestedUpdate(E,m);let D;A==="replace"?D=R:A==="shallow"?D={...M,...R}:D=this.deepMergeWithState(R,M),this.globalStateUpdater({_local:D}),H.log(`[resultTo] Saved to _local.${E} via globalStateUpdater (merge=${A}):`,m)}else if(b==="_global"&&this.globalStateUpdater){const T=this.buildNestedUpdate(E,m);this.globalStateUpdater(T),H.log(`[resultTo] Saved to _global.${E}:`,m)}else if(b==="_isolated"&&a.isolatedContext){const T=this.buildNestedUpdate(E,m);a.isolatedContext.mergeState(T,A),H.log(`[resultTo] Saved to _isolated.${E} (merge=${A}):`,m)}else H.warn(`[resultTo] Cannot save result: target=${b}, setState=${!!a.setState}, globalStateUpdater=${!!this.globalStateUpdater}, isolatedContext=${!!a.isolatedContext}`)}if(e.onSuccess){if(r?.isEnabled()&&i&&e.handler==="apiCall"){const S=window.G7Core,E={};S?.state?.get&&(E._global=S.state.get()),a.state&&(E._local=a.state),r.detectStaleClosure?.(i,`${e.handler} → onSuccess`,E,"callback-state-capture",i)}const b={...a,data:{...a.data,result:m,response:m}},v=Array.isArray(e.onSuccess)?e.onSuccess:[e.onSuccess];v.length>1?await this.handleSequence({handler:"sequence",type:"click",actions:v},b):v.length===1&&await this.executeAction(v[0],b)}return i&&r&&r.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),resolvedParams:u,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"success",result:this.sanitizeForDevTools(m)}),{success:!0,data:m}}catch(f){const g=f instanceof It?f:new It(`Failed to execute action: ${e.handler}`,e,f instanceof Error?f:void 0),m=g.originalError?.response||{},b=m.data||{},v=g.originalError?.status||m.status||500,S=b.message||g.message,E={status:v,message:S,errors:b.errors||m.errors,data:b,statusText:g.originalError?.statusText,error_code:b.error_code??m.error_code};if(g.unknownHandler)throw H.warn(`Unknown action handler "${e.handler}" — skipped (extension not loaded?). Not surfaced to the user.`),g;const T=pa().resolve(v,{errorHandling:e.errorHandling,onError:e.onError});if(T.handler){if(r?.isEnabled()&&i&&e.handler==="apiCall"){const M=window.G7Core,R={};M?.state?.get&&(R._global=M.state.get()),a.state&&(R._local=a.state),r.detectStaleClosure?.(i,`${e.handler} → onError`,R,"callback-state-capture",i)}const L={...a,data:{...a.data,error:E}};try{const M={type:"click",handler:T.handler.handler,target:T.handler.target,params:T.handler.params,actions:T.handler.actions};return await this.executeAction(M,L),{success:!1,error:g}}catch(M){return H.error("Error executing error handler:",M),{success:!1,error:g}}}throw i&&r&&r.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),resolvedParams:u,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"error",error:{name:g.name,message:g.message,stack:g.stack}}),g}finally{if(e.handler==="apiCall"&&a.setState&&d){const f=a.state?.loadingActions||{},{[d]:g,...m}=f;a.setState({loadingActions:m})}}}async handleNavigate(e,a,r){let i=e;if(a.query)if(a.mergeQuery===!0)i=this.buildMergedQueryPath(e,a.query);else{const u=new URLSearchParams;for(const[f,g]of Object.entries(a.query))if(g!=null&&g!=="")if(Array.isArray(g)){const m=f.endsWith("[]")?f:`${f}[]`;for(const b of g)b!=null&&b!==""&&u.append(m,String(b))}else u.set(f,String(g));const d=u.toString();d&&(i=`${e}?${d}`)}if(H.log("handleNavigate:",{target:e,params:a,finalPath:i,replace:a.replace,windowLocationSearch:window.location.search}),a.replace===!0){const u=window.G7Core;if(u?.updateQueryParams){const d=typeof a.transition_overlay_target=="string"?a.transition_overlay_target:void 0;await u.updateQueryParams(i,d?{transitionOverlayTarget:d}:void 0),H.log("handleNavigate: Used updateQueryParams for replace mode",d?{transitionOverlayTarget:d}:void 0),this.applyScrollOption(a.scroll,a.scrollBehavior,"top");return}H.warn("handleNavigate: G7Core.updateQueryParams not available, falling back to React Router")}const l=this.resolveNavigateFallbackAction(i,a);if(l){H.warn(`handleNavigate: No route matched, falling back to "${l.handler}"`),await this.dispatchAction({type:"click",handler:l.handler,params:l.params},r),this.applyScrollOption(a.scroll,a.scrollBehavior,"top");return}if(!r.navigate)throw new It("Navigate function is not provided in context");r.navigate(i,{replace:a.replace===!0}),this.applyScrollOption(a.scroll,a.scrollBehavior,"top")}resolveNavigateFallbackAction(e,a){const r=a.fallback;if(r===!1||a.replace===!0)return null;const l=window.__templateApp?.getRouter?.();if(!l||typeof l.match!="function"||typeof l.getRoutes=="function"&&l.getRoutes().length===0)return null;const u=e.split("?")[0];return l.match(u)?null:this.resolveNavigateFallback(r,e,a)}resolveNavigateFallback(e,a,r){return e==null?{handler:"openWindow",params:{path:a,target:"_self"}}:typeof e=="string"?{handler:e,params:{path:a}}:typeof e=="object"&&typeof e.handler=="string"?{handler:e.handler,params:{path:a,...e.params||{}}}:(H.warn("resolveNavigateFallback: unrecognized fallback option, using openWindow",e),{handler:"openWindow",params:{path:a,target:"_blank"}})}applyScrollOption(e,a,r){const i=e===void 0?r:e;if(i==="preserve")return;const l=a==="smooth"?"smooth":"instant",u=b=>{if(typeof b!="object"||b===null)return!1;const v=b;return"container"in v||"to"in v||"block"in v||"offset"in v},d=(b,v,S=0)=>{b===window?window.scrollTo({top:v,left:S,behavior:l}):b.scrollTo({top:v,left:S,behavior:l})},f=(b,v,S,E)=>{if(v===window){b.scrollIntoView({behavior:l,block:S}),E&&window.scrollBy({top:-E,left:0,behavior:l});return}const A=v,T=b.getBoundingClientRect(),L=A.getBoundingClientRect(),M=A.scrollTop+(T.top-L.top);let R;S==="center"?R=M-(A.clientHeight-b.clientHeight)/2:S==="end"?R=M-(A.clientHeight-b.clientHeight):R=M,R-=E,A.scrollTo({top:Math.max(0,R),left:0,behavior:l})},g=()=>{window.scrollTo({top:0,left:0,behavior:l});const b=document.getElementById("app")??document.body;if(!b)return;b.querySelectorAll("*").forEach(S=>{if(S.scrollTop===0&&S.scrollLeft===0)return;const E=window.getComputedStyle(S),A=E.overflowY,T=E.overflowX;(A==="auto"||A==="scroll"||T==="auto"||T==="scroll")&&S.scrollTo({top:0,left:0,behavior:l})})},m=()=>{try{if(u(i)){const b=i,v=b.block??"start",S=typeof b.offset=="number"?b.offset:0;let E=window;if(typeof b.container=="string"&&b.container.length>0){const T=document.querySelector(b.container);if(!T){H.warn(`applyScrollOption: container not found: ${b.container}`);return}E=T}const A=b.to??"top";if(A==="top"){E===window?g():d(E,0);return}if(typeof A=="number"){d(E,A-S);return}if(typeof A=="object"&&A!==null&&("x"in A||"y"in A)){const{x:T=0,y:L=0}=A;d(E,L-S,T);return}if(typeof A=="string"&&(A.startsWith("#")||A.startsWith("."))){const T=document.querySelector(A);T?f(T,E,v,S):H.warn(`applyScrollOption: target element not found: ${A}`);return}H.warn('applyScrollOption: invalid "to" value in extended form',A);return}if(i==="top"){g();return}if(typeof i=="number"){window.scrollTo({top:i,left:0,behavior:l});return}if(typeof i=="object"&&i!==null&&("x"in i||"y"in i)){const{x:b=0,y:v=0}=i;window.scrollTo({top:v,left:b,behavior:l});return}if(typeof i=="string"&&(i.startsWith("#")||i.startsWith("."))){const b=document.querySelector(i);b&&b.scrollIntoView({behavior:l,block:"start"});return}}catch(b){H.warn("applyScrollOption: failed to apply scroll",b)}};typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame(m):m()}async handleOpenWindow(e,a){let r=e;if(a.query){const l=new URLSearchParams;for(const[d,f]of Object.entries(a.query))f!=null&&f!==""&&l.set(d,String(f));const u=l.toString();u&&(r=`${e}?${u}`)}const i=a.target==="_self"?"_self":"_blank";H.log("handleOpenWindow:",{target:e,params:a,finalPath:r,windowTarget:i}),i==="_self"?window.location.assign(r):window.open(r,"_blank")}async handleNavigateBack(){H.log("handleNavigateBack"),window.history.back()}async handleNavigateForward(){H.log("handleNavigateForward"),window.history.forward()}async handleReplaceUrl(e,a){let r=e;if(a.query)if(a.mergeQuery===!0)r=this.buildMergedQueryPath(e,a.query);else{const i=new URLSearchParams;for(const[u,d]of Object.entries(a.query))if(d!=null&&d!=="")if(Array.isArray(d)){const f=u.endsWith("[]")?u:`${u}[]`;for(const g of d)g!=null&&g!==""&&i.append(f,String(g))}else i.set(u,String(d));const l=i.toString();l&&(r=`${e}?${l}`)}H.log("handleReplaceUrl:",{target:e,params:a,finalPath:r}),window.history.replaceState(null,"",r),this.applyScrollOption(a.scroll,a.scrollBehavior,"preserve")}buildMergedQueryPath(e,a){const r=new URLSearchParams(window.location.search);for(const[u,d]of Object.entries(a))if(d==null||d==="")r.delete(u);else if(Array.isArray(d)){const f=u.endsWith("[]")?u:`${u}[]`;r.delete(u),r.delete(f);for(const g of d)g!=null&&g!==""&&r.append(f,String(g))}else r.set(u,String(d));const i=r.toString(),l=e.split("?")[0];return i?`${l}?${i}`:l}async ensureCsrfToken(){try{await fetch("/sanctum/csrf-cookie",{credentials:"include"})}catch(e){throw new It("Failed to fetch CSRF token",void 0,e instanceof Error?e:void 0)}}getCsrfTokenFromCookie(){const r=`; ${document.cookie}`.split("; XSRF-TOKEN=");if(r.length===2){const i=r.pop()?.split(";").shift();return i?decodeURIComponent(i):null}return null}buildQueryString(e){const a=new URLSearchParams;for(const[r,i]of Object.entries(e))if(!(i==null||i===""))if(Array.isArray(i))for(const l of i)l!=null&&l!==""&&a.append(`${r}[]`,String(l));else typeof i=="object"?a.append(r,JSON.stringify(i)):a.append(r,String(i));return a.toString()}async handleEnsureIdentityVerified(e){const a=typeof e.purpose=="string"?e.purpose:"sensitive_action",r=e.target&&typeof e.target=="object"?e.target:void 0;return await St.handle({success:!1,error_code:"identity_verification_required",message:"",verification:{policy_key:e.policy_key??"",purpose:a,provider_id:e.provider_id??null,render_hint:e.render_hint??null,return_request:null}},void 0,r)!==null}handleResolveIdentityChallenge(e){const a=typeof e.result=="string"?e.result:"cancelled";let r;switch(a){case"verified":{const i=typeof e.token=="string"?e.token:"";if(!i){H.warn("resolveIdentityChallenge: result=verified 인데 token 이 비어있습니다. failed 로 강등합니다."),r={status:"failed",failureCode:"MISSING_TOKEN"};break}r={status:"verified",token:i,providerData:e.providerData&&typeof e.providerData=="object"?e.providerData:void 0};break}case"pending":{const i=typeof e.pollUrl=="string"?e.pollUrl:"",l=typeof e.expiresAt=="string"?e.expiresAt:"";if(!i||!l){H.warn("resolveIdentityChallenge: result=pending 인데 pollUrl/expiresAt 누락 — failed 로 강등합니다."),r={status:"failed",failureCode:"MALFORMED_PENDING"};break}r={status:"pending",pollUrl:i,pollIntervalMs:typeof e.pollIntervalMs=="number"?e.pollIntervalMs:void 0,expiresAt:l};break}case"failed":r={status:"failed",failureCode:typeof e.failureCode=="string"?e.failureCode:"UNKNOWN",reason:typeof e.reason=="string"?e.reason:void 0};break;default:r={status:"cancelled"};break}return St.resolveDeferred(r),!0}async handleApiCall(e,a,r,i="none",l){const{method:u="GET",body:d,headers:f,contentType:g}=a;u!=="GET"&&u!=="HEAD"&&await this.ensureCsrfToken();const m=this.getCsrfTokenFromCookie();let b={};if(i==="required"||i==="optional"){const X=$a().getToken();X&&(b={Authorization:`Bearer ${X}`})}let v=e;const S=a.query||(u==="GET"?d:null);if(S&&typeof S=="object"){const P=this.buildQueryString(S);if(P){const X=e.includes("?")?"&":"?";v=`${e}${X}${P}`}}const E=window.G7Core?.state?.getGlobal?.()||r.state?._global||{},A=window.G7Core?.state?.getLocal?.()||r.state?._local||{},T={_global:E,_local:A},L=this.getMatchingGlobalHeaders(e,T),M={};if(typeof window<"u"){const P=localStorage.getItem("g7_locale");P&&(M["Accept-Language"]=P)}const R=g==="multipart/form-data",D={method:u,headers:{...R?{}:{"Content-Type":"application/json"},Accept:"application/json",...M,...m&&{"X-XSRF-TOKEN":m},...b,...L,...f},credentials:"include"};if(d&&u!=="GET")if(R){const P=new FormData;for(const[X,ge]of Object.entries(d))ge instanceof File||ge instanceof Blob?P.append(X,ge):ge!=null&&P.append(X,typeof ge=="object"?JSON.stringify(ge):String(ge));D.body=P}else D.body=JSON.stringify(d);const U=Un();let j=null;U?.isEnabled()&&(j=U.trackRequest(v,u));try{let P=await fetch(v,D),X;try{X=await P.json()}catch{X=null}if(St.isIdentityRequired(P.status,X)){const ge=await St.handle(X,{body:D.body,headers:D.headers,credentials:D.credentials},l);if(ge){P=ge;try{X=await P.json()}catch{X=null}}}if(j&&U?.isEnabled()&&(U.completeRequest(j,P.status,X),j=null),!P.ok){const ge=X||{},Ee=new Error(ge.message||`API call failed: ${P.statusText}`);throw Ee.response=ge,Ee.status=P.status,Ee.statusText=P.statusText,new It(ge.message||`API call failed: ${P.statusText}`,void 0,Ee)}return X}catch(P){throw j&&U?.isEnabled()&&U.failRequest(j,P instanceof Error?P.message:String(P)),P}}async handleLogin(e,a,r){const{body:i}=a;if(!i||!i.email||!i.password)throw new It("Login requires email and password in body params");const l=e==="user"?"user":"admin",u=l==="admin"?"/api/auth/admin/login":"/api/auth/login",d=window.G7Core?.state?.getGlobal?.()||r.state?._global||{},f=window.G7Core?.state?.getLocal?.()||r.state?._local||{},g={_global:d,_local:f},m=this.getMatchingGlobalHeaders(u,g),b=ha.getInstance();try{const v=Object.keys(m).length>0?{headers:m}:void 0;return{user:await b.login(l,{email:i.email,password:i.password},v)}}catch(v){const S=v.message||"Login failed",E=new Error(S);throw E.response=v.response?.data||{},E.status=v.status||v.response?.status||500,new It(S,void 0,E)}}async handleLogout(e,a){await ha.getInstance().logout()}async handleSetState(e,a){H.log("[handleSetState] START, params:",e);const{target:r="component",scope:i,merge:l,__render:u,...d}=e,f=Un(),g=window.G7Core;if(typeof r=="string"&&(r.startsWith("$parent.")||r.startsWith("$root.")))return this.handleParentScopeSetState(r,d,l,a);const m=a.state&&Object.keys(a.state).length>0?a.state:g?.state?.get()||{},b=r==="global"?"_global":r.startsWith("_local.")?r:"_local",v=b==="_global"?m._global:b.startsWith("_local.")?this.getNestedProperty(m._local||{},b.slice(7)):m._local,S=f?.isEnabled()?f.startStateChange(b,v,d,{actionId:a.actionId,handlerType:"setState",source:`target=${r}`}):void 0,E=l==="replace"?"replace":l==="shallow"?"shallow":"deep",A=E!=="deep"?{...d,__mergeMode:E,...S?{__setStateId:S}:{}}:{...d,...S?{__setStateId:S}:{}};if(r==="global"){if(!this.globalStateUpdater){H.warn("Global state updater is not set"),S&&f&&f.completeStateChange(S);return}const T=g?.state?.get()||{},{__setStateId:L,__mergeMode:M,...R}=A,D=E==="deep"?this.deepMergeWithState(R,T):R,U={...D,...S?{__setStateId:S}:{},...E!=="deep"?{__mergeMode:E}:{}};return H.log("setState global:",U),this.globalStateUpdater(U,{render:u}),S&&f&&setTimeout(()=>f.completeStateChange(S),0),{__target:"global",...E!=="deep"?{__mergeMode:E}:{},...D}}else if(r==="isolated"){const T=a.isolatedContext;if(T){const{__mergeMode:L,__setStateId:M,...R}=A;return T.mergeState(R,E),H.log("[handleSetState] isolated state updated:",R,"mergeMode:",E),S&&f&&setTimeout(()=>f.completeStateChange(S),0),{__target:"isolated",...R}}else if(H.warn('[handleSetState] isolated target used but no IsolatedStateContext found. Make sure the component has "isolatedState" attribute. Falling back to local state.'),a.setState){const M=window.__g7PendingLocalState||a.state||{},R=E==="deep"?this.deepMergeWithState(A,M):A;return a.setState(R),S&&f&&setTimeout(()=>f.completeStateChange(S),0),R}else throw S&&f&&f.completeStateChange(S),new It("isolated target used but no IsolatedStateContext found and no setState function in context")}else if(r==="local"||r==="component"||r==="_local"){if(i==="parent"||i==="root"){const L=window.__g7LayoutContextStack||[];if(L.length>0){const M=i==="parent"?L[L.length-1]:L[0];if(M?.setState){const{__mergeMode:R,__setStateId:D,...U}=A,j=E==="deep"?this.deepMergeWithState(U,M.state||{}):U;return H.log(`[handleSetState] scope=${i}: 타겟 컨텍스트에 상태 업데이트`,j),M.setState(j),S&&f&&setTimeout(()=>f.completeStateChange(S),0),j}}H.warn(`[handleSetState] scope=${i}: 레이아웃 컨텍스트 스택이 비어있습니다. current로 폴백합니다.`)}const T=a.setState&&!a._isDispatchFallbackContext;if(H.log("[handleSetState] isRealComponentContext:",T,"context.setState:",!!a.setState,"_isDispatchFallbackContext:",a._isDispatchFallbackContext),T){H.log("[handleSetState] Using COMPONENT setState path"),H.log("[handleSetState] resolvedPayload:",A),H.log("[handleSetState] context.state:",a.state),H.log("[handleSetState] mergeMode:",E);const M=window.__g7PendingLocalState||a.state||{},R=E==="deep"?this.deepMergeWithState(A,{}):A;H.log("[handleSetState] convertedPayload (변경 필드만, dot notation 변환):",R),a.setState(R);const D=E==="deep"?this.deepMergeWithState(A,M):E==="shallow"?{...a.state||{},...A}:A,{__mergeMode:U,__setStateId:j,...P}=D;window.__g7PendingLocalState=P,H.log("[handleSetState] __g7PendingLocalState updated:",P),this.globalStateUpdater&&(this.globalStateUpdater({_local:P},{render:!1}),H.log("[handleSetState] _global._local synced (render:false):",P));const{__mergeMode:X,__setStateId:ge,...Ee}=A;if(E==="replace")window.__g7ForcedLocalFields=Ee;else{const Ce=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=this.deepMergeWithState(Ee,Ce)}return H.log("[handleSetState] __g7ForcedLocalFields updated:",Ee),S&&f&&setTimeout(()=>f.completeStateChange(S),0),{__target:"local",...D}}else if(this.globalStateUpdater){H.log("[handleSetState] Using GLOBAL STATE UPDATER path for _local");const M=window.__g7PendingLocalState||m._local||{};H.log("[handleSetState] currentLocal (with pending):",M);const R=E==="deep"?this.deepMergeWithState(A,M):A;return H.log("[handleSetState] finalLocal (merged):",R),this.globalStateUpdater({_local:R},{render:u}),window.__g7PendingLocalState=R,H.log("[handleSetState] __g7PendingLocalState updated for globalStateUpdater path"),S&&f&&setTimeout(()=>f.completeStateChange(S),0),{__target:"local",...R}}else throw S&&f&&f.completeStateChange(S),new It("setState function is not provided in context and globalStateUpdater is not set")}else if(r.startsWith("_local.")){const T=r.slice(7),{__mergeMode:L,__setStateId:M,...R}=A,D=R.value!==void 0?R.value:Object.values(R)[0];if(a.setState){const j=window.__g7PendingLocalState||a.state||{},P=this.createNestedUpdate(T,D,j),X={...j,...P};return a.setState(P),S&&f&&setTimeout(()=>f.completeStateChange(S),0),X}else throw S&&f&&f.completeStateChange(S),new It("setState function is not provided in context")}else{if(!a.setState)throw S&&f&&f.completeStateChange(S),new It("setState function is not provided in context");const L=window.__g7PendingLocalState||a.state||{},M=E==="deep"?this.deepMergeWithState(A,L):A;return a.setState(M),S&&f&&setTimeout(()=>f.completeStateChange(S),0),M}}async handleParentScopeSetState(e,a,r,i){const l=Un(),u=window.G7Core,d=r==="replace"?"replace":r==="shallow"?"shallow":"deep",f=e.startsWith("$parent."),g=f?"$parent.":"$root.",m=e.slice(g.length);let b,v;if(m==="_local"||m==="_global")b=m,v=void 0;else if(m.startsWith("_local."))b="_local",v=m.slice(7);else if(m.startsWith("_global."))b="_global",v=m.slice(8);else{H.warn(`[handleParentScopeSetState] 지원하지 않는 타겟 형식: ${e}. _local 또는 _global으로 시작해야 합니다.`);return}const S=window.__g7LayoutContextStack||[];if(S.length===0){H.warn(`[handleParentScopeSetState] 레이아웃 컨텍스트 스택이 비어있습니다. target=${e}`);return}const E=f?S[S.length-1]:S[0];if(!E){H.warn(`[handleParentScopeSetState] 타겟 컨텍스트를 찾을 수 없습니다. target=${e}`);return}const A=b==="_global"?E.state?._global:E.state?._local,T=l?.isEnabled()?l.startStateChange(e,A,a,{actionId:i.actionId,handlerType:"setState",source:`target=${e}`}):void 0,{__mergeMode:L,__setStateId:M,...R}=a;if(b==="_global"){if(!this.globalStateUpdater){H.warn("[handleParentScopeSetState] globalStateUpdater가 설정되지 않았습니다."),T&&l&&l.completeStateChange(T);return}const D=u?.state?.get()||{};if(v){const U=R.value!==void 0?R.value:Object.values(R)[0],j=this.createNestedUpdate(v,U,D),P={...D,...j};H.log(`[handleParentScopeSetState] ${e}: 전역 상태 중첩 경로 업데이트`,P),this.globalStateUpdater(P)}else{const U=d==="deep"?this.deepMergeWithState(R,D):R;H.log(`[handleParentScopeSetState] ${e}: 전역 상태 업데이트 (mergeMode=${d})`,U),this.globalStateUpdater(d!=="deep"?{...U,__mergeMode:d}:U)}return T&&l&&setTimeout(()=>l.completeStateChange(T),0),{__target:e,...R}}else{if(!E.setState){H.warn(`[handleParentScopeSetState] 타겟 컨텍스트에 setState가 없습니다. target=${e}`),T&&l&&l.completeStateChange(T);return}const D=E.state||{};if(v){const U=R.value!==void 0?R.value:Object.values(R)[0],j=this.createNestedUpdate(v,U,D),P={...D,...j};return H.log(`[handleParentScopeSetState] ${e}: 로컬 상태 중첩 경로 업데이트`,j),E.setState(j),E.state=P,E.dataContext&&(E.dataContext._local=P),kd(),T&&l&&setTimeout(()=>l.completeStateChange(T),0),P}else{const U=d!=="deep"?{...R,__mergeMode:d}:R,j=d==="replace"?R:d==="shallow"?{...D,...R}:this.deepMergeWithState(R,D);return H.log(`[handleParentScopeSetState] ${e}: 로컬 상태 업데이트 (mergeMode=${d})`,j),E.setState(U),E.state=j,E.dataContext&&(E.dataContext._local=j),kd(),T&&l&&setTimeout(()=>l.completeStateChange(T),0),j}}}deepMergeWithState(e,a){const r=["errors"];let i=e;if("..."in e){const u=e["..."];if(u&&typeof u=="object"&&!Array.isArray(u)){const{"...":d,...f}=e;i={...u,...f}}else{const{"...":d,...f}=e;i=f}}const l={...a};for(const[u,d]of Object.entries(i)){if(r.includes(u)){l[u]=d;continue}if(u.includes(".")&&u!=="..."){const f=this.createNestedUpdate(u,d,l);this.deepMergeInto(l,f,l);continue}if(d!==null&&typeof d=="object"&&!Array.isArray(d)&&Object.getPrototypeOf(d)!==Object.prototype&&Object.getPrototypeOf(d)!==null){l[u]=d;continue}d!==null&&typeof d=="object"&&!Array.isArray(d)&&a[u]!==null&&typeof a[u]=="object"&&!Array.isArray(a[u])?l[u]=this.deepMergeWithState(d,a[u]):l[u]=d}return l}deepMergeInto(e,a,r){for(const[i,l]of Object.entries(a)){if(l===null){e[i]=l;continue}if(e[i]===null){e[i]=l;continue}typeof l=="object"&&!Array.isArray(l)&&e[i]!==void 0&&e[i]!==null&&typeof e[i]=="object"&&!Array.isArray(e[i])?(e[i]===r[i]&&(e[i]={...e[i]}),this.deepMergeInto(e[i],l,r[i]||{})):typeof l=="object"&&!Array.isArray(l)&&e[i]===void 0&&r[i]!==null&&typeof r[i]=="object"&&!Array.isArray(r[i])?e[i]={...r[i],...l}:e[i]=l}}createNestedUpdate(e,a,r){const i=e.split(".");if(i.length===1)return{[i[0]]:a};const l={};let u=l,d=r;for(let f=0;f{this.globalStateUpdater({_local:S})};m.push({state:b,setState:v,dataContext:{_local:b||a.data?._local,_global:l?a.data?._global:a.data?._global||i?.state?.get?.(),_computed:a.data?._computed}}),window.__g7LayoutContextStack=m,H.log(`[handleOpenModal] 레이아웃 컨텍스트 스택에 push, 스택 크기: ${m.length}, state:`,b,l?"(direct)":"(fallback via G7Core)")}else H.warn(`[handleOpenModal] 컨텍스트 스택에 push 실패 - setState: ${!!a.setState}, state: ${a.state!==void 0}, G7Core: ${!!i?.state?.getLocal}`);const f=[...r,e];this.globalStateUpdater({modalStack:f,activeModal:e});const g=Un();if(g?.isEnabled()){const m=r.length>0?r[r.length-1]:void 0;g.trackModalOpen?.({modalId:e,modalName:e,scopeType:"isolated",parentModalId:m,initialState:a.state?{...a.state}:{}})}}async handleCloseModal(e){if(!this.globalStateUpdater){H.warn("Global state updater is not set for closeModal");return}const a=e?.data?._global?.modalStack||[],r=a.length>0?a[a.length-1]:null,i=a.slice(0,-1),l=i.length>0?i[i.length-1]:null,u=window.__g7LayoutContextStack||[];if(u.length>0){const d=u[u.length-1];d&&(d.dataContext=void 0),u.pop(),window.__g7LayoutContextStack=u,H.log(`[handleCloseModal] 레이아웃 컨텍스트 스택에서 pop, 스택 크기: ${u.length}`)}if(r){const d=Un();d?.isEnabled()&&d.trackModalClose?.(r,e?.state)}this.globalStateUpdater({modalStack:i,activeModal:l})}async handleShowAlert(e,a){let r=e;this.translationEngine&&this.translationContext&&e.startsWith("$t:")&&(r=this.translationEngine.resolveTranslations(e,this.translationContext,a.data)),alert(r)}async handleToast(e,a){const{type:r="info",message:i,icon:l,duration:u}=e;if(r==="error"){const f=a.data?.error;if((f?.error_code==="identity_verification_required"||f?.data?.error_code==="identity_verification_required")&&St.consumeDomainNoticeShown()){H.log("[Toast] IDV 도메인 안내 표출됨 — 중복 가드 토스트 1건 skip");return}}let d=i;if(this.translationEngine&&this.translationContext&&i?.startsWith("$t:")&&(d=this.translationEngine.resolveTranslations(i,this.translationContext,a.data)),this.globalStateUpdater){const g={id:`toast_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,type:r,message:d,...l&&{icon:l},...u&&{duration:u}},S=[...window.G7Core?.state?.get()?.toasts||[],g];this.globalStateUpdater({toasts:S})}else H.log(`[Toast ${r}] ${d}`)}async handleSwitch(e,a){const{cases:r}=e;if(!r){H.warn("switch handler requires cases property");return}const i=this.resolveParams(e.params,a.data);let l;if(i?.value!==void 0?(l=i.value,H.log("switch handler: using params.value as case key:",l)):(l=a.data?.$args?.[0],H.log("switch handler: using $args[0] as case key:",l)),l==null){if(r.default)return H.log("switch handler: case key is undefined, using default case"),await this.executeAction(r.default,a);H.warn("switch handler: case key is not defined and no default case");return}const u=String(l);let d=r[u];if(!d&&r.default&&(H.log(`switch handler: no case found for key "${u}", using default case`),d=r.default),!d){H.warn(`switch handler: no case found for key "${u}" and no default case`);return}return await this.executeAction(d,a)}async handleConditions(e,a){const{conditions:r}=e;if(!r||!Array.isArray(r)){H.warn("conditions handler requires conditions array");return}const i=a.data||{},l=op(r,i,this.bindingEngine);if(!l.matched){H.log("conditions handler: no matching branch found");return}const u=r[l.branchIndex];if(H.log(`conditions handler: matched branch ${l.branchIndex}`),!u.then){H.warn('conditions handler: matched branch has no "then" action');return}return Array.isArray(u.then)?await this.handleSequence({...e,actions:u.then},a):await this.executeAction(u.then,a)}handleStartInterval(e,a){const r=typeof e.id=="string"?e.id:"",i=Number(e.intervalMs??1e3),l=Array.isArray(e.actions)?e.actions:[];if(r===""||!l.length||i<=0)return H.warn("startInterval requires non-empty id, positive intervalMs, and actions array"),{success:!1};const u=this.intervals.get(r);u&&(clearInterval(u),this.intervals.delete(r));const d=setInterval(()=>{for(const f of l)this.executeAction(f,a).catch(g=>{H.error(`[startInterval:${r}] tick action failed`,g)})},i);return this.intervals.set(r,d),{success:!0,id:r}}handleStopInterval(e){const a=typeof e.id=="string"?e.id:"";if(a==="")return H.warn("stopInterval requires id parameter"),{success:!1};const r=this.intervals.get(a);return r&&(clearInterval(r),this.intervals.delete(a)),{success:!0,id:a}}stopAllIntervals(){for(const e of this.intervals.values())clearInterval(e);this.intervals.clear()}async handleSequence(e,a){const r=e.actions||e.params?.actions;if(!r||!Array.isArray(r)||r.length===0)return H.warn("sequence handler requires non-empty actions array"),[];const i=Un(),l=i?.isEnabled()&&i.startSequenceExecution?.({eventType:e.type})||"";window.__g7SequenceLocalSync=void 0;const u=[];let d,f=a.state?{...a.state}:{},g=a.isolatedContext?.state?{...a.isolatedContext.state}:{},m=a.data?._computed||{};const b=window.G7Core,v=()=>({_global:b?.state?.get()||{},_local:{...f},_isolated:Object.keys(g).length>0?{...g}:void 0});for(let S=0;S0){const R={},D={...a.data,_local:f,_computed:R,$computed:R,_isolated:g};for(const[U,j]of Object.entries(M))if(typeof j=="string"){const P=j.trim();if(P.startsWith("{{")&&P.endsWith("}}"))try{const X=P.slice(2,-2).trim();R[U]=this.bindingEngine.evaluateExpression(X,D,{skipCache:!0})}catch{R[U]=m[U]}}m=R,H.log("[handleSequence] _computed recalculated after setState:",m)}}if(E.handler!=="setState"){const M=window.__g7SequenceLocalSync;if(M&&M!==f){f=M,window.__g7SequenceLocalSync=void 0,H.log("[handleSequence] currentState synchronized from __g7SequenceLocalSync after custom handler:",E.handler);const R=a.data?._computedDefinitions;if(R&&Object.keys(R).length>0){const D={},U={...a.data,_local:f,_computed:D,$computed:D,_isolated:g};for(const[j,P]of Object.entries(R))if(typeof P=="string"){const X=P.trim();if(X.startsWith("{{")&&X.endsWith("}}"))try{const ge=X.slice(2,-2).trim();D[j]=this.bindingEngine.evaluateExpression(ge,U,{skipCache:!0})}catch{D[j]=m[j]}}m=D,H.log("[handleSequence] _computed recalculated after custom handler:",m)}}}l&&i?.isEnabled()&&i.captureSequenceActionAfter?.(l,S,v(),Date.now()-A,L.data)}catch(L){throw l&&i?.isEnabled()&&(i.captureSequenceActionAfter?.(l,S,v(),Date.now()-A,void 0,L),i.endSequenceExecution?.(l,L)),H.error(`sequence handler: action[${S}] failed:`,L),L}}return window.__g7SequenceLocalSync=void 0,l&&i?.isEnabled()&&i.endSequenceExecution?.(l),u}async handleParallel(e,a){const r=e.actions||e.params?.actions;if(!r||!Array.isArray(r)||r.length===0)return H.warn("parallel handler requires non-empty actions array"),[];H.log(`parallel handler: executing ${r.length} actions in parallel`);const i=a.isolatedContext?{...a.isolatedContext,state:{...a.isolatedContext.state}}:null,l=r.map((f,g)=>{const m={...a,isolatedContext:i};return this.executeAction(f,m).catch(b=>{throw H.error(`parallel handler: action[${g}] failed:`,b),b})}),u=await Promise.allSettled(l),d=u.filter(f=>f.status==="rejected").length;return d>0&&H.warn(`parallel handler: ${d}/${r.length} actions failed`),u}async handleLoadScript(e,a,r){const{src:i,id:l,async:u=!0,defer:d=!1}=e;if(!i)throw new It('loadScript handler requires "src" parameter',a);const f=l||`script_${i.replace(/[^a-zA-Z0-9]/g,"_")}`;return cs.loadedScripts.has(f)?(H.log(`loadScript: script already loaded, skipping: ${f}`),a.onLoad&&await this.executeAction(a.onLoad,r),!0):document.getElementById(f)?(H.log(`loadScript: script element already exists: ${f}`),cs.loadedScripts.add(f),a.onLoad&&await this.executeAction(a.onLoad,r),!0):(H.log(`loadScript: loading script: ${i}`),new Promise((m,b)=>{const v=document.createElement("script");v.id=f,v.src=i,v.async=u,v.defer=d,v.onload=async()=>{if(H.log(`loadScript: script loaded successfully: ${f}`),cs.loadedScripts.add(f),a.onLoad)try{await this.executeAction(a.onLoad,r)}catch(S){H.error("loadScript: onLoad action failed:",S)}m(!0)},v.onerror=S=>{H.error(`loadScript: failed to load script: ${i}`,S),b(new It(`Failed to load script: ${i}`,a))},document.head.appendChild(v)}))}async handleCallExternal(e,a,r){const i=e.constructor,l=e.args||{},u=e.method,d=e.methodArgs||[],f=e.callbackEvent,g=e.embedTarget,m=e.callbackSetState,b=e.callbackAction;if(!i)throw new It('callExternal handler requires "constructor" parameter',a);const v=this.getNestedProperty(window,i);if(!v||typeof v!="function")throw new It(`Constructor not found or not a function: ${i}. Make sure the script is loaded first using loadScript handler.`,a);H.log(`callExternal: calling constructor ${i}`);const S={...l};for(const[A,T]of Object.entries(l))T===!0&&(S[A]=L=>{if(H.log(`callExternal: callback triggered for ${A}`,L),f&&typeof window<"u"&&window.G7Core?.componentEvent&&window.G7Core.componentEvent.emit(f,L),m&&r.setState){const M=U=>{const j={};for(const[P,X]of Object.entries(U))typeof X=="string"?j[P]=this.getNestedProperty(L,X):typeof X=="object"&&X!==null&&(j[P]=M(X));return j},R=M(m);H.log("callExternal: callbackSetState mapping result",R);const D=this.deepMergeWithState(R,r.state||{});H.log("callExternal: merged with existing state",D),r.setState(D)}else f&&r.setState&&r.setState({[`${f.replace(/:/g,"_")}_result`]:L});if(b){const M={...r,data:{...r.data,$event:L}},R=Array.isArray(b)?b:[b];for(const D of R)try{this.executeAction(D,M)}catch(U){H.error("callExternal: callbackAction failed:",U)}}});const E=new v(S);if(u&&typeof E[u]=="function"){if(H.log(`callExternal: calling method ${u}`),u==="embed"&&g){const A=document.querySelector(g);if(A)return E[u](A,...d);throw new It(`Embed target element not found: ${g}`,a)}return E[u](...d)}return E}async handleCallExternalEmbed(e,a,r){const i=e.constructor,l=e.args||{},u=e.callbackSetState,d=e.callbackEvent,f=e.layerClassName,g=e.callbackAction;if(!i)throw new It('callExternalEmbed handler requires "constructor" parameter',a);const m=this.getNestedProperty(window,i);if(!m||typeof m!="function")throw new It(`Constructor not found or not a function: ${i}. Make sure the script is loaded first.`,a);H.log(`callExternalEmbed: creating layer for ${i}`);const{layer:b,closeLayer:v}=this.createEmbedLayer(f),S={...l};for(const[A,T]of Object.entries(l))T===!0&&(S[A]=L=>{if(H.log(`callExternalEmbed: callback triggered for ${A}`,L),v(),d&&typeof window<"u"&&window.G7Core?.componentEvent&&window.G7Core.componentEvent.emit(d,L),u&&r.setState){const M=U=>{const j={};for(const[P,X]of Object.entries(U))typeof X=="string"?j[P]=this.getNestedProperty(L,X):typeof X=="object"&&X!==null&&(j[P]=M(X));return j},R=M(u);H.log("callExternalEmbed: callbackSetState mapping result",R);const D=this.deepMergeWithState(R,r.state||{});H.log("callExternalEmbed: merged with existing state",D),r.setState(D)}if(g){const M={...r,data:{...r.data,$event:L}},R=Array.isArray(g)?g:[g];for(const D of R)try{this.executeAction(D,M)}catch(U){H.error("callExternalEmbed: callbackAction failed:",U)}}});const E=new m(S);if(typeof E.embed=="function")E.embed(b),H.log("callExternalEmbed: embedded in layer");else throw v(),new It(`Constructor ${i} does not have embed method`,a);return E}isImeComposing(e){return e?.isComposing===!0||e?.keyCode===229}createEmbedLayer(e){const a=document.createElement("div");a.id="g7-embed-overlay",a.style.cssText=` +`+l)}}catch{}}throw r}}_request(e,a){typeof e=="string"?(a=a||{},a.url=e):a=e||{},a=fi(this.defaults,a);const{transitional:r,paramsSerializer:i,headers:l}=a;r!==void 0&&Gl.assertOptions(r,{silentJSONParsing:Jn.transitional(Jn.boolean),forcedJSONParsing:Jn.transitional(Jn.boolean),clarifyTimeoutError:Jn.transitional(Jn.boolean),legacyInterceptorReqResOrdering:Jn.transitional(Jn.boolean)},!1),i!=null&&(F.isFunction(i)?a.paramsSerializer={serialize:i}:Gl.assertOptions(i,{encode:Jn.function,serialize:Jn.function},!0)),a.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?a.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:a.allowAbsoluteUrls=!0),Gl.assertOptions(a,{baseUrl:Jn.spelling("baseURL"),withXsrfToken:Jn.spelling("withXSRFToken")},!0),a.method=(a.method||this.defaults.method||"get").toLowerCase();let u=l&&F.merge(l.common,l[a.method]);l&&F.forEach(["delete","get","head","post","put","patch","query","common"],E=>{delete l[E]}),a.headers=Cn.concat(u,l);const d=[];let f=!0;this.interceptors.request.forEach(function(A){if(typeof A.runWhen=="function"&&A.runWhen(a)===!1)return;f=f&&A.synchronous;const T=a.transitional||md;T&&T.legacyInterceptorReqResOrdering?d.unshift(A.fulfilled,A.rejected):d.push(A.fulfilled,A.rejected)});const g=[];this.interceptors.response.forEach(function(A){g.push(A.fulfilled,A.rejected)});let m,b=0,v;if(!f){const E=[Gp.bind(this),void 0];for(E.unshift(...d),E.push(...g),v=E.length,m=Promise.resolve(a);b{if(!r._listeners)return;let l=r._listeners.length;for(;l-- >0;)r._listeners[l](i);r._listeners=null}),this.promise.then=i=>{let l;const u=new Promise(d=>{r.subscribe(d),l=d}).then(i);return u.cancel=function(){r.unsubscribe(l)},u},e(function(l,u,d){r.reason||(r.reason=new io(l,u,d),a(r.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){if(this.reason){e(this.reason);return}this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const a=this._listeners.indexOf(e);a!==-1&&this._listeners.splice(a,1)}toAbortSignal(){const e=new AbortController,a=r=>{e.abort(r)};return this.subscribe(a),e.signal.unsubscribe=()=>this.unsubscribe(a),e.signal}static source(){let e;return{token:new kS(function(i){e=i}),cancel:e}}};function q0(o){return function(a){return o.apply(null,a)}}function G0(o){return F.isObject(o)&&o.isAxiosError===!0}const Ed={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511,WebServerIsDown:521,ConnectionTimedOut:522,OriginIsUnreachable:523,TimeoutOccurred:524,SslHandshakeFailed:525,InvalidSslCertificate:526};Object.entries(Ed).forEach(([o,e])=>{Ed[e]=o});function Fp(o){const e=new hi(o),a=hp(hi.prototype.request,e);return F.extend(a,hi.prototype,e,{allOwnKeys:!0}),F.extend(a,e,null,{allOwnKeys:!0}),a.create=function(i){return Fp(fi(o,i))},a}const Pt=Fp(ro);Pt.Axios=hi,Pt.CanceledError=io,Pt.CancelToken=P0,Pt.isCancel=Op,Pt.VERSION=Sd,Pt.toFormData=Ul,Pt.AxiosError=Oe,Pt.Cancel=Pt.CanceledError,Pt.all=function(e){return Promise.all(e)},Pt.spread=q0,Pt.isAxiosError=G0,Pt.mergeConfig=fi,Pt.AxiosHeaders=Cn,Pt.formToJSON=o=>Dp(F.isHTMLForm(o)?new FormData(o):o),Pt.getAdapter=qp.getAdapter,Pt.HttpStatusCode=Ed,Pt.default=Pt;const{Axios:sT,AxiosError:oT,CanceledError:lT,isCancel:cT,CancelToken:uT,VERSION:dT,all:fT,Cancel:hT,isAxiosError:gT,spread:pT,toFormData:mT,AxiosHeaders:yT,HttpStatusCode:bT,formToJSON:vT,getAdapter:ST,mergeConfig:wT,create:CT}=Pt,_d="g7.identity.redirectStash",Vl=ct("IdentityGuardInterceptor");class St{static setLauncher(e){this.launcher=e}static hasLauncher(){return this.launcher!==null}static markDomainNoticeShown(){this.domainNoticeShown=!0}static consumeDomainNoticeShown(){const e=this.domainNoticeShown;return this.domainNoticeShown=!1,e}static resolveDeferred(e){const a=this.deferredResolver;if(!a){Vl.warn("IdentityGuardInterceptor.resolveDeferred 호출됐지만 대기 중인 launcher 가 없습니다. 모달이 launcher 외부에서 열렸는지 확인하세요.");return}this.deferredResolver=null,a(e)}static createDeferred(){if(this.deferredResolver){const e=this.deferredResolver;this.deferredResolver=null,e({status:"cancelled"})}return new Promise(e=>{this.deferredResolver=e})}static isIdentityRequired(e,a){return e===428&&typeof a=="object"&&a!==null&&a.error_code==="identity_verification_required"}static async handle(e,a,r){this.domainNoticeShown=!1;const i=this.launcher??F0,u=!!(r&&(r.email||r.phone))?{...e.verification,target:r}:e.verification,d=await i(u);if(d.status!=="verified")return null;const f=u.return_request;if(!f)return null;const g=V0(f.url,d.token);return fetch(g,{method:f.method,headers:a?.headers??{Accept:"application/json","Content-Type":"application/json"},body:a?.body,credentials:a?.credentials??"same-origin"})}static redirectExternally(e){const a=e.redirect_url;if(!a)return Vl.error("redirectExternally 호출 시 verification.redirect_url 이 없습니다. payload:",e),Promise.resolve({status:"failed",failureCode:"MISSING_REDIRECT_URL",reason:"verification.redirect_url is required for external_redirect flow"});if(typeof window<"u"){const r={return_url:window.location.href,payload:e,stashed_at:Date.now()};try{window.sessionStorage?.setItem(_d,JSON.stringify(r))}catch(i){Vl.warn("sessionStorage 접근 실패 — stash 없이 redirect 합니다.",i)}window.location.href=a}return new Promise(()=>{})}static reset(){if(this.deferredResolver){const e=this.deferredResolver;this.deferredResolver=null;try{e({status:"cancelled"})}catch{}}this.launcher=null,this.domainNoticeShown=!1}}$(St,"launcher",null),$(St,"deferredResolver",null),$(St,"domainNoticeShown",!1);function V0(o,e){if(!e)return o;try{const a=typeof window<"u"?window.location.origin:"http://localhost",r=new URL(o,a);return r.searchParams.set("verification_token",e),/^https?:\/\//i.test(o)?r.toString():`${r.pathname}${r.search}${r.hash}`}catch{const a=o.includes("?")?"&":"?";return`${o}${a}verification_token=${encodeURIComponent(e)}`}}const F0=async o=>{if(typeof window>"u")return{status:"cancelled"};if(o.render_hint==="external_redirect"||o.redirect_url)return St.redirectExternally(o);const e=window.G7Core;if(!e?.dispatch)return console.error("[IdentityGuardInterceptor] defaultLauncher: G7Core 가 초기화되지 않아 본인인증 흐름을 시작할 수 없습니다."),{status:"failed",failureCode:"G7_NOT_READY"};try{await e.dispatch({handler:"toast",params:{message:"본인 확인이 필요합니다.",variant:"warning"}})}catch{}const a=window.location.href,r={return_url:a,payload:o,stashed_at:Date.now()};try{window.sessionStorage?.setItem(_d,JSON.stringify(r))}catch{}const i=`/identity/challenge?return=${encodeURIComponent(a)}`;try{await e.dispatch({handler:"navigate",params:{path:i}})}catch(l){Vl.warn("navigate 실패 — window.location 으로 폴백",l),window.location.href=i}return new Promise(()=>{})},K0=ct("ApiClient");function Ad(){return typeof window<"u"&&window.__G7_DEVTOOLS__?window.__G7_DEVTOOLS__:null}class W0{constructor(e={}){$(this,"client");$(this,"config");$(this,"TOKEN_KEY","auth_token");this.config={baseURL:e.baseURL||"/api",timeout:e.timeout||3e4,onTokenExpired:e.onTokenExpired,onUnauthorized:e.onUnauthorized,onError:e.onError},this.client=Pt.create({baseURL:this.config.baseURL,timeout:this.config.timeout,headers:{"Content-Type":"application/json",Accept:"application/json"},paramsSerializer:{serialize:a=>{const r=[];for(const[i,l]of Object.entries(a))if(l!=null)if(Array.isArray(l)){const u=i.endsWith("[]")?i:`${i}[]`;for(const d of l)r.push(`${encodeURIComponent(u)}=${encodeURIComponent(String(d))}`)}else r.push(`${encodeURIComponent(i)}=${encodeURIComponent(String(l))}`);return r.join("&")}}}),this.setupInterceptors()}setToken(e){typeof window<"u"&&localStorage.setItem(this.TOKEN_KEY,e)}getToken(){return typeof window<"u"?localStorage.getItem(this.TOKEN_KEY):null}removeToken(){typeof window<"u"&&localStorage.removeItem(this.TOKEN_KEY)}setupInterceptors(){this.client.interceptors.request.use(e=>{e.url?.startsWith("/api")&&e.baseURL==="/api"&&(e.baseURL="");const a=this.getToken();if(a&&e.headers&&(e.headers.Authorization=`Bearer ${a}`),typeof window<"u"&&e.headers){const i=localStorage.getItem("g7_locale");i&&(e.headers["Accept-Language"]=i)}const r=Ad();if(r?.isEnabled()){const i=this.buildFullUrl(e),l=(e.method||"GET").toUpperCase(),u=r.trackRequest(i,l,{requestBody:e.data});e._devToolsRequestId=u}return e},e=>Promise.reject(e)),this.client.interceptors.response.use(e=>{const a=e.config,r=a._devToolsRequestId;if(r){const i=Ad();i?.isEnabled()&&i.completeRequest(r,e.status,e.data),a._devToolsRequestId=null}return e},async e=>{const a=e.config,r=a?.url||"",l=["/auth/","/layouts/"].some(u=>r.includes(u));if(e.response?.status===401&&!a?._retry&&!l){if(a._retry=!0,await ha.getInstance().refreshToken()){const f=this.getToken();return f&&(a.headers.Authorization=`Bearer ${f}`),a._devToolsRequestId=null,this.client(a)}return this.completeDevToolsRequest(a,e),this.removeToken(),this.config.onUnauthorized&&this.config.onUnauthorized(),Promise.reject(e)}if(e.response?.status===401&&l)return this.completeDevToolsRequest(a,e),Promise.reject(e);if(St.isIdentityRequired(e.response?.status,e.response?.data)){this.completeDevToolsRequest(a,e);const u={},d=a?.headers??{};for(const[v,S]of Object.entries(d))typeof S=="string"&&(u[v]=S);let f;a?.data!==void 0&&a?.data!==null&&(f=typeof a.data=="string"?a.data:JSON.stringify(a.data),u["Content-Type"]=u["Content-Type"]??"application/json");const g=a?.identity_target,m=await St.handle(e.response.data,{headers:u,body:f,credentials:"same-origin"},g);if(!m)return Promise.reject(e);let b=null;try{b=await m.json()}catch{b=null}return m.ok?{...e.response,status:m.status,data:b}:Promise.reject(Object.assign(new Error("replay failed"),{response:{status:m.status,data:b}}))}return e.response?.status===403?(this.completeDevToolsRequest(a,e),this.callOnError(e),Promise.reject(e)):(this.completeDevToolsRequest(a,e),e.response&&this.callOnError(e),Promise.reject(e))})}async get(e,a){return(await this.client.get(e,a)).data}async post(e,a,r){return(await this.client.post(e,a,r)).data}async put(e,a,r){return(await this.client.put(e,a,r)).data}async patch(e,a,r){return(await this.client.patch(e,a,r)).data}async delete(e,a){return(await this.client.delete(e,a)).data}getInstance(){return this.client}setOnUnauthorized(e){this.config.onUnauthorized=e}setOnError(e){this.config.onError=e}completeDevToolsRequest(e,a){if(!e?._devToolsRequestId)return;const r=Ad();if(!r?.isEnabled())return;const i=e._devToolsRequestId;e._devToolsRequestId=null,a.response?r.completeRequest(i,a.response.status,a.response.data):a.request?r.failRequest(i,a.message||"Network error"):r.failRequest(i,a.message||"Request error")}buildFullUrl(e){let a=e.url||"";if(e.baseURL&&!a.startsWith("http")&&(a=`${e.baseURL}${a.startsWith("/")?"":"/"}${a}`),e.params&&typeof e.params=="object"){const r=e.params,i=[];for(const[l,u]of Object.entries(r))if(u!=null)if(Array.isArray(u)){const d=l.endsWith("[]")?l:`${l}[]`;for(const f of u)i.push(`${encodeURIComponent(d)}=${encodeURIComponent(String(f))}`)}else i.push(`${encodeURIComponent(l)}=${encodeURIComponent(String(u))}`);i.length>0&&(a+=(a.includes("?")?"&":"?")+i.join("&"))}return a}callOnError(e){if(!this.config.onError)return;const a={status:e.response?.status||0,message:e.response?.data?.message||e.message||"Unknown error",data:e.response?.data,statusText:e.response?.statusText};try{this.config.onError(a)}catch(r){K0.error("Error in onError handler:",r)}}}let xd=null;function $a(){return xd||(xd=new W0),xd}const so=ct("AuthManager");function ts(o,e,a,r){try{window.G7Core?.devTools?.trackAuthEvent?.(o,e,a,r)}catch{}}const Fl={admin:{type:"admin",loginPath:"/admin/login",defaultPath:"/admin",userEndpoint:"/admin/auth/user",loginEndpoint:"/auth/admin/login",logoutEndpoint:"/admin/auth/logout",refreshEndpoint:"/admin/auth/refresh"},user:{type:"user",loginPath:"/login",defaultPath:"/",userEndpoint:"/auth/user",loginEndpoint:"/auth/login",logoutEndpoint:"/auth/logout",refreshEndpoint:"/auth/refresh"}},wa=class wa{constructor(){$(this,"state");$(this,"config");$(this,"isRefreshing",!1);$(this,"refreshPromise",null);$(this,"eventHandlers",new Map);this.state={isAuthenticated:!1,user:null,type:null},this.config=new Map,this.config.set("admin",Fl.admin),this.config.set("user",Fl.user)}static getInstance(){return wa.instance||(wa.instance=new wa),wa.instance}on(e,a){this.eventHandlers.has(e)||this.eventHandlers.set(e,[]),this.eventHandlers.get(e).push(a)}emit(e,...a){const r=this.eventHandlers.get(e);r&&r.forEach(i=>i(...a))}isAuthenticated(){return this.state.isAuthenticated}getUser(){return this.state.user}getAuthType(){return this.state.type}async checkAuth(e){const a=$a();if(!a.getToken())return this.clearState(),!1;const i=this.config.get(e);if(!i)return so.error(`Unknown auth type: ${e}`),!1;try{const l=await a.get(i.userEndpoint);return l.success&&l.data?(this.state={isAuthenticated:!0,user:l.data,type:e},this.emit("authStateChange",this.state),!0):(this.clearState(),!1)}catch(l){return l.response?.status===401&&await this.refreshToken()?this.checkAuth(e):(this.clearState(),!1)}}async preloadAuth(e){try{return await this.checkAuth(e)}catch(a){return so.warn(`Preload auth failed for type ${e}:`,a),!1}}async login(e,a,r){const i=$a();if(!this.config.get(e))throw new Error(`Unknown auth type: ${e}`);const u=e==="admin"?Fl.admin.loginEndpoint:Fl.user.loginEndpoint;try{const d=r?.headers?{headers:r.headers}:void 0,f=await i.post(u,a,d);if(f.success&&f.data){i.setToken(f.data.token);const g=f.data.user.language,m=localStorage.getItem(wa.LOCALE_STORAGE_KEY),b=g&&g!==m;if(g)try{localStorage.setItem(wa.LOCALE_STORAGE_KEY,g)}catch(v){so.warn("Failed to save user language to localStorage:",v)}return this.state={isAuthenticated:!0,user:f.data.user,type:e},this.emit("login",this.state),this.emit("authStateChange",this.state),ts("login",!0,void 0,{userId:f.data.user.uuid,email:f.data.user.email,type:e}),b&&window.__templateApp&&window.__templateApp.changeLocale(g),f.data.user}throw new Error("Login failed")}catch(d){this.clearState();const f=d.response?.data?.message,g=new Error(f||d.message||"Login failed");throw g.response=d.response,g.status=d.response?.status,ts("login",!1,g.message,{type:e,status:d.response?.status}),g}}async logout(){const e=$a(),a=this.state.type?this.config.get(this.state.type):null;try{a&&await e.post(a.logoutEndpoint)}catch(r){so.warn("Logout API call failed:",r)}finally{e.removeToken();const r={...this.state};if(this.clearState(),this.emit("logout",r),this.emit("authStateChange",this.state),ts("logout",!0,void 0,{previousType:r.type}),a&&r.type){const i=window.location.pathname+window.location.search;window.location.href=this.getLoginRedirectUrl(r.type,i)}}}async refreshToken(){if(this.isRefreshing&&this.refreshPromise)return this.refreshPromise;this.isRefreshing=!0,this.refreshPromise=this.doRefreshToken();try{return await this.refreshPromise}finally{this.isRefreshing=!1,this.refreshPromise=null}}async doRefreshToken(){const e=this.state.type;if(!e)return!1;const a=this.config.get(e);if(!a)return!1;const r=$a();try{const i=await r.post(a.refreshEndpoint);return i.success&&i.data?.token?(r.setToken(i.data.token),this.emit("tokenRefreshed"),ts("token-refresh",!0,void 0,{type:e}),!0):(ts("token-refresh",!1,"No token in response",{type:e}),!1)}catch(i){return so.error("Token refresh failed:",i),ts("token-refresh",!1,i instanceof Error?i.message:"Unknown error",{type:e}),!1}}getLoginRedirectUrl(e,a,r){const i=this.config.get(e);if(!i)return"/login";const l=encodeURIComponent(a);let u=`${i.loginPath}?redirect=${l}`;return r&&(u+=`&reason=${encodeURIComponent(r)}`),u}updateConfig(e,a){if(a.loginPath!==void 0){const i=a.loginPath;if(!i.startsWith("/")||i.startsWith("//"))throw new Error(`AuthManager.updateConfig: loginPath must be a same-origin path starting with '/' (got: ${i})`)}const r=this.config.get(e);r&&this.config.set(e,{...r,...a})}getRedirectUrl(e){const r=this.config.get(e)?.defaultPath||"/",l=new URLSearchParams(window.location.search).get("redirect");if(l)try{const u=decodeURIComponent(l);if(u.startsWith("/"))return u}catch{}return r}getConfig(e){return this.config.get(e)}clearState(){this.state={isAuthenticated:!1,user:null,type:null}}static resetInstance(){wa.instance=null}};$(wa,"instance"),$(wa,"LOCALE_STORAGE_KEY","g7_locale");let ha=wa;const Kp={401:{handler:"navigate",params:{path:"{{auth.loginPath}}"}},403:{handler:"toast",params:{type:"error",message:"{{error.message}}"}},404:{handler:"toast",params:{type:"error",message:"{{error.message}}"}},422:{handler:"toast",params:{type:"error",message:"{{error.message}}"}},default:{handler:"toast",params:{type:"error",message:"{{error.message}}"}}},Ja={findHandler(o,e){if(o){if(o[e])return o[e];if(o[String(e)])return o[String(e)];if(o.default)return o.default}},normalizeOnError(o){return o?Array.isArray(o)?o:[o]:[]},injectErrorCode(o,e,a){if(o.handler!=="showErrorPage"||o.params?.errorCode!==void 0)return o;const r=typeof e=="string"?parseInt(e,10):e,i=isNaN(r)?a:r;return i===void 0?o:{...o,params:{...o.params,errorCode:i}}}},ga=ct("ErrorHandlingResolver"),kr=class kr{constructor(){$(this,"templateErrorHandling",null);$(this,"layoutErrorHandling",null);$(this,"executeAction",null)}static getInstance(){return kr.instance||(kr.instance=new kr),kr.instance}static resetInstance(){kr.instance=null}setTemplateConfig(e){this.templateErrorHandling=e,ga.log("Template config set:",e)}setLayoutConfig(e){this.layoutErrorHandling=e,ga.log("Layout config set:",e)}setActionExecutor(e){this.executeAction=e}resolve(e,a={}){const{errorHandling:r,onError:i}=a;ga.log("Resolving error:",e,{hasActionErrorHandling:!!r,hasActionOnError:!!i,hasLayoutConfig:!!this.layoutErrorHandling,hasTemplateConfig:!!this.templateErrorHandling});let l=Ja.findHandler(r,e);if(l){const u=this.getMatchedKey(r,e);return{handler:Ja.injectErrorCode(l,u,e),level:"action",matchedKey:u}}if(i){const u=Ja.normalizeOnError(i);if(u.length>0)return{handler:u.length===1?u[0]:{handler:"sequence",actions:u},level:"action",matchedKey:"onError"}}if(l=Ja.findHandler(this.layoutErrorHandling||void 0,e),l){const u=this.getMatchedKey(this.layoutErrorHandling,e);return{handler:Ja.injectErrorCode(l,u,e),level:"layout",matchedKey:u}}if(l=Ja.findHandler(this.templateErrorHandling||void 0,e),l){const u=this.getMatchedKey(this.templateErrorHandling,e);return{handler:Ja.injectErrorCode(l,u,e),level:"template",matchedKey:u}}if(l=Ja.findHandler(Kp,e),l){const u=this.getMatchedKey(Kp,e);return{handler:Ja.injectErrorCode(l,u,e),level:"system",matchedKey:u}}return{handler:null,level:null,matchedKey:null}}async execute(e,a){if(!this.executeAction){ga.error("Action executor is not set");return}ga.log("Executing handler:",e.handler,{errorContext:a});try{return await this.executeAction(e,{error:a})}catch(r){throw ga.error("Failed to execute handler:",r),r}}async resolveAndExecute(e,a,r={}){const i=this.resolve(e,r);if(ga.log("Resolve result:",{errorCode:e,handler:i.handler?.handler,level:i.level,matchedKey:i.matchedKey}),!i.handler)return ga.warn("No handler found for error:",e),{handled:!1};try{return{handled:!0,result:await this.execute(i.handler,a)}}catch(l){return ga.error("Handler execution failed:",l),{handled:!1}}}getMatchedKey(e,a){return e[a]?a:e[String(a)]?String(a):"default"}clearLayoutConfig(){this.layoutErrorHandling=null,ga.log("Layout config cleared")}clearAllConfig(){this.templateErrorHandling=null,this.layoutErrorHandling=null,ga.log("All config cleared")}getConfigStatus(){return{hasTemplate:this.templateErrorHandling!==null,hasLayout:this.layoutErrorHandling!==null,hasExecutor:this.executeAction!==null}}};$(kr,"instance",null);let Td=kr;function pa(){return Td.getInstance()}var Rd={exports:{}},oo={};var Wp;function Y0(){if(Wp)return oo;Wp=1;var o=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function a(r,i,l){var u=null;if(l!==void 0&&(u=""+l),i.key!==void 0&&(u=""+i.key),"key"in i){l={};for(var d in i)d!=="key"&&(l[d]=i[d])}else l=i;return i=l.ref,{$$typeof:o,type:r,key:u,ref:i!==void 0?i:null,props:l}}return oo.Fragment=e,oo.jsx=a,oo.jsxs=a,oo}var Yp;function X0(){return Yp||(Yp=1,Rd.exports=Y0()),Rd.exports}var ut=X0();const J0=Wa({__proto__:null,default:Ya(ut)},[ut]),kd=ct("ParentContextProvider"),Xp=N.createContext(null);let Kl=null;function Dd(){Kl?(kd.log("[triggerModalParentUpdate] 모달 부모 컨텍스트 업데이트 트리거"),Kl()):kd.warn("[triggerModalParentUpdate] Provider가 아직 마운트되지 않음")}const Jp=({children:o})=>{const[e,a]=N.useState(0),r=N.useRef(!0),i=N.useCallback(()=>{const u=window.__g7LayoutContextStack||[];return u[u.length-1]?.dataContext},[]);N.useEffect(()=>(r.current=!0,Kl=()=>{r.current&&(a(u=>u+1),kd.log("[ParentContextProvider] 버전 업데이트됨"))},()=>{r.current=!1,Kl=null}),[]);const l={version:e,getParentDataContext:i};return ut.jsx(Xp.Provider,{value:l,children:o})};function Q0(){return N.useContext(Xp)}const H=ct("ActionDispatcher"),Qp=new Set(["navigate","navigateBack","navigateForward","replaceUrl","refresh","logout"]),Z0=new Set(["redirect"]);function Un(){try{return window.G7Core?.devTools}catch{return}}class It extends Error{constructor(a,r,i){super(a);$(this,"action");$(this,"originalError");$(this,"unknownHandler",!1);this.action=r,this.originalError=i,this.name="ActionError"}}const us=class us{constructor(e={},a,r){$(this,"bindingEngine");$(this,"translationEngine");$(this,"translationContext");$(this,"customHandlers",new Map);$(this,"defaultContext");$(this,"globalStateUpdater");$(this,"errorHandlingSetup",!1);$(this,"debounceTimers",new Map);$(this,"pendingDebounceFlushers",new Map);$(this,"debounceAccumulatedValues",new Map);$(this,"globalHeaders",[]);$(this,"namedActions",{});$(this,"previewMode",!1);$(this,"intervals",new Map);this.bindingEngine=new wn,this.translationEngine=a,this.translationContext=r,this.defaultContext=e,this.registerDefaultHandlers(),this.setupErrorHandling()}setGlobalHeaders(e){this.globalHeaders=e||[]}setNamedActions(e){this.namedActions=e||{};const a=Un();a?.isEnabled?.()&&a.setNamedActionDefinitions?.(this.namedActions),H.log("[setNamedActions] registered:",Object.keys(this.namedActions))}getNamedActions(){return this.namedActions}setPreviewMode(e){this.previewMode=e,H.log("Preview mode:",e?"enabled":"disabled")}isPreviewMode(){return this.previewMode}static getPreviewSuppressedHandlers(){return Qp}static getPreviewSuppressedLayoutFeatures(){return Z0}resolveActionRef(e){if(!e.actionRef)return e;const a=this.namedActions[e.actionRef];if(!a)return H.warn(`[resolveActionRef] named action not found: "${e.actionRef}"`),e;const r=Un();r?.isEnabled?.()&&r.trackNamedActionRef?.({actionRefName:e.actionRef,resolvedHandler:a.handler,timestamp:Date.now()});const{actionRef:i,type:l,key:u,event:d,...f}=e,g={...a,...Object.fromEntries(Object.entries(f).filter(([,m])=>m!==void 0)),type:l??a.type};return u!==void 0&&(g.key=u),d!==void 0&&(g.event=d),g}matchesPattern(e,a){if(a==="*")return!0;const r=a.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${r}$`).test(e)}getMatchingGlobalHeaders(e,a){const r={};for(const i of this.globalHeaders)this.matchesPattern(e,i.pattern)&&Object.entries(i.headers).forEach(([l,u])=>{const d=Ji(u,a,{skipCache:!0});d!=null&&d!==""&&(r[l]=String(d))});return r}setupErrorHandling(){if(this.errorHandlingSetup)return;pa().setActionExecutor(async(a,r)=>{const i={type:"click",handler:a.handler,target:a.target,params:a.params,actions:a.actions},l={data:{...this.defaultContext.data,error:r.error}};return await this.dispatchAction(i,l)}),this.errorHandlingSetup=!0}registerDefaultHandlers(){this.registerHandler("refetchDataSource",async(a,r)=>{const i=a.params?.dataSourceId,l=a.params?.sync;if(!i){H.warn("refetchDataSource: dataSourceId is required");return}if(typeof window<"u"&&window.G7Core?.dataSource?.refetch){const u=window.G7Core?.state?.get?.()||{},d={...r.state?._global,...u},f=window.G7Core?.state?.getLocal?.()||{},g=r.data?._local||r.state||{},m={...f,...g},b=r.isolatedContext?.state;H.log("[refetchDataSource] localStateOverride:",m),await window.G7Core.dataSource.refetch(i,{...l?{sync:!0}:{},...d?{globalStateOverride:d}:{},...m?{localStateOverride:m}:{},...b?{isolatedStateOverride:b}:{}})}else H.warn("refetchDataSource: G7Core.dataSource.refetch is not available")}),this.registerHandler("appendDataSource",async(a,r)=>{const{dataSourceId:i,dataPath:l,newData:u}=a.params||{};if(!i){H.warn("appendDataSource: dataSourceId is required");return}if(u===void 0){H.warn("appendDataSource: newData is required");return}if(typeof window<"u"&&window.G7Core?.dataSource?.updateData){if(!Array.isArray(u)){H.warn("appendDataSource: newData must be an array, got:",typeof u,u);return}await window.G7Core.dataSource.updateData(i,l||null,u,"append")}else H.warn("appendDataSource: G7Core.dataSource.updateData is not available")}),this.registerHandler("updateDataSource",async(a,r)=>{const{dataSourceId:i,data:l,merge:u=!1}=a.params||{};if(!i){H.warn("updateDataSource: dataSourceId is required");return}if(l===void 0){H.warn("updateDataSource: data is required");return}typeof window<"u"&&window.G7Core?.dataSource?.set?(H.log(`[updateDataSource] Updating dataSource '${i}' with:`,l),window.G7Core.dataSource.set(i,l,{merge:u})):H.warn("updateDataSource: G7Core.dataSource.set is not available")}),this.registerHandler("scrollIntoView",async(a,r)=>{const{selector:i,behavior:l="smooth",block:u="nearest",inline:d="nearest",waitForElement:f=!1,timeout:g=2e3,delay:m=0,retryCount:b=0,retryInterval:v=50,scrollContainer:S}=a.params||{};if(!i){H.warn("scrollIntoView: selector is required");return}if(typeof window>"u"||typeof document>"u"){H.warn("scrollIntoView: window/document is not available");return}let E=null;if(f){if(E=await new Promise(A=>{const T=document.querySelector(i);if(T){A(T);return}const L=setTimeout(()=>{M.disconnect(),A(null)},g),M=new MutationObserver(()=>{const R=document.querySelector(i);R&&(clearTimeout(L),M.disconnect(),A(R))});M.observe(document.body,{childList:!0,subtree:!0})}),!E){H.warn(`scrollIntoView: element not found for selector "${i}" after ${g}ms timeout`);return}}else{m>0&&await new Promise(T=>setTimeout(T,m)),E=document.querySelector(i);let A=0;for(;!E&&AsetTimeout(T,v)),E=document.querySelector(i),A++;if(!E){H.warn(`scrollIntoView: element not found for selector "${i}" after ${A+1} attempts`);return}}if(S){const A=document.querySelector(S);if(!A){H.warn(`scrollIntoView: container not found for selector "${S}"`);return}const T=E.getBoundingClientRect(),L=A.getBoundingClientRect(),M=T.top-L.top+A.scrollTop,R=M+T.height;let D;switch(u){case"start":D=M;break;case"center":D=M-A.clientHeight/2+T.height/2;break;case"end":D=R-A.clientHeight;break;default:const U=T.topL.bottom;if(U)D=M;else if(j)D=R-A.clientHeight;else return;break}A.scrollTo({top:Math.max(0,D),behavior:l});return}E.scrollIntoView({behavior:l,block:u,inline:d})}),this.registerHandler("reloadExtensions",async(a,r)=>{if(typeof window>"u"){H.warn("reloadExtensions: window is not available");return}const i=window.__templateApp;if(!i){H.warn("reloadExtensions: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState()}catch(d){throw H.error("reloadExtensions: reloadExtensionState failed",d),d}else H.warn("reloadExtensions: TemplateApp.reloadExtensionState unavailable");const{moduleInfo:l,pluginInfo:u}=a.params||{};if(l)try{await this.executeAction({handler:"reloadModuleHandlers",params:a.params},r)}catch(d){H.error("reloadExtensions: reloadModuleHandlers failed",d)}if(u)try{await this.executeAction({handler:"reloadPluginHandlers",params:a.params},r)}catch(d){H.error("reloadExtensions: reloadPluginHandlers failed",d)}H.log("reloadExtensions: done")}),this.registerHandler("reloadRoutes",async(a,r)=>{if(typeof window>"u"){H.warn("reloadRoutes: window is not available");return}const i=window.__templateApp;if(!i){H.warn("reloadRoutes: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState(),H.log("reloadRoutes: delegated to reloadExtensionState")}catch(l){throw H.error("reloadRoutes: Failed to reload routes",l),l}else{const l=i.getRouter?.();l&&(await l.loadRoutes(),H.log("reloadRoutes: Routes reloaded (legacy fallback)"))}}),this.registerHandler("refresh",async(a,r)=>{if(typeof window>"u"){H.warn("refresh: window is not available");return}const i=Number(a.params?.delayMs??0);i>0&&await new Promise(l=>setTimeout(l,i)),window.location.reload()}),this.registerHandler("remount",async(a,r)=>{const{componentId:i}=a.params||{};if(!i){H.warn("remount: componentId parameter is required");return}if(!this.globalStateUpdater){H.warn("remount: globalStateUpdater is not set");return}const d=(window.G7Core?.state?.get()||{})._global?._remountKeys||{},f=d[i]||0;this.globalStateUpdater({_remountKeys:{...d,[i]:f+1}}),H.log(`remount: ${i} key incremented to ${f+1}`)}),this.registerHandler("reloadTranslations",async(a,r)=>{if(typeof window>"u"){H.warn("reloadTranslations: window is not available");return}const i=window.__templateApp;if(!i){H.warn("reloadTranslations: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState(),H.log("reloadTranslations: delegated to reloadExtensionState")}catch(l){throw H.error("reloadTranslations: Failed to reload translations",l),l}}),this.registerHandler("reloadModuleHandlers",async(a,r)=>{if(typeof window>"u"){H.warn("reloadModuleHandlers: window is not available");return}const{moduleInfo:i,action:l}=a.params||{};if(!i){H.warn("reloadModuleHandlers: moduleInfo is required");return}const u=i.data||i;if(!u.identifier){H.warn("reloadModuleHandlers: moduleInfo with identifier is required");return}if(!l||l!=="add"&&l!=="remove"){H.warn('reloadModuleHandlers: action must be "add" or "remove"');return}const d=window.G7Config;if(!d){H.warn("reloadModuleHandlers: G7Config not available");return}const f=u.identifier;try{if(l==="add"){if(u.assets&&(d.moduleAssets=d.moduleAssets||{},d.moduleAssets[f]=u.assets,H.log(`reloadModuleHandlers: Added assets for ${f}`),u.assets.js)){const g=u.assets.js,m=`module-${f}`;if(document.getElementById(m)){H.warn(`reloadModuleHandlers: Script ${m} already loaded`);return}const b=document.createElement("script");if(b.id=m,b.src=g,b.async=!0,await new Promise((v,S)=>{b.onload=()=>{H.log(`reloadModuleHandlers: Script loaded successfully for ${f}`),v()},b.onerror=()=>{H.error(`reloadModuleHandlers: Failed to load script for ${f}`),S(new Error(`Failed to load module script: ${g}`))},document.head.appendChild(b)}),u.assets.css){const v=u.assets.css,S=`module-css-${f}`;if(!document.getElementById(S)){const E=document.createElement("link");E.id=S,E.rel="stylesheet",E.href=v,document.head.appendChild(E),H.log(`reloadModuleHandlers: CSS loaded for ${f}`)}}}}else if(l==="remove"){d.moduleAssets&&d.moduleAssets[f]&&(delete d.moduleAssets[f],H.log(`reloadModuleHandlers: Removed assets for ${f}`));const g=`module-${f}`,m=document.getElementById(g);m&&(m.remove(),H.log(`reloadModuleHandlers: Removed script for ${f}`));const b=`module-css-${f}`,v=document.getElementById(b);v&&(v.remove(),H.log(`reloadModuleHandlers: Removed CSS for ${f}`))}}catch(g){throw H.error(`reloadModuleHandlers: Failed to ${l} module assets`,g),g}}),this.registerHandler("reloadPluginHandlers",async(a,r)=>{if(typeof window>"u"){H.warn("reloadPluginHandlers: window is not available");return}const{pluginInfo:i,action:l}=a.params||{};if(!i){H.warn("reloadPluginHandlers: pluginInfo is required");return}const u=i.data||i;if(!u.identifier){H.warn("reloadPluginHandlers: pluginInfo with identifier is required");return}if(!l||l!=="add"&&l!=="remove"){H.warn('reloadPluginHandlers: action must be "add" or "remove"');return}const d=window.G7Config;if(!d){H.warn("reloadPluginHandlers: G7Config not available");return}const f=u.identifier;try{if(l==="add"){if(u.assets&&(d.pluginAssets=d.pluginAssets||{},d.pluginAssets[f]=u.assets,H.log(`reloadPluginHandlers: Added assets for ${f}`),u.assets.js)){const g=u.assets.js,m=`plugin-${f}`;if(document.getElementById(m)){H.warn(`reloadPluginHandlers: Script ${m} already loaded`);return}const b=document.createElement("script");if(b.id=m,b.src=g,b.async=!0,await new Promise((v,S)=>{b.onload=()=>{H.log(`reloadPluginHandlers: Script loaded successfully for ${f}`),v()},b.onerror=()=>{H.error(`reloadPluginHandlers: Failed to load script for ${f}`),S(new Error(`Failed to load plugin script: ${g}`))},document.head.appendChild(b)}),u.assets.css){const v=u.assets.css,S=`plugin-css-${f}`;if(!document.getElementById(S)){const E=document.createElement("link");E.id=S,E.rel="stylesheet",E.href=v,document.head.appendChild(E),H.log(`reloadPluginHandlers: CSS loaded for ${f}`)}}}}else if(l==="remove"){d.pluginAssets&&d.pluginAssets[f]&&(delete d.pluginAssets[f],H.log(`reloadPluginHandlers: Removed assets for ${f}`));const g=`plugin-${f}`,m=document.getElementById(g);m&&(m.remove(),H.log(`reloadPluginHandlers: Removed script for ${f}`));const b=`plugin-css-${f}`,v=document.getElementById(b);v&&(v.remove(),H.log(`reloadPluginHandlers: Removed CSS for ${f}`))}}catch(g){throw H.error(`reloadPluginHandlers: Failed to ${l} plugin assets`,g),g}});let e=!1;this.registerHandler("showErrorPage",async(a,r)=>{if(e){H.log("showErrorPage: Already active, skipping duplicate call");return}if(e=!0,typeof window>"u"){e=!1,H.warn("showErrorPage: window is not available");return}const i=window.__templateApp;if(!i){e=!1,H.warn("showErrorPage: TemplateApp not initialized");return}const l=i.getErrorPageHandler?.();if(!l){e=!1,H.warn("showErrorPage: ErrorPageHandler not available");return}const u=a.params?.errorCode||500,d=a.params?.target||"content";let f=a.params?.containerId;f||(f=d==="full"?"app":"main_content"),H.log("showErrorPage:",{errorCode:u,target:d,containerId:f});const g=(m,b=6e4)=>new Promise((v,S)=>{const E=document.getElementById(m);if(E){v(E);return}H.log(`showErrorPage: Waiting for container #${m}...`);let A;const T=new MutationObserver((L,M)=>{const R=document.getElementById(m);R&&(H.log(`showErrorPage: Container #${m} found`),M.disconnect(),clearTimeout(A),v(R))});T.observe(document.body,{childList:!0,subtree:!0}),A=setTimeout(()=>{T.disconnect(),S(new Error(`Container #${m} not found within ${b}ms`))},b)});try{await g(f);const m=pa(),b=m.layoutErrorHandling;m.clearLayoutConfig();try{await l.renderError(u,f)||H.warn(`showErrorPage: Failed to render error page for code ${u}`)}finally{m.setLayoutConfig(b)}}catch(m){throw H.error("showErrorPage: Error rendering error page:",m),m}finally{e=!1}}),this.registerHandler("emitEvent",async(a,r)=>{const i=a.params?.event,l=a.params?.data;if(!i){H.warn("emitEvent: event parameter is required");return}if(typeof window>"u"){H.warn("emitEvent: window is not available");return}const u=window.G7Core;if(!u?.componentEvent?.emit){H.warn("emitEvent: G7Core.componentEvent is not available");return}try{H.log(`emitEvent: Emitting "${i}"`,l);const d={...l,_context:{data:r.data,state:r.state}},f=await u.componentEvent.emit(i,d);if(!f||f.length===0?H.warn(`emitEvent: No listeners found for "${i}"`):H.log(`emitEvent: Event "${i}" completed with ${f.length} listener(s)`,f),this.globalStateUpdater){const g=(u?.state?.get()||{})._local||{},m={event:i,success:!0,data:f.length===1?f[0]:f,listeners:f.length};this.globalStateUpdater({_local:{...g,_eventResult:m}});const b=r.state&&typeof r.state=="object"&&!Array.isArray(r.state)?r.state:g;window.__g7SequenceLocalSync={...b,_eventResult:m}}}catch(d){if(H.error(`emitEvent: Event "${i}" failed`,d),this.globalStateUpdater){const f=u?.state?.get()||{};this.globalStateUpdater({_local:{...f._local,_eventResult:{event:i,success:!1,error:d instanceof Error?d.message:String(d)}}})}throw d}}),this.registerHandler("updateProductField",async(a,r)=>{const{productId:i,field:l,value:u}=a.params||{};if(!i||!l){H.warn("updateProductField: productId and field are required");return}if(typeof window>"u"){H.warn("updateProductField: window is not available");return}const d=window.G7Core;if(!d?.state?.get||!this.globalStateUpdater){H.warn("updateProductField: G7Core.state or globalStateUpdater is not available");return}try{const f=d.state.get()||{},m=(f.products?.data?.data||[]).map(v=>v.id===i?{...v,[l]:u,_modified:!0}:v),b=new Set(f._local?.modifiedProductIds||[]);b.add(i),this.globalStateUpdater({products:{...f.products,data:{...f.products?.data,data:m}},_local:{...f._local,modifiedProductIds:Array.from(b)}}),H.log(`updateProductField: Updated product ${i}, field: ${l}, value:`,u)}catch(f){throw H.error("updateProductField: Error updating product field",f),f}}),this.registerHandler("updateOptionField",async(a,r)=>{const{productId:i,optionId:l,field:u,value:d}=a.params||{};if(!i||!l||!u){H.warn("updateOptionField: productId, optionId and field are required");return}if(typeof window>"u"){H.warn("updateOptionField: window is not available");return}const f=window.G7Core;if(!f?.state?.get||!this.globalStateUpdater){H.warn("updateOptionField: G7Core.state or globalStateUpdater is not available");return}try{const g=f.state.get()||{},b=(g.products?.data?.data||[]).map(S=>{if(S.id===i&&S.options){const E=S.options.map(A=>A.id===l?{...A,[u]:d,_modified:!0}:A);return{...S,options:E,_modified:!0}}return S}),v=new Set(g._local?.modifiedProductIds||[]);v.add(i),this.globalStateUpdater({products:{...g.products,data:{...g.products?.data,data:b}},_local:{...g._local,modifiedProductIds:Array.from(v)}}),H.log(`updateOptionField: Updated product ${i} option ${l}, field: ${u}, value:`,d)}catch(g){throw H.error("updateOptionField: Error updating option field",g),g}}),this.registerHandler("setLocale",async(a,r)=>{const i=a.target;if(!i||typeof i!="string"){H.warn("setLocale: Invalid locale:",i);return}const l=window.__templateApp;if(l&&typeof l.changeLocale=="function")try{await l.changeLocale(i),H.log("setLocale: Locale changed to",i)}catch(u){H.error("setLocale: Failed to change locale:",u),window.location.reload()}else{H.warn("setLocale: TemplateApp not found, falling back to page reload");try{localStorage.setItem("g7_locale",i)}catch{}window.location.reload()}}),this.registerHandler("suppress",async()=>{H.log("suppress: Error intentionally suppressed")}),this.registerBuiltInHandlerMetadata()}registerBuiltInHandlerMetadata(){const e=Un();if(!e?.isEnabled())return;const a=[{name:"refetchDataSource",description:"데이터 소스를 다시 fetch합니다"},{name:"appendDataSource",description:"데이터 소스에 새 데이터를 병합합니다 (무한 스크롤용)"},{name:"updateDataSource",description:"API 응답으로 데이터 소스를 직접 업데이트합니다 (refetch 대체)"},{name:"reloadRoutes",description:"라우트를 다시 로드합니다"},{name:"refresh",description:"현재 페이지를 새로고침합니다"},{name:"remount",description:"컴포넌트를 리마운트합니다"},{name:"reloadTranslations",description:"다국어 파일을 다시 로드합니다"},{name:"showErrorPage",description:"에러 페이지를 표시합니다"},{name:"emitEvent",description:"이벤트를 발생시킵니다"},{name:"updateProductField",description:"상품 필드를 인라인 수정합니다"},{name:"updateOptionField",description:"상품 옵션 필드를 인라인 수정합니다"},{name:"setLocale",description:"언어를 변경합니다 (DB 저장 + UI 리렌더링)"}];for(const r of a)e.trackHandlerRegistration(r.name,"built-in",r.description)}createHandler(e,a,r){H.log("createHandler called for:",e.handler,e.type);const i=window.__g7DevTools,l=Date.now(),u=r?.state?{...r.state}:null,d=`handler_${e.handler}_${l}`;return async f=>{if(H.log("Handler invoked for:",e.handler,"event:",f.type),i?.isEnabled?.()&&u){const m=window.G7Core?.state?.getLocal?.()??r?.state??{},b=Date.now()-l;for(const v of Object.keys(u)){const S=u[v],E=m[v];S!==E&&b>100&&(i.trackStaleClosureWarning?.({type:"event-handler-stale",location:`createHandler(${e.handler})`,capturedPath:`_local.${v}`,capturedValue:S,capturedAt:l,currentValue:E,actionId:d,stackTrace:new Error().stack}),H.warn(`[Stale Closure] _local.${v} changed after handler creation:`,`captured="${S}" → current="${E}" (${b}ms ago)`))}}try{f.type!=="change"&&f.preventDefault();let g={};if(f.type==="submit"&&f.target instanceof HTMLFormElement){const v=f.target;new FormData(v).forEach((E,A)=>{g[A]=E})}const m={...this.defaultContext,data:{...a,form:g,_local:r?.state||{},$event:f},event:f,...r&&{state:r.state,setState:r.setState},isolatedContext:r?.isolatedContext};if(e.confirm){let v=this.resolveValue(e.confirm,m.data);if(this.translationEngine&&this.translationContext&&v.startsWith("$t:")&&(v=this.translationEngine.resolveTranslations(v,this.translationContext,m.data)),!confirm(v))return}const b=window.__g7ActionContext;window.__g7ActionContext={...r,data:m.data};try{await this.executeAction(e,m)}finally{window.__g7ActionContext=b}}catch(g){if(H.error("Action execution failed:",g),e.onError){const m=g instanceof It&&g.originalError?g.originalError:g,b={...this.defaultContext,data:{...a,error:m,_local:r?.state||{},$event:f},event:f,...r&&{state:r.state,setState:r.setState}},v=Array.isArray(e.onError)?e.onError:[e.onError];for(const S of v)await this.executeAction(S,b)}}}}generateActionId(e,a){const r=e.handler,i=a||"no-target",l=Date.now(),u=Math.random().toString(36).substring(2,9);return`${r}_${i.replace(/[^a-zA-Z0-9]/g,"_")}_${l}_${u}`}async executeAction(e,a){if(e=this.resolveActionRef(e),typeof e.handler=="string"&&e.handler.includes("{{")){const f=this.evaluateExpression(e.handler,a.data);e={...e,handler:f==null?"":String(f)}}const r=Un(),i=r?.isEnabled()?`action_${Date.now()}_${Math.random().toString(36).substring(2,11)}`:void 0,l=performance.now();let u;if(i&&r&&r.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),context:this.sanitizeForDevTools({hasState:!!a.state,hasSetState:!!a.setState,dataKeys:a.data?Object.keys(a.data):[]}),startTime:l,status:"started"}),e.if!==void 0)try{const f=this.resolveValue(e.if,a.data),g=f===!0||f==="true"||f&&f!=="false"&&f!=="0"&&f!==!1;if(H.log("[executeAction] if condition result:",e.handler,g),!g)return i&&r&&r.logAction({id:i,type:e.handler,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"success",result:{skipped:!0,reason:"if condition false"}}),{success:!0,data:void 0}}catch(f){return H.error("[executeAction] if condition error:",e.handler,f),i&&r&&r.logAction({id:i,type:e.handler,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"error",error:{name:"ConditionEvaluationError",message:f instanceof Error?f.message:String(f),stack:f instanceof Error?f.stack:void 0}}),{success:!0,data:void 0}}let d;try{const f=this.resolveParams(e.params,a.data);i&&(u=this.sanitizeForDevTools(f));const g=e.target?this.resolveValue(e.target,a.data):void 0;if(e.handler==="apiCall"&&a.setState){d=this.generateActionId(e,g);const b=a.state?.loadingActions||{};a.setState({loadingActions:{...b,[d]:!0}})}if(this.previewMode&&Qp.has(e.handler))return H.warn(`Preview mode: "${e.handler}" suppressed`,g||f),i&&r&&r.logAction({id:i,type:e.handler,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"skipped",metadata:{reason:"preview_mode_suppressed"}}),{success:!0,data:void 0};let m;switch(e.handler){case"ensureIdentityVerified":m=await this.handleEnsureIdentityVerified(f);break;case"resolveIdentityChallenge":m=this.handleResolveIdentityChallenge(f);break;case"navigate":const b=f.path||g;m=await this.handleNavigate(b,f,a);break;case"navigateBack":m=await this.handleNavigateBack();break;case"navigateForward":m=await this.handleNavigateForward();break;case"openWindow":{const E=f.path||g;m=await this.handleOpenWindow(E,f);break}case"replaceUrl":{const E=f.path||g||window.location.pathname;m=await this.handleReplaceUrl(E,f);break}case"apiCall":if(e.onSuccess&&r?.isEnabled()&&i){const E=window.G7Core,A={};if(E?.state?.get){const T=E.state.get();A._global=T}a.state&&(A._local=a.state),r.registerStateCaptureForHandler?.(i,["_global","_local"],A)}const v=e.auth_mode??(e.auth_required?"required":"none"),S=e.identity_target?this.resolveParams(e.identity_target,a.data):void 0;m=await this.handleApiCall(g,f,a,v,S);break;case"login":m=await this.handleLogin(g,f,a);break;case"logout":m=await this.handleLogout(g,a);break;case"setState":H.log("[executeAction] setState resolvedParams:",f),m=await this.handleSetState(e.render!==void 0?{...f,__render:e.render}:f,a);break;case"setError":m=await this.handleSetError(g,f,a);break;case"openModal":m=await this.handleOpenModal(g,a);break;case"closeModal":m=await this.handleCloseModal(a);break;case"showAlert":m=await this.handleShowAlert(g,a);break;case"toast":m=await this.handleToast(f,a);break;case"switch":m=await this.handleSwitch(e,a);break;case"conditions":m=await this.handleConditions(e,a);break;case"sequence":m=await this.handleSequence(e,a);break;case"parallel":m=await this.handleParallel(e,a);break;case"startInterval":m=this.handleStartInterval(f,a);break;case"stopInterval":m=this.handleStopInterval(f);break;case"loadScript":m=await this.handleLoadScript(f,e,a);break;case"callExternal":m=await this.handleCallExternal(f,e,a);break;case"callExternalEmbed":m=await this.handleCallExternalEmbed(f,e,a);break;case"saveToLocalStorage":m=await this.handleSaveToLocalStorage(f,a);break;case"loadFromLocalStorage":m=await this.handleLoadFromLocalStorage(f,a);break;default:m=await this.handleCustomAction({...e,target:g,params:f},a);break}if(e.resultTo&&m!==void 0){const{target:b,key:v,merge:S}=e.resultTo,E=this.resolveValue(v,a.data),A=S==="replace"?"replace":S==="shallow"?"shallow":"deep";if(b==="_local"&&a.setState){const T=this.buildNestedUpdate(E,m),L=A!=="deep"?{...T,__mergeMode:A}:T;a.setState(L),H.log(`[resultTo] Saved to _local.${E} (merge=${A}):`,m)}else if(b==="_local"&&this.globalStateUpdater){const M=(window.G7Core?.state?.get()||{})._local||{},R=this.buildNestedUpdate(E,m);let D;A==="replace"?D=R:A==="shallow"?D={...M,...R}:D=this.deepMergeWithState(R,M),this.globalStateUpdater({_local:D}),H.log(`[resultTo] Saved to _local.${E} via globalStateUpdater (merge=${A}):`,m)}else if(b==="_global"&&this.globalStateUpdater){const T=this.buildNestedUpdate(E,m);this.globalStateUpdater(T),H.log(`[resultTo] Saved to _global.${E}:`,m)}else if(b==="_isolated"&&a.isolatedContext){const T=this.buildNestedUpdate(E,m);a.isolatedContext.mergeState(T,A),H.log(`[resultTo] Saved to _isolated.${E} (merge=${A}):`,m)}else H.warn(`[resultTo] Cannot save result: target=${b}, setState=${!!a.setState}, globalStateUpdater=${!!this.globalStateUpdater}, isolatedContext=${!!a.isolatedContext}`)}if(e.onSuccess){if(r?.isEnabled()&&i&&e.handler==="apiCall"){const S=window.G7Core,E={};S?.state?.get&&(E._global=S.state.get()),a.state&&(E._local=a.state),r.detectStaleClosure?.(i,`${e.handler} → onSuccess`,E,"callback-state-capture",i)}const b={...a,data:{...a.data,result:m,response:m}},v=Array.isArray(e.onSuccess)?e.onSuccess:[e.onSuccess];v.length>1?await this.handleSequence({handler:"sequence",type:"click",actions:v},b):v.length===1&&await this.executeAction(v[0],b)}return i&&r&&r.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),resolvedParams:u,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"success",result:this.sanitizeForDevTools(m)}),{success:!0,data:m}}catch(f){const g=f instanceof It?f:new It(`Failed to execute action: ${e.handler}`,e,f instanceof Error?f:void 0),m=g.originalError?.response||{},b=m.data||{},v=g.originalError?.status||m.status||500,S=b.message||g.message,E={status:v,message:S,errors:b.errors||m.errors,data:b,statusText:g.originalError?.statusText,error_code:b.error_code??m.error_code};if(g.unknownHandler)throw H.warn(`Unknown action handler "${e.handler}" — skipped (extension not loaded?). Not surfaced to the user.`),g;const T=pa().resolve(v,{errorHandling:e.errorHandling,onError:e.onError});if(T.handler){if(r?.isEnabled()&&i&&e.handler==="apiCall"){const M=window.G7Core,R={};M?.state?.get&&(R._global=M.state.get()),a.state&&(R._local=a.state),r.detectStaleClosure?.(i,`${e.handler} → onError`,R,"callback-state-capture",i)}const L={...a,data:{...a.data,error:E}};try{const M={type:"click",handler:T.handler.handler,target:T.handler.target,params:T.handler.params,actions:T.handler.actions};return await this.executeAction(M,L),{success:!1,error:g}}catch(M){return H.error("Error executing error handler:",M),{success:!1,error:g}}}throw i&&r&&r.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),resolvedParams:u,startTime:l,endTime:performance.now(),duration:performance.now()-l,status:"error",error:{name:g.name,message:g.message,stack:g.stack}}),g}finally{if(e.handler==="apiCall"&&a.setState&&d){const f=a.state?.loadingActions||{},{[d]:g,...m}=f;a.setState({loadingActions:m})}}}async handleNavigate(e,a,r){let i=e;if(a.query||a.mergeQuery===!0)if(a.mergeQuery===!0)i=this.buildMergedQueryPath(e,a.query??{});else{const u=new URLSearchParams;for(const[f,g]of Object.entries(a.query))if(g!=null&&g!=="")if(Array.isArray(g)){const m=f.endsWith("[]")?f:`${f}[]`;for(const b of g)b!=null&&b!==""&&u.append(m,String(b))}else u.set(f,String(g));const d=u.toString();d&&(i=`${e}?${d}`)}if(H.log("handleNavigate:",{target:e,params:a,finalPath:i,replace:a.replace,windowLocationSearch:window.location.search}),a.replace===!0){const u=window.G7Core;if(u?.updateQueryParams){const d=typeof a.transition_overlay_target=="string"?a.transition_overlay_target:void 0;await u.updateQueryParams(i,d?{transitionOverlayTarget:d}:void 0),H.log("handleNavigate: Used updateQueryParams for replace mode",d?{transitionOverlayTarget:d}:void 0),this.applyScrollOption(a.scroll,a.scrollBehavior,"top");return}H.warn("handleNavigate: G7Core.updateQueryParams not available, falling back to React Router")}const l=this.resolveNavigateFallbackAction(i,a);if(l){H.warn(`handleNavigate: No route matched, falling back to "${l.handler}"`),await this.dispatchAction({type:"click",handler:l.handler,params:l.params},r),this.applyScrollOption(a.scroll,a.scrollBehavior,"top");return}if(!r.navigate)throw new It("Navigate function is not provided in context");r.navigate(i,{replace:a.replace===!0}),this.applyScrollOption(a.scroll,a.scrollBehavior,"top")}resolveNavigateFallbackAction(e,a){const r=a.fallback;if(r===!1||a.replace===!0)return null;const l=window.__templateApp?.getRouter?.();if(!l||typeof l.match!="function"||typeof l.getRoutes=="function"&&l.getRoutes().length===0)return null;const u=e.split("?")[0];return l.match(u)?null:this.resolveNavigateFallback(r,e,a)}resolveNavigateFallback(e,a,r){return e==null?{handler:"openWindow",params:{path:a,target:"_self"}}:typeof e=="string"?{handler:e,params:{path:a}}:typeof e=="object"&&typeof e.handler=="string"?{handler:e.handler,params:{path:a,...e.params||{}}}:(H.warn("resolveNavigateFallback: unrecognized fallback option, using openWindow",e),{handler:"openWindow",params:{path:a,target:"_blank"}})}applyScrollOption(e,a,r){const i=e===void 0?r:e;if(i==="preserve")return;const l=a==="smooth"?"smooth":"instant",u=b=>{if(typeof b!="object"||b===null)return!1;const v=b;return"container"in v||"to"in v||"block"in v||"offset"in v},d=(b,v,S=0)=>{b===window?window.scrollTo({top:v,left:S,behavior:l}):b.scrollTo({top:v,left:S,behavior:l})},f=(b,v,S,E)=>{if(v===window){b.scrollIntoView({behavior:l,block:S}),E&&window.scrollBy({top:-E,left:0,behavior:l});return}const A=v,T=b.getBoundingClientRect(),L=A.getBoundingClientRect(),M=A.scrollTop+(T.top-L.top);let R;S==="center"?R=M-(A.clientHeight-b.clientHeight)/2:S==="end"?R=M-(A.clientHeight-b.clientHeight):R=M,R-=E,A.scrollTo({top:Math.max(0,R),left:0,behavior:l})},g=()=>{window.scrollTo({top:0,left:0,behavior:l});const b=document.getElementById("app")??document.body;if(!b)return;b.querySelectorAll("*").forEach(S=>{if(S.scrollTop===0&&S.scrollLeft===0)return;const E=window.getComputedStyle(S),A=E.overflowY,T=E.overflowX;(A==="auto"||A==="scroll"||T==="auto"||T==="scroll")&&S.scrollTo({top:0,left:0,behavior:l})})},m=()=>{try{if(u(i)){const b=i,v=b.block??"start",S=typeof b.offset=="number"?b.offset:0;let E=window;if(typeof b.container=="string"&&b.container.length>0){const T=document.querySelector(b.container);if(!T){H.warn(`applyScrollOption: container not found: ${b.container}`);return}E=T}const A=b.to??"top";if(A==="top"){E===window?g():d(E,0);return}if(typeof A=="number"){d(E,A-S);return}if(typeof A=="object"&&A!==null&&("x"in A||"y"in A)){const{x:T=0,y:L=0}=A;d(E,L-S,T);return}if(typeof A=="string"&&(A.startsWith("#")||A.startsWith("."))){const T=document.querySelector(A);T?f(T,E,v,S):H.warn(`applyScrollOption: target element not found: ${A}`);return}H.warn('applyScrollOption: invalid "to" value in extended form',A);return}if(i==="top"){g();return}if(typeof i=="number"){window.scrollTo({top:i,left:0,behavior:l});return}if(typeof i=="object"&&i!==null&&("x"in i||"y"in i)){const{x:b=0,y:v=0}=i;window.scrollTo({top:v,left:b,behavior:l});return}if(typeof i=="string"&&(i.startsWith("#")||i.startsWith("."))){const b=document.querySelector(i);b&&b.scrollIntoView({behavior:l,block:"start"});return}}catch(b){H.warn("applyScrollOption: failed to apply scroll",b)}};typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame(m):m()}async handleOpenWindow(e,a){let r=e;if(a.query){const l=new URLSearchParams;for(const[d,f]of Object.entries(a.query))f!=null&&f!==""&&l.set(d,String(f));const u=l.toString();u&&(r=`${e}?${u}`)}const i=a.target==="_self"?"_self":"_blank";H.log("handleOpenWindow:",{target:e,params:a,finalPath:r,windowTarget:i}),i==="_self"?window.location.assign(r):window.open(r,"_blank")}async handleNavigateBack(){H.log("handleNavigateBack"),window.history.back()}async handleNavigateForward(){H.log("handleNavigateForward"),window.history.forward()}async handleReplaceUrl(e,a){let r=e;if(a.query||a.mergeQuery===!0)if(a.mergeQuery===!0)r=this.buildMergedQueryPath(e,a.query??{});else{const i=new URLSearchParams;for(const[u,d]of Object.entries(a.query))if(d!=null&&d!=="")if(Array.isArray(d)){const f=u.endsWith("[]")?u:`${u}[]`;for(const g of d)g!=null&&g!==""&&i.append(f,String(g))}else i.set(u,String(d));const l=i.toString();l&&(r=`${e}?${l}`)}H.log("handleReplaceUrl:",{target:e,params:a,finalPath:r}),window.history.replaceState(null,"",r),this.applyScrollOption(a.scroll,a.scrollBehavior,"preserve")}buildMergedQueryPath(e,a){const r=new URLSearchParams(window.location.search);for(const[u,d]of Object.entries(a))if(d==null||d==="")r.delete(u);else if(Array.isArray(d)){const f=u.endsWith("[]")?u:`${u}[]`;r.delete(u),r.delete(f);for(const g of d)g!=null&&g!==""&&r.append(f,String(g))}else r.set(u,String(d));const i=r.toString(),l=e.split("?")[0];return i?`${l}?${i}`:l}async ensureCsrfToken(){try{await fetch("/sanctum/csrf-cookie",{credentials:"include"})}catch(e){throw new It("Failed to fetch CSRF token",void 0,e instanceof Error?e:void 0)}}getCsrfTokenFromCookie(){const r=`; ${document.cookie}`.split("; XSRF-TOKEN=");if(r.length===2){const i=r.pop()?.split(";").shift();return i?decodeURIComponent(i):null}return null}buildQueryString(e){const a=new URLSearchParams;for(const[r,i]of Object.entries(e))if(!(i==null||i===""))if(Array.isArray(i))for(const l of i)l!=null&&l!==""&&a.append(`${r}[]`,String(l));else typeof i=="object"?a.append(r,JSON.stringify(i)):a.append(r,String(i));return a.toString()}async handleEnsureIdentityVerified(e){const a=typeof e.purpose=="string"?e.purpose:"sensitive_action",r=e.target&&typeof e.target=="object"?e.target:void 0;return await St.handle({success:!1,error_code:"identity_verification_required",message:"",verification:{policy_key:e.policy_key??"",purpose:a,provider_id:e.provider_id??null,render_hint:e.render_hint??null,return_request:null}},void 0,r)!==null}handleResolveIdentityChallenge(e){const a=typeof e.result=="string"?e.result:"cancelled";let r;switch(a){case"verified":{const i=typeof e.token=="string"?e.token:"";if(!i){H.warn("resolveIdentityChallenge: result=verified 인데 token 이 비어있습니다. failed 로 강등합니다."),r={status:"failed",failureCode:"MISSING_TOKEN"};break}r={status:"verified",token:i,providerData:e.providerData&&typeof e.providerData=="object"?e.providerData:void 0};break}case"pending":{const i=typeof e.pollUrl=="string"?e.pollUrl:"",l=typeof e.expiresAt=="string"?e.expiresAt:"";if(!i||!l){H.warn("resolveIdentityChallenge: result=pending 인데 pollUrl/expiresAt 누락 — failed 로 강등합니다."),r={status:"failed",failureCode:"MALFORMED_PENDING"};break}r={status:"pending",pollUrl:i,pollIntervalMs:typeof e.pollIntervalMs=="number"?e.pollIntervalMs:void 0,expiresAt:l};break}case"failed":r={status:"failed",failureCode:typeof e.failureCode=="string"?e.failureCode:"UNKNOWN",reason:typeof e.reason=="string"?e.reason:void 0};break;default:r={status:"cancelled"};break}return St.resolveDeferred(r),!0}async handleApiCall(e,a,r,i="none",l){const{method:u="GET",body:d,headers:f,contentType:g}=a;u!=="GET"&&u!=="HEAD"&&await this.ensureCsrfToken();const m=this.getCsrfTokenFromCookie();let b={};if(i==="required"||i==="optional"){const X=$a().getToken();X&&(b={Authorization:`Bearer ${X}`})}let v=e;const S=a.query||(u==="GET"?d:null);if(S&&typeof S=="object"){const P=this.buildQueryString(S);if(P){const X=e.includes("?")?"&":"?";v=`${e}${X}${P}`}}const E=window.G7Core?.state?.getGlobal?.()||r.state?._global||{},A=window.G7Core?.state?.getLocal?.()||r.state?._local||{},T={_global:E,_local:A},L=this.getMatchingGlobalHeaders(e,T),M={};if(typeof window<"u"){const P=localStorage.getItem("g7_locale");P&&(M["Accept-Language"]=P)}const R=g==="multipart/form-data",D={method:u,headers:{...R?{}:{"Content-Type":"application/json"},Accept:"application/json",...M,...m&&{"X-XSRF-TOKEN":m},...b,...L,...f},credentials:"include"};if(d&&u!=="GET")if(R){const P=new FormData;for(const[X,ge]of Object.entries(d))ge instanceof File||ge instanceof Blob?P.append(X,ge):ge!=null&&P.append(X,typeof ge=="object"?JSON.stringify(ge):String(ge));D.body=P}else D.body=JSON.stringify(d);const U=Un();let j=null;U?.isEnabled()&&(j=U.trackRequest(v,u));try{let P=await fetch(v,D),X;try{X=await P.json()}catch{X=null}if(St.isIdentityRequired(P.status,X)){const ge=await St.handle(X,{body:D.body,headers:D.headers,credentials:D.credentials},l);if(ge){P=ge;try{X=await P.json()}catch{X=null}}}if(j&&U?.isEnabled()&&(U.completeRequest(j,P.status,X),j=null),!P.ok){const ge=X||{},Ee=new Error(ge.message||`API call failed: ${P.statusText}`);throw Ee.response=ge,Ee.status=P.status,Ee.statusText=P.statusText,new It(ge.message||`API call failed: ${P.statusText}`,void 0,Ee)}return X}catch(P){throw j&&U?.isEnabled()&&U.failRequest(j,P instanceof Error?P.message:String(P)),P}}async handleLogin(e,a,r){const{body:i}=a;if(!i||!i.email||!i.password)throw new It("Login requires email and password in body params");const l=e==="user"?"user":"admin",u=l==="admin"?"/api/auth/admin/login":"/api/auth/login",d=window.G7Core?.state?.getGlobal?.()||r.state?._global||{},f=window.G7Core?.state?.getLocal?.()||r.state?._local||{},g={_global:d,_local:f},m=this.getMatchingGlobalHeaders(u,g),b=ha.getInstance();try{const v=Object.keys(m).length>0?{headers:m}:void 0;return{user:await b.login(l,{email:i.email,password:i.password},v)}}catch(v){const S=v.message||"Login failed",E=new Error(S);throw E.response=v.response?.data||{},E.status=v.status||v.response?.status||500,new It(S,void 0,E)}}async handleLogout(e,a){await ha.getInstance().logout()}async handleSetState(e,a){H.log("[handleSetState] START, params:",e);const{target:r="component",scope:i,merge:l,__render:u,...d}=e,f=Un(),g=window.G7Core;if(typeof r=="string"&&(r.startsWith("$parent.")||r.startsWith("$root.")))return this.handleParentScopeSetState(r,d,l,a);const m=a.state&&Object.keys(a.state).length>0?a.state:g?.state?.get()||{},b=r==="global"?"_global":r.startsWith("_local.")?r:"_local",v=b==="_global"?m._global:b.startsWith("_local.")?this.getNestedProperty(m._local||{},b.slice(7)):m._local,S=f?.isEnabled()?f.startStateChange(b,v,d,{actionId:a.actionId,handlerType:"setState",source:`target=${r}`}):void 0,E=l==="replace"?"replace":l==="shallow"?"shallow":"deep",A=E!=="deep"?{...d,__mergeMode:E,...S?{__setStateId:S}:{}}:{...d,...S?{__setStateId:S}:{}};if(r==="global"){if(!this.globalStateUpdater){H.warn("Global state updater is not set"),S&&f&&f.completeStateChange(S);return}const T=g?.state?.get()||{},{__setStateId:L,__mergeMode:M,...R}=A,D=E==="deep"?this.deepMergeWithState(R,T):R,U={...D,...S?{__setStateId:S}:{},...E!=="deep"?{__mergeMode:E}:{}};return H.log("setState global:",U),this.globalStateUpdater(U,{render:u}),S&&f&&setTimeout(()=>f.completeStateChange(S),0),{__target:"global",...E!=="deep"?{__mergeMode:E}:{},...D}}else if(r==="isolated"){const T=a.isolatedContext;if(T){const{__mergeMode:L,__setStateId:M,...R}=A;return T.mergeState(R,E),H.log("[handleSetState] isolated state updated:",R,"mergeMode:",E),S&&f&&setTimeout(()=>f.completeStateChange(S),0),{__target:"isolated",...R}}else if(H.warn('[handleSetState] isolated target used but no IsolatedStateContext found. Make sure the component has "isolatedState" attribute. Falling back to local state.'),a.setState){const M=window.__g7PendingLocalState||a.state||{},R=E==="deep"?this.deepMergeWithState(A,M):A;return a.setState(R),S&&f&&setTimeout(()=>f.completeStateChange(S),0),R}else throw S&&f&&f.completeStateChange(S),new It("isolated target used but no IsolatedStateContext found and no setState function in context")}else if(r==="local"||r==="component"||r==="_local"){if(i==="parent"||i==="root"){const L=window.__g7LayoutContextStack||[];if(L.length>0){const M=i==="parent"?L[L.length-1]:L[0];if(M?.setState){const{__mergeMode:R,__setStateId:D,...U}=A,j=E==="deep"?this.deepMergeWithState(U,M.state||{}):U;return H.log(`[handleSetState] scope=${i}: 타겟 컨텍스트에 상태 업데이트`,j),M.setState(j),S&&f&&setTimeout(()=>f.completeStateChange(S),0),j}}H.warn(`[handleSetState] scope=${i}: 레이아웃 컨텍스트 스택이 비어있습니다. current로 폴백합니다.`)}const T=a.setState&&!a._isDispatchFallbackContext;if(H.log("[handleSetState] isRealComponentContext:",T,"context.setState:",!!a.setState,"_isDispatchFallbackContext:",a._isDispatchFallbackContext),T){H.log("[handleSetState] Using COMPONENT setState path"),H.log("[handleSetState] resolvedPayload:",A),H.log("[handleSetState] context.state:",a.state),H.log("[handleSetState] mergeMode:",E);const M=window.__g7PendingLocalState||a.state||{},R=E==="deep"?this.deepMergeWithState(A,{}):A;H.log("[handleSetState] convertedPayload (변경 필드만, dot notation 변환):",R),a.setState(R);const D=E==="deep"?this.deepMergeWithState(A,M):E==="shallow"?{...a.state||{},...A}:A,{__mergeMode:U,__setStateId:j,...P}=D;window.__g7PendingLocalState=P,H.log("[handleSetState] __g7PendingLocalState updated:",P),this.globalStateUpdater&&(this.globalStateUpdater({_local:P},{render:!1}),H.log("[handleSetState] _global._local synced (render:false):",P));const{__mergeMode:X,__setStateId:ge,...Ee}=A;if(E==="replace")window.__g7ForcedLocalFields=Ee;else{const Ce=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=this.deepMergeWithState(Ee,Ce)}return H.log("[handleSetState] __g7ForcedLocalFields updated:",Ee),S&&f&&setTimeout(()=>f.completeStateChange(S),0),{__target:"local",...D}}else if(this.globalStateUpdater){H.log("[handleSetState] Using GLOBAL STATE UPDATER path for _local");const M=window.__g7PendingLocalState||m._local||{};H.log("[handleSetState] currentLocal (with pending):",M);const R=E==="deep"?this.deepMergeWithState(A,M):A;return H.log("[handleSetState] finalLocal (merged):",R),this.globalStateUpdater({_local:R},{render:u}),window.__g7PendingLocalState=R,H.log("[handleSetState] __g7PendingLocalState updated for globalStateUpdater path"),S&&f&&setTimeout(()=>f.completeStateChange(S),0),{__target:"local",...R}}else throw S&&f&&f.completeStateChange(S),new It("setState function is not provided in context and globalStateUpdater is not set")}else if(r.startsWith("_local.")){const T=r.slice(7),{__mergeMode:L,__setStateId:M,...R}=A,D=R.value!==void 0?R.value:Object.values(R)[0];if(a.setState){const j=window.__g7PendingLocalState||a.state||{},P=this.createNestedUpdate(T,D,j),X={...j,...P};return a.setState(P),S&&f&&setTimeout(()=>f.completeStateChange(S),0),X}else throw S&&f&&f.completeStateChange(S),new It("setState function is not provided in context")}else{if(!a.setState)throw S&&f&&f.completeStateChange(S),new It("setState function is not provided in context");const L=window.__g7PendingLocalState||a.state||{},M=E==="deep"?this.deepMergeWithState(A,L):A;return a.setState(M),S&&f&&setTimeout(()=>f.completeStateChange(S),0),M}}async handleParentScopeSetState(e,a,r,i){const l=Un(),u=window.G7Core,d=r==="replace"?"replace":r==="shallow"?"shallow":"deep",f=e.startsWith("$parent."),g=f?"$parent.":"$root.",m=e.slice(g.length);let b,v;if(m==="_local"||m==="_global")b=m,v=void 0;else if(m.startsWith("_local."))b="_local",v=m.slice(7);else if(m.startsWith("_global."))b="_global",v=m.slice(8);else{H.warn(`[handleParentScopeSetState] 지원하지 않는 타겟 형식: ${e}. _local 또는 _global으로 시작해야 합니다.`);return}const S=window.__g7LayoutContextStack||[];if(S.length===0){H.warn(`[handleParentScopeSetState] 레이아웃 컨텍스트 스택이 비어있습니다. target=${e}`);return}const E=f?S[S.length-1]:S[0];if(!E){H.warn(`[handleParentScopeSetState] 타겟 컨텍스트를 찾을 수 없습니다. target=${e}`);return}const A=b==="_global"?E.state?._global:E.state?._local,T=l?.isEnabled()?l.startStateChange(e,A,a,{actionId:i.actionId,handlerType:"setState",source:`target=${e}`}):void 0,{__mergeMode:L,__setStateId:M,...R}=a;if(b==="_global"){if(!this.globalStateUpdater){H.warn("[handleParentScopeSetState] globalStateUpdater가 설정되지 않았습니다."),T&&l&&l.completeStateChange(T);return}const D=u?.state?.get()||{};if(v){const U=R.value!==void 0?R.value:Object.values(R)[0],j=this.createNestedUpdate(v,U,D),P={...D,...j};H.log(`[handleParentScopeSetState] ${e}: 전역 상태 중첩 경로 업데이트`,P),this.globalStateUpdater(P)}else{const U=d==="deep"?this.deepMergeWithState(R,D):R;H.log(`[handleParentScopeSetState] ${e}: 전역 상태 업데이트 (mergeMode=${d})`,U),this.globalStateUpdater(d!=="deep"?{...U,__mergeMode:d}:U)}return T&&l&&setTimeout(()=>l.completeStateChange(T),0),{__target:e,...R}}else{if(!E.setState){H.warn(`[handleParentScopeSetState] 타겟 컨텍스트에 setState가 없습니다. target=${e}`),T&&l&&l.completeStateChange(T);return}const D=E.state||{};if(v){const U=R.value!==void 0?R.value:Object.values(R)[0],j=this.createNestedUpdate(v,U,D),P={...D,...j};return H.log(`[handleParentScopeSetState] ${e}: 로컬 상태 중첩 경로 업데이트`,j),E.setState(j),E.state=P,E.dataContext&&(E.dataContext._local=P),Dd(),T&&l&&setTimeout(()=>l.completeStateChange(T),0),P}else{const U=d!=="deep"?{...R,__mergeMode:d}:R,j=d==="replace"?R:d==="shallow"?{...D,...R}:this.deepMergeWithState(R,D);return H.log(`[handleParentScopeSetState] ${e}: 로컬 상태 업데이트 (mergeMode=${d})`,j),E.setState(U),E.state=j,E.dataContext&&(E.dataContext._local=j),Dd(),T&&l&&setTimeout(()=>l.completeStateChange(T),0),j}}}deepMergeWithState(e,a){const r=["errors"];let i=e;if("..."in e){const u=e["..."];if(u&&typeof u=="object"&&!Array.isArray(u)){const{"...":d,...f}=e;i={...u,...f}}else{const{"...":d,...f}=e;i=f}}const l={...a};for(const[u,d]of Object.entries(i)){if(r.includes(u)){l[u]=d;continue}if(u.includes(".")&&u!=="..."){const f=this.createNestedUpdate(u,d,l);this.deepMergeInto(l,f,l);continue}if(d!==null&&typeof d=="object"&&!Array.isArray(d)&&Object.getPrototypeOf(d)!==Object.prototype&&Object.getPrototypeOf(d)!==null){l[u]=d;continue}d!==null&&typeof d=="object"&&!Array.isArray(d)&&a[u]!==null&&typeof a[u]=="object"&&!Array.isArray(a[u])?l[u]=this.deepMergeWithState(d,a[u]):l[u]=d}return l}deepMergeInto(e,a,r){for(const[i,l]of Object.entries(a)){if(l===null){e[i]=l;continue}if(e[i]===null){e[i]=l;continue}typeof l=="object"&&!Array.isArray(l)&&e[i]!==void 0&&e[i]!==null&&typeof e[i]=="object"&&!Array.isArray(e[i])?(e[i]===r[i]&&(e[i]={...e[i]}),this.deepMergeInto(e[i],l,r[i]||{})):typeof l=="object"&&!Array.isArray(l)&&e[i]===void 0&&r[i]!==null&&typeof r[i]=="object"&&!Array.isArray(r[i])?e[i]={...r[i],...l}:e[i]=l}}createNestedUpdate(e,a,r){const i=e.split(".");if(i.length===1)return{[i[0]]:a};const l={};let u=l,d=r;for(let f=0;f{this.globalStateUpdater({_local:S})};m.push({state:b,setState:v,dataContext:{_local:b||a.data?._local,_global:l?a.data?._global:a.data?._global||i?.state?.get?.(),_computed:a.data?._computed}}),window.__g7LayoutContextStack=m,H.log(`[handleOpenModal] 레이아웃 컨텍스트 스택에 push, 스택 크기: ${m.length}, state:`,b,l?"(direct)":"(fallback via G7Core)")}else H.warn(`[handleOpenModal] 컨텍스트 스택에 push 실패 - setState: ${!!a.setState}, state: ${a.state!==void 0}, G7Core: ${!!i?.state?.getLocal}`);const f=[...r,e];this.globalStateUpdater({modalStack:f,activeModal:e});const g=Un();if(g?.isEnabled()){const m=r.length>0?r[r.length-1]:void 0;g.trackModalOpen?.({modalId:e,modalName:e,scopeType:"isolated",parentModalId:m,initialState:a.state?{...a.state}:{}})}}async handleCloseModal(e){if(!this.globalStateUpdater){H.warn("Global state updater is not set for closeModal");return}const a=e?.data?._global?.modalStack||[],r=a.length>0?a[a.length-1]:null,i=a.slice(0,-1),l=i.length>0?i[i.length-1]:null,u=window.__g7LayoutContextStack||[];if(u.length>0){const d=u[u.length-1];d&&(d.dataContext=void 0),u.pop(),window.__g7LayoutContextStack=u,H.log(`[handleCloseModal] 레이아웃 컨텍스트 스택에서 pop, 스택 크기: ${u.length}`)}if(r){const d=Un();d?.isEnabled()&&d.trackModalClose?.(r,e?.state)}this.globalStateUpdater({modalStack:i,activeModal:l})}async handleShowAlert(e,a){let r=e;this.translationEngine&&this.translationContext&&e.startsWith("$t:")&&(r=this.translationEngine.resolveTranslations(e,this.translationContext,a.data)),alert(r)}async handleToast(e,a){const{type:r="info",message:i,icon:l,duration:u}=e;if(r==="error"){const f=a.data?.error;if((f?.error_code==="identity_verification_required"||f?.data?.error_code==="identity_verification_required")&&St.consumeDomainNoticeShown()){H.log("[Toast] IDV 도메인 안내 표출됨 — 중복 가드 토스트 1건 skip");return}}let d=i;if(this.translationEngine&&this.translationContext&&i?.startsWith("$t:")&&(d=this.translationEngine.resolveTranslations(i,this.translationContext,a.data)),this.globalStateUpdater){const g={id:`toast_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,type:r,message:d,...l&&{icon:l},...u&&{duration:u}},S=[...window.G7Core?.state?.get()?.toasts||[],g];this.globalStateUpdater({toasts:S})}else H.log(`[Toast ${r}] ${d}`)}async handleSwitch(e,a){const{cases:r}=e;if(!r){H.warn("switch handler requires cases property");return}const i=this.resolveParams(e.params,a.data);let l;if(i?.value!==void 0?(l=i.value,H.log("switch handler: using params.value as case key:",l)):(l=a.data?.$args?.[0],H.log("switch handler: using $args[0] as case key:",l)),l==null){if(r.default)return H.log("switch handler: case key is undefined, using default case"),await this.executeAction(r.default,a);H.warn("switch handler: case key is not defined and no default case");return}const u=String(l);let d=r[u];if(!d&&r.default&&(H.log(`switch handler: no case found for key "${u}", using default case`),d=r.default),!d){H.warn(`switch handler: no case found for key "${u}" and no default case`);return}return await this.executeAction(d,a)}async handleConditions(e,a){const{conditions:r}=e;if(!r||!Array.isArray(r)){H.warn("conditions handler requires conditions array");return}const i=a.data||{},l=op(r,i,this.bindingEngine);if(!l.matched){H.log("conditions handler: no matching branch found");return}const u=r[l.branchIndex];if(H.log(`conditions handler: matched branch ${l.branchIndex}`),!u.then){H.warn('conditions handler: matched branch has no "then" action');return}return Array.isArray(u.then)?await this.handleSequence({...e,actions:u.then},a):await this.executeAction(u.then,a)}handleStartInterval(e,a){const r=typeof e.id=="string"?e.id:"",i=Number(e.intervalMs??1e3),l=Array.isArray(e.actions)?e.actions:[];if(r===""||!l.length||i<=0)return H.warn("startInterval requires non-empty id, positive intervalMs, and actions array"),{success:!1};const u=this.intervals.get(r);u&&(clearInterval(u),this.intervals.delete(r));const d=setInterval(()=>{for(const f of l)this.executeAction(f,a).catch(g=>{H.error(`[startInterval:${r}] tick action failed`,g)})},i);return this.intervals.set(r,d),{success:!0,id:r}}handleStopInterval(e){const a=typeof e.id=="string"?e.id:"";if(a==="")return H.warn("stopInterval requires id parameter"),{success:!1};const r=this.intervals.get(a);return r&&(clearInterval(r),this.intervals.delete(a)),{success:!0,id:a}}stopAllIntervals(){for(const e of this.intervals.values())clearInterval(e);this.intervals.clear()}async handleSequence(e,a){const r=e.actions||e.params?.actions;if(!r||!Array.isArray(r)||r.length===0)return H.warn("sequence handler requires non-empty actions array"),[];const i=Un(),l=i?.isEnabled()&&i.startSequenceExecution?.({eventType:e.type})||"";window.__g7SequenceLocalSync=void 0;const u=[];let d,f=a.state?{...a.state}:{},g=a.isolatedContext?.state?{...a.isolatedContext.state}:{},m=a.data?._computed||{};const b=window.G7Core,v=()=>({_global:b?.state?.get()||{},_local:{...f},_isolated:Object.keys(g).length>0?{...g}:void 0});for(let S=0;S0){const R={},D={...a.data,_local:f,_computed:R,$computed:R,_isolated:g};for(const[U,j]of Object.entries(M))if(typeof j=="string"){const P=j.trim();if(P.startsWith("{{")&&P.endsWith("}}"))try{const X=P.slice(2,-2).trim();R[U]=this.bindingEngine.evaluateExpression(X,D,{skipCache:!0})}catch{R[U]=m[U]}}m=R,H.log("[handleSequence] _computed recalculated after setState:",m)}}if(E.handler!=="setState"){const M=window.__g7SequenceLocalSync;if(M&&M!==f){f=M,window.__g7SequenceLocalSync=void 0,H.log("[handleSequence] currentState synchronized from __g7SequenceLocalSync after custom handler:",E.handler);const R=a.data?._computedDefinitions;if(R&&Object.keys(R).length>0){const D={},U={...a.data,_local:f,_computed:D,$computed:D,_isolated:g};for(const[j,P]of Object.entries(R))if(typeof P=="string"){const X=P.trim();if(X.startsWith("{{")&&X.endsWith("}}"))try{const ge=X.slice(2,-2).trim();D[j]=this.bindingEngine.evaluateExpression(ge,U,{skipCache:!0})}catch{D[j]=m[j]}}m=D,H.log("[handleSequence] _computed recalculated after custom handler:",m)}}}l&&i?.isEnabled()&&i.captureSequenceActionAfter?.(l,S,v(),Date.now()-A,L.data)}catch(L){throw l&&i?.isEnabled()&&(i.captureSequenceActionAfter?.(l,S,v(),Date.now()-A,void 0,L),i.endSequenceExecution?.(l,L)),H.error(`sequence handler: action[${S}] failed:`,L),L}}return window.__g7SequenceLocalSync=void 0,l&&i?.isEnabled()&&i.endSequenceExecution?.(l),u}async handleParallel(e,a){const r=e.actions||e.params?.actions;if(!r||!Array.isArray(r)||r.length===0)return H.warn("parallel handler requires non-empty actions array"),[];H.log(`parallel handler: executing ${r.length} actions in parallel`);const i=a.isolatedContext?{...a.isolatedContext,state:{...a.isolatedContext.state}}:null,l=r.map((f,g)=>{const m={...a,isolatedContext:i};return this.executeAction(f,m).catch(b=>{throw H.error(`parallel handler: action[${g}] failed:`,b),b})}),u=await Promise.allSettled(l),d=u.filter(f=>f.status==="rejected").length;return d>0&&H.warn(`parallel handler: ${d}/${r.length} actions failed`),u}async handleLoadScript(e,a,r){const{src:i,id:l,async:u=!0,defer:d=!1}=e;if(!i)throw new It('loadScript handler requires "src" parameter',a);const f=l||`script_${i.replace(/[^a-zA-Z0-9]/g,"_")}`;return us.loadedScripts.has(f)?(H.log(`loadScript: script already loaded, skipping: ${f}`),a.onLoad&&await this.executeAction(a.onLoad,r),!0):document.getElementById(f)?(H.log(`loadScript: script element already exists: ${f}`),us.loadedScripts.add(f),a.onLoad&&await this.executeAction(a.onLoad,r),!0):(H.log(`loadScript: loading script: ${i}`),new Promise((m,b)=>{const v=document.createElement("script");v.id=f,v.src=i,v.async=u,v.defer=d,v.onload=async()=>{if(H.log(`loadScript: script loaded successfully: ${f}`),us.loadedScripts.add(f),a.onLoad)try{await this.executeAction(a.onLoad,r)}catch(S){H.error("loadScript: onLoad action failed:",S)}m(!0)},v.onerror=S=>{H.error(`loadScript: failed to load script: ${i}`,S),b(new It(`Failed to load script: ${i}`,a))},document.head.appendChild(v)}))}async handleCallExternal(e,a,r){const i=e.constructor,l=e.args||{},u=e.method,d=e.methodArgs||[],f=e.callbackEvent,g=e.embedTarget,m=e.callbackSetState,b=e.callbackAction;if(!i)throw new It('callExternal handler requires "constructor" parameter',a);const v=this.getNestedProperty(window,i);if(!v||typeof v!="function")throw new It(`Constructor not found or not a function: ${i}. Make sure the script is loaded first using loadScript handler.`,a);H.log(`callExternal: calling constructor ${i}`);const S={...l};for(const[A,T]of Object.entries(l))T===!0&&(S[A]=L=>{if(H.log(`callExternal: callback triggered for ${A}`,L),f&&typeof window<"u"&&window.G7Core?.componentEvent&&window.G7Core.componentEvent.emit(f,L),m&&r.setState){const M=U=>{const j={};for(const[P,X]of Object.entries(U))typeof X=="string"?j[P]=this.getNestedProperty(L,X):typeof X=="object"&&X!==null&&(j[P]=M(X));return j},R=M(m);H.log("callExternal: callbackSetState mapping result",R);const D=this.deepMergeWithState(R,r.state||{});H.log("callExternal: merged with existing state",D),r.setState(D)}else f&&r.setState&&r.setState({[`${f.replace(/:/g,"_")}_result`]:L});if(b){const M={...r,data:{...r.data,$event:L}},R=Array.isArray(b)?b:[b];for(const D of R)try{this.executeAction(D,M)}catch(U){H.error("callExternal: callbackAction failed:",U)}}});const E=new v(S);if(u&&typeof E[u]=="function"){if(H.log(`callExternal: calling method ${u}`),u==="embed"&&g){const A=document.querySelector(g);if(A)return E[u](A,...d);throw new It(`Embed target element not found: ${g}`,a)}return E[u](...d)}return E}async handleCallExternalEmbed(e,a,r){const i=e.constructor,l=e.args||{},u=e.callbackSetState,d=e.callbackEvent,f=e.layerClassName,g=e.callbackAction;if(!i)throw new It('callExternalEmbed handler requires "constructor" parameter',a);const m=this.getNestedProperty(window,i);if(!m||typeof m!="function")throw new It(`Constructor not found or not a function: ${i}. Make sure the script is loaded first.`,a);H.log(`callExternalEmbed: creating layer for ${i}`);const{layer:b,closeLayer:v}=this.createEmbedLayer(f),S={...l};for(const[A,T]of Object.entries(l))T===!0&&(S[A]=L=>{if(H.log(`callExternalEmbed: callback triggered for ${A}`,L),v(),d&&typeof window<"u"&&window.G7Core?.componentEvent&&window.G7Core.componentEvent.emit(d,L),u&&r.setState){const M=U=>{const j={};for(const[P,X]of Object.entries(U))typeof X=="string"?j[P]=this.getNestedProperty(L,X):typeof X=="object"&&X!==null&&(j[P]=M(X));return j},R=M(u);H.log("callExternalEmbed: callbackSetState mapping result",R);const D=this.deepMergeWithState(R,r.state||{});H.log("callExternalEmbed: merged with existing state",D),r.setState(D)}if(g){const M={...r,data:{...r.data,$event:L}},R=Array.isArray(g)?g:[g];for(const D of R)try{this.executeAction(D,M)}catch(U){H.error("callExternalEmbed: callbackAction failed:",U)}}});const E=new m(S);if(typeof E.embed=="function")E.embed(b),H.log("callExternalEmbed: embedded in layer");else throw v(),new It(`Constructor ${i} does not have embed method`,a);return E}isImeComposing(e){return e?.isComposing===!0||e?.keyCode===229}createEmbedLayer(e){const a=document.createElement("div");a.id="g7-embed-overlay",a.style.cssText=` position: fixed; inset: 0; background-color: rgba(0, 0, 0, 0.5); @@ -47,11 +47,11 @@ Error generating stack: `+c.message+` justify-content: center; color: #666; transition: background-color 0.2s; - `,i.onmouseenter=()=>{i.style.backgroundColor="rgba(0, 0, 0, 0.2)"},i.onmouseleave=()=>{i.style.backgroundColor="rgba(0, 0, 0, 0.1)"};const l=()=>{a.parentNode&&a.parentNode.removeChild(a)};i.onclick=l;const u=d=>{this.isImeComposing(d)||d.key==="Escape"&&(l(),document.removeEventListener("keydown",u))};return document.addEventListener("keydown",u),a.onclick=d=>{d.target===a&&l()},r.appendChild(i),a.appendChild(r),document.body.appendChild(a),{overlay:a,layer:r,closeLayer:l}}getNestedProperty(e,a){return a.split(".").reduce((r,i)=>r&&r[i]!==void 0?r[i]:void 0,e)}async handleSaveToLocalStorage(e,a){const{key:r,value:i}=e;if(!r)return H.error("saveToLocalStorage: key parameter is required"),!1;try{const l=typeof i=="string"?i:JSON.stringify(i);return localStorage.setItem(r,l),H.log(`saveToLocalStorage: saved ${r}`,i),!0}catch(l){return H.error("saveToLocalStorage: failed to save",{key:r,error:l}),!1}}async handleLoadFromLocalStorage(e,a){const{key:r,target:i,stateKey:l,defaultValue:u}=e;if(!r)return H.error("loadFromLocalStorage: key parameter is required"),u;try{const d=localStorage.getItem(r);if(d===null)return H.log(`loadFromLocalStorage: no value found for ${r}, using default`),l&&a.setState&&a.setState({[l]:u}),u;let f;try{f=JSON.parse(d)}catch{f=d}return H.log(`loadFromLocalStorage: loaded ${r}`,f),l&&a.setState&&a.setState({[l]:f}),f}catch(d){return H.error("loadFromLocalStorage: failed to load",{key:r,error:d}),u}}async handleCustomAction(e,a){const r=this.customHandlers.get(e.handler);if(!r){if(this.previewMode){H.warn(`[Preview] Unknown action handler "${e.handler}" — skipped (preview mode)`);return}const i=new It(`Unknown action handler: ${e.handler}`,e);throw i.unknownHandler=!0,i}return await r(e,a)}resolveParams(e,a){if(!e)return{};const r={};for(const[i,l]of Object.entries(e))i.includes("{{")&&H.warn(`[resolveParams] setState params의 키에 표현식이 포함되어 있습니다: "${i}". 키는 해석되지 않습니다. 배열 항목 수정은 .map()/.filter() 패턴을 사용하세요.`),typeof l=="string"&&l.includes("{{")?r[i]=this.evaluateExpression(l,a):typeof l=="string"?r[i]=l:Array.isArray(l)?r[i]=l.map(u=>typeof u=="string"&&u.includes("{{")?this.evaluateExpression(u,a):u):typeof l=="object"&&l!==null&&!Array.isArray(l)&&Object.getPrototypeOf(l)!==Object.prototype&&Object.getPrototypeOf(l)!==null?r[i]=l:typeof l=="object"&&l!==null?r[i]=this.resolveParams(l,a):r[i]=l;return r}resolveValue(e,a){return a?this.bindingEngine.resolveBindings(e,a,{skipCache:!0}):e}evaluateExpressions(e,a){let r={};for(const[i,l]of Object.entries(e))if(i==="..."){let u=l;typeof l=="string"&&l.includes("{{")&&(u=this.evaluateExpression(l,a)),u&&typeof u=="object"&&!Array.isArray(u)&&(r={...r,...u})}else typeof l=="string"&&l.includes("{{")?r[i]=this.evaluateExpression(l,a):typeof l=="object"&&l!==null&&!Array.isArray(l)?r[i]=this.evaluateExpressions(l,a):r[i]=l;return r}evaluateExpressionsIfNeeded(e,a){const r={};for(const[i,l]of Object.entries(e))typeof l=="string"&&l.includes("{{")?r[i]=this.evaluateExpression(l,a):r[i]=l;return r}evaluateExpression(e,a){if(!a)return e;const r=e.match(/^\{\{(.+)\}\}$/);if(!(r&&!r[1].includes("}}")&&!r[1].includes("{{"))){let d=a;if(e.includes("_global")){const g=window.G7Core?.state?.get()?._global;g&&(d={...a,_global:g})}if(e.includes("_computed")||e.includes("$computed")){const g=window.__g7ActionContext?.computedRef?.current;g&&Object.keys(g).length>0&&(d={...d,_computed:g,$computed:g})}return this.bindingEngine.resolveBindings(e,d,{skipCache:!0})}let l=r[1].trim();l=l.replace(/\$args\.(\d+)/g,"$args[$1]");let u=a;if(l.includes("_global")){const f=window.G7Core?.state?.get()?._global;f&&(u={...a,_global:f})}if(l.includes("_computed")||l.includes("$computed")){const f=window.__g7ActionContext?.computedRef?.current;f&&Object.keys(f).length>0&&(u={...u,_computed:f,$computed:f})}l.includes("_global.modules")&&(H.log("[evaluateExpression] expression:",l),H.log("[evaluateExpression] dataContext._global:",u._global),H.log("[evaluateExpression] dataContext._global?.modules:",u._global?.modules));try{const d=this.bindingEngine.evaluateExpression(l,u);return l.includes("_global.modules")&&H.log("[evaluateExpression] result:",d),typeof d=="string"&&d.startsWith("$t:")&&this.translationEngine&&this.translationContext?this.translationEngine.resolveTranslations(d,this.translationContext,a):d}catch(d){return H.error("Expression evaluation failed:",e,d),e}}setDefaultContext(e){this.defaultContext={...this.defaultContext,...e}}setGlobalStateUpdater(e){this.globalStateUpdater=e}getGlobalStateUpdater(){return this.globalStateUpdater}async dispatchAction(e,a){const r={...this.defaultContext,...a,data:{...this.defaultContext.data,...a?.data}};if(e.confirm){let i=this.resolveValue(e.confirm,r.data);if(this.translationEngine&&this.translationContext&&i.startsWith("$t:")&&(i=this.translationEngine.resolveTranslations(i,this.translationContext,r.data)),!confirm(i))return{success:!1}}try{return await this.executeAction(e,r)}catch(i){if(H.error("dispatchAction failed:",i),e.onError){const l=i instanceof It&&i.originalError?{message:i.originalError.message,response:i.originalError.response}:{message:i instanceof Error?i.message:String(i)},u={...r,data:{...r.data,error:l}},d=Array.isArray(e.onError)?e.onError:[e.onError];for(const f of d)await this.executeAction(f,u)}return{success:!1,error:i instanceof Error?i:new Error(String(i))}}}registerHandler(e,a,r){this.customHandlers.set(e,a);const i=Un();i?.isEnabled()&&i.trackHandlerRegistration(e,r?.category??"custom",r?.description,r?.source)}unregisterHandler(e){this.customHandlers.delete(e);const a=Un();a?.isEnabled()&&a.trackHandlerUnregistration(e)}getRegisteredHandlers(){return Array.from(this.customHandlers.keys())}getHandler(e){return this.customHandlers.get(e)}normalizeDebounceConfig(e){return typeof e=="number"?{delay:e,leading:!1,trailing:!0}:{delay:e.delay,leading:e.leading??!1,trailing:e.trailing??!0}}extractEventData(e){const a=e.target;if(a&&!("tagName"in a)){const l={type:e.type??"custom",target:{value:a.value,name:a.name??""}};return e._changedKeys&&(l._changedKeys=e._changedKeys),l}const i=a?{value:a.value,name:a.name??"",checked:a.checked??!1,type:a.type??"",tagName:a.tagName}:{};if(e.type==="scroll"&&a){const l=a;i.scrollHeight=l.scrollHeight??0,i.scrollTop=l.scrollTop??0,i.clientHeight=l.clientHeight??0,i.scrollLeft=l.scrollLeft??0,i.clientWidth=l.clientWidth??0,i.scrollWidth=l.scrollWidth??0}return{type:e.type,target:a?i:null}}executeDebouncedAction(e,a,r,i,l){const u={...r,$event:a,$args:l},d={type:a.type,target:a.target,preventDefault:()=>{},stopPropagation:()=>{}};this.createHandler(e,u,i)(d)}handleDebouncedAction(e,a,r,i,l,u){const d=this.normalizeDebounceConfig(e.debounce),f=l||`default-${e.handler}-${Date.now()}`,g=this.extractEventData(a),m=g._changedKeys;if(m&&Array.isArray(m)&&g?.target?.value&&typeof g.target.value=="object"&&!Array.isArray(g.target.value)){const E=this.debounceAccumulatedValues.get(f);if(E){const A={...E};for(const T of m)A[T]=g.target.value[T];g.target.value=A}this.debounceAccumulatedValues.set(f,g.target.value)}const b=this.debounceTimers.get(f);b&&(clearTimeout(b),this.debounceTimers.delete(f));const v=Un();v?.isEnabled()&&v.trackAction({handler:typeof e.handler=="string"?e.handler:String(e.handler),type:e.type,status:"pending",params:e.params,debounce:{delay:d.delay,status:"pending",scheduledAt:Date.now()}});const S=!this.debounceTimers.has(f+"_leading");if(d.leading&&S&&(this.debounceTimers.set(f+"_leading",setTimeout(()=>{},0)),this.executeDebouncedAction(e,g,r,i,u),v?.isEnabled()&&v.trackAction({handler:typeof e.handler=="string"?e.handler:String(e.handler),type:e.type,status:"success",params:e.params,debounce:{delay:d.delay,status:"executed",executedAt:Date.now(),mode:"leading"}})),d.trailing){const E=()=>{this.executeDebouncedAction(e,g,r,i,u),v?.isEnabled()&&v.trackAction({handler:typeof e.handler=="string"?e.handler:String(e.handler),type:e.type,status:"success",params:e.params,debounce:{delay:d.delay,status:"executed",executedAt:Date.now(),mode:"trailing"}})},A=setTimeout(()=>{this.debounceTimers.delete(f),this.debounceTimers.delete(f+"_leading"),this.pendingDebounceFlushers.delete(f),this.debounceAccumulatedValues.delete(f),E()},d.delay);this.debounceTimers.set(f,A),this.pendingDebounceFlushers.set(f,E)}}clearDebounceTimers(e){if(e)for(const[a,r]of this.debounceTimers)a.startsWith(e+"-")&&(clearTimeout(r),this.debounceTimers.delete(a),this.pendingDebounceFlushers.delete(a),this.debounceAccumulatedValues.delete(a));else{for(const a of this.debounceTimers.values())clearTimeout(a);this.debounceTimers.clear(),this.pendingDebounceFlushers.clear(),this.debounceAccumulatedValues.clear()}}debouncedCall(e,a,r){const i=this.debounceTimers.get(e);i&&(clearTimeout(i),this.debounceTimers.delete(e));const l=setTimeout(()=>{this.debounceTimers.delete(e),this.pendingDebounceFlushers.delete(e),r()},a);this.debounceTimers.set(e,l),this.pendingDebounceFlushers.set(e,r)}flushPendingDebounceTimers(){if(this.pendingDebounceFlushers.size===0)return;const e=new Map(this.pendingDebounceFlushers);for(const[a,r]of e){const i=this.debounceTimers.get(a);i&&(clearTimeout(i),this.debounceTimers.delete(a)),this.debounceTimers.delete(a+"_leading"),this.pendingDebounceFlushers.delete(a),r()}this.globalStateUpdater&&this.globalStateUpdater({})}bindActionsToProps(e,a,r){const i={...e};if(e.actions&&Array.isArray(e.actions)){const l=new Map;for(const m of e.actions){const b=this.resolveActionRef(m),v=b.event||this.getEventHandlerName(b.type);l.has(v)||l.set(v,[]),l.get(v).push(b)}const u=e.name||e.id||"unknown",d=l.has("onDrop"),f=l.has("onDragOver"),g=l.has("onDragEnter");d&&!f&&(i.onDragOver=m=>{m.preventDefault()}),d&&!g&&(i.onDragEnter=m=>{m.preventDefault()});for(const[m,b]of l)i[m]=(...v)=>{for(const S of b){const E=v[0],A=E&&typeof E=="object"&&"preventDefault"in E;if(A&&(m==="onDragOver"||m==="onDrop")&&E.preventDefault(),A&&S.key&&"key"in E){if(this.isImeComposing(E)){H.log("Key filter skipped (IME composing):",S.key);continue}if(E.key!==S.key){H.log("Key filter not matched:",S.key,"actual:",E.key);continue}H.log("Key filter matched:",S.key)}if(S.debounce){const T=`${u}-${S.handler}-${m}`,L=E&&typeof E=="object"&&!("preventDefault"in E)&&"target"in E&&E.target!==null;let M;if(A)M=E;else if(L){const D={type:"custom",target:E.target,preventDefault:()=>{},stopPropagation:()=>{}};E._changedKeys&&(D._changedKeys=E._changedKeys),M=D}else M=new Event("custom");const R=S.event?{...a,$args:v}:a;this.handleDebouncedAction(S,M,R,r,T,v)}else if(this.flushPendingDebounceTimers(),S.event){const T={...a,$args:v},L=A?E:new Event("custom");this.createHandler(S,T,r)(L)}else if(A)this.createHandler(S,a,r)(E);else if(E&&typeof E=="object"&&!("preventDefault"in E)&&"target"in E&&E.target!==null){const L={type:"custom",target:E.target,preventDefault:()=>{},stopPropagation:()=>{}};this.createHandler(S,a,r)(L)}}}}return i}getEventHandlerName(e){return{click:"onClick",change:"onChange",input:"onInput",submit:"onSubmit",focus:"onFocus",blur:"onBlur",keydown:"onKeyDown",keyup:"onKeyUp",keypress:"onKeyPress",mousedown:"onMouseDown",mouseup:"onMouseUp",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",scroll:"onScroll",dragstart:"onDragStart",drag:"onDrag",dragend:"onDragEnd",dragenter:"onDragEnter",dragover:"onDragOver",dragleave:"onDragLeave",drop:"onDrop"}[e]||`on${e.charAt(0).toUpperCase()}${e.slice(1)}`}sanitizeForDevTools(e,a=5){const r=new WeakSet,i=(l,u)=>{if(l==null||typeof l=="string"||typeof l=="number"||typeof l=="boolean")return l;if(u>a)return"[Max Depth Exceeded]";if(typeof l=="function")return`[Function: ${l.name||"anonymous"}]`;if(l instanceof Element)return`[Element: ${l.tagName}${l.className?"."+l.className.split(" ").join("."):""}]`;if(l instanceof Event)return`[Event: ${l.type}]`;if(Array.isArray(l)){if(r.has(l))return"[Circular Array]";r.add(l);const d=l.slice(0,10).map(f=>i(f,u+1));return l.length>10&&d.push(`... ${l.length-10} more items`),d}if(typeof l=="object"){if(r.has(l))return"[Circular Reference]";r.add(l);const d={},f=Object.keys(l),g=f.slice(0,20);for(const m of g)try{d[m]=i(l[m],u+1)}catch{d[m]="[Error accessing property]"}return f.length>20&&(d["..."]=`${f.length-20} more properties`),d}return String(l)};return i(e,0)}};$(cs,"loadedScripts",new Set);let oo=cs,Kl=null;function Zp(o){return Kl||(Kl=new oo(o)),Kl}function eC(o){Kl=o}const em=ct("TransitionManager");class tC{constructor(){$(this,"isPending",!1);$(this,"subscribers",new Set)}setPending(e){this.isPending!==e&&(em.log("setPending:",{from:this.isPending,to:e,stack:new Error().stack}),this.isPending=e,this.notifySubscribers())}getIsPending(){return this.isPending}subscribe(e){return this.subscribers.add(e),()=>{this.subscribers.delete(e)}}notifySubscribers(){em.log("notifySubscribers:",{isPending:this.isPending,subscriberCount:this.subscribers.size}),this.subscribers.forEach(e=>{e(this.isPending)})}clearSubscribers(){this.subscribers.clear()}}const Na=new tC,Wl=ct("TransitionContext"),tm=N.createContext({isTransitioning:!1}),Dd=({children:o})=>{const[e,a]=N.useState(()=>{const i=Na.getIsPending();return Wl.log("Initial state:",i),i});N.useEffect(()=>{Wl.log("Subscribing to TransitionManager");const i=Na.subscribe(l=>{Wl.log("Received isPending update:",l),a(l)});return()=>{Wl.log("Unsubscribing from TransitionManager"),i()}},[]);const r=N.useMemo(()=>({isTransitioning:e}),[e]);return ut.jsx(tm.Provider,{value:r,children:o})},nm=()=>N.useContext(tm),Yl="__g7LocalInitTracking";function Od(){const o=globalThis;return o[Yl]||(o[Yl]={hash:"",timestamp:void 0,consumed:void 0}),o[Yl]}function nC(){const o=globalThis;o[Yl]={hash:"",timestamp:void 0,consumed:void 0}}function aC(o){Od().consumed=o}function rC(o){return Od().consumed===o}function iC(o,e){return typeof o=="number"&&typeof e=="number"?Math.max(o,e):e??o}function sC(o,e){if(e===void 0)return o;if(!(o!==null&&typeof o=="object"&&e!==null&&typeof e=="object"&&!rC(o)))return e;const{_forceLocalInit:r,...i}=o,{_forceLocalInit:l,...u}=e,d={...i,...u},f=iC(r,l);return f!==void 0&&(d._forceLocalInit=f),d}function oC(o){return o<768?"mobile":o<1024?"tablet":"desktop"}function am(o){const e=oC(o);return{width:o,isMobile:e==="mobile",isTablet:e==="tablet",isDesktop:e==="desktop",matchedPreset:e}}const Ld=N.createContext(am(1024)),Xl=({children:o,overrideWidth:e})=>{const[a,r]=N.useState(()=>ci.getWidth());N.useEffect(()=>{const u=ci.subscribe(d=>{r(d)});return()=>{u()}},[]);const i=e??a,l=N.useMemo(()=>am(i),[i]);return ut.jsx(Ld.Provider,{value:l,children:o})},Md=()=>N.useContext(Ld);window.G7Core?.createLogger?.("Core:State");function lC(o,e,a,r){const{syncOnControlledChange:i=!0,isEqual:l}=r??{},u=o!==void 0;N.useRef(u);const[d,f]=N.useState(o!==void 0?o:e),g=d,m=N.useRef(o),b=N.useRef(!1);N.useEffect(()=>{if(b.current){m.current=o;return}i&&u&&o!==m.current&&(l?!l(d,o):d!==o)&&f(o),m.current=o},[o,u,i,l,d]);const v=N.useCallback(S=>{const E=typeof S=="function"?S(g):S;(l?l(g,E):g===E)||(b.current=!0,f(E),a?.(E),requestAnimationFrame(()=>{b.current=!1}))},[g,u,a,l]);return[g,v]}function cC(o,e){return o===e?!0:o.length!==e.length?!1:o.every((a,r)=>a===e[r])}function rm(o,e){if(o===e)return!0;const a=Object.keys(o),r=Object.keys(e);return a.length!==r.length?!1:a.every(i=>o[i]===e[i])}const im=N.createContext({}),uC=({children:o,value:e})=>ut.jsx(im.Provider,{value:e,children:o}),dC=()=>N.useContext(im),fC=(o,e)=>{if(!o)return;const a=e.split(".");let r=o;for(const i of a){if(r==null)return;r=r[i]}return r},hC=(o,e,a)=>{const r=e.split(".");if(r.length===1)return{...o,[r[0]]:a};const i={...o};let l=i;for(let u=0;u{ts.warn("IsolatedStateContext not available: setState called outside IsolatedStateProvider")},getState:()=>{},mergeState:()=>{ts.warn("IsolatedStateContext not available: mergeState called outside IsolatedStateProvider")},stateRef:{current:{}},scopeId:""},sm=N.createContext(gC);let pC=0;function mC(){return`isolated-${++pC}-${Date.now().toString(36)}`}function om(o,e){if(e==null)return o;if(typeof e!="object"||Array.isArray(e))return e;const a={...o};for(const r of Object.keys(e)){const i=e[r],l=o?.[r];i!==null&&typeof i=="object"&&!Array.isArray(i)&&l!==null&&typeof l=="object"&&!Array.isArray(l)?a[r]=om(l,i):a[r]=i}return a}function yC(o,e){return e?e.split(".").reduce((a,r)=>a?.[r],o):o}function bC(o,e,a){const r=e.split("."),i={...o};let l=i;for(let u=0;u{const i=N.useRef(e||mC()).current,[l,u]=N.useState(o),d=N.useRef(l);d.current=l;const f=N.useCallback(S=>yC(d.current,S),[]),g=N.useCallback((S,E)=>{u(A=>{const T=bC(A,S,E);return ts.log(`[${i}] setState: ${S} =`,E),T})},[i]),m=N.useCallback((S,E="deep")=>{u(A=>{let T;return E==="replace"?T=S:E==="shallow"?T={...A,...S}:T=om(A,S),ts.log(`[${i}] mergeState (${E}):`,S),T})},[i]),b=N.useMemo(()=>({state:l,setState:g,getState:f,mergeState:m,stateRef:d,scopeId:i}),[l,g,f,m,i]),v=N.useMemo(()=>({state:d.current,setState:g,getState:f,mergeState:m}),[g,f,m]);return N.useEffect(()=>{const S=window.G7Core,E=window.__g7IsolatedStates||{};return window.__g7IsolatedStates||(window.__g7IsolatedStates=E),E[i]=v,S&&(S._isolatedStates||(S._isolatedStates={}),S._isolatedStates[i]=l),S?.devTools?.isEnabled?.()&&S.devTools.emit?.("isolated:created",{id:i,state:l}),ts.log(`[${i}] IsolatedStateProvider mounted with initial state:`,l),()=>{delete E[i],S?._isolatedStates&&delete S._isolatedStates[i],S?.devTools?.isEnabled?.()&&S.devTools.emit?.("isolated:destroyed",{id:i}),ts.log(`[${i}] IsolatedStateProvider unmounted`)}},[i,v]),N.useEffect(()=>{const S=window.G7Core,E=window.__g7IsolatedStates;E?.[i]&&(E[i].state=l),S?._isolatedStates&&(S._isolatedStates[i]=l),S?.devTools?.isEnabled?.()&&S.devTools.emit?.("isolated:updated",{id:i,state:l})},[l,i]),ut.jsx(sm.Provider,{value:b,children:a})},SC=()=>{const o=N.useContext(sm);return o.scopeId?o:null};var Ar=zg();function wC(){for(var o=arguments.length,e=new Array(o),a=0;ar=>{e.forEach(i=>i(r))},e)}const Jl=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function ns(o){const e=Object.prototype.toString.call(o);return e==="[object Window]"||e==="[object global]"}function $d(o){return"nodeType"in o}function Tn(o){var e,a;return o?ns(o)?o:$d(o)&&(e=(a=o.ownerDocument)==null?void 0:a.defaultView)!=null?e:window:window}function Nd(o){const{Document:e}=Tn(o);return o instanceof e}function lo(o){return ns(o)?!1:o instanceof Tn(o).HTMLElement}function lm(o){return o instanceof Tn(o).SVGElement}function as(o){return o?ns(o)?o.document:$d(o)?Nd(o)?o:lo(o)||lm(o)?o.ownerDocument:document:document:document}const Ia=Jl?N.useLayoutEffect:N.useEffect;function Id(o){const e=N.useRef(o);return Ia(()=>{e.current=o}),N.useCallback(function(){for(var a=arguments.length,r=new Array(a),i=0;i{o.current=setInterval(r,i)},[]),a=N.useCallback(()=>{o.current!==null&&(clearInterval(o.current),o.current=null)},[]);return[e,a]}function co(o,e){e===void 0&&(e=[o]);const a=N.useRef(o);return Ia(()=>{a.current!==o&&(a.current=o)},e),a}function uo(o,e){const a=N.useRef();return N.useMemo(()=>{const r=o(a.current);return a.current=r,r},[...e])}function Ql(o){const e=Id(o),a=N.useRef(null),r=N.useCallback(i=>{i!==a.current&&e?.(i,a.current),a.current=i},[]);return[a,r]}function Hd(o){const e=N.useRef();return N.useEffect(()=>{e.current=o},[o]),e.current}let zd={};function fo(o,e){return N.useMemo(()=>{if(e)return e;const a=zd[o]==null?0:zd[o]+1;return zd[o]=a,o+"-"+a},[o,e])}function cm(o){return function(e){for(var a=arguments.length,r=new Array(a>1?a-1:0),i=1;i{const d=Object.entries(u);for(const[f,g]of d){const m=l[f];m!=null&&(l[f]=m+o*g)}return l},{...e})}}const rs=cm(1),ho=cm(-1);function EC(o){return"clientX"in o&&"clientY"in o}function jd(o){if(!o)return!1;const{KeyboardEvent:e}=Tn(o.target);return e&&o instanceof e}function _C(o){if(!o)return!1;const{TouchEvent:e}=Tn(o.target);return e&&o instanceof e}function Ud(o){if(_C(o)){if(o.touches&&o.touches.length){const{clientX:e,clientY:a}=o.touches[0];return{x:e,y:a}}else if(o.changedTouches&&o.changedTouches.length){const{clientX:e,clientY:a}=o.changedTouches[0];return{x:e,y:a}}}return EC(o)?{x:o.clientX,y:o.clientY}:null}const go=Object.freeze({Translate:{toString(o){if(!o)return;const{x:e,y:a}=o;return"translate3d("+(e?Math.round(e):0)+"px, "+(a?Math.round(a):0)+"px, 0)"}},Scale:{toString(o){if(!o)return;const{scaleX:e,scaleY:a}=o;return"scaleX("+e+") scaleY("+a+")"}},Transform:{toString(o){if(o)return[go.Translate.toString(o),go.Scale.toString(o)].join(" ")}},Transition:{toString(o){let{property:e,duration:a,easing:r}=o;return e+" "+a+"ms "+r}}}),um="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function AC(o){return o.matches(um)?o:o.querySelector(um)}const xC={display:"none"};function TC(o){let{id:e,value:a}=o;return Ye.createElement("div",{id:e,style:xC},a)}function RC(o){let{id:e,announcement:a,ariaLiveType:r="assertive"}=o;const i={position:"fixed",top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};return Ye.createElement("div",{id:e,style:i,role:"status","aria-live":r,"aria-atomic":!0},a)}function kC(){const[o,e]=N.useState("");return{announce:N.useCallback(r=>{r!=null&&e(r)},[]),announcement:o}}const dm=N.createContext(null);function DC(o){const e=N.useContext(dm);N.useEffect(()=>{if(!e)throw new Error("useDndMonitor must be used within a children of ");return e(o)},[o,e])}function OC(){const[o]=N.useState(()=>new Set),e=N.useCallback(r=>(o.add(r),()=>o.delete(r)),[o]);return[N.useCallback(r=>{let{type:i,event:l}=r;o.forEach(u=>{var d;return(d=u[i])==null?void 0:d.call(u,l)})},[o]),e]}const LC={draggable:` + `,i.onmouseenter=()=>{i.style.backgroundColor="rgba(0, 0, 0, 0.2)"},i.onmouseleave=()=>{i.style.backgroundColor="rgba(0, 0, 0, 0.1)"};const l=()=>{a.parentNode&&a.parentNode.removeChild(a)};i.onclick=l;const u=d=>{this.isImeComposing(d)||d.key==="Escape"&&(l(),document.removeEventListener("keydown",u))};return document.addEventListener("keydown",u),a.onclick=d=>{d.target===a&&l()},r.appendChild(i),a.appendChild(r),document.body.appendChild(a),{overlay:a,layer:r,closeLayer:l}}getNestedProperty(e,a){return a.split(".").reduce((r,i)=>r&&r[i]!==void 0?r[i]:void 0,e)}async handleSaveToLocalStorage(e,a){const{key:r,value:i}=e;if(!r)return H.error("saveToLocalStorage: key parameter is required"),!1;try{const l=typeof i=="string"?i:JSON.stringify(i);return localStorage.setItem(r,l),H.log(`saveToLocalStorage: saved ${r}`,i),!0}catch(l){return H.error("saveToLocalStorage: failed to save",{key:r,error:l}),!1}}async handleLoadFromLocalStorage(e,a){const{key:r,target:i,stateKey:l,defaultValue:u}=e;if(!r)return H.error("loadFromLocalStorage: key parameter is required"),u;try{const d=localStorage.getItem(r);if(d===null)return H.log(`loadFromLocalStorage: no value found for ${r}, using default`),l&&a.setState&&a.setState({[l]:u}),u;let f;try{f=JSON.parse(d)}catch{f=d}return H.log(`loadFromLocalStorage: loaded ${r}`,f),l&&a.setState&&a.setState({[l]:f}),f}catch(d){return H.error("loadFromLocalStorage: failed to load",{key:r,error:d}),u}}async handleCustomAction(e,a){const r=this.customHandlers.get(e.handler);if(!r){if(this.previewMode){H.warn(`[Preview] Unknown action handler "${e.handler}" — skipped (preview mode)`);return}const i=new It(`Unknown action handler: ${e.handler}`,e);throw i.unknownHandler=!0,i}return await r(e,a)}resolveParams(e,a){if(!e)return{};const r={};for(const[i,l]of Object.entries(e))i.includes("{{")&&H.warn(`[resolveParams] setState params의 키에 표현식이 포함되어 있습니다: "${i}". 키는 해석되지 않습니다. 배열 항목 수정은 .map()/.filter() 패턴을 사용하세요.`),typeof l=="string"&&l.includes("{{")?r[i]=this.evaluateExpression(l,a):typeof l=="string"?r[i]=l:Array.isArray(l)?r[i]=l.map(u=>typeof u=="string"&&u.includes("{{")?this.evaluateExpression(u,a):u):typeof l=="object"&&l!==null&&!Array.isArray(l)&&Object.getPrototypeOf(l)!==Object.prototype&&Object.getPrototypeOf(l)!==null?r[i]=l:typeof l=="object"&&l!==null?r[i]=this.resolveParams(l,a):r[i]=l;return r}resolveValue(e,a){return a?this.bindingEngine.resolveBindings(e,a,{skipCache:!0}):e}evaluateExpressions(e,a){let r={};for(const[i,l]of Object.entries(e))if(i==="..."){let u=l;typeof l=="string"&&l.includes("{{")&&(u=this.evaluateExpression(l,a)),u&&typeof u=="object"&&!Array.isArray(u)&&(r={...r,...u})}else typeof l=="string"&&l.includes("{{")?r[i]=this.evaluateExpression(l,a):typeof l=="object"&&l!==null&&!Array.isArray(l)?r[i]=this.evaluateExpressions(l,a):r[i]=l;return r}evaluateExpressionsIfNeeded(e,a){const r={};for(const[i,l]of Object.entries(e))typeof l=="string"&&l.includes("{{")?r[i]=this.evaluateExpression(l,a):r[i]=l;return r}evaluateExpression(e,a){if(!a)return e;const r=e.match(/^\{\{(.+)\}\}$/);if(!(r&&!r[1].includes("}}")&&!r[1].includes("{{"))){let d=a;if(e.includes("_global")){const g=window.G7Core?.state?.get()?._global;g&&(d={...a,_global:g})}if(e.includes("_computed")||e.includes("$computed")){const g=window.__g7ActionContext?.computedRef?.current;g&&Object.keys(g).length>0&&(d={...d,_computed:g,$computed:g})}return this.bindingEngine.resolveBindings(e,d,{skipCache:!0})}let l=r[1].trim();l=l.replace(/\$args\.(\d+)/g,"$args[$1]");let u=a;if(l.includes("_global")){const f=window.G7Core?.state?.get()?._global;f&&(u={...a,_global:f})}if(l.includes("_computed")||l.includes("$computed")){const f=window.__g7ActionContext?.computedRef?.current;f&&Object.keys(f).length>0&&(u={...u,_computed:f,$computed:f})}l.includes("_global.modules")&&(H.log("[evaluateExpression] expression:",l),H.log("[evaluateExpression] dataContext._global:",u._global),H.log("[evaluateExpression] dataContext._global?.modules:",u._global?.modules));try{const d=this.bindingEngine.evaluateExpression(l,u);return l.includes("_global.modules")&&H.log("[evaluateExpression] result:",d),typeof d=="string"&&d.startsWith("$t:")&&this.translationEngine&&this.translationContext?this.translationEngine.resolveTranslations(d,this.translationContext,a):d}catch(d){return H.error("Expression evaluation failed:",e,d),e}}setDefaultContext(e){this.defaultContext={...this.defaultContext,...e}}setGlobalStateUpdater(e){this.globalStateUpdater=e}getGlobalStateUpdater(){return this.globalStateUpdater}async dispatchAction(e,a){const r={...this.defaultContext,...a,data:{...this.defaultContext.data,...a?.data}};if(e.confirm){let i=this.resolveValue(e.confirm,r.data);if(this.translationEngine&&this.translationContext&&i.startsWith("$t:")&&(i=this.translationEngine.resolveTranslations(i,this.translationContext,r.data)),!confirm(i))return{success:!1}}try{return await this.executeAction(e,r)}catch(i){if(H.error("dispatchAction failed:",i),e.onError){const l=i instanceof It&&i.originalError?{message:i.originalError.message,response:i.originalError.response}:{message:i instanceof Error?i.message:String(i)},u={...r,data:{...r.data,error:l}},d=Array.isArray(e.onError)?e.onError:[e.onError];for(const f of d)await this.executeAction(f,u)}return{success:!1,error:i instanceof Error?i:new Error(String(i))}}}registerHandler(e,a,r){this.customHandlers.set(e,a);const i=Un();i?.isEnabled()&&i.trackHandlerRegistration(e,r?.category??"custom",r?.description,r?.source)}unregisterHandler(e){this.customHandlers.delete(e);const a=Un();a?.isEnabled()&&a.trackHandlerUnregistration(e)}getRegisteredHandlers(){return Array.from(this.customHandlers.keys())}getHandler(e){return this.customHandlers.get(e)}normalizeDebounceConfig(e){return typeof e=="number"?{delay:e,leading:!1,trailing:!0}:{delay:e.delay,leading:e.leading??!1,trailing:e.trailing??!0}}extractEventData(e){const a=e.target;if(a&&!("tagName"in a)){const l={type:e.type??"custom",target:{value:a.value,name:a.name??""}};return e._changedKeys&&(l._changedKeys=e._changedKeys),l}const i=a?{value:a.value,name:a.name??"",checked:a.checked??!1,type:a.type??"",tagName:a.tagName}:{};if(e.type==="scroll"&&a){const l=a;i.scrollHeight=l.scrollHeight??0,i.scrollTop=l.scrollTop??0,i.clientHeight=l.clientHeight??0,i.scrollLeft=l.scrollLeft??0,i.clientWidth=l.clientWidth??0,i.scrollWidth=l.scrollWidth??0}return{type:e.type,target:a?i:null}}executeDebouncedAction(e,a,r,i,l){const u={...r,$event:a,$args:l},d={type:a.type,target:a.target,preventDefault:()=>{},stopPropagation:()=>{}};this.createHandler(e,u,i)(d)}handleDebouncedAction(e,a,r,i,l,u){const d=this.normalizeDebounceConfig(e.debounce),f=l||`default-${e.handler}-${Date.now()}`,g=this.extractEventData(a),m=g._changedKeys;if(m&&Array.isArray(m)&&g?.target?.value&&typeof g.target.value=="object"&&!Array.isArray(g.target.value)){const E=this.debounceAccumulatedValues.get(f);if(E){const A={...E};for(const T of m)A[T]=g.target.value[T];g.target.value=A}this.debounceAccumulatedValues.set(f,g.target.value)}const b=this.debounceTimers.get(f);b&&(clearTimeout(b),this.debounceTimers.delete(f));const v=Un();v?.isEnabled()&&v.trackAction({handler:typeof e.handler=="string"?e.handler:String(e.handler),type:e.type,status:"pending",params:e.params,debounce:{delay:d.delay,status:"pending",scheduledAt:Date.now()}});const S=!this.debounceTimers.has(f+"_leading");if(d.leading&&S&&(this.debounceTimers.set(f+"_leading",setTimeout(()=>{},0)),this.executeDebouncedAction(e,g,r,i,u),v?.isEnabled()&&v.trackAction({handler:typeof e.handler=="string"?e.handler:String(e.handler),type:e.type,status:"success",params:e.params,debounce:{delay:d.delay,status:"executed",executedAt:Date.now(),mode:"leading"}})),d.trailing){const E=()=>{this.executeDebouncedAction(e,g,r,i,u),v?.isEnabled()&&v.trackAction({handler:typeof e.handler=="string"?e.handler:String(e.handler),type:e.type,status:"success",params:e.params,debounce:{delay:d.delay,status:"executed",executedAt:Date.now(),mode:"trailing"}})},A=setTimeout(()=>{this.debounceTimers.delete(f),this.debounceTimers.delete(f+"_leading"),this.pendingDebounceFlushers.delete(f),this.debounceAccumulatedValues.delete(f),E()},d.delay);this.debounceTimers.set(f,A),this.pendingDebounceFlushers.set(f,E)}}clearDebounceTimers(e){if(e)for(const[a,r]of this.debounceTimers)a.startsWith(e+"-")&&(clearTimeout(r),this.debounceTimers.delete(a),this.pendingDebounceFlushers.delete(a),this.debounceAccumulatedValues.delete(a));else{for(const a of this.debounceTimers.values())clearTimeout(a);this.debounceTimers.clear(),this.pendingDebounceFlushers.clear(),this.debounceAccumulatedValues.clear()}}debouncedCall(e,a,r){const i=this.debounceTimers.get(e);i&&(clearTimeout(i),this.debounceTimers.delete(e));const l=setTimeout(()=>{this.debounceTimers.delete(e),this.pendingDebounceFlushers.delete(e),r()},a);this.debounceTimers.set(e,l),this.pendingDebounceFlushers.set(e,r)}flushPendingDebounceTimers(){if(this.pendingDebounceFlushers.size===0)return;const e=new Map(this.pendingDebounceFlushers);for(const[a,r]of e){const i=this.debounceTimers.get(a);i&&(clearTimeout(i),this.debounceTimers.delete(a)),this.debounceTimers.delete(a+"_leading"),this.pendingDebounceFlushers.delete(a),r()}this.globalStateUpdater&&this.globalStateUpdater({})}bindActionsToProps(e,a,r){const i={...e};if(e.actions&&Array.isArray(e.actions)){const l=new Map;for(const m of e.actions){const b=this.resolveActionRef(m),v=b.event||this.getEventHandlerName(b.type);l.has(v)||l.set(v,[]),l.get(v).push(b)}const u=e.name||e.id||"unknown",d=l.has("onDrop"),f=l.has("onDragOver"),g=l.has("onDragEnter");d&&!f&&(i.onDragOver=m=>{m.preventDefault()}),d&&!g&&(i.onDragEnter=m=>{m.preventDefault()});for(const[m,b]of l)i[m]=(...v)=>{for(const S of b){const E=v[0],A=E&&typeof E=="object"&&"preventDefault"in E;if(A&&(m==="onDragOver"||m==="onDrop")&&E.preventDefault(),A&&S.key&&"key"in E){if(this.isImeComposing(E)){H.log("Key filter skipped (IME composing):",S.key);continue}if(E.key!==S.key){H.log("Key filter not matched:",S.key,"actual:",E.key);continue}H.log("Key filter matched:",S.key)}if(S.debounce){const T=`${u}-${S.handler}-${m}`,L=E&&typeof E=="object"&&!("preventDefault"in E)&&"target"in E&&E.target!==null;let M;if(A)M=E;else if(L){const D={type:"custom",target:E.target,preventDefault:()=>{},stopPropagation:()=>{}};E._changedKeys&&(D._changedKeys=E._changedKeys),M=D}else M=new Event("custom");const R=S.event?{...a,$args:v}:a;this.handleDebouncedAction(S,M,R,r,T,v)}else if(this.flushPendingDebounceTimers(),S.event){const T={...a,$args:v},L=A?E:new Event("custom");this.createHandler(S,T,r)(L)}else if(A)this.createHandler(S,a,r)(E);else if(E&&typeof E=="object"&&!("preventDefault"in E)&&"target"in E&&E.target!==null){const L={type:"custom",target:E.target,preventDefault:()=>{},stopPropagation:()=>{}};this.createHandler(S,a,r)(L)}}}}return i}getEventHandlerName(e){return{click:"onClick",change:"onChange",input:"onInput",submit:"onSubmit",focus:"onFocus",blur:"onBlur",keydown:"onKeyDown",keyup:"onKeyUp",keypress:"onKeyPress",mousedown:"onMouseDown",mouseup:"onMouseUp",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",scroll:"onScroll",dragstart:"onDragStart",drag:"onDrag",dragend:"onDragEnd",dragenter:"onDragEnter",dragover:"onDragOver",dragleave:"onDragLeave",drop:"onDrop"}[e]||`on${e.charAt(0).toUpperCase()}${e.slice(1)}`}sanitizeForDevTools(e,a=5){const r=new WeakSet,i=(l,u)=>{if(l==null||typeof l=="string"||typeof l=="number"||typeof l=="boolean")return l;if(u>a)return"[Max Depth Exceeded]";if(typeof l=="function")return`[Function: ${l.name||"anonymous"}]`;if(l instanceof Element)return`[Element: ${l.tagName}${l.className?"."+l.className.split(" ").join("."):""}]`;if(l instanceof Event)return`[Event: ${l.type}]`;if(Array.isArray(l)){if(r.has(l))return"[Circular Array]";r.add(l);const d=l.slice(0,10).map(f=>i(f,u+1));return l.length>10&&d.push(`... ${l.length-10} more items`),d}if(typeof l=="object"){if(r.has(l))return"[Circular Reference]";r.add(l);const d={},f=Object.keys(l),g=f.slice(0,20);for(const m of g)try{d[m]=i(l[m],u+1)}catch{d[m]="[Error accessing property]"}return f.length>20&&(d["..."]=`${f.length-20} more properties`),d}return String(l)};return i(e,0)}};$(us,"loadedScripts",new Set);let lo=us,Wl=null;function Zp(o){return Wl||(Wl=new lo(o)),Wl}function eC(o){Wl=o}const em=ct("TransitionManager");class tC{constructor(){$(this,"isPending",!1);$(this,"subscribers",new Set)}setPending(e){this.isPending!==e&&(em.log("setPending:",{from:this.isPending,to:e,stack:new Error().stack}),this.isPending=e,this.notifySubscribers())}getIsPending(){return this.isPending}subscribe(e){return this.subscribers.add(e),()=>{this.subscribers.delete(e)}}notifySubscribers(){em.log("notifySubscribers:",{isPending:this.isPending,subscriberCount:this.subscribers.size}),this.subscribers.forEach(e=>{e(this.isPending)})}clearSubscribers(){this.subscribers.clear()}}const Na=new tC,Yl=ct("TransitionContext"),tm=N.createContext({isTransitioning:!1}),Od=({children:o})=>{const[e,a]=N.useState(()=>{const i=Na.getIsPending();return Yl.log("Initial state:",i),i});N.useEffect(()=>{Yl.log("Subscribing to TransitionManager");const i=Na.subscribe(l=>{Yl.log("Received isPending update:",l),a(l)});return()=>{Yl.log("Unsubscribing from TransitionManager"),i()}},[]);const r=N.useMemo(()=>({isTransitioning:e}),[e]);return ut.jsx(tm.Provider,{value:r,children:o})},nm=()=>N.useContext(tm),Xl="__g7LocalInitTracking";function Ld(){const o=globalThis;return o[Xl]||(o[Xl]={hash:"",timestamp:void 0,consumed:void 0}),o[Xl]}function nC(){const o=globalThis;o[Xl]={hash:"",timestamp:void 0,consumed:void 0}}function aC(o){Ld().consumed=o}function rC(o){return Ld().consumed===o}function iC(o,e){return typeof o=="number"&&typeof e=="number"?Math.max(o,e):e??o}function sC(o,e){if(e===void 0)return o;if(!(o!==null&&typeof o=="object"&&e!==null&&typeof e=="object"&&!rC(o)))return e;const{_forceLocalInit:r,...i}=o,{_forceLocalInit:l,...u}=e,d={...i,...u},f=iC(r,l);return f!==void 0&&(d._forceLocalInit=f),d}function oC(o){return o<768?"mobile":o<1024?"tablet":"desktop"}function am(o){const e=oC(o);return{width:o,isMobile:e==="mobile",isTablet:e==="tablet",isDesktop:e==="desktop",matchedPreset:e}}const Md=N.createContext(am(1024)),Jl=({children:o,overrideWidth:e})=>{const[a,r]=N.useState(()=>ui.getWidth());N.useEffect(()=>{const u=ui.subscribe(d=>{r(d)});return()=>{u()}},[]);const i=e??a,l=N.useMemo(()=>am(i),[i]);return ut.jsx(Md.Provider,{value:l,children:o})},$d=()=>N.useContext(Md);window.G7Core?.createLogger?.("Core:State");function lC(o,e,a,r){const{syncOnControlledChange:i=!0,isEqual:l}=r??{},u=o!==void 0;N.useRef(u);const[d,f]=N.useState(o!==void 0?o:e),g=d,m=N.useRef(o),b=N.useRef(!1);N.useEffect(()=>{if(b.current){m.current=o;return}i&&u&&o!==m.current&&(l?!l(d,o):d!==o)&&f(o),m.current=o},[o,u,i,l,d]);const v=N.useCallback(S=>{const E=typeof S=="function"?S(g):S;(l?l(g,E):g===E)||(b.current=!0,f(E),a?.(E),requestAnimationFrame(()=>{b.current=!1}))},[g,u,a,l]);return[g,v]}function cC(o,e){return o===e?!0:o.length!==e.length?!1:o.every((a,r)=>a===e[r])}function rm(o,e){if(o===e)return!0;const a=Object.keys(o),r=Object.keys(e);return a.length!==r.length?!1:a.every(i=>o[i]===e[i])}const im=N.createContext({}),uC=({children:o,value:e})=>ut.jsx(im.Provider,{value:e,children:o}),dC=()=>N.useContext(im),fC=(o,e)=>{if(!o)return;const a=e.split(".");let r=o;for(const i of a){if(r==null)return;r=r[i]}return r},hC=(o,e,a)=>{const r=e.split(".");if(r.length===1)return{...o,[r[0]]:a};const i={...o};let l=i;for(let u=0;u{ns.warn("IsolatedStateContext not available: setState called outside IsolatedStateProvider")},getState:()=>{},mergeState:()=>{ns.warn("IsolatedStateContext not available: mergeState called outside IsolatedStateProvider")},stateRef:{current:{}},scopeId:""},sm=N.createContext(gC);let pC=0;function mC(){return`isolated-${++pC}-${Date.now().toString(36)}`}function om(o,e){if(e==null)return o;if(typeof e!="object"||Array.isArray(e))return e;const a={...o};for(const r of Object.keys(e)){const i=e[r],l=o?.[r];i!==null&&typeof i=="object"&&!Array.isArray(i)&&l!==null&&typeof l=="object"&&!Array.isArray(l)?a[r]=om(l,i):a[r]=i}return a}function yC(o,e){return e?e.split(".").reduce((a,r)=>a?.[r],o):o}function bC(o,e,a){const r=e.split("."),i={...o};let l=i;for(let u=0;u{const i=N.useRef(e||mC()).current,[l,u]=N.useState(o),d=N.useRef(l);d.current=l;const f=N.useCallback(S=>yC(d.current,S),[]),g=N.useCallback((S,E)=>{u(A=>{const T=bC(A,S,E);return ns.log(`[${i}] setState: ${S} =`,E),T})},[i]),m=N.useCallback((S,E="deep")=>{u(A=>{let T;return E==="replace"?T=S:E==="shallow"?T={...A,...S}:T=om(A,S),ns.log(`[${i}] mergeState (${E}):`,S),T})},[i]),b=N.useMemo(()=>({state:l,setState:g,getState:f,mergeState:m,stateRef:d,scopeId:i}),[l,g,f,m,i]),v=N.useMemo(()=>({state:d.current,setState:g,getState:f,mergeState:m}),[g,f,m]);return N.useEffect(()=>{const S=window.G7Core,E=window.__g7IsolatedStates||{};return window.__g7IsolatedStates||(window.__g7IsolatedStates=E),E[i]=v,S&&(S._isolatedStates||(S._isolatedStates={}),S._isolatedStates[i]=l),S?.devTools?.isEnabled?.()&&S.devTools.emit?.("isolated:created",{id:i,state:l}),ns.log(`[${i}] IsolatedStateProvider mounted with initial state:`,l),()=>{delete E[i],S?._isolatedStates&&delete S._isolatedStates[i],S?.devTools?.isEnabled?.()&&S.devTools.emit?.("isolated:destroyed",{id:i}),ns.log(`[${i}] IsolatedStateProvider unmounted`)}},[i,v]),N.useEffect(()=>{const S=window.G7Core,E=window.__g7IsolatedStates;E?.[i]&&(E[i].state=l),S?._isolatedStates&&(S._isolatedStates[i]=l),S?.devTools?.isEnabled?.()&&S.devTools.emit?.("isolated:updated",{id:i,state:l})},[l,i]),ut.jsx(sm.Provider,{value:b,children:a})},SC=()=>{const o=N.useContext(sm);return o.scopeId?o:null};var Ar=jg();function wC(){for(var o=arguments.length,e=new Array(o),a=0;ar=>{e.forEach(i=>i(r))},e)}const Ql=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function as(o){const e=Object.prototype.toString.call(o);return e==="[object Window]"||e==="[object global]"}function Nd(o){return"nodeType"in o}function Tn(o){var e,a;return o?as(o)?o:Nd(o)&&(e=(a=o.ownerDocument)==null?void 0:a.defaultView)!=null?e:window:window}function Id(o){const{Document:e}=Tn(o);return o instanceof e}function co(o){return as(o)?!1:o instanceof Tn(o).HTMLElement}function lm(o){return o instanceof Tn(o).SVGElement}function rs(o){return o?as(o)?o.document:Nd(o)?Id(o)?o:co(o)||lm(o)?o.ownerDocument:document:document:document}const Ia=Ql?N.useLayoutEffect:N.useEffect;function Hd(o){const e=N.useRef(o);return Ia(()=>{e.current=o}),N.useCallback(function(){for(var a=arguments.length,r=new Array(a),i=0;i{o.current=setInterval(r,i)},[]),a=N.useCallback(()=>{o.current!==null&&(clearInterval(o.current),o.current=null)},[]);return[e,a]}function uo(o,e){e===void 0&&(e=[o]);const a=N.useRef(o);return Ia(()=>{a.current!==o&&(a.current=o)},e),a}function fo(o,e){const a=N.useRef();return N.useMemo(()=>{const r=o(a.current);return a.current=r,r},[...e])}function Zl(o){const e=Hd(o),a=N.useRef(null),r=N.useCallback(i=>{i!==a.current&&e?.(i,a.current),a.current=i},[]);return[a,r]}function zd(o){const e=N.useRef();return N.useEffect(()=>{e.current=o},[o]),e.current}let jd={};function ho(o,e){return N.useMemo(()=>{if(e)return e;const a=jd[o]==null?0:jd[o]+1;return jd[o]=a,o+"-"+a},[o,e])}function cm(o){return function(e){for(var a=arguments.length,r=new Array(a>1?a-1:0),i=1;i{const d=Object.entries(u);for(const[f,g]of d){const m=l[f];m!=null&&(l[f]=m+o*g)}return l},{...e})}}const is=cm(1),go=cm(-1);function EC(o){return"clientX"in o&&"clientY"in o}function Ud(o){if(!o)return!1;const{KeyboardEvent:e}=Tn(o.target);return e&&o instanceof e}function _C(o){if(!o)return!1;const{TouchEvent:e}=Tn(o.target);return e&&o instanceof e}function Bd(o){if(_C(o)){if(o.touches&&o.touches.length){const{clientX:e,clientY:a}=o.touches[0];return{x:e,y:a}}else if(o.changedTouches&&o.changedTouches.length){const{clientX:e,clientY:a}=o.changedTouches[0];return{x:e,y:a}}}return EC(o)?{x:o.clientX,y:o.clientY}:null}const po=Object.freeze({Translate:{toString(o){if(!o)return;const{x:e,y:a}=o;return"translate3d("+(e?Math.round(e):0)+"px, "+(a?Math.round(a):0)+"px, 0)"}},Scale:{toString(o){if(!o)return;const{scaleX:e,scaleY:a}=o;return"scaleX("+e+") scaleY("+a+")"}},Transform:{toString(o){if(o)return[po.Translate.toString(o),po.Scale.toString(o)].join(" ")}},Transition:{toString(o){let{property:e,duration:a,easing:r}=o;return e+" "+a+"ms "+r}}}),um="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function AC(o){return o.matches(um)?o:o.querySelector(um)}const xC={display:"none"};function TC(o){let{id:e,value:a}=o;return Ye.createElement("div",{id:e,style:xC},a)}function RC(o){let{id:e,announcement:a,ariaLiveType:r="assertive"}=o;const i={position:"fixed",top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};return Ye.createElement("div",{id:e,style:i,role:"status","aria-live":r,"aria-atomic":!0},a)}function kC(){const[o,e]=N.useState("");return{announce:N.useCallback(r=>{r!=null&&e(r)},[]),announcement:o}}const dm=N.createContext(null);function DC(o){const e=N.useContext(dm);N.useEffect(()=>{if(!e)throw new Error("useDndMonitor must be used within a children of ");return e(o)},[o,e])}function OC(){const[o]=N.useState(()=>new Set),e=N.useCallback(r=>(o.add(r),()=>o.delete(r)),[o]);return[N.useCallback(r=>{let{type:i,event:l}=r;o.forEach(u=>{var d;return(d=u[i])==null?void 0:d.call(u,l)})},[o]),e]}const LC={draggable:` To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel. - `},MC={onDragStart(o){let{active:e}=o;return"Picked up draggable item "+e.id+"."},onDragOver(o){let{active:e,over:a}=o;return a?"Draggable item "+e.id+" was moved over droppable area "+a.id+".":"Draggable item "+e.id+" is no longer over a droppable area."},onDragEnd(o){let{active:e,over:a}=o;return a?"Draggable item "+e.id+" was dropped over droppable area "+a.id:"Draggable item "+e.id+" was dropped."},onDragCancel(o){let{active:e}=o;return"Dragging was cancelled. Draggable item "+e.id+" was dropped."}};function $C(o){let{announcements:e=MC,container:a,hiddenTextDescribedById:r,screenReaderInstructions:i=LC}=o;const{announce:l,announcement:u}=kC(),d=fo("DndLiveRegion"),[f,g]=N.useState(!1);if(N.useEffect(()=>{g(!0)},[]),DC(N.useMemo(()=>({onDragStart(b){let{active:v}=b;l(e.onDragStart({active:v}))},onDragMove(b){let{active:v,over:S}=b;e.onDragMove&&l(e.onDragMove({active:v,over:S}))},onDragOver(b){let{active:v,over:S}=b;l(e.onDragOver({active:v,over:S}))},onDragEnd(b){let{active:v,over:S}=b;l(e.onDragEnd({active:v,over:S}))},onDragCancel(b){let{active:v,over:S}=b;l(e.onDragCancel({active:v,over:S}))}}),[l,e])),!f)return null;const m=Ye.createElement(Ye.Fragment,null,Ye.createElement(TC,{id:r,value:i.draggable}),Ye.createElement(RC,{id:d,announcement:u}));return a?Ar.createPortal(m,a):m}var Zt;(function(o){o.DragStart="dragStart",o.DragMove="dragMove",o.DragEnd="dragEnd",o.DragCancel="dragCancel",o.DragOver="dragOver",o.RegisterDroppable="registerDroppable",o.SetDroppableDisabled="setDroppableDisabled",o.UnregisterDroppable="unregisterDroppable"})(Zt||(Zt={}));function Zl(){}function fm(o,e){return N.useMemo(()=>({sensor:o,options:e??{}}),[o,e])}function NC(){for(var o=arguments.length,e=new Array(o),a=0;a[...e].filter(r=>r!=null),[...e])}const ma=Object.freeze({x:0,y:0});function hm(o,e){return Math.sqrt(Math.pow(o.x-e.x,2)+Math.pow(o.y-e.y,2))}function gm(o,e){let{data:{value:a}}=o,{data:{value:r}}=e;return a-r}function IC(o,e){let{data:{value:a}}=o,{data:{value:r}}=e;return r-a}function pm(o){let{left:e,top:a,height:r,width:i}=o;return[{x:e,y:a},{x:e+i,y:a},{x:e,y:a+r},{x:e+i,y:a+r}]}function mm(o,e){if(!o||o.length===0)return null;const[a]=o;return a[e]}function ym(o,e,a){return e===void 0&&(e=o.left),a===void 0&&(a=o.top),{x:e+o.width*.5,y:a+o.height*.5}}const HC=o=>{let{collisionRect:e,droppableRects:a,droppableContainers:r}=o;const i=ym(e,e.left,e.top),l=[];for(const u of r){const{id:d}=u,f=a.get(d);if(f){const g=hm(ym(f),i);l.push({id:d,data:{droppableContainer:u,value:g}})}}return l.sort(gm)},zC=o=>{let{collisionRect:e,droppableRects:a,droppableContainers:r}=o;const i=pm(e),l=[];for(const u of r){const{id:d}=u,f=a.get(d);if(f){const g=pm(f),m=i.reduce((v,S,E)=>v+hm(g[E],S),0),b=Number((m/4).toFixed(4));l.push({id:d,data:{droppableContainer:u,value:b}})}}return l.sort(gm)};function jC(o,e){const a=Math.max(e.top,o.top),r=Math.max(e.left,o.left),i=Math.min(e.left+e.width,o.left+o.width),l=Math.min(e.top+e.height,o.top+o.height),u=i-r,d=l-a;if(r{let{collisionRect:e,droppableRects:a,droppableContainers:r}=o;const i=[];for(const l of r){const{id:u}=l,d=a.get(u);if(d){const f=jC(d,e);f>0&&i.push({id:u,data:{droppableContainer:l,value:f}})}}return i.sort(IC)};function BC(o,e,a){return{...o,scaleX:e&&a?e.width/a.width:1,scaleY:e&&a?e.height/a.height:1}}function bm(o,e){return o&&e?{x:o.left-e.left,y:o.top-e.top}:ma}function PC(o){return function(a){for(var r=arguments.length,i=new Array(r>1?r-1:0),l=1;l({...u,top:u.top+o*d.y,bottom:u.bottom+o*d.y,left:u.left+o*d.x,right:u.right+o*d.x}),{...a})}}const qC=PC(1);function GC(o){if(o.startsWith("matrix3d(")){const e=o.slice(9,-1).split(/, /);return{x:+e[12],y:+e[13],scaleX:+e[0],scaleY:+e[5]}}else if(o.startsWith("matrix(")){const e=o.slice(7,-1).split(/, /);return{x:+e[4],y:+e[5],scaleX:+e[0],scaleY:+e[3]}}return null}function VC(o,e,a){const r=GC(e);if(!r)return o;const{scaleX:i,scaleY:l,x:u,y:d}=r,f=o.left-u-(1-i)*parseFloat(a),g=o.top-d-(1-l)*parseFloat(a.slice(a.indexOf(" ")+1)),m=i?o.width/i:o.width,b=l?o.height/l:o.height;return{width:m,height:b,top:g,right:f+m,bottom:g+b,left:f}}const FC={ignoreTransform:!1};function is(o,e){e===void 0&&(e=FC);let a=o.getBoundingClientRect();if(e.ignoreTransform){const{transform:g,transformOrigin:m}=Tn(o).getComputedStyle(o);g&&(a=VC(a,g,m))}const{top:r,left:i,width:l,height:u,bottom:d,right:f}=a;return{top:r,left:i,width:l,height:u,bottom:d,right:f}}function vm(o){return is(o,{ignoreTransform:!0})}function KC(o){const e=o.innerWidth,a=o.innerHeight;return{top:0,left:0,right:e,bottom:a,width:e,height:a}}function WC(o,e){return e===void 0&&(e=Tn(o).getComputedStyle(o)),e.position==="fixed"}function YC(o,e){e===void 0&&(e=Tn(o).getComputedStyle(o));const a=/(auto|scroll|overlay)/;return["overflow","overflowX","overflowY"].some(i=>{const l=e[i];return typeof l=="string"?a.test(l):!1})}function ec(o,e){const a=[];function r(i){if(e!=null&&a.length>=e||!i)return a;if(Nd(i)&&i.scrollingElement!=null&&!a.includes(i.scrollingElement))return a.push(i.scrollingElement),a;if(!lo(i)||lm(i)||a.includes(i))return a;const l=Tn(o).getComputedStyle(i);return i!==o&&YC(i,l)&&a.push(i),WC(i,l)?a:r(i.parentNode)}return o?r(o):a}function Sm(o){const[e]=ec(o,1);return e??null}function Bd(o){return!Jl||!o?null:ns(o)?o:$d(o)?Nd(o)||o===as(o).scrollingElement?window:lo(o)?o:null:null}function wm(o){return ns(o)?o.scrollX:o.scrollLeft}function Cm(o){return ns(o)?o.scrollY:o.scrollTop}function Pd(o){return{x:wm(o),y:Cm(o)}}var ln;(function(o){o[o.Forward=1]="Forward",o[o.Backward=-1]="Backward"})(ln||(ln={}));function Em(o){return!Jl||!o?!1:o===document.scrollingElement}function _m(o){const e={x:0,y:0},a=Em(o)?{height:window.innerHeight,width:window.innerWidth}:{height:o.clientHeight,width:o.clientWidth},r={x:o.scrollWidth-a.width,y:o.scrollHeight-a.height},i=o.scrollTop<=e.y,l=o.scrollLeft<=e.x,u=o.scrollTop>=r.y,d=o.scrollLeft>=r.x;return{isTop:i,isLeft:l,isBottom:u,isRight:d,maxScroll:r,minScroll:e}}const XC={x:.2,y:.2};function JC(o,e,a,r,i){let{top:l,left:u,right:d,bottom:f}=a;r===void 0&&(r=10),i===void 0&&(i=XC);const{isTop:g,isBottom:m,isLeft:b,isRight:v}=_m(o),S={x:0,y:0},E={x:0,y:0},A={height:e.height*i.y,width:e.width*i.x};return!g&&l<=e.top+A.height?(S.y=ln.Backward,E.y=r*Math.abs((e.top+A.height-l)/A.height)):!m&&f>=e.bottom-A.height&&(S.y=ln.Forward,E.y=r*Math.abs((e.bottom-A.height-f)/A.height)),!v&&d>=e.right-A.width?(S.x=ln.Forward,E.x=r*Math.abs((e.right-A.width-d)/A.width)):!b&&u<=e.left+A.width&&(S.x=ln.Backward,E.x=r*Math.abs((e.left+A.width-u)/A.width)),{direction:S,speed:E}}function QC(o){if(o===document.scrollingElement){const{innerWidth:l,innerHeight:u}=window;return{top:0,left:0,right:l,bottom:u,width:l,height:u}}const{top:e,left:a,right:r,bottom:i}=o.getBoundingClientRect();return{top:e,left:a,right:r,bottom:i,width:o.clientWidth,height:o.clientHeight}}function Am(o){return o.reduce((e,a)=>rs(e,Pd(a)),ma)}function ZC(o){return o.reduce((e,a)=>e+wm(a),0)}function eE(o){return o.reduce((e,a)=>e+Cm(a),0)}function tE(o,e){if(e===void 0&&(e=is),!o)return;const{top:a,left:r,bottom:i,right:l}=e(o);Sm(o)&&(i<=0||l<=0||a>=window.innerHeight||r>=window.innerWidth)&&o.scrollIntoView({block:"center",inline:"center"})}const nE=[["x",["left","right"],ZC],["y",["top","bottom"],eE]];class qd{constructor(e,a){this.rect=void 0,this.width=void 0,this.height=void 0,this.top=void 0,this.bottom=void 0,this.right=void 0,this.left=void 0;const r=ec(a),i=Am(r);this.rect={...e},this.width=e.width,this.height=e.height;for(const[l,u,d]of nE)for(const f of u)Object.defineProperty(this,f,{get:()=>{const g=d(r),m=i[l]-g;return this.rect[f]+m},enumerable:!0});Object.defineProperty(this,"rect",{enumerable:!1})}}class po{constructor(e){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(a=>{var r;return(r=this.target)==null?void 0:r.removeEventListener(...a)})},this.target=e}add(e,a,r){var i;(i=this.target)==null||i.addEventListener(e,a,r),this.listeners.push([e,a,r])}}function aE(o){const{EventTarget:e}=Tn(o);return o instanceof e?o:as(o)}function Gd(o,e){const a=Math.abs(o.x),r=Math.abs(o.y);return typeof e=="number"?Math.sqrt(a**2+r**2)>e:"x"in e&&"y"in e?a>e.x&&r>e.y:"x"in e?a>e.x:"y"in e?r>e.y:!1}var Qn;(function(o){o.Click="click",o.DragStart="dragstart",o.Keydown="keydown",o.ContextMenu="contextmenu",o.Resize="resize",o.SelectionChange="selectionchange",o.VisibilityChange="visibilitychange"})(Qn||(Qn={}));function xm(o){o.preventDefault()}function rE(o){o.stopPropagation()}var it;(function(o){o.Space="Space",o.Down="ArrowDown",o.Right="ArrowRight",o.Left="ArrowLeft",o.Up="ArrowUp",o.Esc="Escape",o.Enter="Enter",o.Tab="Tab"})(it||(it={}));const Tm={start:[it.Space,it.Enter],cancel:[it.Esc],end:[it.Space,it.Enter,it.Tab]},iE=(o,e)=>{let{currentCoordinates:a}=e;switch(o.code){case it.Right:return{...a,x:a.x+25};case it.Left:return{...a,x:a.x-25};case it.Down:return{...a,y:a.y+25};case it.Up:return{...a,y:a.y-25}}};class Vd{constructor(e){this.props=void 0,this.autoScrollEnabled=!1,this.referenceCoordinates=void 0,this.listeners=void 0,this.windowListeners=void 0,this.props=e;const{event:{target:a}}=e;this.props=e,this.listeners=new po(as(a)),this.windowListeners=new po(Tn(a)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(Qn.Resize,this.handleCancel),this.windowListeners.add(Qn.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(Qn.Keydown,this.handleKeyDown))}handleStart(){const{activeNode:e,onStart:a}=this.props,r=e.node.current;r&&tE(r),a(ma)}handleKeyDown(e){if(jd(e)){const{active:a,context:r,options:i}=this.props,{keyboardCodes:l=Tm,coordinateGetter:u=iE,scrollBehavior:d="smooth"}=i,{code:f}=e;if(l.end.includes(f)){this.handleEnd(e);return}if(l.cancel.includes(f)){this.handleCancel(e);return}const{collisionRect:g}=r.current,m=g?{x:g.left,y:g.top}:ma;this.referenceCoordinates||(this.referenceCoordinates=m);const b=u(e,{active:a,context:r.current,currentCoordinates:m});if(b){const v=ho(b,m),S={x:0,y:0},{scrollableAncestors:E}=r.current;for(const A of E){const T=e.code,{isTop:L,isRight:M,isLeft:R,isBottom:D,maxScroll:U,minScroll:j}=_m(A),P=QC(A),X={x:Math.min(T===it.Right?P.right-P.width/2:P.right,Math.max(T===it.Right?P.left:P.left+P.width/2,b.x)),y:Math.min(T===it.Down?P.bottom-P.height/2:P.bottom,Math.max(T===it.Down?P.top:P.top+P.height/2,b.y))},ge=T===it.Right&&!M||T===it.Left&&!R,Ee=T===it.Down&&!D||T===it.Up&&!L;if(ge&&X.x!==b.x){const Ce=A.scrollLeft+v.x,$e=T===it.Right&&Ce<=U.x||T===it.Left&&Ce>=j.x;if($e&&!v.y){A.scrollTo({left:Ce,behavior:d});return}$e?S.x=A.scrollLeft-Ce:S.x=T===it.Right?A.scrollLeft-U.x:A.scrollLeft-j.x,S.x&&A.scrollBy({left:-S.x,behavior:d});break}else if(Ee&&X.y!==b.y){const Ce=A.scrollTop+v.y,$e=T===it.Down&&Ce<=U.y||T===it.Up&&Ce>=j.y;if($e&&!v.x){A.scrollTo({top:Ce,behavior:d});return}$e?S.y=A.scrollTop-Ce:S.y=T===it.Down?A.scrollTop-U.y:A.scrollTop-j.y,S.y&&A.scrollBy({top:-S.y,behavior:d});break}}this.handleMove(e,rs(ho(b,this.referenceCoordinates),S))}}}handleMove(e,a){const{onMove:r}=this.props;e.preventDefault(),r(a)}handleEnd(e){const{onEnd:a}=this.props;e.preventDefault(),this.detach(),a()}handleCancel(e){const{onCancel:a}=this.props;e.preventDefault(),this.detach(),a()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}}Vd.activators=[{eventName:"onKeyDown",handler:(o,e,a)=>{let{keyboardCodes:r=Tm,onActivation:i}=e,{active:l}=a;const{code:u}=o.nativeEvent;if(r.start.includes(u)){const d=l.activatorNode.current;return d&&o.target!==d?!1:(o.preventDefault(),i?.({event:o.nativeEvent}),!0)}return!1}}];function Rm(o){return!!(o&&"distance"in o)}function km(o){return!!(o&&"delay"in o)}class Fd{constructor(e,a,r){var i;r===void 0&&(r=aE(e.event.target)),this.props=void 0,this.events=void 0,this.autoScrollEnabled=!0,this.document=void 0,this.activated=!1,this.initialCoordinates=void 0,this.timeoutId=null,this.listeners=void 0,this.documentListeners=void 0,this.windowListeners=void 0,this.props=e,this.events=a;const{event:l}=e,{target:u}=l;this.props=e,this.events=a,this.document=as(u),this.documentListeners=new po(this.document),this.listeners=new po(r),this.windowListeners=new po(Tn(u)),this.initialCoordinates=(i=Ud(l))!=null?i:ma,this.handleStart=this.handleStart.bind(this),this.handleMove=this.handleMove.bind(this),this.handleEnd=this.handleEnd.bind(this),this.handleCancel=this.handleCancel.bind(this),this.handleKeydown=this.handleKeydown.bind(this),this.removeTextSelection=this.removeTextSelection.bind(this),this.attach()}attach(){const{events:e,props:{options:{activationConstraint:a,bypassActivationConstraint:r}}}=this;if(this.listeners.add(e.move.name,this.handleMove,{passive:!1}),this.listeners.add(e.end.name,this.handleEnd),e.cancel&&this.listeners.add(e.cancel.name,this.handleCancel),this.windowListeners.add(Qn.Resize,this.handleCancel),this.windowListeners.add(Qn.DragStart,xm),this.windowListeners.add(Qn.VisibilityChange,this.handleCancel),this.windowListeners.add(Qn.ContextMenu,xm),this.documentListeners.add(Qn.Keydown,this.handleKeydown),a){if(r!=null&&r({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(km(a)){this.timeoutId=setTimeout(this.handleStart,a.delay),this.handlePending(a);return}if(Rm(a)){this.handlePending(a);return}}this.handleStart()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll(),setTimeout(this.documentListeners.removeAll,50),this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}handlePending(e,a){const{active:r,onPending:i}=this.props;i(r,e,this.initialCoordinates,a)}handleStart(){const{initialCoordinates:e}=this,{onStart:a}=this.props;e&&(this.activated=!0,this.documentListeners.add(Qn.Click,rE,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(Qn.SelectionChange,this.removeTextSelection),a(e))}handleMove(e){var a;const{activated:r,initialCoordinates:i,props:l}=this,{onMove:u,options:{activationConstraint:d}}=l;if(!i)return;const f=(a=Ud(e))!=null?a:ma,g=ho(i,f);if(!r&&d){if(Rm(d)){if(d.tolerance!=null&&Gd(g,d.tolerance))return this.handleCancel();if(Gd(g,d.distance))return this.handleStart()}if(km(d)&&Gd(g,d.tolerance))return this.handleCancel();this.handlePending(d,g);return}e.cancelable&&e.preventDefault(),u(f)}handleEnd(){const{onAbort:e,onEnd:a}=this.props;this.detach(),this.activated||e(this.props.active),a()}handleCancel(){const{onAbort:e,onCancel:a}=this.props;this.detach(),this.activated||e(this.props.active),a()}handleKeydown(e){e.code===it.Esc&&this.handleCancel()}removeTextSelection(){var e;(e=this.document.getSelection())==null||e.removeAllRanges()}}const sE={cancel:{name:"pointercancel"},move:{name:"pointermove"},end:{name:"pointerup"}};class Kd extends Fd{constructor(e){const{event:a}=e,r=as(a.target);super(e,sE,r)}}Kd.activators=[{eventName:"onPointerDown",handler:(o,e)=>{let{nativeEvent:a}=o,{onActivation:r}=e;return!a.isPrimary||a.button!==0?!1:(r?.({event:a}),!0)}}];const oE={move:{name:"mousemove"},end:{name:"mouseup"}};var Wd;(function(o){o[o.RightClick=2]="RightClick"})(Wd||(Wd={}));class lE extends Fd{constructor(e){super(e,oE,as(e.event.target))}}lE.activators=[{eventName:"onMouseDown",handler:(o,e)=>{let{nativeEvent:a}=o,{onActivation:r}=e;return a.button===Wd.RightClick?!1:(r?.({event:a}),!0)}}];const Yd={cancel:{name:"touchcancel"},move:{name:"touchmove"},end:{name:"touchend"}};class cE extends Fd{constructor(e){super(e,Yd)}static setup(){return window.addEventListener(Yd.move.name,e,{capture:!1,passive:!1}),function(){window.removeEventListener(Yd.move.name,e)};function e(){}}}cE.activators=[{eventName:"onTouchStart",handler:(o,e)=>{let{nativeEvent:a}=o,{onActivation:r}=e;const{touches:i}=a;return i.length>1?!1:(r?.({event:a}),!0)}}];var mo;(function(o){o[o.Pointer=0]="Pointer",o[o.DraggableRect=1]="DraggableRect"})(mo||(mo={}));var tc;(function(o){o[o.TreeOrder=0]="TreeOrder",o[o.ReversedTreeOrder=1]="ReversedTreeOrder"})(tc||(tc={}));function uE(o){let{acceleration:e,activator:a=mo.Pointer,canScroll:r,draggingRect:i,enabled:l,interval:u=5,order:d=tc.TreeOrder,pointerCoordinates:f,scrollableAncestors:g,scrollableAncestorRects:m,delta:b,threshold:v}=o;const S=fE({delta:b,disabled:!l}),[E,A]=CC(),T=N.useRef({x:0,y:0}),L=N.useRef({x:0,y:0}),M=N.useMemo(()=>{switch(a){case mo.Pointer:return f?{top:f.y,bottom:f.y,left:f.x,right:f.x}:null;case mo.DraggableRect:return i}},[a,i,f]),R=N.useRef(null),D=N.useCallback(()=>{const j=R.current;if(!j)return;const P=T.current.x*L.current.x,X=T.current.y*L.current.y;j.scrollBy(P,X)},[]),U=N.useMemo(()=>d===tc.TreeOrder?[...g].reverse():g,[d,g]);N.useEffect(()=>{if(!l||!g.length||!M){A();return}for(const j of U){if(r?.(j)===!1)continue;const P=g.indexOf(j),X=m[P];if(!X)continue;const{direction:ge,speed:Ee}=JC(j,X,M,e,v);for(const Ce of["x","y"])S[Ce][ge[Ce]]||(Ee[Ce]=0,ge[Ce]=0);if(Ee.x>0||Ee.y>0){A(),R.current=j,E(D,u),T.current=Ee,L.current=ge;return}}T.current={x:0,y:0},L.current={x:0,y:0},A()},[e,D,r,A,l,u,JSON.stringify(M),JSON.stringify(S),E,g,U,m,JSON.stringify(v)])}const dE={x:{[ln.Backward]:!1,[ln.Forward]:!1},y:{[ln.Backward]:!1,[ln.Forward]:!1}};function fE(o){let{delta:e,disabled:a}=o;const r=Hd(e);return uo(i=>{if(a||!r||!i)return dE;const l={x:Math.sign(e.x-r.x),y:Math.sign(e.y-r.y)};return{x:{[ln.Backward]:i.x[ln.Backward]||l.x===-1,[ln.Forward]:i.x[ln.Forward]||l.x===1},y:{[ln.Backward]:i.y[ln.Backward]||l.y===-1,[ln.Forward]:i.y[ln.Forward]||l.y===1}}},[a,e,r])}function hE(o,e){const a=e!=null?o.get(e):void 0,r=a?a.node.current:null;return uo(i=>{var l;return e==null?null:(l=r??i)!=null?l:null},[r,e])}function gE(o,e){return N.useMemo(()=>o.reduce((a,r)=>{const{sensor:i}=r,l=i.activators.map(u=>({eventName:u.eventName,handler:e(u.handler,r)}));return[...a,...l]},[]),[o,e])}var yo;(function(o){o[o.Always=0]="Always",o[o.BeforeDragging=1]="BeforeDragging",o[o.WhileDragging=2]="WhileDragging"})(yo||(yo={}));var Xd;(function(o){o.Optimized="optimized"})(Xd||(Xd={}));const Dm=new Map;function pE(o,e){let{dragging:a,dependencies:r,config:i}=e;const[l,u]=N.useState(null),{frequency:d,measure:f,strategy:g}=i,m=N.useRef(o),b=T(),v=co(b),S=N.useCallback(function(L){L===void 0&&(L=[]),!v.current&&u(M=>M===null?L:M.concat(L.filter(R=>!M.includes(R))))},[v]),E=N.useRef(null),A=uo(L=>{if(b&&!a)return Dm;if(!L||L===Dm||m.current!==o||l!=null){const M=new Map;for(let R of o){if(!R)continue;if(l&&l.length>0&&!l.includes(R.id)&&R.rect.current){M.set(R.id,R.rect.current);continue}const D=R.node.current,U=D?new qd(f(D),D):null;R.rect.current=U,U&&M.set(R.id,U)}return M}return L},[o,l,a,b,f]);return N.useEffect(()=>{m.current=o},[o]),N.useEffect(()=>{b||S()},[a,b]),N.useEffect(()=>{l&&l.length>0&&u(null)},[JSON.stringify(l)]),N.useEffect(()=>{b||typeof d!="number"||E.current!==null||(E.current=setTimeout(()=>{S(),E.current=null},d))},[d,b,S,...r]),{droppableRects:A,measureDroppableContainers:S,measuringScheduled:l!=null};function T(){switch(g){case yo.Always:return!1;case yo.BeforeDragging:return a;default:return!a}}}function Om(o,e){return uo(a=>o?a||(typeof e=="function"?e(o):o):null,[e,o])}function mE(o,e){return Om(o,e)}function yE(o){let{callback:e,disabled:a}=o;const r=Id(e),i=N.useMemo(()=>{if(a||typeof window>"u"||typeof window.MutationObserver>"u")return;const{MutationObserver:l}=window;return new l(r)},[r,a]);return N.useEffect(()=>()=>i?.disconnect(),[i]),i}function nc(o){let{callback:e,disabled:a}=o;const r=Id(e),i=N.useMemo(()=>{if(a||typeof window>"u"||typeof window.ResizeObserver>"u")return;const{ResizeObserver:l}=window;return new l(r)},[a]);return N.useEffect(()=>()=>i?.disconnect(),[i]),i}function bE(o){return new qd(is(o),o)}function Lm(o,e,a){e===void 0&&(e=bE);const[r,i]=N.useState(null);function l(){i(f=>{if(!o)return null;if(o.isConnected===!1){var g;return(g=f??a)!=null?g:null}const m=e(o);return JSON.stringify(f)===JSON.stringify(m)?f:m})}const u=yE({callback(f){if(o)for(const g of f){const{type:m,target:b}=g;if(m==="childList"&&b instanceof HTMLElement&&b.contains(o)){l();break}}}}),d=nc({callback:l});return Ia(()=>{l(),o?(d?.observe(o),u?.observe(document.body,{childList:!0,subtree:!0})):(d?.disconnect(),u?.disconnect())},[o]),r}function vE(o){const e=Om(o);return bm(o,e)}const Mm=[];function SE(o){const e=N.useRef(o),a=uo(r=>o?r&&r!==Mm&&o&&e.current&&o.parentNode===e.current.parentNode?r:ec(o):Mm,[o]);return N.useEffect(()=>{e.current=o},[o]),a}function wE(o){const[e,a]=N.useState(null),r=N.useRef(o),i=N.useCallback(l=>{const u=Bd(l.target);u&&a(d=>d?(d.set(u,Pd(u)),new Map(d)):null)},[]);return N.useEffect(()=>{const l=r.current;if(o!==l){u(l);const d=o.map(f=>{const g=Bd(f);return g?(g.addEventListener("scroll",i,{passive:!0}),[g,Pd(g)]):null}).filter(f=>f!=null);a(d.length?new Map(d):null),r.current=o}return()=>{u(o),u(l)};function u(d){d.forEach(f=>{const g=Bd(f);g?.removeEventListener("scroll",i)})}},[i,o]),N.useMemo(()=>o.length?e?Array.from(e.values()).reduce((l,u)=>rs(l,u),ma):Am(o):ma,[o,e])}function $m(o,e){e===void 0&&(e=[]);const a=N.useRef(null);return N.useEffect(()=>{a.current=null},e),N.useEffect(()=>{const r=o!==ma;r&&!a.current&&(a.current=o),!r&&a.current&&(a.current=null)},[o]),a.current?ho(o,a.current):ma}function CE(o){N.useEffect(()=>{if(!Jl)return;const e=o.map(a=>{let{sensor:r}=a;return r.setup==null?void 0:r.setup()});return()=>{for(const a of e)a?.()}},o.map(e=>{let{sensor:a}=e;return a}))}function EE(o,e){return N.useMemo(()=>o.reduce((a,r)=>{let{eventName:i,handler:l}=r;return a[i]=u=>{l(u,e)},a},{}),[o,e])}function Nm(o){return N.useMemo(()=>o?KC(o):null,[o])}const Im=[];function _E(o,e){e===void 0&&(e=is);const[a]=o,r=Nm(a?Tn(a):null),[i,l]=N.useState(Im);function u(){l(()=>o.length?o.map(f=>Em(f)?r:new qd(e(f),f)):Im)}const d=nc({callback:u});return Ia(()=>{d?.disconnect(),u(),o.forEach(f=>d?.observe(f))},[o]),i}function AE(o){if(!o)return null;if(o.children.length>1)return o;const e=o.children[0];return lo(e)?e:o}function xE(o){let{measure:e}=o;const[a,r]=N.useState(null),i=N.useCallback(g=>{for(const{target:m}of g)if(lo(m)){r(b=>{const v=e(m);return b?{...b,width:v.width,height:v.height}:v});break}},[e]),l=nc({callback:i}),u=N.useCallback(g=>{const m=AE(g);l?.disconnect(),m&&l?.observe(m),r(m?e(m):null)},[e,l]),[d,f]=Ql(u);return N.useMemo(()=>({nodeRef:d,rect:a,setRef:f}),[a,d,f])}const TE=[{sensor:Kd,options:{}},{sensor:Vd,options:{}}],RE={current:{}},ac={draggable:{measure:vm},droppable:{measure:vm,strategy:yo.WhileDragging,frequency:Xd.Optimized},dragOverlay:{measure:is}};class bo extends Map{get(e){var a;return e!=null&&(a=super.get(e))!=null?a:void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(e=>{let{disabled:a}=e;return!a})}getNodeFor(e){var a,r;return(a=(r=this.get(e))==null?void 0:r.node.current)!=null?a:void 0}}const kE={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new bo,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:Zl},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:ac,measureDroppableContainers:Zl,windowRect:null,measuringScheduled:!1},DE={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:""},dispatch:Zl,draggableNodes:new Map,over:null,measureDroppableContainers:Zl},rc=N.createContext(DE),Hm=N.createContext(kE);function OE(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new bo}}}function LE(o,e){switch(e.type){case Zt.DragStart:return{...o,draggable:{...o.draggable,initialCoordinates:e.initialCoordinates,active:e.active}};case Zt.DragMove:return o.draggable.active==null?o:{...o,draggable:{...o.draggable,translate:{x:e.coordinates.x-o.draggable.initialCoordinates.x,y:e.coordinates.y-o.draggable.initialCoordinates.y}}};case Zt.DragEnd:case Zt.DragCancel:return{...o,draggable:{...o.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case Zt.RegisterDroppable:{const{element:a}=e,{id:r}=a,i=new bo(o.droppable.containers);return i.set(r,a),{...o,droppable:{...o.droppable,containers:i}}}case Zt.SetDroppableDisabled:{const{id:a,key:r,disabled:i}=e,l=o.droppable.containers.get(a);if(!l||r!==l.key)return o;const u=new bo(o.droppable.containers);return u.set(a,{...l,disabled:i}),{...o,droppable:{...o.droppable,containers:u}}}case Zt.UnregisterDroppable:{const{id:a,key:r}=e,i=o.droppable.containers.get(a);if(!i||r!==i.key)return o;const l=new bo(o.droppable.containers);return l.delete(a),{...o,droppable:{...o.droppable,containers:l}}}default:return o}}function ME(o){let{disabled:e}=o;const{active:a,activatorEvent:r,draggableNodes:i}=N.useContext(rc),l=Hd(r),u=Hd(a?.id);return N.useEffect(()=>{if(!e&&!r&&l&&u!=null){if(!jd(l)||document.activeElement===l.target)return;const d=i.get(u);if(!d)return;const{activatorNode:f,node:g}=d;if(!f.current&&!g.current)return;requestAnimationFrame(()=>{for(const m of[f.current,g.current]){if(!m)continue;const b=AC(m);if(b){b.focus();break}}})}},[r,e,i,u,l]),null}function $E(o,e){let{transform:a,...r}=e;return o!=null&&o.length?o.reduce((i,l)=>l({transform:i,...r}),a):a}function NE(o){return N.useMemo(()=>({draggable:{...ac.draggable,...o?.draggable},droppable:{...ac.droppable,...o?.droppable},dragOverlay:{...ac.dragOverlay,...o?.dragOverlay}}),[o?.draggable,o?.droppable,o?.dragOverlay])}function IE(o){let{activeNode:e,measure:a,initialRect:r,config:i=!0}=o;const l=N.useRef(!1),{x:u,y:d}=typeof i=="boolean"?{x:i,y:i}:i;Ia(()=>{if(!u&&!d||!e){l.current=!1;return}if(l.current||!r)return;const g=e?.node.current;if(!g||g.isConnected===!1)return;const m=a(g),b=bm(m,r);if(u||(b.x=0),d||(b.y=0),l.current=!0,Math.abs(b.x)>0||Math.abs(b.y)>0){const v=Sm(g);v&&v.scrollBy({top:b.y,left:b.x})}},[e,u,d,r,a])}const zm=N.createContext({...ma,scaleX:1,scaleY:1});var xr;(function(o){o[o.Uninitialized=0]="Uninitialized",o[o.Initializing=1]="Initializing",o[o.Initialized=2]="Initialized"})(xr||(xr={}));const HE=N.memo(function(e){var a,r,i,l;let{id:u,accessibility:d,autoScroll:f=!0,children:g,sensors:m=TE,collisionDetection:b=UC,measuring:v,modifiers:S,...E}=e;const A=N.useReducer(LE,void 0,OE),[T,L]=A,[M,R]=OC(),[D,U]=N.useState(xr.Uninitialized),j=D===xr.Initialized,{draggable:{active:P,nodes:X,translate:ge},droppable:{containers:Ee}}=T,Ce=P!=null?X.get(P):null,$e=N.useRef({initial:null,translated:null}),Pe=N.useMemo(()=>{var Re;return P!=null?{id:P,data:(Re=Ce?.data)!=null?Re:RE,rect:$e}:null},[P,Ce]),Xe=N.useRef(null),[ht,Q]=N.useState(null),[fe,ye]=N.useState(null),te=co(E,Object.values(E)),he=fo("DndDescribedBy",u),x=N.useMemo(()=>Ee.getEnabled(),[Ee]),K=NE(v),{droppableRects:re,measureDroppableContainers:de,measuringScheduled:se}=pE(x,{dragging:j,dependencies:[ge.x,ge.y],config:K.droppable}),me=hE(X,P),Ne=N.useMemo(()=>fe?Ud(fe):null,[fe]),ve=Se(),He=mE(me,K.draggable.measure);IE({activeNode:P!=null?X.get(P):null,config:ve.layoutShiftCompensation,initialRect:He,measure:K.draggable.measure});const Ae=Lm(me,K.draggable.measure,He),Et=Lm(me?me.parentElement:null),Rt=N.useRef({activatorEvent:null,active:null,activeNode:me,collisionRect:null,collisions:null,droppableRects:re,draggableNodes:X,draggingNode:null,draggingNodeRect:null,droppableContainers:Ee,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),_t=Ee.getNodeFor((a=Rt.current.over)==null?void 0:a.id),ft=xE({measure:K.dragOverlay.measure}),un=(r=ft.nodeRef.current)!=null?r:me,gt=j?(i=ft.rect)!=null?i:Ae:null,ja=!!(ft.nodeRef.current&&ft.rect),kn=vE(ja?null:Ae),Dn=Nm(un?Tn(un):null),jt=SE(j?_t??me:null),On=_E(jt),ea=$E(S,{transform:{x:ge.x-kn.x,y:ge.y-kn.y,scaleX:1,scaleY:1},activatorEvent:fe,active:Pe,activeNodeRect:Ae,containerNodeRect:Et,draggingNodeRect:gt,over:Rt.current.over,overlayNodeRect:ft.rect,scrollableAncestors:jt,scrollableAncestorRects:On,windowRect:Dn}),Ua=Ne?rs(Ne,ge):null,Ft=wE(jt),Dr=$m(Ft),er=$m(Ft,[Ae]),bn=rs(ea,Dr),en=gt?qC(gt,ea):null,et=Pe&&en?b({active:Pe,collisionRect:en,droppableRects:re,droppableContainers:x,pointerCoordinates:Ua}):null,ta=mm(et,"id"),[En,tr]=N.useState(null),Ea=ja?ea:rs(ea,er),tn=BC(Ea,(l=En?.rect)!=null?l:null,Ae),_n=N.useRef(null),q=N.useCallback((Re,xe)=>{let{sensor:je,options:ze}=xe;if(Xe.current==null)return;const Le=X.get(Xe.current);if(!Le)return;const ke=Re.nativeEvent,We=new je({active:Xe.current,activeNode:Le,event:ke,options:ze,context:Rt,onAbort(_e){if(!X.get(_e))return;const{onDragAbort:Ue}=te.current,st={id:_e};Ue?.(st),M({type:"onDragAbort",event:st})},onPending(_e,Te,Ue,st){if(!X.get(_e))return;const{onDragPending:nn}=te.current,Kt={id:_e,constraint:Te,initialCoordinates:Ue,offset:st};nn?.(Kt),M({type:"onDragPending",event:Kt})},onStart(_e){const Te=Xe.current;if(Te==null)return;const Ue=X.get(Te);if(!Ue)return;const{onDragStart:st}=te.current,Dt={activatorEvent:ke,active:{id:Te,data:Ue.data,rect:$e}};Ar.unstable_batchedUpdates(()=>{st?.(Dt),U(xr.Initializing),L({type:Zt.DragStart,initialCoordinates:_e,active:Te}),M({type:"onDragStart",event:Dt}),Q(_n.current),ye(ke)})},onMove(_e){L({type:Zt.DragMove,coordinates:_e})},onEnd:Fe(Zt.DragEnd),onCancel:Fe(Zt.DragCancel)});_n.current=We;function Fe(_e){return async function(){const{active:Ue,collisions:st,over:Dt,scrollAdjustedTranslate:nn}=Rt.current;let Kt=null;if(Ue&&nn){const{cancelDrop:qn}=te.current;Kt={activatorEvent:ke,active:Ue,collisions:st,delta:nn,over:Dt},_e===Zt.DragEnd&&typeof qn=="function"&&await Promise.resolve(qn(Kt))&&(_e=Zt.DragCancel)}Xe.current=null,Ar.unstable_batchedUpdates(()=>{L({type:_e}),U(xr.Uninitialized),tr(null),Q(null),ye(null),_n.current=null;const qn=_e===Zt.DragEnd?"onDragEnd":"onDragCancel";if(Kt){const Ln=te.current[qn];Ln?.(Kt),M({type:qn,event:Kt})}})}}},[X]),ce=N.useCallback((Re,xe)=>(je,ze)=>{const Le=je.nativeEvent,ke=X.get(ze);if(Xe.current!==null||!ke||Le.dndKit||Le.defaultPrevented)return;const We={active:ke};Re(je,xe.options,We)===!0&&(Le.dndKit={capturedBy:xe.sensor},Xe.current=ze,q(je,xe))},[X,q]),le=gE(m,ce);CE(m),Ia(()=>{Ae&&D===xr.Initializing&&U(xr.Initialized)},[Ae,D]),N.useEffect(()=>{const{onDragMove:Re}=te.current,{active:xe,activatorEvent:je,collisions:ze,over:Le}=Rt.current;if(!xe||!je)return;const ke={active:xe,activatorEvent:je,collisions:ze,delta:{x:bn.x,y:bn.y},over:Le};Ar.unstable_batchedUpdates(()=>{Re?.(ke),M({type:"onDragMove",event:ke})})},[bn.x,bn.y]),N.useEffect(()=>{const{active:Re,activatorEvent:xe,collisions:je,droppableContainers:ze,scrollAdjustedTranslate:Le}=Rt.current;if(!Re||Xe.current==null||!xe||!Le)return;const{onDragOver:ke}=te.current,We=ze.get(ta),Fe=We&&We.rect.current?{id:We.id,rect:We.rect.current,data:We.data,disabled:We.disabled}:null,_e={active:Re,activatorEvent:xe,collisions:je,delta:{x:Le.x,y:Le.y},over:Fe};Ar.unstable_batchedUpdates(()=>{tr(Fe),ke?.(_e),M({type:"onDragOver",event:_e})})},[ta]),Ia(()=>{Rt.current={activatorEvent:fe,active:Pe,activeNode:me,collisionRect:en,collisions:et,droppableRects:re,draggableNodes:X,draggingNode:un,draggingNodeRect:gt,droppableContainers:Ee,over:En,scrollableAncestors:jt,scrollAdjustedTranslate:bn},$e.current={initial:gt,translated:en}},[Pe,me,et,en,X,un,gt,re,Ee,En,jt,bn]),uE({...ve,delta:ge,draggingRect:en,pointerCoordinates:Ua,scrollableAncestors:jt,scrollableAncestorRects:On});const Z=N.useMemo(()=>({active:Pe,activeNode:me,activeNodeRect:Ae,activatorEvent:fe,collisions:et,containerNodeRect:Et,dragOverlay:ft,draggableNodes:X,droppableContainers:Ee,droppableRects:re,over:En,measureDroppableContainers:de,scrollableAncestors:jt,scrollableAncestorRects:On,measuringConfiguration:K,measuringScheduled:se,windowRect:Dn}),[Pe,me,Ae,fe,et,Et,ft,X,Ee,re,En,de,jt,On,K,se,Dn]),be=N.useMemo(()=>({activatorEvent:fe,activators:le,active:Pe,activeNodeRect:Ae,ariaDescribedById:{draggable:he},dispatch:L,draggableNodes:X,over:En,measureDroppableContainers:de}),[fe,le,Pe,Ae,L,he,X,En,de]);return Ye.createElement(dm.Provider,{value:R},Ye.createElement(rc.Provider,{value:be},Ye.createElement(Hm.Provider,{value:Z},Ye.createElement(zm.Provider,{value:tn},g)),Ye.createElement(ME,{disabled:d?.restoreFocus===!1})),Ye.createElement($C,{...d,hiddenTextDescribedById:he}));function Se(){const Re=ht?.autoScrollEnabled===!1,xe=typeof f=="object"?f.enabled===!1:f===!1,je=j&&!Re&&!xe;return typeof f=="object"?{...f,enabled:je}:{enabled:je}}}),zE=N.createContext(null),jm="button",jE="Draggable";function UE(o){let{id:e,data:a,disabled:r=!1,attributes:i}=o;const l=fo(jE),{activators:u,activatorEvent:d,active:f,activeNodeRect:g,ariaDescribedById:m,draggableNodes:b,over:v}=N.useContext(rc),{role:S=jm,roleDescription:E="draggable",tabIndex:A=0}=i??{},T=f?.id===e,L=N.useContext(T?zm:zE),[M,R]=Ql(),[D,U]=Ql(),j=EE(u,e),P=co(a);Ia(()=>(b.set(e,{id:e,key:l,node:M,activatorNode:D,data:P}),()=>{const ge=b.get(e);ge&&ge.key===l&&b.delete(e)}),[b,e]);const X=N.useMemo(()=>({role:S,tabIndex:A,"aria-disabled":r,"aria-pressed":T&&S===jm?!0:void 0,"aria-roledescription":E,"aria-describedby":m.draggable}),[r,S,A,T,E,m.draggable]);return{active:f,activatorEvent:d,activeNodeRect:g,attributes:X,isDragging:T,listeners:r?void 0:j,node:M,over:v,setNodeRef:R,setActivatorNodeRef:U,transform:L}}function BE(){return N.useContext(Hm)}const PE="Droppable",qE={timeout:25};function GE(o){let{data:e,disabled:a=!1,id:r,resizeObserverConfig:i}=o;const l=fo(PE),{active:u,dispatch:d,over:f,measureDroppableContainers:g}=N.useContext(rc),m=N.useRef({disabled:a}),b=N.useRef(!1),v=N.useRef(null),S=N.useRef(null),{disabled:E,updateMeasurementsFor:A,timeout:T}={...qE,...i},L=co(A??r),M=N.useCallback(()=>{if(!b.current){b.current=!0;return}S.current!=null&&clearTimeout(S.current),S.current=setTimeout(()=>{g(Array.isArray(L.current)?L.current:[L.current]),S.current=null},T)},[T]),R=nc({callback:M,disabled:E||!u}),D=N.useCallback((X,ge)=>{R&&(ge&&(R.unobserve(ge),b.current=!1),X&&R.observe(X))},[R]),[U,j]=Ql(D),P=co(e);return N.useEffect(()=>{!R||!U.current||(R.disconnect(),b.current=!1,R.observe(U.current))},[U,R]),N.useEffect(()=>(d({type:Zt.RegisterDroppable,element:{id:r,key:l,disabled:a,node:U,rect:v,data:P}}),()=>d({type:Zt.UnregisterDroppable,key:l,id:r})),[r]),N.useEffect(()=>{a!==m.current.disabled&&(d({type:Zt.SetDroppableDisabled,id:r,key:l,disabled:a}),m.current.disabled=a)},[r,l,a,d]),{active:u,rect:v,isOver:f?.id===r,node:U,over:f,setNodeRef:j}}function Jd(o,e,a){const r=o.slice();return r.splice(a<0?r.length+a:a,0,r.splice(e,1)[0]),r}function VE(o,e){return o.reduce((a,r,i)=>{const l=e.get(r);return l&&(a[i]=l),a},Array(o.length))}function ic(o){return o!==null&&o>=0}function FE(o,e){if(o===e)return!0;if(o.length!==e.length)return!1;for(let a=0;a{var e;let{rects:a,activeNodeRect:r,activeIndex:i,overIndex:l,index:u}=o;const d=(e=a[i])!=null?e:r;if(!d)return null;const f=YE(a,u,i);if(u===i){const g=a[l];return g?{x:ii&&u<=l?{x:-d.width-f,y:0,...sc}:u=l?{x:d.width+f,y:0,...sc}:{x:0,y:0,...sc}};function YE(o,e,a){const r=o[e],i=o[e-1],l=o[e+1];return!r||!i&&!l?0:a{let{rects:e,activeIndex:a,overIndex:r,index:i}=o;const l=Jd(e,r,a),u=e[i],d=l[i];return!d||!u?null:{x:d.left-u.left,y:d.top-u.top,scaleX:d.width/u.width,scaleY:d.height/u.height}},oc={scaleX:1,scaleY:1},XE=o=>{var e;let{activeIndex:a,activeNodeRect:r,index:i,rects:l,overIndex:u}=o;const d=(e=l[a])!=null?e:r;if(!d)return null;if(i===a){const g=l[u];return g?{x:0,y:aa&&i<=u?{x:0,y:-d.height-f,...oc}:i=u?{x:0,y:d.height+f,...oc}:{x:0,y:0,...oc}};function JE(o,e,a){const r=o[e],i=o[e-1],l=o[e+1];return r?ar.map(j=>typeof j=="object"&&"id"in j?j.id:j),[r]),E=u!=null,A=u?S.indexOf(u.id):-1,T=g?S.indexOf(g.id):-1,L=N.useRef(S),M=!FE(S,L.current),R=T!==-1&&A===-1||M,D=KE(l);Ia(()=>{M&&E&&m(S)},[M,S,E,m]),N.useEffect(()=>{L.current=S},[S]);const U=N.useMemo(()=>({activeIndex:A,containerId:b,disabled:D,disableTransforms:R,items:S,overIndex:T,useDragOverlay:v,sortedRects:VE(S,f),strategy:i}),[A,b,D.draggable,D.droppable,R,S,T,f,v,i]);return Ye.createElement(Bm.Provider,{value:U},e)}const ZE=o=>{let{id:e,items:a,activeIndex:r,overIndex:i}=o;return Jd(a,r,i).indexOf(e)},e_=o=>{let{containerId:e,isSorting:a,wasDragging:r,index:i,items:l,newIndex:u,previousItems:d,previousContainerId:f,transition:g}=o;return!g||!r||d!==l&&i===u?!1:a?!0:u!==i&&e===f},t_={duration:200,easing:"ease"},Pm="transform",n_=go.Transition.toString({property:Pm,duration:0,easing:"linear"}),a_={roleDescription:"sortable"};function r_(o){let{disabled:e,index:a,node:r,rect:i}=o;const[l,u]=N.useState(null),d=N.useRef(a);return Ia(()=>{if(!e&&a!==d.current&&r.current){const f=i.current;if(f){const g=is(r.current,{ignoreTransform:!0}),m={x:f.left-g.left,y:f.top-g.top,scaleX:f.width/g.width,scaleY:f.height/g.height};(m.x||m.y)&&u(m)}}a!==d.current&&(d.current=a)},[e,a,r,i]),N.useEffect(()=>{l&&u(null)},[l]),l}function i_(o){let{animateLayoutChanges:e=e_,attributes:a,disabled:r,data:i,getNewIndex:l=ZE,id:u,strategy:d,resizeObserverConfig:f,transition:g=t_}=o;const{items:m,containerId:b,activeIndex:v,disabled:S,disableTransforms:E,sortedRects:A,overIndex:T,useDragOverlay:L,strategy:M}=N.useContext(Bm),R=s_(r,S),D=m.indexOf(u),U=N.useMemo(()=>({sortable:{containerId:b,index:D,items:m},...i}),[b,i,D,m]),j=N.useMemo(()=>m.slice(m.indexOf(u)),[m,u]),{rect:P,node:X,isOver:ge,setNodeRef:Ee}=GE({id:u,data:U,disabled:R.droppable,resizeObserverConfig:{updateMeasurementsFor:j,...f}}),{active:Ce,activatorEvent:$e,activeNodeRect:Pe,attributes:Xe,setNodeRef:ht,listeners:Q,isDragging:fe,over:ye,setActivatorNodeRef:te,transform:he}=UE({id:u,data:U,attributes:{...a_,...a},disabled:R.draggable}),x=wC(Ee,ht),K=!!Ce,re=K&&!E&&ic(v)&&ic(T),de=!L&&fe,se=de&&re?he:null,Ne=re?se??(d??M)({rects:A,activeNodeRect:Pe,activeIndex:v,overIndex:T,index:D}):null,ve=ic(v)&&ic(T)?l({id:u,items:m,activeIndex:v,overIndex:T}):D,He=Ce?.id,Ae=N.useRef({activeId:He,items:m,newIndex:ve,containerId:b}),Et=m!==Ae.current.items,Rt=e({active:Ce,containerId:b,isDragging:fe,isSorting:K,id:u,index:D,items:m,newIndex:Ae.current.newIndex,previousItems:Ae.current.items,previousContainerId:Ae.current.containerId,transition:g,wasDragging:Ae.current.activeId!=null}),_t=r_({disabled:!Rt,index:D,node:X,rect:P});return N.useEffect(()=>{K&&Ae.current.newIndex!==ve&&(Ae.current.newIndex=ve),b!==Ae.current.containerId&&(Ae.current.containerId=b),m!==Ae.current.items&&(Ae.current.items=m)},[K,ve,b,m]),N.useEffect(()=>{if(He===Ae.current.activeId)return;if(He!=null&&Ae.current.activeId==null){Ae.current.activeId=He;return}const un=setTimeout(()=>{Ae.current.activeId=He},50);return()=>clearTimeout(un)},[He]),{active:Ce,activeIndex:v,attributes:Xe,data:U,rect:P,index:D,newIndex:ve,items:m,isOver:ge,isSorting:K,isDragging:fe,listeners:Q,node:X,overIndex:T,over:ye,setNodeRef:x,setActivatorNodeRef:te,setDroppableNodeRef:Ee,setDraggableNodeRef:ht,transform:_t??Ne,transition:ft()};function ft(){if(_t||Et&&Ae.current.newIndex===D)return n_;if(!(de&&!jd($e)||!g)&&(K||Rt))return go.Transition.toString({...g,property:Pm})}}function s_(o,e){var a,r;return typeof o=="boolean"?{draggable:o,droppable:!1}:{draggable:(a=o?.draggable)!=null?a:e.draggable,droppable:(r=o?.droppable)!=null?r:e.droppable}}function lc(o){if(!o)return!1;const e=o.data.current;return!!(e&&"sortable"in e&&typeof e.sortable=="object"&&"containerId"in e.sortable&&"items"in e.sortable&&"index"in e.sortable)}const o_=[it.Down,it.Right,it.Up,it.Left],l_=(o,e)=>{let{context:{active:a,collisionRect:r,droppableRects:i,droppableContainers:l,over:u,scrollableAncestors:d}}=e;if(o_.includes(o.code)){if(o.preventDefault(),!a||!r)return;const f=[];l.getEnabled().forEach(b=>{if(!b||b!=null&&b.disabled)return;const v=i.get(b.id);if(v)switch(o.code){case it.Down:r.topv.top&&f.push(b);break;case it.Left:r.left>v.left&&f.push(b);break;case it.Right:r.left1&&(m=g[1].id),m!=null){const b=l.get(a.id),v=l.get(m),S=v?i.get(v.id):null,E=v?.node.current;if(E&&S&&b&&v){const T=ec(E).some((j,P)=>d[P]!==j),L=qm(b,v),M=c_(b,v),R=T||!L?{x:0,y:0}:{x:M?r.width-S.width:0,y:M?r.height-S.height:0},D={x:S.left,y:S.top};return R.x&&R.y?D:ho(D,R)}}}};function qm(o,e){return!lc(o)||!lc(e)?!1:o.data.current.sortable.containerId===e.data.current.sortable.containerId}function c_(o,e){return!lc(o)||!lc(e)||!qm(o,e)?!1:o.data.current.sortable.index{const d=N.useId(),f=N.useRef({inProgress:!1,lastSortTime:0,lastActiveId:null}),g=NC(fm(Kd,{activationConstraint:{distance:5}}),fm(Vd,{coordinateGetter:l_})),m=N.useCallback(S=>{f.current={inProgress:!0,lastSortTime:Date.now(),lastActiveId:S.active.id},l?.({activeId:S.active.id})},[l]),b=N.useCallback(S=>{const{active:E,over:A}=S,T=Date.now();if(!A||E.id===A.id){f.current.inProgress=!1;return}const{lastSortTime:L,lastActiveId:M,inProgress:R}=f.current;if(M===E.id&&T-L<500&&!R)return;f.current={inProgress:!1,lastSortTime:T,lastActiveId:E.id};const D=o.findIndex(j=>String(j[e])===String(E.id)),U=o.findIndex(j=>String(j[e])===String(A.id));if(D!==-1&&U!==-1&&D!==U){const j=Jd(o,D,U);i?.(j,{oldIndex:D,newIndex:U})}},[o,e,i]),v=o.map(S=>String(S[e]));return ut.jsx(HE,{id:d,sensors:g,collisionDetection:HC,onDragStart:m,onDragEnd:b,children:ut.jsx(QE,{items:v,strategy:u_[a],children:r})},u!==void 0?`${d}-v${u}`:d)},Gm=N.createContext(null),f_=({value:o,children:e})=>ut.jsx(Gm.Provider,{value:o,children:e}),h_=()=>N.useContext(Gm),g_=({id:o,handle:e,as:a="div",children:r})=>{const{attributes:i,listeners:l,setNodeRef:u,transform:d,transition:f,isDragging:g}=i_({id:o}),m={transform:go.Transform.toString(d),transition:f,opacity:g?.5:1,position:"relative"};return ut.jsx(a,{ref:u,style:m,...i,...e?{}:l,"data-sortable-item":!0,"data-sortable-id":String(o),"data-dragging":g,children:ut.jsx(f_,{value:{listeners:l,handle:e,isDragging:g},children:r})})},dt=ct("DynamicRenderer");function Qa(){try{return window.G7Core?.devTools}catch{return}}function Zd(o,e,a,r){if(typeof o=="string"){if(/\$t:[a-zA-Z_][a-zA-Z0-9_.\-]*/.test(o))try{return e.resolveTranslations(o,a,r)}catch{return o}return o}if(Array.isArray(o))return o.map(i=>Zd(i,e,a,r));if(o&&typeof o=="object"){const i={};for(const[l,u]of Object.entries(o))i[l]=Zd(u,e,a,r);return i}return o}function p_(o){const e=Object.keys(o);return e.length>0&&e.every(a=>/^\d+$/.test(a))}const ya=(o,e)=>{const a=["errors"],r={...o};for(const i of Object.keys(e)){const l=e[i],u=o[i];if(l===null){r[i]=null;continue}if(a.includes(i)){r[i]=l;continue}if(Array.isArray(l)){r[i]=l;continue}if(Array.isArray(u)&&l!==null&&typeof l=="object"&&!Array.isArray(l)&&p_(l)){const d=Object.keys(l).map(g=>parseInt(g,10));if((d.length>0?Math.max(...d):0)>=u.length+d.length+10)r[i]={...l};else{const g=[...u];for(const[m,b]of Object.entries(l)){const v=parseInt(m,10);v>=0&&v=g.length&&(g[v]=b)}r[i]=g}}else l!==null&&typeof l=="object"&&u!==null&&typeof u=="object"&&!Array.isArray(u)?r[i]=ya(u,l):r[i]=l}return r},Vm=(o,e)=>{const a={...o};for(const r of Object.keys(e)){if(!(r in a))continue;const i=e[r],l=a[r];if(i!==null&&typeof i=="object"&&!Array.isArray(i)&&l!==null&&typeof l=="object"&&!Array.isArray(l)){const u=Vm(l,i);Object.keys(u).length===0?delete a[r]:a[r]=u}else delete a[r]}return a},m_=o=>{const e={},a=o.split(";").filter(r=>r.trim());for(const r of a){const i=r.indexOf(":");if(i===-1)continue;const l=r.substring(0,i).trim(),u=r.substring(i+1).trim();if(l&&u){const d=l.replace(/-([a-z])/g,(f,g)=>g.toUpperCase());e[d]=u}}return e};class y_ extends N.Component{constructor(e){super(e),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,a){dt.error(`컴포넌트 렌더링 에러 (ID: ${this.props.componentId}, Name: ${this.props.componentName}):`,e,a)}render(){return this.state.hasError?this.props.fallback?this.props.fallback:ut.jsxs("div",{className:"p-4 my-2 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg text-red-800 dark:text-red-400",children:[ut.jsx("div",{className:"font-semibold mb-1",children:"컴포넌트 로드 실패"}),ut.jsxs("div",{className:"text-xs opacity-80",children:[this.props.componentName&&`[${this.props.componentName}] `,"데이터를 표시할 수 없습니다."]}),this.state.error&&ut.jsxs("details",{className:"mt-2",children:[ut.jsx("summary",{className:"cursor-pointer text-xs opacity-70 hover:opacity-100",children:"상세 정보"}),ut.jsx("div",{className:"mt-1 p-2 bg-red-100 dark:bg-red-900/30 rounded text-xs font-mono whitespace-pre-wrap break-all",children:this.state.error.message})]})]}):this.props.children}}const Ha=N.memo(({componentDef:o,dataContext:e,translationContext:a,registry:r,bindingEngine:i,translationEngine:l,actionDispatcher:u,parentComponentContext:d,parentFormContextProp:f,parentDataContext:g,isRootRenderer:m=!1,isInsideIteration:b=!1,isEditMode:v=!1,onComponentSelect:S,onComponentHover:E,onDragStart:A,onDragEnd:T,componentPath:L,layoutKey:M})=>{const[R,D]=N.useState({loadingActions:{}});N.useLayoutEffect(()=>{d||(i.startRenderCycle(),window.__g7SetLocalOverrideKeys||(window.__g7ForcedLocalFields=void 0),window.__g7PendingLocalState=null)});const U=N.useRef(null);N.useLayoutEffect(()=>{if(!d&&e._localInit&&typeof e._localInit=="object"){const{_forceLocalInit:q,_merge:ce,...le}=e._localInit,Z=`${JSON.stringify(le)}:${q||"no-force"}`;if(U.current!==Z){U.current=Z;const be=ce||"shallow",Re=window.G7Core?.state?.get?.()?._local||{},xe=window.__g7PendingLocalState||{},je={...Re,...xe};be==="replace"?window.__g7PendingLocalState={loadingActions:je.loadingActions||{},...le,hasChanges:!1}:be==="deep"?window.__g7PendingLocalState=ya(je,{...le,hasChanges:!1}):window.__g7PendingLocalState={...je,...le,hasChanges:!1};const ze=window.__g7SetLocalOverrideKeys;ze&&typeof ze=="object"&&(be==="replace"?window.__g7SetLocalOverrideKeys={...le,hasChanges:!1}:window.__g7SetLocalOverrideKeys=ya(ze,{...le,hasChanges:!1}))}}}),N.useLayoutEffect(()=>{if(!d){const q=window.__g7SetLocalOverrideKeys;if(q){D(be=>Vm(be,q));const ce=q,le=window.__g7ForcedLocalFields,Z=window.__g7LastSetLocalSnapshot;queueMicrotask(()=>{window.__g7SetLocalOverrideKeys===ce&&(window.__g7SetLocalOverrideKeys=void 0),window.__g7ForcedLocalFields===le&&(window.__g7ForcedLocalFields=void 0),window.__g7LastSetLocalSnapshot===Z&&(window.__g7LastSetLocalSnapshot=void 0)})}}},[e._local]);const j=N.useRef(M);N.useEffect(()=>{o._fromBase&&M&&j.current!==M&&(j.current=M,D({loadingActions:{}}))},[M,o._fromBase]);const P=N.useRef(""),X=N.useRef(!1),ge=N.useRef(null),Ee=N.useRef({}),Ce=N.useRef({}),$e=N.useRef(g),Pe=SC(),Xe=Q0(),ht=Xe?.getParentDataContext()??g;N.useEffect(()=>{if(e._localInit&&typeof e._localInit=="object"){const{_forceLocalInit:q,...ce}=e._localInit,le=JSON.stringify(ce),Z=q!==void 0,be=Od(),Se=`${le}:${q||"no-force"}`;if(be.hash!==Se){be.hash=Se,be.timestamp=q,P.current=le,Z&&(X.current=!0);const{_merge:je,...ze}=ce,Le=je||"shallow";if(D(ke=>Le==="replace"?{loadingActions:ke.loadingActions||{},...ze,hasChanges:!1}:Le==="deep"?ya(ke,{...ze,hasChanges:!1}):{...ke,...ze,hasChanges:!1}),e._globalSetState){const ke=e._global?._local||{};let We;Le==="replace"?We={...ze,hasChanges:!1}:Le==="deep"?We=ya(ke,{...ze,hasChanges:!1}):We={...ke,...ze,hasChanges:!1},e._globalSetState({_local:We})}i.invalidateCacheByKeys(["_local"]),dt.log("_localInit applied (data changed):",Object.keys(ce))}ge.current=e._localInit,aC(e._localInit)}},[e._localInit,g,i]);const{isTransitioning:Q}=nm(),fe=dC(),ye=f??fe,{width:te}=Md(),he=h_(),x=N.useMemo(()=>{let q=o;if(o.type==="iterator"&&o.data){const{data:Z,itemName:be,indexName:Se,...Re}=o;q={...Re,iteration:{source:Z,item_var:be||"item",index_var:Se}}}if(!q.responsive)return q;const ce=ci.getMatchingKey(q.responsive,te);if(!ce)return q;const le=q.responsive[ce];return{...q,props:{...q.props,...le.props},children:le.children??q.children,text:le.text??q.text,if:le.if??q.if,iteration:le.iteration??q.iteration,__responsiveChildrenKey:le.children!==void 0?ce:void 0}},[o,te]),K=N.useCallback(q=>{const ce=q?.__setStateId;if(D(le=>{const Z=window.__g7PendingLocalState,Se=window.__g7SetLocalOverrideKeys||Z,Re=Se?ya(le,Se):le;if(typeof q=="function"){const ke=q(Re);return ya(Re,ke)}const{__mergeMode:xe,__setStateId:je,...ze}=q;let Le;if(xe==="replace"?Le=ze:xe==="shallow"?Le={...Re,...ze}:Le=ya(Re,ze),xe!==void 0){const ke=window.__g7ForcedLocalFields;ke&&(window.__g7ForcedLocalFields={...ke,...ze})}return Le}),ce){const le=Qa();if(le?.isEnabled()){const Z=x.id||"unknown",be=x.name||"Unknown";setTimeout(()=>{le.trackComponentRender?.(Z,be,0,["_local"],[]),le.completeStateChange?.(ce)},0)}}},[x.id,x.name]),re=d?.state??R,de=d?.setState??K,se=N.useMemo(()=>{const q=e._localInit&&e._localInit!==ge.current;let ce;q&&e._local?ce=e._local:ce=e._local?ya(e._local,re):re;const le=window.__g7ForcedLocalFields;le&&(ce=ya(ce,le));const Z={...e,_local:ce},be=e._computedDefinitions;if(be&&Object.keys(be).length>0){const Se=new wn,Re={...Z,...Pe?{_isolated:Pe.state}:{}},xe={},je=Qa(),ze=je?.isEnabled()??!1;for(const[Le,ke]of Object.entries(be)){const We=ze?Date.now():0,Fe=ze?e._computed?.[Le]:void 0;let _e;try{if(typeof ke=="string")if(ke.startsWith("{{")&&ke.endsWith("}}")){const Te=ke.slice(2,-2).trim(),Ue=Se.evaluateExpression(Te,Re,{skipCache:!0});xe[Le]=Ue}else xe[Le]=ke;else if(ke&&typeof ke=="object"&&"$switch"in ke){const Te=Se.resolveSwitch(ke,Re,{skipCache:!0});xe[Le]=Te}}catch(Te){dt.warn(`Failed to recalculate computed value: ${Le}`,Te),xe[Le]=e._computed?.[Le],_e=Te instanceof Error?Te.message:String(Te)}if(ze&&(_e||Fe!==xe[Le])){const Ue=Date.now()-We;je.trackComputedProperty?.(Le,typeof ke=="string"?ke:JSON.stringify(ke),[{type:"_local",path:"_local",value:Z._local}],xe[Le],Ue,x.id,_e),Fe!==xe[Le]&&je.trackComputedRecalc?.(Le,"dependency-change",Fe,xe[Le],Ue,{type:"_local",path:"_local"},x.id)}}Z._computed=xe}if(Pe&&(Z._isolated=Pe.state),ht&&(Z.$parent=ht),o.extensionPointProps){const Se=i.resolveObject(o.extensionPointProps,Z,b?{skipCache:!0}:void 0);Z.extensionPointProps=v&&l?Zd(Se,l,a,Z):Se}return o.extensionPointCallbacks&&(Z.extensionPointCallbacks=o.extensionPointCallbacks),v&&(Z.$templateId===void 0&&a?.templateId&&(Z.$templateId=a.templateId),Z.$locale===void 0&&a?.locale&&(Z.$locale=a.locale)),Z},[e,re,Pe?.state,ht,Xe?.version,o.extensionPointProps,o.extensionPointCallbacks]);Ee.current=se._local,Ce.current=se._computed||{},$e.current=ht,N.useEffect(()=>{const q=Qa();if(!q?.isEnabled())return;const ce=se._local;ce&&q.updateLocalState(ce);const le=se._computed;le&&q.updateComputedState(le),ht&&q.updateParentContext?.(ht);const Z=x.id||`comp-${Date.now()}`,be=x.name||"Unknown",Se={global:Object.keys(e._global||{}),local:Object.keys(ce||{}),context:d?Object.keys(d.state||{}):[]},Re={type:d?"componentContext":"dynamicState",hasComponentContext:!!d,parentId:d?"parent":void 0};q.trackComponentStateSource?.(Z,be,Se,Re),re&&Object.keys(re).length>0&&q.trackDynamicState?.(Z,re);const xe=!!(x.expandChildren||x.props?.expandChildren);q.trackContextFlow?.(Z,be,!!d,xe,!0)},[se._local,e,x.id,x.name,d,re,x.expandChildren,x.props?.expandChildren,ht]);const me=N.useMemo(()=>({state:{...se._local},setState:de,stateRef:Ee,computedRef:Ce,isolatedContext:Pe,parentDataContext:se}),[se._local,de,R,Pe,se]),Ne=N.useMemo(()=>{const q=Yi({if:x.if,condition:x.condition,conditions:x.conditions},se,i,x.id);if(x.if||x.condition!==void 0||x.conditions){const le=Qa();le?.isEnabled()&&x.if&&le.trackIfCondition(x.id||`if-${Date.now()}`,x.if,q)}return q},[x.if,x.conditions,se,i,x.id]),ve=N.useMemo(()=>{if(!x.slot)return null;const q=x.slot;if(q.startsWith("{{")&&q.endsWith("}}")){const ce=q.slice(2,-2).trim();try{const le={componentId:x.id,componentName:x.name,propName:"slot"},Z=i.evaluateExpression(ce,se,le);return dt.log(`[Slot] 표현식 평가: "${ce}" => "${Z}" (컴포넌트: ${x.id})`),typeof Z=="string"?Z:null}catch(le){return dt.warn(`slot 표현식 평가 실패 (컴포넌트: ${x.id}):`,le),null}}return dt.log(`[Slot] 정적 슬롯 ID: "${q}" (컴포넌트: ${x.id})`),q},[x.slot,x.id,se,i]),He=N.useMemo(()=>!ve||!x.id?"":`${x.id}-${ve}-${JSON.stringify(x.slotOrder??0)}`,[ve,x.id,x.slotOrder]),Ae=N.useRef(null);N.useEffect(()=>{const q=window.__slotContextValue,ce=q?.isEnabled??!1;if(x.slot&&dt.log(`[Slot Registration] 컴포넌트: ${x.id}, isSlotEnabled: ${ce}, shouldRender: ${Ne}, resolvedSlotId: ${ve}`),!ce||!Ne){x.slot&&dt.log(`[Slot Registration] 등록 스킵 - isSlotEnabled: ${ce}, shouldRender: ${Ne}`),Ae.current&&x.id&&q&&(q.unregisterFromSlot(Ae.current,x.id),Ae.current=null);return}if(!ve||!x.id){x.slot&&dt.log(`[Slot Registration] 등록 스킵 - resolvedSlotId: ${ve}, id: ${x.id}`),Ae.current&&x.id&&q&&(q.unregisterFromSlot(Ae.current,x.id),Ae.current=null);return}Ae.current&&Ae.current!==ve&&q.unregisterFromSlot(Ae.current,x.id);const le={...x,slot:void 0,slotOrder:void 0};return q.registerToSlot(ve,x.id,{componentDef:le,dataContext:e,order:x.slotOrder??0,parentFormContext:f??null,getParentComponentContext:()=>me,translationContext:a,registrationKey:He}),Ae.current=ve,()=>{const Z=window.__slotContextValue;ve&&x.id&&Z&&Z.unregisterFromSlot(ve,x.id)}},[Ne,ve,x,e,f,me,a,He]);const Et=N.useCallback(q=>{if(typeof q=="string"){if(rp(q))return sp(q);if(ip(q)){const ce=[],le=q.replace(new RegExp(`${Tl}([^${Ws}]*)${Ws}`,"g"),(be,Se)=>(ce.push(Se),`${_r}${ce.length-1}${_r}`));let Z=le;return/\$t:[a-zA-Z0-9._-]+/.test(le)&&(Z=l.resolveTranslations(le,a,se)),Z.replace(new RegExp(`${_r}(\\d+)${_r}`,"g"),(be,Se)=>ce[parseInt(Se)])}if(q.startsWith("$t:defer:"))return q;if(/\$t:[a-zA-Z0-9._-]+/.test(q)){const ce=q.trim();return ce.startsWith("{")&&ce.endsWith("}")||ce.startsWith("[")&&ce.endsWith("]")?q:l.resolveTranslations(q,a,se)}return q}if(Array.isArray(q))return q.map(ce=>Et(ce));if(q&&typeof q=="object"){const ce={};for(const[le,Z]of Object.entries(q))ce[le]=Et(Z);return ce}return q},[l,a,se]),Rt=N.useCallback(q=>/[?:|&!+\-*/<>=()]/.test(q),[]),_t=N.useCallback(q=>{if(!q.startsWith("{{")||!q.endsWith("}}"))return null;const ce=q.slice(2,-2);let le=null,Z=0;for(let be=0;be0?ce[be-1]:"")!=="\\"&&((Se==='"'||Se==="'")&&!le?le=Se:Se===le&&(le=null),!le&&(Se==="{"&&Z++,Se==="}"&&Z--,Z<0)))return null}return Z===0?ce.trim():null},[]),ft=N.useMemo(()=>{let q={...x.props||{}};const ce=["cellChildren","expandChildren","expandContext","render"],Z=r.getMetadata(x.name)?.skipBindingKeys||[],be=[...new Set([...ce,...Z])],Se=b?{skipCache:!0}:void 0,Re=_e=>{if(Se)return Se;if(_e.startsWith("_computed")||_e.startsWith("$computed"))return{skipCache:!0}};for(const[_e,Te]of Object.entries(q))if(!be.includes(_e))if(typeof Te=="string"){const Ue=_t(Te);if(Ue!==null){let st=!1,Dt=Ue;Ue.startsWith(Er)&&(st=!0,Dt=Ue.slice(Er.length));const nn={componentId:x.id,componentName:x.name,propName:_e};let Kt;if(Rt(Dt))try{Kt=i.evaluateExpression(Dt,se,nn)}catch(qn){dt.warn(`표현식 평가 실패 (컴포넌트: ${x.id}, prop: ${_e}):`,qn),Kt=void 0}else Kt=i.resolve(Dt,se,Re(Dt),nn);q[_e]=st&&Kt!=null?Xs(Kt):Kt}else{const st={componentId:x.id,componentName:x.name,propName:_e};q[_e]=i.resolveBindings(Te,se,Se,st)}}else Array.isArray(Te)?q[_e]=Te.map(Ue=>typeof Ue=="string"?i.resolveBindings(Ue,se,Se):typeof Ue=="object"&&Ue!==null?i.resolveObject(Ue,se,Se):Ue):Te&&typeof Te=="object"&&(q[_e]=i.resolveObject(Te,se,Se));for(const[_e,Te]of Object.entries(q))q[_e]=Et(Te);if(typeof q.style=="string"&&(q.style=m_(q.style)),q=od(q,v?void 0:x.actions,se,{componentContext:me,actionDispatcher:u}),x.classMap){const _e=ow(x.classMap,se,i,{skipCache:!0});if(_e){const Te=q.className||"";q.className=Te?`${Te} ${_e}`:_e}}x.style&&(q.style=x.style),x.actions&&x.actions.length>0&&x.type==="composite"&&Object.assign(q,re),x.component_layout&&(q.__componentLayoutDefs=x.component_layout);const xe=x.expandChildren||x.props?.expandChildren,je=x.props?.cellChildren,ze=x.children&&x.children.length>0,Le=x.component_layout,ke=x.slot,We=x.props?.modalId,Fe=x.type==="composite";return(xe||je||ze||Le||ke||We||Fe)&&(q.__componentContext=me),q},[x.props,x.actions,x.style,x.classMap,x.id,se,a,i,l,me,re,Et,Rt,_t,b]),un=N.useRef(null),gt=N.useMemo(()=>un.current&&rm(un.current,ft)?un.current:(un.current=ft,ft),[ft]),ja=N.useMemo(()=>{const q=x.id;if(typeof q!="string"||!q.includes("{{"))return q;const ce=i.resolveBindings(q,se,{skipCache:!0});return typeof ce=="string"?ce:q},[x.id,se,i]),kn=N.useMemo(()=>{const q=x.dataKey,ce=x.trackChanges,le=x.debounce;if(q){const Z=q.startsWith("_global."),be=Z?q.slice(8):q,Se=Z?e._global:se._local;return{dataKey:be,trackChanges:ce??!1,debounce:le,setState:Z?xe=>{e._globalSetState?e._globalSetState(xe):dt.warn("_global.formData 사용 시 _globalSetState가 필요합니다.")}:de,state:Se??{},_isGlobal:Z}}if(ye.dataKey)return ye},[x.dataKey,x.trackChanges,x.debounce,x.id,de,se._local,e._global,e._globalSetState,ye]),Dn=N.useRef(new Set);N.useEffect(()=>{Dn.current.clear()},[e._global?._remountKeys]);const jt=N.useCallback((q,ce)=>{const le=e._global?._remountKeys;return q&&le?.[q]&&!Dn.current.has(q)?(Dn.current.add(q),`${q}-remount-${le[q]}`):q||ce},[e._global?._remountKeys]),On=N.useMemo(()=>{if(x.text!==void 0){if(typeof x.text=="string"){const q=x.text;let ce=q;const le={componentId:x.id,componentName:x.name,propName:"text",skipCache:!0},Z=_t(q);if(Z!==null)if(ap(Z))ce=i.resolveBindings(q,se,{skipCache:!0},le);else if(Rt(Z))try{ce=i.evaluateExpression(Z,se,le)}catch(be){dt.warn(`text 표현식 평가 실패 (컴포넌트: ${x.id}):`,be),ce=""}else ce=i.resolve(Z,se,{skipCache:!0},le);else q.includes("{{")&&(ce=i.resolveBindings(q,se,{skipCache:!0},le));return ce=Et(ce),ce??""}return x.text}return!x.children||x.children.length===0?null:x.children.map((q,ce)=>{if(typeof q=="string")return q;const le=x.__responsiveChildrenKey,Z=le?`responsive.${le}.children`:"children",be=L?`${L}.${Z}.${ce}`:`${ce}`,Se=q._fromBase?q.id||`child-${ce}`:jt(q.id,`child-${ce}`),Re=!q._fromBase&&M?`${Se}_${M}`:Se;return ut.jsx(Ha,{componentDef:q,dataContext:se,translationContext:a,registry:r,bindingEngine:i,translationEngine:l,actionDispatcher:u,parentComponentContext:me,parentFormContextProp:kn,isInsideIteration:b,isEditMode:v,onComponentSelect:S,onComponentHover:E,componentPath:be,onDragStart:A,onDragEnd:T,layoutKey:M},Re)})},[x.text,x.children,x.id,e,se,a,r,i,l,u,me,kn,_t,Rt,Et,jt,b,v,S,E,L,A,T,M]),ea=N.useMemo(()=>{if(!x.iteration)return null;try{const q=sd(x.iteration.source,se,i);if(!Array.isArray(q))return dt.warn(`iteration source가 배열이 아닙니다 (컴포넌트: ${x.id}):`,q),null;const ce=Qa();return ce?.isEnabled()&&ce.trackIteration(x.id||`iteration-${Date.now()}`,x.iteration.source,x.iteration.item_var,x.iteration.index_var,q.length),q.map((le,Z)=>{const be={...se,[x.iteration.item_var]:le};x.iteration.index_var&&(be[x.iteration.index_var]=Z);const Se=Z===0||Z===q.length-1;ce?.isEnabled()&&Se&&ce.trackNestedContext?.({componentId:`${x.id||"unknown"}-iter-${Z}`,componentType:"iteration",parentContext:{available:Object.keys(se),values:{}},ownContext:{added:[x.iteration.item_var,...x.iteration.index_var?[x.iteration.index_var]:[]],values:{[x.iteration.item_var]:le,...x.iteration.index_var?{[x.iteration.index_var]:Z}:{}}},depth:1});const Re={...x,iteration:void 0,responsive:void 0},xe=L?`${L}.iteration.${Z}`:`iteration.${Z}`,je=`${jt(x.id,"item")}-${Z}`;return ut.jsx(Ha,{componentDef:Re,dataContext:be,translationContext:a,registry:r,bindingEngine:i,translationEngine:l,actionDispatcher:u,parentComponentContext:me,parentFormContextProp:kn,isInsideIteration:!0,isEditMode:v,onComponentSelect:S,onComponentHover:E,componentPath:xe,onDragStart:A,onDragEnd:T,layoutKey:M},je)})}catch(q){return dt.error(`iteration 렌더링 실패 (컴포넌트: ${x.id}):`,q),null}},[x.iteration,x.children,x.id,e,se,a,r,i,l,u,me,kn,jt,v,S,E,L,A,T,M]),[Ua,Ft]=N.useState(0),Dr=N.useMemo(()=>{if(!x.sortable||!x.itemTemplate)return null;const{sortable:q,itemTemplate:ce}=x;try{const le=sd(q.source,se,i);if(!Array.isArray(le))return dt.warn(`sortable source가 배열이 아닙니다 (컴포넌트: ${x.id}):`,le),null;if(le.length===0)return null;const Z=q.itemKey||"id",be=q.strategy||"verticalList",Se=q.itemVar||"$item",Re=q.indexVar||"$index",xe=q.handle,je=q.wrapperElement,ze=(We,Fe)=>{const _e=x.actions?.filter(Te=>Te.event==="onSortEnd"||Te.type==="onSortEnd");if(Ft(Te=>Te+1),_e&&_e.length>0&&u){const Te={...se,$sortedItems:We,$sortEvent:Fe};_e.forEach(Ue=>{try{const st=u.createHandler(Ue,Te,me),Dt=new Event("sortend");st(Dt)}catch(st){dt.error(`onSortEnd action failed: ${Ue.handler}`,st)}})}},Le=We=>{const Fe=x.actions?.filter(_e=>_e.event==="onSortStart"||_e.type==="onSortStart");if(Fe&&Fe.length>0&&u){const _e={...se,$activeId:We.activeId};Fe.forEach(Te=>{try{const Ue=u.createHandler(Te,_e,me),st=new Event("sortstart");Ue(st)}catch(Ue){dt.error(`onSortStart action failed: ${Te.handler}`,Ue)}})}},ke=le.map((We,Fe)=>{const _e=String(We[Z]),Te={...se,[Se]:We,[Re]:Fe},Ue=L?`${L}.sortable.${Fe}`:`sortable.${Fe}`,st=`${jt(x.id,"sortable-item")}-v${Ua}-${_e}`;return ut.jsx(g_,{id:_e,handle:xe,...je?{as:je}:{},children:(je&&ce.children?ce.children:[ce]).map((Dt,nn)=>ut.jsx(Ha,{componentDef:Dt,dataContext:Te,translationContext:a,registry:r,bindingEngine:i,translationEngine:l,actionDispatcher:u,parentComponentContext:me,parentFormContextProp:void 0,isInsideIteration:!0,isEditMode:v,onComponentSelect:S,onComponentHover:E,componentPath:Ue,onDragStart:A,onDragEnd:T,layoutKey:M},`${st}-child-${nn}`))},st)});return ut.jsx(d_,{items:le,itemKey:Z,strategy:be,onSortEnd:ze,onSortStart:Le,sortVersion:Ua,children:ke})}catch(le){return dt.error(`sortable 렌더링 실패 (컴포넌트: ${x.id}):`,le),null}},[x.sortable,x.itemTemplate,x.actions,x.id,e,se,a,r,i,l,u,me,jt,v,S,E,L,A,T,Ua,M]),er=N.useRef(!1);N.useEffect(()=>{if(er.current)return;er.current=!0;const q=Qa();if(q?.isEnabled()&&q.trackMount(o.id,{name:o.name,type:o.type||"component",props:gt}),o.lifecycle?.onMount&&o.lifecycle.onMount.length>0)for(const le of o.lifecycle.onMount)try{const Z=u.createHandler(le,se,me),be=new Event("mount");Z(be),dt.log(`Lifecycle onMount executed: ${le.handler} (Component: ${o.id})`)}catch(Z){dt.error(`Lifecycle onMount failed: ${le.handler} (Component: ${o.id})`,Z)}const ce=[];if(o.onComponentEvent&&o.onComponentEvent.length>0){const le=window.G7Core;if(le?.componentEvent?.on)for(const Z of o.onComponentEvent){if(!Z.event){dt.warn(`onComponentEvent: event name is required (Component: ${o.id})`);continue}const be=async Re=>{try{const xe={...se,_eventData:Re},ze=await u.createHandler({handler:Z.handler,params:Z.params,onSuccess:Z.onSuccess,onError:Z.onError},xe,me)(new CustomEvent(Z.event,{detail:Re}));return dt.log(`onComponentEvent "${Z.event}" handled: ${Z.handler} (Component: ${o.id})`,{eventData:Re,result:ze}),ze}catch(xe){throw dt.error(`onComponentEvent "${Z.event}" failed: ${Z.handler} (Component: ${o.id})`,xe),xe}},Se=le.componentEvent.on(Z.event,be);ce.push(Se),dt.log(`onComponentEvent: Subscribed to "${Z.event}" (Component: ${o.id})`)}else dt.warn(`onComponentEvent: G7Core.componentEvent is not available (Component: ${o.id})`)}return()=>{const le=Qa();le?.isEnabled()&&le.trackUnmount(o.id);for(const Z of ce)try{Z()}catch(be){dt.error(`onComponentEvent: Failed to unsubscribe (Component: ${o.id})`,be)}if(ce.length>0&&dt.log(`onComponentEvent: Unsubscribed ${ce.length} event(s) (Component: ${o.id})`),o.lifecycle?.onUnmount&&o.lifecycle.onUnmount.length>0)for(const Z of o.lifecycle.onUnmount)try{const be=u.createHandler(Z,se,me),Se=new Event("unmount");be(Se),dt.log(`Lifecycle onUnmount executed: ${Z.handler} (Component: ${o.id})`)}catch(be){dt.error(`Lifecycle onUnmount failed: ${Z.handler} (Component: ${o.id})`,be)}}},[]);const bn=N.useMemo(()=>{const q=gt.dataKey,ce=gt.trackChanges,le=gt.debounce;return q?{dataKey:q,trackChanges:ce??!1,debounce:le,setState:de,state:re}:null},[gt.dataKey,gt.trackChanges,gt.debounce,de,re]);N.useEffect(()=>{const q=x.dataKey||gt.dataKey;if(!q)return;const ce=Qa();if(!ce?.isEnabled())return;const le=[],Z=Se=>{if(Se)for(const Re of Se){const xe=Re?.props?.name;if(xe&&le.push({name:xe,type:Re.name||Re.type||"unknown"}),Re?.children&&Z(Re.children),Re?.slots)for(const je of Object.values(Re.slots))Array.isArray(je)&&Z(je)}};if(o.children&&Z(o.children),o.slots)for(const Se of Object.values(o.slots))Array.isArray(Se)&&Z(Se);const be=o.id||`form-${q}`;return ce.trackForm(be,q,le),()=>{ce.untrackForm(be)}},[x,gt.dataKey,o.id,o.children]);const en=N.useRef(null),et=N.useRef(void 0);N.useEffect(()=>{const q=gt?.name;if(!q||!ye.dataKey||!ye.setState||gt?.autoBinding===!1)return;const ce=`${ye.dataKey}.${q}`,le=window.__g7AutoBindingPaths??new Map;return window.__g7AutoBindingPaths=le,le.set(ce,(le.get(ce)??0)+1),()=>{const Z=le.get(ce)??0;Z<=1?le.delete(ce):le.set(ce,Z-1)}},[gt?.name,gt?.autoBinding,ye.dataKey,ye.setState]);const ta=N.useMemo(()=>{const{dataKey:q,trackChanges:ce,debounce:le,...Z}=gt,be=Z.name;if(!be||!ye.dataKey||!ye.setState)return Z;if(Z.autoBinding===!1){const{autoBinding:_e,...Te}=Z;return Te}const Se=`${ye.dataKey}.${be}`,Re=fC(ye.state,Se),xe=Re!==void 0?Re:Z.value,ze=r.getMetadata(o.name)?.bindingType,Le=typeof xe=="boolean"&&(ze==="checked"||ze==="checkable"&&["checkbox","radio"].includes(Z?.type)),ke=ye.debounce,We=_e=>{const Te=ye.state||{},Ue=hC(Te,Se,_e);if(ye.trackChanges&&(Ue.hasChanges=!0),window.__g7PendingLocalState=Ue,ye.setState(Ue),ye._isGlobal)return;const st=window.G7Core,Dt={[Se]:_e};ye.trackChanges&&(Dt.hasChanges=!0),st?.state?.setLocal?.(Dt,{render:!1})},Fe=(_e,Te)=>{ke&&ke>0?(en.current&&clearTimeout(en.current),en.current=setTimeout(()=>{We(_e),en.current=null,Te&&(Te(),window.__g7PendingLocalState=null)},ke)):(We(_e),Te&&(Te(),window.__g7PendingLocalState=null))};if(Le)return{...Z,checked:xe,onChange:Te=>{const Ue=Te.target.checked;We(Ue),Z.onChange&&Z.onChange(Te)}};{const _e=Ue=>{const st=Ue?.target?.value!==void 0?Ue.target.value:Ue;ke&&ke>0&&(et.current=st);const Dt=Ue?.target?{target:{value:st,name:Ue.target.name,type:Ue.target.type,checked:Ue.target.checked},currentTarget:Ue.currentTarget?{value:st,name:Ue.currentTarget.name}:void 0}:Ue;Fe(st,()=>{Z.onChange&&Z.onChange(Dt)})};let Te;return et.current!==void 0?en.current!==null?Te=et.current:String(xe??"")===String(et.current)?(et.current=void 0,Te=xe??""):Te=et.current:Te=xe??"",{...Z,value:Te,onChange:_e}}},[gt,ye,ye.state,ye.debounce]),En=N.useMemo(()=>{const q=Qa();if(q?.isEnabled()&&q.trackRender(o.name),!Ne)return null;if(x.sortable&&x.itemTemplate)return Dr;if(x.iteration)return ea;if(x.type==="extension_point"){const{layout:ze,columns:Le,gap:ke,className:We,...Fe}=x.props||{};let _e=We||"";return ze==="grid"&&Le?_e=`${_e} grid grid-cols-${Le} gap-${ke||4}`.trim():ze==="flex"&&(_e=`${_e} flex flex-col gap-${ke||4}`.trim()),ut.jsx("div",{id:ja,className:_e||void 0,...Fe,children:On})}const ce=r.getComponent(x.name);if(!ce)return dt.error(`컴포넌트를 찾을 수 없습니다: ${x.name} (ID: ${x.id})`,"componentDef:",JSON.stringify(x,null,2)),null;const le=e._global?._remountKeys,Z={...ta,id:ta.id??ja,...le&&Object.keys(le).length>0&&{__remountTrigger:JSON.stringify(le)}};if(he?.listeners&&he.handle&&ta["data-drag-handle"]!==void 0&&(Object.assign(Z,he.listeners),Z.style={...Z.style,cursor:he.isDragging?"grabbing":"grab"}),v){const ze=x.id||`auto_${x.name||x.type||"unknown"}_${Math.random().toString(36).substring(2,8)}`,Le=Fe=>{typeof Fe.preventDefault=="function"&&Fe.preventDefault(),S&&(Fe.stopPropagation(),S(ze,Fe))},ke={"data-editor-id":ze,"data-editor-name":x.name,"data-editor-type":x.type,onClick:Le};L&&(ke["data-editor-path"]=L);const We=x.__editorSlotName??x.slot;typeof We=="string"&&(ke["data-editor-slot"]=We),E&&(ke.onMouseMove=Fe=>{Fe.stopPropagation(),E(ze,Fe)},ke.onMouseLeave=Fe=>{E(null,Fe)}),Object.assign(Z,ke),Z.editorAttrs=ke}const be=x.type==="basic",Se=x.type==="layout",xe=be||Se?(()=>{const ze={};for(const[Le,ke]of Object.entries(Z))Le.startsWith("__")||Le==="editorAttrs"&&be||(ze[Le]=ke);return ze})():Z;let je=ut.jsx(ce,{...xe,children:On});if(kn&&(je=ut.jsx(uC,{value:kn,children:je})),x.isolatedState){const ze=typeof x.isolatedState=="object"?x.isolatedState:{},Le=e?._isolatedInit,ke=Le?{...ze,...Le}:ze;je=ut.jsx(vC,{initialState:ke,scopeId:x.isolatedScopeId,children:je})}return je},[Ne,x.iteration,x.sortable,x.itemTemplate,x.type,x.name,x.id,x.props,x.isolatedState,x.isolatedScopeId,r,ta,On,ea,Dr,he,bn,v,S,E,A,T,L,e._global?._remountKeys]),tr=N.useMemo(()=>{const q=x.blur_until_loaded;if(!q||e?._global?.__isPreview)return!1;if(typeof q=="string"){const Z=_t(q);if(Z!==null)try{const be={componentId:x.id,componentName:x.name,propName:"blur_until_loaded"};return!!i.evaluateExpression(Z,se,be)}catch(be){return dt.warn(`blur_until_loaded 표현식 평가 실패 (컴포넌트: ${x.id}):`,be),!1}return!1}if(typeof q=="object"&&q!==null){if(!q.enabled)return!1;if(q.data_sources)return(Array.isArray(q.data_sources)?q.data_sources:[q.data_sources]).some(Re=>e[Re]===void 0);if(Q)return!0;const Z=["route","query","_global","_local","_dataSourceErrors"];return Object.keys(e).filter(Se=>!Z.includes(Se)&&!Se.startsWith("_")).some(Se=>e[Se]===void 0)}if(Q)return!0;const ce=["route","query","_global","_local","_dataSourceErrors"];return Object.keys(e).filter(Z=>!ce.includes(Z)&&!Z.startsWith("_")).some(Z=>e[Z]===void 0)},[x.blur_until_loaded,x.id,Q,e,se,i,_t]);if(tr){const q=x.blur_until_loaded;if(typeof q=="object"&&q?.data_sources){const le=(Array.isArray(q.data_sources)?q.data_sources:[q.data_sources]).reduce((be,Se)=>(be[Se]=e[Se]===void 0?"UNDEFINED":"LOADED",be),{}),Z=Object.keys(e).filter(be=>!be.startsWith("_"));dt.log(`[BLUR APPLIED] Component: ${x.id}, data_sources status:`,le,"Available keys:",Z)}else dt.log(`[BLUR APPLIED] Component: ${x.id}, blur_until_loaded:`,q)}const Ea=N.useMemo(()=>{if(!x.blur_until_loaded)return{wrapperClasses:"",innerClasses:""};const q=ft?.className||"";if(!q)return{wrapperClasses:"",innerClasses:""};const ce=[/^(sm:|md:|lg:|xl:|2xl:)?(col-span-|row-span-|col-start-|col-end-|row-start-|row-end-)/,/^(sm:|md:|lg:|xl:|2xl:)?(self-|place-self-|order-)/,/^(sm:|md:|lg:|xl:|2xl:)?(flex-shrink|flex-grow|flex-\d|basis-)/],le=q.split(/\s+/).filter(Boolean),Z=[],be=[];for(const Se of le)ce.some(xe=>xe.test(Se))?Z.push(Se):be.push(Se);return{wrapperClasses:Z.join(" "),innerClasses:be.join(" ")}},[x.blur_until_loaded,ft?.className]),tn=window.__slotContextValue;return ve&&tn?.isEnabled?null:ut.jsx(y_,{componentId:o.id,componentName:o.name,children:x.blur_until_loaded?ut.jsx("div",{className:[Ea.wrapperClasses,tr?"opacity-50 blur-sm transition-all duration-300 pointer-events-none":void 0].filter(Boolean).join(" ")||void 0,children:En}):En})});Ha.displayName="DynamicRenderer",typeof window<"u"&&(window.__DynamicRenderer=Ha);function b_(o){const e={};try{const r=new URL(o,typeof window<"u"?window.location.origin:"http://localhost").searchParams,i=new Set;for(const l of r.keys()){if(i.has(l))continue;i.add(l);const u=r.getAll(l);u.length>1||l.endsWith("[]")?e[l]=u:e[l]=u[0]}}catch{}return e}function v_(o){try{return new URL(o,typeof window<"u"?window.location.origin:"http://localhost").pathname}catch{return o.split("?")[0]}}const mi=class mi{constructor(){$(this,"config",{enabled:!1,maxHistorySize:100,logLevel:"info",serverEndpoint:"/_boost/g7-debug/dump-state",autoCapture:!0});$(this,"stateHistory",[]);$(this,"snapshotIdCounter",0);$(this,"stateWatchers",new Map);$(this,"currentLocalState",{});$(this,"currentComputedState",{});$(this,"currentParentContext");$(this,"actionHistory",[]);$(this,"actionWatchers",new Set);$(this,"cacheStats",{hits:0,misses:0,entries:0});$(this,"cacheDecisions",[]);$(this,"cacheDecisionIdCounter",0);$(this,"maxCacheDecisions",200);$(this,"currentRenderCycleId",null);$(this,"isInActionExecution",!1);$(this,"isInIteration",!1);$(this,"mountedComponents",new Map);$(this,"eventListeners",new Map);$(this,"mountWatchers",new Set);$(this,"unmountWatchers",new Set);$(this,"renderCounts",new Map);$(this,"bindingEvalCount",0);$(this,"profilingData",[]);$(this,"isProfiling",!1);$(this,"profilingStartTime",0);$(this,"activeRequests",new Map);$(this,"requestHistory",[]);$(this,"pendingDataSources",new Set);$(this,"requestWatchers",new Set);$(this,"wsConnections",new Map);$(this,"wsMessageHistory",[]);$(this,"wsMessageWatchers",new Set);$(this,"ifConditions",new Map);$(this,"iterations",new Map);$(this,"conditionWatchers",new Set);$(this,"forms",new Map);$(this,"formWatchers",new Set);$(this,"expressionHistory",[]);$(this,"expressionWatchers",new Set);$(this,"expressionIdCounter",0);$(this,"dataSources",new Map);$(this,"dataPathTransforms",[]);$(this,"maxDataPathTransforms",100);$(this,"nestedContexts",[]);$(this,"nestedContextIdCounter",0);$(this,"maxNestedContexts",100);$(this,"formBindingIssues",[]);$(this,"formBindingValidations",[]);$(this,"formBindingIssueIdCounter",0);$(this,"maxFormBindingIssues",100);$(this,"computedProperties",new Map);$(this,"computedRecalcLogs",[]);$(this,"computedRecalcIdCounter",0);$(this,"maxComputedRecalcLogs",100);$(this,"handlers",new Map);$(this,"componentEventSubscriptions",new Map);$(this,"componentEventEmitHistory",[]);$(this,"componentEventIdCounter",0);$(this,"maxComponentEventHistory",100);$(this,"stateRenderingLogs",[]);$(this,"currentStateChangeContext",null);$(this,"stateRenderingIdCounter",0);$(this,"componentRenderCounts",new Map);$(this,"stateToComponentMap",new Map);$(this,"maxStateRenderingLogs",100);$(this,"componentStateSources",new Map);$(this,"contextFlowNodes",new Map);$(this,"dynamicStates",new Map);$(this,"styleIssues",[]);$(this,"componentStyles",new Map);$(this,"authEvents",[]);$(this,"authHeaderHistory",[]);$(this,"authEventIdCounter",0);$(this,"maxAuthEventHistory",50);$(this,"logHistory",[]);$(this,"logIdCounter",0);$(this,"maxLogHistory",500);$(this,"currentLayout",null);$(this,"layoutHistory",[]);$(this,"layoutIdCounter",0);$(this,"layoutStats",{totalLoads:0,cacheHits:0,apiLoads:0});$(this,"maxLayoutHistory",50);$(this,"executionDetails",new Map);$(this,"stateChangeHistory",[]);$(this,"dataSourceChangeHistory",[]);$(this,"changeAlerts",[]);$(this,"changeExpectations",new Map);$(this,"executionIdCounter",0);$(this,"stateChangeIdCounter",0);$(this,"alertIdCounter",0);$(this,"maxExecutionDetails",100);$(this,"maxStateChangeHistory",200);$(this,"maxChangeAlerts",100);$(this,"sequenceExecutions",[]);$(this,"sequenceExecutionStack",[]);$(this,"sequenceIdCounter",0);$(this,"maxSequenceExecutions",50);$(this,"staleClosureWarnings",[]);$(this,"staleClosureIdCounter",0);$(this,"maxStaleClosureWarnings",100);$(this,"stateCaptureRegistry",new Map);$(this,"modalStates",new Map);$(this,"modalStateIssues",[]);$(this,"modalStateRelations",[]);$(this,"modalStateChangeLogs",[]);$(this,"modalStateIssueIdCounter",0);$(this,"modalStateChangeLogIdCounter",0);$(this,"maxModalStateIssues",100);$(this,"maxModalStateChangeLogs",200);$(this,"namedActionDefinitions",{});$(this,"namedActionRefLogs",[]);$(this,"namedActionRefIdCounter",0);$(this,"maxNamedActionRefLogs",200);$(this,"debounceActionHistory",[]);$(this,"dataSourceUpdateHistory",[]);$(this,"debounceActionIdCounter",0);$(this,"dataSourceUpdateIdCounter",0)}static getInstance(){return mi.instance||(mi.instance=new mi),mi.instance}initialize(){if(this.config.enabled=this.checkDebugMode(),!this.config.enabled){console.log("[G7DevTools] 비활성화됨 (환경설정 > 고급 설정 > 디버그 모드를 켜세요)");return}console.log("[G7DevTools] 활성화됨"),this.setupGlobalErrorHandler()}checkDebugMode(){try{if(window.G7Config?.debug===!0)return!0;const r=window.G7Core?.state?.get?.();return r?.settings?.advanced?.debug_mode===!0||r?._global?.settings?.advanced?.debug_mode===!0}catch{return!1}}isEnabled(){return this.config.enabled}setupGlobalErrorHandler(){window.addEventListener("error",e=>{this.config.enabled&&this.logAction({id:this.generateId(),type:"globalError",startTime:Date.now(),status:"error",error:{name:"Error",message:e.message,stack:e.error?.stack}})}),window.addEventListener("unhandledrejection",e=>{this.config.enabled&&this.logAction({id:this.generateId(),type:"unhandledRejection",startTime:Date.now(),status:"error",error:{name:"UnhandledRejection",message:String(e.reason)}})})}captureStateSnapshot(e){if(!this.config.enabled)return;const a={id:++this.snapshotIdCounter,timestamp:Date.now(),source:e.source,prev:this.sanitizeObject(e.prev),next:this.sanitizeObject(e.next),diff:e.diff};this.stateHistory.push(a),this.stateHistory.length>this.config.maxHistorySize&&this.stateHistory.shift(),this.notifyStateWatchers(a)}getState(){try{const e=window.G7Core,a=e?.state?.get?.()||{},r={};if(e?._isolatedStates&&typeof e._isolatedStates=="object")for(const[i,l]of Object.entries(e._isolatedStates))r[i]=this.sanitizeObject(l);return{_global:a._global||a,_local:this.currentLocalState,_computed:this.currentComputedState,_isolated:Object.keys(r).length>0?r:void 0,$parent:this.currentParentContext}}catch{return{_global:{},_local:this.currentLocalState,_computed:this.currentComputedState}}}updateLocalState(e){this.config.enabled&&(this.currentLocalState=this.sanitizeObject(e))}updateComputedState(e){this.config.enabled&&(this.currentComputedState=this.sanitizeObject(e))}updateParentContext(e){this.config.enabled&&(this.currentParentContext=e?this.sanitizeObject(e):void 0)}getStateHistory(){return[...this.stateHistory]}getDualStorageMismatch(){const e=this.currentLocalState||{};let a={};try{a=(window.G7Core?.state?.get?.()||{})._local||{}}catch{a={}}const r=this.findMismatchedLeafPaths(e,a);return{hasMismatch:r.length>0,mismatchedPaths:r,storageA:e,storageB:a}}findMismatchedLeafPaths(e,a,r=""){const i=[],l=new Set([...Object.keys(e||{}),...Object.keys(a||{})]);for(const u of l){const d=r?`${r}.${u}`:u,f=e?.[u],g=a?.[u],m=f&&typeof f=="object"&&!Array.isArray(f),b=g&&typeof g=="object"&&!Array.isArray(g);if(m&&b)i.push(...this.findMismatchedLeafPaths(f,g,d));else{const v=f===void 0?"__undefined__":JSON.stringify(f),S=g===void 0?"__undefined__":JSON.stringify(g);v!==S&&i.push(d)}}return i}watchState(e,a){return this.stateWatchers.has(e)||this.stateWatchers.set(e,new Set),this.stateWatchers.get(e).add(a),()=>{this.stateWatchers.get(e)?.delete(a)}}notifyStateWatchers(e){if(this.stateWatchers.get("*")?.forEach(a=>{try{a(e.next,e.prev,"*")}catch(r){console.error("[G7DevTools] State watcher error:",r)}}),e.diff)for(const a of e.diff.changed)this.stateWatchers.get(a.path)?.forEach(r=>{try{r(a.newValue,a.oldValue,a.path)}catch(i){console.error("[G7DevTools] State watcher error:",i)}})}diffSnapshots(e,a){const r=this.stateHistory.find(l=>l.id===e),i=this.stateHistory.find(l=>l.id===a);return!r||!i?null:this.calculateDiff(r.next,i.next)}calculateDiff(e,a,r=""){const i={added:[],removed:[],changed:[]},l=new Set(Object.keys(e)),u=new Set(Object.keys(a));for(const d of u){const f=r?`${r}.${d}`:d;l.has(d)?JSON.stringify(e[d])!==JSON.stringify(a[d])&&i.changed.push({path:f,oldValue:e[d],newValue:a[d]}):i.added.push(f)}for(const d of l){const f=r?`${r}.${d}`:d;u.has(d)||i.removed.push(f)}return i}logAction(e){if(!this.config.enabled)return;const a=this.actionHistory.findIndex(r=>r.id===e.id);a>=0?this.actionHistory[a]={...this.actionHistory[a],...e}:(this.actionHistory.push(e),this.actionHistory.length>this.config.maxHistorySize&&this.actionHistory.shift()),this.isProfiling&&this.profilingData.push({type:"action",action:e.type,timestamp:performance.now(),duration:e.duration}),this.notifyActionWatchers(e)}getActionHistory(){return[...this.actionHistory]}watchActions(e){return this.actionWatchers.add(e),()=>{this.actionWatchers.delete(e)}}notifyActionWatchers(e){this.actionWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Action watcher error:",r)}})}getActionMetrics(){const e=this.actionHistory.filter(l=>l.status==="success"),a=this.actionHistory.filter(l=>l.status==="error"),r={};for(const l of this.actionHistory)r[l.type]=(r[l.type]||0)+1;const i=e.reduce((l,u)=>l+(u.duration||0),0);return{totalActions:this.actionHistory.length,successCount:e.length,errorCount:a.length,averageDuration:e.length>0?i/e.length:0,actionsByType:r}}recordCacheHit(){this.config.enabled&&this.cacheStats.hits++}recordCacheMiss(){this.config.enabled&&this.cacheStats.misses++}updateCacheEntries(e){this.config.enabled&&(this.cacheStats.entries=e)}getCacheStats(){const e=this.cacheStats.hits+this.cacheStats.misses;return{...this.cacheStats,hitRate:e>0?this.cacheStats.hits/e:0}}resetCacheStats(){this.cacheStats={hits:0,misses:0,entries:0}}trackCacheDecision(e){if(!this.config.enabled)return;const a={id:`cache-${++this.cacheDecisionIdCounter}`,timestamp:Date.now(),expression:e.expression,decision:e.decision,reason:e.reason,context:{isInIteration:this.isInIteration,isInAction:this.isInActionExecution,renderCycleId:this.currentRenderCycleId||void 0,componentId:e.componentId,skipCacheOption:e.skipCacheOption},cachedValue:e.cachedValue!==void 0?this.safeClone(e.cachedValue):void 0,freshValue:e.freshValue!==void 0?this.safeClone(e.freshValue):void 0,valueMatch:e.cachedValue!==void 0&&e.freshValue!==void 0?JSON.stringify(e.cachedValue)===JSON.stringify(e.freshValue):void 0,duration:e.duration};this.cacheDecisions.push(a),this.cacheDecisions.length>this.maxCacheDecisions&&this.cacheDecisions.shift(),e.decision==="cache_hit"?this.cacheStats.hits++:(e.decision==="cache_miss"||e.decision==="skip_cache")&&this.cacheStats.misses++}startRenderCycle(e){return this.currentRenderCycleId=`render-${Date.now()}-${e||"root"}`,this.currentRenderCycleId}endRenderCycle(){this.currentRenderCycleId=null}startActionContext(){this.isInActionExecution=!0}endActionContext(){this.isInActionExecution=!1}startIterationContext(){this.isInIteration=!0}endIterationContext(){this.isInIteration=!1}getCacheDecisionTrackingInfo(){const e=this.getCacheDecisionStats();return{decisions:[...this.cacheDecisions],stats:e,timestamp:Date.now()}}getCacheDecisionStats(){const e=this.cacheDecisions;let a=0,r=0,i=0,l=0;const u={},d={};for(const g of e)g.decision==="cache_hit"?a++:g.decision==="cache_miss"?r++:g.decision==="skip_cache"?i++:g.decision==="invalidate"&&l++,u[g.reason]=(u[g.reason]||0)+1,g.context.componentId&&(d[g.context.componentId]=(d[g.context.componentId]||0)+1);const f=a+r+i;return{totalDecisions:e.length,cacheHits:a,cacheMisses:r,skipCacheCount:i,invalidateCount:l,byReason:u,byComponent:d,avgHitRate:f>0?a/f:0}}getRecentCacheDecisions(e=20,a){let r=[...this.cacheDecisions];return a&&(r=r.filter(i=>i.decision===a)),r.slice(-e)}clearCacheDecisionData(){this.cacheDecisions=[],this.cacheDecisionIdCounter=0}summarizePropsForLifecycle(e){if(!e||typeof e!="object")return e;const a={},r=["children","ref","key"];for(const[i,l]of Object.entries(e))if(!r.includes(i))if(l==null)a[i]=l;else if(Array.isArray(l))a[i]=`[Array(${l.length})]`;else if(typeof l=="object"){const u=Object.keys(l);u.length<=3?a[i]=`{${u.join(", ")}}`:a[i]=`{${u.slice(0,3).join(", ")}, ... +${u.length-3}}`}else typeof l=="string"&&l.length>50?a[i]=l.substring(0,50)+"...":typeof l=="function"?a[i]="[Function]":a[i]=l;return a}trackMount(e,a){if(!this.config.enabled)return;const r=this.summarizePropsForLifecycle(a.props),i={...a,props:r,id:e,mountTime:Date.now()};this.mountedComponents.set(e,i),this.mountWatchers.forEach(l=>{try{l({componentId:e,componentName:a.name,timestamp:i.mountTime})}catch(u){console.error("[G7DevTools] Mount watcher error:",u)}})}trackUnmount(e){if(!this.config.enabled)return;const a=this.mountedComponents.get(e),r=this.eventListeners.get(e)||[];r.length>0&&console.warn(`[G7DevTools] 컴포넌트 ${e} 언마운트 시 ${r.length}개 리스너 미정리`),a&&this.unmountWatchers.forEach(i=>{try{i({componentId:e,componentName:a.name,timestamp:Date.now(),orphanedListeners:r.length})}catch(l){console.error("[G7DevTools] Unmount watcher error:",l)}}),this.mountedComponents.delete(e)}trackListener(e,a,r){if(!this.config.enabled)return;const i=this.eventListeners.get(e)||[];i.push({type:a,target:r,addedAt:Date.now()}),this.eventListeners.set(e,i)}removeListener(e,a){if(!this.config.enabled)return;const r=this.eventListeners.get(e)||[],i=r.findIndex(l=>l.type===a);i>=0&&r.splice(i,1)}getMountedComponents(){return Array.from(this.mountedComponents.values())}getOrphanedListeners(){const e=[];for(const[a,r]of this.eventListeners)this.mountedComponents.has(a)||e.push(...r.map(i=>({...i,componentId:a})));return e}watchMount(e){return this.mountWatchers.add(e),()=>{this.mountWatchers.delete(e)}}watchUnmount(e){return this.unmountWatchers.add(e),()=>{this.unmountWatchers.delete(e)}}trackRender(e){if(!this.config.enabled)return;const a=this.renderCounts.get(e)||0;this.renderCounts.set(e,a+1),this.isProfiling&&this.profilingData.push({type:"render",component:e,timestamp:performance.now()})}trackBindingEval(e){this.config.enabled&&(this.bindingEvalCount++,this.isProfiling&&e&&this.profilingData.push({type:"binding",expression:e,timestamp:performance.now()}))}getRenderCount(){return new Map(this.renderCounts)}getBindingEvalCount(){return this.bindingEvalCount}getMemoryWarnings(){const e=[];try{const i=this.getState(),l=JSON.stringify(i).length;l>1e6&&e.push({type:"large-state",message:`상태 크기가 ${(l/1024/1024).toFixed(2)}MB입니다`,suggestion:"불필요한 데이터 정리 필요",severity:l>5e6?"error":"warning"})}catch{}this.stateHistory.length>this.config.maxHistorySize*.8&&e.push({type:"large-history",message:`상태 이력이 ${this.stateHistory.length}개입니다`,suggestion:"maxHistory 설정 조정 필요",severity:"warning"});const a=this.getOrphanedListeners().length;a>0&&e.push({type:"orphaned-listeners",message:`${a}개의 정리되지 않은 이벤트 리스너`,suggestion:"useEffect cleanup 또는 removeEventListener 확인",severity:a>10?"error":"warning"});const r=Array.from(this.renderCounts.entries()).filter(([,i])=>i>50);return r.length>0&&e.push({type:"excessive-renders",message:`${r.length}개 컴포넌트가 50회 이상 렌더링`,suggestion:"React.memo, useMemo, useCallback 사용 고려",severity:"warning"}),e}startProfiling(){this.config.enabled&&(this.isProfiling=!0,this.profilingData=[],this.profilingStartTime=performance.now(),console.log("[G7DevTools] 프로파일링 시작"))}stopProfiling(){this.isProfiling=!1;const e=performance.now()-this.profilingStartTime,a=this.analyzeProfile(e);return console.log("[G7DevTools] 프로파일링 완료",a),a}analyzeProfile(e){const a=this.profilingData.filter(g=>g.type==="render"),r=this.profilingData.filter(g=>g.type==="binding"),i=this.profilingData.filter(g=>g.type==="action"),l={};for(const g of a)g.component&&(l[g.component]||(l[g.component]={count:0,durations:[]}),l[g.component].count++,g.duration&&l[g.component].durations.push(g.duration));const u=Object.entries(l).map(([g,m])=>({name:g,renderCount:m.count,avgDuration:m.durations.length>0?m.durations.reduce((b,v)=>b+v,0)/m.durations.length:0})).sort((g,m)=>m.renderCount-g.renderCount).slice(0,10),d={};for(const g of r)g.expression&&(d[g.expression]=(d[g.expression]||0)+1);const f=Object.entries(d).sort(([,g],[,m])=>m-g).slice(0,10).map(([g])=>g);return{duration:e,entries:this.profilingData,summary:{totalRenders:a.length,totalBindings:r.length,totalActions:i.length,slowestComponents:u,hotPaths:f}}}resetPerformanceStats(){this.renderCounts.clear(),this.bindingEvalCount=0,this.profilingData=[]}trackRequest(e,a,r){if(!this.config.enabled)return"";const i=this.generateId(),l=v_(e),u=b_(e);return this.activeRequests.set(i,{id:i,url:l,fullUrl:e,queryParams:u,method:a,startTime:Date.now(),status:"pending",requestBody:r?.requestBody?this.sanitizeObject(r.requestBody):void 0,dataSourceId:r?.dataSourceId}),this.isProfiling&&this.profilingData.push({type:"network",timestamp:performance.now()}),i}completeRequest(e,a,r){if(!this.config.enabled)return;const i=this.activeRequests.get(e);if(!i)return;const l={...i,status:a>=200&&a<300?"success":"error",statusCode:a,duration:Date.now()-i.startTime,endTime:Date.now(),response:this.sanitizeObject(r)};this.requestHistory.push(l),this.activeRequests.delete(e),this.requestHistory.length>this.config.maxHistorySize&&this.requestHistory.shift(),this.notifyRequestWatchers(l)}failRequest(e,a){if(!this.config.enabled)return;const r=this.activeRequests.get(e);if(!r)return;const i={...r,status:"error",error:a,duration:Date.now()-r.startTime,endTime:Date.now()};this.requestHistory.push(i),this.activeRequests.delete(e),this.notifyRequestWatchers(i)}trackDataSource(e){this.config.enabled&&this.pendingDataSources.add(e)}completeDataSource(e){this.config.enabled&&this.pendingDataSources.delete(e)}getActiveRequests(){return Array.from(this.activeRequests.values())}getRequestHistory(){return[...this.requestHistory]}getPendingDataSources(){return Array.from(this.pendingDataSources)}watchRequest(e){return this.requestWatchers.add(e),()=>{this.requestWatchers.delete(e)}}notifyRequestWatchers(e){this.requestWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Request watcher error:",r)}})}trackWebSocketConnection(e,a,r){this.config.enabled&&this.wsConnections.set(e,{id:e,url:a,state:r,connectedAt:r==="open"?Date.now():void 0})}trackWebSocketMessage(e,a,r,i){if(!this.config.enabled)return;const l={id:this.generateId(),connectionId:e,direction:a,type:r,payload:this.sanitizeObject(i),timestamp:Date.now(),sequence:this.wsMessageHistory.length};this.wsMessageHistory.push(l),this.wsMessageHistory.length>this.config.maxHistorySize&&this.wsMessageHistory.shift(),this.notifyWebSocketWatchers(l)}getWebSocketConnections(){return Array.from(this.wsConnections.values())}getWebSocketMessageHistory(){return[...this.wsMessageHistory]}getWebSocketConnectionState(){const e=Array.from(this.wsConnections.values());return e.some(a=>a.state==="open")?"connected":e.some(a=>a.state==="connecting")?"reconnecting":"disconnected"}watchWebSocketMessage(e){return this.wsMessageWatchers.add(e),()=>{this.wsMessageWatchers.delete(e)}}notifyWebSocketWatchers(e){this.wsMessageWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] WebSocket watcher error:",r)}})}trackIfCondition(e,a,r){if(!this.config.enabled)return;const i=this.ifConditions.get(e),l=i?.evaluatedValue;this.ifConditions.set(e,{id:e,expression:a,evaluatedValue:r,evaluationCount:(i?.evaluationCount||0)+1,lastEvaluated:Date.now()}),i&&l!==r&&this.notifyConditionWatchers({id:e,expression:a,oldValue:l,newValue:r,timestamp:Date.now()})}trackIteration(e,a){this.config.enabled&&this.iterations.set(e,{id:e,...a,lastRendered:Date.now()})}getIfConditions(){return Array.from(this.ifConditions.values())}getIterations(){return Array.from(this.iterations.values())}getScopeChain(e){const a=[],r=this.getState();return a.push({name:"_global",value:r._global,source:"global"}),a.push({name:"_local",value:r._local,source:"local"}),a.push({name:"_computed",value:r._computed,source:"computed"}),a}watchConditionChange(e){return this.conditionWatchers.add(e),()=>{this.conditionWatchers.delete(e)}}notifyConditionWatchers(e){this.conditionWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Condition watcher error:",r)}})}trackForm(e,a,r){this.config.enabled&&this.forms.set(e,{id:e,dataKey:a,inputs:r,trackedAt:Date.now()})}trackFormChange(e,a,r){if(!this.config.enabled)return;const i={formId:e,inputName:a,value:r,timestamp:Date.now()};this.notifyFormWatchers(i)}untrackForm(e){this.forms.delete(e)}getForms(){return Array.from(this.forms.values())}getFormState(e){const a=this.getState();return this.getNestedValue(a,e)||{}}getBindingPath(e,a){return`${e}.${a}`}watchFormChange(e){return this.formWatchers.add(e),()=>{this.formWatchers.delete(e)}}notifyFormWatchers(e){this.formWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Form watcher error:",r)}})}trackFormBindingIssue(e,a,r){if(!this.config.enabled)return;const i={id:`form-issue-${++this.formBindingIssueIdCounter}`,timestamp:Date.now(),type:e,severity:a,formId:r.formId,formDataKey:r.formDataKey,inputInfo:r.inputInfo,contextInfo:r.contextInfo,description:r.description,suggestion:r.suggestion,docLink:r.docLink};this.formBindingIssues.push(i),this.formBindingIssues.length>this.maxFormBindingIssues&&this.formBindingIssues.shift()}validateFormBinding(e,a,r,i){const l=r.map(f=>{const g=[];let m=!0;return f.name||(g.push("Input에 name 속성이 없습니다"),m=!1,this.trackFormBindingIssue("missing-input-name","error",{formId:e,formDataKey:a,inputInfo:{name:f.name,type:f.type},description:"Input에 name 속성이 없어 자동 바인딩이 동작하지 않습니다",suggestion:"Input에 name 속성을 추가하세요",docLink:"troubleshooting-components-form.md"})),a||(g.push("Form에 dataKey가 없습니다"),m=!1),{inputName:f.name||"(unnamed)",inputType:f.type,bindingPath:a&&f.name?`${a}.${f.name}`:"-",isValid:m,currentValue:f.value,issues:g}});if(a||this.trackFormBindingIssue("missing-datakey","error",{formId:e,description:"Form에 dataKey가 설정되지 않아 자동 바인딩이 동작하지 않습니다",suggestion:"Form 컴포넌트에 dataKey props를 설정하세요",docLink:"troubleshooting-components-form.md"}),i.isContextBroken){const f=i.breakReason?.includes("sortable")?"sortable-context-break":i.breakReason?.includes("modal")?"modal-context-isolation":"context-not-propagated";this.trackFormBindingIssue(f,"warning",{formId:e,formDataKey:a,contextInfo:{hasParentFormContext:i.hasParentContext,parentFormContextProp:i.parentContextProp,isInsideSortable:i.breakReason?.includes("sortable")||!1,isInsideModal:i.breakReason?.includes("modal")||!1,depth:0},description:i.breakReason||"Form 컨텍스트가 제대로 전파되지 않았습니다",suggestion:"parentFormContextProp={undefined}를 확인하거나 중첩 구조를 검토하세요",docLink:"troubleshooting-components-form.md"})}const u={formId:e,dataKey:a,timestamp:Date.now(),contextPropagation:i,inputBindings:l,isValid:l.every(f=>f.isValid)&&!!a&&!i.isContextBroken,issueCount:l.filter(f=>!f.isValid).length+(a?0:1)+(i.isContextBroken?1:0)},d=this.formBindingValidations.findIndex(f=>f.formId===e);return d>=0?this.formBindingValidations[d]=u:this.formBindingValidations.push(u),u}getFormBindingValidationTrackingInfo(){const e=this.getFormBindingValidationStats();return{issues:[...this.formBindingIssues],validations:[...this.formBindingValidations],stats:e,timestamp:Date.now()}}getFormBindingValidationStats(){const e={"missing-datakey":0,"missing-input-name":0,"context-not-propagated":0,"sortable-context-break":0,"modal-context-isolation":0,"duplicate-input-name":0,"value-type-mismatch":0,"binding-path-invalid":0},a={info:0,warning:0,error:0};for(const i of this.formBindingIssues)e[i.type]++,a[i.severity]++;const r=Object.entries(e).filter(([,i])=>i>0).sort((i,l)=>l[1]-i[1]).slice(0,5).map(([i,l])=>({type:i,count:l,description:this.getIssueTypeDescription(i)}));return{totalFormsValidated:this.formBindingValidations.length,validForms:this.formBindingValidations.filter(i=>i.isValid).length,formsWithIssues:this.formBindingValidations.filter(i=>!i.isValid).length,totalIssues:this.formBindingIssues.length,byIssueType:e,bySeverity:a,topIssues:r}}getIssueTypeDescription(e){return{"missing-datakey":"Form에 dataKey 누락","missing-input-name":"Input에 name 속성 누락","context-not-propagated":"Form 컨텍스트 전파 실패","sortable-context-break":"Sortable 컨테이너에서 컨텍스트 단절","modal-context-isolation":"모달에서 부모 Form 컨텍스트 격리","duplicate-input-name":"동일 Form 내 중복 Input name","value-type-mismatch":"값 타입과 Input 타입 불일치","binding-path-invalid":"바인딩 경로 유효하지 않음"}[e]||e}clearFormBindingIssues(){this.formBindingIssues=[],this.formBindingValidations=[],this.formBindingIssueIdCounter=0}trackComputedProperty(e,a,r,i,l,u,d){if(!this.config.enabled)return;const f=`computed-${e}-${u||"global"}`,g={id:f,name:e,expression:a,componentId:u,dependencies:r,currentValue:this.safeClone(i),lastComputedAt:Date.now(),computationTime:l,error:d};this.computedProperties.set(f,g)}trackComputedRecalc(e,a,r,i,l,u,d){if(!this.config.enabled)return;const f=`computed-${e}-${d||"global"}`,g=JSON.stringify(r)!==JSON.stringify(i),m={id:`recalc-${++this.computedRecalcIdCounter}`,computedId:f,computedName:e,timestamp:Date.now(),trigger:a,triggeredBy:u,previousValue:this.safeClone(r),newValue:this.safeClone(i),valueChanged:g,computationTime:l,cascadeCount:0};this.computedRecalcLogs.push(m),this.computedRecalcLogs.length>this.maxComputedRecalcLogs&&this.computedRecalcLogs.shift();const b=this.computedProperties.get(f);b&&(b.currentValue=this.safeClone(i),b.lastComputedAt=Date.now(),b.computationTime=l)}analyzeComputedDependencyChain(e,a){const r=new Set,i=[];let l=!1,u,d=0;const f=(m,b)=>{if(d=Math.max(d,b),r.has(m))return l=!0,u=[...i,m],{name:m,type:"computed",children:[],depth:b};r.add(m),i.push(m);const v=this.computedProperties.get(`computed-${m}-${a||"global"}`),S=[];if(v)for(const E of v.dependencies)E.type==="computed"?S.push(f(E.path,b+1)):S.push({name:E.path,type:E.type,children:[],depth:b+1});return i.pop(),r.delete(m),{name:m,type:"computed",children:S,depth:b}},g=f(e,0);return{root:e,tree:g,hasCycle:l,cyclePath:u,maxDepth:d}}getComputedDependencyTrackingInfo(){const e=Array.from(this.computedProperties.values()),a=this.getComputedDependencyStats(),r=[];for(const i of e){const l=this.analyzeComputedDependencyChain(i.name,i.componentId);r.push(l)}return{properties:e,recalcLogs:[...this.computedRecalcLogs],dependencyChains:r,stats:a,timestamp:Date.now()}}getComputedDependencyStats(){const e={"state-change":0,"datasource-update":0,"dependency-change":0,manual:0,initial:0},a={},r={};let i=0,l=0;for(const g of this.computedRecalcLogs)e[g.trigger]++,g.valueChanged||l++,a[g.computedName]=(a[g.computedName]||0)+1,r[g.computedName]||(r[g.computedName]=[]),r[g.computedName].push(g.computationTime),i+=g.computationTime;const u=Object.entries(a).sort((g,m)=>m[1]-g[1]).slice(0,5).map(([g,m])=>({name:g,count:m})),d=Object.entries(r).map(([g,m])=>({name:g,avgTime:m.reduce((b,v)=>b+v,0)/m.length})).sort((g,m)=>m.avgTime-g.avgTime).slice(0,5);let f=0;for(const g of this.computedProperties.values())this.analyzeComputedDependencyChain(g.name,g.componentId).hasCycle&&f++;return{totalComputed:this.computedProperties.size,totalRecalculations:this.computedRecalcLogs.length,unnecessaryRecalculations:l,avgComputationTime:this.computedRecalcLogs.length>0?i/this.computedRecalcLogs.length:0,topRecalculated:u,slowestComputed:d,cycleDetectionCount:f,byTrigger:e}}clearComputedTracking(){this.computedProperties.clear(),this.computedRecalcLogs=[],this.computedRecalcIdCounter=0}trackModalOpen(e){if(!this.config.enabled)return;const a={modalId:e.modalId,modalName:e.modalName,openedAt:Date.now(),closedAt:null,scopeType:e.scopeType||"isolated",parentModalId:e.parentModalId,componentId:e.componentId,initialState:e.initialState?{...e.initialState}:{},currentState:e.initialState?{...e.initialState}:{},stateChangeCount:0,isolatedStateKeys:e.isolatedStateKeys||[],sharedStateKeys:e.sharedStateKeys||[]};this.modalStates.set(e.modalId,a),this.validateModalDefinitionExists(e.modalId,e.modalName),e.parentModalId&&(this.modalStateRelations.find(i=>i.parentModalId===e.parentModalId&&i.childModalId===e.modalId)||this.modalStateRelations.push({parentModalId:e.parentModalId,childModalId:e.modalId,sharedKeys:e.sharedStateKeys||[],isolatedKeys:e.isolatedStateKeys||[],relationType:"parent-child"}))}trackModalClose(e,a){if(!this.config.enabled)return;const r=this.modalStates.get(e);r&&(r.closedAt=Date.now(),a&&(r.currentState={...a}),this.detectStateLeakage(r))}validateModalDefinitionExists(e,a){const r=this.currentLayout;if(!r?.layoutJson)return;const i=r.layoutJson.modals;if(!i){this.recordModalStateIssue({type:"missing-definition",modalId:e,modalName:a,severity:"error",description:`모달 "${e}"이(가) modalStack에 추가되었으나, 현재 레이아웃에 modals 섹션이 없습니다. 레이아웃 경로: ${r.layoutPath}`,affectedStateKeys:[],expectedValue:`modals 섹션에 id="${e}" 정의 존재`,actualValue:"modals 섹션 없음"});return}const l=Array.isArray(i)?i:Object.values(i);l.some(d=>d?.id===e||d?.props?.id===e)||this.recordModalStateIssue({type:"missing-definition",modalId:e,modalName:a,severity:"error",description:`모달 "${e}"이(가) modalStack에 추가되었으나, 렌더링된 레이아웃의 modals 섹션에 해당 ID의 정의가 없습니다. partial 로딩 실패, 레이아웃 병합 문제, extends 상속 누락 등을 확인하세요. 레이아웃 경로: ${r.layoutPath}`,affectedStateKeys:[],expectedValue:`modals 배열에 id="${e}" 항목 존재`,actualValue:`modals 배열에 ${l.length}개 모달 정의 (${l.map(d=>d?.id||"unknown").join(", ")})`})}trackModalStateChange(e){if(!this.config.enabled)return;const a=this.modalStates.get(e.modalId);if(!a)return;a.stateChangeCount++,a.currentState[e.stateKey]=e.newValue;const r=this.checkIsolationViolation(a,e.stateKey),i={id:`modal-change-${++this.modalStateChangeLogIdCounter}`,modalId:e.modalId,modalName:a.modalName,timestamp:Date.now(),stateKey:e.stateKey,previousValue:e.previousValue,newValue:e.newValue,changeSource:e.changeSource||"user-action",violatesIsolation:r};this.modalStateChangeLogs.push(i),this.modalStateChangeLogs.length>this.maxModalStateChangeLogs&&this.modalStateChangeLogs.shift(),r&&this.recordModalStateIssue({type:"isolation-violation",modalId:e.modalId,modalName:a.modalName,severity:"warning",description:`모달 '${a.modalName}'에서 격리된 상태 키 '${e.stateKey}'가 변경됨`,affectedStateKeys:[e.stateKey]})}detectStateLeakage(e){if(e.scopeType==="isolated")for(const a of e.isolatedStateKeys){const r=e.initialState[a],i=e.currentState[a];if(r!==i&&e.parentModalId){const l=this.modalStates.get(e.parentModalId);l&&l.currentState.hasOwnProperty(a)&&this.recordModalStateIssue({type:"state-leakage",modalId:e.modalId,modalName:e.modalName,severity:"error",description:`모달 닫힘 후 상태 '${a}'가 부모 모달로 유출될 수 있음`,affectedStateKeys:[a],leakedValue:i,expectedValue:r})}}}checkIsolationViolation(e,a){return e.scopeType==="isolated",!1}recordModalStateIssue(e){const a={id:`modal-issue-${++this.modalStateIssueIdCounter}`,type:e.type,modalId:e.modalId,modalName:e.modalName,timestamp:Date.now(),severity:e.severity,description:e.description,affectedStateKeys:e.affectedStateKeys,leakedValue:e.leakedValue,expectedValue:e.expectedValue,actualValue:e.actualValue,stackInfo:e.stackInfo};this.modalStateIssues.push(a),this.modalStateIssues.length>this.maxModalStateIssues&&this.modalStateIssues.shift()}getModalStateScopeTrackingInfo(){const e=Array.from(this.modalStates.values()),a=this.getModalStateScopeStats();return{modals:e,issues:[...this.modalStateIssues],relations:[...this.modalStateRelations],changeLogs:[...this.modalStateChangeLogs],stats:a,timestamp:Date.now()}}getModalStateScopeStats(){const e=Array.from(this.modalStates.values()),a={warning:0,error:0},r={"state-leakage":0,"isolation-violation":0,"parent-mutation":0,"orphaned-state":0,"scope-mismatch":0,"cleanup-failure":0,"missing-definition":0};for(const l of this.modalStateIssues)a[l.severity]++,r[l.type]++;const i={isolated:0,shared:0,inherited:0};for(const l of e)i[l.scopeType]++;return{totalModals:e.length,openModals:e.filter(l=>l.closedAt===null).length,nestedModals:e.filter(l=>l.parentModalId!==void 0).length,totalIssues:this.modalStateIssues.length,issuesBySeverity:a,issuesByType:r,byScope:i,leakageDetectionCount:r["state-leakage"],cleanupFailureCount:r["cleanup-failure"]}}clearModalStateScopeTracking(){this.modalStates.clear(),this.modalStateIssues=[],this.modalStateRelations=[],this.modalStateChangeLogs=[],this.modalStateIssueIdCounter=0,this.modalStateChangeLogIdCounter=0}setNamedActionDefinitions(e){this.config.enabled&&(this.namedActionDefinitions=e||{})}trackNamedActionRef(e){if(!this.config.enabled)return;const a={...e,id:`named_action_ref_${++this.namedActionRefIdCounter}`};this.namedActionRefLogs.push(a),this.namedActionRefLogs.length>this.maxNamedActionRefLogs&&(this.namedActionRefLogs=this.namedActionRefLogs.slice(-this.maxNamedActionRefLogs))}getNamedActionTrackingInfo(){const e={};for(const r of this.namedActionRefLogs)e[r.actionRefName]=(e[r.actionRefName]||0)+1;const a=Object.keys(this.namedActionDefinitions).filter(r=>!e[r]);return{definitions:this.namedActionDefinitions,refLogs:[...this.namedActionRefLogs],stats:{totalDefinitions:Object.keys(this.namedActionDefinitions).length,totalRefs:this.namedActionRefLogs.length,refCountByName:e,unusedDefinitions:a},timestamp:Date.now()}}clearNamedActionTracking(){this.namedActionDefinitions={},this.namedActionRefLogs=[],this.namedActionRefIdCounter=0}trackExpressionEval(e){if(!this.config.enabled)return;const a={...e,id:`expr-${++this.expressionIdCounter}`,timestamp:Date.now(),warning:this.detectExpressionWarning(e)};this.expressionHistory.push(a),this.expressionHistory.length>500&&this.expressionHistory.shift(),this.isProfiling&&this.profilingData.push({type:"binding",expression:e.expression,timestamp:performance.now(),duration:e.duration}),this.notifyExpressionWatchers(a)}detectExpressionWarning(e){const{expression:a,result:r,resultType:i,method:l,duration:u}=e;if(i==="undefined"&&!a.includes("??")&&!a.includes("||")&&/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(a.replace(/{{|}}/g,"").trim()))return{type:"undefined-result",message:"표현식 결과가 undefined입니다",suggestion:`데이터가 로드되었는지 확인하거나 fallback 값을 추가하세요: ${a} ?? ''`};if(i==="null")return{type:"null-result",message:"표현식 결과가 null입니다",suggestion:`nullish coalescing 연산자를 사용하세요: ${a} ?? ''`};if(l==="resolveBindings"&&i==="string"){const d=String(r);if(d.includes("[object Object]")||/^\[.*\]$/.test(d))return{type:"array-to-string",message:"배열/객체가 문자열로 변환되었습니다",suggestion:"evaluateExpression()을 사용하여 원본 타입을 유지하세요"}}if(l==="resolveBindings"&&i==="string"&&String(r).includes("[object Object]"))return{type:"object-to-string",message:"객체가 [object Object]로 변환되었습니다",suggestion:"evaluateExpression()을 사용하거나 특정 속성에 접근하세요"};if(i==="undefined"&&a.includes(".")&&!a.includes("?.")){const d=a.replace(/{{|}}/g,"").trim().split(".");if(d.length>=2)return{type:"missing-optional-chain",message:"Optional chaining(?.) 누락 가능성",suggestion:`안전한 접근을 위해 ?. 사용을 고려하세요: ${d.join("?.")}`}}if((a.includes("{{item.")||a.includes("{{index}}"))&&Array.from(this.iterations.values()).some(g=>g.itemVar!=="item"))return{type:"wrong-iteration-var",message:"'item'/'index' 대신 iteration에서 정의한 변수명을 사용해야 합니다",suggestion:"iteration의 item_var/index_var에 정의된 변수명을 확인하세요"};if(u&&u>10)return{type:"slow-evaluation",message:`표현식 평가에 ${u.toFixed(2)}ms 소요됨`,suggestion:"복잡한 표현식을 단순화하거나 computed 값으로 분리하세요"}}getExpressions(){return[...this.expressionHistory]}getExpressionWarnings(){return this.expressionHistory.filter(e=>e.warning!=null)}searchExpressions(e){const a=e.toLowerCase();return this.expressionHistory.filter(r=>r.expression.toLowerCase().includes(a)||r.componentName?.toLowerCase().includes(a)||r.propName?.toLowerCase().includes(a))}getExpressionStats(){const e=this.expressionHistory,a=new Set(e.map(f=>f.expression)),r=e.filter(f=>f.warning!=null),i=e.filter(f=>f.fromCache),l=e.filter(f=>f.duration!=null).map(f=>f.duration),u={};for(const f of e)u[f.resultType]=(u[f.resultType]||0)+1;const d={};for(const f of r)f.warning&&(d[f.warning.type]=(d[f.warning.type]||0)+1);return{totalEvaluations:e.length,uniqueExpressions:a.size,warningCount:r.length,cacheHitRate:e.length>0?i.length/e.length:0,averageDuration:l.length>0?l.reduce((f,g)=>f+g,0)/l.length:0,byType:u,byWarning:d}}clearExpressions(){this.expressionHistory=[],this.expressionIdCounter=0}watchExpressions(e){return this.expressionWatchers.add(e),()=>{this.expressionWatchers.delete(e)}}notifyExpressionWatchers(e){this.expressionWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Expression watcher error:",r)}})}setLogLevel(e){this.config.logLevel=e}setMaxHistory(e){this.config.maxHistorySize=Math.max(10,Math.min(1e3,e))}setServerEndpoint(e){this.config.serverEndpoint=e}getConfig(){return{...this.config}}generateId(){return`${Date.now()}-${Math.random().toString(36).substr(2,9)}`}sanitizeObject(e,a=new WeakSet){if(e===null||typeof e!="object")return e;if(a.has(e))return"[Circular]";if(a.add(e),Array.isArray(e))return e.map(i=>this.sanitizeObject(i,a));const r={};for(const i of Object.keys(e))try{r[i]=this.sanitizeObject(e[i],a)}catch{r[i]="[Unable to serialize]"}return r}getNestedValue(e,a){if(!a)return e;const r=a.split(".");let i=e;for(const l of r){if(i==null)return;i=i[l]}return i}getLifecycleInfo(){return{mountedComponents:Array.from(this.mountedComponents.values()),orphanedListeners:this.getOrphanedListeners()}}getPerformanceInfo(){return{renderCounts:this.renderCounts,bindingEvalCount:this.bindingEvalCount,memoryWarnings:this.getMemoryWarnings()}}getNetworkInfo(){return{activeRequests:Array.from(this.activeRequests.values()),requestHistory:[...this.requestHistory],pendingDataSources:Array.from(this.pendingDataSources)}}getConditionalInfo(){return{ifConditions:Array.from(this.ifConditions.values()),iterations:Array.from(this.iterations.values())}}getFormInfo(){return Array.from(this.forms.values())}getWebSocketInfo(){return{connections:Array.from(this.wsConnections.values()),messageHistory:[...this.wsMessageHistory],connectionState:this.getWebSocketConnectionState()}}getStateAtTime(e){const a=[...this.stateHistory].reverse().find(r=>r.timestamp<=e);if(a)return{_global:a.next,_local:{}}}reset(){this.stateHistory=[],this.actionHistory=[],this.cacheStats={hits:0,misses:0,entries:0},this.cacheDecisions=[],this.cacheDecisionIdCounter=0,this.currentRenderCycleId=null,this.isInActionExecution=!1,this.isInIteration=!1,this.mountedComponents.clear(),this.eventListeners.clear(),this.renderCounts.clear(),this.bindingEvalCount=0,this.profilingData=[],this.activeRequests.clear(),this.requestHistory=[],this.pendingDataSources.clear(),this.wsConnections.clear(),this.wsMessageHistory=[],this.ifConditions.clear(),this.iterations.clear(),this.forms.clear(),this.expressionHistory=[],this.expressionIdCounter=0,this.dataSources.clear(),this.dataPathTransforms=[],this.nestedContexts=[],this.nestedContextIdCounter=0,this.formBindingIssues=[],this.formBindingValidations=[],this.formBindingIssueIdCounter=0,this.computedProperties.clear(),this.computedRecalcLogs=[],this.computedRecalcIdCounter=0,this.modalStates.clear(),this.modalStateIssues=[],this.modalStateRelations=[],this.modalStateChangeLogs=[],this.modalStateIssueIdCounter=0,this.modalStateChangeLogIdCounter=0,this.logHistory=[],this.logIdCounter=0}getExpressionInfo(){return{expressions:this.getExpressions(),stats:this.getExpressionStats()}}trackLog(e,a,r){if(!this.config.enabled)return;const i=r.map(u=>{if(typeof u=="string")return u;try{return JSON.stringify(u)}catch{return String(u)}}).join(" "),l={id:`log-${++this.logIdCounter}`,level:e,prefix:a,message:i,args:this.sanitizeObject(r),timestamp:Date.now(),stack:e==="error"?new Error().stack:void 0};this.logHistory.push(l),this.logHistory.length>this.maxLogHistory&&this.logHistory.shift()}trackAction(e){if(!this.config.enabled)return;const a={id:`debounce-action-${++this.debounceActionIdCounter}`,...e,timestamp:Date.now()};this.debounceActionHistory.push(a),this.debounceActionHistory.length>100&&this.debounceActionHistory.shift()}trackDataSourceUpdate(e){if(!this.config.enabled)return;const a={id:`ds-update-${++this.dataSourceUpdateIdCounter}`,...e};this.dataSourceUpdateHistory.push(a),this.dataSourceUpdateHistory.length>100&&this.dataSourceUpdateHistory.shift()}getDebounceActionHistory(e){let a=[...this.debounceActionHistory];return e?.handler&&(a=a.filter(r=>r.handler.includes(e.handler))),e?.status&&(a=a.filter(r=>r.status===e.status)),e?.limit&&(a=a.slice(-e.limit)),a}getDataSourceUpdateHistory(e){let a=[...this.dataSourceUpdateHistory];return e?.dataSourceId&&(a=a.filter(r=>r.dataSourceId===e.dataSourceId)),e?.updateType&&(a=a.filter(r=>r.updateType===e.updateType)),e?.limit&&(a=a.slice(-e.limit)),a}getLogs(e){let a=[...this.logHistory];if(e?.level){const r=Array.isArray(e.level)?e.level:[e.level];a=a.filter(i=>r.includes(i.level))}if(e?.prefix){const r=e.prefix.toLowerCase();a=a.filter(i=>i.prefix.toLowerCase().includes(r))}if(e?.search){const r=e.search.toLowerCase();a=a.filter(i=>i.message.toLowerCase().includes(r))}return e?.since&&(a=a.filter(r=>r.timestamp>=e.since)),e?.limit&&(a=a.slice(-e.limit)),a}getLogStats(){const a=Date.now()-6e4,r={log:0,warn:0,error:0,debug:0,info:0},i={};let l=0,u=0;for(const d of this.logHistory)r[d.level]++,i[d.prefix]=(i[d.prefix]||0)+1,d.timestamp>=a&&(d.level==="error"&&l++,d.level==="warn"&&u++);return{totalLogs:this.logHistory.length,byLevel:r,byPrefix:i,recentErrors:l,recentWarnings:u}}clearLogs(){this.logHistory=[],this.logIdCounter=0}getLogInfo(){return{entries:this.getLogs(),stats:this.getLogStats()}}trackDataSourceDefinition(e){this.config.enabled&&this.dataSources.set(e.id,{...e,status:"idle"})}trackDataSourceLoading(e){if(!this.config.enabled)return;const a=this.dataSources.get(e);a&&this.dataSources.set(e,{...a,status:"loading"})}trackDataSourceLoaded(e,a,r){if(!this.config.enabled)return;const i=this.dataSources.get(e);if(!i)return;let l,u,d=r;a&&(Array.isArray(a)?(l=a.length,u=a.length>0&&typeof a[0]=="object"?Object.keys(a[0]):void 0):typeof a=="object"&&(Array.isArray(a.data)?(d=d||"data",l=a.data.length,u=a.data.length>0&&typeof a.data[0]=="object"?Object.keys(a.data[0]):void 0):Array.isArray(a.items)?(d=d||"items",l=a.items.length,u=a.items.length>0&&typeof a.items[0]=="object"?Object.keys(a.items[0]):void 0):u=Object.keys(a))),this.dataSources.set(e,{...i,status:"loaded",dataPath:d,itemCount:l,keys:u,lastLoadedAt:Date.now(),error:void 0})}trackDataSourceError(e,a){if(!this.config.enabled)return;const r=this.dataSources.get(e);r&&this.dataSources.set(e,{...r,status:"error",error:a,lastLoadedAt:Date.now()})}untrackDataSource(e){this.dataSources.delete(e)}getDataSources(){return Array.from(this.dataSources.values())}getDataSource(e){return this.dataSources.get(e)}clearDataSources(){this.dataSources.clear()}trackDataPathTransform(e){if(!this.config.enabled)return;let a=this.dataPathTransforms.find(r=>r.dataSourceId===e.dataSourceId);a||(a={dataSourceId:e.dataSourceId,timestamp:Date.now(),transformSteps:[],warnings:[]},this.dataPathTransforms.push(a),this.dataPathTransforms.length>this.maxDataPathTransforms&&this.dataPathTransforms.shift()),a.transformSteps.push({step:e.step,inputPath:e.inputPath,inputValue:this.safeClone(e.inputValue),outputPath:e.outputPath,outputValue:this.safeClone(e.outputValue),config:e.config}),e.warning&&a.warnings.push(e.warning)}setDataPathFinalBinding(e,a){if(!this.config.enabled)return;const r=this.dataPathTransforms.find(i=>i.dataSourceId===e);r&&(r.finalBinding={expression:a.expression,resolvedPath:a.resolvedPath,value:this.safeClone(a.value)})}getDataPathTransformTrackingInfo(){const e=this.getDataPathTransformStats();return{transforms:[...this.dataPathTransforms],stats:e,timestamp:Date.now()}}getDataPathTransformStats(){const e=this.dataPathTransforms,a={};let r=0;const i={};for(const u of e){a[u.dataSourceId]=(a[u.dataSourceId]||0)+1,r+=u.warnings.length;for(const d of u.warnings)i[d]=(i[d]||0)+1}const l=Object.entries(i).map(([u,d])=>({warning:u,count:d})).sort((u,d)=>d.count-u.count).slice(0,10);return{totalTransforms:e.length,byDataSource:a,warningsCount:r,commonWarnings:l}}getDataPathTransformForDataSource(e){return this.dataPathTransforms.find(a=>a.dataSourceId===e)}clearDataPathTransforms(){this.dataPathTransforms=[]}trackNestedContext(e){if(!this.config.enabled)return"";const a=`nested-${++this.nestedContextIdCounter}`,r=[...new Set([...e.parentContext.available,...e.ownContext.added])],i={...e.parentContext.values,...e.ownContext.values},l={id:a,timestamp:Date.now(),componentId:e.componentId,componentType:e.componentType,parentContext:{available:e.parentContext.available,values:this.safeClone(e.parentContext.values)},ownContext:{added:e.ownContext.added,values:this.safeClone(e.ownContext.values)},mergedContext:{all:r,values:this.safeClone(i)},accessAttempts:[],depth:e.depth,parentId:e.parentId};return this.nestedContexts.push(l),this.nestedContexts.length>this.maxNestedContexts&&this.nestedContexts.shift(),a}trackNestedContextAccess(e,a){if(!this.config.enabled)return;const r=this.nestedContexts.find(i=>i.id===e);r&&r.accessAttempts.push({path:a.path,found:a.found,value:a.found?this.safeClone(a.value):void 0,error:a.error})}getNestedContextTrackingInfo(){const e=this.getNestedContextStats();return{contexts:[...this.nestedContexts],stats:e,timestamp:Date.now()}}getNestedContextStats(){const e=this.nestedContexts,a={expandChildren:0,cellChildren:0,iteration:0,modal:0,slot:0};let r=0,i=0;const l={};for(const d of e){a[d.componentType]++,d.depth>r&&(r=d.depth);for(const f of d.accessAttempts)f.found||(i++,l[f.path]=(l[f.path]||0)+1)}const u=Object.entries(l).map(([d,f])=>({path:d,count:f})).sort((d,f)=>f.count-d.count).slice(0,10);return{totalContexts:e.length,byType:a,maxDepth:r,failedAccessCount:i,commonFailedPaths:u}}getNestedContextForComponent(e){return this.nestedContexts.find(a=>a.componentId===e)}clearNestedContexts(){this.nestedContexts=[],this.nestedContextIdCounter=0}trackHandlerRegistration(e,a="custom",r,i){this.isEnabled&&this.handlers.set(e,{name:e,category:a,description:r,registeredAt:Date.now(),source:i})}trackHandlerUnregistration(e){this.isEnabled&&this.handlers.delete(e)}getHandlers(){return Array.from(this.handlers.values())}getHandler(e){return this.handlers.get(e)}getHandlersByCategory(e){return Array.from(this.handlers.values()).filter(a=>a.category===e)}clearHandlers(){this.handlers.clear()}trackEventSubscribe(e){if(!this.isEnabled)return;const a=this.componentEventSubscriptions.get(e),r=Date.now();a?(a.subscriberCount++,a.lastSubscribedAt=r):this.componentEventSubscriptions.set(e,{eventName:e,subscriberCount:1,firstSubscribedAt:r,lastSubscribedAt:r})}trackEventUnsubscribe(e){if(!this.isEnabled)return;const a=this.componentEventSubscriptions.get(e);a&&(a.subscriberCount--,a.subscriberCount<=0&&this.componentEventSubscriptions.delete(e))}trackEventEmit(e,a,r,i,l){if(!this.isEnabled)return;const u={id:`evt_${++this.componentEventIdCounter}`,eventName:e,data:this.sanitizeForLogging(a),timestamp:Date.now(),listenerCount:r,results:i?this.sanitizeForLogging(i):void 0,hasError:!!l,errorMessage:l?.message};this.componentEventEmitHistory.push(u),this.componentEventEmitHistory.length>this.maxComponentEventHistory&&(this.componentEventEmitHistory=this.componentEventEmitHistory.slice(-this.maxComponentEventHistory))}trackEventOff(e){this.isEnabled&&this.componentEventSubscriptions.delete(e)}trackEventClear(){this.isEnabled&&this.componentEventSubscriptions.clear()}getComponentEventInfo(){const e=Array.from(this.componentEventSubscriptions.values());return{subscriptions:e,emitHistory:[...this.componentEventEmitHistory],totalSubscribers:e.reduce((a,r)=>a+r.subscriberCount,0),totalEmits:this.componentEventEmitHistory.length}}getEventEmitHistory(){return[...this.componentEventEmitHistory]}getEventSubscriptions(){return Array.from(this.componentEventSubscriptions.values())}clearComponentEvents(){this.componentEventSubscriptions.clear(),this.componentEventEmitHistory=[],this.componentEventIdCounter=0}sanitizeForLogging(e){if(e==null||typeof e!="object")return e;try{return JSON.parse(JSON.stringify(e))}catch{return"[Circular or Non-serializable]"}}startStateChange(e,a,r,i){if(!this.config.enabled)return"";const l=`setState_${++this.stateRenderingIdCounter}`;this.currentStateChangeContext={setStateId:l,startTime:performance.now(),changedPath:e,trigger:i||{},renderedComponents:[]};const u={id:`sr_${this.stateRenderingIdCounter}`,setStateId:l,statePath:e,oldValue:this.sanitizeForLogging(a),newValue:this.sanitizeForLogging(r),timestamp:Date.now(),triggeredBy:i||{},renderedComponents:[],totalRenderDuration:0,affectedBindingsCount:0};return this.stateRenderingLogs.push(u),this.stateRenderingLogs.length>this.maxStateRenderingLogs&&this.stateRenderingLogs.shift(),l}trackComponentRender(e,a,r,i=[],l=[],u){if(!this.config.enabled)return;const d=this.componentRenderCounts.get(a)||0;this.componentRenderCounts.set(a,d+1);for(const f of i)this.stateToComponentMap.has(f)||this.stateToComponentMap.set(f,new Set),this.stateToComponentMap.get(f).add(a);if(this.currentStateChangeContext){const f={componentId:e,componentName:a,renderDuration:r,accessedStatePaths:i,evaluatedBindings:l,renderOrder:this.currentStateChangeContext.renderedComponents.length,parentId:u};this.currentStateChangeContext.renderedComponents.push(f)}this.trackRender(a)}completeStateChange(e){if(!this.config.enabled||!this.currentStateChangeContext||this.currentStateChangeContext.setStateId!==e)return;const a=this.currentStateChangeContext,i=performance.now()-a.startTime,l=this.stateRenderingLogs.findIndex(u=>u.setStateId===e);if(l>=0){const u=this.stateRenderingLogs[l];u.renderedComponents=a.renderedComponents,u.totalRenderDuration=i,u.affectedBindingsCount=a.renderedComponents.reduce((d,f)=>d+f.evaluatedBindings.length,0)}this.currentStateChangeContext=null}getCurrentStateChangeContext(){return this.currentStateChangeContext}getStateRenderingLogs(){return[...this.stateRenderingLogs]}getStateRenderingInfo(){const e=this.stateRenderingLogs,a=Object.fromEntries(this.componentRenderCounts),r={};for(const[i,l]of this.stateToComponentMap)r[i]=Array.from(l);return{logs:e,componentRenderCounts:a,stateToComponentMap:r,stats:this.calculateStateRenderingStats()}}calculateStateRenderingStats(){const e=this.stateRenderingLogs;if(e.length===0)return{totalStateChanges:0,totalRenders:0,avgRenderDuration:0,avgComponentsPerChange:0,topRenderedComponents:[],topInfluentialPaths:[]};const a=e.reduce((d,f)=>d+f.renderedComponents.length,0),r=e.reduce((d,f)=>d+f.totalRenderDuration,0)/e.length,i=a/e.length,l=Array.from(this.componentRenderCounts.entries()).sort((d,f)=>f[1]-d[1]).slice(0,5).map(([d,f])=>({name:d,count:f})),u=Array.from(this.stateToComponentMap.entries()).sort((d,f)=>f[1].size-d[1].size).slice(0,5).map(([d,f])=>({path:d,affectedComponents:f.size}));return{totalStateChanges:e.length,totalRenders:a,avgRenderDuration:r,avgComponentsPerChange:i,topRenderedComponents:l,topInfluentialPaths:u}}getComponentsAffectedByState(e){const a=this.stateToComponentMap.get(e);return a?Array.from(a):[]}getComponentRenderHistory(e){return this.stateRenderingLogs.filter(a=>a.renderedComponents.some(r=>r.componentName===e))}clearStateRenderingLogs(){this.stateRenderingLogs=[],this.componentRenderCounts.clear(),this.stateToComponentMap.clear(),this.currentStateChangeContext=null,this.stateRenderingIdCounter=0}trackComponentStateSource(e,a,r,i){this.config.enabled&&this.componentStateSources.set(e,{componentId:e,componentName:a,stateSource:r,stateProvider:i})}trackDynamicState(e,a){this.config.enabled&&this.dynamicStates.set(e,a)}trackContextFlow(e,a,r,i,l,u){if(!this.config.enabled)return;const d={component:a,componentId:e,contextReceived:r,passedToChildren:i,usedInRender:l};if(this.contextFlowNodes.set(e,d),u){const f=this.contextFlowNodes.get(u);f&&(f.children||(f.children=[]),f.children.push(d))}}getStateHierarchyInfo(e=!0){const a=this.buildStateHierarchyLayers(),r=this.detectStateConflicts(a),i=Array.from(this.componentStateSources.values());return{layers:e?a.map(u=>({...u,values:this.summarizeValues(u.values,2)})):a,conflicts:r,componentStateSources:i,timestamp:Date.now()}}summarizeValues(e,a,r=0){if(e==null)return e;if(typeof e!="object")return typeof e=="string"&&e.length>100?e.substring(0,100)+`... (${e.length}자)`:e;if(r>=a){if(Array.isArray(e))return`[Array(${e.length})]`;const u=Object.keys(e);return`{${u.slice(0,5).join(", ")}${u.length>5?`, ... +${u.length-5}`:""}}`}if(Array.isArray(e))return e.length<=3?e.map(u=>this.summarizeValues(u,a,r+1)):{__type:"array",__length:e.length,__preview:e.slice(0,3).map(u=>this.summarizeValues(u,a,r+1))};const i={},l=Object.keys(e);for(const u of l)i[u]=this.summarizeValues(e[u],a,r+1);return i}buildStateHierarchyLayers(){const e=[];try{const r=window.G7Core?.state?.get?.();if(!r)return e;r._local&&e.push({name:"Global _local",type:"global",path:"_local",values:r._local,priority:1}),r._global&&e.push({name:"Global _global",type:"global",path:"_global",values:r._global,priority:1});for(const[l,u]of this.dynamicStates)u&&Object.keys(u).length>0&&e.push({name:`DynamicState (${l})`,type:"dynamicState",componentId:l,values:u,priority:2});const i=this.computeEffectiveState(r._local||{});e.push({name:"Effective _local (merged)",type:"effective",values:i,priority:3})}catch(a){console.warn("[G7DevTools] 상태 계층 빌드 실패:",a)}return e}computeEffectiveState(e){const a={...e};for(const[,r]of this.dynamicStates)r._local&&Object.assign(a,r._local);return a}detectStateConflicts(e){const a=[],r=e.find(l=>l.type==="global"&&l.path==="_local");if(!r)return a;const i=e.filter(l=>l.type==="dynamicState");for(const l of i){const u=l.values._local||l.values;for(const[d,f]of Object.entries(u)){const g=r.values[d];if(JSON.stringify(g)!==JSON.stringify(f)){const m=[],b=[];for(const v of this.componentStateSources.values())v.stateSource.local.some(E=>E===`_local.${d}`||E===d)&&(v.stateProvider.type==="dynamicState"?m.push(v.componentName):v.stateProvider.type==="globalState"&&b.push(v.componentName));a.push({path:`_local.${d}`,globalValue:g,dynamicStateValue:f,effectiveValue:f,usedBy:m,notUsedBy:b,severity:b.length>0?"warning":"info",description:b.length>0?`${b.join(", ")}은(는) globalState._local을 읽어 dynamicState 값을 사용하지 못함`:"dynamicState 값이 globalState와 다르지만 모든 컴포넌트가 dynamicState를 사용"})}}}return a}getContextFlowInfo(){const e=[],a=new Set(this.contextFlowNodes.keys());for(const r of this.contextFlowNodes.values())if(r.children)for(const i of r.children)a.delete(i.componentId);for(const r of a){const i=this.contextFlowNodes.get(r);i&&e.push(i)}return{rootComponent:e.length>0?e[0].component:"Unknown",contextFlow:e,timestamp:Date.now()}}clearStateHierarchyData(){this.componentStateSources.clear(),this.contextFlowNodes.clear(),this.dynamicStates.clear()}trackComponentStyle(e,a,r,i){if(!this.config.enabled)return;const l=this.analyzeTailwindClasses(r),u={componentId:e,componentName:a,classes:r,computedStyles:i,tailwindAnalysis:l};this.componentStyles.set(e,u),this.detectStyleIssues(u)}analyzeTailwindClasses(e){const a=[],r=[],i=[],l=[],u=["sm:","md:","lg:","xl:","2xl:"],d=[/bg-\w+-\d+/,/text-\w+-\d+/,/border-\w+-\d+/];for(const f of e){l.push(f),f.startsWith("dark:")&&a.push(f);for(const g of u)if(f.startsWith(g)){r.push(f);break}for(const g of d)if(g.test(f)){i.push(f);break}}return{usedClasses:l,darkClasses:a,responsiveClasses:r,dynamicClasses:i}}detectStyleIssues(e){const{componentId:a,componentName:r,computedStyles:i,tailwindAnalysis:l}=e;(i.opacity==="0"||i.visibility==="hidden"||i.display==="none"||i.width==="0px"&&i.height==="0px")&&this.addStyleIssue({id:this.generateId(),type:"invisible-element",componentId:a,componentName:r,property:i.opacity==="0"?"opacity":i.visibility==="hidden"?"visibility":i.display==="none"?"display":"width/height",currentValue:i.opacity==="0"?"0":i.visibility==="hidden"?"hidden":i.display==="none"?"none":"0px",severity:"warning",description:"요소가 화면에 보이지 않습니다.",suggestion:"opacity, visibility, display, width/height 값을 확인하세요."});const u=l.usedClasses.filter(f=>f.startsWith("bg-")&&!f.startsWith("dark:")),d=l.darkClasses.filter(f=>f.includes("bg-"));u.length>0&&d.length===0&&this.addStyleIssue({id:this.generateId(),type:"dark-mode-missing",componentId:a,componentName:r,property:"background-color",currentValue:u.join(", "),expectedValue:"dark:bg-* 클래스 필요",severity:"info",description:"다크 모드 배경색 클래스가 누락되었습니다.",suggestion:`${u[0]}에 대응하는 dark: 클래스를 추가하세요.`}),l.dynamicClasses.length>0&&this.addStyleIssue({id:this.generateId(),type:"tailwind-purging",componentId:a,componentName:r,property:"class",currentValue:l.dynamicClasses.join(", "),severity:"info",description:"동적으로 생성된 Tailwind 클래스가 있습니다.",suggestion:"tailwind.config.js의 safelist에 추가하거나 전체 클래스명을 상수로 정의하세요."})}addStyleIssue(e){this.styleIssues.some(r=>r.componentId===e.componentId&&r.type===e.type&&r.property===e.property)||this.styleIssues.push(e)}getStyleValidationInfo(){const e=Array.from(this.componentStyles.values());return{issues:[...this.styleIssues],componentStyles:e,stats:{totalComponents:e.length,invisibleCount:this.styleIssues.filter(a=>a.type==="invisible-element").length,tailwindIssueCount:this.styleIssues.filter(a=>a.type==="tailwind-purging").length,darkModeIssueCount:this.styleIssues.filter(a=>a.type==="dark-mode-missing").length},timestamp:Date.now()}}clearStyleValidationData(){this.styleIssues=[],this.componentStyles.clear()}trackAuthEvent(e,a,r,i){if(!this.config.enabled)return;const l={id:`auth_${++this.authEventIdCounter}`,type:e,timestamp:Date.now(),success:a,error:r,details:i};this.authEvents.push(l),this.authEvents.length>this.maxAuthEventHistory&&(this.authEvents=this.authEvents.slice(-this.maxAuthEventHistory))}trackAuthHeader(e,a,r,i,l){if(!this.config.enabled)return;const u={url:e,hasAuthHeader:a,headerType:r,tokenValid:i??!1,responseStatus:l,timestamp:Date.now()};this.authHeaderHistory.push(u),this.authHeaderHistory.length>this.maxAuthEventHistory&&(this.authHeaderHistory=this.authHeaderHistory.slice(-this.maxAuthEventHistory)),l===401&&this.trackAuthEvent("api-unauthorized",!1,`401 Unauthorized: ${e}`,{url:e})}getAuthState(){try{const e=window.G7Core,a=e?.api;let r=e?.auth;!r&&e?.AuthManager?.getInstance&&(r=e.AuthManager.getInstance());const i=a?.getToken?.()||r?.getAccessToken?.()||localStorage.getItem("auth_token")||localStorage.getItem("access_token"),l=r?.getRefreshToken?.()||localStorage.getItem("refresh_token");let u="unknown",d=r?.getUser?.();if(d&&(u="AuthManager"),!d){const S=e?.state?.get?.();d=S?._global?.user||S?._global?.currentUser||S?.user||S?.currentUser,d&&(u="G7Core.state")}const f=r?.isAuthenticated?.()??!1;let g="memory";localStorage.getItem("auth_token")||localStorage.getItem("access_token")?g="localStorage":(sessionStorage.getItem("auth_token")||sessionStorage.getItem("access_token"))&&(g="sessionStorage");const m=!!i&&(!!d||f);let b;i&&typeof i=="string"&&i.length>20?b=`${i.substring(0,10)}...${i.substring(i.length-6)}`:i&&(b="***");const v=d?{id:d.id,email:d.email,name:d.name,roles:d.roles?.map(S=>typeof S=="string"?{name:S}:{id:S.id,name:S.name,guard_name:S.guard_name}),permissions:d.permissions?.map(S=>typeof S=="string"?{name:S}:{id:S.id,name:S.name,guard_name:S.guard_name}),avatar:d.avatar||d.profile_photo_url||d.profile_image,created_at:d.created_at,updated_at:d.updated_at,last_login_at:d.last_login_at,email_verified_at:d.email_verified_at,...d.phone&&{phone:d.phone},...d.nickname&&{nickname:d.nickname},...d.status&&{status:d.status},...d.locale&&{locale:d.locale}}:void 0;return{isAuthenticated:m,user:v,tokens:{hasAccessToken:!!i,hasRefreshToken:!!l,storage:g,accessTokenPreview:b},lastActivity:Date.now(),source:u}}catch{return{isAuthenticated:!1,tokens:{hasAccessToken:!1,hasRefreshToken:!1,storage:"memory"},source:"unknown"}}}getAuthDebugInfo(){const e=[...this.authEvents];return{state:this.getAuthState(),events:e,headerAnalysis:[...this.authHeaderHistory],stats:{loginAttempts:e.filter(a=>a.type==="login").length,successfulLogins:e.filter(a=>a.type==="login"&&a.success).length,failedLogins:e.filter(a=>a.type==="login"&&!a.success).length,tokenRefreshes:e.filter(a=>a.type==="token-refresh").length,unauthorizedResponses:e.filter(a=>a.type==="api-unauthorized").length},timestamp:Date.now()}}clearAuthData(){this.authEvents=[],this.authHeaderHistory=[],this.authEventIdCounter=0}trackLayoutLoad(e,a,r,i="api"){if(!this.config.enabled)return;const l=Date.now();this.currentLayout={layoutPath:e,templateId:a,layoutJson:this.sanitizeObject(r),loadedAt:l,version:r.version,layoutName:r.layout_name,source:i};const u={id:`layout-${++this.layoutIdCounter}`,layoutPath:e,templateId:a,loadedAt:l,source:i,version:r.version};this.layoutHistory.push(u),this.layoutHistory.length>this.maxLayoutHistory&&this.layoutHistory.shift(),this.layoutStats.totalLoads++,i==="cache"?this.layoutStats.cacheHits++:this.layoutStats.apiLoads++}getCurrentLayout(){return this.currentLayout}getLayoutHistory(){return[...this.layoutHistory]}getLayoutDebugInfo(){return{current:this.currentLayout,history:[...this.layoutHistory],stats:{...this.layoutStats}}}clearLayoutData(){this.currentLayout=null,this.layoutHistory=[],this.layoutIdCounter=0,this.layoutStats={totalLoads:0,cacheHits:0,apiLoads:0}}startHandlerExecution(e){if(!this.config.enabled)return"";const a=`exec_${++this.executionIdCounter}_${Date.now()}`,r={handlerName:e,executionId:a,startTime:Date.now(),stateChanges:[],dataSourceChanges:[],alerts:[]};if(this.executionDetails.set(a,r),this.executionDetails.size>this.maxExecutionDetails){const i=Array.from(this.executionDetails.keys());i.slice(0,i.length-this.maxExecutionDetails).forEach(u=>this.executionDetails.delete(u))}return a}endHandlerExecution(e,a,r,i){if(!this.config.enabled||!e)return;const l=this.executionDetails.get(e);if(!l)return;l.endTime=Date.now(),l.duration=l.endTime-l.startTime,l.exitReason=a,l.exitLocation=r,l.exitDescription=i;const u=this.changeExpectations.get(e);u&&(l.expectedChanges=u,this.checkExpectations(e,l,u),this.changeExpectations.delete(e)),a==="normal"&&l.stateChanges.length===0&&l.dataSourceChanges.length===0&&this.addChangeAlert(e,{type:"no-state-change",severity:"warning",message:`핸들러 "${l.handlerName}"이(가) 상태 변경 없이 완료됨`,description:"핸들러가 성공적으로 완료되었지만 상태나 데이터소스 변경이 없습니다. 의도한 동작인지 확인하세요.",handlerName:l.handlerName,suggestion:'핸들러 내부 조건문을 확인하거나 DevTools의 "변경감지" 탭에서 exitLocation을 확인하세요.',docLink:"troubleshooting-state.md"}),(a==="early-return-condition"||a==="early-return-validation")&&this.addChangeAlert(e,{type:"early-return-detected",severity:"info",message:`핸들러 "${l.handlerName}"이(가) early return으로 종료됨`,description:i||`종료 위치: ${r||"알 수 없음"}`,handlerName:l.handlerName,suggestion:a==="early-return-validation"?"검증 실패로 인한 early return입니다. 입력 데이터를 확인하세요.":"조건부 early return입니다. 조건문의 평가 결과를 확인하세요."})}recordExitReason(e,a,r,i){if(!this.config.enabled||!e)return;const l=this.executionDetails.get(e);l&&(l.exitReason=a,l.exitLocation=r,l.exitDescription=i)}recordStateChange(e,a,r,i,l){if(!this.config.enabled)return;const u={id:`sc_${++this.stateChangeIdCounter}`,path:a,changeType:r,oldValue:this.safeClone(i),newValue:this.safeClone(l),timestamp:Date.now(),comparison:this.compareValues(i,l),executionId:e};if(this.stateChangeHistory.push(u),e){const d=this.executionDetails.get(e);d&&d.stateChanges.push(u)}this.stateChangeHistory.length>this.maxStateChangeHistory&&this.stateChangeHistory.splice(0,this.stateChangeHistory.length-this.maxStateChangeHistory),u.comparison.isDeepEqual&&typeof i=="object"&&i!==null&&this.addChangeAlert(e||"",{type:"object-reference-same",severity:"warning",message:`상태 "${a}"가 변경되었으나 값이 동일함`,description:"객체 참조가 동일하거나 깊은 비교 결과 변경이 없습니다. 변경 감지가 실패할 수 있습니다.",handlerName:e&&this.executionDetails.get(e)?.handlerName||"unknown",statePath:a,suggestion:"불변성을 유지하여 새 객체를 생성하세요. 예: { ...oldObject, newField: value }",docLink:"troubleshooting-state.md#object-mutation"})}recordDataSourceChange(e,a,r,i,l){if(!this.config.enabled)return;const u={dataSourceId:a,changeType:r,timestamp:Date.now(),previousStatus:i,newStatus:l,executionId:e};if(this.dataSourceChangeHistory.push(u),e){const d=this.executionDetails.get(e);d&&d.dataSourceChanges.push(u)}this.dataSourceChangeHistory.length>this.maxStateChangeHistory&&this.dataSourceChangeHistory.splice(0,this.dataSourceChangeHistory.length-this.maxStateChangeHistory)}expectChange(e,a,r){if(!this.config.enabled||!e)return;const i=this.executionDetails.get(e);if(!i)return;const l={expectedStatePaths:a,expectedDataSources:r,setAt:Date.now(),source:i.handlerName};this.changeExpectations.set(e,l)}checkExpectations(e,a,r){const i=new Set(a.stateChanges.map(u=>u.path)),l=new Set(a.dataSourceChanges.map(u=>u.dataSourceId));for(const u of r.expectedStatePaths)i.has(u)||this.addChangeAlert(e,{type:"expected-not-fulfilled",severity:"error",message:`기대한 상태 변경 "${u}"가 발생하지 않음`,description:`핸들러 "${a.handlerName}"이(가) "${u}" 변경을 예고했지만 실제로 변경되지 않았습니다.`,handlerName:a.handlerName,statePath:u,suggestion:"핸들러 내부 로직을 확인하세요. early return이나 조건부 분기로 인해 변경이 생략되었을 수 있습니다.",docLink:"troubleshooting-state.md"});for(const u of r.expectedDataSources)l.has(u)||this.addChangeAlert(e,{type:"expected-not-fulfilled",severity:"error",message:`기대한 데이터소스 갱신 "${u}"가 발생하지 않음`,description:`핸들러 "${a.handlerName}"이(가) "${u}" 갱신을 예고했지만 실제로 갱신되지 않았습니다.`,handlerName:a.handlerName,dataSourceId:u,suggestion:"refetchDataSource 호출이 실행되었는지 확인하세요.",docLink:"data-sources.md"})}addChangeAlert(e,a){const r={...a,id:`alert_${++this.alertIdCounter}`,timestamp:Date.now()};if(this.changeAlerts.push(r),e){const i=this.executionDetails.get(e);i&&i.alerts.push(r)}this.changeAlerts.length>this.maxChangeAlerts&&this.changeAlerts.splice(0,this.changeAlerts.length-this.maxChangeAlerts)}compareValues(e,a){const r=this.getValueType(e),i=this.getValueType(a),l=r!==i;let u=!1,d;return!l&&(r==="object"||r==="array")?(u=this.deepEqual(e,a),!u&&r==="object"&&(d=this.getChangedKeys(e,a))):u=e===a,{typeChanged:l,oldType:r,newType:i,isDeepEqual:u,changedKeys:d}}getValueType(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}deepEqual(e,a){if(e===a)return!0;if(typeof e!=typeof a)return!1;if(e===null||a===null||typeof e!="object")return e===a;if(Array.isArray(e)!==Array.isArray(a))return!1;const r=Object.keys(e),i=Object.keys(a);if(r.length!==i.length)return!1;for(const l of r)if(!i.includes(l)||!this.deepEqual(e[l],a[l]))return!1;return!0}getChangedKeys(e,a){const r=[],i=new Set([...Object.keys(e),...Object.keys(a)]);for(const l of i)this.deepEqual(e[l],a[l])||r.push(l);return r}getChangeDetectionInfo(){const e=Array.from(this.executionDetails.values()),a={totalExecutions:e.length,executionsWithStateChange:e.filter(r=>r.stateChanges.length>0).length,executionsWithoutStateChange:e.filter(r=>r.stateChanges.length===0&&r.exitReason==="normal").length,earlyReturnCount:e.filter(r=>r.exitReason==="early-return-condition"||r.exitReason==="early-return-validation").length,alertCount:this.changeAlerts.length,alertsByType:this.getAlertsByType()};return{executionDetails:e,stateChangeHistory:[...this.stateChangeHistory],dataSourceChangeHistory:[...this.dataSourceChangeHistory],alerts:[...this.changeAlerts],stats:a,timestamp:Date.now()}}getAlertsByType(){const e={"no-state-change":0,"no-datasource-change":0,"expected-not-fulfilled":0,"object-reference-same":0,"early-return-detected":0,"async-timing-issue":0};for(const a of this.changeAlerts)e[a.type]++;return e}clearChangeDetectionData(){this.executionDetails.clear(),this.stateChangeHistory=[],this.dataSourceChangeHistory=[],this.changeAlerts=[],this.changeExpectations.clear(),this.executionIdCounter=0,this.stateChangeIdCounter=0,this.alertIdCounter=0}getRecentAlerts(e=10,a){let r=[...this.changeAlerts];return a&&(r=r.filter(i=>i.severity===a)),r.slice(-e)}getHandlerExecutions(e,a=10){return Array.from(this.executionDetails.values()).filter(i=>i.handlerName===e).slice(-a)}findExecutionInStack(e){return this.sequenceExecutionStack.find(a=>a.sequenceId===e)}startSequenceExecution(e){if(!this.config.enabled)return"";const a=`seq_${++this.sequenceIdCounter}_${Date.now()}`,r={sequenceId:a,startTime:Date.now(),totalDuration:0,trigger:e,actions:[],status:"running"};return this.sequenceExecutionStack.push(r),a}captureSequenceActionBefore(e,a,r,i,l){if(!this.config.enabled)return;const u=this.findExecutionInStack(e);if(!u)return;const d={index:a,handler:r,params:this.safeClone(i),stateBeforeAction:{_global:this.safeClone(l._global),_local:this.safeClone(l._local),_isolated:l._isolated?this.safeClone(l._isolated):void 0},stateAfterAction:{_global:{},_local:{}},duration:0,status:"success"};u.actions.push(d)}captureSequenceActionAfter(e,a,r,i,l,u){if(!this.config.enabled)return;const d=this.findExecutionInStack(e);if(!d)return;const f=d.actions.find(m=>m.index===a);if(!f)return;f.stateAfterAction={_global:this.safeClone(r._global),_local:this.safeClone(r._local),_isolated:r._isolated?this.safeClone(r._isolated):void 0},f.duration=i,f.result=this.safeClone(l),f.stateDiff={global:this.computeStateDiff(f.stateBeforeAction._global,f.stateAfterAction._global),local:this.computeStateDiff(f.stateBeforeAction._local,f.stateAfterAction._local)},f.stateBeforeAction._isolated&&f.stateAfterAction._isolated&&(f.stateDiff.isolated=this.computeStateDiff(f.stateBeforeAction._isolated,f.stateAfterAction._isolated));const g=window.__g7PendingLocalState;g&&(f.pendingState=this.safeClone(g)),u&&(f.status="error",f.error={name:u.name,message:u.message,stack:u.stack})}endSequenceExecution(e,a){if(!this.config.enabled)return;const r=this.sequenceExecutionStack.findIndex(l=>l.sequenceId===e);if(r===-1)return;const i=this.sequenceExecutionStack[r];if(i.endTime=Date.now(),i.totalDuration=i.endTime-i.startTime,a){i.status="error",i.error={name:a.name,message:a.message,stack:a.stack};const l=i.actions.find(u=>u.status==="error");l&&(i.failedAtIndex=l.index)}else i.status="success";this.sequenceExecutions.push(i),this.sequenceExecutions.length>this.maxSequenceExecutions&&this.sequenceExecutions.shift(),this.sequenceExecutionStack.splice(r,1)}computeStateDiff(e,a){const r=[],i=[],l=[],u=new Set(Object.keys(e)),d=new Set(Object.keys(a));for(const f of d)u.has(f)||r.push(f);for(const f of u)d.has(f)||i.push(f);for(const f of u)if(d.has(f)){const g=e[f],m=a[f];JSON.stringify(g)!==JSON.stringify(m)&&l.push({path:f,oldValue:g,newValue:m})}return{added:r,removed:i,changed:l}}getSequenceTrackingInfo(){const e=this.getSequenceStats(),a=this.sequenceExecutionStack.length>0?this.sequenceExecutionStack[this.sequenceExecutionStack.length-1]:void 0;return{executions:[...this.sequenceExecutions],currentExecution:a,stats:e}}getSequenceStats(){const e=this.sequenceExecutions,a=e.length,r=e.filter(g=>g.status==="success").length,i=e.filter(g=>g.status==="error").length,l=e.reduce((g,m)=>g+m.actions.length,0),u=a>0?e.reduce((g,m)=>g+m.totalDuration,0)/a:0,d={};for(const g of e)for(const m of g.actions)d[m.handler]=(d[m.handler]||0)+1;const f=Object.entries(d).sort(([,g],[,m])=>m-g).slice(0,5).map(([g,m])=>({handler:g,count:m}));return{totalExecutions:a,successCount:r,errorCount:i,totalActions:l,avgDuration:u,topHandlers:f}}clearSequenceData(){this.sequenceExecutions=[],this.sequenceExecutionStack=[],this.sequenceIdCounter=0}getSequenceExecution(e){const a=this.findExecutionInStack(e);return a||this.sequenceExecutions.find(r=>r.sequenceId===e)}getRecentSequences(e=10){return this.sequenceExecutions.slice(-e)}registerStateCaptureForHandler(e,a,r){if(!this.config.enabled)return;const i=new Map,l=Date.now();for(const u of a)i.set(u,{value:this.safeClone(r[u]),capturedAt:l});this.stateCaptureRegistry.set(e,i)}detectStaleClosure(e,a,r,i,l){if(!this.config.enabled)return[];const u=this.stateCaptureRegistry.get(e);if(!u)return[];const d=Date.now(),f=[];for(const[g,m]of u){const b=this.getValueByPath(r,g),v=d-m.capturedAt;if(!this.isDeepEqual(m.value,b)&&v>0){const S=this.createStaleClosureWarning(i,a,g,m.value,m.capturedAt,b,d,v,l);f.push(S),this.addStaleClosureWarning(S)}}return this.stateCaptureRegistry.delete(e),f}trackStaleClosureWarning(e){if(!this.config.enabled)return;const a=Date.now(),r=this.createStaleClosureWarning(e.type,e.location,e.capturedPath,e.capturedValue,e.capturedAt,e.currentValue,a,a-e.capturedAt,e.actionId,e.stackTrace);this.addStaleClosureWarning(r)}createStaleClosureWarning(e,a,r,i,l,u,d,f,g,m){const b=this.getStaleClosureSeverity(e,f),{description:v,suggestion:S,docLink:E}=this.getStaleClosureMessages(e,r,f);return{id:`stale_${++this.staleClosureIdCounter}_${Date.now()}`,timestamp:Date.now(),type:e,location:a,capturedState:{path:r,capturedValue:this.safeClone(i),capturedAt:l},currentState:{path:r,currentValue:this.safeClone(u),retrievedAt:d},timeDiff:f,severity:b,description:v,suggestion:S,docLink:E,actionId:g,stackTrace:m}}getStaleClosureSeverity(e,a){if(a>5e3)return"error";if(a>1e3)return"warning";switch(e){case"async-state-capture":case"sequence-state-mismatch":return"warning";case"callback-state-capture":case"timeout-state-capture":return"info";case"event-handler-stale":return"warning";default:return"info"}}getStaleClosureMessages(e,a,r){const i=r<1e3?`${r}ms`:`${(r/1e3).toFixed(1)}s`;switch(e){case"async-state-capture":return{description:`await 후 ${i} 경과 시점에 '${a}' 상태가 변경됨. 캡처된 상태 대신 최신 상태를 사용해야 함`,suggestion:"await 이후에는 G7Core.state.get()으로 최신 상태를 다시 조회하거나, useRef + getter 패턴을 사용하세요",docLink:"troubleshooting-state-closure.md"};case"callback-state-capture":return{description:`콜백에서 ${i} 전에 캡처된 '${a}' 상태를 사용 중. 최신 상태와 다름`,suggestion:"콜백에서 상태를 참조할 때는 stateRef.current 패턴 또는 G7Core.state.get()를 사용하세요",docLink:"troubleshooting-state-closure.md"};case"timeout-state-capture":return{description:`setTimeout/setInterval 콜백에서 '${a}' 상태가 ${i} 전 값 사용 중`,suggestion:"타이머 콜백 내에서는 G7Core.state.get()으로 최신 상태를 조회하세요",docLink:"troubleshooting-state-closure.md"};case"sequence-state-mismatch":return{description:`sequence 내 '${a}' 상태가 이전 액션 결과와 불일치. context.state 대신 캡처된 값 사용 의심`,suggestion:"sequence 내에서는 context.state 또는 $prev를 사용하여 최신 상태를 참조하세요",docLink:"troubleshooting-state-setstate.md"};case"event-handler-stale":return{description:`이벤트 핸들러에서 ${i} 전에 바인딩된 '${a}' 상태 사용 중`,suggestion:"이벤트 핸들러에서 상태를 참조할 때는 useRef 패턴 또는 G7Core.state.get()를 사용하세요",docLink:"troubleshooting-state-closure.md"};default:return{description:`'${a}' 상태에서 stale closure 감지됨 (${i} 경과)`,suggestion:"상태 참조 시 최신 값을 사용하는지 확인하세요"}}}addStaleClosureWarning(e){this.staleClosureWarnings.push(e),this.staleClosureWarnings.length>this.maxStaleClosureWarnings&&this.staleClosureWarnings.shift()}getValueByPath(e,a){const r=a.split(".");let i=e;for(const l of r){if(i==null)return;i=i[l]}return i}isDeepEqual(e,a){if(e===a)return!0;if(e===null||a===null)return e===a;if(typeof e!=typeof a)return!1;if(typeof e!="object")return e===a;try{return JSON.stringify(e)===JSON.stringify(a)}catch{return!1}}getStaleClosureTrackingInfo(){const e=this.getStaleClosureStats();return{warnings:[...this.staleClosureWarnings],stats:e,timestamp:Date.now()}}getStaleClosureStats(){const e=this.staleClosureWarnings,a={"async-state-capture":0,"callback-state-capture":0,"timeout-state-capture":0,"sequence-state-mismatch":0,"event-handler-stale":0};for(const f of e)a[f.type]++;const r={info:0,warning:0,error:0};for(const f of e)r[f.severity]++;const i={};for(const f of e)i[f.location]=(i[f.location]||0)+1;const l=Object.entries(i).sort(([,f],[,g])=>g-f).slice(0,5).map(([f,g])=>({location:f,count:g})),u={};for(const f of e)u[f.capturedState.path]=(u[f.capturedState.path]||0)+1;const d=Object.entries(u).sort(([,f],[,g])=>g-f).slice(0,5).map(([f,g])=>({path:f,count:g}));return{totalWarnings:e.length,warningsByType:a,warningsBySeverity:r,topLocations:l,topAffectedPaths:d}}clearStaleClosureData(){this.staleClosureWarnings=[],this.staleClosureIdCounter=0,this.stateCaptureRegistry.clear()}getRecentStaleClosureWarnings(e=10,a){let r=[...this.staleClosureWarnings];return a&&(r=r.filter(i=>i.severity===a)),r.slice(-e)}safeClone(e){if(e==null||typeof e!="object")return e;try{return JSON.parse(JSON.stringify(e))}catch{if(Array.isArray(e))return e.map(r=>{try{return JSON.parse(JSON.stringify(r))}catch{return"[Unserializable]"}});const a={};for(const r of Object.keys(e))try{a[r]=JSON.parse(JSON.stringify(e[r]))}catch{a[r]="[Unserializable]"}return a}}};$(mi,"instance");let Tr=mi;const Bn=ct("LayoutLoader");class ba extends Error{constructor(a,r,i){super(a);$(this,"code");$(this,"details");this.code=r,this.details=i,this.name="LayoutLoaderError"}}class ef{constructor(e){$(this,"componentRegistry");$(this,"currentLayout",null);$(this,"layoutCache",new Map);$(this,"cacheVersion",0);this.componentRegistry=e}setCacheVersion(e){this.cacheVersion!==e&&(Bn.log("Cache version updated:",this.cacheVersion,"->",e),this.cacheVersion=e,this.layoutCache.clear())}getCacheVersion(){return this.cacheVersion}async loadLayout(e,a){const r=`${e}:${a}`;if(this.layoutCache.has(r)){Bn.log("Loading layout from cache:",a);const l=await this.layoutCache.get(r),u=JSON.parse(JSON.stringify(l));return this.currentLayout=u,Tr.getInstance().trackLayoutLoad(a,e,u,"cache"),u}const i=this.fetchLayout(e,a);return this.layoutCache.set(r,i),i.catch(()=>{this.layoutCache.get(r)===i&&this.layoutCache.delete(r)}),i}async fetchLayout(e,a,r=!1){try{const i=this.cacheVersion>0?this.cacheVersion:null;let l;if(a.startsWith("__preview__/")){const v=a.replace("__preview__/","");l=La(`/api/layouts/preview/${v}`,"json",i)}else l=La(`/api/layouts/${e}/${a}`,"json",i);Bn.log("Fetching layout from API:",l);const u=$a(),d=r?null:u.getToken(),f={Accept:"application/json"};d&&(f.Authorization=`Bearer ${d}`);const g=await Al(l,{init:{headers:f},label:`layout: ${a}`});let m;try{m=await g.json()}catch{m=null}if(!g.ok){if(g.status===401&&!r&&d){Bn.log("Token invalid, removing and retrying without token"),u.removeToken();try{return await this.fetchLayout(e,a,!0)}catch(S){throw S instanceof ba&&S.details?.status===401?new ba(S.message,S.code,{...S.details,hadToken:!0}):S}}const v=m?.message||m?.error;throw new ba(`Failed to fetch layout: ${g.status} ${g.statusText}`,"FETCH_FAILED",{status:g.status,statusText:g.statusText,url:l,apiMessage:v})}const b=m.data||m;return this.validateLayoutData(b),this.currentLayout=b,Tr.getInstance().trackLayoutLoad(a,e,b,"api"),Bn.log("Layout fetched and cached successfully:",b.layout_name),b}catch(i){const l=`${e}:${a}`;throw this.layoutCache.delete(l),i instanceof ba?i:new ba("Failed to load layout","LOAD_FAILED",{originalError:i})}}prefetchLayout(e,a){return this.loadLayout(e,a)}validateLayoutData(e){if(!e.version)throw new ba("Layout data missing required field: version","VALIDATION_FAILED",{field:"version"});if(!e.layout_name)throw new ba("Layout data missing required field: layout_name","VALIDATION_FAILED",{field:"layout_name"});if(!Array.isArray(e.components))throw new ba('Layout data field "components" must be an array',"VALIDATION_FAILED",{field:"components",value:e.components});Bn.log("Layout data validation passed")}renderLayout(e,a){try{const r=a||this.currentLayout;if(!r)throw new ba("No layout data to render","NO_LAYOUT_DATA");Bn.log("Rendering layout:",r.layout_name),e.innerHTML="",this.renderComponents(e,r.components),Bn.log("Layout rendered successfully")}catch(r){Bn.error("Render error:",r),this.renderErrorState(e,r)}}renderComponents(e,a){for(const r of a){const i=this.renderComponent(r);i&&e.appendChild(i)}}renderComponent(e){try{if(!this.componentRegistry.getComponent(e.type))return Bn.warn(`Component not found: ${e.type}`),this.createPlaceholderElement(e.type);const r=document.createElement("div");return r.setAttribute("data-component",e.type),e.props&&Object.entries(e.props).forEach(([i,l])=>{r.setAttribute(`data-prop-${i}`,JSON.stringify(l))}),e.children&&e.children.length>0?this.renderComponents(r,e.children):e.text&&(r.textContent=e.text),r}catch(a){return Bn.error(`Error rendering component ${e.type}:`,a),this.createErrorElement(e.type,a)}}createPlaceholderElement(e){const a=document.createElement("div");return a.className="component-placeholder",a.setAttribute("data-component-type",e),a.innerHTML=` + `},MC={onDragStart(o){let{active:e}=o;return"Picked up draggable item "+e.id+"."},onDragOver(o){let{active:e,over:a}=o;return a?"Draggable item "+e.id+" was moved over droppable area "+a.id+".":"Draggable item "+e.id+" is no longer over a droppable area."},onDragEnd(o){let{active:e,over:a}=o;return a?"Draggable item "+e.id+" was dropped over droppable area "+a.id:"Draggable item "+e.id+" was dropped."},onDragCancel(o){let{active:e}=o;return"Dragging was cancelled. Draggable item "+e.id+" was dropped."}};function $C(o){let{announcements:e=MC,container:a,hiddenTextDescribedById:r,screenReaderInstructions:i=LC}=o;const{announce:l,announcement:u}=kC(),d=ho("DndLiveRegion"),[f,g]=N.useState(!1);if(N.useEffect(()=>{g(!0)},[]),DC(N.useMemo(()=>({onDragStart(b){let{active:v}=b;l(e.onDragStart({active:v}))},onDragMove(b){let{active:v,over:S}=b;e.onDragMove&&l(e.onDragMove({active:v,over:S}))},onDragOver(b){let{active:v,over:S}=b;l(e.onDragOver({active:v,over:S}))},onDragEnd(b){let{active:v,over:S}=b;l(e.onDragEnd({active:v,over:S}))},onDragCancel(b){let{active:v,over:S}=b;l(e.onDragCancel({active:v,over:S}))}}),[l,e])),!f)return null;const m=Ye.createElement(Ye.Fragment,null,Ye.createElement(TC,{id:r,value:i.draggable}),Ye.createElement(RC,{id:d,announcement:u}));return a?Ar.createPortal(m,a):m}var en;(function(o){o.DragStart="dragStart",o.DragMove="dragMove",o.DragEnd="dragEnd",o.DragCancel="dragCancel",o.DragOver="dragOver",o.RegisterDroppable="registerDroppable",o.SetDroppableDisabled="setDroppableDisabled",o.UnregisterDroppable="unregisterDroppable"})(en||(en={}));function ec(){}function fm(o,e){return N.useMemo(()=>({sensor:o,options:e??{}}),[o,e])}function NC(){for(var o=arguments.length,e=new Array(o),a=0;a[...e].filter(r=>r!=null),[...e])}const ma=Object.freeze({x:0,y:0});function hm(o,e){return Math.sqrt(Math.pow(o.x-e.x,2)+Math.pow(o.y-e.y,2))}function gm(o,e){let{data:{value:a}}=o,{data:{value:r}}=e;return a-r}function IC(o,e){let{data:{value:a}}=o,{data:{value:r}}=e;return r-a}function pm(o){let{left:e,top:a,height:r,width:i}=o;return[{x:e,y:a},{x:e+i,y:a},{x:e,y:a+r},{x:e+i,y:a+r}]}function mm(o,e){if(!o||o.length===0)return null;const[a]=o;return a[e]}function ym(o,e,a){return e===void 0&&(e=o.left),a===void 0&&(a=o.top),{x:e+o.width*.5,y:a+o.height*.5}}const HC=o=>{let{collisionRect:e,droppableRects:a,droppableContainers:r}=o;const i=ym(e,e.left,e.top),l=[];for(const u of r){const{id:d}=u,f=a.get(d);if(f){const g=hm(ym(f),i);l.push({id:d,data:{droppableContainer:u,value:g}})}}return l.sort(gm)},zC=o=>{let{collisionRect:e,droppableRects:a,droppableContainers:r}=o;const i=pm(e),l=[];for(const u of r){const{id:d}=u,f=a.get(d);if(f){const g=pm(f),m=i.reduce((v,S,E)=>v+hm(g[E],S),0),b=Number((m/4).toFixed(4));l.push({id:d,data:{droppableContainer:u,value:b}})}}return l.sort(gm)};function jC(o,e){const a=Math.max(e.top,o.top),r=Math.max(e.left,o.left),i=Math.min(e.left+e.width,o.left+o.width),l=Math.min(e.top+e.height,o.top+o.height),u=i-r,d=l-a;if(r{let{collisionRect:e,droppableRects:a,droppableContainers:r}=o;const i=[];for(const l of r){const{id:u}=l,d=a.get(u);if(d){const f=jC(d,e);f>0&&i.push({id:u,data:{droppableContainer:l,value:f}})}}return i.sort(IC)};function BC(o,e,a){return{...o,scaleX:e&&a?e.width/a.width:1,scaleY:e&&a?e.height/a.height:1}}function bm(o,e){return o&&e?{x:o.left-e.left,y:o.top-e.top}:ma}function PC(o){return function(a){for(var r=arguments.length,i=new Array(r>1?r-1:0),l=1;l({...u,top:u.top+o*d.y,bottom:u.bottom+o*d.y,left:u.left+o*d.x,right:u.right+o*d.x}),{...a})}}const qC=PC(1);function GC(o){if(o.startsWith("matrix3d(")){const e=o.slice(9,-1).split(/, /);return{x:+e[12],y:+e[13],scaleX:+e[0],scaleY:+e[5]}}else if(o.startsWith("matrix(")){const e=o.slice(7,-1).split(/, /);return{x:+e[4],y:+e[5],scaleX:+e[0],scaleY:+e[3]}}return null}function VC(o,e,a){const r=GC(e);if(!r)return o;const{scaleX:i,scaleY:l,x:u,y:d}=r,f=o.left-u-(1-i)*parseFloat(a),g=o.top-d-(1-l)*parseFloat(a.slice(a.indexOf(" ")+1)),m=i?o.width/i:o.width,b=l?o.height/l:o.height;return{width:m,height:b,top:g,right:f+m,bottom:g+b,left:f}}const FC={ignoreTransform:!1};function ss(o,e){e===void 0&&(e=FC);let a=o.getBoundingClientRect();if(e.ignoreTransform){const{transform:g,transformOrigin:m}=Tn(o).getComputedStyle(o);g&&(a=VC(a,g,m))}const{top:r,left:i,width:l,height:u,bottom:d,right:f}=a;return{top:r,left:i,width:l,height:u,bottom:d,right:f}}function vm(o){return ss(o,{ignoreTransform:!0})}function KC(o){const e=o.innerWidth,a=o.innerHeight;return{top:0,left:0,right:e,bottom:a,width:e,height:a}}function WC(o,e){return e===void 0&&(e=Tn(o).getComputedStyle(o)),e.position==="fixed"}function YC(o,e){e===void 0&&(e=Tn(o).getComputedStyle(o));const a=/(auto|scroll|overlay)/;return["overflow","overflowX","overflowY"].some(i=>{const l=e[i];return typeof l=="string"?a.test(l):!1})}function tc(o,e){const a=[];function r(i){if(e!=null&&a.length>=e||!i)return a;if(Id(i)&&i.scrollingElement!=null&&!a.includes(i.scrollingElement))return a.push(i.scrollingElement),a;if(!co(i)||lm(i)||a.includes(i))return a;const l=Tn(o).getComputedStyle(i);return i!==o&&YC(i,l)&&a.push(i),WC(i,l)?a:r(i.parentNode)}return o?r(o):a}function Sm(o){const[e]=tc(o,1);return e??null}function Pd(o){return!Ql||!o?null:as(o)?o:Nd(o)?Id(o)||o===rs(o).scrollingElement?window:co(o)?o:null:null}function wm(o){return as(o)?o.scrollX:o.scrollLeft}function Cm(o){return as(o)?o.scrollY:o.scrollTop}function qd(o){return{x:wm(o),y:Cm(o)}}var ln;(function(o){o[o.Forward=1]="Forward",o[o.Backward=-1]="Backward"})(ln||(ln={}));function Em(o){return!Ql||!o?!1:o===document.scrollingElement}function _m(o){const e={x:0,y:0},a=Em(o)?{height:window.innerHeight,width:window.innerWidth}:{height:o.clientHeight,width:o.clientWidth},r={x:o.scrollWidth-a.width,y:o.scrollHeight-a.height},i=o.scrollTop<=e.y,l=o.scrollLeft<=e.x,u=o.scrollTop>=r.y,d=o.scrollLeft>=r.x;return{isTop:i,isLeft:l,isBottom:u,isRight:d,maxScroll:r,minScroll:e}}const XC={x:.2,y:.2};function JC(o,e,a,r,i){let{top:l,left:u,right:d,bottom:f}=a;r===void 0&&(r=10),i===void 0&&(i=XC);const{isTop:g,isBottom:m,isLeft:b,isRight:v}=_m(o),S={x:0,y:0},E={x:0,y:0},A={height:e.height*i.y,width:e.width*i.x};return!g&&l<=e.top+A.height?(S.y=ln.Backward,E.y=r*Math.abs((e.top+A.height-l)/A.height)):!m&&f>=e.bottom-A.height&&(S.y=ln.Forward,E.y=r*Math.abs((e.bottom-A.height-f)/A.height)),!v&&d>=e.right-A.width?(S.x=ln.Forward,E.x=r*Math.abs((e.right-A.width-d)/A.width)):!b&&u<=e.left+A.width&&(S.x=ln.Backward,E.x=r*Math.abs((e.left+A.width-u)/A.width)),{direction:S,speed:E}}function QC(o){if(o===document.scrollingElement){const{innerWidth:l,innerHeight:u}=window;return{top:0,left:0,right:l,bottom:u,width:l,height:u}}const{top:e,left:a,right:r,bottom:i}=o.getBoundingClientRect();return{top:e,left:a,right:r,bottom:i,width:o.clientWidth,height:o.clientHeight}}function Am(o){return o.reduce((e,a)=>is(e,qd(a)),ma)}function ZC(o){return o.reduce((e,a)=>e+wm(a),0)}function eE(o){return o.reduce((e,a)=>e+Cm(a),0)}function tE(o,e){if(e===void 0&&(e=ss),!o)return;const{top:a,left:r,bottom:i,right:l}=e(o);Sm(o)&&(i<=0||l<=0||a>=window.innerHeight||r>=window.innerWidth)&&o.scrollIntoView({block:"center",inline:"center"})}const nE=[["x",["left","right"],ZC],["y",["top","bottom"],eE]];class Gd{constructor(e,a){this.rect=void 0,this.width=void 0,this.height=void 0,this.top=void 0,this.bottom=void 0,this.right=void 0,this.left=void 0;const r=tc(a),i=Am(r);this.rect={...e},this.width=e.width,this.height=e.height;for(const[l,u,d]of nE)for(const f of u)Object.defineProperty(this,f,{get:()=>{const g=d(r),m=i[l]-g;return this.rect[f]+m},enumerable:!0});Object.defineProperty(this,"rect",{enumerable:!1})}}class mo{constructor(e){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(a=>{var r;return(r=this.target)==null?void 0:r.removeEventListener(...a)})},this.target=e}add(e,a,r){var i;(i=this.target)==null||i.addEventListener(e,a,r),this.listeners.push([e,a,r])}}function aE(o){const{EventTarget:e}=Tn(o);return o instanceof e?o:rs(o)}function Vd(o,e){const a=Math.abs(o.x),r=Math.abs(o.y);return typeof e=="number"?Math.sqrt(a**2+r**2)>e:"x"in e&&"y"in e?a>e.x&&r>e.y:"x"in e?a>e.x:"y"in e?r>e.y:!1}var Qn;(function(o){o.Click="click",o.DragStart="dragstart",o.Keydown="keydown",o.ContextMenu="contextmenu",o.Resize="resize",o.SelectionChange="selectionchange",o.VisibilityChange="visibilitychange"})(Qn||(Qn={}));function xm(o){o.preventDefault()}function rE(o){o.stopPropagation()}var it;(function(o){o.Space="Space",o.Down="ArrowDown",o.Right="ArrowRight",o.Left="ArrowLeft",o.Up="ArrowUp",o.Esc="Escape",o.Enter="Enter",o.Tab="Tab"})(it||(it={}));const Tm={start:[it.Space,it.Enter],cancel:[it.Esc],end:[it.Space,it.Enter,it.Tab]},iE=(o,e)=>{let{currentCoordinates:a}=e;switch(o.code){case it.Right:return{...a,x:a.x+25};case it.Left:return{...a,x:a.x-25};case it.Down:return{...a,y:a.y+25};case it.Up:return{...a,y:a.y-25}}};class Fd{constructor(e){this.props=void 0,this.autoScrollEnabled=!1,this.referenceCoordinates=void 0,this.listeners=void 0,this.windowListeners=void 0,this.props=e;const{event:{target:a}}=e;this.props=e,this.listeners=new mo(rs(a)),this.windowListeners=new mo(Tn(a)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(Qn.Resize,this.handleCancel),this.windowListeners.add(Qn.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(Qn.Keydown,this.handleKeyDown))}handleStart(){const{activeNode:e,onStart:a}=this.props,r=e.node.current;r&&tE(r),a(ma)}handleKeyDown(e){if(Ud(e)){const{active:a,context:r,options:i}=this.props,{keyboardCodes:l=Tm,coordinateGetter:u=iE,scrollBehavior:d="smooth"}=i,{code:f}=e;if(l.end.includes(f)){this.handleEnd(e);return}if(l.cancel.includes(f)){this.handleCancel(e);return}const{collisionRect:g}=r.current,m=g?{x:g.left,y:g.top}:ma;this.referenceCoordinates||(this.referenceCoordinates=m);const b=u(e,{active:a,context:r.current,currentCoordinates:m});if(b){const v=go(b,m),S={x:0,y:0},{scrollableAncestors:E}=r.current;for(const A of E){const T=e.code,{isTop:L,isRight:M,isLeft:R,isBottom:D,maxScroll:U,minScroll:j}=_m(A),P=QC(A),X={x:Math.min(T===it.Right?P.right-P.width/2:P.right,Math.max(T===it.Right?P.left:P.left+P.width/2,b.x)),y:Math.min(T===it.Down?P.bottom-P.height/2:P.bottom,Math.max(T===it.Down?P.top:P.top+P.height/2,b.y))},ge=T===it.Right&&!M||T===it.Left&&!R,Ee=T===it.Down&&!D||T===it.Up&&!L;if(ge&&X.x!==b.x){const Ce=A.scrollLeft+v.x,$e=T===it.Right&&Ce<=U.x||T===it.Left&&Ce>=j.x;if($e&&!v.y){A.scrollTo({left:Ce,behavior:d});return}$e?S.x=A.scrollLeft-Ce:S.x=T===it.Right?A.scrollLeft-U.x:A.scrollLeft-j.x,S.x&&A.scrollBy({left:-S.x,behavior:d});break}else if(Ee&&X.y!==b.y){const Ce=A.scrollTop+v.y,$e=T===it.Down&&Ce<=U.y||T===it.Up&&Ce>=j.y;if($e&&!v.x){A.scrollTo({top:Ce,behavior:d});return}$e?S.y=A.scrollTop-Ce:S.y=T===it.Down?A.scrollTop-U.y:A.scrollTop-j.y,S.y&&A.scrollBy({top:-S.y,behavior:d});break}}this.handleMove(e,is(go(b,this.referenceCoordinates),S))}}}handleMove(e,a){const{onMove:r}=this.props;e.preventDefault(),r(a)}handleEnd(e){const{onEnd:a}=this.props;e.preventDefault(),this.detach(),a()}handleCancel(e){const{onCancel:a}=this.props;e.preventDefault(),this.detach(),a()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}}Fd.activators=[{eventName:"onKeyDown",handler:(o,e,a)=>{let{keyboardCodes:r=Tm,onActivation:i}=e,{active:l}=a;const{code:u}=o.nativeEvent;if(r.start.includes(u)){const d=l.activatorNode.current;return d&&o.target!==d?!1:(o.preventDefault(),i?.({event:o.nativeEvent}),!0)}return!1}}];function Rm(o){return!!(o&&"distance"in o)}function km(o){return!!(o&&"delay"in o)}class Kd{constructor(e,a,r){var i;r===void 0&&(r=aE(e.event.target)),this.props=void 0,this.events=void 0,this.autoScrollEnabled=!0,this.document=void 0,this.activated=!1,this.initialCoordinates=void 0,this.timeoutId=null,this.listeners=void 0,this.documentListeners=void 0,this.windowListeners=void 0,this.props=e,this.events=a;const{event:l}=e,{target:u}=l;this.props=e,this.events=a,this.document=rs(u),this.documentListeners=new mo(this.document),this.listeners=new mo(r),this.windowListeners=new mo(Tn(u)),this.initialCoordinates=(i=Bd(l))!=null?i:ma,this.handleStart=this.handleStart.bind(this),this.handleMove=this.handleMove.bind(this),this.handleEnd=this.handleEnd.bind(this),this.handleCancel=this.handleCancel.bind(this),this.handleKeydown=this.handleKeydown.bind(this),this.removeTextSelection=this.removeTextSelection.bind(this),this.attach()}attach(){const{events:e,props:{options:{activationConstraint:a,bypassActivationConstraint:r}}}=this;if(this.listeners.add(e.move.name,this.handleMove,{passive:!1}),this.listeners.add(e.end.name,this.handleEnd),e.cancel&&this.listeners.add(e.cancel.name,this.handleCancel),this.windowListeners.add(Qn.Resize,this.handleCancel),this.windowListeners.add(Qn.DragStart,xm),this.windowListeners.add(Qn.VisibilityChange,this.handleCancel),this.windowListeners.add(Qn.ContextMenu,xm),this.documentListeners.add(Qn.Keydown,this.handleKeydown),a){if(r!=null&&r({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(km(a)){this.timeoutId=setTimeout(this.handleStart,a.delay),this.handlePending(a);return}if(Rm(a)){this.handlePending(a);return}}this.handleStart()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll(),setTimeout(this.documentListeners.removeAll,50),this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}handlePending(e,a){const{active:r,onPending:i}=this.props;i(r,e,this.initialCoordinates,a)}handleStart(){const{initialCoordinates:e}=this,{onStart:a}=this.props;e&&(this.activated=!0,this.documentListeners.add(Qn.Click,rE,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(Qn.SelectionChange,this.removeTextSelection),a(e))}handleMove(e){var a;const{activated:r,initialCoordinates:i,props:l}=this,{onMove:u,options:{activationConstraint:d}}=l;if(!i)return;const f=(a=Bd(e))!=null?a:ma,g=go(i,f);if(!r&&d){if(Rm(d)){if(d.tolerance!=null&&Vd(g,d.tolerance))return this.handleCancel();if(Vd(g,d.distance))return this.handleStart()}if(km(d)&&Vd(g,d.tolerance))return this.handleCancel();this.handlePending(d,g);return}e.cancelable&&e.preventDefault(),u(f)}handleEnd(){const{onAbort:e,onEnd:a}=this.props;this.detach(),this.activated||e(this.props.active),a()}handleCancel(){const{onAbort:e,onCancel:a}=this.props;this.detach(),this.activated||e(this.props.active),a()}handleKeydown(e){e.code===it.Esc&&this.handleCancel()}removeTextSelection(){var e;(e=this.document.getSelection())==null||e.removeAllRanges()}}const sE={cancel:{name:"pointercancel"},move:{name:"pointermove"},end:{name:"pointerup"}};class Wd extends Kd{constructor(e){const{event:a}=e,r=rs(a.target);super(e,sE,r)}}Wd.activators=[{eventName:"onPointerDown",handler:(o,e)=>{let{nativeEvent:a}=o,{onActivation:r}=e;return!a.isPrimary||a.button!==0?!1:(r?.({event:a}),!0)}}];const oE={move:{name:"mousemove"},end:{name:"mouseup"}};var Yd;(function(o){o[o.RightClick=2]="RightClick"})(Yd||(Yd={}));class lE extends Kd{constructor(e){super(e,oE,rs(e.event.target))}}lE.activators=[{eventName:"onMouseDown",handler:(o,e)=>{let{nativeEvent:a}=o,{onActivation:r}=e;return a.button===Yd.RightClick?!1:(r?.({event:a}),!0)}}];const Xd={cancel:{name:"touchcancel"},move:{name:"touchmove"},end:{name:"touchend"}};class cE extends Kd{constructor(e){super(e,Xd)}static setup(){return window.addEventListener(Xd.move.name,e,{capture:!1,passive:!1}),function(){window.removeEventListener(Xd.move.name,e)};function e(){}}}cE.activators=[{eventName:"onTouchStart",handler:(o,e)=>{let{nativeEvent:a}=o,{onActivation:r}=e;const{touches:i}=a;return i.length>1?!1:(r?.({event:a}),!0)}}];var yo;(function(o){o[o.Pointer=0]="Pointer",o[o.DraggableRect=1]="DraggableRect"})(yo||(yo={}));var nc;(function(o){o[o.TreeOrder=0]="TreeOrder",o[o.ReversedTreeOrder=1]="ReversedTreeOrder"})(nc||(nc={}));function uE(o){let{acceleration:e,activator:a=yo.Pointer,canScroll:r,draggingRect:i,enabled:l,interval:u=5,order:d=nc.TreeOrder,pointerCoordinates:f,scrollableAncestors:g,scrollableAncestorRects:m,delta:b,threshold:v}=o;const S=fE({delta:b,disabled:!l}),[E,A]=CC(),T=N.useRef({x:0,y:0}),L=N.useRef({x:0,y:0}),M=N.useMemo(()=>{switch(a){case yo.Pointer:return f?{top:f.y,bottom:f.y,left:f.x,right:f.x}:null;case yo.DraggableRect:return i}},[a,i,f]),R=N.useRef(null),D=N.useCallback(()=>{const j=R.current;if(!j)return;const P=T.current.x*L.current.x,X=T.current.y*L.current.y;j.scrollBy(P,X)},[]),U=N.useMemo(()=>d===nc.TreeOrder?[...g].reverse():g,[d,g]);N.useEffect(()=>{if(!l||!g.length||!M){A();return}for(const j of U){if(r?.(j)===!1)continue;const P=g.indexOf(j),X=m[P];if(!X)continue;const{direction:ge,speed:Ee}=JC(j,X,M,e,v);for(const Ce of["x","y"])S[Ce][ge[Ce]]||(Ee[Ce]=0,ge[Ce]=0);if(Ee.x>0||Ee.y>0){A(),R.current=j,E(D,u),T.current=Ee,L.current=ge;return}}T.current={x:0,y:0},L.current={x:0,y:0},A()},[e,D,r,A,l,u,JSON.stringify(M),JSON.stringify(S),E,g,U,m,JSON.stringify(v)])}const dE={x:{[ln.Backward]:!1,[ln.Forward]:!1},y:{[ln.Backward]:!1,[ln.Forward]:!1}};function fE(o){let{delta:e,disabled:a}=o;const r=zd(e);return fo(i=>{if(a||!r||!i)return dE;const l={x:Math.sign(e.x-r.x),y:Math.sign(e.y-r.y)};return{x:{[ln.Backward]:i.x[ln.Backward]||l.x===-1,[ln.Forward]:i.x[ln.Forward]||l.x===1},y:{[ln.Backward]:i.y[ln.Backward]||l.y===-1,[ln.Forward]:i.y[ln.Forward]||l.y===1}}},[a,e,r])}function hE(o,e){const a=e!=null?o.get(e):void 0,r=a?a.node.current:null;return fo(i=>{var l;return e==null?null:(l=r??i)!=null?l:null},[r,e])}function gE(o,e){return N.useMemo(()=>o.reduce((a,r)=>{const{sensor:i}=r,l=i.activators.map(u=>({eventName:u.eventName,handler:e(u.handler,r)}));return[...a,...l]},[]),[o,e])}var bo;(function(o){o[o.Always=0]="Always",o[o.BeforeDragging=1]="BeforeDragging",o[o.WhileDragging=2]="WhileDragging"})(bo||(bo={}));var Jd;(function(o){o.Optimized="optimized"})(Jd||(Jd={}));const Dm=new Map;function pE(o,e){let{dragging:a,dependencies:r,config:i}=e;const[l,u]=N.useState(null),{frequency:d,measure:f,strategy:g}=i,m=N.useRef(o),b=T(),v=uo(b),S=N.useCallback(function(L){L===void 0&&(L=[]),!v.current&&u(M=>M===null?L:M.concat(L.filter(R=>!M.includes(R))))},[v]),E=N.useRef(null),A=fo(L=>{if(b&&!a)return Dm;if(!L||L===Dm||m.current!==o||l!=null){const M=new Map;for(let R of o){if(!R)continue;if(l&&l.length>0&&!l.includes(R.id)&&R.rect.current){M.set(R.id,R.rect.current);continue}const D=R.node.current,U=D?new Gd(f(D),D):null;R.rect.current=U,U&&M.set(R.id,U)}return M}return L},[o,l,a,b,f]);return N.useEffect(()=>{m.current=o},[o]),N.useEffect(()=>{b||S()},[a,b]),N.useEffect(()=>{l&&l.length>0&&u(null)},[JSON.stringify(l)]),N.useEffect(()=>{b||typeof d!="number"||E.current!==null||(E.current=setTimeout(()=>{S(),E.current=null},d))},[d,b,S,...r]),{droppableRects:A,measureDroppableContainers:S,measuringScheduled:l!=null};function T(){switch(g){case bo.Always:return!1;case bo.BeforeDragging:return a;default:return!a}}}function Om(o,e){return fo(a=>o?a||(typeof e=="function"?e(o):o):null,[e,o])}function mE(o,e){return Om(o,e)}function yE(o){let{callback:e,disabled:a}=o;const r=Hd(e),i=N.useMemo(()=>{if(a||typeof window>"u"||typeof window.MutationObserver>"u")return;const{MutationObserver:l}=window;return new l(r)},[r,a]);return N.useEffect(()=>()=>i?.disconnect(),[i]),i}function ac(o){let{callback:e,disabled:a}=o;const r=Hd(e),i=N.useMemo(()=>{if(a||typeof window>"u"||typeof window.ResizeObserver>"u")return;const{ResizeObserver:l}=window;return new l(r)},[a]);return N.useEffect(()=>()=>i?.disconnect(),[i]),i}function bE(o){return new Gd(ss(o),o)}function Lm(o,e,a){e===void 0&&(e=bE);const[r,i]=N.useState(null);function l(){i(f=>{if(!o)return null;if(o.isConnected===!1){var g;return(g=f??a)!=null?g:null}const m=e(o);return JSON.stringify(f)===JSON.stringify(m)?f:m})}const u=yE({callback(f){if(o)for(const g of f){const{type:m,target:b}=g;if(m==="childList"&&b instanceof HTMLElement&&b.contains(o)){l();break}}}}),d=ac({callback:l});return Ia(()=>{l(),o?(d?.observe(o),u?.observe(document.body,{childList:!0,subtree:!0})):(d?.disconnect(),u?.disconnect())},[o]),r}function vE(o){const e=Om(o);return bm(o,e)}const Mm=[];function SE(o){const e=N.useRef(o),a=fo(r=>o?r&&r!==Mm&&o&&e.current&&o.parentNode===e.current.parentNode?r:tc(o):Mm,[o]);return N.useEffect(()=>{e.current=o},[o]),a}function wE(o){const[e,a]=N.useState(null),r=N.useRef(o),i=N.useCallback(l=>{const u=Pd(l.target);u&&a(d=>d?(d.set(u,qd(u)),new Map(d)):null)},[]);return N.useEffect(()=>{const l=r.current;if(o!==l){u(l);const d=o.map(f=>{const g=Pd(f);return g?(g.addEventListener("scroll",i,{passive:!0}),[g,qd(g)]):null}).filter(f=>f!=null);a(d.length?new Map(d):null),r.current=o}return()=>{u(o),u(l)};function u(d){d.forEach(f=>{const g=Pd(f);g?.removeEventListener("scroll",i)})}},[i,o]),N.useMemo(()=>o.length?e?Array.from(e.values()).reduce((l,u)=>is(l,u),ma):Am(o):ma,[o,e])}function $m(o,e){e===void 0&&(e=[]);const a=N.useRef(null);return N.useEffect(()=>{a.current=null},e),N.useEffect(()=>{const r=o!==ma;r&&!a.current&&(a.current=o),!r&&a.current&&(a.current=null)},[o]),a.current?go(o,a.current):ma}function CE(o){N.useEffect(()=>{if(!Ql)return;const e=o.map(a=>{let{sensor:r}=a;return r.setup==null?void 0:r.setup()});return()=>{for(const a of e)a?.()}},o.map(e=>{let{sensor:a}=e;return a}))}function EE(o,e){return N.useMemo(()=>o.reduce((a,r)=>{let{eventName:i,handler:l}=r;return a[i]=u=>{l(u,e)},a},{}),[o,e])}function Nm(o){return N.useMemo(()=>o?KC(o):null,[o])}const Im=[];function _E(o,e){e===void 0&&(e=ss);const[a]=o,r=Nm(a?Tn(a):null),[i,l]=N.useState(Im);function u(){l(()=>o.length?o.map(f=>Em(f)?r:new Gd(e(f),f)):Im)}const d=ac({callback:u});return Ia(()=>{d?.disconnect(),u(),o.forEach(f=>d?.observe(f))},[o]),i}function AE(o){if(!o)return null;if(o.children.length>1)return o;const e=o.children[0];return co(e)?e:o}function xE(o){let{measure:e}=o;const[a,r]=N.useState(null),i=N.useCallback(g=>{for(const{target:m}of g)if(co(m)){r(b=>{const v=e(m);return b?{...b,width:v.width,height:v.height}:v});break}},[e]),l=ac({callback:i}),u=N.useCallback(g=>{const m=AE(g);l?.disconnect(),m&&l?.observe(m),r(m?e(m):null)},[e,l]),[d,f]=Zl(u);return N.useMemo(()=>({nodeRef:d,rect:a,setRef:f}),[a,d,f])}const TE=[{sensor:Wd,options:{}},{sensor:Fd,options:{}}],RE={current:{}},rc={draggable:{measure:vm},droppable:{measure:vm,strategy:bo.WhileDragging,frequency:Jd.Optimized},dragOverlay:{measure:ss}};class vo extends Map{get(e){var a;return e!=null&&(a=super.get(e))!=null?a:void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(e=>{let{disabled:a}=e;return!a})}getNodeFor(e){var a,r;return(a=(r=this.get(e))==null?void 0:r.node.current)!=null?a:void 0}}const kE={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new vo,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:ec},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:rc,measureDroppableContainers:ec,windowRect:null,measuringScheduled:!1},DE={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:""},dispatch:ec,draggableNodes:new Map,over:null,measureDroppableContainers:ec},ic=N.createContext(DE),Hm=N.createContext(kE);function OE(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new vo}}}function LE(o,e){switch(e.type){case en.DragStart:return{...o,draggable:{...o.draggable,initialCoordinates:e.initialCoordinates,active:e.active}};case en.DragMove:return o.draggable.active==null?o:{...o,draggable:{...o.draggable,translate:{x:e.coordinates.x-o.draggable.initialCoordinates.x,y:e.coordinates.y-o.draggable.initialCoordinates.y}}};case en.DragEnd:case en.DragCancel:return{...o,draggable:{...o.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case en.RegisterDroppable:{const{element:a}=e,{id:r}=a,i=new vo(o.droppable.containers);return i.set(r,a),{...o,droppable:{...o.droppable,containers:i}}}case en.SetDroppableDisabled:{const{id:a,key:r,disabled:i}=e,l=o.droppable.containers.get(a);if(!l||r!==l.key)return o;const u=new vo(o.droppable.containers);return u.set(a,{...l,disabled:i}),{...o,droppable:{...o.droppable,containers:u}}}case en.UnregisterDroppable:{const{id:a,key:r}=e,i=o.droppable.containers.get(a);if(!i||r!==i.key)return o;const l=new vo(o.droppable.containers);return l.delete(a),{...o,droppable:{...o.droppable,containers:l}}}default:return o}}function ME(o){let{disabled:e}=o;const{active:a,activatorEvent:r,draggableNodes:i}=N.useContext(ic),l=zd(r),u=zd(a?.id);return N.useEffect(()=>{if(!e&&!r&&l&&u!=null){if(!Ud(l)||document.activeElement===l.target)return;const d=i.get(u);if(!d)return;const{activatorNode:f,node:g}=d;if(!f.current&&!g.current)return;requestAnimationFrame(()=>{for(const m of[f.current,g.current]){if(!m)continue;const b=AC(m);if(b){b.focus();break}}})}},[r,e,i,u,l]),null}function $E(o,e){let{transform:a,...r}=e;return o!=null&&o.length?o.reduce((i,l)=>l({transform:i,...r}),a):a}function NE(o){return N.useMemo(()=>({draggable:{...rc.draggable,...o?.draggable},droppable:{...rc.droppable,...o?.droppable},dragOverlay:{...rc.dragOverlay,...o?.dragOverlay}}),[o?.draggable,o?.droppable,o?.dragOverlay])}function IE(o){let{activeNode:e,measure:a,initialRect:r,config:i=!0}=o;const l=N.useRef(!1),{x:u,y:d}=typeof i=="boolean"?{x:i,y:i}:i;Ia(()=>{if(!u&&!d||!e){l.current=!1;return}if(l.current||!r)return;const g=e?.node.current;if(!g||g.isConnected===!1)return;const m=a(g),b=bm(m,r);if(u||(b.x=0),d||(b.y=0),l.current=!0,Math.abs(b.x)>0||Math.abs(b.y)>0){const v=Sm(g);v&&v.scrollBy({top:b.y,left:b.x})}},[e,u,d,r,a])}const zm=N.createContext({...ma,scaleX:1,scaleY:1});var xr;(function(o){o[o.Uninitialized=0]="Uninitialized",o[o.Initializing=1]="Initializing",o[o.Initialized=2]="Initialized"})(xr||(xr={}));const HE=N.memo(function(e){var a,r,i,l;let{id:u,accessibility:d,autoScroll:f=!0,children:g,sensors:m=TE,collisionDetection:b=UC,measuring:v,modifiers:S,...E}=e;const A=N.useReducer(LE,void 0,OE),[T,L]=A,[M,R]=OC(),[D,U]=N.useState(xr.Uninitialized),j=D===xr.Initialized,{draggable:{active:P,nodes:X,translate:ge},droppable:{containers:Ee}}=T,Ce=P!=null?X.get(P):null,$e=N.useRef({initial:null,translated:null}),Pe=N.useMemo(()=>{var Re;return P!=null?{id:P,data:(Re=Ce?.data)!=null?Re:RE,rect:$e}:null},[P,Ce]),Xe=N.useRef(null),[ht,Q]=N.useState(null),[fe,ye]=N.useState(null),te=uo(E,Object.values(E)),he=ho("DndDescribedBy",u),x=N.useMemo(()=>Ee.getEnabled(),[Ee]),K=NE(v),{droppableRects:re,measureDroppableContainers:de,measuringScheduled:ie}=pE(x,{dragging:j,dependencies:[ge.x,ge.y],config:K.droppable}),me=hE(X,P),Ne=N.useMemo(()=>fe?Bd(fe):null,[fe]),Se=ve(),He=mE(me,K.draggable.measure);IE({activeNode:P!=null?X.get(P):null,config:Se.layoutShiftCompensation,initialRect:He,measure:K.draggable.measure});const Ae=Lm(me,K.draggable.measure,He),Et=Lm(me?me.parentElement:null),kt=N.useRef({activatorEvent:null,active:null,activeNode:me,collisionRect:null,collisions:null,droppableRects:re,draggableNodes:X,draggingNode:null,draggingNodeRect:null,droppableContainers:Ee,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),_t=Ee.getNodeFor((a=kt.current.over)==null?void 0:a.id),ft=xE({measure:K.dragOverlay.measure}),un=(r=ft.nodeRef.current)!=null?r:me,gt=j?(i=ft.rect)!=null?i:Ae:null,ja=!!(ft.nodeRef.current&&ft.rect),kn=vE(ja?null:Ae),Dn=Nm(un?Tn(un):null),jt=SE(j?_t??me:null),On=_E(jt),ea=$E(S,{transform:{x:ge.x-kn.x,y:ge.y-kn.y,scaleX:1,scaleY:1},activatorEvent:fe,active:Pe,activeNodeRect:Ae,containerNodeRect:Et,draggingNodeRect:gt,over:kt.current.over,overlayNodeRect:ft.rect,scrollableAncestors:jt,scrollableAncestorRects:On,windowRect:Dn}),Ua=Ne?is(Ne,ge):null,Kt=wE(jt),Dr=$m(Kt),er=$m(Kt,[Ae]),bn=is(ea,Dr),tn=gt?qC(gt,ea):null,et=Pe&&tn?b({active:Pe,collisionRect:tn,droppableRects:re,droppableContainers:x,pointerCoordinates:Ua}):null,ta=mm(et,"id"),[En,tr]=N.useState(null),Ea=ja?ea:is(ea,er),nn=BC(Ea,(l=En?.rect)!=null?l:null,Ae),_n=N.useRef(null),q=N.useCallback((Re,xe)=>{let{sensor:je,options:ze}=xe;if(Xe.current==null)return;const Le=X.get(Xe.current);if(!Le)return;const ke=Re.nativeEvent,We=new je({active:Xe.current,activeNode:Le,event:ke,options:ze,context:kt,onAbort(_e){if(!X.get(_e))return;const{onDragAbort:Ue}=te.current,st={id:_e};Ue?.(st),M({type:"onDragAbort",event:st})},onPending(_e,Te,Ue,st){if(!X.get(_e))return;const{onDragPending:Wt}=te.current,qt={id:_e,constraint:Te,initialCoordinates:Ue,offset:st};Wt?.(qt),M({type:"onDragPending",event:qt})},onStart(_e){const Te=Xe.current;if(Te==null)return;const Ue=X.get(Te);if(!Ue)return;const{onDragStart:st}=te.current,At={activatorEvent:ke,active:{id:Te,data:Ue.data,rect:$e}};Ar.unstable_batchedUpdates(()=>{st?.(At),U(xr.Initializing),L({type:en.DragStart,initialCoordinates:_e,active:Te}),M({type:"onDragStart",event:At}),Q(_n.current),ye(ke)})},onMove(_e){L({type:en.DragMove,coordinates:_e})},onEnd:Fe(en.DragEnd),onCancel:Fe(en.DragCancel)});_n.current=We;function Fe(_e){return async function(){const{active:Ue,collisions:st,over:At,scrollAdjustedTranslate:Wt}=kt.current;let qt=null;if(Ue&&Wt){const{cancelDrop:qn}=te.current;qt={activatorEvent:ke,active:Ue,collisions:st,delta:Wt,over:At},_e===en.DragEnd&&typeof qn=="function"&&await Promise.resolve(qn(qt))&&(_e=en.DragCancel)}Xe.current=null,Ar.unstable_batchedUpdates(()=>{L({type:_e}),U(xr.Uninitialized),tr(null),Q(null),ye(null),_n.current=null;const qn=_e===en.DragEnd?"onDragEnd":"onDragCancel";if(qt){const Ln=te.current[qn];Ln?.(qt),M({type:qn,event:qt})}})}}},[X]),ce=N.useCallback((Re,xe)=>(je,ze)=>{const Le=je.nativeEvent,ke=X.get(ze);if(Xe.current!==null||!ke||Le.dndKit||Le.defaultPrevented)return;const We={active:ke};Re(je,xe.options,We)===!0&&(Le.dndKit={capturedBy:xe.sensor},Xe.current=ze,q(je,xe))},[X,q]),le=gE(m,ce);CE(m),Ia(()=>{Ae&&D===xr.Initializing&&U(xr.Initialized)},[Ae,D]),N.useEffect(()=>{const{onDragMove:Re}=te.current,{active:xe,activatorEvent:je,collisions:ze,over:Le}=kt.current;if(!xe||!je)return;const ke={active:xe,activatorEvent:je,collisions:ze,delta:{x:bn.x,y:bn.y},over:Le};Ar.unstable_batchedUpdates(()=>{Re?.(ke),M({type:"onDragMove",event:ke})})},[bn.x,bn.y]),N.useEffect(()=>{const{active:Re,activatorEvent:xe,collisions:je,droppableContainers:ze,scrollAdjustedTranslate:Le}=kt.current;if(!Re||Xe.current==null||!xe||!Le)return;const{onDragOver:ke}=te.current,We=ze.get(ta),Fe=We&&We.rect.current?{id:We.id,rect:We.rect.current,data:We.data,disabled:We.disabled}:null,_e={active:Re,activatorEvent:xe,collisions:je,delta:{x:Le.x,y:Le.y},over:Fe};Ar.unstable_batchedUpdates(()=>{tr(Fe),ke?.(_e),M({type:"onDragOver",event:_e})})},[ta]),Ia(()=>{kt.current={activatorEvent:fe,active:Pe,activeNode:me,collisionRect:tn,collisions:et,droppableRects:re,draggableNodes:X,draggingNode:un,draggingNodeRect:gt,droppableContainers:Ee,over:En,scrollableAncestors:jt,scrollAdjustedTranslate:bn},$e.current={initial:gt,translated:tn}},[Pe,me,et,tn,X,un,gt,re,Ee,En,jt,bn]),uE({...Se,delta:ge,draggingRect:tn,pointerCoordinates:Ua,scrollableAncestors:jt,scrollableAncestorRects:On});const Z=N.useMemo(()=>({active:Pe,activeNode:me,activeNodeRect:Ae,activatorEvent:fe,collisions:et,containerNodeRect:Et,dragOverlay:ft,draggableNodes:X,droppableContainers:Ee,droppableRects:re,over:En,measureDroppableContainers:de,scrollableAncestors:jt,scrollableAncestorRects:On,measuringConfiguration:K,measuringScheduled:ie,windowRect:Dn}),[Pe,me,Ae,fe,et,Et,ft,X,Ee,re,En,de,jt,On,K,ie,Dn]),be=N.useMemo(()=>({activatorEvent:fe,activators:le,active:Pe,activeNodeRect:Ae,ariaDescribedById:{draggable:he},dispatch:L,draggableNodes:X,over:En,measureDroppableContainers:de}),[fe,le,Pe,Ae,L,he,X,En,de]);return Ye.createElement(dm.Provider,{value:R},Ye.createElement(ic.Provider,{value:be},Ye.createElement(Hm.Provider,{value:Z},Ye.createElement(zm.Provider,{value:nn},g)),Ye.createElement(ME,{disabled:d?.restoreFocus===!1})),Ye.createElement($C,{...d,hiddenTextDescribedById:he}));function ve(){const Re=ht?.autoScrollEnabled===!1,xe=typeof f=="object"?f.enabled===!1:f===!1,je=j&&!Re&&!xe;return typeof f=="object"?{...f,enabled:je}:{enabled:je}}}),zE=N.createContext(null),jm="button",jE="Draggable";function UE(o){let{id:e,data:a,disabled:r=!1,attributes:i}=o;const l=ho(jE),{activators:u,activatorEvent:d,active:f,activeNodeRect:g,ariaDescribedById:m,draggableNodes:b,over:v}=N.useContext(ic),{role:S=jm,roleDescription:E="draggable",tabIndex:A=0}=i??{},T=f?.id===e,L=N.useContext(T?zm:zE),[M,R]=Zl(),[D,U]=Zl(),j=EE(u,e),P=uo(a);Ia(()=>(b.set(e,{id:e,key:l,node:M,activatorNode:D,data:P}),()=>{const ge=b.get(e);ge&&ge.key===l&&b.delete(e)}),[b,e]);const X=N.useMemo(()=>({role:S,tabIndex:A,"aria-disabled":r,"aria-pressed":T&&S===jm?!0:void 0,"aria-roledescription":E,"aria-describedby":m.draggable}),[r,S,A,T,E,m.draggable]);return{active:f,activatorEvent:d,activeNodeRect:g,attributes:X,isDragging:T,listeners:r?void 0:j,node:M,over:v,setNodeRef:R,setActivatorNodeRef:U,transform:L}}function BE(){return N.useContext(Hm)}const PE="Droppable",qE={timeout:25};function GE(o){let{data:e,disabled:a=!1,id:r,resizeObserverConfig:i}=o;const l=ho(PE),{active:u,dispatch:d,over:f,measureDroppableContainers:g}=N.useContext(ic),m=N.useRef({disabled:a}),b=N.useRef(!1),v=N.useRef(null),S=N.useRef(null),{disabled:E,updateMeasurementsFor:A,timeout:T}={...qE,...i},L=uo(A??r),M=N.useCallback(()=>{if(!b.current){b.current=!0;return}S.current!=null&&clearTimeout(S.current),S.current=setTimeout(()=>{g(Array.isArray(L.current)?L.current:[L.current]),S.current=null},T)},[T]),R=ac({callback:M,disabled:E||!u}),D=N.useCallback((X,ge)=>{R&&(ge&&(R.unobserve(ge),b.current=!1),X&&R.observe(X))},[R]),[U,j]=Zl(D),P=uo(e);return N.useEffect(()=>{!R||!U.current||(R.disconnect(),b.current=!1,R.observe(U.current))},[U,R]),N.useEffect(()=>(d({type:en.RegisterDroppable,element:{id:r,key:l,disabled:a,node:U,rect:v,data:P}}),()=>d({type:en.UnregisterDroppable,key:l,id:r})),[r]),N.useEffect(()=>{a!==m.current.disabled&&(d({type:en.SetDroppableDisabled,id:r,key:l,disabled:a}),m.current.disabled=a)},[r,l,a,d]),{active:u,rect:v,isOver:f?.id===r,node:U,over:f,setNodeRef:j}}function Qd(o,e,a){const r=o.slice();return r.splice(a<0?r.length+a:a,0,r.splice(e,1)[0]),r}function VE(o,e){return o.reduce((a,r,i)=>{const l=e.get(r);return l&&(a[i]=l),a},Array(o.length))}function sc(o){return o!==null&&o>=0}function FE(o,e){if(o===e)return!0;if(o.length!==e.length)return!1;for(let a=0;a{var e;let{rects:a,activeNodeRect:r,activeIndex:i,overIndex:l,index:u}=o;const d=(e=a[i])!=null?e:r;if(!d)return null;const f=YE(a,u,i);if(u===i){const g=a[l];return g?{x:ii&&u<=l?{x:-d.width-f,y:0,...oc}:u=l?{x:d.width+f,y:0,...oc}:{x:0,y:0,...oc}};function YE(o,e,a){const r=o[e],i=o[e-1],l=o[e+1];return!r||!i&&!l?0:a{let{rects:e,activeIndex:a,overIndex:r,index:i}=o;const l=Qd(e,r,a),u=e[i],d=l[i];return!d||!u?null:{x:d.left-u.left,y:d.top-u.top,scaleX:d.width/u.width,scaleY:d.height/u.height}},lc={scaleX:1,scaleY:1},XE=o=>{var e;let{activeIndex:a,activeNodeRect:r,index:i,rects:l,overIndex:u}=o;const d=(e=l[a])!=null?e:r;if(!d)return null;if(i===a){const g=l[u];return g?{x:0,y:aa&&i<=u?{x:0,y:-d.height-f,...lc}:i=u?{x:0,y:d.height+f,...lc}:{x:0,y:0,...lc}};function JE(o,e,a){const r=o[e],i=o[e-1],l=o[e+1];return r?ar.map(j=>typeof j=="object"&&"id"in j?j.id:j),[r]),E=u!=null,A=u?S.indexOf(u.id):-1,T=g?S.indexOf(g.id):-1,L=N.useRef(S),M=!FE(S,L.current),R=T!==-1&&A===-1||M,D=KE(l);Ia(()=>{M&&E&&m(S)},[M,S,E,m]),N.useEffect(()=>{L.current=S},[S]);const U=N.useMemo(()=>({activeIndex:A,containerId:b,disabled:D,disableTransforms:R,items:S,overIndex:T,useDragOverlay:v,sortedRects:VE(S,f),strategy:i}),[A,b,D.draggable,D.droppable,R,S,T,f,v,i]);return Ye.createElement(Bm.Provider,{value:U},e)}const ZE=o=>{let{id:e,items:a,activeIndex:r,overIndex:i}=o;return Qd(a,r,i).indexOf(e)},e_=o=>{let{containerId:e,isSorting:a,wasDragging:r,index:i,items:l,newIndex:u,previousItems:d,previousContainerId:f,transition:g}=o;return!g||!r||d!==l&&i===u?!1:a?!0:u!==i&&e===f},t_={duration:200,easing:"ease"},Pm="transform",n_=po.Transition.toString({property:Pm,duration:0,easing:"linear"}),a_={roleDescription:"sortable"};function r_(o){let{disabled:e,index:a,node:r,rect:i}=o;const[l,u]=N.useState(null),d=N.useRef(a);return Ia(()=>{if(!e&&a!==d.current&&r.current){const f=i.current;if(f){const g=ss(r.current,{ignoreTransform:!0}),m={x:f.left-g.left,y:f.top-g.top,scaleX:f.width/g.width,scaleY:f.height/g.height};(m.x||m.y)&&u(m)}}a!==d.current&&(d.current=a)},[e,a,r,i]),N.useEffect(()=>{l&&u(null)},[l]),l}function i_(o){let{animateLayoutChanges:e=e_,attributes:a,disabled:r,data:i,getNewIndex:l=ZE,id:u,strategy:d,resizeObserverConfig:f,transition:g=t_}=o;const{items:m,containerId:b,activeIndex:v,disabled:S,disableTransforms:E,sortedRects:A,overIndex:T,useDragOverlay:L,strategy:M}=N.useContext(Bm),R=s_(r,S),D=m.indexOf(u),U=N.useMemo(()=>({sortable:{containerId:b,index:D,items:m},...i}),[b,i,D,m]),j=N.useMemo(()=>m.slice(m.indexOf(u)),[m,u]),{rect:P,node:X,isOver:ge,setNodeRef:Ee}=GE({id:u,data:U,disabled:R.droppable,resizeObserverConfig:{updateMeasurementsFor:j,...f}}),{active:Ce,activatorEvent:$e,activeNodeRect:Pe,attributes:Xe,setNodeRef:ht,listeners:Q,isDragging:fe,over:ye,setActivatorNodeRef:te,transform:he}=UE({id:u,data:U,attributes:{...a_,...a},disabled:R.draggable}),x=wC(Ee,ht),K=!!Ce,re=K&&!E&&sc(v)&&sc(T),de=!L&&fe,ie=de&&re?he:null,Ne=re?ie??(d??M)({rects:A,activeNodeRect:Pe,activeIndex:v,overIndex:T,index:D}):null,Se=sc(v)&&sc(T)?l({id:u,items:m,activeIndex:v,overIndex:T}):D,He=Ce?.id,Ae=N.useRef({activeId:He,items:m,newIndex:Se,containerId:b}),Et=m!==Ae.current.items,kt=e({active:Ce,containerId:b,isDragging:fe,isSorting:K,id:u,index:D,items:m,newIndex:Ae.current.newIndex,previousItems:Ae.current.items,previousContainerId:Ae.current.containerId,transition:g,wasDragging:Ae.current.activeId!=null}),_t=r_({disabled:!kt,index:D,node:X,rect:P});return N.useEffect(()=>{K&&Ae.current.newIndex!==Se&&(Ae.current.newIndex=Se),b!==Ae.current.containerId&&(Ae.current.containerId=b),m!==Ae.current.items&&(Ae.current.items=m)},[K,Se,b,m]),N.useEffect(()=>{if(He===Ae.current.activeId)return;if(He!=null&&Ae.current.activeId==null){Ae.current.activeId=He;return}const un=setTimeout(()=>{Ae.current.activeId=He},50);return()=>clearTimeout(un)},[He]),{active:Ce,activeIndex:v,attributes:Xe,data:U,rect:P,index:D,newIndex:Se,items:m,isOver:ge,isSorting:K,isDragging:fe,listeners:Q,node:X,overIndex:T,over:ye,setNodeRef:x,setActivatorNodeRef:te,setDroppableNodeRef:Ee,setDraggableNodeRef:ht,transform:_t??Ne,transition:ft()};function ft(){if(_t||Et&&Ae.current.newIndex===D)return n_;if(!(de&&!Ud($e)||!g)&&(K||kt))return po.Transition.toString({...g,property:Pm})}}function s_(o,e){var a,r;return typeof o=="boolean"?{draggable:o,droppable:!1}:{draggable:(a=o?.draggable)!=null?a:e.draggable,droppable:(r=o?.droppable)!=null?r:e.droppable}}function cc(o){if(!o)return!1;const e=o.data.current;return!!(e&&"sortable"in e&&typeof e.sortable=="object"&&"containerId"in e.sortable&&"items"in e.sortable&&"index"in e.sortable)}const o_=[it.Down,it.Right,it.Up,it.Left],l_=(o,e)=>{let{context:{active:a,collisionRect:r,droppableRects:i,droppableContainers:l,over:u,scrollableAncestors:d}}=e;if(o_.includes(o.code)){if(o.preventDefault(),!a||!r)return;const f=[];l.getEnabled().forEach(b=>{if(!b||b!=null&&b.disabled)return;const v=i.get(b.id);if(v)switch(o.code){case it.Down:r.topv.top&&f.push(b);break;case it.Left:r.left>v.left&&f.push(b);break;case it.Right:r.left1&&(m=g[1].id),m!=null){const b=l.get(a.id),v=l.get(m),S=v?i.get(v.id):null,E=v?.node.current;if(E&&S&&b&&v){const T=tc(E).some((j,P)=>d[P]!==j),L=qm(b,v),M=c_(b,v),R=T||!L?{x:0,y:0}:{x:M?r.width-S.width:0,y:M?r.height-S.height:0},D={x:S.left,y:S.top};return R.x&&R.y?D:go(D,R)}}}};function qm(o,e){return!cc(o)||!cc(e)?!1:o.data.current.sortable.containerId===e.data.current.sortable.containerId}function c_(o,e){return!cc(o)||!cc(e)||!qm(o,e)?!1:o.data.current.sortable.index{const d=N.useId(),f=N.useRef({inProgress:!1,lastSortTime:0,lastActiveId:null}),g=NC(fm(Wd,{activationConstraint:{distance:5}}),fm(Fd,{coordinateGetter:l_})),m=N.useCallback(S=>{f.current={inProgress:!0,lastSortTime:Date.now(),lastActiveId:S.active.id},l?.({activeId:S.active.id})},[l]),b=N.useCallback(S=>{const{active:E,over:A}=S,T=Date.now();if(!A||E.id===A.id){f.current.inProgress=!1;return}const{lastSortTime:L,lastActiveId:M,inProgress:R}=f.current;if(M===E.id&&T-L<500&&!R)return;f.current={inProgress:!1,lastSortTime:T,lastActiveId:E.id};const D=o.findIndex(j=>String(j[e])===String(E.id)),U=o.findIndex(j=>String(j[e])===String(A.id));if(D!==-1&&U!==-1&&D!==U){const j=Qd(o,D,U);i?.(j,{oldIndex:D,newIndex:U})}},[o,e,i]),v=o.map(S=>String(S[e]));return ut.jsx(HE,{id:d,sensors:g,collisionDetection:HC,onDragStart:m,onDragEnd:b,children:ut.jsx(QE,{items:v,strategy:u_[a],children:r})},u!==void 0?`${d}-v${u}`:d)},Gm=N.createContext(null),f_=({value:o,children:e})=>ut.jsx(Gm.Provider,{value:o,children:e}),h_=()=>N.useContext(Gm),g_=({id:o,handle:e,as:a="div",children:r})=>{const{attributes:i,listeners:l,setNodeRef:u,transform:d,transition:f,isDragging:g}=i_({id:o}),m={transform:po.Transform.toString(d),transition:f,opacity:g?.5:1,position:"relative"};return ut.jsx(a,{ref:u,style:m,...i,...e?{}:l,"data-sortable-item":!0,"data-sortable-id":String(o),"data-dragging":g,children:ut.jsx(f_,{value:{listeners:l,handle:e,isDragging:g},children:r})})},dt=ct("DynamicRenderer");function Qa(){try{return window.G7Core?.devTools}catch{return}}function ef(o,e,a,r){if(typeof o=="string"){if(/\$t:[a-zA-Z_][a-zA-Z0-9_.\-]*/.test(o))try{return e.resolveTranslations(o,a,r)}catch{return o}return o}if(Array.isArray(o))return o.map(i=>ef(i,e,a,r));if(o&&typeof o=="object"){const i={};for(const[l,u]of Object.entries(o))i[l]=ef(u,e,a,r);return i}return o}function p_(o){const e=Object.keys(o);return e.length>0&&e.every(a=>/^\d+$/.test(a))}const ya=(o,e)=>{const a=["errors"],r={...o};for(const i of Object.keys(e)){const l=e[i],u=o[i];if(l===null){r[i]=null;continue}if(a.includes(i)){r[i]=l;continue}if(Array.isArray(l)){r[i]=l;continue}if(Array.isArray(u)&&l!==null&&typeof l=="object"&&!Array.isArray(l)&&p_(l)){const d=Object.keys(l).map(g=>parseInt(g,10));if((d.length>0?Math.max(...d):0)>=u.length+d.length+10)r[i]={...l};else{const g=[...u];for(const[m,b]of Object.entries(l)){const v=parseInt(m,10);v>=0&&v=g.length&&(g[v]=b)}r[i]=g}}else l!==null&&typeof l=="object"&&u!==null&&typeof u=="object"&&!Array.isArray(u)?r[i]=ya(u,l):r[i]=l}return r},Vm=(o,e)=>{const a={...o};for(const r of Object.keys(e)){if(!(r in a))continue;const i=e[r],l=a[r];if(i!==null&&typeof i=="object"&&!Array.isArray(i)&&l!==null&&typeof l=="object"&&!Array.isArray(l)){const u=Vm(l,i);Object.keys(u).length===0?delete a[r]:a[r]=u}else delete a[r]}return a},m_=o=>{const e={},a=o.split(";").filter(r=>r.trim());for(const r of a){const i=r.indexOf(":");if(i===-1)continue;const l=r.substring(0,i).trim(),u=r.substring(i+1).trim();if(l&&u){const d=l.replace(/-([a-z])/g,(f,g)=>g.toUpperCase());e[d]=u}}return e};class y_ extends N.Component{constructor(e){super(e),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,a){dt.error(`컴포넌트 렌더링 에러 (ID: ${this.props.componentId}, Name: ${this.props.componentName}):`,e,a)}render(){return this.state.hasError?this.props.fallback?this.props.fallback:ut.jsxs("div",{className:"p-4 my-2 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg text-red-800 dark:text-red-400",children:[ut.jsx("div",{className:"font-semibold mb-1",children:"컴포넌트 로드 실패"}),ut.jsxs("div",{className:"text-xs opacity-80",children:[this.props.componentName&&`[${this.props.componentName}] `,"데이터를 표시할 수 없습니다."]}),this.state.error&&ut.jsxs("details",{className:"mt-2",children:[ut.jsx("summary",{className:"cursor-pointer text-xs opacity-70 hover:opacity-100",children:"상세 정보"}),ut.jsx("div",{className:"mt-1 p-2 bg-red-100 dark:bg-red-900/30 rounded text-xs font-mono whitespace-pre-wrap break-all",children:this.state.error.message})]})]}):this.props.children}}const Ha=N.memo(({componentDef:o,dataContext:e,translationContext:a,registry:r,bindingEngine:i,translationEngine:l,actionDispatcher:u,parentComponentContext:d,parentFormContextProp:f,parentDataContext:g,isRootRenderer:m=!1,isInsideIteration:b=!1,isEditMode:v=!1,onComponentSelect:S,onComponentHover:E,onDragStart:A,onDragEnd:T,componentPath:L,layoutKey:M})=>{const[R,D]=N.useState({loadingActions:{}});N.useLayoutEffect(()=>{d||(i.startRenderCycle(),window.__g7SetLocalOverrideKeys||(window.__g7ForcedLocalFields=void 0),window.__g7PendingLocalState=null)});const U=N.useRef(null);N.useLayoutEffect(()=>{if(!d&&e._localInit&&typeof e._localInit=="object"){const{_forceLocalInit:q,_merge:ce,...le}=e._localInit,Z=`${JSON.stringify(le)}:${q||"no-force"}`;if(U.current!==Z){U.current=Z;const be=ce||"shallow",Re=window.G7Core?.state?.get?.()?._local||{},xe=window.__g7PendingLocalState||{},je={...Re,...xe};be==="replace"?window.__g7PendingLocalState={loadingActions:je.loadingActions||{},...le,hasChanges:!1}:be==="deep"?window.__g7PendingLocalState=ya(je,{...le,hasChanges:!1}):window.__g7PendingLocalState={...je,...le,hasChanges:!1};const ze=window.__g7SetLocalOverrideKeys;ze&&typeof ze=="object"&&(be==="replace"?window.__g7SetLocalOverrideKeys={...le,hasChanges:!1}:window.__g7SetLocalOverrideKeys=ya(ze,{...le,hasChanges:!1}))}}}),N.useLayoutEffect(()=>{if(!d){const q=window.__g7SetLocalOverrideKeys;if(q){D(be=>Vm(be,q));const ce=q,le=window.__g7ForcedLocalFields,Z=window.__g7LastSetLocalSnapshot;queueMicrotask(()=>{window.__g7SetLocalOverrideKeys===ce&&(window.__g7SetLocalOverrideKeys=void 0),window.__g7ForcedLocalFields===le&&(window.__g7ForcedLocalFields=void 0),window.__g7LastSetLocalSnapshot===Z&&(window.__g7LastSetLocalSnapshot=void 0)})}}},[e._local]);const j=N.useRef(M);N.useEffect(()=>{o._fromBase&&M&&j.current!==M&&(j.current=M,D({loadingActions:{}}))},[M,o._fromBase]);const P=N.useRef(""),X=N.useRef(!1),ge=N.useRef(null),Ee=N.useRef({}),Ce=N.useRef({}),$e=N.useRef(g),Pe=SC(),Xe=Q0(),ht=Xe?.getParentDataContext()??g;N.useEffect(()=>{if(e._localInit&&typeof e._localInit=="object"){const{_forceLocalInit:q,...ce}=e._localInit,le=JSON.stringify(ce),Z=q!==void 0,be=Ld(),ve=`${le}:${q||"no-force"}`;if(be.hash!==ve){be.hash=ve,be.timestamp=q,P.current=le,Z&&(X.current=!0);const{_merge:je,...ze}=ce,Le=je||"shallow";if(D(ke=>Le==="replace"?{loadingActions:ke.loadingActions||{},...ze,hasChanges:!1}:Le==="deep"?ya(ke,{...ze,hasChanges:!1}):{...ke,...ze,hasChanges:!1}),e._globalSetState){const ke=e._global?._local||{};let We;Le==="replace"?We={...ze,hasChanges:!1}:Le==="deep"?We=ya(ke,{...ze,hasChanges:!1}):We={...ke,...ze,hasChanges:!1},e._globalSetState({_local:We})}i.invalidateCacheByKeys(["_local"]),dt.log("_localInit applied (data changed):",Object.keys(ce))}ge.current=e._localInit,aC(e._localInit)}},[e._localInit,g,i]);const{isTransitioning:Q}=nm(),fe=dC(),ye=f??fe,{width:te}=$d(),he=h_(),x=N.useMemo(()=>{let q=o;if(o.type==="iterator"&&o.data){const{data:Z,itemName:be,indexName:ve,...Re}=o;q={...Re,iteration:{source:Z,item_var:be||"item",index_var:ve}}}if(!q.responsive)return q;const ce=ui.getMatchingKey(q.responsive,te);if(!ce)return q;const le=q.responsive[ce];return{...q,props:{...q.props,...le.props},children:le.children??q.children,text:le.text??q.text,if:le.if??q.if,iteration:le.iteration??q.iteration,__responsiveChildrenKey:le.children!==void 0?ce:void 0}},[o,te]),K=N.useCallback(q=>{const ce=q?.__setStateId;if(D(le=>{const Z=window.__g7PendingLocalState,ve=window.__g7SetLocalOverrideKeys||Z,Re=ve?ya(le,ve):le;if(typeof q=="function"){const ke=q(Re);return ya(Re,ke)}const{__mergeMode:xe,__setStateId:je,...ze}=q;let Le;if(xe==="replace"?Le=ze:xe==="shallow"?Le={...Re,...ze}:Le=ya(Re,ze),xe!==void 0){const ke=window.__g7ForcedLocalFields;ke&&(window.__g7ForcedLocalFields={...ke,...ze})}return Le}),ce){const le=Qa();if(le?.isEnabled()){const Z=x.id||"unknown",be=x.name||"Unknown";setTimeout(()=>{le.trackComponentRender?.(Z,be,0,["_local"],[]),le.completeStateChange?.(ce)},0)}}},[x.id,x.name]),re=d?.state??R,de=d?.setState??K,ie=N.useMemo(()=>{const q=e._localInit&&e._localInit!==ge.current;let ce;q&&e._local?ce=e._local:ce=e._local?ya(e._local,re):re;const le=window.__g7ForcedLocalFields;le&&(ce=ya(ce,le));const Z={...e,_local:ce},be=e._computedDefinitions;if(be&&Object.keys(be).length>0){const ve=new wn,Re={...Z,...Pe?{_isolated:Pe.state}:{}},xe={},je=Qa(),ze=je?.isEnabled()??!1;for(const[Le,ke]of Object.entries(be)){const We=ze?Date.now():0,Fe=ze?e._computed?.[Le]:void 0;let _e;try{if(typeof ke=="string")if(ke.startsWith("{{")&&ke.endsWith("}}")){const Te=ke.slice(2,-2).trim(),Ue=ve.evaluateExpression(Te,Re,{skipCache:!0});xe[Le]=Ue}else xe[Le]=ke;else if(ke&&typeof ke=="object"&&"$switch"in ke){const Te=ve.resolveSwitch(ke,Re,{skipCache:!0});xe[Le]=Te}}catch(Te){dt.warn(`Failed to recalculate computed value: ${Le}`,Te),xe[Le]=e._computed?.[Le],_e=Te instanceof Error?Te.message:String(Te)}if(ze&&(_e||Fe!==xe[Le])){const Ue=Date.now()-We;je.trackComputedProperty?.(Le,typeof ke=="string"?ke:JSON.stringify(ke),[{type:"_local",path:"_local",value:Z._local}],xe[Le],Ue,x.id,_e),Fe!==xe[Le]&&je.trackComputedRecalc?.(Le,"dependency-change",Fe,xe[Le],Ue,{type:"_local",path:"_local"},x.id)}}Z._computed=xe}if(Pe&&(Z._isolated=Pe.state),ht&&(Z.$parent=ht),o.extensionPointProps){const ve=i.resolveObject(o.extensionPointProps,Z,b?{skipCache:!0}:void 0);Z.extensionPointProps=v&&l?ef(ve,l,a,Z):ve}return o.extensionPointCallbacks&&(Z.extensionPointCallbacks=o.extensionPointCallbacks),v&&(Z.$templateId===void 0&&a?.templateId&&(Z.$templateId=a.templateId),Z.$locale===void 0&&a?.locale&&(Z.$locale=a.locale)),Z},[e,re,Pe?.state,ht,Xe?.version,o.extensionPointProps,o.extensionPointCallbacks]);Ee.current=ie._local,Ce.current=ie._computed||{},$e.current=ht,N.useEffect(()=>{const q=Qa();if(!q?.isEnabled())return;const ce=ie._local;ce&&q.updateLocalState(ce);const le=ie._computed;le&&q.updateComputedState(le),ht&&q.updateParentContext?.(ht);const Z=x.id||`comp-${Date.now()}`,be=x.name||"Unknown",ve={global:Object.keys(e._global||{}),local:Object.keys(ce||{}),context:d?Object.keys(d.state||{}):[]},Re={type:d?"componentContext":"dynamicState",hasComponentContext:!!d,parentId:d?"parent":void 0};q.trackComponentStateSource?.(Z,be,ve,Re),re&&Object.keys(re).length>0&&q.trackDynamicState?.(Z,re);const xe=!!(x.expandChildren||x.props?.expandChildren);q.trackContextFlow?.(Z,be,!!d,xe,!0)},[ie._local,e,x.id,x.name,d,re,x.expandChildren,x.props?.expandChildren,ht]);const me=N.useMemo(()=>({state:{...ie._local},setState:de,stateRef:Ee,computedRef:Ce,isolatedContext:Pe,parentDataContext:ie}),[ie._local,de,R,Pe,ie]),Ne=N.useMemo(()=>{const q=Xi({if:x.if,condition:x.condition,conditions:x.conditions},ie,i,x.id);if(x.if||x.condition!==void 0||x.conditions){const le=Qa();le?.isEnabled()&&x.if&&le.trackIfCondition(x.id||`if-${Date.now()}`,x.if,q)}return q},[x.if,x.conditions,ie,i,x.id]),Se=N.useMemo(()=>{if(!x.slot)return null;const q=x.slot;if(q.startsWith("{{")&&q.endsWith("}}")){const ce=q.slice(2,-2).trim();try{const le={componentId:x.id,componentName:x.name,propName:"slot"},Z=i.evaluateExpression(ce,ie,le);return dt.log(`[Slot] 표현식 평가: "${ce}" => "${Z}" (컴포넌트: ${x.id})`),typeof Z=="string"?Z:null}catch(le){return dt.warn(`slot 표현식 평가 실패 (컴포넌트: ${x.id}):`,le),null}}return dt.log(`[Slot] 정적 슬롯 ID: "${q}" (컴포넌트: ${x.id})`),q},[x.slot,x.id,ie,i]),He=N.useMemo(()=>!Se||!x.id?"":`${x.id}-${Se}-${JSON.stringify(x.slotOrder??0)}`,[Se,x.id,x.slotOrder]),Ae=N.useRef(null);N.useEffect(()=>{const q=window.__slotContextValue,ce=q?.isEnabled??!1;if(x.slot&&dt.log(`[Slot Registration] 컴포넌트: ${x.id}, isSlotEnabled: ${ce}, shouldRender: ${Ne}, resolvedSlotId: ${Se}`),!ce||!Ne){x.slot&&dt.log(`[Slot Registration] 등록 스킵 - isSlotEnabled: ${ce}, shouldRender: ${Ne}`),Ae.current&&x.id&&q&&(q.unregisterFromSlot(Ae.current,x.id),Ae.current=null);return}if(!Se||!x.id){x.slot&&dt.log(`[Slot Registration] 등록 스킵 - resolvedSlotId: ${Se}, id: ${x.id}`),Ae.current&&x.id&&q&&(q.unregisterFromSlot(Ae.current,x.id),Ae.current=null);return}Ae.current&&Ae.current!==Se&&q.unregisterFromSlot(Ae.current,x.id);const le={...x,slot:void 0,slotOrder:void 0};return q.registerToSlot(Se,x.id,{componentDef:le,dataContext:e,order:x.slotOrder??0,parentFormContext:f??null,getParentComponentContext:()=>me,translationContext:a,registrationKey:He}),Ae.current=Se,()=>{const Z=window.__slotContextValue;Se&&x.id&&Z&&Z.unregisterFromSlot(Se,x.id)}},[Ne,Se,x,e,f,me,a,He]);const Et=N.useCallback(q=>{if(typeof q=="string"){if(rp(q))return sp(q);if(ip(q)){const ce=[],le=q.replace(new RegExp(`${Rl}([^${Ys}]*)${Ys}`,"g"),(be,ve)=>(ce.push(ve),`${_r}${ce.length-1}${_r}`));let Z=le;return/\$t:[a-zA-Z0-9._-]+/.test(le)&&(Z=l.resolveTranslations(le,a,ie)),Z.replace(new RegExp(`${_r}(\\d+)${_r}`,"g"),(be,ve)=>ce[parseInt(ve)])}if(q.startsWith("$t:defer:"))return q;if(/\$t:[a-zA-Z0-9._-]+/.test(q)){const ce=q.trim();return ce.startsWith("{")&&ce.endsWith("}")||ce.startsWith("[")&&ce.endsWith("]")?q:l.resolveTranslations(q,a,ie)}return q}if(Array.isArray(q))return q.map(ce=>Et(ce));if(q&&typeof q=="object"){const ce={};for(const[le,Z]of Object.entries(q))ce[le]=Et(Z);return ce}return q},[l,a,ie]),kt=N.useCallback(q=>/[?:|&!+\-*/<>=()]/.test(q),[]),_t=N.useCallback(q=>{if(!q.startsWith("{{")||!q.endsWith("}}"))return null;const ce=q.slice(2,-2);let le=null,Z=0;for(let be=0;be0?ce[be-1]:"")!=="\\"&&((ve==='"'||ve==="'")&&!le?le=ve:ve===le&&(le=null),!le&&(ve==="{"&&Z++,ve==="}"&&Z--,Z<0)))return null}return Z===0?ce.trim():null},[]),ft=N.useMemo(()=>{let q={...x.props||{}};const ce=["cellChildren","expandChildren","expandContext","render"],Z=r.getMetadata(x.name)?.skipBindingKeys||[],be=[...new Set([...ce,...Z])],ve=b?{skipCache:!0}:void 0,Re=_e=>{if(ve)return ve;if(_e.startsWith("_computed")||_e.startsWith("$computed"))return{skipCache:!0}};for(const[_e,Te]of Object.entries(q))if(!be.includes(_e))if(typeof Te=="string"){const Ue=_t(Te);if(Ue!==null){let st=!1,At=Ue;Ue.startsWith(Er)&&(st=!0,At=Ue.slice(Er.length));const Wt={componentId:x.id,componentName:x.name,propName:_e};let qt;if(ci(At))qt=i.resolveBindings(`{{${At}}}`,ie,ve,Wt);else if(kt(At))try{qt=i.evaluateExpression(At,ie,Wt)}catch(qn){dt.warn(`표현식 평가 실패 (컴포넌트: ${x.id}, prop: ${_e}):`,qn),qt=void 0}else qt=i.resolve(At,ie,Re(At),Wt);q[_e]=st&&qt!=null?Js(qt):qt}else{const st={componentId:x.id,componentName:x.name,propName:_e};q[_e]=i.resolveBindings(Te,ie,ve,st)}}else Array.isArray(Te)?q[_e]=Te.map(Ue=>typeof Ue=="string"?i.resolveBindings(Ue,ie,ve):typeof Ue=="object"&&Ue!==null?i.resolveObject(Ue,ie,ve):Ue):Te&&typeof Te=="object"&&(q[_e]=i.resolveObject(Te,ie,ve));for(const[_e,Te]of Object.entries(q))q[_e]=Et(Te);if(typeof q.style=="string"&&(q.style=m_(q.style)),q=ld(q,v?void 0:x.actions,ie,{componentContext:me,actionDispatcher:u}),x.classMap){const _e=ow(x.classMap,ie,i,{skipCache:!0});if(_e){const Te=q.className||"";q.className=Te?`${Te} ${_e}`:_e}}x.style&&(q.style=x.style),x.actions&&x.actions.length>0&&x.type==="composite"&&Object.assign(q,re),x.component_layout&&(q.__componentLayoutDefs=x.component_layout);const xe=x.expandChildren||x.props?.expandChildren,je=x.props?.cellChildren,ze=x.children&&x.children.length>0,Le=x.component_layout,ke=x.slot,We=x.props?.modalId,Fe=x.type==="composite";return(xe||je||ze||Le||ke||We||Fe)&&(q.__componentContext=me),q},[x.props,x.actions,x.style,x.classMap,x.id,ie,a,i,l,me,re,Et,kt,_t,b]),un=N.useRef(null),gt=N.useMemo(()=>un.current&&rm(un.current,ft)?un.current:(un.current=ft,ft),[ft]),ja=N.useMemo(()=>{const q=x.id;if(typeof q!="string"||!q.includes("{{"))return q;const ce=i.resolveBindings(q,ie,{skipCache:!0});return typeof ce=="string"?ce:q},[x.id,ie,i]),kn=N.useMemo(()=>{const q=x.dataKey,ce=x.trackChanges,le=x.debounce;if(q){const Z=q.startsWith("_global."),be=Z?q.slice(8):q,ve=Z?e._global:ie._local;return{dataKey:be,trackChanges:ce??!1,debounce:le,setState:Z?xe=>{e._globalSetState?e._globalSetState(xe):dt.warn("_global.formData 사용 시 _globalSetState가 필요합니다.")}:de,state:ve??{},_isGlobal:Z}}if(ye.dataKey)return ye},[x.dataKey,x.trackChanges,x.debounce,x.id,de,ie._local,e._global,e._globalSetState,ye]),Dn=N.useRef(new Set);N.useEffect(()=>{Dn.current.clear()},[e._global?._remountKeys]);const jt=N.useCallback((q,ce)=>{const le=e._global?._remountKeys;return q&&le?.[q]&&!Dn.current.has(q)?(Dn.current.add(q),`${q}-remount-${le[q]}`):q||ce},[e._global?._remountKeys]),On=N.useMemo(()=>{if(x.text!==void 0){if(typeof x.text=="string"){const q=x.text;let ce=q;const le={componentId:x.id,componentName:x.name,propName:"text",skipCache:!0},Z=_t(q);if(Z!==null)if(ci(Z))ce=i.resolveBindings(q,ie,{skipCache:!0},le);else if(kt(Z))try{ce=i.evaluateExpression(Z,ie,le)}catch(be){dt.warn(`text 표현식 평가 실패 (컴포넌트: ${x.id}):`,be),ce=""}else ce=i.resolve(Z,ie,{skipCache:!0},le);else q.includes("{{")&&(ce=i.resolveBindings(q,ie,{skipCache:!0},le));return ce=Et(ce),ce??""}return x.text}return!x.children||x.children.length===0?null:x.children.map((q,ce)=>{if(typeof q=="string")return q;const le=x.__responsiveChildrenKey,Z=le?`responsive.${le}.children`:"children",be=L?`${L}.${Z}.${ce}`:`${ce}`,ve=q._fromBase?q.id||`child-${ce}`:jt(q.id,`child-${ce}`),Re=!q._fromBase&&M?`${ve}_${M}`:ve;return ut.jsx(Ha,{componentDef:q,dataContext:ie,translationContext:a,registry:r,bindingEngine:i,translationEngine:l,actionDispatcher:u,parentComponentContext:me,parentFormContextProp:kn,isInsideIteration:b,isEditMode:v,onComponentSelect:S,onComponentHover:E,componentPath:be,onDragStart:A,onDragEnd:T,layoutKey:M},Re)})},[x.text,x.children,x.id,e,ie,a,r,i,l,u,me,kn,_t,kt,Et,jt,b,v,S,E,L,A,T,M]),ea=N.useMemo(()=>{if(!x.iteration)return null;try{const q=od(x.iteration.source,ie,i);if(!Array.isArray(q))return dt.warn(`iteration source가 배열이 아닙니다 (컴포넌트: ${x.id}):`,q),null;const ce=Qa();return ce?.isEnabled()&&ce.trackIteration(x.id||`iteration-${Date.now()}`,x.iteration.source,x.iteration.item_var,x.iteration.index_var,q.length),q.map((le,Z)=>{const be={...ie,[x.iteration.item_var]:le};x.iteration.index_var&&(be[x.iteration.index_var]=Z);const ve=Z===0||Z===q.length-1;ce?.isEnabled()&&ve&&ce.trackNestedContext?.({componentId:`${x.id||"unknown"}-iter-${Z}`,componentType:"iteration",parentContext:{available:Object.keys(ie),values:{}},ownContext:{added:[x.iteration.item_var,...x.iteration.index_var?[x.iteration.index_var]:[]],values:{[x.iteration.item_var]:le,...x.iteration.index_var?{[x.iteration.index_var]:Z}:{}}},depth:1});const Re={...x,iteration:void 0,responsive:void 0},xe=L?`${L}.iteration.${Z}`:`iteration.${Z}`,je=`${jt(x.id,"item")}-${Z}`;return ut.jsx(Ha,{componentDef:Re,dataContext:be,translationContext:a,registry:r,bindingEngine:i,translationEngine:l,actionDispatcher:u,parentComponentContext:me,parentFormContextProp:kn,isInsideIteration:!0,isEditMode:v,onComponentSelect:S,onComponentHover:E,componentPath:xe,onDragStart:A,onDragEnd:T,layoutKey:M},je)})}catch(q){return dt.error(`iteration 렌더링 실패 (컴포넌트: ${x.id}):`,q),null}},[x.iteration,x.children,x.id,e,ie,a,r,i,l,u,me,kn,jt,v,S,E,L,A,T,M]),[Ua,Kt]=N.useState(0),Dr=N.useMemo(()=>{if(!x.sortable||!x.itemTemplate)return null;const{sortable:q,itemTemplate:ce}=x;try{const le=od(q.source,ie,i);if(!Array.isArray(le))return dt.warn(`sortable source가 배열이 아닙니다 (컴포넌트: ${x.id}):`,le),null;if(le.length===0)return null;const Z=q.itemKey||"id",be=q.strategy||"verticalList",ve=q.itemVar||"$item",Re=q.indexVar||"$index",xe=q.handle,je=q.wrapperElement,ze=(We,Fe)=>{const _e=x.actions?.filter(Te=>Te.event==="onSortEnd"||Te.type==="onSortEnd");if(Kt(Te=>Te+1),_e&&_e.length>0&&u){const Te={...ie,$sortedItems:We,$sortEvent:Fe};_e.forEach(Ue=>{try{const st=u.createHandler(Ue,Te,me),At=new Event("sortend");st(At)}catch(st){dt.error(`onSortEnd action failed: ${Ue.handler}`,st)}})}},Le=We=>{const Fe=x.actions?.filter(_e=>_e.event==="onSortStart"||_e.type==="onSortStart");if(Fe&&Fe.length>0&&u){const _e={...ie,$activeId:We.activeId};Fe.forEach(Te=>{try{const Ue=u.createHandler(Te,_e,me),st=new Event("sortstart");Ue(st)}catch(Ue){dt.error(`onSortStart action failed: ${Te.handler}`,Ue)}})}},ke=le.map((We,Fe)=>{const _e=String(We[Z]),Te={...ie,[ve]:We,[Re]:Fe},Ue=L?`${L}.sortable.${Fe}`:`sortable.${Fe}`,st=`${jt(x.id,"sortable-item")}-v${Ua}-${_e}`;return ut.jsx(g_,{id:_e,handle:xe,...je?{as:je}:{},children:(je&&ce.children?ce.children:[ce]).map((At,Wt)=>ut.jsx(Ha,{componentDef:At,dataContext:Te,translationContext:a,registry:r,bindingEngine:i,translationEngine:l,actionDispatcher:u,parentComponentContext:me,parentFormContextProp:void 0,isInsideIteration:!0,isEditMode:v,onComponentSelect:S,onComponentHover:E,componentPath:Ue,onDragStart:A,onDragEnd:T,layoutKey:M},`${st}-child-${Wt}`))},st)});return ut.jsx(d_,{items:le,itemKey:Z,strategy:be,onSortEnd:ze,onSortStart:Le,sortVersion:Ua,children:ke})}catch(le){return dt.error(`sortable 렌더링 실패 (컴포넌트: ${x.id}):`,le),null}},[x.sortable,x.itemTemplate,x.actions,x.id,e,ie,a,r,i,l,u,me,jt,v,S,E,L,A,T,Ua,M]),er=N.useRef(!1);N.useEffect(()=>{if(er.current)return;er.current=!0;const q=Qa();if(q?.isEnabled()&&q.trackMount(o.id,{name:o.name,type:o.type||"component",props:gt}),o.lifecycle?.onMount&&o.lifecycle.onMount.length>0)for(const le of o.lifecycle.onMount)try{const Z=u.createHandler(le,ie,me),be=new Event("mount");Z(be),dt.log(`Lifecycle onMount executed: ${le.handler} (Component: ${o.id})`)}catch(Z){dt.error(`Lifecycle onMount failed: ${le.handler} (Component: ${o.id})`,Z)}const ce=[];if(o.onComponentEvent&&o.onComponentEvent.length>0){const le=window.G7Core;if(le?.componentEvent?.on)for(const Z of o.onComponentEvent){if(!Z.event){dt.warn(`onComponentEvent: event name is required (Component: ${o.id})`);continue}const be=async Re=>{try{const xe={...ie,_eventData:Re},ze=await u.createHandler({handler:Z.handler,params:Z.params,onSuccess:Z.onSuccess,onError:Z.onError},xe,me)(new CustomEvent(Z.event,{detail:Re}));return dt.log(`onComponentEvent "${Z.event}" handled: ${Z.handler} (Component: ${o.id})`,{eventData:Re,result:ze}),ze}catch(xe){throw dt.error(`onComponentEvent "${Z.event}" failed: ${Z.handler} (Component: ${o.id})`,xe),xe}},ve=le.componentEvent.on(Z.event,be);ce.push(ve),dt.log(`onComponentEvent: Subscribed to "${Z.event}" (Component: ${o.id})`)}else dt.warn(`onComponentEvent: G7Core.componentEvent is not available (Component: ${o.id})`)}return()=>{const le=Qa();le?.isEnabled()&&le.trackUnmount(o.id);for(const Z of ce)try{Z()}catch(be){dt.error(`onComponentEvent: Failed to unsubscribe (Component: ${o.id})`,be)}if(ce.length>0&&dt.log(`onComponentEvent: Unsubscribed ${ce.length} event(s) (Component: ${o.id})`),o.lifecycle?.onUnmount&&o.lifecycle.onUnmount.length>0)for(const Z of o.lifecycle.onUnmount)try{const be=u.createHandler(Z,ie,me),ve=new Event("unmount");be(ve),dt.log(`Lifecycle onUnmount executed: ${Z.handler} (Component: ${o.id})`)}catch(be){dt.error(`Lifecycle onUnmount failed: ${Z.handler} (Component: ${o.id})`,be)}}},[]);const bn=N.useMemo(()=>{const q=gt.dataKey,ce=gt.trackChanges,le=gt.debounce;return q?{dataKey:q,trackChanges:ce??!1,debounce:le,setState:de,state:re}:null},[gt.dataKey,gt.trackChanges,gt.debounce,de,re]);N.useEffect(()=>{const q=x.dataKey||gt.dataKey;if(!q)return;const ce=Qa();if(!ce?.isEnabled())return;const le=[],Z=ve=>{if(ve)for(const Re of ve){const xe=Re?.props?.name;if(xe&&le.push({name:xe,type:Re.name||Re.type||"unknown"}),Re?.children&&Z(Re.children),Re?.slots)for(const je of Object.values(Re.slots))Array.isArray(je)&&Z(je)}};if(o.children&&Z(o.children),o.slots)for(const ve of Object.values(o.slots))Array.isArray(ve)&&Z(ve);const be=o.id||`form-${q}`;return ce.trackForm(be,q,le),()=>{ce.untrackForm(be)}},[x,gt.dataKey,o.id,o.children]);const tn=N.useRef(null),et=N.useRef(void 0);N.useEffect(()=>{const q=gt?.name;if(!q||!ye.dataKey||!ye.setState||gt?.autoBinding===!1)return;const ce=`${ye.dataKey}.${q}`,le=window.__g7AutoBindingPaths??new Map;return window.__g7AutoBindingPaths=le,le.set(ce,(le.get(ce)??0)+1),()=>{const Z=le.get(ce)??0;Z<=1?le.delete(ce):le.set(ce,Z-1)}},[gt?.name,gt?.autoBinding,ye.dataKey,ye.setState]);const ta=N.useMemo(()=>{const{dataKey:q,trackChanges:ce,debounce:le,...Z}=gt,be=Z.name;if(!be||!ye.dataKey||!ye.setState)return Z;if(Z.autoBinding===!1){const{autoBinding:_e,...Te}=Z;return Te}const ve=`${ye.dataKey}.${be}`,Re=fC(ye.state,ve),xe=Re!==void 0?Re:Z.value,ze=r.getMetadata(o.name)?.bindingType,Le=typeof xe=="boolean"&&(ze==="checked"||ze==="checkable"&&["checkbox","radio"].includes(Z?.type)),ke=ye.debounce,We=_e=>{const Te=ye.state||{},Ue=hC(Te,ve,_e);if(ye.trackChanges&&(Ue.hasChanges=!0),window.__g7PendingLocalState=Ue,ye.setState(Ue),ye._isGlobal)return;const st=window.G7Core,At={[ve]:_e};ye.trackChanges&&(At.hasChanges=!0),st?.state?.setLocal?.(At,{render:!1})},Fe=(_e,Te)=>{ke&&ke>0?(tn.current&&clearTimeout(tn.current),tn.current=setTimeout(()=>{We(_e),tn.current=null,Te&&(Te(),window.__g7PendingLocalState=null)},ke)):(We(_e),Te&&(Te(),window.__g7PendingLocalState=null))};if(Le)return{...Z,checked:xe,onChange:Te=>{const Ue=Te.target.checked;We(Ue),Z.onChange&&Z.onChange(Te)}};{const _e=Ue=>{const st=Ue?.target?.value!==void 0?Ue.target.value:Ue;ke&&ke>0&&(et.current=st);const At=Ue?.target?{target:{value:st,name:Ue.target.name,type:Ue.target.type,checked:Ue.target.checked},currentTarget:Ue.currentTarget?{value:st,name:Ue.currentTarget.name}:void 0}:Ue;Fe(st,()=>{Z.onChange&&Z.onChange(At)})};let Te;return et.current!==void 0?tn.current!==null?Te=et.current:String(xe??"")===String(et.current)?(et.current=void 0,Te=xe??""):Te=et.current:Te=xe??"",{...Z,value:Te,onChange:_e}}},[gt,ye,ye.state,ye.debounce]),En=N.useMemo(()=>{const q=Qa();if(q?.isEnabled()&&q.trackRender(o.name),!Ne)return null;if(x.sortable&&x.itemTemplate)return Dr;if(x.iteration)return ea;if(x.type==="extension_point"){const{layout:ze,columns:Le,gap:ke,className:We,...Fe}=x.props||{};let _e=We||"";return ze==="grid"&&Le?_e=`${_e} grid grid-cols-${Le} gap-${ke||4}`.trim():ze==="flex"&&(_e=`${_e} flex flex-col gap-${ke||4}`.trim()),ut.jsx("div",{id:ja,className:_e||void 0,...Fe,children:On})}const ce=r.getComponent(x.name);if(!ce)return dt.error(`컴포넌트를 찾을 수 없습니다: ${x.name} (ID: ${x.id})`,"componentDef:",JSON.stringify(x,null,2)),null;const le=e._global?._remountKeys,Z={...ta,id:ta.id??ja,...le&&Object.keys(le).length>0&&{__remountTrigger:JSON.stringify(le)}};if(he?.listeners&&he.handle&&ta["data-drag-handle"]!==void 0&&(Object.assign(Z,he.listeners),Z.style={...Z.style,cursor:he.isDragging?"grabbing":"grab"}),v){const ze=x.id||`auto_${x.name||x.type||"unknown"}_${Math.random().toString(36).substring(2,8)}`,Le=Fe=>{typeof Fe.preventDefault=="function"&&Fe.preventDefault(),S&&(Fe.stopPropagation(),S(ze,Fe))},ke={"data-editor-id":ze,"data-editor-name":x.name,"data-editor-type":x.type,onClick:Le};L&&(ke["data-editor-path"]=L);const We=x.__editorSlotName??x.slot;typeof We=="string"&&(ke["data-editor-slot"]=We),E&&(ke.onMouseMove=Fe=>{Fe.stopPropagation(),E(ze,Fe)},ke.onMouseLeave=Fe=>{E(null,Fe)}),Object.assign(Z,ke),Z.editorAttrs=ke}const be=x.type==="basic",ve=x.type==="layout",xe=be||ve?(()=>{const ze={};for(const[Le,ke]of Object.entries(Z))Le.startsWith("__")||Le==="editorAttrs"&&be||(ze[Le]=ke);return ze})():Z;let je=ut.jsx(ce,{...xe,children:On});if(kn&&(je=ut.jsx(uC,{value:kn,children:je})),x.isolatedState){const ze=typeof x.isolatedState=="object"?x.isolatedState:{},Le=e?._isolatedInit,ke=Le?{...ze,...Le}:ze;je=ut.jsx(vC,{initialState:ke,scopeId:x.isolatedScopeId,children:je})}return je},[Ne,x.iteration,x.sortable,x.itemTemplate,x.type,x.name,x.id,x.props,x.isolatedState,x.isolatedScopeId,r,ta,On,ea,Dr,he,bn,v,S,E,A,T,L,e._global?._remountKeys]),tr=N.useMemo(()=>{const q=x.blur_until_loaded;if(!q||e?._global?.__isPreview)return!1;if(typeof q=="string"){const Z=_t(q);if(Z!==null)try{const be={componentId:x.id,componentName:x.name,propName:"blur_until_loaded"};return!!i.evaluateExpression(Z,ie,be)}catch(be){return dt.warn(`blur_until_loaded 표현식 평가 실패 (컴포넌트: ${x.id}):`,be),!1}return!1}if(typeof q=="object"&&q!==null){if(!q.enabled)return!1;if(q.data_sources)return(Array.isArray(q.data_sources)?q.data_sources:[q.data_sources]).some(Re=>e[Re]===void 0);if(Q)return!0;const Z=["route","query","_global","_local","_dataSourceErrors"];return Object.keys(e).filter(ve=>!Z.includes(ve)&&!ve.startsWith("_")).some(ve=>e[ve]===void 0)}if(Q)return!0;const ce=["route","query","_global","_local","_dataSourceErrors"];return Object.keys(e).filter(Z=>!ce.includes(Z)&&!Z.startsWith("_")).some(Z=>e[Z]===void 0)},[x.blur_until_loaded,x.id,Q,e,ie,i,_t]);if(tr){const q=x.blur_until_loaded;if(typeof q=="object"&&q?.data_sources){const le=(Array.isArray(q.data_sources)?q.data_sources:[q.data_sources]).reduce((be,ve)=>(be[ve]=e[ve]===void 0?"UNDEFINED":"LOADED",be),{}),Z=Object.keys(e).filter(be=>!be.startsWith("_"));dt.log(`[BLUR APPLIED] Component: ${x.id}, data_sources status:`,le,"Available keys:",Z)}else dt.log(`[BLUR APPLIED] Component: ${x.id}, blur_until_loaded:`,q)}const Ea=N.useMemo(()=>{if(!x.blur_until_loaded)return{wrapperClasses:"",innerClasses:""};const q=ft?.className||"";if(!q)return{wrapperClasses:"",innerClasses:""};const ce=[/^(sm:|md:|lg:|xl:|2xl:)?(col-span-|row-span-|col-start-|col-end-|row-start-|row-end-)/,/^(sm:|md:|lg:|xl:|2xl:)?(self-|place-self-|order-)/,/^(sm:|md:|lg:|xl:|2xl:)?(flex-shrink|flex-grow|flex-\d|basis-)/],le=q.split(/\s+/).filter(Boolean),Z=[],be=[];for(const ve of le)ce.some(xe=>xe.test(ve))?Z.push(ve):be.push(ve);return{wrapperClasses:Z.join(" "),innerClasses:be.join(" ")}},[x.blur_until_loaded,ft?.className]),nn=window.__slotContextValue;return Se&&nn?.isEnabled?null:ut.jsx(y_,{componentId:o.id,componentName:o.name,children:x.blur_until_loaded?ut.jsx("div",{className:[Ea.wrapperClasses,tr?"opacity-50 blur-sm transition-all duration-300 pointer-events-none":void 0].filter(Boolean).join(" ")||void 0,children:En}):En})});Ha.displayName="DynamicRenderer",typeof window<"u"&&(window.__DynamicRenderer=Ha);function b_(o){const e={};try{const r=new URL(o,typeof window<"u"?window.location.origin:"http://localhost").searchParams,i=new Set;for(const l of r.keys()){if(i.has(l))continue;i.add(l);const u=r.getAll(l);u.length>1||l.endsWith("[]")?e[l]=u:e[l]=u[0]}}catch{}return e}function v_(o){try{return new URL(o,typeof window<"u"?window.location.origin:"http://localhost").pathname}catch{return o.split("?")[0]}}const yi=class yi{constructor(){$(this,"config",{enabled:!1,maxHistorySize:100,logLevel:"info",serverEndpoint:"/_boost/g7-debug/dump-state",autoCapture:!0});$(this,"stateHistory",[]);$(this,"snapshotIdCounter",0);$(this,"stateWatchers",new Map);$(this,"currentLocalState",{});$(this,"currentComputedState",{});$(this,"currentParentContext");$(this,"actionHistory",[]);$(this,"actionWatchers",new Set);$(this,"cacheStats",{hits:0,misses:0,entries:0});$(this,"cacheDecisions",[]);$(this,"cacheDecisionIdCounter",0);$(this,"maxCacheDecisions",200);$(this,"currentRenderCycleId",null);$(this,"isInActionExecution",!1);$(this,"isInIteration",!1);$(this,"mountedComponents",new Map);$(this,"eventListeners",new Map);$(this,"mountWatchers",new Set);$(this,"unmountWatchers",new Set);$(this,"renderCounts",new Map);$(this,"bindingEvalCount",0);$(this,"profilingData",[]);$(this,"isProfiling",!1);$(this,"profilingStartTime",0);$(this,"activeRequests",new Map);$(this,"requestHistory",[]);$(this,"pendingDataSources",new Set);$(this,"requestWatchers",new Set);$(this,"wsConnections",new Map);$(this,"wsMessageHistory",[]);$(this,"wsMessageWatchers",new Set);$(this,"ifConditions",new Map);$(this,"iterations",new Map);$(this,"conditionWatchers",new Set);$(this,"forms",new Map);$(this,"formWatchers",new Set);$(this,"expressionHistory",[]);$(this,"expressionWatchers",new Set);$(this,"expressionIdCounter",0);$(this,"dataSources",new Map);$(this,"dataPathTransforms",[]);$(this,"maxDataPathTransforms",100);$(this,"nestedContexts",[]);$(this,"nestedContextIdCounter",0);$(this,"maxNestedContexts",100);$(this,"formBindingIssues",[]);$(this,"formBindingValidations",[]);$(this,"formBindingIssueIdCounter",0);$(this,"maxFormBindingIssues",100);$(this,"computedProperties",new Map);$(this,"computedRecalcLogs",[]);$(this,"computedRecalcIdCounter",0);$(this,"maxComputedRecalcLogs",100);$(this,"handlers",new Map);$(this,"componentEventSubscriptions",new Map);$(this,"componentEventEmitHistory",[]);$(this,"componentEventIdCounter",0);$(this,"maxComponentEventHistory",100);$(this,"stateRenderingLogs",[]);$(this,"currentStateChangeContext",null);$(this,"stateRenderingIdCounter",0);$(this,"componentRenderCounts",new Map);$(this,"stateToComponentMap",new Map);$(this,"maxStateRenderingLogs",100);$(this,"componentStateSources",new Map);$(this,"contextFlowNodes",new Map);$(this,"dynamicStates",new Map);$(this,"styleIssues",[]);$(this,"componentStyles",new Map);$(this,"authEvents",[]);$(this,"authHeaderHistory",[]);$(this,"authEventIdCounter",0);$(this,"maxAuthEventHistory",50);$(this,"logHistory",[]);$(this,"logIdCounter",0);$(this,"maxLogHistory",500);$(this,"currentLayout",null);$(this,"layoutHistory",[]);$(this,"layoutIdCounter",0);$(this,"layoutStats",{totalLoads:0,cacheHits:0,apiLoads:0});$(this,"maxLayoutHistory",50);$(this,"executionDetails",new Map);$(this,"stateChangeHistory",[]);$(this,"dataSourceChangeHistory",[]);$(this,"changeAlerts",[]);$(this,"changeExpectations",new Map);$(this,"executionIdCounter",0);$(this,"stateChangeIdCounter",0);$(this,"alertIdCounter",0);$(this,"maxExecutionDetails",100);$(this,"maxStateChangeHistory",200);$(this,"maxChangeAlerts",100);$(this,"sequenceExecutions",[]);$(this,"sequenceExecutionStack",[]);$(this,"sequenceIdCounter",0);$(this,"maxSequenceExecutions",50);$(this,"staleClosureWarnings",[]);$(this,"staleClosureIdCounter",0);$(this,"maxStaleClosureWarnings",100);$(this,"stateCaptureRegistry",new Map);$(this,"modalStates",new Map);$(this,"modalStateIssues",[]);$(this,"modalStateRelations",[]);$(this,"modalStateChangeLogs",[]);$(this,"modalStateIssueIdCounter",0);$(this,"modalStateChangeLogIdCounter",0);$(this,"maxModalStateIssues",100);$(this,"maxModalStateChangeLogs",200);$(this,"namedActionDefinitions",{});$(this,"namedActionRefLogs",[]);$(this,"namedActionRefIdCounter",0);$(this,"maxNamedActionRefLogs",200);$(this,"debounceActionHistory",[]);$(this,"dataSourceUpdateHistory",[]);$(this,"debounceActionIdCounter",0);$(this,"dataSourceUpdateIdCounter",0)}static getInstance(){return yi.instance||(yi.instance=new yi),yi.instance}initialize(){if(this.config.enabled=this.checkDebugMode(),!this.config.enabled){console.log("[G7DevTools] 비활성화됨 (환경설정 > 고급 설정 > 디버그 모드를 켜세요)");return}console.log("[G7DevTools] 활성화됨"),this.setupGlobalErrorHandler()}checkDebugMode(){try{if(window.G7Config?.debug===!0)return!0;const r=window.G7Core?.state?.get?.();return r?.settings?.advanced?.debug_mode===!0||r?._global?.settings?.advanced?.debug_mode===!0}catch{return!1}}isEnabled(){return this.config.enabled}setupGlobalErrorHandler(){window.addEventListener("error",e=>{this.config.enabled&&this.logAction({id:this.generateId(),type:"globalError",startTime:Date.now(),status:"error",error:{name:"Error",message:e.message,stack:e.error?.stack}})}),window.addEventListener("unhandledrejection",e=>{this.config.enabled&&this.logAction({id:this.generateId(),type:"unhandledRejection",startTime:Date.now(),status:"error",error:{name:"UnhandledRejection",message:String(e.reason)}})})}captureStateSnapshot(e){if(!this.config.enabled)return;const a={id:++this.snapshotIdCounter,timestamp:Date.now(),source:e.source,prev:this.sanitizeObject(e.prev),next:this.sanitizeObject(e.next),diff:e.diff};this.stateHistory.push(a),this.stateHistory.length>this.config.maxHistorySize&&this.stateHistory.shift(),this.notifyStateWatchers(a)}getState(){try{const e=window.G7Core,a=e?.state?.get?.()||{},r={};if(e?._isolatedStates&&typeof e._isolatedStates=="object")for(const[i,l]of Object.entries(e._isolatedStates))r[i]=this.sanitizeObject(l);return{_global:a._global||a,_local:this.currentLocalState,_computed:this.currentComputedState,_isolated:Object.keys(r).length>0?r:void 0,$parent:this.currentParentContext}}catch{return{_global:{},_local:this.currentLocalState,_computed:this.currentComputedState}}}updateLocalState(e){this.config.enabled&&(this.currentLocalState=this.sanitizeObject(e))}updateComputedState(e){this.config.enabled&&(this.currentComputedState=this.sanitizeObject(e))}updateParentContext(e){this.config.enabled&&(this.currentParentContext=e?this.sanitizeObject(e):void 0)}getStateHistory(){return[...this.stateHistory]}getDualStorageMismatch(){const e=this.currentLocalState||{};let a={};try{a=(window.G7Core?.state?.get?.()||{})._local||{}}catch{a={}}const r=this.findMismatchedLeafPaths(e,a);return{hasMismatch:r.length>0,mismatchedPaths:r,storageA:e,storageB:a}}findMismatchedLeafPaths(e,a,r=""){const i=[],l=new Set([...Object.keys(e||{}),...Object.keys(a||{})]);for(const u of l){const d=r?`${r}.${u}`:u,f=e?.[u],g=a?.[u],m=f&&typeof f=="object"&&!Array.isArray(f),b=g&&typeof g=="object"&&!Array.isArray(g);if(m&&b)i.push(...this.findMismatchedLeafPaths(f,g,d));else{const v=f===void 0?"__undefined__":JSON.stringify(f),S=g===void 0?"__undefined__":JSON.stringify(g);v!==S&&i.push(d)}}return i}watchState(e,a){return this.stateWatchers.has(e)||this.stateWatchers.set(e,new Set),this.stateWatchers.get(e).add(a),()=>{this.stateWatchers.get(e)?.delete(a)}}notifyStateWatchers(e){if(this.stateWatchers.get("*")?.forEach(a=>{try{a(e.next,e.prev,"*")}catch(r){console.error("[G7DevTools] State watcher error:",r)}}),e.diff)for(const a of e.diff.changed)this.stateWatchers.get(a.path)?.forEach(r=>{try{r(a.newValue,a.oldValue,a.path)}catch(i){console.error("[G7DevTools] State watcher error:",i)}})}diffSnapshots(e,a){const r=this.stateHistory.find(l=>l.id===e),i=this.stateHistory.find(l=>l.id===a);return!r||!i?null:this.calculateDiff(r.next,i.next)}calculateDiff(e,a,r=""){const i={added:[],removed:[],changed:[]},l=new Set(Object.keys(e)),u=new Set(Object.keys(a));for(const d of u){const f=r?`${r}.${d}`:d;l.has(d)?JSON.stringify(e[d])!==JSON.stringify(a[d])&&i.changed.push({path:f,oldValue:e[d],newValue:a[d]}):i.added.push(f)}for(const d of l){const f=r?`${r}.${d}`:d;u.has(d)||i.removed.push(f)}return i}logAction(e){if(!this.config.enabled)return;const a=this.actionHistory.findIndex(r=>r.id===e.id);a>=0?this.actionHistory[a]={...this.actionHistory[a],...e}:(this.actionHistory.push(e),this.actionHistory.length>this.config.maxHistorySize&&this.actionHistory.shift()),this.isProfiling&&this.profilingData.push({type:"action",action:e.type,timestamp:performance.now(),duration:e.duration}),this.notifyActionWatchers(e)}getActionHistory(){return[...this.actionHistory]}watchActions(e){return this.actionWatchers.add(e),()=>{this.actionWatchers.delete(e)}}notifyActionWatchers(e){this.actionWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Action watcher error:",r)}})}getActionMetrics(){const e=this.actionHistory.filter(l=>l.status==="success"),a=this.actionHistory.filter(l=>l.status==="error"),r={};for(const l of this.actionHistory)r[l.type]=(r[l.type]||0)+1;const i=e.reduce((l,u)=>l+(u.duration||0),0);return{totalActions:this.actionHistory.length,successCount:e.length,errorCount:a.length,averageDuration:e.length>0?i/e.length:0,actionsByType:r}}recordCacheHit(){this.config.enabled&&this.cacheStats.hits++}recordCacheMiss(){this.config.enabled&&this.cacheStats.misses++}updateCacheEntries(e){this.config.enabled&&(this.cacheStats.entries=e)}getCacheStats(){const e=this.cacheStats.hits+this.cacheStats.misses;return{...this.cacheStats,hitRate:e>0?this.cacheStats.hits/e:0}}resetCacheStats(){this.cacheStats={hits:0,misses:0,entries:0}}trackCacheDecision(e){if(!this.config.enabled)return;const a={id:`cache-${++this.cacheDecisionIdCounter}`,timestamp:Date.now(),expression:e.expression,decision:e.decision,reason:e.reason,context:{isInIteration:this.isInIteration,isInAction:this.isInActionExecution,renderCycleId:this.currentRenderCycleId||void 0,componentId:e.componentId,skipCacheOption:e.skipCacheOption},cachedValue:e.cachedValue!==void 0?this.safeClone(e.cachedValue):void 0,freshValue:e.freshValue!==void 0?this.safeClone(e.freshValue):void 0,valueMatch:e.cachedValue!==void 0&&e.freshValue!==void 0?JSON.stringify(e.cachedValue)===JSON.stringify(e.freshValue):void 0,duration:e.duration};this.cacheDecisions.push(a),this.cacheDecisions.length>this.maxCacheDecisions&&this.cacheDecisions.shift(),e.decision==="cache_hit"?this.cacheStats.hits++:(e.decision==="cache_miss"||e.decision==="skip_cache")&&this.cacheStats.misses++}startRenderCycle(e){return this.currentRenderCycleId=`render-${Date.now()}-${e||"root"}`,this.currentRenderCycleId}endRenderCycle(){this.currentRenderCycleId=null}startActionContext(){this.isInActionExecution=!0}endActionContext(){this.isInActionExecution=!1}startIterationContext(){this.isInIteration=!0}endIterationContext(){this.isInIteration=!1}getCacheDecisionTrackingInfo(){const e=this.getCacheDecisionStats();return{decisions:[...this.cacheDecisions],stats:e,timestamp:Date.now()}}getCacheDecisionStats(){const e=this.cacheDecisions;let a=0,r=0,i=0,l=0;const u={},d={};for(const g of e)g.decision==="cache_hit"?a++:g.decision==="cache_miss"?r++:g.decision==="skip_cache"?i++:g.decision==="invalidate"&&l++,u[g.reason]=(u[g.reason]||0)+1,g.context.componentId&&(d[g.context.componentId]=(d[g.context.componentId]||0)+1);const f=a+r+i;return{totalDecisions:e.length,cacheHits:a,cacheMisses:r,skipCacheCount:i,invalidateCount:l,byReason:u,byComponent:d,avgHitRate:f>0?a/f:0}}getRecentCacheDecisions(e=20,a){let r=[...this.cacheDecisions];return a&&(r=r.filter(i=>i.decision===a)),r.slice(-e)}clearCacheDecisionData(){this.cacheDecisions=[],this.cacheDecisionIdCounter=0}summarizePropsForLifecycle(e){if(!e||typeof e!="object")return e;const a={},r=["children","ref","key"];for(const[i,l]of Object.entries(e))if(!r.includes(i))if(l==null)a[i]=l;else if(Array.isArray(l))a[i]=`[Array(${l.length})]`;else if(typeof l=="object"){const u=Object.keys(l);u.length<=3?a[i]=`{${u.join(", ")}}`:a[i]=`{${u.slice(0,3).join(", ")}, ... +${u.length-3}}`}else typeof l=="string"&&l.length>50?a[i]=l.substring(0,50)+"...":typeof l=="function"?a[i]="[Function]":a[i]=l;return a}trackMount(e,a){if(!this.config.enabled)return;const r=this.summarizePropsForLifecycle(a.props),i={...a,props:r,id:e,mountTime:Date.now()};this.mountedComponents.set(e,i),this.mountWatchers.forEach(l=>{try{l({componentId:e,componentName:a.name,timestamp:i.mountTime})}catch(u){console.error("[G7DevTools] Mount watcher error:",u)}})}trackUnmount(e){if(!this.config.enabled)return;const a=this.mountedComponents.get(e),r=this.eventListeners.get(e)||[];r.length>0&&console.warn(`[G7DevTools] 컴포넌트 ${e} 언마운트 시 ${r.length}개 리스너 미정리`),a&&this.unmountWatchers.forEach(i=>{try{i({componentId:e,componentName:a.name,timestamp:Date.now(),orphanedListeners:r.length})}catch(l){console.error("[G7DevTools] Unmount watcher error:",l)}}),this.mountedComponents.delete(e)}trackListener(e,a,r){if(!this.config.enabled)return;const i=this.eventListeners.get(e)||[];i.push({type:a,target:r,addedAt:Date.now()}),this.eventListeners.set(e,i)}removeListener(e,a){if(!this.config.enabled)return;const r=this.eventListeners.get(e)||[],i=r.findIndex(l=>l.type===a);i>=0&&r.splice(i,1)}getMountedComponents(){return Array.from(this.mountedComponents.values())}getOrphanedListeners(){const e=[];for(const[a,r]of this.eventListeners)this.mountedComponents.has(a)||e.push(...r.map(i=>({...i,componentId:a})));return e}watchMount(e){return this.mountWatchers.add(e),()=>{this.mountWatchers.delete(e)}}watchUnmount(e){return this.unmountWatchers.add(e),()=>{this.unmountWatchers.delete(e)}}trackRender(e){if(!this.config.enabled)return;const a=this.renderCounts.get(e)||0;this.renderCounts.set(e,a+1),this.isProfiling&&this.profilingData.push({type:"render",component:e,timestamp:performance.now()})}trackBindingEval(e){this.config.enabled&&(this.bindingEvalCount++,this.isProfiling&&e&&this.profilingData.push({type:"binding",expression:e,timestamp:performance.now()}))}getRenderCount(){return new Map(this.renderCounts)}getBindingEvalCount(){return this.bindingEvalCount}getMemoryWarnings(){const e=[];try{const i=this.getState(),l=JSON.stringify(i).length;l>1e6&&e.push({type:"large-state",message:`상태 크기가 ${(l/1024/1024).toFixed(2)}MB입니다`,suggestion:"불필요한 데이터 정리 필요",severity:l>5e6?"error":"warning"})}catch{}this.stateHistory.length>this.config.maxHistorySize*.8&&e.push({type:"large-history",message:`상태 이력이 ${this.stateHistory.length}개입니다`,suggestion:"maxHistory 설정 조정 필요",severity:"warning"});const a=this.getOrphanedListeners().length;a>0&&e.push({type:"orphaned-listeners",message:`${a}개의 정리되지 않은 이벤트 리스너`,suggestion:"useEffect cleanup 또는 removeEventListener 확인",severity:a>10?"error":"warning"});const r=Array.from(this.renderCounts.entries()).filter(([,i])=>i>50);return r.length>0&&e.push({type:"excessive-renders",message:`${r.length}개 컴포넌트가 50회 이상 렌더링`,suggestion:"React.memo, useMemo, useCallback 사용 고려",severity:"warning"}),e}startProfiling(){this.config.enabled&&(this.isProfiling=!0,this.profilingData=[],this.profilingStartTime=performance.now(),console.log("[G7DevTools] 프로파일링 시작"))}stopProfiling(){this.isProfiling=!1;const e=performance.now()-this.profilingStartTime,a=this.analyzeProfile(e);return console.log("[G7DevTools] 프로파일링 완료",a),a}analyzeProfile(e){const a=this.profilingData.filter(g=>g.type==="render"),r=this.profilingData.filter(g=>g.type==="binding"),i=this.profilingData.filter(g=>g.type==="action"),l={};for(const g of a)g.component&&(l[g.component]||(l[g.component]={count:0,durations:[]}),l[g.component].count++,g.duration&&l[g.component].durations.push(g.duration));const u=Object.entries(l).map(([g,m])=>({name:g,renderCount:m.count,avgDuration:m.durations.length>0?m.durations.reduce((b,v)=>b+v,0)/m.durations.length:0})).sort((g,m)=>m.renderCount-g.renderCount).slice(0,10),d={};for(const g of r)g.expression&&(d[g.expression]=(d[g.expression]||0)+1);const f=Object.entries(d).sort(([,g],[,m])=>m-g).slice(0,10).map(([g])=>g);return{duration:e,entries:this.profilingData,summary:{totalRenders:a.length,totalBindings:r.length,totalActions:i.length,slowestComponents:u,hotPaths:f}}}resetPerformanceStats(){this.renderCounts.clear(),this.bindingEvalCount=0,this.profilingData=[]}trackRequest(e,a,r){if(!this.config.enabled)return"";const i=this.generateId(),l=v_(e),u=b_(e);return this.activeRequests.set(i,{id:i,url:l,fullUrl:e,queryParams:u,method:a,startTime:Date.now(),status:"pending",requestBody:r?.requestBody?this.sanitizeObject(r.requestBody):void 0,dataSourceId:r?.dataSourceId}),this.isProfiling&&this.profilingData.push({type:"network",timestamp:performance.now()}),i}completeRequest(e,a,r){if(!this.config.enabled)return;const i=this.activeRequests.get(e);if(!i)return;const l={...i,status:a>=200&&a<300?"success":"error",statusCode:a,duration:Date.now()-i.startTime,endTime:Date.now(),response:this.sanitizeObject(r)};this.requestHistory.push(l),this.activeRequests.delete(e),this.requestHistory.length>this.config.maxHistorySize&&this.requestHistory.shift(),this.notifyRequestWatchers(l)}failRequest(e,a){if(!this.config.enabled)return;const r=this.activeRequests.get(e);if(!r)return;const i={...r,status:"error",error:a,duration:Date.now()-r.startTime,endTime:Date.now()};this.requestHistory.push(i),this.activeRequests.delete(e),this.notifyRequestWatchers(i)}trackDataSource(e){this.config.enabled&&this.pendingDataSources.add(e)}completeDataSource(e){this.config.enabled&&this.pendingDataSources.delete(e)}getActiveRequests(){return Array.from(this.activeRequests.values())}getRequestHistory(){return[...this.requestHistory]}getPendingDataSources(){return Array.from(this.pendingDataSources)}watchRequest(e){return this.requestWatchers.add(e),()=>{this.requestWatchers.delete(e)}}notifyRequestWatchers(e){this.requestWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Request watcher error:",r)}})}trackWebSocketConnection(e,a,r){this.config.enabled&&this.wsConnections.set(e,{id:e,url:a,state:r,connectedAt:r==="open"?Date.now():void 0})}trackWebSocketMessage(e,a,r,i){if(!this.config.enabled)return;const l={id:this.generateId(),connectionId:e,direction:a,type:r,payload:this.sanitizeObject(i),timestamp:Date.now(),sequence:this.wsMessageHistory.length};this.wsMessageHistory.push(l),this.wsMessageHistory.length>this.config.maxHistorySize&&this.wsMessageHistory.shift(),this.notifyWebSocketWatchers(l)}getWebSocketConnections(){return Array.from(this.wsConnections.values())}getWebSocketMessageHistory(){return[...this.wsMessageHistory]}getWebSocketConnectionState(){const e=Array.from(this.wsConnections.values());return e.some(a=>a.state==="open")?"connected":e.some(a=>a.state==="connecting")?"reconnecting":"disconnected"}watchWebSocketMessage(e){return this.wsMessageWatchers.add(e),()=>{this.wsMessageWatchers.delete(e)}}notifyWebSocketWatchers(e){this.wsMessageWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] WebSocket watcher error:",r)}})}trackIfCondition(e,a,r){if(!this.config.enabled)return;const i=this.ifConditions.get(e),l=i?.evaluatedValue;this.ifConditions.set(e,{id:e,expression:a,evaluatedValue:r,evaluationCount:(i?.evaluationCount||0)+1,lastEvaluated:Date.now()}),i&&l!==r&&this.notifyConditionWatchers({id:e,expression:a,oldValue:l,newValue:r,timestamp:Date.now()})}trackIteration(e,a){this.config.enabled&&this.iterations.set(e,{id:e,...a,lastRendered:Date.now()})}getIfConditions(){return Array.from(this.ifConditions.values())}getIterations(){return Array.from(this.iterations.values())}getScopeChain(e){const a=[],r=this.getState();return a.push({name:"_global",value:r._global,source:"global"}),a.push({name:"_local",value:r._local,source:"local"}),a.push({name:"_computed",value:r._computed,source:"computed"}),a}watchConditionChange(e){return this.conditionWatchers.add(e),()=>{this.conditionWatchers.delete(e)}}notifyConditionWatchers(e){this.conditionWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Condition watcher error:",r)}})}trackForm(e,a,r){this.config.enabled&&this.forms.set(e,{id:e,dataKey:a,inputs:r,trackedAt:Date.now()})}trackFormChange(e,a,r){if(!this.config.enabled)return;const i={formId:e,inputName:a,value:r,timestamp:Date.now()};this.notifyFormWatchers(i)}untrackForm(e){this.forms.delete(e)}getForms(){return Array.from(this.forms.values())}getFormState(e){const a=this.getState();return this.getNestedValue(a,e)||{}}getBindingPath(e,a){return`${e}.${a}`}watchFormChange(e){return this.formWatchers.add(e),()=>{this.formWatchers.delete(e)}}notifyFormWatchers(e){this.formWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Form watcher error:",r)}})}trackFormBindingIssue(e,a,r){if(!this.config.enabled)return;const i={id:`form-issue-${++this.formBindingIssueIdCounter}`,timestamp:Date.now(),type:e,severity:a,formId:r.formId,formDataKey:r.formDataKey,inputInfo:r.inputInfo,contextInfo:r.contextInfo,description:r.description,suggestion:r.suggestion,docLink:r.docLink};this.formBindingIssues.push(i),this.formBindingIssues.length>this.maxFormBindingIssues&&this.formBindingIssues.shift()}validateFormBinding(e,a,r,i){const l=r.map(f=>{const g=[];let m=!0;return f.name||(g.push("Input에 name 속성이 없습니다"),m=!1,this.trackFormBindingIssue("missing-input-name","error",{formId:e,formDataKey:a,inputInfo:{name:f.name,type:f.type},description:"Input에 name 속성이 없어 자동 바인딩이 동작하지 않습니다",suggestion:"Input에 name 속성을 추가하세요",docLink:"troubleshooting-components-form.md"})),a||(g.push("Form에 dataKey가 없습니다"),m=!1),{inputName:f.name||"(unnamed)",inputType:f.type,bindingPath:a&&f.name?`${a}.${f.name}`:"-",isValid:m,currentValue:f.value,issues:g}});if(a||this.trackFormBindingIssue("missing-datakey","error",{formId:e,description:"Form에 dataKey가 설정되지 않아 자동 바인딩이 동작하지 않습니다",suggestion:"Form 컴포넌트에 dataKey props를 설정하세요",docLink:"troubleshooting-components-form.md"}),i.isContextBroken){const f=i.breakReason?.includes("sortable")?"sortable-context-break":i.breakReason?.includes("modal")?"modal-context-isolation":"context-not-propagated";this.trackFormBindingIssue(f,"warning",{formId:e,formDataKey:a,contextInfo:{hasParentFormContext:i.hasParentContext,parentFormContextProp:i.parentContextProp,isInsideSortable:i.breakReason?.includes("sortable")||!1,isInsideModal:i.breakReason?.includes("modal")||!1,depth:0},description:i.breakReason||"Form 컨텍스트가 제대로 전파되지 않았습니다",suggestion:"parentFormContextProp={undefined}를 확인하거나 중첩 구조를 검토하세요",docLink:"troubleshooting-components-form.md"})}const u={formId:e,dataKey:a,timestamp:Date.now(),contextPropagation:i,inputBindings:l,isValid:l.every(f=>f.isValid)&&!!a&&!i.isContextBroken,issueCount:l.filter(f=>!f.isValid).length+(a?0:1)+(i.isContextBroken?1:0)},d=this.formBindingValidations.findIndex(f=>f.formId===e);return d>=0?this.formBindingValidations[d]=u:this.formBindingValidations.push(u),u}getFormBindingValidationTrackingInfo(){const e=this.getFormBindingValidationStats();return{issues:[...this.formBindingIssues],validations:[...this.formBindingValidations],stats:e,timestamp:Date.now()}}getFormBindingValidationStats(){const e={"missing-datakey":0,"missing-input-name":0,"context-not-propagated":0,"sortable-context-break":0,"modal-context-isolation":0,"duplicate-input-name":0,"value-type-mismatch":0,"binding-path-invalid":0},a={info:0,warning:0,error:0};for(const i of this.formBindingIssues)e[i.type]++,a[i.severity]++;const r=Object.entries(e).filter(([,i])=>i>0).sort((i,l)=>l[1]-i[1]).slice(0,5).map(([i,l])=>({type:i,count:l,description:this.getIssueTypeDescription(i)}));return{totalFormsValidated:this.formBindingValidations.length,validForms:this.formBindingValidations.filter(i=>i.isValid).length,formsWithIssues:this.formBindingValidations.filter(i=>!i.isValid).length,totalIssues:this.formBindingIssues.length,byIssueType:e,bySeverity:a,topIssues:r}}getIssueTypeDescription(e){return{"missing-datakey":"Form에 dataKey 누락","missing-input-name":"Input에 name 속성 누락","context-not-propagated":"Form 컨텍스트 전파 실패","sortable-context-break":"Sortable 컨테이너에서 컨텍스트 단절","modal-context-isolation":"모달에서 부모 Form 컨텍스트 격리","duplicate-input-name":"동일 Form 내 중복 Input name","value-type-mismatch":"값 타입과 Input 타입 불일치","binding-path-invalid":"바인딩 경로 유효하지 않음"}[e]||e}clearFormBindingIssues(){this.formBindingIssues=[],this.formBindingValidations=[],this.formBindingIssueIdCounter=0}trackComputedProperty(e,a,r,i,l,u,d){if(!this.config.enabled)return;const f=`computed-${e}-${u||"global"}`,g={id:f,name:e,expression:a,componentId:u,dependencies:r,currentValue:this.safeClone(i),lastComputedAt:Date.now(),computationTime:l,error:d};this.computedProperties.set(f,g)}trackComputedRecalc(e,a,r,i,l,u,d){if(!this.config.enabled)return;const f=`computed-${e}-${d||"global"}`,g=JSON.stringify(r)!==JSON.stringify(i),m={id:`recalc-${++this.computedRecalcIdCounter}`,computedId:f,computedName:e,timestamp:Date.now(),trigger:a,triggeredBy:u,previousValue:this.safeClone(r),newValue:this.safeClone(i),valueChanged:g,computationTime:l,cascadeCount:0};this.computedRecalcLogs.push(m),this.computedRecalcLogs.length>this.maxComputedRecalcLogs&&this.computedRecalcLogs.shift();const b=this.computedProperties.get(f);b&&(b.currentValue=this.safeClone(i),b.lastComputedAt=Date.now(),b.computationTime=l)}analyzeComputedDependencyChain(e,a){const r=new Set,i=[];let l=!1,u,d=0;const f=(m,b)=>{if(d=Math.max(d,b),r.has(m))return l=!0,u=[...i,m],{name:m,type:"computed",children:[],depth:b};r.add(m),i.push(m);const v=this.computedProperties.get(`computed-${m}-${a||"global"}`),S=[];if(v)for(const E of v.dependencies)E.type==="computed"?S.push(f(E.path,b+1)):S.push({name:E.path,type:E.type,children:[],depth:b+1});return i.pop(),r.delete(m),{name:m,type:"computed",children:S,depth:b}},g=f(e,0);return{root:e,tree:g,hasCycle:l,cyclePath:u,maxDepth:d}}getComputedDependencyTrackingInfo(){const e=Array.from(this.computedProperties.values()),a=this.getComputedDependencyStats(),r=[];for(const i of e){const l=this.analyzeComputedDependencyChain(i.name,i.componentId);r.push(l)}return{properties:e,recalcLogs:[...this.computedRecalcLogs],dependencyChains:r,stats:a,timestamp:Date.now()}}getComputedDependencyStats(){const e={"state-change":0,"datasource-update":0,"dependency-change":0,manual:0,initial:0},a={},r={};let i=0,l=0;for(const g of this.computedRecalcLogs)e[g.trigger]++,g.valueChanged||l++,a[g.computedName]=(a[g.computedName]||0)+1,r[g.computedName]||(r[g.computedName]=[]),r[g.computedName].push(g.computationTime),i+=g.computationTime;const u=Object.entries(a).sort((g,m)=>m[1]-g[1]).slice(0,5).map(([g,m])=>({name:g,count:m})),d=Object.entries(r).map(([g,m])=>({name:g,avgTime:m.reduce((b,v)=>b+v,0)/m.length})).sort((g,m)=>m.avgTime-g.avgTime).slice(0,5);let f=0;for(const g of this.computedProperties.values())this.analyzeComputedDependencyChain(g.name,g.componentId).hasCycle&&f++;return{totalComputed:this.computedProperties.size,totalRecalculations:this.computedRecalcLogs.length,unnecessaryRecalculations:l,avgComputationTime:this.computedRecalcLogs.length>0?i/this.computedRecalcLogs.length:0,topRecalculated:u,slowestComputed:d,cycleDetectionCount:f,byTrigger:e}}clearComputedTracking(){this.computedProperties.clear(),this.computedRecalcLogs=[],this.computedRecalcIdCounter=0}trackModalOpen(e){if(!this.config.enabled)return;const a={modalId:e.modalId,modalName:e.modalName,openedAt:Date.now(),closedAt:null,scopeType:e.scopeType||"isolated",parentModalId:e.parentModalId,componentId:e.componentId,initialState:e.initialState?{...e.initialState}:{},currentState:e.initialState?{...e.initialState}:{},stateChangeCount:0,isolatedStateKeys:e.isolatedStateKeys||[],sharedStateKeys:e.sharedStateKeys||[]};this.modalStates.set(e.modalId,a),this.validateModalDefinitionExists(e.modalId,e.modalName),e.parentModalId&&(this.modalStateRelations.find(i=>i.parentModalId===e.parentModalId&&i.childModalId===e.modalId)||this.modalStateRelations.push({parentModalId:e.parentModalId,childModalId:e.modalId,sharedKeys:e.sharedStateKeys||[],isolatedKeys:e.isolatedStateKeys||[],relationType:"parent-child"}))}trackModalClose(e,a){if(!this.config.enabled)return;const r=this.modalStates.get(e);r&&(r.closedAt=Date.now(),a&&(r.currentState={...a}),this.detectStateLeakage(r))}validateModalDefinitionExists(e,a){const r=this.currentLayout;if(!r?.layoutJson)return;const i=r.layoutJson.modals;if(!i){this.recordModalStateIssue({type:"missing-definition",modalId:e,modalName:a,severity:"error",description:`모달 "${e}"이(가) modalStack에 추가되었으나, 현재 레이아웃에 modals 섹션이 없습니다. 레이아웃 경로: ${r.layoutPath}`,affectedStateKeys:[],expectedValue:`modals 섹션에 id="${e}" 정의 존재`,actualValue:"modals 섹션 없음"});return}const l=Array.isArray(i)?i:Object.values(i);l.some(d=>d?.id===e||d?.props?.id===e)||this.recordModalStateIssue({type:"missing-definition",modalId:e,modalName:a,severity:"error",description:`모달 "${e}"이(가) modalStack에 추가되었으나, 렌더링된 레이아웃의 modals 섹션에 해당 ID의 정의가 없습니다. partial 로딩 실패, 레이아웃 병합 문제, extends 상속 누락 등을 확인하세요. 레이아웃 경로: ${r.layoutPath}`,affectedStateKeys:[],expectedValue:`modals 배열에 id="${e}" 항목 존재`,actualValue:`modals 배열에 ${l.length}개 모달 정의 (${l.map(d=>d?.id||"unknown").join(", ")})`})}trackModalStateChange(e){if(!this.config.enabled)return;const a=this.modalStates.get(e.modalId);if(!a)return;a.stateChangeCount++,a.currentState[e.stateKey]=e.newValue;const r=this.checkIsolationViolation(a,e.stateKey),i={id:`modal-change-${++this.modalStateChangeLogIdCounter}`,modalId:e.modalId,modalName:a.modalName,timestamp:Date.now(),stateKey:e.stateKey,previousValue:e.previousValue,newValue:e.newValue,changeSource:e.changeSource||"user-action",violatesIsolation:r};this.modalStateChangeLogs.push(i),this.modalStateChangeLogs.length>this.maxModalStateChangeLogs&&this.modalStateChangeLogs.shift(),r&&this.recordModalStateIssue({type:"isolation-violation",modalId:e.modalId,modalName:a.modalName,severity:"warning",description:`모달 '${a.modalName}'에서 격리된 상태 키 '${e.stateKey}'가 변경됨`,affectedStateKeys:[e.stateKey]})}detectStateLeakage(e){if(e.scopeType==="isolated")for(const a of e.isolatedStateKeys){const r=e.initialState[a],i=e.currentState[a];if(r!==i&&e.parentModalId){const l=this.modalStates.get(e.parentModalId);l&&l.currentState.hasOwnProperty(a)&&this.recordModalStateIssue({type:"state-leakage",modalId:e.modalId,modalName:e.modalName,severity:"error",description:`모달 닫힘 후 상태 '${a}'가 부모 모달로 유출될 수 있음`,affectedStateKeys:[a],leakedValue:i,expectedValue:r})}}}checkIsolationViolation(e,a){return e.scopeType==="isolated",!1}recordModalStateIssue(e){const a={id:`modal-issue-${++this.modalStateIssueIdCounter}`,type:e.type,modalId:e.modalId,modalName:e.modalName,timestamp:Date.now(),severity:e.severity,description:e.description,affectedStateKeys:e.affectedStateKeys,leakedValue:e.leakedValue,expectedValue:e.expectedValue,actualValue:e.actualValue,stackInfo:e.stackInfo};this.modalStateIssues.push(a),this.modalStateIssues.length>this.maxModalStateIssues&&this.modalStateIssues.shift()}getModalStateScopeTrackingInfo(){const e=Array.from(this.modalStates.values()),a=this.getModalStateScopeStats();return{modals:e,issues:[...this.modalStateIssues],relations:[...this.modalStateRelations],changeLogs:[...this.modalStateChangeLogs],stats:a,timestamp:Date.now()}}getModalStateScopeStats(){const e=Array.from(this.modalStates.values()),a={warning:0,error:0},r={"state-leakage":0,"isolation-violation":0,"parent-mutation":0,"orphaned-state":0,"scope-mismatch":0,"cleanup-failure":0,"missing-definition":0};for(const l of this.modalStateIssues)a[l.severity]++,r[l.type]++;const i={isolated:0,shared:0,inherited:0};for(const l of e)i[l.scopeType]++;return{totalModals:e.length,openModals:e.filter(l=>l.closedAt===null).length,nestedModals:e.filter(l=>l.parentModalId!==void 0).length,totalIssues:this.modalStateIssues.length,issuesBySeverity:a,issuesByType:r,byScope:i,leakageDetectionCount:r["state-leakage"],cleanupFailureCount:r["cleanup-failure"]}}clearModalStateScopeTracking(){this.modalStates.clear(),this.modalStateIssues=[],this.modalStateRelations=[],this.modalStateChangeLogs=[],this.modalStateIssueIdCounter=0,this.modalStateChangeLogIdCounter=0}setNamedActionDefinitions(e){this.config.enabled&&(this.namedActionDefinitions=e||{})}trackNamedActionRef(e){if(!this.config.enabled)return;const a={...e,id:`named_action_ref_${++this.namedActionRefIdCounter}`};this.namedActionRefLogs.push(a),this.namedActionRefLogs.length>this.maxNamedActionRefLogs&&(this.namedActionRefLogs=this.namedActionRefLogs.slice(-this.maxNamedActionRefLogs))}getNamedActionTrackingInfo(){const e={};for(const r of this.namedActionRefLogs)e[r.actionRefName]=(e[r.actionRefName]||0)+1;const a=Object.keys(this.namedActionDefinitions).filter(r=>!e[r]);return{definitions:this.namedActionDefinitions,refLogs:[...this.namedActionRefLogs],stats:{totalDefinitions:Object.keys(this.namedActionDefinitions).length,totalRefs:this.namedActionRefLogs.length,refCountByName:e,unusedDefinitions:a},timestamp:Date.now()}}clearNamedActionTracking(){this.namedActionDefinitions={},this.namedActionRefLogs=[],this.namedActionRefIdCounter=0}trackExpressionEval(e){if(!this.config.enabled)return;const a={...e,id:`expr-${++this.expressionIdCounter}`,timestamp:Date.now(),warning:this.detectExpressionWarning(e)};this.expressionHistory.push(a),this.expressionHistory.length>500&&this.expressionHistory.shift(),this.isProfiling&&this.profilingData.push({type:"binding",expression:e.expression,timestamp:performance.now(),duration:e.duration}),this.notifyExpressionWatchers(a)}detectExpressionWarning(e){const{expression:a,result:r,resultType:i,method:l,duration:u}=e;if(i==="undefined"&&!a.includes("??")&&!a.includes("||")&&/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(a.replace(/{{|}}/g,"").trim()))return{type:"undefined-result",message:"표현식 결과가 undefined입니다",suggestion:`데이터가 로드되었는지 확인하거나 fallback 값을 추가하세요: ${a} ?? ''`};if(i==="null")return{type:"null-result",message:"표현식 결과가 null입니다",suggestion:`nullish coalescing 연산자를 사용하세요: ${a} ?? ''`};if(l==="resolveBindings"&&i==="string"){const d=String(r);if(d.includes("[object Object]")||/^\[.*\]$/.test(d))return{type:"array-to-string",message:"배열/객체가 문자열로 변환되었습니다",suggestion:"evaluateExpression()을 사용하여 원본 타입을 유지하세요"}}if(l==="resolveBindings"&&i==="string"&&String(r).includes("[object Object]"))return{type:"object-to-string",message:"객체가 [object Object]로 변환되었습니다",suggestion:"evaluateExpression()을 사용하거나 특정 속성에 접근하세요"};if(i==="undefined"&&a.includes(".")&&!a.includes("?.")){const d=a.replace(/{{|}}/g,"").trim().split(".");if(d.length>=2)return{type:"missing-optional-chain",message:"Optional chaining(?.) 누락 가능성",suggestion:`안전한 접근을 위해 ?. 사용을 고려하세요: ${d.join("?.")}`}}if((a.includes("{{item.")||a.includes("{{index}}"))&&Array.from(this.iterations.values()).some(g=>g.itemVar!=="item"))return{type:"wrong-iteration-var",message:"'item'/'index' 대신 iteration에서 정의한 변수명을 사용해야 합니다",suggestion:"iteration의 item_var/index_var에 정의된 변수명을 확인하세요"};if(u&&u>10)return{type:"slow-evaluation",message:`표현식 평가에 ${u.toFixed(2)}ms 소요됨`,suggestion:"복잡한 표현식을 단순화하거나 computed 값으로 분리하세요"}}getExpressions(){return[...this.expressionHistory]}getExpressionWarnings(){return this.expressionHistory.filter(e=>e.warning!=null)}searchExpressions(e){const a=e.toLowerCase();return this.expressionHistory.filter(r=>r.expression.toLowerCase().includes(a)||r.componentName?.toLowerCase().includes(a)||r.propName?.toLowerCase().includes(a))}getExpressionStats(){const e=this.expressionHistory,a=new Set(e.map(f=>f.expression)),r=e.filter(f=>f.warning!=null),i=e.filter(f=>f.fromCache),l=e.filter(f=>f.duration!=null).map(f=>f.duration),u={};for(const f of e)u[f.resultType]=(u[f.resultType]||0)+1;const d={};for(const f of r)f.warning&&(d[f.warning.type]=(d[f.warning.type]||0)+1);return{totalEvaluations:e.length,uniqueExpressions:a.size,warningCount:r.length,cacheHitRate:e.length>0?i.length/e.length:0,averageDuration:l.length>0?l.reduce((f,g)=>f+g,0)/l.length:0,byType:u,byWarning:d}}clearExpressions(){this.expressionHistory=[],this.expressionIdCounter=0}watchExpressions(e){return this.expressionWatchers.add(e),()=>{this.expressionWatchers.delete(e)}}notifyExpressionWatchers(e){this.expressionWatchers.forEach(a=>{try{a(e)}catch(r){console.error("[G7DevTools] Expression watcher error:",r)}})}setLogLevel(e){this.config.logLevel=e}setMaxHistory(e){this.config.maxHistorySize=Math.max(10,Math.min(1e3,e))}setServerEndpoint(e){this.config.serverEndpoint=e}getConfig(){return{...this.config}}generateId(){return`${Date.now()}-${Math.random().toString(36).substr(2,9)}`}sanitizeObject(e,a=new WeakSet){if(e===null||typeof e!="object")return e;if(a.has(e))return"[Circular]";if(a.add(e),Array.isArray(e))return e.map(i=>this.sanitizeObject(i,a));const r={};for(const i of Object.keys(e))try{r[i]=this.sanitizeObject(e[i],a)}catch{r[i]="[Unable to serialize]"}return r}getNestedValue(e,a){if(!a)return e;const r=a.split(".");let i=e;for(const l of r){if(i==null)return;i=i[l]}return i}getLifecycleInfo(){return{mountedComponents:Array.from(this.mountedComponents.values()),orphanedListeners:this.getOrphanedListeners()}}getPerformanceInfo(){return{renderCounts:this.renderCounts,bindingEvalCount:this.bindingEvalCount,memoryWarnings:this.getMemoryWarnings()}}getNetworkInfo(){return{activeRequests:Array.from(this.activeRequests.values()),requestHistory:[...this.requestHistory],pendingDataSources:Array.from(this.pendingDataSources)}}getConditionalInfo(){return{ifConditions:Array.from(this.ifConditions.values()),iterations:Array.from(this.iterations.values())}}getFormInfo(){return Array.from(this.forms.values())}getWebSocketInfo(){return{connections:Array.from(this.wsConnections.values()),messageHistory:[...this.wsMessageHistory],connectionState:this.getWebSocketConnectionState()}}getStateAtTime(e){const a=[...this.stateHistory].reverse().find(r=>r.timestamp<=e);if(a)return{_global:a.next,_local:{}}}reset(){this.stateHistory=[],this.actionHistory=[],this.cacheStats={hits:0,misses:0,entries:0},this.cacheDecisions=[],this.cacheDecisionIdCounter=0,this.currentRenderCycleId=null,this.isInActionExecution=!1,this.isInIteration=!1,this.mountedComponents.clear(),this.eventListeners.clear(),this.renderCounts.clear(),this.bindingEvalCount=0,this.profilingData=[],this.activeRequests.clear(),this.requestHistory=[],this.pendingDataSources.clear(),this.wsConnections.clear(),this.wsMessageHistory=[],this.ifConditions.clear(),this.iterations.clear(),this.forms.clear(),this.expressionHistory=[],this.expressionIdCounter=0,this.dataSources.clear(),this.dataPathTransforms=[],this.nestedContexts=[],this.nestedContextIdCounter=0,this.formBindingIssues=[],this.formBindingValidations=[],this.formBindingIssueIdCounter=0,this.computedProperties.clear(),this.computedRecalcLogs=[],this.computedRecalcIdCounter=0,this.modalStates.clear(),this.modalStateIssues=[],this.modalStateRelations=[],this.modalStateChangeLogs=[],this.modalStateIssueIdCounter=0,this.modalStateChangeLogIdCounter=0,this.logHistory=[],this.logIdCounter=0}getExpressionInfo(){return{expressions:this.getExpressions(),stats:this.getExpressionStats()}}trackLog(e,a,r){if(!this.config.enabled)return;const i=r.map(u=>{if(typeof u=="string")return u;try{return JSON.stringify(u)}catch{return String(u)}}).join(" "),l={id:`log-${++this.logIdCounter}`,level:e,prefix:a,message:i,args:this.sanitizeObject(r),timestamp:Date.now(),stack:e==="error"?new Error().stack:void 0};this.logHistory.push(l),this.logHistory.length>this.maxLogHistory&&this.logHistory.shift()}trackAction(e){if(!this.config.enabled)return;const a={id:`debounce-action-${++this.debounceActionIdCounter}`,...e,timestamp:Date.now()};this.debounceActionHistory.push(a),this.debounceActionHistory.length>100&&this.debounceActionHistory.shift()}trackDataSourceUpdate(e){if(!this.config.enabled)return;const a={id:`ds-update-${++this.dataSourceUpdateIdCounter}`,...e};this.dataSourceUpdateHistory.push(a),this.dataSourceUpdateHistory.length>100&&this.dataSourceUpdateHistory.shift()}getDebounceActionHistory(e){let a=[...this.debounceActionHistory];return e?.handler&&(a=a.filter(r=>r.handler.includes(e.handler))),e?.status&&(a=a.filter(r=>r.status===e.status)),e?.limit&&(a=a.slice(-e.limit)),a}getDataSourceUpdateHistory(e){let a=[...this.dataSourceUpdateHistory];return e?.dataSourceId&&(a=a.filter(r=>r.dataSourceId===e.dataSourceId)),e?.updateType&&(a=a.filter(r=>r.updateType===e.updateType)),e?.limit&&(a=a.slice(-e.limit)),a}getLogs(e){let a=[...this.logHistory];if(e?.level){const r=Array.isArray(e.level)?e.level:[e.level];a=a.filter(i=>r.includes(i.level))}if(e?.prefix){const r=e.prefix.toLowerCase();a=a.filter(i=>i.prefix.toLowerCase().includes(r))}if(e?.search){const r=e.search.toLowerCase();a=a.filter(i=>i.message.toLowerCase().includes(r))}return e?.since&&(a=a.filter(r=>r.timestamp>=e.since)),e?.limit&&(a=a.slice(-e.limit)),a}getLogStats(){const a=Date.now()-6e4,r={log:0,warn:0,error:0,debug:0,info:0},i={};let l=0,u=0;for(const d of this.logHistory)r[d.level]++,i[d.prefix]=(i[d.prefix]||0)+1,d.timestamp>=a&&(d.level==="error"&&l++,d.level==="warn"&&u++);return{totalLogs:this.logHistory.length,byLevel:r,byPrefix:i,recentErrors:l,recentWarnings:u}}clearLogs(){this.logHistory=[],this.logIdCounter=0}getLogInfo(){return{entries:this.getLogs(),stats:this.getLogStats()}}trackDataSourceDefinition(e){this.config.enabled&&this.dataSources.set(e.id,{...e,status:"idle"})}trackDataSourceLoading(e){if(!this.config.enabled)return;const a=this.dataSources.get(e);a&&this.dataSources.set(e,{...a,status:"loading"})}trackDataSourceLoaded(e,a,r){if(!this.config.enabled)return;const i=this.dataSources.get(e);if(!i)return;let l,u,d=r;a&&(Array.isArray(a)?(l=a.length,u=a.length>0&&typeof a[0]=="object"?Object.keys(a[0]):void 0):typeof a=="object"&&(Array.isArray(a.data)?(d=d||"data",l=a.data.length,u=a.data.length>0&&typeof a.data[0]=="object"?Object.keys(a.data[0]):void 0):Array.isArray(a.items)?(d=d||"items",l=a.items.length,u=a.items.length>0&&typeof a.items[0]=="object"?Object.keys(a.items[0]):void 0):u=Object.keys(a))),this.dataSources.set(e,{...i,status:"loaded",dataPath:d,itemCount:l,keys:u,lastLoadedAt:Date.now(),error:void 0})}trackDataSourceError(e,a){if(!this.config.enabled)return;const r=this.dataSources.get(e);r&&this.dataSources.set(e,{...r,status:"error",error:a,lastLoadedAt:Date.now()})}untrackDataSource(e){this.dataSources.delete(e)}getDataSources(){return Array.from(this.dataSources.values())}getDataSource(e){return this.dataSources.get(e)}clearDataSources(){this.dataSources.clear()}trackDataPathTransform(e){if(!this.config.enabled)return;let a=this.dataPathTransforms.find(r=>r.dataSourceId===e.dataSourceId);a||(a={dataSourceId:e.dataSourceId,timestamp:Date.now(),transformSteps:[],warnings:[]},this.dataPathTransforms.push(a),this.dataPathTransforms.length>this.maxDataPathTransforms&&this.dataPathTransforms.shift()),a.transformSteps.push({step:e.step,inputPath:e.inputPath,inputValue:this.safeClone(e.inputValue),outputPath:e.outputPath,outputValue:this.safeClone(e.outputValue),config:e.config}),e.warning&&a.warnings.push(e.warning)}setDataPathFinalBinding(e,a){if(!this.config.enabled)return;const r=this.dataPathTransforms.find(i=>i.dataSourceId===e);r&&(r.finalBinding={expression:a.expression,resolvedPath:a.resolvedPath,value:this.safeClone(a.value)})}getDataPathTransformTrackingInfo(){const e=this.getDataPathTransformStats();return{transforms:[...this.dataPathTransforms],stats:e,timestamp:Date.now()}}getDataPathTransformStats(){const e=this.dataPathTransforms,a={};let r=0;const i={};for(const u of e){a[u.dataSourceId]=(a[u.dataSourceId]||0)+1,r+=u.warnings.length;for(const d of u.warnings)i[d]=(i[d]||0)+1}const l=Object.entries(i).map(([u,d])=>({warning:u,count:d})).sort((u,d)=>d.count-u.count).slice(0,10);return{totalTransforms:e.length,byDataSource:a,warningsCount:r,commonWarnings:l}}getDataPathTransformForDataSource(e){return this.dataPathTransforms.find(a=>a.dataSourceId===e)}clearDataPathTransforms(){this.dataPathTransforms=[]}trackNestedContext(e){if(!this.config.enabled)return"";const a=`nested-${++this.nestedContextIdCounter}`,r=[...new Set([...e.parentContext.available,...e.ownContext.added])],i={...e.parentContext.values,...e.ownContext.values},l={id:a,timestamp:Date.now(),componentId:e.componentId,componentType:e.componentType,parentContext:{available:e.parentContext.available,values:this.safeClone(e.parentContext.values)},ownContext:{added:e.ownContext.added,values:this.safeClone(e.ownContext.values)},mergedContext:{all:r,values:this.safeClone(i)},accessAttempts:[],depth:e.depth,parentId:e.parentId};return this.nestedContexts.push(l),this.nestedContexts.length>this.maxNestedContexts&&this.nestedContexts.shift(),a}trackNestedContextAccess(e,a){if(!this.config.enabled)return;const r=this.nestedContexts.find(i=>i.id===e);r&&r.accessAttempts.push({path:a.path,found:a.found,value:a.found?this.safeClone(a.value):void 0,error:a.error})}getNestedContextTrackingInfo(){const e=this.getNestedContextStats();return{contexts:[...this.nestedContexts],stats:e,timestamp:Date.now()}}getNestedContextStats(){const e=this.nestedContexts,a={expandChildren:0,cellChildren:0,iteration:0,modal:0,slot:0};let r=0,i=0;const l={};for(const d of e){a[d.componentType]++,d.depth>r&&(r=d.depth);for(const f of d.accessAttempts)f.found||(i++,l[f.path]=(l[f.path]||0)+1)}const u=Object.entries(l).map(([d,f])=>({path:d,count:f})).sort((d,f)=>f.count-d.count).slice(0,10);return{totalContexts:e.length,byType:a,maxDepth:r,failedAccessCount:i,commonFailedPaths:u}}getNestedContextForComponent(e){return this.nestedContexts.find(a=>a.componentId===e)}clearNestedContexts(){this.nestedContexts=[],this.nestedContextIdCounter=0}trackHandlerRegistration(e,a="custom",r,i){this.isEnabled&&this.handlers.set(e,{name:e,category:a,description:r,registeredAt:Date.now(),source:i})}trackHandlerUnregistration(e){this.isEnabled&&this.handlers.delete(e)}getHandlers(){return Array.from(this.handlers.values())}getHandler(e){return this.handlers.get(e)}getHandlersByCategory(e){return Array.from(this.handlers.values()).filter(a=>a.category===e)}clearHandlers(){this.handlers.clear()}trackEventSubscribe(e){if(!this.isEnabled)return;const a=this.componentEventSubscriptions.get(e),r=Date.now();a?(a.subscriberCount++,a.lastSubscribedAt=r):this.componentEventSubscriptions.set(e,{eventName:e,subscriberCount:1,firstSubscribedAt:r,lastSubscribedAt:r})}trackEventUnsubscribe(e){if(!this.isEnabled)return;const a=this.componentEventSubscriptions.get(e);a&&(a.subscriberCount--,a.subscriberCount<=0&&this.componentEventSubscriptions.delete(e))}trackEventEmit(e,a,r,i,l){if(!this.isEnabled)return;const u={id:`evt_${++this.componentEventIdCounter}`,eventName:e,data:this.sanitizeForLogging(a),timestamp:Date.now(),listenerCount:r,results:i?this.sanitizeForLogging(i):void 0,hasError:!!l,errorMessage:l?.message};this.componentEventEmitHistory.push(u),this.componentEventEmitHistory.length>this.maxComponentEventHistory&&(this.componentEventEmitHistory=this.componentEventEmitHistory.slice(-this.maxComponentEventHistory))}trackEventOff(e){this.isEnabled&&this.componentEventSubscriptions.delete(e)}trackEventClear(){this.isEnabled&&this.componentEventSubscriptions.clear()}getComponentEventInfo(){const e=Array.from(this.componentEventSubscriptions.values());return{subscriptions:e,emitHistory:[...this.componentEventEmitHistory],totalSubscribers:e.reduce((a,r)=>a+r.subscriberCount,0),totalEmits:this.componentEventEmitHistory.length}}getEventEmitHistory(){return[...this.componentEventEmitHistory]}getEventSubscriptions(){return Array.from(this.componentEventSubscriptions.values())}clearComponentEvents(){this.componentEventSubscriptions.clear(),this.componentEventEmitHistory=[],this.componentEventIdCounter=0}sanitizeForLogging(e){if(e==null||typeof e!="object")return e;try{return JSON.parse(JSON.stringify(e))}catch{return"[Circular or Non-serializable]"}}startStateChange(e,a,r,i){if(!this.config.enabled)return"";const l=`setState_${++this.stateRenderingIdCounter}`;this.currentStateChangeContext={setStateId:l,startTime:performance.now(),changedPath:e,trigger:i||{},renderedComponents:[]};const u={id:`sr_${this.stateRenderingIdCounter}`,setStateId:l,statePath:e,oldValue:this.sanitizeForLogging(a),newValue:this.sanitizeForLogging(r),timestamp:Date.now(),triggeredBy:i||{},renderedComponents:[],totalRenderDuration:0,affectedBindingsCount:0};return this.stateRenderingLogs.push(u),this.stateRenderingLogs.length>this.maxStateRenderingLogs&&this.stateRenderingLogs.shift(),l}trackComponentRender(e,a,r,i=[],l=[],u){if(!this.config.enabled)return;const d=this.componentRenderCounts.get(a)||0;this.componentRenderCounts.set(a,d+1);for(const f of i)this.stateToComponentMap.has(f)||this.stateToComponentMap.set(f,new Set),this.stateToComponentMap.get(f).add(a);if(this.currentStateChangeContext){const f={componentId:e,componentName:a,renderDuration:r,accessedStatePaths:i,evaluatedBindings:l,renderOrder:this.currentStateChangeContext.renderedComponents.length,parentId:u};this.currentStateChangeContext.renderedComponents.push(f)}this.trackRender(a)}completeStateChange(e){if(!this.config.enabled||!this.currentStateChangeContext||this.currentStateChangeContext.setStateId!==e)return;const a=this.currentStateChangeContext,i=performance.now()-a.startTime,l=this.stateRenderingLogs.findIndex(u=>u.setStateId===e);if(l>=0){const u=this.stateRenderingLogs[l];u.renderedComponents=a.renderedComponents,u.totalRenderDuration=i,u.affectedBindingsCount=a.renderedComponents.reduce((d,f)=>d+f.evaluatedBindings.length,0)}this.currentStateChangeContext=null}getCurrentStateChangeContext(){return this.currentStateChangeContext}getStateRenderingLogs(){return[...this.stateRenderingLogs]}getStateRenderingInfo(){const e=this.stateRenderingLogs,a=Object.fromEntries(this.componentRenderCounts),r={};for(const[i,l]of this.stateToComponentMap)r[i]=Array.from(l);return{logs:e,componentRenderCounts:a,stateToComponentMap:r,stats:this.calculateStateRenderingStats()}}calculateStateRenderingStats(){const e=this.stateRenderingLogs;if(e.length===0)return{totalStateChanges:0,totalRenders:0,avgRenderDuration:0,avgComponentsPerChange:0,topRenderedComponents:[],topInfluentialPaths:[]};const a=e.reduce((d,f)=>d+f.renderedComponents.length,0),r=e.reduce((d,f)=>d+f.totalRenderDuration,0)/e.length,i=a/e.length,l=Array.from(this.componentRenderCounts.entries()).sort((d,f)=>f[1]-d[1]).slice(0,5).map(([d,f])=>({name:d,count:f})),u=Array.from(this.stateToComponentMap.entries()).sort((d,f)=>f[1].size-d[1].size).slice(0,5).map(([d,f])=>({path:d,affectedComponents:f.size}));return{totalStateChanges:e.length,totalRenders:a,avgRenderDuration:r,avgComponentsPerChange:i,topRenderedComponents:l,topInfluentialPaths:u}}getComponentsAffectedByState(e){const a=this.stateToComponentMap.get(e);return a?Array.from(a):[]}getComponentRenderHistory(e){return this.stateRenderingLogs.filter(a=>a.renderedComponents.some(r=>r.componentName===e))}clearStateRenderingLogs(){this.stateRenderingLogs=[],this.componentRenderCounts.clear(),this.stateToComponentMap.clear(),this.currentStateChangeContext=null,this.stateRenderingIdCounter=0}trackComponentStateSource(e,a,r,i){this.config.enabled&&this.componentStateSources.set(e,{componentId:e,componentName:a,stateSource:r,stateProvider:i})}trackDynamicState(e,a){this.config.enabled&&this.dynamicStates.set(e,a)}trackContextFlow(e,a,r,i,l,u){if(!this.config.enabled)return;const d={component:a,componentId:e,contextReceived:r,passedToChildren:i,usedInRender:l};if(this.contextFlowNodes.set(e,d),u){const f=this.contextFlowNodes.get(u);f&&(f.children||(f.children=[]),f.children.push(d))}}getStateHierarchyInfo(e=!0){const a=this.buildStateHierarchyLayers(),r=this.detectStateConflicts(a),i=Array.from(this.componentStateSources.values());return{layers:e?a.map(u=>({...u,values:this.summarizeValues(u.values,2)})):a,conflicts:r,componentStateSources:i,timestamp:Date.now()}}summarizeValues(e,a,r=0){if(e==null)return e;if(typeof e!="object")return typeof e=="string"&&e.length>100?e.substring(0,100)+`... (${e.length}자)`:e;if(r>=a){if(Array.isArray(e))return`[Array(${e.length})]`;const u=Object.keys(e);return`{${u.slice(0,5).join(", ")}${u.length>5?`, ... +${u.length-5}`:""}}`}if(Array.isArray(e))return e.length<=3?e.map(u=>this.summarizeValues(u,a,r+1)):{__type:"array",__length:e.length,__preview:e.slice(0,3).map(u=>this.summarizeValues(u,a,r+1))};const i={},l=Object.keys(e);for(const u of l)i[u]=this.summarizeValues(e[u],a,r+1);return i}buildStateHierarchyLayers(){const e=[];try{const r=window.G7Core?.state?.get?.();if(!r)return e;r._local&&e.push({name:"Global _local",type:"global",path:"_local",values:r._local,priority:1}),r._global&&e.push({name:"Global _global",type:"global",path:"_global",values:r._global,priority:1});for(const[l,u]of this.dynamicStates)u&&Object.keys(u).length>0&&e.push({name:`DynamicState (${l})`,type:"dynamicState",componentId:l,values:u,priority:2});const i=this.computeEffectiveState(r._local||{});e.push({name:"Effective _local (merged)",type:"effective",values:i,priority:3})}catch(a){console.warn("[G7DevTools] 상태 계층 빌드 실패:",a)}return e}computeEffectiveState(e){const a={...e};for(const[,r]of this.dynamicStates)r._local&&Object.assign(a,r._local);return a}detectStateConflicts(e){const a=[],r=e.find(l=>l.type==="global"&&l.path==="_local");if(!r)return a;const i=e.filter(l=>l.type==="dynamicState");for(const l of i){const u=l.values._local||l.values;for(const[d,f]of Object.entries(u)){const g=r.values[d];if(JSON.stringify(g)!==JSON.stringify(f)){const m=[],b=[];for(const v of this.componentStateSources.values())v.stateSource.local.some(E=>E===`_local.${d}`||E===d)&&(v.stateProvider.type==="dynamicState"?m.push(v.componentName):v.stateProvider.type==="globalState"&&b.push(v.componentName));a.push({path:`_local.${d}`,globalValue:g,dynamicStateValue:f,effectiveValue:f,usedBy:m,notUsedBy:b,severity:b.length>0?"warning":"info",description:b.length>0?`${b.join(", ")}은(는) globalState._local을 읽어 dynamicState 값을 사용하지 못함`:"dynamicState 값이 globalState와 다르지만 모든 컴포넌트가 dynamicState를 사용"})}}}return a}getContextFlowInfo(){const e=[],a=new Set(this.contextFlowNodes.keys());for(const r of this.contextFlowNodes.values())if(r.children)for(const i of r.children)a.delete(i.componentId);for(const r of a){const i=this.contextFlowNodes.get(r);i&&e.push(i)}return{rootComponent:e.length>0?e[0].component:"Unknown",contextFlow:e,timestamp:Date.now()}}clearStateHierarchyData(){this.componentStateSources.clear(),this.contextFlowNodes.clear(),this.dynamicStates.clear()}trackComponentStyle(e,a,r,i){if(!this.config.enabled)return;const l=this.analyzeTailwindClasses(r),u={componentId:e,componentName:a,classes:r,computedStyles:i,tailwindAnalysis:l};this.componentStyles.set(e,u),this.detectStyleIssues(u)}analyzeTailwindClasses(e){const a=[],r=[],i=[],l=[],u=["sm:","md:","lg:","xl:","2xl:"],d=[/bg-\w+-\d+/,/text-\w+-\d+/,/border-\w+-\d+/];for(const f of e){l.push(f),f.startsWith("dark:")&&a.push(f);for(const g of u)if(f.startsWith(g)){r.push(f);break}for(const g of d)if(g.test(f)){i.push(f);break}}return{usedClasses:l,darkClasses:a,responsiveClasses:r,dynamicClasses:i}}detectStyleIssues(e){const{componentId:a,componentName:r,computedStyles:i,tailwindAnalysis:l}=e;(i.opacity==="0"||i.visibility==="hidden"||i.display==="none"||i.width==="0px"&&i.height==="0px")&&this.addStyleIssue({id:this.generateId(),type:"invisible-element",componentId:a,componentName:r,property:i.opacity==="0"?"opacity":i.visibility==="hidden"?"visibility":i.display==="none"?"display":"width/height",currentValue:i.opacity==="0"?"0":i.visibility==="hidden"?"hidden":i.display==="none"?"none":"0px",severity:"warning",description:"요소가 화면에 보이지 않습니다.",suggestion:"opacity, visibility, display, width/height 값을 확인하세요."});const u=l.usedClasses.filter(f=>f.startsWith("bg-")&&!f.startsWith("dark:")),d=l.darkClasses.filter(f=>f.includes("bg-"));u.length>0&&d.length===0&&this.addStyleIssue({id:this.generateId(),type:"dark-mode-missing",componentId:a,componentName:r,property:"background-color",currentValue:u.join(", "),expectedValue:"dark:bg-* 클래스 필요",severity:"info",description:"다크 모드 배경색 클래스가 누락되었습니다.",suggestion:`${u[0]}에 대응하는 dark: 클래스를 추가하세요.`}),l.dynamicClasses.length>0&&this.addStyleIssue({id:this.generateId(),type:"tailwind-purging",componentId:a,componentName:r,property:"class",currentValue:l.dynamicClasses.join(", "),severity:"info",description:"동적으로 생성된 Tailwind 클래스가 있습니다.",suggestion:"tailwind.config.js의 safelist에 추가하거나 전체 클래스명을 상수로 정의하세요."})}addStyleIssue(e){this.styleIssues.some(r=>r.componentId===e.componentId&&r.type===e.type&&r.property===e.property)||this.styleIssues.push(e)}getStyleValidationInfo(){const e=Array.from(this.componentStyles.values());return{issues:[...this.styleIssues],componentStyles:e,stats:{totalComponents:e.length,invisibleCount:this.styleIssues.filter(a=>a.type==="invisible-element").length,tailwindIssueCount:this.styleIssues.filter(a=>a.type==="tailwind-purging").length,darkModeIssueCount:this.styleIssues.filter(a=>a.type==="dark-mode-missing").length},timestamp:Date.now()}}clearStyleValidationData(){this.styleIssues=[],this.componentStyles.clear()}trackAuthEvent(e,a,r,i){if(!this.config.enabled)return;const l={id:`auth_${++this.authEventIdCounter}`,type:e,timestamp:Date.now(),success:a,error:r,details:i};this.authEvents.push(l),this.authEvents.length>this.maxAuthEventHistory&&(this.authEvents=this.authEvents.slice(-this.maxAuthEventHistory))}trackAuthHeader(e,a,r,i,l){if(!this.config.enabled)return;const u={url:e,hasAuthHeader:a,headerType:r,tokenValid:i??!1,responseStatus:l,timestamp:Date.now()};this.authHeaderHistory.push(u),this.authHeaderHistory.length>this.maxAuthEventHistory&&(this.authHeaderHistory=this.authHeaderHistory.slice(-this.maxAuthEventHistory)),l===401&&this.trackAuthEvent("api-unauthorized",!1,`401 Unauthorized: ${e}`,{url:e})}getAuthState(){try{const e=window.G7Core,a=e?.api;let r=e?.auth;!r&&e?.AuthManager?.getInstance&&(r=e.AuthManager.getInstance());const i=a?.getToken?.()||r?.getAccessToken?.()||localStorage.getItem("auth_token")||localStorage.getItem("access_token"),l=r?.getRefreshToken?.()||localStorage.getItem("refresh_token");let u="unknown",d=r?.getUser?.();if(d&&(u="AuthManager"),!d){const S=e?.state?.get?.();d=S?._global?.user||S?._global?.currentUser||S?.user||S?.currentUser,d&&(u="G7Core.state")}const f=r?.isAuthenticated?.()??!1;let g="memory";localStorage.getItem("auth_token")||localStorage.getItem("access_token")?g="localStorage":(sessionStorage.getItem("auth_token")||sessionStorage.getItem("access_token"))&&(g="sessionStorage");const m=!!i&&(!!d||f);let b;i&&typeof i=="string"&&i.length>20?b=`${i.substring(0,10)}...${i.substring(i.length-6)}`:i&&(b="***");const v=d?{id:d.id,email:d.email,name:d.name,roles:d.roles?.map(S=>typeof S=="string"?{name:S}:{id:S.id,name:S.name,guard_name:S.guard_name}),permissions:d.permissions?.map(S=>typeof S=="string"?{name:S}:{id:S.id,name:S.name,guard_name:S.guard_name}),avatar:d.avatar||d.profile_photo_url||d.profile_image,created_at:d.created_at,updated_at:d.updated_at,last_login_at:d.last_login_at,email_verified_at:d.email_verified_at,...d.phone&&{phone:d.phone},...d.nickname&&{nickname:d.nickname},...d.status&&{status:d.status},...d.locale&&{locale:d.locale}}:void 0;return{isAuthenticated:m,user:v,tokens:{hasAccessToken:!!i,hasRefreshToken:!!l,storage:g,accessTokenPreview:b},lastActivity:Date.now(),source:u}}catch{return{isAuthenticated:!1,tokens:{hasAccessToken:!1,hasRefreshToken:!1,storage:"memory"},source:"unknown"}}}getAuthDebugInfo(){const e=[...this.authEvents];return{state:this.getAuthState(),events:e,headerAnalysis:[...this.authHeaderHistory],stats:{loginAttempts:e.filter(a=>a.type==="login").length,successfulLogins:e.filter(a=>a.type==="login"&&a.success).length,failedLogins:e.filter(a=>a.type==="login"&&!a.success).length,tokenRefreshes:e.filter(a=>a.type==="token-refresh").length,unauthorizedResponses:e.filter(a=>a.type==="api-unauthorized").length},timestamp:Date.now()}}clearAuthData(){this.authEvents=[],this.authHeaderHistory=[],this.authEventIdCounter=0}trackLayoutLoad(e,a,r,i="api"){if(!this.config.enabled)return;const l=Date.now();this.currentLayout={layoutPath:e,templateId:a,layoutJson:this.sanitizeObject(r),loadedAt:l,version:r.version,layoutName:r.layout_name,source:i};const u={id:`layout-${++this.layoutIdCounter}`,layoutPath:e,templateId:a,loadedAt:l,source:i,version:r.version};this.layoutHistory.push(u),this.layoutHistory.length>this.maxLayoutHistory&&this.layoutHistory.shift(),this.layoutStats.totalLoads++,i==="cache"?this.layoutStats.cacheHits++:this.layoutStats.apiLoads++}getCurrentLayout(){return this.currentLayout}getLayoutHistory(){return[...this.layoutHistory]}getLayoutDebugInfo(){return{current:this.currentLayout,history:[...this.layoutHistory],stats:{...this.layoutStats}}}clearLayoutData(){this.currentLayout=null,this.layoutHistory=[],this.layoutIdCounter=0,this.layoutStats={totalLoads:0,cacheHits:0,apiLoads:0}}startHandlerExecution(e){if(!this.config.enabled)return"";const a=`exec_${++this.executionIdCounter}_${Date.now()}`,r={handlerName:e,executionId:a,startTime:Date.now(),stateChanges:[],dataSourceChanges:[],alerts:[]};if(this.executionDetails.set(a,r),this.executionDetails.size>this.maxExecutionDetails){const i=Array.from(this.executionDetails.keys());i.slice(0,i.length-this.maxExecutionDetails).forEach(u=>this.executionDetails.delete(u))}return a}endHandlerExecution(e,a,r,i){if(!this.config.enabled||!e)return;const l=this.executionDetails.get(e);if(!l)return;l.endTime=Date.now(),l.duration=l.endTime-l.startTime,l.exitReason=a,l.exitLocation=r,l.exitDescription=i;const u=this.changeExpectations.get(e);u&&(l.expectedChanges=u,this.checkExpectations(e,l,u),this.changeExpectations.delete(e)),a==="normal"&&l.stateChanges.length===0&&l.dataSourceChanges.length===0&&this.addChangeAlert(e,{type:"no-state-change",severity:"warning",message:`핸들러 "${l.handlerName}"이(가) 상태 변경 없이 완료됨`,description:"핸들러가 성공적으로 완료되었지만 상태나 데이터소스 변경이 없습니다. 의도한 동작인지 확인하세요.",handlerName:l.handlerName,suggestion:'핸들러 내부 조건문을 확인하거나 DevTools의 "변경감지" 탭에서 exitLocation을 확인하세요.',docLink:"troubleshooting-state.md"}),(a==="early-return-condition"||a==="early-return-validation")&&this.addChangeAlert(e,{type:"early-return-detected",severity:"info",message:`핸들러 "${l.handlerName}"이(가) early return으로 종료됨`,description:i||`종료 위치: ${r||"알 수 없음"}`,handlerName:l.handlerName,suggestion:a==="early-return-validation"?"검증 실패로 인한 early return입니다. 입력 데이터를 확인하세요.":"조건부 early return입니다. 조건문의 평가 결과를 확인하세요."})}recordExitReason(e,a,r,i){if(!this.config.enabled||!e)return;const l=this.executionDetails.get(e);l&&(l.exitReason=a,l.exitLocation=r,l.exitDescription=i)}recordStateChange(e,a,r,i,l){if(!this.config.enabled)return;const u={id:`sc_${++this.stateChangeIdCounter}`,path:a,changeType:r,oldValue:this.safeClone(i),newValue:this.safeClone(l),timestamp:Date.now(),comparison:this.compareValues(i,l),executionId:e};if(this.stateChangeHistory.push(u),e){const d=this.executionDetails.get(e);d&&d.stateChanges.push(u)}this.stateChangeHistory.length>this.maxStateChangeHistory&&this.stateChangeHistory.splice(0,this.stateChangeHistory.length-this.maxStateChangeHistory),u.comparison.isDeepEqual&&typeof i=="object"&&i!==null&&this.addChangeAlert(e||"",{type:"object-reference-same",severity:"warning",message:`상태 "${a}"가 변경되었으나 값이 동일함`,description:"객체 참조가 동일하거나 깊은 비교 결과 변경이 없습니다. 변경 감지가 실패할 수 있습니다.",handlerName:e&&this.executionDetails.get(e)?.handlerName||"unknown",statePath:a,suggestion:"불변성을 유지하여 새 객체를 생성하세요. 예: { ...oldObject, newField: value }",docLink:"troubleshooting-state.md#object-mutation"})}recordDataSourceChange(e,a,r,i,l){if(!this.config.enabled)return;const u={dataSourceId:a,changeType:r,timestamp:Date.now(),previousStatus:i,newStatus:l,executionId:e};if(this.dataSourceChangeHistory.push(u),e){const d=this.executionDetails.get(e);d&&d.dataSourceChanges.push(u)}this.dataSourceChangeHistory.length>this.maxStateChangeHistory&&this.dataSourceChangeHistory.splice(0,this.dataSourceChangeHistory.length-this.maxStateChangeHistory)}expectChange(e,a,r){if(!this.config.enabled||!e)return;const i=this.executionDetails.get(e);if(!i)return;const l={expectedStatePaths:a,expectedDataSources:r,setAt:Date.now(),source:i.handlerName};this.changeExpectations.set(e,l)}checkExpectations(e,a,r){const i=new Set(a.stateChanges.map(u=>u.path)),l=new Set(a.dataSourceChanges.map(u=>u.dataSourceId));for(const u of r.expectedStatePaths)i.has(u)||this.addChangeAlert(e,{type:"expected-not-fulfilled",severity:"error",message:`기대한 상태 변경 "${u}"가 발생하지 않음`,description:`핸들러 "${a.handlerName}"이(가) "${u}" 변경을 예고했지만 실제로 변경되지 않았습니다.`,handlerName:a.handlerName,statePath:u,suggestion:"핸들러 내부 로직을 확인하세요. early return이나 조건부 분기로 인해 변경이 생략되었을 수 있습니다.",docLink:"troubleshooting-state.md"});for(const u of r.expectedDataSources)l.has(u)||this.addChangeAlert(e,{type:"expected-not-fulfilled",severity:"error",message:`기대한 데이터소스 갱신 "${u}"가 발생하지 않음`,description:`핸들러 "${a.handlerName}"이(가) "${u}" 갱신을 예고했지만 실제로 갱신되지 않았습니다.`,handlerName:a.handlerName,dataSourceId:u,suggestion:"refetchDataSource 호출이 실행되었는지 확인하세요.",docLink:"data-sources.md"})}addChangeAlert(e,a){const r={...a,id:`alert_${++this.alertIdCounter}`,timestamp:Date.now()};if(this.changeAlerts.push(r),e){const i=this.executionDetails.get(e);i&&i.alerts.push(r)}this.changeAlerts.length>this.maxChangeAlerts&&this.changeAlerts.splice(0,this.changeAlerts.length-this.maxChangeAlerts)}compareValues(e,a){const r=this.getValueType(e),i=this.getValueType(a),l=r!==i;let u=!1,d;return!l&&(r==="object"||r==="array")?(u=this.deepEqual(e,a),!u&&r==="object"&&(d=this.getChangedKeys(e,a))):u=e===a,{typeChanged:l,oldType:r,newType:i,isDeepEqual:u,changedKeys:d}}getValueType(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}deepEqual(e,a){if(e===a)return!0;if(typeof e!=typeof a)return!1;if(e===null||a===null||typeof e!="object")return e===a;if(Array.isArray(e)!==Array.isArray(a))return!1;const r=Object.keys(e),i=Object.keys(a);if(r.length!==i.length)return!1;for(const l of r)if(!i.includes(l)||!this.deepEqual(e[l],a[l]))return!1;return!0}getChangedKeys(e,a){const r=[],i=new Set([...Object.keys(e),...Object.keys(a)]);for(const l of i)this.deepEqual(e[l],a[l])||r.push(l);return r}getChangeDetectionInfo(){const e=Array.from(this.executionDetails.values()),a={totalExecutions:e.length,executionsWithStateChange:e.filter(r=>r.stateChanges.length>0).length,executionsWithoutStateChange:e.filter(r=>r.stateChanges.length===0&&r.exitReason==="normal").length,earlyReturnCount:e.filter(r=>r.exitReason==="early-return-condition"||r.exitReason==="early-return-validation").length,alertCount:this.changeAlerts.length,alertsByType:this.getAlertsByType()};return{executionDetails:e,stateChangeHistory:[...this.stateChangeHistory],dataSourceChangeHistory:[...this.dataSourceChangeHistory],alerts:[...this.changeAlerts],stats:a,timestamp:Date.now()}}getAlertsByType(){const e={"no-state-change":0,"no-datasource-change":0,"expected-not-fulfilled":0,"object-reference-same":0,"early-return-detected":0,"async-timing-issue":0};for(const a of this.changeAlerts)e[a.type]++;return e}clearChangeDetectionData(){this.executionDetails.clear(),this.stateChangeHistory=[],this.dataSourceChangeHistory=[],this.changeAlerts=[],this.changeExpectations.clear(),this.executionIdCounter=0,this.stateChangeIdCounter=0,this.alertIdCounter=0}getRecentAlerts(e=10,a){let r=[...this.changeAlerts];return a&&(r=r.filter(i=>i.severity===a)),r.slice(-e)}getHandlerExecutions(e,a=10){return Array.from(this.executionDetails.values()).filter(i=>i.handlerName===e).slice(-a)}findExecutionInStack(e){return this.sequenceExecutionStack.find(a=>a.sequenceId===e)}startSequenceExecution(e){if(!this.config.enabled)return"";const a=`seq_${++this.sequenceIdCounter}_${Date.now()}`,r={sequenceId:a,startTime:Date.now(),totalDuration:0,trigger:e,actions:[],status:"running"};return this.sequenceExecutionStack.push(r),a}captureSequenceActionBefore(e,a,r,i,l){if(!this.config.enabled)return;const u=this.findExecutionInStack(e);if(!u)return;const d={index:a,handler:r,params:this.safeClone(i),stateBeforeAction:{_global:this.safeClone(l._global),_local:this.safeClone(l._local),_isolated:l._isolated?this.safeClone(l._isolated):void 0},stateAfterAction:{_global:{},_local:{}},duration:0,status:"success"};u.actions.push(d)}captureSequenceActionAfter(e,a,r,i,l,u){if(!this.config.enabled)return;const d=this.findExecutionInStack(e);if(!d)return;const f=d.actions.find(m=>m.index===a);if(!f)return;f.stateAfterAction={_global:this.safeClone(r._global),_local:this.safeClone(r._local),_isolated:r._isolated?this.safeClone(r._isolated):void 0},f.duration=i,f.result=this.safeClone(l),f.stateDiff={global:this.computeStateDiff(f.stateBeforeAction._global,f.stateAfterAction._global),local:this.computeStateDiff(f.stateBeforeAction._local,f.stateAfterAction._local)},f.stateBeforeAction._isolated&&f.stateAfterAction._isolated&&(f.stateDiff.isolated=this.computeStateDiff(f.stateBeforeAction._isolated,f.stateAfterAction._isolated));const g=window.__g7PendingLocalState;g&&(f.pendingState=this.safeClone(g)),u&&(f.status="error",f.error={name:u.name,message:u.message,stack:u.stack})}endSequenceExecution(e,a){if(!this.config.enabled)return;const r=this.sequenceExecutionStack.findIndex(l=>l.sequenceId===e);if(r===-1)return;const i=this.sequenceExecutionStack[r];if(i.endTime=Date.now(),i.totalDuration=i.endTime-i.startTime,a){i.status="error",i.error={name:a.name,message:a.message,stack:a.stack};const l=i.actions.find(u=>u.status==="error");l&&(i.failedAtIndex=l.index)}else i.status="success";this.sequenceExecutions.push(i),this.sequenceExecutions.length>this.maxSequenceExecutions&&this.sequenceExecutions.shift(),this.sequenceExecutionStack.splice(r,1)}computeStateDiff(e,a){const r=[],i=[],l=[],u=new Set(Object.keys(e)),d=new Set(Object.keys(a));for(const f of d)u.has(f)||r.push(f);for(const f of u)d.has(f)||i.push(f);for(const f of u)if(d.has(f)){const g=e[f],m=a[f];JSON.stringify(g)!==JSON.stringify(m)&&l.push({path:f,oldValue:g,newValue:m})}return{added:r,removed:i,changed:l}}getSequenceTrackingInfo(){const e=this.getSequenceStats(),a=this.sequenceExecutionStack.length>0?this.sequenceExecutionStack[this.sequenceExecutionStack.length-1]:void 0;return{executions:[...this.sequenceExecutions],currentExecution:a,stats:e}}getSequenceStats(){const e=this.sequenceExecutions,a=e.length,r=e.filter(g=>g.status==="success").length,i=e.filter(g=>g.status==="error").length,l=e.reduce((g,m)=>g+m.actions.length,0),u=a>0?e.reduce((g,m)=>g+m.totalDuration,0)/a:0,d={};for(const g of e)for(const m of g.actions)d[m.handler]=(d[m.handler]||0)+1;const f=Object.entries(d).sort(([,g],[,m])=>m-g).slice(0,5).map(([g,m])=>({handler:g,count:m}));return{totalExecutions:a,successCount:r,errorCount:i,totalActions:l,avgDuration:u,topHandlers:f}}clearSequenceData(){this.sequenceExecutions=[],this.sequenceExecutionStack=[],this.sequenceIdCounter=0}getSequenceExecution(e){const a=this.findExecutionInStack(e);return a||this.sequenceExecutions.find(r=>r.sequenceId===e)}getRecentSequences(e=10){return this.sequenceExecutions.slice(-e)}registerStateCaptureForHandler(e,a,r){if(!this.config.enabled)return;const i=new Map,l=Date.now();for(const u of a)i.set(u,{value:this.safeClone(r[u]),capturedAt:l});this.stateCaptureRegistry.set(e,i)}detectStaleClosure(e,a,r,i,l){if(!this.config.enabled)return[];const u=this.stateCaptureRegistry.get(e);if(!u)return[];const d=Date.now(),f=[];for(const[g,m]of u){const b=this.getValueByPath(r,g),v=d-m.capturedAt;if(!this.isDeepEqual(m.value,b)&&v>0){const S=this.createStaleClosureWarning(i,a,g,m.value,m.capturedAt,b,d,v,l);f.push(S),this.addStaleClosureWarning(S)}}return this.stateCaptureRegistry.delete(e),f}trackStaleClosureWarning(e){if(!this.config.enabled)return;const a=Date.now(),r=this.createStaleClosureWarning(e.type,e.location,e.capturedPath,e.capturedValue,e.capturedAt,e.currentValue,a,a-e.capturedAt,e.actionId,e.stackTrace);this.addStaleClosureWarning(r)}createStaleClosureWarning(e,a,r,i,l,u,d,f,g,m){const b=this.getStaleClosureSeverity(e,f),{description:v,suggestion:S,docLink:E}=this.getStaleClosureMessages(e,r,f);return{id:`stale_${++this.staleClosureIdCounter}_${Date.now()}`,timestamp:Date.now(),type:e,location:a,capturedState:{path:r,capturedValue:this.safeClone(i),capturedAt:l},currentState:{path:r,currentValue:this.safeClone(u),retrievedAt:d},timeDiff:f,severity:b,description:v,suggestion:S,docLink:E,actionId:g,stackTrace:m}}getStaleClosureSeverity(e,a){if(a>5e3)return"error";if(a>1e3)return"warning";switch(e){case"async-state-capture":case"sequence-state-mismatch":return"warning";case"callback-state-capture":case"timeout-state-capture":return"info";case"event-handler-stale":return"warning";default:return"info"}}getStaleClosureMessages(e,a,r){const i=r<1e3?`${r}ms`:`${(r/1e3).toFixed(1)}s`;switch(e){case"async-state-capture":return{description:`await 후 ${i} 경과 시점에 '${a}' 상태가 변경됨. 캡처된 상태 대신 최신 상태를 사용해야 함`,suggestion:"await 이후에는 G7Core.state.get()으로 최신 상태를 다시 조회하거나, useRef + getter 패턴을 사용하세요",docLink:"troubleshooting-state-closure.md"};case"callback-state-capture":return{description:`콜백에서 ${i} 전에 캡처된 '${a}' 상태를 사용 중. 최신 상태와 다름`,suggestion:"콜백에서 상태를 참조할 때는 stateRef.current 패턴 또는 G7Core.state.get()를 사용하세요",docLink:"troubleshooting-state-closure.md"};case"timeout-state-capture":return{description:`setTimeout/setInterval 콜백에서 '${a}' 상태가 ${i} 전 값 사용 중`,suggestion:"타이머 콜백 내에서는 G7Core.state.get()으로 최신 상태를 조회하세요",docLink:"troubleshooting-state-closure.md"};case"sequence-state-mismatch":return{description:`sequence 내 '${a}' 상태가 이전 액션 결과와 불일치. context.state 대신 캡처된 값 사용 의심`,suggestion:"sequence 내에서는 context.state 또는 $prev를 사용하여 최신 상태를 참조하세요",docLink:"troubleshooting-state-setstate.md"};case"event-handler-stale":return{description:`이벤트 핸들러에서 ${i} 전에 바인딩된 '${a}' 상태 사용 중`,suggestion:"이벤트 핸들러에서 상태를 참조할 때는 useRef 패턴 또는 G7Core.state.get()를 사용하세요",docLink:"troubleshooting-state-closure.md"};default:return{description:`'${a}' 상태에서 stale closure 감지됨 (${i} 경과)`,suggestion:"상태 참조 시 최신 값을 사용하는지 확인하세요"}}}addStaleClosureWarning(e){this.staleClosureWarnings.push(e),this.staleClosureWarnings.length>this.maxStaleClosureWarnings&&this.staleClosureWarnings.shift()}getValueByPath(e,a){const r=a.split(".");let i=e;for(const l of r){if(i==null)return;i=i[l]}return i}isDeepEqual(e,a){if(e===a)return!0;if(e===null||a===null)return e===a;if(typeof e!=typeof a)return!1;if(typeof e!="object")return e===a;try{return JSON.stringify(e)===JSON.stringify(a)}catch{return!1}}getStaleClosureTrackingInfo(){const e=this.getStaleClosureStats();return{warnings:[...this.staleClosureWarnings],stats:e,timestamp:Date.now()}}getStaleClosureStats(){const e=this.staleClosureWarnings,a={"async-state-capture":0,"callback-state-capture":0,"timeout-state-capture":0,"sequence-state-mismatch":0,"event-handler-stale":0};for(const f of e)a[f.type]++;const r={info:0,warning:0,error:0};for(const f of e)r[f.severity]++;const i={};for(const f of e)i[f.location]=(i[f.location]||0)+1;const l=Object.entries(i).sort(([,f],[,g])=>g-f).slice(0,5).map(([f,g])=>({location:f,count:g})),u={};for(const f of e)u[f.capturedState.path]=(u[f.capturedState.path]||0)+1;const d=Object.entries(u).sort(([,f],[,g])=>g-f).slice(0,5).map(([f,g])=>({path:f,count:g}));return{totalWarnings:e.length,warningsByType:a,warningsBySeverity:r,topLocations:l,topAffectedPaths:d}}clearStaleClosureData(){this.staleClosureWarnings=[],this.staleClosureIdCounter=0,this.stateCaptureRegistry.clear()}getRecentStaleClosureWarnings(e=10,a){let r=[...this.staleClosureWarnings];return a&&(r=r.filter(i=>i.severity===a)),r.slice(-e)}safeClone(e){if(e==null||typeof e!="object")return e;try{return JSON.parse(JSON.stringify(e))}catch{if(Array.isArray(e))return e.map(r=>{try{return JSON.parse(JSON.stringify(r))}catch{return"[Unserializable]"}});const a={};for(const r of Object.keys(e))try{a[r]=JSON.parse(JSON.stringify(e[r]))}catch{a[r]="[Unserializable]"}return a}}};$(yi,"instance");let Tr=yi;const Bn=ct("LayoutLoader");class ba extends Error{constructor(a,r,i){super(a);$(this,"code");$(this,"details");this.code=r,this.details=i,this.name="LayoutLoaderError"}}class tf{constructor(e){$(this,"componentRegistry");$(this,"currentLayout",null);$(this,"layoutCache",new Map);$(this,"cacheVersion",0);this.componentRegistry=e}setCacheVersion(e){this.cacheVersion!==e&&(Bn.log("Cache version updated:",this.cacheVersion,"->",e),this.cacheVersion=e,this.layoutCache.clear())}getCacheVersion(){return this.cacheVersion}async loadLayout(e,a){const r=`${e}:${a}`;if(this.layoutCache.has(r)){Bn.log("Loading layout from cache:",a);const l=await this.layoutCache.get(r),u=JSON.parse(JSON.stringify(l));return this.currentLayout=u,Tr.getInstance().trackLayoutLoad(a,e,u,"cache"),u}const i=this.fetchLayout(e,a);return this.layoutCache.set(r,i),i.catch(()=>{this.layoutCache.get(r)===i&&this.layoutCache.delete(r)}),i}async fetchLayout(e,a,r=!1){try{const i=this.cacheVersion>0?this.cacheVersion:null;let l;if(a.startsWith("__preview__/")){const v=a.replace("__preview__/","");l=La(`/api/layouts/preview/${v}`,"json",i)}else l=La(`/api/layouts/${e}/${a}`,"json",i);Bn.log("Fetching layout from API:",l);const u=$a(),d=r?null:u.getToken(),f={Accept:"application/json"};d&&(f.Authorization=`Bearer ${d}`);const g=await xl(l,{init:{headers:f},label:`layout: ${a}`});let m;try{m=await g.json()}catch{m=null}if(!g.ok){if(g.status===401&&!r&&d){Bn.log("Token invalid, removing and retrying without token"),u.removeToken();try{return await this.fetchLayout(e,a,!0)}catch(S){throw S instanceof ba&&S.details?.status===401?new ba(S.message,S.code,{...S.details,hadToken:!0}):S}}const v=m?.message||m?.error;throw new ba(`Failed to fetch layout: ${g.status} ${g.statusText}`,"FETCH_FAILED",{status:g.status,statusText:g.statusText,url:l,apiMessage:v})}const b=m.data||m;return this.validateLayoutData(b),this.currentLayout=b,Tr.getInstance().trackLayoutLoad(a,e,b,"api"),Bn.log("Layout fetched and cached successfully:",b.layout_name),b}catch(i){const l=`${e}:${a}`;throw this.layoutCache.delete(l),i instanceof ba?i:new ba("Failed to load layout","LOAD_FAILED",{originalError:i})}}prefetchLayout(e,a){return this.loadLayout(e,a)}validateLayoutData(e){if(!e.version)throw new ba("Layout data missing required field: version","VALIDATION_FAILED",{field:"version"});if(!e.layout_name)throw new ba("Layout data missing required field: layout_name","VALIDATION_FAILED",{field:"layout_name"});if(!Array.isArray(e.components))throw new ba('Layout data field "components" must be an array',"VALIDATION_FAILED",{field:"components",value:e.components});Bn.log("Layout data validation passed")}renderLayout(e,a){try{const r=a||this.currentLayout;if(!r)throw new ba("No layout data to render","NO_LAYOUT_DATA");Bn.log("Rendering layout:",r.layout_name),e.innerHTML="",this.renderComponents(e,r.components),Bn.log("Layout rendered successfully")}catch(r){Bn.error("Render error:",r),this.renderErrorState(e,r)}}renderComponents(e,a){for(const r of a){const i=this.renderComponent(r);i&&e.appendChild(i)}}renderComponent(e){try{if(!this.componentRegistry.getComponent(e.type))return Bn.warn(`Component not found: ${e.type}`),this.createPlaceholderElement(e.type);const r=document.createElement("div");return r.setAttribute("data-component",e.type),e.props&&Object.entries(e.props).forEach(([i,l])=>{r.setAttribute(`data-prop-${i}`,JSON.stringify(l))}),e.children&&e.children.length>0?this.renderComponents(r,e.children):e.text&&(r.textContent=e.text),r}catch(a){return Bn.error(`Error rendering component ${e.type}:`,a),this.createErrorElement(e.type,a)}}createPlaceholderElement(e){const a=document.createElement("div");return a.className="component-placeholder",a.setAttribute("data-component-type",e),a.innerHTML=`

Component not found: ${e}

@@ -102,8 +102,8 @@ Error generating stack: `+c.message+` " >페이지 새로고침 - `,Bn.error("Error state rendered:",i,r)}getCurrentLayout(){return this.currentLayout}clear(){this.currentLayout=null,this.layoutCache.clear(),Bn.log("Layout data and cache cleared")}}const S_=ct("TranslationContext"),tf=N.createContext(null),cc=({children:o,translationEngine:e,translationContext:a})=>{const r=N.useMemo(()=>(l,u)=>{if(u){const d="|"+Object.entries(u).map(([f,g])=>`${f}=${g}`).join("|");return e.translate(l,a,d)}return e.translate(l,a)},[e,a]),i=N.useMemo(()=>({translationEngine:e,translationContext:a,t:r}),[e,a,r]);return ut.jsx(tf.Provider,{value:i,children:o})},Fm=()=>{const o=N.useContext(tf);return o||(S_.warn("TranslationProvider 외부에서 호출되었습니다. 키를 그대로 반환합니다."),{t:e=>e,translationEngine:null,translationContext:null})},Rr=ct("SlotContext"),w_={registerToSlot:()=>{Rr.warn("SlotContext not available: registerToSlot called outside SlotProvider")},unregisterFromSlot:()=>{Rr.warn("SlotContext not available: unregisterFromSlot called outside SlotProvider")},getSlotComponents:()=>[],subscribeToSlot:()=>()=>{},clearAllSlots:()=>{},isEnabled:!1},C_=N.createContext(w_),nf=({children:o})=>{const e=N.useRef(new Map),a=N.useRef(new Map),r=N.useCallback(m=>{const b=a.current.get(m);b&&b.forEach(v=>{try{v()}catch(S){Rr.error(`Slot subscriber error (slotId: ${m}):`,S)}})},[]),i=N.useCallback((m,b,v)=>{if(!m||!b){Rr.warn("registerToSlot: slotId and componentId are required");return}e.current.has(m)||e.current.set(m,new Map);const S=e.current.get(m),E=S.get(b);E&&E.registrationKey===v.registrationKey||(S.set(b,v),Rr.log(`Component registered to slot: ${b} -> ${m} (order: ${v.order})`),r(m))},[r]),l=N.useCallback((m,b)=>{const v=e.current.get(m);v&&v.has(b)&&(v.delete(b),Rr.log(`Component unregistered from slot: ${b} <- ${m}`),v.size===0&&e.current.delete(m),r(m))},[r]),u=N.useCallback(m=>{const b=e.current.get(m);return b?Array.from(b.values()).sort((v,S)=>v.order-S.order):[]},[]),d=N.useCallback((m,b)=>{a.current.has(m)||a.current.set(m,new Set);const v=a.current.get(m);return v.add(b),()=>{v.delete(b),v.size===0&&a.current.delete(m)}},[]),f=N.useCallback(()=>{e.current.forEach((m,b)=>{r(b)}),e.current.clear(),a.current.clear(),Rr.log("All slots cleared")},[r]),g=N.useMemo(()=>({registerToSlot:i,unregisterFromSlot:l,getSlotComponents:u,subscribeToSlot:d,clearAllSlots:f,isEnabled:!0}),[i,l,u,d,f]);return N.useLayoutEffect(()=>{typeof window<"u"&&(window.__slotContextValue=g,Rr.log("SlotContext exposed to window.__slotContextValue"))},[g]),ut.jsx(C_.Provider,{value:g,children:o})};class af{constructor(){this.notificationCreatedEvent=".Illuminate\\Notifications\\Events\\BroadcastNotificationCreated"}listenForWhisper(e,a){return this.listen(".client-"+e,a)}notification(e){return this.listen(this.notificationCreatedEvent,e)}stopListeningForNotification(e){return this.stopListening(this.notificationCreatedEvent,e)}stopListeningForWhisper(e,a){return this.stopListening(".client-"+e,a)}}class Km{constructor(e){this.namespace=e}format(e){return[".","\\"].includes(e.charAt(0))?e.substring(1):(this.namespace&&(e=this.namespace+"."+e),e.replace(/\./g,"\\"))}setNamespace(e){this.namespace=e}}function E_(o){try{return Reflect.construct(String,[],o),!0}catch{return!1}}class rf extends af{constructor(e,a,r){super(),this.name=a,this.pusher=e,this.options=r,this.eventFormatter=new Km(this.options.namespace),this.subscribe()}subscribe(){this.subscription=this.pusher.subscribe(this.name)}unsubscribe(){this.pusher.unsubscribe(this.name)}listen(e,a){return this.on(this.eventFormatter.format(e),a),this}listenToAll(e){return this.subscription.bind_global((a,r)=>{if(a.startsWith("pusher:"))return;let i=String(this.options.namespace??"").replace(/\./g,"\\"),l=a.startsWith(i)?a.substring(i.length+1):"."+a;e(l,r)}),this}stopListening(e,a){return a?this.subscription.unbind(this.eventFormatter.format(e),a):this.subscription.unbind(this.eventFormatter.format(e)),this}stopListeningToAll(e){return e?this.subscription.unbind_global(e):this.subscription.unbind_global(),this}subscribed(e){return this.on("pusher:subscription_succeeded",()=>{e()}),this}error(e){return this.on("pusher:subscription_error",a=>{e(a)}),this}on(e,a){return this.subscription.bind(e,a),this}}class Wm extends rf{whisper(e,a){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,a),this}}class __ extends rf{whisper(e,a){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,a),this}}class A_ extends Wm{here(e){return this.on("pusher:subscription_succeeded",a=>{e(Object.keys(a.members).map(r=>a.members[r]))}),this}joining(e){return this.on("pusher:member_added",a=>{e(a.info)}),this}whisper(e,a){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,a),this}leaving(e){return this.on("pusher:member_removed",a=>{e(a.info)}),this}}class Ym extends af{constructor(e,a,r){super(),this.events={},this.listeners={},this.name=a,this.socket=e,this.options=r,this.eventFormatter=new Km(this.options.namespace),this.subscribe()}subscribe(){this.socket.emit("subscribe",{channel:this.name,auth:this.options.auth||{}})}unsubscribe(){this.unbind(),this.socket.emit("unsubscribe",{channel:this.name,auth:this.options.auth||{}})}listen(e,a){return this.on(this.eventFormatter.format(e),a),this}stopListening(e,a){return this.unbindEvent(this.eventFormatter.format(e),a),this}subscribed(e){return this.on("connect",a=>{e(a)}),this}error(e){return this}on(e,a){return this.listeners[e]=this.listeners[e]||[],this.events[e]||(this.events[e]=(r,i)=>{this.name===r&&this.listeners[e]&&this.listeners[e].forEach(l=>l(i))},this.socket.on(e,this.events[e])),this.listeners[e].push(a),this}unbind(){Object.keys(this.events).forEach(e=>{this.unbindEvent(e)})}unbindEvent(e,a){this.listeners[e]=this.listeners[e]||[],a&&(this.listeners[e]=this.listeners[e].filter(r=>r!==a)),(!a||this.listeners[e].length===0)&&(this.events[e]&&(this.socket.removeListener(e,this.events[e]),delete this.events[e]),delete this.listeners[e])}}class Xm extends Ym{whisper(e,a){return this.socket.emit("client event",{channel:this.name,event:`client-${e}`,data:a}),this}}class x_ extends Xm{here(e){return this.on("presence:subscribed",a=>{e(a.map(r=>r.user_info))}),this}joining(e){return this.on("presence:joining",a=>e(a.user_info)),this}whisper(e,a){return this.socket.emit("client event",{channel:this.name,event:`client-${e}`,data:a}),this}leaving(e){return this.on("presence:leaving",a=>e(a.user_info)),this}}class uc extends af{subscribe(){}unsubscribe(){}listen(e,a){return this}listenToAll(e){return this}stopListening(e,a){return this}subscribed(e){return this}error(e){return this}on(e,a){return this}}class Jm extends uc{whisper(e,a){return this}}class T_ extends uc{whisper(e,a){return this}}class R_ extends Jm{here(e){return this}joining(e){return this}whisper(e,a){return this}leaving(e){return this}}const Qm=class DS{constructor(e){this.setOptions(e),this.connect()}setOptions(e){this.options={...DS._defaultOptions,...e,broadcaster:e.broadcaster};let a=this.csrfToken();a&&(this.options.auth.headers["X-CSRF-TOKEN"]=a,this.options.userAuthentication.headers["X-CSRF-TOKEN"]=a),a=this.options.bearerToken,a&&(this.options.auth.headers.Authorization="Bearer "+a,this.options.userAuthentication.headers.Authorization="Bearer "+a)}csrfToken(){var e,a;return typeof window<"u"&&(e=window.Laravel)!=null&&e.csrfToken?window.Laravel.csrfToken:this.options.csrfToken?this.options.csrfToken:typeof document<"u"&&typeof document.querySelector=="function"?((a=document.querySelector('meta[name="csrf-token"]'))==null?void 0:a.getAttribute("content"))??null:null}};Qm._defaultOptions={auth:{headers:{}},authEndpoint:"/broadcasting/auth",userAuthentication:{endpoint:"/broadcasting/user-auth",headers:{}},csrfToken:null,bearerToken:null,host:null,key:null,namespace:"App.Events"};let sf=Qm;class dc extends sf{constructor(){super(...arguments),this.channels={}}connect(){if(typeof this.options.client<"u")this.pusher=this.options.client;else if(this.options.Pusher)this.pusher=new this.options.Pusher(this.options.key,this.options);else if(typeof window<"u"&&typeof window.Pusher<"u")this.pusher=new window.Pusher(this.options.key,this.options);else throw new Error("Pusher client not found. Should be globally available or passed via options.client")}signin(){this.pusher.signin()}listen(e,a,r){return this.channel(e).listen(a,r)}channel(e){return this.channels[e]||(this.channels[e]=new rf(this.pusher,e,this.options)),this.channels[e]}privateChannel(e){return this.channels["private-"+e]||(this.channels["private-"+e]=new Wm(this.pusher,"private-"+e,this.options)),this.channels["private-"+e]}encryptedPrivateChannel(e){return this.channels["private-encrypted-"+e]||(this.channels["private-encrypted-"+e]=new __(this.pusher,"private-encrypted-"+e,this.options)),this.channels["private-encrypted-"+e]}presenceChannel(e){return this.channels["presence-"+e]||(this.channels["presence-"+e]=new A_(this.pusher,"presence-"+e,this.options)),this.channels["presence-"+e]}leave(e){[e,"private-"+e,"private-encrypted-"+e,"presence-"+e].forEach(a=>{this.leaveChannel(a)})}leaveChannel(e){this.channels[e]&&(this.channels[e].unsubscribe(),delete this.channels[e])}socketId(){return this.pusher.connection.socket_id}connectionStatus(){const e=this.pusher.connection.state;switch(e){case"connected":case"connecting":return e;case"failed":case"unavailable":return"failed";default:return"disconnected"}}onConnectionChange(e){const a=()=>{e(this.connectionStatus())},r=["state_change","connected","disconnected"];return r.forEach(i=>{this.pusher.connection.bind(i,a)}),()=>{r.forEach(i=>{this.pusher.connection.unbind(i,a)})}}disconnect(){this.pusher.disconnect()}}class k_ extends sf{constructor(){super(...arguments),this.channels={}}connect(){let e=this.getSocketIO();this.socket=e(this.options.host??void 0,this.options),this.socket.io.on("reconnect",()=>{Object.values(this.channels).forEach(a=>{a.subscribe()})})}getSocketIO(){if(typeof this.options.client<"u")return this.options.client;if(typeof window<"u"&&typeof window.io<"u")return window.io;throw new Error("Socket.io client not found. Should be globally available or passed via options.client")}listen(e,a,r){return this.channel(e).listen(a,r)}channel(e){return this.channels[e]||(this.channels[e]=new Ym(this.socket,e,this.options)),this.channels[e]}privateChannel(e){return this.channels["private-"+e]||(this.channels["private-"+e]=new Xm(this.socket,"private-"+e,this.options)),this.channels["private-"+e]}presenceChannel(e){return this.channels["presence-"+e]||(this.channels["presence-"+e]=new x_(this.socket,"presence-"+e,this.options)),this.channels["presence-"+e]}leave(e){[e,"private-"+e,"presence-"+e].forEach(a=>{this.leaveChannel(a)})}leaveChannel(e){this.channels[e]&&(this.channels[e].unsubscribe(),delete this.channels[e])}socketId(){return this.socket.id}connectionStatus(){return this.socket.connected?"connected":this.socket.io._reconnecting?"reconnecting":this.socket.id!==void 0?"disconnected":"connecting"}onConnectionChange(e){const a=()=>{e(this.connectionStatus())},r=["connect","disconnect","connect_error","reconnect_attempt","reconnect","reconnect_error","reconnect_failed"];return r.forEach(i=>{this.socket.on(i,a)}),()=>{r.forEach(i=>{this.socket.off(i,a)})}}disconnect(){this.socket.disconnect()}}class Zm extends sf{constructor(){super(...arguments),this.channels={}}connect(){}listen(e,a,r){return new uc}channel(e){return new uc}privateChannel(e){return new Jm}encryptedPrivateChannel(e){return new T_}presenceChannel(e){return new R_}leave(e){}leaveChannel(e){}socketId(){return"fake-socket-id"}connectionStatus(){return"connected"}onConnectionChange(e){return()=>{}}disconnect(){}}class D_{constructor(e){this.options=e,this.connect(),this.options.withoutInterceptors||this.registerInterceptors()}channel(e){return this.connector.channel(e)}connect(){if(this.options.broadcaster==="reverb")this.connector=new dc({...this.options,cluster:""});else if(this.options.broadcaster==="pusher")this.connector=new dc(this.options);else if(this.options.broadcaster==="ably")this.connector=new dc({...this.options,cluster:"",broadcaster:"pusher"});else if(this.options.broadcaster==="socket.io")this.connector=new k_(this.options);else if(this.options.broadcaster==="null")this.connector=new Zm(this.options);else if(typeof this.options.broadcaster=="function"&&E_(this.options.broadcaster))this.connector=new this.options.broadcaster(this.options);else throw new Error(`Broadcaster ${typeof this.options.broadcaster} ${String(this.options.broadcaster)} is not supported.`)}disconnect(){this.connector.disconnect()}join(e){return this.connector.presenceChannel(e)}leave(e){this.connector.leave(e)}leaveChannel(e){this.connector.leaveChannel(e)}leaveAllChannels(){for(const e in this.connector.channels)this.leaveChannel(e)}listen(e,a,r){return this.connector.listen(e,a,r)}private(e){return this.connector.privateChannel(e)}encryptedPrivate(e){if(this.connectorSupportsEncryptedPrivateChannels(this.connector))return this.connector.encryptedPrivateChannel(e);throw new Error(`Broadcaster ${typeof this.options.broadcaster} ${String(this.options.broadcaster)} does not support encrypted private channels.`)}connectorSupportsEncryptedPrivateChannels(e){return e instanceof dc||e instanceof Zm}socketId(){return this.connector.socketId()}connectionStatus(){return this.connector.connectionStatus()}registerInterceptors(){typeof Vue<"u"&&Vue!=null&&Vue.http&&this.registerVueRequestInterceptor(),typeof axios=="function"&&this.registerAxiosRequestInterceptor(),typeof jQuery=="function"&&this.registerjQueryAjaxSetup(),typeof Turbo=="object"&&this.registerTurboRequestInterceptor()}registerVueRequestInterceptor(){Vue.http.interceptors.push((e,a)=>{this.socketId()&&e.headers.set("X-Socket-ID",this.socketId()),a()})}registerAxiosRequestInterceptor(){axios.interceptors.request.use(e=>(this.socketId()&&(e.headers["X-Socket-Id"]=this.socketId()),e))}registerjQueryAjaxSetup(){typeof jQuery.ajax<"u"&&jQuery.ajaxPrefilter((e,a,r)=>{this.socketId()&&r.setRequestHeader("X-Socket-Id",this.socketId())})}registerTurboRequestInterceptor(){document.addEventListener("turbo:before-fetch-request",e=>{e.detail.fetchOptions.headers["X-Socket-Id"]=this.socketId()})}}var of={exports:{}};var ey;function O_(){return ey||(ey=1,(function(o,e){(function(r,i){o.exports=i()})(self,()=>(()=>{var a={594(u,d){var f=this&&this.__extends||(function(){var M=function(R,D){return M=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(U,j){U.__proto__=j}||function(U,j){for(var P in j)j.hasOwnProperty(P)&&(U[P]=j[P])},M(R,D)};return function(R,D){M(R,D);function U(){this.constructor=R}R.prototype=D===null?Object.create(D):(U.prototype=D.prototype,new U)}})();Object.defineProperty(d,"__esModule",{value:!0});var g=256,m=(function(){function M(R){R===void 0&&(R="="),this._paddingCharacter=R}return M.prototype.encodedLength=function(R){return this._paddingCharacter?(R+2)/3*4|0:(R*8+5)/6|0},M.prototype.encode=function(R){for(var D="",U=0;U>>18&63),D+=this._encodeByte(j>>>12&63),D+=this._encodeByte(j>>>6&63),D+=this._encodeByte(j>>>0&63)}var P=R.length-U;if(P>0){var j=R[U]<<16|(P===2?R[U+1]<<8:0);D+=this._encodeByte(j>>>18&63),D+=this._encodeByte(j>>>12&63),P===2?D+=this._encodeByte(j>>>6&63):D+=this._paddingCharacter||"",D+=this._paddingCharacter||""}return D},M.prototype.maxDecodedLength=function(R){return this._paddingCharacter?R/4*3|0:(R*6+7)/8|0},M.prototype.decodedLength=function(R){return this.maxDecodedLength(R.length-this._getPaddingLength(R))},M.prototype.decode=function(R){if(R.length===0)return new Uint8Array(0);for(var D=this._getPaddingLength(R),U=R.length-D,j=new Uint8Array(this.maxDecodedLength(U)),P=0,X=0,ge=0,Ee=0,Ce=0,$e=0,Pe=0;X>>4,j[P++]=Ce<<4|$e>>>2,j[P++]=$e<<6|Pe,ge|=Ee&g,ge|=Ce&g,ge|=$e&g,ge|=Pe&g;if(X>>4,ge|=Ee&g,ge|=Ce&g),X>>2,ge|=$e&g),X>>8&6,D+=51-R>>>8&-75,D+=61-R>>>8&-15,D+=62-R>>>8&3,String.fromCharCode(D)},M.prototype._decodeChar=function(R){var D=g;return D+=(42-R&R-44)>>>8&-g+R-43+62,D+=(46-R&R-48)>>>8&-g+R-47+63,D+=(47-R&R-58)>>>8&-g+R-48+52,D+=(64-R&R-91)>>>8&-g+R-65+0,D+=(96-R&R-123)>>>8&-g+R-97+26,D},M.prototype._getPaddingLength=function(R){var D=0;if(this._paddingCharacter){for(var U=R.length-1;U>=0&&R[U]===this._paddingCharacter;U--)D++;if(R.length<4||D>2)throw new Error("Base64Coder: incorrect padding")}return D},M})();d.Coder=m;var b=new m;function v(M){return b.encode(M)}d.encode=v;function S(M){return b.decode(M)}d.decode=S;var E=(function(M){f(R,M);function R(){return M!==null&&M.apply(this,arguments)||this}return R.prototype._encodeByte=function(D){var U=D;return U+=65,U+=25-D>>>8&6,U+=51-D>>>8&-75,U+=61-D>>>8&-13,U+=62-D>>>8&49,String.fromCharCode(U)},R.prototype._decodeChar=function(D){var U=g;return U+=(44-D&D-46)>>>8&-g+D-45+62,U+=(94-D&D-96)>>>8&-g+D-95+63,U+=(47-D&D-58)>>>8&-g+D-48+52,U+=(64-D&D-91)>>>8&-g+D-65+0,U+=(96-D&D-123)>>>8&-g+D-97+26,U},R})(m);d.URLSafeCoder=E;var A=new E;function T(M){return A.encode(M)}d.encodeURLSafe=T;function L(M){return A.decode(M)}d.decodeURLSafe=L,d.encodedLength=function(M){return b.encodedLength(M)},d.maxDecodedLength=function(M){return b.maxDecodedLength(M)},d.decodedLength=function(M){return b.decodedLength(M)}},978(u,d){var f="utf8: invalid source encoding";function g(m){for(var b=[],v=0;v=m.length)throw new Error(f);var A=m[++v];if((A&192)!==128)throw new Error(f);S=(S&31)<<6|A&63,E=128}else if(S<240){if(v>=m.length-1)throw new Error(f);var A=m[++v],T=m[++v];if((A&192)!==128||(T&192)!==128)throw new Error(f);S=(S&15)<<12|(A&63)<<6|T&63,E=2048}else if(S<248){if(v>=m.length-2)throw new Error(f);var A=m[++v],T=m[++v],L=m[++v];if((A&192)!==128||(T&192)!==128||(L&192)!==128)throw new Error(f);S=(S&15)<<18|(A&63)<<12|(T&63)<<6|L&63,E=65536}else throw new Error(f);if(S=55296&&S<=57343)throw new Error(f);if(S>=65536){if(S>1114111)throw new Error(f);S-=65536,b.push(String.fromCharCode(55296|S>>10)),S=56320|S&1023}}b.push(String.fromCharCode(S))}return b.join("")}d.D4=g},721(u,d,f){u.exports=f(207).default},207(u,d,f){f.d(d,{default:()=>ps});class g{constructor(y,C){this.lastId=0,this.prefix=y,this.name=C}create(y){this.lastId++;var C=this.lastId,O=this.prefix+C,I=this.name+"["+C+"]",ne=!1,pe=function(){ne||(y.apply(null,arguments),ne=!0)};return this[C]=pe,{number:C,id:O,name:I,callback:pe}}remove(y){delete this[y.number]}}var m=new g("_pusher_script_","Pusher.ScriptReceivers"),b={VERSION:"8.5.0",PROTOCOL:7,wsPort:80,wssPort:443,wsPath:"",httpHost:"sockjs.pusher.com",httpPort:80,httpsPort:443,httpPath:"/pusher",stats_host:"stats.pusher.com",authEndpoint:"/pusher/auth",authTransport:"ajax",activityTimeout:12e4,pongTimeout:3e4,unavailableTimeout:1e4,userAuthentication:{endpoint:"/pusher/user-auth",transport:"ajax"},channelAuthorization:{endpoint:"/pusher/auth",transport:"ajax"},cdn_http:"http://js.pusher.com",cdn_https:"https://js.pusher.com",dependency_suffix:""};const v=b;class S{constructor(y){this.options=y,this.receivers=y.receivers||m,this.loading={}}load(y,C,O){var I=this;if(I.loading[y]&&I.loading[y].length>0)I.loading[y].push(O);else{I.loading[y]=[O];var ne=Be.createScriptRequest(I.getPath(y,C)),pe=I.receivers.create(function(Me){if(I.receivers.remove(pe),I.loading[y]){var Ve=I.loading[y];delete I.loading[y];for(var ot=function(Nt){Nt||ne.cleanup()},pt=0;pt>>6)+Q(128|y&63):Q(224|y>>>12&15)+Q(128|y>>>6&63)+Q(128|y&63)},te=function(_){return _.replace(/[^\x00-\x7F]/g,ye)},he=function(_){var y=[0,2,1][_.length%3],C=_.charCodeAt(0)<<16|(_.length>1?_.charCodeAt(1):0)<<8|(_.length>2?_.charCodeAt(2):0),O=[fe.charAt(C>>>18),fe.charAt(C>>>12&63),y>=2?"=":fe.charAt(C>>>6&63),y>=1?"=":fe.charAt(C&63)];return O.join("")},x=window.btoa||function(_){return _.replace(/[\s\S]{1,3}/g,he)};class K{constructor(y,C,O,I){this.clear=C,this.timer=y(()=>{this.timer&&(this.timer=I(this.timer))},O)}isRunning(){return this.timer!==null}ensureAborted(){this.timer&&(this.clear(this.timer),this.timer=null)}}const re=K;function de(_){window.clearTimeout(_)}function se(_){window.clearInterval(_)}class me extends re{constructor(y,C){super(setTimeout,de,y,function(O){return C(),null})}}class Ne extends re{constructor(y,C){super(setInterval,se,y,function(O){return C(),O})}}var ve={now(){return Date.now?Date.now():new Date().valueOf()},defer(_){return new me(0,_)},method(_,...y){var C=Array.prototype.slice.call(arguments,1);return function(O){return O[_].apply(O,C.concat(arguments))}}};const He=ve;function Ae(_,...y){for(var C=0;C{window.console&&window.console.log&&window.console.log(y)}}debug(...y){this.log(this.globalLog,y)}warn(...y){this.log(this.globalLogWarn,y)}error(...y){this.log(this.globalLogError,y)}globalLogWarn(y){window.console&&window.console.warn?window.console.warn(y):this.globalLog(y)}globalLogError(y){window.console&&window.console.error?window.console.error(y):this.globalLogWarn(y)}log(y,...C){var O=Et.apply(this,arguments);ps.log?ps.log(O):ps.logToConsole&&y.bind(this)(O)}}const et=new en;var ta=function(_,y,C,O,I){(C.headers!==void 0||C.headersProvider!=null)&&et.warn(`To send headers with the ${O.toString()} request, you must use AJAX, rather than JSONP.`);var ne=_.nextAuthCallbackID.toString();_.nextAuthCallbackID++;var pe=_.getDocument(),Me=pe.createElement("script");_.auth_callbacks[ne]=function(pt){I(null,pt)};var Ve="Pusher.auth_callbacks['"+ne+"']";Me.src=C.endpoint+"?callback="+encodeURIComponent(Ve)+"&"+y;var ot=pe.getElementsByTagName("head")[0]||pe.documentElement;ot.insertBefore(Me,ot.firstChild)};const En=ta;class tr{constructor(y){this.src=y}send(y){var C=this,O="Error loading "+C.src;C.script=document.createElement("script"),C.script.id=y.id,C.script.src=C.src,C.script.type="text/javascript",C.script.charset="UTF-8",C.script.addEventListener?(C.script.onerror=function(){y.callback(O)},C.script.onload=function(){y.callback(null)}):C.script.onreadystatechange=function(){(C.script.readyState==="loaded"||C.script.readyState==="complete")&&y.callback(null)},C.script.async===void 0&&document.attachEvent&&/opera/i.test(navigator.userAgent)?(C.errorScript=document.createElement("script"),C.errorScript.id=y.id+"_error",C.errorScript.text=y.name+"('"+O+"');",C.script.async=C.errorScript.async=!1):C.script.async=!0;var I=document.getElementsByTagName("head")[0];I.insertBefore(C.script,I.firstChild),C.errorScript&&I.insertBefore(C.errorScript,C.script.nextSibling)}cleanup(){this.script&&(this.script.onload=this.script.onerror=null,this.script.onreadystatechange=null),this.script&&this.script.parentNode&&this.script.parentNode.removeChild(this.script),this.errorScript&&this.errorScript.parentNode&&this.errorScript.parentNode.removeChild(this.errorScript),this.script=null,this.errorScript=null}}class Ea{constructor(y,C){this.url=y,this.data=C}send(y){if(!this.request){var C=Dr(this.data),O=this.url+"/"+y.number+"?"+C;this.request=Be.createScriptRequest(O),this.request.send(y)}}cleanup(){this.request&&this.request.cleanup()}}var tn=function(_,y){return function(C,O){var I="http"+(y?"s":"")+"://",ne=I+(_.host||_.options.host)+_.options.path,pe=Be.createJSONPRequest(ne,C),Me=Be.ScriptReceivers.create(function(Ve,ot){m.remove(Me),pe.cleanup(),ot&&ot.host&&(_.host=ot.host),O&&O(Ve,ot)});pe.send(Me)}},_n={name:"jsonp",getAgent:tn};const q=_n;function ce(_,y,C){var O=_+(y.useTLS?"s":""),I=y.useTLS?y.hostTLS:y.hostNonTLS;return O+"://"+I+C}function le(_,y){var C="/app/"+_,O="?protocol="+v.PROTOCOL+"&client=js&version="+v.VERSION+(y?"&"+y:"");return C+O}var Z={getInitial:function(_,y){var C=(y.httpPath||"")+le(_,"flash=false");return ce("ws",y,C)}},be={getInitial:function(_,y){var C=(y.httpPath||"/pusher")+le(_);return ce("http",y,C)}},Se={getInitial:function(_,y){return ce("http",y,y.httpPath||"/pusher")},getPath:function(_,y){return le(_)}};class Re{constructor(){this._callbacks={}}get(y){return this._callbacks[xe(y)]}add(y,C,O){var I=xe(y);this._callbacks[I]=this._callbacks[I]||[],this._callbacks[I].push({fn:C,context:O})}remove(y,C,O){if(!y&&!C&&!O){this._callbacks={};return}var I=y?[xe(y)]:ft(this._callbacks);C||O?this.removeCallback(I,C,O):this.removeAllCallbacks(I)}removeCallback(y,C,O){gt(y,function(I){this._callbacks[I]=Dn(this._callbacks[I]||[],function(ne){return C&&C!==ne.fn||O&&O!==ne.context}),this._callbacks[I].length===0&&delete this._callbacks[I]},this)}removeAllCallbacks(y){gt(y,function(C){delete this._callbacks[C]},this)}}function xe(_){return"_"+_}class je{constructor(y){this.callbacks=new Re,this.global_callbacks=[],this.failThrough=y}bind(y,C,O){return this.callbacks.add(y,C,O),this}bind_global(y){return this.global_callbacks.push(y),this}unbind(y,C,O){return this.callbacks.remove(y,C,O),this}unbind_global(y){return y?(this.global_callbacks=Dn(this.global_callbacks||[],C=>C!==y),this):(this.global_callbacks=[],this)}unbind_all(){return this.unbind(),this.unbind_global(),this}emit(y,C,O){for(var I=0;I0)for(var I=0;I{this.onError(C),this.changeState("closed")}),!1}return this.bindListeners(),et.debug("Connecting",{transport:this.name,url:y}),this.changeState("connecting"),!0}close(){return this.socket?(this.socket.close(),!0):!1}send(y){return this.state==="open"?(He.defer(()=>{this.socket&&this.socket.send(y)}),!0):!1}ping(){this.state==="open"&&this.supportsPing()&&this.socket.ping()}onOpen(){this.hooks.beforeOpen&&this.hooks.beforeOpen(this.socket,this.hooks.urls.getPath(this.key,this.options)),this.changeState("open"),this.socket.onopen=void 0}onError(y){this.emit("error",{type:"WebSocketError",error:y}),this.timeline.error(this.buildTimelineMessage({error:y.toString()}))}onClose(y){y?this.changeState("closed",{code:y.code,reason:y.reason,wasClean:y.wasClean}):this.changeState("closed"),this.unbindListeners(),this.socket=void 0}onMessage(y){this.emit("message",y)}onActivity(){this.emit("activity")}bindListeners(){this.socket.onopen=()=>{this.onOpen()},this.socket.onerror=y=>{this.onError(y)},this.socket.onclose=y=>{this.onClose(y)},this.socket.onmessage=y=>{this.onMessage(y)},this.supportsPing()&&(this.socket.onactivity=()=>{this.onActivity()})}unbindListeners(){this.socket&&(this.socket.onopen=void 0,this.socket.onerror=void 0,this.socket.onclose=void 0,this.socket.onmessage=void 0,this.supportsPing()&&(this.socket.onactivity=void 0))}changeState(y,C){this.state=y,this.timeline.info(this.buildTimelineMessage({state:y,params:C})),this.emit(y,C)}buildTimelineMessage(y){return Ae({cid:this.id},y)}}class Le{constructor(y){this.hooks=y}isSupported(y){return this.hooks.isSupported(y)}createConnection(y,C,O,I){return new ze(this.hooks,y,C,O,I)}}var ke=new Le({urls:Z,handlesActivityChecks:!1,supportsPing:!1,isInitialized:function(){return!!Be.getWebSocketAPI()},isSupported:function(){return!!Be.getWebSocketAPI()},getSocket:function(_){return Be.createWebSocket(_)}}),We={urls:be,handlesActivityChecks:!1,supportsPing:!0,isInitialized:function(){return!0}},Fe=Ae({getSocket:function(_){return Be.HTTPFactory.createStreamingSocket(_)}},We),_e=Ae({getSocket:function(_){return Be.HTTPFactory.createPollingSocket(_)}},We),Te={isSupported:function(){return Be.isXHRSupported()}},Ue=new Le(Ae({},Fe,Te)),st=new Le(Ae({},_e,Te)),Dt={ws:ke,xhr_streaming:Ue,xhr_polling:st};const nn=Dt;var Kt=new Le({file:"sockjs",urls:Se,handlesActivityChecks:!0,supportsPing:!1,isSupported:function(){return!0},isInitialized:function(){return window.SockJS!==void 0},getSocket:function(_,y){return new window.SockJS(_,null,{js_path:A.getPath("sockjs",{useTLS:y.useTLS}),ignore_null_origin:y.ignoreNullOrigin})},beforeOpen:function(_,y){_.send(JSON.stringify({path:y}))}}),qn={isSupported:function(_){var y=Be.isXDRSupported(_.useTLS);return y}},Ln=new Le(Ae({},Fe,qn)),an=new Le(Ae({},_e,qn));nn.xdr_streaming=Ln,nn.xdr_polling=an,nn.sockjs=Kt;const vn=nn;class Or extends je{constructor(){super();var y=this;window.addEventListener!==void 0&&(window.addEventListener("online",function(){y.emit("online")},!1),window.addEventListener("offline",function(){y.emit("offline")},!1))}isOnline(){return window.navigator.onLine===void 0?!0:window.navigator.onLine}}var To=new Or;class gf{constructor(y,C,O){this.manager=y,this.transport=C,this.minPingDelay=O.minPingDelay,this.maxPingDelay=O.maxPingDelay,this.pingDelay=void 0}createConnection(y,C,O,I){I=Ae({},I,{activityTimeout:this.pingDelay});var ne=this.transport.createConnection(y,C,O,I),pe=null,Me=function(){ne.unbind("open",Me),ne.bind("closed",Ve),pe=He.now()},Ve=ot=>{if(ne.unbind("closed",Ve),ot.code===1002||ot.code===1003)this.manager.reportDeath();else if(!ot.wasClean&&pe){var pt=He.now()-pe;pt<2*this.maxPingDelay&&(this.manager.reportDeath(),this.pingDelay=Math.max(pt/2,this.minPingDelay))}};return ne.bind("open",Me),ne}isSupported(y){return this.manager.isAlive()&&this.transport.isSupported(y)}}const bc={decodeMessage:function(_){try{var y=JSON.parse(_.data),C=y.data;if(typeof C=="string")try{C=JSON.parse(y.data)}catch{}var O={event:y.event,channel:y.channel,data:C};return y.user_id&&(O.user_id=y.user_id),O}catch(I){throw{type:"MessageParseError",error:I,data:_.data}}},encodeMessage:function(_){return JSON.stringify(_)},processHandshake:function(_){var y=bc.decodeMessage(_);if(y.event==="pusher:connection_established"){if(!y.data.activity_timeout)throw"No activity timeout specified in handshake";return{action:"connected",id:y.data.socket_id,activityTimeout:y.data.activity_timeout*1e3}}else{if(y.event==="pusher:error")return{action:this.getCloseAction(y.data),error:this.getCloseError(y.data)};throw"Invalid handshake"}},getCloseAction:function(_){return _.code<4e3?_.code>=1002&&_.code<=1004?"backoff":null:_.code===4e3?"tls_only":_.code<4100?"refused":_.code<4200?"backoff":_.code<4300?"retry":"refused"},getCloseError:function(_){return _.code!==1e3&&_.code!==1001?{type:"PusherError",data:{code:_.code,message:_.reason||_.message}}:null}},Ba=bc;class yi extends je{constructor(y,C){super(),this.id=y,this.transport=C,this.activityTimeout=C.activityTimeout,this.bindListeners()}handlesActivityChecks(){return this.transport.handlesActivityChecks()}send(y){return this.transport.send(y)}send_event(y,C,O){var I={event:y,data:C};return O&&(I.channel=O),et.debug("Event sent",I),this.send(Ba.encodeMessage(I))}ping(){this.transport.supportsPing()?this.transport.ping():this.send_event("pusher:ping",{})}close(){this.transport.close()}bindListeners(){var y={message:O=>{var I;try{I=Ba.decodeMessage(O)}catch(ne){this.emit("error",{type:"MessageParseError",error:ne,data:O.data})}if(I!==void 0){switch(et.debug("Event recd",I),I.event){case"pusher:error":this.emit("error",{type:"PusherError",data:I.data});break;case"pusher:ping":this.emit("ping");break;case"pusher:pong":this.emit("pong");break}this.emit("message",I)}},activity:()=>{this.emit("activity")},error:O=>{this.emit("error",O)},closed:O=>{C(),O&&O.code&&this.handleCloseEvent(O),this.transport=null,this.emit("closed")}},C=()=>{_t(y,(O,I)=>{this.transport.unbind(I,O)})};_t(y,(O,I)=>{this.transport.bind(I,O)})}handleCloseEvent(y){var C=Ba.getCloseAction(y),O=Ba.getCloseError(y);O&&this.emit("error",O),C&&this.emit(C,{action:C,error:O})}}class Ro{constructor(y,C){this.transport=y,this.callback=C,this.bindListeners()}close(){this.unbindListeners(),this.transport.close()}bindListeners(){this.onMessage=y=>{this.unbindListeners();var C;try{C=Ba.processHandshake(y)}catch(O){this.finish("error",{error:O}),this.transport.close();return}C.action==="connected"?this.finish("connected",{connection:new yi(C.id,this.transport),activityTimeout:C.activityTimeout}):(this.finish(C.action,{error:C.error}),this.transport.close())},this.onClosed=y=>{this.unbindListeners();var C=Ba.getCloseAction(y)||"backoff",O=Ba.getCloseError(y);this.finish(C,{error:O})},this.transport.bind("message",this.onMessage),this.transport.bind("closed",this.onClosed)}unbindListeners(){this.transport.unbind("message",this.onMessage),this.transport.unbind("closed",this.onClosed)}finish(y,C){this.callback(Ae({transport:this.transport,action:y},C))}}class Lr{constructor(y,C){this.timeline=y,this.options=C||{}}send(y,C){this.timeline.isEmpty()||this.timeline.send(Be.TimelineTransport.getAgent(this,y),C)}}class Pa extends je{constructor(y,C){super(function(O,I){et.debug("No callbacks on "+y+" for "+O)}),this.name=y,this.pusher=C,this.subscribed=!1,this.subscriptionPending=!1,this.subscriptionCancelled=!1}authorize(y,C){return C(null,{auth:""})}trigger(y,C){if(y.indexOf("client-")!==0)throw new D("Event '"+y+"' does not start with 'client-'");if(!this.subscribed){var O=M.buildLogSuffix("triggeringClientEvents");et.warn(`Client event triggered before channel 'subscription_succeeded' event . ${O}`)}return this.pusher.send_event(y,C,this.name)}disconnect(){this.subscribed=!1,this.subscriptionPending=!1}handleEvent(y){var C=y.event,O=y.data;if(C==="pusher_internal:subscription_succeeded")this.handleSubscriptionSucceededEvent(y);else if(C==="pusher_internal:subscription_count")this.handleSubscriptionCountEvent(y);else if(C.indexOf("pusher_internal:")!==0){var I={};this.emit(C,O,I)}}handleSubscriptionSucceededEvent(y){this.subscriptionPending=!1,this.subscribed=!0,this.subscriptionCancelled?this.pusher.unsubscribe(this.name):this.emit("pusher:subscription_succeeded",y.data)}handleSubscriptionCountEvent(y){y.data.subscription_count&&(this.subscriptionCount=y.data.subscription_count),this.emit("pusher:subscription_count",y.data)}subscribe(){this.subscribed||(this.subscriptionPending=!0,this.subscriptionCancelled=!1,this.authorize(this.pusher.connection.socket_id,(y,C)=>{y?(this.subscriptionPending=!1,et.error(y.toString()),this.emit("pusher:subscription_error",Object.assign({},{type:"AuthError",error:y.message},y instanceof $e?{status:y.status}:{}))):this.pusher.send_event("pusher:subscribe",{auth:C.auth,channel_data:C.channel_data,channel:this.name})}))}unsubscribe(){this.subscribed=!1,this.pusher.send_event("pusher:unsubscribe",{channel:this.name})}cancelSubscription(){this.subscriptionCancelled=!0}reinstateSubscription(){this.subscriptionCancelled=!1}}class nr extends Pa{authorize(y,C){return this.pusher.config.channelAuthorizer({channelName:this.name,socketId:y},C)}}class Mr{constructor(){this.reset()}get(y){return Object.prototype.hasOwnProperty.call(this.members,y)?{id:y,info:this.members[y]}:null}each(y){_t(this.members,(C,O)=>{y(this.get(O))})}setMyID(y){this.myID=y}onSubscription(y){this.members=y.presence.hash,this.count=y.presence.count,this.me=this.get(this.myID)}addMember(y){return this.get(y.user_id)===null&&this.count++,this.members[y.user_id]=y.user_info,this.get(y.user_id)}removeMember(y){var C=this.get(y.user_id);return C&&(delete this.members[y.user_id],this.count--),C}reset(){this.members={},this.count=0,this.myID=null,this.me=null}}var Wt=function(_,y,C,O){function I(ne){return ne instanceof C?ne:new C(function(pe){pe(ne)})}return new(C||(C=Promise))(function(ne,pe){function Me(pt){try{ot(O.next(pt))}catch(Nt){pe(Nt)}}function Ve(pt){try{ot(O.throw(pt))}catch(Nt){pe(Nt)}}function ot(pt){pt.done?ne(pt.value):I(pt.value).then(Me,Ve)}ot((O=O.apply(_,y||[])).next())})};class vc extends nr{constructor(y,C){super(y,C),this.members=new Mr}authorize(y,C){super.authorize(y,(O,I)=>Wt(this,void 0,void 0,function*(){if(!O)if(I=I,I.channel_data!=null){var ne=JSON.parse(I.channel_data);this.members.setMyID(ne.user_id)}else if(yield this.pusher.user.signinDonePromise,this.pusher.user.user_data!=null)this.members.setMyID(this.pusher.user.user_data.id);else{let pe=M.buildLogSuffix("authorizationEndpoint");et.error(`Invalid auth response for channel '${this.name}', expected 'channel_data' field. ${pe}, or the user should be signed in.`),C("Invalid auth response");return}C(O,I)}))}handleEvent(y){var C=y.event;if(C.indexOf("pusher_internal:")===0)this.handleInternalEvent(y);else{var O=y.data,I={};y.user_id&&(I.user_id=y.user_id),this.emit(C,O,I)}}handleInternalEvent(y){var C=y.event,O=y.data;switch(C){case"pusher_internal:subscription_succeeded":this.handleSubscriptionSucceededEvent(y);break;case"pusher_internal:subscription_count":this.handleSubscriptionCountEvent(y);break;case"pusher_internal:member_added":var I=this.members.addMember(O);this.emit("pusher:member_added",I);break;case"pusher_internal:member_removed":var ne=this.members.removeMember(O);ne&&this.emit("pusher:member_removed",ne);break}}handleSubscriptionSucceededEvent(y){this.subscriptionPending=!1,this.subscribed=!0,this.subscriptionCancelled?this.pusher.unsubscribe(this.name):(this.members.onSubscription(y.data),this.emit("pusher:subscription_succeeded",this.members))}disconnect(){this.members.reset(),super.disconnect()}}var Sc=f(978),_a=f(594);class $r extends nr{constructor(y,C,O){super(y,C),this.key=null,this.nacl=O}authorize(y,C){super.authorize(y,(O,I)=>{if(O){C(O,I);return}let ne=I.shared_secret;if(!ne){C(new Error(`No shared_secret key in auth payload for encrypted channel: ${this.name}`),null);return}this.key=(0,_a.decode)(ne),delete I.shared_secret,C(null,I)})}trigger(y,C){throw new ge("Client events are not currently supported for encrypted channels")}handleEvent(y){var C=y.event,O=y.data;if(C.indexOf("pusher_internal:")===0||C.indexOf("pusher:")===0){super.handleEvent(y);return}this.handleEncryptedEvent(C,O)}handleEncryptedEvent(y,C){if(!this.key){et.debug("Received encrypted event before key has been retrieved from the authEndpoint");return}if(!C.ciphertext||!C.nonce){et.error("Unexpected format for encrypted event, expected object with `ciphertext` and `nonce` fields, got: "+C);return}let O=(0,_a.decode)(C.ciphertext);if(O.length{if(pe){et.error(`Failed to make a request to the authEndpoint: ${Me}. Unable to fetch new key, so dropping encrypted event`);return}if(ne=this.nacl.secretbox.open(O,I,this.key),ne===null){et.error("Failed to decrypt event with new key. Dropping encrypted event");return}this.emit(y,this.getDataToEmit(ne))});return}this.emit(y,this.getDataToEmit(ne))}getDataToEmit(y){let C=(0,Sc.D4)(y);try{return JSON.parse(C)}catch{return C}}}class pf extends je{constructor(y,C){super(),this.state="initialized",this.connection=null,this.key=y,this.options=C,this.timeline=this.options.timeline,this.usingTLS=this.options.useTLS,this.errorCallbacks=this.buildErrorCallbacks(),this.connectionCallbacks=this.buildConnectionCallbacks(this.errorCallbacks),this.handshakeCallbacks=this.buildHandshakeCallbacks(this.errorCallbacks);var O=Be.getNetwork();O.bind("online",()=>{this.timeline.info({netinfo:"online"}),(this.state==="connecting"||this.state==="unavailable")&&this.retryIn(0)}),O.bind("offline",()=>{this.timeline.info({netinfo:"offline"}),this.connection&&this.sendActivityCheck()}),this.updateStrategy()}switchCluster(y){this.key=y,this.updateStrategy(),this.retryIn(0)}connect(){if(!(this.connection||this.runner)){if(!this.strategy.isSupported()){this.updateState("failed");return}this.updateState("connecting"),this.startConnecting(),this.setUnavailableTimer()}}send(y){return this.connection?this.connection.send(y):!1}send_event(y,C,O){return this.connection?this.connection.send_event(y,C,O):!1}disconnect(){this.disconnectInternally(),this.updateState("disconnected")}isUsingTLS(){return this.usingTLS}startConnecting(){var y=(C,O)=>{C?this.runner=this.strategy.connect(0,y):O.action==="error"?(this.emit("error",{type:"HandshakeError",error:O.error}),this.timeline.error({handshakeError:O.error})):(this.abortConnecting(),this.handshakeCallbacks[O.action](O))};this.runner=this.strategy.connect(0,y)}abortConnecting(){this.runner&&(this.runner.abort(),this.runner=null)}disconnectInternally(){if(this.abortConnecting(),this.clearRetryTimer(),this.clearUnavailableTimer(),this.connection){var y=this.abandonConnection();y.close()}}updateStrategy(){this.strategy=this.options.getStrategy({key:this.key,timeline:this.timeline,useTLS:this.usingTLS})}retryIn(y){this.timeline.info({action:"retry",delay:y}),y>0&&this.emit("connecting_in",Math.round(y/1e3)),this.retryTimer=new me(y||0,()=>{this.disconnectInternally(),this.connect()})}clearRetryTimer(){this.retryTimer&&(this.retryTimer.ensureAborted(),this.retryTimer=null)}setUnavailableTimer(){this.unavailableTimer=new me(this.options.unavailableTimeout,()=>{this.updateState("unavailable")})}clearUnavailableTimer(){this.unavailableTimer&&this.unavailableTimer.ensureAborted()}sendActivityCheck(){this.stopActivityCheck(),this.connection.ping(),this.activityTimer=new me(this.options.pongTimeout,()=>{this.timeline.error({pong_timed_out:this.options.pongTimeout}),this.retryIn(0)})}resetActivityCheck(){this.stopActivityCheck(),this.connection&&!this.connection.handlesActivityChecks()&&(this.activityTimer=new me(this.activityTimeout,()=>{this.sendActivityCheck()}))}stopActivityCheck(){this.activityTimer&&this.activityTimer.ensureAborted()}buildConnectionCallbacks(y){return Ae({},y,{message:C=>{this.resetActivityCheck(),this.emit("message",C)},ping:()=>{this.send_event("pusher:pong",{})},activity:()=>{this.resetActivityCheck()},error:C=>{this.emit("error",C)},closed:()=>{this.abandonConnection(),this.shouldRetry()&&this.retryIn(1e3)}})}buildHandshakeCallbacks(y){return Ae({},y,{connected:C=>{this.activityTimeout=Math.min(this.options.activityTimeout,C.activityTimeout,C.connection.activityTimeout||1/0),this.clearUnavailableTimer(),this.setConnection(C.connection),this.socket_id=this.connection.id,this.updateState("connected",{socket_id:this.socket_id})}})}buildErrorCallbacks(){let y=C=>O=>{O.error&&this.emit("error",{type:"WebSocketError",error:O.error}),C(O)};return{tls_only:y(()=>{this.usingTLS=!0,this.updateStrategy(),this.retryIn(0)}),refused:y(()=>{this.disconnect()}),backoff:y(()=>{this.retryIn(1e3)}),retry:y(()=>{this.retryIn(0)})}}setConnection(y){this.connection=y;for(var C in this.connectionCallbacks)this.connection.bind(C,this.connectionCallbacks[C]);this.resetActivityCheck()}abandonConnection(){if(this.connection){this.stopActivityCheck();for(var y in this.connectionCallbacks)this.connection.unbind(y,this.connectionCallbacks[y]);var C=this.connection;return this.connection=null,C}}updateState(y,C){var O=this.state;if(this.state=y,O!==y){var I=y;I==="connected"&&(I+=" with new socket ID "+C.socket_id),et.debug("State changed",O+" -> "+I),this.timeline.info({state:y,params:C}),this.emit("state_change",{previous:O,current:y}),this.emit(y,C)}}shouldRetry(){return this.state==="connecting"||this.state==="connected"}}class wc{constructor(){this.channels={}}add(y,C){return this.channels[y]||(this.channels[y]=Cc(y,C)),this.channels[y]}all(){return un(this.channels)}find(y){return this.channels[y]}remove(y){var C=this.channels[y];return delete this.channels[y],C}disconnect(){_t(this.channels,function(y){y.disconnect()})}}function Cc(_,y){if(_.indexOf("private-encrypted-")===0){if(y.config.nacl)return Mn.createEncryptedChannel(_,y,y.config.nacl);let C="Tried to subscribe to a private-encrypted- channel but no nacl implementation available",O=M.buildLogSuffix("encryptedChannelSupport");throw new ge(`${C}. ${O}`)}else{if(_.indexOf("private-")===0)return Mn.createPrivateChannel(_,y);if(_.indexOf("presence-")===0)return Mn.createPresenceChannel(_,y);if(_.indexOf("#")===0)throw new U('Cannot create a channel with name "'+_+'".');return Mn.createChannel(_,y)}}var mf={createChannels(){return new wc},createConnectionManager(_,y){return new pf(_,y)},createChannel(_,y){return new Pa(_,y)},createPrivateChannel(_,y){return new nr(_,y)},createPresenceChannel(_,y){return new vc(_,y)},createEncryptedChannel(_,y,C){return new $r(_,y,C)},createTimelineSender(_,y){return new Lr(_,y)},createHandshake(_,y){return new Ro(_,y)},createAssistantToTheTransportManager(_,y,C){return new gf(_,y,C)}};const Mn=mf;class bi{constructor(y){this.options=y||{},this.livesLeft=this.options.lives||1/0}getAssistant(y){return Mn.createAssistantToTheTransportManager(this,y,{minPingDelay:this.options.minPingDelay,maxPingDelay:this.options.maxPingDelay})}isAlive(){return this.livesLeft>0}reportDeath(){this.livesLeft-=1}}class dn{constructor(y,C){this.strategies=y,this.loop=!!C.loop,this.failFast=!!C.failFast,this.timeout=C.timeout,this.timeoutLimit=C.timeoutLimit}isSupported(){return ea(this.strategies,He.method("isSupported"))}connect(y,C){var O=this.strategies,I=0,ne=this.timeout,pe=null,Me=(Ve,ot)=>{ot?C(null,ot):(I=I+1,this.loop&&(I=I%O.length),I0&&(ne=new me(O.timeout,function(){pe.abort(),I(!0)})),pe=y.connect(C,function(Me,Ve){Me&&ne&&ne.isRunning()&&!O.failFast||(ne&&ne.ensureAborted(),I(Me,Ve))}),{abort:function(){ne&&ne.ensureAborted(),pe.abort()},forceMinPriority:function(Me){pe.forceMinPriority(Me)}}}}class Sn{constructor(y){this.strategies=y}isSupported(){return ea(this.strategies,He.method("isSupported"))}connect(y,C){return Ec(this.strategies,y,function(O,I){return function(ne,pe){if(I[O].error=ne,ne){yf(I)&&C(!0);return}gt(I,function(Me){Me.forceMinPriority(pe.transport.priority)}),C(null,pe)}})}}function Ec(_,y,C){var O=ja(_,function(I,ne,pe,Me){return I.connect(y,C(ne,Me))});return{abort:function(){gt(O,ko)},forceMinPriority:function(I){gt(O,function(ne){ne.forceMinPriority(I)})}}}function yf(_){return Ua(_,function(y){return!!y.error})}function ko(_){!_.error&&!_.aborted&&(_.abort(),_.aborted=!0)}class _c{constructor(y,C,O){this.strategy=y,this.transports=C,this.ttl=O.ttl||18e5,this.usingTLS=O.useTLS,this.timeline=O.timeline}isSupported(){return this.strategy.isSupported()}connect(y,C){var O=this.usingTLS,I=bf(O),ne=I&&I.cacheSkipCount?I.cacheSkipCount:0,pe=[this.strategy];if(I&&I.timestamp+this.ttl>=He.now()){var Me=this.transports[I.transport];Me&&(["ws","wss"].includes(I.transport)||ne>3?(this.timeline.info({cached:!0,transport:I.transport,latency:I.latency}),pe.push(new dn([Me],{timeout:I.latency*2+1e3,failFast:!0}))):ne++)}var Ve=He.now(),ot=pe.pop().connect(y,function pt(Nt,Ra){Nt?(us(O),pe.length>0?(Ve=He.now(),ot=pe.pop().connect(y,pt)):C(Nt)):($n(O,Ra.transport.name,He.now()-Ve,ne),C(null,Ra))});return{abort:function(){ot.abort()},forceMinPriority:function(pt){y=pt,ot&&ot.forceMinPriority(pt)}}}}function Nr(_){return"pusherTransport"+(_?"TLS":"NonTLS")}function bf(_){var y=Be.getLocalStorage();if(y)try{var C=y[Nr(_)];if(C)return JSON.parse(C)}catch{us(_)}return null}function $n(_,y,C,O){var I=Be.getLocalStorage();if(I)try{I[Nr(_)]=bn({timestamp:He.now(),transport:y,latency:C,cacheSkipCount:O})}catch{}}function us(_){var y=Be.getLocalStorage();if(y)try{delete y[Nr(_)]}catch{}}class vi{constructor(y,{delay:C}){this.strategy=y,this.options={delay:C}}isSupported(){return this.strategy.isSupported()}connect(y,C){var O=this.strategy,I,ne=new me(this.options.delay,function(){I=O.connect(y,C)});return{abort:function(){ne.ensureAborted(),I&&I.abort()},forceMinPriority:function(pe){y=pe,I&&I.forceMinPriority(pe)}}}}class ar{constructor(y,C,O){this.test=y,this.trueBranch=C,this.falseBranch=O}isSupported(){var y=this.test()?this.trueBranch:this.falseBranch;return y.isSupported()}connect(y,C){var O=this.test()?this.trueBranch:this.falseBranch;return O.connect(y,C)}}class Ir{constructor(y){this.strategy=y}isSupported(){return this.strategy.isSupported()}connect(y,C){var O=this.strategy.connect(y,function(I,ne){ne&&O.abort(),C(I,ne)});return O}}function Hr(_){return function(){return _.isSupported()}}var Ac=function(_,y,C){var O={};function I(qo,jc,Uc,jf,Uf){var Bc=C(_,qo,jc,Uc,jf,Uf);return O[qo]=Bc,Bc}var ne=Object.assign({},y,{hostNonTLS:_.wsHost+":"+_.wsPort,hostTLS:_.wsHost+":"+_.wssPort,httpPath:_.wsPath}),pe=Object.assign({},ne,{useTLS:!0}),Me=Object.assign({},y,{hostNonTLS:_.httpHost+":"+_.httpPort,hostTLS:_.httpHost+":"+_.httpsPort,httpPath:_.httpPath}),Ve={loop:!0,timeout:15e3,timeoutLimit:6e4},ot=new bi({minPingDelay:1e4,maxPingDelay:_.activityTimeout}),pt=new bi({lives:2,minPingDelay:1e4,maxPingDelay:_.activityTimeout}),Nt=I("ws","ws",3,ne,ot),Ra=I("wss","ws",3,pe,ot),If=I("sockjs","sockjs",1,Me),Hc=I("xhr_streaming","xhr_streaming",1,Me,pt),Hf=I("xdr_streaming","xdr_streaming",1,Me,pt),Uo=I("xhr_polling","xhr_polling",1,Me),zc=I("xdr_polling","xdr_polling",1,Me),Ur=new dn([Nt],Ve),Ai=new dn([Ra],Ve),zf=new dn([If],Ve),xi=new dn([new ar(Hr(Hc),Hc,Hf)],Ve),Bo=new dn([new ar(Hr(Uo),Uo,zc)],Ve),Po=new dn([new ar(Hr(xi),new Sn([xi,new vi(Bo,{delay:4e3})]),Bo)],Ve),Ti=new ar(Hr(Po),Po,zf),Ri;return y.useTLS?Ri=new Sn([Ur,new vi(Ti,{delay:2e3})]):Ri=new Sn([Ur,new vi(Ai,{delay:2e3}),new vi(Ti,{delay:5e3})]),new _c(new Ir(new ar(Hr(Nt),Ri,Ti)),O,{ttl:18e5,timeline:y.timeline,useTLS:y.useTLS})};const zr=Ac;function vf(){var _=this;_.timeline.info(_.buildTimelineMessage({transport:_.name+(_.options.useTLS?"s":"")})),_.hooks.isInitialized()?_.changeState("initialized"):_.hooks.file?(_.changeState("initializing"),A.load(_.hooks.file,{useTLS:_.options.useTLS},function(y,C){_.hooks.isInitialized()?(_.changeState("initialized"),C(!0)):(y&&_.onError(y),_.onClose(),C(!1))})):_.onClose()}var xc={getRequest:function(_){var y=new window.XDomainRequest;return y.ontimeout=function(){_.emit("error",new j),_.close()},y.onerror=function(C){_.emit("error",C),_.close()},y.onprogress=function(){y.responseText&&y.responseText.length>0&&_.onChunk(200,y.responseText)},y.onload=function(){y.responseText&&y.responseText.length>0&&_.onChunk(200,y.responseText),_.emit("finished",200),_.close()},y},abortRequest:function(_){_.ontimeout=_.onerror=_.onprogress=_.onload=null,_.abort()}};const Tc=xc,Do=256*1024;class Sf extends je{constructor(y,C,O){super(),this.hooks=y,this.method=C,this.url=O}start(y){this.position=0,this.xhr=this.hooks.getRequest(this),this.unloader=()=>{this.close()},Be.addUnloadListener(this.unloader),this.xhr.open(this.method,this.url,!0),this.xhr.setRequestHeader&&this.xhr.setRequestHeader("Content-Type","application/json"),this.xhr.send(y)}close(){this.unloader&&(Be.removeUnloadListener(this.unloader),this.unloader=null),this.xhr&&(this.hooks.abortRequest(this.xhr),this.xhr=null)}onChunk(y,C){for(;;){var O=this.advanceBuffer(C);if(O)this.emit("chunk",{status:y,data:O});else break}this.isBufferTooLong(C)&&this.emit("buffer_too_long")}advanceBuffer(y){var C=y.slice(this.position),O=C.indexOf(` -`);return O!==-1?(this.position+=O+1,C.slice(0,O)):null}isBufferTooLong(y){return this.position===y.length&&y.length>Do}}var Oo;(function(_){_[_.CONNECTING=0]="CONNECTING",_[_.OPEN=1]="OPEN",_[_.CLOSED=3]="CLOSED"})(Oo||(Oo={}));const na=Oo;var Aa=1;class Lo{constructor(y,C){this.hooks=y,this.session=ds(1e3)+"/"+kc(8),this.location=Mo(C),this.readyState=na.CONNECTING,this.openStream()}send(y){return this.sendRaw(JSON.stringify([y]))}ping(){this.hooks.sendHeartbeat(this)}close(y,C){this.onClose(y,C,!0)}sendRaw(y){if(this.readyState===na.OPEN)try{return Be.createSocketRequest("POST",rr(jr(this.location,this.session))).start(y),!0}catch{return!1}else return!1}reconnect(){this.closeStream(),this.openStream()}onClose(y,C,O){this.closeStream(),this.readyState=na.CLOSED,this.onclose&&this.onclose({code:y,reason:C,wasClean:O})}onChunk(y){if(y.status===200){this.readyState===na.OPEN&&this.onActivity();var C,O=y.data.slice(0,1);switch(O){case"o":C=JSON.parse(y.data.slice(1)||"{}"),this.onOpen(C);break;case"a":C=JSON.parse(y.data.slice(1)||"[]");for(var I=0;I{this.onChunk(y)}),this.stream.bind("finished",y=>{this.hooks.onFinished(this,y)}),this.stream.bind("buffer_too_long",()=>{this.reconnect()});try{this.stream.start()}catch(y){He.defer(()=>{this.onError(y),this.onClose(1006,"Could not start streaming",!1)})}}closeStream(){this.stream&&(this.stream.unbind_all(),this.stream.close(),this.stream=null)}}function Mo(_){var y=/([^\?]*)\/*(\??.*)/.exec(_);return{base:y[1],queryString:y[2]}}function jr(_,y){return _.base+"/"+y+"/xhr_send"}function rr(_){var y=_.indexOf("?")===-1?"?":"&";return _+y+"t="+ +new Date+"&n="+Aa++}function Rc(_,y){var C=/(https?:\/\/)([^\/:]+)((\/|:)?.*)/.exec(_);return C[1]+y+C[3]}function ds(_){return Be.randomInt(_)}function kc(_){for(var y=[],C=0;C<_;C++)y.push(ds(32).toString(32));return y.join("")}const Si=Lo;var xa={getReceiveURL:function(_,y){return _.base+"/"+y+"/xhr_streaming"+_.queryString},onHeartbeat:function(_){_.sendRaw("[]")},sendHeartbeat:function(_){_.sendRaw("[]")},onFinished:function(_,y){_.onClose(1006,"Connection interrupted ("+y+")",!1)}};const $o=xa;var wi={getReceiveURL:function(_,y){return _.base+"/"+y+"/xhr"+_.queryString},onHeartbeat:function(){},sendHeartbeat:function(_){_.sendRaw("[]")},onFinished:function(_,y){y===200?_.reconnect():_.onClose(1006,"Connection interrupted ("+y+")",!1)}};const qa=wi;var No={getRequest:function(_){var y=Be.getXHRAPI(),C=new y;return C.onreadystatechange=C.onprogress=function(){switch(C.readyState){case 3:C.responseText&&C.responseText.length>0&&_.onChunk(C.status,C.responseText);break;case 4:C.responseText&&C.responseText.length>0&&_.onChunk(C.status,C.responseText),_.emit("finished",C.status),_.close();break}},C},abortRequest:function(_){_.onreadystatechange=null,_.abort()}};const fs=No;var Dc={createStreamingSocket(_){return this.createSocket($o,_)},createPollingSocket(_){return this.createSocket(qa,_)},createSocket(_,y){return new Si(_,y)},createXHR(_,y){return this.createRequest(fs,_,y)},createRequest(_,y,C){return new Sf(_,y,C)}};const Ci=Dc;Ci.createXDR=function(_,y){return this.createRequest(Tc,_,y)};var Oc={nextAuthCallbackID:1,auth_callbacks:{},ScriptReceivers:m,DependenciesReceivers:E,getDefaultStrategy:zr,Transports:vn,transportConnectionInitializer:vf,HTTPFactory:Ci,TimelineTransport:q,getXHRAPI(){return window.XMLHttpRequest},getWebSocketAPI(){return window.WebSocket||window.MozWebSocket},setup(_){window.Pusher=_;var y=()=>{this.onDocumentBody(_.ready)};window.JSON?y():A.load("json2",{},y)},getDocument(){return document},getProtocol(){return this.getDocument().location.protocol},getAuthorizers(){return{ajax:Xe,jsonp:En}},onDocumentBody(_){document.body?_():setTimeout(()=>{this.onDocumentBody(_)},0)},createJSONPRequest(_,y){return new Ea(_,y)},createScriptRequest(_){return new tr(_)},getLocalStorage(){try{return window.localStorage}catch{return}},createXHR(){return this.getXHRAPI()?this.createXMLHttpRequest():this.createMicrosoftXHR()},createXMLHttpRequest(){var _=this.getXHRAPI();return new _},createMicrosoftXHR(){return new ActiveXObject("Microsoft.XMLHTTP")},getNetwork(){return To},createWebSocket(_){var y=this.getWebSocketAPI();return new y(_)},createSocketRequest(_,y){if(this.isXHRSupported())return this.HTTPFactory.createXHR(_,y);if(this.isXDRSupported(y.indexOf("https:")===0))return this.HTTPFactory.createXDR(_,y);throw"Cross-origin HTTP requests are not supported"},isXHRSupported(){var _=this.getXHRAPI();return!!_&&new _().withCredentials!==void 0},isXDRSupported(_){var y=_?"https:":"http:",C=this.getProtocol();return!!window.XDomainRequest&&C===y},addUnloadListener(_){window.addEventListener!==void 0?window.addEventListener("unload",_,!1):window.attachEvent!==void 0&&window.attachEvent("onunload",_)},removeUnloadListener(_){window.addEventListener!==void 0?window.removeEventListener("unload",_,!1):window.detachEvent!==void 0&&window.detachEvent("onunload",_)},randomInt(_){return Math.floor(function(){return(window.crypto||window.msCrypto).getRandomValues(new Uint32Array(1))[0]/Math.pow(2,32)}()*_)}};const Be=Oc;var Ta;(function(_){_[_.ERROR=3]="ERROR",_[_.INFO=6]="INFO",_[_.DEBUG=7]="DEBUG"})(Ta||(Ta={}));const ir=Ta;class Ei{constructor(y,C,O){this.key=y,this.session=C,this.events=[],this.options=O||{},this.sent=0,this.uniqueID=0}log(y,C){y<=this.options.level&&(this.events.push(Ae({},C,{timestamp:He.now()})),this.options.limit&&this.events.length>this.options.limit&&this.events.shift())}error(y){this.log(ir.ERROR,y)}info(y){this.log(ir.INFO,y)}debug(y){this.log(ir.DEBUG,y)}isEmpty(){return this.events.length===0}send(y,C){var O=Ae({session:this.session,bundle:this.sent+1,key:this.key,lib:"js",version:this.options.version,cluster:this.options.cluster,features:this.options.features,timeline:this.events},this.options.params);return this.events=[],y(O,(I,ne)=>{I||this.sent++,C&&C(I,ne)}),!0}generateUniqueID(){return this.uniqueID++,this.uniqueID}}class wf{constructor(y,C,O,I){this.name=y,this.priority=C,this.transport=O,this.options=I||{}}isSupported(){return this.transport.isSupported({useTLS:this.options.useTLS})}connect(y,C){if(this.isSupported()){if(this.priority{O||(pt(),ne?ne.close():I.close())},forceMinPriority:Nt=>{O||this.priority{var C="socket_id="+encodeURIComponent(_.socketId);for(var O in y.params)C+="&"+encodeURIComponent(O)+"="+encodeURIComponent(y.params[O]);if(y.paramsProvider!=null){let I=y.paramsProvider();for(var O in I)C+="&"+encodeURIComponent(O)+"="+encodeURIComponent(I[O])}return C},Ef=_=>{if(typeof Be.getAuthorizers()[_.transport]>"u")throw`'${_.transport}' is not a recognized auth transport`;return(y,C)=>{const O=Cf(y,_);Be.getAuthorizers()[_.transport](Be,O,_,R.UserAuthentication,C)}},zo=(_,y)=>{var C="socket_id="+encodeURIComponent(_.socketId);C+="&channel_name="+encodeURIComponent(_.channelName);for(var O in y.params)C+="&"+encodeURIComponent(O)+"="+encodeURIComponent(y.params[O]);if(y.paramsProvider!=null){let I=y.paramsProvider();for(var O in I)C+="&"+encodeURIComponent(O)+"="+encodeURIComponent(I[O])}return C},_f=_=>{if(typeof Be.getAuthorizers()[_.transport]>"u")throw`'${_.transport}' is not a recognized auth transport`;return(y,C)=>{const O=zo(y,_);Be.getAuthorizers()[_.transport](Be,O,_,R.ChannelAuthorization,C)}},Af=(_,y,C)=>{const O={authTransport:y.transport,authEndpoint:y.endpoint,auth:{params:y.params,headers:y.headers}};return(I,ne)=>{const pe=_.channel(I.channelName);C(pe,O).authorize(I.socketId,ne)}};function Mc(_,y){let C={activityTimeout:_.activityTimeout||v.activityTimeout,cluster:_.cluster,httpPath:_.httpPath||v.httpPath,httpPort:_.httpPort||v.httpPort,httpsPort:_.httpsPort||v.httpsPort,pongTimeout:_.pongTimeout||v.pongTimeout,statsHost:_.statsHost||v.stats_host,unavailableTimeout:_.unavailableTimeout||v.unavailableTimeout,wsPath:_.wsPath||v.wsPath,wsPort:_.wsPort||v.wsPort,wssPort:_.wssPort||v.wssPort,enableStats:kf(_),httpHost:xf(_),useTLS:Rf(_),wsHost:$c(_),userAuthenticator:jo(_),channelAuthorizer:Of(_,y)};return"disabledTransports"in _&&(C.disabledTransports=_.disabledTransports),"enabledTransports"in _&&(C.enabledTransports=_.enabledTransports),"ignoreNullOrigin"in _&&(C.ignoreNullOrigin=_.ignoreNullOrigin),"timelineParams"in _&&(C.timelineParams=_.timelineParams),"nacl"in _&&(C.nacl=_.nacl),C}function xf(_){return _.httpHost?_.httpHost:_.cluster?`sockjs-${_.cluster}.pusher.com`:v.httpHost}function $c(_){return _.wsHost?_.wsHost:Tf(_.cluster)}function Tf(_){return`ws-${_}.pusher.com`}function Rf(_){return Be.getProtocol()==="https:"?!0:_.forceTLS!==!1}function kf(_){return"enableStats"in _?_.enableStats:"disableStats"in _?!_.disableStats:!1}const Nc=_=>"customHandler"in _&&_.customHandler!=null;function jo(_){const y=Object.assign(Object.assign({},v.userAuthentication),_.userAuthentication);return Nc(y)?y.customHandler:Ef(y)}function Df(_,y){let C;if("channelAuthorization"in _)C=Object.assign(Object.assign({},v.channelAuthorization),_.channelAuthorization);else if(C={transport:_.authTransport||v.authTransport,endpoint:_.authEndpoint||v.authEndpoint},"auth"in _&&("params"in _.auth&&(C.params=_.auth.params),"headers"in _.auth&&(C.headers=_.auth.headers)),"authorizer"in _)return{customHandler:Af(y,C,_.authorizer)};return C}function Of(_,y){const C=Df(_,y);return Nc(C)?C.customHandler:_f(C)}class Lf extends je{constructor(y){super(function(C,O){et.debug(`No callbacks on watchlist events for ${C}`)}),this.pusher=y,this.bindWatchlistInternalEvent()}handleEvent(y){y.data.events.forEach(C=>{this.emit(C.name,C)})}bindWatchlistInternalEvent(){this.pusher.connection.bind("message",y=>{var C=y.event;C==="pusher_internal:watchlist_events"&&this.handleEvent(y)})}}function Ic(){let _,y;return{promise:new Promise((O,I)=>{_=O,y=I}),resolve:_,reject:y}}const Mf=Ic;class $f extends je{constructor(y){super(function(C,O){et.debug("No callbacks on user for "+C)}),this.signin_requested=!1,this.user_data=null,this.serverToUserChannel=null,this.signinDonePromise=null,this._signinDoneResolve=null,this._onAuthorize=(C,O)=>{if(C){et.warn(`Error during signin: ${C}`),this._cleanup();return}this.pusher.send_event("pusher:signin",{auth:O.auth,user_data:O.user_data})},this.pusher=y,this.pusher.connection.bind("state_change",({previous:C,current:O})=>{C!=="connected"&&O==="connected"&&this._signin(),C==="connected"&&O!=="connected"&&(this._cleanup(),this._newSigninPromiseIfNeeded())}),this.watchlist=new Lf(y),this.pusher.connection.bind("message",C=>{var O=C.event;O==="pusher:signin_success"&&this._onSigninSuccess(C.data),this.serverToUserChannel&&this.serverToUserChannel.name===C.channel&&this.serverToUserChannel.handleEvent(C)})}signin(){this.signin_requested||(this.signin_requested=!0,this._signin())}_signin(){this.signin_requested&&(this._newSigninPromiseIfNeeded(),this.pusher.connection.state==="connected"&&this.pusher.config.userAuthenticator({socketId:this.pusher.connection.socket_id},this._onAuthorize))}_onSigninSuccess(y){try{this.user_data=JSON.parse(y.user_data)}catch{et.error(`Failed parsing user data after signin: ${y.user_data}`),this._cleanup();return}if(typeof this.user_data.id!="string"||this.user_data.id===""){et.error(`user_data doesn't contain an id. user_data: ${this.user_data}`),this._cleanup();return}this._signinDoneResolve(),this._subscribeChannels()}_subscribeChannels(){const y=C=>{C.subscriptionPending&&C.subscriptionCancelled?C.reinstateSubscription():!C.subscriptionPending&&this.pusher.connection.state==="connected"&&C.subscribe()};this.serverToUserChannel=new Pa(`#server-to-user-${this.user_data.id}`,this.pusher),this.serverToUserChannel.bind_global((C,O)=>{C.indexOf("pusher_internal:")===0||C.indexOf("pusher:")===0||this.emit(C,O)}),y(this.serverToUserChannel)}_cleanup(){this.user_data=null,this.serverToUserChannel&&(this.serverToUserChannel.unbind_all(),this.serverToUserChannel.disconnect(),this.serverToUserChannel=null),this.signin_requested&&this._signinDoneResolve()}_newSigninPromiseIfNeeded(){if(!this.signin_requested||this.signinDonePromise&&!this.signinDonePromise.done)return;const{promise:y,resolve:C}=Mf();y.done=!1;const O=()=>{y.done=!0};y.then(O).catch(O),this.signinDonePromise=y,this._signinDoneResolve=C}}class rn{static ready(){rn.isReady=!0;for(var y=0,C=rn.instances.length;yBe.getDefaultStrategy(this.config,I,_i);this.connection=Mn.createConnectionManager(this.key,{getStrategy:O,timeline:this.timeline,activityTimeout:this.config.activityTimeout,pongTimeout:this.config.pongTimeout,unavailableTimeout:this.config.unavailableTimeout,useTLS:!!this.config.useTLS}),this.connection.bind("connected",()=>{this.subscribeAll(),this.timelineSender&&this.timelineSender.send(this.connection.isUsingTLS())}),this.connection.bind("message",I=>{var ne=I.event,pe=ne.indexOf("pusher_internal:")===0;if(I.channel){var Me=this.channel(I.channel);Me&&Me.handleEvent(I)}pe||this.global_emitter.emit(I.event,I.data)}),this.connection.bind("connecting",()=>{this.channels.disconnect()}),this.connection.bind("disconnected",()=>{this.channels.disconnect()}),this.connection.bind("error",I=>{et.warn(I)}),rn.instances.push(this),this.timeline.info({instances:rn.instances.length}),this.user=new $f(this),rn.isReady&&this.connect()}switchCluster(y){const{appKey:C,cluster:O}=y;this.key=C,this.options=Object.assign(Object.assign({},this.options),{cluster:O}),this.config=Mc(this.options,this),this.connection.switchCluster(this.key)}channel(y){return this.channels.find(y)}allChannels(){return this.channels.all()}connect(){if(this.connection.connect(),this.timelineSender&&!this.timelineSenderTimer){var y=this.connection.isUsingTLS(),C=this.timelineSender;this.timelineSenderTimer=new Ne(6e4,function(){C.send(y)})}}disconnect(){this.connection.disconnect(),this.timelineSenderTimer&&(this.timelineSenderTimer.ensureAborted(),this.timelineSenderTimer=null)}bind(y,C,O){return this.global_emitter.bind(y,C,O),this}unbind(y,C,O){return this.global_emitter.unbind(y,C,O),this}bind_global(y){return this.global_emitter.bind_global(y),this}unbind_global(y){return this.global_emitter.unbind_global(y),this}unbind_all(y){return this.global_emitter.unbind_all(),this}subscribeAll(){var y;for(y in this.channels.channels)this.channels.channels.hasOwnProperty(y)&&this.subscribe(y)}subscribe(y){var C=this.channels.add(y,this);return C.subscriptionPending&&C.subscriptionCancelled?C.reinstateSubscription():!C.subscriptionPending&&this.connection.state==="connected"&&C.subscribe(),C}unsubscribe(y){var C=this.channels.find(y);C&&C.subscriptionPending?C.cancelSubscription():(C=this.channels.remove(y),C&&C.subscribed&&C.unsubscribe())}send_event(y,C,O){return this.connection.send_event(y,C,O)}shouldUseTLS(){return this.config.useTLS}signin(){this.user.signin()}}rn.instances=[],rn.isReady=!1,rn.logToConsole=!1,rn.Runtime=Be,rn.ScriptReceivers=Be.ScriptReceivers,rn.DependenciesReceivers=Be.DependenciesReceivers,rn.auth_callbacks=Be.auth_callbacks;const ps=rn;function Nf(_){if(_==null)throw"You must pass your app key when you instantiate Pusher."}Be.setup(rn)}},r={};function i(u){var d=r[u];if(d!==void 0)return d.exports;var f=r[u]={exports:{}};return a[u].call(f.exports,f,f.exports,i),f.exports}i.d=(u,d)=>{for(var f in d)i.o(d,f)&&!i.o(u,f)&&Object.defineProperty(u,f,{enumerable:!0,get:d[f]})},i.o=(u,d)=>Object.prototype.hasOwnProperty.call(u,d);var l=i(721);return l})())})(of)),of.exports}var L_=O_();const ty=Ya(L_),Ht=ct("WebSocketManager");class M_{constructor(){$(this,"echo",null);$(this,"subscriptions",new Map);$(this,"initialized",!1);$(this,"config",null)}configure(e){if(this.initialized){Ht.warn("[WebSocketManager] 이미 초기화되어 설정을 변경할 수 없습니다.");return}this.config=e,Ht.log("[WebSocketManager] 설정 완료:",{appKey:e.appKey?"***":"(없음)",host:e.host,port:e.port,scheme:e.scheme})}initialize(){if(this.initialized)return;if(!this.config||!this.config.appKey){Ht.warn("[WebSocketManager] WebSocket 설정이 없습니다. initTemplateApp에서 websocket 옵션을 전달해주세요.");return}const{appKey:e,host:a="localhost",port:r=80,scheme:i="https",authEndpoint:l="/api/broadcasting/auth"}=this.config,u=Number(r)||80,d=i==="https";Ht.log("[WebSocketManager] 연결 설정:",{host:a,port:u,scheme:i,useTLS:d,authEndpoint:l}),window.Pusher=ty;const f=localStorage.getItem("auth_token"),g={wsHost:a,wsPort:u,wssPort:u,forceTLS:d,disableStats:!0,enabledTransports:["ws","wss"],cluster:"mt1",authEndpoint:l,auth:{headers:{Authorization:f?`Bearer ${f}`:"",Accept:"application/json"}}};Ht.log("[WebSocketManager] Pusher 옵션:",g);const m=new ty(e,g);m.connection.bind("connecting",()=>{Ht.log("[WebSocketManager] 연결 시도 중...")}),m.connection.bind("connected",()=>{Ht.log("[WebSocketManager] 연결 성공! Socket ID:",m.connection.socket_id)}),m.connection.bind("failed",()=>{Ht.error("[WebSocketManager] 연결 실패 - WebSocket을 사용할 수 없습니다.")}),m.connection.bind("error",b=>{Ht.error("[WebSocketManager] 연결 오류:",b)}),m.connection.bind("state_change",b=>{Ht.log(`[WebSocketManager] 상태 변경: ${b.previous} → ${b.current}`)}),m.connection.bind("unavailable",()=>{Ht.error("[WebSocketManager] WebSocket 사용 불가 - 연결할 수 없습니다.")}),m.connection.bind("disconnected",()=>{Ht.warn("[WebSocketManager] 연결이 끊어졌습니다.")}),Ht.log("[WebSocketManager] 초기 연결 상태:",m.connection.state),this.echo=new D_({broadcaster:"reverb",client:m}),Ht.log("[WebSocketManager] 연결 시작 시도..."),m.connect(),window.Echo=this.echo,this.initialized=!0,Ht.log("[WebSocketManager] Echo 초기화 완료")}subscribe(e,a,r,i={}){if(this.initialize(),!this.echo)return Ht.warn("[WebSocketManager] Echo가 초기화되지 않았습니다."),"";const{channelType:l="private"}=i,u=`${e}:${a}`;if(this.subscriptions.has(u))return Ht.log(`[WebSocketManager] 이미 구독 중: ${u}`),u;let d;switch(l){case"public":d=this.echo.channel(e);break;case"presence":d=this.echo.join(e);break;default:d=this.echo.private(e)}return d.listen(`.${a}`,r),this.subscriptions.set(u,d),Ht.log(`[WebSocketManager] 구독 완료: ${u} (${l})`),u}unsubscribe(e){const a=this.subscriptions.get(e);if(!a)return;const r=e.lastIndexOf(":"),i=r>=0?e.substring(r+1):"";if(i)try{a.stopListening(`.${i}`)}catch(l){Ht.warn(`[WebSocketManager] stopListening 실패: ${e}`,l)}this.subscriptions.delete(e),Ht.log(`[WebSocketManager] 구독 해제: ${e}`)}leaveChannel(e){if(!this.echo)return;this.echo.leave(e);const a=[];this.subscriptions.forEach((r,i)=>{i.startsWith(`${e}:`)&&a.push(i)}),a.forEach(r=>this.subscriptions.delete(r)),Ht.log(`[WebSocketManager] 채널 구독 해제: ${e}`)}disconnect(){this.echo&&(this.echo.disconnect(),this.subscriptions.clear(),this.initialized=!1,Ht.log("[WebSocketManager] 연결 종료"))}getEcho(){return this.echo}isInitialized(){return this.initialized}isConfigured(){return this.config!==null&&!!this.config.appKey}getSubscriptionCount(){return this.subscriptions.size}}const fc=new M_,bt=ct("DataSourceManager"),$_=new wn;function hc(o,e){const a=o.match(/^\{\{(.+)\}\}$/);if(a){const r=a[1].trim();try{return $_.evaluateExpression(r,e)}catch(i){return bt.error("Failed to evaluate param expression:",r,i),o}}return Xi(o,e,{skipCache:!0})}function ny(o){const e={};for(const a of o.keys()){if(a in e)continue;const r=o.getAll(a);r.length>1?e[a]=r:r.length===1&&(a.endsWith("[]")?e[a]=r:e[a]=r[0])}return e}function N_(){try{return window.G7Core?.devTools}catch{return}}const yc=class yc{constructor(e={}){$(this,"options");$(this,"dataCache",new Map);$(this,"bindingEngine");$(this,"globalHeaders",[]);this.options=e,this.bindingEngine=new wn}setGlobalHeaders(e){this.globalHeaders=e||[]}matchesPattern(e,a){if(a==="*")return!0;const r=a.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${r}$`).test(e)}toFormData(e){const a=new FormData;for(const[r,i]of Object.entries(e))i instanceof File||i instanceof Blob?a.append(r,i):i!=null&&a.append(r,typeof i=="object"?JSON.stringify(i):String(i));return a}getMatchingGlobalHeaders(e,a){const r={};for(const i of this.globalHeaders)this.matchesPattern(e,i.pattern)&&Object.entries(i.headers).forEach(([l,u])=>{const d=hc(u,a);d!=null&&d!==""&&(r[l]=String(d))});return r}filterByCondition(e,a={}){const r=new Set,i=[];for(const l of e){if(r.has(l.id))continue;if(!l.if&&!l.conditions){r.add(l.id),i.push(l);continue}Yi({if:l.if,conditions:l.conditions},a,this.bindingEngine,`data_source:${l.id}`)&&(r.add(l.id),i.push(l))}return i}checkErrorCondition(e,a){if(!e.errorCondition?.if||e.errorCondition?.errorCode===void 0)return null;try{const r={response:a};if(Yi({if:e.errorCondition.if},r,this.bindingEngine,`errorCondition:${e.id}`))return bt.log(`errorCondition matched for ${e.id}, triggering error ${e.errorCondition.errorCode}`),e.errorCondition.errorCode}catch(r){bt.error(`Failed to evaluate errorCondition for ${e.id}:`,r)}return null}async fetchDataSources(e,a={},r=new URLSearchParams,i,l){const u={},d=!!this.options.sampleProvider,f=e.filter(g=>(d||g.auto_fetch!==!1)&&g.type!=="websocket");return await Promise.all(f.map(async g=>{try{const m=await this.fetchDataSource(g,a,r,i,l);u[g.id]=m,this.dataCache.set(g.id,{data:m,timestamp:Date.now()});const b=this.checkErrorCondition(g,m);if(b!==null){const v={status:b,message:`Error condition matched for ${g.id}`,data:m},S=pa(),E=S.resolve(b,{errorHandling:g.errorHandling,onError:g.onError});if(E.handler)try{await S.execute(E.handler,v)}catch(A){bt.error(`Error executing errorCondition handler for ${g.id}:`,A)}g.fallback!==void 0&&(u[g.id]=g.fallback,this.dataCache.set(g.id,{data:g.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${g.id} (errorCondition)`));return}if(g.onSuccess)try{const v={data:m,sourceId:g.id};await this.executeOnSuccessHandler(g.onSuccess,v)}catch(v){bt.error(`Error executing onSuccess handler for ${g.id}:`,v)}}catch(m){bt.error(`Failed to fetch data source: ${g.id}`,m);const b=m?.response?.status||m?.status||500,v=m?.response?.data,S=v?.message||m.message||"Unknown error",E={status:b,message:S,errors:v?.errors,data:v,statusText:m?.response?.statusText},A=pa(),T=A.resolve(b,{errorHandling:g.errorHandling,onError:g.onError});if(T.handler)try{await A.execute(T.handler,E)}catch(L){bt.error(`Error executing error handler for ${g.id}:`,L)}g.fallback!==void 0&&(u[g.id]=g.fallback,this.dataCache.set(g.id,{data:g.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${g.id}`)),this.options.onError&&this.options.onError(m,g)}})),u}async fetchDataSourcesWithResults(e,a={},r=new URLSearchParams,i,l,u){if(e.some(m=>m.type==="websocket")){const m=e.filter(b=>b.type==="websocket").map(b=>b.id).join(", ");bt.warn(`fetchDataSourcesWithResults received WebSocket sources (caller should filter them out before calling): ${m}. WebSocket sources are event listeners, not data providers — they should not be passed to fetch.`)}const f=u?.ignoreAutoFetch?e.filter(m=>m.type!=="websocket"):e.filter(m=>m.auto_fetch!==!1&&m.type!=="websocket");return await Promise.all(f.map(async m=>{try{const b=await this.fetchDataSource(m,a,r,i,l);this.dataCache.set(m.id,{data:b,timestamp:Date.now()});const v=this.checkErrorCondition(m,b);if(v!==null){const S={status:v,message:`Error condition matched for ${m.id}`,data:b},E=pa(),A=E.resolve(v,{errorHandling:m.errorHandling,onError:m.onError});let T=!1;if(A.handler)if(m.loading_strategy==="blocking")E.execute(A.handler,S).catch(L=>{bt.error(`Error executing errorCondition handler for ${m.id}:`,L)}),T=!0;else try{await E.execute(A.handler,S),T=!0}catch(L){bt.error(`Error executing errorCondition handler for ${m.id}:`,L)}return m.fallback!==void 0?(this.dataCache.set(m.id,{data:m.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${m.id} (errorCondition)`),{id:m.id,state:"success",data:m.fallback}):{id:m.id,state:"error",error:new Error(`Error condition matched: ${v}`),errorCode:v,errorHandled:T}}if(m.onSuccess)try{const S={data:b,sourceId:m.id};await this.executeOnSuccessHandler(m.onSuccess,S)}catch(S){bt.error(`Error executing onSuccess handler for ${m.id}:`,S)}return{id:m.id,state:"success",data:b}}catch(b){bt.error(`Failed to fetch data source: ${m.id}`,b);const v=b?.response?.status||b?.status||500,S=b?.response?.data,E=S?.message||b.message||"Unknown error",A={status:v,message:E,errors:S?.errors,data:S,statusText:b?.response?.statusText},T=pa(),L=T.resolve(v,{errorHandling:m.errorHandling,onError:m.onError});let M=!1;if(L.handler)if(m.loading_strategy==="blocking")T.execute(L.handler,A).catch(R=>{bt.error(`Error executing error handler for ${m.id}:`,R)}),M=!0;else try{await T.execute(L.handler,A),M=!0}catch(R){bt.error(`Error executing error handler for ${m.id}:`,R)}return m.fallback!==void 0?(this.dataCache.set(m.id,{data:m.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${m.id}`),{id:m.id,state:"success",data:m.fallback}):(this.options.onError&&this.options.onError(b,m),{id:m.id,state:"error",error:b,errorCode:v,errorHandled:M})}}))}fetchDataSourcesInBackground(e,a={},r=new URLSearchParams,i){e.filter(u=>u.auto_fetch!==!1&&u.loading_strategy==="background"&&u.type!=="websocket").forEach(u=>{this.fetchDataSource(u,a,r).then(async d=>{this.dataCache.set(u.id,{data:d,timestamp:Date.now()});const f=this.checkErrorCondition(u,d);if(f!==null){const g={status:f,message:`Error condition matched for ${u.id}`,data:d},m=pa(),b=m.resolve(f,{errorHandling:u.errorHandling,onError:u.onError});if(b.handler)try{await m.execute(b.handler,g)}catch(v){bt.error(`Error executing errorCondition handler for ${u.id}:`,v)}u.fallback!==void 0&&(this.dataCache.set(u.id,{data:u.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${u.id} (errorCondition)`),i&&i(u.id,u.fallback));return}if(u.onSuccess)try{const g={data:d,sourceId:u.id};await this.executeOnSuccessHandler(u.onSuccess,g)}catch(g){bt.error(`Error executing onSuccess handler for ${u.id}:`,g)}i&&i(u.id,d)}).catch(async d=>{bt.error(`Background fetch failed: ${u.id}`,d);const f=d?.response?.status||d?.status||500,g=d?.response?.data,m=g?.message||d.message||"Unknown error",b={status:f,message:m,errors:g?.errors,data:g,statusText:d?.response?.statusText},v=pa(),S=v.resolve(f,{errorHandling:u.errorHandling,onError:u.onError});if(S.handler)try{await v.execute(S.handler,b)}catch(E){bt.error(`Error executing error handler for ${u.id}:`,E)}if(u.fallback!==void 0){this.dataCache.set(u.id,{data:u.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${u.id}`),i&&i(u.id,u.fallback);return}this.options.onError&&this.options.onError(d,u)})})}async fetchDataSource(e,a,r,i,l){switch(e.type){case"api":return this.fetchApiDataSource(e,a,r,i,l);case"static":return e.data;case"route_params":return a;case"query_params":return ny(r);default:throw new Error(`Unknown data source type: ${e.type}`)}}async fetchApiDataSource(e,a,r,i,l){if(this.options.sampleProvider?.has(e.id))return await Promise.resolve(this.options.sampleProvider.resolve(e));if(!e.endpoint)throw new Error(`API data source ${e.id} has no endpoint`);const u={route:a,query:ny(r)};i&&(u._global=i),l&&(u._local=l);let d=Xi(e.endpoint,u,{skipCache:!0});const f=e.method||"GET",m=(e.contentType?typeof e.contentType=="string"&&e.contentType.includes("{{")?Xi(e.contentType,u,{skipCache:!0}):e.contentType:"application/json")==="multipart/form-data";let b=m?{...e.params||{}}:JSON.parse(JSON.stringify(e.params||{}));Object.entries(b).forEach(([E,A])=>{typeof A=="string"&&(b[E]=hc(A,u))}),Object.keys(b).forEach(E=>{b[E]===""&&delete b[E]});const v=N_();let S=null;if(v?.isEnabled()){v.trackDataSourceDefinition({id:e.id,type:e.type,endpoint:d,method:f,autoFetch:e.auto_fetch,initLocal:e.initLocal,initGlobal:e.initGlobal});let E=d;if(f==="GET"&&Object.keys(b).length>0){const A=new URLSearchParams;Object.entries(b).forEach(([L,M])=>{Array.isArray(M)?M.forEach(R=>A.append(L,String(R))):M!=null&&A.append(L,String(M))});const T=A.toString();E=T?`${d}?${T}`:d}S=v.trackRequest(E,f,{requestBody:f!=="GET"?b:void 0,dataSourceId:e.id}),v.trackDataSourceLoading(e.id)}try{let E;const A=e.auth_mode??(e.auth_required===!0?"required":"none"),T=ha.getInstance().isAuthenticated();if(A==="required"&&!T){bt.log(`[DataSourceManager] Skipping ${e.id}: auth_mode is 'required' but no token available`),v?.isEnabled()&&(v.trackDataSourceError(e.id,"Skipped: auth_mode required but not authenticated"),S&&v.failRequest(S,"Skipped: not authenticated"));const M=new Error("Auth required but not authenticated");throw M.response={status:401,statusText:"Unauthorized",data:null},M.status=401,M._authSkipped=!0,M}const L=A==="required"||A==="optional"&&T;if(L){const M=$a(),R=d.startsWith("/api/")?d.substring(4):d.startsWith("/api")?d.substring(4)||"/":d;this.options.onError&&bt.log(`[DataSourceManager] Normalized endpoint: ${d} -> ${R}`);const D=this.getMatchingGlobalHeaders(d,u),U={};e.headers&&Object.entries(e.headers).forEach(([ge,Ee])=>{const Ce=hc(Ee,u);Ce!=null&&Ce!==""&&(U[ge]=String(Ce))});const j={...D,...U},P=Object.keys(j).length>0,X=m?this.toFormData(b):b;switch(f){case"GET":E=await M.get(R,{params:b,...P&&{headers:j}});break;case"POST":P?E=await M.post(R,X,{headers:j}):E=await M.post(R,X);break;case"PUT":P?E=await M.put(R,X,{headers:j}):E=await M.put(R,X);break;case"PATCH":P?E=await M.patch(R,X,{headers:j}):E=await M.patch(R,X);break;case"DELETE":E=await M.delete(R,{params:b,...P&&{headers:j}});break;default:throw new Error(`Unsupported HTTP method: ${f}`)}}else{let M=d;if(f==="GET"){const X=new URLSearchParams(b).toString();M=X?`${d}?${X}`:d}const R={...m?{}:{"Content-Type":"application/json"},Accept:"application/json"};if(typeof window<"u"){const X=localStorage.getItem("g7_locale");X&&(R["Accept-Language"]=X)}const D=this.getMatchingGlobalHeaders(d,u);Object.assign(R,D),e.headers&&Object.entries(e.headers).forEach(([X,ge])=>{const Ee=hc(ge,u);Ee!=null&&Ee!==""&&(R[X]=String(Ee))});let U;f!=="GET"&&(m?(U=this.toFormData(b),delete R["Content-Type"]):U=JSON.stringify(b));const j=await fetch(M,{method:f,headers:R,body:U});let P;try{P=await j.json()}catch{P=null}if(S&&v?.isEnabled()&&(v.completeRequest(S,j.status,P),S=null),!j.ok){v?.isEnabled()&&v.trackDataSourceError(e.id,`HTTP ${j.status}: ${j.statusText}`);const X=new Error(`HTTP error! status: ${j.status}`);throw X.response={status:j.status,statusText:j.statusText,data:P},X.status=j.status,X}E=P,v?.isEnabled()&&v.trackDataSourceLoaded(e.id,E)}return L&&S&&v?.isEnabled()&&(v.completeRequest(S,200,E),v.trackDataSourceLoaded(e.id,E)),E}catch(E){if(S&&v?.isEnabled()){const A=E;A?.response?v.completeRequest(S,A.response.status,A.response.data):v.failRequest(S,E instanceof Error?E.message:String(E)),v.trackDataSourceError(e.id,E instanceof Error?E.message:String(E))}throw E}}getCachedData(e){const a=this.dataCache.get(e);if(!a)return;if(Date.now()-a.timestamp>yc.DATA_CACHE_TTL){this.dataCache.delete(e);return}return a.data}clearCache(){this.dataCache.clear()}subscribeWebSockets(e,a,r={}){const i=[],l=e.filter(u=>u.type==="websocket");return l.length===0||l.forEach(u=>{if(!u.channel||!u.event){bt.warn(`WebSocket source ${u.id} missing channel or event`);return}let d,f;try{d=Xi(u.channel,r,{skipCache:!0}),f=Xi(u.event,r,{skipCache:!0})}catch(b){bt.error(`Failed to resolve WebSocket channel/event for source ${u.id}:`,b);return}const g=b=>!!(!b||b.trim()===""||b.includes("{{")||b.endsWith(".")||b.endsWith(":")||b.startsWith(".")||b.startsWith(":")||b.includes("..")||b.includes("::"));if(g(d)||g(f)){bt.warn(`WebSocket source ${u.id} has invalid channel/event after expression resolution, skipping. Original channel="${u.channel}", resolved="${d}". Original event="${u.event}", resolved="${f}". Available context keys: [${Object.keys(r).join(", ")}]`);return}const m=fc.subscribe(d,f,b=>{const v=u.target_source||u.id;this.dataCache.set(v,{data:b,timestamp:Date.now()}),a(v,b)},{channelType:u.channel_type||"private"});m&&i.push(m)}),i}unsubscribeWebSockets(e){e.length!==0&&e.forEach(a=>{fc.unsubscribe(a)})}async executeOnSuccessHandler(e,a){const r=this.options.actionDispatcher??Zp();if(!r){bt.warn("ActionDispatcher not available, skipping onSuccess handler");return}const i=Array.isArray(e)?e:[e];for(const l of i)try{await r.dispatchAction({type:"click",...l},{data:{response:a}})}catch(u){throw bt.error("Failed to execute onSuccess handler:",u),u}}};$(yc,"DATA_CACHE_TTL",3e5);let va=yc;const I_=new va,hi=ct("ModalDataSourceWrapper");function H_(o,e){if(!o||!e)return o;const r=e.replace(/\?\./g,".").split(/\.(?![^\[]*\])/).flatMap(l=>{const u=l.match(/^([^\[]*)((?:\[\d+\])*)$/);if(u){const[,d,f]=u,g=[];d&&g.push(d);const m=f.match(/\[\d+\]/g);return m&&g.push(...m),g}return[l]}).filter(l=>l!=="");let i=o;for(const l of r){if(i==null)return;if(l.startsWith("[")&&l.endsWith("]")){const u=parseInt(l.slice(1,-1),10);i=i[u]}else i=i[l]}return i}const ay=({isOpen:o,modalId:e,dataSources:a,dataContext:r,globalStateUpdater:i,bindingEngine:l,debug:u=!1,children:d})=>{const[f,g]=N.useState(!1),[m,b]=N.useState(!1),v=N.useRef(!1),S=N.useRef(null);S.current||(S.current=new va);const E=N.useCallback(async()=>{if(!(!a||a.length===0)&&S.current){g(!0);try{const A=r.route||{},T=new URLSearchParams(window.location.search),L=a.map(R=>{let D={...R};if(R.endpoint&&l){const U=l.resolveBindings(R.endpoint,r,{skipCache:!0});D.endpoint=U}if(R.params&&l){const U={};Object.entries(R.params).forEach(([j,P])=>{typeof P=="string"?U[j]=l.resolveBindings(P,r,{skipCache:!0}):U[j]=P}),D.params=U}return D});u&&hi.log(`[ModalDataSourceWrapper] Modal "${e}" fetching data sources:`,L.map(R=>({id:R.id,endpoint:R.endpoint})));const M=await S.current.fetchDataSourcesWithResults(L,A,T);i&&M.forEach(R=>{if(R.state==="success"&&R.data!==void 0){const D=L.find(U=>U.id===R.id);if(D?.initGlobal){const U=R.data?.data??R.data,j=Array.isArray(D.initGlobal)?D.initGlobal:[D.initGlobal];for(const P of j)if(typeof P=="string")i({[P]:U}),u&&hi.log(`[ModalDataSourceWrapper] Modal "${e}" initGlobal: ${R.id}.data -> _global.${P}`);else if(typeof P=="object"&&P.key){const{key:X,path:ge}=P,Ee=ge?H_(U,ge):U;i({[X]:Ee}),u&&hi.log(`Modal "${e}" initGlobal: ${R.id}.data${ge?"."+ge:""} -> _global.${X}`)}}}else R.state==="error"&&hi.error(`Modal "${e}" data source error:`,R.id,R.error)}),u&&hi.log(`Modal "${e}" data sources fetched successfully`)}catch(A){hi.error(`Modal "${e}" data source fetch error:`,A)}finally{g(!1),b(!0)}}},[a,r,i,l,e,u]);return N.useEffect(()=>{if(!a||a.length===0)return;const A=window.__templateApp;return A?.registerModalDataSources&&A.registerModalDataSources(e,a),()=>{A?.unregisterModalDataSources&&A.unregisterModalDataSources(e)}},[e,a]),N.useEffect(()=>{!o&&v.current&&(b(!1),u&&hi.log(`[ModalDataSourceWrapper] Modal "${e}" closed, reset fetch state`)),o&&!v.current&&a&&a.length>0&&!m&&E(),v.current=o},[o,a,m,E,e,u]),ut.jsx(ut.Fragment,{children:d})};class gc extends Error{constructor(a,r,i={}){super(r);$(this,"code");$(this,"userMessageKey");$(this,"showStack");$(this,"icon");$(this,"recoverable");this.name="TemplateEngineError",this.code=a,this.userMessageKey=r,this.showStack=i.showStack??!0,this.icon=i.icon??"fa-circle-exclamation",this.recoverable=i.recoverable??!0,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}getUserMessage(a,r){if(!r||!a)return this.userMessageKey;try{return r.translate(this.userMessageKey,a)}catch{return this.userMessageKey}}}class z_ extends gc{constructor(){super("TEMPLATE_NOT_FOUND","$t:core.errors.template_not_found",{showStack:!1,icon:"fa-paint-brush",recoverable:!1}),this.name="TemplateNotFoundError"}}function ry(o){if(o instanceof gc)return o;if(o instanceof Error){const e=new gc("TEMPLATE_INIT_ERROR",o.message||"$t:core.errors.template_init_error",{showStack:!0,icon:"fa-circle-exclamation",recoverable:!0});return e.stack=o.stack,e}return new gc("TEMPLATE_INIT_ERROR","$t:core.errors.template_init_error",{showStack:!1,icon:"fa-circle-exclamation",recoverable:!0})}const j_=ct("ErrorDisplay");class lf{static render(e,a){const r=document.getElementById(e);if(!r){j_.error(`Container #${e} not found`);return}const i=a.debug&&a.showStack&&a.stackTrace,l=window.matchMedia("(prefers-color-scheme: dark)").matches,u={container:` + `,Bn.error("Error state rendered:",i,r)}getCurrentLayout(){return this.currentLayout}clear(){this.currentLayout=null,this.layoutCache.clear(),Bn.log("Layout data and cache cleared")}}const S_=ct("TranslationContext"),nf=N.createContext(null),uc=({children:o,translationEngine:e,translationContext:a})=>{const r=N.useMemo(()=>(l,u)=>{if(u){const d="|"+Object.entries(u).map(([f,g])=>`${f}=${g}`).join("|");return e.translate(l,a,d)}return e.translate(l,a)},[e,a]),i=N.useMemo(()=>({translationEngine:e,translationContext:a,t:r}),[e,a,r]);return ut.jsx(nf.Provider,{value:i,children:o})},Fm=()=>{const o=N.useContext(nf);return o||(S_.warn("TranslationProvider 외부에서 호출되었습니다. 키를 그대로 반환합니다."),{t:e=>e,translationEngine:null,translationContext:null})},Rr=ct("SlotContext"),w_={registerToSlot:()=>{Rr.warn("SlotContext not available: registerToSlot called outside SlotProvider")},unregisterFromSlot:()=>{Rr.warn("SlotContext not available: unregisterFromSlot called outside SlotProvider")},getSlotComponents:()=>[],subscribeToSlot:()=>()=>{},clearAllSlots:()=>{},isEnabled:!1},C_=N.createContext(w_),af=({children:o})=>{const e=N.useRef(new Map),a=N.useRef(new Map),r=N.useCallback(m=>{const b=a.current.get(m);b&&b.forEach(v=>{try{v()}catch(S){Rr.error(`Slot subscriber error (slotId: ${m}):`,S)}})},[]),i=N.useCallback((m,b,v)=>{if(!m||!b){Rr.warn("registerToSlot: slotId and componentId are required");return}e.current.has(m)||e.current.set(m,new Map);const S=e.current.get(m),E=S.get(b);E&&E.registrationKey===v.registrationKey||(S.set(b,v),Rr.log(`Component registered to slot: ${b} -> ${m} (order: ${v.order})`),r(m))},[r]),l=N.useCallback((m,b)=>{const v=e.current.get(m);v&&v.has(b)&&(v.delete(b),Rr.log(`Component unregistered from slot: ${b} <- ${m}`),v.size===0&&e.current.delete(m),r(m))},[r]),u=N.useCallback(m=>{const b=e.current.get(m);return b?Array.from(b.values()).sort((v,S)=>v.order-S.order):[]},[]),d=N.useCallback((m,b)=>{a.current.has(m)||a.current.set(m,new Set);const v=a.current.get(m);return v.add(b),()=>{v.delete(b),v.size===0&&a.current.delete(m)}},[]),f=N.useCallback(()=>{e.current.forEach((m,b)=>{r(b)}),e.current.clear(),a.current.clear(),Rr.log("All slots cleared")},[r]),g=N.useMemo(()=>({registerToSlot:i,unregisterFromSlot:l,getSlotComponents:u,subscribeToSlot:d,clearAllSlots:f,isEnabled:!0}),[i,l,u,d,f]);return N.useLayoutEffect(()=>{typeof window<"u"&&(window.__slotContextValue=g,Rr.log("SlotContext exposed to window.__slotContextValue"))},[g]),ut.jsx(C_.Provider,{value:g,children:o})};class rf{constructor(){this.notificationCreatedEvent=".Illuminate\\Notifications\\Events\\BroadcastNotificationCreated"}listenForWhisper(e,a){return this.listen(".client-"+e,a)}notification(e){return this.listen(this.notificationCreatedEvent,e)}stopListeningForNotification(e){return this.stopListening(this.notificationCreatedEvent,e)}stopListeningForWhisper(e,a){return this.stopListening(".client-"+e,a)}}class Km{constructor(e){this.namespace=e}format(e){return[".","\\"].includes(e.charAt(0))?e.substring(1):(this.namespace&&(e=this.namespace+"."+e),e.replace(/\./g,"\\"))}setNamespace(e){this.namespace=e}}function E_(o){try{return Reflect.construct(String,[],o),!0}catch{return!1}}class sf extends rf{constructor(e,a,r){super(),this.name=a,this.pusher=e,this.options=r,this.eventFormatter=new Km(this.options.namespace),this.subscribe()}subscribe(){this.subscription=this.pusher.subscribe(this.name)}unsubscribe(){this.pusher.unsubscribe(this.name)}listen(e,a){return this.on(this.eventFormatter.format(e),a),this}listenToAll(e){return this.subscription.bind_global((a,r)=>{if(a.startsWith("pusher:"))return;let i=String(this.options.namespace??"").replace(/\./g,"\\"),l=a.startsWith(i)?a.substring(i.length+1):"."+a;e(l,r)}),this}stopListening(e,a){return a?this.subscription.unbind(this.eventFormatter.format(e),a):this.subscription.unbind(this.eventFormatter.format(e)),this}stopListeningToAll(e){return e?this.subscription.unbind_global(e):this.subscription.unbind_global(),this}subscribed(e){return this.on("pusher:subscription_succeeded",()=>{e()}),this}error(e){return this.on("pusher:subscription_error",a=>{e(a)}),this}on(e,a){return this.subscription.bind(e,a),this}}class Wm extends sf{whisper(e,a){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,a),this}}class __ extends sf{whisper(e,a){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,a),this}}class A_ extends Wm{here(e){return this.on("pusher:subscription_succeeded",a=>{e(Object.keys(a.members).map(r=>a.members[r]))}),this}joining(e){return this.on("pusher:member_added",a=>{e(a.info)}),this}whisper(e,a){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,a),this}leaving(e){return this.on("pusher:member_removed",a=>{e(a.info)}),this}}class Ym extends rf{constructor(e,a,r){super(),this.events={},this.listeners={},this.name=a,this.socket=e,this.options=r,this.eventFormatter=new Km(this.options.namespace),this.subscribe()}subscribe(){this.socket.emit("subscribe",{channel:this.name,auth:this.options.auth||{}})}unsubscribe(){this.unbind(),this.socket.emit("unsubscribe",{channel:this.name,auth:this.options.auth||{}})}listen(e,a){return this.on(this.eventFormatter.format(e),a),this}stopListening(e,a){return this.unbindEvent(this.eventFormatter.format(e),a),this}subscribed(e){return this.on("connect",a=>{e(a)}),this}error(e){return this}on(e,a){return this.listeners[e]=this.listeners[e]||[],this.events[e]||(this.events[e]=(r,i)=>{this.name===r&&this.listeners[e]&&this.listeners[e].forEach(l=>l(i))},this.socket.on(e,this.events[e])),this.listeners[e].push(a),this}unbind(){Object.keys(this.events).forEach(e=>{this.unbindEvent(e)})}unbindEvent(e,a){this.listeners[e]=this.listeners[e]||[],a&&(this.listeners[e]=this.listeners[e].filter(r=>r!==a)),(!a||this.listeners[e].length===0)&&(this.events[e]&&(this.socket.removeListener(e,this.events[e]),delete this.events[e]),delete this.listeners[e])}}class Xm extends Ym{whisper(e,a){return this.socket.emit("client event",{channel:this.name,event:`client-${e}`,data:a}),this}}class x_ extends Xm{here(e){return this.on("presence:subscribed",a=>{e(a.map(r=>r.user_info))}),this}joining(e){return this.on("presence:joining",a=>e(a.user_info)),this}whisper(e,a){return this.socket.emit("client event",{channel:this.name,event:`client-${e}`,data:a}),this}leaving(e){return this.on("presence:leaving",a=>e(a.user_info)),this}}class dc extends rf{subscribe(){}unsubscribe(){}listen(e,a){return this}listenToAll(e){return this}stopListening(e,a){return this}subscribed(e){return this}error(e){return this}on(e,a){return this}}class Jm extends dc{whisper(e,a){return this}}class T_ extends dc{whisper(e,a){return this}}class R_ extends Jm{here(e){return this}joining(e){return this}whisper(e,a){return this}leaving(e){return this}}const Qm=class DS{constructor(e){this.setOptions(e),this.connect()}setOptions(e){this.options={...DS._defaultOptions,...e,broadcaster:e.broadcaster};let a=this.csrfToken();a&&(this.options.auth.headers["X-CSRF-TOKEN"]=a,this.options.userAuthentication.headers["X-CSRF-TOKEN"]=a),a=this.options.bearerToken,a&&(this.options.auth.headers.Authorization="Bearer "+a,this.options.userAuthentication.headers.Authorization="Bearer "+a)}csrfToken(){var e,a;return typeof window<"u"&&(e=window.Laravel)!=null&&e.csrfToken?window.Laravel.csrfToken:this.options.csrfToken?this.options.csrfToken:typeof document<"u"&&typeof document.querySelector=="function"?((a=document.querySelector('meta[name="csrf-token"]'))==null?void 0:a.getAttribute("content"))??null:null}};Qm._defaultOptions={auth:{headers:{}},authEndpoint:"/broadcasting/auth",userAuthentication:{endpoint:"/broadcasting/user-auth",headers:{}},csrfToken:null,bearerToken:null,host:null,key:null,namespace:"App.Events"};let of=Qm;class fc extends of{constructor(){super(...arguments),this.channels={}}connect(){if(typeof this.options.client<"u")this.pusher=this.options.client;else if(this.options.Pusher)this.pusher=new this.options.Pusher(this.options.key,this.options);else if(typeof window<"u"&&typeof window.Pusher<"u")this.pusher=new window.Pusher(this.options.key,this.options);else throw new Error("Pusher client not found. Should be globally available or passed via options.client")}signin(){this.pusher.signin()}listen(e,a,r){return this.channel(e).listen(a,r)}channel(e){return this.channels[e]||(this.channels[e]=new sf(this.pusher,e,this.options)),this.channels[e]}privateChannel(e){return this.channels["private-"+e]||(this.channels["private-"+e]=new Wm(this.pusher,"private-"+e,this.options)),this.channels["private-"+e]}encryptedPrivateChannel(e){return this.channels["private-encrypted-"+e]||(this.channels["private-encrypted-"+e]=new __(this.pusher,"private-encrypted-"+e,this.options)),this.channels["private-encrypted-"+e]}presenceChannel(e){return this.channels["presence-"+e]||(this.channels["presence-"+e]=new A_(this.pusher,"presence-"+e,this.options)),this.channels["presence-"+e]}leave(e){[e,"private-"+e,"private-encrypted-"+e,"presence-"+e].forEach(a=>{this.leaveChannel(a)})}leaveChannel(e){this.channels[e]&&(this.channels[e].unsubscribe(),delete this.channels[e])}socketId(){return this.pusher.connection.socket_id}connectionStatus(){const e=this.pusher.connection.state;switch(e){case"connected":case"connecting":return e;case"failed":case"unavailable":return"failed";default:return"disconnected"}}onConnectionChange(e){const a=()=>{e(this.connectionStatus())},r=["state_change","connected","disconnected"];return r.forEach(i=>{this.pusher.connection.bind(i,a)}),()=>{r.forEach(i=>{this.pusher.connection.unbind(i,a)})}}disconnect(){this.pusher.disconnect()}}class k_ extends of{constructor(){super(...arguments),this.channels={}}connect(){let e=this.getSocketIO();this.socket=e(this.options.host??void 0,this.options),this.socket.io.on("reconnect",()=>{Object.values(this.channels).forEach(a=>{a.subscribe()})})}getSocketIO(){if(typeof this.options.client<"u")return this.options.client;if(typeof window<"u"&&typeof window.io<"u")return window.io;throw new Error("Socket.io client not found. Should be globally available or passed via options.client")}listen(e,a,r){return this.channel(e).listen(a,r)}channel(e){return this.channels[e]||(this.channels[e]=new Ym(this.socket,e,this.options)),this.channels[e]}privateChannel(e){return this.channels["private-"+e]||(this.channels["private-"+e]=new Xm(this.socket,"private-"+e,this.options)),this.channels["private-"+e]}presenceChannel(e){return this.channels["presence-"+e]||(this.channels["presence-"+e]=new x_(this.socket,"presence-"+e,this.options)),this.channels["presence-"+e]}leave(e){[e,"private-"+e,"presence-"+e].forEach(a=>{this.leaveChannel(a)})}leaveChannel(e){this.channels[e]&&(this.channels[e].unsubscribe(),delete this.channels[e])}socketId(){return this.socket.id}connectionStatus(){return this.socket.connected?"connected":this.socket.io._reconnecting?"reconnecting":this.socket.id!==void 0?"disconnected":"connecting"}onConnectionChange(e){const a=()=>{e(this.connectionStatus())},r=["connect","disconnect","connect_error","reconnect_attempt","reconnect","reconnect_error","reconnect_failed"];return r.forEach(i=>{this.socket.on(i,a)}),()=>{r.forEach(i=>{this.socket.off(i,a)})}}disconnect(){this.socket.disconnect()}}class Zm extends of{constructor(){super(...arguments),this.channels={}}connect(){}listen(e,a,r){return new dc}channel(e){return new dc}privateChannel(e){return new Jm}encryptedPrivateChannel(e){return new T_}presenceChannel(e){return new R_}leave(e){}leaveChannel(e){}socketId(){return"fake-socket-id"}connectionStatus(){return"connected"}onConnectionChange(e){return()=>{}}disconnect(){}}class D_{constructor(e){this.options=e,this.connect(),this.options.withoutInterceptors||this.registerInterceptors()}channel(e){return this.connector.channel(e)}connect(){if(this.options.broadcaster==="reverb")this.connector=new fc({...this.options,cluster:""});else if(this.options.broadcaster==="pusher")this.connector=new fc(this.options);else if(this.options.broadcaster==="ably")this.connector=new fc({...this.options,cluster:"",broadcaster:"pusher"});else if(this.options.broadcaster==="socket.io")this.connector=new k_(this.options);else if(this.options.broadcaster==="null")this.connector=new Zm(this.options);else if(typeof this.options.broadcaster=="function"&&E_(this.options.broadcaster))this.connector=new this.options.broadcaster(this.options);else throw new Error(`Broadcaster ${typeof this.options.broadcaster} ${String(this.options.broadcaster)} is not supported.`)}disconnect(){this.connector.disconnect()}join(e){return this.connector.presenceChannel(e)}leave(e){this.connector.leave(e)}leaveChannel(e){this.connector.leaveChannel(e)}leaveAllChannels(){for(const e in this.connector.channels)this.leaveChannel(e)}listen(e,a,r){return this.connector.listen(e,a,r)}private(e){return this.connector.privateChannel(e)}encryptedPrivate(e){if(this.connectorSupportsEncryptedPrivateChannels(this.connector))return this.connector.encryptedPrivateChannel(e);throw new Error(`Broadcaster ${typeof this.options.broadcaster} ${String(this.options.broadcaster)} does not support encrypted private channels.`)}connectorSupportsEncryptedPrivateChannels(e){return e instanceof fc||e instanceof Zm}socketId(){return this.connector.socketId()}connectionStatus(){return this.connector.connectionStatus()}registerInterceptors(){typeof Vue<"u"&&Vue!=null&&Vue.http&&this.registerVueRequestInterceptor(),typeof axios=="function"&&this.registerAxiosRequestInterceptor(),typeof jQuery=="function"&&this.registerjQueryAjaxSetup(),typeof Turbo=="object"&&this.registerTurboRequestInterceptor()}registerVueRequestInterceptor(){Vue.http.interceptors.push((e,a)=>{this.socketId()&&e.headers.set("X-Socket-ID",this.socketId()),a()})}registerAxiosRequestInterceptor(){axios.interceptors.request.use(e=>(this.socketId()&&(e.headers["X-Socket-Id"]=this.socketId()),e))}registerjQueryAjaxSetup(){typeof jQuery.ajax<"u"&&jQuery.ajaxPrefilter((e,a,r)=>{this.socketId()&&r.setRequestHeader("X-Socket-Id",this.socketId())})}registerTurboRequestInterceptor(){document.addEventListener("turbo:before-fetch-request",e=>{e.detail.fetchOptions.headers["X-Socket-Id"]=this.socketId()})}}var lf={exports:{}};var ey;function O_(){return ey||(ey=1,(function(o,e){(function(r,i){o.exports=i()})(self,()=>(()=>{var a={594(u,d){var f=this&&this.__extends||(function(){var M=function(R,D){return M=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(U,j){U.__proto__=j}||function(U,j){for(var P in j)j.hasOwnProperty(P)&&(U[P]=j[P])},M(R,D)};return function(R,D){M(R,D);function U(){this.constructor=R}R.prototype=D===null?Object.create(D):(U.prototype=D.prototype,new U)}})();Object.defineProperty(d,"__esModule",{value:!0});var g=256,m=(function(){function M(R){R===void 0&&(R="="),this._paddingCharacter=R}return M.prototype.encodedLength=function(R){return this._paddingCharacter?(R+2)/3*4|0:(R*8+5)/6|0},M.prototype.encode=function(R){for(var D="",U=0;U>>18&63),D+=this._encodeByte(j>>>12&63),D+=this._encodeByte(j>>>6&63),D+=this._encodeByte(j>>>0&63)}var P=R.length-U;if(P>0){var j=R[U]<<16|(P===2?R[U+1]<<8:0);D+=this._encodeByte(j>>>18&63),D+=this._encodeByte(j>>>12&63),P===2?D+=this._encodeByte(j>>>6&63):D+=this._paddingCharacter||"",D+=this._paddingCharacter||""}return D},M.prototype.maxDecodedLength=function(R){return this._paddingCharacter?R/4*3|0:(R*6+7)/8|0},M.prototype.decodedLength=function(R){return this.maxDecodedLength(R.length-this._getPaddingLength(R))},M.prototype.decode=function(R){if(R.length===0)return new Uint8Array(0);for(var D=this._getPaddingLength(R),U=R.length-D,j=new Uint8Array(this.maxDecodedLength(U)),P=0,X=0,ge=0,Ee=0,Ce=0,$e=0,Pe=0;X>>4,j[P++]=Ce<<4|$e>>>2,j[P++]=$e<<6|Pe,ge|=Ee&g,ge|=Ce&g,ge|=$e&g,ge|=Pe&g;if(X>>4,ge|=Ee&g,ge|=Ce&g),X>>2,ge|=$e&g),X>>8&6,D+=51-R>>>8&-75,D+=61-R>>>8&-15,D+=62-R>>>8&3,String.fromCharCode(D)},M.prototype._decodeChar=function(R){var D=g;return D+=(42-R&R-44)>>>8&-g+R-43+62,D+=(46-R&R-48)>>>8&-g+R-47+63,D+=(47-R&R-58)>>>8&-g+R-48+52,D+=(64-R&R-91)>>>8&-g+R-65+0,D+=(96-R&R-123)>>>8&-g+R-97+26,D},M.prototype._getPaddingLength=function(R){var D=0;if(this._paddingCharacter){for(var U=R.length-1;U>=0&&R[U]===this._paddingCharacter;U--)D++;if(R.length<4||D>2)throw new Error("Base64Coder: incorrect padding")}return D},M})();d.Coder=m;var b=new m;function v(M){return b.encode(M)}d.encode=v;function S(M){return b.decode(M)}d.decode=S;var E=(function(M){f(R,M);function R(){return M!==null&&M.apply(this,arguments)||this}return R.prototype._encodeByte=function(D){var U=D;return U+=65,U+=25-D>>>8&6,U+=51-D>>>8&-75,U+=61-D>>>8&-13,U+=62-D>>>8&49,String.fromCharCode(U)},R.prototype._decodeChar=function(D){var U=g;return U+=(44-D&D-46)>>>8&-g+D-45+62,U+=(94-D&D-96)>>>8&-g+D-95+63,U+=(47-D&D-58)>>>8&-g+D-48+52,U+=(64-D&D-91)>>>8&-g+D-65+0,U+=(96-D&D-123)>>>8&-g+D-97+26,U},R})(m);d.URLSafeCoder=E;var A=new E;function T(M){return A.encode(M)}d.encodeURLSafe=T;function L(M){return A.decode(M)}d.decodeURLSafe=L,d.encodedLength=function(M){return b.encodedLength(M)},d.maxDecodedLength=function(M){return b.maxDecodedLength(M)},d.decodedLength=function(M){return b.decodedLength(M)}},978(u,d){var f="utf8: invalid source encoding";function g(m){for(var b=[],v=0;v=m.length)throw new Error(f);var A=m[++v];if((A&192)!==128)throw new Error(f);S=(S&31)<<6|A&63,E=128}else if(S<240){if(v>=m.length-1)throw new Error(f);var A=m[++v],T=m[++v];if((A&192)!==128||(T&192)!==128)throw new Error(f);S=(S&15)<<12|(A&63)<<6|T&63,E=2048}else if(S<248){if(v>=m.length-2)throw new Error(f);var A=m[++v],T=m[++v],L=m[++v];if((A&192)!==128||(T&192)!==128||(L&192)!==128)throw new Error(f);S=(S&15)<<18|(A&63)<<12|(T&63)<<6|L&63,E=65536}else throw new Error(f);if(S=55296&&S<=57343)throw new Error(f);if(S>=65536){if(S>1114111)throw new Error(f);S-=65536,b.push(String.fromCharCode(55296|S>>10)),S=56320|S&1023}}b.push(String.fromCharCode(S))}return b.join("")}d.D4=g},721(u,d,f){u.exports=f(207).default},207(u,d,f){f.d(d,{default:()=>ms});class g{constructor(y,C){this.lastId=0,this.prefix=y,this.name=C}create(y){this.lastId++;var C=this.lastId,O=this.prefix+C,I=this.name+"["+C+"]",ne=!1,pe=function(){ne||(y.apply(null,arguments),ne=!0)};return this[C]=pe,{number:C,id:O,name:I,callback:pe}}remove(y){delete this[y.number]}}var m=new g("_pusher_script_","Pusher.ScriptReceivers"),b={VERSION:"8.5.0",PROTOCOL:7,wsPort:80,wssPort:443,wsPath:"",httpHost:"sockjs.pusher.com",httpPort:80,httpsPort:443,httpPath:"/pusher",stats_host:"stats.pusher.com",authEndpoint:"/pusher/auth",authTransport:"ajax",activityTimeout:12e4,pongTimeout:3e4,unavailableTimeout:1e4,userAuthentication:{endpoint:"/pusher/user-auth",transport:"ajax"},channelAuthorization:{endpoint:"/pusher/auth",transport:"ajax"},cdn_http:"http://js.pusher.com",cdn_https:"https://js.pusher.com",dependency_suffix:""};const v=b;class S{constructor(y){this.options=y,this.receivers=y.receivers||m,this.loading={}}load(y,C,O){var I=this;if(I.loading[y]&&I.loading[y].length>0)I.loading[y].push(O);else{I.loading[y]=[O];var ne=Be.createScriptRequest(I.getPath(y,C)),pe=I.receivers.create(function(Me){if(I.receivers.remove(pe),I.loading[y]){var Ve=I.loading[y];delete I.loading[y];for(var ot=function(Nt){Nt||ne.cleanup()},pt=0;pt>>6)+Q(128|y&63):Q(224|y>>>12&15)+Q(128|y>>>6&63)+Q(128|y&63)},te=function(_){return _.replace(/[^\x00-\x7F]/g,ye)},he=function(_){var y=[0,2,1][_.length%3],C=_.charCodeAt(0)<<16|(_.length>1?_.charCodeAt(1):0)<<8|(_.length>2?_.charCodeAt(2):0),O=[fe.charAt(C>>>18),fe.charAt(C>>>12&63),y>=2?"=":fe.charAt(C>>>6&63),y>=1?"=":fe.charAt(C&63)];return O.join("")},x=window.btoa||function(_){return _.replace(/[\s\S]{1,3}/g,he)};class K{constructor(y,C,O,I){this.clear=C,this.timer=y(()=>{this.timer&&(this.timer=I(this.timer))},O)}isRunning(){return this.timer!==null}ensureAborted(){this.timer&&(this.clear(this.timer),this.timer=null)}}const re=K;function de(_){window.clearTimeout(_)}function ie(_){window.clearInterval(_)}class me extends re{constructor(y,C){super(setTimeout,de,y,function(O){return C(),null})}}class Ne extends re{constructor(y,C){super(setInterval,ie,y,function(O){return C(),O})}}var Se={now(){return Date.now?Date.now():new Date().valueOf()},defer(_){return new me(0,_)},method(_,...y){var C=Array.prototype.slice.call(arguments,1);return function(O){return O[_].apply(O,C.concat(arguments))}}};const He=Se;function Ae(_,...y){for(var C=0;C{window.console&&window.console.log&&window.console.log(y)}}debug(...y){this.log(this.globalLog,y)}warn(...y){this.log(this.globalLogWarn,y)}error(...y){this.log(this.globalLogError,y)}globalLogWarn(y){window.console&&window.console.warn?window.console.warn(y):this.globalLog(y)}globalLogError(y){window.console&&window.console.error?window.console.error(y):this.globalLogWarn(y)}log(y,...C){var O=Et.apply(this,arguments);ms.log?ms.log(O):ms.logToConsole&&y.bind(this)(O)}}const et=new tn;var ta=function(_,y,C,O,I){(C.headers!==void 0||C.headersProvider!=null)&&et.warn(`To send headers with the ${O.toString()} request, you must use AJAX, rather than JSONP.`);var ne=_.nextAuthCallbackID.toString();_.nextAuthCallbackID++;var pe=_.getDocument(),Me=pe.createElement("script");_.auth_callbacks[ne]=function(pt){I(null,pt)};var Ve="Pusher.auth_callbacks['"+ne+"']";Me.src=C.endpoint+"?callback="+encodeURIComponent(Ve)+"&"+y;var ot=pe.getElementsByTagName("head")[0]||pe.documentElement;ot.insertBefore(Me,ot.firstChild)};const En=ta;class tr{constructor(y){this.src=y}send(y){var C=this,O="Error loading "+C.src;C.script=document.createElement("script"),C.script.id=y.id,C.script.src=C.src,C.script.type="text/javascript",C.script.charset="UTF-8",C.script.addEventListener?(C.script.onerror=function(){y.callback(O)},C.script.onload=function(){y.callback(null)}):C.script.onreadystatechange=function(){(C.script.readyState==="loaded"||C.script.readyState==="complete")&&y.callback(null)},C.script.async===void 0&&document.attachEvent&&/opera/i.test(navigator.userAgent)?(C.errorScript=document.createElement("script"),C.errorScript.id=y.id+"_error",C.errorScript.text=y.name+"('"+O+"');",C.script.async=C.errorScript.async=!1):C.script.async=!0;var I=document.getElementsByTagName("head")[0];I.insertBefore(C.script,I.firstChild),C.errorScript&&I.insertBefore(C.errorScript,C.script.nextSibling)}cleanup(){this.script&&(this.script.onload=this.script.onerror=null,this.script.onreadystatechange=null),this.script&&this.script.parentNode&&this.script.parentNode.removeChild(this.script),this.errorScript&&this.errorScript.parentNode&&this.errorScript.parentNode.removeChild(this.errorScript),this.script=null,this.errorScript=null}}class Ea{constructor(y,C){this.url=y,this.data=C}send(y){if(!this.request){var C=Dr(this.data),O=this.url+"/"+y.number+"?"+C;this.request=Be.createScriptRequest(O),this.request.send(y)}}cleanup(){this.request&&this.request.cleanup()}}var nn=function(_,y){return function(C,O){var I="http"+(y?"s":"")+"://",ne=I+(_.host||_.options.host)+_.options.path,pe=Be.createJSONPRequest(ne,C),Me=Be.ScriptReceivers.create(function(Ve,ot){m.remove(Me),pe.cleanup(),ot&&ot.host&&(_.host=ot.host),O&&O(Ve,ot)});pe.send(Me)}},_n={name:"jsonp",getAgent:nn};const q=_n;function ce(_,y,C){var O=_+(y.useTLS?"s":""),I=y.useTLS?y.hostTLS:y.hostNonTLS;return O+"://"+I+C}function le(_,y){var C="/app/"+_,O="?protocol="+v.PROTOCOL+"&client=js&version="+v.VERSION+(y?"&"+y:"");return C+O}var Z={getInitial:function(_,y){var C=(y.httpPath||"")+le(_,"flash=false");return ce("ws",y,C)}},be={getInitial:function(_,y){var C=(y.httpPath||"/pusher")+le(_);return ce("http",y,C)}},ve={getInitial:function(_,y){return ce("http",y,y.httpPath||"/pusher")},getPath:function(_,y){return le(_)}};class Re{constructor(){this._callbacks={}}get(y){return this._callbacks[xe(y)]}add(y,C,O){var I=xe(y);this._callbacks[I]=this._callbacks[I]||[],this._callbacks[I].push({fn:C,context:O})}remove(y,C,O){if(!y&&!C&&!O){this._callbacks={};return}var I=y?[xe(y)]:ft(this._callbacks);C||O?this.removeCallback(I,C,O):this.removeAllCallbacks(I)}removeCallback(y,C,O){gt(y,function(I){this._callbacks[I]=Dn(this._callbacks[I]||[],function(ne){return C&&C!==ne.fn||O&&O!==ne.context}),this._callbacks[I].length===0&&delete this._callbacks[I]},this)}removeAllCallbacks(y){gt(y,function(C){delete this._callbacks[C]},this)}}function xe(_){return"_"+_}class je{constructor(y){this.callbacks=new Re,this.global_callbacks=[],this.failThrough=y}bind(y,C,O){return this.callbacks.add(y,C,O),this}bind_global(y){return this.global_callbacks.push(y),this}unbind(y,C,O){return this.callbacks.remove(y,C,O),this}unbind_global(y){return y?(this.global_callbacks=Dn(this.global_callbacks||[],C=>C!==y),this):(this.global_callbacks=[],this)}unbind_all(){return this.unbind(),this.unbind_global(),this}emit(y,C,O){for(var I=0;I0)for(var I=0;I{this.onError(C),this.changeState("closed")}),!1}return this.bindListeners(),et.debug("Connecting",{transport:this.name,url:y}),this.changeState("connecting"),!0}close(){return this.socket?(this.socket.close(),!0):!1}send(y){return this.state==="open"?(He.defer(()=>{this.socket&&this.socket.send(y)}),!0):!1}ping(){this.state==="open"&&this.supportsPing()&&this.socket.ping()}onOpen(){this.hooks.beforeOpen&&this.hooks.beforeOpen(this.socket,this.hooks.urls.getPath(this.key,this.options)),this.changeState("open"),this.socket.onopen=void 0}onError(y){this.emit("error",{type:"WebSocketError",error:y}),this.timeline.error(this.buildTimelineMessage({error:y.toString()}))}onClose(y){y?this.changeState("closed",{code:y.code,reason:y.reason,wasClean:y.wasClean}):this.changeState("closed"),this.unbindListeners(),this.socket=void 0}onMessage(y){this.emit("message",y)}onActivity(){this.emit("activity")}bindListeners(){this.socket.onopen=()=>{this.onOpen()},this.socket.onerror=y=>{this.onError(y)},this.socket.onclose=y=>{this.onClose(y)},this.socket.onmessage=y=>{this.onMessage(y)},this.supportsPing()&&(this.socket.onactivity=()=>{this.onActivity()})}unbindListeners(){this.socket&&(this.socket.onopen=void 0,this.socket.onerror=void 0,this.socket.onclose=void 0,this.socket.onmessage=void 0,this.supportsPing()&&(this.socket.onactivity=void 0))}changeState(y,C){this.state=y,this.timeline.info(this.buildTimelineMessage({state:y,params:C})),this.emit(y,C)}buildTimelineMessage(y){return Ae({cid:this.id},y)}}class Le{constructor(y){this.hooks=y}isSupported(y){return this.hooks.isSupported(y)}createConnection(y,C,O,I){return new ze(this.hooks,y,C,O,I)}}var ke=new Le({urls:Z,handlesActivityChecks:!1,supportsPing:!1,isInitialized:function(){return!!Be.getWebSocketAPI()},isSupported:function(){return!!Be.getWebSocketAPI()},getSocket:function(_){return Be.createWebSocket(_)}}),We={urls:be,handlesActivityChecks:!1,supportsPing:!0,isInitialized:function(){return!0}},Fe=Ae({getSocket:function(_){return Be.HTTPFactory.createStreamingSocket(_)}},We),_e=Ae({getSocket:function(_){return Be.HTTPFactory.createPollingSocket(_)}},We),Te={isSupported:function(){return Be.isXHRSupported()}},Ue=new Le(Ae({},Fe,Te)),st=new Le(Ae({},_e,Te)),At={ws:ke,xhr_streaming:Ue,xhr_polling:st};const Wt=At;var qt=new Le({file:"sockjs",urls:ve,handlesActivityChecks:!0,supportsPing:!1,isSupported:function(){return!0},isInitialized:function(){return window.SockJS!==void 0},getSocket:function(_,y){return new window.SockJS(_,null,{js_path:A.getPath("sockjs",{useTLS:y.useTLS}),ignore_null_origin:y.ignoreNullOrigin})},beforeOpen:function(_,y){_.send(JSON.stringify({path:y}))}}),qn={isSupported:function(_){var y=Be.isXDRSupported(_.useTLS);return y}},Ln=new Le(Ae({},Fe,qn)),an=new Le(Ae({},_e,qn));Wt.xdr_streaming=Ln,Wt.xdr_polling=an,Wt.sockjs=qt;const vn=Wt;class Or extends je{constructor(){super();var y=this;window.addEventListener!==void 0&&(window.addEventListener("online",function(){y.emit("online")},!1),window.addEventListener("offline",function(){y.emit("offline")},!1))}isOnline(){return window.navigator.onLine===void 0?!0:window.navigator.onLine}}var Ro=new Or;class pf{constructor(y,C,O){this.manager=y,this.transport=C,this.minPingDelay=O.minPingDelay,this.maxPingDelay=O.maxPingDelay,this.pingDelay=void 0}createConnection(y,C,O,I){I=Ae({},I,{activityTimeout:this.pingDelay});var ne=this.transport.createConnection(y,C,O,I),pe=null,Me=function(){ne.unbind("open",Me),ne.bind("closed",Ve),pe=He.now()},Ve=ot=>{if(ne.unbind("closed",Ve),ot.code===1002||ot.code===1003)this.manager.reportDeath();else if(!ot.wasClean&&pe){var pt=He.now()-pe;pt<2*this.maxPingDelay&&(this.manager.reportDeath(),this.pingDelay=Math.max(pt/2,this.minPingDelay))}};return ne.bind("open",Me),ne}isSupported(y){return this.manager.isAlive()&&this.transport.isSupported(y)}}const vc={decodeMessage:function(_){try{var y=JSON.parse(_.data),C=y.data;if(typeof C=="string")try{C=JSON.parse(y.data)}catch{}var O={event:y.event,channel:y.channel,data:C};return y.user_id&&(O.user_id=y.user_id),O}catch(I){throw{type:"MessageParseError",error:I,data:_.data}}},encodeMessage:function(_){return JSON.stringify(_)},processHandshake:function(_){var y=vc.decodeMessage(_);if(y.event==="pusher:connection_established"){if(!y.data.activity_timeout)throw"No activity timeout specified in handshake";return{action:"connected",id:y.data.socket_id,activityTimeout:y.data.activity_timeout*1e3}}else{if(y.event==="pusher:error")return{action:this.getCloseAction(y.data),error:this.getCloseError(y.data)};throw"Invalid handshake"}},getCloseAction:function(_){return _.code<4e3?_.code>=1002&&_.code<=1004?"backoff":null:_.code===4e3?"tls_only":_.code<4100?"refused":_.code<4200?"backoff":_.code<4300?"retry":"refused"},getCloseError:function(_){return _.code!==1e3&&_.code!==1001?{type:"PusherError",data:{code:_.code,message:_.reason||_.message}}:null}},Ba=vc;class bi extends je{constructor(y,C){super(),this.id=y,this.transport=C,this.activityTimeout=C.activityTimeout,this.bindListeners()}handlesActivityChecks(){return this.transport.handlesActivityChecks()}send(y){return this.transport.send(y)}send_event(y,C,O){var I={event:y,data:C};return O&&(I.channel=O),et.debug("Event sent",I),this.send(Ba.encodeMessage(I))}ping(){this.transport.supportsPing()?this.transport.ping():this.send_event("pusher:ping",{})}close(){this.transport.close()}bindListeners(){var y={message:O=>{var I;try{I=Ba.decodeMessage(O)}catch(ne){this.emit("error",{type:"MessageParseError",error:ne,data:O.data})}if(I!==void 0){switch(et.debug("Event recd",I),I.event){case"pusher:error":this.emit("error",{type:"PusherError",data:I.data});break;case"pusher:ping":this.emit("ping");break;case"pusher:pong":this.emit("pong");break}this.emit("message",I)}},activity:()=>{this.emit("activity")},error:O=>{this.emit("error",O)},closed:O=>{C(),O&&O.code&&this.handleCloseEvent(O),this.transport=null,this.emit("closed")}},C=()=>{_t(y,(O,I)=>{this.transport.unbind(I,O)})};_t(y,(O,I)=>{this.transport.bind(I,O)})}handleCloseEvent(y){var C=Ba.getCloseAction(y),O=Ba.getCloseError(y);O&&this.emit("error",O),C&&this.emit(C,{action:C,error:O})}}class ko{constructor(y,C){this.transport=y,this.callback=C,this.bindListeners()}close(){this.unbindListeners(),this.transport.close()}bindListeners(){this.onMessage=y=>{this.unbindListeners();var C;try{C=Ba.processHandshake(y)}catch(O){this.finish("error",{error:O}),this.transport.close();return}C.action==="connected"?this.finish("connected",{connection:new bi(C.id,this.transport),activityTimeout:C.activityTimeout}):(this.finish(C.action,{error:C.error}),this.transport.close())},this.onClosed=y=>{this.unbindListeners();var C=Ba.getCloseAction(y)||"backoff",O=Ba.getCloseError(y);this.finish(C,{error:O})},this.transport.bind("message",this.onMessage),this.transport.bind("closed",this.onClosed)}unbindListeners(){this.transport.unbind("message",this.onMessage),this.transport.unbind("closed",this.onClosed)}finish(y,C){this.callback(Ae({transport:this.transport,action:y},C))}}class Lr{constructor(y,C){this.timeline=y,this.options=C||{}}send(y,C){this.timeline.isEmpty()||this.timeline.send(Be.TimelineTransport.getAgent(this,y),C)}}class Pa extends je{constructor(y,C){super(function(O,I){et.debug("No callbacks on "+y+" for "+O)}),this.name=y,this.pusher=C,this.subscribed=!1,this.subscriptionPending=!1,this.subscriptionCancelled=!1}authorize(y,C){return C(null,{auth:""})}trigger(y,C){if(y.indexOf("client-")!==0)throw new D("Event '"+y+"' does not start with 'client-'");if(!this.subscribed){var O=M.buildLogSuffix("triggeringClientEvents");et.warn(`Client event triggered before channel 'subscription_succeeded' event . ${O}`)}return this.pusher.send_event(y,C,this.name)}disconnect(){this.subscribed=!1,this.subscriptionPending=!1}handleEvent(y){var C=y.event,O=y.data;if(C==="pusher_internal:subscription_succeeded")this.handleSubscriptionSucceededEvent(y);else if(C==="pusher_internal:subscription_count")this.handleSubscriptionCountEvent(y);else if(C.indexOf("pusher_internal:")!==0){var I={};this.emit(C,O,I)}}handleSubscriptionSucceededEvent(y){this.subscriptionPending=!1,this.subscribed=!0,this.subscriptionCancelled?this.pusher.unsubscribe(this.name):this.emit("pusher:subscription_succeeded",y.data)}handleSubscriptionCountEvent(y){y.data.subscription_count&&(this.subscriptionCount=y.data.subscription_count),this.emit("pusher:subscription_count",y.data)}subscribe(){this.subscribed||(this.subscriptionPending=!0,this.subscriptionCancelled=!1,this.authorize(this.pusher.connection.socket_id,(y,C)=>{y?(this.subscriptionPending=!1,et.error(y.toString()),this.emit("pusher:subscription_error",Object.assign({},{type:"AuthError",error:y.message},y instanceof $e?{status:y.status}:{}))):this.pusher.send_event("pusher:subscribe",{auth:C.auth,channel_data:C.channel_data,channel:this.name})}))}unsubscribe(){this.subscribed=!1,this.pusher.send_event("pusher:unsubscribe",{channel:this.name})}cancelSubscription(){this.subscriptionCancelled=!0}reinstateSubscription(){this.subscriptionCancelled=!1}}class nr extends Pa{authorize(y,C){return this.pusher.config.channelAuthorizer({channelName:this.name,socketId:y},C)}}class Mr{constructor(){this.reset()}get(y){return Object.prototype.hasOwnProperty.call(this.members,y)?{id:y,info:this.members[y]}:null}each(y){_t(this.members,(C,O)=>{y(this.get(O))})}setMyID(y){this.myID=y}onSubscription(y){this.members=y.presence.hash,this.count=y.presence.count,this.me=this.get(this.myID)}addMember(y){return this.get(y.user_id)===null&&this.count++,this.members[y.user_id]=y.user_info,this.get(y.user_id)}removeMember(y){var C=this.get(y.user_id);return C&&(delete this.members[y.user_id],this.count--),C}reset(){this.members={},this.count=0,this.myID=null,this.me=null}}var Yt=function(_,y,C,O){function I(ne){return ne instanceof C?ne:new C(function(pe){pe(ne)})}return new(C||(C=Promise))(function(ne,pe){function Me(pt){try{ot(O.next(pt))}catch(Nt){pe(Nt)}}function Ve(pt){try{ot(O.throw(pt))}catch(Nt){pe(Nt)}}function ot(pt){pt.done?ne(pt.value):I(pt.value).then(Me,Ve)}ot((O=O.apply(_,y||[])).next())})};class Sc extends nr{constructor(y,C){super(y,C),this.members=new Mr}authorize(y,C){super.authorize(y,(O,I)=>Yt(this,void 0,void 0,function*(){if(!O)if(I=I,I.channel_data!=null){var ne=JSON.parse(I.channel_data);this.members.setMyID(ne.user_id)}else if(yield this.pusher.user.signinDonePromise,this.pusher.user.user_data!=null)this.members.setMyID(this.pusher.user.user_data.id);else{let pe=M.buildLogSuffix("authorizationEndpoint");et.error(`Invalid auth response for channel '${this.name}', expected 'channel_data' field. ${pe}, or the user should be signed in.`),C("Invalid auth response");return}C(O,I)}))}handleEvent(y){var C=y.event;if(C.indexOf("pusher_internal:")===0)this.handleInternalEvent(y);else{var O=y.data,I={};y.user_id&&(I.user_id=y.user_id),this.emit(C,O,I)}}handleInternalEvent(y){var C=y.event,O=y.data;switch(C){case"pusher_internal:subscription_succeeded":this.handleSubscriptionSucceededEvent(y);break;case"pusher_internal:subscription_count":this.handleSubscriptionCountEvent(y);break;case"pusher_internal:member_added":var I=this.members.addMember(O);this.emit("pusher:member_added",I);break;case"pusher_internal:member_removed":var ne=this.members.removeMember(O);ne&&this.emit("pusher:member_removed",ne);break}}handleSubscriptionSucceededEvent(y){this.subscriptionPending=!1,this.subscribed=!0,this.subscriptionCancelled?this.pusher.unsubscribe(this.name):(this.members.onSubscription(y.data),this.emit("pusher:subscription_succeeded",this.members))}disconnect(){this.members.reset(),super.disconnect()}}var wc=f(978),_a=f(594);class $r extends nr{constructor(y,C,O){super(y,C),this.key=null,this.nacl=O}authorize(y,C){super.authorize(y,(O,I)=>{if(O){C(O,I);return}let ne=I.shared_secret;if(!ne){C(new Error(`No shared_secret key in auth payload for encrypted channel: ${this.name}`),null);return}this.key=(0,_a.decode)(ne),delete I.shared_secret,C(null,I)})}trigger(y,C){throw new ge("Client events are not currently supported for encrypted channels")}handleEvent(y){var C=y.event,O=y.data;if(C.indexOf("pusher_internal:")===0||C.indexOf("pusher:")===0){super.handleEvent(y);return}this.handleEncryptedEvent(C,O)}handleEncryptedEvent(y,C){if(!this.key){et.debug("Received encrypted event before key has been retrieved from the authEndpoint");return}if(!C.ciphertext||!C.nonce){et.error("Unexpected format for encrypted event, expected object with `ciphertext` and `nonce` fields, got: "+C);return}let O=(0,_a.decode)(C.ciphertext);if(O.length{if(pe){et.error(`Failed to make a request to the authEndpoint: ${Me}. Unable to fetch new key, so dropping encrypted event`);return}if(ne=this.nacl.secretbox.open(O,I,this.key),ne===null){et.error("Failed to decrypt event with new key. Dropping encrypted event");return}this.emit(y,this.getDataToEmit(ne))});return}this.emit(y,this.getDataToEmit(ne))}getDataToEmit(y){let C=(0,wc.D4)(y);try{return JSON.parse(C)}catch{return C}}}class mf extends je{constructor(y,C){super(),this.state="initialized",this.connection=null,this.key=y,this.options=C,this.timeline=this.options.timeline,this.usingTLS=this.options.useTLS,this.errorCallbacks=this.buildErrorCallbacks(),this.connectionCallbacks=this.buildConnectionCallbacks(this.errorCallbacks),this.handshakeCallbacks=this.buildHandshakeCallbacks(this.errorCallbacks);var O=Be.getNetwork();O.bind("online",()=>{this.timeline.info({netinfo:"online"}),(this.state==="connecting"||this.state==="unavailable")&&this.retryIn(0)}),O.bind("offline",()=>{this.timeline.info({netinfo:"offline"}),this.connection&&this.sendActivityCheck()}),this.updateStrategy()}switchCluster(y){this.key=y,this.updateStrategy(),this.retryIn(0)}connect(){if(!(this.connection||this.runner)){if(!this.strategy.isSupported()){this.updateState("failed");return}this.updateState("connecting"),this.startConnecting(),this.setUnavailableTimer()}}send(y){return this.connection?this.connection.send(y):!1}send_event(y,C,O){return this.connection?this.connection.send_event(y,C,O):!1}disconnect(){this.disconnectInternally(),this.updateState("disconnected")}isUsingTLS(){return this.usingTLS}startConnecting(){var y=(C,O)=>{C?this.runner=this.strategy.connect(0,y):O.action==="error"?(this.emit("error",{type:"HandshakeError",error:O.error}),this.timeline.error({handshakeError:O.error})):(this.abortConnecting(),this.handshakeCallbacks[O.action](O))};this.runner=this.strategy.connect(0,y)}abortConnecting(){this.runner&&(this.runner.abort(),this.runner=null)}disconnectInternally(){if(this.abortConnecting(),this.clearRetryTimer(),this.clearUnavailableTimer(),this.connection){var y=this.abandonConnection();y.close()}}updateStrategy(){this.strategy=this.options.getStrategy({key:this.key,timeline:this.timeline,useTLS:this.usingTLS})}retryIn(y){this.timeline.info({action:"retry",delay:y}),y>0&&this.emit("connecting_in",Math.round(y/1e3)),this.retryTimer=new me(y||0,()=>{this.disconnectInternally(),this.connect()})}clearRetryTimer(){this.retryTimer&&(this.retryTimer.ensureAborted(),this.retryTimer=null)}setUnavailableTimer(){this.unavailableTimer=new me(this.options.unavailableTimeout,()=>{this.updateState("unavailable")})}clearUnavailableTimer(){this.unavailableTimer&&this.unavailableTimer.ensureAborted()}sendActivityCheck(){this.stopActivityCheck(),this.connection.ping(),this.activityTimer=new me(this.options.pongTimeout,()=>{this.timeline.error({pong_timed_out:this.options.pongTimeout}),this.retryIn(0)})}resetActivityCheck(){this.stopActivityCheck(),this.connection&&!this.connection.handlesActivityChecks()&&(this.activityTimer=new me(this.activityTimeout,()=>{this.sendActivityCheck()}))}stopActivityCheck(){this.activityTimer&&this.activityTimer.ensureAborted()}buildConnectionCallbacks(y){return Ae({},y,{message:C=>{this.resetActivityCheck(),this.emit("message",C)},ping:()=>{this.send_event("pusher:pong",{})},activity:()=>{this.resetActivityCheck()},error:C=>{this.emit("error",C)},closed:()=>{this.abandonConnection(),this.shouldRetry()&&this.retryIn(1e3)}})}buildHandshakeCallbacks(y){return Ae({},y,{connected:C=>{this.activityTimeout=Math.min(this.options.activityTimeout,C.activityTimeout,C.connection.activityTimeout||1/0),this.clearUnavailableTimer(),this.setConnection(C.connection),this.socket_id=this.connection.id,this.updateState("connected",{socket_id:this.socket_id})}})}buildErrorCallbacks(){let y=C=>O=>{O.error&&this.emit("error",{type:"WebSocketError",error:O.error}),C(O)};return{tls_only:y(()=>{this.usingTLS=!0,this.updateStrategy(),this.retryIn(0)}),refused:y(()=>{this.disconnect()}),backoff:y(()=>{this.retryIn(1e3)}),retry:y(()=>{this.retryIn(0)})}}setConnection(y){this.connection=y;for(var C in this.connectionCallbacks)this.connection.bind(C,this.connectionCallbacks[C]);this.resetActivityCheck()}abandonConnection(){if(this.connection){this.stopActivityCheck();for(var y in this.connectionCallbacks)this.connection.unbind(y,this.connectionCallbacks[y]);var C=this.connection;return this.connection=null,C}}updateState(y,C){var O=this.state;if(this.state=y,O!==y){var I=y;I==="connected"&&(I+=" with new socket ID "+C.socket_id),et.debug("State changed",O+" -> "+I),this.timeline.info({state:y,params:C}),this.emit("state_change",{previous:O,current:y}),this.emit(y,C)}}shouldRetry(){return this.state==="connecting"||this.state==="connected"}}class Cc{constructor(){this.channels={}}add(y,C){return this.channels[y]||(this.channels[y]=Ec(y,C)),this.channels[y]}all(){return un(this.channels)}find(y){return this.channels[y]}remove(y){var C=this.channels[y];return delete this.channels[y],C}disconnect(){_t(this.channels,function(y){y.disconnect()})}}function Ec(_,y){if(_.indexOf("private-encrypted-")===0){if(y.config.nacl)return Mn.createEncryptedChannel(_,y,y.config.nacl);let C="Tried to subscribe to a private-encrypted- channel but no nacl implementation available",O=M.buildLogSuffix("encryptedChannelSupport");throw new ge(`${C}. ${O}`)}else{if(_.indexOf("private-")===0)return Mn.createPrivateChannel(_,y);if(_.indexOf("presence-")===0)return Mn.createPresenceChannel(_,y);if(_.indexOf("#")===0)throw new U('Cannot create a channel with name "'+_+'".');return Mn.createChannel(_,y)}}var yf={createChannels(){return new Cc},createConnectionManager(_,y){return new mf(_,y)},createChannel(_,y){return new Pa(_,y)},createPrivateChannel(_,y){return new nr(_,y)},createPresenceChannel(_,y){return new Sc(_,y)},createEncryptedChannel(_,y,C){return new $r(_,y,C)},createTimelineSender(_,y){return new Lr(_,y)},createHandshake(_,y){return new ko(_,y)},createAssistantToTheTransportManager(_,y,C){return new pf(_,y,C)}};const Mn=yf;class vi{constructor(y){this.options=y||{},this.livesLeft=this.options.lives||1/0}getAssistant(y){return Mn.createAssistantToTheTransportManager(this,y,{minPingDelay:this.options.minPingDelay,maxPingDelay:this.options.maxPingDelay})}isAlive(){return this.livesLeft>0}reportDeath(){this.livesLeft-=1}}class dn{constructor(y,C){this.strategies=y,this.loop=!!C.loop,this.failFast=!!C.failFast,this.timeout=C.timeout,this.timeoutLimit=C.timeoutLimit}isSupported(){return ea(this.strategies,He.method("isSupported"))}connect(y,C){var O=this.strategies,I=0,ne=this.timeout,pe=null,Me=(Ve,ot)=>{ot?C(null,ot):(I=I+1,this.loop&&(I=I%O.length),I0&&(ne=new me(O.timeout,function(){pe.abort(),I(!0)})),pe=y.connect(C,function(Me,Ve){Me&&ne&&ne.isRunning()&&!O.failFast||(ne&&ne.ensureAborted(),I(Me,Ve))}),{abort:function(){ne&&ne.ensureAborted(),pe.abort()},forceMinPriority:function(Me){pe.forceMinPriority(Me)}}}}class Sn{constructor(y){this.strategies=y}isSupported(){return ea(this.strategies,He.method("isSupported"))}connect(y,C){return _c(this.strategies,y,function(O,I){return function(ne,pe){if(I[O].error=ne,ne){bf(I)&&C(!0);return}gt(I,function(Me){Me.forceMinPriority(pe.transport.priority)}),C(null,pe)}})}}function _c(_,y,C){var O=ja(_,function(I,ne,pe,Me){return I.connect(y,C(ne,Me))});return{abort:function(){gt(O,Do)},forceMinPriority:function(I){gt(O,function(ne){ne.forceMinPriority(I)})}}}function bf(_){return Ua(_,function(y){return!!y.error})}function Do(_){!_.error&&!_.aborted&&(_.abort(),_.aborted=!0)}class Ac{constructor(y,C,O){this.strategy=y,this.transports=C,this.ttl=O.ttl||18e5,this.usingTLS=O.useTLS,this.timeline=O.timeline}isSupported(){return this.strategy.isSupported()}connect(y,C){var O=this.usingTLS,I=vf(O),ne=I&&I.cacheSkipCount?I.cacheSkipCount:0,pe=[this.strategy];if(I&&I.timestamp+this.ttl>=He.now()){var Me=this.transports[I.transport];Me&&(["ws","wss"].includes(I.transport)||ne>3?(this.timeline.info({cached:!0,transport:I.transport,latency:I.latency}),pe.push(new dn([Me],{timeout:I.latency*2+1e3,failFast:!0}))):ne++)}var Ve=He.now(),ot=pe.pop().connect(y,function pt(Nt,Ra){Nt?(ds(O),pe.length>0?(Ve=He.now(),ot=pe.pop().connect(y,pt)):C(Nt)):($n(O,Ra.transport.name,He.now()-Ve,ne),C(null,Ra))});return{abort:function(){ot.abort()},forceMinPriority:function(pt){y=pt,ot&&ot.forceMinPriority(pt)}}}}function Nr(_){return"pusherTransport"+(_?"TLS":"NonTLS")}function vf(_){var y=Be.getLocalStorage();if(y)try{var C=y[Nr(_)];if(C)return JSON.parse(C)}catch{ds(_)}return null}function $n(_,y,C,O){var I=Be.getLocalStorage();if(I)try{I[Nr(_)]=bn({timestamp:He.now(),transport:y,latency:C,cacheSkipCount:O})}catch{}}function ds(_){var y=Be.getLocalStorage();if(y)try{delete y[Nr(_)]}catch{}}class Si{constructor(y,{delay:C}){this.strategy=y,this.options={delay:C}}isSupported(){return this.strategy.isSupported()}connect(y,C){var O=this.strategy,I,ne=new me(this.options.delay,function(){I=O.connect(y,C)});return{abort:function(){ne.ensureAborted(),I&&I.abort()},forceMinPriority:function(pe){y=pe,I&&I.forceMinPriority(pe)}}}}class ar{constructor(y,C,O){this.test=y,this.trueBranch=C,this.falseBranch=O}isSupported(){var y=this.test()?this.trueBranch:this.falseBranch;return y.isSupported()}connect(y,C){var O=this.test()?this.trueBranch:this.falseBranch;return O.connect(y,C)}}class Ir{constructor(y){this.strategy=y}isSupported(){return this.strategy.isSupported()}connect(y,C){var O=this.strategy.connect(y,function(I,ne){ne&&O.abort(),C(I,ne)});return O}}function Hr(_){return function(){return _.isSupported()}}var xc=function(_,y,C){var O={};function I(Go,Uc,Bc,Uf,Bf){var Pc=C(_,Go,Uc,Bc,Uf,Bf);return O[Go]=Pc,Pc}var ne=Object.assign({},y,{hostNonTLS:_.wsHost+":"+_.wsPort,hostTLS:_.wsHost+":"+_.wssPort,httpPath:_.wsPath}),pe=Object.assign({},ne,{useTLS:!0}),Me=Object.assign({},y,{hostNonTLS:_.httpHost+":"+_.httpPort,hostTLS:_.httpHost+":"+_.httpsPort,httpPath:_.httpPath}),Ve={loop:!0,timeout:15e3,timeoutLimit:6e4},ot=new vi({minPingDelay:1e4,maxPingDelay:_.activityTimeout}),pt=new vi({lives:2,minPingDelay:1e4,maxPingDelay:_.activityTimeout}),Nt=I("ws","ws",3,ne,ot),Ra=I("wss","ws",3,pe,ot),Hf=I("sockjs","sockjs",1,Me),zc=I("xhr_streaming","xhr_streaming",1,Me,pt),zf=I("xdr_streaming","xdr_streaming",1,Me,pt),Bo=I("xhr_polling","xhr_polling",1,Me),jc=I("xdr_polling","xdr_polling",1,Me),Ur=new dn([Nt],Ve),xi=new dn([Ra],Ve),jf=new dn([Hf],Ve),Ti=new dn([new ar(Hr(zc),zc,zf)],Ve),Po=new dn([new ar(Hr(Bo),Bo,jc)],Ve),qo=new dn([new ar(Hr(Ti),new Sn([Ti,new Si(Po,{delay:4e3})]),Po)],Ve),Ri=new ar(Hr(qo),qo,jf),ki;return y.useTLS?ki=new Sn([Ur,new Si(Ri,{delay:2e3})]):ki=new Sn([Ur,new Si(xi,{delay:2e3}),new Si(Ri,{delay:5e3})]),new Ac(new Ir(new ar(Hr(Nt),ki,Ri)),O,{ttl:18e5,timeline:y.timeline,useTLS:y.useTLS})};const zr=xc;function Sf(){var _=this;_.timeline.info(_.buildTimelineMessage({transport:_.name+(_.options.useTLS?"s":"")})),_.hooks.isInitialized()?_.changeState("initialized"):_.hooks.file?(_.changeState("initializing"),A.load(_.hooks.file,{useTLS:_.options.useTLS},function(y,C){_.hooks.isInitialized()?(_.changeState("initialized"),C(!0)):(y&&_.onError(y),_.onClose(),C(!1))})):_.onClose()}var Tc={getRequest:function(_){var y=new window.XDomainRequest;return y.ontimeout=function(){_.emit("error",new j),_.close()},y.onerror=function(C){_.emit("error",C),_.close()},y.onprogress=function(){y.responseText&&y.responseText.length>0&&_.onChunk(200,y.responseText)},y.onload=function(){y.responseText&&y.responseText.length>0&&_.onChunk(200,y.responseText),_.emit("finished",200),_.close()},y},abortRequest:function(_){_.ontimeout=_.onerror=_.onprogress=_.onload=null,_.abort()}};const Rc=Tc,Oo=256*1024;class wf extends je{constructor(y,C,O){super(),this.hooks=y,this.method=C,this.url=O}start(y){this.position=0,this.xhr=this.hooks.getRequest(this),this.unloader=()=>{this.close()},Be.addUnloadListener(this.unloader),this.xhr.open(this.method,this.url,!0),this.xhr.setRequestHeader&&this.xhr.setRequestHeader("Content-Type","application/json"),this.xhr.send(y)}close(){this.unloader&&(Be.removeUnloadListener(this.unloader),this.unloader=null),this.xhr&&(this.hooks.abortRequest(this.xhr),this.xhr=null)}onChunk(y,C){for(;;){var O=this.advanceBuffer(C);if(O)this.emit("chunk",{status:y,data:O});else break}this.isBufferTooLong(C)&&this.emit("buffer_too_long")}advanceBuffer(y){var C=y.slice(this.position),O=C.indexOf(` +`);return O!==-1?(this.position+=O+1,C.slice(0,O)):null}isBufferTooLong(y){return this.position===y.length&&y.length>Oo}}var Lo;(function(_){_[_.CONNECTING=0]="CONNECTING",_[_.OPEN=1]="OPEN",_[_.CLOSED=3]="CLOSED"})(Lo||(Lo={}));const na=Lo;var Aa=1;class Mo{constructor(y,C){this.hooks=y,this.session=fs(1e3)+"/"+Dc(8),this.location=$o(C),this.readyState=na.CONNECTING,this.openStream()}send(y){return this.sendRaw(JSON.stringify([y]))}ping(){this.hooks.sendHeartbeat(this)}close(y,C){this.onClose(y,C,!0)}sendRaw(y){if(this.readyState===na.OPEN)try{return Be.createSocketRequest("POST",rr(jr(this.location,this.session))).start(y),!0}catch{return!1}else return!1}reconnect(){this.closeStream(),this.openStream()}onClose(y,C,O){this.closeStream(),this.readyState=na.CLOSED,this.onclose&&this.onclose({code:y,reason:C,wasClean:O})}onChunk(y){if(y.status===200){this.readyState===na.OPEN&&this.onActivity();var C,O=y.data.slice(0,1);switch(O){case"o":C=JSON.parse(y.data.slice(1)||"{}"),this.onOpen(C);break;case"a":C=JSON.parse(y.data.slice(1)||"[]");for(var I=0;I{this.onChunk(y)}),this.stream.bind("finished",y=>{this.hooks.onFinished(this,y)}),this.stream.bind("buffer_too_long",()=>{this.reconnect()});try{this.stream.start()}catch(y){He.defer(()=>{this.onError(y),this.onClose(1006,"Could not start streaming",!1)})}}closeStream(){this.stream&&(this.stream.unbind_all(),this.stream.close(),this.stream=null)}}function $o(_){var y=/([^\?]*)\/*(\??.*)/.exec(_);return{base:y[1],queryString:y[2]}}function jr(_,y){return _.base+"/"+y+"/xhr_send"}function rr(_){var y=_.indexOf("?")===-1?"?":"&";return _+y+"t="+ +new Date+"&n="+Aa++}function kc(_,y){var C=/(https?:\/\/)([^\/:]+)((\/|:)?.*)/.exec(_);return C[1]+y+C[3]}function fs(_){return Be.randomInt(_)}function Dc(_){for(var y=[],C=0;C<_;C++)y.push(fs(32).toString(32));return y.join("")}const wi=Mo;var xa={getReceiveURL:function(_,y){return _.base+"/"+y+"/xhr_streaming"+_.queryString},onHeartbeat:function(_){_.sendRaw("[]")},sendHeartbeat:function(_){_.sendRaw("[]")},onFinished:function(_,y){_.onClose(1006,"Connection interrupted ("+y+")",!1)}};const No=xa;var Ci={getReceiveURL:function(_,y){return _.base+"/"+y+"/xhr"+_.queryString},onHeartbeat:function(){},sendHeartbeat:function(_){_.sendRaw("[]")},onFinished:function(_,y){y===200?_.reconnect():_.onClose(1006,"Connection interrupted ("+y+")",!1)}};const qa=Ci;var Io={getRequest:function(_){var y=Be.getXHRAPI(),C=new y;return C.onreadystatechange=C.onprogress=function(){switch(C.readyState){case 3:C.responseText&&C.responseText.length>0&&_.onChunk(C.status,C.responseText);break;case 4:C.responseText&&C.responseText.length>0&&_.onChunk(C.status,C.responseText),_.emit("finished",C.status),_.close();break}},C},abortRequest:function(_){_.onreadystatechange=null,_.abort()}};const hs=Io;var Oc={createStreamingSocket(_){return this.createSocket(No,_)},createPollingSocket(_){return this.createSocket(qa,_)},createSocket(_,y){return new wi(_,y)},createXHR(_,y){return this.createRequest(hs,_,y)},createRequest(_,y,C){return new wf(_,y,C)}};const Ei=Oc;Ei.createXDR=function(_,y){return this.createRequest(Rc,_,y)};var Lc={nextAuthCallbackID:1,auth_callbacks:{},ScriptReceivers:m,DependenciesReceivers:E,getDefaultStrategy:zr,Transports:vn,transportConnectionInitializer:Sf,HTTPFactory:Ei,TimelineTransport:q,getXHRAPI(){return window.XMLHttpRequest},getWebSocketAPI(){return window.WebSocket||window.MozWebSocket},setup(_){window.Pusher=_;var y=()=>{this.onDocumentBody(_.ready)};window.JSON?y():A.load("json2",{},y)},getDocument(){return document},getProtocol(){return this.getDocument().location.protocol},getAuthorizers(){return{ajax:Xe,jsonp:En}},onDocumentBody(_){document.body?_():setTimeout(()=>{this.onDocumentBody(_)},0)},createJSONPRequest(_,y){return new Ea(_,y)},createScriptRequest(_){return new tr(_)},getLocalStorage(){try{return window.localStorage}catch{return}},createXHR(){return this.getXHRAPI()?this.createXMLHttpRequest():this.createMicrosoftXHR()},createXMLHttpRequest(){var _=this.getXHRAPI();return new _},createMicrosoftXHR(){return new ActiveXObject("Microsoft.XMLHTTP")},getNetwork(){return Ro},createWebSocket(_){var y=this.getWebSocketAPI();return new y(_)},createSocketRequest(_,y){if(this.isXHRSupported())return this.HTTPFactory.createXHR(_,y);if(this.isXDRSupported(y.indexOf("https:")===0))return this.HTTPFactory.createXDR(_,y);throw"Cross-origin HTTP requests are not supported"},isXHRSupported(){var _=this.getXHRAPI();return!!_&&new _().withCredentials!==void 0},isXDRSupported(_){var y=_?"https:":"http:",C=this.getProtocol();return!!window.XDomainRequest&&C===y},addUnloadListener(_){window.addEventListener!==void 0?window.addEventListener("unload",_,!1):window.attachEvent!==void 0&&window.attachEvent("onunload",_)},removeUnloadListener(_){window.addEventListener!==void 0?window.removeEventListener("unload",_,!1):window.detachEvent!==void 0&&window.detachEvent("onunload",_)},randomInt(_){return Math.floor(function(){return(window.crypto||window.msCrypto).getRandomValues(new Uint32Array(1))[0]/Math.pow(2,32)}()*_)}};const Be=Lc;var Ta;(function(_){_[_.ERROR=3]="ERROR",_[_.INFO=6]="INFO",_[_.DEBUG=7]="DEBUG"})(Ta||(Ta={}));const ir=Ta;class _i{constructor(y,C,O){this.key=y,this.session=C,this.events=[],this.options=O||{},this.sent=0,this.uniqueID=0}log(y,C){y<=this.options.level&&(this.events.push(Ae({},C,{timestamp:He.now()})),this.options.limit&&this.events.length>this.options.limit&&this.events.shift())}error(y){this.log(ir.ERROR,y)}info(y){this.log(ir.INFO,y)}debug(y){this.log(ir.DEBUG,y)}isEmpty(){return this.events.length===0}send(y,C){var O=Ae({session:this.session,bundle:this.sent+1,key:this.key,lib:"js",version:this.options.version,cluster:this.options.cluster,features:this.options.features,timeline:this.events},this.options.params);return this.events=[],y(O,(I,ne)=>{I||this.sent++,C&&C(I,ne)}),!0}generateUniqueID(){return this.uniqueID++,this.uniqueID}}class Cf{constructor(y,C,O,I){this.name=y,this.priority=C,this.transport=O,this.options=I||{}}isSupported(){return this.transport.isSupported({useTLS:this.options.useTLS})}connect(y,C){if(this.isSupported()){if(this.priority{O||(pt(),ne?ne.close():I.close())},forceMinPriority:Nt=>{O||this.priority{var C="socket_id="+encodeURIComponent(_.socketId);for(var O in y.params)C+="&"+encodeURIComponent(O)+"="+encodeURIComponent(y.params[O]);if(y.paramsProvider!=null){let I=y.paramsProvider();for(var O in I)C+="&"+encodeURIComponent(O)+"="+encodeURIComponent(I[O])}return C},_f=_=>{if(typeof Be.getAuthorizers()[_.transport]>"u")throw`'${_.transport}' is not a recognized auth transport`;return(y,C)=>{const O=Ef(y,_);Be.getAuthorizers()[_.transport](Be,O,_,R.UserAuthentication,C)}},jo=(_,y)=>{var C="socket_id="+encodeURIComponent(_.socketId);C+="&channel_name="+encodeURIComponent(_.channelName);for(var O in y.params)C+="&"+encodeURIComponent(O)+"="+encodeURIComponent(y.params[O]);if(y.paramsProvider!=null){let I=y.paramsProvider();for(var O in I)C+="&"+encodeURIComponent(O)+"="+encodeURIComponent(I[O])}return C},Af=_=>{if(typeof Be.getAuthorizers()[_.transport]>"u")throw`'${_.transport}' is not a recognized auth transport`;return(y,C)=>{const O=jo(y,_);Be.getAuthorizers()[_.transport](Be,O,_,R.ChannelAuthorization,C)}},xf=(_,y,C)=>{const O={authTransport:y.transport,authEndpoint:y.endpoint,auth:{params:y.params,headers:y.headers}};return(I,ne)=>{const pe=_.channel(I.channelName);C(pe,O).authorize(I.socketId,ne)}};function $c(_,y){let C={activityTimeout:_.activityTimeout||v.activityTimeout,cluster:_.cluster,httpPath:_.httpPath||v.httpPath,httpPort:_.httpPort||v.httpPort,httpsPort:_.httpsPort||v.httpsPort,pongTimeout:_.pongTimeout||v.pongTimeout,statsHost:_.statsHost||v.stats_host,unavailableTimeout:_.unavailableTimeout||v.unavailableTimeout,wsPath:_.wsPath||v.wsPath,wsPort:_.wsPort||v.wsPort,wssPort:_.wssPort||v.wssPort,enableStats:Df(_),httpHost:Tf(_),useTLS:kf(_),wsHost:Nc(_),userAuthenticator:Uo(_),channelAuthorizer:Lf(_,y)};return"disabledTransports"in _&&(C.disabledTransports=_.disabledTransports),"enabledTransports"in _&&(C.enabledTransports=_.enabledTransports),"ignoreNullOrigin"in _&&(C.ignoreNullOrigin=_.ignoreNullOrigin),"timelineParams"in _&&(C.timelineParams=_.timelineParams),"nacl"in _&&(C.nacl=_.nacl),C}function Tf(_){return _.httpHost?_.httpHost:_.cluster?`sockjs-${_.cluster}.pusher.com`:v.httpHost}function Nc(_){return _.wsHost?_.wsHost:Rf(_.cluster)}function Rf(_){return`ws-${_}.pusher.com`}function kf(_){return Be.getProtocol()==="https:"?!0:_.forceTLS!==!1}function Df(_){return"enableStats"in _?_.enableStats:"disableStats"in _?!_.disableStats:!1}const Ic=_=>"customHandler"in _&&_.customHandler!=null;function Uo(_){const y=Object.assign(Object.assign({},v.userAuthentication),_.userAuthentication);return Ic(y)?y.customHandler:_f(y)}function Of(_,y){let C;if("channelAuthorization"in _)C=Object.assign(Object.assign({},v.channelAuthorization),_.channelAuthorization);else if(C={transport:_.authTransport||v.authTransport,endpoint:_.authEndpoint||v.authEndpoint},"auth"in _&&("params"in _.auth&&(C.params=_.auth.params),"headers"in _.auth&&(C.headers=_.auth.headers)),"authorizer"in _)return{customHandler:xf(y,C,_.authorizer)};return C}function Lf(_,y){const C=Of(_,y);return Ic(C)?C.customHandler:Af(C)}class Mf extends je{constructor(y){super(function(C,O){et.debug(`No callbacks on watchlist events for ${C}`)}),this.pusher=y,this.bindWatchlistInternalEvent()}handleEvent(y){y.data.events.forEach(C=>{this.emit(C.name,C)})}bindWatchlistInternalEvent(){this.pusher.connection.bind("message",y=>{var C=y.event;C==="pusher_internal:watchlist_events"&&this.handleEvent(y)})}}function Hc(){let _,y;return{promise:new Promise((O,I)=>{_=O,y=I}),resolve:_,reject:y}}const $f=Hc;class Nf extends je{constructor(y){super(function(C,O){et.debug("No callbacks on user for "+C)}),this.signin_requested=!1,this.user_data=null,this.serverToUserChannel=null,this.signinDonePromise=null,this._signinDoneResolve=null,this._onAuthorize=(C,O)=>{if(C){et.warn(`Error during signin: ${C}`),this._cleanup();return}this.pusher.send_event("pusher:signin",{auth:O.auth,user_data:O.user_data})},this.pusher=y,this.pusher.connection.bind("state_change",({previous:C,current:O})=>{C!=="connected"&&O==="connected"&&this._signin(),C==="connected"&&O!=="connected"&&(this._cleanup(),this._newSigninPromiseIfNeeded())}),this.watchlist=new Mf(y),this.pusher.connection.bind("message",C=>{var O=C.event;O==="pusher:signin_success"&&this._onSigninSuccess(C.data),this.serverToUserChannel&&this.serverToUserChannel.name===C.channel&&this.serverToUserChannel.handleEvent(C)})}signin(){this.signin_requested||(this.signin_requested=!0,this._signin())}_signin(){this.signin_requested&&(this._newSigninPromiseIfNeeded(),this.pusher.connection.state==="connected"&&this.pusher.config.userAuthenticator({socketId:this.pusher.connection.socket_id},this._onAuthorize))}_onSigninSuccess(y){try{this.user_data=JSON.parse(y.user_data)}catch{et.error(`Failed parsing user data after signin: ${y.user_data}`),this._cleanup();return}if(typeof this.user_data.id!="string"||this.user_data.id===""){et.error(`user_data doesn't contain an id. user_data: ${this.user_data}`),this._cleanup();return}this._signinDoneResolve(),this._subscribeChannels()}_subscribeChannels(){const y=C=>{C.subscriptionPending&&C.subscriptionCancelled?C.reinstateSubscription():!C.subscriptionPending&&this.pusher.connection.state==="connected"&&C.subscribe()};this.serverToUserChannel=new Pa(`#server-to-user-${this.user_data.id}`,this.pusher),this.serverToUserChannel.bind_global((C,O)=>{C.indexOf("pusher_internal:")===0||C.indexOf("pusher:")===0||this.emit(C,O)}),y(this.serverToUserChannel)}_cleanup(){this.user_data=null,this.serverToUserChannel&&(this.serverToUserChannel.unbind_all(),this.serverToUserChannel.disconnect(),this.serverToUserChannel=null),this.signin_requested&&this._signinDoneResolve()}_newSigninPromiseIfNeeded(){if(!this.signin_requested||this.signinDonePromise&&!this.signinDonePromise.done)return;const{promise:y,resolve:C}=$f();y.done=!1;const O=()=>{y.done=!0};y.then(O).catch(O),this.signinDonePromise=y,this._signinDoneResolve=C}}class rn{static ready(){rn.isReady=!0;for(var y=0,C=rn.instances.length;yBe.getDefaultStrategy(this.config,I,Ai);this.connection=Mn.createConnectionManager(this.key,{getStrategy:O,timeline:this.timeline,activityTimeout:this.config.activityTimeout,pongTimeout:this.config.pongTimeout,unavailableTimeout:this.config.unavailableTimeout,useTLS:!!this.config.useTLS}),this.connection.bind("connected",()=>{this.subscribeAll(),this.timelineSender&&this.timelineSender.send(this.connection.isUsingTLS())}),this.connection.bind("message",I=>{var ne=I.event,pe=ne.indexOf("pusher_internal:")===0;if(I.channel){var Me=this.channel(I.channel);Me&&Me.handleEvent(I)}pe||this.global_emitter.emit(I.event,I.data)}),this.connection.bind("connecting",()=>{this.channels.disconnect()}),this.connection.bind("disconnected",()=>{this.channels.disconnect()}),this.connection.bind("error",I=>{et.warn(I)}),rn.instances.push(this),this.timeline.info({instances:rn.instances.length}),this.user=new Nf(this),rn.isReady&&this.connect()}switchCluster(y){const{appKey:C,cluster:O}=y;this.key=C,this.options=Object.assign(Object.assign({},this.options),{cluster:O}),this.config=$c(this.options,this),this.connection.switchCluster(this.key)}channel(y){return this.channels.find(y)}allChannels(){return this.channels.all()}connect(){if(this.connection.connect(),this.timelineSender&&!this.timelineSenderTimer){var y=this.connection.isUsingTLS(),C=this.timelineSender;this.timelineSenderTimer=new Ne(6e4,function(){C.send(y)})}}disconnect(){this.connection.disconnect(),this.timelineSenderTimer&&(this.timelineSenderTimer.ensureAborted(),this.timelineSenderTimer=null)}bind(y,C,O){return this.global_emitter.bind(y,C,O),this}unbind(y,C,O){return this.global_emitter.unbind(y,C,O),this}bind_global(y){return this.global_emitter.bind_global(y),this}unbind_global(y){return this.global_emitter.unbind_global(y),this}unbind_all(y){return this.global_emitter.unbind_all(),this}subscribeAll(){var y;for(y in this.channels.channels)this.channels.channels.hasOwnProperty(y)&&this.subscribe(y)}subscribe(y){var C=this.channels.add(y,this);return C.subscriptionPending&&C.subscriptionCancelled?C.reinstateSubscription():!C.subscriptionPending&&this.connection.state==="connected"&&C.subscribe(),C}unsubscribe(y){var C=this.channels.find(y);C&&C.subscriptionPending?C.cancelSubscription():(C=this.channels.remove(y),C&&C.subscribed&&C.unsubscribe())}send_event(y,C,O){return this.connection.send_event(y,C,O)}shouldUseTLS(){return this.config.useTLS}signin(){this.user.signin()}}rn.instances=[],rn.isReady=!1,rn.logToConsole=!1,rn.Runtime=Be,rn.ScriptReceivers=Be.ScriptReceivers,rn.DependenciesReceivers=Be.DependenciesReceivers,rn.auth_callbacks=Be.auth_callbacks;const ms=rn;function If(_){if(_==null)throw"You must pass your app key when you instantiate Pusher."}Be.setup(rn)}},r={};function i(u){var d=r[u];if(d!==void 0)return d.exports;var f=r[u]={exports:{}};return a[u].call(f.exports,f,f.exports,i),f.exports}i.d=(u,d)=>{for(var f in d)i.o(d,f)&&!i.o(u,f)&&Object.defineProperty(u,f,{enumerable:!0,get:d[f]})},i.o=(u,d)=>Object.prototype.hasOwnProperty.call(u,d);var l=i(721);return l})())})(lf)),lf.exports}var L_=O_();const ty=Ya(L_),Ht=ct("WebSocketManager");class M_{constructor(){$(this,"echo",null);$(this,"subscriptions",new Map);$(this,"initialized",!1);$(this,"config",null)}configure(e){if(this.initialized){Ht.warn("[WebSocketManager] 이미 초기화되어 설정을 변경할 수 없습니다.");return}this.config=e,Ht.log("[WebSocketManager] 설정 완료:",{appKey:e.appKey?"***":"(없음)",host:e.host,port:e.port,scheme:e.scheme})}initialize(){if(this.initialized)return;if(!this.config||!this.config.appKey){Ht.warn("[WebSocketManager] WebSocket 설정이 없습니다. initTemplateApp에서 websocket 옵션을 전달해주세요.");return}const{appKey:e,host:a="localhost",port:r=80,scheme:i="https",authEndpoint:l="/api/broadcasting/auth"}=this.config,u=Number(r)||80,d=i==="https";Ht.log("[WebSocketManager] 연결 설정:",{host:a,port:u,scheme:i,useTLS:d,authEndpoint:l}),window.Pusher=ty;const f=localStorage.getItem("auth_token"),g={wsHost:a,wsPort:u,wssPort:u,forceTLS:d,disableStats:!0,enabledTransports:["ws","wss"],cluster:"mt1",authEndpoint:l,auth:{headers:{Authorization:f?`Bearer ${f}`:"",Accept:"application/json"}}};Ht.log("[WebSocketManager] Pusher 옵션:",g);const m=new ty(e,g);m.connection.bind("connecting",()=>{Ht.log("[WebSocketManager] 연결 시도 중...")}),m.connection.bind("connected",()=>{Ht.log("[WebSocketManager] 연결 성공! Socket ID:",m.connection.socket_id)}),m.connection.bind("failed",()=>{Ht.error("[WebSocketManager] 연결 실패 - WebSocket을 사용할 수 없습니다.")}),m.connection.bind("error",b=>{Ht.error("[WebSocketManager] 연결 오류:",b)}),m.connection.bind("state_change",b=>{Ht.log(`[WebSocketManager] 상태 변경: ${b.previous} → ${b.current}`)}),m.connection.bind("unavailable",()=>{Ht.error("[WebSocketManager] WebSocket 사용 불가 - 연결할 수 없습니다.")}),m.connection.bind("disconnected",()=>{Ht.warn("[WebSocketManager] 연결이 끊어졌습니다.")}),Ht.log("[WebSocketManager] 초기 연결 상태:",m.connection.state),this.echo=new D_({broadcaster:"reverb",client:m}),Ht.log("[WebSocketManager] 연결 시작 시도..."),m.connect(),window.Echo=this.echo,this.initialized=!0,Ht.log("[WebSocketManager] Echo 초기화 완료")}subscribe(e,a,r,i={}){if(this.initialize(),!this.echo)return Ht.warn("[WebSocketManager] Echo가 초기화되지 않았습니다."),"";const{channelType:l="private"}=i,u=`${e}:${a}`;if(this.subscriptions.has(u))return Ht.log(`[WebSocketManager] 이미 구독 중: ${u}`),u;let d;switch(l){case"public":d=this.echo.channel(e);break;case"presence":d=this.echo.join(e);break;default:d=this.echo.private(e)}return d.listen(`.${a}`,r),this.subscriptions.set(u,d),Ht.log(`[WebSocketManager] 구독 완료: ${u} (${l})`),u}unsubscribe(e){const a=this.subscriptions.get(e);if(!a)return;const r=e.lastIndexOf(":"),i=r>=0?e.substring(r+1):"";if(i)try{a.stopListening(`.${i}`)}catch(l){Ht.warn(`[WebSocketManager] stopListening 실패: ${e}`,l)}this.subscriptions.delete(e),Ht.log(`[WebSocketManager] 구독 해제: ${e}`)}leaveChannel(e){if(!this.echo)return;this.echo.leave(e);const a=[];this.subscriptions.forEach((r,i)=>{i.startsWith(`${e}:`)&&a.push(i)}),a.forEach(r=>this.subscriptions.delete(r)),Ht.log(`[WebSocketManager] 채널 구독 해제: ${e}`)}disconnect(){this.echo&&(this.echo.disconnect(),this.subscriptions.clear(),this.initialized=!1,Ht.log("[WebSocketManager] 연결 종료"))}getEcho(){return this.echo}isInitialized(){return this.initialized}isConfigured(){return this.config!==null&&!!this.config.appKey}getSubscriptionCount(){return this.subscriptions.size}}const hc=new M_,bt=ct("DataSourceManager"),$_=new wn;function gc(o,e){const a=o.match(/^\{\{(.+)\}\}$/);if(a){const r=a[1].trim();try{return $_.evaluateExpression(r,e)}catch(i){return bt.error("Failed to evaluate param expression:",r,i),o}}return Ji(o,e,{skipCache:!0})}function ny(o){const e={};for(const a of o.keys()){if(a in e)continue;const r=o.getAll(a);r.length>1?e[a]=r:r.length===1&&(a.endsWith("[]")?e[a]=r:e[a]=r[0])}return e}function N_(){try{return window.G7Core?.devTools}catch{return}}const bc=class bc{constructor(e={}){$(this,"options");$(this,"dataCache",new Map);$(this,"bindingEngine");$(this,"globalHeaders",[]);this.options=e,this.bindingEngine=new wn}setGlobalHeaders(e){this.globalHeaders=e||[]}matchesPattern(e,a){if(a==="*")return!0;const r=a.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${r}$`).test(e)}toFormData(e){const a=new FormData;for(const[r,i]of Object.entries(e))i instanceof File||i instanceof Blob?a.append(r,i):i!=null&&a.append(r,typeof i=="object"?JSON.stringify(i):String(i));return a}getMatchingGlobalHeaders(e,a){const r={};for(const i of this.globalHeaders)this.matchesPattern(e,i.pattern)&&Object.entries(i.headers).forEach(([l,u])=>{const d=gc(u,a);d!=null&&d!==""&&(r[l]=String(d))});return r}filterByCondition(e,a={}){const r=new Set,i=[];for(const l of e){if(r.has(l.id))continue;if(!l.if&&!l.conditions){r.add(l.id),i.push(l);continue}Xi({if:l.if,conditions:l.conditions},a,this.bindingEngine,`data_source:${l.id}`)&&(r.add(l.id),i.push(l))}return i}checkErrorCondition(e,a){if(!e.errorCondition?.if||e.errorCondition?.errorCode===void 0)return null;try{const r={response:a};if(Xi({if:e.errorCondition.if},r,this.bindingEngine,`errorCondition:${e.id}`))return bt.log(`errorCondition matched for ${e.id}, triggering error ${e.errorCondition.errorCode}`),e.errorCondition.errorCode}catch(r){bt.error(`Failed to evaluate errorCondition for ${e.id}:`,r)}return null}async fetchDataSources(e,a={},r=new URLSearchParams,i,l){const u={},d=!!this.options.sampleProvider,f=e.filter(g=>(d||g.auto_fetch!==!1)&&g.type!=="websocket");return await Promise.all(f.map(async g=>{try{const m=await this.fetchDataSource(g,a,r,i,l);u[g.id]=m,this.dataCache.set(g.id,{data:m,timestamp:Date.now()});const b=this.checkErrorCondition(g,m);if(b!==null){const v={status:b,message:`Error condition matched for ${g.id}`,data:m},S=pa(),E=S.resolve(b,{errorHandling:g.errorHandling,onError:g.onError});if(E.handler)try{await S.execute(E.handler,v)}catch(A){bt.error(`Error executing errorCondition handler for ${g.id}:`,A)}g.fallback!==void 0&&(u[g.id]=g.fallback,this.dataCache.set(g.id,{data:g.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${g.id} (errorCondition)`));return}if(g.onSuccess)try{const v={data:m,sourceId:g.id};await this.executeOnSuccessHandler(g.onSuccess,v)}catch(v){bt.error(`Error executing onSuccess handler for ${g.id}:`,v)}}catch(m){bt.error(`Failed to fetch data source: ${g.id}`,m);const b=m?.response?.status||m?.status||500,v=m?.response?.data,S=v?.message||m.message||"Unknown error",E={status:b,message:S,errors:v?.errors,data:v,statusText:m?.response?.statusText},A=pa(),T=A.resolve(b,{errorHandling:g.errorHandling,onError:g.onError});if(T.handler)try{await A.execute(T.handler,E)}catch(L){bt.error(`Error executing error handler for ${g.id}:`,L)}g.fallback!==void 0&&(u[g.id]=g.fallback,this.dataCache.set(g.id,{data:g.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${g.id}`)),this.options.onError&&this.options.onError(m,g)}})),u}async fetchDataSourcesWithResults(e,a={},r=new URLSearchParams,i,l,u){if(e.some(m=>m.type==="websocket")){const m=e.filter(b=>b.type==="websocket").map(b=>b.id).join(", ");bt.warn(`fetchDataSourcesWithResults received WebSocket sources (caller should filter them out before calling): ${m}. WebSocket sources are event listeners, not data providers — they should not be passed to fetch.`)}const f=u?.ignoreAutoFetch?e.filter(m=>m.type!=="websocket"):e.filter(m=>m.auto_fetch!==!1&&m.type!=="websocket");return await Promise.all(f.map(async m=>{try{const b=await this.fetchDataSource(m,a,r,i,l);this.dataCache.set(m.id,{data:b,timestamp:Date.now()});const v=this.checkErrorCondition(m,b);if(v!==null){const S={status:v,message:`Error condition matched for ${m.id}`,data:b},E=pa(),A=E.resolve(v,{errorHandling:m.errorHandling,onError:m.onError});let T=!1;if(A.handler)if(m.loading_strategy==="blocking")E.execute(A.handler,S).catch(L=>{bt.error(`Error executing errorCondition handler for ${m.id}:`,L)}),T=!0;else try{await E.execute(A.handler,S),T=!0}catch(L){bt.error(`Error executing errorCondition handler for ${m.id}:`,L)}return m.fallback!==void 0?(this.dataCache.set(m.id,{data:m.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${m.id} (errorCondition)`),{id:m.id,state:"success",data:m.fallback}):{id:m.id,state:"error",error:new Error(`Error condition matched: ${v}`),errorCode:v,errorHandled:T}}if(m.onSuccess)try{const S={data:b,sourceId:m.id};await this.executeOnSuccessHandler(m.onSuccess,S)}catch(S){bt.error(`Error executing onSuccess handler for ${m.id}:`,S)}return{id:m.id,state:"success",data:b}}catch(b){bt.error(`Failed to fetch data source: ${m.id}`,b);const v=b?.response?.status||b?.status||500,S=b?.response?.data,E=S?.message||b.message||"Unknown error",A={status:v,message:E,errors:S?.errors,data:S,statusText:b?.response?.statusText},T=pa(),L=T.resolve(v,{errorHandling:m.errorHandling,onError:m.onError});let M=!1;if(L.handler)if(m.loading_strategy==="blocking")T.execute(L.handler,A).catch(R=>{bt.error(`Error executing error handler for ${m.id}:`,R)}),M=!0;else try{await T.execute(L.handler,A),M=!0}catch(R){bt.error(`Error executing error handler for ${m.id}:`,R)}return m.fallback!==void 0?(this.dataCache.set(m.id,{data:m.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${m.id}`),{id:m.id,state:"success",data:m.fallback}):(this.options.onError&&this.options.onError(b,m),{id:m.id,state:"error",error:b,errorCode:v,errorHandled:M})}}))}fetchDataSourcesInBackground(e,a={},r=new URLSearchParams,i){e.filter(u=>u.auto_fetch!==!1&&u.loading_strategy==="background"&&u.type!=="websocket").forEach(u=>{this.fetchDataSource(u,a,r).then(async d=>{this.dataCache.set(u.id,{data:d,timestamp:Date.now()});const f=this.checkErrorCondition(u,d);if(f!==null){const g={status:f,message:`Error condition matched for ${u.id}`,data:d},m=pa(),b=m.resolve(f,{errorHandling:u.errorHandling,onError:u.onError});if(b.handler)try{await m.execute(b.handler,g)}catch(v){bt.error(`Error executing errorCondition handler for ${u.id}:`,v)}u.fallback!==void 0&&(this.dataCache.set(u.id,{data:u.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${u.id} (errorCondition)`),i&&i(u.id,u.fallback));return}if(u.onSuccess)try{const g={data:d,sourceId:u.id};await this.executeOnSuccessHandler(u.onSuccess,g)}catch(g){bt.error(`Error executing onSuccess handler for ${u.id}:`,g)}i&&i(u.id,d)}).catch(async d=>{bt.error(`Background fetch failed: ${u.id}`,d);const f=d?.response?.status||d?.status||500,g=d?.response?.data,m=g?.message||d.message||"Unknown error",b={status:f,message:m,errors:g?.errors,data:g,statusText:d?.response?.statusText},v=pa(),S=v.resolve(f,{errorHandling:u.errorHandling,onError:u.onError});if(S.handler)try{await v.execute(S.handler,b)}catch(E){bt.error(`Error executing error handler for ${u.id}:`,E)}if(u.fallback!==void 0){this.dataCache.set(u.id,{data:u.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${u.id}`),i&&i(u.id,u.fallback);return}this.options.onError&&this.options.onError(d,u)})})}async fetchDataSource(e,a,r,i,l){switch(e.type){case"api":return this.fetchApiDataSource(e,a,r,i,l);case"static":return e.data;case"route_params":return a;case"query_params":return ny(r);default:throw new Error(`Unknown data source type: ${e.type}`)}}async fetchApiDataSource(e,a,r,i,l){if(this.options.sampleProvider?.has(e.id))return await Promise.resolve(this.options.sampleProvider.resolve(e));if(!e.endpoint)throw new Error(`API data source ${e.id} has no endpoint`);const u={route:a,query:ny(r)};i&&(u._global=i),l&&(u._local=l);let d=Ji(e.endpoint,u,{skipCache:!0});const f=e.method||"GET",m=(e.contentType?typeof e.contentType=="string"&&e.contentType.includes("{{")?Ji(e.contentType,u,{skipCache:!0}):e.contentType:"application/json")==="multipart/form-data";let b=m?{...e.params||{}}:JSON.parse(JSON.stringify(e.params||{}));Object.entries(b).forEach(([E,A])=>{typeof A=="string"&&(b[E]=gc(A,u))}),Object.keys(b).forEach(E=>{b[E]===""&&delete b[E]});const v=N_();let S=null;if(v?.isEnabled()){v.trackDataSourceDefinition({id:e.id,type:e.type,endpoint:d,method:f,autoFetch:e.auto_fetch,initLocal:e.initLocal,initGlobal:e.initGlobal});let E=d;if(f==="GET"&&Object.keys(b).length>0){const A=new URLSearchParams;Object.entries(b).forEach(([L,M])=>{Array.isArray(M)?M.forEach(R=>A.append(L,String(R))):M!=null&&A.append(L,String(M))});const T=A.toString();E=T?`${d}?${T}`:d}S=v.trackRequest(E,f,{requestBody:f!=="GET"?b:void 0,dataSourceId:e.id}),v.trackDataSourceLoading(e.id)}try{let E;const A=e.auth_mode??(e.auth_required===!0?"required":"none"),T=ha.getInstance().isAuthenticated();if(A==="required"&&!T){bt.log(`[DataSourceManager] Skipping ${e.id}: auth_mode is 'required' but no token available`),v?.isEnabled()&&(v.trackDataSourceError(e.id,"Skipped: auth_mode required but not authenticated"),S&&v.failRequest(S,"Skipped: not authenticated"));const M=new Error("Auth required but not authenticated");throw M.response={status:401,statusText:"Unauthorized",data:null},M.status=401,M._authSkipped=!0,M}const L=A==="required"||A==="optional"&&T;if(L){const M=$a(),R=d.startsWith("/api/")?d.substring(4):d.startsWith("/api")?d.substring(4)||"/":d;this.options.onError&&bt.log(`[DataSourceManager] Normalized endpoint: ${d} -> ${R}`);const D=this.getMatchingGlobalHeaders(d,u),U={};e.headers&&Object.entries(e.headers).forEach(([ge,Ee])=>{const Ce=gc(Ee,u);Ce!=null&&Ce!==""&&(U[ge]=String(Ce))});const j={...D,...U},P=Object.keys(j).length>0,X=m?this.toFormData(b):b;switch(f){case"GET":E=await M.get(R,{params:b,...P&&{headers:j}});break;case"POST":P?E=await M.post(R,X,{headers:j}):E=await M.post(R,X);break;case"PUT":P?E=await M.put(R,X,{headers:j}):E=await M.put(R,X);break;case"PATCH":P?E=await M.patch(R,X,{headers:j}):E=await M.patch(R,X);break;case"DELETE":E=await M.delete(R,{params:b,...P&&{headers:j}});break;default:throw new Error(`Unsupported HTTP method: ${f}`)}}else{let M=d;if(f==="GET"){const X=new URLSearchParams(b).toString();M=X?`${d}?${X}`:d}const R={...m?{}:{"Content-Type":"application/json"},Accept:"application/json"};if(typeof window<"u"){const X=localStorage.getItem("g7_locale");X&&(R["Accept-Language"]=X)}const D=this.getMatchingGlobalHeaders(d,u);Object.assign(R,D),e.headers&&Object.entries(e.headers).forEach(([X,ge])=>{const Ee=gc(ge,u);Ee!=null&&Ee!==""&&(R[X]=String(Ee))});let U;f!=="GET"&&(m?(U=this.toFormData(b),delete R["Content-Type"]):U=JSON.stringify(b));const j=await fetch(M,{method:f,headers:R,body:U});let P;try{P=await j.json()}catch{P=null}if(S&&v?.isEnabled()&&(v.completeRequest(S,j.status,P),S=null),!j.ok){v?.isEnabled()&&v.trackDataSourceError(e.id,`HTTP ${j.status}: ${j.statusText}`);const X=new Error(`HTTP error! status: ${j.status}`);throw X.response={status:j.status,statusText:j.statusText,data:P},X.status=j.status,X}E=P,v?.isEnabled()&&v.trackDataSourceLoaded(e.id,E)}return L&&S&&v?.isEnabled()&&(v.completeRequest(S,200,E),v.trackDataSourceLoaded(e.id,E)),E}catch(E){if(S&&v?.isEnabled()){const A=E;A?.response?v.completeRequest(S,A.response.status,A.response.data):v.failRequest(S,E instanceof Error?E.message:String(E)),v.trackDataSourceError(e.id,E instanceof Error?E.message:String(E))}throw E}}getCachedData(e){const a=this.dataCache.get(e);if(!a)return;if(Date.now()-a.timestamp>bc.DATA_CACHE_TTL){this.dataCache.delete(e);return}return a.data}clearCache(){this.dataCache.clear()}subscribeWebSockets(e,a,r={}){const i=[],l=e.filter(u=>u.type==="websocket");return l.length===0||l.forEach(u=>{if(!u.channel||!u.event){bt.warn(`WebSocket source ${u.id} missing channel or event`);return}let d,f;try{d=Ji(u.channel,r,{skipCache:!0}),f=Ji(u.event,r,{skipCache:!0})}catch(b){bt.error(`Failed to resolve WebSocket channel/event for source ${u.id}:`,b);return}const g=b=>!!(!b||b.trim()===""||b.includes("{{")||b.endsWith(".")||b.endsWith(":")||b.startsWith(".")||b.startsWith(":")||b.includes("..")||b.includes("::"));if(g(d)||g(f)){bt.warn(`WebSocket source ${u.id} has invalid channel/event after expression resolution, skipping. Original channel="${u.channel}", resolved="${d}". Original event="${u.event}", resolved="${f}". Available context keys: [${Object.keys(r).join(", ")}]`);return}const m=hc.subscribe(d,f,b=>{const v=u.target_source||u.id;this.dataCache.set(v,{data:b,timestamp:Date.now()}),a(v,b)},{channelType:u.channel_type||"private"});m&&i.push(m)}),i}unsubscribeWebSockets(e){e.length!==0&&e.forEach(a=>{hc.unsubscribe(a)})}async executeOnSuccessHandler(e,a){const r=this.options.actionDispatcher??Zp();if(!r){bt.warn("ActionDispatcher not available, skipping onSuccess handler");return}const i=Array.isArray(e)?e:[e];for(const l of i)try{await r.dispatchAction({type:"click",...l},{data:{response:a}})}catch(u){throw bt.error("Failed to execute onSuccess handler:",u),u}}};$(bc,"DATA_CACHE_TTL",3e5);let va=bc;const I_=new va,gi=ct("ModalDataSourceWrapper");function H_(o,e){if(!o||!e)return o;const r=e.replace(/\?\./g,".").split(/\.(?![^\[]*\])/).flatMap(l=>{const u=l.match(/^([^\[]*)((?:\[\d+\])*)$/);if(u){const[,d,f]=u,g=[];d&&g.push(d);const m=f.match(/\[\d+\]/g);return m&&g.push(...m),g}return[l]}).filter(l=>l!=="");let i=o;for(const l of r){if(i==null)return;if(l.startsWith("[")&&l.endsWith("]")){const u=parseInt(l.slice(1,-1),10);i=i[u]}else i=i[l]}return i}const ay=({isOpen:o,modalId:e,dataSources:a,dataContext:r,globalStateUpdater:i,bindingEngine:l,debug:u=!1,children:d})=>{const[f,g]=N.useState(!1),[m,b]=N.useState(!1),v=N.useRef(!1),S=N.useRef(null);S.current||(S.current=new va);const E=N.useCallback(async()=>{if(!(!a||a.length===0)&&S.current){g(!0);try{const A=r.route||{},T=new URLSearchParams(window.location.search),L=a.map(R=>{let D={...R};if(R.endpoint&&l){const U=l.resolveBindings(R.endpoint,r,{skipCache:!0});D.endpoint=U}if(R.params&&l){const U={};Object.entries(R.params).forEach(([j,P])=>{typeof P=="string"?U[j]=l.resolveBindings(P,r,{skipCache:!0}):U[j]=P}),D.params=U}return D});u&&gi.log(`[ModalDataSourceWrapper] Modal "${e}" fetching data sources:`,L.map(R=>({id:R.id,endpoint:R.endpoint})));const M=await S.current.fetchDataSourcesWithResults(L,A,T);i&&M.forEach(R=>{if(R.state==="success"&&R.data!==void 0){const D=L.find(U=>U.id===R.id);if(D?.initGlobal){const U=R.data?.data??R.data,j=Array.isArray(D.initGlobal)?D.initGlobal:[D.initGlobal];for(const P of j)if(typeof P=="string")i({[P]:U}),u&&gi.log(`[ModalDataSourceWrapper] Modal "${e}" initGlobal: ${R.id}.data -> _global.${P}`);else if(typeof P=="object"&&P.key){const{key:X,path:ge}=P,Ee=ge?H_(U,ge):U;i({[X]:Ee}),u&&gi.log(`Modal "${e}" initGlobal: ${R.id}.data${ge?"."+ge:""} -> _global.${X}`)}}}else R.state==="error"&&gi.error(`Modal "${e}" data source error:`,R.id,R.error)}),u&&gi.log(`Modal "${e}" data sources fetched successfully`)}catch(A){gi.error(`Modal "${e}" data source fetch error:`,A)}finally{g(!1),b(!0)}}},[a,r,i,l,e,u]);return N.useEffect(()=>{if(!a||a.length===0)return;const A=window.__templateApp;return A?.registerModalDataSources&&A.registerModalDataSources(e,a),()=>{A?.unregisterModalDataSources&&A.unregisterModalDataSources(e)}},[e,a]),N.useEffect(()=>{!o&&v.current&&(b(!1),u&&gi.log(`[ModalDataSourceWrapper] Modal "${e}" closed, reset fetch state`)),o&&!v.current&&a&&a.length>0&&!m&&E(),v.current=o},[o,a,m,E,e,u]),ut.jsx(ut.Fragment,{children:d})};class pc extends Error{constructor(a,r,i={}){super(r);$(this,"code");$(this,"userMessageKey");$(this,"showStack");$(this,"icon");$(this,"recoverable");this.name="TemplateEngineError",this.code=a,this.userMessageKey=r,this.showStack=i.showStack??!0,this.icon=i.icon??"fa-circle-exclamation",this.recoverable=i.recoverable??!0,Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}getUserMessage(a,r){if(!r||!a)return this.userMessageKey;try{return r.translate(this.userMessageKey,a)}catch{return this.userMessageKey}}}class z_ extends pc{constructor(){super("TEMPLATE_NOT_FOUND","$t:core.errors.template_not_found",{showStack:!1,icon:"fa-paint-brush",recoverable:!1}),this.name="TemplateNotFoundError"}}function ry(o){if(o instanceof pc)return o;if(o instanceof Error){const e=new pc("TEMPLATE_INIT_ERROR",o.message||"$t:core.errors.template_init_error",{showStack:!0,icon:"fa-circle-exclamation",recoverable:!0});return e.stack=o.stack,e}return new pc("TEMPLATE_INIT_ERROR","$t:core.errors.template_init_error",{showStack:!1,icon:"fa-circle-exclamation",recoverable:!0})}const j_=ct("ErrorDisplay");class cf{static render(e,a){const r=document.getElementById(e);if(!r){j_.error(`Container #${e} not found`);return}const i=a.debug&&a.showStack&&a.stackTrace,l=window.matchMedia("(prefers-color-scheme: dark)").matches,u={container:` display: flex; align-items: center; justify-content: center; @@ -224,7 +224,7 @@ Error generating stack: `+c.message+` `:""} - `}static renderFromError(e,a,r,i=!1,l,u,d){let f,g;if(a.userMessageKey.startsWith("$t:"))if(u&&l)try{f=u.translate(a.userMessageKey,l)}catch{f=a.userMessageKey.replace("$t:","")}else f=a.userMessageKey.replace("$t:","");else f=a.userMessageKey;if(d){const m=d;m.details?.apiMessage?g=m.details.apiMessage:m.response?.data?.message&&(g=m.response.data.message)}this.render(e,{title:r,message:f,detailMessage:g,icon:a.icon,showStack:a.showStack,stackTrace:a.stack,showReloadButton:a.recoverable,debug:i})}static escapeHtml(e){if(!e)return"";const a=document.createElement("div");return a.textContent=e,a.innerHTML}}const ss=ct("Router");class U_{constructor(e){$(this,"routes",[]);$(this,"templateIdentifier");$(this,"eventHandlers",new Map);$(this,"pendingNavigation",null);$(this,"isNavigating",!1);$(this,"handlePopState",()=>{this.navigateToCurrentPath()});this.templateIdentifier=e,this.initPopstateListener()}initPopstateListener(){window.addEventListener("popstate",this.handlePopState)}on(e,a){this.eventHandlers.has(e)||this.eventHandlers.set(e,[]),this.eventHandlers.get(e).push(a)}async emit(e,...a){const r=this.eventHandlers.get(e);r&&await Promise.all(r.map(i=>i(...a)))}async loadRoutes(e){try{const a=e!==void 0&&e>0?e:null,r=await fetch(La(`/api/templates/${this.templateIdentifier}/routes`,"json",a));if(!r.ok)throw new Error(`Failed to load routes: ${r.statusText}`);const i=await r.json();if(!i.success)throw new Error("Failed to load routes from API");if(i.data&&Array.isArray(i.data.routes))this.routes=i.data.routes,ss.log(`Loaded ${this.routes.length} routes${e?` (v=${e})`:""}`);else throw new Error("Invalid routes data format")}catch(a){throw ss.error("Error loading routes:",a),a}}setRoutes(e){this.routes=e,ss.log(`Set ${this.routes.length} routes`)}match(e){const a=this.normalizePathname(e);for(const r of this.routes){const i=this.matchPattern(r.path,a);if(i!==null)return{route:r,params:i}}return null}normalizePathname(e){return e.length>1&&e.endsWith("/")?e.replace(/\/+$/,"")||"/":e}matchPattern(e,a){const r=[];let i=e.replace(/:([^/]+)/g,(f,g)=>(r.push(g),"([^/]+)"));i.startsWith("*/")&&(i="(?:/[^/]+)?"+i.slice(1)),i=i.replace(/\//g,"\\/");const l=new RegExp(`^${i}$`),u=a.match(l);if(!u)return null;const d={};return r.forEach((f,g)=>{d[f]=u[g+1]}),d}getRoutes(){return[...this.routes]}getAuthType(e,a){return e.auth_type?e.auth_type:a.startsWith("/admin")?"admin":"user"}async navigateToCurrentPath(){const e=window.location.pathname,a=window.location.search,r=this.match(e);if(!r){ss.warn(`No route matched for path: ${e}`),this.emit("routeNotFound",e);return}if(r.route.redirect){ss.log(`Redirecting from ${e} to ${r.route.redirect}`),this.navigate(r.route.redirect);return}if(r.route.auth_required){const u=this.getAuthType(r.route,e),d=ha.getInstance();let f=d.isAuthenticated()&&d.getAuthType()===u;if(f||(f=await d.checkAuth(u)),!f){const g=d.getLoginRedirectUrl(u,e+a);ss.log(`Not authenticated, redirecting to: ${g}`),window.location.href=g;return}}const i=new URLSearchParams(a),l={};for(const u of i.keys()){if(u in l)continue;const d=i.getAll(u);d.length>1?l[u]=d:d.length===1&&(u.endsWith("[]")?l[u]=d:l[u]=d[0])}await this.emit("routeChange",{path:e,layout:r.route.layout,endpoint:r.route.endpoint,params:{...r.route.params||{},...r.params},query:l,auth_required:r.route.auth_required,auth_type:r.route.auth_type,meta:r.route.meta})}navigate(e){if(this.isNavigating){this.pendingNavigation=e;return}this.executeNavigation(e)}async executeNavigation(e){this.isNavigating=!0,this.pendingNavigation=null;try{window.history.pushState({},"",e),await this.navigateToCurrentPath()}finally{if(this.isNavigating=!1,this.pendingNavigation){const a=this.pendingNavigation;this.executeNavigation(a)}}}}const B_=/^\/admin\/layout-editor\/([^/?#]+)\/?$/;function iy(o){const e=B_.exec(o);return e?{templateIdentifier:e[1]}:null}const zt=ct("ErrorPageHandler");class P_{constructor(e){$(this,"templateId");$(this,"layoutLoader");$(this,"locale");$(this,"debug");$(this,"renderFunction");$(this,"dataSourceManager");$(this,"globalState");$(this,"errorConfig",null);$(this,"configLoaded",!1);this.templateId=e.templateId,this.layoutLoader=e.layoutLoader,this.locale=e.locale,this.debug=e.debug,this.renderFunction=e.renderFunction,this.dataSourceManager=e.dataSourceManager,this.globalState=e.globalState||{}}async loadConfig(){if(this.configLoaded)return this.errorConfig;try{const e=await fetch(La(`/api/templates/${this.templateId}/config`,"json"));if(!e.ok)return this.debug&&zt.warn("Failed to load template config:",e.statusText),this.configLoaded=!0,null;const a=await e.json();if(!a.success||!a.data)return this.debug&&zt.warn("Invalid template config response"),this.configLoaded=!0,null;const r=a.data;return!r.error_config||!r.error_config.layouts?(this.debug&&zt.warn("No error_config found in template.json"),this.configLoaded=!0,null):(this.errorConfig=r.error_config,this.configLoaded=!0,this.debug&&zt.log("Error config loaded:",this.errorConfig),this.errorConfig)}catch(e){return zt.error("Failed to load error config:",e),this.configLoaded=!0,null}}async renderError(e,a="app"){try{const r=await this.loadConfig();if(!r)return this.debug&&zt.warn("No error config available, cannot render error page"),!1;const i=r.layouts[e]||r.layouts[String(e)];if(!i)return this.debug&&zt.warn(`No layout defined for error code: ${e}`),!1;this.debug&&zt.log(`Loading error layout: ${i} for code: ${e}`);const l=await this.layoutLoader.loadLayout(this.templateId,i);if(!l)return this.debug&&zt.error(`Failed to load error layout: ${i}`),!1;this.debug&&zt.log("Error layout loaded:",l);let u={};const d=l.data_sources||[];if(d.length>0){this.debug&&zt.log("Fetching data sources:",d.map(S=>S.id));const m=d.filter(S=>S.loading_strategy==="blocking"),b=d.filter(S=>!S.loading_strategy||S.loading_strategy==="progressive"),v=[...m,...b];if(v.length>0)try{u=await this.dataSourceManager.fetchDataSources(v,{},new URLSearchParams),this.debug&&zt.log("Data sources fetched:",Object.keys(u))}catch(S){zt.error("Failed to fetch data sources:",S)}}const f={};d.length>0&&(this.processInitOptions(d,u,f),this.debug&&zt.log("initOptions processed:",{globalKeys:Object.keys(this.globalState),localKeys:Object.keys(f)}));const g={...u,errorCode:e,_global:{...this.globalState},_local:{...f}};return await this.renderFunction({containerId:a,layoutJson:l,dataContext:g,translationContext:{templateId:this.templateId,locale:this.locale}}),this.debug&&zt.log(`Error page ${e} rendered successfully`),!0}catch(r){return zt.error(`Failed to render error page ${e}:`,r),!1}}processInitOptions(e,a,r){for(const i of e){const l=a[i.id];if(!l)continue;const u=l?.data??l;if(i.initLocal){if(typeof i.initLocal=="string")r[i.initLocal]=u,zt.log(`initLocal: ${i.id}.data -> _local.${i.initLocal}`);else if(typeof i.initLocal=="object"&&"key"in i.initLocal){const{key:d,path:f}=i.initLocal;r[d]=f?this.getValueByPath(u,f):u,zt.log(`initLocal: ${i.id}.data${f?"."+f:""} -> _local.${d}`)}}if(i.initGlobal){const d=Array.isArray(i.initGlobal)?i.initGlobal:[i.initGlobal];for(const f of d)if(typeof f=="string")this.globalState[f]=u,zt.log(`initGlobal: ${i.id}.data -> _global.${f}`);else if(typeof f=="object"&&f!==null&&"key"in f){const{key:g,path:m}=f;this.globalState[g]=m?this.getValueByPath(u,m):u,zt.log(`initGlobal: ${i.id}.data${m?"."+m:""} -> _global.${g}`)}}}}getValueByPath(e,a){return a.split(".").reduce((r,i)=>r?.[i],e)}updateGlobalState(e){this.globalState={...this.globalState,...e}}updateLocale(e){this.locale=e,this.debug&&zt.log("Locale updated:",e)}isConfigLoaded(){return this.configLoaded}async hasErrorLayout(e){const a=await this.loadConfig();return a?!!(a.layouts[e]||a.layouts[String(e)]):!1}clearConfigCache(){this.errorConfig=null,this.configLoaded=!1,this.debug&&zt.log("Config cache cleared")}}const $t=ct("ModuleAssetLoader");class q_{constructor(){$(this,"loadedAssets",new Map);$(this,"loadingPromises",new Map);$(this,"failedJsAssets",new Set)}hasFailedJsAssets(){return this.failedJsAssets.size>0}getFailedJsAssets(){return[...this.failedJsAssets]}async loadActiveExtensionAssets(e){if(!e||e.length===0){$t.log("No module assets to load");return}const a=[...e].sort((d,f)=>d.priority-f.priority);$t.log("Loading module assets:",a.map(d=>d.identifier));const r=a.filter(d=>d.css).map(d=>this.loadCSS(d.identifier,d.css)),i=a.filter(d=>d.js).map(d=>this.loadJS(d.identifier,d.js)),l=await Promise.allSettled([...r,...i]),u=l.filter(d=>d.status==="rejected");if(u.length>0){$t.warn(`Some module assets failed to load (${u.length}/${l.length}); continuing with the rest`,this.getFailedJsAssets());return}$t.log("All module assets loaded successfully")}async loadBundle(e,a,r){const i=[];if(r&&i.push(this.loadBundleCss(e,r)),a&&i.push(this.loadBundleJs(e,a)),i.length===0){$t.log(`No bundle assets to load for: ${e}`);return}await Promise.all(i)}async loadBundleCss(e,a){const r=`ext-bundle-css-${e}`;if(document.getElementById(r)){$t.log(`Bundle CSS already loaded: ${e}`);return}return new Promise(i=>{const l=document.createElement("link");l.rel="stylesheet",l.href=a,l.id=r,l.onload=()=>{$t.log(`Bundle CSS loaded: ${e}`),this.registerLoadedAsset(`bundle-${e}`,{type:"css",element:l}),i()},l.onerror=()=>{$t.warn(`Failed to load bundle CSS: ${e} (${a})`),i()},document.head.appendChild(l)})}async loadBundleJs(e,a){const r=`ext-bundle-js-${e}`;if(document.getElementById(r)){$t.log(`Bundle JS already loaded: ${e}`);return}const i=this.loadingPromises.get(r);if(i)return $t.log(`Bundle JS already loading: ${e}`),i;const l=Yg(a,{id:r},{label:`bundle JS: ${e}`}).then(()=>{$t.log(`Bundle JS loaded: ${e}`);const u=document.getElementById(r);u&&this.registerLoadedAsset(`bundle-${e}`,{type:"js",element:u}),this.loadingPromises.delete(r)}).catch(u=>{throw $t.warn(`Failed to load bundle JS: ${e} (${a})`,u),this.failedJsAssets.add(e),this.loadingPromises.delete(r),u});return this.loadingPromises.set(r,l),l}async loadCSS(e,a){const r=`module-css-${e}`;if(document.getElementById(r)){$t.log(`CSS already loaded: ${e}`);return}return new Promise((i,l)=>{const u=document.createElement("link");u.rel="stylesheet",u.href=a,u.id=r,u.onload=()=>{$t.log(`CSS loaded: ${e}`),this.registerLoadedAsset(e,{type:"css",element:u}),i()},u.onerror=()=>{$t.warn(`Failed to load CSS: ${e} (${a})`),i()},document.head.appendChild(u)})}async loadJS(e,a){const r=`module-js-${e}`;if(document.getElementById(r)){$t.log(`JS already loaded: ${e}`);return}const i=this.loadingPromises.get(e);if(i)return $t.log(`JS already loading: ${e}`),i;const l=Yg(a,{id:r},{label:`JS: ${e}`}).then(()=>{$t.log(`JS loaded: ${e}`);const u=document.getElementById(r);u&&this.registerLoadedAsset(e,{type:"js",element:u}),this.loadingPromises.delete(e)}).catch(u=>{throw $t.warn(`Failed to load JS: ${e} (${a})`,u),this.failedJsAssets.add(e),this.loadingPromises.delete(e),u});return this.loadingPromises.set(e,l),l}registerLoadedAsset(e,a){const r=this.loadedAssets.get(e)||[];r.push(a),this.loadedAssets.set(e,r)}unloadExtensionAsset(e){const a=this.loadedAssets.get(e);if(!a||a.length===0){$t.log(`No assets to unload for: ${e}`);return}a.forEach(r=>{r.element.parentNode&&(r.element.parentNode.removeChild(r.element),$t.log(`${r.type.toUpperCase()} unloaded: ${e}`))}),this.loadedAssets.delete(e),$t.log(`All assets unloaded for: ${e}`)}unloadAllAssets(){Array.from(this.loadedAssets.keys()).forEach(a=>{this.unloadExtensionAsset(a)}),$t.log("All module assets unloaded")}isLoaded(e){return this.loadedAssets.has(e)}getLoadedModules(){return Array.from(this.loadedAssets.keys())}}let cf=null;function uf(){return cf||(cf=new q_),cf}function G_(){if(typeof window>"u")return[];const o=window.G7Config;if(!o?.moduleAssets)return[];const e=[];for(const[a,r]of Object.entries(o.moduleAssets)){const i=r;e.push({identifier:a,js:i.js?wr(i.js):i.js,css:i.css?wr(i.css):i.css,priority:i.priority,external:i.external})}return e}function V_(){if(typeof window>"u")return null;const o=window.G7Config;if(!o?.bundleUrls)return null;const e=o.bundleUrls;return{moduleJs:e.moduleJs?wr(e.moduleJs):e.moduleJs,moduleCss:e.moduleCss?wr(e.moduleCss):e.moduleCss,pluginJs:e.pluginJs?wr(e.pluginJs):e.pluginJs,pluginCss:e.pluginCss?wr(e.pluginCss):e.pluginCss}}function F_(){if(typeof window>"u")return[];const o=window.G7Config;if(!o?.pluginAssets)return[];const e=[];for(const[a,r]of Object.entries(o.pluginAssets)){const i=r;e.push({identifier:a,js:i.js?wr(i.js):i.js,css:i.css?wr(i.css):i.css,priority:i.priority,external:i.external})}return e}const df=ct("SystemBannerManager");class pc{static show(e){this.banners.set(e.id,e),this.render(),df.log(`Banner shown: ${e.id}`)}static hide(e){this.banners.delete(e)&&(this.render(),df.log(`Banner hidden: ${e}`))}static hideAll(){this.banners.clear(),this.render(),df.log("All banners hidden")}static detectLocale(){try{const a=window.G7Core;if(a?.locale?.current)return a.locale.current()}catch{}return(navigator.language||"ko").split("-")[0]}static resolveMessage(e,a){return typeof e=="string"?e:e[a]||e.en||e.ko||Object.values(e)[0]||""}static render(){if(typeof document>"u")return;let e=document.getElementById(this.containerId);if(this.banners.size===0){e&&(e.remove(),this.adjustAppPadding(0));return}e||(e=document.createElement("div"),e.id=this.containerId,e.style.cssText="position:fixed;top:0;left:0;right:0;z-index:99999;",document.body.prepend(e));const a=Array.from(this.banners.values()).sort((i,l)=>(i.order??0)-(l.order??0)),r=this.detectLocale();e.innerHTML=a.map(i=>{const l=this.resolveMessage(i.message,r),u=i.background||"#f59e0b",d=i.color||"white";return`
${l}
`}).join(""),requestAnimationFrame(()=>{e&&this.adjustAppPadding(e.offsetHeight)})}static adjustAppPadding(e){const a=document.getElementById("app");a&&(a.style.paddingTop=e>0?`${e}px`:"")}}$(pc,"banners",new Map),$(pc,"containerId","g7-system-banners");const B=ct("TemplateApp");function sy(o){const e={};for(const a of o.keys()){if(a in e)continue;const r=o.getAll(a);r.length>1?e[a]=r:r.length===1&&(a.endsWith("[]")?e[a]=r:e[a]=r[0])}return e}const Ca=class Ca{constructor(e){$(this,"router",null);$(this,"layoutLoader",null);$(this,"errorPageHandler",null);$(this,"config");$(this,"globalState");$(this,"globalStateListeners",new Set);$(this,"currentRouteChangeId",0);$(this,"currentDataSources",[]);$(this,"currentRawDataSources",[]);$(this,"currentRouteParams",{});$(this,"currentQueryParams",new URLSearchParams);$(this,"currentFetchedData",{});$(this,"currentLayoutName","");$(this,"templateErrorHandling",null);$(this,"currentWebSocketSubscriptions",[]);$(this,"extensionCacheVersion",0);$(this,"currentGlobalHeaders",[]);$(this,"transitionOverlayEl",null);$(this,"skeletonOverlayRoot",null);$(this,"skeletonOverlayContainer",null);$(this,"_spinnerState",null);$(this,"modalDataSources",new Map);this.globalState={sidebarOpen:!1},this.loadG7Config(),this.migrateLocaleStorage();const a=this.loadLocaleFromStorage(),r=a||e.locale||"ko";this.config={...e,locale:r},!a&&e.locale&&this.saveLocaleToStorage(e.locale)}loadG7Config(){if(typeof window<"u"&&window.G7Config){const e=window.G7Config;e.settings&&(this.globalState.settings=e.settings,B.log("Loaded settings from G7Config:",Object.keys(e.settings)),e.settings.upload&&(this.globalState.uploadSettings=e.settings.upload)),e.plugins&&(this.globalState.plugins=e.plugins,B.log("Loaded plugin settings from G7Config:",Object.keys(e.plugins))),e.modules&&(this.globalState.modules=e.modules,B.log("Loaded module settings from G7Config:",Object.keys(e.modules))),e.appConfig&&(this.globalState.appConfig=e.appConfig,B.log("Loaded appConfig from G7Config:",Object.keys(e.appConfig)))}}resolveRouteExpressions(e){const a=new wn,r={_global:this.globalState};return e.map(i=>{const l={...i};if(l.path&&l.path.includes("{{")){const u=l.path;l.path=a.resolveBindings(l.path,r),l.path=l.path.replace(/\/\/+/g,"/")||"/",l.path.includes("{{")&&(B.warn("Route expression resolution failed, using fallback:",u),l.path=u.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/")}if(l.redirect&&l.redirect.includes("{{")){const u=l.redirect;l.redirect=a.resolveBindings(l.redirect,r),l.redirect=l.redirect.replace(/\/\/+/g,"/")||"/",l.redirect.includes("{{")&&(B.warn("Route redirect expression resolution failed:",u),l.redirect=u.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/")}return l})}migrateLocaleStorage(){const e=["locale","g7_template_locale"];for(const a of e)try{const r=localStorage.getItem(a);r&&r!==localStorage.getItem(Ca.LOCALE_STORAGE_KEY)&&(localStorage.setItem(Ca.LOCALE_STORAGE_KEY,r),B.log(`Migrated locale from '${a}' to '${Ca.LOCALE_STORAGE_KEY}'`)),localStorage.removeItem(a)}catch(r){B.warn(`Failed to migrate locale key '${a}':`,r)}}async init(){try{Fs.getInstance().setDebug(this.config.debug),B.log("Initializing with config:",this.config),US();const e=da.getInstance(),a=ha.getInstance(),r=this.loadCacheVersionFromStorage()||0,[i,l,u,d,f]=await Promise.all([_o({templateId:this.config.templateId,templateType:this.config.templateType,locale:this.config.locale,debug:this.config.debug,cacheVersion:r}),e.loadComponents(this.config.templateId,this.config.templateType),Al(La(`/api/templates/${this.config.templateId}/routes`,"json",r>0?r:null),{label:"routes.json"}).then(A=>{if(!A.ok)throw new Error(`Failed to load routes: ${A.statusText}`);return A.json()}).then(A=>{if(!A.success)throw new Error("Failed to load routes from API");return A.data}).catch(A=>{throw B.error("Error loading routes:",A),A}),a.preloadAuth(this.config.templateType==="admin"?"admin":"user"),fetch(La(`/api/templates/${this.config.templateId}/config`,"json")).then(A=>A.ok?A.json():null).then(A=>!A?.success||!A?.data?null:A.data).catch(A=>(B.warn("Error loading template config:",A),null))]);if(B.log("Template Engine initialized"),B.log("ComponentRegistry loaded"),B.log("Routes data loaded"),B.log("User info preloaded"),B.log("Template config loaded:",f),f?.cache_version!==void 0){const A=this.loadCacheVersionFromStorage();if(this.extensionCacheVersion=f.cache_version,this.saveCacheVersionToStorage(this.extensionCacheVersion),B.log("Extension cache version:",this.extensionCacheVersion),A!==null&&A!==this.extensionCacheVersion){B.log("Cache version changed, reloading routes...");const T=await Al(La(`/api/templates/${this.config.templateId}/routes`,"json",this.extensionCacheVersion),{label:"routes.json (reload)"}).then(L=>{if(!L.ok)throw new Error(`Failed to reload routes: ${L.statusText}`);return L.json()}).then(L=>{if(!L.success)throw new Error("Failed to reload routes from API");return L.data});Array.isArray(T.routes)&&(T.routes=this.resolveRouteExpressions(T.routes),Object.assign(u,T),B.log("Routes reloaded with new cache version"));try{const{TranslationEngine:L}=await Promise.resolve().then(()=>ep),M=L.getInstance();M.setCacheVersion(this.extensionCacheVersion);const R=this.config.locale||"ko",D="en";await M.loadTranslations(this.config.templateId,R,"/api",!0),R!==D&&await M.loadTranslations(this.config.templateId,D,"/api",!0),B.log("Translations reloaded with new cache version")}catch(L){B.error("Failed to reload translations:",L)}}}f?.errorHandling&&(this.templateErrorHandling=f.errorHandling,pa().setTemplateConfig(this.templateErrorHandling),B.log("Template errorHandling registered:",this.templateErrorHandling)),a.on("logout",()=>{B.log("User logged out")}),a.on("authStateChange",A=>{B.log("Auth state changed:",A)}),B.log("AuthManager event handlers registered");const g=$a(),m=this.config.templateType==="admin"?"admin":"user",b=a.getConfig(m);g.setOnUnauthorized(()=>{B.log("Unauthorized - redirecting to login page"),g.removeToken();const A=window.location.pathname+window.location.search,T=a.getLoginRedirectUrl(m,A,"session_expired");window.location.href=T}),B.log("ApiClient onUnauthorized callback registered"),this.layoutLoader=new ef(e),this.extensionCacheVersion>0&&this.layoutLoader.setCacheVersion(this.extensionCacheVersion),B.log("LayoutLoader initialized:",this.layoutLoader);const v=new va({onUnauthorized:()=>{B.warn("Unauthorized request in error page")}});if(this.errorPageHandler=new P_({templateId:this.config.templateId,layoutLoader:this.layoutLoader,locale:this.config.locale,debug:this.config.debug,renderFunction:os,dataSourceManager:v,globalState:this.globalState}),B.log("ErrorPageHandler initialized with DataSourceManager"),await this.handleServerError()){B.log("Server error handled, skipping normal initialization");return}if(this.router=new U_(this.config.templateId),Array.isArray(u.routes)){const A=this.resolveRouteExpressions(u.routes);this.router.setRoutes(A)}else throw new Error("Invalid routes data format");B.log("Router initialized:",this.router),B.log("Routes set:",this.router.getRoutes());const{getActionDispatcher:S}=await Promise.resolve().then(()=>za),E=S();if(E&&(E.setDefaultContext({navigate:A=>this.router?.navigate(A)}),E.setGlobalStateUpdater((A,T)=>this.setGlobalState(A,T)),B.log("Navigate function and setGlobalState injected to ActionDispatcher")),await this.loadExtensionAssets(),this.reinitializeTemplateHandlers(),this.router.on("routeChange",A=>this.handleRouteChange(A)),this.router.on("routeNotFound",A=>this.handleRouteNotFound(A)),typeof window<"u"&&iy(window.location.pathname)){B.log("Layout editor mode detected — skipping router match"),await os({containerId:"app",layoutJson:{components:[]},dataContext:{},translationContext:{templateId:this.config.templateId,locale:this.config.locale}}),B.log("Template App initialized in layout editor mode");return}this.router.navigateToCurrentPath(),B.log("Template App initialized successfully")}catch(e){B.error("Initialization failed:",e),this.showInitError(e)}}async loadExtensionAssets(){try{const e=uf(),a=V_();if(!a){await this.loadExtensionAssetsIndividually();return}await e.loadBundle("module",a.moduleJs,a.moduleCss),await e.loadBundle("plugin",a.pluginJs,a.pluginCss),B.log("Extension bundle assets loaded successfully")}catch(e){B.warn("Failed to load extension assets:",e)}}async loadExtensionAssetsIndividually(){const e=uf(),a=G_();a.length>0&&(B.log("Loading module assets (individual fallback):",a.map(i=>i.identifier)),await e.loadActiveExtensionAssets(a));const r=F_();r.length>0&&(B.log("Loading plugin assets (individual fallback):",r.map(i=>i.identifier)),await e.loadActiveExtensionAssets(r))}async handleRouteChange(e){const a=++this.currentRouteChangeId;window.__g7ForcedLocalFields=void 0,window.__g7ActionContext=void 0,window.__g7PendingLocalState=void 0,window.__g7LastSetLocalSnapshot=void 0,window.__g7SetLocalOverrideKeys=void 0,window.__g7SequenceLocalSync=void 0,window.__g7AutoBindingPaths=new Map;try{if(B.log("Route changed:",e,"requestId:",a),!this.layoutLoader)throw new Error("LayoutLoader is not initialized");if(!e.layout)throw new Error("Route layout is not defined");let r=e.layout;const i=r==="__preview__";i&&e.params?.token&&(r=`__preview__/${e.params.token}`);const l=await this.layoutLoader.loadLayout(this.config.templateId,r);if(a!==this.currentRouteChangeId){B.log("Route change cancelled (newer request exists):",a);return}B.log("Layout loaded:",l);const u=pa();l.errorHandling?(u.setLayoutConfig(l.errorHandling),B.log("Layout errorHandling registered:",l.errorHandling)):u.clearLayoutConfig();const d=l.data_sources||[],f=e.query||{},g=new URLSearchParams;for(const[te,he]of Object.entries(f))if(Array.isArray(he))for(const x of he)g.append(te,x);else g.set(te,he);const m={route:e.params||{},query:f,_global:this.globalState};l.scripts&&Array.isArray(l.scripts)&&await this.loadLayoutScripts(l.scripts,m);const{DataSourceManager:b,getActionDispatcher:v}=await Promise.resolve().then(()=>za),S=new b;if(i){const te=v();te&&te.setPreviewMode(!0),this.setGlobalState({__isPreview:!0}),pc.show({id:"preview-mode",message:{ko:"⚠ 미리보기 모드 — 페이지 이동이 비활성화됩니다",en:"⚠ Preview Mode — Navigation is disabled"},background:"linear-gradient(90deg, #f59e0b, #d97706)",color:"white"}),B.log("Preview mode activated")}else{const te=v();te?.isPreviewMode()&&(te.setPreviewMode(!1),pc.hide("preview-mode"))}if(this.currentGlobalHeaders=l.globalHeaders||[],this.currentGlobalHeaders.length>0){S.setGlobalHeaders(this.currentGlobalHeaders);const te=v();te&&te.setGlobalHeaders(this.currentGlobalHeaders),B.log("globalHeaders set:",this.currentGlobalHeaders.map(he=>he.pattern))}if(l.named_actions&&Object.keys(l.named_actions).length>0){const te=v();te&&te.setNamedActions(l.named_actions)}const E=S.filterByCondition(d,m);d.length!==E.length&&B.log("Data sources filtered by condition:",{before:d.map(te=>te.id),after:E.map(te=>te.id)});const A=E.filter(te=>te.loading_strategy==="blocking"),T=E.filter(te=>(te.loading_strategy||"progressive")!=="blocking"&&te.type!=="websocket"),L=Array.isArray(l.transition_overlay?.wait_for)?l.transition_overlay.wait_for:[],M=L.length>0&&E.some(te=>L.includes(te.id)&&te.type!=="websocket"&&(te.loading_strategy||"progressive")!=="background");if((A.length>0||M)&&l.transition_overlay){const te=typeof l.transition_overlay=="boolean"?{enabled:l.transition_overlay,style:"opaque"}:l.transition_overlay;te.enabled&&te.style==="skeleton"&&te.skeleton?.component&&te.target?this.renderSkeletonOverlay(te.target,te.skeleton,l,te.fallback_target):te.enabled&&te.style==="spinner"&&te.target&&this.renderSpinnerOverlay(te.target,te.spinner,te.fallback_target)}let R={},D={},U={},j={};this.currentWebSocketSubscriptions.length>0&&(B.log("Unsubscribing previous WebSocket subscriptions:",this.currentWebSocketSubscriptions),S.unsubscribeWebSockets(this.currentWebSocketSubscriptions),this.currentWebSocketSubscriptions=[]),this.currentDataSources=E,this.currentRawDataSources=d,this.currentRouteParams=e.params||{},this.currentQueryParams=g,B.log(`handleRouteChange #${a} - queryObject:`,f),B.log(`handleRouteChange #${a} - queryParams:`,g.toString()),A.length>0&&(B.log("Fetching blocking data sources:",A.map(he=>he.id)),(await S.fetchDataSourcesWithResults(A,e.params||{},g)).forEach(he=>{if(he.state==="success"&&he.data!==void 0)R[he.id]=he.data;else if(he.state==="error"&&he.error){const x=he.error,K=x.response?.data?.message;D[he.id]={message:K||he.error.message,status:x.response?.status||x.status}}}),this.processInitOptions(A,R,U,j),this.currentFetchedData={...R},B.log("Blocking data loaded:",Object.keys(R)),Object.keys(D).length>0&&B.log("Data source errors:",D),Object.keys(U).length>0&&B.log("Local state init (blocking):",Object.keys(U)),Object.keys(j).length>0&&B.log("Isolated state init (blocking):",Object.keys(j)));const P=T.length>0;if(P&&(Na.setPending(!0),B.log("Transition started before rendering")),a!==this.currentRouteChangeId){B.log("Route change cancelled after blocking data (newer request exists):",a);return}const{getState:X}=await Promise.resolve().then(()=>za),ge=X().currentDataContext||{},Ee=T.map(te=>te.id),Ce={};if(P){Ee.forEach(he=>{ge[he]!==void 0?Ce[he]=ge[he]:Ce[he]=void 0});const te=Object.keys(Ce).filter(he=>Ce[he]!==void 0);te.length>0&&B.log("Preserving previous progressive data:",te),B.log("Progressive data sources initialized:",Ee)}const $e=l.defines||{},Pe={...Ce,...e.params,...R,route:{...e.params||{},path:e.path},query:f,_global:{...this.globalState},_globalSetState:te=>this.setGlobalState(te),_dataSourceErrors:Object.keys(D).length>0?D:void 0,_localInit:Object.keys(U).length>0?U:void 0,_isolatedInit:Object.keys(j).length>0?j:void 0,_defines:Object.keys($e).length>0?$e:void 0};if(l.computed&&Object.keys(l.computed).length>0){const te=this.calculateComputed(l.computed,Pe);Object.keys(te).length>0&&(Pe._computed=te,this.globalState._computed=te,B.log("Computed values calculated:",Object.keys(te))),Pe._computedDefinitions=l.computed}const Xe=l.layout_name||e.layout;this.currentLayoutName!==""&&this.currentLayoutName!==Xe&&(B.log("_local reset due to layout change:",{from:this.currentLayoutName,to:Xe}),this.globalState._local={},nC()),this.currentLayoutName=Xe;const Q=l.initLocal||l.state;if(Q&&Object.keys(Q).length>0){this.globalState._local||(this.globalState._local={});for(const[te,he]of Object.entries(Q))this.globalState._local[te]===void 0&&(this.globalState._local[te]=JSON.parse(JSON.stringify(he)));Pe._local={...this.globalState._local},B.log("initLocal applied to _local:",Object.keys(Q))}if(l.initGlobal&&Object.keys(l.initGlobal).length>0){for(const[te,he]of Object.entries(l.initGlobal))this.globalState[te]===void 0&&(this.globalState[te]=JSON.parse(JSON.stringify(he)));B.log("initGlobal applied to _global:",Object.keys(l.initGlobal))}if(l.initIsolated&&Object.keys(l.initIsolated).length>0){for(const[te,he]of Object.entries(l.initIsolated))j[te]===void 0&&(j[te]=JSON.parse(JSON.stringify(he)));B.log("initIsolated applied:",Object.keys(l.initIsolated))}Pe._global={...this.globalState,layoutWarnings:l.warnings||[]};const fe=l.initActions||l.init_actions;if(fe&&fe.length>0){await this.executeInitActions(fe,Pe),B.log("initActions executed before render");const te=this.globalState;if(te._local){if(Object.keys(U).length>0){for(const[he,x]of Object.entries(U))te._local[he]!==void 0?te._local[he]=this.deepMerge(te._local[he],x):te._local[he]=x;B.log("localInit merged into _local after initActions:",Object.keys(U))}Pe._local=te._local,B.log("_local merged into dataContext:",te._local)}if(Pe._global={...this.globalState,layoutWarnings:l.warnings||[]},B.log("_global merged into dataContext after initActions"),l.computed&&Object.keys(l.computed).length>0){const he=this.calculateComputed(l.computed,Pe);Object.keys(he).length>0&&(Pe._computed=he,this.globalState._computed=he,B.log("Computed values recalculated after init_actions:",Object.keys(he)))}if(Object.keys(this.currentFetchedData).length>0){for(const[he,x]of Object.entries(this.currentFetchedData))Pe[he]=x;B.log("Fetched data sources merged into dataContext after initActions:",Object.keys(this.currentFetchedData))}}if(l.transition_overlay&&!this.skeletonOverlayContainer&&this.showTransitionOverlay(l.transition_overlay,l),await os({containerId:"app",layoutJson:l,dataContext:Pe,translationContext:{templateId:this.config.templateId,locale:this.config.locale}}),B.log("Initial render complete with blocking data"),this.reattachSpinnerOverlay(),T.length>0){if(a!==this.currentRouteChangeId){B.log("Route change cancelled before progressive fetch (newer request exists):",a),Na.setPending(!1),this.hideTransitionOverlay();return}B.log("Fetching progressive/background data sources:",T.map(x=>x.id));const{updateTemplateData:te,getState:he}=await Promise.resolve().then(()=>za);try{const x=T.map(async K=>{try{const de=(await S.fetchDataSourcesWithResults([K],e.params||{},g,this.globalState))[0];if(!de){B.log(`Data source ${K.id} skipped (no fetch result)`);return}if(a!==this.currentRouteChangeId){B.log(`Data source ${K.id} fetch cancelled (newer request exists)`);return}if(de.state==="success"&&de.data!==void 0){B.log(`Progressive data source loaded: ${K.id}`),this.currentFetchedData[K.id]=de.data;const se={};this.processInitOptions([K],{[K.id]:de.data},se);const me=he();if(me.bindingEngine){const ve=[K.id];K.initGlobal&&ve.push("_global"),K.initLocal&&ve.push("_local"),me.bindingEngine.invalidateCacheByKeys(ve)}const Ne={[K.id]:de.data};Object.keys(se).length>0&&(Ne._localInit=se,Object.assign(U,se)),K.initGlobal&&(Ne._global={...this.globalState}),te(Ne)}else if(de.state==="error"&&de.error){const se=de.error,me=se.response?.data?.message;D[K.id]={message:me||de.error.message,status:se.response?.status||se.status},B.log(`Progressive data source error: ${K.id}`,D[K.id]),te({[K.id]:null,_dataSourceErrors:{...D}})}}catch(re){B.error(`Failed to fetch data source: ${K.id}`,re)}});if(await Promise.all(x),a!==this.currentRouteChangeId){B.log("Route change cancelled after progressive fetch (newer request exists):",a);return}B.log("All progressive data sources loaded")}finally{Na.setPending(!1),this.hideTransitionOverlay()}}else this.hideTransitionOverlay();const ye=E.filter(te=>te.type==="websocket");if(ye.length>0){B.log("Subscribing WebSocket data sources:",ye.map(K=>K.id));const{updateTemplateData:te,getState:he}=await Promise.resolve().then(()=>za),x={...this.currentFetchedData,...e.params,route:{...e.params||{},path:e.path},query:f,_global:{...this.globalState}};B.log("WebSocket binding context keys:",Object.keys(x)),this.currentWebSocketSubscriptions=S.subscribeWebSockets(E,(K,re)=>{B.log(`WebSocket data received for: ${K}`,re),this.currentFetchedData[K]=re;const de=E.find(ve=>ve.id===K),se=he();if(se.bindingEngine){const ve=[K];de?.initGlobal&&ve.push("_global"),de?.initLocal&&ve.push("_local"),se.bindingEngine.invalidateCacheByKeys(ve)}te({[K]:re});const Ne=E.find(ve=>ve.type==="websocket"&&(ve.target_source||ve.id)===K)?.onReceive;Array.isArray(Ne)&&Ne.length>0&&window.G7Core?.dispatch&&(async()=>{for(const He of Ne)try{const Ae=this.getActionDispatcher?.();Ae&&await Ae.dispatchAction(He,{navigate:this.getRouter?.()?(Et,Rt)=>this.getRouter().navigate(Et,Rt):void 0,setState:Et=>this.setGlobalState(Et),state:this.globalState,data:{...this.globalState,$args:[re],$event:re},_isDispatchFallbackContext:!0})}catch(Ae){B.error(`WebSocket onReceive action failed for ${K}:`,Ae)}})()},x),B.log("WebSocket subscriptions established:",this.currentWebSocketSubscriptions)}B.log("Layout rendered successfully")}catch(r){B.error("Route change handling failed:",r),this.hideTransitionOverlay(),this.showRouteError(r)}}processInitOptions(e,a,r,i){e.some(u=>u.refetchOnMount===!0&&u.initLocal)&&(r._forceLocalInit=Date.now(),B.log("refetchOnMount detected, forcing local state init")),e.forEach(u=>{const d=a[u.id];if(!d)return;const f=d.data??d;if(u.initLocal){if(typeof u.initLocal=="string"){let g=f;if(u.initLocalDefaults&&typeof u.initLocalDefaults=="object"){const b=this.evaluateDefaults(u.initLocalDefaults,a);g={...b,...f},B.log(`initLocalDefaults applied for ${u.initLocal}:`,Object.keys(b))}const m=this.globalState._local?.[u.initLocal];m!==void 0&&typeof m=="object"&&typeof g=="object"?(r[u.initLocal]=this.deepMerge(m,g),B.log(`initLocal (merged): ${u.id}.data -> _local.${u.initLocal}`)):(r[u.initLocal]=g,B.log(`initLocal: ${u.id}.data -> _local.${u.initLocal}`))}else if(typeof u.initLocal=="object"&&u.initLocal.key){const{key:g,path:m}=u.initLocal;let b=m?this.extractValueByPathOrExpression(f,m,u.id):f;if(u.initLocalDefaults&&typeof u.initLocalDefaults=="object"){const S=this.evaluateDefaults(u.initLocalDefaults,a);b={...S,...b},B.log(`initLocalDefaults applied for ${g}:`,Object.keys(S))}const v=this.globalState._local?.[g];v!==void 0&&typeof v=="object"&&typeof b=="object"?(r[g]=this.deepMerge(v,b),B.log(`initLocal (merged): ${u.id}.data${m?"."+m:""} -> _local.${g}`)):(r[g]=b,B.log(`initLocal: ${u.id}.data${m?"."+m:""} -> _local.${g}`))}else if(typeof u.initLocal=="object"){const g=u.initLocal._merge||"deep",m=this.flattenNestedObjectToMappings(u.initLocal);for(const{targetPath:b,sourcePath:v}of m){const S=this.extractValueByPathOrExpression(f,v,u.id);if(b.includes(".")){const E=b.split(".")[0];r[E]===void 0&&this.globalState._local?.[E]!==void 0&&(r[E]=JSON.parse(JSON.stringify(this.globalState._local[E]))),this.setValueAtPath(r,b,S,g),B.log(`initLocal map (${g}): ${u.id} ${v} -> _local.${b}`)}else{const E=this.globalState._local?.[b];g==="replace"?(r[b]=S,B.log(`initLocal map (replace): ${u.id} ${v} -> _local.${b}`)):g==="shallow"?E!==void 0&&typeof E=="object"&&typeof S=="object"?(r[b]={...E,...S},B.log(`initLocal map (shallow): ${u.id} ${v} -> _local.${b}`)):(r[b]=S,B.log(`initLocal map: ${u.id} ${v} -> _local.${b}`)):E!==void 0&&typeof E=="object"&&typeof S=="object"?(r[b]=this.deepMerge(E,S),B.log(`initLocal map (deep): ${u.id} ${v} -> _local.${b}`)):(r[b]=S,B.log(`initLocal map: ${u.id} ${v} -> _local.${b}`))}}}}if(u.initGlobal)if(typeof u.initGlobal=="object"&&!Array.isArray(u.initGlobal)&&!("key"in u.initGlobal))for(const[m,b]of Object.entries(u.initGlobal)){if(typeof b!="string"){B.warn(`initGlobal map value must be string, got ${typeof b} for key ${m}`);continue}const v=this.extractValueByPathOrExpression(f,b,u.id),S=this.globalState[m];S!==void 0&&typeof S=="object"&&typeof v=="object"?(this.globalState[m]=this.deepMerge(S,v),B.log(`initGlobal map (merged): ${u.id} ${b} -> _global.${m}`)):(this.globalState[m]=v,B.log(`initGlobal map: ${u.id} ${b} -> _global.${m}`))}else{const m=Array.isArray(u.initGlobal)?u.initGlobal:[u.initGlobal];for(const b of m)if(typeof b=="string"){const v=this.globalState[b];v!==void 0&&typeof v=="object"&&typeof f=="object"?(this.globalState[b]=this.deepMerge(v,f),B.log(`initGlobal (merged): ${u.id}.data -> _global.${b}`)):(this.globalState[b]=f,B.log(`initGlobal: ${u.id}.data -> _global.${b}`))}else if(typeof b=="object"&&b.key){const{key:v,path:S}=b,E=S?this.extractValueByPathOrExpression(f,S,u.id):f,A=this.globalState[v];A!==void 0&&typeof A=="object"&&typeof E=="object"?(this.globalState[v]=this.deepMerge(A,E),B.log(`initGlobal (merged): ${u.id}.data${S?"."+S:""} -> _global.${v}`)):(this.globalState[v]=E,B.log(`initGlobal: ${u.id}.data${S?"."+S:""} -> _global.${v}`))}}if(i&&u.initIsolated){if(typeof u.initIsolated=="string"){const g=i[u.initIsolated];g!==void 0&&typeof g=="object"&&typeof f=="object"?(i[u.initIsolated]=this.deepMerge(g,f),B.log(`initIsolated (merged): ${u.id}.data -> _isolated.${u.initIsolated}`)):(i[u.initIsolated]=f,B.log(`initIsolated: ${u.id}.data -> _isolated.${u.initIsolated}`))}else if(typeof u.initIsolated=="object"&&u.initIsolated.key){const{key:g,path:m}=u.initIsolated,b=m?this.extractValueByPathOrExpression(f,m,u.id):f,v=i[g];v!==void 0&&typeof v=="object"&&typeof b=="object"?(i[g]=this.deepMerge(v,b),B.log(`initIsolated (merged): ${u.id}.data${m?"."+m:""} -> _isolated.${g}`)):(i[g]=b,B.log(`initIsolated: ${u.id}.data${m?"."+m:""} -> _isolated.${g}`))}else if(typeof u.initIsolated=="object")for(const[g,m]of Object.entries(u.initIsolated)){if(typeof m!="string"){B.warn(`initIsolated map value must be string, got ${typeof m} for key ${g}`);continue}const b=this.extractValueByPathOrExpression(f,m,u.id),v=i[g];v!==void 0&&typeof v=="object"&&typeof b=="object"?(i[g]=this.deepMerge(v,b),B.log(`initIsolated map (merged): ${u.id} ${m} -> _isolated.${g}`)):(i[g]=b,B.log(`initIsolated map: ${u.id} ${m} -> _isolated.${g}`))}}})}evaluateDefaults(e,a){const r={};for(const[i,l]of Object.entries(e))if(typeof l=="string"&&l.startsWith("{{")&&l.endsWith("}}")){const u=l.slice(2,-2).trim();r[i]=this.evaluateExpression(u,a)}else r[i]=l;return r}evaluateExpression(e,a){try{const r=e.split("??").map(i=>i.trim());for(const i of r){if(/^['"].*['"]$/.test(i))return i.slice(1,-1);if(i==="true")return!0;if(i==="false")return!1;if(/^-?\d+(\.\d+)?$/.test(i))return Number(i);const l=this.getNestedValue(a,i);if(l!=null)return l}return}catch(r){B.warn(`Expression evaluation failed: ${e}`,r);return}}getNestedValue(e,a){const r=a.replace(/\?\./g,".");let i=e;const l=r.split(/\.(?![^\[]*\])/).flatMap(u=>{const d=u.match(/^([^\[]*)((?:\[\d+\])*)$/);if(d){const[,f,g]=d,m=[];f&&m.push(f);const b=g.match(/\[\d+\]/g);return b&&m.push(...b),m}return[u]}).filter(u=>u!=="");for(const u of l){if(i==null)return;if(u.startsWith("[")&&u.endsWith("]")){const d=parseInt(u.slice(1,-1),10);i=i[d]}else i=i[u]}return i}extractValueByPathOrExpression(e,a,r){const i=a.match(/^\{\{(.+)\}\}$/);if(i){const l=i[1].trim(),u=new wn,d={data:e,_global:this.globalState,_local:this.globalState._local||{}};try{const f=u.evaluateExpression(l,d);return B.log(`initLocal/initGlobal expression evaluated: ${a} -> `,f),f}catch(f){B.warn(`initLocal/initGlobal expression evaluation failed for ${r}:`,a,f);return}}return this.getNestedValue(e,a)}async loadLayoutScripts(e,a){const r=[];for(const i of e){if((i.if!==void 0||i.conditions!==void 0)&&!Yi({if:i.if,conditions:i.conditions},a,this.bindingEngine,`script:${i.id}`)){B.log(`Script skipped (condition not met): ${i.id}`);continue}if(document.getElementById(i.id)){B.log(`Script already loaded: ${i.id}`);continue}const u=new Promise((d,f)=>{const g=document.createElement("script");g.src=i.src,g.id=i.id,g.async=i.async??!0,g.onload=()=>{B.log(`Script loaded successfully: ${i.id}`),d()},g.onerror=()=>{B.warn(`Failed to load script: ${i.id} (${i.src})`),d()},document.head.appendChild(g)});r.push(u)}r.length>0&&(await Promise.all(r),B.log(`All scripts loaded: ${e.filter(i=>!document.getElementById(i.id)||r.length>0).map(i=>i.id).join(", ")}`))}evaluateScriptCondition(e,a){try{if(e.startsWith("{{")&&e.endsWith("}}")){const r=e.slice(2,-2).trim();return new Function("ctx",` + `}static renderFromError(e,a,r,i=!1,l,u,d){let f,g;if(a.userMessageKey.startsWith("$t:"))if(u&&l)try{f=u.translate(a.userMessageKey,l)}catch{f=a.userMessageKey.replace("$t:","")}else f=a.userMessageKey.replace("$t:","");else f=a.userMessageKey;if(d){const m=d;m.details?.apiMessage?g=m.details.apiMessage:m.response?.data?.message&&(g=m.response.data.message)}this.render(e,{title:r,message:f,detailMessage:g,icon:a.icon,showStack:a.showStack,stackTrace:a.stack,showReloadButton:a.recoverable,debug:i})}static escapeHtml(e){if(!e)return"";const a=document.createElement("div");return a.textContent=e,a.innerHTML}}const os=ct("Router");class U_{constructor(e){$(this,"routes",[]);$(this,"templateIdentifier");$(this,"eventHandlers",new Map);$(this,"pendingNavigation",null);$(this,"isNavigating",!1);$(this,"handlePopState",()=>{this.navigateToCurrentPath()});this.templateIdentifier=e,this.initPopstateListener()}initPopstateListener(){window.addEventListener("popstate",this.handlePopState)}on(e,a){this.eventHandlers.has(e)||this.eventHandlers.set(e,[]),this.eventHandlers.get(e).push(a)}async emit(e,...a){const r=this.eventHandlers.get(e);r&&await Promise.all(r.map(i=>i(...a)))}async loadRoutes(e){try{const a=e!==void 0&&e>0?e:null,r=await fetch(La(`/api/templates/${this.templateIdentifier}/routes`,"json",a));if(!r.ok)throw new Error(`Failed to load routes: ${r.statusText}`);const i=await r.json();if(!i.success)throw new Error("Failed to load routes from API");if(i.data&&Array.isArray(i.data.routes))this.routes=i.data.routes,os.log(`Loaded ${this.routes.length} routes${e?` (v=${e})`:""}`);else throw new Error("Invalid routes data format")}catch(a){throw os.error("Error loading routes:",a),a}}setRoutes(e){this.routes=e,os.log(`Set ${this.routes.length} routes`)}match(e){const a=this.normalizePathname(e);for(const r of this.routes){const i=this.matchPattern(r.path,a);if(i!==null)return{route:r,params:i}}return null}normalizePathname(e){return e.length>1&&e.endsWith("/")?e.replace(/\/+$/,"")||"/":e}matchPattern(e,a){const r=[];let i=e.replace(/:([^/]+)/g,(f,g)=>(r.push(g),"([^/]+)"));i.startsWith("*/")&&(i="(?:/[^/]+)?"+i.slice(1)),i=i.replace(/\//g,"\\/");const l=new RegExp(`^${i}$`),u=a.match(l);if(!u)return null;const d={};return r.forEach((f,g)=>{d[f]=u[g+1]}),d}getRoutes(){return[...this.routes]}getAuthType(e,a){return e.auth_type?e.auth_type:a.startsWith("/admin")?"admin":"user"}async navigateToCurrentPath(){const e=window.location.pathname,a=window.location.search,r=this.match(e);if(!r){os.warn(`No route matched for path: ${e}`),this.emit("routeNotFound",e);return}if(r.route.redirect){os.log(`Redirecting from ${e} to ${r.route.redirect}`),this.navigate(r.route.redirect);return}if(r.route.auth_required){const u=this.getAuthType(r.route,e),d=ha.getInstance();let f=d.isAuthenticated()&&d.getAuthType()===u;if(f||(f=await d.checkAuth(u)),!f){const g=d.getLoginRedirectUrl(u,e+a);os.log(`Not authenticated, redirecting to: ${g}`),window.location.href=g;return}}const i=new URLSearchParams(a),l={};for(const u of i.keys()){if(u in l)continue;const d=i.getAll(u);d.length>1?l[u]=d:d.length===1&&(u.endsWith("[]")?l[u]=d:l[u]=d[0])}await this.emit("routeChange",{path:e,layout:r.route.layout,endpoint:r.route.endpoint,params:{...r.route.params||{},...r.params},query:l,auth_required:r.route.auth_required,auth_type:r.route.auth_type,meta:r.route.meta})}navigate(e){if(this.isNavigating){this.pendingNavigation=e;return}this.executeNavigation(e)}async executeNavigation(e){this.isNavigating=!0,this.pendingNavigation=null;try{window.history.pushState({},"",e),await this.navigateToCurrentPath()}finally{if(this.isNavigating=!1,this.pendingNavigation){const a=this.pendingNavigation;this.executeNavigation(a)}}}}const B_=/^\/admin\/layout-editor\/([^/?#]+)\/?$/;function iy(o){const e=B_.exec(o);return e?{templateIdentifier:e[1]}:null}const zt=ct("ErrorPageHandler");class P_{constructor(e){$(this,"templateId");$(this,"layoutLoader");$(this,"locale");$(this,"debug");$(this,"renderFunction");$(this,"dataSourceManager");$(this,"globalState");$(this,"errorConfig",null);$(this,"configLoaded",!1);this.templateId=e.templateId,this.layoutLoader=e.layoutLoader,this.locale=e.locale,this.debug=e.debug,this.renderFunction=e.renderFunction,this.dataSourceManager=e.dataSourceManager,this.globalState=e.globalState||{}}async loadConfig(){if(this.configLoaded)return this.errorConfig;try{const e=await fetch(La(`/api/templates/${this.templateId}/config`,"json"));if(!e.ok)return this.debug&&zt.warn("Failed to load template config:",e.statusText),this.configLoaded=!0,null;const a=await e.json();if(!a.success||!a.data)return this.debug&&zt.warn("Invalid template config response"),this.configLoaded=!0,null;const r=a.data;return!r.error_config||!r.error_config.layouts?(this.debug&&zt.warn("No error_config found in template.json"),this.configLoaded=!0,null):(this.errorConfig=r.error_config,this.configLoaded=!0,this.debug&&zt.log("Error config loaded:",this.errorConfig),this.errorConfig)}catch(e){return zt.error("Failed to load error config:",e),this.configLoaded=!0,null}}async renderError(e,a="app"){try{const r=await this.loadConfig();if(!r)return this.debug&&zt.warn("No error config available, cannot render error page"),!1;const i=r.layouts[e]||r.layouts[String(e)];if(!i)return this.debug&&zt.warn(`No layout defined for error code: ${e}`),!1;this.debug&&zt.log(`Loading error layout: ${i} for code: ${e}`);const l=await this.layoutLoader.loadLayout(this.templateId,i);if(!l)return this.debug&&zt.error(`Failed to load error layout: ${i}`),!1;this.debug&&zt.log("Error layout loaded:",l);let u={};const d=l.data_sources||[];if(d.length>0){this.debug&&zt.log("Fetching data sources:",d.map(S=>S.id));const m=d.filter(S=>S.loading_strategy==="blocking"),b=d.filter(S=>!S.loading_strategy||S.loading_strategy==="progressive"),v=[...m,...b];if(v.length>0)try{u=await this.dataSourceManager.fetchDataSources(v,{},new URLSearchParams),this.debug&&zt.log("Data sources fetched:",Object.keys(u))}catch(S){zt.error("Failed to fetch data sources:",S)}}const f={};d.length>0&&(this.processInitOptions(d,u,f),this.debug&&zt.log("initOptions processed:",{globalKeys:Object.keys(this.globalState),localKeys:Object.keys(f)}));const g={...u,errorCode:e,_global:{...this.globalState},_local:{...f}};return await this.renderFunction({containerId:a,layoutJson:l,dataContext:g,translationContext:{templateId:this.templateId,locale:this.locale}}),this.debug&&zt.log(`Error page ${e} rendered successfully`),!0}catch(r){return zt.error(`Failed to render error page ${e}:`,r),!1}}processInitOptions(e,a,r){for(const i of e){const l=a[i.id];if(!l)continue;const u=l?.data??l;if(i.initLocal){if(typeof i.initLocal=="string")r[i.initLocal]=u,zt.log(`initLocal: ${i.id}.data -> _local.${i.initLocal}`);else if(typeof i.initLocal=="object"&&"key"in i.initLocal){const{key:d,path:f}=i.initLocal;r[d]=f?this.getValueByPath(u,f):u,zt.log(`initLocal: ${i.id}.data${f?"."+f:""} -> _local.${d}`)}}if(i.initGlobal){const d=Array.isArray(i.initGlobal)?i.initGlobal:[i.initGlobal];for(const f of d)if(typeof f=="string")this.globalState[f]=u,zt.log(`initGlobal: ${i.id}.data -> _global.${f}`);else if(typeof f=="object"&&f!==null&&"key"in f){const{key:g,path:m}=f;this.globalState[g]=m?this.getValueByPath(u,m):u,zt.log(`initGlobal: ${i.id}.data${m?"."+m:""} -> _global.${g}`)}}}}getValueByPath(e,a){return a.split(".").reduce((r,i)=>r?.[i],e)}updateGlobalState(e){this.globalState={...this.globalState,...e}}updateLocale(e){this.locale=e,this.debug&&zt.log("Locale updated:",e)}isConfigLoaded(){return this.configLoaded}async hasErrorLayout(e){const a=await this.loadConfig();return a?!!(a.layouts[e]||a.layouts[String(e)]):!1}clearConfigCache(){this.errorConfig=null,this.configLoaded=!1,this.debug&&zt.log("Config cache cleared")}}const $t=ct("ModuleAssetLoader");class q_{constructor(){$(this,"loadedAssets",new Map);$(this,"loadingPromises",new Map);$(this,"failedJsAssets",new Set)}hasFailedJsAssets(){return this.failedJsAssets.size>0}getFailedJsAssets(){return[...this.failedJsAssets]}async loadActiveExtensionAssets(e){if(!e||e.length===0){$t.log("No module assets to load");return}const a=[...e].sort((d,f)=>d.priority-f.priority);$t.log("Loading module assets:",a.map(d=>d.identifier));const r=a.filter(d=>d.css).map(d=>this.loadCSS(d.identifier,d.css)),i=a.filter(d=>d.js).map(d=>this.loadJS(d.identifier,d.js)),l=await Promise.allSettled([...r,...i]),u=l.filter(d=>d.status==="rejected");if(u.length>0){$t.warn(`Some module assets failed to load (${u.length}/${l.length}); continuing with the rest`,this.getFailedJsAssets());return}$t.log("All module assets loaded successfully")}async loadBundle(e,a,r){const i=[];if(r&&i.push(this.loadBundleCss(e,r)),a&&i.push(this.loadBundleJs(e,a)),i.length===0){$t.log(`No bundle assets to load for: ${e}`);return}await Promise.all(i)}async loadBundleCss(e,a){const r=`ext-bundle-css-${e}`;if(document.getElementById(r)){$t.log(`Bundle CSS already loaded: ${e}`);return}return new Promise(i=>{const l=document.createElement("link");l.rel="stylesheet",l.href=a,l.id=r,l.onload=()=>{$t.log(`Bundle CSS loaded: ${e}`),this.registerLoadedAsset(`bundle-${e}`,{type:"css",element:l}),i()},l.onerror=()=>{$t.warn(`Failed to load bundle CSS: ${e} (${a})`),i()},document.head.appendChild(l)})}async loadBundleJs(e,a){const r=`ext-bundle-js-${e}`;if(document.getElementById(r)){$t.log(`Bundle JS already loaded: ${e}`);return}const i=this.loadingPromises.get(r);if(i)return $t.log(`Bundle JS already loading: ${e}`),i;const l=Xg(a,{id:r},{label:`bundle JS: ${e}`}).then(()=>{$t.log(`Bundle JS loaded: ${e}`);const u=document.getElementById(r);u&&this.registerLoadedAsset(`bundle-${e}`,{type:"js",element:u}),this.loadingPromises.delete(r)}).catch(u=>{throw $t.warn(`Failed to load bundle JS: ${e} (${a})`,u),this.failedJsAssets.add(e),this.loadingPromises.delete(r),u});return this.loadingPromises.set(r,l),l}async loadCSS(e,a){const r=`module-css-${e}`;if(document.getElementById(r)){$t.log(`CSS already loaded: ${e}`);return}return new Promise((i,l)=>{const u=document.createElement("link");u.rel="stylesheet",u.href=a,u.id=r,u.onload=()=>{$t.log(`CSS loaded: ${e}`),this.registerLoadedAsset(e,{type:"css",element:u}),i()},u.onerror=()=>{$t.warn(`Failed to load CSS: ${e} (${a})`),i()},document.head.appendChild(u)})}async loadJS(e,a){const r=`module-js-${e}`;if(document.getElementById(r)){$t.log(`JS already loaded: ${e}`);return}const i=this.loadingPromises.get(e);if(i)return $t.log(`JS already loading: ${e}`),i;const l=Xg(a,{id:r},{label:`JS: ${e}`}).then(()=>{$t.log(`JS loaded: ${e}`);const u=document.getElementById(r);u&&this.registerLoadedAsset(e,{type:"js",element:u}),this.loadingPromises.delete(e)}).catch(u=>{throw $t.warn(`Failed to load JS: ${e} (${a})`,u),this.failedJsAssets.add(e),this.loadingPromises.delete(e),u});return this.loadingPromises.set(e,l),l}registerLoadedAsset(e,a){const r=this.loadedAssets.get(e)||[];r.push(a),this.loadedAssets.set(e,r)}unloadExtensionAsset(e){const a=this.loadedAssets.get(e);if(!a||a.length===0){$t.log(`No assets to unload for: ${e}`);return}a.forEach(r=>{r.element.parentNode&&(r.element.parentNode.removeChild(r.element),$t.log(`${r.type.toUpperCase()} unloaded: ${e}`))}),this.loadedAssets.delete(e),$t.log(`All assets unloaded for: ${e}`)}unloadAllAssets(){Array.from(this.loadedAssets.keys()).forEach(a=>{this.unloadExtensionAsset(a)}),$t.log("All module assets unloaded")}isLoaded(e){return this.loadedAssets.has(e)}getLoadedModules(){return Array.from(this.loadedAssets.keys())}}let uf=null;function df(){return uf||(uf=new q_),uf}function G_(){if(typeof window>"u")return[];const o=window.G7Config;if(!o?.moduleAssets)return[];const e=[];for(const[a,r]of Object.entries(o.moduleAssets)){const i=r;e.push({identifier:a,js:i.js?wr(i.js):i.js,css:i.css?wr(i.css):i.css,priority:i.priority,external:i.external})}return e}function V_(){if(typeof window>"u")return null;const o=window.G7Config;if(!o?.bundleUrls)return null;const e=o.bundleUrls;return{moduleJs:e.moduleJs?wr(e.moduleJs):e.moduleJs,moduleCss:e.moduleCss?wr(e.moduleCss):e.moduleCss,pluginJs:e.pluginJs?wr(e.pluginJs):e.pluginJs,pluginCss:e.pluginCss?wr(e.pluginCss):e.pluginCss}}function F_(){if(typeof window>"u")return[];const o=window.G7Config;if(!o?.pluginAssets)return[];const e=[];for(const[a,r]of Object.entries(o.pluginAssets)){const i=r;e.push({identifier:a,js:i.js?wr(i.js):i.js,css:i.css?wr(i.css):i.css,priority:i.priority,external:i.external})}return e}const ff=ct("SystemBannerManager");class mc{static show(e){this.banners.set(e.id,e),this.render(),ff.log(`Banner shown: ${e.id}`)}static hide(e){this.banners.delete(e)&&(this.render(),ff.log(`Banner hidden: ${e}`))}static hideAll(){this.banners.clear(),this.render(),ff.log("All banners hidden")}static detectLocale(){try{const a=window.G7Core;if(a?.locale?.current)return a.locale.current()}catch{}return(navigator.language||"ko").split("-")[0]}static resolveMessage(e,a){return typeof e=="string"?e:e[a]||e.en||e.ko||Object.values(e)[0]||""}static render(){if(typeof document>"u")return;let e=document.getElementById(this.containerId);if(this.banners.size===0){e&&(e.remove(),this.adjustAppPadding(0));return}e||(e=document.createElement("div"),e.id=this.containerId,e.style.cssText="position:fixed;top:0;left:0;right:0;z-index:99999;",document.body.prepend(e));const a=Array.from(this.banners.values()).sort((i,l)=>(i.order??0)-(l.order??0)),r=this.detectLocale();e.innerHTML=a.map(i=>{const l=this.resolveMessage(i.message,r),u=i.background||"#f59e0b",d=i.color||"white";return`
${l}
`}).join(""),requestAnimationFrame(()=>{e&&this.adjustAppPadding(e.offsetHeight)})}static adjustAppPadding(e){const a=document.getElementById("app");a&&(a.style.paddingTop=e>0?`${e}px`:"")}}$(mc,"banners",new Map),$(mc,"containerId","g7-system-banners");const B=ct("TemplateApp");function sy(o){const e={};for(const a of o.keys()){if(a in e)continue;const r=o.getAll(a);r.length>1?e[a]=r:r.length===1&&(a.endsWith("[]")?e[a]=r:e[a]=r[0])}return e}const Ca=class Ca{constructor(e){$(this,"router",null);$(this,"layoutLoader",null);$(this,"errorPageHandler",null);$(this,"config");$(this,"globalState");$(this,"globalStateListeners",new Set);$(this,"currentRouteChangeId",0);$(this,"currentDataSources",[]);$(this,"currentRawDataSources",[]);$(this,"currentRouteParams",{});$(this,"currentQueryParams",new URLSearchParams);$(this,"currentFetchedData",{});$(this,"currentLayoutName","");$(this,"templateErrorHandling",null);$(this,"currentWebSocketSubscriptions",[]);$(this,"extensionCacheVersion",0);$(this,"currentGlobalHeaders",[]);$(this,"transitionOverlayEl",null);$(this,"skeletonOverlayRoot",null);$(this,"skeletonOverlayContainer",null);$(this,"_spinnerState",null);$(this,"modalDataSources",new Map);this.globalState={sidebarOpen:!1},this.loadG7Config(),this.migrateLocaleStorage();const a=this.loadLocaleFromStorage(),r=a||e.locale||"ko";this.config={...e,locale:r},!a&&e.locale&&this.saveLocaleToStorage(e.locale)}loadG7Config(){if(typeof window<"u"&&window.G7Config){const e=window.G7Config;e.settings&&(this.globalState.settings=e.settings,B.log("Loaded settings from G7Config:",Object.keys(e.settings)),e.settings.upload&&(this.globalState.uploadSettings=e.settings.upload)),e.plugins&&(this.globalState.plugins=e.plugins,B.log("Loaded plugin settings from G7Config:",Object.keys(e.plugins))),e.modules&&(this.globalState.modules=e.modules,B.log("Loaded module settings from G7Config:",Object.keys(e.modules))),e.appConfig&&(this.globalState.appConfig=e.appConfig,B.log("Loaded appConfig from G7Config:",Object.keys(e.appConfig)))}}resolveRouteExpressions(e){const a=new wn,r={_global:this.globalState};return e.map(i=>{const l={...i};if(l.path&&l.path.includes("{{")){const u=l.path;l.path=a.resolveBindings(l.path,r),l.path=l.path.replace(/\/\/+/g,"/")||"/",l.path.includes("{{")&&(B.warn("Route expression resolution failed, using fallback:",u),l.path=u.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/")}if(l.redirect&&l.redirect.includes("{{")){const u=l.redirect;l.redirect=a.resolveBindings(l.redirect,r),l.redirect=l.redirect.replace(/\/\/+/g,"/")||"/",l.redirect.includes("{{")&&(B.warn("Route redirect expression resolution failed:",u),l.redirect=u.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/")}return l})}migrateLocaleStorage(){const e=["locale","g7_template_locale"];for(const a of e)try{const r=localStorage.getItem(a);r&&r!==localStorage.getItem(Ca.LOCALE_STORAGE_KEY)&&(localStorage.setItem(Ca.LOCALE_STORAGE_KEY,r),B.log(`Migrated locale from '${a}' to '${Ca.LOCALE_STORAGE_KEY}'`)),localStorage.removeItem(a)}catch(r){B.warn(`Failed to migrate locale key '${a}':`,r)}}async init(){try{Ks.getInstance().setDebug(this.config.debug),B.log("Initializing with config:",this.config),US();const e=da.getInstance(),a=ha.getInstance(),r=this.loadCacheVersionFromStorage()||0,[i,l,u,d,f]=await Promise.all([Ao({templateId:this.config.templateId,templateType:this.config.templateType,locale:this.config.locale,debug:this.config.debug,cacheVersion:r}),e.loadComponents(this.config.templateId,this.config.templateType),xl(La(`/api/templates/${this.config.templateId}/routes`,"json",r>0?r:null),{label:"routes.json"}).then(A=>{if(!A.ok)throw new Error(`Failed to load routes: ${A.statusText}`);return A.json()}).then(A=>{if(!A.success)throw new Error("Failed to load routes from API");return A.data}).catch(A=>{throw B.error("Error loading routes:",A),A}),a.preloadAuth(this.config.templateType==="admin"?"admin":"user"),fetch(La(`/api/templates/${this.config.templateId}/config`,"json")).then(A=>A.ok?A.json():null).then(A=>!A?.success||!A?.data?null:A.data).catch(A=>(B.warn("Error loading template config:",A),null))]);if(B.log("Template Engine initialized"),B.log("ComponentRegistry loaded"),B.log("Routes data loaded"),B.log("User info preloaded"),B.log("Template config loaded:",f),f?.cache_version!==void 0){const A=this.loadCacheVersionFromStorage();if(this.extensionCacheVersion=f.cache_version,this.saveCacheVersionToStorage(this.extensionCacheVersion),B.log("Extension cache version:",this.extensionCacheVersion),A!==null&&A!==this.extensionCacheVersion){B.log("Cache version changed, reloading routes...");const T=await xl(La(`/api/templates/${this.config.templateId}/routes`,"json",this.extensionCacheVersion),{label:"routes.json (reload)"}).then(L=>{if(!L.ok)throw new Error(`Failed to reload routes: ${L.statusText}`);return L.json()}).then(L=>{if(!L.success)throw new Error("Failed to reload routes from API");return L.data});Array.isArray(T.routes)&&(T.routes=this.resolveRouteExpressions(T.routes),Object.assign(u,T),B.log("Routes reloaded with new cache version"));try{const{TranslationEngine:L}=await Promise.resolve().then(()=>tp),M=L.getInstance();M.setCacheVersion(this.extensionCacheVersion);const R=this.config.locale||"ko",D="en";await M.loadTranslations(this.config.templateId,R,"/api",!0),R!==D&&await M.loadTranslations(this.config.templateId,D,"/api",!0),B.log("Translations reloaded with new cache version")}catch(L){B.error("Failed to reload translations:",L)}}}f?.errorHandling&&(this.templateErrorHandling=f.errorHandling,pa().setTemplateConfig(this.templateErrorHandling),B.log("Template errorHandling registered:",this.templateErrorHandling)),a.on("logout",()=>{B.log("User logged out")}),a.on("authStateChange",A=>{B.log("Auth state changed:",A)}),B.log("AuthManager event handlers registered");const g=$a(),m=this.config.templateType==="admin"?"admin":"user",b=a.getConfig(m);g.setOnUnauthorized(()=>{B.log("Unauthorized - redirecting to login page"),g.removeToken();const A=window.location.pathname+window.location.search,T=a.getLoginRedirectUrl(m,A,"session_expired");window.location.href=T}),B.log("ApiClient onUnauthorized callback registered"),this.layoutLoader=new tf(e),this.extensionCacheVersion>0&&this.layoutLoader.setCacheVersion(this.extensionCacheVersion),B.log("LayoutLoader initialized:",this.layoutLoader);const v=new va({onUnauthorized:()=>{B.warn("Unauthorized request in error page")}});if(this.errorPageHandler=new P_({templateId:this.config.templateId,layoutLoader:this.layoutLoader,locale:this.config.locale,debug:this.config.debug,renderFunction:ls,dataSourceManager:v,globalState:this.globalState}),B.log("ErrorPageHandler initialized with DataSourceManager"),await this.handleServerError()){B.log("Server error handled, skipping normal initialization");return}if(this.router=new U_(this.config.templateId),Array.isArray(u.routes)){const A=this.resolveRouteExpressions(u.routes);this.router.setRoutes(A)}else throw new Error("Invalid routes data format");B.log("Router initialized:",this.router),B.log("Routes set:",this.router.getRoutes());const{getActionDispatcher:S}=await Promise.resolve().then(()=>za),E=S();if(E&&(E.setDefaultContext({navigate:A=>this.router?.navigate(A)}),E.setGlobalStateUpdater((A,T)=>this.setGlobalState(A,T)),B.log("Navigate function and setGlobalState injected to ActionDispatcher")),await this.loadExtensionAssets(),this.reinitializeTemplateHandlers(),this.router.on("routeChange",A=>this.handleRouteChange(A)),this.router.on("routeNotFound",A=>this.handleRouteNotFound(A)),typeof window<"u"&&iy(window.location.pathname)){B.log("Layout editor mode detected — skipping router match"),await ls({containerId:"app",layoutJson:{components:[]},dataContext:{},translationContext:{templateId:this.config.templateId,locale:this.config.locale}}),B.log("Template App initialized in layout editor mode");return}this.router.navigateToCurrentPath(),B.log("Template App initialized successfully")}catch(e){B.error("Initialization failed:",e),this.showInitError(e)}}async loadExtensionAssets(){try{const e=df(),a=V_();if(!a){await this.loadExtensionAssetsIndividually();return}await e.loadBundle("module",a.moduleJs,a.moduleCss),await e.loadBundle("plugin",a.pluginJs,a.pluginCss),B.log("Extension bundle assets loaded successfully")}catch(e){B.warn("Failed to load extension assets:",e)}}async loadExtensionAssetsIndividually(){const e=df(),a=G_();a.length>0&&(B.log("Loading module assets (individual fallback):",a.map(i=>i.identifier)),await e.loadActiveExtensionAssets(a));const r=F_();r.length>0&&(B.log("Loading plugin assets (individual fallback):",r.map(i=>i.identifier)),await e.loadActiveExtensionAssets(r))}async handleRouteChange(e){const a=++this.currentRouteChangeId;window.__g7ForcedLocalFields=void 0,window.__g7ActionContext=void 0,window.__g7PendingLocalState=void 0,window.__g7LastSetLocalSnapshot=void 0,window.__g7SetLocalOverrideKeys=void 0,window.__g7SequenceLocalSync=void 0,window.__g7AutoBindingPaths=new Map;try{if(B.log("Route changed:",e,"requestId:",a),!this.layoutLoader)throw new Error("LayoutLoader is not initialized");if(!e.layout)throw new Error("Route layout is not defined");let r=e.layout;const i=r==="__preview__";i&&e.params?.token&&(r=`__preview__/${e.params.token}`);const l=await this.layoutLoader.loadLayout(this.config.templateId,r);if(a!==this.currentRouteChangeId){B.log("Route change cancelled (newer request exists):",a);return}B.log("Layout loaded:",l);const u=pa();l.errorHandling?(u.setLayoutConfig(l.errorHandling),B.log("Layout errorHandling registered:",l.errorHandling)):u.clearLayoutConfig();const d=l.data_sources||[],f=e.query||{},g=new URLSearchParams;for(const[te,he]of Object.entries(f))if(Array.isArray(he))for(const x of he)g.append(te,x);else g.set(te,he);const m={route:e.params||{},query:f,_global:this.globalState};l.scripts&&Array.isArray(l.scripts)&&await this.loadLayoutScripts(l.scripts,m);const{DataSourceManager:b,getActionDispatcher:v}=await Promise.resolve().then(()=>za),S=new b;if(i){const te=v();te&&te.setPreviewMode(!0),this.setGlobalState({__isPreview:!0}),mc.show({id:"preview-mode",message:{ko:"⚠ 미리보기 모드 — 페이지 이동이 비활성화됩니다",en:"⚠ Preview Mode — Navigation is disabled"},background:"linear-gradient(90deg, #f59e0b, #d97706)",color:"white"}),B.log("Preview mode activated")}else{const te=v();te?.isPreviewMode()&&(te.setPreviewMode(!1),mc.hide("preview-mode"))}if(this.currentGlobalHeaders=l.globalHeaders||[],this.currentGlobalHeaders.length>0){S.setGlobalHeaders(this.currentGlobalHeaders);const te=v();te&&te.setGlobalHeaders(this.currentGlobalHeaders),B.log("globalHeaders set:",this.currentGlobalHeaders.map(he=>he.pattern))}if(l.named_actions&&Object.keys(l.named_actions).length>0){const te=v();te&&te.setNamedActions(l.named_actions)}const E=S.filterByCondition(d,m);d.length!==E.length&&B.log("Data sources filtered by condition:",{before:d.map(te=>te.id),after:E.map(te=>te.id)});const A=E.filter(te=>te.loading_strategy==="blocking"),T=E.filter(te=>(te.loading_strategy||"progressive")!=="blocking"&&te.type!=="websocket"),L=Array.isArray(l.transition_overlay?.wait_for)?l.transition_overlay.wait_for:[],M=L.length>0&&E.some(te=>L.includes(te.id)&&te.type!=="websocket"&&(te.loading_strategy||"progressive")!=="background");if((A.length>0||M)&&l.transition_overlay){const te=typeof l.transition_overlay=="boolean"?{enabled:l.transition_overlay,style:"opaque"}:l.transition_overlay;te.enabled&&te.style==="skeleton"&&te.skeleton?.component&&te.target?this.renderSkeletonOverlay(te.target,te.skeleton,l,te.fallback_target):te.enabled&&te.style==="spinner"&&te.target&&this.renderSpinnerOverlay(te.target,te.spinner,te.fallback_target)}let R={},D={},U={},j={};this.currentWebSocketSubscriptions.length>0&&(B.log("Unsubscribing previous WebSocket subscriptions:",this.currentWebSocketSubscriptions),S.unsubscribeWebSockets(this.currentWebSocketSubscriptions),this.currentWebSocketSubscriptions=[]),this.currentDataSources=E,this.currentRawDataSources=d,this.currentRouteParams=e.params||{},this.currentQueryParams=g,B.log(`handleRouteChange #${a} - queryObject:`,f),B.log(`handleRouteChange #${a} - queryParams:`,g.toString()),A.length>0&&(B.log("Fetching blocking data sources:",A.map(he=>he.id)),(await S.fetchDataSourcesWithResults(A,e.params||{},g)).forEach(he=>{if(he.state==="success"&&he.data!==void 0)R[he.id]=he.data;else if(he.state==="error"&&he.error){const x=he.error,K=x.response?.data?.message;D[he.id]={message:K||he.error.message,status:x.response?.status||x.status}}}),this.processInitOptions(A,R,U,j),this.currentFetchedData={...R},B.log("Blocking data loaded:",Object.keys(R)),Object.keys(D).length>0&&B.log("Data source errors:",D),Object.keys(U).length>0&&B.log("Local state init (blocking):",Object.keys(U)),Object.keys(j).length>0&&B.log("Isolated state init (blocking):",Object.keys(j)));const P=T.length>0;if(P&&(Na.setPending(!0),B.log("Transition started before rendering")),a!==this.currentRouteChangeId){B.log("Route change cancelled after blocking data (newer request exists):",a);return}const{getState:X}=await Promise.resolve().then(()=>za),ge=X().currentDataContext||{},Ee=T.map(te=>te.id),Ce={};if(P){Ee.forEach(he=>{ge[he]!==void 0?Ce[he]=ge[he]:Ce[he]=void 0});const te=Object.keys(Ce).filter(he=>Ce[he]!==void 0);te.length>0&&B.log("Preserving previous progressive data:",te),B.log("Progressive data sources initialized:",Ee)}const $e=l.defines||{},Pe={...Ce,...e.params,...R,route:{...e.params||{},path:e.path},query:f,_global:{...this.globalState},_globalSetState:te=>this.setGlobalState(te),_dataSourceErrors:Object.keys(D).length>0?D:void 0,_localInit:Object.keys(U).length>0?U:void 0,_isolatedInit:Object.keys(j).length>0?j:void 0,_defines:Object.keys($e).length>0?$e:void 0};if(l.computed&&Object.keys(l.computed).length>0){const te=this.calculateComputed(l.computed,Pe);Object.keys(te).length>0&&(Pe._computed=te,this.globalState._computed=te,B.log("Computed values calculated:",Object.keys(te))),Pe._computedDefinitions=l.computed}const Xe=l.layout_name||e.layout;this.currentLayoutName!==""&&this.currentLayoutName!==Xe&&(B.log("_local reset due to layout change:",{from:this.currentLayoutName,to:Xe}),this.globalState._local={},nC()),this.currentLayoutName=Xe;const Q=l.initLocal||l.state;if(Q&&Object.keys(Q).length>0){this.globalState._local||(this.globalState._local={});for(const[te,he]of Object.entries(Q))this.globalState._local[te]===void 0&&(this.globalState._local[te]=JSON.parse(JSON.stringify(he)));Pe._local={...this.globalState._local},B.log("initLocal applied to _local:",Object.keys(Q))}if(l.initGlobal&&Object.keys(l.initGlobal).length>0){for(const[te,he]of Object.entries(l.initGlobal))this.globalState[te]===void 0&&(this.globalState[te]=JSON.parse(JSON.stringify(he)));B.log("initGlobal applied to _global:",Object.keys(l.initGlobal))}if(l.initIsolated&&Object.keys(l.initIsolated).length>0){for(const[te,he]of Object.entries(l.initIsolated))j[te]===void 0&&(j[te]=JSON.parse(JSON.stringify(he)));B.log("initIsolated applied:",Object.keys(l.initIsolated))}Pe._global={...this.globalState,layoutWarnings:l.warnings||[]};const fe=l.initActions||l.init_actions;if(fe&&fe.length>0){await this.executeInitActions(fe,Pe),B.log("initActions executed before render");const te=this.globalState;if(te._local){if(Object.keys(U).length>0){for(const[he,x]of Object.entries(U))te._local[he]!==void 0?te._local[he]=this.deepMerge(te._local[he],x):te._local[he]=x;B.log("localInit merged into _local after initActions:",Object.keys(U))}Pe._local=te._local,B.log("_local merged into dataContext:",te._local)}if(Pe._global={...this.globalState,layoutWarnings:l.warnings||[]},B.log("_global merged into dataContext after initActions"),l.computed&&Object.keys(l.computed).length>0){const he=this.calculateComputed(l.computed,Pe);Object.keys(he).length>0&&(Pe._computed=he,this.globalState._computed=he,B.log("Computed values recalculated after init_actions:",Object.keys(he)))}if(Object.keys(this.currentFetchedData).length>0){for(const[he,x]of Object.entries(this.currentFetchedData))Pe[he]=x;B.log("Fetched data sources merged into dataContext after initActions:",Object.keys(this.currentFetchedData))}}if(l.transition_overlay&&!this.skeletonOverlayContainer&&this.showTransitionOverlay(l.transition_overlay,l),await ls({containerId:"app",layoutJson:l,dataContext:Pe,translationContext:{templateId:this.config.templateId,locale:this.config.locale}}),B.log("Initial render complete with blocking data"),this.reattachSpinnerOverlay(),T.length>0){if(a!==this.currentRouteChangeId){B.log("Route change cancelled before progressive fetch (newer request exists):",a),Na.setPending(!1),this.hideTransitionOverlay();return}B.log("Fetching progressive/background data sources:",T.map(x=>x.id));const{updateTemplateData:te,getState:he}=await Promise.resolve().then(()=>za);try{const x=T.map(async K=>{try{const de=(await S.fetchDataSourcesWithResults([K],e.params||{},g,this.globalState))[0];if(!de){B.log(`Data source ${K.id} skipped (no fetch result)`);return}if(a!==this.currentRouteChangeId){B.log(`Data source ${K.id} fetch cancelled (newer request exists)`);return}if(de.state==="success"&&de.data!==void 0){B.log(`Progressive data source loaded: ${K.id}`),this.currentFetchedData[K.id]=de.data;const ie={};this.processInitOptions([K],{[K.id]:de.data},ie);const me=he();if(me.bindingEngine){const Se=[K.id];K.initGlobal&&Se.push("_global"),K.initLocal&&Se.push("_local"),me.bindingEngine.invalidateCacheByKeys(Se)}const Ne={[K.id]:de.data};Object.keys(ie).length>0&&(Ne._localInit=ie,Object.assign(U,ie)),K.initGlobal&&(Ne._global={...this.globalState}),te(Ne)}else if(de.state==="error"&&de.error){const ie=de.error,me=ie.response?.data?.message;D[K.id]={message:me||de.error.message,status:ie.response?.status||ie.status},B.log(`Progressive data source error: ${K.id}`,D[K.id]),te({[K.id]:null,_dataSourceErrors:{...D}})}}catch(re){B.error(`Failed to fetch data source: ${K.id}`,re)}});if(await Promise.all(x),a!==this.currentRouteChangeId){B.log("Route change cancelled after progressive fetch (newer request exists):",a);return}B.log("All progressive data sources loaded")}finally{Na.setPending(!1),this.hideTransitionOverlay()}}else this.hideTransitionOverlay();const ye=E.filter(te=>te.type==="websocket");if(ye.length>0){B.log("Subscribing WebSocket data sources:",ye.map(K=>K.id));const{updateTemplateData:te,getState:he}=await Promise.resolve().then(()=>za),x={...this.currentFetchedData,...e.params,route:{...e.params||{},path:e.path},query:f,_global:{...this.globalState}};B.log("WebSocket binding context keys:",Object.keys(x)),this.currentWebSocketSubscriptions=S.subscribeWebSockets(E,(K,re)=>{B.log(`WebSocket data received for: ${K}`,re),this.currentFetchedData[K]=re;const de=E.find(Se=>Se.id===K),ie=he();if(ie.bindingEngine){const Se=[K];de?.initGlobal&&Se.push("_global"),de?.initLocal&&Se.push("_local"),ie.bindingEngine.invalidateCacheByKeys(Se)}te({[K]:re});const Ne=E.find(Se=>Se.type==="websocket"&&(Se.target_source||Se.id)===K)?.onReceive;Array.isArray(Ne)&&Ne.length>0&&window.G7Core?.dispatch&&(async()=>{for(const He of Ne)try{const Ae=this.getActionDispatcher?.();Ae&&await Ae.dispatchAction(He,{navigate:this.getRouter?.()?(Et,kt)=>this.getRouter().navigate(Et,kt):void 0,setState:Et=>this.setGlobalState(Et),state:this.globalState,data:{...this.globalState,$args:[re],$event:re},_isDispatchFallbackContext:!0})}catch(Ae){B.error(`WebSocket onReceive action failed for ${K}:`,Ae)}})()},x),B.log("WebSocket subscriptions established:",this.currentWebSocketSubscriptions)}B.log("Layout rendered successfully")}catch(r){B.error("Route change handling failed:",r),this.hideTransitionOverlay(),this.showRouteError(r)}}processInitOptions(e,a,r,i){e.some(u=>u.refetchOnMount===!0&&u.initLocal)&&(r._forceLocalInit=Date.now(),B.log("refetchOnMount detected, forcing local state init")),e.forEach(u=>{const d=a[u.id];if(!d)return;const f=d.data??d;if(u.initLocal){if(typeof u.initLocal=="string"){let g=f;if(u.initLocalDefaults&&typeof u.initLocalDefaults=="object"){const b=this.evaluateDefaults(u.initLocalDefaults,a);g={...b,...f},B.log(`initLocalDefaults applied for ${u.initLocal}:`,Object.keys(b))}const m=this.globalState._local?.[u.initLocal];m!==void 0&&typeof m=="object"&&typeof g=="object"?(r[u.initLocal]=this.deepMerge(m,g),B.log(`initLocal (merged): ${u.id}.data -> _local.${u.initLocal}`)):(r[u.initLocal]=g,B.log(`initLocal: ${u.id}.data -> _local.${u.initLocal}`))}else if(typeof u.initLocal=="object"&&u.initLocal.key){const{key:g,path:m}=u.initLocal;let b=m?this.extractValueByPathOrExpression(f,m,u.id):f;if(u.initLocalDefaults&&typeof u.initLocalDefaults=="object"){const S=this.evaluateDefaults(u.initLocalDefaults,a);b={...S,...b},B.log(`initLocalDefaults applied for ${g}:`,Object.keys(S))}const v=this.globalState._local?.[g];v!==void 0&&typeof v=="object"&&typeof b=="object"?(r[g]=this.deepMerge(v,b),B.log(`initLocal (merged): ${u.id}.data${m?"."+m:""} -> _local.${g}`)):(r[g]=b,B.log(`initLocal: ${u.id}.data${m?"."+m:""} -> _local.${g}`))}else if(typeof u.initLocal=="object"){const g=u.initLocal._merge||"deep",m=this.flattenNestedObjectToMappings(u.initLocal);for(const{targetPath:b,sourcePath:v}of m){const S=this.extractValueByPathOrExpression(f,v,u.id);if(b.includes(".")){const E=b.split(".")[0];r[E]===void 0&&this.globalState._local?.[E]!==void 0&&(r[E]=JSON.parse(JSON.stringify(this.globalState._local[E]))),this.setValueAtPath(r,b,S,g),B.log(`initLocal map (${g}): ${u.id} ${v} -> _local.${b}`)}else{const E=this.globalState._local?.[b];g==="replace"?(r[b]=S,B.log(`initLocal map (replace): ${u.id} ${v} -> _local.${b}`)):g==="shallow"?E!==void 0&&typeof E=="object"&&typeof S=="object"?(r[b]={...E,...S},B.log(`initLocal map (shallow): ${u.id} ${v} -> _local.${b}`)):(r[b]=S,B.log(`initLocal map: ${u.id} ${v} -> _local.${b}`)):E!==void 0&&typeof E=="object"&&typeof S=="object"?(r[b]=this.deepMerge(E,S),B.log(`initLocal map (deep): ${u.id} ${v} -> _local.${b}`)):(r[b]=S,B.log(`initLocal map: ${u.id} ${v} -> _local.${b}`))}}}}if(u.initGlobal)if(typeof u.initGlobal=="object"&&!Array.isArray(u.initGlobal)&&!("key"in u.initGlobal))for(const[m,b]of Object.entries(u.initGlobal)){if(typeof b!="string"){B.warn(`initGlobal map value must be string, got ${typeof b} for key ${m}`);continue}const v=this.extractValueByPathOrExpression(f,b,u.id),S=this.globalState[m];S!==void 0&&typeof S=="object"&&typeof v=="object"?(this.globalState[m]=this.deepMerge(S,v),B.log(`initGlobal map (merged): ${u.id} ${b} -> _global.${m}`)):(this.globalState[m]=v,B.log(`initGlobal map: ${u.id} ${b} -> _global.${m}`))}else{const m=Array.isArray(u.initGlobal)?u.initGlobal:[u.initGlobal];for(const b of m)if(typeof b=="string"){const v=this.globalState[b];v!==void 0&&typeof v=="object"&&typeof f=="object"?(this.globalState[b]=this.deepMerge(v,f),B.log(`initGlobal (merged): ${u.id}.data -> _global.${b}`)):(this.globalState[b]=f,B.log(`initGlobal: ${u.id}.data -> _global.${b}`))}else if(typeof b=="object"&&b.key){const{key:v,path:S}=b,E=S?this.extractValueByPathOrExpression(f,S,u.id):f,A=this.globalState[v];A!==void 0&&typeof A=="object"&&typeof E=="object"?(this.globalState[v]=this.deepMerge(A,E),B.log(`initGlobal (merged): ${u.id}.data${S?"."+S:""} -> _global.${v}`)):(this.globalState[v]=E,B.log(`initGlobal: ${u.id}.data${S?"."+S:""} -> _global.${v}`))}}if(i&&u.initIsolated){if(typeof u.initIsolated=="string"){const g=i[u.initIsolated];g!==void 0&&typeof g=="object"&&typeof f=="object"?(i[u.initIsolated]=this.deepMerge(g,f),B.log(`initIsolated (merged): ${u.id}.data -> _isolated.${u.initIsolated}`)):(i[u.initIsolated]=f,B.log(`initIsolated: ${u.id}.data -> _isolated.${u.initIsolated}`))}else if(typeof u.initIsolated=="object"&&u.initIsolated.key){const{key:g,path:m}=u.initIsolated,b=m?this.extractValueByPathOrExpression(f,m,u.id):f,v=i[g];v!==void 0&&typeof v=="object"&&typeof b=="object"?(i[g]=this.deepMerge(v,b),B.log(`initIsolated (merged): ${u.id}.data${m?"."+m:""} -> _isolated.${g}`)):(i[g]=b,B.log(`initIsolated: ${u.id}.data${m?"."+m:""} -> _isolated.${g}`))}else if(typeof u.initIsolated=="object")for(const[g,m]of Object.entries(u.initIsolated)){if(typeof m!="string"){B.warn(`initIsolated map value must be string, got ${typeof m} for key ${g}`);continue}const b=this.extractValueByPathOrExpression(f,m,u.id),v=i[g];v!==void 0&&typeof v=="object"&&typeof b=="object"?(i[g]=this.deepMerge(v,b),B.log(`initIsolated map (merged): ${u.id} ${m} -> _isolated.${g}`)):(i[g]=b,B.log(`initIsolated map: ${u.id} ${m} -> _isolated.${g}`))}}})}evaluateDefaults(e,a){const r={};for(const[i,l]of Object.entries(e))if(typeof l=="string"&&l.startsWith("{{")&&l.endsWith("}}")){const u=l.slice(2,-2).trim();r[i]=this.evaluateExpression(u,a)}else r[i]=l;return r}evaluateExpression(e,a){try{const r=e.split("??").map(i=>i.trim());for(const i of r){if(/^['"].*['"]$/.test(i))return i.slice(1,-1);if(i==="true")return!0;if(i==="false")return!1;if(/^-?\d+(\.\d+)?$/.test(i))return Number(i);const l=this.getNestedValue(a,i);if(l!=null)return l}return}catch(r){B.warn(`Expression evaluation failed: ${e}`,r);return}}getNestedValue(e,a){const r=a.replace(/\?\./g,".");let i=e;const l=r.split(/\.(?![^\[]*\])/).flatMap(u=>{const d=u.match(/^([^\[]*)((?:\[\d+\])*)$/);if(d){const[,f,g]=d,m=[];f&&m.push(f);const b=g.match(/\[\d+\]/g);return b&&m.push(...b),m}return[u]}).filter(u=>u!=="");for(const u of l){if(i==null)return;if(u.startsWith("[")&&u.endsWith("]")){const d=parseInt(u.slice(1,-1),10);i=i[d]}else i=i[u]}return i}extractValueByPathOrExpression(e,a,r){const i=a.match(/^\{\{(.+)\}\}$/);if(i){const l=i[1].trim(),u=new wn,d={data:e,_global:this.globalState,_local:this.globalState._local||{}};try{const f=u.evaluateExpression(l,d);return B.log(`initLocal/initGlobal expression evaluated: ${a} -> `,f),f}catch(f){B.warn(`initLocal/initGlobal expression evaluation failed for ${r}:`,a,f);return}}return this.getNestedValue(e,a)}async loadLayoutScripts(e,a){const r=[];for(const i of e){if((i.if!==void 0||i.conditions!==void 0)&&!Xi({if:i.if,conditions:i.conditions},a,this.bindingEngine,`script:${i.id}`)){B.log(`Script skipped (condition not met): ${i.id}`);continue}if(document.getElementById(i.id)){B.log(`Script already loaded: ${i.id}`);continue}const u=new Promise((d,f)=>{const g=document.createElement("script");g.src=i.src,g.id=i.id,g.async=i.async??!0,g.onload=()=>{B.log(`Script loaded successfully: ${i.id}`),d()},g.onerror=()=>{B.warn(`Failed to load script: ${i.id} (${i.src})`),d()},document.head.appendChild(g)});r.push(u)}r.length>0&&(await Promise.all(r),B.log(`All scripts loaded: ${e.filter(i=>!document.getElementById(i.id)||r.length>0).map(i=>i.id).join(", ")}`))}evaluateScriptCondition(e,a){try{if(e.startsWith("{{")&&e.endsWith("}}")){const r=e.slice(2,-2).trim();return new Function("ctx",` with(ctx) { try { return Boolean(${r}); @@ -232,7 +232,7 @@ Error generating stack: `+c.message+` return false; } } - `)(a)}return!!e}catch(r){return B.warn(`Failed to evaluate script condition: ${e}`,r),!1}}showInitError(e){if(ed()){B.warn("Init failed while document is unloading — skipping error screen",e);return}const a=ry(e);lf.renderFromError("app",a,"초기화 실패",this.config.debug,{templateId:this.config.templateId,locale:this.config.locale},void 0,e)}showTransitionOverlay(e,a){const r=typeof e=="boolean"?{enabled:e,style:"opaque",target:void 0,skeleton:void 0,spinner:void 0}:{enabled:e.enabled,style:e.style||"opaque",target:e.target,skeleton:e.skeleton,spinner:e.spinner,fallback_target:e.fallback_target};if(!r.enabled)return;if(this.hideTransitionOverlay(),r.style==="skeleton"&&r.skeleton?.component&&r.target&&a){this.renderSkeletonOverlay(r.target,r.skeleton,a,r.fallback_target);return}if(r.style==="spinner"&&r.target){this.renderSpinnerOverlay(r.target,r.spinner,r.fallback_target);return}const i=document.documentElement.classList.contains("dark");let l,u="";switch(r.style){case"blur":l=i?"rgba(17,24,39,0.3)":"rgba(255,255,255,0.3)",u="backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);";break;case"fade":l=i?"rgba(17,24,39,0.8)":"rgba(255,255,255,0.8)";break;case"skeleton":l=i?"rgb(17,24,39)":"rgb(249,250,251)";break;default:l=i?"rgb(17,24,39)":"rgb(249,250,251)";break}if(r.target){const d=`#${CSS.escape(r.target)}`,f=document.createElement("style");f.id="g7-transition-overlay",f.textContent=`${d}{position:relative;z-index:0;}${d}::after{content:'';position:absolute;inset:0;background:${l};${u}z-index:2147483647;pointer-events:none;}`,document.head.appendChild(f),this.transitionOverlayEl=f}else{const d=document.createElement("div");d.id="g7-transition-overlay",d.setAttribute("aria-hidden","true"),d.style.position="fixed",d.style.inset="0",d.style.zIndex="9999",d.style.pointerEvents="none",d.style.background=l;for(const f of u.split(";")){const g=f.indexOf(":");g!==-1&&d.style.setProperty(f.slice(0,g).trim(),f.slice(g+1).trim())}document.body.appendChild(d),this.transitionOverlayEl=d}}hideTransitionOverlay(){this.transitionOverlayEl&&(this.transitionOverlayEl.remove(),this.transitionOverlayEl=null),this.hideSkeletonOverlay()}renderSkeletonOverlay(e,a,r,i){const u=da.getInstance().getComponent(a.component);if(!u){B.log(`Skeleton component "${a.component}" not found in registry, falling back to opaque overlay`),this.showTransitionOverlay({enabled:!0,style:"opaque",target:e});return}let d=document.getElementById(e),f="target";if(!d&&i&&(d=document.getElementById(i),f="fallback"),d||(d=document.getElementById("app"),f="fullpage"),!d){B.log(`Skeleton overlay: no target found (target="#${e}", fallback="${i||"none"}"), falling back to opaque overlay`),this.showTransitionOverlay({enabled:!0,style:"opaque",target:e});return}this.hideSkeletonOverlay();const m=document.documentElement.classList.contains("dark")?"rgb(17,24,39)":"rgb(249,250,251)",b=f==="fullpage"?"app":f==="fallback"?i:e,v=`#${CSS.escape(b)}`,S=document.createElement("style");S.id="g7-skeleton-overlay-style",S.textContent=`${v}{position:relative;z-index:0;}${v}::after{content:'';position:absolute;inset:0;background:${m};z-index:2147483646;pointer-events:none;}`,document.head.appendChild(S),this.transitionOverlayEl=S;const E=document.createElement("div");if(E.id="g7-skeleton-overlay",E.setAttribute("role","status"),E.setAttribute("aria-busy","true"),E.setAttribute("aria-label","Loading..."),f==="fullpage")E.style.cssText=["position:fixed","inset:0","z-index:20","overflow:hidden","pointer-events:none",`background:${m}`].join(";")+";";else{const R=d.getBoundingClientRect(),D=window.scrollX||document.documentElement.scrollLeft,U=window.scrollY||document.documentElement.scrollTop;E.style.cssText=["position:absolute",`top:${R.top+U}px`,`left:${R.left+D}px`,`width:${R.width}px`,`height:${R.height}px`,"z-index:20","overflow:hidden","pointer-events:none",`background:${m}`].join(";")+";"}document.body.appendChild(E),this.skeletonOverlayContainer=E;const A=r.components||[];let T;if(f==="fullpage")T=A;else{const R=f==="fallback"?i:e;T=this.findComponentChildrenById(A,R)}const L=Xu.createRoot(E);this.skeletonOverlayRoot=L,Ar.flushSync(()=>{L.render(Ye.createElement(u,{components:T,options:{animation:a.animation||"pulse",iteration_count:a.iteration_count||5}}))});const M=f==="fullpage"?"fullpage (#app)":f==="fallback"?`fallback (#${i})`:`target (#${e})`;B.log(`Skeleton overlay rendered [${M}] with "${a.component}" (${T.length} components)`)}findComponentChildrenById(e,a){const r=i=>{for(const l of i){if(l.id===a)return l.children||[];if(l.children&&Array.isArray(l.children)){const u=r(l.children);if(u!==null)return u}}return null};return r(e)||e}renderSpinnerOverlay(e,a,r){let i=document.getElementById(e),l="target";if(!i&&r&&(i=document.getElementById(r),l="fallback"),i||(i=document.getElementById("app"),l="fullpage"),!i){B.log(`Spinner overlay: no target found (target="#${e}", fallback="${r||"none"}"), falling back to opaque overlay`),this.showTransitionOverlay({enabled:!0,style:"opaque",target:e});return}this.hideSkeletonOverlay();const u=l==="fullpage"?"app":l==="fallback"?r:e,d=`#${CSS.escape(u)}`,f=document.createElement("style");f.id="g7-skeleton-overlay-style",f.textContent=[`${d}{position:relative;}`,"@keyframes g7-spin{to{transform:rotate(360deg)}}"].join(""),document.head.appendChild(f),this.transitionOverlayEl=f;const g=a?.text||window.G7Core?.t?.("nav.loading")||"";this._spinnerState={target:e,fallbackTarget:r,spinnerConfig:a,resolvedText:g},this._mountSpinnerInTarget(i);const m=l==="fullpage"?"fullpage (#app)":l==="fallback"?`fallback (#${r})`:`target (#${e})`,b=a?.component||"default spinner";B.log(`Spinner overlay rendered [${m}] with "${b}"`)}_mountSpinnerInTarget(e){if(!this._spinnerState)return;const{spinnerConfig:a,resolvedText:r}=this._spinnerState;if(this.skeletonOverlayRoot){try{this.skeletonOverlayRoot.unmount()}catch{}this.skeletonOverlayRoot=null}if(this.skeletonOverlayContainer){try{this.skeletonOverlayContainer.remove()}catch{}this.skeletonOverlayContainer=null}const i=document.createElement("div");if(i.id="g7-skeleton-overlay",i.setAttribute("role","status"),i.setAttribute("aria-busy","true"),e.appendChild(i),this.skeletonOverlayContainer=i,a?.component){const u=da.getInstance().getComponent(a.component);if(u){const d=Xu.createRoot(i);this.skeletonOverlayRoot=d,Ar.flushSync(()=>{d.render(Ye.createElement(u,{options:{text:r}}))});return}B.log(`Spinner component "${a.component}" not found in registry, using default spinner`)}i.innerHTML='
'}reattachSpinnerOverlay(){if(!this._spinnerState)return;const{target:e,fallbackTarget:a}=this._spinnerState;let r=document.getElementById(e);!r&&a&&(r=document.getElementById(a)),r||(r=document.getElementById("app")),r&&(this._mountSpinnerInTarget(r),B.log("Spinner overlay reattached to new DOM target"))}hideSkeletonOverlay(){if(this.skeletonOverlayRoot){try{this.skeletonOverlayRoot.unmount()}catch{}this.skeletonOverlayRoot=null}if(this.skeletonOverlayContainer){try{this.skeletonOverlayContainer.parentNode&&this.skeletonOverlayContainer.remove()}catch{}this.skeletonOverlayContainer=null}const e=document.getElementById("g7-skeleton-overlay-style");e&&e.remove(),this._spinnerState=null}showRouteError(e){if(e instanceof ba&&e.details?.status===401){const r=this.config.templateId||"",i=window.location.pathname,l=r.includes("admin")||i.startsWith("/admin")?"admin":"user",u=i+window.location.search,d=!!$a().getToken()||e.details?.hadToken===!0,f=ha.getInstance().getLoginRedirectUrl(l,u,d?"session_expired":void 0);window.location.href=f;return}const a=ry(e);lf.renderFromError("app",a,"페이지 로딩 실패",this.config.debug,{templateId:this.config.templateId,locale:this.config.locale},void 0,e)}async handleServerError(){const e=window.G7Error;if(!e)return!1;B.warn("Server error detected:",e);try{return this.errorPageHandler&&(e.data&&(this.globalState.errorData=e.data),this.errorPageHandler.updateGlobalState(this.globalState),this.errorPageHandler.updateLocale(this.config.locale),await this.errorPageHandler.renderError(e.code,"app"))?(B.log(`${e.code} error page rendered successfully`),!0):(B.log(`Falling back to ErrorDisplay for ${e.code}`),this.showInitError(new Error(`Service unavailable (${e.code})`)),!0)}catch(a){return B.error(`Failed to render ${e.code} page:`,a),this.showInitError(new Error(`Service unavailable (${e.code})`)),!0}}async handleRouteNotFound(e){B.warn("Route not found:",e);try{if(this.errorPageHandler&&(this.errorPageHandler.updateGlobalState(this.globalState),this.errorPageHandler.updateLocale(this.config.locale),await this.errorPageHandler.renderError(404,"app"))){B.log("404 error page rendered successfully");return}B.log("Falling back to ErrorDisplay for 404"),this.showRouteError(new Error(`Page not found: ${e}`))}catch(a){B.error("Failed to render 404 page:",a),this.showRouteError(new Error(`Page not found: ${e}`))}}getRouter(){return this.router}getConfig(){return this.config}getLayoutLoader(){return this.layoutLoader}async reloadExtensionState(){B.log("reloadExtensionState: start");let e;try{const a=await fetch(La(`/api/templates/${this.config.templateId}/config`,"json",null,`_=${Date.now()}`));if(a.ok){const r=await a.json();r?.success&&r?.data?.cache_version!==void 0&&(e=r.data.cache_version)}}catch(a){B.warn("reloadExtensionState: failed to fetch config.json",a)}e!==void 0&&e!==this.extensionCacheVersion&&(B.log(`reloadExtensionState: cache version ${this.extensionCacheVersion} -> ${e}`),this.extensionCacheVersion=e,this.saveCacheVersionToStorage(e));try{this.router&&(await this.router.loadRoutes(this.extensionCacheVersion),B.log("reloadExtensionState: routes reloaded"))}catch(a){B.error("reloadExtensionState: routes reload failed",a)}try{this.layoutLoader&&(this.extensionCacheVersion>0&&this.layoutLoader.setCacheVersion(this.extensionCacheVersion),this.layoutLoader.clear(),B.log("reloadExtensionState: layout cache cleared"))}catch(a){B.error("reloadExtensionState: layout cache clear failed",a)}try{const{TranslationEngine:a}=await Promise.resolve().then(()=>ep),r=a.getInstance();this.extensionCacheVersion>0&&r.setCacheVersion(this.extensionCacheVersion);const i=this.config.locale||"ko",l="en";await r.loadTranslations(this.config.templateId,i,"/api",!0),i!==l&&await r.loadTranslations(this.config.templateId,l,"/api",!0),B.log("reloadExtensionState: translations reloaded")}catch(a){B.error("reloadExtensionState: translations reload failed",a)}try{const a=await fetch(`/api/locales/active?_=${Date.now()}`);if(a.ok){const i=(await a.json())?.data?.locales;if(Array.isArray(i)&&i.length>0){const l=this.globalState.appConfig??{};this.setGlobalState({appConfig:{...l,supportedLocales:i}}),B.log("reloadExtensionState: supportedLocales refreshed",i)}}}catch(a){B.warn("reloadExtensionState: supportedLocales refresh failed",a)}B.log("reloadExtensionState: done")}getActionDispatcher(){return Za().actionDispatcher}async changeLocale(e){try{if(B.log("Changing locale to:",e),this.config.locale===e){B.log("Locale is already",e);return}this.config.locale=e,this.saveLocaleToStorage(e),await this.saveLocaleToDatabase(e),this.layoutLoader&&(this.layoutLoader.clear(),B.log("Layout cache cleared")),this.errorPageHandler&&(this.errorPageHandler.updateLocale(e),B.log("ErrorPageHandler locale updated")),mc(),await _o({templateId:this.config.templateId,templateType:this.config.templateType,locale:e,debug:this.config.debug,cacheVersion:this.extensionCacheVersion}),B.log("Template Engine re-initialized with new locale");const{getActionDispatcher:a}=await Promise.resolve().then(()=>za),r=a();r&&(r.setDefaultContext({navigate:i=>this.router?.navigate(i)}),r.setGlobalStateUpdater((i,l)=>this.setGlobalState(i,l)),B.log("Navigate function and setGlobalState re-injected to ActionDispatcher")),this.reinitializeModuleHandlers(),B.log("Module handlers re-initialized"),this.reinitializeTemplateHandlers(),B.log("Template handlers re-initialized"),this.reinitializePluginHandlers(),B.log("Plugin handlers re-initialized"),this.router&&this.router.navigateToCurrentPath(),B.log("Locale changed successfully to",e)}catch(a){throw B.error("Failed to change locale:",a),a}}loadLocaleFromStorage(){try{return localStorage.getItem(Ca.LOCALE_STORAGE_KEY)}catch(e){return B.warn("Failed to load locale from storage:",e),null}}saveLocaleToStorage(e){try{localStorage.setItem(Ca.LOCALE_STORAGE_KEY,e)}catch(a){B.warn("Failed to save locale to storage:",a)}}async saveLocaleToDatabase(e){const a=localStorage.getItem("auth_token");if(!a){B.log("No auth token, skipping DB locale save");return}let r,i;if(this.config.localeApi)r=this.config.localeApi.endpoint,i=this.config.localeApi.method;else{const l=this.config.templateType==="admin";r=l?"/api/admin/users/me/language":"/api/user/profile/update-language",i=l?"PATCH":"POST"}try{const l=this.getXsrfToken(),u=await fetch(r,{method:i,headers:{"Content-Type":"application/json",Accept:"application/json",...l&&{"X-XSRF-TOKEN":l},Authorization:`Bearer ${a}`},credentials:"include",body:JSON.stringify({language:e})});u.ok?B.log("Locale saved to DB:",e):B.warn("Failed to save locale to DB (UI will still change):",u.statusText)}catch(l){B.warn("Failed to call locale API (UI will still change):",l)}}getXsrfToken(){if(typeof document>"u")return null;const a=`; ${document.cookie}`.split("; XSRF-TOKEN=");return a.length===2?decodeURIComponent(a.pop()?.split(";").shift()||""):null}loadCacheVersionFromStorage(){try{const e=localStorage.getItem(Ca.CACHE_VERSION_STORAGE_KEY);return e?parseInt(e,10):null}catch(e){return B.warn("Failed to load cache version from storage:",e),null}}saveCacheVersionToStorage(e){try{localStorage.setItem(Ca.CACHE_VERSION_STORAGE_KEY,String(e))}catch(a){B.warn("Failed to save cache version to storage:",a)}}reinitializeModuleHandlers(){if(typeof window>"u")return;const e="__",a=window;Object.keys(a).forEach(r=>{if(r.startsWith(e)&&typeof a[r]?.initModule=="function")try{a[r].initModule(),B.log(`Module handler re-initialized: ${r}`)}catch(i){B.warn(`Failed to re-initialize module handlers for ${r}:`,i)}})}reinitializeTemplateHandlers(){if(typeof window>"u")return;const e=window.G7TemplateHandlers;if(!e){B.warn("Template handlers not found on window.G7TemplateHandlers");return}const a=this.getActionDispatcher();if(!a){B.warn("ActionDispatcher not available for template handler registration");return}Object.entries(e).forEach(([r,i])=>{a.registerHandler(r,i)}),B.log(`${Object.keys(e).length} template handler(s) re-registered:`,Object.keys(e))}reinitializePluginHandlers(){if(typeof window>"u")return;const e="__",a=window;Object.keys(a).forEach(r=>{if(r.startsWith(e)&&typeof a[r]?.initPlugin=="function")try{a[r].initPlugin(),B.log(`Plugin handler re-initialized: ${r}`)}catch(i){B.warn(`Failed to re-initialize plugin handlers for ${r}:`,i)}})}getLocale(){return this.config.locale}getErrorPageHandler(){return this.errorPageHandler}getGlobalState(){return{...this.globalState}}setGlobalState(e,a){const r={...this.globalState};typeof e=="function"?this.globalState=e(this.globalState):this.globalState={...this.globalState,...e},B.log("Global state updated:",this.globalState),window.G7Core?.devTools?.captureStateSnapshot?.({source:"setGlobalState",prev:r,next:this.globalState}),this.globalStateListeners.forEach(l=>{l(this.globalState)}),a?.render!==!1&&Promise.resolve().then(()=>za).then(({updateTemplateData:l,getState:u})=>{const d=u();d.reactRoot&&d.currentLayoutJson&&l({_global:{...this.globalState},_local:this.globalState._local||{}})})}onGlobalStateChange(e){this.globalStateListeners.add(e)}offGlobalStateChange(e){this.globalStateListeners.delete(e)}async refetchDataSource(e,a){let r=this.currentDataSources.find(i=>i.id===e);if(!r)for(const[,i]of this.modalDataSources){const l=i.find(u=>u.id===e);if(l){r=l;break}}if(!r){B.warn(`Data source not found: ${e}`);return}B.log(`Refetching data source: ${e}`,a?.sync?"(sync mode)":"",a?.globalStateOverride?"(with global override)":"",a?.localStateOverride?"(with local override)":""),Na.setPending(!0);try{const i=new va;this.currentGlobalHeaders.length>0&&i.setGlobalHeaders(this.currentGlobalHeaders);const l=Za(),u=l.currentDataContext?._global||{},d=a?.globalStateOverride?{...u,...a.globalStateOverride}:u,f=l.currentDataContext?._local||{},g=a?.localStateOverride?{...f,...a.localStateOverride}:f,b=(await i.fetchDataSourcesWithResults([r],this.currentRouteParams,this.currentQueryParams,d,g,{ignoreAutoFetch:!0}))[0];if(b.state==="success"&&b.data!==void 0){this.currentFetchedData[e]=b.data;const v={};this.processInitOptions([r],{[e]:b.data},v);const S=Za();if(S.bindingEngine){const A=[e];r.initGlobal&&A.push("_global"),r.initLocal&&A.push("_local"),S.bindingEngine.invalidateCacheByKeys(A)}const E={[e]:b.data};return Object.keys(v).length>0&&(E._localInit=v),r.initGlobal&&(E._global={...this.globalState}),ls(E,a?.sync?{sync:!0}:void 0),B.log(`Data source refetched successfully: ${e}`),b.data}else if(b.state==="error"){B.error(`Failed to refetch data source: ${e}`,b.error);return}}catch(i){B.error(`Error refetching data source: ${e}`,i);return}finally{Na.setPending(!1)}}registerModalDataSources(e,a){this.modalDataSources.set(e,a),B.log(`Modal data sources registered: ${e} (${a.length} sources)`)}unregisterModalDataSources(e){this.modalDataSources.delete(e),B.log(`Modal data sources unregistered: ${e}`)}getDataSource(e){return this.currentFetchedData[e]}setDataSource(e,a,r){if(!e){B.warn("setDataSource: dataSourceId is required");return}const{merge:i=!1,sync:l=!1}=r||{};i&&this.currentFetchedData[e]?this.currentFetchedData[e]={...this.currentFetchedData[e],...a}:this.currentFetchedData[e]=a,Promise.resolve().then(()=>za).then(({updateTemplateData:u})=>{u({[e]:this.currentFetchedData[e]},l?{sync:!0}:void 0)}),B.log(`setDataSource: Updated ${e}`,i?"(merged)":"(replaced)")}updateDataSourceItem(e,a,r,i,l){const{idField:u="id",merge:d=!0,skipRender:f=!1}=l||{},g=this.currentFetchedData[e];if(!g)return B.warn(`updateDataSourceItem: DataSource '${e}' not found`),!1;const m=this.parseItemPath(a);let b=g;for(const E of m)if(b=b?.[E],b===void 0)return B.warn(`updateDataSourceItem: Path '${a}' not found in dataSource`),!1;if(!Array.isArray(b))return B.warn(`updateDataSourceItem: Target at '${a}' is not an array`),!1;const v=b.findIndex(E=>String(E[u])===String(r));if(v===-1)return B.warn(`updateDataSourceItem: Item with ${u}='${r}' not found`),!1;d?b[v]=this.deepMerge(b[v],i):b[v]={...b[v],...i};const S=window.G7Core?.devTools;return S?.isEnabled?.()&&S.trackDataSourceUpdate?.({dataSourceId:e,updateType:"partial",itemPath:a,itemId:r,updates:i,timestamp:Date.now()}),f||Promise.resolve().then(()=>za).then(({updateTemplateData:E})=>{E({[e]:this.currentFetchedData[e]},{sync:!1})}),B.log(`updateDataSourceItem: Updated ${e}.${a}[${u}=${r}]`),!0}parseItemPath(e){const a=[],r=/([^\.\[\]]+)|\[(\d+)\]/g;let i;for(;(i=r.exec(e))!==null;)i[1]!==void 0?a.push(i[1]):i[2]!==void 0&&a.push(parseInt(i[2],10));return a}deepMerge(e,a){if(a==null)return e;if(typeof a!="object"||Array.isArray(a))return a;const r={...e};for(const i of Object.keys(a))typeof a[i]=="object"&&a[i]!==null&&!Array.isArray(a[i])?r[i]=this.deepMerge(r[i]||{},a[i]):r[i]=a[i];return r}setValueAtPath(e,a,r,i="deep"){const l=a.split(".");let u=e;for(let g=0;g0?l.filterByCondition(this.currentRawDataSources,d):this.currentDataSources;this.currentDataSources=f;const g=f.filter(A=>A.auto_fetch!==!1&&A.type!=="websocket");if(g.length===0){B.log("No auto_fetch data sources to refetch");return}B.log(`Refetching ${g.length} auto_fetch data sources`),Na.setPending(!0);const m=Za().currentLayoutJson,b=m?.transition_overlay,v=Array.isArray(b?.wait_for)?b.wait_for:[],S=g.some(A=>(A.loading_strategy||"progressive")==="blocking"),E=v.length>0&&g.some(A=>v.includes(A.id)&&A.type!=="websocket"&&(A.loading_strategy||"progressive")!=="background");if((S||E)&&b&&typeof b=="object"){const A=a?.transitionOverlayTarget||b.target;b.enabled&&b.style==="skeleton"&&b.skeleton?.component&&A?this.renderSkeletonOverlay(A,b.skeleton,m,b.fallback_target):b.enabled&&b.style==="spinner"&&A&&this.renderSpinnerOverlay(A,b.spinner,b.fallback_target)}try{const A=new va;this.currentGlobalHeaders.length>0&&A.setGlobalHeaders(this.currentGlobalHeaders);const T=Za(),L=T.currentDataContext?._global||{},M=await A.fetchDataSourcesWithResults(g,this.currentRouteParams,this.currentQueryParams,L,void 0,{ignoreAutoFetch:!1}),R={},D={},U=new Map(g.map(j=>[j.id,j]));for(const j of M){const P=U.get(j.id);if(!P){B.warn(`Refetch result id not found in autoFetchDataSources: ${j.id}`);continue}const X=j.id;j.state==="success"&&j.data!==void 0?(this.currentFetchedData[X]=j.data,R[X]=j.data,this.processInitOptions([P],{[X]:j.data},D),B.log(`Data source refetched: ${X}`)):j.state==="error"&&B.error(`Failed to refetch data source: ${X}`,j.error)}if(T.bindingEngine){const j=Object.keys(R);j.push("query"),T.bindingEngine.invalidateCacheByKeys(j)}if(Object.keys(D).length>0&&(R._localInit=D),Object.keys(R).length>0){if(R.query=sy(this.currentQueryParams),T.currentLayoutJson?.computed&&Object.keys(T.currentLayoutJson.computed).length>0){const j={...T.currentDataContext,...R,query:R.query},P=this.calculateComputed(T.currentLayoutJson.computed,j);Object.keys(P).length>0&&(R._computed=P,this.globalState._computed=P,B.log("Computed values recalculated in updateQueryParams:",Object.keys(P)))}ls(R,{sync:!0}),B.log("Template data updated with new query params")}}catch(A){B.error("Error in updateQueryParams:",A)}finally{Na.setPending(!1),this.hideTransitionOverlay()}}calculateComputed(e,a){const r={},i=new wn;for(const[l,u]of Object.entries(e))try{let d;if(this.isComputedSwitchDefinition(u))d=i.resolveSwitch(u,a,{skipCache:!0});else if(typeof u=="string")if(u.startsWith("{{")&&u.endsWith("}}")){const f=u.slice(2,-2).trim();d=this.evaluateComputedExpression(f,a)}else d=u;r[l]=d,B.log(`Computed ${l}:`,d)}catch(d){B.warn(`Failed to calculate computed value: ${l}`,d),r[l]=void 0}return r}isComputedSwitchDefinition(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&"$switch"in e&&"$cases"in e}evaluateComputedExpression(e,a){try{return new Function("ctx",` + `)(a)}return!!e}catch(r){return B.warn(`Failed to evaluate script condition: ${e}`,r),!1}}showInitError(e){if(td()){B.warn("Init failed while document is unloading — skipping error screen",e);return}const a=ry(e);cf.renderFromError("app",a,"초기화 실패",this.config.debug,{templateId:this.config.templateId,locale:this.config.locale},void 0,e)}showTransitionOverlay(e,a){const r=typeof e=="boolean"?{enabled:e,style:"opaque",target:void 0,skeleton:void 0,spinner:void 0}:{enabled:e.enabled,style:e.style||"opaque",target:e.target,skeleton:e.skeleton,spinner:e.spinner,fallback_target:e.fallback_target};if(!r.enabled)return;if(this.hideTransitionOverlay(),r.style==="skeleton"&&r.skeleton?.component&&r.target&&a){this.renderSkeletonOverlay(r.target,r.skeleton,a,r.fallback_target);return}if(r.style==="spinner"&&r.target){this.renderSpinnerOverlay(r.target,r.spinner,r.fallback_target);return}const i=document.documentElement.classList.contains("dark");let l,u="";switch(r.style){case"blur":l=i?"rgba(17,24,39,0.3)":"rgba(255,255,255,0.3)",u="backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);";break;case"fade":l=i?"rgba(17,24,39,0.8)":"rgba(255,255,255,0.8)";break;case"skeleton":l=i?"rgb(17,24,39)":"rgb(249,250,251)";break;default:l=i?"rgb(17,24,39)":"rgb(249,250,251)";break}if(r.target){const d=`#${CSS.escape(r.target)}`,f=document.createElement("style");f.id="g7-transition-overlay",f.textContent=`${d}{position:relative;z-index:0;}${d}::after{content:'';position:absolute;inset:0;background:${l};${u}z-index:2147483647;pointer-events:none;}`,document.head.appendChild(f),this.transitionOverlayEl=f}else{const d=document.createElement("div");d.id="g7-transition-overlay",d.setAttribute("aria-hidden","true"),d.style.position="fixed",d.style.inset="0",d.style.zIndex="9999",d.style.pointerEvents="none",d.style.background=l;for(const f of u.split(";")){const g=f.indexOf(":");g!==-1&&d.style.setProperty(f.slice(0,g).trim(),f.slice(g+1).trim())}document.body.appendChild(d),this.transitionOverlayEl=d}}hideTransitionOverlay(){this.transitionOverlayEl&&(this.transitionOverlayEl.remove(),this.transitionOverlayEl=null),this.hideSkeletonOverlay()}renderSkeletonOverlay(e,a,r,i){const u=da.getInstance().getComponent(a.component);if(!u){B.log(`Skeleton component "${a.component}" not found in registry, falling back to opaque overlay`),this.showTransitionOverlay({enabled:!0,style:"opaque",target:e});return}let d=document.getElementById(e),f="target";if(!d&&i&&(d=document.getElementById(i),f="fallback"),d||(d=document.getElementById("app"),f="fullpage"),!d){B.log(`Skeleton overlay: no target found (target="#${e}", fallback="${i||"none"}"), falling back to opaque overlay`),this.showTransitionOverlay({enabled:!0,style:"opaque",target:e});return}this.hideSkeletonOverlay();const m=document.documentElement.classList.contains("dark")?"rgb(17,24,39)":"rgb(249,250,251)",b=f==="fullpage"?"app":f==="fallback"?i:e,v=`#${CSS.escape(b)}`,S=document.createElement("style");S.id="g7-skeleton-overlay-style",S.textContent=`${v}{position:relative;z-index:0;}${v}::after{content:'';position:absolute;inset:0;background:${m};z-index:2147483646;pointer-events:none;}`,document.head.appendChild(S),this.transitionOverlayEl=S;const E=document.createElement("div");if(E.id="g7-skeleton-overlay",E.setAttribute("role","status"),E.setAttribute("aria-busy","true"),E.setAttribute("aria-label","Loading..."),f==="fullpage")E.style.cssText=["position:fixed","inset:0","z-index:20","overflow:hidden","pointer-events:none",`background:${m}`].join(";")+";";else{const R=d.getBoundingClientRect(),D=window.scrollX||document.documentElement.scrollLeft,U=window.scrollY||document.documentElement.scrollTop;E.style.cssText=["position:absolute",`top:${R.top+U}px`,`left:${R.left+D}px`,`width:${R.width}px`,`height:${R.height}px`,"z-index:20","overflow:hidden","pointer-events:none",`background:${m}`].join(";")+";"}document.body.appendChild(E),this.skeletonOverlayContainer=E;const A=r.components||[];let T;if(f==="fullpage")T=A;else{const R=f==="fallback"?i:e;T=this.findComponentChildrenById(A,R)}const L=Ju.createRoot(E);this.skeletonOverlayRoot=L,Ar.flushSync(()=>{L.render(Ye.createElement(u,{components:T,options:{animation:a.animation||"pulse",iteration_count:a.iteration_count||5}}))});const M=f==="fullpage"?"fullpage (#app)":f==="fallback"?`fallback (#${i})`:`target (#${e})`;B.log(`Skeleton overlay rendered [${M}] with "${a.component}" (${T.length} components)`)}findComponentChildrenById(e,a){const r=i=>{for(const l of i){if(l.id===a)return l.children||[];if(l.children&&Array.isArray(l.children)){const u=r(l.children);if(u!==null)return u}}return null};return r(e)||e}renderSpinnerOverlay(e,a,r){let i=document.getElementById(e),l="target";if(!i&&r&&(i=document.getElementById(r),l="fallback"),i||(i=document.getElementById("app"),l="fullpage"),!i){B.log(`Spinner overlay: no target found (target="#${e}", fallback="${r||"none"}"), falling back to opaque overlay`),this.showTransitionOverlay({enabled:!0,style:"opaque",target:e});return}this.hideSkeletonOverlay();const u=l==="fullpage"?"app":l==="fallback"?r:e,d=`#${CSS.escape(u)}`,f=document.createElement("style");f.id="g7-skeleton-overlay-style",f.textContent=[`${d}{position:relative;}`,"@keyframes g7-spin{to{transform:rotate(360deg)}}"].join(""),document.head.appendChild(f),this.transitionOverlayEl=f;const g=a?.text||window.G7Core?.t?.("nav.loading")||"";this._spinnerState={target:e,fallbackTarget:r,spinnerConfig:a,resolvedText:g},this._mountSpinnerInTarget(i);const m=l==="fullpage"?"fullpage (#app)":l==="fallback"?`fallback (#${r})`:`target (#${e})`,b=a?.component||"default spinner";B.log(`Spinner overlay rendered [${m}] with "${b}"`)}_mountSpinnerInTarget(e){if(!this._spinnerState)return;const{spinnerConfig:a,resolvedText:r}=this._spinnerState;if(this.skeletonOverlayRoot){try{this.skeletonOverlayRoot.unmount()}catch{}this.skeletonOverlayRoot=null}if(this.skeletonOverlayContainer){try{this.skeletonOverlayContainer.remove()}catch{}this.skeletonOverlayContainer=null}const i=document.createElement("div");if(i.id="g7-skeleton-overlay",i.setAttribute("role","status"),i.setAttribute("aria-busy","true"),e.appendChild(i),this.skeletonOverlayContainer=i,a?.component){const u=da.getInstance().getComponent(a.component);if(u){const d=Ju.createRoot(i);this.skeletonOverlayRoot=d,Ar.flushSync(()=>{d.render(Ye.createElement(u,{options:{text:r}}))});return}B.log(`Spinner component "${a.component}" not found in registry, using default spinner`)}i.innerHTML='
'}reattachSpinnerOverlay(){if(!this._spinnerState)return;const{target:e,fallbackTarget:a}=this._spinnerState;let r=document.getElementById(e);!r&&a&&(r=document.getElementById(a)),r||(r=document.getElementById("app")),r&&(this._mountSpinnerInTarget(r),B.log("Spinner overlay reattached to new DOM target"))}hideSkeletonOverlay(){if(this.skeletonOverlayRoot){try{this.skeletonOverlayRoot.unmount()}catch{}this.skeletonOverlayRoot=null}if(this.skeletonOverlayContainer){try{this.skeletonOverlayContainer.parentNode&&this.skeletonOverlayContainer.remove()}catch{}this.skeletonOverlayContainer=null}const e=document.getElementById("g7-skeleton-overlay-style");e&&e.remove(),this._spinnerState=null}showRouteError(e){if(e instanceof ba&&e.details?.status===401){const r=this.config.templateId||"",i=window.location.pathname,l=r.includes("admin")||i.startsWith("/admin")?"admin":"user",u=i+window.location.search,d=!!$a().getToken()||e.details?.hadToken===!0,f=ha.getInstance().getLoginRedirectUrl(l,u,d?"session_expired":void 0);window.location.href=f;return}const a=ry(e);cf.renderFromError("app",a,"페이지 로딩 실패",this.config.debug,{templateId:this.config.templateId,locale:this.config.locale},void 0,e)}async handleServerError(){const e=window.G7Error;if(!e)return!1;B.warn("Server error detected:",e);try{return this.errorPageHandler&&(e.data&&(this.globalState.errorData=e.data),this.errorPageHandler.updateGlobalState(this.globalState),this.errorPageHandler.updateLocale(this.config.locale),await this.errorPageHandler.renderError(e.code,"app"))?(B.log(`${e.code} error page rendered successfully`),!0):(B.log(`Falling back to ErrorDisplay for ${e.code}`),this.showInitError(new Error(`Service unavailable (${e.code})`)),!0)}catch(a){return B.error(`Failed to render ${e.code} page:`,a),this.showInitError(new Error(`Service unavailable (${e.code})`)),!0}}async handleRouteNotFound(e){B.warn("Route not found:",e);try{if(this.errorPageHandler&&(this.errorPageHandler.updateGlobalState(this.globalState),this.errorPageHandler.updateLocale(this.config.locale),await this.errorPageHandler.renderError(404,"app"))){B.log("404 error page rendered successfully");return}B.log("Falling back to ErrorDisplay for 404"),this.showRouteError(new Error(`Page not found: ${e}`))}catch(a){B.error("Failed to render 404 page:",a),this.showRouteError(new Error(`Page not found: ${e}`))}}getRouter(){return this.router}getConfig(){return this.config}getLayoutLoader(){return this.layoutLoader}async reloadExtensionState(){B.log("reloadExtensionState: start");let e;try{const a=await fetch(La(`/api/templates/${this.config.templateId}/config`,"json",null,`_=${Date.now()}`));if(a.ok){const r=await a.json();r?.success&&r?.data?.cache_version!==void 0&&(e=r.data.cache_version)}}catch(a){B.warn("reloadExtensionState: failed to fetch config.json",a)}e!==void 0&&e!==this.extensionCacheVersion&&(B.log(`reloadExtensionState: cache version ${this.extensionCacheVersion} -> ${e}`),this.extensionCacheVersion=e,this.saveCacheVersionToStorage(e));try{this.router&&(await this.router.loadRoutes(this.extensionCacheVersion),B.log("reloadExtensionState: routes reloaded"))}catch(a){B.error("reloadExtensionState: routes reload failed",a)}try{this.layoutLoader&&(this.extensionCacheVersion>0&&this.layoutLoader.setCacheVersion(this.extensionCacheVersion),this.layoutLoader.clear(),B.log("reloadExtensionState: layout cache cleared"))}catch(a){B.error("reloadExtensionState: layout cache clear failed",a)}try{const{TranslationEngine:a}=await Promise.resolve().then(()=>tp),r=a.getInstance();this.extensionCacheVersion>0&&r.setCacheVersion(this.extensionCacheVersion);const i=this.config.locale||"ko",l="en";await r.loadTranslations(this.config.templateId,i,"/api",!0),i!==l&&await r.loadTranslations(this.config.templateId,l,"/api",!0),B.log("reloadExtensionState: translations reloaded")}catch(a){B.error("reloadExtensionState: translations reload failed",a)}try{const a=await fetch(`/api/locales/active?_=${Date.now()}`);if(a.ok){const i=(await a.json())?.data?.locales;if(Array.isArray(i)&&i.length>0){const l=this.globalState.appConfig??{};this.setGlobalState({appConfig:{...l,supportedLocales:i}}),B.log("reloadExtensionState: supportedLocales refreshed",i)}}}catch(a){B.warn("reloadExtensionState: supportedLocales refresh failed",a)}B.log("reloadExtensionState: done")}getActionDispatcher(){return Za().actionDispatcher}async changeLocale(e){try{if(B.log("Changing locale to:",e),this.config.locale===e){B.log("Locale is already",e);return}this.config.locale=e,this.saveLocaleToStorage(e),await this.saveLocaleToDatabase(e),this.layoutLoader&&(this.layoutLoader.clear(),B.log("Layout cache cleared")),this.errorPageHandler&&(this.errorPageHandler.updateLocale(e),B.log("ErrorPageHandler locale updated")),yc(),await Ao({templateId:this.config.templateId,templateType:this.config.templateType,locale:e,debug:this.config.debug,cacheVersion:this.extensionCacheVersion}),B.log("Template Engine re-initialized with new locale");const{getActionDispatcher:a}=await Promise.resolve().then(()=>za),r=a();r&&(r.setDefaultContext({navigate:i=>this.router?.navigate(i)}),r.setGlobalStateUpdater((i,l)=>this.setGlobalState(i,l)),B.log("Navigate function and setGlobalState re-injected to ActionDispatcher")),this.reinitializeModuleHandlers(),B.log("Module handlers re-initialized"),this.reinitializeTemplateHandlers(),B.log("Template handlers re-initialized"),this.reinitializePluginHandlers(),B.log("Plugin handlers re-initialized"),this.router&&this.router.navigateToCurrentPath(),B.log("Locale changed successfully to",e)}catch(a){throw B.error("Failed to change locale:",a),a}}loadLocaleFromStorage(){try{return localStorage.getItem(Ca.LOCALE_STORAGE_KEY)}catch(e){return B.warn("Failed to load locale from storage:",e),null}}saveLocaleToStorage(e){try{localStorage.setItem(Ca.LOCALE_STORAGE_KEY,e)}catch(a){B.warn("Failed to save locale to storage:",a)}}async saveLocaleToDatabase(e){const a=localStorage.getItem("auth_token");if(!a){B.log("No auth token, skipping DB locale save");return}let r,i;if(this.config.localeApi)r=this.config.localeApi.endpoint,i=this.config.localeApi.method;else{const l=this.config.templateType==="admin";r=l?"/api/admin/users/me/language":"/api/user/profile/update-language",i=l?"PATCH":"POST"}try{const l=this.getXsrfToken(),u=await fetch(r,{method:i,headers:{"Content-Type":"application/json",Accept:"application/json",...l&&{"X-XSRF-TOKEN":l},Authorization:`Bearer ${a}`},credentials:"include",body:JSON.stringify({language:e})});u.ok?B.log("Locale saved to DB:",e):B.warn("Failed to save locale to DB (UI will still change):",u.statusText)}catch(l){B.warn("Failed to call locale API (UI will still change):",l)}}getXsrfToken(){if(typeof document>"u")return null;const a=`; ${document.cookie}`.split("; XSRF-TOKEN=");return a.length===2?decodeURIComponent(a.pop()?.split(";").shift()||""):null}loadCacheVersionFromStorage(){try{const e=localStorage.getItem(Ca.CACHE_VERSION_STORAGE_KEY);return e?parseInt(e,10):null}catch(e){return B.warn("Failed to load cache version from storage:",e),null}}saveCacheVersionToStorage(e){try{localStorage.setItem(Ca.CACHE_VERSION_STORAGE_KEY,String(e))}catch(a){B.warn("Failed to save cache version to storage:",a)}}reinitializeModuleHandlers(){if(typeof window>"u")return;const e="__",a=window;Object.keys(a).forEach(r=>{if(r.startsWith(e)&&typeof a[r]?.initModule=="function")try{a[r].initModule(),B.log(`Module handler re-initialized: ${r}`)}catch(i){B.warn(`Failed to re-initialize module handlers for ${r}:`,i)}})}reinitializeTemplateHandlers(){if(typeof window>"u")return;const e=window.G7TemplateHandlers;if(!e){B.warn("Template handlers not found on window.G7TemplateHandlers");return}const a=this.getActionDispatcher();if(!a){B.warn("ActionDispatcher not available for template handler registration");return}Object.entries(e).forEach(([r,i])=>{a.registerHandler(r,i)}),B.log(`${Object.keys(e).length} template handler(s) re-registered:`,Object.keys(e))}reinitializePluginHandlers(){if(typeof window>"u")return;const e="__",a=window;Object.keys(a).forEach(r=>{if(r.startsWith(e)&&typeof a[r]?.initPlugin=="function")try{a[r].initPlugin(),B.log(`Plugin handler re-initialized: ${r}`)}catch(i){B.warn(`Failed to re-initialize plugin handlers for ${r}:`,i)}})}getLocale(){return this.config.locale}getErrorPageHandler(){return this.errorPageHandler}getGlobalState(){return{...this.globalState}}setGlobalState(e,a){const r={...this.globalState};typeof e=="function"?this.globalState=e(this.globalState):this.globalState={...this.globalState,...e},B.log("Global state updated:",this.globalState),window.G7Core?.devTools?.captureStateSnapshot?.({source:"setGlobalState",prev:r,next:this.globalState}),this.globalStateListeners.forEach(l=>{l(this.globalState)}),a?.render!==!1&&Promise.resolve().then(()=>za).then(({updateTemplateData:l,getState:u})=>{const d=u();d.reactRoot&&d.currentLayoutJson&&l({_global:{...this.globalState},_local:this.globalState._local||{}})})}onGlobalStateChange(e){this.globalStateListeners.add(e)}offGlobalStateChange(e){this.globalStateListeners.delete(e)}async refetchDataSource(e,a){let r=this.currentDataSources.find(i=>i.id===e);if(!r)for(const[,i]of this.modalDataSources){const l=i.find(u=>u.id===e);if(l){r=l;break}}if(!r){B.warn(`Data source not found: ${e}`);return}B.log(`Refetching data source: ${e}`,a?.sync?"(sync mode)":"",a?.globalStateOverride?"(with global override)":"",a?.localStateOverride?"(with local override)":""),Na.setPending(!0);try{const i=new va;this.currentGlobalHeaders.length>0&&i.setGlobalHeaders(this.currentGlobalHeaders);const l=Za(),u=l.currentDataContext?._global||{},d=a?.globalStateOverride?{...u,...a.globalStateOverride}:u,f=l.currentDataContext?._local||{},g=a?.localStateOverride?{...f,...a.localStateOverride}:f,b=(await i.fetchDataSourcesWithResults([r],this.currentRouteParams,this.currentQueryParams,d,g,{ignoreAutoFetch:!0}))[0];if(b.state==="success"&&b.data!==void 0){this.currentFetchedData[e]=b.data;const v={};this.processInitOptions([r],{[e]:b.data},v);const S=Za();if(S.bindingEngine){const A=[e];r.initGlobal&&A.push("_global"),r.initLocal&&A.push("_local"),S.bindingEngine.invalidateCacheByKeys(A)}const E={[e]:b.data};return Object.keys(v).length>0&&(E._localInit=v),r.initGlobal&&(E._global={...this.globalState}),cs(E,a?.sync?{sync:!0}:void 0),B.log(`Data source refetched successfully: ${e}`),b.data}else if(b.state==="error"){B.error(`Failed to refetch data source: ${e}`,b.error);return}}catch(i){B.error(`Error refetching data source: ${e}`,i);return}finally{Na.setPending(!1)}}registerModalDataSources(e,a){this.modalDataSources.set(e,a),B.log(`Modal data sources registered: ${e} (${a.length} sources)`)}unregisterModalDataSources(e){this.modalDataSources.delete(e),B.log(`Modal data sources unregistered: ${e}`)}getDataSource(e){return this.currentFetchedData[e]}setDataSource(e,a,r){if(!e){B.warn("setDataSource: dataSourceId is required");return}const{merge:i=!1,sync:l=!1}=r||{};i&&this.currentFetchedData[e]?this.currentFetchedData[e]={...this.currentFetchedData[e],...a}:this.currentFetchedData[e]=a,Promise.resolve().then(()=>za).then(({updateTemplateData:u})=>{u({[e]:this.currentFetchedData[e]},l?{sync:!0}:void 0)}),B.log(`setDataSource: Updated ${e}`,i?"(merged)":"(replaced)")}updateDataSourceItem(e,a,r,i,l){const{idField:u="id",merge:d=!0,skipRender:f=!1}=l||{},g=this.currentFetchedData[e];if(!g)return B.warn(`updateDataSourceItem: DataSource '${e}' not found`),!1;const m=this.parseItemPath(a);let b=g;for(const E of m)if(b=b?.[E],b===void 0)return B.warn(`updateDataSourceItem: Path '${a}' not found in dataSource`),!1;if(!Array.isArray(b))return B.warn(`updateDataSourceItem: Target at '${a}' is not an array`),!1;const v=b.findIndex(E=>String(E[u])===String(r));if(v===-1)return B.warn(`updateDataSourceItem: Item with ${u}='${r}' not found`),!1;d?b[v]=this.deepMerge(b[v],i):b[v]={...b[v],...i};const S=window.G7Core?.devTools;return S?.isEnabled?.()&&S.trackDataSourceUpdate?.({dataSourceId:e,updateType:"partial",itemPath:a,itemId:r,updates:i,timestamp:Date.now()}),f||Promise.resolve().then(()=>za).then(({updateTemplateData:E})=>{E({[e]:this.currentFetchedData[e]},{sync:!1})}),B.log(`updateDataSourceItem: Updated ${e}.${a}[${u}=${r}]`),!0}parseItemPath(e){const a=[],r=/([^\.\[\]]+)|\[(\d+)\]/g;let i;for(;(i=r.exec(e))!==null;)i[1]!==void 0?a.push(i[1]):i[2]!==void 0&&a.push(parseInt(i[2],10));return a}deepMerge(e,a){if(a==null)return e;if(typeof a!="object"||Array.isArray(a))return a;const r={...e};for(const i of Object.keys(a))typeof a[i]=="object"&&a[i]!==null&&!Array.isArray(a[i])?r[i]=this.deepMerge(r[i]||{},a[i]):r[i]=a[i];return r}setValueAtPath(e,a,r,i="deep"){const l=a.split(".");let u=e;for(let g=0;g0?l.filterByCondition(this.currentRawDataSources,d):this.currentDataSources;this.currentDataSources=f;const g=f.filter(A=>A.auto_fetch!==!1&&A.type!=="websocket");if(g.length===0){B.log("No auto_fetch data sources to refetch");return}B.log(`Refetching ${g.length} auto_fetch data sources`),Na.setPending(!0);const m=Za().currentLayoutJson,b=m?.transition_overlay,v=Array.isArray(b?.wait_for)?b.wait_for:[],S=g.some(A=>(A.loading_strategy||"progressive")==="blocking"),E=v.length>0&&g.some(A=>v.includes(A.id)&&A.type!=="websocket"&&(A.loading_strategy||"progressive")!=="background");if((S||E)&&b&&typeof b=="object"){const A=a?.transitionOverlayTarget||b.target;b.enabled&&b.style==="skeleton"&&b.skeleton?.component&&A?this.renderSkeletonOverlay(A,b.skeleton,m,b.fallback_target):b.enabled&&b.style==="spinner"&&A&&this.renderSpinnerOverlay(A,b.spinner,b.fallback_target)}try{const A=new va;this.currentGlobalHeaders.length>0&&A.setGlobalHeaders(this.currentGlobalHeaders);const T=Za(),L=T.currentDataContext?._global||{},M=await A.fetchDataSourcesWithResults(g,this.currentRouteParams,this.currentQueryParams,L,void 0,{ignoreAutoFetch:!1}),R={},D={},U=new Map(g.map(j=>[j.id,j]));for(const j of M){const P=U.get(j.id);if(!P){B.warn(`Refetch result id not found in autoFetchDataSources: ${j.id}`);continue}const X=j.id;j.state==="success"&&j.data!==void 0?(this.currentFetchedData[X]=j.data,R[X]=j.data,this.processInitOptions([P],{[X]:j.data},D),B.log(`Data source refetched: ${X}`)):j.state==="error"&&B.error(`Failed to refetch data source: ${X}`,j.error)}if(T.bindingEngine){const j=Object.keys(R);j.push("query"),T.bindingEngine.invalidateCacheByKeys(j)}if(Object.keys(D).length>0&&(R._localInit=D),Object.keys(R).length>0){if(R.query=sy(this.currentQueryParams),T.currentLayoutJson?.computed&&Object.keys(T.currentLayoutJson.computed).length>0){const j={...T.currentDataContext,...R,query:R.query},P=this.calculateComputed(T.currentLayoutJson.computed,j);Object.keys(P).length>0&&(R._computed=P,this.globalState._computed=P,B.log("Computed values recalculated in updateQueryParams:",Object.keys(P)))}cs(R,{sync:!0}),B.log("Template data updated with new query params")}}catch(A){B.error("Error in updateQueryParams:",A)}finally{Na.setPending(!1),this.hideTransitionOverlay()}}calculateComputed(e,a){const r={},i=new wn;for(const[l,u]of Object.entries(e))try{let d;if(this.isComputedSwitchDefinition(u))d=i.resolveSwitch(u,a,{skipCache:!0});else if(typeof u=="string")if(u.startsWith("{{")&&u.endsWith("}}")){const f=u.slice(2,-2).trim();d=this.evaluateComputedExpression(f,a)}else d=u;r[l]=d,B.log(`Computed ${l}:`,d)}catch(d){B.warn(`Failed to calculate computed value: ${l}`,d),r[l]=void 0}return r}isComputedSwitchDefinition(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&"$switch"in e&&"$cases"in e}evaluateComputedExpression(e,a){try{return new Function("ctx",` with(ctx) { try { return ${e}; @@ -240,5 +240,5 @@ Error generating stack: `+c.message+` return undefined; } } - `)(a)}catch(r){B.warn(`Expression evaluation failed: ${e}`,r);return}}async executeInitActions(e,a={}){const{getActionDispatcher:r}=await Promise.resolve().then(()=>za),i=r();if(!i){B.warn("ActionDispatcher not available for init_actions");return}B.log("Executing init_actions:",e.map(d=>d.handler)),B.log("Init actions dataContext:",a),B.log("Init actions dataContext._global:",a._global);const l=e.map(d=>d.handler).filter(d=>d.includes("."));l.length>0&&await this.waitForHandlers(i,l);let u={...a};for(const d of e)try{const f={type:"click",handler:d.handler,target:d.target,params:d.params,resultTo:d.resultTo,onSuccess:d.onSuccess,onError:d.onError,if:d.if,conditions:d.conditions,auth_mode:d.auth_mode,auth_required:d.auth_required},g=i.createHandler(f,u),m=new Event("init");await g(m),B.log(`Init action executed: ${d.handler}`);const b=this.globalState;u={...u,_global:{...b},_local:b._local||u._local||{}},B.log(`Data context refreshed after ${d.handler}:`,{cartKey:u._global?.cartKey})}catch(f){B.error(`Failed to execute init action: ${d.handler}`,f)}}async waitForHandlers(e,a,r=5e3){const i=Date.now(),l=50,u=()=>a.every(f=>e.customHandlers?.has(f));if(u()){B.log("All module handlers already registered");return}const d=uf().getFailedJsAssets();if(d.length>0){const f=d.some(b=>b==="module"||b==="plugin"),g=a.filter(b=>!e.customHandlers?.has(b)),m=g.length>0&&g.every(b=>d.some(v=>b.startsWith(`${v}.`)));if(f||m){B.warn("Extension asset load failed — not waiting for handlers that will never register:",{pending:g,failedAssets:d});return}}return B.log("Waiting for module handlers:",a),new Promise(f=>{const g=()=>{if(u()){B.log("All module handlers now registered"),f();return}if(Date.now()-i>=r){const m=a.filter(b=>!e.customHandlers?.has(b));B.warn("Timeout waiting for handlers:",m),f();return}setTimeout(g,l)};g()})}};$(Ca,"LOCALE_STORAGE_KEY","g7_locale"),$(Ca,"CACHE_VERSION_STORAGE_KEY","g7_cache_version");let vo=Ca;function ff(o){const e=new vo(o);return o.websocket&&(fc.configure(o.websocket),B.log("WebSocket 설정 완료")),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{e.init(),window.__templateApp=e}):(e.init(),window.__templateApp=e),e}typeof window<"u"&&(window.G7Core=window.G7Core||{},window.G7Core.initTemplateApp=ff,window.G7Core.dataSource={refetch:async(o,e)=>{const a=window.__templateApp;if(!a){B.warn("TemplateApp not initialized (G7Core.dataSource.refetch)");return}return a.refetchDataSource(o,e)},get:o=>{const e=window.__templateApp;if(!e){B.warn("TemplateApp not initialized (G7Core.dataSource.get)");return}return e.getDataSource(o)}});function K_(o={}){const{checked:e,value:a,name:r,type:i="checkbox"}=o,u=a!==void 0?a:i==="checkbox"||i==="radio"?e??!1:String(e??""),d={checked:e??!1,value:u,name:r??"",type:i};return{target:d,currentTarget:d,preventDefault:()=>{},stopPropagation:()=>{},nativeEvent:new Event("change"),bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:Event.AT_TARGET,isTrusted:!1,timeStamp:Date.now(),type:"change",isDefaultPrevented:()=>!1,isPropagationStopped:()=>!1,persist:()=>{}}}function W_(o={}){const{button:e=0,clientX:a=0,clientY:r=0}=o;return{button:e,clientX:a,clientY:r,preventDefault:()=>{},stopPropagation:()=>{},nativeEvent:new MouseEvent("click"),bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:Event.AT_TARGET,isTrusted:!1,timeStamp:Date.now(),type:"click",isDefaultPrevented:()=>!1,isPropagationStopped:()=>!1,persist:()=>{},target:document.createElement("div"),currentTarget:document.createElement("div")}}function Y_(){return{preventDefault:()=>{},stopPropagation:()=>{},nativeEvent:new Event("submit"),bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:Event.AT_TARGET,isTrusted:!1,timeStamp:Date.now(),type:"submit",isDefaultPrevented:()=>!1,isPropagationStopped:()=>!1,persist:()=>{},target:document.createElement("form"),currentTarget:document.createElement("form")}}function X_(o,e="keydown"){return{key:o,code:o.length===1?`Key${o.toUpperCase()}`:o,preventDefault:()=>{},stopPropagation:()=>{},nativeEvent:new KeyboardEvent(e,{key:o}),bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:Event.AT_TARGET,isTrusted:!1,timeStamp:Date.now(),type:e,isDefaultPrevented:()=>!1,isPropagationStopped:()=>!1,persist:()=>{},target:document.createElement("div"),currentTarget:document.createElement("div"),altKey:!1,ctrlKey:!1,metaKey:!1,shiftKey:!1,repeat:!1}}const J_={justify:/^justify-(start|end|center|between|around|evenly)$/,items:/^items-(start|end|center|baseline|stretch)$/,content:/^content-(start|end|center|between|around|evenly|stretch)$/,self:/^self-(auto|start|end|center|stretch|baseline)$/,flex:/^flex-(row|row-reverse|col|col-reverse|wrap|wrap-reverse|nowrap|1|auto|initial|none)$/,grow:/^(grow|grow-0)$/,shrink:/^(shrink|shrink-0)$/,basis:/^basis-/,order:/^(order-|-)order-/,gap:/^gap(-x|-y)?-/,gridCols:/^grid-cols-/,gridRows:/^grid-rows-/,colSpan:/^col-(span-|start-|end-)/,rowSpan:/^row-(span-|start-|end-)/,display:/^(block|inline-block|inline|flex|inline-flex|table|inline-table|table-caption|table-cell|table-column|table-column-group|table-footer-group|table-header-group|table-row-group|table-row|flow-root|grid|inline-grid|contents|list-item|hidden)$/,position:/^(static|fixed|absolute|relative|sticky)$/,inset:/^(inset|top|right|bottom|left)-/,zIndex:/^z-/,width:/^w-/,minWidth:/^min-w-/,maxWidth:/^max-w-/,height:/^h-/,minHeight:/^min-h-/,maxHeight:/^max-h-/,padding:/^p[xytblr]?-/,margin:/^-?m[xytblr]?-/,space:/^space-(x|y)-/,fontSize:/^text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl)$/,fontWeight:/^font-(thin|extralight|light|normal|medium|semibold|bold|extrabold|black)$/,fontStyle:/^(italic|not-italic)$/,fontFamily:/^font-(sans|serif|mono)/,textAlign:/^text-(left|center|right|justify|start|end)$/,textColor:/^text-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-/,textDecoration:/^(underline|overline|line-through|no-underline)$/,textTransform:/^(uppercase|lowercase|capitalize|normal-case)$/,lineHeight:/^leading-/,letterSpacing:/^tracking-/,textOverflow:/^(truncate|text-ellipsis|text-clip)$/,whitespace:/^whitespace-/,wordBreak:/^break-/,bgColor:/^bg-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-/,bgGradient:/^bg-gradient-/,bgSize:/^bg-(auto|cover|contain)$/,bgPosition:/^bg-(bottom|center|left|left-bottom|left-top|right|right-bottom|right-top|top)$/,bgRepeat:/^bg-(repeat|no-repeat|repeat-x|repeat-y|repeat-round|repeat-space)$/,bgAttachment:/^bg-(fixed|local|scroll)$/,bgClip:/^bg-clip-/,bgOrigin:/^bg-origin-/,borderWidth:/^border(-[xytblr])?(-0|-2|-4|-8)?$/,borderColor:/^border-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-/,borderStyle:/^border-(solid|dashed|dotted|double|hidden|none)$/,borderRadius:/^rounded(-[tblrse]{1,2})?(-none|-sm|-md|-lg|-xl|-2xl|-3xl|-full)?$/,ringWidth:/^ring(-0|-1|-2|-4|-8|-inset)?$/,ringColor:/^ring-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-/,ringOffset:/^ring-offset-/,shadow:/^shadow(-sm|-md|-lg|-xl|-2xl|-inner|-none)?$/,opacity:/^opacity-/,mixBlend:/^mix-blend-/,bgBlend:/^bg-blend-/,blur:/^blur(-none|-sm|-md|-lg|-xl|-2xl|-3xl)?$/,brightness:/^brightness-/,contrast:/^contrast-/,grayscale:/^grayscale(-0)?$/,hueRotate:/^-?hue-rotate-/,invert:/^invert(-0)?$/,saturate:/^saturate-/,sepia:/^sepia(-0)?$/,backdropBlur:/^backdrop-blur-/,backdropBrightness:/^backdrop-brightness-/,backdropContrast:/^backdrop-contrast-/,backdropGrayscale:/^backdrop-grayscale-/,backdropHueRotate:/^backdrop-hue-rotate-/,backdropInvert:/^backdrop-invert-/,backdropOpacity:/^backdrop-opacity-/,backdropSaturate:/^backdrop-saturate-/,backdropSepia:/^backdrop-sepia-/,scale:/^scale(-x|-y)?-/,rotate:/^-?rotate-/,translate:/^-?translate-[xy]-/,skew:/^-?skew-[xy]-/,transformOrigin:/^origin-/,transition:/^transition(-none|-all|-colors|-opacity|-shadow|-transform)?$/,duration:/^duration-/,ease:/^ease-(linear|in|out|in-out)$/,delay:/^delay-/,animate:/^animate-/,cursor:/^cursor-/,userSelect:/^select-/,pointerEvents:/^pointer-events-/,resize:/^resize(-none|-x|-y)?$/,scrollBehavior:/^scroll-(auto|smooth)$/,touchAction:/^touch-/,overflow:/^overflow(-x|-y)?-(auto|hidden|clip|visible|scroll)$/,overscroll:/^overscroll(-x|-y)?-(auto|contain|none)$/,visibility:/^(visible|invisible|collapse)$/,aspectRatio:/^aspect-/,columns:/^columns-/,breakAfter:/^break-after-/,breakBefore:/^break-before-/,breakInside:/^break-inside-/,boxDecorationBreak:/^box-decoration-/,boxSizing:/^box-(border|content)$/,float:/^float-(right|left|none)$/,clear:/^clear-(left|right|both|none)$/,isolation:/^(isolate|isolation-auto)$/,objectFit:/^object-(contain|cover|fill|none|scale-down)$/,objectPosition:/^object-/};function oy(o){const e=o.replace(/^(dark:|hover:|focus:|active:|disabled:|group-hover:|sm:|md:|lg:|xl:|2xl:)+/,"");for(const[a,r]of Object.entries(J_))if(r.test(e))return a;return null}function ly(o){const e=o.match(/^((dark:|hover:|focus:|active:|disabled:|group-hover:|sm:|md:|lg:|xl:|2xl:)+)/);return e?e[1]:""}function Q_(o,e){if(!e||e.trim()==="")return o;if(!o||o.trim()==="")return e;const a=o.split(/\s+/).filter(Boolean),r=e.split(/\s+/).filter(Boolean),i=new Map;for(const u of r){const d=oy(u);if(d){const f=ly(u),g=`${d}:${f}`;i.set(g,u)}}return[...a.filter(u=>{const d=oy(u);if(!d)return!0;const f=ly(u),g=`${d}:${f}`;return!i.has(g)}),...r].join(" ")}function Z_(o){return Object.entries(o).filter(([,e])=>e).map(([e])=>e).join(" ")}function eA(...o){return o.filter(e=>typeof e=="string"&&e.length>0).join(" ")}const we=ct("G7CoreGlobals");function tA(){window.React=Ye,window.ReactDOM={...Ju,createPortal:Ar.createPortal,unstable_batchedUpdates:o=>o()},window.ReactJSXRuntime=J0,we.log("전역 객체 window.React, window.ReactDOM, window.ReactJSXRuntime에 노출됨")}function nA(o){const e=new Map,a=Tr.getInstance();o.componentEvent={on:(r,i)=>(e.has(r)||e.set(r,new Set),e.get(r).add(i),a.trackEventSubscribe(r),()=>{e.get(r)?.delete(i),a.trackEventUnsubscribe(r)}),emit:async(r,i)=>{const l=e.get(r),u=l?.size??0;if(!l||l.size===0)return a.trackEventEmit(r,i,0),[];let d,f=[];try{f=await Promise.all(Array.from(l).map(async g=>{try{return await g(i)}catch(m){throw we.error(`componentEvent: Error in listener for "${r}":`,m),m}}))}catch(g){d=g instanceof Error?g:new Error(String(g))}if(a.trackEventEmit(r,i,u,f,d),d)throw d;return f},off:r=>{e.delete(r),a.trackEventOff(r)},clear:()=>{e.clear(),a.trackEventClear()}},we.log("전역 객체 window.G7Core.componentEvent에 노출됨")}function aA(o){o.__runtime||(o.__runtime={DynamicRenderer:Ha,ComponentRegistry:da,TranslationEngine:Cr,DataSourceManager:va,dataSourceManager:I_,DataBindingEngine:wn,dataBindingEngine:XS,ActionDispatcher:oo,TranslationReactContext:tf,TranslationProvider:cc,useTranslation:Fm,ResponsiveContext:Ld,ResponsiveProvider:Xl,useResponsive:Md,responsiveManager:ci,BREAKPOINT_PRESETS:kl,AuthManager:ha,createLogger:ct,G7DevToolsCore:Tr},we.log("전역 객체 window.G7Core.__runtime(코어 런타임 표면)에 노출됨"))}function rA(o){if(o.layoutEditor&&o.layoutEditor.__isStub!==!0||o.layoutEditor&&o.layoutEditor.__isStub===!0)return;const e=[],a=[];o.layoutEditor={__isStub:!0,__queue:e,__readyCallbacks:a,registerWidget:(r,i)=>e.push(["widget",r,i]),registerNodeEditor:(r,i)=>e.push(["nodeEditor",r,i]),registerCanvasOverlay:(r,i)=>e.push(["canvasOverlay",r,i]),onReady:r=>{typeof r=="function"&&a.push(r)}},we.log("전역 객체 window.G7Core.layoutEditor 예약 접수함(stub) 노출됨")}function iA(o,e){o.useTranslation=Fm,o.t=(a,r)=>{const i=e.getState();if(!i.translationEngine||!i.translationContext)return a;if(r){const l="|"+Object.entries(r).map(([u,d])=>`${u}=${d}`).join("|");return i.translationEngine.translate(a,i.translationContext,l)}return i.translationEngine.translate(a,i.translationContext)},we.log("전역 객체 window.G7Core.useTranslation에 노출됨")}function sA(o,e){o.createChangeEvent=K_,o.createClickEvent=W_,o.createSubmitEvent=Y_,o.createKeyboardEvent=X_,o.uuid=()=>typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,a=>{const r=Math.random()*16|0;return(a==="x"?r:r&3|8).toString(16)}),o.createLogger=ct,we.log("전역 객체 window.G7Core.createLogger에 노출됨"),o.renderItemChildren=(a,r,i,l,u)=>{const d=e.getState(),m={_global:window.__templateApp?.getGlobalState?.()||{},_local:r._local||{},_computed:r._computed||{},...r},b=new Set,v=(E,A)=>{const T=m._global?._remountKeys;return E&&T?.[E]&&!b.has(E)?(b.add(E),`${E}-remount-${T[E]}`):E||A},S={translationContext:d.translationContext,translationEngine:d.translationEngine,bindingEngine:d.bindingEngine,actionDispatcher:d.actionDispatcher,getRemountKey:v,...u};return Qs(a,m,i,l,S)},o.getComponentMap=()=>da.getInstance().getComponentMap(),o.renderComponentLayout=(a,r,i)=>{if(!a||!Array.isArray(a)||a.length===0)return null;const l=da.getInstance().getComponentMap(),u=e.getState(),f=window.__templateApp?.getGlobalState?.()||{},g={_global:f._global||{},_local:f._local||{},_computed:f._computed||{},...r},m=new Set,b=(v,S)=>{const E=g._global?._remountKeys;return v&&E?.[v]&&!m.has(v)?(m.add(v),`${v}-remount-${E[v]}`):v||S};return Qs(a,g,l,i,{translationContext:u.translationContext,translationEngine:u.translationEngine,bindingEngine:u.bindingEngine,actionDispatcher:u.actionDispatcher,getRemountKey:b})},o.renderExpandContent=a=>{const{children:r,row:i,expandContext:l,componentContext:u,keyPrefix:d}=a;if(!r||!Array.isArray(r)||r.length===0)return null;const f=a.componentMap||da.getInstance().getComponentMap(),g=e.getState(),m=o.state?.get?.()||{},b=u?.stateRef?.current??u?.state??{},v={...m._local||{},...b},S=u?.computedRef?.current??m._computed??{},E=g.bindingEngine??o.getDataBindingEngine?.(),A={...m,_local:v,_computed:S,row:i,item:i,$item:i};let T={};if(l&&typeof l=="object"&&E)try{for(const[D,U]of Object.entries(l))if(typeof U=="string"){const j=U.match(/^\{\{([^}]+)\}\}$/);if(j){const P=j[1].trim();try{T[D]=E.evaluateExpression(P,A,{skipCache:!0})}catch{T[D]=void 0}}else T[D]=E.resolveBindings(U,A,{skipCache:!0})}else T[D]=U}catch(D){we.warn("renderExpandContent: expandContext 평가 오류:",D)}const L={row:i,item:i,$item:i,_local:v,_global:m._global||{},_computed:m._computed||{},...T},M=new Set,R=(D,U)=>{const j=L._global?._remountKeys;return D&&j?.[D]&&!M.has(D)?(M.add(D),`${D}-remount-${j[D]}`):D||U};return Qs(r,L,f,d,{translationContext:g.translationContext,translationEngine:g.translationEngine??void 0,bindingEngine:g.bindingEngine??void 0,actionDispatcher:g.actionDispatcher,componentContext:u,getRemountKey:R})},o.$get=function(r,i,l=void 0){if(r==null)return l;const u=Array.isArray(i)?i:[i];if(u.length===0)return r;let d=r;for(const f of u){if(d==null||f==null)return l;d=d[f]}return d??l},we.log("전역 객체 window.G7Core.renderItemChildren에 노출됨"),we.log("전역 객체 window.G7Core.renderComponentLayout에 노출됨"),we.log("전역 객체 window.G7Core.renderExpandContent에 노출됨"),we.log("전역 객체 window.G7Core.$get에 노출됨")}function oA(o){o.dispatch=async(e,a)=>{const r=window.__templateApp;if(!r)return we.warn("G7Core.dispatch: TemplateApp이 초기화되지 않았습니다."),{success:!1,error:new Error("TemplateApp이 초기화되지 않았습니다.")};const i=r.getActionDispatcher?.();if(!i)return we.warn("G7Core.dispatch: ActionDispatcher를 찾을 수 없습니다."),{success:!1,error:new Error("ActionDispatcher를 찾을 수 없습니다.")};const l=r.getRouter?.(),u=r.getGlobalState?.(),d=r.setGlobalState?.bind(r),g=a?.componentContext||window.__g7ActionContext,m=window.__g7PendingLocalState;let b=g?.state??u;m&&g&&(b=m,we.log("[dispatch] Using __g7PendingLocalState for context.state:",m));let v=g?.data??u;m&&g?.data?._local&&(v={...g.data,_local:m},we.log("[dispatch] Updated context.data._local with pendingLocalState"));const S={navigate:l?(E,A)=>l.navigate(E,A):void 0,setState:g?.setState??d,state:b,data:v,_isDispatchFallbackContext:!g?.setState};if(e.debounce){const E=e.debounceKey||`dispatch-${e.handler}`,A=typeof e.debounce=="number"?e.debounce:e.debounce.delay;return i.debouncedCall(E,A,()=>{const{debounce:T,debounceKey:L,...M}=e;i.dispatchAction(M,S)}),{success:!0,debounced:!0}}try{return await i.dispatchAction(e,S)}catch(E){return we.error("G7Core.dispatch: 액션 실행 오류:",E),{success:!1,error:E instanceof Error?E:new Error(String(E))}}},we.log("전역 객체 window.G7Core.dispatch에 노출됨")}function So(o){const e={};for(const[a,r]of Object.entries(o))if(a.includes(".")){const i=a.split(".");let l=e;for(let u=0;u0&&e.every(a=>/^\d+$/.test(a))}function uy(o,e){const a={...o};for(const r of Object.keys(e))r in a?a[r]!==null&&typeof a[r]=="object"&&!Array.isArray(a[r])&&e[r]!==null&&typeof e[r]=="object"&&!Array.isArray(e[r])&&(a[r]=uy(a[r],e[r])):a[r]=e[r];return a}function Zn(o,e){if(Array.isArray(o)&&!Array.isArray(e)&&lA(e)){const r=Object.keys(e).map(l=>parseInt(l,10));if(!((r.length>0?Math.max(...r):0)>=o.length+r.length+10)){const l=[...o];for(const[u,d]of Object.entries(e)){const f=parseInt(u,10);f>=0&&f=l.length&&(l[f]=d)}return l}}const a={...o};for(const[r,i]of Object.entries(e))i!==null&&typeof i=="object"&&!Array.isArray(i)?a[r]!==null&&typeof a[r]=="object"?a[r]=Zn(a[r],i):a[r]={...i}:a[r]=i;return a}function cA(o){o.state={get:()=>window.__templateApp?.getGlobalState?.()||{},set:(e,a)=>{const r=window.__templateApp;if(r?.setGlobalState&&r?.getGlobalState){const i=a?.merge||"deep",l=So(e);let u;if(i==="replace")u=l;else if(i==="shallow")u={...r.getGlobalState(),...l};else{const d=r.getGlobalState();u=Zn(d,l)}r.setGlobalState(u,{render:a?.render})}else we.warn("G7Core.state.set: TemplateApp이 초기화되지 않았습니다.")},setLocal:(e,a)=>{const r=window.__templateApp;if(a?.render===!1&&!a?.selfManaged){const T=window.__g7AutoBindingPaths;T&&T.size>0&&cy(So(e)).some(M=>T.has(M))&&(we.log("[setLocal] render:false + 자동바인딩 경로 겹침 감지 → render:true 자동 승격 (engine-v1.43.0)"),a={...a,render:!0})}if(a?.debounce){const T=r?.getActionDispatcher?.();if(T){const L=a.debounceKey||`setLocal-${Object.keys(e).join(",")}`,{debounce:M,debounceKey:R,...D}=a;T.debouncedCall(L,a.debounce,()=>{o.state.setLocal(e,D)});return}}const i=a?.scope??"current",l=a?.merge||"deep",u=window.__g7ActionContext,d=So(e);if(i==="parent"||i==="root"){const T=window.__g7LayoutContextStack||[];if(T.length>0){const L=i==="parent"?T[T.length-1]:T[0];if(L?.setState){L.setState(M=>l==="replace"?d:l==="shallow"?{...M||{},...d}:Zn(M||{},d)),we.log(`[setLocal] scope=${i}: 타겟 컨텍스트에 상태 업데이트 (mergeMode=${l})`,d);return}}we.warn(`[setLocal] scope=${i}: 레이아웃 컨텍스트 스택이 비어있습니다. current로 폴백합니다.`)}const f=window.__g7PendingLocalState,g=r?.getGlobalState?.()?._local||{},v=!((window.__g7LayoutContextStack||[]).length>0)&&u?.state?u.state:void 0,S=v?uy(g,v):g,E=f||S;let A;if(l==="replace"?A=d:l==="shallow"?A={...E,...d}:A=Zn(E,d),r?.setGlobalState&&(r.setGlobalState({_local:A},{render:a?.render}),we.log(`[setLocal] globalLocal updated via setGlobalState (mergeMode=${l}, render=${a?.render??!0}):`,d)),window.__g7PendingLocalState=A,we.log("[setLocal] __g7PendingLocalState updated:",A),window.__g7SequenceLocalSync=A,window.__g7LastSetLocalSnapshot=A,l==="replace")window.__g7ForcedLocalFields=d;else{const T=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=Zn(T,d)}if(we.log("[setLocal] __g7ForcedLocalFields updated:",d),l==="replace")window.__g7SetLocalOverrideKeys=d;else{const T=window.__g7SetLocalOverrideKeys||{};window.__g7SetLocalOverrideKeys=Zn(T,d)}we.log("[setLocal] __g7SetLocalOverrideKeys updated:",d),u?.setState&&u.setState(T=>l==="replace"?d:l==="shallow"?{...T||{},...d}:Zn(T||{},d)),r?.setGlobalState||we.warn("G7Core.state.setLocal: TemplateApp이 없습니다.")},getLocal:()=>{const r=(window.__templateApp?.getGlobalState?.()||{})._local||{},i=window.__g7PendingLocalState;if(i)return Zn(r,i);const l=window.__g7LastSetLocalSnapshot;return l&&l!==r?Zn(r,l):r},update:e=>{const a=window.__templateApp;if(a?.getGlobalState&&a?.setGlobalState){const r=a.getGlobalState(),i=e(r);a.setGlobalState(i)}else we.warn("G7Core.state.update: TemplateApp이 초기화되지 않았습니다.")},subscribe:e=>{const a=window.__templateApp;return a?.onGlobalStateChange?a.onGlobalStateChange(e):(we.warn("G7Core.state.subscribe: TemplateApp이 초기화되지 않았습니다."),()=>{})},getDataSource:e=>window.__templateApp?.getDataSource?.(e),getIsolated:e=>e?window.__g7IsolatedStates?.[e]?.state??null:window.__g7ActionContext?.isolatedContext?.state??null,setIsolated:(e,a,r)=>{let i,l,u;typeof e=="string"?(i=e,l=a||{},u=r):(l=e,u=a&&typeof a=="object"&&"merge"in a?a:r);const d=u?.merge||"deep",f=So(l);if(i){const b=window.__g7IsolatedStates?.[i];b?.mergeState?b.mergeState(f,d):we.warn(`G7Core.state.setIsolated: scopeId '${i}'를 찾을 수 없습니다.`);return}const g=window.__g7ActionContext;g?.isolatedContext?.mergeState?g.isolatedContext.mergeState(f,d):we.warn("G7Core.state.setIsolated: 액션 컨텍스트에 isolatedContext가 없습니다.")},getParent:()=>{const e=window.__g7LayoutContextStack||[];if(e.length===0)return we.log("[getParent] 레이아웃 컨텍스트 스택이 비어있습니다."),null;const a=e[e.length-1];if(!a)return null;const r=a.dataContext||{};return{_local:a.state||r._local||{},_global:r._global||o.state.get()||{},setState:a.setState}},setParentLocal:(e,a,r)=>{const i=window.__g7LayoutContextStack||[];if(i.length===0){we.warn("[setParentLocal] 레이아웃 컨텍스트 스택이 비어있습니다.");return}const l=i[i.length-1];if(!l?.setState){we.warn("[setParentLocal] 부모 컨텍스트에 setState가 없습니다.");return}let u,d;typeof e=="string"?(u={[e]:a},d=r):(u=e,d=a&&typeof a=="object"&&"merge"in a?a:r);const f=d?.merge||"deep",g=So(u),m=l.state?._local!==void 0,b=m?l.state._local:l.state||{};let v;f==="replace"?v=g:f==="shallow"?v={...b,...g}:v=Zn(b,g),window.__g7PendingLocalState=v;const S=window.__templateApp;if(S?.setGlobalState&&S.setGlobalState({_local:v}),l.setState(v),m?l.state._local=v:l.state=v,l.dataContext&&(l.dataContext._local=v),f==="replace")window.__g7ForcedLocalFields=g;else{const E=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=Zn(E,g)}kd()},setParentGlobal:(e,a)=>{let r;typeof e=="string"?r={[e]:a}:r=e,o.state.set(r),we.log("[setParentGlobal] 전역 상태 업데이트:",r)}},window.__g7IsolatedStates||(window.__g7IsolatedStates={}),o.state.getGlobal=o.state.get,o.state.setGlobal=o.state.set,we.log("전역 객체 window.G7Core.state에 노출됨")}function uA(o){o.dataSource={get:e=>window.__templateApp?.getDataSource?.(e),set:(e,a,r)=>{const i=window.__templateApp;i?.setDataSource?i.setDataSource(e,a,r):we.warn("G7Core.dataSource.set: TemplateApp이 초기화되지 않았습니다.")},refetch:async(e,a)=>{const r=window.__templateApp;if(r?.refetchDataSource)return r.refetchDataSource(e,a);we.warn("G7Core.dataSource.refetch: TemplateApp이 초기화되지 않았습니다.")},updateItem:(e,a,r,i,l)=>{const u=window.__templateApp;return u?.updateDataSourceItem?u.updateDataSourceItem(e,a,r,i,l):(we.warn("G7Core.dataSource.updateItem: TemplateApp이 초기화되지 않았습니다."),!1)},updateData:(e,a,r,i="append")=>{const l=window.__templateApp;if(!l?.getDataSource||!l?.setDataSource)return we.warn("G7Core.dataSource.updateData: TemplateApp이 초기화되지 않았습니다."),!1;const u=l.getDataSource(e);if(!u)return we.warn(`G7Core.dataSource.updateData: 데이터 소스 '${e}'를 찾을 수 없습니다.`),!1;let d,f=u,g=null;if(a){const b=a.split(".");g=b.pop();for(const v of b)if(f&&typeof f=="object"&&v in f)f=f[v];else return we.warn(`G7Core.dataSource.updateData: 경로 '${a}'를 찾을 수 없습니다.`),!1;d=f[g]}else d=u;if(!Array.isArray(d))return we.warn("G7Core.dataSource.updateData: 대상 경로의 데이터가 배열이 아닙니다."),!1;if(!Array.isArray(r))return we.warn("G7Core.dataSource.updateData: newData가 배열이 아닙니다."),!1;const m=i==="prepend"?[...r,...d]:[...d,...r];return a&&g?(f[g]=m,l.setDataSource(e,u,{merge:!1})):l.setDataSource(e,m,{merge:!1}),we.log(`G7Core.dataSource.updateData: '${e}'에 ${r.length}개 항목 ${i==="prepend"?"앞에":"뒤에"} 추가됨`),!0}},we.log("전역 객체 window.G7Core.dataSource에 노출됨")}function dA(o,e){o.locale={current:()=>window.__templateApp?.getLocale?.()||"ko",supported:()=>{const r=window.__templateApp?.globalState?.appConfig?.supportedLocales;return Array.isArray(r)&&r.length>0?r:e.getState().templateMetadata?.locales||["ko","en"]},change:async a=>{const r=window.__templateApp;r?.changeLocale?await r.changeLocale(a):we.warn("G7Core.locale.change: TemplateApp이 초기화되지 않았습니다.")}},we.log("전역 객체 window.G7Core.locale에 노출됨")}function fA(o){o.toast={show:(e,a)=>{o.dispatch({handler:"toast",params:{message:e,type:a?.type||"info",...a?.duration&&{duration:a.duration}}})},success:(e,a)=>{o.toast.show(e,{type:"success",duration:a})},error:(e,a)=>{o.toast.show(e,{type:"error",duration:a})},warning:(e,a)=>{o.toast.show(e,{type:"warning",duration:a})},info:(e,a)=>{o.toast.show(e,{type:"info",duration:a})}},we.log("전역 객체 window.G7Core.toast에 노출됨")}function hA(o){o.modal={open:e=>{o.dispatch({handler:"openModal",target:e})},close:e=>{o.dispatch({handler:"closeModal",...e&&{target:e}})},closeAll:()=>{o.dispatch({handler:"closeAllModals"})},isOpen:e=>{const a=o.state.get();return a._global?.activeModal===e||a._global?.modalStack?.includes(e)||!1},getStack:()=>o.state.get()._global?.modalStack||[]},we.log("전역 객체 window.G7Core.modal에 노출됨")}function gA(o){o.style={mergeClasses:Q_,conditionalClass:Z_,joinClasses:eA},we.log("전역 객체 window.G7Core.style에 노출됨")}function pA(o,e){const{webSocketManager:a}=e;o.websocket={manager:a,subscribe:(r,i,l,u)=>a.subscribe(r,i,l,u),unsubscribe:r=>a.unsubscribe(r),leaveChannel:r=>a.leaveChannel(r),disconnect:()=>a.disconnect(),isInitialized:()=>a.isInitialized(),getSubscriptionCount:()=>a.getSubscriptionCount()},we.log("전역 객체 window.G7Core.websocket에 노출됨")}function mA(o,e){const{transitionManager:a}=e;o.navigation={isPending:()=>a?.getIsPending?.()||!1,onComplete:r=>{if(!a)return r(),()=>{};let i=a.getIsPending();const l=a.subscribe(u=>{u?i=!0:i&&(r(),l())});return l}},we.log("전역 객체 window.G7Core.navigation에 노출됨")}function yA(o){o.plugin={getSettings:e=>window.G7Config?.plugins?.[e],get:(e,a,r)=>window.G7Config?.plugins?.[e]?.[a]??r,getAll:()=>window.G7Config?.plugins??{}},we.log("전역 객체 window.G7Core.plugin에 노출됨")}function bA(o){o.module={getSettings:e=>window.G7Config?.modules?.[e],get:(e,a,r)=>window.G7Config?.modules?.[e]?.[a]??r,getAll:()=>window.G7Config?.modules??{}},we.log("전역 객체 window.G7Core.module에 노출됨")}function vA(o,e){const{transitionManager:a,responsiveManager:r}=e;o.AuthManager=ha,o.api=$a(),o.TransitionManager=a,o.useTransitionState=nm,o.ResponsiveManager=r,o.useResponsive=Md,o.useControllableState=lC,o.shallowArrayEqual=cC,o.shallowObjectEqual=rm,o.updateQueryParams=async(i,l)=>{const u=window.__templateApp;if(u?.updateQueryParams)return u.updateQueryParams(i,l);we.warn("G7Core.updateQueryParams: TemplateApp이 초기화되지 않았습니다.")},we.log("전역 객체 window.G7Core.AuthManager에 노출됨"),we.log("전역 객체 window.G7Core.api에 노출됨"),we.log("전역 객체 window.G7Core.ResponsiveManager에 노출됨"),we.log("전역 객체 window.G7Core.useResponsive에 노출됨"),we.log("전역 객체 window.G7Core.useControllableState에 노출됨"),we.log("전역 객체 window.G7Core.updateQueryParams에 노출됨")}function SA(o,e){o.getSlotContext=()=>window.__slotContextValue??null,o.getDynamicRenderer=()=>window.__DynamicRenderer??null,o.getComponentRegistry=()=>e.getComponentRegistry?.()??da.getInstance(),o.getDataBindingEngine=()=>e.getDataBindingEngine?.()??e.getState().bindingEngine,o.getTranslationEngine=()=>e.getTranslationEngine?.()??e.getState().translationEngine,o.getActionDispatcher=()=>e.getActionDispatcher?.()??e.getState().actionDispatcher,we.log("전역 객체 window.G7Core 슬롯 API에 노출됨 (getSlotContext, getDynamicRenderer 등)")}function wA(o){o.identity={setLauncher:St.setLauncher.bind(St),handle:St.handle.bind(St),isIdentityRequired:St.isIdentityRequired.bind(St),hasLauncher:St.hasLauncher.bind(St),markDomainNoticeShown:St.markDomainNoticeShown.bind(St),redirectExternally:St.redirectExternally.bind(St),createDeferred:St.createDeferred.bind(St),resolveDeferred:St.resolveDeferred.bind(St),reset:St.reset.bind(St),redirectStashKey:Ed},we.log("전역 객체 window.G7Core 본인인증(IDV) API에 노출됨 (identity)")}function CA(o){if(typeof window>"u")return;tA(),window.G7Core||(window.G7Core={});const e=window.G7Core;aA(e),nA(e),rA(e),vA(e,o),iA(e,o),sA(e,o),oA(e),cA(e),uA(e),dA(e,o),fA(e),hA(e),gA(e),pA(e,o),mA(e,o),yA(e),bA(e),SA(e,o),wA(e),we.log("G7Core 전역 객체 초기화 완료")}function EA(){const o=window.G7Core;if(!o){we.warn("G7Core가 초기화되지 않았습니다.");return}const e=()=>Tr.getInstance(),a={isEnabled:()=>{try{return e().isEnabled()}catch{return!1}},trackRender:r=>{try{e().isEnabled()&&e().trackRender(r)}catch{}},trackIteration:(r,i,l,u,d)=>{try{e().isEnabled()&&e().trackIteration(r,{source:i,itemVar:l,indexVar:u,sourceLength:d})}catch{}},trackIfCondition:(r,i,l,u)=>{try{e().isEnabled()&&e().trackIfCondition(r,i,l)}catch{}},trackMount:(r,i)=>{try{e().isEnabled()&&e().trackMount(r,{...i,id:r})}catch{}},trackUnmount:r=>{try{e().isEnabled()&&e().trackUnmount(r)}catch{}},trackExpressionEval:r=>{try{e().isEnabled()&&e().trackExpressionEval(r)}catch{}},trackBindingEval:r=>{try{e().isEnabled()&&e().trackBindingEval(r)}catch{}},recordCacheHit:()=>{try{e().isEnabled()&&e().recordCacheHit()}catch{}},recordCacheMiss:()=>{try{e().isEnabled()&&e().recordCacheMiss()}catch{}},trackHandlerRegistration:(r,i,l,u)=>{try{e().isEnabled()&&e().trackHandlerRegistration(r,i,l,u)}catch{}},trackHandlerUnregistration:r=>{try{e().isEnabled()&&e().trackHandlerUnregistration(r)}catch{}},logAction:r=>{try{e().isEnabled()&&e().logAction(r)}catch{}},trackRequest:(r,i)=>{try{return e().isEnabled()?e().trackRequest(r,i):""}catch{return""}},completeRequest:(r,i,l)=>{try{e().isEnabled()&&e().completeRequest(r,i,l)}catch{}},failRequest:(r,i)=>{try{e().isEnabled()&&e().failRequest(r,i)}catch{}},trackDataSourceDefinition:r=>{try{e().isEnabled()&&e().trackDataSourceDefinition(r)}catch{}},trackDataSourceLoading:r=>{try{e().isEnabled()&&e().trackDataSourceLoading(r)}catch{}},trackDataSourceLoaded:(r,i,l)=>{try{e().isEnabled()&&e().trackDataSourceLoaded(r,i,l)}catch{}},trackDataSourceError:(r,i)=>{try{e().isEnabled()&&e().trackDataSourceError(r,i)}catch{}},trackForm:(r,i,l)=>{try{e().isEnabled()&&e().trackForm(r,i,l)}catch{}},untrackForm:r=>{try{e().isEnabled()&&e().untrackForm(r)}catch{}},startStateChange:(r,i,l,u)=>{try{return e().isEnabled()?e().startStateChange(r,i,l,u):""}catch{return""}},completeStateChange:r=>{try{e().isEnabled()&&e().completeStateChange(r)}catch{}},trackComponentRender:(r,i,l,u,d,f)=>{try{e().isEnabled()&&e().trackComponentRender(r,i,l,u,d,f)}catch{}},updateLocalState:r=>{try{e().isEnabled()&&e().updateLocalState(r)}catch{}},updateComputedState:r=>{try{e().isEnabled()&&e().updateComputedState(r)}catch{}},updateParentContext:r=>{try{e().isEnabled()&&e().updateParentContext(r)}catch{}},trackComponentStateSource:(r,i,l,u)=>{try{e().isEnabled()&&e().trackComponentStateSource(r,i,l,u)}catch{}},trackDynamicState:(r,i)=>{try{e().isEnabled()&&e().trackDynamicState(r,i)}catch{}},trackContextFlow:(r,i,l,u,d,f)=>{try{e().isEnabled()&&e().trackContextFlow(r,i,l,u,d,f)}catch{}},trackComponentStyle:(r,i,l,u)=>{try{e().isEnabled()&&e().trackComponentStyle(r,i,l,u)}catch{}},trackAuthEvent:(r,i,l,u)=>{try{e().isEnabled()&&e().trackAuthEvent(r,i,l,u)}catch{}},trackAuthHeader:(r,i,l,u,d)=>{try{e().isEnabled()&&e().trackAuthHeader(r,i,l,u,d)}catch{}},trackLog:(r,i,l)=>{try{e().isEnabled()&&e().trackLog(r,i,l)}catch{}},trackAction:r=>{try{e().isEnabled()&&e().trackAction?.(r)}catch{}},trackDataSourceUpdate:r=>{try{e().isEnabled()&&e().trackDataSourceUpdate?.(r)}catch{}},startSequenceExecution:r=>{try{return e().isEnabled()?e().startSequenceExecution(r):""}catch{return""}},captureSequenceActionBefore:(r,i,l,u,d)=>{try{e().isEnabled()&&e().captureSequenceActionBefore(r,i,l,u,d)}catch{}},captureSequenceActionAfter:(r,i,l,u,d,f)=>{try{e().isEnabled()&&e().captureSequenceActionAfter(r,i,l,u,d,f)}catch{}},endSequenceExecution:(r,i)=>{try{e().isEnabled()&&e().endSequenceExecution(r,i)}catch{}},registerStateCaptureForHandler:(r,i,l)=>{try{e().isEnabled()&&e().registerStateCaptureForHandler(r,i,l)}catch{}},detectStaleClosure:(r,i,l,u,d)=>{try{return e().isEnabled()?e().detectStaleClosure(r,i,l,u,d):[]}catch{return[]}},trackStaleClosureWarning:r=>{try{e().isEnabled()&&e().trackStaleClosureWarning(r)}catch{}},trackModalOpen:r=>{try{e().isEnabled()&&e().trackModalOpen(r)}catch{}},trackModalClose:(r,i)=>{try{e().isEnabled()&&e().trackModalClose(r,i)}catch{}},trackModalStateChange:r=>{try{e().isEnabled()&&e().trackModalStateChange(r)}catch{}},trackNestedContext:r=>{try{return e().isEnabled()?e().trackNestedContext(r):""}catch{return""}},trackNestedContextAccess:(r,i)=>{try{e().isEnabled()&&e().trackNestedContextAccess(r,i)}catch{}},trackComputedProperty:(r,i,l,u,d,f,g)=>{try{e().isEnabled()&&e().trackComputedProperty(r,i,l,u,d,f,g)}catch{}},trackComputedRecalc:(r,i,l,u,d,f,g)=>{try{e().isEnabled()&&e().trackComputedRecalc(r,i,l,u,d,f,g)}catch{}},setNamedActionDefinitions:r=>{try{e().isEnabled()&&e().setNamedActionDefinitions(r)}catch{}},trackNamedActionRef:r=>{try{e().isEnabled()&&e().trackNamedActionRef(r)}catch{}}};o.devTools=a,we.log("G7Core.devTools 인터페이스 초기화 완료")}let wo=null;function _A(){const o=window.G7Core;return o?.__devtools?Promise.resolve(o.__devtools):wo||(wo=new Promise((e,a)=>{const r=window.G7Config?.coreDevToolsAsset||"/build/core/devtools.min.js",i="g7-devtools-bundle",l=()=>{const f=window.G7Core?.__devtools;f?e(f):a(new Error("DevTools 번들 로드됨 — 그러나 __devtools 미노출"))};window.G7Core=window.G7Core||{},window.G7Core.__onDevToolsReady=l;const u=document.getElementById(i);if(u){u.addEventListener("load",l,{once:!0}),u.addEventListener("error",()=>a(new Error(`DevTools 번들 로드 실패: ${r}`)),{once:!0});return}const d=document.createElement("script");d.id=i,d.src=r,d.async=!1,d.addEventListener("load",l,{once:!0}),d.addEventListener("error",()=>{wo=null,a(new Error(`DevTools 번들 로드 실패: ${r}`))},{once:!0}),document.head.appendChild(d)}),wo)}function AA(){const o=window.G7Core;if(!o){we.warn("G7Core가 초기화되지 않았습니다.");return}const e=Tr.getInstance();if(e.initialize(),!e.isEnabled()){window.G7DevTools={isEnabled:()=>!1,enable:()=>{we.log("환경설정 > 고급 설정 > 디버그 모드를 켜세요")}},Zu(),we.log("G7DevTools 비활성화됨 (디버그 모드 꺼짐)");return}xA(o,e)}async function xA(o,e){let a;try{a=await _A()}catch(g){we.warn("DevTools 번들 로드 실패 — 최소 API 로 폴백:",g),window.G7DevTools={isEnabled:()=>!1,enable:()=>{}},Zu();return}const{DiagnosticEngine:r,getServerConnector:i,getStyleTracker:l}=a;EA(),Zu();try{l().enable(),we.log("StyleTracker 활성화됨")}catch(g){we.warn("StyleTracker 활성화 실패:",g)}const u=new r,d=i(),f={isEnabled:()=>e.isEnabled(),state:{get:()=>e.getState(),getHistory:()=>e.getStateHistory(),watch:(g,m)=>e.watchState(g,m)},actions:{getHistory:()=>e.getActionHistory(),watch:g=>e.watchActions(g),getMetrics:()=>e.getActionMetrics()},binding:{evaluate:g=>{const m=o.getDataBindingEngine?.();if(!m){we.warn("DataBindingEngine이 없습니다.");return}return m.evaluateExpression(g,e.getState())},getCacheStats:()=>e.getCacheStats(),clearStats:()=>{e.resetCacheStats(),we.log("캐시 통계 초기화됨")}},diagnose:{analyze:g=>u.analyze(g),suggestFix:g=>u.suggestFix(g),getCommonIssues:()=>u.getCommonIssues(),getRulesByCategory:g=>u.getRulesByCategory(g)},server:{dumpState:g=>d.dumpState(g),sendLog:g=>d.sendLog(g),sendError:(g,m)=>d.sendError(g,m),isConnected:()=>d.isConnected(),testConnection:()=>d.testConnection()},config:{isDebugMode:()=>e.isEnabled(),setLogLevel:g=>e.setLogLevel(g),setMaxHistory:g=>e.setMaxHistory(g)},lifecycle:{getMountedComponents:()=>e.getLifecycleInfo().mountedComponents,getOrphanedListeners:()=>e.getLifecycleInfo().orphanedListeners},performance:{getRenderCount:()=>e.getPerformanceInfo().renderCounts,getBindingEvalCount:()=>e.getPerformanceInfo().bindingEvalCount,getMemoryWarnings:()=>e.getPerformanceInfo().memoryWarnings,startProfiling:()=>e.startProfiling(),stopProfiling:()=>e.stopProfiling()},network:{getActiveRequests:()=>e.getNetworkInfo().activeRequests,getRequestHistory:()=>e.getNetworkInfo().requestHistory,getPendingDataSources:()=>e.getNetworkInfo().pendingDataSources},conditional:{getIfConditions:()=>e.getConditionalInfo().ifConditions,getIterations:()=>e.getConditionalInfo().iterations},form:{getForms:()=>e.getFormInfo()},websocket:{getInfo:()=>e.getWebSocketInfo()}};window.G7DevTools=f,o.devtools=f,we.log("G7DevTools 전역 객체 초기화 완료 (window.G7DevTools)"),TA(a.DevToolsPanel)}function TA(o){if(document.getElementById("g7-devtools-root")){we.log("DevToolsPanel 이미 렌더링됨");return}const e=document.createElement("div");e.id="g7-devtools-root",document.body.appendChild(e);try{Ju.createRoot(e).render(Ye.createElement(o)),we.log("DevToolsPanel UI 렌더링 완료")}catch(a){we.error("DevToolsPanel UI 렌더링 실패:",a)}}const Ze=ct("TemplateEngine"),ie={templateId:null,locale:"ko",isInitialized:!1,reactRoot:null,containerId:null,currentLayoutJson:null,currentDataContext:{},translationContext:{templateId:"",locale:"ko"},registry:null,bindingEngine:null,translationEngine:null,actionDispatcher:null,templateMetadata:null};let Co=!1;const Eo=[];async function RA(o){try{Ze.log("템플릿 메타데이터 로드 중...",o);const e=o.split("-").map(r=>r.split("_").map(i=>i.charAt(0).toUpperCase()+i.slice(1)).join("")).join(""),a=window[e];return a?.templateMetadata?(Ze.log("템플릿 메타데이터 로드 완료 (전역 변수)",a.templateMetadata),a.templateMetadata):(Ze.warn(`템플릿 번들에 메타데이터가 없습니다. 전역 변수: ${e}`),{identifier:o,locales:["ko","en"],name:{ko:o,en:o},description:{ko:"",en:""},version:"1.0.0",type:"admin"})}catch(e){return Ze.error("템플릿 메타데이터 로드 실패",e),{identifier:o,locales:["ko","en"],name:{ko:o,en:o},description:{ko:"",en:""},version:"1.0.0",type:"admin"}}}function dy(){const e=(typeof window<"u"?window.__templateApp:void 0)?.globalState?.appConfig?.supportedLocales,a=ie.templateMetadata?.locales;return{$locale:ie.locale,$locales:Array.isArray(e)&&e.length>0?e:a||["ko","en"],$templateLocales:a||["ko","en"],$templateId:ie.templateId}}async function _o(o){try{if(Ze.log("템플릿 엔진 초기화 시작",o),ie.isInitialized)throw new Error("템플릿 엔진이 이미 초기화되었습니다. destroyTemplate()을 먼저 호출하세요.");if(!o.templateId)throw new z_;Co=o.debug??!1,typeof window<"u"&&(window.G7Config||(window.G7Config={}),window.G7Config.debug=Co),AA(),ie.templateId=o.templateId,ie.locale=o.locale||"ko",Ze.log("엔진 인스턴스 생성 중..."),ie.registry=da.getInstance(),ie.bindingEngine=new wn,ie.translationEngine=Cr.getInstance(),o.cacheVersion!==void 0&&o.cacheVersion>0&&ie.translationEngine.setCacheVersion(o.cacheVersion),ie.translationContext={templateId:o.templateId,locale:ie.locale},ie.actionDispatcher=new oo({},ie.translationEngine,ie.translationContext),eC(ie.actionDispatcher),Ze.log("다국어 파일 로드 중...",o.templateId,ie.locale);const e="en",a=[ie.translationEngine.loadTranslations(o.templateId,ie.locale).then(()=>{Ze.log(`다국어 파일 로드 완료: ${ie.locale}`)}).catch(r=>{Ze.warn(`다국어 파일 로드 실패 (${ie.locale}):`,r instanceof Error?r.message:r)})];ie.locale!==e&&a.push(ie.translationEngine.loadTranslations(o.templateId,e).then(()=>{Ze.log(`폴백 다국어 파일 로드 완료: ${e}`)}).catch(r=>{Ze.warn(`폴백 다국어 파일 로드 실패 (${e}):`,r instanceof Error?r.message:r)})),await Promise.allSettled(a),Ze.log("템플릿 메타데이터 로드 중...",o.templateId),ie.templateMetadata=await RA(o.templateId),ie.isInitialized=!0,Ze.log("템플릿 엔진 초기화 완료 (ComponentRegistry는 별도 로드)")}catch(e){throw Ze.error("템플릿 엔진 초기화 실패",e),ie.isInitialized=!1,ie.registry=null,ie.bindingEngine=null,ie.translationEngine=null,ie.actionDispatcher=null,e}}let Ao=null;function hf(){const o=window.G7Core;return o?.__LayoutEditorChrome?Promise.resolve(o.__LayoutEditorChrome):Ao||(Ao=new Promise((e,a)=>{const r=window.G7Config?.coreEditorAsset||"/build/core/layout-editor.min.js",i="g7-layout-editor-bundle",l=document.getElementById(i),u=()=>{const f=window.G7Core?.__LayoutEditorChrome;f?e(f):a(new Error("편집기 번들 로드됨 — 그러나 __LayoutEditorChrome 미노출"))};if(window.G7Core=window.G7Core||{},window.G7Core.__onChromeReady=u,l){l.addEventListener("load",u,{once:!0}),l.addEventListener("error",()=>a(new Error(`편집기 번들 로드 실패: ${r}`)),{once:!0});return}const d=document.createElement("script");d.id=i,d.src=r,d.async=!1,d.addEventListener("load",u,{once:!0}),d.addEventListener("error",()=>{Ao=null,a(new Error(`편집기 번들 로드 실패: ${r}`))},{once:!0}),document.head.appendChild(d)}),Ao)}async function os(o){try{if(Ze.log("템플릿 렌더링 시작",o),!ie.isInitialized)throw new Error("템플릿 엔진이 초기화되지 않았습니다. initTemplateEngine()을 먼저 호출하세요.");if(!o.containerId)throw new Error("containerId는 필수입니다.");if(!o.layoutJson)throw new Error("layoutJson은 필수입니다.");const e=document.getElementById(o.containerId);if(!e)throw new Error(`컨테이너를 찾을 수 없습니다: #${o.containerId}`);const a=dy();if(ie.containerId=o.containerId,ie.currentLayoutJson=o.layoutJson,ie.currentDataContext={...a,...o.dataContext||{}},ie.translationContext=o.translationContext||{templateId:ie.templateId||"",locale:ie.locale},ie.reactRoot||(Ze.log("React Root 생성"),ie.reactRoot=Ju.createRoot(e)),typeof window<"u"){const l=iy(window.location.pathname);if(l){Ze.log("레이아웃 편집기 모드 진입",l);let u;try{u=await hf()}catch(f){Ze.error("레이아웃 편집기 번들 로드 실패",f),lf.render(o.containerId,{title:"레이아웃 편집기 로드 실패",message:f instanceof Error?f.message:"편집기 번들을 불러오지 못했습니다.",icon:"fas fa-triangle-exclamation",showStack:!1,showReloadButton:!0,debug:Co});return}const d=Ye.createElement(u,{templateIdentifier:l.templateIdentifier,initialLocale:ie.locale});ie.reactRoot.render(Ye.createElement(cc,{translationEngine:ie.translationEngine,translationContext:ie.translationContext,children:Ye.createElement(Dd,{children:Ye.createElement(Xl,{children:Ye.createElement(nf,{children:d})})})}));return}}const r=o.layoutJson.components||[];if(r.length===0){Ze.warn("렌더링할 컴포넌트가 없습니다.");return}const i=o.layoutJson.modals||[];if(Ze.log("modals 배열:",i),Ze.log("modals 개수:",i.length),Ze.log("DynamicRenderer로 렌더링 시작"),ie.reactRoot.render(Ye.createElement(cc,{translationEngine:ie.translationEngine,translationContext:ie.translationContext},Ye.createElement(Dd,null,Ye.createElement(Xl,null,Ye.createElement(nf,null,[...r.map((l,u)=>{const d=ie.currentLayoutJson?.layout_name||"";return Ye.createElement(Ha,{key:d&&!l._fromBase?`${l.id}_${d}`:l.id,componentDef:l,dataContext:ie.currentDataContext,translationContext:ie.translationContext,registry:ie.registry,bindingEngine:ie.bindingEngine,translationEngine:ie.translationEngine,actionDispatcher:ie.actionDispatcher,isRootRenderer:u===0,layoutKey:d})}),Ye.createElement(Jp,{key:"__modal_parent_context_provider"},i.map(l=>{const u=ie.currentDataContext._global?.modalStack||[],f=u.includes(l.id)||ie.currentDataContext._global?.activeModal===l.id,g=u.indexOf(l.id),m=g>=0?50+g:50,b=window.__g7LayoutContextStack||[],S=b[b.length-1]?.dataContext,E=Ye.createElement(Ha,{key:`modal_${l.id}_renderer`,componentDef:{...l,props:{...l.props,isOpen:f,style:{...l.props?.style,zIndex:m},onClose:ie.actionDispatcher?.createHandler({type:"click",handler:"closeModal"},ie.currentDataContext)}},dataContext:ie.currentDataContext,translationContext:ie.translationContext,registry:ie.registry,bindingEngine:ie.bindingEngine,translationEngine:ie.translationEngine,actionDispatcher:ie.actionDispatcher,parentDataContext:S});return l.data_sources&&l.data_sources.length>0?Ye.createElement(ay,{key:`modal_${l.id}`,isOpen:f,modalId:l.id,dataSources:l.data_sources,dataContext:ie.currentDataContext,globalStateUpdater:ie.actionDispatcher?.getGlobalStateUpdater(),bindingEngine:ie.bindingEngine,debug:Co,children:E}):E}))]))))),Ze.log("템플릿 렌더링 완료"),Eo.length>0){Ze.log(`대기 중인 데이터 업데이트 ${Eo.length}건 적용`);const l=[...Eo];Eo.length=0;for(const{data:u,options:d}of l)ls(u,d)}}catch(e){throw Ze.error("템플릿 렌더링 실패",e),e}}function ls(o,e){try{if(Ze.log("템플릿 데이터 업데이트 시작",Object.keys(o)),!ie.isInitialized)throw new Error("템플릿 엔진이 초기화되지 않았습니다.");if(!ie.reactRoot||!ie.currentLayoutJson){Ze.log("React 미준비 - 데이터 업데이트 큐잉:",Object.keys(o)),Eo.push({data:o,options:e});return}const a=dy(),r={...ie.currentDataContext._global||{},...o._global||{}},i=sC(ie.currentDataContext._localInit,o._localInit);ie.currentDataContext={...a,...ie.currentDataContext,...o,_global:r,_localInit:i},r._local!==void 0&&(ie.currentDataContext._local=r._local),r._computed!==void 0&&(ie.currentDataContext._computed=r._computed);const l=ie.currentLayoutJson.components||[],u=ie.currentLayoutJson.modals||[];Ze.log("updateTemplateData - modals 배열:",u),Ze.log("updateTemplateData - modals 개수:",u.length),Ze.log("updateTemplateData - activeModal:",ie.currentDataContext._global?.activeModal);const d=()=>{ie.reactRoot.render(Ye.createElement(cc,{translationEngine:ie.translationEngine,translationContext:ie.translationContext},Ye.createElement(Dd,null,Ye.createElement(Xl,null,Ye.createElement(nf,null,[...l.map((f,g)=>{const m=ie.currentLayoutJson?.layout_name||"";return Ye.createElement(Ha,{key:m&&!f._fromBase?`${f.id}_${m}`:f.id,componentDef:f,dataContext:ie.currentDataContext,translationContext:ie.translationContext,registry:ie.registry,bindingEngine:ie.bindingEngine,translationEngine:ie.translationEngine,actionDispatcher:ie.actionDispatcher,isRootRenderer:g===0,layoutKey:m})}),Ye.createElement(Jp,{key:"__modal_parent_context_provider_update"},u.map(f=>{const g=ie.currentDataContext._global?.modalStack||[],b=g.includes(f.id)||ie.currentDataContext._global?.activeModal===f.id,v=g.indexOf(f.id),S=v>=0?50+v:50,E=window.__g7LayoutContextStack||[],T=E[E.length-1]?.dataContext,L=Ye.createElement(Ha,{key:`modal_${f.id}_renderer`,componentDef:{...f,props:{...f.props,isOpen:b,style:{...f.props?.style,zIndex:S},onClose:ie.actionDispatcher?.createHandler({type:"click",handler:"closeModal"},ie.currentDataContext)}},dataContext:ie.currentDataContext,translationContext:ie.translationContext,registry:ie.registry,bindingEngine:ie.bindingEngine,translationEngine:ie.translationEngine,actionDispatcher:ie.actionDispatcher,parentDataContext:T});return f.data_sources&&f.data_sources.length>0?Ye.createElement(ay,{key:`modal_${f.id}`,isOpen:b,modalId:f.id,dataSources:f.data_sources,dataContext:ie.currentDataContext,globalStateUpdater:ie.actionDispatcher?.getGlobalStateUpdater(),bindingEngine:ie.bindingEngine,debug:Co,children:L}):L}))])))))};e?.sync?(Ze.log("재렌더링 시작 (sync mode - 즉시 렌더링)"),d()):(Ze.log("재렌더링 시작 (with startTransition)"),N.startTransition(()=>{d()})),Ze.log("템플릿 데이터 업데이트 완료")}catch(a){throw Ze.error("템플릿 데이터 업데이트 실패",a),a}}function mc(){try{Ze.log("템플릿 정리 시작"),ie.reactRoot&&(Ze.log("React Root 언마운트"),ie.reactRoot.unmount(),ie.reactRoot=null),ie.templateId=null,ie.locale="ko",ie.isInitialized=!1,ie.containerId=null,ie.currentLayoutJson=null,ie.currentDataContext={},ie.translationContext={templateId:"",locale:"ko"},ie.registry=null,ie.bindingEngine=null,ie.translationEngine=null,ie.actionDispatcher=null,ie.templateMetadata=null,Ze.log("템플릿 정리 완료")}catch(o){throw Ze.error("템플릿 정리 실패",o),o}}function Za(){return Object.freeze({...ie})}function fy(){return ie.actionDispatcher}const xo={initTemplateEngine:_o,renderTemplate:os,updateTemplateData:ls,destroyTemplate:mc,getState:Za};typeof window<"u"&&(window.G7Core||(window.G7Core={}),window.G7Core.TemplateEngine=xo,CA({getState:()=>({translationEngine:ie.translationEngine,translationContext:ie.translationContext,bindingEngine:ie.bindingEngine,actionDispatcher:ie.actionDispatcher,templateMetadata:ie.templateMetadata}),transitionManager:Na,responsiveManager:ci,webSocketManager:fc}),Ze.log("전역 객체 window.G7Core.TemplateEngine에 노출됨"));const za=Object.freeze(Object.defineProperty({__proto__:null,DataSourceManager:va,LayoutLoader:ef,TemplateApp:vo,TemplateEngine:xo,default:xo,destroyTemplate:mc,getActionDispatcher:fy,getState:Za,initTemplateApp:ff,initTemplateEngine:_o,loadLayoutEditorBundle:hf,renderTemplate:os,updateTemplateData:ls},Symbol.toStringTag,{value:"Module"}));Vt.DataSourceManager=va,Vt.LayoutLoader=ef,Vt.TemplateApp=vo,Vt.TemplateEngine=xo,Vt.default=xo,Vt.destroyTemplate=mc,Vt.getActionDispatcher=fy,Vt.getState=Za,Vt.initTemplateApp=ff,Vt.initTemplateEngine=_o,Vt.loadLayoutEditorBundle=hf,Vt.renderTemplate=os,Vt.updateTemplateData=ls,Object.defineProperties(Vt,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})})(this.G7Core=this.G7Core||{}); + `)(a)}catch(r){B.warn(`Expression evaluation failed: ${e}`,r);return}}async executeInitActions(e,a={}){const{getActionDispatcher:r}=await Promise.resolve().then(()=>za),i=r();if(!i){B.warn("ActionDispatcher not available for init_actions");return}B.log("Executing init_actions:",e.map(d=>d.handler)),B.log("Init actions dataContext:",a),B.log("Init actions dataContext._global:",a._global);const l=e.map(d=>d.handler).filter(d=>d.includes("."));l.length>0&&await this.waitForHandlers(i,l);let u={...a};for(const d of e)try{const f={type:"click",handler:d.handler,target:d.target,params:d.params,resultTo:d.resultTo,onSuccess:d.onSuccess,onError:d.onError,if:d.if,conditions:d.conditions,auth_mode:d.auth_mode,auth_required:d.auth_required},g=i.createHandler(f,u),m=new Event("init");await g(m),B.log(`Init action executed: ${d.handler}`);const b=this.globalState;u={...u,_global:{...b},_local:b._local||u._local||{}},B.log(`Data context refreshed after ${d.handler}:`,{cartKey:u._global?.cartKey})}catch(f){B.error(`Failed to execute init action: ${d.handler}`,f)}}async waitForHandlers(e,a,r=5e3){const i=Date.now(),l=50,u=()=>a.every(f=>e.customHandlers?.has(f));if(u()){B.log("All module handlers already registered");return}const d=df().getFailedJsAssets();if(d.length>0){const f=d.some(b=>b==="module"||b==="plugin"),g=a.filter(b=>!e.customHandlers?.has(b)),m=g.length>0&&g.every(b=>d.some(v=>b.startsWith(`${v}.`)));if(f||m){B.warn("Extension asset load failed — not waiting for handlers that will never register:",{pending:g,failedAssets:d});return}}return B.log("Waiting for module handlers:",a),new Promise(f=>{const g=()=>{if(u()){B.log("All module handlers now registered"),f();return}if(Date.now()-i>=r){const m=a.filter(b=>!e.customHandlers?.has(b));B.warn("Timeout waiting for handlers:",m),f();return}setTimeout(g,l)};g()})}};$(Ca,"LOCALE_STORAGE_KEY","g7_locale"),$(Ca,"CACHE_VERSION_STORAGE_KEY","g7_cache_version");let So=Ca;function hf(o){const e=new So(o);return o.websocket&&(hc.configure(o.websocket),B.log("WebSocket 설정 완료")),document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{e.init(),window.__templateApp=e}):(e.init(),window.__templateApp=e),e}typeof window<"u"&&(window.G7Core=window.G7Core||{},window.G7Core.initTemplateApp=hf,window.G7Core.dataSource={refetch:async(o,e)=>{const a=window.__templateApp;if(!a){B.warn("TemplateApp not initialized (G7Core.dataSource.refetch)");return}return a.refetchDataSource(o,e)},get:o=>{const e=window.__templateApp;if(!e){B.warn("TemplateApp not initialized (G7Core.dataSource.get)");return}return e.getDataSource(o)}});function K_(o={}){const{checked:e,value:a,name:r,type:i="checkbox"}=o,u=a!==void 0?a:i==="checkbox"||i==="radio"?e??!1:String(e??""),d={checked:e??!1,value:u,name:r??"",type:i};return{target:d,currentTarget:d,preventDefault:()=>{},stopPropagation:()=>{},nativeEvent:new Event("change"),bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:Event.AT_TARGET,isTrusted:!1,timeStamp:Date.now(),type:"change",isDefaultPrevented:()=>!1,isPropagationStopped:()=>!1,persist:()=>{}}}function W_(o={}){const{button:e=0,clientX:a=0,clientY:r=0}=o;return{button:e,clientX:a,clientY:r,preventDefault:()=>{},stopPropagation:()=>{},nativeEvent:new MouseEvent("click"),bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:Event.AT_TARGET,isTrusted:!1,timeStamp:Date.now(),type:"click",isDefaultPrevented:()=>!1,isPropagationStopped:()=>!1,persist:()=>{},target:document.createElement("div"),currentTarget:document.createElement("div")}}function Y_(){return{preventDefault:()=>{},stopPropagation:()=>{},nativeEvent:new Event("submit"),bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:Event.AT_TARGET,isTrusted:!1,timeStamp:Date.now(),type:"submit",isDefaultPrevented:()=>!1,isPropagationStopped:()=>!1,persist:()=>{},target:document.createElement("form"),currentTarget:document.createElement("form")}}function X_(o,e="keydown"){return{key:o,code:o.length===1?`Key${o.toUpperCase()}`:o,preventDefault:()=>{},stopPropagation:()=>{},nativeEvent:new KeyboardEvent(e,{key:o}),bubbles:!0,cancelable:!0,defaultPrevented:!1,eventPhase:Event.AT_TARGET,isTrusted:!1,timeStamp:Date.now(),type:e,isDefaultPrevented:()=>!1,isPropagationStopped:()=>!1,persist:()=>{},target:document.createElement("div"),currentTarget:document.createElement("div"),altKey:!1,ctrlKey:!1,metaKey:!1,shiftKey:!1,repeat:!1}}const J_={justify:/^justify-(start|end|center|between|around|evenly)$/,items:/^items-(start|end|center|baseline|stretch)$/,content:/^content-(start|end|center|between|around|evenly|stretch)$/,self:/^self-(auto|start|end|center|stretch|baseline)$/,flex:/^flex-(row|row-reverse|col|col-reverse|wrap|wrap-reverse|nowrap|1|auto|initial|none)$/,grow:/^(grow|grow-0)$/,shrink:/^(shrink|shrink-0)$/,basis:/^basis-/,order:/^(order-|-)order-/,gap:/^gap(-x|-y)?-/,gridCols:/^grid-cols-/,gridRows:/^grid-rows-/,colSpan:/^col-(span-|start-|end-)/,rowSpan:/^row-(span-|start-|end-)/,display:/^(block|inline-block|inline|flex|inline-flex|table|inline-table|table-caption|table-cell|table-column|table-column-group|table-footer-group|table-header-group|table-row-group|table-row|flow-root|grid|inline-grid|contents|list-item|hidden)$/,position:/^(static|fixed|absolute|relative|sticky)$/,inset:/^(inset|top|right|bottom|left)-/,zIndex:/^z-/,width:/^w-/,minWidth:/^min-w-/,maxWidth:/^max-w-/,height:/^h-/,minHeight:/^min-h-/,maxHeight:/^max-h-/,padding:/^p[xytblr]?-/,margin:/^-?m[xytblr]?-/,space:/^space-(x|y)-/,fontSize:/^text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl)$/,fontWeight:/^font-(thin|extralight|light|normal|medium|semibold|bold|extrabold|black)$/,fontStyle:/^(italic|not-italic)$/,fontFamily:/^font-(sans|serif|mono)/,textAlign:/^text-(left|center|right|justify|start|end)$/,textColor:/^text-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-/,textDecoration:/^(underline|overline|line-through|no-underline)$/,textTransform:/^(uppercase|lowercase|capitalize|normal-case)$/,lineHeight:/^leading-/,letterSpacing:/^tracking-/,textOverflow:/^(truncate|text-ellipsis|text-clip)$/,whitespace:/^whitespace-/,wordBreak:/^break-/,bgColor:/^bg-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-/,bgGradient:/^bg-gradient-/,bgSize:/^bg-(auto|cover|contain)$/,bgPosition:/^bg-(bottom|center|left|left-bottom|left-top|right|right-bottom|right-top|top)$/,bgRepeat:/^bg-(repeat|no-repeat|repeat-x|repeat-y|repeat-round|repeat-space)$/,bgAttachment:/^bg-(fixed|local|scroll)$/,bgClip:/^bg-clip-/,bgOrigin:/^bg-origin-/,borderWidth:/^border(-[xytblr])?(-0|-2|-4|-8)?$/,borderColor:/^border-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-/,borderStyle:/^border-(solid|dashed|dotted|double|hidden|none)$/,borderRadius:/^rounded(-[tblrse]{1,2})?(-none|-sm|-md|-lg|-xl|-2xl|-3xl|-full)?$/,ringWidth:/^ring(-0|-1|-2|-4|-8|-inset)?$/,ringColor:/^ring-(inherit|current|transparent|black|white|slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-/,ringOffset:/^ring-offset-/,shadow:/^shadow(-sm|-md|-lg|-xl|-2xl|-inner|-none)?$/,opacity:/^opacity-/,mixBlend:/^mix-blend-/,bgBlend:/^bg-blend-/,blur:/^blur(-none|-sm|-md|-lg|-xl|-2xl|-3xl)?$/,brightness:/^brightness-/,contrast:/^contrast-/,grayscale:/^grayscale(-0)?$/,hueRotate:/^-?hue-rotate-/,invert:/^invert(-0)?$/,saturate:/^saturate-/,sepia:/^sepia(-0)?$/,backdropBlur:/^backdrop-blur-/,backdropBrightness:/^backdrop-brightness-/,backdropContrast:/^backdrop-contrast-/,backdropGrayscale:/^backdrop-grayscale-/,backdropHueRotate:/^backdrop-hue-rotate-/,backdropInvert:/^backdrop-invert-/,backdropOpacity:/^backdrop-opacity-/,backdropSaturate:/^backdrop-saturate-/,backdropSepia:/^backdrop-sepia-/,scale:/^scale(-x|-y)?-/,rotate:/^-?rotate-/,translate:/^-?translate-[xy]-/,skew:/^-?skew-[xy]-/,transformOrigin:/^origin-/,transition:/^transition(-none|-all|-colors|-opacity|-shadow|-transform)?$/,duration:/^duration-/,ease:/^ease-(linear|in|out|in-out)$/,delay:/^delay-/,animate:/^animate-/,cursor:/^cursor-/,userSelect:/^select-/,pointerEvents:/^pointer-events-/,resize:/^resize(-none|-x|-y)?$/,scrollBehavior:/^scroll-(auto|smooth)$/,touchAction:/^touch-/,overflow:/^overflow(-x|-y)?-(auto|hidden|clip|visible|scroll)$/,overscroll:/^overscroll(-x|-y)?-(auto|contain|none)$/,visibility:/^(visible|invisible|collapse)$/,aspectRatio:/^aspect-/,columns:/^columns-/,breakAfter:/^break-after-/,breakBefore:/^break-before-/,breakInside:/^break-inside-/,boxDecorationBreak:/^box-decoration-/,boxSizing:/^box-(border|content)$/,float:/^float-(right|left|none)$/,clear:/^clear-(left|right|both|none)$/,isolation:/^(isolate|isolation-auto)$/,objectFit:/^object-(contain|cover|fill|none|scale-down)$/,objectPosition:/^object-/};function oy(o){const e=o.replace(/^(dark:|hover:|focus:|active:|disabled:|group-hover:|sm:|md:|lg:|xl:|2xl:)+/,"");for(const[a,r]of Object.entries(J_))if(r.test(e))return a;return null}function ly(o){const e=o.match(/^((dark:|hover:|focus:|active:|disabled:|group-hover:|sm:|md:|lg:|xl:|2xl:)+)/);return e?e[1]:""}function Q_(o,e){if(!e||e.trim()==="")return o;if(!o||o.trim()==="")return e;const a=o.split(/\s+/).filter(Boolean),r=e.split(/\s+/).filter(Boolean),i=new Map;for(const u of r){const d=oy(u);if(d){const f=ly(u),g=`${d}:${f}`;i.set(g,u)}}return[...a.filter(u=>{const d=oy(u);if(!d)return!0;const f=ly(u),g=`${d}:${f}`;return!i.has(g)}),...r].join(" ")}function Z_(o){return Object.entries(o).filter(([,e])=>e).map(([e])=>e).join(" ")}function eA(...o){return o.filter(e=>typeof e=="string"&&e.length>0).join(" ")}const we=ct("G7CoreGlobals");function tA(){window.React=Ye,window.ReactDOM={...Qu,createPortal:Ar.createPortal,unstable_batchedUpdates:o=>o()},window.ReactJSXRuntime=J0,we.log("전역 객체 window.React, window.ReactDOM, window.ReactJSXRuntime에 노출됨")}function nA(o){const e=new Map,a=Tr.getInstance();o.componentEvent={on:(r,i)=>(e.has(r)||e.set(r,new Set),e.get(r).add(i),a.trackEventSubscribe(r),()=>{e.get(r)?.delete(i),a.trackEventUnsubscribe(r)}),emit:async(r,i)=>{const l=e.get(r),u=l?.size??0;if(!l||l.size===0)return a.trackEventEmit(r,i,0),[];let d,f=[];try{f=await Promise.all(Array.from(l).map(async g=>{try{return await g(i)}catch(m){throw we.error(`componentEvent: Error in listener for "${r}":`,m),m}}))}catch(g){d=g instanceof Error?g:new Error(String(g))}if(a.trackEventEmit(r,i,u,f,d),d)throw d;return f},off:r=>{e.delete(r),a.trackEventOff(r)},clear:()=>{e.clear(),a.trackEventClear()}},we.log("전역 객체 window.G7Core.componentEvent에 노출됨")}function aA(o){o.__runtime||(o.__runtime={DynamicRenderer:Ha,ComponentRegistry:da,TranslationEngine:Cr,DataSourceManager:va,dataSourceManager:I_,DataBindingEngine:wn,dataBindingEngine:XS,ActionDispatcher:lo,TranslationReactContext:nf,TranslationProvider:uc,useTranslation:Fm,ResponsiveContext:Md,ResponsiveProvider:Jl,useResponsive:$d,responsiveManager:ui,BREAKPOINT_PRESETS:Dl,AuthManager:ha,createLogger:ct,G7DevToolsCore:Tr},we.log("전역 객체 window.G7Core.__runtime(코어 런타임 표면)에 노출됨"))}function rA(o){if(o.layoutEditor&&o.layoutEditor.__isStub!==!0||o.layoutEditor&&o.layoutEditor.__isStub===!0)return;const e=[],a=[];o.layoutEditor={__isStub:!0,__queue:e,__readyCallbacks:a,registerWidget:(r,i)=>e.push(["widget",r,i]),registerNodeEditor:(r,i)=>e.push(["nodeEditor",r,i]),registerCanvasOverlay:(r,i)=>e.push(["canvasOverlay",r,i]),onReady:r=>{typeof r=="function"&&a.push(r)}},we.log("전역 객체 window.G7Core.layoutEditor 예약 접수함(stub) 노출됨")}function iA(o,e){o.useTranslation=Fm,o.t=(a,r)=>{const i=e.getState();if(!i.translationEngine||!i.translationContext)return a;if(r){const l="|"+Object.entries(r).map(([u,d])=>`${u}=${d}`).join("|");return i.translationEngine.translate(a,i.translationContext,l)}return i.translationEngine.translate(a,i.translationContext)},we.log("전역 객체 window.G7Core.useTranslation에 노출됨")}function sA(o,e){o.createChangeEvent=K_,o.createClickEvent=W_,o.createSubmitEvent=Y_,o.createKeyboardEvent=X_,o.uuid=()=>typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,a=>{const r=Math.random()*16|0;return(a==="x"?r:r&3|8).toString(16)}),o.createLogger=ct,we.log("전역 객체 window.G7Core.createLogger에 노출됨"),o.renderItemChildren=(a,r,i,l,u)=>{const d=e.getState(),m={_global:window.__templateApp?.getGlobalState?.()||{},_local:r._local||{},_computed:r._computed||{},...r},b=new Set,v=(E,A)=>{const T=m._global?._remountKeys;return E&&T?.[E]&&!b.has(E)?(b.add(E),`${E}-remount-${T[E]}`):E||A},S={translationContext:d.translationContext,translationEngine:d.translationEngine,bindingEngine:d.bindingEngine,actionDispatcher:d.actionDispatcher,getRemountKey:v,...u};return Zs(a,m,i,l,S)},o.getComponentMap=()=>da.getInstance().getComponentMap(),o.renderComponentLayout=(a,r,i)=>{if(!a||!Array.isArray(a)||a.length===0)return null;const l=da.getInstance().getComponentMap(),u=e.getState(),f=window.__templateApp?.getGlobalState?.()||{},g={_global:f._global||{},_local:f._local||{},_computed:f._computed||{},...r},m=new Set,b=(v,S)=>{const E=g._global?._remountKeys;return v&&E?.[v]&&!m.has(v)?(m.add(v),`${v}-remount-${E[v]}`):v||S};return Zs(a,g,l,i,{translationContext:u.translationContext,translationEngine:u.translationEngine,bindingEngine:u.bindingEngine,actionDispatcher:u.actionDispatcher,getRemountKey:b})},o.renderExpandContent=a=>{const{children:r,row:i,expandContext:l,componentContext:u,keyPrefix:d}=a;if(!r||!Array.isArray(r)||r.length===0)return null;const f=a.componentMap||da.getInstance().getComponentMap(),g=e.getState(),m=o.state?.get?.()||{},b=u?.stateRef?.current??u?.state??{},v={...m._local||{},...b},S=u?.computedRef?.current??m._computed??{},E=g.bindingEngine??o.getDataBindingEngine?.(),A={...m,_local:v,_computed:S,row:i,item:i,$item:i};let T={};if(l&&typeof l=="object"&&E)try{for(const[D,U]of Object.entries(l))if(typeof U=="string"){const j=U.match(/^\{\{([^}]+)\}\}$/);if(j){const P=j[1].trim();try{T[D]=E.evaluateExpression(P,A,{skipCache:!0})}catch{T[D]=void 0}}else T[D]=E.resolveBindings(U,A,{skipCache:!0})}else T[D]=U}catch(D){we.warn("renderExpandContent: expandContext 평가 오류:",D)}const L={row:i,item:i,$item:i,_local:v,_global:m._global||{},_computed:m._computed||{},...T},M=new Set,R=(D,U)=>{const j=L._global?._remountKeys;return D&&j?.[D]&&!M.has(D)?(M.add(D),`${D}-remount-${j[D]}`):D||U};return Zs(r,L,f,d,{translationContext:g.translationContext,translationEngine:g.translationEngine??void 0,bindingEngine:g.bindingEngine??void 0,actionDispatcher:g.actionDispatcher,componentContext:u,getRemountKey:R})},o.$get=function(r,i,l=void 0){if(r==null)return l;const u=Array.isArray(i)?i:[i];if(u.length===0)return r;let d=r;for(const f of u){if(d==null||f==null)return l;d=d[f]}return d??l},we.log("전역 객체 window.G7Core.renderItemChildren에 노출됨"),we.log("전역 객체 window.G7Core.renderComponentLayout에 노출됨"),we.log("전역 객체 window.G7Core.renderExpandContent에 노출됨"),we.log("전역 객체 window.G7Core.$get에 노출됨")}function oA(o){o.dispatch=async(e,a)=>{const r=window.__templateApp;if(!r)return we.warn("G7Core.dispatch: TemplateApp이 초기화되지 않았습니다."),{success:!1,error:new Error("TemplateApp이 초기화되지 않았습니다.")};const i=r.getActionDispatcher?.();if(!i)return we.warn("G7Core.dispatch: ActionDispatcher를 찾을 수 없습니다."),{success:!1,error:new Error("ActionDispatcher를 찾을 수 없습니다.")};const l=r.getRouter?.(),u=r.getGlobalState?.(),d=r.setGlobalState?.bind(r),g=a?.componentContext||window.__g7ActionContext,m=window.__g7PendingLocalState;let b=g?.state??u;m&&g&&(b=m,we.log("[dispatch] Using __g7PendingLocalState for context.state:",m));let v=g?.data??u;m&&g?.data?._local&&(v={...g.data,_local:m},we.log("[dispatch] Updated context.data._local with pendingLocalState"));const S={navigate:l?(E,A)=>l.navigate(E,A):void 0,setState:g?.setState??d,state:b,data:v,_isDispatchFallbackContext:!g?.setState};if(e.debounce){const E=e.debounceKey||`dispatch-${e.handler}`,A=typeof e.debounce=="number"?e.debounce:e.debounce.delay;return i.debouncedCall(E,A,()=>{const{debounce:T,debounceKey:L,...M}=e;i.dispatchAction(M,S)}),{success:!0,debounced:!0}}try{return await i.dispatchAction(e,S)}catch(E){return we.error("G7Core.dispatch: 액션 실행 오류:",E),{success:!1,error:E instanceof Error?E:new Error(String(E))}}},we.log("전역 객체 window.G7Core.dispatch에 노출됨")}function wo(o){const e={};for(const[a,r]of Object.entries(o))if(a.includes(".")){const i=a.split(".");let l=e;for(let u=0;u0&&e.every(a=>/^\d+$/.test(a))}function uy(o,e){const a={...o};for(const r of Object.keys(e))r in a?a[r]!==null&&typeof a[r]=="object"&&!Array.isArray(a[r])&&e[r]!==null&&typeof e[r]=="object"&&!Array.isArray(e[r])&&(a[r]=uy(a[r],e[r])):a[r]=e[r];return a}function Zn(o,e){if(Array.isArray(o)&&!Array.isArray(e)&&lA(e)){const r=Object.keys(e).map(l=>parseInt(l,10));if(!((r.length>0?Math.max(...r):0)>=o.length+r.length+10)){const l=[...o];for(const[u,d]of Object.entries(e)){const f=parseInt(u,10);f>=0&&f=l.length&&(l[f]=d)}return l}}const a={...o};for(const[r,i]of Object.entries(e))i!==null&&typeof i=="object"&&!Array.isArray(i)?a[r]!==null&&typeof a[r]=="object"?a[r]=Zn(a[r],i):a[r]={...i}:a[r]=i;return a}function cA(o){o.state={get:()=>window.__templateApp?.getGlobalState?.()||{},set:(e,a)=>{const r=window.__templateApp;if(r?.setGlobalState&&r?.getGlobalState){const i=a?.merge||"deep",l=wo(e);let u;if(i==="replace")u=l;else if(i==="shallow")u={...r.getGlobalState(),...l};else{const d=r.getGlobalState();u=Zn(d,l)}r.setGlobalState(u,{render:a?.render})}else we.warn("G7Core.state.set: TemplateApp이 초기화되지 않았습니다.")},setLocal:(e,a)=>{const r=window.__templateApp;if(a?.render===!1&&!a?.selfManaged){const T=window.__g7AutoBindingPaths;T&&T.size>0&&cy(wo(e)).some(M=>T.has(M))&&(we.log("[setLocal] render:false + 자동바인딩 경로 겹침 감지 → render:true 자동 승격 (engine-v1.43.0)"),a={...a,render:!0})}if(a?.debounce){const T=r?.getActionDispatcher?.();if(T){const L=a.debounceKey||`setLocal-${Object.keys(e).join(",")}`,{debounce:M,debounceKey:R,...D}=a;T.debouncedCall(L,a.debounce,()=>{o.state.setLocal(e,D)});return}}const i=a?.scope??"current",l=a?.merge||"deep",u=window.__g7ActionContext,d=wo(e);if(i==="parent"||i==="root"){const T=window.__g7LayoutContextStack||[];if(T.length>0){const L=i==="parent"?T[T.length-1]:T[0];if(L?.setState){L.setState(M=>l==="replace"?d:l==="shallow"?{...M||{},...d}:Zn(M||{},d)),we.log(`[setLocal] scope=${i}: 타겟 컨텍스트에 상태 업데이트 (mergeMode=${l})`,d);return}}we.warn(`[setLocal] scope=${i}: 레이아웃 컨텍스트 스택이 비어있습니다. current로 폴백합니다.`)}const f=window.__g7PendingLocalState,g=r?.getGlobalState?.()?._local||{},v=!((window.__g7LayoutContextStack||[]).length>0)&&u?.state?u.state:void 0,S=v?uy(g,v):g,E=f||S;let A;if(l==="replace"?A=d:l==="shallow"?A={...E,...d}:A=Zn(E,d),r?.setGlobalState&&(r.setGlobalState({_local:A},{render:a?.render}),we.log(`[setLocal] globalLocal updated via setGlobalState (mergeMode=${l}, render=${a?.render??!0}):`,d)),window.__g7PendingLocalState=A,we.log("[setLocal] __g7PendingLocalState updated:",A),window.__g7SequenceLocalSync=A,window.__g7LastSetLocalSnapshot=A,l==="replace")window.__g7ForcedLocalFields=d;else{const T=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=Zn(T,d)}if(we.log("[setLocal] __g7ForcedLocalFields updated:",d),l==="replace")window.__g7SetLocalOverrideKeys=d;else{const T=window.__g7SetLocalOverrideKeys||{};window.__g7SetLocalOverrideKeys=Zn(T,d)}we.log("[setLocal] __g7SetLocalOverrideKeys updated:",d),u?.setState&&u.setState(T=>l==="replace"?d:l==="shallow"?{...T||{},...d}:Zn(T||{},d)),r?.setGlobalState||we.warn("G7Core.state.setLocal: TemplateApp이 없습니다.")},getLocal:()=>{const r=(window.__templateApp?.getGlobalState?.()||{})._local||{},i=window.__g7PendingLocalState;if(i)return Zn(r,i);const l=window.__g7LastSetLocalSnapshot;return l&&l!==r?Zn(r,l):r},update:e=>{const a=window.__templateApp;if(a?.getGlobalState&&a?.setGlobalState){const r=a.getGlobalState(),i=e(r);a.setGlobalState(i)}else we.warn("G7Core.state.update: TemplateApp이 초기화되지 않았습니다.")},subscribe:e=>{const a=window.__templateApp;return a?.onGlobalStateChange?a.onGlobalStateChange(e):(we.warn("G7Core.state.subscribe: TemplateApp이 초기화되지 않았습니다."),()=>{})},getDataSource:e=>window.__templateApp?.getDataSource?.(e),getIsolated:e=>e?window.__g7IsolatedStates?.[e]?.state??null:window.__g7ActionContext?.isolatedContext?.state??null,setIsolated:(e,a,r)=>{let i,l,u;typeof e=="string"?(i=e,l=a||{},u=r):(l=e,u=a&&typeof a=="object"&&"merge"in a?a:r);const d=u?.merge||"deep",f=wo(l);if(i){const b=window.__g7IsolatedStates?.[i];b?.mergeState?b.mergeState(f,d):we.warn(`G7Core.state.setIsolated: scopeId '${i}'를 찾을 수 없습니다.`);return}const g=window.__g7ActionContext;g?.isolatedContext?.mergeState?g.isolatedContext.mergeState(f,d):we.warn("G7Core.state.setIsolated: 액션 컨텍스트에 isolatedContext가 없습니다.")},getParent:()=>{const e=window.__g7LayoutContextStack||[];if(e.length===0)return we.log("[getParent] 레이아웃 컨텍스트 스택이 비어있습니다."),null;const a=e[e.length-1];if(!a)return null;const r=a.dataContext||{};return{_local:a.state||r._local||{},_global:r._global||o.state.get()||{},setState:a.setState}},setParentLocal:(e,a,r)=>{const i=window.__g7LayoutContextStack||[];if(i.length===0){we.warn("[setParentLocal] 레이아웃 컨텍스트 스택이 비어있습니다.");return}const l=i[i.length-1];if(!l?.setState){we.warn("[setParentLocal] 부모 컨텍스트에 setState가 없습니다.");return}let u,d;typeof e=="string"?(u={[e]:a},d=r):(u=e,d=a&&typeof a=="object"&&"merge"in a?a:r);const f=d?.merge||"deep",g=wo(u),m=l.state?._local!==void 0,b=m?l.state._local:l.state||{};let v;f==="replace"?v=g:f==="shallow"?v={...b,...g}:v=Zn(b,g),window.__g7PendingLocalState=v;const S=window.__templateApp;if(S?.setGlobalState&&S.setGlobalState({_local:v}),l.setState(v),m?l.state._local=v:l.state=v,l.dataContext&&(l.dataContext._local=v),f==="replace")window.__g7ForcedLocalFields=g;else{const E=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=Zn(E,g)}Dd()},setParentGlobal:(e,a)=>{let r;typeof e=="string"?r={[e]:a}:r=e,o.state.set(r),we.log("[setParentGlobal] 전역 상태 업데이트:",r)}},window.__g7IsolatedStates||(window.__g7IsolatedStates={}),o.state.getGlobal=o.state.get,o.state.setGlobal=o.state.set,we.log("전역 객체 window.G7Core.state에 노출됨")}function uA(o){o.dataSource={get:e=>window.__templateApp?.getDataSource?.(e),set:(e,a,r)=>{const i=window.__templateApp;i?.setDataSource?i.setDataSource(e,a,r):we.warn("G7Core.dataSource.set: TemplateApp이 초기화되지 않았습니다.")},refetch:async(e,a)=>{const r=window.__templateApp;if(r?.refetchDataSource)return r.refetchDataSource(e,a);we.warn("G7Core.dataSource.refetch: TemplateApp이 초기화되지 않았습니다.")},updateItem:(e,a,r,i,l)=>{const u=window.__templateApp;return u?.updateDataSourceItem?u.updateDataSourceItem(e,a,r,i,l):(we.warn("G7Core.dataSource.updateItem: TemplateApp이 초기화되지 않았습니다."),!1)},updateData:(e,a,r,i="append")=>{const l=window.__templateApp;if(!l?.getDataSource||!l?.setDataSource)return we.warn("G7Core.dataSource.updateData: TemplateApp이 초기화되지 않았습니다."),!1;const u=l.getDataSource(e);if(!u)return we.warn(`G7Core.dataSource.updateData: 데이터 소스 '${e}'를 찾을 수 없습니다.`),!1;let d,f=u,g=null;if(a){const b=a.split(".");g=b.pop();for(const v of b)if(f&&typeof f=="object"&&v in f)f=f[v];else return we.warn(`G7Core.dataSource.updateData: 경로 '${a}'를 찾을 수 없습니다.`),!1;d=f[g]}else d=u;if(!Array.isArray(d))return we.warn("G7Core.dataSource.updateData: 대상 경로의 데이터가 배열이 아닙니다."),!1;if(!Array.isArray(r))return we.warn("G7Core.dataSource.updateData: newData가 배열이 아닙니다."),!1;const m=i==="prepend"?[...r,...d]:[...d,...r];return a&&g?(f[g]=m,l.setDataSource(e,u,{merge:!1})):l.setDataSource(e,m,{merge:!1}),we.log(`G7Core.dataSource.updateData: '${e}'에 ${r.length}개 항목 ${i==="prepend"?"앞에":"뒤에"} 추가됨`),!0}},we.log("전역 객체 window.G7Core.dataSource에 노출됨")}function dA(o,e){o.locale={current:()=>window.__templateApp?.getLocale?.()||"ko",supported:()=>{const r=window.__templateApp?.globalState?.appConfig?.supportedLocales;return Array.isArray(r)&&r.length>0?r:e.getState().templateMetadata?.locales||["ko","en"]},change:async a=>{const r=window.__templateApp;r?.changeLocale?await r.changeLocale(a):we.warn("G7Core.locale.change: TemplateApp이 초기화되지 않았습니다.")}},we.log("전역 객체 window.G7Core.locale에 노출됨")}function fA(o){o.toast={show:(e,a)=>{o.dispatch({handler:"toast",params:{message:e,type:a?.type||"info",...a?.duration&&{duration:a.duration}}})},success:(e,a)=>{o.toast.show(e,{type:"success",duration:a})},error:(e,a)=>{o.toast.show(e,{type:"error",duration:a})},warning:(e,a)=>{o.toast.show(e,{type:"warning",duration:a})},info:(e,a)=>{o.toast.show(e,{type:"info",duration:a})}},we.log("전역 객체 window.G7Core.toast에 노출됨")}function hA(o){o.modal={open:e=>{o.dispatch({handler:"openModal",target:e})},close:e=>{o.dispatch({handler:"closeModal",...e&&{target:e}})},closeAll:()=>{o.dispatch({handler:"closeAllModals"})},isOpen:e=>{const a=o.state.get();return a._global?.activeModal===e||a._global?.modalStack?.includes(e)||!1},getStack:()=>o.state.get()._global?.modalStack||[]},we.log("전역 객체 window.G7Core.modal에 노출됨")}function gA(o){o.style={mergeClasses:Q_,conditionalClass:Z_,joinClasses:eA},we.log("전역 객체 window.G7Core.style에 노출됨")}function pA(o,e){const{webSocketManager:a}=e;o.websocket={manager:a,subscribe:(r,i,l,u)=>a.subscribe(r,i,l,u),unsubscribe:r=>a.unsubscribe(r),leaveChannel:r=>a.leaveChannel(r),disconnect:()=>a.disconnect(),isInitialized:()=>a.isInitialized(),getSubscriptionCount:()=>a.getSubscriptionCount()},we.log("전역 객체 window.G7Core.websocket에 노출됨")}function mA(o,e){const{transitionManager:a}=e;o.navigation={isPending:()=>a?.getIsPending?.()||!1,onComplete:r=>{if(!a)return r(),()=>{};let i=a.getIsPending();const l=a.subscribe(u=>{u?i=!0:i&&(r(),l())});return l}},we.log("전역 객체 window.G7Core.navigation에 노출됨")}function yA(o){o.plugin={getSettings:e=>window.G7Config?.plugins?.[e],get:(e,a,r)=>window.G7Config?.plugins?.[e]?.[a]??r,getAll:()=>window.G7Config?.plugins??{}},we.log("전역 객체 window.G7Core.plugin에 노출됨")}function bA(o){o.module={getSettings:e=>window.G7Config?.modules?.[e],get:(e,a,r)=>window.G7Config?.modules?.[e]?.[a]??r,getAll:()=>window.G7Config?.modules??{}},we.log("전역 객체 window.G7Core.module에 노출됨")}function vA(o,e){const{transitionManager:a,responsiveManager:r}=e;o.AuthManager=ha,o.api=$a(),o.TransitionManager=a,o.useTransitionState=nm,o.ResponsiveManager=r,o.useResponsive=$d,o.useControllableState=lC,o.shallowArrayEqual=cC,o.shallowObjectEqual=rm,o.updateQueryParams=async(i,l)=>{const u=window.__templateApp;if(u?.updateQueryParams)return u.updateQueryParams(i,l);we.warn("G7Core.updateQueryParams: TemplateApp이 초기화되지 않았습니다.")},we.log("전역 객체 window.G7Core.AuthManager에 노출됨"),we.log("전역 객체 window.G7Core.api에 노출됨"),we.log("전역 객체 window.G7Core.ResponsiveManager에 노출됨"),we.log("전역 객체 window.G7Core.useResponsive에 노출됨"),we.log("전역 객체 window.G7Core.useControllableState에 노출됨"),we.log("전역 객체 window.G7Core.updateQueryParams에 노출됨")}function SA(o,e){o.getSlotContext=()=>window.__slotContextValue??null,o.getDynamicRenderer=()=>window.__DynamicRenderer??null,o.getComponentRegistry=()=>e.getComponentRegistry?.()??da.getInstance(),o.getDataBindingEngine=()=>e.getDataBindingEngine?.()??e.getState().bindingEngine,o.getTranslationEngine=()=>e.getTranslationEngine?.()??e.getState().translationEngine,o.getActionDispatcher=()=>e.getActionDispatcher?.()??e.getState().actionDispatcher,we.log("전역 객체 window.G7Core 슬롯 API에 노출됨 (getSlotContext, getDynamicRenderer 등)")}function wA(o){o.identity={setLauncher:St.setLauncher.bind(St),handle:St.handle.bind(St),isIdentityRequired:St.isIdentityRequired.bind(St),hasLauncher:St.hasLauncher.bind(St),markDomainNoticeShown:St.markDomainNoticeShown.bind(St),redirectExternally:St.redirectExternally.bind(St),createDeferred:St.createDeferred.bind(St),resolveDeferred:St.resolveDeferred.bind(St),reset:St.reset.bind(St),redirectStashKey:_d},we.log("전역 객체 window.G7Core 본인인증(IDV) API에 노출됨 (identity)")}function CA(o){if(typeof window>"u")return;tA(),window.G7Core||(window.G7Core={});const e=window.G7Core;aA(e),nA(e),rA(e),vA(e,o),iA(e,o),sA(e,o),oA(e),cA(e),uA(e),dA(e,o),fA(e),hA(e),gA(e),pA(e,o),mA(e,o),yA(e),bA(e),SA(e,o),wA(e),we.log("G7Core 전역 객체 초기화 완료")}function EA(){const o=window.G7Core;if(!o){we.warn("G7Core가 초기화되지 않았습니다.");return}const e=()=>Tr.getInstance(),a={isEnabled:()=>{try{return e().isEnabled()}catch{return!1}},trackRender:r=>{try{e().isEnabled()&&e().trackRender(r)}catch{}},trackIteration:(r,i,l,u,d)=>{try{e().isEnabled()&&e().trackIteration(r,{source:i,itemVar:l,indexVar:u,sourceLength:d})}catch{}},trackIfCondition:(r,i,l,u)=>{try{e().isEnabled()&&e().trackIfCondition(r,i,l)}catch{}},trackMount:(r,i)=>{try{e().isEnabled()&&e().trackMount(r,{...i,id:r})}catch{}},trackUnmount:r=>{try{e().isEnabled()&&e().trackUnmount(r)}catch{}},trackExpressionEval:r=>{try{e().isEnabled()&&e().trackExpressionEval(r)}catch{}},trackBindingEval:r=>{try{e().isEnabled()&&e().trackBindingEval(r)}catch{}},recordCacheHit:()=>{try{e().isEnabled()&&e().recordCacheHit()}catch{}},recordCacheMiss:()=>{try{e().isEnabled()&&e().recordCacheMiss()}catch{}},trackHandlerRegistration:(r,i,l,u)=>{try{e().isEnabled()&&e().trackHandlerRegistration(r,i,l,u)}catch{}},trackHandlerUnregistration:r=>{try{e().isEnabled()&&e().trackHandlerUnregistration(r)}catch{}},logAction:r=>{try{e().isEnabled()&&e().logAction(r)}catch{}},trackRequest:(r,i)=>{try{return e().isEnabled()?e().trackRequest(r,i):""}catch{return""}},completeRequest:(r,i,l)=>{try{e().isEnabled()&&e().completeRequest(r,i,l)}catch{}},failRequest:(r,i)=>{try{e().isEnabled()&&e().failRequest(r,i)}catch{}},trackDataSourceDefinition:r=>{try{e().isEnabled()&&e().trackDataSourceDefinition(r)}catch{}},trackDataSourceLoading:r=>{try{e().isEnabled()&&e().trackDataSourceLoading(r)}catch{}},trackDataSourceLoaded:(r,i,l)=>{try{e().isEnabled()&&e().trackDataSourceLoaded(r,i,l)}catch{}},trackDataSourceError:(r,i)=>{try{e().isEnabled()&&e().trackDataSourceError(r,i)}catch{}},trackForm:(r,i,l)=>{try{e().isEnabled()&&e().trackForm(r,i,l)}catch{}},untrackForm:r=>{try{e().isEnabled()&&e().untrackForm(r)}catch{}},startStateChange:(r,i,l,u)=>{try{return e().isEnabled()?e().startStateChange(r,i,l,u):""}catch{return""}},completeStateChange:r=>{try{e().isEnabled()&&e().completeStateChange(r)}catch{}},trackComponentRender:(r,i,l,u,d,f)=>{try{e().isEnabled()&&e().trackComponentRender(r,i,l,u,d,f)}catch{}},updateLocalState:r=>{try{e().isEnabled()&&e().updateLocalState(r)}catch{}},updateComputedState:r=>{try{e().isEnabled()&&e().updateComputedState(r)}catch{}},updateParentContext:r=>{try{e().isEnabled()&&e().updateParentContext(r)}catch{}},trackComponentStateSource:(r,i,l,u)=>{try{e().isEnabled()&&e().trackComponentStateSource(r,i,l,u)}catch{}},trackDynamicState:(r,i)=>{try{e().isEnabled()&&e().trackDynamicState(r,i)}catch{}},trackContextFlow:(r,i,l,u,d,f)=>{try{e().isEnabled()&&e().trackContextFlow(r,i,l,u,d,f)}catch{}},trackComponentStyle:(r,i,l,u)=>{try{e().isEnabled()&&e().trackComponentStyle(r,i,l,u)}catch{}},trackAuthEvent:(r,i,l,u)=>{try{e().isEnabled()&&e().trackAuthEvent(r,i,l,u)}catch{}},trackAuthHeader:(r,i,l,u,d)=>{try{e().isEnabled()&&e().trackAuthHeader(r,i,l,u,d)}catch{}},trackLog:(r,i,l)=>{try{e().isEnabled()&&e().trackLog(r,i,l)}catch{}},trackAction:r=>{try{e().isEnabled()&&e().trackAction?.(r)}catch{}},trackDataSourceUpdate:r=>{try{e().isEnabled()&&e().trackDataSourceUpdate?.(r)}catch{}},startSequenceExecution:r=>{try{return e().isEnabled()?e().startSequenceExecution(r):""}catch{return""}},captureSequenceActionBefore:(r,i,l,u,d)=>{try{e().isEnabled()&&e().captureSequenceActionBefore(r,i,l,u,d)}catch{}},captureSequenceActionAfter:(r,i,l,u,d,f)=>{try{e().isEnabled()&&e().captureSequenceActionAfter(r,i,l,u,d,f)}catch{}},endSequenceExecution:(r,i)=>{try{e().isEnabled()&&e().endSequenceExecution(r,i)}catch{}},registerStateCaptureForHandler:(r,i,l)=>{try{e().isEnabled()&&e().registerStateCaptureForHandler(r,i,l)}catch{}},detectStaleClosure:(r,i,l,u,d)=>{try{return e().isEnabled()?e().detectStaleClosure(r,i,l,u,d):[]}catch{return[]}},trackStaleClosureWarning:r=>{try{e().isEnabled()&&e().trackStaleClosureWarning(r)}catch{}},trackModalOpen:r=>{try{e().isEnabled()&&e().trackModalOpen(r)}catch{}},trackModalClose:(r,i)=>{try{e().isEnabled()&&e().trackModalClose(r,i)}catch{}},trackModalStateChange:r=>{try{e().isEnabled()&&e().trackModalStateChange(r)}catch{}},trackNestedContext:r=>{try{return e().isEnabled()?e().trackNestedContext(r):""}catch{return""}},trackNestedContextAccess:(r,i)=>{try{e().isEnabled()&&e().trackNestedContextAccess(r,i)}catch{}},trackComputedProperty:(r,i,l,u,d,f,g)=>{try{e().isEnabled()&&e().trackComputedProperty(r,i,l,u,d,f,g)}catch{}},trackComputedRecalc:(r,i,l,u,d,f,g)=>{try{e().isEnabled()&&e().trackComputedRecalc(r,i,l,u,d,f,g)}catch{}},setNamedActionDefinitions:r=>{try{e().isEnabled()&&e().setNamedActionDefinitions(r)}catch{}},trackNamedActionRef:r=>{try{e().isEnabled()&&e().trackNamedActionRef(r)}catch{}}};o.devTools=a,we.log("G7Core.devTools 인터페이스 초기화 완료")}let Co=null;function _A(){const o=window.G7Core;return o?.__devtools?Promise.resolve(o.__devtools):Co||(Co=new Promise((e,a)=>{const r=window.G7Config?.coreDevToolsAsset||"/build/core/devtools.min.js",i="g7-devtools-bundle",l=()=>{const f=window.G7Core?.__devtools;f?e(f):a(new Error("DevTools 번들 로드됨 — 그러나 __devtools 미노출"))};window.G7Core=window.G7Core||{},window.G7Core.__onDevToolsReady=l;const u=document.getElementById(i);if(u){u.addEventListener("load",l,{once:!0}),u.addEventListener("error",()=>a(new Error(`DevTools 번들 로드 실패: ${r}`)),{once:!0});return}const d=document.createElement("script");d.id=i,d.src=r,d.async=!1,d.addEventListener("load",l,{once:!0}),d.addEventListener("error",()=>{Co=null,a(new Error(`DevTools 번들 로드 실패: ${r}`))},{once:!0}),document.head.appendChild(d)}),Co)}function AA(){const o=window.G7Core;if(!o){we.warn("G7Core가 초기화되지 않았습니다.");return}const e=Tr.getInstance();if(e.initialize(),!e.isEnabled()){window.G7DevTools={isEnabled:()=>!1,enable:()=>{we.log("환경설정 > 고급 설정 > 디버그 모드를 켜세요")}},ed(),we.log("G7DevTools 비활성화됨 (디버그 모드 꺼짐)");return}xA(o,e)}async function xA(o,e){let a;try{a=await _A()}catch(g){we.warn("DevTools 번들 로드 실패 — 최소 API 로 폴백:",g),window.G7DevTools={isEnabled:()=>!1,enable:()=>{}},ed();return}const{DiagnosticEngine:r,getServerConnector:i,getStyleTracker:l}=a;EA(),ed();try{l().enable(),we.log("StyleTracker 활성화됨")}catch(g){we.warn("StyleTracker 활성화 실패:",g)}const u=new r,d=i(),f={isEnabled:()=>e.isEnabled(),state:{get:()=>e.getState(),getHistory:()=>e.getStateHistory(),watch:(g,m)=>e.watchState(g,m)},actions:{getHistory:()=>e.getActionHistory(),watch:g=>e.watchActions(g),getMetrics:()=>e.getActionMetrics()},binding:{evaluate:g=>{const m=o.getDataBindingEngine?.();if(!m){we.warn("DataBindingEngine이 없습니다.");return}return m.evaluateExpression(g,e.getState())},getCacheStats:()=>e.getCacheStats(),clearStats:()=>{e.resetCacheStats(),we.log("캐시 통계 초기화됨")}},diagnose:{analyze:g=>u.analyze(g),suggestFix:g=>u.suggestFix(g),getCommonIssues:()=>u.getCommonIssues(),getRulesByCategory:g=>u.getRulesByCategory(g)},server:{dumpState:g=>d.dumpState(g),sendLog:g=>d.sendLog(g),sendError:(g,m)=>d.sendError(g,m),isConnected:()=>d.isConnected(),testConnection:()=>d.testConnection()},config:{isDebugMode:()=>e.isEnabled(),setLogLevel:g=>e.setLogLevel(g),setMaxHistory:g=>e.setMaxHistory(g)},lifecycle:{getMountedComponents:()=>e.getLifecycleInfo().mountedComponents,getOrphanedListeners:()=>e.getLifecycleInfo().orphanedListeners},performance:{getRenderCount:()=>e.getPerformanceInfo().renderCounts,getBindingEvalCount:()=>e.getPerformanceInfo().bindingEvalCount,getMemoryWarnings:()=>e.getPerformanceInfo().memoryWarnings,startProfiling:()=>e.startProfiling(),stopProfiling:()=>e.stopProfiling()},network:{getActiveRequests:()=>e.getNetworkInfo().activeRequests,getRequestHistory:()=>e.getNetworkInfo().requestHistory,getPendingDataSources:()=>e.getNetworkInfo().pendingDataSources},conditional:{getIfConditions:()=>e.getConditionalInfo().ifConditions,getIterations:()=>e.getConditionalInfo().iterations},form:{getForms:()=>e.getFormInfo()},websocket:{getInfo:()=>e.getWebSocketInfo()}};window.G7DevTools=f,o.devtools=f,we.log("G7DevTools 전역 객체 초기화 완료 (window.G7DevTools)"),TA(a.DevToolsPanel)}function TA(o){if(document.getElementById("g7-devtools-root")){we.log("DevToolsPanel 이미 렌더링됨");return}const e=document.createElement("div");e.id="g7-devtools-root",document.body.appendChild(e);try{Qu.createRoot(e).render(Ye.createElement(o)),we.log("DevToolsPanel UI 렌더링 완료")}catch(a){we.error("DevToolsPanel UI 렌더링 실패:",a)}}const Ze=ct("TemplateEngine"),se={templateId:null,locale:"ko",isInitialized:!1,reactRoot:null,containerId:null,currentLayoutJson:null,currentDataContext:{},translationContext:{templateId:"",locale:"ko"},registry:null,bindingEngine:null,translationEngine:null,actionDispatcher:null,templateMetadata:null};let Eo=!1;const _o=[];async function RA(o){try{Ze.log("템플릿 메타데이터 로드 중...",o);const e=o.split("-").map(r=>r.split("_").map(i=>i.charAt(0).toUpperCase()+i.slice(1)).join("")).join(""),a=window[e];return a?.templateMetadata?(Ze.log("템플릿 메타데이터 로드 완료 (전역 변수)",a.templateMetadata),a.templateMetadata):(Ze.warn(`템플릿 번들에 메타데이터가 없습니다. 전역 변수: ${e}`),{identifier:o,locales:["ko","en"],name:{ko:o,en:o},description:{ko:"",en:""},version:"1.0.0",type:"admin"})}catch(e){return Ze.error("템플릿 메타데이터 로드 실패",e),{identifier:o,locales:["ko","en"],name:{ko:o,en:o},description:{ko:"",en:""},version:"1.0.0",type:"admin"}}}function dy(){const e=(typeof window<"u"?window.__templateApp:void 0)?.globalState?.appConfig?.supportedLocales,a=se.templateMetadata?.locales;return{$locale:se.locale,$locales:Array.isArray(e)&&e.length>0?e:a||["ko","en"],$templateLocales:a||["ko","en"],$templateId:se.templateId}}async function Ao(o){try{if(Ze.log("템플릿 엔진 초기화 시작",o),se.isInitialized)throw new Error("템플릿 엔진이 이미 초기화되었습니다. destroyTemplate()을 먼저 호출하세요.");if(!o.templateId)throw new z_;Eo=o.debug??!1,typeof window<"u"&&(window.G7Config||(window.G7Config={}),window.G7Config.debug=Eo),AA(),se.templateId=o.templateId,se.locale=o.locale||"ko",Ze.log("엔진 인스턴스 생성 중..."),se.registry=da.getInstance(),se.bindingEngine=new wn,se.translationEngine=Cr.getInstance(),o.cacheVersion!==void 0&&o.cacheVersion>0&&se.translationEngine.setCacheVersion(o.cacheVersion),se.translationContext={templateId:o.templateId,locale:se.locale},se.actionDispatcher=new lo({},se.translationEngine,se.translationContext),eC(se.actionDispatcher),Ze.log("다국어 파일 로드 중...",o.templateId,se.locale);const e="en",a=[se.translationEngine.loadTranslations(o.templateId,se.locale).then(()=>{Ze.log(`다국어 파일 로드 완료: ${se.locale}`)}).catch(r=>{Ze.warn(`다국어 파일 로드 실패 (${se.locale}):`,r instanceof Error?r.message:r)})];se.locale!==e&&a.push(se.translationEngine.loadTranslations(o.templateId,e).then(()=>{Ze.log(`폴백 다국어 파일 로드 완료: ${e}`)}).catch(r=>{Ze.warn(`폴백 다국어 파일 로드 실패 (${e}):`,r instanceof Error?r.message:r)})),await Promise.allSettled(a),Ze.log("템플릿 메타데이터 로드 중...",o.templateId),se.templateMetadata=await RA(o.templateId),se.isInitialized=!0,Ze.log("템플릿 엔진 초기화 완료 (ComponentRegistry는 별도 로드)")}catch(e){throw Ze.error("템플릿 엔진 초기화 실패",e),se.isInitialized=!1,se.registry=null,se.bindingEngine=null,se.translationEngine=null,se.actionDispatcher=null,e}}let xo=null;function gf(){const o=window.G7Core;return o?.__LayoutEditorChrome?Promise.resolve(o.__LayoutEditorChrome):xo||(xo=new Promise((e,a)=>{const r=window.G7Config?.coreEditorAsset||"/build/core/layout-editor.min.js",i="g7-layout-editor-bundle",l=document.getElementById(i),u=()=>{const f=window.G7Core?.__LayoutEditorChrome;f?e(f):a(new Error("편집기 번들 로드됨 — 그러나 __LayoutEditorChrome 미노출"))};if(window.G7Core=window.G7Core||{},window.G7Core.__onChromeReady=u,l){l.addEventListener("load",u,{once:!0}),l.addEventListener("error",()=>a(new Error(`편집기 번들 로드 실패: ${r}`)),{once:!0});return}const d=document.createElement("script");d.id=i,d.src=r,d.async=!1,d.addEventListener("load",u,{once:!0}),d.addEventListener("error",()=>{xo=null,a(new Error(`편집기 번들 로드 실패: ${r}`))},{once:!0}),document.head.appendChild(d)}),xo)}async function ls(o){try{if(Ze.log("템플릿 렌더링 시작",o),!se.isInitialized)throw new Error("템플릿 엔진이 초기화되지 않았습니다. initTemplateEngine()을 먼저 호출하세요.");if(!o.containerId)throw new Error("containerId는 필수입니다.");if(!o.layoutJson)throw new Error("layoutJson은 필수입니다.");const e=document.getElementById(o.containerId);if(!e)throw new Error(`컨테이너를 찾을 수 없습니다: #${o.containerId}`);const a=dy();if(se.containerId=o.containerId,se.currentLayoutJson=o.layoutJson,se.currentDataContext={...a,...o.dataContext||{}},se.translationContext=o.translationContext||{templateId:se.templateId||"",locale:se.locale},se.reactRoot||(Ze.log("React Root 생성"),se.reactRoot=Qu.createRoot(e)),typeof window<"u"){const l=iy(window.location.pathname);if(l){Ze.log("레이아웃 편집기 모드 진입",l);let u;try{u=await gf()}catch(f){Ze.error("레이아웃 편집기 번들 로드 실패",f),cf.render(o.containerId,{title:"레이아웃 편집기 로드 실패",message:f instanceof Error?f.message:"편집기 번들을 불러오지 못했습니다.",icon:"fas fa-triangle-exclamation",showStack:!1,showReloadButton:!0,debug:Eo});return}const d=Ye.createElement(u,{templateIdentifier:l.templateIdentifier,initialLocale:se.locale});se.reactRoot.render(Ye.createElement(uc,{translationEngine:se.translationEngine,translationContext:se.translationContext,children:Ye.createElement(Od,{children:Ye.createElement(Jl,{children:Ye.createElement(af,{children:d})})})}));return}}const r=o.layoutJson.components||[];if(r.length===0){Ze.warn("렌더링할 컴포넌트가 없습니다.");return}const i=o.layoutJson.modals||[];if(Ze.log("modals 배열:",i),Ze.log("modals 개수:",i.length),Ze.log("DynamicRenderer로 렌더링 시작"),se.reactRoot.render(Ye.createElement(uc,{translationEngine:se.translationEngine,translationContext:se.translationContext},Ye.createElement(Od,null,Ye.createElement(Jl,null,Ye.createElement(af,null,[...r.map((l,u)=>{const d=se.currentLayoutJson?.layout_name||"";return Ye.createElement(Ha,{key:d&&!l._fromBase?`${l.id}_${d}`:l.id,componentDef:l,dataContext:se.currentDataContext,translationContext:se.translationContext,registry:se.registry,bindingEngine:se.bindingEngine,translationEngine:se.translationEngine,actionDispatcher:se.actionDispatcher,isRootRenderer:u===0,layoutKey:d})}),Ye.createElement(Jp,{key:"__modal_parent_context_provider"},i.map(l=>{const u=se.currentDataContext._global?.modalStack||[],f=u.includes(l.id)||se.currentDataContext._global?.activeModal===l.id,g=u.indexOf(l.id),m=g>=0?50+g:50,b=window.__g7LayoutContextStack||[],S=b[b.length-1]?.dataContext,E=Ye.createElement(Ha,{key:`modal_${l.id}_renderer`,componentDef:{...l,props:{...l.props,isOpen:f,style:{...l.props?.style,zIndex:m},onClose:se.actionDispatcher?.createHandler({type:"click",handler:"closeModal"},se.currentDataContext)}},dataContext:se.currentDataContext,translationContext:se.translationContext,registry:se.registry,bindingEngine:se.bindingEngine,translationEngine:se.translationEngine,actionDispatcher:se.actionDispatcher,parentDataContext:S});return l.data_sources&&l.data_sources.length>0?Ye.createElement(ay,{key:`modal_${l.id}`,isOpen:f,modalId:l.id,dataSources:l.data_sources,dataContext:se.currentDataContext,globalStateUpdater:se.actionDispatcher?.getGlobalStateUpdater(),bindingEngine:se.bindingEngine,debug:Eo,children:E}):E}))]))))),Ze.log("템플릿 렌더링 완료"),_o.length>0){Ze.log(`대기 중인 데이터 업데이트 ${_o.length}건 적용`);const l=[..._o];_o.length=0;for(const{data:u,options:d}of l)cs(u,d)}}catch(e){throw Ze.error("템플릿 렌더링 실패",e),e}}function cs(o,e){try{if(Ze.log("템플릿 데이터 업데이트 시작",Object.keys(o)),!se.isInitialized)throw new Error("템플릿 엔진이 초기화되지 않았습니다.");if(!se.reactRoot||!se.currentLayoutJson){Ze.log("React 미준비 - 데이터 업데이트 큐잉:",Object.keys(o)),_o.push({data:o,options:e});return}const a=dy(),r={...se.currentDataContext._global||{},...o._global||{}},i=sC(se.currentDataContext._localInit,o._localInit);se.currentDataContext={...a,...se.currentDataContext,...o,_global:r,_localInit:i},r._local!==void 0&&(se.currentDataContext._local=r._local),r._computed!==void 0&&(se.currentDataContext._computed=r._computed);const l=se.currentLayoutJson.components||[],u=se.currentLayoutJson.modals||[];Ze.log("updateTemplateData - modals 배열:",u),Ze.log("updateTemplateData - modals 개수:",u.length),Ze.log("updateTemplateData - activeModal:",se.currentDataContext._global?.activeModal);const d=()=>{se.reactRoot.render(Ye.createElement(uc,{translationEngine:se.translationEngine,translationContext:se.translationContext},Ye.createElement(Od,null,Ye.createElement(Jl,null,Ye.createElement(af,null,[...l.map((f,g)=>{const m=se.currentLayoutJson?.layout_name||"";return Ye.createElement(Ha,{key:m&&!f._fromBase?`${f.id}_${m}`:f.id,componentDef:f,dataContext:se.currentDataContext,translationContext:se.translationContext,registry:se.registry,bindingEngine:se.bindingEngine,translationEngine:se.translationEngine,actionDispatcher:se.actionDispatcher,isRootRenderer:g===0,layoutKey:m})}),Ye.createElement(Jp,{key:"__modal_parent_context_provider_update"},u.map(f=>{const g=se.currentDataContext._global?.modalStack||[],b=g.includes(f.id)||se.currentDataContext._global?.activeModal===f.id,v=g.indexOf(f.id),S=v>=0?50+v:50,E=window.__g7LayoutContextStack||[],T=E[E.length-1]?.dataContext,L=Ye.createElement(Ha,{key:`modal_${f.id}_renderer`,componentDef:{...f,props:{...f.props,isOpen:b,style:{...f.props?.style,zIndex:S},onClose:se.actionDispatcher?.createHandler({type:"click",handler:"closeModal"},se.currentDataContext)}},dataContext:se.currentDataContext,translationContext:se.translationContext,registry:se.registry,bindingEngine:se.bindingEngine,translationEngine:se.translationEngine,actionDispatcher:se.actionDispatcher,parentDataContext:T});return f.data_sources&&f.data_sources.length>0?Ye.createElement(ay,{key:`modal_${f.id}`,isOpen:b,modalId:f.id,dataSources:f.data_sources,dataContext:se.currentDataContext,globalStateUpdater:se.actionDispatcher?.getGlobalStateUpdater(),bindingEngine:se.bindingEngine,debug:Eo,children:L}):L}))])))))};e?.sync?(Ze.log("재렌더링 시작 (sync mode - 즉시 렌더링)"),d()):(Ze.log("재렌더링 시작 (with startTransition)"),N.startTransition(()=>{d()})),Ze.log("템플릿 데이터 업데이트 완료")}catch(a){throw Ze.error("템플릿 데이터 업데이트 실패",a),a}}function yc(){try{Ze.log("템플릿 정리 시작"),se.reactRoot&&(Ze.log("React Root 언마운트"),se.reactRoot.unmount(),se.reactRoot=null),se.templateId=null,se.locale="ko",se.isInitialized=!1,se.containerId=null,se.currentLayoutJson=null,se.currentDataContext={},se.translationContext={templateId:"",locale:"ko"},se.registry=null,se.bindingEngine=null,se.translationEngine=null,se.actionDispatcher=null,se.templateMetadata=null,Ze.log("템플릿 정리 완료")}catch(o){throw Ze.error("템플릿 정리 실패",o),o}}function Za(){return Object.freeze({...se})}function fy(){return se.actionDispatcher}const To={initTemplateEngine:Ao,renderTemplate:ls,updateTemplateData:cs,destroyTemplate:yc,getState:Za};typeof window<"u"&&(window.G7Core||(window.G7Core={}),window.G7Core.TemplateEngine=To,CA({getState:()=>({translationEngine:se.translationEngine,translationContext:se.translationContext,bindingEngine:se.bindingEngine,actionDispatcher:se.actionDispatcher,templateMetadata:se.templateMetadata}),transitionManager:Na,responsiveManager:ui,webSocketManager:hc}),Ze.log("전역 객체 window.G7Core.TemplateEngine에 노출됨"));const za=Object.freeze(Object.defineProperty({__proto__:null,DataSourceManager:va,LayoutLoader:tf,TemplateApp:So,TemplateEngine:To,default:To,destroyTemplate:yc,getActionDispatcher:fy,getState:Za,initTemplateApp:hf,initTemplateEngine:Ao,loadLayoutEditorBundle:gf,renderTemplate:ls,updateTemplateData:cs},Symbol.toStringTag,{value:"Module"}));Ft.DataSourceManager=va,Ft.LayoutLoader=tf,Ft.TemplateApp=So,Ft.TemplateEngine=To,Ft.default=To,Ft.destroyTemplate=yc,Ft.getActionDispatcher=fy,Ft.getState=Za,Ft.initTemplateApp=hf,Ft.initTemplateEngine=Ao,Ft.loadLayoutEditorBundle=gf,Ft.renderTemplate=ls,Ft.updateTemplateData=cs,Object.defineProperties(Ft,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})})(this.G7Core=this.G7Core||{}); //# sourceMappingURL=template-engine.min.js.map diff --git a/resources/js/core/__tests__/ConditionEvaluator.test.ts b/resources/js/core/__tests__/ConditionEvaluator.test.ts index 842353e5..b24a7207 100644 --- a/resources/js/core/__tests__/ConditionEvaluator.test.ts +++ b/resources/js/core/__tests__/ConditionEvaluator.test.ts @@ -190,6 +190,28 @@ describe('ConditionEvaluator', () => { }); }); + describe('파이프 표현식', () => { + // 회귀 배경: `|` 를 연산자로 판정해 evaluateExpression 으로 라우팅하면 + // `value | pipe` 가 JS 비트 OR 로 평가되어 조건이 잘못 판정된다. + // @since engine-v1.54.3 + it('인자 있는 파이프 결과로 조건을 판정한다', () => { + const context = { row: { created_at: '2024-01-15T14:30:00' } }; + expect( + evaluateStringCondition("{{row.created_at | datetime('YYYY-MM-DD')}}", context, bindingEngine) + ).toBe(true); + }); + + it('인자 없는 파이프 결과로 조건을 판정한다', () => { + const context = { row: { code: 'abc' } }; + expect(evaluateStringCondition('{{row.code | uppercase}}', context, bindingEngine)).toBe(true); + }); + + it('파이프 결과가 빈 문자열이면 false 를 반환한다', () => { + const context = { row: { code: '' } }; + expect(evaluateStringCondition('{{row.code | uppercase}}', context, bindingEngine)).toBe(false); + }); + }); + describe('빈 조건', () => { it('빈 문자열 조건은 true 반환', () => { expect(evaluateStringCondition('', {}, bindingEngine)).toBe(true); diff --git a/resources/js/core/template-engine/ActionDispatcher.ts b/resources/js/core/template-engine/ActionDispatcher.ts index 7b994508..2d944ac1 100644 --- a/resources/js/core/template-engine/ActionDispatcher.ts +++ b/resources/js/core/template-engine/ActionDispatcher.ts @@ -2745,10 +2745,14 @@ export class ActionDispatcher { let finalPath = target; // query 파라미터 처리 - if (params.query) { + // mergeQuery: true 는 query 키 없이도 병합을 수행한다 (@since engine-v1.54.2). + // 이전에는 `if (params.query)` 게이트에 걸려 `mergeQuery: true` 만 적은 액션이 병합 + // 자체를 건너뛰고 쿼리를 통째로 잃었다 — 작성자 관점에서 가장 자연스러운 형태가 + // 정반대로 동작하던 함정이라 게이트를 넓힌다. + if (params.query || params.mergeQuery === true) { if (params.mergeQuery === true) { // mergeQuery가 true이면 기존 쿼리스트링과 병합 - finalPath = this.buildMergedQueryPath(target, params.query); + finalPath = this.buildMergedQueryPath(target, params.query ?? {}); } else { // mergeQuery가 false이거나 없으면 새 쿼리스트링으로 대체 const queryString = new URLSearchParams(); @@ -3255,10 +3259,10 @@ export class ActionDispatcher { ): Promise { let finalPath = target; - // query 파라미터 처리 (navigate와 동일 로직) - if (params.query) { + // query 파라미터 처리 (navigate와 동일 로직 — 게이트도 동일하게 유지, @since engine-v1.54.2) + if (params.query || params.mergeQuery === true) { if (params.mergeQuery === true) { - finalPath = this.buildMergedQueryPath(target, params.query); + finalPath = this.buildMergedQueryPath(target, params.query ?? {}); } else { const queryString = new URLSearchParams(); for (const [key, value] of Object.entries(params.query)) { diff --git a/resources/js/core/template-engine/CHANGELOG.md b/resources/js/core/template-engine/CHANGELOG.md index c305034a..85e282e7 100644 --- a/resources/js/core/template-engine/CHANGELOG.md +++ b/resources/js/core/template-engine/CHANGELOG.md @@ -5,6 +5,28 @@ > > 형식: [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/) +## [engine-v1.54.3] - 2026-07-25 + +### Fixed + +#### DataGrid `cellChildren` 등 반복 렌더 컨텍스트에서 단일 바인딩의 파이프가 적용되지 않던 문제 + +- `RenderHelpers.ts` `renderItemChildren` — 단일 바인딩 판정 후 파이프(`|`) 분기를 추가했다. 종전에는 `|` 가 복잡 표현식 문자로 분류되어 `evaluateExpression` 으로 라우팅되었고, JS 비트 OR 로 평가되어 인자 있는 파이프(`{{row.created_at | datetime('YYYY-MM-DD HH:mm')}}`)는 예외로 값이 사라지고, 인자 없는 파이프(`{{row.code | uppercase}}`)는 `0` 같은 조용한 오답이 되었다. 같은 표현식이 일반 컴포넌트의 `text` 에서는 정상 동작해 재현 위치를 특정하기 어려웠다. (#87 @glitter-gim 님께서 제보해주셨습니다.) +- 적용 범위: DataGrid 의 `cellChildren`·카드 뷰, CardGrid 의 카드 children, `expandChildren`, `footerCells` 등 반복 렌더 경로 전체. 컴포넌트의 `text` 와 props 값 모두 동일하게 해석된다. +- 같은 결함이 있던 나머지 단일 바인딩 경로도 함께 정렬했다 — `DynamicRenderer.tsx` 의 props 해석(예외가 나면 해당 prop 이 `undefined` 로 떨어짐), `DataBindingEngine.ts` `resolveObject`(예외가 밖으로 전파되어 그 컴포넌트의 props 해석 전체가 중단), `ConditionEvaluator.ts` `evaluateStringCondition` 과 `RenderHelpers.ts` `evaluateIfCondition`(`if` 조건 오판정). +- `blur_until_loaded` 는 의도적으로 제외한다 — truthiness 게이트라 문자열 결과가 항상 참이 되어 블러가 영구히 켜질 수 있다. 값 서식용인 파이프를 쓰는 자리가 아니다. +- 기존 동작 무영향: 파이프가 포함된 단일 바인딩에서만 경로가 바뀐다. 논리 OR(`||`)·따옴표 안의 `|`(다국어 파라미터 구분자)는 파이프로 인식하지 않으며, 파이프 없는 단일 바인딩은 종전대로 원본 타입을 유지한다. + +## [engine-v1.54.2] - 2026-07-24 + +### Fixed + +#### `mergeQuery: true` 에 `query` 키가 없으면 병합이 통째로 건너뛰어지던 문제 + +- `ActionDispatcher.ts` `handleNavigate` / `handleReplaceUrl` — 쿼리 처리 진입 조건을 `if (params.query)` 에서 `if (params.query || params.mergeQuery === true)` 로 넓히고, 병합 대상이 없으면 빈 객체를 넘긴다. 종전에는 `mergeQuery: true` 만 적고 `query` 를 생략한 액션이 조건문에 걸려 병합 자체를 수행하지 못했고, 그 결과 이동 후 URL 의 쿼리스트링이 **전부** 사라졌다. 작성자 관점에서 "현재 쿼리를 유지한다" 는 의도를 가장 자연스럽게 표현한 형태가 정반대로 동작하던 함정이다. +- 두 핸들러의 게이트를 같은 형태로 유지한다 — 한쪽만 고치면 같은 params 를 써도 `navigate` 와 `replaceUrl` 의 결과가 갈린다. +- 기존 동작 무영향: `mergeQuery: true` + `query` 생략 조합은 저장소 전체에 0건임을 정적 스캔으로 확인했다. `mergeQuery: false` + `query` 생략은 종전대로 쿼리를 붙이지 않는다. + ## [engine-v1.54.1] - 2026-07-23 ### Fixed diff --git a/resources/js/core/template-engine/DataBindingEngine.ts b/resources/js/core/template-engine/DataBindingEngine.ts index ed290192..448027ad 100644 --- a/resources/js/core/template-engine/DataBindingEngine.ts +++ b/resources/js/core/template-engine/DataBindingEngine.ts @@ -976,10 +976,16 @@ export class DataBindingEngine { // 복잡 표현식(연산자 포함)은 evaluateExpression으로 라우팅 // resolveBindings()와 동일한 isBaseExpression 판별 기준 사용 + // 단, 파이프 표현식은 resolveBindings 로 위임한다 — `|` 를 연산자로 보아 + // evaluateExpression 으로 보내면 `value | pipe` 가 JS 비트 OR 로 평가되어 + // 인자 있는 파이프는 예외를 던지고(props 해석 전체가 중단), 인자 없는 + // 파이프는 포맷이 적용되지 않은 오답이 된다. @since engine-v1.54.3 const isBaseExpression = /[?:|&!+\-*/<>=()]/.test(effectivePath) || /\[['"]/.test(effectivePath); - const resolved = isBaseExpression - ? this.evaluateExpression(effectivePath, context, options) - : this.resolve(effectivePath, context, options); + const resolved = hasPipes(effectivePath) + ? this.resolveBindings(`{{${effectivePath}}}`, context, options) + : isBaseExpression + ? this.evaluateExpression(effectivePath, context, options) + : this.resolve(effectivePath, context, options); result[key] = isRawBinding && resolved != null ? wrapRawDeep(resolved) : resolved; } else { // 문자열 보간 diff --git a/resources/js/core/template-engine/DynamicRenderer.tsx b/resources/js/core/template-engine/DynamicRenderer.tsx index 2cf0034e..fec3f75f 100644 --- a/resources/js/core/template-engine/DynamicRenderer.tsx +++ b/resources/js/core/template-engine/DynamicRenderer.tsx @@ -2287,7 +2287,13 @@ const DynamicRenderer: React.FC = memo( }; let resolvedValue; - if (isComplexExpression(effectivePath)) { + if (hasPipes(effectivePath)) { + // 파이프 표현식은 resolveBindings 로 위임 (파이프 체인 실행 포함). + // isComplexExpression 은 `|` 를 연산자로 보므로 그대로 두면 + // `value | pipe` 가 JS 비트 OR 로 평가된다 — text 처리와 동일 분기. + // @since engine-v1.54.3 + resolvedValue = bindingEngine.resolveBindings(`{{${effectivePath}}}`, extendedDataContext, bindingOptions, trackingInfo); + } else if (isComplexExpression(effectivePath)) { try { resolvedValue = bindingEngine.evaluateExpression(effectivePath, extendedDataContext, trackingInfo); } catch (error) { @@ -3951,6 +3957,10 @@ const DynamicRenderer: React.FC = memo( componentName: effectiveComponentDef.name, propName: 'blur_until_loaded', }; + // blur_until_loaded 는 truthiness 게이트다. 파이프를 resolveBindings 로 + // 위임하면 결과가 항상 문자열이 되어 "false"/"0" 도 truthy 가 되므로 + // 여기서는 파이프 분기를 두지 않는다(블러가 영구히 켜지는 편이 더 나쁘다). + // 파이프는 값 서식용이므로 이 속성에 쓰이지 않는다. const result = bindingEngine.evaluateExpression(singleBindingPath, extendedDataContext, blurTrackingInfo); return Boolean(result); } catch (error) { diff --git a/resources/js/core/template-engine/__tests__/ActionDispatcher.test.ts b/resources/js/core/template-engine/__tests__/ActionDispatcher.test.ts index 0371b8a3..26642c2a 100644 --- a/resources/js/core/template-engine/__tests__/ActionDispatcher.test.ts +++ b/resources/js/core/template-engine/__tests__/ActionDispatcher.test.ts @@ -841,6 +841,60 @@ describe('ActionDispatcher', () => { expect(mockNavigate).toHaveBeenCalledWith('/admin/users?new_param=value', { replace: false }); }); + + it('query: {} 이면 현재 쿼리를 전부 유지해야 함', async () => { + const action: ActionDefinition = { + type: 'click', + handler: 'navigate', + params: { path: '/admin/users/7', mergeQuery: true, query: {} }, + }; + + await dispatcher.createHandler(action)({ + preventDefault: vi.fn(), + type: 'click', + target: null, + } as unknown as Event); + + const navigatedPath = mockNavigate.mock.calls[0][0]; + expect(navigatedPath).toContain('page=1'); + expect(navigatedPath).toContain('filter=active'); + }); + + // engine-v1.54.2: 이전에는 `if (params.query)` 게이트에 걸려 병합이 통째로 no-op 이 되고 + // 쿼리가 전부 사라졌다. 작성자 관점에서 가장 자연스러운 형태가 정반대로 동작하던 함정. + it('query 키가 없어도 mergeQuery: true 면 현재 쿼리를 유지해야 함 (engine-v1.54.2)', async () => { + const action: ActionDefinition = { + type: 'click', + handler: 'navigate', + params: { path: '/admin/users/7', mergeQuery: true }, + }; + + await dispatcher.createHandler(action)({ + preventDefault: vi.fn(), + type: 'click', + target: null, + } as unknown as Event); + + const navigatedPath = mockNavigate.mock.calls[0][0]; + expect(navigatedPath).toContain('page=1'); + expect(navigatedPath).toContain('filter=active'); + }); + + it('mergeQuery: false 는 query 키가 없으면 쿼리를 붙이지 않는다 (기존 동작 유지)', async () => { + const action: ActionDefinition = { + type: 'click', + handler: 'navigate', + params: { path: '/admin/users/7', mergeQuery: false }, + }; + + await dispatcher.createHandler(action)({ + preventDefault: vi.fn(), + type: 'click', + target: null, + } as unknown as Event); + + expect(mockNavigate).toHaveBeenCalledWith('/admin/users/7', { replace: false }); + }); }); describe('navigate scroll 옵션 (engine-v1.37.0)', () => { @@ -7019,6 +7073,24 @@ describe('ActionDispatcher', () => { expect(calledPath).toContain('mode=edit'); }); + // engine-v1.54.2: navigate 와 동일한 게이트 확장 — 한쪽만 고치면 두 핸들러의 동작이 갈린다. + it('query 키가 없어도 mergeQuery: true 면 현재 쿼리를 유지해야 함 (engine-v1.54.2)', async () => { + const action: ActionDefinition = { + type: 'click', + handler: 'replaceUrl', + params: { path: '/admin/menus', mergeQuery: true }, + }; + + await dispatcher.createHandler(action)({ + preventDefault: vi.fn(), + type: 'click', + target: null, + } as unknown as Event); + + expect(replaceStateSpy).toHaveBeenCalled(); + expect(replaceStateSpy.mock.calls[0][2] as string).toContain('existing=param'); + }); + it('query 없이 path만 전달해도 동작해야 함', async () => { const action: ActionDefinition = { type: 'click', diff --git a/resources/js/core/template-engine/__tests__/DataBindingEngine.pipe.test.ts b/resources/js/core/template-engine/__tests__/DataBindingEngine.pipe.test.ts index c99a1c02..cc7719f7 100644 --- a/resources/js/core/template-engine/__tests__/DataBindingEngine.pipe.test.ts +++ b/resources/js/core/template-engine/__tests__/DataBindingEngine.pipe.test.ts @@ -190,6 +190,39 @@ describe('DataBindingEngine - Pipe Integration', () => { }); }); + describe('resolveObject 단일 바인딩과 파이프', () => { + // 회귀 배경: 단일 바인딩 판정 후 `|` 를 연산자로 보아 evaluateExpression 으로 + // 라우팅되어, 인자 있는 파이프는 "datetime is not a function" 예외로 props + // 해석 전체가 중단되고 인자 없는 파이프는 비트 OR 로 오답이 되었다. + // @since engine-v1.54.3 + it('인자 있는 파이프가 예외 없이 포맷된 값을 반환한다', () => { + const context = { post: { created_at: '2024-01-15T14:30:00' } }; + const result = engine.resolveObject( + { title: "{{post.created_at | datetime('YYYY-MM-DD HH:mm')}}" }, + context + ); + expect(result.title).toBe('2024-01-15 14:30'); + }); + + it('인자 없는 파이프가 비트 연산으로 오염되지 않는다', () => { + const context = { product: { price: 1234567 } }; + const result = engine.resolveObject({ label: '{{product.price | number}}' }, context); + expect(result.label).toBe('1,234,567'); + }); + + it('파이프가 없는 단일 바인딩은 원본 타입을 유지한다 (회귀 보호)', () => { + const context = { items: [1, 2, 3] }; + const result = engine.resolveObject({ options: '{{items}}' }, context); + expect(result.options).toEqual([1, 2, 3]); + }); + + it('논리 OR(||) 표현식은 파이프로 오인되지 않는다 (회귀 보호)', () => { + const context = { product: { name: '' } }; + const result = engine.resolveObject({ label: "{{product.name || '-'}}" }, context); + expect(result.label).toBe('-'); + }); + }); + describe('skipCache와 파이프', () => { it('skipCache: true로 매번 새로 평가', () => { let counter = 0; diff --git a/resources/js/core/template-engine/__tests__/renderItemChildren-pipe.test.ts b/resources/js/core/template-engine/__tests__/renderItemChildren-pipe.test.ts new file mode 100644 index 00000000..456f3a1a --- /dev/null +++ b/resources/js/core/template-engine/__tests__/renderItemChildren-pipe.test.ts @@ -0,0 +1,158 @@ +/** + * renderItemChildren 파이프 표현식 처리 테스트 + * + * DataGrid 의 cellChildren, CardGrid 의 카드 children 등 반복 컨텍스트에서 + * 단일 바인딩 `{{path | pipe}}` 가 파이프 체인을 거쳐 해석되는지 검증합니다. + * + * 회귀 배경: 단일 바인딩 판정 후 `|` 가 포함되면 복잡 표현식으로 분류되어 + * `evaluateExpression` 으로 라우팅되었고, JS 비트 OR 로 평가되어 + * 인자 있는 파이프는 예외(값 소실), 인자 없는 파이프는 조용한 오답이 되었다. + * + * @since engine-v1.54.3 + */ + +import { describe, it, expect, vi, beforeEach } from 'vitest'; +import React from 'react'; +import { renderItemChildren } from '../helpers/RenderHelpers'; +import { DataBindingEngine } from '../DataBindingEngine'; +import { TranslationEngine } from '../TranslationEngine'; + +// AuthManager mock +vi.mock('../../auth/AuthManager', () => ({ + AuthManager: { + getInstance: vi.fn(() => ({ + login: vi.fn().mockResolvedValue({ id: 1, name: 'Test User' }), + logout: vi.fn().mockResolvedValue(undefined), + })), + }, +})); + +// ApiClient mock +vi.mock('../../api/ApiClient', () => ({ + getApiClient: vi.fn(() => ({ + getToken: vi.fn(), + })), +})); + +const TestSpan: React.FC = ({ children, ...props }) => + React.createElement('span', props, children); + +describe('renderItemChildren - 파이프 표현식', () => { + let bindingEngine: DataBindingEngine; + let translationEngine: TranslationEngine; + + const componentMap: Record> = { + Span: TestSpan, + }; + + const render = (children: any[], context: Record) => + renderItemChildren(children as any, context, componentMap, 'test', { + bindingEngine, + translationEngine, + translationContext: { templateId: '', locale: 'ko' }, + }); + + beforeEach(() => { + bindingEngine = new DataBindingEngine(); + translationEngine = TranslationEngine.getInstance(); + (translationEngine as any).translations.set(':ko', {}); + }); + + it('text 단일 바인딩 + 인자 있는 파이프(datetime) 가 포맷된 값을 반환한다', () => { + const children = [ + { + type: 'basic' as const, + name: 'Span', + text: "{{row.created_at | datetime('YYYY-MM-DD HH:mm')}}", + }, + ]; + + const result = render(children, { row: { created_at: '2026-07-26T05:42:00.000000Z' } }); + + const element = result[0] as React.ReactElement; + // 브라우저 타임존에 의존하지 않도록 형식만 검증 + expect(element.props.children).toMatch(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/); + }); + + it('text 단일 바인딩 + 인자 없는 파이프(number) 가 천단위 구분자를 적용한다', () => { + const children = [ + { type: 'basic' as const, name: 'Span', text: '{{row.price | number}}' }, + ]; + + const result = render(children, { row: { price: 1234567 } }); + + const element = result[0] as React.ReactElement; + expect(element.props.children).toBe('1,234,567'); + }); + + it('문자열 파이프(uppercase) 가 비트 연산으로 오염되지 않는다', () => { + const children = [ + { type: 'basic' as const, name: 'Span', text: '{{row.code | uppercase}}' }, + ]; + + const result = render(children, { row: { code: 'abc' } }); + + const element = result[0] as React.ReactElement; + expect(element.props.children).toBe('ABC'); + }); + + it('파이프 체인이 순차 적용된다', () => { + const children = [ + { type: 'basic' as const, name: 'Span', text: '{{row.code | uppercase | truncate(2)}}' }, + ]; + + const result = render(children, { row: { code: 'abcdef' } }); + + const element = result[0] as React.ReactElement; + expect(element.props.children).toContain('AB'); + }); + + it('props 값의 파이프도 해석된다', () => { + const children = [ + { + type: 'basic' as const, + name: 'Span', + text: 'x', + props: { title: '{{row.price | number}}' }, + }, + ]; + + const result = render(children, { row: { price: 12345 } }); + + const element = result[0] as React.ReactElement; + expect(element.props.title).toBe('12,345'); + }); + + it('혼합 보간 형태의 파이프는 기존대로 동작한다 (회귀 보호)', () => { + const children = [ + { type: 'basic' as const, name: 'Span', text: '[{{row.price | number}}]' }, + ]; + + const result = render(children, { row: { price: 12345 } }); + + const element = result[0] as React.ReactElement; + expect(element.props.children).toBe('[12,345]'); + }); + + it('파이프가 없는 단일 바인딩은 원본 타입을 유지한다 (회귀 보호)', () => { + const children = [ + { type: 'basic' as const, name: 'Span', text: '{{row.count}}' }, + ]; + + const result = render(children, { row: { count: 0 } }); + + const element = result[0] as React.ReactElement; + expect(element.props.children).toBe(0); + }); + + it('논리 OR(||) 표현식은 파이프로 오인되지 않는다 (회귀 보호)', () => { + const children = [ + { type: 'basic' as const, name: 'Span', text: "{{row.name || '-'}}" }, + ]; + + const result = render(children, { row: { name: '' } }); + + const element = result[0] as React.ReactElement; + expect(element.props.children).toBe('-'); + }); +}); diff --git a/resources/js/core/template-engine/__tests__/troubleshooting-components.test.ts b/resources/js/core/template-engine/__tests__/troubleshooting-components.test.ts index 7ef6baf1..fe8ee719 100644 --- a/resources/js/core/template-engine/__tests__/troubleshooting-components.test.ts +++ b/resources/js/core/template-engine/__tests__/troubleshooting-components.test.ts @@ -13,6 +13,8 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { Logger } from '../../utils/Logger'; import { hasExplicitSetStateForField } from '../FormContext'; import { responsiveManager } from '../ResponsiveManager'; +import { hasPipes } from '../PipeRegistry'; +import { DataBindingEngine } from '../DataBindingEngine'; describe('트러블슈팅 회귀 테스트 - flex 압착(shrink)', () => { /** @@ -1433,3 +1435,51 @@ describe('트러블슈팅 회귀 테스트 - 렌더링 구조', () => { }); }); }); + +describe('트러블슈팅 회귀 테스트 - DataGrid cellChildren 파이프', () => { + /** + * 사례: cellChildren 단일 바인딩의 파이프가 적용되지 않아 셀이 비어 보임 + * + * 단일 바인딩 판정 후 `|` 가 복잡 표현식 문자로 분류되어 evaluateExpression 으로 + * 라우팅되면 JS 비트 OR 로 평가된다. 인자 있는 파이프는 예외(값 소실), + * 인자 없는 파이프는 조용한 오답이 된다. 라우팅 판정 자체를 고정한다. + * + * @see docs/frontend/troubleshooting-components-datagrid.md "DataGrid cellChildren 파이프 이슈" + * @see resources/js/core/template-engine/__tests__/renderItemChildren-pipe.test.ts (렌더 결과 검증) + */ + describe('[사례 1] 파이프 판정이 복잡 표현식 판정보다 먼저 적용된다', () => { + it('파이프 표현식은 hasPipes 로 먼저 걸러진다 (인자 유무 무관)', () => { + expect(hasPipes("row.created_at | datetime('YYYY-MM-DD HH:mm')")).toBe(true); + expect(hasPipes('row.price | number')).toBe(true); + expect(hasPipes('row.code | uppercase | truncate(2)')).toBe(true); + }); + + it('논리 OR 와 따옴표 안의 | 는 파이프로 오인되지 않는다', () => { + expect(hasPipes("row.name || '-'")).toBe(false); + // 다국어 파라미터 구분자는 문자열 리터럴 내부이므로 파이프가 아니다 + expect(hasPipes("row.flag ? '$t:common.badge|count=1' : ''")).toBe(false); + }); + + it('파이프를 evaluateExpression 으로 보내면 비트 OR 오답이 된다 (수정 전 동작 고정)', () => { + const engine = new DataBindingEngine(); + // 인자 없는 파이프: 문자열이 0 으로 붕괴 + expect(engine.evaluateExpression('row.code | uppercase', { row: { code: 'abc' } })).toBe(0); + // 인자 있는 파이프: 함수 호출 실패로 예외 + expect(() => + engine.evaluateExpression("row.created_at | datetime('YYYY-MM-DD')", { + row: { created_at: '2024-01-15T14:30:00' }, + }) + ).toThrow(); + }); + + it('파이프 표현식은 resolveBindings 경로에서 서식이 적용된다', () => { + const engine = new DataBindingEngine(); + expect(engine.resolveBindings('{{row.code | uppercase}}', { row: { code: 'abc' } })).toBe('ABC'); + expect( + engine.resolveBindings("{{row.created_at | datetime('YYYY-MM-DD HH:mm')}}", { + row: { created_at: '2024-01-15T14:30:00' }, + }) + ).toBe('2024-01-15 14:30'); + }); + }); +}); diff --git a/resources/js/core/template-engine/helpers/ConditionEvaluator.ts b/resources/js/core/template-engine/helpers/ConditionEvaluator.ts index 88f7dc96..ff11c343 100644 --- a/resources/js/core/template-engine/helpers/ConditionEvaluator.ts +++ b/resources/js/core/template-engine/helpers/ConditionEvaluator.ts @@ -10,6 +10,7 @@ */ import { DataBindingEngine, BindingContext } from '../DataBindingEngine'; +import { hasPipes } from '../PipeRegistry'; import { createLogger } from '../../utils/Logger'; const logger = createLogger('ConditionEvaluator'); @@ -241,6 +242,12 @@ export function evaluateStringCondition( const literalValue = resolveLiteral(singleBindingPath); if (literalValue !== undefined) { resolved = literalValue.value; + } else if (hasPipes(singleBindingPath)) { + // 파이프 표현식은 resolveBindings 로 위임 (파이프 체인 실행 포함). + // isComplexExpression 은 `|` 를 연산자로 보므로 그대로 두면 + // `value | pipe` 가 JS 비트 OR 로 평가되어 조건이 잘못 판정된다. + // @since engine-v1.54.3 + resolved = bindingEngine.resolveBindings(`{{${singleBindingPath}}}`, context, { skipCache: true }); } else if (isComplexExpression(singleBindingPath)) { // Optional chaining(?.)이나 복잡한 표현식은 evaluateExpression 사용 resolved = bindingEngine.evaluateExpression(singleBindingPath, context); diff --git a/resources/js/core/template-engine/helpers/RenderHelpers.ts b/resources/js/core/template-engine/helpers/RenderHelpers.ts index ac885775..14674b44 100644 --- a/resources/js/core/template-engine/helpers/RenderHelpers.ts +++ b/resources/js/core/template-engine/helpers/RenderHelpers.ts @@ -15,6 +15,7 @@ import { responsiveManager } from '../ResponsiveManager'; import { getActionDispatcher } from '../ActionDispatcher'; import { createLogger } from '../../utils/Logger'; import { RAW_PREFIX, RAW_MARKER_START, RAW_MARKER_END, RAW_PLACEHOLDER_MARKER, isRawWrapped, unwrapRaw, containsRawMarker, wrapRawDeep } from '../rawMarkers'; +import { hasPipes } from '../PipeRegistry'; import type { G7DevToolsInterface } from '../G7CoreGlobals'; import { evaluateConditionExpression, @@ -438,6 +439,11 @@ export function evaluateIfCondition( const literal = LITERALS.get(singleBindingPath); if (literal !== undefined) { resolved = literal; + } else if (hasPipes(singleBindingPath)) { + // 파이프 표현식은 resolveBindings 로 위임 (파이프 체인 실행 포함). + // `|` 를 연산자로 보아 evaluateExpression 으로 보내면 JS 비트 OR 로 + // 평가되어 조건이 잘못 판정된다. @since engine-v1.54.3 + resolved = bindingEngine.resolveBindings(`{{${singleBindingPath}}}`, context, { skipCache: true }); } else if (isComplexExpression(singleBindingPath)) { // Optional chaining(?.)이나 복잡한 표현식은 evaluateExpression 사용 resolved = bindingEngine.evaluateExpression(singleBindingPath, context); @@ -753,7 +759,17 @@ export function renderItemChildren( } let result; - if (isComplexExpression(effectivePath)) { + if (hasPipes(effectivePath)) { + // 파이프 표현식은 resolveBindings 로 위임 (파이프 체인 실행 포함) + // isComplexExpression 은 `|` 를 연산자로 보아 evaluateExpression 으로 보내는데, + // 그 경로에서는 `value | pipe` 가 JS 비트 OR 로 평가되어 + // 인자 있는 파이프는 예외(값 소실), 인자 없는 파이프는 조용한 오답이 된다. + // DynamicRenderer 의 text 처리와 동일한 분기 순서를 유지한다. + // raw: 접두사는 아래 공통 분기(wrapRawDeep)가 담당하므로 여기서는 제거된 + // effectivePath 만 넘긴다 — 원본 value 를 넘기면 raw 마커가 이중으로 감싸진다. + // @since engine-v1.54.3 + result = bindingEngine.resolveBindings(`{{${effectivePath}}}`, context, { skipCache: true }); + } else if (isComplexExpression(effectivePath)) { try { result = bindingEngine.evaluateExpression(effectivePath, context); } catch (error) { diff --git a/templates/_bundled/sirsoft-admin_basic/CHANGELOG.md b/templates/_bundled/sirsoft-admin_basic/CHANGELOG.md index 07efb90b..c969ac63 100644 --- a/templates/_bundled/sirsoft-admin_basic/CHANGELOG.md +++ b/templates/_bundled/sirsoft-admin_basic/CHANGELOG.md @@ -25,6 +25,11 @@ ### Fixed +- 관리자 회원·역할·활동이력·알림 로그·모듈/플러그인·템플릿·스케줄 목록에서 상세나 등록/수정 화면에 다녀오면 보고 있던 페이지와 검색 조건이 사라지던 문제를 수정했습니다. 새로고침 버튼도 걸어 둔 조건을 지우지 않고 보고 있던 목록을 그대로 다시 부릅니다. 초기화 버튼과 탭 전환은 종전처럼 조건을 비웁니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 회원 목록에서 회원을 열어 보거나 등록/수정 화면에 다녀오면 보고 있던 페이지와 검색 조건이 사라지던 문제를 수정했습니다. 새로고침 버튼도 걸어 둔 조건을 지우지 않습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 회원 목록에서 뒤쪽 페이지를 보던 중 검색하면 그 페이지 번호가 그대로 유지돼 결과가 없는 빈 화면이 열리던 문제를 수정했습니다. 검색은 1페이지부터 보여주며, 사용자가 고른 표시 개수와 정렬은 그대로 유지됩니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 템플릿 목록에서 검색하면 사용자가 고른 표시 개수가 기본값으로 되돌아가던 문제를 수정했습니다. 검색은 검색어와 페이지만 새로 정하고 나머지 조건은 그대로 둡니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 관리자 메뉴 관리와 템플릿 레이아웃 편집 화면에서 왼쪽 목록의 항목을 고르면 걸어 둔 조건이 사라지던 문제를 수정했습니다. 항목 선택은 선택 상태만 주소에 기록합니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 저장이나 삭제가 실패했을 때 아무 안내 없이 조용히 넘어가던 화면들을 수정했습니다. 이제 실패하면 그 이유가 화면에 표시되므로, 반영되지 않은 변경을 성공한 것으로 오해하지 않습니다. - 오류 안내가 뜨기는 하지만 내용이 비어 있던 문제를 수정했습니다. 서버가 알려 준 실패 사유가 그대로 표시됩니다. - 모듈·플러그인·템플릿·언어팩 목록과 일정 관리 화면의 아이콘이 의도한 크기보다 크거나 작게 보이던 문제를 수정했습니다. diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_activity_log_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_activity_log_list.json index 17a08c1e..39a0ca38 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_activity_log_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_activity_log_list.json @@ -81,7 +81,7 @@ "handler": "navigate", "params": { "path": "/admin/activity-logs", - "replace": true, + "mergeQuery": true, "query": { "page": 1, "search": "{{_local.filter.search || undefined}}", @@ -91,6 +91,7 @@ "date_from": "{{_local.filter.dateFrom || undefined}}", "date_to": "{{_local.filter.dateTo || undefined}}" }, + "replace": true, "transition_overlay_target": "activity_log_datagrid__body" } } @@ -148,7 +149,8 @@ "handler": "navigate", "params": { "path": "/admin/activity-logs", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], @@ -232,13 +234,13 @@ "handler": "navigate", "params": { "path": "/admin/activity-logs", - "replace": true, "mergeQuery": true, "query": { "sort_by": "created_at", "sort_order": "{{$event.target.value.split('_').pop()}}", "page": 1 }, + "replace": true, "transition_overlay_target": "activity_log_datagrid__body" } } @@ -276,12 +278,12 @@ "handler": "navigate", "params": { "path": "/admin/activity-logs", - "replace": true, "mergeQuery": true, "query": { "per_page": "{{$event.target.value}}", "page": 1 }, + "replace": true, "transition_overlay_target": "activity_log_datagrid__body" } } diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_identity_logs.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_identity_logs.json index 5bcecc2a..19474b34 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_identity_logs.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_identity_logs.json @@ -133,7 +133,6 @@ "handler": "navigate", "params": { "path": "/admin/identity/logs", - "replace": true, "mergeQuery": true, "query": { "page": 1, @@ -150,6 +149,7 @@ "status": null, "purpose": null }, + "replace": true, "transition_overlay_target": "identity_log_datagrid__body" } } @@ -295,6 +295,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 제공자 탭 전환 — 직전 setState 가 필터를 전부 비우고, '전체' 선택 시 query 가 [] 로 리셋되어야 한다. 병합하면 이전 제공자의 조건이 남아 초기화가 무력화된다.", "handler": "navigate", "params": { "path": "/admin/identity/logs", @@ -370,13 +371,13 @@ "handler": "navigate", "params": { "path": "/admin/identity/logs", - "replace": true, "mergeQuery": true, "query": { "sort_by": "{{$event.target.value.split('_').slice(0, -1).join('_')}}", "sort_order": "{{$event.target.value.split('_').pop()}}", "page": 1 }, + "replace": true, "transition_overlay_target": "identity_log_datagrid__body" } } @@ -402,12 +403,12 @@ "handler": "navigate", "params": { "path": "/admin/identity/logs", - "replace": true, "mergeQuery": true, "query": { "per_page": "{{$event.target.value}}", "page": 1 }, + "replace": true, "transition_overlay_target": "identity_log_datagrid__body" } } diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_module_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_module_list.json index cc9a7850..ad5c57f3 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_module_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_module_list.json @@ -608,6 +608,7 @@ "handler": "navigate", "params": { "path": "/admin/modules", + "mergeQuery": true, "query": { "search": "{{_local.searchQuery || undefined}}", "page": 1 @@ -1314,7 +1315,9 @@ "manage_language_packs": { "handler": "navigate", "params": { - "path": "/admin/modules/{{row.identifier}}/language-packs" + "path": "/admin/modules/{{row.identifier}}/language-packs", + "mergeQuery": true, + "query": {} } }, "uninstall": { diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_notification_log_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_notification_log_list.json index 8c3f8cde..edcd6b01 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_notification_log_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_notification_log_list.json @@ -96,7 +96,6 @@ "handler": "navigate", "params": { "path": "/admin/notification-logs", - "replace": true, "mergeQuery": true, "query": { "page": 1, @@ -105,6 +104,7 @@ "extension_type": "{{_local.filter.extensionTypes?.length > 0 ? _local.filter.extensionTypes[0] : undefined}}", "status": "{{_local.filter.statuses?.length > 0 ? _local.filter.statuses[0] : undefined}}" }, + "replace": true, "transition_overlay_target": "notification_log_datagrid__body" } } @@ -163,7 +163,8 @@ "handler": "navigate", "params": { "path": "/admin/notification-logs", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ], @@ -192,6 +193,7 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 채널 탭 전환 — 탭마다 다루는 대상이 다르고 '전체' 선택 시 query 가 [] 로 리셋되어야 한다. 병합하면 이전 채널의 조건이 남는다.", "event": "onTabChange", "type": "change", "handler": "navigate", @@ -279,13 +281,13 @@ "handler": "navigate", "params": { "path": "/admin/notification-logs", - "replace": true, "mergeQuery": true, "query": { "sort_by": "{{$event.target.value.split('_').slice(0, -1).join('_')}}", "sort_order": "{{$event.target.value.split('_').pop()}}", "page": 1 }, + "replace": true, "transition_overlay_target": "notification_log_datagrid__body" } } @@ -323,12 +325,12 @@ "handler": "navigate", "params": { "path": "/admin/notification-logs", - "replace": true, "mergeQuery": true, "query": { "per_page": "{{$event.target.value}}", "page": 1 }, + "replace": true, "transition_overlay_target": "notification_log_datagrid__body" } } diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_plugin_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_plugin_list.json index 8c7006fb..8b2d8239 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_plugin_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_plugin_list.json @@ -617,6 +617,7 @@ "handler": "navigate", "params": { "path": "/admin/plugins", + "mergeQuery": true, "query": { "search": "{{_local.searchQuery || undefined}}", "page": 1 @@ -1268,6 +1269,7 @@ "handler": "switch", "cases": { "settings": { + "comment": "audit:allow layout-list-context-navigate-merge-query 플러그인 설정 화면으로 이동 — 목적지는 각 플러그인이 선언한 임의 경로로, 플러그인 목록 클러스터 밖이다.", "handler": "navigate", "params": { "path": "{{row.settings_route}}" @@ -1292,7 +1294,9 @@ "manage_language_packs": { "handler": "navigate", "params": { - "path": "/admin/plugins/{{row.identifier}}/language-packs" + "path": "/admin/plugins/{{row.identifier}}/language-packs", + "mergeQuery": true, + "query": {} } }, "view_detail": { diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_role_form.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_role_form.json index 72ea8d4b..62ee3dac 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_role_form.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_role_form.json @@ -315,7 +315,9 @@ { "handler": "navigate", "params": { - "path": "/admin/roles" + "path": "/admin/roles", + "mergeQuery": true, + "query": {} } } ] @@ -723,7 +725,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/roles" + "path": "/admin/roles", + "mergeQuery": true, + "query": {} } } ], @@ -795,7 +799,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/roles" + "path": "/admin/roles", + "mergeQuery": true, + "query": {} } } ], diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_role_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_role_list.json index b8df1548..d94b3bf2 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_role_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_role_list.json @@ -129,7 +129,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/roles/create" + "path": "/admin/roles/create", + "mergeQuery": true, + "query": {} } } ], @@ -195,6 +197,7 @@ "handler": "navigate", "params": { "path": "/admin/roles", + "mergeQuery": true, "query": { "search": "{{_local.searchQuery || undefined}}", "page": 1 @@ -451,11 +454,11 @@ "handler": "navigate", "params": { "path": "/admin/roles", - "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, + "replace": true, "transition_overlay_target": "roles_data_grid__body" } }, @@ -467,13 +470,16 @@ "edit": { "handler": "navigate", "params": { - "path": "/admin/roles/{{$args[1].id}}/edit" + "path": "/admin/roles/{{$args[1].id}}/edit", + "mergeQuery": true, + "query": {} } }, "clone": { "handler": "navigate", "params": { "path": "/admin/roles/create", + "mergeQuery": true, "query": { "clone_from": "{{$args[1].id}}" } diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_schedule_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_schedule_list.json index 1e2edac5..4802c660 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_schedule_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_schedule_list.json @@ -123,7 +123,8 @@ "handler": "navigate", "params": { "path": "{{route.path}}", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ] diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_settings.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_settings.json index fadb39d5..f8b7896e 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_settings.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_settings.json @@ -490,6 +490,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 탭 전환 — 탭마다 다루는 대상이 달라 이전 탭의 목록 상태를 물려받으면 오히려 잘못된 화면이 된다.", "handler": "navigate", "params": { "path": "/admin/settings", diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_template_layout_edit.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_template_layout_edit.json index f2cfda4c..18714b12 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_template_layout_edit.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_template_layout_edit.json @@ -685,8 +685,10 @@ } }, { + "comment": "편집 대상 레이아웃만 주소에 기록한다 — 템플릿 목록에서 실어 온 페이지·검색어는 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "route": "" } @@ -717,8 +719,10 @@ } }, { + "comment": "편집 대상 레이아웃만 주소에 기록한다 — 템플릿 목록에서 실어 온 페이지·검색어는 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "route": "{{(layout_files?.data ?? []).find(f => f.name === $event.target.value.slice(7))?.route_path ?? ''}}" } @@ -868,8 +872,10 @@ } }, { + "comment": "편집 대상 레이아웃만 주소에 기록한다 — 템플릿 목록에서 실어 온 페이지·검색어는 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "route": "{{file.route_path ?? ''}}" } @@ -1047,8 +1053,10 @@ } }, { + "comment": "편집 대상 레이아웃만 주소에 기록한다 — 템플릿 목록에서 실어 온 페이지·검색어는 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "route": "" } diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_template_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_template_list.json index 6b610632..09f51476 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_template_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_template_list.json @@ -614,6 +614,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 탭 전환 — 사용자 템플릿과 관리자 템플릿은 각자 검색어·페이지를 갖는 서로 다른 목록이므로, 이전 탭의 목록 상태를 물려받으면 남의 검색 결과로 걸러진 화면이 열린다.", "handler": "navigate", "params": { "path": "/admin/templates/{{$args[0]}}" diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_detail.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_detail.json index 859ec028..69f91e9b 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_detail.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_detail.json @@ -133,7 +133,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/users/{{route?.id}}/edit" + "path": "/admin/users/{{route?.id}}/edit", + "mergeQuery": true, + "query": {} } } ], diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_form.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_form.json index 9827152c..046e0cd5 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_form.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_form.json @@ -1588,7 +1588,9 @@ { "handler": "navigate", "params": { - "path": "/admin/users" + "path": "/admin/users", + "mergeQuery": true, + "query": {} } } ], diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_list.json index 673f0ad2..fe9962dd 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/admin_user_list.json @@ -69,11 +69,13 @@ ], "named_actions": { "searchUsers": { + "comment": "검색 실행 — 열거한 검색 조건만 덮어쓰고 정렬/페이지당 개수 등 나머지 목록 상태는 유지한다. page 는 새 검색이므로 1페이지로 되돌린다 (#75).", "handler": "navigate", "params": { "path": "/admin/users", "mergeQuery": true, "query": { + "page": "", "filters[0][field]": "{{_local.searchField || 'all'}}", "filters[0][value]": "{{_local.searchQuery || undefined}}", "filters[0][operator]": "like" @@ -118,11 +120,13 @@ }, "actions": [ { + "comment": "새로고침은 보고 있던 목록을 그대로 다시 부르는 것이다 — 페이지와 걸어둔 검색 조건을 유지한다 (#75).", "type": "click", "handler": "navigate", "params": { "path": "/admin/users", - "mergeQuery": false + "mergeQuery": true, + "query": {} } } ] @@ -137,10 +141,13 @@ }, "actions": [ { + "comment": "등록 폼은 회원 목록 클러스터 안이다 — 취소하고 돌아왔을 때 보고 있던 페이지·검색 조건이 그대로여야 한다 (#75).", "type": "click", "handler": "navigate", "params": { - "path": "/admin/users/create" + "path": "/admin/users/create", + "mergeQuery": true, + "query": {} } } ], @@ -1050,15 +1057,21 @@ "handler": "switch", "cases": { "view": { + "comment": "상세는 회원 목록 클러스터 안이다 — 돌아왔을 때 보고 있던 페이지·검색 조건이 그대로여야 한다 (#75).", "handler": "navigate", "params": { - "path": "/admin/users/{{$args[1].uuid}}" + "path": "/admin/users/{{$args[1].uuid}}", + "mergeQuery": true, + "query": {} } }, "edit": { + "comment": "수정 폼도 같은 클러스터다 — 취소하고 돌아왔을 때 목록 상태가 살아 있어야 한다 (#75).", "handler": "navigate", "params": { - "path": "/admin/users/{{$args[1].uuid}}/edit" + "path": "/admin/users/{{$args[1].uuid}}/edit", + "mergeQuery": true, + "query": {} } }, "delete": { @@ -1187,7 +1200,7 @@ "params": { "path": "/admin/users", "mergeQuery": true, - "query": [] + "query": {} } }, { @@ -1342,7 +1355,7 @@ "params": { "path": "/admin/users", "mergeQuery": true, - "query": [] + "query": {} } }, { @@ -1706,7 +1719,7 @@ "params": { "path": "/admin/users", "mergeQuery": true, - "query": [] + "query": {} } }, { @@ -1861,7 +1874,7 @@ "params": { "path": "/admin/users", "mergeQuery": true, - "query": [] + "query": {} } }, { diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_activity_log_list/_partial_datagrid.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_activity_log_list/_partial_datagrid.json index ffa81c80..58dac106 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_activity_log_list/_partial_datagrid.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_activity_log_list/_partial_datagrid.json @@ -460,11 +460,12 @@ "handler": "navigate", "params": { "path": "/admin/activity-logs", - "replace": true, + "mergeQuery": true, "query": { "created_by": "{{row.user.uuid}}", "page": 1 }, + "replace": true, "transition_overlay_target": "activity_log_datagrid__body" } } @@ -515,11 +516,11 @@ "handler": "navigate", "params": { "path": "/admin/activity-logs", - "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, + "replace": true, "transition_overlay_target": "activity_log_datagrid__body" } }, diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_activity_log_list/_partial_filter.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_activity_log_list/_partial_filter.json index c7e41fe5..7bc72eff 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_activity_log_list/_partial_filter.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_activity_log_list/_partial_filter.json @@ -768,9 +768,11 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { - "path": "/admin/activity-logs" + "path": "/admin/activity-logs", + "mergeQuery": false } } ] diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_identity_logs/_partial_filter.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_identity_logs/_partial_filter.json index 817273d4..5205d242 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_identity_logs/_partial_filter.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_identity_logs/_partial_filter.json @@ -770,9 +770,11 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { - "path": "/admin/identity/logs" + "path": "/admin/identity/logs", + "mergeQuery": false } } ] diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_menu_list/_panel_menu_list.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_menu_list/_panel_menu_list.json index e9c1958f..0f1e38f3 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_menu_list/_panel_menu_list.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_menu_list/_panel_menu_list.json @@ -64,8 +64,10 @@ } }, { + "comment": "선택 상태만 주소에 기록한다 — 왼쪽 목록에 걸어둔 조건은 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "menu": "{{$args[0].slug}}", "mode": "view" diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_menu_list/_panel_view.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_menu_list/_panel_view.json index 732d58a1..96b24c24 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_menu_list/_panel_view.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_menu_list/_panel_view.json @@ -674,8 +674,10 @@ } }, { + "comment": "편집 모드 전환만 주소에 기록한다 — 왼쪽 목록에 걸어둔 조건은 그대로 둔다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "menu": "{{_global.selectedMenu?.slug}}", "mode": "edit" diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_notification_log_list/_partial_datagrid.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_notification_log_list/_partial_datagrid.json index 9f9f2cb5..f87d0858 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_notification_log_list/_partial_datagrid.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_notification_log_list/_partial_datagrid.json @@ -275,11 +275,12 @@ "handler": "navigate", "params": { "path": "/admin/notification-logs", - "replace": true, + "mergeQuery": true, "query": { "recipient_user_id": "{{row.recipient_user_id}}", "page": 1 }, + "replace": true, "transition_overlay_target": "notification_log_datagrid__body" } } @@ -383,11 +384,12 @@ "handler": "navigate", "params": { "path": "/admin/notification-logs", - "replace": true, + "mergeQuery": true, "query": { "sender_user_id": "{{row.sender_user_id}}", "page": 1 }, + "replace": true, "transition_overlay_target": "notification_log_datagrid__body" } } @@ -483,11 +485,11 @@ "handler": "navigate", "params": { "path": "/admin/notification-logs", - "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, + "replace": true, "transition_overlay_target": "notification_log_datagrid__body" } }, diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_notification_log_list/_partial_filter.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_notification_log_list/_partial_filter.json index 2aa45bdd..598f34e1 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_notification_log_list/_partial_filter.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_notification_log_list/_partial_filter.json @@ -528,9 +528,11 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "handler": "navigate", "params": { - "path": "/admin/notification-logs" + "path": "/admin/notification-logs", + "mergeQuery": false } } ] diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_schedule_list/_tab_schedules.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_schedule_list/_tab_schedules.json index 53179c95..217113cd 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_schedule_list/_tab_schedules.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_schedule_list/_tab_schedules.json @@ -1069,6 +1069,7 @@ } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 초기화 버튼 — type/frequency/status/검색어가 모두 URL 쿼리로 구동되므로(=이 화면의 필터 SSoT), 병합하면 초기화가 아무 일도 하지 않게 된다.", "handler": "navigate", "params": { "path": "/admin/schedules", @@ -1670,11 +1671,11 @@ "handler": "navigate", "params": { "path": "/admin/schedules", - "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, + "replace": true, "transition_overlay_target": "schedules_data_grid__body" } }, diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_settings/_tab_identity_policies.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_settings/_tab_identity_policies.json index 4343802e..b8186adc 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_settings/_tab_identity_policies.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_settings/_tab_identity_policies.json @@ -356,6 +356,7 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 걸려 있던 조건을 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "type": "click", "handler": "navigate", "params": { diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_template_list/_tab_admin.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_template_list/_tab_admin.json index 6f315f74..d63d6057 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_template_list/_tab_admin.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_template_list/_tab_admin.json @@ -67,13 +67,15 @@ } }, { + "comment": "검색은 조건을 바꾸는 액션이지 리셋이 아니다 — 검색어와 페이지만 새로 정하고 사용자가 고른 표시 개수는 그대로 둔다 (#75).", "type": "submit", "handler": "navigate", "params": { "path": "/admin/templates/admin", + "mergeQuery": true, "query": { "search": "{{_local.searchQuery || undefined}}", - "page": 1 + "page": "" } } } @@ -414,7 +416,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/templates/{{row.identifier}}/edit" + "path": "/admin/templates/{{row.identifier}}/edit", + "mergeQuery": true, + "query": {} } } ], @@ -787,7 +791,9 @@ "manage_language_packs": { "handler": "navigate", "params": { - "path": "/admin/templates/{{row.identifier}}/language-packs" + "path": "/admin/templates/{{row.identifier}}/language-packs", + "mergeQuery": true, + "query": {} } }, "uninstall": { diff --git a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_template_list/_tab_user.json b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_template_list/_tab_user.json index b00a303c..d578cf3a 100644 --- a/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_template_list/_tab_user.json +++ b/templates/_bundled/sirsoft-admin_basic/layouts/partials/admin_template_list/_tab_user.json @@ -67,13 +67,15 @@ } }, { + "comment": "검색은 조건을 바꾸는 액션이지 리셋이 아니다 — 검색어와 페이지만 새로 정하고 사용자가 고른 표시 개수는 그대로 둔다 (#75).", "type": "submit", "handler": "navigate", "params": { "path": "/admin/templates/user", + "mergeQuery": true, "query": { "search": "{{_local.searchQuery || undefined}}", - "page": 1 + "page": "" } } } @@ -414,7 +416,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/admin/templates/{{row.identifier}}/edit" + "path": "/admin/templates/{{row.identifier}}/edit", + "mergeQuery": true, + "query": {} } } ], @@ -779,7 +783,9 @@ "manage_language_packs": { "handler": "navigate", "params": { - "path": "/admin/templates/{{row.identifier}}/language-packs" + "path": "/admin/templates/{{row.identifier}}/language-packs", + "mergeQuery": true, + "query": {} } }, "uninstall": { diff --git a/templates/_bundled/sirsoft-admin_basic/src/__tests__/layouts/admin-list-context-round-trip.test.ts b/templates/_bundled/sirsoft-admin_basic/src/__tests__/layouts/admin-list-context-round-trip.test.ts new file mode 100644 index 00000000..e59b02de --- /dev/null +++ b/templates/_bundled/sirsoft-admin_basic/src/__tests__/layouts/admin-list-context-round-trip.test.ts @@ -0,0 +1,324 @@ +/** + * @file admin-list-context-round-trip.test.ts + * @description 관리자 코어 목록(회원/역할/로그/확장) 컨텍스트 왕복 시 URL 목록 상태 보존 회귀 (#75) + * + * 결함: 회원·역할·활동이력·알림로그·모듈/플러그인 목록에서 상세·폼으로 들어갔다 돌아오면 + * navigate 가 `mergeQuery` 없이 실행되어 page/검색/필터가 URL 에서 사라졌다. + * + * 검증 방식 2단: + * 1. 실 레이아웃 JSON 전수 분석 — 클러스터 내 navigate 가 모두 `mergeQuery: true` 인지 + * 2. 실 액션을 엔진에 태워 실행(`triggerAction`) — 선언이 실제 목적지 URL 로 이어지는지 + * 선언만 검사하면 "JSON 에 리터럴이 적혀 있다" 까지만 고정되고 병합 결과는 미검증으로 남는다. + * + * @scenario leg=row_click|detail_return|form_cancel|filter_apply + * @effects navigation_preserves_list_query + * + * @vitest-environment jsdom + */ + +import { describe, it, expect, afterEach } from 'vitest'; +import fs from 'fs'; +import path from 'path'; + +import { + createLayoutTest, + createMockComponentRegistryWithBasics, +} from '@core/template-engine/__tests__/utils/layoutTestUtils'; + +const LAYOUTS_ROOT = path.resolve(__dirname, '../../../layouts'); + +/** 이 템플릿이 소유한 페이지네이션 목록 라우트 */ +const LIST_ROUTES = [ + '/admin/users', + '/admin/roles', + '/admin/activity-logs', + '/admin/identity/logs', + '/admin/notification-logs', + '/admin/notification-templates', + '/admin/modules', + '/admin/plugins', + '/admin/schedules', + '/admin/templates/admin', + '/admin/templates/user', +]; + +/** 목록 클러스터에 속하는 레이아웃 파일 */ +const CLUSTER_FILES = [ + 'admin_user_list.json', + 'admin_user_detail.json', + 'admin_user_form.json', + 'admin_role_list.json', + 'admin_role_form.json', + 'admin_activity_log_list.json', + 'admin_identity_logs.json', + 'admin_module_list.json', + 'admin_notification_log_list.json', + 'admin_plugin_list.json', + 'partials/admin_activity_log_list/_partial_datagrid.json', + 'partials/admin_activity_log_list/_partial_filter.json', + 'partials/admin_identity_logs/_partial_filter.json', + 'partials/admin_notification_log_list/_partial_datagrid.json', + 'partials/admin_notification_log_list/_partial_filter.json', + 'partials/admin_schedule_list/_tab_schedules.json', + // 템플릿 목록은 LIST_ROUTES 에 있으면서 클러스터 파일 목록에서 빠져 있었다. + // 그 탓에 검색 submit 이 표시 개수를 떨구는 회귀가 검사망을 그대로 통과했다 (#75). + 'admin_template_list.json', + 'partials/admin_template_list/_tab_admin.json', + 'partials/admin_template_list/_tab_user.json', +]; + +type NavAction = { + handler: string; + comment?: string; + params: { path?: string; mergeQuery?: unknown; query?: unknown }; +}; + +/** + * JSON 트리에서 navigate/replaceUrl 액션을 모두 수집합니다. + * + * @param node 순회 시작 노드 + * @returns 액션 목록 + */ +function collectNavActions(node: unknown): NavAction[] { + const out: NavAction[] = []; + const walk = (n: unknown): void => { + if (Array.isArray(n)) { + n.forEach(walk); + return; + } + if (!n || typeof n !== 'object') return; + const obj = n as Record; + if ( + (obj.handler === 'navigate' || obj.handler === 'replaceUrl') && + obj.params && + typeof obj.params === 'object' + ) { + out.push(obj as unknown as NavAction); + } + Object.values(obj).forEach(walk); + }; + walk(node); + return out; +} + +/** + * 목적지 경로를 비교용 표준형(`{{expr}}` → `*`)으로 바꿉니다. + * + * @param raw 원본 경로 + * @returns 표준형 경로 (판정 불가 시 null) + */ +function normalizePath(raw: unknown): string | null { + if (typeof raw !== 'string' || raw === '') return null; + const p = raw.replace(/\{\{[^}]*\}\}/g, '*').split('?')[0].replace(/\/+$/, ''); + return p.startsWith('/') ? p : null; +} + +/** + * 경로가 목록 라우트와 같은 클러스터인지 판정합니다. + * + * @param dest 표준형 목적지 + * @param list 표준형 목록 라우트 + * @returns 같은 클러스터 여부 + */ +function inFamily(dest: string, list: string): boolean { + return dest === list || dest.startsWith(`${list}/`); +} + +/** + * 레이아웃 파일을 읽어 파싱합니다. + * + * @param rel 레이아웃 루트 기준 상대 경로 + * @returns 파싱된 JSON + */ +function readLayout(rel: string): unknown { + return JSON.parse(fs.readFileSync(path.join(LAYOUTS_ROOT, rel), 'utf8')); +} + +describe('#75 관리자 코어 목록 컨텍스트 왕복 — mergeQuery 전수', () => { + it.each(CLUSTER_FILES)('%s 의 클러스터 내 navigate 는 모두 mergeQuery: true', (rel) => { + const offenders = collectNavActions(readLayout(rel)) + .filter((a) => { + if (typeof a.comment === 'string' && a.comment.includes('audit:allow')) return false; + const dest = normalizePath(a.params.path); + if (!dest) return false; + if (!LIST_ROUTES.some((l) => inFamily(dest, l))) return false; + return a.params.mergeQuery !== true; + }) + .map((a) => `${a.params.path} (mergeQuery=${JSON.stringify(a.params.mergeQuery)})`); + + expect(offenders, `목록 상태를 떨구는 navigate: \n ${offenders.join('\n ')}`).toEqual([]); + }); + + // 회원 상세(admin_user_detail)에는 '목록' 복귀 navigate 가 없다 — 브라우저 뒤로가기로 돌아간다. + // 상세에서 '수정' 으로 넘어가는 leg 은 위 전수 검사가 덮는다. + it("회원 등록/수정 폼의 '목록' 복귀가 목록 상태를 복원한다", () => { + const backs = collectNavActions(readLayout('admin_user_form.json')).filter( + (a) => a.params.path === '/admin/users' + ); + expect(backs.length, "admin_user_form.json 에 '/admin/users' 복귀 navigate 없음").toBeGreaterThan(0); + backs.forEach((a) => expect(a.params.mergeQuery).toBe(true)); + }); +}); + +// --------------------------------------------------------------------------- +// 실행 검증 — 실 액션을 엔진에 태워 목적지 URL 을 확인한다 +// --------------------------------------------------------------------------- + +/** + * 실 JSON 액션을 현재 URL 상태에서 실행하고 목적지를 돌려줍니다. + * + * @param action 실 레이아웃 JSON 에서 뽑은 navigate 액션 + * @returns navigate 목적지 경로 + */ +async function runNav(action: NavAction): Promise { + const utils = createLayoutTest( + { + version: '1.0.0', + layout_name: 'nav_action_probe', + data_sources: [], + components: [{ type: 'basic', name: 'Div', props: { 'data-testid': 'probe' } }], + } as never, + { componentRegistry: createMockComponentRegistryWithBasics() as never, locale: 'ko' } + ); + await utils.render(); + await utils.triggerAction({ type: 'click', ...action } as never); + const dest = utils.getNavigationHistory()[0]; + utils.cleanup(); + return dest; +} + +/** + * 목적지 URL 의 쿼리스트링을 파싱합니다. + * + * @param dest navigate 목적지 + * @returns URLSearchParams + */ +function queryOf(dest: string): URLSearchParams { + return new URLSearchParams(dest.includes('?') ? dest.slice(dest.indexOf('?')) : ''); +} + +describe('#75 회원/역할 목록 컨텍스트 왕복 — 실행 결과 URL', () => { + afterEach(() => { + window.history.replaceState({}, '', '/'); + }); + + it('회원 목록 행의 상세 이동이 검색/페이지를 상세 URL 로 나른다', async () => { + window.history.replaceState({}, '', '/admin/users?page=3&search=홍길동&per_page=20'); + + const action = collectNavActions(readLayout('admin_user_list.json')).find((a) => + /^\/admin\/users\/\{\{/.test(String(a.params.path ?? '')) + ); + expect(action, '회원 목록 행 이동 navigate 를 찾지 못했습니다.').toBeTruthy(); + + const q = queryOf(await runNav(action as NavAction)); + + expect(q.get('page')).toBe('3'); + expect(q.get('search')).toBe('홍길동'); + expect(q.get('per_page')).toBe('20'); + }); + + // 검색은 조건을 바꾸는 액션이므로 page 를 되돌린다. mergeQuery 가 현재 페이지까지 나르기 때문에 + // 되돌리지 않으면 3페이지를 보던 중 검색했을 때 결과의 3페이지로 이동해 빈 화면이 열린다. + // 표시 개수(per_page)·정렬은 사용자가 고른 값이므로 그대로 유지한다 (#75). + it('회원 목록 검색은 page 를 떨구고 표시 개수는 유지한다', async () => { + window.history.replaceState({}, '', '/admin/users?page=3&per_page=50&sort_by=created_at'); + + const search = (readLayout('admin_user_list.json') as { + named_actions: { searchUsers: NavAction }; + }).named_actions.searchUsers; + + const q = queryOf(await runNav(search)); + + expect(q.get('page')).toBeNull(); + expect(q.get('per_page')).toBe('50'); + expect(q.get('sort_by')).toBe('created_at'); + }); + + it("회원 폼의 '목록' 복귀가 목록 상태를 복원한다", async () => { + window.history.replaceState({}, '', '/admin/users/9/edit?page=3&search=홍길동'); + + const action = collectNavActions(readLayout('admin_user_form.json')).find( + (a) => a.params.path === '/admin/users' + ); + + const q = queryOf(await runNav(action as NavAction)); + + expect(q.get('page')).toBe('3'); + expect(q.get('search')).toBe('홍길동'); + }); + + // 검색은 조건을 "바꾸는" 액션이지 리셋이 아니다. 검색어와 페이지만 새로 정하고 + // 사용자가 고른 표시 개수(per_page)·정렬은 그대로 둔다. 같은 파일의 페이지네이션은 + // 이미 병합하고 있어서, 검색만 비병합이면 한 화면 안에서 규약이 엇갈린다 (#75). + it.each([ + ['admin', 'partials/admin_template_list/_tab_admin.json'], + ['user', 'partials/admin_template_list/_tab_user.json'], + ])('템플릿(%s) 목록 검색이 표시 개수를 유지한다', async (kind, rel) => { + window.history.replaceState({}, '', `/admin/templates/${kind}?page=3&per_page=48`); + + const action = collectNavActions(readLayout(rel)).find( + (a) => a.params.path === `/admin/templates/${kind}` + ); + expect(action, `${rel} 의 검색 navigate 를 찾지 못했습니다.`).toBeTruthy(); + + const q = queryOf(await runNav(action as NavAction)); + + expect(q.get('per_page')).toBe('48'); + expect(q.get('page')).toBeNull(); + }); + + it("역할 폼의 '목록' 복귀가 목록 상태를 복원한다", async () => { + window.history.replaceState({}, '', '/admin/roles/4/edit?page=2&search=관리'); + + const action = collectNavActions(readLayout('admin_role_form.json')).find( + (a) => a.params.path === '/admin/roles' + ); + expect(action, "역할 폼의 '/admin/roles' 복귀 navigate 를 찾지 못했습니다.").toBeTruthy(); + + const q = queryOf(await runNav(action as NavAction)); + + expect(q.get('page')).toBe('2'); + expect(q.get('search')).toBe('관리'); + }); +}); + +// --------------------------------------------------------------------------- +// 반대 방향 — 탭 전환은 상태를 승계하지 않는다 +// +// 템플릿 목록은 탭마다 라우트가 갈리고(`/admin/templates/user` ↔ `/admin/templates/admin`) +// 각 탭이 자기 검색어·페이지를 갖는 별개의 목록이다. 여기에 병합을 붙이면 다른 탭의 +// 검색 결과로 걸러진 페이지가 열린다 (#75 수정 중 실제로 한 번 들어갔던 회귀). +// --------------------------------------------------------------------------- + +describe('#75 탭 전환은 이전 탭의 목록 상태를 물려받지 않는다', () => { + afterEach(() => { + window.history.replaceState({}, '', '/'); + }); + + it('템플릿 목록 탭 전환 navigate 에 mergeQuery 가 없다', () => { + const tabNav = collectNavActions(readLayout('admin_template_list.json')).find((a) => + String(a.params.path ?? '').startsWith('/admin/templates/{{$args[0]') + ); + expect(tabNav, '템플릿 목록 탭 전환 navigate 를 찾지 못했습니다.').toBeTruthy(); + expect((tabNav as NavAction).params.mergeQuery).not.toBe(true); + expect(String((tabNav as NavAction).comment ?? '')).toContain('audit:allow'); + }); + + it('탭을 바꾸면 이전 탭의 검색어·페이지가 따라오지 않는다', async () => { + window.history.replaceState({}, '', '/admin/templates/user?page=3&search=sirsoft'); + + const tabNav = collectNavActions(readLayout('admin_template_list.json')).find((a) => + String(a.params.path ?? '').startsWith('/admin/templates/{{$args[0]') + ); + + const dest = await runNav({ + ...(tabNav as NavAction), + params: { ...(tabNav as NavAction).params, path: '/admin/templates/admin' }, + }); + const q = queryOf(dest); + + expect(dest.startsWith('/admin/templates/admin')).toBe(true); + expect(q.get('search')).toBeNull(); + expect(q.get('page')).toBeNull(); + }); +}); diff --git a/templates/_bundled/sirsoft-admin_basic/tests/Playwright/fixtures/admin-template-auth.ts b/templates/_bundled/sirsoft-admin_basic/tests/Playwright/fixtures/admin-template-auth.ts index 77de981e..74c464d2 100644 --- a/templates/_bundled/sirsoft-admin_basic/tests/Playwright/fixtures/admin-template-auth.ts +++ b/templates/_bundled/sirsoft-admin_basic/tests/Playwright/fixtures/admin-template-auth.ts @@ -14,6 +14,10 @@ type AdminTemplateAuthFixtures = { layoutEditToken: string; /** 관리자 대시보드 진입 권한 보유 토큰 (모바일 뷰포트 검증용) */ adminDashboardToken: string; + /** 회원 목록·등록 권한 보유 토큰 (목록 컨텍스트 왕복 검증용) */ + userManageToken: string; + /** 템플릿 목록 조회 권한 보유 토큰 (탭 전환 검증용) */ + templateReadToken: string; }; export const test = base.extend({ @@ -23,6 +27,12 @@ export const test = base.extend({ adminDashboardToken: async ({}, use) => { await use(issueToken('core.dashboard.read')); }, + userManageToken: async ({}, use) => { + await use(issueToken('core.users.read', 'core.users.write')); + }, + templateReadToken: async ({}, use) => { + await use(issueToken('core.templates.read')); + }, }); export { issueToken, authenticatePage }; diff --git a/templates/_bundled/sirsoft-admin_basic/tests/Playwright/specs/admin/admin-list-context-round-trip.spec.ts b/templates/_bundled/sirsoft-admin_basic/tests/Playwright/specs/admin/admin-list-context-round-trip.spec.ts new file mode 100644 index 00000000..ce66c725 --- /dev/null +++ b/templates/_bundled/sirsoft-admin_basic/tests/Playwright/specs/admin/admin-list-context-round-trip.spec.ts @@ -0,0 +1,72 @@ +/** + * sirsoft-admin_basic — 관리자 코어 목록 컨텍스트 왕복 (공개 이슈 #75). + * + * 결함: 회원·역할 목록에서 등록/수정 폼으로 들어갔다 돌아오면 표시 개수·검색어 같은 목록 상태가 + * URL 에서 사라져, 돌아온 목록이 항상 1페이지 기본 상태로 초기화됐다. + * + * 반대 방향도 함께 고정한다 — 템플릿 목록의 사용자/관리자 탭은 각자 검색어·페이지를 갖는 별개의 + * 목록이므로 탭을 바꿀 때 이전 탭의 상태가 따라오면 안 된다. 수정 과정에서 실제로 한 번 + * 병합이 붙어 남의 검색 결과로 걸러진 빈 페이지가 열렸던 자리다. + * + * 표시 개수(`per_page`)를 표식으로 쓴다 — 시드 건수와 무관하게 항상 URL 에 실리는 목록 상태다. + * + * @scenario admin-list-context-round-trip + * @axes leg=enter leg=cancel leg=tab_switch + * @effects list_return_preserves_query tab_switch_resets_query + */ +import { test, expect, authenticatePage } from '../../fixtures/admin-template-auth'; + +const LIST_STATE = 'per_page=10'; + +/** + * 현재 URL 의 쿼리 파라미터를 돌려줍니다. + * + * @param url 페이지 URL + * @returns 쿼리 파라미터 + */ +function queryOf(url: string): URLSearchParams { + return new URL(url).searchParams; +} + +test.describe('@sirsoft-admin_basic 관리자 목록 컨텍스트 왕복 (#75)', () => { + // @scenario leg=enter + // @effects list_return_preserves_query + test('회원 목록에서 등록 폼으로 들어가도 목록 상태가 URL 에 남는다', async ({ page, userManageToken }) => { + await authenticatePage(page, userManageToken); + await page.goto(`/admin/users?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#add_user_button').click(); + await page.waitForURL(/\/admin\/users\/create\?/, { timeout: 30_000 }); + + expect(queryOf(page.url()).get('per_page')).toBe('10'); + }); + + // @scenario leg=cancel + // @effects list_return_preserves_query + test('역할 등록 폼에서 취소하면 목록 상태가 유지된 채 목록으로 돌아온다', async ({ page, userManageToken }) => { + await authenticatePage(page, userManageToken); + await page.goto(`/admin/roles/create?${LIST_STATE}`); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#footer_cancel_button').click(); + await page.waitForURL(/\/admin\/roles\?/, { timeout: 30_000 }); + + expect(queryOf(page.url()).get('per_page')).toBe('10'); + }); + + // @scenario leg=tab_switch + // @effects tab_switch_resets_query + test('템플릿 목록 탭을 바꾸면 이전 탭의 검색어·페이지가 따라오지 않는다', async ({ page, templateReadToken }) => { + await authenticatePage(page, templateReadToken); + await page.goto('/admin/templates/user?search=sirsoft&page=2'); + await page.waitForLoadState('networkidle', { timeout: 30_000 }); + + await page.locator('#tab_navigation').getByRole('button').nth(1).click(); + await page.waitForURL(/\/admin\/templates\/admin/, { timeout: 30_000 }); + + const q = queryOf(page.url()); + expect(q.get('search')).toBeNull(); + expect(q.get('page')).toBeNull(); + }); +}); diff --git a/templates/_bundled/sirsoft-admin_basic/tests/scenarios/admin-list-context-round-trip.yaml b/templates/_bundled/sirsoft-admin_basic/tests/scenarios/admin-list-context-round-trip.yaml new file mode 100644 index 00000000..0350b2d7 --- /dev/null +++ b/templates/_bundled/sirsoft-admin_basic/tests/scenarios/admin-list-context-round-trip.yaml @@ -0,0 +1,29 @@ +feature: 관리자 코어 목록 컨텍스트 왕복 + +description: | + 회원·역할·활동이력·알림로그·모듈/플러그인·템플릿 목록과 그에 딸린 상세·등록/수정 폼은 하나의 + "목록 클러스터" 다. 이 안에서의 이동은 URL 목록 상태(page / per_page / search / 정렬 / 필터)를 + 손실 없이 이어받아야 한다 (공개 이슈 #75). + + 이 템플릿에는 반대 방향의 함정도 있다. 템플릿 목록의 사용자/관리자 탭은 라우트가 갈리고 + (`/admin/templates/user` ↔ `/admin/templates/admin`) 탭마다 자기 검색어·페이지를 갖는 **별개의 + 목록**이다. 여기에 상태 승계를 붙이면 남의 검색어로 걸러진 페이지(대개 빈 화면)가 열린다. + 실제로 #75 수정 과정에서 한 번 들어갔던 회귀라 두 방향을 함께 고정한다. + +axes: + # 목록 클러스터 안팎에서 발생하는 이동 leg + leg: [enter, cancel, tab_switch] # 목록→폼 진입 / 폼 취소→목록 / 탭 전환(다른 목록) + +effects: + - list_return_preserves_query # 클러스터 내 이동이 URL 목록 상태를 그대로 이어받음 + - tab_switch_resets_query # 탭 전환은 이전 탭의 검색어·페이지를 물려받지 않음 + +test_files: + - templates/_bundled/sirsoft-admin_basic/tests/Playwright/specs/admin/admin-list-context-round-trip.spec.ts + - templates/_bundled/sirsoft-admin_basic/src/__tests__/layouts/admin-list-context-round-trip.test.ts + +validation: + note: | + 목록 행 클릭(진입 leg)은 행 끝 액션 메뉴가 포털로 렌더돼 브라우저 로케이터가 불안정하므로 + 레이아웃 테스트가 실 JSON 의 액션 params 와 실행 결과 URL 로 고정한다. 브라우저 spec 은 + 화면 상단 버튼으로 확인 가능한 leg(등록 진입 / 폼 취소 / 탭 전환)을 실측한다. diff --git a/templates/_bundled/sirsoft-basic/CHANGELOG.md b/templates/_bundled/sirsoft-basic/CHANGELOG.md index 1e51b9d4..20a224a5 100644 --- a/templates/_bundled/sirsoft-basic/CHANGELOG.md +++ b/templates/_bundled/sirsoft-basic/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixed +- 게시글 목록에서 글을 열어 이전글·다음글로 넘어가면 보고 있던 페이지 번호와 검색어·분류가 사라져, 이어서 '목록'을 누르면 1페이지로 되돌아가던 문제를 수정했습니다. 이제 목록 ↔ 상세 ↔ 이전/다음 글 ↔ 글쓰기·수정 어디로 오가든, 글쓰기를 취소하고 돌아올 때도 보고 있던 목록 상태가 그대로 유지됩니다. 마이페이지 주문·마일리지 목록과 상품 목록(상품 상세에서 목록으로 돌아오는 경우 포함)도 동일하게 개선됐습니다. 검색 초기화와 탭 전환은 종전처럼 조건을 비웁니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) +- 상품 목록에서 상품을 열고 상세의 탭(상세정보·리뷰·문의)을 누르면 보고 있던 페이지·정렬·검색어·분류가 주소에서 사라져, 이어서 '상품 목록'을 눌러도 1페이지로 되돌아가던 문제를 수정했습니다. 이제 탭을 오가도 목록 상태가 그대로 유지됩니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) - 상품 상세에서 옵션을 선택해 장바구니에 담거나 바로 구매할 때, 표시 언어(로케일)나 관리자의 옵션 이름 수정과 무관하게 선택한 옵션이 정확히 담기도록 개선했습니다. 특정 상황에서 "해당 옵션 조합을 찾을 수 없습니다" 오류로 담기가 실패하던 문제가 해소됩니다. - 저장이나 삭제가 실패했을 때 아무 안내 없이 조용히 넘어가던 화면들을 수정했습니다. 이제 실패하면 그 이유가 화면에 표시되므로, 반영되지 않은 변경을 성공한 것으로 오해하지 않습니다. - 오류 안내가 뜨기는 하지만 내용이 비어 있던 문제를 수정했습니다. 서버가 알려 준 실패 사유가 그대로 표시됩니다. diff --git a/templates/_bundled/sirsoft-basic/dist/js/components.iife.js b/templates/_bundled/sirsoft-basic/dist/js/components.iife.js index 664587c5..f452ea12 100644 --- a/templates/_bundled/sirsoft-basic/dist/js/components.iife.js +++ b/templates/_bundled/sirsoft-basic/dist/js/components.iife.js @@ -1,4 +1,4 @@ -var SirsoftBasic=(function(J,c,k,Jt){"use strict";function Ic(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}}return t.default=e,Object.freeze(t)}const T=Ic(k),Dc=()=>window.G7Core,Q=k.forwardRef(({children:e,variant:t="primary",size:r="md",className:n="",...o},a)=>{const s="inline-flex items-center justify-center",l=Dc()?.style?.mergeClasses?.(s,n)??`${s} ${n}`;return c.jsx("button",{ref:a,className:l,...o,children:e})});Q.displayName="Button";const W=k.forwardRef(({children:e,className:t="",...r},n)=>c.jsx("div",{ref:n,className:t,...r,children:e})),ee=({children:e,className:t="",...r})=>c.jsx("span",{className:t,...r,children:e}),fn=({children:e,className:t="",...r})=>c.jsx("svg",{className:t,...r,children:e}),xt=k.forwardRef(({label:e,error:t,className:r="",onChange:n,onKeyPress:o,value:a,defaultValue:s,type:l="text",checked:f,defaultChecked:h,...d},i)=>{const u=l==="radio"||l==="checkbox",g=k.useRef(!1),p=k.useRef(null);k.useImperativeHandle(i,()=>p.current);const[m,w]=k.useState(a??s??"");k.useEffect(()=>{!u&&!g.current&&a!==void 0&&w(a)},[a,u]);const x=k.useCallback(()=>{g.current=!0},[]),A=k.useCallback(y=>{if(g.current=!1,n){const N=y.target.value;w(N);const M=new Event("change",{bubbles:!0});Object.defineProperty(M,"target",{writable:!1,value:{value:N}}),Object.defineProperty(M,"currentTarget",{writable:!1,value:{value:N}}),n(M)}},[n]),v=k.useCallback(y=>{const N=y.target.value;w(N),!g.current&&n&&n(y)},[n]),E=k.useCallback(y=>{g.current||o&&o(y)},[o]),{loadingactions:O,formdata:_,...I}=d;if(u)return c.jsx("input",{ref:p,type:l,className:r,onChange:n,checked:f,defaultChecked:h,value:a,...I});const C=a!==void 0?{value:m}:{defaultValue:s};return c.jsx("input",{ref:p,type:l,className:r,onChange:v,onKeyPress:E,onCompositionStart:x,onCompositionEnd:A,...C,...I})});xt.displayName="Input";const Ba=k.forwardRef(({accept:e,maxSize:t,onChange:r,onError:n,buttonText:o="Browse",placeholder:a="No file selected",className:s="",disabled:l,...f},h)=>{const d=k.useRef(null),i=h||d,[u,g]=k.useState(""),p={},m={};Object.entries(f).forEach(([v,E])=>{v.startsWith("data-editor-")||v==="id"||v==="onMouseMove"||v==="onMouseLeave"?p[v]=E:m[v]=E});const w=k.useCallback(()=>{!l&&i.current&&i.current.click()},[l,i]),x=k.useCallback(v=>{const E=v.target.files?.[0]||null;if(!E){g(""),r?.(null);return}if(t&&E.size>t*1024*1024){const O=`File size exceeds ${t}MB limit`;n?.(O),i.current&&(i.current.value=""),g("");return}g(E.name),r?.(E)},[t,r,n,i]),A=k.useCallback(v=>{v.stopPropagation(),i.current&&(i.current.value=""),g(""),r?.(null)},[r,i]);return c.jsxs(W,{className:`flex items-center gap-2 ${s}`,...p,children:[c.jsx(xt,{ref:i,type:"file",accept:e,onChange:x,disabled:l,className:"hidden",...m}),c.jsx(Q,{type:"button",onClick:w,disabled:l,className:"px-4 py-2 bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed",children:o}),c.jsx(ee,{className:"flex-1 text-sm text-gray-600 dark:text-gray-400 truncate",children:u||a}),u&&!l&&c.jsx(Q,{type:"button",onClick:A,className:"p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200","aria-label":"Clear file",children:c.jsx(fn,{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})});Ba.displayName="FileInput";var Je=(e=>(e.User="fa-user",e.Users="fa-users",e.UserCircle="fa-user-circle",e.UserPlus="fa-user-plus",e.UserMinus="fa-user-minus",e.UserShield="fa-user-shield",e.Search="fa-search",e.Edit="fa-edit",e.Pencil="fa-pencil-alt",e.Trash="fa-trash",e.Save="fa-save",e.Plus="fa-plus",e.Minus="fa-minus",e.Check="fa-check",e.Times="fa-times",e.Download="fa-download",e.Upload="fa-upload",e.Copy="fa-copy",e.ExternalLink="fa-external-link-alt",e.Home="fa-home",e.ChevronLeft="fa-chevron-left",e.ChevronRight="fa-chevron-right",e.ChevronUp="fa-chevron-up",e.ChevronDown="fa-chevron-down",e.AngleLeft="fa-angle-left",e.AngleRight="fa-angle-right",e.AngleUp="fa-angle-up",e.AngleDown="fa-angle-down",e.ArrowUp="fa-arrow-up",e.ArrowDown="fa-arrow-down",e.ArrowLeft="fa-arrow-left",e.ArrowRight="fa-arrow-right",e.Bars="fa-bars",e.EllipsisVertical="fa-ellipsis-v",e.EllipsisHorizontal="fa-ellipsis-h",e.CheckCircle="fa-check-circle",e.TimesCircle="fa-times-circle",e.ExclamationCircle="fa-exclamation-circle",e.ExclamationTriangle="fa-exclamation-triangle",e.InfoCircle="fa-info-circle",e.QuestionCircle="fa-question-circle",e.XCircle="fa-times-circle",e.ShoppingCart="fa-shopping-cart",e.ShoppingBag="fa-shopping-bag",e.CreditCard="fa-credit-card",e.Tag="fa-tag",e.Tags="fa-tags",e.File="fa-file",e.FileAlt="fa-file-alt",e.Folder="fa-folder",e.FolderOpen="fa-folder-open",e.Envelope="fa-envelope",e.Phone="fa-phone",e.Comment="fa-comment",e.Comments="fa-comments",e.Cog="fa-cog",e.Cogs="fa-cogs",e.Settings="fa-cog",e.Wrench="fa-wrench",e.Sliders="fa-sliders-h",e.Image="fa-image",e.Images="fa-images",e.Video="fa-video",e.Camera="fa-camera",e.Heart="fa-heart",e.Star="fa-star",e.ThumbsUp="fa-thumbs-up",e.ThumbsDown="fa-thumbs-down",e.Share="fa-share",e.Clock="fa-clock",e.Calendar="fa-calendar",e.CalendarAlt="fa-calendar-alt",e.Lock="fa-lock",e.Unlock="fa-unlock",e.Eye="fa-eye",e.EyeSlash="fa-eye-slash",e.Bell="fa-bell",e.Flag="fa-flag",e.Map="fa-map",e.MapMarker="fa-map-marker-alt",e.Globe="fa-globe",e.Link="fa-link",e.Unlink="fa-unlink",e.Sun="fa-sun",e.Moon="fa-moon",e.ChartBar="fa-chart-bar",e.ChartLine="fa-chart-line",e.ChartPie="fa-chart-pie",e.ChartArea="fa-chart-area",e.Spinner="fa-spinner",e.CircleNotch="fa-circle-notch",e.CheckBadge="fa-badge-check",e.BellSlash="fa-bell-slash",e.BookOpen="fa-book-open",e.Building="fa-building",e.FileCircleCheck="fa-file-circle-check",e.WandMagicSparkles="fa-wand-magic-sparkles",e.UserXmark="fa-user-xmark",e.Cube="fa-cube",e.Cubes="fa-cubes",e.Plug="fa-plug",e.PuzzlePiece="fa-puzzle-piece",e.Fire="fa-fire",e.CommentDots="fa-comment-dots",e.DollarSign="fa-dollar-sign",e.Bars2="fa-bars",e.X="fa-times",e.List="fa-list",e.ThLarge="fa-th-large",e.Inbox="fa-inbox",e.Box="fa-box",e.PaperPlane="fa-paper-plane",e.FileText="fa-file-alt",e.Paperclip="fa-paperclip",e.Truck="fa-truck",e.Sync="fa-sync",e.RotateLeft="fa-rotate-left",e.MapPin="fa-map-marker-alt",e.HelpCircle="fa-question-circle",e))(Je||{});const Lc={user:"fa-user",users:"fa-users","user-circle":"fa-user-circle","user-plus":"fa-user-plus","user-minus":"fa-user-minus","user-shield":"fa-user-shield",search:"fa-search",edit:"fa-edit",pencil:"fa-pencil-alt",trash:"fa-trash",save:"fa-save",plus:"fa-plus",minus:"fa-minus",check:"fa-check",times:"fa-times",download:"fa-download",upload:"fa-upload",copy:"fa-copy","external-link":"fa-external-link-alt",home:"fa-home","chevron-left":"fa-chevron-left","chevron-right":"fa-chevron-right","chevron-up":"fa-chevron-up","chevron-down":"fa-chevron-down","angle-left":"fa-angle-left","angle-right":"fa-angle-right","angle-up":"fa-angle-up","angle-down":"fa-angle-down","arrow-up":"fa-arrow-up","arrow-down":"fa-arrow-down","arrow-left":"fa-arrow-left","arrow-right":"fa-arrow-right",bars:"fa-bars","ellipsis-vertical":"fa-ellipsis-v","ellipsis-v":"fa-ellipsis-v","ellipsis-horizontal":"fa-ellipsis-h","ellipsis-h":"fa-ellipsis-h","check-circle":"fa-check-circle","times-circle":"fa-times-circle","x-circle":"fa-times-circle","exclamation-circle":"fa-exclamation-circle","exclamation-triangle":"fa-exclamation-triangle","info-circle":"fa-info-circle","question-circle":"fa-question-circle","shopping-cart":"fa-shopping-cart","shopping-bag":"fa-shopping-bag","credit-card":"fa-credit-card",tag:"fa-tag",tags:"fa-tags",file:"fa-file","file-alt":"fa-file-alt",folder:"fa-folder","folder-open":"fa-folder-open",envelope:"fa-envelope",phone:"fa-phone",comment:"fa-comment",comments:"fa-comments",cog:"fa-cog",cogs:"fa-cogs",settings:"fa-cog",wrench:"fa-wrench",sliders:"fa-sliders-h",image:"fa-image",images:"fa-images",video:"fa-video",camera:"fa-camera",heart:"fa-heart",star:"fa-star","thumbs-up":"fa-thumbs-up","thumbs-down":"fa-thumbs-down",share:"fa-share",clock:"fa-clock",calendar:"fa-calendar","calendar-alt":"fa-calendar-alt",lock:"fa-lock",unlock:"fa-unlock",eye:"fa-eye","eye-slash":"fa-eye-slash",bell:"fa-bell",flag:"fa-flag",map:"fa-map","map-marker":"fa-map-marker-alt",globe:"fa-globe",link:"fa-link",unlink:"fa-unlink",sun:"fa-sun",moon:"fa-moon","chart-bar":"fa-chart-bar","chart-line":"fa-chart-line","chart-pie":"fa-chart-pie","chart-area":"fa-chart-area",spinner:"fa-spinner","circle-notch":"fa-circle-notch","check-badge":"fa-badge-check","badge-check":"fa-badge-check",cube:"fa-cube",cubes:"fa-cubes",plug:"fa-plug","puzzle-piece":"fa-puzzle-piece",flame:"fa-fire",fire:"fa-fire","message-square":"fa-comment-dots","dollar-sign":"fa-dollar-sign",menu:"fa-bars",x:"fa-times",list:"fa-list","layout-grid":"fa-th-large","th-large":"fa-th-large",grid:"fa-th-large",inbox:"fa-inbox",package:"fa-box",box:"fa-box",send:"fa-paper-plane","paper-plane":"fa-paper-plane","file-text":"fa-file-alt",paperclip:"fa-paperclip",truck:"fa-truck","refresh-cw":"fa-sync",sync:"fa-sync","undo-2":"fa-rotate-left","rotate-left":"fa-rotate-left","map-pin":"fa-map-marker-alt","help-circle":"fa-question-circle","alert-triangle":"fa-exclamation-triangle","bell-off":"fa-bell-slash","book-open":"fa-book-open",building:"fa-building","edit-2":"fa-edit","edit-3":"fa-edit","file-check":"fa-file-circle-check",mail:"fa-envelope",sparkles:"fa-wand-magic-sparkles","trash-2":"fa-trash","user-x":"fa-user-xmark"},de=({name:e,iconStyle:t="solid",size:r,color:n,spin:o=!1,pulse:a=!1,fixedWidth:s=!1,ariaLabel:l,className:f="",style:h,...d})=>{const i={solid:"fas",regular:"far",light:"fal",duotone:"fad",brands:"fab"},u=typeof e=="string"?e:String(e),g=Lc[u],p=g?String(g).replace(/^fa-/,""):u.replace(/^fa-/,""),m=[i[t],`fa-${p}`,r&&`fa-${r}`,o&&"fa-spin",a&&"fa-pulse",s&&"fa-fw",n,f].filter(Boolean).join(" "),w=l||p.replace(/-/g," ");return c.jsx("i",{className:m,style:h,"aria-label":w,role:"img",...d})},br=(e,t)=>window.G7Core?.t?.(e,t)??e,ro={minLength:{key:"minLength",labelKey:"auth.password_input.rules.minLength",defaultParam:6,validate:(e,t=6)=>e.length>=t},maxLength:{key:"maxLength",labelKey:"auth.password_input.rules.maxLength",defaultParam:20,validate:(e,t=20)=>e.length<=t},hasUppercase:{key:"hasUppercase",labelKey:"auth.password_input.rules.hasUppercase",validate:e=>/[A-Z]/.test(e)},hasLowercase:{key:"hasLowercase",labelKey:"auth.password_input.rules.hasLowercase",validate:e=>/[a-z]/.test(e)},hasNumber:{key:"hasNumber",labelKey:"auth.password_input.rules.hasNumber",validate:e=>/[0-9]/.test(e)},hasSpecial:{key:"hasSpecial",labelKey:"auth.password_input.rules.hasSpecial",validate:e=>/[!@#$%^&*(),.?":{}|<>]/.test(e)},noSpaces:{key:"noSpaces",labelKey:"auth.password_input.rules.noSpaces",validate:e=>!/\s/.test(e)},minTypes:{key:"minTypes",labelKey:"auth.password_input.rules.minTypes",defaultParam:3,validate:(e,t=3)=>{let r=0;return/[A-Z]/.test(e)&&r++,/[a-z]/.test(e)&&r++,/[0-9]/.test(e)&&r++,/[!@#$%^&*(),.?":{}|<>]/.test(e)&&r++,r>=t}}},Wa=[ro.minLength];function Pc(e){const[t,r]=e.split(":"),n=ro[t];if(!n)return null;const o=r?parseInt(r,10):n.defaultParam;return{rule:n,param:isNaN(o)?n.defaultParam:o}}const Ka=k.forwardRef(({label:e,error:t,showToggle:r=!0,showValidation:n=!1,isConfirmField:o=!1,confirmTarget:a,onMatchChange:s,onValidityChange:l,rules:f,enableRules:h,showRules:d,wrapperClassName:i="",validationClassName:u="",className:g="",onChange:p,value:m,defaultValue:w,disabled:x,...A},v)=>{const E=k.useRef(null);k.useImperativeHandle(v,()=>E.current);const[O,_]=k.useState(!1),[I,C]=k.useState(!1),[y,N]=k.useState(m??w??"");k.useEffect(()=>{m!==void 0&&N(m)},[m]);const M=k.useMemo(()=>f&&f.length>0?f.map(j=>({rule:j,param:j.defaultParam})):h&&h.length>0?h.map(j=>Pc(j)).filter(j=>j!==null):Wa.map(j=>({rule:j,param:j.defaultParam})),[f,h]),P=k.useMemo(()=>!d||d.length===0?M:M.filter(j=>d.includes(j.rule.key)),[M,d]),D=k.useMemo(()=>!n||o?{}:P.reduce((j,{rule:H,param:Z})=>(j[H.key]=H.validate(y,Z),j),{}),[y,P,n,o]),L=k.useMemo(()=>!o||a===void 0?!0:y===a&&y.length>0,[o,y,a]),U=k.useMemo(()=>n?Object.values(D).every(j=>j):!0,[D,n]);k.useEffect(()=>{if(l&&n&&!o){const j=Object.entries(D).filter(([,H])=>!H).map(([H])=>H);l(U,j)}},[U,D,l,n,o]),k.useEffect(()=>{s&&o&&s(L)},[L,s,o]);const S=k.useCallback(()=>{_(j=>!j)},[]),b=k.useCallback(j=>{const H=j.target.value;N(H),p&&p(j)},[p]),$=k.useCallback(j=>{C(j.getModifierState("CapsLock"))},[]),{loadingactions:F,formdata:G,...Y}=A,B={},V={};for(const[j,H]of Object.entries(Y))j.startsWith("data-editor-")||j==="onMouseMove"||j==="onMouseLeave"?B[j]=H:V[j]=H;return c.jsxs("div",{className:`relative ${i}`,...B,children:[c.jsxs("div",{className:"relative",children:[c.jsx("input",{ref:E,type:O?"text":"password",className:`${g} ${r?"pr-10":""}`,value:m!==void 0?m:void 0,defaultValue:m===void 0?w:void 0,onChange:b,onKeyDown:$,onKeyUp:$,disabled:x,...V}),r&&c.jsx("button",{type:"button",onClick:S,disabled:x,className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 disabled:opacity-50 disabled:cursor-not-allowed dark:disabled:opacity-50","aria-label":br(O?"auth.password_input.hide":"auth.password_input.show"),children:c.jsx(de,{name:O?"eye-slash":"eye",className:"w-5 h-5"})})]}),I&&!O&&c.jsxs("div",{className:"mt-2 flex items-center gap-1.5 text-sm text-yellow-600 dark:text-yellow-400",children:[c.jsx(de,{name:"triangle-exclamation",className:"w-4 h-4"}),c.jsx("span",{children:br("auth.password_input.caps_lock_on")})]}),o&&a!==void 0&&y.length>0&&c.jsxs("div",{className:`mt-2 flex items-center gap-1.5 text-sm ${L?"text-green-600 dark:text-green-400":"text-red-600 dark:text-red-400"}`,children:[c.jsx(de,{name:L?"check-circle":"xmark-circle",className:"w-4 h-4"}),c.jsx("span",{children:br(L?"auth.password_input.match":"auth.password_input.mismatch")})]}),n&&!o&&y.length>0&&c.jsx("div",{className:`mt-2 space-y-1 ${u}`,children:P.map(({rule:j,param:H})=>{const Z=D[j.key],ue=H!==void 0?{count:H}:void 0;return c.jsxs("div",{className:`flex items-center gap-1.5 text-sm ${Z?"text-green-600 dark:text-green-400":"text-gray-500 dark:text-gray-400"}`,children:[c.jsx(de,{name:Z?"check-circle":"circle",className:"w-4 h-4"}),c.jsx("span",{children:br(j.labelKey,ue)})]},j.key)})}),t&&c.jsx("p",{className:"mt-1 text-sm text-red-600 dark:text-red-400",children:t})]})});Ka.displayName="PasswordInput";const no=({label:e,error:t,className:r="",onChange:n,value:o,defaultValue:a,...s})=>{const l=k.useRef(!1),f=k.useRef(null),[h,d]=k.useState(o??a??"");k.useEffect(()=>{!l.current&&o!==void 0&&d(o)},[o]);const i=k.useCallback(()=>{l.current=!0},[]),u=k.useCallback(A=>{if(l.current=!1,n){const v=A.target.value;d(v);const E=new Event("change",{bubbles:!0});Object.defineProperty(E,"target",{writable:!1,value:{value:v}}),Object.defineProperty(E,"currentTarget",{writable:!1,value:{value:v}}),n(E)}},[n]),g=k.useCallback(A=>{const v=A.target.value;d(v),!l.current&&n&&n(A)},[n]),{loadingactions:p,formdata:m,...w}=s,x=o!==void 0?{value:h}:{defaultValue:a};return c.jsx("textarea",{ref:f,className:r,onChange:g,onCompositionStart:i,onCompositionEnd:u,...x,...w})},yr=({children:e,className:t="",...r})=>c.jsx("label",{className:t,...r,children:e}),Dt=({children:e,className:t="",...r})=>c.jsx("p",{className:t,...r,children:e}),Lt=({className:e="",alt:t="",...r})=>c.jsx("img",{className:e,alt:t,...r}),Fc=({children:e,className:t="",...r})=>c.jsx("h1",{className:t,...r,children:e}),Va=({children:e,className:t="",...r})=>c.jsx("h2",{className:t,...r,children:e}),gn=({children:e,className:t="",...r})=>c.jsx("h3",{className:t,...r,children:e}),Ya=({children:e,className:t="",...r})=>c.jsx("h4",{className:t,...r,children:e}),oo=({children:e,className:t="",...r})=>c.jsx("ul",{className:t,...r,children:e}),$c=({children:e,className:t="",...r})=>c.jsx("ol",{className:t,...r,children:e}),Xt=({children:e,className:t="",...r})=>c.jsx("li",{className:t,...r,children:e}),ao=({children:e,className:t="",...r})=>c.jsx("a",{className:t,...r,children:e}),so=({children:e,className:t="",...r})=>c.jsx("form",{className:t,...r,children:e}),Uc=window.G7Core?.createLogger?.("Comp:Select")??{log:(...e)=>console.log("[Comp:Select]",...e),warn:(...e)=>console.warn("[Comp:Select]",...e),error:(...e)=>console.error("[Comp:Select]",...e)};function zc(e){const t=window.G7Core?.state?.get?.("_global.appConfig.localeNames")?.[e];return t||{ko:"한국어",en:"English",ja:"日本語",zh:"中文",es:"Español",fr:"Français",de:"Deutsch"}[e]||e}const Xa=({children:e,label:t,error:r,options:n,className:o="",value:a,onChange:s,disabled:l,searchable:f=!1,searchPlaceholder:h,editorAttrs:d,...i})=>{const[u,g]=k.useState(!1),[p,m]=k.useState(""),[w,x]=k.useState(null),A=k.useRef(null),v=k.useRef(null),E=k.useRef(null),O=k.useRef(null),_=k.useMemo(()=>n?Array.isArray(n)?n.length===0?[]:typeof n[0]=="string"?n.map(S=>({value:S,label:zc(S)})):n:(Uc.warn("options prop is not an array:",n),null):null,[n]),I=k.useMemo(()=>_&&_.find(b=>String(b.value)===String(a))?.label||"",[_,a]),C=k.useMemo(()=>{if(!_)return null;if(!f||p.trim()==="")return _;const S=p.trim().toLowerCase();return _.filter(b=>b.label.toLowerCase().includes(S)||String(b.value).toLowerCase().includes(S))},[_,f,p]);k.useEffect(()=>{if(u&&f){m("");const S=setTimeout(()=>E.current?.focus(),0);return()=>clearTimeout(S)}u||m("")},[u,f]);const y=k.useCallback(()=>{if(!v.current)return;const S=v.current.getBoundingClientRect(),b=window.innerHeight-S.bottom,F=b<280&&S.top>b;x(F?{bottom:window.innerHeight-S.top+4,left:S.left,width:S.width}:{top:S.bottom+4,left:S.left,width:S.width})},[]);k.useEffect(()=>{if(!u){x(null);return}return y(),window.addEventListener("scroll",y,!0),window.addEventListener("resize",y),()=>{window.removeEventListener("scroll",y,!0),window.removeEventListener("resize",y)}},[u,y]),k.useEffect(()=>{const S=b=>{const $=b.target;A.current&&!A.current.contains($)&&(!O.current||!O.current.contains($))&&g(!1)};return u&&document.addEventListener("mousedown",S),()=>{document.removeEventListener("mousedown",S)}},[u]),k.useEffect(()=>{const S=b=>{b.key==="Escape"&&u&&(g(!1),v.current?.focus())};return document.addEventListener("keydown",S),()=>document.removeEventListener("keydown",S)},[u]);const N=()=>{l||g(!u)},M=S=>{s&&s({target:{value:S},preventDefault:()=>{},stopPropagation:()=>{},type:"change"}),g(!1),v.current?.focus()};if(!_)return c.jsx("select",{className:o,value:a,onChange:s,disabled:l,...d,...i,children:e});const P=o&&o.includes("bg-"),D=o&&/text-(gray|red|blue|green|yellow|white|black|indigo|purple|pink|orange|amber|emerald|teal|cyan|slate)-\d+|text-white|text-black/.test(o),L=P?`${o}${D?"":" text-gray-700 dark:text-gray-200"}`:`w-full px-4 py-2.5 bg-gray-100 dark:bg-gray-700 border-0 rounded-xl text-gray-700 dark:text-gray-200 font-medium focus:ring-2 focus:ring-blue-500 focus:outline-none ${o}`,U={...d,...i};return c.jsxs(W,{ref:A,className:"relative",...U,children:[c.jsxs(Q,{ref:v,type:"button",onClick:N,disabled:l,className:`${L} flex items-center justify-between gap-2 text-left cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed`,"aria-haspopup":"listbox","aria-expanded":u,children:[c.jsx(ee,{className:"truncate",children:I||" "}),c.jsx(fn,{className:`w-4 h-4 flex-shrink-0 transition-transform duration-200 ${u?"rotate-180":""}`,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]}),u&&w&&Jt.createPortal(c.jsxs(W,{ref:O,className:"fixed z-[9999] bg-white dark:bg-gray-800 rounded-2xl shadow-lg border border-gray-200 dark:border-gray-600 overflow-hidden",style:{top:w.top,bottom:w.bottom,left:w.left,width:w.width},role:"listbox",children:[f&&c.jsx(W,{className:"p-2 border-b border-gray-200 dark:border-gray-600",children:c.jsx(xt,{ref:E,type:"text",value:p,onChange:S=>m(S.target.value),placeholder:h??"Search...",className:"w-full px-3 py-2 bg-gray-100 dark:bg-gray-700 border-0 rounded-lg text-sm text-gray-700 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500 focus:outline-none",role:"searchbox","aria-label":h??"Search"})}),c.jsxs(W,{className:"py-2 max-h-60 overflow-auto",children:[C&&C.length===0&&c.jsx(W,{className:"px-4 py-3 text-sm text-gray-500 dark:text-gray-400 text-center",children:p?"No results":""}),(C??[]).map(S=>{const b=String(S.value)===String(a);return c.jsxs(Q,{type:"button",onClick:()=>!S.disabled&&M(S.value),disabled:S.disabled,className:`w-full px-4 py-3 text-left flex items-center justify-between hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors ${b?"text-blue-600 dark:text-blue-400 font-medium":"text-gray-700 dark:text-gray-200"} ${S.disabled?"opacity-50 cursor-not-allowed":"cursor-pointer"}`,role:"option","aria-selected":b,children:[c.jsx(ee,{children:S.label}),b&&c.jsx(fn,{className:"w-5 h-5 text-blue-600 dark:text-blue-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})})]},S.value)})]})]}),document.body)]})},Hc=({children:e,className:t="",...r})=>c.jsx("option",{className:t,...r,children:e}),Gc=({children:e,className:t="",...r})=>c.jsx("optgroup",{className:t,...r,children:e}),Za=k.forwardRef(({label:e,className:t="",...r},n)=>c.jsx("input",{ref:n,type:"checkbox",className:t,...r}));Za.displayName="Checkbox";const jc=({children:e,className:t="",...r})=>c.jsx("table",{className:t,...r,children:e}),Bc=({children:e,className:t="",...r})=>c.jsx("thead",{className:t,...r,children:e}),Wc=({children:e,className:t="",...r})=>c.jsx("tbody",{className:t,...r,children:e}),Kc=({children:e,className:t="",...r})=>c.jsx("tr",{className:t,...r,children:e}),Vc=({children:e,className:t="",...r})=>c.jsx("th",{className:t,...r,children:e}),Yc=({children:e,className:t="",...r})=>c.jsx("td",{className:t,...r,children:e}),$r=k.forwardRef(({children:e,className:t="",...r},n)=>c.jsx("nav",{ref:n,className:t,...r,children:e}));$r.displayName="Nav";const qa=({children:e,className:t="",...r})=>c.jsx("section",{className:t,...r,children:e}),Xc=({children:e,className:t="",...r})=>c.jsx("code",{className:t,...r,children:e}),lo=k.forwardRef(({className:e="",...t},r)=>c.jsx("hr",{ref:r,className:e,...t})),Zc=k.forwardRef(({children:e,className:t="",...r},n)=>c.jsx("header",{ref:n,className:t,...r,children:e})),Qa=e=>e==="auto"?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e,io=e=>{const t=Qa(e);document.documentElement.setAttribute("data-theme",t),t==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")},qc=()=>{const e=localStorage.getItem("g7_color_scheme");return e&&["auto","light","dark"].includes(e)?e:"auto"},hn=({onThemeChange:e,className:t="",autoText:r="System",lightText:n="Light",darkText:o="Dark",id:a,editorAttrs:s})=>{const l=qc(),[f,h]=k.useState(l),[d,i]=k.useState(!1),u=k.useRef(null);k.useEffect(()=>{io(f)},[]),k.useEffect(()=>{if(f!=="auto")return;const m=window.matchMedia("(prefers-color-scheme: dark)"),w=()=>{io("auto")};return m.addEventListener("change",w),()=>m.removeEventListener("change",w)},[f]),k.useEffect(()=>{const m=w=>{u.current&&!u.current.contains(w.target)&&i(!1)};return document.addEventListener("mousedown",m),()=>document.removeEventListener("mousedown",m)},[]);const g=m=>{h(m),localStorage.setItem("g7_color_scheme",m),io(m),i(!1),e?.(m)},p=()=>Qa(f)==="dark"?Je.Moon:Je.Sun;return c.jsxs(W,{ref:u,className:`relative ${t}`,id:a,...s,children:[c.jsx(Q,{onClick:()=>i(!d),className:"p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors text-gray-600 dark:text-gray-400","aria-label":"Toggle theme",children:c.jsx(de,{name:p(),className:"w-5 h-5"})}),d&&c.jsx(W,{className:"absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-50",children:c.jsxs(W,{className:"py-2",children:[c.jsxs(Q,{onClick:()=>g("auto"),className:` +var SirsoftBasic=(function(J,c,k,Jt){"use strict";function Ic(e){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const r in e)if(r!=="default"){const n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:()=>e[r]})}}return t.default=e,Object.freeze(t)}const T=Ic(k),Dc=()=>window.G7Core,Q=k.forwardRef(({children:e,variant:t="primary",size:r="md",className:n="",...o},a)=>{const s="inline-flex items-center justify-center",l=Dc()?.style?.mergeClasses?.(s,n)??`${s} ${n}`;return c.jsx("button",{ref:a,className:l,...o,children:e})});Q.displayName="Button";const W=k.forwardRef(({children:e,className:t="",...r},n)=>c.jsx("div",{ref:n,className:t,...r,children:e})),ee=({children:e,className:t="",...r})=>c.jsx("span",{className:t,...r,children:e}),fn=({children:e,className:t="",...r})=>c.jsx("svg",{className:t,...r,children:e}),xt=k.forwardRef(({label:e,error:t,className:r="",onChange:n,onKeyPress:o,value:a,defaultValue:s,type:l="text",checked:f,defaultChecked:h,...d},i)=>{const u=l==="radio"||l==="checkbox",g=k.useRef(!1),p=k.useRef(null);k.useImperativeHandle(i,()=>p.current);const[m,w]=k.useState(a??s??"");k.useEffect(()=>{!u&&!g.current&&a!==void 0&&w(a)},[a,u]);const x=k.useCallback(()=>{g.current=!0},[]),O=k.useCallback(v=>{if(g.current=!1,n){const N=v.target.value;w(N);const A=new Event("change",{bubbles:!0});Object.defineProperty(A,"target",{writable:!1,value:{value:N}}),Object.defineProperty(A,"currentTarget",{writable:!1,value:{value:N}}),n(A)}},[n]),y=k.useCallback(v=>{const N=v.target.value;w(N),!g.current&&n&&n(v)},[n]),E=k.useCallback(v=>{g.current||o&&o(v)},[o]),{loadingactions:M,formdata:_,...I}=d;if(u)return c.jsx("input",{ref:p,type:l,className:r,onChange:n,checked:f,defaultChecked:h,value:a,...I});const C=a!==void 0?{value:m}:{defaultValue:s};return c.jsx("input",{ref:p,type:l,className:r,onChange:y,onKeyPress:E,onCompositionStart:x,onCompositionEnd:O,...C,...I})});xt.displayName="Input";const Ba=k.forwardRef(({accept:e,maxSize:t,onChange:r,onError:n,buttonText:o="Browse",placeholder:a="No file selected",className:s="",disabled:l,...f},h)=>{const d=k.useRef(null),i=h||d,[u,g]=k.useState(""),p={},m={};Object.entries(f).forEach(([y,E])=>{y.startsWith("data-editor-")||y==="id"||y==="onMouseMove"||y==="onMouseLeave"?p[y]=E:m[y]=E});const w=k.useCallback(()=>{!l&&i.current&&i.current.click()},[l,i]),x=k.useCallback(y=>{const E=y.target.files?.[0]||null;if(!E){g(""),r?.(null);return}if(t&&E.size>t*1024*1024){const M=`File size exceeds ${t}MB limit`;n?.(M),i.current&&(i.current.value=""),g("");return}g(E.name),r?.(E)},[t,r,n,i]),O=k.useCallback(y=>{y.stopPropagation(),i.current&&(i.current.value=""),g(""),r?.(null)},[r,i]);return c.jsxs(W,{className:`flex items-center gap-2 ${s}`,...p,children:[c.jsx(xt,{ref:i,type:"file",accept:e,onChange:x,disabled:l,className:"hidden",...m}),c.jsx(Q,{type:"button",onClick:w,disabled:l,className:"px-4 py-2 bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md text-sm font-medium text-gray-700 dark:text-gray-200 hover:bg-gray-200 dark:hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed",children:o}),c.jsx(ee,{className:"flex-1 text-sm text-gray-600 dark:text-gray-400 truncate",children:u||a}),u&&!l&&c.jsx(Q,{type:"button",onClick:O,className:"p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200","aria-label":"Clear file",children:c.jsx(fn,{className:"w-4 h-4",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]})});Ba.displayName="FileInput";var Je=(e=>(e.User="fa-user",e.Users="fa-users",e.UserCircle="fa-user-circle",e.UserPlus="fa-user-plus",e.UserMinus="fa-user-minus",e.UserShield="fa-user-shield",e.Search="fa-search",e.Edit="fa-edit",e.Pencil="fa-pencil-alt",e.Trash="fa-trash",e.Save="fa-save",e.Plus="fa-plus",e.Minus="fa-minus",e.Check="fa-check",e.Times="fa-times",e.Download="fa-download",e.Upload="fa-upload",e.Copy="fa-copy",e.ExternalLink="fa-external-link-alt",e.Home="fa-home",e.ChevronLeft="fa-chevron-left",e.ChevronRight="fa-chevron-right",e.ChevronUp="fa-chevron-up",e.ChevronDown="fa-chevron-down",e.AngleLeft="fa-angle-left",e.AngleRight="fa-angle-right",e.AngleUp="fa-angle-up",e.AngleDown="fa-angle-down",e.ArrowUp="fa-arrow-up",e.ArrowDown="fa-arrow-down",e.ArrowLeft="fa-arrow-left",e.ArrowRight="fa-arrow-right",e.Bars="fa-bars",e.EllipsisVertical="fa-ellipsis-v",e.EllipsisHorizontal="fa-ellipsis-h",e.CheckCircle="fa-check-circle",e.TimesCircle="fa-times-circle",e.ExclamationCircle="fa-exclamation-circle",e.ExclamationTriangle="fa-exclamation-triangle",e.InfoCircle="fa-info-circle",e.QuestionCircle="fa-question-circle",e.XCircle="fa-times-circle",e.ShoppingCart="fa-shopping-cart",e.ShoppingBag="fa-shopping-bag",e.CreditCard="fa-credit-card",e.Tag="fa-tag",e.Tags="fa-tags",e.File="fa-file",e.FileAlt="fa-file-alt",e.Folder="fa-folder",e.FolderOpen="fa-folder-open",e.Envelope="fa-envelope",e.Phone="fa-phone",e.Comment="fa-comment",e.Comments="fa-comments",e.Cog="fa-cog",e.Cogs="fa-cogs",e.Settings="fa-cog",e.Wrench="fa-wrench",e.Sliders="fa-sliders-h",e.Image="fa-image",e.Images="fa-images",e.Video="fa-video",e.Camera="fa-camera",e.Heart="fa-heart",e.Star="fa-star",e.ThumbsUp="fa-thumbs-up",e.ThumbsDown="fa-thumbs-down",e.Share="fa-share",e.Clock="fa-clock",e.Calendar="fa-calendar",e.CalendarAlt="fa-calendar-alt",e.Lock="fa-lock",e.Unlock="fa-unlock",e.Eye="fa-eye",e.EyeSlash="fa-eye-slash",e.Bell="fa-bell",e.Flag="fa-flag",e.Map="fa-map",e.MapMarker="fa-map-marker-alt",e.Globe="fa-globe",e.Link="fa-link",e.Unlink="fa-unlink",e.Sun="fa-sun",e.Moon="fa-moon",e.ChartBar="fa-chart-bar",e.ChartLine="fa-chart-line",e.ChartPie="fa-chart-pie",e.ChartArea="fa-chart-area",e.Spinner="fa-spinner",e.CircleNotch="fa-circle-notch",e.CheckBadge="fa-badge-check",e.BellSlash="fa-bell-slash",e.BookOpen="fa-book-open",e.Building="fa-building",e.FileCircleCheck="fa-file-circle-check",e.WandMagicSparkles="fa-wand-magic-sparkles",e.UserXmark="fa-user-xmark",e.Cube="fa-cube",e.Cubes="fa-cubes",e.Plug="fa-plug",e.PuzzlePiece="fa-puzzle-piece",e.Fire="fa-fire",e.CommentDots="fa-comment-dots",e.DollarSign="fa-dollar-sign",e.Bars2="fa-bars",e.X="fa-times",e.List="fa-list",e.ThLarge="fa-th-large",e.Inbox="fa-inbox",e.Box="fa-box",e.PaperPlane="fa-paper-plane",e.FileText="fa-file-alt",e.Paperclip="fa-paperclip",e.Truck="fa-truck",e.Sync="fa-sync",e.RotateLeft="fa-rotate-left",e.MapPin="fa-map-marker-alt",e.HelpCircle="fa-question-circle",e))(Je||{});const Lc={user:"fa-user",users:"fa-users","user-circle":"fa-user-circle","user-plus":"fa-user-plus","user-minus":"fa-user-minus","user-shield":"fa-user-shield",search:"fa-search",edit:"fa-edit",pencil:"fa-pencil-alt",trash:"fa-trash",save:"fa-save",plus:"fa-plus",minus:"fa-minus",check:"fa-check",times:"fa-times",download:"fa-download",upload:"fa-upload",copy:"fa-copy","external-link":"fa-external-link-alt",home:"fa-home","chevron-left":"fa-chevron-left","chevron-right":"fa-chevron-right","chevron-up":"fa-chevron-up","chevron-down":"fa-chevron-down","angle-left":"fa-angle-left","angle-right":"fa-angle-right","angle-up":"fa-angle-up","angle-down":"fa-angle-down","arrow-up":"fa-arrow-up","arrow-down":"fa-arrow-down","arrow-left":"fa-arrow-left","arrow-right":"fa-arrow-right",bars:"fa-bars","ellipsis-vertical":"fa-ellipsis-v","ellipsis-v":"fa-ellipsis-v","ellipsis-horizontal":"fa-ellipsis-h","ellipsis-h":"fa-ellipsis-h","check-circle":"fa-check-circle","times-circle":"fa-times-circle","x-circle":"fa-times-circle","exclamation-circle":"fa-exclamation-circle","exclamation-triangle":"fa-exclamation-triangle","info-circle":"fa-info-circle","question-circle":"fa-question-circle","shopping-cart":"fa-shopping-cart","shopping-bag":"fa-shopping-bag","credit-card":"fa-credit-card",tag:"fa-tag",tags:"fa-tags",file:"fa-file","file-alt":"fa-file-alt",folder:"fa-folder","folder-open":"fa-folder-open",envelope:"fa-envelope",phone:"fa-phone",comment:"fa-comment",comments:"fa-comments",cog:"fa-cog",cogs:"fa-cogs",settings:"fa-cog",wrench:"fa-wrench",sliders:"fa-sliders-h",image:"fa-image",images:"fa-images",video:"fa-video",camera:"fa-camera",heart:"fa-heart",star:"fa-star","thumbs-up":"fa-thumbs-up","thumbs-down":"fa-thumbs-down",share:"fa-share",clock:"fa-clock",calendar:"fa-calendar","calendar-alt":"fa-calendar-alt",lock:"fa-lock",unlock:"fa-unlock",eye:"fa-eye","eye-slash":"fa-eye-slash",bell:"fa-bell",flag:"fa-flag",map:"fa-map","map-marker":"fa-map-marker-alt",globe:"fa-globe",link:"fa-link",unlink:"fa-unlink",sun:"fa-sun",moon:"fa-moon","chart-bar":"fa-chart-bar","chart-line":"fa-chart-line","chart-pie":"fa-chart-pie","chart-area":"fa-chart-area",spinner:"fa-spinner","circle-notch":"fa-circle-notch","check-badge":"fa-badge-check","badge-check":"fa-badge-check",cube:"fa-cube",cubes:"fa-cubes",plug:"fa-plug","puzzle-piece":"fa-puzzle-piece",flame:"fa-fire",fire:"fa-fire","message-square":"fa-comment-dots","dollar-sign":"fa-dollar-sign",menu:"fa-bars",x:"fa-times",list:"fa-list","layout-grid":"fa-th-large","th-large":"fa-th-large",grid:"fa-th-large",inbox:"fa-inbox",package:"fa-box",box:"fa-box",send:"fa-paper-plane","paper-plane":"fa-paper-plane","file-text":"fa-file-alt",paperclip:"fa-paperclip",truck:"fa-truck","refresh-cw":"fa-sync",sync:"fa-sync","undo-2":"fa-rotate-left","rotate-left":"fa-rotate-left","map-pin":"fa-map-marker-alt","help-circle":"fa-question-circle","alert-triangle":"fa-exclamation-triangle","bell-off":"fa-bell-slash","book-open":"fa-book-open",building:"fa-building","edit-2":"fa-edit","edit-3":"fa-edit","file-check":"fa-file-circle-check",mail:"fa-envelope",sparkles:"fa-wand-magic-sparkles","trash-2":"fa-trash","user-x":"fa-user-xmark"},de=({name:e,iconStyle:t="solid",size:r,color:n,spin:o=!1,pulse:a=!1,fixedWidth:s=!1,ariaLabel:l,className:f="",style:h,...d})=>{const i={solid:"fas",regular:"far",light:"fal",duotone:"fad",brands:"fab"},u=typeof e=="string"?e:String(e),g=Lc[u],p=g?String(g).replace(/^fa-/,""):u.replace(/^fa-/,""),m=[i[t],`fa-${p}`,r&&`fa-${r}`,o&&"fa-spin",a&&"fa-pulse",s&&"fa-fw",n,f].filter(Boolean).join(" "),w=l||p.replace(/-/g," ");return c.jsx("i",{className:m,style:h,"aria-label":w,role:"img",...d})},br=(e,t)=>window.G7Core?.t?.(e,t)??e,ro={minLength:{key:"minLength",labelKey:"auth.password_input.rules.minLength",defaultParam:6,validate:(e,t=6)=>e.length>=t},maxLength:{key:"maxLength",labelKey:"auth.password_input.rules.maxLength",defaultParam:20,validate:(e,t=20)=>e.length<=t},hasUppercase:{key:"hasUppercase",labelKey:"auth.password_input.rules.hasUppercase",validate:e=>/[A-Z]/.test(e)},hasLowercase:{key:"hasLowercase",labelKey:"auth.password_input.rules.hasLowercase",validate:e=>/[a-z]/.test(e)},hasNumber:{key:"hasNumber",labelKey:"auth.password_input.rules.hasNumber",validate:e=>/[0-9]/.test(e)},hasSpecial:{key:"hasSpecial",labelKey:"auth.password_input.rules.hasSpecial",validate:e=>/[!@#$%^&*(),.?":{}|<>]/.test(e)},noSpaces:{key:"noSpaces",labelKey:"auth.password_input.rules.noSpaces",validate:e=>!/\s/.test(e)},minTypes:{key:"minTypes",labelKey:"auth.password_input.rules.minTypes",defaultParam:3,validate:(e,t=3)=>{let r=0;return/[A-Z]/.test(e)&&r++,/[a-z]/.test(e)&&r++,/[0-9]/.test(e)&&r++,/[!@#$%^&*(),.?":{}|<>]/.test(e)&&r++,r>=t}}},Wa=[ro.minLength];function Pc(e){const[t,r]=e.split(":"),n=ro[t];if(!n)return null;const o=r?parseInt(r,10):n.defaultParam;return{rule:n,param:isNaN(o)?n.defaultParam:o}}const Ka=k.forwardRef(({label:e,error:t,showToggle:r=!0,showValidation:n=!1,isConfirmField:o=!1,confirmTarget:a,onMatchChange:s,onValidityChange:l,rules:f,enableRules:h,showRules:d,wrapperClassName:i="",validationClassName:u="",className:g="",onChange:p,value:m,defaultValue:w,disabled:x,...O},y)=>{const E=k.useRef(null);k.useImperativeHandle(y,()=>E.current);const[M,_]=k.useState(!1),[I,C]=k.useState(!1),[v,N]=k.useState(m??w??"");k.useEffect(()=>{m!==void 0&&N(m)},[m]);const A=k.useMemo(()=>f&&f.length>0?f.map(j=>({rule:j,param:j.defaultParam})):h&&h.length>0?h.map(j=>Pc(j)).filter(j=>j!==null):Wa.map(j=>({rule:j,param:j.defaultParam})),[f,h]),P=k.useMemo(()=>!d||d.length===0?A:A.filter(j=>d.includes(j.rule.key)),[A,d]),D=k.useMemo(()=>!n||o?{}:P.reduce((j,{rule:H,param:q})=>(j[H.key]=H.validate(v,q),j),{}),[v,P,n,o]),L=k.useMemo(()=>!o||a===void 0?!0:v===a&&v.length>0,[o,v,a]),U=k.useMemo(()=>n?Object.values(D).every(j=>j):!0,[D,n]);k.useEffect(()=>{if(l&&n&&!o){const j=Object.entries(D).filter(([,H])=>!H).map(([H])=>H);l(U,j)}},[U,D,l,n,o]),k.useEffect(()=>{s&&o&&s(L)},[L,s,o]);const S=k.useCallback(()=>{_(j=>!j)},[]),b=k.useCallback(j=>{const H=j.target.value;N(H),p&&p(j)},[p]),$=k.useCallback(j=>{C(j.getModifierState("CapsLock"))},[]),{loadingactions:F,formdata:G,...Y}=O,B={},V={};for(const[j,H]of Object.entries(Y))j.startsWith("data-editor-")||j==="onMouseMove"||j==="onMouseLeave"?B[j]=H:V[j]=H;return c.jsxs("div",{className:`relative ${i}`,...B,children:[c.jsxs("div",{className:"relative",children:[c.jsx("input",{ref:E,type:M?"text":"password",className:`${g} ${r?"pr-10":""}`,value:m!==void 0?m:void 0,defaultValue:m===void 0?w:void 0,onChange:b,onKeyDown:$,onKeyUp:$,disabled:x,...V}),r&&c.jsx("button",{type:"button",onClick:S,disabled:x,className:"absolute right-2 top-1/2 -translate-y-1/2 p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 disabled:opacity-50 disabled:cursor-not-allowed dark:disabled:opacity-50","aria-label":br(M?"auth.password_input.hide":"auth.password_input.show"),children:c.jsx(de,{name:M?"eye-slash":"eye",className:"w-5 h-5"})})]}),I&&!M&&c.jsxs("div",{className:"mt-2 flex items-center gap-1.5 text-sm text-yellow-600 dark:text-yellow-400",children:[c.jsx(de,{name:"triangle-exclamation",className:"w-4 h-4"}),c.jsx("span",{children:br("auth.password_input.caps_lock_on")})]}),o&&a!==void 0&&v.length>0&&c.jsxs("div",{className:`mt-2 flex items-center gap-1.5 text-sm ${L?"text-green-600 dark:text-green-400":"text-red-600 dark:text-red-400"}`,children:[c.jsx(de,{name:L?"check-circle":"xmark-circle",className:"w-4 h-4"}),c.jsx("span",{children:br(L?"auth.password_input.match":"auth.password_input.mismatch")})]}),n&&!o&&v.length>0&&c.jsx("div",{className:`mt-2 space-y-1 ${u}`,children:P.map(({rule:j,param:H})=>{const q=D[j.key],ue=H!==void 0?{count:H}:void 0;return c.jsxs("div",{className:`flex items-center gap-1.5 text-sm ${q?"text-green-600 dark:text-green-400":"text-gray-500 dark:text-gray-400"}`,children:[c.jsx(de,{name:q?"check-circle":"circle",className:"w-4 h-4"}),c.jsx("span",{children:br(j.labelKey,ue)})]},j.key)})}),t&&c.jsx("p",{className:"mt-1 text-sm text-red-600 dark:text-red-400",children:t})]})});Ka.displayName="PasswordInput";const no=({label:e,error:t,className:r="",onChange:n,value:o,defaultValue:a,...s})=>{const l=k.useRef(!1),f=k.useRef(null),[h,d]=k.useState(o??a??"");k.useEffect(()=>{!l.current&&o!==void 0&&d(o)},[o]);const i=k.useCallback(()=>{l.current=!0},[]),u=k.useCallback(O=>{if(l.current=!1,n){const y=O.target.value;d(y);const E=new Event("change",{bubbles:!0});Object.defineProperty(E,"target",{writable:!1,value:{value:y}}),Object.defineProperty(E,"currentTarget",{writable:!1,value:{value:y}}),n(E)}},[n]),g=k.useCallback(O=>{const y=O.target.value;d(y),!l.current&&n&&n(O)},[n]),{loadingactions:p,formdata:m,...w}=s,x=o!==void 0?{value:h}:{defaultValue:a};return c.jsx("textarea",{ref:f,className:r,onChange:g,onCompositionStart:i,onCompositionEnd:u,...x,...w})},yr=({children:e,className:t="",...r})=>c.jsx("label",{className:t,...r,children:e}),Dt=({children:e,className:t="",...r})=>c.jsx("p",{className:t,...r,children:e}),Lt=({className:e="",alt:t="",...r})=>c.jsx("img",{className:e,alt:t,...r}),Fc=({children:e,className:t="",...r})=>c.jsx("h1",{className:t,...r,children:e}),Va=({children:e,className:t="",...r})=>c.jsx("h2",{className:t,...r,children:e}),gn=({children:e,className:t="",...r})=>c.jsx("h3",{className:t,...r,children:e}),Ya=({children:e,className:t="",...r})=>c.jsx("h4",{className:t,...r,children:e}),oo=({children:e,className:t="",...r})=>c.jsx("ul",{className:t,...r,children:e}),$c=({children:e,className:t="",...r})=>c.jsx("ol",{className:t,...r,children:e}),Xt=({children:e,className:t="",...r})=>c.jsx("li",{className:t,...r,children:e}),ao=({children:e,className:t="",...r})=>c.jsx("a",{className:t,...r,children:e}),so=({children:e,className:t="",...r})=>c.jsx("form",{className:t,...r,children:e}),Uc=window.G7Core?.createLogger?.("Comp:Select")??{log:(...e)=>console.log("[Comp:Select]",...e),warn:(...e)=>console.warn("[Comp:Select]",...e),error:(...e)=>console.error("[Comp:Select]",...e)};function zc(e){const t=window.G7Core?.state?.get?.("_global.appConfig.localeNames")?.[e];return t||{ko:"한국어",en:"English",ja:"日本語",zh:"中文",es:"Español",fr:"Français",de:"Deutsch"}[e]||e}const Xa=({children:e,label:t,error:r,options:n,className:o="",value:a,onChange:s,disabled:l,searchable:f=!1,searchPlaceholder:h,editorAttrs:d,...i})=>{const[u,g]=k.useState(!1),[p,m]=k.useState(""),[w,x]=k.useState(null),O=k.useRef(null),y=k.useRef(null),E=k.useRef(null),M=k.useRef(null),_=k.useMemo(()=>n?Array.isArray(n)?n.length===0?[]:typeof n[0]=="string"?n.map(S=>({value:S,label:zc(S)})):n:(Uc.warn("options prop is not an array:",n),null):null,[n]),I=k.useMemo(()=>_&&_.find(b=>String(b.value)===String(a))?.label||"",[_,a]),C=k.useMemo(()=>{if(!_)return null;if(!f||p.trim()==="")return _;const S=p.trim().toLowerCase();return _.filter(b=>b.label.toLowerCase().includes(S)||String(b.value).toLowerCase().includes(S))},[_,f,p]);k.useEffect(()=>{if(u&&f){m("");const S=setTimeout(()=>E.current?.focus(),0);return()=>clearTimeout(S)}u||m("")},[u,f]);const v=k.useCallback(()=>{if(!y.current)return;const S=y.current.getBoundingClientRect(),b=window.innerHeight-S.bottom,F=b<280&&S.top>b;x(F?{bottom:window.innerHeight-S.top+4,left:S.left,width:S.width}:{top:S.bottom+4,left:S.left,width:S.width})},[]);k.useEffect(()=>{if(!u){x(null);return}return v(),window.addEventListener("scroll",v,!0),window.addEventListener("resize",v),()=>{window.removeEventListener("scroll",v,!0),window.removeEventListener("resize",v)}},[u,v]),k.useEffect(()=>{const S=b=>{const $=b.target;O.current&&!O.current.contains($)&&(!M.current||!M.current.contains($))&&g(!1)};return u&&document.addEventListener("mousedown",S),()=>{document.removeEventListener("mousedown",S)}},[u]),k.useEffect(()=>{const S=b=>{b.key==="Escape"&&u&&(g(!1),y.current?.focus())};return document.addEventListener("keydown",S),()=>document.removeEventListener("keydown",S)},[u]);const N=()=>{l||g(!u)},A=S=>{s&&s({target:{value:S},preventDefault:()=>{},stopPropagation:()=>{},type:"change"}),g(!1),y.current?.focus()};if(!_)return c.jsx("select",{className:o,value:a,onChange:s,disabled:l,...d,...i,children:e});const P=o&&o.includes("bg-"),D=o&&/text-(gray|red|blue|green|yellow|white|black|indigo|purple|pink|orange|amber|emerald|teal|cyan|slate)-\d+|text-white|text-black/.test(o),L=P?`${o}${D?"":" text-gray-700 dark:text-gray-200"}`:`w-full px-4 py-2.5 bg-gray-100 dark:bg-gray-700 border-0 rounded-xl text-gray-700 dark:text-gray-200 font-medium focus:ring-2 focus:ring-blue-500 focus:outline-none ${o}`,U={...d,...i};return c.jsxs(W,{ref:O,className:"relative",...U,children:[c.jsxs(Q,{ref:y,type:"button",onClick:N,disabled:l,className:`${L} flex items-center justify-between gap-2 text-left cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed`,"aria-haspopup":"listbox","aria-expanded":u,children:[c.jsx(ee,{className:"truncate",children:I||" "}),c.jsx(fn,{className:`w-4 h-4 flex-shrink-0 transition-transform duration-200 ${u?"rotate-180":""}`,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})]}),u&&w&&Jt.createPortal(c.jsxs(W,{ref:M,className:"fixed z-[9999] bg-white dark:bg-gray-800 rounded-2xl shadow-lg border border-gray-200 dark:border-gray-600 overflow-hidden",style:{top:w.top,bottom:w.bottom,left:w.left,width:w.width},role:"listbox",children:[f&&c.jsx(W,{className:"p-2 border-b border-gray-200 dark:border-gray-600",children:c.jsx(xt,{ref:E,type:"text",value:p,onChange:S=>m(S.target.value),placeholder:h??"Search...",className:"w-full px-3 py-2 bg-gray-100 dark:bg-gray-700 border-0 rounded-lg text-sm text-gray-700 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500 focus:ring-2 focus:ring-blue-500 focus:outline-none",role:"searchbox","aria-label":h??"Search"})}),c.jsxs(W,{className:"py-2 max-h-60 overflow-auto",children:[C&&C.length===0&&c.jsx(W,{className:"px-4 py-3 text-sm text-gray-500 dark:text-gray-400 text-center",children:p?"No results":""}),(C??[]).map(S=>{const b=String(S.value)===String(a);return c.jsxs(Q,{type:"button",onClick:()=>!S.disabled&&A(S.value),disabled:S.disabled,className:`w-full px-4 py-3 text-left flex items-center justify-between hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors ${b?"text-blue-600 dark:text-blue-400 font-medium":"text-gray-700 dark:text-gray-200"} ${S.disabled?"opacity-50 cursor-not-allowed":"cursor-pointer"}`,role:"option","aria-selected":b,children:[c.jsx(ee,{children:S.label}),b&&c.jsx(fn,{className:"w-5 h-5 text-blue-600 dark:text-blue-400",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})})]},S.value)})]})]}),document.body)]})},Hc=({children:e,className:t="",...r})=>c.jsx("option",{className:t,...r,children:e}),Gc=({children:e,className:t="",...r})=>c.jsx("optgroup",{className:t,...r,children:e}),qa=k.forwardRef(({label:e,className:t="",...r},n)=>c.jsx("input",{ref:n,type:"checkbox",className:t,...r}));qa.displayName="Checkbox";const jc=({children:e,className:t="",...r})=>c.jsx("table",{className:t,...r,children:e}),Bc=({children:e,className:t="",...r})=>c.jsx("thead",{className:t,...r,children:e}),Wc=({children:e,className:t="",...r})=>c.jsx("tbody",{className:t,...r,children:e}),Kc=({children:e,className:t="",...r})=>c.jsx("tr",{className:t,...r,children:e}),Vc=({children:e,className:t="",...r})=>c.jsx("th",{className:t,...r,children:e}),Yc=({children:e,className:t="",...r})=>c.jsx("td",{className:t,...r,children:e}),$r=k.forwardRef(({children:e,className:t="",...r},n)=>c.jsx("nav",{ref:n,className:t,...r,children:e}));$r.displayName="Nav";const Za=({children:e,className:t="",...r})=>c.jsx("section",{className:t,...r,children:e}),Xc=({children:e,className:t="",...r})=>c.jsx("code",{className:t,...r,children:e}),lo=k.forwardRef(({className:e="",...t},r)=>c.jsx("hr",{ref:r,className:e,...t})),qc=k.forwardRef(({children:e,className:t="",...r},n)=>c.jsx("header",{ref:n,className:t,...r,children:e})),Qa=e=>e==="auto"?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e,io=e=>{const t=Qa(e);document.documentElement.setAttribute("data-theme",t),t==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")},Zc=()=>{const e=localStorage.getItem("g7_color_scheme");return e&&["auto","light","dark"].includes(e)?e:"auto"},hn=({onThemeChange:e,className:t="",autoText:r="System",lightText:n="Light",darkText:o="Dark",id:a,editorAttrs:s})=>{const l=Zc(),[f,h]=k.useState(l),[d,i]=k.useState(!1),u=k.useRef(null);k.useEffect(()=>{io(f)},[]),k.useEffect(()=>{if(f!=="auto")return;const m=window.matchMedia("(prefers-color-scheme: dark)"),w=()=>{io("auto")};return m.addEventListener("change",w),()=>m.removeEventListener("change",w)},[f]),k.useEffect(()=>{const m=w=>{u.current&&!u.current.contains(w.target)&&i(!1)};return document.addEventListener("mousedown",m),()=>document.removeEventListener("mousedown",m)},[]);const g=m=>{h(m),localStorage.setItem("g7_color_scheme",m),io(m),i(!1),e?.(m)},p=()=>Qa(f)==="dark"?Je.Moon:Je.Sun;return c.jsxs(W,{ref:u,className:`relative ${t}`,id:a,...s,children:[c.jsx(Q,{onClick:()=>i(!d),className:"p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors text-gray-600 dark:text-gray-400","aria-label":"Toggle theme",children:c.jsx(de,{name:p(),className:"w-5 h-5"})}),d&&c.jsx(W,{className:"absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-50",children:c.jsxs(W,{className:"py-2",children:[c.jsxs(Q,{onClick:()=>g("auto"),className:` w-full px-4 py-2 text-left hover:bg-gray-50 dark:hover:bg-gray-700 flex items-center gap-3 transition-colors ${f==="auto"?"bg-gray-50 dark:bg-gray-700":""} `,children:[c.jsx(de,{name:Je.Settings,className:"w-5 h-5 text-gray-600 dark:text-gray-400"}),c.jsx(ee,{className:"flex-1 text-left text-gray-900 dark:text-white",children:r}),f==="auto"&&c.jsx(de,{name:Je.Check,className:"w-4 h-4 text-blue-600 dark:text-blue-400 ml-auto"})]}),c.jsxs(Q,{onClick:()=>g("light"),className:` @@ -7,12 +7,12 @@ var SirsoftBasic=(function(J,c,k,Jt){"use strict";function Ic(e){const t=Object. `,children:[c.jsx(de,{name:Je.Sun,className:"w-5 h-5 text-gray-600 dark:text-gray-400"}),c.jsx(ee,{className:"flex-1 text-left text-gray-900 dark:text-white",children:n}),f==="light"&&c.jsx(de,{name:Je.Check,className:"w-4 h-4 text-blue-600 dark:text-blue-400 ml-auto"})]}),c.jsxs(Q,{onClick:()=>g("dark"),className:` w-full px-4 py-2 text-left hover:bg-gray-50 dark:hover:bg-gray-700 flex items-center gap-3 transition-colors ${f==="dark"?"bg-gray-50 dark:bg-gray-700":""} - `,children:[c.jsx(de,{name:Je.Moon,className:"w-5 h-5 text-gray-600 dark:text-gray-400"}),c.jsx(ee,{className:"flex-1 text-left text-gray-900 dark:text-white",children:o}),f==="dark"&&c.jsx(de,{name:Je.Check,className:"w-4 h-4 text-blue-600 dark:text-blue-400 ml-auto"})]})]})})]})},Qc=Object.freeze(Object.defineProperty({__proto__:null,ThemeToggle:hn,default:hn},Symbol.toStringTag,{value:"Module"})),Ja={xs:"w-6 h-6 text-xs",sm:"w-8 h-8 text-sm",md:"w-10 h-10 text-base",lg:"w-12 h-12 text-lg",xl:"w-16 h-16 text-xl","2xl":"w-24 h-24 text-2xl","3xl":"w-32 h-32 text-3xl","4xl":"w-40 h-40 text-4xl","5xl":"w-48 h-48 text-5xl"},Jc="rounded-full overflow-hidden flex-shrink-0 border border-gray-200 dark:border-gray-700",Rc="grayscale opacity-50",co={normal:"bg-gradient-to-br from-blue-500 to-purple-600",withdrawn:"bg-gray-300 dark:bg-gray-600",guest:"bg-gray-200 dark:bg-gray-700"},Ur=({author:e,name:t,avatar:r,size:n="md",className:o="",text:a,isWithdrawn:s=!1,isGuest:l=!1,id:f,editorAttrs:h})=>{const d=r??e?.avatar,i=a??t??e?.name??"?",u=s||e?.status==="withdrawn",g=l||e?.is_guest||!1,p=k.useMemo(()=>[Ja[n]||Ja.md,Jc,u?Rc:"",o].filter(Boolean).join(" "),[n,u,o]),m=g?co.guest:u?co.withdrawn:co.normal,w=()=>g?c.jsx(W,{className:`w-full h-full flex items-center justify-center ${m}`,children:c.jsx(de,{name:"user",className:"text-gray-400 dark:text-gray-500"})}):u?c.jsx(W,{className:`w-full h-full flex items-center justify-center ${m}`,children:c.jsx(de,{name:"user",className:"text-gray-500 dark:text-gray-400"})}):c.jsx(W,{className:`w-full h-full flex items-center justify-center text-white font-semibold ${m}`,children:i.charAt(0).toUpperCase()});return c.jsx(W,{className:p,id:f,...h,children:d&&!g&&!u?c.jsx(Lt,{src:d,alt:i,className:"w-full h-full object-cover"}):w()})},ed=Object.freeze(Object.defineProperty({__proto__:null,Avatar:Ur},Symbol.toStringTag,{value:"Module"})),td=window.G7Core?.createLogger?.("Comp:SlotContainer")??{log:(...e)=>console.log("[Comp:SlotContainer]",...e),warn:(...e)=>console.warn("[Comp:SlotContainer]",...e),error:(...e)=>console.error("[Comp:SlotContainer]",...e)};function Ra(e,t){return t&&e&&typeof e.id=="string"&&e.id.length>0?{...e,id:`${e.id}__${t}`}:e}const pn=({slotId:e,className:t="",emptyContent:r,style:n,id:o,children:a})=>{const[s,l]=k.useState([]),[,f]=k.useState({}),h=k.useCallback(()=>{const p=window.__slotContextValue;if(p)return p;const m=window.G7Core;return m&&m.getSlotContext?.()||null},[]),d=k.useCallback(()=>{const p=h();p&&p.isEnabled&&l(p.getSlotComponents(e))},[e,h]);k.useEffect(()=>{const p=h();return!p||!p.isEnabled?void 0:(d(),p.subscribeToSlot(e,()=>{d(),f({})}))},[e,h,d]);const i=k.useCallback(()=>{const p=window.G7Core;return p?p.getDynamicRenderer?.():null},[]);if(s.length===0)return r?c.jsx(W,{className:t,style:n,id:o,children:r}):a?c.jsx(W,{className:t,style:n,id:o,children:a}):null;const u=i(),g=window.G7Core;return!u||!g?(td.error("G7Core or DynamicRenderer not available"),null):c.jsxs(W,{className:t,style:n,id:o,children:[s.map(p=>{const{componentDef:m,dataContext:w,parentFormContext:x,getParentComponentContext:A,translationContext:v}=p,E=Ra(m,o);return c.jsx(u,{componentDef:E,dataContext:w,translationContext:v,registry:g.getComponentRegistry(),bindingEngine:g.getDataBindingEngine(),translationEngine:g.getTranslationEngine(),actionDispatcher:g.getActionDispatcher(),parentComponentContext:A?.(),parentFormContextProp:x,isRootRenderer:!1},E.id||`slot-${e}-${p.order}`)}),a]})},rd=Object.freeze(Object.defineProperty({__proto__:null,SlotContainer:pn,default:pn,scopeSlotChildDef:Ra},Symbol.toStringTag,{value:"Module"})),mn=({notifications:e=[],unreadCount:t=0,hasMore:r=!1,loading:n=!1,titleText:o="알림",emptyText:a="알림이 없습니다.",markAllReadText:s="모두 읽음",deleteAllText:l="모두 삭제",unreadOnlyText:f="안 읽은 알림만",unreadOnly:h=!1,onNotificationClick:d,onClose:i,onLoadMore:u,onMarkAllRead:g,onDeleteAll:p,onDelete:m,onUnreadOnlyToggle:w,dropdownAlign:x="right",className:A="",id:v,editorAttrs:E})=>{const[O,_]=k.useState(!1),I=k.useRef(null),C=k.useRef(null),y=k.useRef(null),N=k.useRef(null),M=k.useRef(new Set),P=k.useRef(u),D=k.useRef(r),L=k.useRef(n),U=k.useRef(e.length),S=k.useRef(-1);k.useEffect(()=>{P.current=u,D.current=r,L.current=n,U.current=e.length}),k.useEffect(()=>{if(!N.current||!y.current||!O)return;S.current=-1;const G=new IntersectionObserver(([Y])=>{Y.isIntersecting&&(L.current||!D.current||S.current!==U.current&&(S.current=U.current,P.current?.()))},{root:y.current,threshold:.1});return G.observe(N.current),()=>G.disconnect()},[O]),k.useEffect(()=>{if(!y.current||!O)return;const G=new IntersectionObserver(B=>{B.forEach(V=>{const j=V.target.getAttribute("data-notification-id"),H=V.target.getAttribute("data-unread")==="true";j&&H&&V.isIntersecting&&M.current.add(j)})},{root:y.current,threshold:.5});return y.current.querySelectorAll("[data-notification-id]").forEach(B=>G.observe(B)),()=>G.disconnect()},[O,e]);const b=t>0?t:e.filter(G=>!G.read).length,$=k.useCallback(()=>{if(O){if(b>0){const G=Array.from(M.current).filter(Y=>{const B=e.find(V=>String(V.id)===String(Y));return B&&!B.read});G.length>0&&i?.(G)}M.current.clear(),_(!1)}},[O,i,b,e]);k.useEffect(()=>{if(!O)return;const G=Y=>{I.current&&!I.current.contains(Y.target)&&$()};return document.addEventListener("mousedown",G),()=>document.removeEventListener("mousedown",G)},[O,$]);const F=k.useCallback(()=>{O?$():_(!0)},[O,$]);return k.useLayoutEffect(()=>{const G=C.current;if(!O||!G)return;G.style.transform="";const Y=G.getBoundingClientRect(),B=typeof window<"u"?window.innerWidth:0;if(Y.width===0&&Y.height===0)return;const V=8;let j=0;Y.right>B-V?j=-(Y.right-(B-V)):Y.left0&&c.jsx(ee,{className:"absolute -top-1 -right-1 w-5 h-5 flex items-center justify-center text-xs font-bold text-white bg-red-500 dark:bg-red-600 rounded-full",children:b>99?"99+":b})]}),O&&c.jsxs(W,{ref:C,className:`absolute ${x==="left"?"left-0":"right-0"} mt-2 w-80 max-w-[calc(100vw-1rem)] bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-50`,children:[c.jsxs(W,{className:"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between gap-2",children:[c.jsxs(W,{className:"flex items-center gap-3 min-w-0",children:[c.jsx(ee,{className:"font-semibold text-gray-900 dark:text-white",children:o}),w&&c.jsxs(W,{className:"flex items-center gap-1.5 cursor-pointer select-none",onClick:()=>w(!h),children:[c.jsx(xt,{type:"checkbox",checked:h,onChange:G=>{G.stopPropagation(),w(G.target.checked)},onClick:G=>G.stopPropagation(),className:"w-3.5 h-3.5 rounded border-gray-300 dark:border-gray-600 text-blue-600 dark:text-blue-400 focus:ring-blue-500 dark:focus:ring-blue-400 cursor-pointer"}),c.jsx(ee,{className:"text-xs text-gray-600 dark:text-gray-400",children:f})]})]}),c.jsxs(W,{className:"flex items-center gap-3 flex-shrink-0",children:[g&&b>0&&c.jsx(Q,{onClick:()=>{g(),M.current.clear()},className:"text-xs text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 hover:underline cursor-pointer",children:s}),p&&e.length>0&&c.jsx(Q,{onClick:()=>{p()},className:"text-xs text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300 hover:underline cursor-pointer",children:l})]})]}),c.jsx(W,{ref:y,className:"max-h-96 overflow-y-auto",children:e.length===0&&!n?c.jsx(W,{className:"px-4 py-8 text-center text-gray-500 dark:text-gray-400",children:c.jsx(ee,{children:a})}):c.jsxs(c.Fragment,{children:[e.map(G=>{const Y=!G.read;return c.jsxs(W,{"data-notification-id":G.id,"data-unread":Y?"true":"false",onClick:()=>{G.onClick?.(),d?.(G),_(!1)},className:`group flex items-start gap-3 px-4 py-3 text-left border-b border-gray-100 dark:border-gray-700 transition-colors cursor-pointer ${Y?"bg-blue-50/70 dark:bg-blue-900/20 hover:bg-blue-50 dark:hover:bg-blue-900/30":"bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700/50 opacity-70"}`,children:[G.iconName&&c.jsx(de,{name:G.iconName,className:`w-5 h-5 mt-0.5 flex-shrink-0 ${Y?"text-blue-600 dark:text-blue-400":"text-gray-400 dark:text-gray-500"}`}),c.jsxs(W,{className:"flex-1 min-w-0",children:[c.jsx(W,{className:`text-sm truncate ${Y?"font-semibold text-gray-900 dark:text-white":"font-normal text-gray-600 dark:text-gray-400"}`,children:G.title}),c.jsx(W,{className:`text-sm mt-1 line-clamp-2 ${Y?"text-gray-700 dark:text-gray-300":"text-gray-500 dark:text-gray-500"}`,children:G.message}),c.jsx(W,{className:"text-gray-400 dark:text-gray-500 text-xs mt-1 font-mono",children:G.time})]}),c.jsxs(W,{className:"flex flex-col items-center gap-2 flex-shrink-0",children:[Y&&c.jsx(ee,{className:"w-2 h-2 bg-blue-500 dark:bg-blue-400 rounded-full mt-1.5"}),m&&c.jsx(Q,{onClick:B=>{B.stopPropagation(),m(G)},className:"p-1 text-gray-400 dark:text-gray-500 hover:text-red-600 dark:hover:text-red-400 rounded hover:bg-red-50 dark:hover:bg-red-900/20 cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity","aria-label":"Delete notification",children:c.jsx(de,{name:Je.Trash,className:"w-4 h-4"})})]})]},G.id)}),r&&c.jsx(W,{ref:N,className:"px-4 py-3 text-center",children:n?c.jsx(ee,{className:"text-sm text-gray-400 dark:text-gray-500",children:"..."}):c.jsx(ee,{className:"text-sm text-gray-400 dark:text-gray-500"})}),n&&!r&&e.length>0&&c.jsx(W,{className:"px-4 py-2 text-center",children:c.jsx(ee,{className:"text-sm text-gray-400 dark:text-gray-500",children:"..."})})]})})]})]})},nd=Object.freeze(Object.defineProperty({__proto__:null,NotificationCenter:mn,default:mn},Symbol.toStringTag,{value:"Module"})),Xe=(e,t)=>window.G7Core?.t?.(e,t)??e,pt=e=>{window.G7Core?.dispatch?.({handler:"navigate",params:{path:e}})},es=({logo:e,siteName:t="그누보드7",user:r,cartCount:n=0,notificationCount:o=0,boards:a=[],maxVisibleBoards:s=5,onMobileMenuOpen:l,availableLocales:f=[],currentLocale:h="ko",shopBase:d="/shop",className:i="",editorAttrs:u,notifications:g=[],notificationHasMore:p=!1,notificationLoading:m=!1,notificationUnreadOnly:w=!1,notificationTitleText:x,notificationEmptyText:A,notificationMarkAllReadText:v,notificationDeleteAllText:E,notificationUnreadOnlyText:O,onNotificationClose:_,onNotificationClick:I,onNotificationLoadMore:C,onNotificationMarkAllRead:y,onNotificationDeleteAll:N,onNotificationDelete:M,onNotificationUnreadOnlyToggle:P})=>{const[D,L]=k.useState(""),[U,S]=k.useState(!1),[b,$]=k.useState(!1),[F,G]=k.useState(!1),[Y,B]=k.useState({top:0,left:0}),[V,j]=k.useState(window.location.pathname),H=k.useRef(null),Z=k.useRef(null),ue=k.useRef(null),fe=window.G7Core?.useResponsive,R=fe?.(),ke=R?R.width<768:typeof window<"u"&&window.innerWidth<768;k.useEffect(()=>{const K=()=>j(window.location.pathname);window.addEventListener("popstate",K);const re=history.pushState;return history.pushState=function(...oe){re.apply(this,oe),j(window.location.pathname)},()=>{window.removeEventListener("popstate",K),history.pushState=re}},[]);const me=(K,re=!1)=>re?V===K:V===K||V.startsWith(K+"/"),Ge=()=>{const K=d==="/"?"":d;return V.startsWith(`${K}/products`)||V.startsWith(`${K}/cart`)||V.startsWith(`${K}/checkout`)||V.startsWith(`${K}/category`)},De=K=>{const re="px-3 py-2 text-sm font-medium whitespace-nowrap cursor-pointer rounded-lg transition-colors";return K?`${re} bg-gray-900 text-white dark:bg-white dark:text-gray-900`:`${re} text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-800`};k.useEffect(()=>{const K=re=>{H.current&&!H.current.contains(re.target)&&S(!1),Z.current&&!Z.current.contains(re.target)&&$(!1),ue.current&&!ue.current.contains(re.target)&&G(!1)};return document.addEventListener("mousedown",K),()=>document.removeEventListener("mousedown",K)},[]);const ye=a.slice(0,s),Me=a.slice(s),Ce=K=>{K.preventDefault(),D.trim()&&pt(`/search?q=${encodeURIComponent(D)}`)},we=async()=>{window.G7Core?.dispatch?.({handler:"logout"})},$e=K=>{window.G7Core?.dispatch?.({handler:"setLocale",target:K}),G(!1)},Le=K=>window.G7Core?.state?.get?.("_global.appConfig.localeNames")?.[K]??(K==="ko"?"한국어":K==="en"?"English":K==="ja"?"日本語":K==="zh"?"中文":K==="es"?"Español":K==="fr"?"Français":K==="de"?"Deutsch":K.toUpperCase());return c.jsxs(Zc,{...u??{},className:`sticky top-0 z-50 bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800 ${i}`,children:[c.jsx(W,{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",children:c.jsxs(W,{className:"flex items-center justify-between h-16",children:[c.jsx(Q,{onClick:()=>pt("/"),className:"flex items-center gap-2 flex-shrink-0 cursor-pointer",children:e?c.jsx(Lt,{src:e,alt:t,className:"h-8"}):c.jsx(ee,{className:"text-xl font-bold text-gray-900 dark:text-white",children:t})}),!ke&&c.jsx(so,{onSubmit:Ce,className:"flex flex-1 max-w-lg mx-8",children:c.jsxs(W,{className:"relative w-full",children:[c.jsx(xt,{type:"text",value:D,onChange:K=>L(K.target.value),placeholder:Xe("common.search_placeholder"),className:"w-full px-4 py-2 pl-10 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500"}),c.jsx(de,{name:"search",className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 dark:text-gray-500"})]})}),c.jsxs(W,{className:"flex items-center gap-2",children:[c.jsx(hn,{autoText:Xe("common.theme.auto"),lightText:Xe("common.theme.light"),darkText:Xe("common.theme.dark")}),r?.uuid&&c.jsx(mn,{notifications:g,unreadCount:o,hasMore:p,loading:m,unreadOnly:w,titleText:x??Xe("mypage.notifications.title"),emptyText:A??Xe("mypage.notifications.empty"),markAllReadText:v??Xe("mypage.notifications.mark_all_read"),deleteAllText:E??Xe("mypage.notifications.delete_all"),unreadOnlyText:O??Xe("mypage.notifications.unread_only"),onClose:_,onNotificationClick:I,onLoadMore:C,onMarkAllRead:y,onDeleteAll:N,onDelete:M,onUnreadOnlyToggle:P,dropdownAlign:"right"}),c.jsxs(Q,{onClick:()=>pt(`${d}/cart`),className:"relative p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white cursor-pointer",children:[c.jsx(de,{name:"shopping-cart",className:"w-5 h-5"}),n>0&&c.jsx(ee,{className:"absolute -top-1 -right-1 w-5 h-5 flex items-center justify-center text-xs bg-blue-500 text-white rounded-full",children:n>99?"99+":n})]}),f&&f.length>1&&c.jsxs(W,{ref:ue,className:"relative",children:[c.jsxs(Q,{onClick:()=>G(!F),className:"flex items-center gap-1.5 px-2.5 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg cursor-pointer transition-colors","aria-haspopup":"listbox","aria-expanded":F,"aria-label":Xe("common.language"),children:[c.jsx(de,{name:"globe",className:"w-4 h-4"}),c.jsx(ee,{className:"font-medium uppercase",children:h}),c.jsx(de,{name:"chevron-down",className:"w-3 h-3"})]}),F&&c.jsx(W,{role:"listbox",className:"absolute right-0 mt-2 w-44 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg py-1 z-50 overflow-hidden",children:f.map(K=>{const re=K===h;return c.jsxs(Q,{role:"option","aria-selected":re,onClick:()=>$e(K),className:`w-full px-4 py-2.5 text-left text-sm flex items-center gap-3 cursor-pointer transition-colors ${re?"bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"}`,children:[c.jsx(de,{name:"globe",className:"w-4 h-4"}),c.jsx(ee,{className:"flex-1 font-medium",children:Le(K)}),re&&c.jsx(de,{name:"check",className:"w-4 h-4"})]},K)})})]}),c.jsx(pn,{slotId:"header_currency",id:"header_currency_slot_desktop",className:"flex items-center"}),r?.uuid?c.jsxs(W,{ref:H,className:"relative",children:[c.jsxs(Q,{onClick:()=>S(!U),className:"flex items-center gap-2 p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white",children:[c.jsx(Ur,{avatar:r.avatar,name:r.name,size:"sm"}),c.jsx(ee,{className:"hidden sm:inline text-sm font-medium",children:r.name}),c.jsx(de,{name:"chevron-down",className:"w-4 h-4"})]}),U&&c.jsxs(W,{className:"absolute right-0 mt-2 w-56 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg py-1 z-50",children:[c.jsx(W,{className:"px-4 py-3 border-b border-gray-200 dark:border-gray-700",children:c.jsxs(W,{className:"flex items-center gap-3",children:[c.jsx(Ur,{avatar:r.avatar,name:r.name,size:"md"}),c.jsxs(W,{children:[c.jsx(W,{className:"text-sm font-medium text-gray-900 dark:text-white",children:r.name}),c.jsx(W,{className:"text-xs text-gray-500 dark:text-gray-400",children:Xe("common.member")})]})]})}),c.jsxs(W,{className:"py-1",children:[r.is_admin&&c.jsxs(c.Fragment,{children:[c.jsxs(ao,{href:"/admin",className:"block w-full text-left px-4 py-2 text-sm text-blue-600 dark:text-blue-400 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer font-medium",children:[c.jsx(de,{name:"settings",className:"inline w-4 h-4 mr-2"}),Xe("common.admin_menu")]}),c.jsx(lo,{className:"my-1 border-gray-200 dark:border-gray-700"})]}),c.jsxs(Q,{onClick:()=>{pt("/mypage"),S(!1)},className:"block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer",children:[c.jsx(de,{name:"user",className:"inline w-4 h-4 mr-2"}),Xe("common.mypage")]}),c.jsxs(Q,{onClick:()=>{pt("/mypage/orders"),S(!1)},className:"block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer",children:[c.jsx(de,{name:"shopping-bag",className:"inline w-4 h-4 mr-2"}),Xe("mypage.tabs.orders")]}),c.jsxs(Q,{onClick:()=>{pt("/mypage/wishlist"),S(!1)},className:"block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer",children:[c.jsx(de,{name:"heart",className:"inline w-4 h-4 mr-2"}),Xe("mypage.tabs.wishlist")]})]}),c.jsx(lo,{className:"my-1 border-gray-200 dark:border-gray-700"}),c.jsxs(Q,{onClick:we,className:"block w-full text-left px-4 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer",children:[c.jsx(de,{name:"log-out",className:"inline w-4 h-4 mr-2"}),Xe("auth.logout")]})]})]}):c.jsxs(W,{className:"flex items-center gap-1.5",children:[c.jsx(Q,{onClick:()=>pt("/login?redirect=/mypage/orders"),className:"px-2.5 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white cursor-pointer",children:Xe("shop.guest_order_form.nav_link")}),c.jsx(Q,{onClick:()=>pt("/login"),className:"px-2.5 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white cursor-pointer",children:Xe("auth.login")}),c.jsx(Q,{onClick:()=>pt("/register"),className:"ml-1 px-3 py-2 text-sm font-medium text-white bg-emerald-500 rounded-lg hover:bg-emerald-600 cursor-pointer",children:Xe("auth.register_link")})]}),ke&&c.jsx(Q,{onClick:l,className:"p-2 text-gray-600 dark:text-gray-400",children:c.jsx(de,{name:"menu",className:"w-6 h-6"})})]})]})}),!ke&&c.jsx($r,{className:"border-t border-gray-200 dark:border-gray-800",children:c.jsx(W,{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",children:c.jsxs(W,{className:"flex items-center gap-1 h-12 overflow-x-auto",children:[c.jsx(Q,{onClick:()=>pt("/"),className:De(me("/",!0)),"data-testid":"nav-home",children:Xe("nav.home")}),c.jsxs(Q,{onClick:()=>pt("/boards/popular"),className:`flex items-center gap-1 ${De(me("/boards/popular"))}`,"data-testid":"nav-popular",children:[c.jsx(ee,{className:"text-orange-500",children:"🔥"}),Xe("nav.popular")]}),c.jsxs(Q,{onClick:()=>pt(`${d==="/"?"":d}/products`),className:`flex items-center gap-1 ${De(Ge())}`,"data-testid":"nav-shop",children:[c.jsx(ee,{children:"🛒"}),Xe("nav.shop")]}),ye.map(K=>c.jsxs(Q,{onClick:()=>pt(`/board/${K.slug}`),className:De(me(`/board/${K.slug}`)),children:[K.icon&&c.jsx(ee,{className:"mr-1",children:K.icon}),K.name]},K.id)),Me.length>0&&c.jsxs(W,{ref:Z,className:"relative",children:[c.jsxs(Q,{onClick:()=>{if(!b&&Z.current){const K=Z.current.getBoundingClientRect();B({top:K.bottom+4,left:K.left})}$(!b)},className:"flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white",children:[Xe("nav.more"),c.jsx(de,{name:"chevron-down",className:"w-4 h-4"})]}),b&&c.jsx(W,{className:"fixed w-48 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg py-1 z-50",style:{top:`${Y.top}px`,left:`${Y.left}px`},children:Me.map(K=>{const re=me(`/board/${K.slug}`);return c.jsxs(Q,{onClick:()=>{pt(`/board/${K.slug}`),$(!1)},className:`block w-full text-left px-4 py-2 text-sm cursor-pointer ${re?"bg-gray-900 text-white dark:bg-white dark:text-gray-900":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"}`,children:[K.icon&&c.jsx(ee,{className:"mr-1",children:K.icon}),K.name]},K.id)})})]})]})})})]})},od=Object.freeze(Object.defineProperty({__proto__:null,default:es},Symbol.toStringTag,{value:"Module"})),ad=k.forwardRef(({children:e,className:t="",...r},n)=>c.jsx("footer",{ref:n,className:t,...r,children:e})),kt=(e,t)=>window.G7Core?.t?.(e,t)??e,sd=768,ts=1024,ld=e=>{window.G7Core?.dispatch?.({handler:"navigate",params:{path:e}})},rs=({siteName:e="그누보드7",siteDescription:t,copyrightText:r,socialLinks:n={},linkGroups:o,className:a="",editorAttrs:s})=>{const l=new Date().getFullYear(),h=window.G7Core?.useResponsive,i=h?.()?.width??(typeof window<"u"?window.innerWidth:ts),u=i=ts,p=u?1:g?5:2,m=[{title:kt("footer.community"),links:[{label:kt("nav.home"),href:"/"},{label:kt("nav.popular"),href:"/boards/popular"},{label:kt("footer.all_boards"),href:"/boards"}]},{title:kt("footer.info"),links:[{label:kt("footer.about"),href:"/page/about"},{label:kt("footer.faq"),href:"/page/faq"},{label:kt("footer.contact"),href:"/page/contact"}]},{title:kt("footer.policy"),links:[{label:kt("footer.terms"),href:"/page/terms"},{label:kt("footer.privacy"),href:"/page/privacy"},{label:kt("footer.refund"),href:"/page/refund"}]}],w=o||m,x={github:"github",twitter:"twitter",discord:"discord",facebook:"facebook",instagram:"instagram"};return c.jsx(ad,{...s??{},className:`bg-gray-50 dark:bg-gray-900 border-t border-gray-200 dark:border-gray-800 ${a}`,children:c.jsxs(W,{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12",children:[c.jsxs(W,{className:"grid gap-8",style:{gridTemplateColumns:`repeat(${p}, minmax(0, 1fr))`},children:[c.jsxs(W,{style:g?{gridColumn:"span 2 / span 2"}:void 0,children:[c.jsx(gn,{className:"text-lg font-bold text-gray-900 dark:text-white",children:e}),t&&c.jsx(Dt,{className:"mt-2 text-sm text-gray-600 dark:text-gray-400",children:t}),c.jsx(W,{className:"mt-4 flex items-center gap-4",children:Object.entries(n).map(([A,v])=>v?c.jsx(ao,{href:v,target:"_blank",rel:"noopener noreferrer",className:"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200","aria-label":A,children:c.jsx(de,{name:x[A],className:"w-5 h-5"})},A):null)})]}),w.map((A,v)=>c.jsxs(W,{children:[c.jsx(Ya,{className:"text-sm font-semibold text-gray-900 dark:text-white uppercase tracking-wider",children:A.title}),c.jsx(oo,{className:"mt-4 space-y-2",children:A.links.map((E,O)=>c.jsx(Xt,{children:c.jsx(Q,{onClick:()=>ld(E.href),className:"text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white cursor-pointer",children:E.label})},O))})]},v))]}),c.jsxs(W,{className:"mt-8 pt-8 border-t border-gray-200 dark:border-gray-800 flex justify-between items-center gap-4",style:{flexDirection:u?"column":"row"},children:[c.jsx(Dt,{className:"text-sm text-gray-500 dark:text-gray-400",children:r||`© ${l} ${e}. All rights reserved.`}),c.jsx(Dt,{className:"text-sm text-gray-500 dark:text-gray-400",children:kt("footer.powered_by")})]})]})})},id=Object.freeze(Object.defineProperty({__proto__:null,default:rs},Symbol.toStringTag,{value:"Module"})),Pt=(e,t)=>window.G7Core?.t?.(e,t)??e,Tt=e=>{window.G7Core?.dispatch?.({handler:"navigate",params:{path:e}})},ns=({isOpen:e,onClose:t,logo:r,siteName:n="그누보드7",user:o,boards:a=[],cartCount:s=0})=>{const l=k.useRef(null),h=window.G7Core?.useResponsive,d=h?.(),i=d?d.width<1024:typeof window<"u"&&window.innerWidth<1024;k.useEffect(()=>{const g=p=>{p.key==="Escape"&&t()};return e&&(document.addEventListener("keydown",g),document.body.style.overflow="hidden"),()=>{document.removeEventListener("keydown",g),document.body.style.overflow=""}},[e,t]);const u=g=>{g.target===g.currentTarget&&t()};return!e||!i?null:c.jsxs(W,{className:"fixed inset-0 z-50",onClick:u,children:[c.jsx(W,{className:"fixed inset-0 bg-black/50 transition-opacity"}),c.jsxs(W,{ref:l,className:`fixed inset-y-0 left-0 w-80 max-w-[85vw] bg-white dark:bg-gray-900 shadow-xl transform transition-transform duration-300 ${e?"translate-x-0":"-translate-x-full"}`,children:[c.jsxs(W,{className:"flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-800",children:[c.jsx(Q,{onClick:()=>{t(),Tt("/")},className:"flex items-center gap-2 cursor-pointer",children:r?c.jsx(Lt,{src:r,alt:n,className:"h-8"}):c.jsx(ee,{className:"text-xl font-bold text-gray-900 dark:text-white",children:n})}),c.jsx(Q,{onClick:t,className:"p-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200","aria-label":"메뉴 닫기",children:c.jsx(de,{name:"x",className:"w-6 h-6"})})]}),o?c.jsx(W,{className:"p-4 border-b border-gray-200 dark:border-gray-800",children:c.jsxs(W,{className:"flex items-center gap-3",children:[o.avatar?c.jsx(Lt,{src:o.avatar,alt:o.name,className:"w-12 h-12 rounded-full"}):c.jsx(W,{className:"w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center text-white text-lg font-medium",children:(o.name||"U").charAt(0).toUpperCase()}),c.jsxs(W,{children:[c.jsx(Dt,{className:"font-medium text-gray-900 dark:text-white",children:o.name}),c.jsx(Q,{onClick:()=>{t(),Tt("/mypage")},className:"text-sm text-blue-600 dark:text-blue-400 hover:underline cursor-pointer",children:Pt("common.mypage")})]})]})}):c.jsx(W,{className:"p-4 border-b border-gray-200 dark:border-gray-800",children:c.jsxs(W,{className:"flex gap-2",children:[c.jsx(Q,{onClick:()=>{t(),Tt("/login")},className:"flex-1 py-2 text-center text-sm font-medium text-white bg-gray-900 dark:bg-white dark:text-gray-900 rounded-lg cursor-pointer",children:Pt("auth.login")}),c.jsx(Q,{onClick:()=>{t(),Tt("/register")},className:"flex-1 py-2 text-center text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg cursor-pointer",children:Pt("auth.register")})]})}),c.jsx($r,{className:"p-4 overflow-y-auto max-h-[calc(100vh-200px)]",children:c.jsxs(oo,{className:"space-y-1",children:[c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt("/")},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[c.jsx(de,{name:"home",className:"w-5 h-5"}),Pt("nav.home")]})}),c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt("/popular")},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[c.jsx(ee,{className:"text-orange-500",children:"🔥"}),Pt("nav.popular")]})}),c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt("/shop")},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[c.jsx(ee,{children:"🛒"}),Pt("nav.shop")]})}),c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt("/cart")},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[c.jsx(de,{name:"shopping-cart",className:"w-5 h-5"}),Pt("nav.cart"),s>0&&c.jsx(ee,{className:"ml-auto px-2 py-0.5 text-xs bg-blue-500 text-white rounded-full",children:s})]})}),c.jsx(Xt,{className:"my-4 border-t border-gray-200 dark:border-gray-800"}),c.jsx(Xt,{className:"px-3 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider",children:Pt("nav.boards")}),a.map(g=>c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt(`/board/${g.slug}`)},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[g.icon&&c.jsx(ee,{children:g.icon}),g.name]})},g.id))]})}),c.jsx(W,{className:"absolute bottom-0 left-0 right-0 p-4 border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900",children:c.jsxs(W,{className:"flex items-center justify-between text-sm text-gray-500 dark:text-gray-400",children:[c.jsx(Q,{onClick:()=>{t(),Tt("/about")},className:"hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer",children:Pt("footer.about")}),c.jsx(Q,{onClick:()=>{t(),Tt("/terms")},className:"hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer",children:Pt("footer.terms")}),c.jsx(Q,{onClick:()=>{t(),Tt("/privacy")},className:"hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer",children:Pt("footer.privacy")})]})})]})]})},cd=Object.freeze(Object.defineProperty({__proto__:null,default:ns},Symbol.toStringTag,{value:"Module"}));const{entries:os,setPrototypeOf:as,isFrozen:dd,getPrototypeOf:ud,getOwnPropertyDescriptor:fd}=Object;let{freeze:ft,seal:Nt,create:uo}=Object,{apply:fo,construct:go}=typeof Reflect<"u"&&Reflect;ft||(ft=function(t){return t}),Nt||(Nt=function(t){return t}),fo||(fo=function(t,r){for(var n=arguments.length,o=new Array(n>2?n-2:0),a=2;a1?r-1:0),o=1;o1?r-1:0),o=1;o2&&arguments[2]!==void 0?arguments[2]:yn;as&&as(e,null);let n=t.length;for(;n--;){let o=t[n];if(typeof o=="string"){const a=r(o);a!==o&&(dd(t)||(t[n]=a),o=a)}e[o]=!0}return e}function yd(e){for(let t=0;t/gm),Cd=Nt(/\$\{[\w\W]*/gm),Sd=Nt(/^data-[\-\w.\u00B7-\uFFFF]+$/),_d=Nt(/^aria-[\-\w]+$/),us=Nt(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Ed=Nt(/^(?:\w+script|data):/i),Td=Nt(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),fs=Nt(/^html$/i),Nd=Nt(/^[a-z][.\w]*(-[.\w]+)+$/i);var gs=Object.freeze({__proto__:null,ARIA_ATTR:_d,ATTR_WHITESPACE:Td,CUSTOM_ELEMENT:Nd,DATA_ATTR:Sd,DOCTYPE_NAME:fs,ERB_EXPR:kd,IS_ALLOWED_URI:us,IS_SCRIPT_OR_DATA:Ed,MUSTACHE_EXPR:xd,TMPLIT_EXPR:Cd});const Br={element:1,text:3,progressingInstruction:7,comment:8,document:9},Ad=function(){return typeof window>"u"?null:window},Md=function(t,r){if(typeof t!="object"||typeof t.createPolicy!="function")return null;let n=null;const o="data-tt-policy-suffix";r&&r.hasAttribute(o)&&(n=r.getAttribute(o));const a="dompurify"+(n?"#"+n:"");try{return t.createPolicy(a,{createHTML(s){return s},createScriptURL(s){return s}})}catch{return console.warn("TrustedTypes policy "+a+" could not be created."),null}},hs=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}};function ps(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Ad();const t=ge=>ps(ge);if(t.version="3.3.1",t.removed=[],!e||!e.document||e.document.nodeType!==Br.document||!e.Element)return t.isSupported=!1,t;let{document:r}=e;const n=r,o=n.currentScript,{DocumentFragment:a,HTMLTemplateElement:s,Node:l,Element:f,NodeFilter:h,NamedNodeMap:d=e.NamedNodeMap||e.MozNamedAttrMap,HTMLFormElement:i,DOMParser:u,trustedTypes:g}=e,p=f.prototype,m=jr(p,"cloneNode"),w=jr(p,"remove"),x=jr(p,"nextSibling"),A=jr(p,"childNodes"),v=jr(p,"parentNode");if(typeof s=="function"){const ge=r.createElement("template");ge.content&&ge.content.ownerDocument&&(r=ge.content.ownerDocument)}let E,O="";const{implementation:_,createNodeIterator:I,createDocumentFragment:C,getElementsByTagName:y}=r,{importNode:N}=n;let M=hs();t.isSupported=typeof os=="function"&&typeof v=="function"&&_&&_.createHTMLDocument!==void 0;const{MUSTACHE_EXPR:P,ERB_EXPR:D,TMPLIT_EXPR:L,DATA_ATTR:U,ARIA_ATTR:S,IS_SCRIPT_OR_DATA:b,ATTR_WHITESPACE:$,CUSTOM_ELEMENT:F}=gs;let{IS_ALLOWED_URI:G}=gs,Y=null;const B=Ae({},[...ls,...mo,...bo,...yo,...is]);let V=null;const j=Ae({},[...cs,...vo,...ds,...vn]);let H=Object.seal(uo(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),Z=null,ue=null;const te=Object.seal(uo(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let fe=!0,R=!0,ke=!1,me=!0,Ge=!1,De=!0,ye=!1,Me=!1,Ce=!1,we=!1,$e=!1,Le=!1,K=!0,re=!1;const oe="user-content-";let ae=!0,be=!1,xe={},He=null;const Pe=Ae({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Ke=null;const Oe=Ae({},["audio","video","img","source","image","track"]);let X=null;const se=Ae({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),ie="http://www.w3.org/1998/Math/MathML",le="http://www.w3.org/2000/svg",ne="http://www.w3.org/1999/xhtml";let Te=ne,ve=!1,Se=null;const _e=Ae({},[ie,le,ne],ho);let Ue=Ae({},["mi","mo","mn","ms","mtext"]),je=Ae({},["annotation-xml"]);const Ee=Ae({},["title","style","font","a","script"]);let he=null;const Ne=["application/xhtml+xml","text/html"],Ve="text/html";let Fe=null,Be=null;const qe=r.createElement("form"),Zt=function(z){return z instanceof RegExp||z instanceof Function},Ze=function(){let z=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(!(Be&&Be===z)){if((!z||typeof z!="object")&&(z={}),z=Kt(z),he=Ne.indexOf(z.PARSER_MEDIA_TYPE)===-1?Ve:z.PARSER_MEDIA_TYPE,Fe=he==="application/xhtml+xml"?ho:yn,Y=Ft(z,"ALLOWED_TAGS")?Ae({},z.ALLOWED_TAGS,Fe):B,V=Ft(z,"ALLOWED_ATTR")?Ae({},z.ALLOWED_ATTR,Fe):j,Se=Ft(z,"ALLOWED_NAMESPACES")?Ae({},z.ALLOWED_NAMESPACES,ho):_e,X=Ft(z,"ADD_URI_SAFE_ATTR")?Ae(Kt(se),z.ADD_URI_SAFE_ATTR,Fe):se,Ke=Ft(z,"ADD_DATA_URI_TAGS")?Ae(Kt(Oe),z.ADD_DATA_URI_TAGS,Fe):Oe,He=Ft(z,"FORBID_CONTENTS")?Ae({},z.FORBID_CONTENTS,Fe):Pe,Z=Ft(z,"FORBID_TAGS")?Ae({},z.FORBID_TAGS,Fe):Kt({}),ue=Ft(z,"FORBID_ATTR")?Ae({},z.FORBID_ATTR,Fe):Kt({}),xe=Ft(z,"USE_PROFILES")?z.USE_PROFILES:!1,fe=z.ALLOW_ARIA_ATTR!==!1,R=z.ALLOW_DATA_ATTR!==!1,ke=z.ALLOW_UNKNOWN_PROTOCOLS||!1,me=z.ALLOW_SELF_CLOSE_IN_ATTR!==!1,Ge=z.SAFE_FOR_TEMPLATES||!1,De=z.SAFE_FOR_XML!==!1,ye=z.WHOLE_DOCUMENT||!1,we=z.RETURN_DOM||!1,$e=z.RETURN_DOM_FRAGMENT||!1,Le=z.RETURN_TRUSTED_TYPE||!1,Ce=z.FORCE_BODY||!1,K=z.SANITIZE_DOM!==!1,re=z.SANITIZE_NAMED_PROPS||!1,ae=z.KEEP_CONTENT!==!1,be=z.IN_PLACE||!1,G=z.ALLOWED_URI_REGEXP||us,Te=z.NAMESPACE||ne,Ue=z.MATHML_TEXT_INTEGRATION_POINTS||Ue,je=z.HTML_INTEGRATION_POINTS||je,H=z.CUSTOM_ELEMENT_HANDLING||{},z.CUSTOM_ELEMENT_HANDLING&&Zt(z.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(H.tagNameCheck=z.CUSTOM_ELEMENT_HANDLING.tagNameCheck),z.CUSTOM_ELEMENT_HANDLING&&Zt(z.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(H.attributeNameCheck=z.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),z.CUSTOM_ELEMENT_HANDLING&&typeof z.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=="boolean"&&(H.allowCustomizedBuiltInElements=z.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Ge&&(R=!1),$e&&(we=!0),xe&&(Y=Ae({},is),V=[],xe.html===!0&&(Ae(Y,ls),Ae(V,cs)),xe.svg===!0&&(Ae(Y,mo),Ae(V,vo),Ae(V,vn)),xe.svgFilters===!0&&(Ae(Y,bo),Ae(V,vo),Ae(V,vn)),xe.mathMl===!0&&(Ae(Y,yo),Ae(V,ds),Ae(V,vn))),z.ADD_TAGS&&(typeof z.ADD_TAGS=="function"?te.tagCheck=z.ADD_TAGS:(Y===B&&(Y=Kt(Y)),Ae(Y,z.ADD_TAGS,Fe))),z.ADD_ATTR&&(typeof z.ADD_ATTR=="function"?te.attributeCheck=z.ADD_ATTR:(V===j&&(V=Kt(V)),Ae(V,z.ADD_ATTR,Fe))),z.ADD_URI_SAFE_ATTR&&Ae(X,z.ADD_URI_SAFE_ATTR,Fe),z.FORBID_CONTENTS&&(He===Pe&&(He=Kt(He)),Ae(He,z.FORBID_CONTENTS,Fe)),z.ADD_FORBID_CONTENTS&&(He===Pe&&(He=Kt(He)),Ae(He,z.ADD_FORBID_CONTENTS,Fe)),ae&&(Y["#text"]=!0),ye&&Ae(Y,["html","head","body"]),Y.table&&(Ae(Y,["tbody"]),delete Z.tbody),z.TRUSTED_TYPES_POLICY){if(typeof z.TRUSTED_TYPES_POLICY.createHTML!="function")throw Gr('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if(typeof z.TRUSTED_TYPES_POLICY.createScriptURL!="function")throw Gr('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');E=z.TRUSTED_TYPES_POLICY,O=E.createHTML("")}else E===void 0&&(E=Md(g,o)),E!==null&&typeof O=="string"&&(O=E.createHTML(""));ft&&ft(z),Be=z}},jt=Ae({},[...mo,...bo,...vd]),_t=Ae({},[...yo,...wd]),Bt=function(z){let q=v(z);(!q||!q.tagName)&&(q={namespaceURI:Te,tagName:"template"});const ce=yn(z.tagName),Ye=yn(q.tagName);return Se[z.namespaceURI]?z.namespaceURI===le?q.namespaceURI===ne?ce==="svg":q.namespaceURI===ie?ce==="svg"&&(Ye==="annotation-xml"||Ue[Ye]):!!jt[ce]:z.namespaceURI===ie?q.namespaceURI===ne?ce==="math":q.namespaceURI===le?ce==="math"&&je[Ye]:!!_t[ce]:z.namespaceURI===ne?q.namespaceURI===le&&!je[Ye]||q.namespaceURI===ie&&!Ue[Ye]?!1:!_t[ce]&&(Ee[ce]||!jt[ce]):!!(he==="application/xhtml+xml"&&Se[z.namespaceURI]):!1},dt=function(z){zr(t.removed,{element:z});try{v(z).removeChild(z)}catch{w(z)}},Et=function(z,q){try{zr(t.removed,{attribute:q.getAttributeNode(z),from:q})}catch{zr(t.removed,{attribute:null,from:q})}if(q.removeAttribute(z),z==="is")if(we||$e)try{dt(q)}catch{}else try{q.setAttribute(z,"")}catch{}},Wt=function(z){let q=null,ce=null;if(Ce)z=""+z;else{const Qe=po(z,/^[\r\n\t ]+/);ce=Qe&&Qe[0]}he==="application/xhtml+xml"&&Te===ne&&(z=''+z+"");const Ye=E?E.createHTML(z):z;if(Te===ne)try{q=new u().parseFromString(Ye,he)}catch{}if(!q||!q.documentElement){q=_.createDocument(Te,"template",null);try{q.documentElement.innerHTML=ve?O:Ye}catch{}}const ut=q.body||q.documentElement;return z&&ce&&ut.insertBefore(r.createTextNode(ce),ut.childNodes[0]||null),Te===ne?y.call(q,ye?"html":"body")[0]:ye?q.documentElement:ut},nr=function(z){return I.call(z.ownerDocument||z,z,h.SHOW_ELEMENT|h.SHOW_COMMENT|h.SHOW_TEXT|h.SHOW_PROCESSING_INSTRUCTION|h.SHOW_CDATA_SECTION,null)},mr=function(z){return z instanceof i&&(typeof z.nodeName!="string"||typeof z.textContent!="string"||typeof z.removeChild!="function"||!(z.attributes instanceof d)||typeof z.removeAttribute!="function"||typeof z.setAttribute!="function"||typeof z.namespaceURI!="string"||typeof z.insertBefore!="function"||typeof z.hasChildNodes!="function")},_c=function(z){return typeof l=="function"&&z instanceof l};function qt(ge,z,q){bn(ge,ce=>{ce.call(t,z,q,Be)})}const Ec=function(z){let q=null;if(qt(M.beforeSanitizeElements,z,null),mr(z))return dt(z),!0;const ce=Fe(z.nodeName);if(qt(M.uponSanitizeElement,z,{tagName:ce,allowedTags:Y}),De&&z.hasChildNodes()&&!_c(z.firstElementChild)&>(/<[/\w!]/g,z.innerHTML)&>(/<[/\w!]/g,z.textContent)||z.nodeType===Br.progressingInstruction||De&&z.nodeType===Br.comment&>(/<[/\w]/g,z.data))return dt(z),!0;if(!(te.tagCheck instanceof Function&&te.tagCheck(ce))&&(!Y[ce]||Z[ce])){if(!Z[ce]&&Nc(ce)&&(H.tagNameCheck instanceof RegExp&>(H.tagNameCheck,ce)||H.tagNameCheck instanceof Function&&H.tagNameCheck(ce)))return!1;if(ae&&!He[ce]){const Ye=v(z)||z.parentNode,ut=A(z)||z.childNodes;if(ut&&Ye){const Qe=ut.length;for(let wt=Qe-1;wt>=0;--wt){const Qt=m(ut[wt],!0);Qt.__removalCount=(z.__removalCount||0)+1,Ye.insertBefore(Qt,x(z))}}}return dt(z),!0}return z instanceof f&&!Bt(z)||(ce==="noscript"||ce==="noembed"||ce==="noframes")&>(/<\/no(script|embed|frames)/i,z.innerHTML)?(dt(z),!0):(Ge&&z.nodeType===Br.text&&(q=z.textContent,bn([P,D,L],Ye=>{q=Hr(q,Ye," ")}),z.textContent!==q&&(zr(t.removed,{element:z.cloneNode()}),z.textContent=q)),qt(M.afterSanitizeElements,z,null),!1)},Tc=function(z,q,ce){if(K&&(q==="id"||q==="name")&&(ce in r||ce in qe))return!1;if(!(R&&!ue[q]&>(U,q))){if(!(fe&>(S,q))){if(!(te.attributeCheck instanceof Function&&te.attributeCheck(q,z))){if(!V[q]||ue[q]){if(!(Nc(z)&&(H.tagNameCheck instanceof RegExp&>(H.tagNameCheck,z)||H.tagNameCheck instanceof Function&&H.tagNameCheck(z))&&(H.attributeNameCheck instanceof RegExp&>(H.attributeNameCheck,q)||H.attributeNameCheck instanceof Function&&H.attributeNameCheck(q,z))||q==="is"&&H.allowCustomizedBuiltInElements&&(H.tagNameCheck instanceof RegExp&>(H.tagNameCheck,ce)||H.tagNameCheck instanceof Function&&H.tagNameCheck(ce))))return!1}else if(!X[q]){if(!gt(G,Hr(ce,$,""))){if(!((q==="src"||q==="xlink:href"||q==="href")&&z!=="script"&&pd(ce,"data:")===0&&Ke[z])){if(!(ke&&!gt(b,Hr(ce,$,"")))){if(ce)return!1}}}}}}}return!0},Nc=function(z){return z!=="annotation-xml"&&po(z,F)},Ac=function(z){qt(M.beforeSanitizeAttributes,z,null);const{attributes:q}=z;if(!q||mr(z))return;const ce={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:V,forceKeepAttr:void 0};let Ye=q.length;for(;Ye--;){const ut=q[Ye],{name:Qe,namespaceURI:wt,value:Qt}=ut,Fr=Fe(Qe),ja=Qt;let st=Qe==="value"?ja:md(ja);if(ce.attrName=Fr,ce.attrValue=st,ce.keepAttr=!0,ce.forceKeepAttr=void 0,qt(M.uponSanitizeAttribute,z,ce),st=ce.attrValue,re&&(Fr==="id"||Fr==="name")&&(Et(Qe,z),st=oe+st),De&>(/((--!?|])>)|<\/(style|title|textarea)/i,st)){Et(Qe,z);continue}if(Fr==="attributename"&&po(st,"href")){Et(Qe,z);continue}if(ce.forceKeepAttr)continue;if(!ce.keepAttr){Et(Qe,z);continue}if(!me&>(/\/>/i,st)){Et(Qe,z);continue}Ge&&bn([P,D,L],Oc=>{st=Hr(st,Oc," ")});const Mc=Fe(z.nodeName);if(!Tc(Mc,Fr,st)){Et(Qe,z);continue}if(E&&typeof g=="object"&&typeof g.getAttributeType=="function"&&!wt)switch(g.getAttributeType(Mc,Fr)){case"TrustedHTML":{st=E.createHTML(st);break}case"TrustedScriptURL":{st=E.createScriptURL(st);break}}if(st!==ja)try{wt?z.setAttributeNS(wt,Qe,st):z.setAttribute(Qe,st),mr(z)?dt(z):ss(t.removed)}catch{Et(Qe,z)}}qt(M.afterSanitizeAttributes,z,null)},Gp=function ge(z){let q=null;const ce=nr(z);for(qt(M.beforeSanitizeShadowDOM,z,null);q=ce.nextNode();)qt(M.uponSanitizeShadowNode,q,null),Ec(q),Ac(q),q.content instanceof a&&ge(q.content);qt(M.afterSanitizeShadowDOM,z,null)};return t.sanitize=function(ge){let z=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},q=null,ce=null,Ye=null,ut=null;if(ve=!ge,ve&&(ge=""),typeof ge!="string"&&!_c(ge))if(typeof ge.toString=="function"){if(ge=ge.toString(),typeof ge!="string")throw Gr("dirty is not a string, aborting")}else throw Gr("toString is not a function");if(!t.isSupported)return ge;if(Me||Ze(z),t.removed=[],typeof ge=="string"&&(be=!1),be){if(ge.nodeName){const Qt=Fe(ge.nodeName);if(!Y[Qt]||Z[Qt])throw Gr("root node is forbidden and cannot be sanitized in-place")}}else if(ge instanceof l)q=Wt(""),ce=q.ownerDocument.importNode(ge,!0),ce.nodeType===Br.element&&ce.nodeName==="BODY"||ce.nodeName==="HTML"?q=ce:q.appendChild(ce);else{if(!we&&!Ge&&!ye&&ge.indexOf("<")===-1)return E&&Le?E.createHTML(ge):ge;if(q=Wt(ge),!q)return we?null:Le?O:""}q&&Ce&&dt(q.firstChild);const Qe=nr(be?ge:q);for(;Ye=Qe.nextNode();)Ec(Ye),Ac(Ye),Ye.content instanceof a&&Gp(Ye.content);if(be)return ge;if(we){if($e)for(ut=C.call(q.ownerDocument);q.firstChild;)ut.appendChild(q.firstChild);else ut=q;return(V.shadowroot||V.shadowrootmode)&&(ut=N.call(n,ut,!0)),ut}let wt=ye?q.outerHTML:q.innerHTML;return ye&&Y["!doctype"]&&q.ownerDocument&&q.ownerDocument.doctype&&q.ownerDocument.doctype.name&>(fs,q.ownerDocument.doctype.name)&&(wt=" -`+wt),Ge&&bn([P,D,L],Qt=>{wt=Hr(wt,Qt," ")}),E&&Le?E.createHTML(wt):wt},t.setConfig=function(){let ge=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};Ze(ge),Me=!0},t.clearConfig=function(){Be=null,Me=!1},t.isValidAttribute=function(ge,z,q){Be||Ze({});const ce=Fe(ge),Ye=Fe(z);return Tc(ce,Ye,q)},t.addHook=function(ge,z){typeof z=="function"&&zr(M[ge],z)},t.removeHook=function(ge,z){if(z!==void 0){const q=gd(M[ge],z);return q===-1?void 0:hd(M[ge],q,1)[0]}return ss(M[ge])},t.removeHooks=function(ge){M[ge]=[]},t.removeAllHooks=function(){M=hs()},t}var wo=ps();const Od=()=>{const e=()=>{const n=window.G7Core?.state?.get?.();return n&&n.preferredCurrency||"KRW"},[t,r]=k.useState(e);return k.useEffect(()=>{const n=window.G7Core?.state?.subscribe;if(r(e()),typeof n!="function")return;const o=n(a=>{r(a&&a.preferredCurrency||"KRW")});return typeof o=="function"?o:void 0},[]),t},Id=e=>{window.G7Core?.dispatch?.({handler:"navigate",params:{path:e}})},Dd=e=>{const t=Math.round(e*2)/2;return[1,2,3,4,5].map(r=>t>=r?"full":t>=r-.5?"half":"empty")},ms=({product:e,onClick:t,shopBase:r="/shop",className:n="",id:o,editorAttrs:a})=>{const s=Od(),l=A=>{const v=`multi_currency_${A}`,E=e[v];if(E&&E[s])return E[s].formatted;const O=`${A}_formatted`;return e[O]},f=e.name_localized??(typeof e.name=="string"?e.name:"")??"",h=l("selling_price"),d=l("list_price"),i=e.discount_rate&&e.discount_rate>0,u=e.sales_status&&e.sales_status!=="on_sale",g=e.labels??[],p=A=>wo.sanitize(A,{ALLOWED_TAGS:["mark"],ALLOWED_ATTR:[]}),m=e.name_highlighted,w=e.description_highlighted??e.short_description,x=()=>{if(t)t(e.id);else{const A=r==="/"?"":r,v=e.product_code??e.id;Id(`${A}/products/${v}`)}};return c.jsxs(Q,{onClick:x,className:`block w-full text-left group bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden hover:shadow-lg transition-shadow cursor-pointer ${n}`,id:o,...a,children:[c.jsxs(W,{className:"relative aspect-square overflow-hidden bg-gray-100 dark:bg-gray-700",children:[c.jsx(Lt,{src:e.thumbnail_url,alt:f,className:"w-full h-full object-cover group-hover:scale-105 transition-transform duration-200",loading:"lazy"}),u&&c.jsx(W,{className:"absolute inset-0 bg-black/50 flex items-center justify-center",children:c.jsx(ee,{className:`text-lg font-bold ${e.sales_status==="sold_out"?"text-red-300":e.sales_status==="suspended"?"text-amber-300":"text-blue-300"}`,style:{textShadow:"0 1px 4px rgba(0,0,0,0.6)"},children:e.sales_status_label??e.sales_status})}),i&&e.sales_status!=="sold_out"&&e.sales_status!=="suspended"&&c.jsxs(ee,{className:"absolute top-2 left-2 px-2 py-1 bg-red-500 text-white text-xs font-bold rounded",children:[e.discount_rate,"%"]}),g.length>0&&c.jsx(W,{className:"absolute bottom-2 right-2 flex gap-1 flex-wrap justify-end",children:g.map((A,v)=>c.jsx(ee,{className:"text-xs text-white font-medium px-1.5 py-0.5 rounded",style:{backgroundColor:A.color||"#6b7280"},children:A.name},v))})]}),c.jsxs(W,{className:"p-4",children:[c.jsxs(W,{className:"flex items-center gap-1.5 flex-wrap",children:[e.primary_category&&c.jsx(ee,{className:"inline-block text-xs font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30 px-2 py-0.5 rounded",children:e.primary_category}),e.brand_name&&c.jsx(ee,{className:"text-xs text-gray-500 dark:text-gray-400",children:e.brand_name})]}),m?c.jsx(W,{className:"mt-1 font-medium text-gray-900 dark:text-white line-clamp-1 [&_mark]:bg-yellow-200 [&_mark]:dark:bg-yellow-500/40 [&_mark]:px-0.5 [&_mark]:rounded",dangerouslySetInnerHTML:{__html:p(m)}}):c.jsx(gn,{className:"mt-1 font-medium text-gray-900 dark:text-white line-clamp-1",children:f}),w&&c.jsx(W,{className:"mt-1 text-sm text-gray-600 dark:text-gray-400 line-clamp-2 [&_mark]:bg-yellow-200 [&_mark]:dark:bg-yellow-500/40 [&_mark]:px-0.5 [&_mark]:rounded",dangerouslySetInnerHTML:{__html:p(w)}}),c.jsxs(W,{className:"mt-1.5 flex items-center gap-1",children:[Dd(e.rating_avg??0).map((A,v)=>c.jsxs(ee,{className:`text-xs ${A==="empty"?"text-gray-300 dark:text-gray-600":"text-yellow-400"}`,children:[A==="full"&&c.jsx("i",{className:"fa-solid fa-star"}),A==="half"&&c.jsx("i",{className:"fa-solid fa-star-half-stroke"}),A==="empty"&&c.jsx("i",{className:"fa-regular fa-star"})]},v)),c.jsx(ee,{className:"text-xs text-gray-600 dark:text-gray-400 ml-0.5",children:(e.rating_avg??0).toFixed(1)}),c.jsxs(ee,{className:"text-xs text-gray-400 dark:text-gray-500",children:["(",e.review_count??0,")"]})]}),c.jsxs(W,{className:"mt-2 flex items-baseline gap-2",children:[c.jsx(ee,{className:"font-bold text-gray-900 dark:text-white",children:h}),d&&i&&c.jsx(ee,{className:"text-sm text-gray-500 dark:text-gray-400 line-through",children:d})]})]})]})},Ld=Object.freeze(Object.defineProperty({__proto__:null,default:ms},Symbol.toStringTag,{value:"Module"})),Pd={ALLOWED_TAGS:["svg","g","defs","title","desc","rect","circle","ellipse","line","polyline","polygon","path","text","tspan","linearGradient","radialGradient","stop","clipPath"],ALLOWED_ATTR:["xmlns","width","height","viewBox","role","aria-label","aria-hidden","fill","fill-opacity","fill-rule","stroke","stroke-width","stroke-linecap","stroke-linejoin","opacity","transform","x","y","x1","y1","x2","y2","cx","cy","r","rx","ry","d","points","width","height","text-anchor","dominant-baseline","font-family","font-size","font-weight","offset","stop-color","stop-opacity","gradientUnits","id","clip-path"],FORBID_TAGS:["script","foreignObject","image","use","a","style"],FORBID_ATTR:["onload","onerror","onclick","onmouseover","onfocus","onblur","href","xlink:href"]},xo=({brandMark:e,size:t=32,className:r="",id:n,editorAttrs:o})=>{const a=e?.svg,s=e?.text,l=k.useMemo(()=>!a||a.trim()===""?"":wo.sanitize(a,Pd),[a]),f={width:`${t}px`,height:`${t}px`,flex:`0 0 ${t}px`};if(l)return c.jsx(W,{id:n,"aria-hidden":"true",className:`inline-flex items-center justify-center ${r}`.trim(),style:f,dangerouslySetInnerHTML:{__html:l},...o});if(s&&s.trim()!==""){const h=e?.class??"bg-gray-500 text-white";return c.jsx(ee,{id:n,"aria-hidden":"true",className:`inline-flex items-center justify-center rounded-lg text-xs font-bold ${h} ${r}`.trim(),style:f,...o,children:s})}return null},Fd=Object.freeze(Object.defineProperty({__proto__:null,BrandMark:xo,default:xo},Symbol.toStringTag,{value:"Module"})),bs="carousel",Wr="controller",$d="navigation",Ud="no-scroll",ko="portal",zd="root",ys="toolbar",Hd="counter",Kr="fullscreen",vs="slideshow",Vr="thumbnails",ws="zoom",vr="loading",Co="playing",Yr="error",Xr="complete",Gd="placeholder",Zr=e=>`active-slide-${e}`,jd=Zr(vr),Bd=Zr(Co),Wd=Zr(Yr),Kd=Zr(Xr),xs="fullsize",wr="flex_center",Vd="no_scroll",ks="no_scroll_padding",So="slide",Cs="slide_wrapper",Yd="slide_wrapper_interactive",Rt="prev",er="next",_o="swipe",xr="close",Ss="onPointerDown",_s="onPointerMove",Es="onPointerUp",Ts="onPointerLeave",Ns="onPointerCancel",Eo="onKeyDown",Xd="onKeyUp",To="onWheel",Zd="Escape",qd="ArrowLeft",Qd="ArrowRight",Jd="button",wn="icon",As="contain",Ms="cover",Os="Unknown action type",Is="yarl__";function lt(...e){return[...e].filter(Boolean).join(" ")}function pe(e){return`${Is}${e}`}function We(e){return`--${Is}${e}`}function or(e,t){return`${e}${t?`_${t}`:""}`}function ar(e){return t=>or(e,t)}function sr(e,t){var r;return(r=e?.[t])!==null&&r!==void 0?r:t}function Ds(e,t,r){return sr(e,"{index} of {total}").replace(/\{index}/g,`${Oo(r,t.length)+1}`).replace(/\{total}/g,`${t.length}`)}function kr(...e){return()=>{e.forEach(t=>{t()})}}function At(e,t,r){return()=>{const n=T.useContext(r);if(!n)throw new Error(`${e} must be used within a ${t}.Provider`);return n}}function No(){return typeof window<"u"}function Ao(e,t=0){const r=10**t;return Math.round((e+Number.EPSILON)*r)/r}function lr(e){return e.type===void 0||e.type==="image"}function Mo(e,t){return e.imageFit===Ms||e.imageFit!==As&&t===Ms}function xn(e){return typeof e=="string"?Number.parseInt(e,10):e}function kn(e){if(typeof e=="number")return{pixel:e};if(typeof e=="string"){const t=xn(e);return e.endsWith("%")?{percent:t}:{pixel:t}}return{pixel:0}}function Rd(e,t){const r=kn(t),n=r.percent!==void 0?e.width/100*r.percent:r.pixel;return{width:Math.max(e.width-2*n,0),height:Math.max(e.height-2*n,0)}}function eu(){return(No()?window?.devicePixelRatio:void 0)||1}function Oo(e,t){return t>0?(e%t+t)%t:0}function Io(e){return e.length>0}function Do(e,t){return e[Oo(t,e.length)]}function Lo(e,t){return Io(e)?Do(e,t):void 0}function Ls(e){return lr(e)?e.src:void 0}function Cn(e,t,r){if(!r)return e;const{buttons:n,...o}=e,a=n.findIndex(l=>l===t),s=T.isValidElement(r)?T.cloneElement(r,{key:t},null):r;if(a>=0){const l=[...n];return l.splice(a,1,s),{buttons:l,...o}}return{buttons:[s,...n],...o}}function Ps(e,t,r=0){return Math.min(e.preload,Math.max(e.finite?t.length-1:Math.floor(t.length/2),r))}const tu=Number(T.version.split(".")[0])>=19;function ru(e){return{inert:tu?e:e?"":void 0}}function nu(e){e.scrollTop}const Po={open:!1,close:()=>{},index:0,slides:[],render:{},plugins:[],toolbar:{buttons:[xr]},labels:{},animation:{fade:250,swipe:500,easing:{fade:"ease",swipe:"ease-out",navigation:"ease-in-out"}},carousel:{finite:!1,preload:2,padding:"16px",spacing:"30%",imageFit:As,imageProps:{}},controller:{ref:null,focus:!0,aria:!1,touchAction:"none",closeOnPullUp:!1,closeOnPullDown:!1,closeOnBackdropClick:!1,preventDefaultWheelX:!0,preventDefaultWheelY:!1,disableSwipeNavigation:!1},portal:{},noScroll:{disabled:!1},on:{},styles:{},className:""};function Mt(e,t){return{name:e,component:t}}function tt(e,t){return{module:e,children:t}}function Fs(e,t,r){return e.module.name===t?r(e):e.children?[tt(e.module,e.children.flatMap(n=>{var o;return(o=Fs(n,t,r))!==null&&o!==void 0?o:[]}))]:[e]}function Cr(e,t,r){return e.flatMap(n=>{var o;return(o=Fs(n,t,r))!==null&&o!==void 0?o:[]})}function ou(e,t=[],r=[]){let n=e;const o=g=>{const p=[...n];for(;p.length>0;){const m=p.pop();if(m?.module.name===g)return!0;m?.children&&p.push(...m.children)}return!1},a=(g,p)=>{if(g===""){n=[tt(p,n)];return}n=Cr(n,g,m=>[tt(p,[m])])},s=(g,p)=>{n=Cr(n,g,m=>[tt(m.module,[tt(p,m.children)])])},l=(g,p,m)=>{n=Cr(n,g,w=>{var x;return[tt(w.module,[...m?[tt(p)]:[],...(x=w.children)!==null&&x!==void 0?x:[],...m?[]:[tt(p)]])]})},f=(g,p,m)=>{n=Cr(n,g,w=>[...m?[tt(p)]:[],w,...m?[]:[tt(p)]])},h=g=>{s(Wr,g)},d=(g,p)=>{n=Cr(n,g,m=>[tt(p,m.children)])},i=g=>{n=Cr(n,g,p=>p.children)},u=g=>{r.push(g)};return t.forEach(g=>{g({contains:o,addParent:a,append:s,addChild:l,addSibling:f,addModule:h,replace:d,remove:i,augment:u})}),{config:n,augmentation:g=>r.reduce((p,m)=>m(p),g)}}const $s=T.createContext(null),Fo=At("useA11yContext","A11yContext",$s);function au({children:e}){const[t,r]=T.useState(!1),[n,o]=T.useState(!1),a=T.useMemo(()=>({focusWithin:t,trackFocusWithin:(l,f)=>{const h=d=>i=>{var u;i.currentTarget.contains(i.relatedTarget)||r(d),(u=d?l:f)===null||u===void 0||u(i)};return{onFocus:h(!0),onBlur:h(!1)}},autoPlaying:n,setAutoPlaying:o}),[t,n]);return T.createElement($s.Provider,{value:a},e)}const Us=T.createContext(null),Sr=At("useDocument","DocumentContext",Us);function su({nodeRef:e,children:t}){const r=T.useMemo(()=>{const n=a=>{var s;return((s=a||e.current)===null||s===void 0?void 0:s.ownerDocument)||document};return{getOwnerDocument:n,getOwnerWindow:a=>{var s;return((s=n(a))===null||s===void 0?void 0:s.defaultView)||window}}},[e]);return T.createElement(Us.Provider,{value:r},t)}const zs=T.createContext(null),_r=At("useEvents","EventsContext",zs);function lu({children:e}){const[t]=T.useState({});T.useEffect(()=>()=>{Object.keys(t).forEach(n=>delete t[n])},[t]);const r=T.useMemo(()=>{const n=(s,l)=>{var f;(f=t[s])===null||f===void 0||f.splice(0,t[s].length,...t[s].filter(h=>h!==l))};return{publish:(...[s,l])=>{var f;(f=t[s])===null||f===void 0||f.forEach(h=>h(l))},subscribe:(s,l)=>(t[s]||(t[s]=[]),t[s].push(l),()=>n(s,l)),unsubscribe:n}},[t]);return T.createElement(zs.Provider,{value:r},e)}const Hs=T.createContext(null),rt=At("useLightboxProps","LightboxPropsContext",Hs);function Gs({children:e,...t}){return T.createElement(Hs.Provider,{value:t},e)}const js=T.createContext(null),Ot=At("useLightboxState","LightboxStateContext",js),Bs=T.createContext(null),iu=At("useLightboxDispatch","LightboxDispatchContext",Bs);function cu(e,t){switch(t.type){case"swipe":{const{slides:r}=e,n=t?.increment||0,o=e.globalIndex+n,a=Oo(o,r.length),s=Lo(r,a),l=n||t.duration!==void 0?{increment:n,duration:t.duration,easing:t.easing}:void 0;return{slides:r,currentIndex:a,globalIndex:o,currentSlide:s,animation:l}}case"update":return t.slides!==e.slides||t.index!==e.currentIndex?{slides:t.slides,currentIndex:t.index,globalIndex:t.index,currentSlide:Lo(t.slides,t.index)}:e;default:throw new Error(Os)}}function du({slides:e,index:t,children:r}){const[n,o]=T.useReducer(cu,{slides:e,currentIndex:t,globalIndex:t,currentSlide:Lo(e,t)});T.useEffect(()=>{o({type:"update",slides:e,index:t})},[e,t]);const a=T.useMemo(()=>({...n,state:n,dispatch:o}),[n,o]);return T.createElement(Bs.Provider,{value:o},T.createElement(js.Provider,{value:a},r))}const Ws=T.createContext(null),qr=At("useTimeouts","TimeoutsContext",Ws);function uu({children:e}){const[t]=T.useState([]);T.useEffect(()=>()=>{t.forEach(n=>window.clearTimeout(n)),t.splice(0,t.length)},[t]);const r=T.useMemo(()=>{const n=s=>{t.splice(0,t.length,...t.filter(l=>l!==s))};return{setTimeout:(s,l)=>{const f=window.setTimeout(()=>{n(f),s()},l);return t.push(f),f},clearTimeout:s=>{s!==void 0&&(n(s),window.clearTimeout(s))}}},[t]);return T.createElement(Ws.Provider,{value:r},e)}const Er=T.forwardRef(function({label:t,className:r,icon:n,renderIcon:o,onClick:a,style:s,...l},f){const{styles:h,labels:d}=rt(),i=sr(d,t);return T.createElement("button",{ref:f,type:"button",title:i,"aria-label":i,className:lt(pe(Jd),r),onClick:a,style:{...s,...h.button},...l},o?o():T.createElement(n,{className:pe(wn),style:h.icon}))});function Ks(e,t){const r=n=>T.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"24",height:"24","aria-hidden":"true",focusable:"false",...n},t);return r.displayName=e,r}function mt(e,t){return Ks(e,T.createElement("g",{fill:"currentColor"},T.createElement("path",{d:"M0 0h24v24H0z",fill:"none"}),t))}function fu(e,t){return Ks(e,T.createElement(T.Fragment,null,T.createElement("defs",null,T.createElement("mask",{id:"strike"},T.createElement("path",{d:"M0 0h24v24H0z",fill:"white"}),T.createElement("path",{d:"M0 0L24 24",stroke:"black",strokeWidth:4}))),T.createElement("path",{d:"M0.70707 2.121320L21.878680 23.292883",stroke:"currentColor",strokeWidth:2}),T.createElement("g",{fill:"currentColor",mask:"url(#strike)"},T.createElement("path",{d:"M0 0h24v24H0z",fill:"none"}),t)))}const gu=mt("Close",T.createElement("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"})),hu=mt("Previous",T.createElement("path",{d:"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"})),pu=mt("Next",T.createElement("path",{d:"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"})),mu=mt("Loading",T.createElement(T.Fragment,null,Array.from({length:8}).map((e,t,r)=>T.createElement("line",{key:t,x1:"12",y1:"6.5",x2:"12",y2:"1.8",strokeLinecap:"round",strokeWidth:"2.6",stroke:"currentColor",strokeOpacity:1/r.length*(t+1),transform:`rotate(${360/r.length*t}, 12, 12)`})))),bu=mt("Error",T.createElement("path",{d:"M21.9,21.9l-8.49-8.49l0,0L3.59,3.59l0,0L2.1,2.1L0.69,3.51L3,5.83V19c0,1.1,0.9,2,2,2h13.17l2.31,2.31L21.9,21.9z M5,18 l3.5-4.5l2.5,3.01L12.17,15l3,3H5z M21,18.17L5.83,3H19c1.1,0,2,0.9,2,2V18.17z"})),$t=No()?T.useLayoutEffect:T.useEffect;function $o(){const[e,t]=T.useState(!1);return T.useEffect(()=>{var r,n;const o=(r=window.matchMedia)===null||r===void 0?void 0:r.call(window,"(prefers-reduced-motion: reduce)");t(o?.matches);const a=s=>t(s.matches);return(n=o?.addEventListener)===null||n===void 0||n.call(o,"change",a),()=>{var s;return(s=o?.removeEventListener)===null||s===void 0?void 0:s.call(o,"change",a)}},[]),e}function yu(e){let t=0,r=0,n=0;const a=window.getComputedStyle(e).transform.match(/matrix.*\((.+)\)/);if(a){const s=a[1].split(",").map(xn);s.length===6?(t=s[4],r=s[5]):s.length===16&&(t=s[12],r=s[13],n=s[14])}return{x:t,y:r,z:n}}function Uo(e,t){const r=T.useRef(void 0),n=T.useRef(void 0),o=$o();return $t(()=>{var a,s,l;if(e.current&&r.current!==void 0&&!o){const{keyframes:f,duration:h,easing:d,onfinish:i}=t(r.current,e.current.getBoundingClientRect(),yu(e.current))||{};if(f&&h){(a=n.current)===null||a===void 0||a.cancel(),n.current=void 0;try{n.current=(l=(s=e.current).animate)===null||l===void 0?void 0:l.call(s,f,{duration:h,easing:d})}catch(u){console.error(u)}n.current&&(n.current.onfinish=()=>{n.current=void 0,i?.()})}}r.current=void 0}),{prepareAnimation:a=>{r.current=a},isAnimationPlaying:()=>{var a;return((a=n.current)===null||a===void 0?void 0:a.playState)==="running"}}}function Vs(){const e=T.useRef(null),t=T.useRef(void 0),[r,n]=T.useState();return{setContainerRef:T.useCallback(a=>{e.current=a,t.current&&(t.current.disconnect(),t.current=void 0);const s=()=>{if(a){const l=window.getComputedStyle(a),f=h=>parseFloat(h)||0;n({width:Math.round(a.clientWidth-f(l.paddingLeft)-f(l.paddingRight)),height:Math.round(a.clientHeight-f(l.paddingTop)-f(l.paddingBottom))})}else n(void 0)};s(),a&&typeof ResizeObserver<"u"&&(t.current=new ResizeObserver(s),t.current.observe(a))},[]),containerRef:e,containerRect:r}}function Sn(){const e=T.useRef(void 0),{setTimeout:t,clearTimeout:r}=qr();return T.useCallback((n,o)=>{r(e.current),e.current=t(n,o>0?o:0)},[t,r])}function Ie(e){const t=T.useRef(e);return $t(()=>{t.current=e}),T.useCallback((...r)=>{var n;return(n=t.current)===null||n===void 0?void 0:n.call(t,...r)},[])}function Ys(e,t){typeof e=="function"?e(t):e&&(e.current=t)}function zo(e,t){return T.useMemo(()=>e==null&&t==null?null:r=>{Ys(e,r),Ys(t,r)},[e,t])}function Xs(e,t=!1){const r=T.useRef(!1);$t(()=>{t&&r.current&&(r.current=!1,e())},[t,e]);const n=T.useCallback(()=>{r.current=!0},[]),o=T.useCallback(()=>{r.current=!1},[]);return{onFocus:n,onBlur:o}}function _n(){const[e,t]=T.useState(!1);return $t(()=>{t(window.getComputedStyle(window.document.documentElement).direction==="rtl")},[]),e}function Zs(){const[e]=T.useState({}),t=T.useCallback((o,a)=>{var s;(s=e[o])===null||s===void 0||s.forEach(l=>{a.isPropagationStopped()||l(a)})},[e]),r=T.useMemo(()=>({onPointerDown:o=>t(Ss,o),onPointerMove:o=>t(_s,o),onPointerUp:o=>t(Es,o),onPointerLeave:o=>t(Ts,o),onPointerCancel:o=>t(Ns,o),onKeyDown:o=>t(Eo,o),onKeyUp:o=>t(Xd,o),onWheel:o=>t(To,o)}),[t]),n=T.useCallback((o,a)=>(e[o]||(e[o]=[]),e[o].unshift(a),()=>{const s=e[o];s&&s.splice(0,s.length,...s.filter(l=>l!==a))}),[e]);return{registerSensors:r,subscribeSensors:n}}function qs(e,t){const r=T.useRef(0),n=Sn(),o=Ie((...a)=>{r.current=Date.now(),e(a)});return T.useCallback((...a)=>{n(()=>{o(a)},t-(Date.now()-r.current))},[t,o,n])}const Ho=ar("slide"),Go=ar("slide_image");function ir({slide:e,offset:t,render:r,rect:n,imageFit:o,imageProps:a,onClick:s,onLoad:l,onError:f,style:h}){var d,i,u,g,p,m,w,x;const[A,v]=T.useState(vr),{publish:E}=_r(),{setTimeout:O}=qr(),_=T.useRef(null);T.useEffect(()=>{t===0&&E(Zr(A))},[t,A,E]);const I=Ie(B=>{("decode"in B?B.decode():Promise.resolve()).catch(()=>{}).then(()=>{B.parentNode&&(v(Xr),O(()=>{l?.(B)},0))})}),C=T.useCallback(B=>{_.current=B,B?.complete&&I(B)},[I]),y=T.useCallback(B=>{I(B.currentTarget)},[I]),N=Ie(()=>{v(Yr),f?.()}),M=Mo(e,o),P=(B,V)=>Number.isFinite(B)?B:V,D=P(Math.max(...((i=(d=e.srcSet)===null||d===void 0?void 0:d.map(B=>B.width))!==null&&i!==void 0?i:[]).concat(e.width?[e.width]:[]).filter(Boolean)),((u=_.current)===null||u===void 0?void 0:u.naturalWidth)||0),L=P(Math.max(...((p=(g=e.srcSet)===null||g===void 0?void 0:g.map(B=>B.height))!==null&&p!==void 0?p:[]).concat(e.height?[e.height]:[]).filter(Boolean)),((m=_.current)===null||m===void 0?void 0:m.naturalHeight)||0),U=D&&L?{maxWidth:`min(${D}px, 100%)`,maxHeight:`min(${L}px, 100%)`}:{maxWidth:"100%",maxHeight:"100%"},S=(w=e.srcSet)===null||w===void 0?void 0:w.sort((B,V)=>B.width-V.width).map(B=>`${B.src} ${B.width}w`).join(", "),b=()=>n&&!M&&e.width&&e.height?n.height/e.height*e.width:Number.MAX_VALUE,$=S&&n&&No()?`${Math.round(Math.min(b(),n.width))}px`:void 0,{style:F,className:G,...Y}=a||{};return T.createElement(T.Fragment,null,T.createElement("img",{ref:C,onLoad:y,onError:N,onClick:s,draggable:!1,className:lt(pe(Go()),M&&pe(Go("cover")),A!==Xr&&pe(Go("loading")),G),style:{...U,...h,...F},...Y,alt:(x=e.alt)!==null&&x!==void 0?x:"",sizes:$,srcSet:S,src:e.src}),A!==Xr&&T.createElement("div",{className:pe(Ho(Gd))},A===vr&&(r?.iconLoading?r.iconLoading():T.createElement(mu,{className:lt(pe(wn),pe(Ho(vr)))})),A===Yr&&(r?.iconError?r.iconError():T.createElement(bu,{className:lt(pe(wn),pe(Ho(Yr)))}))))}const vu=T.forwardRef(function({className:t,children:r,onFocus:n,onBlur:o,...a},s){const l=T.useRef(null),{trackFocusWithin:f}=Fo();return T.createElement(su,{nodeRef:l},T.createElement("div",{ref:zo(s,l),className:lt(pe("root"),t),...f(n,o),...a},r))});var it;(function(e){e[e.NONE=0]="NONE",e[e.SWIPE=1]="SWIPE",e[e.PULL=2]="PULL",e[e.ANIMATION=3]="ANIMATION"})(it||(it={}));function Qs(e,t,r,n,o){T.useEffect(()=>o?()=>{}:kr(e(Ss,t),e(_s,r),e(Es,n),e(Ts,n),e(Ns,n)),[e,t,r,n,o])}var Ut;(function(e){e[e.NONE=0]="NONE",e[e.SWIPE=1]="SWIPE",e[e.PULL=2]="PULL"})(Ut||(Ut={}));const jo=30;function wu({disableSwipeNavigation:e,closeOnBackdropClick:t},r,n,o,a,s,l,f,h,d,i,u,g,p,m,w){const x=T.useRef(0),A=T.useRef([]),v=T.useRef(void 0),E=T.useRef(0),O=T.useRef(Ut.NONE),_=T.useCallback(D=>{v.current===D.pointerId&&(v.current=void 0,O.current=Ut.NONE);const L=A.current;L.splice(0,L.length,...L.filter(U=>U.pointerId!==D.pointerId))},[]),I=T.useCallback(D=>{_(D),D.persist(),A.current.push(D)},[_]),C=T.useCallback(D=>A.current.find(({pointerId:L})=>D.pointerId===L),[]),y=Ie(D=>{I(D)}),N=(D,L)=>i&&D>L||d&&D<-L,M=Ie(D=>{const L=C(D);if(L)if(v.current===D.pointerId){const U=Date.now()-E.current,S=x.current;O.current===Ut.SWIPE?Math.abs(S)>.3*o||Math.abs(S)>5&&U{const L=C(D);if(L){const U=v.current===D.pointerId;if(D.buttons===0){U&&x.current!==0?M(D):_(L);return}const S=D.clientX-L.clientX,b=D.clientY-L.clientY;if(v.current===void 0){const $=F=>{I(D),v.current=D.pointerId,E.current=Date.now(),O.current=F};Math.abs(S)>Math.abs(b)&&Math.abs(S)>jo&&n(S)?e||($(Ut.SWIPE),s()):Math.abs(b)>Math.abs(S)&&N(b,jo)&&($(Ut.PULL),u())}else U&&(O.current===Ut.SWIPE?(x.current=S,l(S)):O.current===Ut.PULL&&(x.current=b,g(b)))}});Qs(r,y,P,M)}function xu({preventDefaultWheelX:e,preventDefaultWheelY:t}){const r=T.useRef(null),n=Ie(o=>{const a=Math.abs(o.deltaX)>Math.abs(o.deltaY);(a&&e||!a&&t||o.ctrlKey)&&o.preventDefault()});return T.useCallback(o=>{var a;o?o.addEventListener("wheel",n,{passive:!1}):(a=r.current)===null||a===void 0||a.removeEventListener("wheel",n),r.current=o},[n])}function ku(e,t,r,n,o,a,s,l,f){const h=T.useRef(0),d=T.useRef(0),i=T.useRef(void 0),u=T.useRef(void 0),g=T.useRef(0),p=T.useRef(void 0),m=T.useRef(0),{setTimeout:w,clearTimeout:x}=qr(),A=T.useCallback(()=>{i.current&&(x(i.current),i.current=void 0)},[x]),v=T.useCallback(()=>{u.current&&(x(u.current),u.current=void 0)},[x]),E=Ie(()=>{e!==it.SWIPE&&(h.current=0,m.current=0,A(),v())});T.useEffect(E,[e,E]);const O=Ie(I=>{u.current=void 0,h.current===I&&f(h.current)}),_=Ie(I=>{if(I.ctrlKey||Math.abs(I.deltaY)>Math.abs(I.deltaX))return;const C=y=>{g.current=y,x(p.current),p.current=y>0?w(()=>{g.current=0,p.current=void 0},300):void 0};if(e===it.NONE){if(Math.abs(I.deltaX)<=1.2*Math.abs(g.current)){C(I.deltaX);return}if(!r(-I.deltaX))return;if(d.current+=I.deltaX,A(),Math.abs(d.current)>30)d.current=0,C(0),m.current=Date.now(),a();else{const y=d.current;i.current=w(()=>{i.current=void 0,y===d.current&&(d.current=0)},o)}}else if(e===it.SWIPE){let y=h.current-I.deltaX;if(y=Math.min(Math.abs(y),n)*Math.sign(y),h.current=y,s(y),v(),Math.abs(y)>.2*n){C(I.deltaX),l(y,Date.now()-m.current);return}u.current=w(()=>O(y),2*o)}else C(I.deltaX)});T.useEffect(()=>t(To,_),[t,_])}const Js=ar("container"),Rs=T.createContext(null),zt=At("useController","ControllerContext",Rs);function Cu({children:e,...t}){var r;const{carousel:n,animation:o,controller:a,on:s,styles:l,render:f}=t,{closeOnPullUp:h,closeOnPullDown:d,preventDefaultWheelX:i,preventDefaultWheelY:u}=a,[g,p]=T.useState(),m=Ot(),w=iu(),[x,A]=T.useState(it.NONE),v=T.useRef(0),E=T.useRef(0),O=T.useRef(1),{registerSensors:_,subscribeSensors:I}=Zs(),{subscribe:C,publish:y}=_r(),N=Sn(),M=Sn(),P=Sn(),{containerRef:D,setContainerRef:L,containerRect:U}=Vs(),S=zo(xu({preventDefaultWheelX:i,preventDefaultWheelY:u}),L),b=T.useRef(null),$=zo(b,void 0),{getOwnerDocument:F}=Sr(),G=_n(),Y=K=>(G?-1:1)*(typeof K=="number"?K:1),B=Ie(()=>{var K;return(K=D.current)===null||K===void 0?void 0:K.focus()}),V=Ie(()=>t),j=Ie(()=>m),H=T.useCallback(K=>y(Rt,K),[y]),Z=T.useCallback(K=>y(er,K),[y]),ue=T.useCallback(()=>y(xr),[y]),te=K=>!(n.finite&&(Y(K)>0&&m.currentIndex===0||Y(K)<0&&m.currentIndex===m.slides.length-1)),fe=K=>{var re;v.current=K,(re=D.current)===null||re===void 0||re.style.setProperty(We("swipe_offset"),`${Math.round(K)}px`)},R=K=>{var re,oe;E.current=K,O.current=(()=>{const xe=d&&K>0?K:h&&K<0?-K:0;return Math.min(Math.max(Ao(1-xe/60*(1-.5),2),.5),1)})(),(re=D.current)===null||re===void 0||re.style.setProperty(We("pull_offset"),`${Math.round(K)}px`),(oe=D.current)===null||oe===void 0||oe.style.setProperty(We("pull_opacity"),`${O.current}`)},{prepareAnimation:ke}=Uo(b,(K,re,oe)=>{if(b.current&&U)return{keyframes:[{transform:`translate(0, ${K.rect.y-re.y+oe.y}px)`,opacity:K.opacity},{transform:"translate(0, 0)",opacity:1}],duration:K.duration,easing:o.easing.fade}}),me=(K,re)=>{if(h||d){R(K);let oe=0;b.current&&(oe=o.fade*(re?2:1),ke({rect:b.current.getBoundingClientRect(),opacity:O.current,duration:oe})),P(()=>{R(0),A(it.NONE)},oe),A(it.ANIMATION),re||ue()}},{prepareAnimation:Ge,isAnimationPlaying:De}=Uo(b,(K,re,oe)=>{var ae;if(b.current&&U&&(!((ae=m.animation)===null||ae===void 0)&&ae.duration)){const be=kn(n.spacing),xe=(be.percent?be.percent*U.width/100:be.pixel)||0;return{keyframes:[{transform:`translate(${Y(m.globalIndex-K.index)*(U.width+xe)+K.rect.x-re.x+oe.x}px, 0)`},{transform:"translate(0, 0)"}],duration:m.animation.duration,easing:m.animation.easing}}}),ye=Ie(K=>{var re,oe;const ae=K.offset||0,be=ae?o.swipe:(re=o.navigation)!==null&&re!==void 0?re:o.swipe,xe=!ae&&!De()?o.easing.navigation:o.easing.swipe;let{direction:He}=K;const Pe=(oe=K.count)!==null&&oe!==void 0?oe:1;let Ke=it.ANIMATION,Oe=be*Pe;if(!He){const se=U?.width,ie=K.duration||0,le=se?be/se*Math.abs(ae):be;Pe!==0?(ie0?Rt:er):Oe=be/2}let X=0;He===Rt?te(Y(1))?X=-Pe:(Ke=it.NONE,Oe=be):He===er&&(te(Y(-1))?X=Pe:(Ke=it.NONE,Oe=be)),Oe=Math.round(Oe),M(()=>{fe(0),A(it.NONE)},Oe),b.current&&Ge({rect:b.current.getBoundingClientRect(),index:m.globalIndex}),A(Ke),y(_o,{type:"swipe",increment:X,duration:Oe,easing:xe})});T.useEffect(()=>{var K,re;!((K=m.animation)===null||K===void 0)&&K.increment&&(!((re=m.animation)===null||re===void 0)&&re.duration)&&N(()=>w({type:"swipe",increment:0}),m.animation.duration)},[m.animation,w,N]);const Me=[I,te,U?.width||0,o.swipe,()=>A(it.SWIPE),K=>fe(K),(K,re)=>ye({offset:K,duration:re,count:1}),K=>ye({offset:K,count:0})],Ce=[()=>{d&&A(it.PULL)},K=>R(K),K=>me(K),K=>me(K,!0)];wu(a,...Me,h,d,...Ce,ue),ku(x,...Me);const we=Ie(()=>{a.focus&&F().querySelector(`.${pe(ko)} .${pe(Js())}`)&&B()});T.useEffect(we,[we]);const $e=Ie(()=>{var K;(K=s.view)===null||K===void 0||K.call(s,{index:m.currentIndex})});T.useEffect($e,[m.globalIndex,$e]),T.useEffect(()=>kr(C(Rt,K=>ye({direction:Rt,...K})),C(er,K=>ye({direction:er,...K})),C(_o,K=>w(K))),[C,ye,w]);const Le=T.useMemo(()=>({prev:H,next:Z,close:ue,focus:B,slideRect:U?Rd(U,n.padding):{width:0,height:0},containerRect:U||{width:0,height:0},subscribeSensors:I,containerRef:D,setCarouselRef:$,toolbarWidth:g,setToolbarWidth:p}),[H,Z,ue,B,I,U,D,$,g,p,n.padding]);return T.useImperativeHandle(a.ref,()=>({prev:H,next:Z,close:ue,focus:B,getLightboxProps:V,getLightboxState:j}),[H,Z,ue,B,V,j]),T.createElement("div",{ref:S,className:lt(pe(Js()),pe(wr)),style:{...x===it.SWIPE?{[We("swipe_offset")]:`${Math.round(v.current)}px`}:null,...x===it.PULL?{[We("pull_offset")]:`${Math.round(E.current)}px`,[We("pull_opacity")]:`${O.current}`}:null,...a.touchAction!=="none"?{[We("controller_touch_action")]:a.touchAction}:null,...l.container},tabIndex:-1,..._},U&&T.createElement(Rs.Provider,{value:Le},e,(r=f.controls)===null||r===void 0?void 0:r.call(f)))}const Su=Mt(Wr,Cu);function cr(e){return or(bs,e)}function el(e){return or(So,e)}function _u({slide:e,offset:t}){const r=T.useRef(null),{currentIndex:n,slides:o}=Ot(),{slideRect:a,focus:s}=zt(),{render:l,carousel:{imageFit:f,imageProps:h},on:{click:d},styles:{slide:i},labels:u}=rt(),{getOwnerDocument:g}=Sr(),p=t!==0;T.useEffect(()=>{var w;p&&(!((w=r.current)===null||w===void 0)&&w.contains(g().activeElement))&&s()},[p,s,g]);const m=()=>{var w,x,A,v;let E=(w=l.slide)===null||w===void 0?void 0:w.call(l,{slide:e,offset:t,rect:a});return!E&&lr(e)&&(E=T.createElement(ir,{slide:e,offset:t,render:l,rect:a,imageFit:f,imageProps:h,onClick:p?void 0:()=>d?.({index:n})})),E?T.createElement(T.Fragment,null,(x=l.slideHeader)===null||x===void 0?void 0:x.call(l,{slide:e}),((A=l.slideContainer)!==null&&A!==void 0?A:(({children:O})=>O))({slide:e,children:E}),(v=l.slideFooter)===null||v===void 0?void 0:v.call(l,{slide:e})):null};return T.createElement("div",{ref:r,className:lt(pe(el()),!p&&pe(el("current")),pe(wr)),...ru(p),style:i,role:"group","aria-roledescription":sr(u,"Slide"),"aria-label":Ds(u,o,n+t)},m())}function Eu(){const e=rt().styles.slide;return T.createElement("div",{className:pe(So),style:e})}function Tu({carousel:e,labels:t}){const{slides:r,currentIndex:n,globalIndex:o}=Ot(),{setCarouselRef:a}=zt(),{autoPlaying:s,focusWithin:l}=Fo(),f=kn(e.spacing),h=kn(e.padding),d=Ps(e,r,1),i=[];if(Io(r))for(let u=n-d;u<=n+d;u+=1){const g=Do(r,u),p=o-n+u,m=e.finite&&(u<0||u>r.length-1);i.push(m?{key:p}:{key:[`${p}`,Ls(g)].filter(Boolean).join("|"),offset:u-n,slide:g})}return T.createElement("div",{ref:a,className:lt(pe(cr()),i.length>0&&pe(cr("with_slides"))),style:{[`${We(cr("slides_count"))}`]:i.length,[`${We(cr("spacing_px"))}`]:f.pixel||0,[`${We(cr("spacing_percent"))}`]:f.percent||0,[`${We(cr("padding_px"))}`]:h.pixel||0,[`${We(cr("padding_percent"))}`]:h.percent||0},role:"region","aria-live":s&&!l?"off":"polite","aria-roledescription":sr(t,"Carousel"),"aria-label":sr(t,"Photo gallery")},i.map(({key:u,slide:g,offset:p})=>g?T.createElement(_u,{key:u,slide:g,offset:p}):T.createElement(Eu,{key:u})))}const Nu=Mt(bs,Tu);function tl(){const{carousel:e}=rt(),{slides:t,currentIndex:r}=Ot(),n=t.length===0||e.finite&&r===0,o=t.length===0||e.finite&&r===t.length-1;return{prevDisabled:n,nextDisabled:o}}function rl(e){var t;const r=_n(),{publish:n}=_r(),{animation:o}=rt(),{prevDisabled:a,nextDisabled:s}=tl(),l=((t=o.navigation)!==null&&t!==void 0?t:o.swipe)/2,f=qs(()=>n(Rt),l),h=qs(()=>n(er),l),d=Ie(i=>{switch(i.key){case Zd:n(xr);break;case qd:(r?s:a)||(r?h:f)();break;case Qd:(r?a:s)||(r?f:h)();break}});T.useEffect(()=>e(Eo,d),[e,d])}function nl({label:e,icon:t,renderIcon:r,action:n,onClick:o,disabled:a,style:s}){return T.createElement(Er,{label:e,icon:t,renderIcon:r,className:pe(`navigation_${n}`),disabled:a,onClick:o,style:s,...Xs(zt().focus,a)})}function Au({render:{buttonPrev:e,buttonNext:t,iconPrev:r,iconNext:n},styles:o}){const{prev:a,next:s,subscribeSensors:l}=zt(),{prevDisabled:f,nextDisabled:h}=tl();return rl(l),T.createElement(T.Fragment,null,e?e():T.createElement(nl,{label:"Previous",action:Rt,icon:hu,renderIcon:r,style:o.navigationPrev,disabled:f,onClick:a}),t?t():T.createElement(nl,{label:"Next",action:er,icon:pu,renderIcon:n,style:o.navigationNext,disabled:h,onClick:s}))}const Mu=Mt($d,Au),ol=pe(Vd),Ou=pe(ks);function Iu(e){return"style"in e}function al(e,t,r){const n=window.getComputedStyle(e),o=r?"padding-left":"padding-right",a=r?n.paddingLeft:n.paddingRight,s=e.style.getPropertyValue(o);return e.style.setProperty(o,`${(xn(a)||0)+t}px`),()=>{s?e.style.setProperty(o,s):e.style.removeProperty(o)}}function Du({noScroll:{disabled:e},children:t}){const r=_n(),{getOwnerDocument:n,getOwnerWindow:o}=Sr();return T.useEffect(()=>{if(e)return()=>{};const a=[],s=o(),{body:l,documentElement:f}=n(),h=Math.round(s.innerWidth-f.clientWidth);if(h>0){a.push(al(l,h,r));const d=l.getElementsByTagName("*");for(let i=0;i{l.classList.remove(ol),a.forEach(d=>d())}},[r,e,n,o]),T.createElement(T.Fragment,null,t)}const Lu=Mt(Ud,Du);function sl(e){return or(ko,e)}function ll(e,t,r){const n=e.getAttribute(t);return e.setAttribute(t,r),()=>{n?e.setAttribute(t,n):e.removeAttribute(t)}}function Pu({children:e,animation:t,styles:r,className:n,on:o,portal:a,close:s,labels:l}){const[f,h]=T.useState(!1),[d,i]=T.useState(!1),u=T.useRef([]),g=T.useRef(null),{setTimeout:p}=qr(),{subscribe:m}=_r(),x=$o()?0:t.fade;T.useEffect(()=>(h(!0),()=>{h(!1),i(!1)}),[]);const A=Ie(()=>{u.current.forEach(_=>_()),u.current=[]}),v=Ie(()=>{var _;i(!1),A(),(_=o.exiting)===null||_===void 0||_.call(o),p(()=>{var I;(I=o.exited)===null||I===void 0||I.call(o),s()},x)});T.useEffect(()=>m(xr,v),[m,v]);const E=Ie(_=>{var I,C,y;nu(_),i(!0),(I=o.entering)===null||I===void 0||I.call(o);const N=(y=(C=_.parentNode)===null||C===void 0?void 0:C.children)!==null&&y!==void 0?y:[];for(let M=0;M{var M,P;(P=(M=g.current)===null||M===void 0?void 0:M.focus)===null||P===void 0||P.call(M)}),p(()=>{var M;(M=o.entered)===null||M===void 0||M.call(o)},x)}),O=T.useCallback(_=>{_?E(_):A()},[E,A]);return f?Jt.createPortal(T.createElement(vu,{ref:O,className:lt(n,pe(sl()),pe(ks),d&&pe(sl("open"))),"aria-modal":!0,role:"dialog","aria-label":sr(l,"Lightbox"),style:{...t.fade!==Po.animation.fade?{[We("fade_animation_duration")]:`${x}ms`}:null,...t.easing.fade!==Po.animation.easing.fade?{[We("fade_animation_timing_function")]:t.easing.fade}:null,...r.root},onFocus:_=>{g.current||(g.current=_.relatedTarget)}},e),a.root||document.body):null}const Fu=Mt(ko,Pu);function $u({children:e}){return T.createElement(T.Fragment,null,e)}const Uu=Mt(zd,$u);function zu(e){return or(ys,e)}function Hu({toolbar:{buttons:e},render:{buttonClose:t,iconClose:r},styles:n}){const{close:o,setToolbarWidth:a}=zt(),{setContainerRef:s,containerRect:l}=Vs();$t(()=>{a(l?.width)},[a,l?.width]);const f=()=>t?t():T.createElement(Er,{key:xr,label:"Close",icon:gu,renderIcon:r,onClick:o});return T.createElement("div",{ref:s,style:n.toolbar,className:pe(zu())},e?.map(h=>h===xr?f():h))}const Gu=Mt(ys,Hu);function il(e,t){var r;return T.createElement(e.module.component,{key:e.module.name,...t},(r=e.children)===null||r===void 0?void 0:r.map(n=>il(n,t)))}function ju(e,t={}){const{easing:r,...n}=e,{easing:o,...a}=t;return{easing:{...r,...o},...n,...a}}function Bu({carousel:e,animation:t,render:r,toolbar:n,controller:o,noScroll:a,on:s,plugins:l,slides:f,index:h,...d}){const{animation:i,carousel:u,render:g,toolbar:p,controller:m,noScroll:w,on:x,slides:A,index:v,plugins:E,...O}=Po,{config:_,augmentation:I}=ou([tt(Fu,[tt(Lu,[tt(Su,[tt(Nu),tt(Gu),tt(Mu)])])])],l||E),C=I({animation:ju(i,t),carousel:{...u,...e},render:{...g,...r},toolbar:{...p,...n},controller:{...m,...o},noScroll:{...w,...a},on:{...x,...s},...O,...d});return C.open?T.createElement(Gs,{...C},T.createElement(du,{slides:f||A,index:xn(h||v)},T.createElement(uu,null,T.createElement(lu,null,T.createElement(au,null,il(tt(Uu,_),C)))))):null}const Wu={minZoom:1,maxZoomPixelRatio:1,zoomInMultiplier:2,doubleTapDelay:300,doubleClickDelay:500,doubleClickMaxStops:2,keyboardMoveDistance:50,wheelZoomDistanceFactor:100,pinchZoomDistanceFactor:100,pinchZoomV4:!1,scrollToZoom:!1};function Ku(e){return Math.min(Math.max(e,Number.EPSILON),1)}function cl(e){const{minZoom:t,...r}={...Wu,...e};return{minZoom:Ku(t),...r}}function Vu(e,t,r,n){const o=T.useRef(void 0),a=T.useRef(void 0),{zoom:s}=rt().animation,l=$o(),f=Ie(()=>{var h,d,i;if((h=o.current)===null||h===void 0||h.cancel(),o.current=void 0,a.current&&n?.current){try{o.current=(i=(d=n.current).animate)===null||i===void 0?void 0:i.call(d,[{transform:a.current},{transform:`scale(${e}) translateX(${t}px) translateY(${r}px)`}],{duration:l?0:s??500,easing:o.current?"ease-out":"ease-in-out"})}catch(u){console.error(u)}a.current=void 0,o.current&&(o.current.onfinish=()=>{o.current=void 0})}});return $t(f,[e,t,r,f]),T.useCallback(()=>{a.current=n?.current?window.getComputedStyle(n.current).transform:void 0},[n])}function Yu(e,t){const{on:r}=rt(),n=Ie(()=>{var o;t||(o=r.zoom)===null||o===void 0||o.call(r,{zoom:e})});T.useEffect(n,[e,n])}function En(){const{zoom:e}=rt();return cl(e)}function Xu(e,t){var r,n;let o={width:0,height:0},a={width:0,height:0};const{currentSlide:s}=Ot(),{imageFit:l}=rt().carousel,{maxZoomPixelRatio:f}=En();if(e&&s){const d={...s,...t};if(lr(d)){const i=Mo(d,l),u=Math.max(...(((r=d.srcSet)===null||r===void 0?void 0:r.map(p=>p.width))||[]).concat(d.width?[d.width]:[])),g=Math.max(...(((n=d.srcSet)===null||n===void 0?void 0:n.map(p=>p.height))||[]).concat(d.height?[d.height]:[]));u>0&&g>0&&e.width>0&&e.height>0&&(a=i?{width:Math.round(Math.min(u,e.width/e.height*g)),height:Math.round(Math.min(g,e.height/e.width*u))}:{width:u,height:g},a={width:a.width*f,height:a.height*f},o=i?{width:Math.min(e.width,a.width,u),height:Math.min(e.height,a.height,g)}:{width:Math.round(Math.min(e.width,e.height/g*u,u)),height:Math.round(Math.min(e.height,e.width/u*g,g))})}}const h=o.width?Math.max(Ao(a.width/o.width,5),1):1;return{imageRect:o,maxZoom:h}}function dl(e,t){return Math.hypot(e.clientX-t.clientX,e.clientY-t.clientY)}function ul(e,t,r=100,n=2){return e*Math.min(1+Math.abs(t/r),n)**Math.sign(t)}function Zu(e,t,r,n,o,a,s,l,f){const h=T.useRef([]),d=T.useRef(0),i=T.useRef(void 0),{globalIndex:u}=Ot(),{getOwnerWindow:g}=Sr(),{containerRef:p,subscribeSensors:m}=zt(),{keyboardMoveDistance:w,zoomInMultiplier:x,wheelZoomDistanceFactor:A,scrollToZoom:v,doubleTapDelay:E,doubleClickDelay:O,doubleClickMaxStops:_,pinchZoomDistanceFactor:I,pinchZoomV4:C}=En(),y=T.useCallback($=>{if(p.current){const{pageX:F,pageY:G}=$,{scrollX:Y,scrollY:B}=g(),{left:V,top:j,width:H,height:Z}=p.current.getBoundingClientRect();return[F-V-Y-H/2,G-j-B-Z/2]}return[]},[p,g]),N=Ie($=>{const{key:F,metaKey:G,ctrlKey:Y}=$,B=G||Y,V=()=>{$.preventDefault(),$.stopPropagation()};if(e>1){const j=(H,Z)=>{V(),l(H,Z)};F==="ArrowDown"?j(0,w):F==="ArrowUp"?j(0,-w):F==="ArrowLeft"?j(-w,0):F==="ArrowRight"&&j(w,0)}F==="+"||B&&F==="="?(V(),o()):F==="-"||B&&F==="_"?(V(),a()):B&&F==="0"&&(V(),s(1))}),M=Ie($=>{if(($.ctrlKey||v)&&Math.abs($.deltaY)>Math.abs($.deltaX)){$.stopPropagation(),s(ul(e,-$.deltaY,A),!0,...y($));return}e>1&&($.stopPropagation(),v||l($.deltaX,$.deltaY))}),P=T.useCallback($=>{const F=h.current;F.splice(0,F.length,...F.filter(G=>G.pointerId!==$.pointerId))},[]),D=T.useCallback($=>{P($),$.persist(),h.current.push($)},[P]),L=Ie($=>{var F;const G=h.current;if($.pointerType==="mouse"&&$.buttons>1||!(!((F=f?.current)===null||F===void 0)&&F.contains($.target)))return;e>1&&$.stopPropagation();const{timeStamp:Y}=$;if(G.length===0&&Y-d.current<($.pointerType==="touch"?E:O)){d.current=0;const B=e>=1?e!==r?e*Math.max(r**(1/_),x):1:e!==t?e/Math.max(t**(-1/_),x):1;s(B,!1,...y($))}else d.current=Y;if(D($),G.length===2){const B=dl(G[0],G[1]);i.current={previousDistance:B,initialDistance:Math.max(B,1),initialZoom:e}}}),U=Ie($=>{const F=h.current,G=F.find(Y=>Y.pointerId===$.pointerId);if(F.length===2&&i.current){$.stopPropagation(),D($);const Y=dl(F[0],F[1]),B=C?i.current.initialZoom/i.current.initialDistance*Y:ul(e,Y-i.current.previousDistance,I);s(B,!0,...F.map(V=>y(V)).reduce((V,j)=>j.map((H,Z)=>V[Z]+H/2))),i.current.previousDistance=Y;return}e>1&&($.stopPropagation(),G&&(F.length===1&&l((G.clientX-$.clientX)/e,(G.clientY-$.clientY)/e),D($)))}),S=T.useCallback($=>{const F=h.current;F.length===2&&F.find(G=>G.pointerId===$.pointerId)&&(i.current=void 0),P($)},[P]),b=T.useCallback(()=>{const $=h.current;$.splice(0,$.length),d.current=0,i.current=void 0},[]);Qs(m,L,U,S,n),T.useEffect(b,[u,b]),T.useEffect(()=>n?()=>{}:kr(b,m(Eo,N),m(To,M)),[n,m,b,N,M])}function qu(e,t,r){const[n,o]=T.useState(1),[a,s]=T.useState(0),[l,f]=T.useState(0),h=Vu(n,a,l,r),{currentSlide:d,globalIndex:i}=Ot(),{containerRect:u,slideRect:g}=zt(),{minZoom:p,zoomInMultiplier:m}=En(),w=d&&lr(d)?d.src:void 0,x=!w||!r?.current;$t(()=>{o(1),s(0),f(0)},[i,w]);const A=T.useCallback((I,C,y)=>{const N=y||n,M=a-(I||0),P=l-(C||0),D=(e.width*N-g.width)/2/N,L=(e.height*N-g.height)/2/N;s(Math.min(Math.abs(M),Math.max(D,0))*Math.sign(M)),f(Math.min(Math.abs(P),Math.max(L,0))*Math.sign(P))},[n,a,l,g,e.width,e.height]),v=T.useCallback((I,C,y,N)=>{const M=Ao(I+.01p?I:p:t,5);C||h(),A(y?y*(1/n-1/M):0,N?N*(1/n-1/M):0,M),o(M)},[n,p,t,A,h]),E=Ie(()=>{n>1&&(n>t&&v(t,!0),A())});$t(E,[u.width,u.height,E]);const O=T.useCallback(()=>{const I=n*m;v(n<1&&I>1?1:I)},[n,m,v]),_=T.useCallback(()=>{const I=n/m;v(n>1&&I<1?1:I)},[n,m,v]);return{zoom:n,offsetX:a,offsetY:l,disabled:x,changeOffsets:A,changeZoom:v,zoomIn:O,zoomOut:_}}const fl=T.createContext(null),Bo=At("useZoom","ZoomControllerContext",fl);function Qu({children:e}){const[t,r]=T.useState(),{slideRect:n}=zt(),{ref:o,minZoom:a}=En(),{imageRect:s,maxZoom:l}=Xu(n,t?.imageDimensions),{zoom:f,offsetX:h,offsetY:d,disabled:i,changeZoom:u,changeOffsets:g,zoomIn:p,zoomOut:m}=qu(s,l,t?.zoomWrapperRef);Yu(f,i),Zu(f,a,l,i,p,m,u,g,t?.zoomWrapperRef);const w=T.useMemo(()=>({zoom:f,minZoom:a,maxZoom:l,offsetX:h,offsetY:d,disabled:i,zoomIn:p,zoomOut:m,changeZoom:u}),[f,a,l,h,d,i,p,m,u]);T.useImperativeHandle(o,()=>w,[w]);const x=T.useMemo(()=>({...w,setZoomWrapper:r}),[w,r]);return T.createElement(fl.Provider,{value:x},e)}const Ju=mt("ZoomIn",T.createElement(T.Fragment,null,T.createElement("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"}),T.createElement("path",{d:"M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z"}))),Ru=mt("ZoomOut",T.createElement("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z"})),gl=T.forwardRef(function({zoomIn:t,onLoseFocus:r},n){const o=T.useRef(!1),a=T.useRef(!1),{zoom:s,minZoom:l,maxZoom:f,zoomIn:h,zoomOut:d,disabled:i}=Bo(),{render:u}=rt(),g=i||(t?s>=f:s<=l);return T.useEffect(()=>{g&&o.current&&a.current&&r(),g||(o.current=!0)},[g,r]),T.createElement(Er,{ref:n,disabled:g,label:t?"Zoom in":"Zoom out",icon:t?Ju:Ru,renderIcon:t?u.iconZoomIn:u.iconZoomOut,onClick:t?h:d,onFocus:()=>{a.current=!0},onBlur:()=>{a.current=!1}})});function ef(){const e=T.useRef(null),t=T.useRef(null),{focus:r}=zt(),n=T.useCallback(s=>{var l,f;!((l=s.current)===null||l===void 0)&&l.disabled?r():(f=s.current)===null||f===void 0||f.focus()},[r]),o=T.useCallback(()=>n(e),[n]),a=T.useCallback(()=>n(t),[n]);return T.createElement(T.Fragment,null,T.createElement(gl,{zoomIn:!0,ref:e,onLoseFocus:a}),T.createElement(gl,{ref:t,onLoseFocus:o}))}function tf(){const{render:e}=rt(),t=Bo();return e.buttonZoom?T.createElement(T.Fragment,null,e.buttonZoom(t)):T.createElement(ef,null)}function rf(e){var t;return(((t=e.srcSet)===null||t===void 0?void 0:t.length)||0)>0}function nf({current:e,preload:t},{type:r,source:n}){switch(r){case"fetch":return e?{current:e,preload:n}:{current:n};case"done":return n===t?{current:n}:{current:e,preload:t};default:throw new Error(Os)}}function of(e){var t,r;const[{current:n,preload:o},a]=T.useReducer(nf,{}),{slide:s,rect:l,imageFit:f,render:h,interactive:d}=e,i=s.srcSet.sort((O,_)=>O.width-_.width),u=(t=s.width)!==null&&t!==void 0?t:i[i.length-1].width,g=(r=s.height)!==null&&r!==void 0?r:i[i.length-1].height,p=Mo(s,f),m=Math.max(...i.map(O=>O.width)),w=Math.min((p?Math.max:Math.min)(l.width,u*(l.height/g)),m),x=eu(),A=Ie(()=>{var O;const _=(O=i.find(I=>I.width>=w*x))!==null&&O!==void 0?O:i[i.length-1];(!n||i.findIndex(I=>I.src===n)I===_))&&a({type:"fetch",source:_.src})});$t(A,[l.width,l.height,x,A]);const v=Ie(O=>a({type:"done",source:O})),E={WebkitTransform:d?"initial":"translateZ(0)"};return p||Object.assign(E,l.width/l.heightv(o),render:{...h,iconLoading:()=>null,iconError:()=>null}}),n&&T.createElement(ir,{key:"current",...e,slide:{...s,src:n,srcSet:void 0},style:E}))}function af({render:e,slide:t,offset:r,rect:n}){var o;const[a,s]=T.useState(),l=T.useRef(null),{zoom:f,maxZoom:h,offsetX:d,offsetY:i,setZoomWrapper:u}=Bo(),g=f>1,{carousel:p,on:m}=rt(),{currentIndex:w}=Ot();$t(()=>r===0?(u({zoomWrapperRef:l,imageDimensions:a}),()=>u(void 0)):()=>{},[r,a,u]);let x=(o=e.slide)===null||o===void 0?void 0:o.call(e,{slide:t,offset:r,rect:n,zoom:f,maxZoom:h});if(!x&&lr(t)){const A={slide:t,offset:r,rect:n,render:e,imageFit:p.imageFit,imageProps:p.imageProps,onClick:r===0?()=>{var v;return(v=m.click)===null||v===void 0?void 0:v.call(m,{index:w})}:void 0};x=rf(t)?T.createElement(of,{...A,slide:t,interactive:g,rect:r===0?{width:n.width*f,height:n.height*f}:n}):T.createElement(ir,{onLoad:v=>s({width:v.naturalWidth,height:v.naturalHeight}),...A})}return x?T.createElement("div",{ref:l,className:lt(pe(xs),pe(wr),pe(Cs),g&&pe(Yd)),style:r===0?{transform:`scale(${f}) translateX(${d}px) translateY(${i}px)`}:void 0},x):null}const sf=({augment:e,addModule:t})=>{e(({zoom:r,toolbar:n,render:o,controller:a,...s})=>{const l=cl(r);return{zoom:l,toolbar:Cn(n,ws,T.createElement(tf,null)),render:{...o,slide:f=>{var h;return lr(f.slide)?T.createElement(af,{render:o,...f}):(h=o.slide)===null||h===void 0?void 0:h.call(o,f)}},controller:{...a,preventDefaultWheelY:l.scrollToZoom},...s}}),t(Mt(ws,Qu))},lf={separator:"/",container:{}},hl=e=>({...lf,...e});function cf({counter:e}){const{slides:t,currentIndex:r}=Ot(),{separator:n,container:{className:o,...a},className:s,...l}=hl(e);return t.length===0?null:T.createElement("div",{className:lt(pe("counter"),o||s),...l,...a,"aria-hidden":!0},r+1," ",n," ",t.length)}function df({augment:e,addChild:t}){e(({counter:r,...n})=>({counter:hl(r),...n})),t(Wr,Mt(Hd,cf))}const uf={autoplay:!1,delay:3e3,ref:null},pl=e=>({...uf,...e}),ml=T.createContext(null),ff=At("useSlideshow","SlideshowContext",ml);function gf({slideshow:e,carousel:{finite:t},on:r,children:n}){const{autoplay:o,delay:a,ref:s}=pl(e),l=T.useRef(o),[f,h]=T.useState(o),d=T.useRef(void 0),i=T.useRef(void 0),{slides:u,currentIndex:g}=Ot(),{setTimeout:p,clearTimeout:m}=qr(),{subscribe:w}=_r(),{next:x}=zt(),{setAutoPlaying:A}=Fo();T.useEffect(()=>A(f),[f,A]);const v=u.length===0||t&&g===u.length-1,E=T.useCallback(()=>{!f&&!v&&h(!0)},[f,v]),O=T.useCallback(()=>{f&&h(!1)},[f]),_=T.useCallback(()=>{m(d.current),d.current=void 0},[m]),I=Ie(()=>{_(),!(!f||v||i.current===vr||i.current===Co)&&(d.current=p(()=>{f&&(i.current=void 0,x())},a))});T.useEffect(I,[g,f,I]),T.useEffect(()=>{f&&v&&h(!1)},[g,f,v]);const C=Ie(()=>{var M;return(M=r.slideshowStart)===null||M===void 0?void 0:M.call(r)}),y=Ie(()=>{var M;return(M=r.slideshowStop)===null||M===void 0?void 0:M.call(r)});T.useEffect(()=>{f?C():l.current&&y(),l.current=f},[f,C,y]),T.useEffect(()=>kr(_,w(jd,()=>{i.current=vr,_()}),w(Bd,()=>{i.current=Co,_()}),w(Wd,()=>{i.current=Yr,I()}),w(Kd,()=>{i.current=Xr,I()})),[w,_,I]);const N=T.useMemo(()=>({playing:f,disabled:v,play:E,pause:O}),[f,v,E,O]);return T.useImperativeHandle(s,()=>N,[N]),T.createElement(ml.Provider,{value:N},n)}const hf=mt("Play",T.createElement("path",{d:"M8 5v14l11-7z"})),pf=mt("Pause",T.createElement("path",{d:"M6 19h4V5H6v14zm8-14v14h4V5h-4z"}));function mf(){const{playing:e,disabled:t,play:r,pause:n}=ff(),{render:o}=rt(),a=Xs(zt().focus,t);return o.buttonSlideshow?T.createElement(T.Fragment,null,o.buttonSlideshow({playing:e,disabled:t,play:r,pause:n})):T.createElement(Er,{label:e?"Pause":"Play",icon:e?pf:hf,renderIcon:e?o.iconSlideshowPause:o.iconSlideshowPlay,onClick:e?n:r,disabled:t,...a})}function bf({augment:e,addModule:t}){e(({slideshow:r,toolbar:n,...o})=>({toolbar:Cn(n,vs,T.createElement(mf,null)),slideshow:pl(r),...o})),t(Mt(vs,gf))}const yf={auto:!1,ref:null},bl=e=>({...yf,...e}),yl=T.createContext(null),vf=At("useFullscreen","FullscreenContext",yl);function wf({fullscreen:e,on:t,children:r}){const{auto:n,ref:o}=bl(e),a=T.useRef(null),[s,l]=T.useState(),[f,h]=T.useState(!1),d=T.useRef(!1),{getOwnerDocument:i}=Sr();$t(()=>{var v,E,O,_;const I=i();l(!((_=(O=(E=(v=I.fullscreenEnabled)!==null&&v!==void 0?v:I.webkitFullscreenEnabled)!==null&&E!==void 0?E:I.mozFullScreenEnabled)!==null&&O!==void 0?O:I.msFullscreenEnabled)!==null&&_!==void 0&&_))},[i]);const u=T.useCallback(()=>{var v;const E=i(),O=E.fullscreenElement||E.webkitFullscreenElement||E.mozFullScreenElement||E.msFullscreenElement;return((v=O?.shadowRoot)===null||v===void 0?void 0:v.fullscreenElement)||O},[i]),g=T.useCallback(()=>{const v=a.current;try{v.requestFullscreen?v.requestFullscreen().catch(()=>{}):v.webkitRequestFullscreen?v.webkitRequestFullscreen():v.mozRequestFullScreen?v.mozRequestFullScreen():v.msRequestFullscreen&&v.msRequestFullscreen()}catch{}},[]),p=T.useCallback(()=>{if(!u())return;const v=i();try{v.exitFullscreen?v.exitFullscreen().catch(()=>{}):v.webkitExitFullscreen?v.webkitExitFullscreen():v.mozCancelFullScreen?v.mozCancelFullScreen():v.msExitFullscreen&&v.msExitFullscreen()}catch{}},[u,i]);T.useEffect(()=>{const v=i(),E=()=>{h(u()===a.current)};return kr(...["fullscreenchange","webkitfullscreenchange","mozfullscreenchange","MSFullscreenChange"].map(O=>(v.addEventListener(O,E),()=>v.removeEventListener(O,E))))},[u,i]);const m=Ie(()=>{var v;return(v=t.enterFullscreen)===null||v===void 0?void 0:v.call(t)}),w=Ie(()=>{var v;return(v=t.exitFullscreen)===null||v===void 0?void 0:v.call(t)});T.useEffect(()=>{f&&(d.current=!0),d.current&&(f?m:w)()},[f,m,w]);const x=Ie(()=>{var v;return(v=n?g:null)===null||v===void 0||v(),p});T.useEffect(x,[x]);const A=T.useMemo(()=>({fullscreen:f,disabled:s,enter:g,exit:p}),[f,s,g,p]);return T.useImperativeHandle(o,()=>A,[A]),T.createElement("div",{ref:a,className:lt(pe(Kr),pe(xs))},T.createElement(yl.Provider,{value:A},r))}const xf=mt("EnterFullscreen",T.createElement("path",{d:"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"})),kf=mt("ExitFullscreen",T.createElement("path",{d:"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"}));function Cf(){var e;const{fullscreen:t,disabled:r,enter:n,exit:o}=vf(),{render:a}=rt();return r?null:a.buttonFullscreen?T.createElement(T.Fragment,null,(e=a.buttonFullscreen)===null||e===void 0?void 0:e.call(a,{fullscreen:t,disabled:r,enter:n,exit:o})):T.createElement(Er,{disabled:r,label:t?"Exit Fullscreen":"Enter Fullscreen",icon:t?kf:xf,renderIcon:t?a.iconExitFullscreen:a.iconEnterFullscreen,onClick:t?o:n})}function Sf({augment:e,contains:t,addParent:r}){e(({fullscreen:n,toolbar:o,...a})=>({toolbar:Cn(o,Kr,T.createElement(Cf,null)),fullscreen:bl(n),...a})),r(t(Vr)?Vr:Wr,Mt(Kr,wf))}const dr={ref:null,position:"bottom",width:120,height:80,border:1,borderRadius:4,padding:4,gap:16,imageFit:"contain",vignette:!0,hidden:!1,showToggle:!1},Wo=e=>({...dr,...e});function vl(){const{thumbnails:e}=rt();return Wo(e)}const ur=e=>or(Vr,e),nt=e=>ur(or("thumbnail",e)),_f=mt("VideoThumbnail",T.createElement("path",{d:"M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"})),Ef=mt("UnknownThumbnail",T.createElement("path",{d:"M23 18V6c0-1.1-.9-2-2-2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zM8.5 12.5l2.5 3.01L14.5 11l4.5 6H5l3.5-4.5z"}));function Tf({slide:e,render:t,rect:r,imageFit:n}){var o;const a=(o=t.thumbnail)===null||o===void 0?void 0:o.call(t,{slide:e,render:t,rect:r,imageFit:n});if(a)return a;const s={render:t,rect:r,imageFit:n};if(e.thumbnail)return T.createElement(ir,{slide:{src:e.thumbnail},...s});if(lr(e))return T.createElement(ir,{slide:e,...s});const l=pe(nt(wn));return e.type==="video"?T.createElement(T.Fragment,null,e.poster&&T.createElement(ir,{slide:{src:e.poster},...s}),T.createElement(_f,{className:l})):T.createElement(Ef,{className:l})}const Nf=ar("active"),Ko=ar("fadein"),Vo=ar("fadeout"),Af=ar("placeholder"),wl="delay",xl="duration";function Mf({slide:e,index:t,onClick:r,fadeIn:n,fadeOut:o,placeholder:a,onLoseFocus:s}){const l=T.useRef(null),{render:f,styles:h,labels:d}=rt(),{slides:i,globalIndex:u}=Ot(),{getOwnerDocument:g}=Sr(),{width:p,height:m,imageFit:w}=vl(),x={width:p,height:m},A=t===u,v=Ie(s);return T.useEffect(()=>{o&&g().activeElement===l.current&&v()},[o,v,g]),T.createElement("button",{ref:l,type:"button",className:lt(pe(wr),pe(nt()),A&&pe(nt(Nf())),n&&pe(nt(Ko())),o&&pe(nt(Vo())),a&&pe(nt(Af()))),style:{...n?{[We(nt(Ko(xl)))]:`${n.duration}ms`,[We(nt(Ko(wl)))]:`${n.delay}ms`}:null,...o?{[We(nt(Vo(xl)))]:`${o.duration}ms`,[We(nt(Vo(wl)))]:`${o.delay}ms`}:null,...h.thumbnail},onClick:r,"aria-current":A?!0:void 0,"aria-label":Ds(d,i,t)},e&&Tf({slide:e,render:f,rect:x,imageFit:w}))}function kl(e){return["top","bottom"].includes(e)}function Cl(e,t){return t+2*(e.border+e.padding)+e.gap}function Of(e){const{thumbnail:t,poster:r}=e||{thumbnail:"placeholder"};return typeof t=="string"&&t||typeof r=="string"&&r||e&&Ls(e)||void 0}function Sl({visible:e,containerRef:t}){const r=T.useRef(null),n=_n(),{publish:o,subscribe:a}=_r(),{carousel:s,styles:l,labels:f}=rt(),{slides:h,globalIndex:d,animation:i}=Ot(),{registerSensors:u,subscribeSensors:g}=Zs();rl(g);const p=vl(),{position:m,width:w,height:x,border:A,borderStyle:v,borderColor:E,borderRadius:O,padding:_,gap:I,vignette:C}=p,y=i?.duration!==void 0&&i?.increment||0,N=i?.duration||0,{prepareAnimation:M}=Uo(r,S=>({keyframes:kl(m)?[{transform:`translateX(${(n?-1:1)*Cl(p,w)*y+S}px)`},{transform:"translateX(0)"}]:[{transform:`translateY(${Cl(p,x)*y+S}px)`},{transform:"translateY(0)"}],duration:N,easing:i?.easing})),P=Ie(()=>{let S=0;if(t.current&&r.current){const b=t.current.getBoundingClientRect(),$=r.current.getBoundingClientRect();S=kl(m)?$.left-b.left-(b.width-$.width)/2:$.top-b.top-(b.height-$.height)/2}M(S)});T.useEffect(()=>kr(a(_o,P)),[a,P]);const D=Ps(s,h),L=[];if(Io(h))for(let S=d-D-Math.abs(y);S<=d+D+Math.abs(y);S+=1){const $=s.finite&&(S<0||S>h.length-1)||y<0&&S0&&S>d+D?null:Do(h,S),F=[`${S}`,Of($)].filter(Boolean).join("|");L.push({key:F,index:S,slide:$})}const U=S=>()=>{S>d?o(er,{count:S-d}):S{const F=N/Math.abs(y||1),G=y>0&&b>d+D-y&&b<=d+D||y<0&&b=d-D?{duration:F,delay:((y>0?b-(d+D-y):d-D-y-b)-1)*F}:void 0,Y=y>0&&bd+D?{duration:F,delay:(y>0?y-(d-D-b):-y-(b-(d+D)))*F}:void 0;return T.createElement(Mf,{key:S,index:b,slide:$,fadeIn:G,fadeOut:Y,placeholder:!$,onClick:U(b),onLoseFocus:()=>{var B;return(B=r.current)===null||B===void 0?void 0:B.focus()}})})),C&&T.createElement("div",{className:pe(ur("vignette"))}))}const _l=T.createContext(null),If=At("useThumbnails","ThumbnailsContext",_l);function Df({children:e,...t}){const{ref:r,position:n,hidden:o}=Wo(t.thumbnails),[a,s]=T.useState(!o),l=T.useRef(null),f=T.useMemo(()=>({visible:a,show:()=>s(!0),hide:()=>s(!1)}),[a]);return T.useImperativeHandle(r,()=>f,[f]),T.createElement(Gs,{...t},T.createElement(_l.Provider,{value:f},T.createElement("div",{ref:l,className:lt(pe(ur()),pe(ur(`${n}`)))},["start","top"].includes(n)&&T.createElement(Sl,{containerRef:l,visible:a}),T.createElement("div",{className:pe(ur("wrapper"))},e),["end","bottom"].includes(n)&&T.createElement(Sl,{containerRef:l,visible:a}))))}const El=()=>T.createElement(T.Fragment,null,T.createElement("path",{strokeWidth:2,stroke:"currentColor",strokeLinejoin:"round",fill:"none",d:"M3 5l18 0l0 14l-18 0l0-14z"}),T.createElement("path",{d:"M5 14h4v3h-4zM10 14h4v3h-4zM15 14h4v3h-4z"})),Lf=mt("ThumbnailsVisible",El()),Pf=fu("ThumbnailsHidden",El());function Ff(){const{visible:e,show:t,hide:r}=If(),{render:n}=rt();return n.buttonThumbnails?T.createElement(T.Fragment,null,n.buttonThumbnails({visible:e,show:t,hide:r})):T.createElement(Er,{label:e?"Hide thumbnails":"Show thumbnails",icon:e?Lf:Pf,renderIcon:e?n.iconThumbnailsVisible:n.iconThumbnailsHidden,onClick:e?r:t})}function $f({augment:e,contains:t,append:r,addParent:n}){e(({thumbnails:a,toolbar:s,...l})=>{const f=Wo(a);return{toolbar:Cn(s,Vr,f.showToggle?T.createElement(Ff,null):null),thumbnails:f,...l}});const o=Mt(Vr,Df);t(Kr)?r(Kr,o):n(Wr,o)}const Ct=({className:e="",children:t,style:r,...n})=>c.jsx("i",{className:e,style:r,...n,children:t}),Yo=window.G7Core,Tn=(e,t)=>Yo?.t?.(e,t)??e,Uf=async(e,t)=>{try{const r=await Yo.api.get(e,{responseType:"blob"});if(r){const n=URL.createObjectURL(r),o=document.createElement("a");o.href=n,o.download=t,document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(n)}}catch(r){console.error("Failed to download file:",r),Yo?.toast?.error?.(Tn("common.download_failed"))}},zf=(e,t)=>{const r=document.createElement("a");r.href=e,r.download=t,r.target="_blank",document.body.appendChild(r),r.click(),document.body.removeChild(r)},Tl=async e=>{const t=e.downloadUrl||e.src,r=e.filename||e.title||"image";e.downloadRequiresAuth?await Uf(t,r):zf(t,r)},Hf=({image:e,index:t,onDownload:r})=>{const[n,o]=k.useState(!1),a=async s=>{if(s.stopPropagation(),r){r(e,t);return}o(!0);try{await Tl(e)}finally{o(!1)}};return c.jsx(Q,{type:"button",onClick:a,disabled:n,className:"yarl__button flex items-center justify-center","aria-label":Tn("common.download"),title:Tn("common.download"),children:n?c.jsx(Ct,{className:"fa-solid fa-spinner fa-spin text-white"}):c.jsx(Ct,{className:"fa-solid fa-download text-white"})})},Tr=({images:e,isOpen:t,onClose:r,startIndex:n=0,enableZoom:o=!0,enableSlideshow:a=!1,enableFullscreen:s=!0,showCounter:l=!0,showDownload:f=!0,showThumbnails:h=!0,onDownload:d,editorAttrs:i,id:u})=>{const[g,p]=k.useState(n),m=k.useRef(n),w=e.map(v=>({src:v.src,title:v.title,description:v.description})),x=[];o&&x.push(sf),a&&x.push(bf),s&&x.push(Sf),l&&x.push(df),h&&x.push($f);const A=e[g];if(k.useEffect(()=>{m.current=g},[g]),i){const v=(e??[]).slice(0,4);return c.jsx(W,{id:u,className:"grid grid-cols-2 gap-2 p-3 rounded-lg border border-dashed border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800",...i,children:v.length>0?v.map((E,O)=>c.jsx(Lt,{src:E.thumbnail||E.src,alt:E.title||"",className:"w-full aspect-square object-cover rounded bg-gray-200 dark:bg-gray-700"},O)):c.jsxs(W,{className:"col-span-2 flex items-center justify-center py-6 text-sm text-gray-400 dark:text-gray-500",children:[c.jsx(Ct,{className:"fa-regular fa-images mr-2"}),Tn("editor.component.image_gallery")]})})}return c.jsx(Bu,{open:t,close:r,slides:w,index:g,plugins:x,on:{view:({index:v})=>{v!==m.current&&p(v)}},zoom:{maxZoomPixelRatio:3,zoomInMultiplier:2,doubleTapDelay:300,doubleClickDelay:300,doubleClickMaxStops:2,keyboardMoveDistance:50,wheelZoomDistanceFactor:100,pinchZoomDistanceFactor:100,scrollToZoom:!0},carousel:{finite:!0,preload:2,padding:"16px",spacing:"30%"},animation:{fade:250,swipe:500,easing:{fade:"ease",swipe:"ease-out",navigation:"ease-in-out"}},controller:{closeOnBackdropClick:!0,closeOnPullDown:!0,closeOnPullUp:!0},thumbnails:{position:"bottom",width:120,height:80,border:2,borderRadius:4,padding:4,gap:16,showToggle:!1,vignette:!0},toolbar:{buttons:[f&&A&&c.jsx(Hf,{image:A,index:g,onDownload:d},"download"),"close"].filter(Boolean)},styles:{container:{backgroundColor:"rgba(0, 0, 0, 0.9)"}}})},Nl=()=>{const[e,t]=k.useState(!1),[r,n]=k.useState([]),[o,a]=k.useState(0),s=k.useCallback((f,h=0)=>{n(f),a(h),t(!0)},[]),l=k.useCallback(()=>{t(!1)},[]);return{isOpen:e,openGallery:s,closeGallery:l,galleryProps:{images:r,isOpen:e,onClose:l,startIndex:o}}};Tr.displayName="ImageGallery";const Al=Object.freeze(Object.defineProperty({__proto__:null,ImageGallery:Tr,default:Tr,executeImageDownload:Tl,useImageGallery:Nl},Symbol.toStringTag,{value:"Module"})),Gf=window.G7Core,Xo=(e,t)=>Gf?.t?.(e,t)??e,Nn=e=>e.url??e.download_url,An=({images:e=[],className:t="",id:r,editorAttrs:n})=>{const[o,a]=k.useState(0),{openGallery:s,galleryProps:l}=Nl(),f=k.useMemo(()=>e.map(d=>({src:Nn(d),title:d.alt_text_current??"",thumbnail:Nn(d),downloadUrl:d.download_url,filename:d.alt_text_current??`image-${d.id}`})),[e]);if(!e||e.length===0)return c.jsx(W,{className:`flex items-center justify-center bg-gray-100 dark:bg-gray-700 rounded-lg aspect-square ${t}`,id:r,...n,children:c.jsxs(W,{className:"text-center text-gray-400 dark:text-gray-500",children:[c.jsx(de,{name:"image",size:"3x",className:"mb-3 opacity-50"}),c.jsx(W,{className:"text-sm",children:Xo("shop.no_image")})]})});const h=e[o]??e[0];return c.jsxs(W,{id:r,className:t,...n,children:[c.jsx(W,{className:"relative overflow-hidden rounded-lg bg-gray-100 dark:bg-gray-700 aspect-square mb-3",children:c.jsx(Q,{type:"button",className:"w-full h-full cursor-zoom-in block",onClick:()=>s(f,o),"aria-label":Xo("shop.view_image"),children:c.jsx(Lt,{src:Nn(h),alt:h.alt_text_current??"",className:"w-full h-full object-contain"})})}),e.length>1&&c.jsx(W,{className:"flex gap-2 overflow-x-auto pb-1",children:e.map((d,i)=>c.jsx(Q,{type:"button",className:`flex-shrink-0 w-16 h-16 rounded-md overflow-hidden border-2 transition-colors cursor-pointer ${i===o?"border-gray-900 dark:border-white":"border-gray-200 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-400"}`,onClick:()=>a(i),"aria-label":d.alt_text_current??`${Xo("shop.image")} ${i+1}`,children:c.jsx(Lt,{src:Nn(d),alt:d.alt_text_current??"",className:"w-full h-full object-cover"})},d.id))}),c.jsx(Tr,{...l})]})};An.displayName="ProductImageViewer";const jf=Object.freeze(Object.defineProperty({__proto__:null,ProductImageViewer:An,default:An},Symbol.toStringTag,{value:"Module"})),Ml=({value:e,min:t=1,max:r=999,onChange:n,size:o="md",disabled:a=!1,className:s="",id:l,editorAttrs:f})=>{const d={sm:{container:"h-8",button:"w-8 h-8 text-sm",input:"w-10 text-sm"},md:{container:"h-10",button:"w-10 h-10",input:"w-14"},lg:{container:"h-12",button:"w-12 h-12 text-lg",input:"w-16 text-lg"}}[o],i=()=>{e>t&&!a&&n(e-1)},u=()=>{e{const A=parseInt(x.target.value,10);if(!isNaN(A)){const v=Math.max(t,Math.min(r,A));n(v)}},p=x=>{const A=parseInt(x.target.value,10);isNaN(A)||Ar&&n(r)},m=a||e<=t,w=a||e>=r;return c.jsxs(W,{className:`inline-flex items-center border border-gray-300 dark:border-gray-600 rounded-lg ${d.container} ${s}`,id:l,...f,children:[c.jsx(Q,{type:"button",onClick:i,disabled:m,className:`${d.button} flex items-center justify-center text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed rounded-l-lg transition-colors`,"aria-label":"수량 감소",children:c.jsx(de,{name:"minus",className:"w-4 h-4"})}),c.jsx(xt,{type:"number",value:e,onChange:g,onBlur:p,min:t,max:r,disabled:a,className:`${d.input} text-center border-x border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`,"aria-label":"수량"}),c.jsx(Q,{type:"button",onClick:u,disabled:w,className:`${d.button} flex items-center justify-center text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed rounded-r-lg transition-colors`,"aria-label":"수량 증가",children:c.jsx(de,{name:"plus",className:"w-4 h-4"})})]})},Bf=Object.freeze(Object.defineProperty({__proto__:null,default:Ml},Symbol.toStringTag,{value:"Module"})),Wf=window.G7Core?.createLogger?.("Comp:PostReactions")??{log:(...e)=>console.log("[Comp:PostReactions]",...e),warn:(...e)=>console.warn("[Comp:PostReactions]",...e),error:(...e)=>console.error("[Comp:PostReactions]",...e)},Ol=(e,t)=>window.G7Core?.t?.(e,t)??e,Kf=[{type:"like",emoji:"👍",labelKey:"board.reactions.like",activeColor:"bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400"},{type:"funny",emoji:"😂",labelKey:"board.reactions.funny",activeColor:"bg-yellow-100 dark:bg-yellow-900/30 text-yellow-600 dark:text-yellow-400"},{type:"agree",emoji:"👌",labelKey:"board.reactions.agree",activeColor:"bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400"},{type:"thanks",emoji:"🙏",labelKey:"board.reactions.thanks",activeColor:"bg-purple-100 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400"},{type:"wow",emoji:"😮",labelKey:"board.reactions.wow",activeColor:"bg-orange-100 dark:bg-orange-900/30 text-orange-600 dark:text-orange-400"}],Il=({reactions:e,userReaction:t,postId:r,onReact:n,size:o="md",className:a="",id:s,editorAttrs:l})=>{const f={sm:"px-2 py-1 text-xs gap-1",md:"px-3 py-1.5 text-sm gap-1.5",lg:"px-4 py-2 text-base gap-2"},h={sm:"text-sm",md:"text-base",lg:"text-lg"},d=u=>e.find(p=>p.type===u)?.count??0,i=async u=>{if(n){n(u);return}try{if(!(await fetch(`/api/posts/${r}/reactions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:u}),credentials:"include"})).ok)throw new Error("리액션 처리 실패");window.location.reload()}catch(g){Wf.error("리액션 오류:",g)}};return c.jsx(W,{className:`flex flex-wrap gap-2 ${a}`,id:s,...l,children:Kf.map(u=>{const g=d(u.type),p=t===u.type;return c.jsxs(Q,{onClick:()=>i(u.type),className:` + `,children:[c.jsx(de,{name:Je.Moon,className:"w-5 h-5 text-gray-600 dark:text-gray-400"}),c.jsx(ee,{className:"flex-1 text-left text-gray-900 dark:text-white",children:o}),f==="dark"&&c.jsx(de,{name:Je.Check,className:"w-4 h-4 text-blue-600 dark:text-blue-400 ml-auto"})]})]})})]})},Qc=Object.freeze(Object.defineProperty({__proto__:null,ThemeToggle:hn,default:hn},Symbol.toStringTag,{value:"Module"})),Ja={xs:"w-6 h-6 text-xs",sm:"w-8 h-8 text-sm",md:"w-10 h-10 text-base",lg:"w-12 h-12 text-lg",xl:"w-16 h-16 text-xl","2xl":"w-24 h-24 text-2xl","3xl":"w-32 h-32 text-3xl","4xl":"w-40 h-40 text-4xl","5xl":"w-48 h-48 text-5xl"},Jc="rounded-full overflow-hidden flex-shrink-0 border border-gray-200 dark:border-gray-700",Rc="grayscale opacity-50",co={normal:"bg-gradient-to-br from-blue-500 to-purple-600",withdrawn:"bg-gray-300 dark:bg-gray-600",guest:"bg-gray-200 dark:bg-gray-700"},Ur=({author:e,name:t,avatar:r,size:n="md",className:o="",text:a,isWithdrawn:s=!1,isGuest:l=!1,id:f,editorAttrs:h})=>{const d=r??e?.avatar,i=a??t??e?.name??"?",u=s||e?.status==="withdrawn",g=l||e?.is_guest||!1,p=k.useMemo(()=>[Ja[n]||Ja.md,Jc,u?Rc:"",o].filter(Boolean).join(" "),[n,u,o]),m=g?co.guest:u?co.withdrawn:co.normal,w=()=>g?c.jsx(W,{className:`w-full h-full flex items-center justify-center ${m}`,children:c.jsx(de,{name:"user",className:"text-gray-400 dark:text-gray-500"})}):u?c.jsx(W,{className:`w-full h-full flex items-center justify-center ${m}`,children:c.jsx(de,{name:"user",className:"text-gray-500 dark:text-gray-400"})}):c.jsx(W,{className:`w-full h-full flex items-center justify-center text-white font-semibold ${m}`,children:i.charAt(0).toUpperCase()});return c.jsx(W,{className:p,id:f,...h,children:d&&!g&&!u?c.jsx(Lt,{src:d,alt:i,className:"w-full h-full object-cover"}):w()})},ed=Object.freeze(Object.defineProperty({__proto__:null,Avatar:Ur},Symbol.toStringTag,{value:"Module"})),td=window.G7Core?.createLogger?.("Comp:SlotContainer")??{log:(...e)=>console.log("[Comp:SlotContainer]",...e),warn:(...e)=>console.warn("[Comp:SlotContainer]",...e),error:(...e)=>console.error("[Comp:SlotContainer]",...e)};function Ra(e,t){return t&&e&&typeof e.id=="string"&&e.id.length>0?{...e,id:`${e.id}__${t}`}:e}const pn=({slotId:e,className:t="",emptyContent:r,style:n,id:o,children:a})=>{const[s,l]=k.useState([]),[,f]=k.useState({}),h=k.useCallback(()=>{const p=window.__slotContextValue;if(p)return p;const m=window.G7Core;return m&&m.getSlotContext?.()||null},[]),d=k.useCallback(()=>{const p=h();p&&p.isEnabled&&l(p.getSlotComponents(e))},[e,h]);k.useEffect(()=>{const p=h();return!p||!p.isEnabled?void 0:(d(),p.subscribeToSlot(e,()=>{d(),f({})}))},[e,h,d]);const i=k.useCallback(()=>{const p=window.G7Core;return p?p.getDynamicRenderer?.():null},[]);if(s.length===0)return r?c.jsx(W,{className:t,style:n,id:o,children:r}):a?c.jsx(W,{className:t,style:n,id:o,children:a}):null;const u=i(),g=window.G7Core;return!u||!g?(td.error("G7Core or DynamicRenderer not available"),null):c.jsxs(W,{className:t,style:n,id:o,children:[s.map(p=>{const{componentDef:m,dataContext:w,parentFormContext:x,getParentComponentContext:O,translationContext:y}=p,E=Ra(m,o);return c.jsx(u,{componentDef:E,dataContext:w,translationContext:y,registry:g.getComponentRegistry(),bindingEngine:g.getDataBindingEngine(),translationEngine:g.getTranslationEngine(),actionDispatcher:g.getActionDispatcher(),parentComponentContext:O?.(),parentFormContextProp:x,isRootRenderer:!1},E.id||`slot-${e}-${p.order}`)}),a]})},rd=Object.freeze(Object.defineProperty({__proto__:null,SlotContainer:pn,default:pn,scopeSlotChildDef:Ra},Symbol.toStringTag,{value:"Module"})),mn=({notifications:e=[],unreadCount:t=0,hasMore:r=!1,loading:n=!1,titleText:o="알림",emptyText:a="알림이 없습니다.",markAllReadText:s="모두 읽음",deleteAllText:l="모두 삭제",unreadOnlyText:f="안 읽은 알림만",unreadOnly:h=!1,onNotificationClick:d,onClose:i,onLoadMore:u,onMarkAllRead:g,onDeleteAll:p,onDelete:m,onUnreadOnlyToggle:w,dropdownAlign:x="right",className:O="",id:y,editorAttrs:E})=>{const[M,_]=k.useState(!1),I=k.useRef(null),C=k.useRef(null),v=k.useRef(null),N=k.useRef(null),A=k.useRef(new Set),P=k.useRef(u),D=k.useRef(r),L=k.useRef(n),U=k.useRef(e.length),S=k.useRef(-1);k.useEffect(()=>{P.current=u,D.current=r,L.current=n,U.current=e.length}),k.useEffect(()=>{if(!N.current||!v.current||!M)return;S.current=-1;const G=new IntersectionObserver(([Y])=>{Y.isIntersecting&&(L.current||!D.current||S.current!==U.current&&(S.current=U.current,P.current?.()))},{root:v.current,threshold:.1});return G.observe(N.current),()=>G.disconnect()},[M]),k.useEffect(()=>{if(!v.current||!M)return;const G=new IntersectionObserver(B=>{B.forEach(V=>{const j=V.target.getAttribute("data-notification-id"),H=V.target.getAttribute("data-unread")==="true";j&&H&&V.isIntersecting&&A.current.add(j)})},{root:v.current,threshold:.5});return v.current.querySelectorAll("[data-notification-id]").forEach(B=>G.observe(B)),()=>G.disconnect()},[M,e]);const b=t>0?t:e.filter(G=>!G.read).length,$=k.useCallback(()=>{if(M){if(b>0){const G=Array.from(A.current).filter(Y=>{const B=e.find(V=>String(V.id)===String(Y));return B&&!B.read});G.length>0&&i?.(G)}A.current.clear(),_(!1)}},[M,i,b,e]);k.useEffect(()=>{if(!M)return;const G=Y=>{I.current&&!I.current.contains(Y.target)&&$()};return document.addEventListener("mousedown",G),()=>document.removeEventListener("mousedown",G)},[M,$]);const F=k.useCallback(()=>{M?$():_(!0)},[M,$]);return k.useLayoutEffect(()=>{const G=C.current;if(!M||!G)return;G.style.transform="";const Y=G.getBoundingClientRect(),B=typeof window<"u"?window.innerWidth:0;if(Y.width===0&&Y.height===0)return;const V=8;let j=0;Y.right>B-V?j=-(Y.right-(B-V)):Y.left0&&c.jsx(ee,{className:"absolute -top-1 -right-1 w-5 h-5 flex items-center justify-center text-xs font-bold text-white bg-red-500 dark:bg-red-600 rounded-full",children:b>99?"99+":b})]}),M&&c.jsxs(W,{ref:C,className:`absolute ${x==="left"?"left-0":"right-0"} mt-2 w-80 max-w-[calc(100vw-1rem)] bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg z-50`,children:[c.jsxs(W,{className:"px-4 py-3 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between gap-2",children:[c.jsxs(W,{className:"flex items-center gap-3 min-w-0",children:[c.jsx(ee,{className:"font-semibold text-gray-900 dark:text-white",children:o}),w&&c.jsxs(W,{className:"flex items-center gap-1.5 cursor-pointer select-none",onClick:()=>w(!h),children:[c.jsx(xt,{type:"checkbox",checked:h,onChange:G=>{G.stopPropagation(),w(G.target.checked)},onClick:G=>G.stopPropagation(),className:"w-3.5 h-3.5 rounded border-gray-300 dark:border-gray-600 text-blue-600 dark:text-blue-400 focus:ring-blue-500 dark:focus:ring-blue-400 cursor-pointer"}),c.jsx(ee,{className:"text-xs text-gray-600 dark:text-gray-400",children:f})]})]}),c.jsxs(W,{className:"flex items-center gap-3 flex-shrink-0",children:[g&&b>0&&c.jsx(Q,{onClick:()=>{g(),A.current.clear()},className:"text-xs text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 hover:underline cursor-pointer",children:s}),p&&e.length>0&&c.jsx(Q,{onClick:()=>{p()},className:"text-xs text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300 hover:underline cursor-pointer",children:l})]})]}),c.jsx(W,{ref:v,className:"max-h-96 overflow-y-auto",children:e.length===0&&!n?c.jsx(W,{className:"px-4 py-8 text-center text-gray-500 dark:text-gray-400",children:c.jsx(ee,{children:a})}):c.jsxs(c.Fragment,{children:[e.map(G=>{const Y=!G.read;return c.jsxs(W,{"data-notification-id":G.id,"data-unread":Y?"true":"false",onClick:()=>{G.onClick?.(),d?.(G),_(!1)},className:`group flex items-start gap-3 px-4 py-3 text-left border-b border-gray-100 dark:border-gray-700 transition-colors cursor-pointer ${Y?"bg-blue-50/70 dark:bg-blue-900/20 hover:bg-blue-50 dark:hover:bg-blue-900/30":"bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700/50 opacity-70"}`,children:[G.iconName&&c.jsx(de,{name:G.iconName,className:`w-5 h-5 mt-0.5 flex-shrink-0 ${Y?"text-blue-600 dark:text-blue-400":"text-gray-400 dark:text-gray-500"}`}),c.jsxs(W,{className:"flex-1 min-w-0",children:[c.jsx(W,{className:`text-sm truncate ${Y?"font-semibold text-gray-900 dark:text-white":"font-normal text-gray-600 dark:text-gray-400"}`,children:G.title}),c.jsx(W,{className:`text-sm mt-1 line-clamp-2 ${Y?"text-gray-700 dark:text-gray-300":"text-gray-500 dark:text-gray-500"}`,children:G.message}),c.jsx(W,{className:"text-gray-400 dark:text-gray-500 text-xs mt-1 font-mono",children:G.time})]}),c.jsxs(W,{className:"flex flex-col items-center gap-2 flex-shrink-0",children:[Y&&c.jsx(ee,{className:"w-2 h-2 bg-blue-500 dark:bg-blue-400 rounded-full mt-1.5"}),m&&c.jsx(Q,{onClick:B=>{B.stopPropagation(),m(G)},className:"p-1 text-gray-400 dark:text-gray-500 hover:text-red-600 dark:hover:text-red-400 rounded hover:bg-red-50 dark:hover:bg-red-900/20 cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity","aria-label":"Delete notification",children:c.jsx(de,{name:Je.Trash,className:"w-4 h-4"})})]})]},G.id)}),r&&c.jsx(W,{ref:N,className:"px-4 py-3 text-center",children:n?c.jsx(ee,{className:"text-sm text-gray-400 dark:text-gray-500",children:"..."}):c.jsx(ee,{className:"text-sm text-gray-400 dark:text-gray-500"})}),n&&!r&&e.length>0&&c.jsx(W,{className:"px-4 py-2 text-center",children:c.jsx(ee,{className:"text-sm text-gray-400 dark:text-gray-500",children:"..."})})]})})]})]})},nd=Object.freeze(Object.defineProperty({__proto__:null,NotificationCenter:mn,default:mn},Symbol.toStringTag,{value:"Module"})),Xe=(e,t)=>window.G7Core?.t?.(e,t)??e,pt=e=>{window.G7Core?.dispatch?.({handler:"navigate",params:{path:e}})},es=({logo:e,siteName:t="그누보드7",user:r,cartCount:n=0,notificationCount:o=0,boards:a=[],maxVisibleBoards:s=5,onMobileMenuOpen:l,availableLocales:f=[],currentLocale:h="ko",shopBase:d="/shop",className:i="",editorAttrs:u,notifications:g=[],notificationHasMore:p=!1,notificationLoading:m=!1,notificationUnreadOnly:w=!1,notificationTitleText:x,notificationEmptyText:O,notificationMarkAllReadText:y,notificationDeleteAllText:E,notificationUnreadOnlyText:M,onNotificationClose:_,onNotificationClick:I,onNotificationLoadMore:C,onNotificationMarkAllRead:v,onNotificationDeleteAll:N,onNotificationDelete:A,onNotificationUnreadOnlyToggle:P})=>{const[D,L]=k.useState(""),[U,S]=k.useState(!1),[b,$]=k.useState(!1),[F,G]=k.useState(!1),[Y,B]=k.useState({top:0,left:0}),[V,j]=k.useState(window.location.pathname),H=k.useRef(null),q=k.useRef(null),ue=k.useRef(null),fe=window.G7Core?.useResponsive,R=fe?.(),ke=R?R.width<768:typeof window<"u"&&window.innerWidth<768;k.useEffect(()=>{const K=()=>j(window.location.pathname);window.addEventListener("popstate",K);const re=history.pushState;return history.pushState=function(...oe){re.apply(this,oe),j(window.location.pathname)},()=>{window.removeEventListener("popstate",K),history.pushState=re}},[]);const me=(K,re=!1)=>re?V===K:V===K||V.startsWith(K+"/"),Ge=()=>{const K=d==="/"?"":d;return V.startsWith(`${K}/products`)||V.startsWith(`${K}/cart`)||V.startsWith(`${K}/checkout`)||V.startsWith(`${K}/category`)},De=K=>{const re="px-3 py-2 text-sm font-medium whitespace-nowrap cursor-pointer rounded-lg transition-colors";return K?`${re} bg-gray-900 text-white dark:bg-white dark:text-gray-900`:`${re} text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-800`};k.useEffect(()=>{const K=re=>{H.current&&!H.current.contains(re.target)&&S(!1),q.current&&!q.current.contains(re.target)&&$(!1),ue.current&&!ue.current.contains(re.target)&&G(!1)};return document.addEventListener("mousedown",K),()=>document.removeEventListener("mousedown",K)},[]);const ye=a.slice(0,s),Me=a.slice(s),Ce=K=>{K.preventDefault(),D.trim()&&pt(`/search?q=${encodeURIComponent(D)}`)},we=async()=>{window.G7Core?.dispatch?.({handler:"logout"})},$e=K=>{window.G7Core?.dispatch?.({handler:"setLocale",target:K}),G(!1)},Le=K=>window.G7Core?.state?.get?.("_global.appConfig.localeNames")?.[K]??(K==="ko"?"한국어":K==="en"?"English":K==="ja"?"日本語":K==="zh"?"中文":K==="es"?"Español":K==="fr"?"Français":K==="de"?"Deutsch":K.toUpperCase());return c.jsxs(qc,{...u??{},className:`sticky top-0 z-50 bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800 ${i}`,children:[c.jsx(W,{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",children:c.jsxs(W,{className:"flex items-center justify-between h-16",children:[c.jsx(Q,{onClick:()=>pt("/"),className:"flex items-center gap-2 flex-shrink-0 cursor-pointer",children:e?c.jsx(Lt,{src:e,alt:t,className:"h-8"}):c.jsx(ee,{className:"text-xl font-bold text-gray-900 dark:text-white",children:t})}),!ke&&c.jsx(so,{onSubmit:Ce,className:"flex flex-1 max-w-lg mx-8",children:c.jsxs(W,{className:"relative w-full",children:[c.jsx(xt,{type:"text",value:D,onChange:K=>L(K.target.value),placeholder:Xe("common.search_placeholder"),className:"w-full px-4 py-2 pl-10 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500"}),c.jsx(de,{name:"search",className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 dark:text-gray-500"})]})}),c.jsxs(W,{className:"flex items-center gap-2",children:[c.jsx(hn,{autoText:Xe("common.theme.auto"),lightText:Xe("common.theme.light"),darkText:Xe("common.theme.dark")}),r?.uuid&&c.jsx(mn,{notifications:g,unreadCount:o,hasMore:p,loading:m,unreadOnly:w,titleText:x??Xe("mypage.notifications.title"),emptyText:O??Xe("mypage.notifications.empty"),markAllReadText:y??Xe("mypage.notifications.mark_all_read"),deleteAllText:E??Xe("mypage.notifications.delete_all"),unreadOnlyText:M??Xe("mypage.notifications.unread_only"),onClose:_,onNotificationClick:I,onLoadMore:C,onMarkAllRead:v,onDeleteAll:N,onDelete:A,onUnreadOnlyToggle:P,dropdownAlign:"right"}),c.jsxs(Q,{onClick:()=>pt(`${d}/cart`),className:"relative p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white cursor-pointer",children:[c.jsx(de,{name:"shopping-cart",className:"w-5 h-5"}),n>0&&c.jsx(ee,{className:"absolute -top-1 -right-1 w-5 h-5 flex items-center justify-center text-xs bg-blue-500 text-white rounded-full",children:n>99?"99+":n})]}),f&&f.length>1&&c.jsxs(W,{ref:ue,className:"relative",children:[c.jsxs(Q,{onClick:()=>G(!F),className:"flex items-center gap-1.5 px-2.5 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg cursor-pointer transition-colors","aria-haspopup":"listbox","aria-expanded":F,"aria-label":Xe("common.language"),children:[c.jsx(de,{name:"globe",className:"w-4 h-4"}),c.jsx(ee,{className:"font-medium uppercase",children:h}),c.jsx(de,{name:"chevron-down",className:"w-3 h-3"})]}),F&&c.jsx(W,{role:"listbox",className:"absolute right-0 mt-2 w-44 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg py-1 z-50 overflow-hidden",children:f.map(K=>{const re=K===h;return c.jsxs(Q,{role:"option","aria-selected":re,onClick:()=>$e(K),className:`w-full px-4 py-2.5 text-left text-sm flex items-center gap-3 cursor-pointer transition-colors ${re?"bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"}`,children:[c.jsx(de,{name:"globe",className:"w-4 h-4"}),c.jsx(ee,{className:"flex-1 font-medium",children:Le(K)}),re&&c.jsx(de,{name:"check",className:"w-4 h-4"})]},K)})})]}),c.jsx(pn,{slotId:"header_currency",id:"header_currency_slot_desktop",className:"flex items-center"}),r?.uuid?c.jsxs(W,{ref:H,className:"relative",children:[c.jsxs(Q,{onClick:()=>S(!U),className:"flex items-center gap-2 p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white",children:[c.jsx(Ur,{avatar:r.avatar,name:r.name,size:"sm"}),c.jsx(ee,{className:"hidden sm:inline text-sm font-medium",children:r.name}),c.jsx(de,{name:"chevron-down",className:"w-4 h-4"})]}),U&&c.jsxs(W,{className:"absolute right-0 mt-2 w-56 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg py-1 z-50",children:[c.jsx(W,{className:"px-4 py-3 border-b border-gray-200 dark:border-gray-700",children:c.jsxs(W,{className:"flex items-center gap-3",children:[c.jsx(Ur,{avatar:r.avatar,name:r.name,size:"md"}),c.jsxs(W,{children:[c.jsx(W,{className:"text-sm font-medium text-gray-900 dark:text-white",children:r.name}),c.jsx(W,{className:"text-xs text-gray-500 dark:text-gray-400",children:Xe("common.member")})]})]})}),c.jsxs(W,{className:"py-1",children:[r.is_admin&&c.jsxs(c.Fragment,{children:[c.jsxs(ao,{href:"/admin",className:"block w-full text-left px-4 py-2 text-sm text-blue-600 dark:text-blue-400 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer font-medium",children:[c.jsx(de,{name:"settings",className:"inline w-4 h-4 mr-2"}),Xe("common.admin_menu")]}),c.jsx(lo,{className:"my-1 border-gray-200 dark:border-gray-700"})]}),c.jsxs(Q,{onClick:()=>{pt("/mypage"),S(!1)},className:"block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer",children:[c.jsx(de,{name:"user",className:"inline w-4 h-4 mr-2"}),Xe("common.mypage")]}),c.jsxs(Q,{onClick:()=>{pt("/mypage/orders"),S(!1)},className:"block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer",children:[c.jsx(de,{name:"shopping-bag",className:"inline w-4 h-4 mr-2"}),Xe("mypage.tabs.orders")]}),c.jsxs(Q,{onClick:()=>{pt("/mypage/wishlist"),S(!1)},className:"block w-full text-left px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer",children:[c.jsx(de,{name:"heart",className:"inline w-4 h-4 mr-2"}),Xe("mypage.tabs.wishlist")]})]}),c.jsx(lo,{className:"my-1 border-gray-200 dark:border-gray-700"}),c.jsxs(Q,{onClick:we,className:"block w-full text-left px-4 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer",children:[c.jsx(de,{name:"log-out",className:"inline w-4 h-4 mr-2"}),Xe("auth.logout")]})]})]}):c.jsxs(W,{className:"flex items-center gap-1.5",children:[c.jsx(Q,{onClick:()=>pt("/login?redirect=/mypage/orders"),className:"px-2.5 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white cursor-pointer",children:Xe("shop.guest_order_form.nav_link")}),c.jsx(Q,{onClick:()=>pt("/login"),className:"px-2.5 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white cursor-pointer",children:Xe("auth.login")}),c.jsx(Q,{onClick:()=>pt("/register"),className:"ml-1 px-3 py-2 text-sm font-medium text-white bg-emerald-500 rounded-lg hover:bg-emerald-600 cursor-pointer",children:Xe("auth.register_link")})]}),ke&&c.jsx(Q,{onClick:l,className:"p-2 text-gray-600 dark:text-gray-400",children:c.jsx(de,{name:"menu",className:"w-6 h-6"})})]})]})}),!ke&&c.jsx($r,{className:"border-t border-gray-200 dark:border-gray-800",children:c.jsx(W,{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",children:c.jsxs(W,{className:"flex items-center gap-1 h-12 overflow-x-auto",children:[c.jsx(Q,{onClick:()=>pt("/"),className:De(me("/",!0)),"data-testid":"nav-home",children:Xe("nav.home")}),c.jsxs(Q,{onClick:()=>pt("/boards/popular"),className:`flex items-center gap-1 ${De(me("/boards/popular"))}`,"data-testid":"nav-popular",children:[c.jsx(ee,{className:"text-orange-500",children:"🔥"}),Xe("nav.popular")]}),c.jsxs(Q,{onClick:()=>pt(`${d==="/"?"":d}/products`),className:`flex items-center gap-1 ${De(Ge())}`,"data-testid":"nav-shop",children:[c.jsx(ee,{children:"🛒"}),Xe("nav.shop")]}),ye.map(K=>c.jsxs(Q,{onClick:()=>pt(`/board/${K.slug}`),className:De(me(`/board/${K.slug}`)),children:[K.icon&&c.jsx(ee,{className:"mr-1",children:K.icon}),K.name]},K.id)),Me.length>0&&c.jsxs(W,{ref:q,className:"relative",children:[c.jsxs(Q,{onClick:()=>{if(!b&&q.current){const K=q.current.getBoundingClientRect();B({top:K.bottom+4,left:K.left})}$(!b)},className:"flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white",children:[Xe("nav.more"),c.jsx(de,{name:"chevron-down",className:"w-4 h-4"})]}),b&&c.jsx(W,{className:"fixed w-48 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg py-1 z-50",style:{top:`${Y.top}px`,left:`${Y.left}px`},children:Me.map(K=>{const re=me(`/board/${K.slug}`);return c.jsxs(Q,{onClick:()=>{pt(`/board/${K.slug}`),$(!1)},className:`block w-full text-left px-4 py-2 text-sm cursor-pointer ${re?"bg-gray-900 text-white dark:bg-white dark:text-gray-900":"text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"}`,children:[K.icon&&c.jsx(ee,{className:"mr-1",children:K.icon}),K.name]},K.id)})})]})]})})})]})},od=Object.freeze(Object.defineProperty({__proto__:null,default:es},Symbol.toStringTag,{value:"Module"})),ad=k.forwardRef(({children:e,className:t="",...r},n)=>c.jsx("footer",{ref:n,className:t,...r,children:e})),kt=(e,t)=>window.G7Core?.t?.(e,t)??e,sd=768,ts=1024,ld=e=>{window.G7Core?.dispatch?.({handler:"navigate",params:{path:e}})},rs=({siteName:e="그누보드7",siteDescription:t,copyrightText:r,socialLinks:n={},linkGroups:o,className:a="",editorAttrs:s})=>{const l=new Date().getFullYear(),h=window.G7Core?.useResponsive,i=h?.()?.width??(typeof window<"u"?window.innerWidth:ts),u=i=ts,p=u?1:g?5:2,m=[{title:kt("footer.community"),links:[{label:kt("nav.home"),href:"/"},{label:kt("nav.popular"),href:"/boards/popular"},{label:kt("footer.all_boards"),href:"/boards"}]},{title:kt("footer.info"),links:[{label:kt("footer.about"),href:"/page/about"},{label:kt("footer.faq"),href:"/page/faq"},{label:kt("footer.contact"),href:"/page/contact"}]},{title:kt("footer.policy"),links:[{label:kt("footer.terms"),href:"/page/terms"},{label:kt("footer.privacy"),href:"/page/privacy"},{label:kt("footer.refund"),href:"/page/refund"}]}],w=o||m,x={github:"github",twitter:"twitter",discord:"discord",facebook:"facebook",instagram:"instagram"};return c.jsx(ad,{...s??{},className:`bg-gray-50 dark:bg-gray-900 border-t border-gray-200 dark:border-gray-800 ${a}`,children:c.jsxs(W,{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12",children:[c.jsxs(W,{className:"grid gap-8",style:{gridTemplateColumns:`repeat(${p}, minmax(0, 1fr))`},children:[c.jsxs(W,{style:g?{gridColumn:"span 2 / span 2"}:void 0,children:[c.jsx(gn,{className:"text-lg font-bold text-gray-900 dark:text-white",children:e}),t&&c.jsx(Dt,{className:"mt-2 text-sm text-gray-600 dark:text-gray-400",children:t}),c.jsx(W,{className:"mt-4 flex items-center gap-4",children:Object.entries(n).map(([O,y])=>y?c.jsx(ao,{href:y,target:"_blank",rel:"noopener noreferrer",className:"text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200","aria-label":O,children:c.jsx(de,{name:x[O],className:"w-5 h-5"})},O):null)})]}),w.map((O,y)=>c.jsxs(W,{children:[c.jsx(Ya,{className:"text-sm font-semibold text-gray-900 dark:text-white uppercase tracking-wider",children:O.title}),c.jsx(oo,{className:"mt-4 space-y-2",children:O.links.map((E,M)=>c.jsx(Xt,{children:c.jsx(Q,{onClick:()=>ld(E.href),className:"text-sm text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white cursor-pointer",children:E.label})},M))})]},y))]}),c.jsxs(W,{className:"mt-8 pt-8 border-t border-gray-200 dark:border-gray-800 flex justify-between items-center gap-4",style:{flexDirection:u?"column":"row"},children:[c.jsx(Dt,{className:"text-sm text-gray-500 dark:text-gray-400",children:r||`© ${l} ${e}. All rights reserved.`}),c.jsx(Dt,{className:"text-sm text-gray-500 dark:text-gray-400",children:kt("footer.powered_by")})]})]})})},id=Object.freeze(Object.defineProperty({__proto__:null,default:rs},Symbol.toStringTag,{value:"Module"})),Pt=(e,t)=>window.G7Core?.t?.(e,t)??e,Tt=e=>{window.G7Core?.dispatch?.({handler:"navigate",params:{path:e}})},ns=({isOpen:e,onClose:t,logo:r,siteName:n="그누보드7",user:o,boards:a=[],cartCount:s=0})=>{const l=k.useRef(null),h=window.G7Core?.useResponsive,d=h?.(),i=d?d.width<1024:typeof window<"u"&&window.innerWidth<1024;k.useEffect(()=>{const g=p=>{p.key==="Escape"&&t()};return e&&(document.addEventListener("keydown",g),document.body.style.overflow="hidden"),()=>{document.removeEventListener("keydown",g),document.body.style.overflow=""}},[e,t]);const u=g=>{g.target===g.currentTarget&&t()};return!e||!i?null:c.jsxs(W,{className:"fixed inset-0 z-50",onClick:u,children:[c.jsx(W,{className:"fixed inset-0 bg-black/50 transition-opacity"}),c.jsxs(W,{ref:l,className:`fixed inset-y-0 left-0 w-80 max-w-[85vw] bg-white dark:bg-gray-900 shadow-xl transform transition-transform duration-300 ${e?"translate-x-0":"-translate-x-full"}`,children:[c.jsxs(W,{className:"flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-800",children:[c.jsx(Q,{onClick:()=>{t(),Tt("/")},className:"flex items-center gap-2 cursor-pointer",children:r?c.jsx(Lt,{src:r,alt:n,className:"h-8"}):c.jsx(ee,{className:"text-xl font-bold text-gray-900 dark:text-white",children:n})}),c.jsx(Q,{onClick:t,className:"p-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200","aria-label":"메뉴 닫기",children:c.jsx(de,{name:"x",className:"w-6 h-6"})})]}),o?c.jsx(W,{className:"p-4 border-b border-gray-200 dark:border-gray-800",children:c.jsxs(W,{className:"flex items-center gap-3",children:[o.avatar?c.jsx(Lt,{src:o.avatar,alt:o.name,className:"w-12 h-12 rounded-full"}):c.jsx(W,{className:"w-12 h-12 rounded-full bg-blue-500 flex items-center justify-center text-white text-lg font-medium",children:(o.name||"U").charAt(0).toUpperCase()}),c.jsxs(W,{children:[c.jsx(Dt,{className:"font-medium text-gray-900 dark:text-white",children:o.name}),c.jsx(Q,{onClick:()=>{t(),Tt("/mypage")},className:"text-sm text-blue-600 dark:text-blue-400 hover:underline cursor-pointer",children:Pt("common.mypage")})]})]})}):c.jsx(W,{className:"p-4 border-b border-gray-200 dark:border-gray-800",children:c.jsxs(W,{className:"flex gap-2",children:[c.jsx(Q,{onClick:()=>{t(),Tt("/login")},className:"flex-1 py-2 text-center text-sm font-medium text-white bg-gray-900 dark:bg-white dark:text-gray-900 rounded-lg cursor-pointer",children:Pt("auth.login")}),c.jsx(Q,{onClick:()=>{t(),Tt("/register")},className:"flex-1 py-2 text-center text-sm font-medium text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg cursor-pointer",children:Pt("auth.register")})]})}),c.jsx($r,{className:"p-4 overflow-y-auto max-h-[calc(100vh-200px)]",children:c.jsxs(oo,{className:"space-y-1",children:[c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt("/")},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[c.jsx(de,{name:"home",className:"w-5 h-5"}),Pt("nav.home")]})}),c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt("/popular")},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[c.jsx(ee,{className:"text-orange-500",children:"🔥"}),Pt("nav.popular")]})}),c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt("/shop")},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[c.jsx(ee,{children:"🛒"}),Pt("nav.shop")]})}),c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt("/cart")},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[c.jsx(de,{name:"shopping-cart",className:"w-5 h-5"}),Pt("nav.cart"),s>0&&c.jsx(ee,{className:"ml-auto px-2 py-0.5 text-xs bg-blue-500 text-white rounded-full",children:s})]})}),c.jsx(Xt,{className:"my-4 border-t border-gray-200 dark:border-gray-800"}),c.jsx(Xt,{className:"px-3 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider",children:Pt("nav.boards")}),a.map(g=>c.jsx(Xt,{children:c.jsxs(Q,{onClick:()=>{t(),Tt(`/board/${g.slug}`)},className:"flex items-center gap-3 px-3 py-2 w-full text-left text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg cursor-pointer",children:[g.icon&&c.jsx(ee,{children:g.icon}),g.name]})},g.id))]})}),c.jsx(W,{className:"absolute bottom-0 left-0 right-0 p-4 border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900",children:c.jsxs(W,{className:"flex items-center justify-between text-sm text-gray-500 dark:text-gray-400",children:[c.jsx(Q,{onClick:()=>{t(),Tt("/about")},className:"hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer",children:Pt("footer.about")}),c.jsx(Q,{onClick:()=>{t(),Tt("/terms")},className:"hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer",children:Pt("footer.terms")}),c.jsx(Q,{onClick:()=>{t(),Tt("/privacy")},className:"hover:text-gray-700 dark:hover:text-gray-200 cursor-pointer",children:Pt("footer.privacy")})]})})]})]})},cd=Object.freeze(Object.defineProperty({__proto__:null,default:ns},Symbol.toStringTag,{value:"Module"}));const{entries:os,setPrototypeOf:as,isFrozen:dd,getPrototypeOf:ud,getOwnPropertyDescriptor:fd}=Object;let{freeze:ft,seal:Nt,create:uo}=Object,{apply:fo,construct:go}=typeof Reflect<"u"&&Reflect;ft||(ft=function(t){return t}),Nt||(Nt=function(t){return t}),fo||(fo=function(t,r){for(var n=arguments.length,o=new Array(n>2?n-2:0),a=2;a1?r-1:0),o=1;o1?r-1:0),o=1;o2&&arguments[2]!==void 0?arguments[2]:yn;as&&as(e,null);let n=t.length;for(;n--;){let o=t[n];if(typeof o=="string"){const a=r(o);a!==o&&(dd(t)||(t[n]=a),o=a)}e[o]=!0}return e}function yd(e){for(let t=0;t/gm),Cd=Nt(/\$\{[\w\W]*/gm),Sd=Nt(/^data-[\-\w.\u00B7-\uFFFF]+$/),_d=Nt(/^aria-[\-\w]+$/),us=Nt(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),Ed=Nt(/^(?:\w+script|data):/i),Td=Nt(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),fs=Nt(/^html$/i),Nd=Nt(/^[a-z][.\w]*(-[.\w]+)+$/i);var gs=Object.freeze({__proto__:null,ARIA_ATTR:_d,ATTR_WHITESPACE:Td,CUSTOM_ELEMENT:Nd,DATA_ATTR:Sd,DOCTYPE_NAME:fs,ERB_EXPR:kd,IS_ALLOWED_URI:us,IS_SCRIPT_OR_DATA:Ed,MUSTACHE_EXPR:xd,TMPLIT_EXPR:Cd});const Br={element:1,text:3,progressingInstruction:7,comment:8,document:9},Ad=function(){return typeof window>"u"?null:window},Md=function(t,r){if(typeof t!="object"||typeof t.createPolicy!="function")return null;let n=null;const o="data-tt-policy-suffix";r&&r.hasAttribute(o)&&(n=r.getAttribute(o));const a="dompurify"+(n?"#"+n:"");try{return t.createPolicy(a,{createHTML(s){return s},createScriptURL(s){return s}})}catch{return console.warn("TrustedTypes policy "+a+" could not be created."),null}},hs=function(){return{afterSanitizeAttributes:[],afterSanitizeElements:[],afterSanitizeShadowDOM:[],beforeSanitizeAttributes:[],beforeSanitizeElements:[],beforeSanitizeShadowDOM:[],uponSanitizeAttribute:[],uponSanitizeElement:[],uponSanitizeShadowNode:[]}};function ps(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Ad();const t=ge=>ps(ge);if(t.version="3.3.1",t.removed=[],!e||!e.document||e.document.nodeType!==Br.document||!e.Element)return t.isSupported=!1,t;let{document:r}=e;const n=r,o=n.currentScript,{DocumentFragment:a,HTMLTemplateElement:s,Node:l,Element:f,NodeFilter:h,NamedNodeMap:d=e.NamedNodeMap||e.MozNamedAttrMap,HTMLFormElement:i,DOMParser:u,trustedTypes:g}=e,p=f.prototype,m=jr(p,"cloneNode"),w=jr(p,"remove"),x=jr(p,"nextSibling"),O=jr(p,"childNodes"),y=jr(p,"parentNode");if(typeof s=="function"){const ge=r.createElement("template");ge.content&&ge.content.ownerDocument&&(r=ge.content.ownerDocument)}let E,M="";const{implementation:_,createNodeIterator:I,createDocumentFragment:C,getElementsByTagName:v}=r,{importNode:N}=n;let A=hs();t.isSupported=typeof os=="function"&&typeof y=="function"&&_&&_.createHTMLDocument!==void 0;const{MUSTACHE_EXPR:P,ERB_EXPR:D,TMPLIT_EXPR:L,DATA_ATTR:U,ARIA_ATTR:S,IS_SCRIPT_OR_DATA:b,ATTR_WHITESPACE:$,CUSTOM_ELEMENT:F}=gs;let{IS_ALLOWED_URI:G}=gs,Y=null;const B=Ae({},[...ls,...mo,...bo,...yo,...is]);let V=null;const j=Ae({},[...cs,...vo,...ds,...vn]);let H=Object.seal(uo(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),q=null,ue=null;const te=Object.seal(uo(null,{tagCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeCheck:{writable:!0,configurable:!1,enumerable:!0,value:null}}));let fe=!0,R=!0,ke=!1,me=!0,Ge=!1,De=!0,ye=!1,Me=!1,Ce=!1,we=!1,$e=!1,Le=!1,K=!0,re=!1;const oe="user-content-";let ae=!0,be=!1,xe={},He=null;const Pe=Ae({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Ke=null;const Oe=Ae({},["audio","video","img","source","image","track"]);let X=null;const se=Ae({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),ie="http://www.w3.org/1998/Math/MathML",le="http://www.w3.org/2000/svg",ne="http://www.w3.org/1999/xhtml";let Te=ne,ve=!1,Se=null;const _e=Ae({},[ie,le,ne],ho);let Ue=Ae({},["mi","mo","mn","ms","mtext"]),je=Ae({},["annotation-xml"]);const Ee=Ae({},["title","style","font","a","script"]);let he=null;const Ne=["application/xhtml+xml","text/html"],Ve="text/html";let Fe=null,Be=null;const Ze=r.createElement("form"),qt=function(z){return z instanceof RegExp||z instanceof Function},qe=function(){let z=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};if(!(Be&&Be===z)){if((!z||typeof z!="object")&&(z={}),z=Kt(z),he=Ne.indexOf(z.PARSER_MEDIA_TYPE)===-1?Ve:z.PARSER_MEDIA_TYPE,Fe=he==="application/xhtml+xml"?ho:yn,Y=Ft(z,"ALLOWED_TAGS")?Ae({},z.ALLOWED_TAGS,Fe):B,V=Ft(z,"ALLOWED_ATTR")?Ae({},z.ALLOWED_ATTR,Fe):j,Se=Ft(z,"ALLOWED_NAMESPACES")?Ae({},z.ALLOWED_NAMESPACES,ho):_e,X=Ft(z,"ADD_URI_SAFE_ATTR")?Ae(Kt(se),z.ADD_URI_SAFE_ATTR,Fe):se,Ke=Ft(z,"ADD_DATA_URI_TAGS")?Ae(Kt(Oe),z.ADD_DATA_URI_TAGS,Fe):Oe,He=Ft(z,"FORBID_CONTENTS")?Ae({},z.FORBID_CONTENTS,Fe):Pe,q=Ft(z,"FORBID_TAGS")?Ae({},z.FORBID_TAGS,Fe):Kt({}),ue=Ft(z,"FORBID_ATTR")?Ae({},z.FORBID_ATTR,Fe):Kt({}),xe=Ft(z,"USE_PROFILES")?z.USE_PROFILES:!1,fe=z.ALLOW_ARIA_ATTR!==!1,R=z.ALLOW_DATA_ATTR!==!1,ke=z.ALLOW_UNKNOWN_PROTOCOLS||!1,me=z.ALLOW_SELF_CLOSE_IN_ATTR!==!1,Ge=z.SAFE_FOR_TEMPLATES||!1,De=z.SAFE_FOR_XML!==!1,ye=z.WHOLE_DOCUMENT||!1,we=z.RETURN_DOM||!1,$e=z.RETURN_DOM_FRAGMENT||!1,Le=z.RETURN_TRUSTED_TYPE||!1,Ce=z.FORCE_BODY||!1,K=z.SANITIZE_DOM!==!1,re=z.SANITIZE_NAMED_PROPS||!1,ae=z.KEEP_CONTENT!==!1,be=z.IN_PLACE||!1,G=z.ALLOWED_URI_REGEXP||us,Te=z.NAMESPACE||ne,Ue=z.MATHML_TEXT_INTEGRATION_POINTS||Ue,je=z.HTML_INTEGRATION_POINTS||je,H=z.CUSTOM_ELEMENT_HANDLING||{},z.CUSTOM_ELEMENT_HANDLING&&qt(z.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(H.tagNameCheck=z.CUSTOM_ELEMENT_HANDLING.tagNameCheck),z.CUSTOM_ELEMENT_HANDLING&&qt(z.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(H.attributeNameCheck=z.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),z.CUSTOM_ELEMENT_HANDLING&&typeof z.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=="boolean"&&(H.allowCustomizedBuiltInElements=z.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),Ge&&(R=!1),$e&&(we=!0),xe&&(Y=Ae({},is),V=[],xe.html===!0&&(Ae(Y,ls),Ae(V,cs)),xe.svg===!0&&(Ae(Y,mo),Ae(V,vo),Ae(V,vn)),xe.svgFilters===!0&&(Ae(Y,bo),Ae(V,vo),Ae(V,vn)),xe.mathMl===!0&&(Ae(Y,yo),Ae(V,ds),Ae(V,vn))),z.ADD_TAGS&&(typeof z.ADD_TAGS=="function"?te.tagCheck=z.ADD_TAGS:(Y===B&&(Y=Kt(Y)),Ae(Y,z.ADD_TAGS,Fe))),z.ADD_ATTR&&(typeof z.ADD_ATTR=="function"?te.attributeCheck=z.ADD_ATTR:(V===j&&(V=Kt(V)),Ae(V,z.ADD_ATTR,Fe))),z.ADD_URI_SAFE_ATTR&&Ae(X,z.ADD_URI_SAFE_ATTR,Fe),z.FORBID_CONTENTS&&(He===Pe&&(He=Kt(He)),Ae(He,z.FORBID_CONTENTS,Fe)),z.ADD_FORBID_CONTENTS&&(He===Pe&&(He=Kt(He)),Ae(He,z.ADD_FORBID_CONTENTS,Fe)),ae&&(Y["#text"]=!0),ye&&Ae(Y,["html","head","body"]),Y.table&&(Ae(Y,["tbody"]),delete q.tbody),z.TRUSTED_TYPES_POLICY){if(typeof z.TRUSTED_TYPES_POLICY.createHTML!="function")throw Gr('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if(typeof z.TRUSTED_TYPES_POLICY.createScriptURL!="function")throw Gr('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');E=z.TRUSTED_TYPES_POLICY,M=E.createHTML("")}else E===void 0&&(E=Md(g,o)),E!==null&&typeof M=="string"&&(M=E.createHTML(""));ft&&ft(z),Be=z}},jt=Ae({},[...mo,...bo,...vd]),_t=Ae({},[...yo,...wd]),Bt=function(z){let Z=y(z);(!Z||!Z.tagName)&&(Z={namespaceURI:Te,tagName:"template"});const ce=yn(z.tagName),Ye=yn(Z.tagName);return Se[z.namespaceURI]?z.namespaceURI===le?Z.namespaceURI===ne?ce==="svg":Z.namespaceURI===ie?ce==="svg"&&(Ye==="annotation-xml"||Ue[Ye]):!!jt[ce]:z.namespaceURI===ie?Z.namespaceURI===ne?ce==="math":Z.namespaceURI===le?ce==="math"&&je[Ye]:!!_t[ce]:z.namespaceURI===ne?Z.namespaceURI===le&&!je[Ye]||Z.namespaceURI===ie&&!Ue[Ye]?!1:!_t[ce]&&(Ee[ce]||!jt[ce]):!!(he==="application/xhtml+xml"&&Se[z.namespaceURI]):!1},dt=function(z){zr(t.removed,{element:z});try{y(z).removeChild(z)}catch{w(z)}},Et=function(z,Z){try{zr(t.removed,{attribute:Z.getAttributeNode(z),from:Z})}catch{zr(t.removed,{attribute:null,from:Z})}if(Z.removeAttribute(z),z==="is")if(we||$e)try{dt(Z)}catch{}else try{Z.setAttribute(z,"")}catch{}},Wt=function(z){let Z=null,ce=null;if(Ce)z=""+z;else{const Qe=po(z,/^[\r\n\t ]+/);ce=Qe&&Qe[0]}he==="application/xhtml+xml"&&Te===ne&&(z=''+z+"");const Ye=E?E.createHTML(z):z;if(Te===ne)try{Z=new u().parseFromString(Ye,he)}catch{}if(!Z||!Z.documentElement){Z=_.createDocument(Te,"template",null);try{Z.documentElement.innerHTML=ve?M:Ye}catch{}}const ut=Z.body||Z.documentElement;return z&&ce&&ut.insertBefore(r.createTextNode(ce),ut.childNodes[0]||null),Te===ne?v.call(Z,ye?"html":"body")[0]:ye?Z.documentElement:ut},nr=function(z){return I.call(z.ownerDocument||z,z,h.SHOW_ELEMENT|h.SHOW_COMMENT|h.SHOW_TEXT|h.SHOW_PROCESSING_INSTRUCTION|h.SHOW_CDATA_SECTION,null)},mr=function(z){return z instanceof i&&(typeof z.nodeName!="string"||typeof z.textContent!="string"||typeof z.removeChild!="function"||!(z.attributes instanceof d)||typeof z.removeAttribute!="function"||typeof z.setAttribute!="function"||typeof z.namespaceURI!="string"||typeof z.insertBefore!="function"||typeof z.hasChildNodes!="function")},_c=function(z){return typeof l=="function"&&z instanceof l};function Zt(ge,z,Z){bn(ge,ce=>{ce.call(t,z,Z,Be)})}const Ec=function(z){let Z=null;if(Zt(A.beforeSanitizeElements,z,null),mr(z))return dt(z),!0;const ce=Fe(z.nodeName);if(Zt(A.uponSanitizeElement,z,{tagName:ce,allowedTags:Y}),De&&z.hasChildNodes()&&!_c(z.firstElementChild)&>(/<[/\w!]/g,z.innerHTML)&>(/<[/\w!]/g,z.textContent)||z.nodeType===Br.progressingInstruction||De&&z.nodeType===Br.comment&>(/<[/\w]/g,z.data))return dt(z),!0;if(!(te.tagCheck instanceof Function&&te.tagCheck(ce))&&(!Y[ce]||q[ce])){if(!q[ce]&&Nc(ce)&&(H.tagNameCheck instanceof RegExp&>(H.tagNameCheck,ce)||H.tagNameCheck instanceof Function&&H.tagNameCheck(ce)))return!1;if(ae&&!He[ce]){const Ye=y(z)||z.parentNode,ut=O(z)||z.childNodes;if(ut&&Ye){const Qe=ut.length;for(let wt=Qe-1;wt>=0;--wt){const Qt=m(ut[wt],!0);Qt.__removalCount=(z.__removalCount||0)+1,Ye.insertBefore(Qt,x(z))}}}return dt(z),!0}return z instanceof f&&!Bt(z)||(ce==="noscript"||ce==="noembed"||ce==="noframes")&>(/<\/no(script|embed|frames)/i,z.innerHTML)?(dt(z),!0):(Ge&&z.nodeType===Br.text&&(Z=z.textContent,bn([P,D,L],Ye=>{Z=Hr(Z,Ye," ")}),z.textContent!==Z&&(zr(t.removed,{element:z.cloneNode()}),z.textContent=Z)),Zt(A.afterSanitizeElements,z,null),!1)},Tc=function(z,Z,ce){if(K&&(Z==="id"||Z==="name")&&(ce in r||ce in Ze))return!1;if(!(R&&!ue[Z]&>(U,Z))){if(!(fe&>(S,Z))){if(!(te.attributeCheck instanceof Function&&te.attributeCheck(Z,z))){if(!V[Z]||ue[Z]){if(!(Nc(z)&&(H.tagNameCheck instanceof RegExp&>(H.tagNameCheck,z)||H.tagNameCheck instanceof Function&&H.tagNameCheck(z))&&(H.attributeNameCheck instanceof RegExp&>(H.attributeNameCheck,Z)||H.attributeNameCheck instanceof Function&&H.attributeNameCheck(Z,z))||Z==="is"&&H.allowCustomizedBuiltInElements&&(H.tagNameCheck instanceof RegExp&>(H.tagNameCheck,ce)||H.tagNameCheck instanceof Function&&H.tagNameCheck(ce))))return!1}else if(!X[Z]){if(!gt(G,Hr(ce,$,""))){if(!((Z==="src"||Z==="xlink:href"||Z==="href")&&z!=="script"&&pd(ce,"data:")===0&&Ke[z])){if(!(ke&&!gt(b,Hr(ce,$,"")))){if(ce)return!1}}}}}}}return!0},Nc=function(z){return z!=="annotation-xml"&&po(z,F)},Ac=function(z){Zt(A.beforeSanitizeAttributes,z,null);const{attributes:Z}=z;if(!Z||mr(z))return;const ce={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:V,forceKeepAttr:void 0};let Ye=Z.length;for(;Ye--;){const ut=Z[Ye],{name:Qe,namespaceURI:wt,value:Qt}=ut,Fr=Fe(Qe),ja=Qt;let st=Qe==="value"?ja:md(ja);if(ce.attrName=Fr,ce.attrValue=st,ce.keepAttr=!0,ce.forceKeepAttr=void 0,Zt(A.uponSanitizeAttribute,z,ce),st=ce.attrValue,re&&(Fr==="id"||Fr==="name")&&(Et(Qe,z),st=oe+st),De&>(/((--!?|])>)|<\/(style|title|textarea)/i,st)){Et(Qe,z);continue}if(Fr==="attributename"&&po(st,"href")){Et(Qe,z);continue}if(ce.forceKeepAttr)continue;if(!ce.keepAttr){Et(Qe,z);continue}if(!me&>(/\/>/i,st)){Et(Qe,z);continue}Ge&&bn([P,D,L],Oc=>{st=Hr(st,Oc," ")});const Mc=Fe(z.nodeName);if(!Tc(Mc,Fr,st)){Et(Qe,z);continue}if(E&&typeof g=="object"&&typeof g.getAttributeType=="function"&&!wt)switch(g.getAttributeType(Mc,Fr)){case"TrustedHTML":{st=E.createHTML(st);break}case"TrustedScriptURL":{st=E.createScriptURL(st);break}}if(st!==ja)try{wt?z.setAttributeNS(wt,Qe,st):z.setAttribute(Qe,st),mr(z)?dt(z):ss(t.removed)}catch{Et(Qe,z)}}Zt(A.afterSanitizeAttributes,z,null)},Gp=function ge(z){let Z=null;const ce=nr(z);for(Zt(A.beforeSanitizeShadowDOM,z,null);Z=ce.nextNode();)Zt(A.uponSanitizeShadowNode,Z,null),Ec(Z),Ac(Z),Z.content instanceof a&&ge(Z.content);Zt(A.afterSanitizeShadowDOM,z,null)};return t.sanitize=function(ge){let z=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},Z=null,ce=null,Ye=null,ut=null;if(ve=!ge,ve&&(ge=""),typeof ge!="string"&&!_c(ge))if(typeof ge.toString=="function"){if(ge=ge.toString(),typeof ge!="string")throw Gr("dirty is not a string, aborting")}else throw Gr("toString is not a function");if(!t.isSupported)return ge;if(Me||qe(z),t.removed=[],typeof ge=="string"&&(be=!1),be){if(ge.nodeName){const Qt=Fe(ge.nodeName);if(!Y[Qt]||q[Qt])throw Gr("root node is forbidden and cannot be sanitized in-place")}}else if(ge instanceof l)Z=Wt(""),ce=Z.ownerDocument.importNode(ge,!0),ce.nodeType===Br.element&&ce.nodeName==="BODY"||ce.nodeName==="HTML"?Z=ce:Z.appendChild(ce);else{if(!we&&!Ge&&!ye&&ge.indexOf("<")===-1)return E&&Le?E.createHTML(ge):ge;if(Z=Wt(ge),!Z)return we?null:Le?M:""}Z&&Ce&&dt(Z.firstChild);const Qe=nr(be?ge:Z);for(;Ye=Qe.nextNode();)Ec(Ye),Ac(Ye),Ye.content instanceof a&&Gp(Ye.content);if(be)return ge;if(we){if($e)for(ut=C.call(Z.ownerDocument);Z.firstChild;)ut.appendChild(Z.firstChild);else ut=Z;return(V.shadowroot||V.shadowrootmode)&&(ut=N.call(n,ut,!0)),ut}let wt=ye?Z.outerHTML:Z.innerHTML;return ye&&Y["!doctype"]&&Z.ownerDocument&&Z.ownerDocument.doctype&&Z.ownerDocument.doctype.name&>(fs,Z.ownerDocument.doctype.name)&&(wt=" +`+wt),Ge&&bn([P,D,L],Qt=>{wt=Hr(wt,Qt," ")}),E&&Le?E.createHTML(wt):wt},t.setConfig=function(){let ge=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};qe(ge),Me=!0},t.clearConfig=function(){Be=null,Me=!1},t.isValidAttribute=function(ge,z,Z){Be||qe({});const ce=Fe(ge),Ye=Fe(z);return Tc(ce,Ye,Z)},t.addHook=function(ge,z){typeof z=="function"&&zr(A[ge],z)},t.removeHook=function(ge,z){if(z!==void 0){const Z=gd(A[ge],z);return Z===-1?void 0:hd(A[ge],Z,1)[0]}return ss(A[ge])},t.removeHooks=function(ge){A[ge]=[]},t.removeAllHooks=function(){A=hs()},t}var wo=ps();const Od=()=>{const e=()=>{const n=window.G7Core?.state?.get?.();return n&&n.preferredCurrency||"KRW"},[t,r]=k.useState(e);return k.useEffect(()=>{const n=window.G7Core?.state?.subscribe;if(r(e()),typeof n!="function")return;const o=n(a=>{r(a&&a.preferredCurrency||"KRW")});return typeof o=="function"?o:void 0},[]),t},Id=(e,t=!1)=>{window.G7Core?.dispatch?.({handler:"navigate",params:t?{path:e,mergeQuery:!0,query:{}}:{path:e}})},Dd=e=>{const t=Math.round(e*2)/2;return[1,2,3,4,5].map(r=>t>=r?"full":t>=r-.5?"half":"empty")},ms=({product:e,onClick:t,shopBase:r="/shop",preserveListQuery:n=!1,className:o="",id:a,editorAttrs:s})=>{const l=Od(),f=y=>{const E=`multi_currency_${y}`,M=e[E];if(M&&M[l])return M[l].formatted;const _=`${y}_formatted`;return e[_]},h=e.name_localized??(typeof e.name=="string"?e.name:"")??"",d=f("selling_price"),i=f("list_price"),u=e.discount_rate&&e.discount_rate>0,g=e.sales_status&&e.sales_status!=="on_sale",p=e.labels??[],m=y=>wo.sanitize(y,{ALLOWED_TAGS:["mark"],ALLOWED_ATTR:[]}),w=e.name_highlighted,x=e.description_highlighted??e.short_description,O=()=>{if(t)t(e.id);else{const y=r==="/"?"":r,E=e.product_code??e.id;Id(`${y}/products/${E}`,n)}};return c.jsxs(Q,{onClick:O,className:`block w-full text-left group bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden hover:shadow-lg transition-shadow cursor-pointer ${o}`,id:a,...s,children:[c.jsxs(W,{className:"relative aspect-square overflow-hidden bg-gray-100 dark:bg-gray-700",children:[c.jsx(Lt,{src:e.thumbnail_url,alt:h,className:"w-full h-full object-cover group-hover:scale-105 transition-transform duration-200",loading:"lazy"}),g&&c.jsx(W,{className:"absolute inset-0 bg-black/50 flex items-center justify-center",children:c.jsx(ee,{className:`text-lg font-bold ${e.sales_status==="sold_out"?"text-red-300":e.sales_status==="suspended"?"text-amber-300":"text-blue-300"}`,style:{textShadow:"0 1px 4px rgba(0,0,0,0.6)"},children:e.sales_status_label??e.sales_status})}),u&&e.sales_status!=="sold_out"&&e.sales_status!=="suspended"&&c.jsxs(ee,{className:"absolute top-2 left-2 px-2 py-1 bg-red-500 text-white text-xs font-bold rounded",children:[e.discount_rate,"%"]}),p.length>0&&c.jsx(W,{className:"absolute bottom-2 right-2 flex gap-1 flex-wrap justify-end",children:p.map((y,E)=>c.jsx(ee,{className:"text-xs text-white font-medium px-1.5 py-0.5 rounded",style:{backgroundColor:y.color||"#6b7280"},children:y.name},E))})]}),c.jsxs(W,{className:"p-4",children:[c.jsxs(W,{className:"flex items-center gap-1.5 flex-wrap",children:[e.primary_category&&c.jsx(ee,{className:"inline-block text-xs font-medium text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/30 px-2 py-0.5 rounded",children:e.primary_category}),e.brand_name&&c.jsx(ee,{className:"text-xs text-gray-500 dark:text-gray-400",children:e.brand_name})]}),w?c.jsx(W,{className:"mt-1 font-medium text-gray-900 dark:text-white line-clamp-1 [&_mark]:bg-yellow-200 [&_mark]:dark:bg-yellow-500/40 [&_mark]:px-0.5 [&_mark]:rounded",dangerouslySetInnerHTML:{__html:m(w)}}):c.jsx(gn,{className:"mt-1 font-medium text-gray-900 dark:text-white line-clamp-1",children:h}),x&&c.jsx(W,{className:"mt-1 text-sm text-gray-600 dark:text-gray-400 line-clamp-2 [&_mark]:bg-yellow-200 [&_mark]:dark:bg-yellow-500/40 [&_mark]:px-0.5 [&_mark]:rounded",dangerouslySetInnerHTML:{__html:m(x)}}),c.jsxs(W,{className:"mt-1.5 flex items-center gap-1",children:[Dd(e.rating_avg??0).map((y,E)=>c.jsxs(ee,{className:`text-xs ${y==="empty"?"text-gray-300 dark:text-gray-600":"text-yellow-400"}`,children:[y==="full"&&c.jsx("i",{className:"fa-solid fa-star"}),y==="half"&&c.jsx("i",{className:"fa-solid fa-star-half-stroke"}),y==="empty"&&c.jsx("i",{className:"fa-regular fa-star"})]},E)),c.jsx(ee,{className:"text-xs text-gray-600 dark:text-gray-400 ml-0.5",children:(e.rating_avg??0).toFixed(1)}),c.jsxs(ee,{className:"text-xs text-gray-400 dark:text-gray-500",children:["(",e.review_count??0,")"]})]}),c.jsxs(W,{className:"mt-2 flex items-baseline gap-2",children:[c.jsx(ee,{className:"font-bold text-gray-900 dark:text-white",children:d}),i&&u&&c.jsx(ee,{className:"text-sm text-gray-500 dark:text-gray-400 line-through",children:i})]})]})]})},Ld=Object.freeze(Object.defineProperty({__proto__:null,default:ms},Symbol.toStringTag,{value:"Module"})),Pd={ALLOWED_TAGS:["svg","g","defs","title","desc","rect","circle","ellipse","line","polyline","polygon","path","text","tspan","linearGradient","radialGradient","stop","clipPath"],ALLOWED_ATTR:["xmlns","width","height","viewBox","role","aria-label","aria-hidden","fill","fill-opacity","fill-rule","stroke","stroke-width","stroke-linecap","stroke-linejoin","opacity","transform","x","y","x1","y1","x2","y2","cx","cy","r","rx","ry","d","points","width","height","text-anchor","dominant-baseline","font-family","font-size","font-weight","offset","stop-color","stop-opacity","gradientUnits","id","clip-path"],FORBID_TAGS:["script","foreignObject","image","use","a","style"],FORBID_ATTR:["onload","onerror","onclick","onmouseover","onfocus","onblur","href","xlink:href"]},xo=({brandMark:e,size:t=32,className:r="",id:n,editorAttrs:o})=>{const a=e?.svg,s=e?.text,l=k.useMemo(()=>!a||a.trim()===""?"":wo.sanitize(a,Pd),[a]),f={width:`${t}px`,height:`${t}px`,flex:`0 0 ${t}px`};if(l)return c.jsx(W,{id:n,"aria-hidden":"true",className:`inline-flex items-center justify-center ${r}`.trim(),style:f,dangerouslySetInnerHTML:{__html:l},...o});if(s&&s.trim()!==""){const h=e?.class??"bg-gray-500 text-white";return c.jsx(ee,{id:n,"aria-hidden":"true",className:`inline-flex items-center justify-center rounded-lg text-xs font-bold ${h} ${r}`.trim(),style:f,...o,children:s})}return null},Fd=Object.freeze(Object.defineProperty({__proto__:null,BrandMark:xo,default:xo},Symbol.toStringTag,{value:"Module"})),bs="carousel",Wr="controller",$d="navigation",Ud="no-scroll",ko="portal",zd="root",ys="toolbar",Hd="counter",Kr="fullscreen",vs="slideshow",Vr="thumbnails",ws="zoom",vr="loading",Co="playing",Yr="error",Xr="complete",Gd="placeholder",qr=e=>`active-slide-${e}`,jd=qr(vr),Bd=qr(Co),Wd=qr(Yr),Kd=qr(Xr),xs="fullsize",wr="flex_center",Vd="no_scroll",ks="no_scroll_padding",So="slide",Cs="slide_wrapper",Yd="slide_wrapper_interactive",Rt="prev",er="next",_o="swipe",xr="close",Ss="onPointerDown",_s="onPointerMove",Es="onPointerUp",Ts="onPointerLeave",Ns="onPointerCancel",Eo="onKeyDown",Xd="onKeyUp",To="onWheel",qd="Escape",Zd="ArrowLeft",Qd="ArrowRight",Jd="button",wn="icon",As="contain",Ms="cover",Os="Unknown action type",Is="yarl__";function lt(...e){return[...e].filter(Boolean).join(" ")}function pe(e){return`${Is}${e}`}function We(e){return`--${Is}${e}`}function or(e,t){return`${e}${t?`_${t}`:""}`}function ar(e){return t=>or(e,t)}function sr(e,t){var r;return(r=e?.[t])!==null&&r!==void 0?r:t}function Ds(e,t,r){return sr(e,"{index} of {total}").replace(/\{index}/g,`${Oo(r,t.length)+1}`).replace(/\{total}/g,`${t.length}`)}function kr(...e){return()=>{e.forEach(t=>{t()})}}function At(e,t,r){return()=>{const n=T.useContext(r);if(!n)throw new Error(`${e} must be used within a ${t}.Provider`);return n}}function No(){return typeof window<"u"}function Ao(e,t=0){const r=10**t;return Math.round((e+Number.EPSILON)*r)/r}function lr(e){return e.type===void 0||e.type==="image"}function Mo(e,t){return e.imageFit===Ms||e.imageFit!==As&&t===Ms}function xn(e){return typeof e=="string"?Number.parseInt(e,10):e}function kn(e){if(typeof e=="number")return{pixel:e};if(typeof e=="string"){const t=xn(e);return e.endsWith("%")?{percent:t}:{pixel:t}}return{pixel:0}}function Rd(e,t){const r=kn(t),n=r.percent!==void 0?e.width/100*r.percent:r.pixel;return{width:Math.max(e.width-2*n,0),height:Math.max(e.height-2*n,0)}}function eu(){return(No()?window?.devicePixelRatio:void 0)||1}function Oo(e,t){return t>0?(e%t+t)%t:0}function Io(e){return e.length>0}function Do(e,t){return e[Oo(t,e.length)]}function Lo(e,t){return Io(e)?Do(e,t):void 0}function Ls(e){return lr(e)?e.src:void 0}function Cn(e,t,r){if(!r)return e;const{buttons:n,...o}=e,a=n.findIndex(l=>l===t),s=T.isValidElement(r)?T.cloneElement(r,{key:t},null):r;if(a>=0){const l=[...n];return l.splice(a,1,s),{buttons:l,...o}}return{buttons:[s,...n],...o}}function Ps(e,t,r=0){return Math.min(e.preload,Math.max(e.finite?t.length-1:Math.floor(t.length/2),r))}const tu=Number(T.version.split(".")[0])>=19;function ru(e){return{inert:tu?e:e?"":void 0}}function nu(e){e.scrollTop}const Po={open:!1,close:()=>{},index:0,slides:[],render:{},plugins:[],toolbar:{buttons:[xr]},labels:{},animation:{fade:250,swipe:500,easing:{fade:"ease",swipe:"ease-out",navigation:"ease-in-out"}},carousel:{finite:!1,preload:2,padding:"16px",spacing:"30%",imageFit:As,imageProps:{}},controller:{ref:null,focus:!0,aria:!1,touchAction:"none",closeOnPullUp:!1,closeOnPullDown:!1,closeOnBackdropClick:!1,preventDefaultWheelX:!0,preventDefaultWheelY:!1,disableSwipeNavigation:!1},portal:{},noScroll:{disabled:!1},on:{},styles:{},className:""};function Mt(e,t){return{name:e,component:t}}function tt(e,t){return{module:e,children:t}}function Fs(e,t,r){return e.module.name===t?r(e):e.children?[tt(e.module,e.children.flatMap(n=>{var o;return(o=Fs(n,t,r))!==null&&o!==void 0?o:[]}))]:[e]}function Cr(e,t,r){return e.flatMap(n=>{var o;return(o=Fs(n,t,r))!==null&&o!==void 0?o:[]})}function ou(e,t=[],r=[]){let n=e;const o=g=>{const p=[...n];for(;p.length>0;){const m=p.pop();if(m?.module.name===g)return!0;m?.children&&p.push(...m.children)}return!1},a=(g,p)=>{if(g===""){n=[tt(p,n)];return}n=Cr(n,g,m=>[tt(p,[m])])},s=(g,p)=>{n=Cr(n,g,m=>[tt(m.module,[tt(p,m.children)])])},l=(g,p,m)=>{n=Cr(n,g,w=>{var x;return[tt(w.module,[...m?[tt(p)]:[],...(x=w.children)!==null&&x!==void 0?x:[],...m?[]:[tt(p)]])]})},f=(g,p,m)=>{n=Cr(n,g,w=>[...m?[tt(p)]:[],w,...m?[]:[tt(p)]])},h=g=>{s(Wr,g)},d=(g,p)=>{n=Cr(n,g,m=>[tt(p,m.children)])},i=g=>{n=Cr(n,g,p=>p.children)},u=g=>{r.push(g)};return t.forEach(g=>{g({contains:o,addParent:a,append:s,addChild:l,addSibling:f,addModule:h,replace:d,remove:i,augment:u})}),{config:n,augmentation:g=>r.reduce((p,m)=>m(p),g)}}const $s=T.createContext(null),Fo=At("useA11yContext","A11yContext",$s);function au({children:e}){const[t,r]=T.useState(!1),[n,o]=T.useState(!1),a=T.useMemo(()=>({focusWithin:t,trackFocusWithin:(l,f)=>{const h=d=>i=>{var u;i.currentTarget.contains(i.relatedTarget)||r(d),(u=d?l:f)===null||u===void 0||u(i)};return{onFocus:h(!0),onBlur:h(!1)}},autoPlaying:n,setAutoPlaying:o}),[t,n]);return T.createElement($s.Provider,{value:a},e)}const Us=T.createContext(null),Sr=At("useDocument","DocumentContext",Us);function su({nodeRef:e,children:t}){const r=T.useMemo(()=>{const n=a=>{var s;return((s=a||e.current)===null||s===void 0?void 0:s.ownerDocument)||document};return{getOwnerDocument:n,getOwnerWindow:a=>{var s;return((s=n(a))===null||s===void 0?void 0:s.defaultView)||window}}},[e]);return T.createElement(Us.Provider,{value:r},t)}const zs=T.createContext(null),_r=At("useEvents","EventsContext",zs);function lu({children:e}){const[t]=T.useState({});T.useEffect(()=>()=>{Object.keys(t).forEach(n=>delete t[n])},[t]);const r=T.useMemo(()=>{const n=(s,l)=>{var f;(f=t[s])===null||f===void 0||f.splice(0,t[s].length,...t[s].filter(h=>h!==l))};return{publish:(...[s,l])=>{var f;(f=t[s])===null||f===void 0||f.forEach(h=>h(l))},subscribe:(s,l)=>(t[s]||(t[s]=[]),t[s].push(l),()=>n(s,l)),unsubscribe:n}},[t]);return T.createElement(zs.Provider,{value:r},e)}const Hs=T.createContext(null),rt=At("useLightboxProps","LightboxPropsContext",Hs);function Gs({children:e,...t}){return T.createElement(Hs.Provider,{value:t},e)}const js=T.createContext(null),Ot=At("useLightboxState","LightboxStateContext",js),Bs=T.createContext(null),iu=At("useLightboxDispatch","LightboxDispatchContext",Bs);function cu(e,t){switch(t.type){case"swipe":{const{slides:r}=e,n=t?.increment||0,o=e.globalIndex+n,a=Oo(o,r.length),s=Lo(r,a),l=n||t.duration!==void 0?{increment:n,duration:t.duration,easing:t.easing}:void 0;return{slides:r,currentIndex:a,globalIndex:o,currentSlide:s,animation:l}}case"update":return t.slides!==e.slides||t.index!==e.currentIndex?{slides:t.slides,currentIndex:t.index,globalIndex:t.index,currentSlide:Lo(t.slides,t.index)}:e;default:throw new Error(Os)}}function du({slides:e,index:t,children:r}){const[n,o]=T.useReducer(cu,{slides:e,currentIndex:t,globalIndex:t,currentSlide:Lo(e,t)});T.useEffect(()=>{o({type:"update",slides:e,index:t})},[e,t]);const a=T.useMemo(()=>({...n,state:n,dispatch:o}),[n,o]);return T.createElement(Bs.Provider,{value:o},T.createElement(js.Provider,{value:a},r))}const Ws=T.createContext(null),Zr=At("useTimeouts","TimeoutsContext",Ws);function uu({children:e}){const[t]=T.useState([]);T.useEffect(()=>()=>{t.forEach(n=>window.clearTimeout(n)),t.splice(0,t.length)},[t]);const r=T.useMemo(()=>{const n=s=>{t.splice(0,t.length,...t.filter(l=>l!==s))};return{setTimeout:(s,l)=>{const f=window.setTimeout(()=>{n(f),s()},l);return t.push(f),f},clearTimeout:s=>{s!==void 0&&(n(s),window.clearTimeout(s))}}},[t]);return T.createElement(Ws.Provider,{value:r},e)}const Er=T.forwardRef(function({label:t,className:r,icon:n,renderIcon:o,onClick:a,style:s,...l},f){const{styles:h,labels:d}=rt(),i=sr(d,t);return T.createElement("button",{ref:f,type:"button",title:i,"aria-label":i,className:lt(pe(Jd),r),onClick:a,style:{...s,...h.button},...l},o?o():T.createElement(n,{className:pe(wn),style:h.icon}))});function Ks(e,t){const r=n=>T.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:"24",height:"24","aria-hidden":"true",focusable:"false",...n},t);return r.displayName=e,r}function mt(e,t){return Ks(e,T.createElement("g",{fill:"currentColor"},T.createElement("path",{d:"M0 0h24v24H0z",fill:"none"}),t))}function fu(e,t){return Ks(e,T.createElement(T.Fragment,null,T.createElement("defs",null,T.createElement("mask",{id:"strike"},T.createElement("path",{d:"M0 0h24v24H0z",fill:"white"}),T.createElement("path",{d:"M0 0L24 24",stroke:"black",strokeWidth:4}))),T.createElement("path",{d:"M0.70707 2.121320L21.878680 23.292883",stroke:"currentColor",strokeWidth:2}),T.createElement("g",{fill:"currentColor",mask:"url(#strike)"},T.createElement("path",{d:"M0 0h24v24H0z",fill:"none"}),t)))}const gu=mt("Close",T.createElement("path",{d:"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"})),hu=mt("Previous",T.createElement("path",{d:"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"})),pu=mt("Next",T.createElement("path",{d:"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"})),mu=mt("Loading",T.createElement(T.Fragment,null,Array.from({length:8}).map((e,t,r)=>T.createElement("line",{key:t,x1:"12",y1:"6.5",x2:"12",y2:"1.8",strokeLinecap:"round",strokeWidth:"2.6",stroke:"currentColor",strokeOpacity:1/r.length*(t+1),transform:`rotate(${360/r.length*t}, 12, 12)`})))),bu=mt("Error",T.createElement("path",{d:"M21.9,21.9l-8.49-8.49l0,0L3.59,3.59l0,0L2.1,2.1L0.69,3.51L3,5.83V19c0,1.1,0.9,2,2,2h13.17l2.31,2.31L21.9,21.9z M5,18 l3.5-4.5l2.5,3.01L12.17,15l3,3H5z M21,18.17L5.83,3H19c1.1,0,2,0.9,2,2V18.17z"})),$t=No()?T.useLayoutEffect:T.useEffect;function $o(){const[e,t]=T.useState(!1);return T.useEffect(()=>{var r,n;const o=(r=window.matchMedia)===null||r===void 0?void 0:r.call(window,"(prefers-reduced-motion: reduce)");t(o?.matches);const a=s=>t(s.matches);return(n=o?.addEventListener)===null||n===void 0||n.call(o,"change",a),()=>{var s;return(s=o?.removeEventListener)===null||s===void 0?void 0:s.call(o,"change",a)}},[]),e}function yu(e){let t=0,r=0,n=0;const a=window.getComputedStyle(e).transform.match(/matrix.*\((.+)\)/);if(a){const s=a[1].split(",").map(xn);s.length===6?(t=s[4],r=s[5]):s.length===16&&(t=s[12],r=s[13],n=s[14])}return{x:t,y:r,z:n}}function Uo(e,t){const r=T.useRef(void 0),n=T.useRef(void 0),o=$o();return $t(()=>{var a,s,l;if(e.current&&r.current!==void 0&&!o){const{keyframes:f,duration:h,easing:d,onfinish:i}=t(r.current,e.current.getBoundingClientRect(),yu(e.current))||{};if(f&&h){(a=n.current)===null||a===void 0||a.cancel(),n.current=void 0;try{n.current=(l=(s=e.current).animate)===null||l===void 0?void 0:l.call(s,f,{duration:h,easing:d})}catch(u){console.error(u)}n.current&&(n.current.onfinish=()=>{n.current=void 0,i?.()})}}r.current=void 0}),{prepareAnimation:a=>{r.current=a},isAnimationPlaying:()=>{var a;return((a=n.current)===null||a===void 0?void 0:a.playState)==="running"}}}function Vs(){const e=T.useRef(null),t=T.useRef(void 0),[r,n]=T.useState();return{setContainerRef:T.useCallback(a=>{e.current=a,t.current&&(t.current.disconnect(),t.current=void 0);const s=()=>{if(a){const l=window.getComputedStyle(a),f=h=>parseFloat(h)||0;n({width:Math.round(a.clientWidth-f(l.paddingLeft)-f(l.paddingRight)),height:Math.round(a.clientHeight-f(l.paddingTop)-f(l.paddingBottom))})}else n(void 0)};s(),a&&typeof ResizeObserver<"u"&&(t.current=new ResizeObserver(s),t.current.observe(a))},[]),containerRef:e,containerRect:r}}function Sn(){const e=T.useRef(void 0),{setTimeout:t,clearTimeout:r}=Zr();return T.useCallback((n,o)=>{r(e.current),e.current=t(n,o>0?o:0)},[t,r])}function Ie(e){const t=T.useRef(e);return $t(()=>{t.current=e}),T.useCallback((...r)=>{var n;return(n=t.current)===null||n===void 0?void 0:n.call(t,...r)},[])}function Ys(e,t){typeof e=="function"?e(t):e&&(e.current=t)}function zo(e,t){return T.useMemo(()=>e==null&&t==null?null:r=>{Ys(e,r),Ys(t,r)},[e,t])}function Xs(e,t=!1){const r=T.useRef(!1);$t(()=>{t&&r.current&&(r.current=!1,e())},[t,e]);const n=T.useCallback(()=>{r.current=!0},[]),o=T.useCallback(()=>{r.current=!1},[]);return{onFocus:n,onBlur:o}}function _n(){const[e,t]=T.useState(!1);return $t(()=>{t(window.getComputedStyle(window.document.documentElement).direction==="rtl")},[]),e}function qs(){const[e]=T.useState({}),t=T.useCallback((o,a)=>{var s;(s=e[o])===null||s===void 0||s.forEach(l=>{a.isPropagationStopped()||l(a)})},[e]),r=T.useMemo(()=>({onPointerDown:o=>t(Ss,o),onPointerMove:o=>t(_s,o),onPointerUp:o=>t(Es,o),onPointerLeave:o=>t(Ts,o),onPointerCancel:o=>t(Ns,o),onKeyDown:o=>t(Eo,o),onKeyUp:o=>t(Xd,o),onWheel:o=>t(To,o)}),[t]),n=T.useCallback((o,a)=>(e[o]||(e[o]=[]),e[o].unshift(a),()=>{const s=e[o];s&&s.splice(0,s.length,...s.filter(l=>l!==a))}),[e]);return{registerSensors:r,subscribeSensors:n}}function Zs(e,t){const r=T.useRef(0),n=Sn(),o=Ie((...a)=>{r.current=Date.now(),e(a)});return T.useCallback((...a)=>{n(()=>{o(a)},t-(Date.now()-r.current))},[t,o,n])}const Ho=ar("slide"),Go=ar("slide_image");function ir({slide:e,offset:t,render:r,rect:n,imageFit:o,imageProps:a,onClick:s,onLoad:l,onError:f,style:h}){var d,i,u,g,p,m,w,x;const[O,y]=T.useState(vr),{publish:E}=_r(),{setTimeout:M}=Zr(),_=T.useRef(null);T.useEffect(()=>{t===0&&E(qr(O))},[t,O,E]);const I=Ie(B=>{("decode"in B?B.decode():Promise.resolve()).catch(()=>{}).then(()=>{B.parentNode&&(y(Xr),M(()=>{l?.(B)},0))})}),C=T.useCallback(B=>{_.current=B,B?.complete&&I(B)},[I]),v=T.useCallback(B=>{I(B.currentTarget)},[I]),N=Ie(()=>{y(Yr),f?.()}),A=Mo(e,o),P=(B,V)=>Number.isFinite(B)?B:V,D=P(Math.max(...((i=(d=e.srcSet)===null||d===void 0?void 0:d.map(B=>B.width))!==null&&i!==void 0?i:[]).concat(e.width?[e.width]:[]).filter(Boolean)),((u=_.current)===null||u===void 0?void 0:u.naturalWidth)||0),L=P(Math.max(...((p=(g=e.srcSet)===null||g===void 0?void 0:g.map(B=>B.height))!==null&&p!==void 0?p:[]).concat(e.height?[e.height]:[]).filter(Boolean)),((m=_.current)===null||m===void 0?void 0:m.naturalHeight)||0),U=D&&L?{maxWidth:`min(${D}px, 100%)`,maxHeight:`min(${L}px, 100%)`}:{maxWidth:"100%",maxHeight:"100%"},S=(w=e.srcSet)===null||w===void 0?void 0:w.sort((B,V)=>B.width-V.width).map(B=>`${B.src} ${B.width}w`).join(", "),b=()=>n&&!A&&e.width&&e.height?n.height/e.height*e.width:Number.MAX_VALUE,$=S&&n&&No()?`${Math.round(Math.min(b(),n.width))}px`:void 0,{style:F,className:G,...Y}=a||{};return T.createElement(T.Fragment,null,T.createElement("img",{ref:C,onLoad:v,onError:N,onClick:s,draggable:!1,className:lt(pe(Go()),A&&pe(Go("cover")),O!==Xr&&pe(Go("loading")),G),style:{...U,...h,...F},...Y,alt:(x=e.alt)!==null&&x!==void 0?x:"",sizes:$,srcSet:S,src:e.src}),O!==Xr&&T.createElement("div",{className:pe(Ho(Gd))},O===vr&&(r?.iconLoading?r.iconLoading():T.createElement(mu,{className:lt(pe(wn),pe(Ho(vr)))})),O===Yr&&(r?.iconError?r.iconError():T.createElement(bu,{className:lt(pe(wn),pe(Ho(Yr)))}))))}const vu=T.forwardRef(function({className:t,children:r,onFocus:n,onBlur:o,...a},s){const l=T.useRef(null),{trackFocusWithin:f}=Fo();return T.createElement(su,{nodeRef:l},T.createElement("div",{ref:zo(s,l),className:lt(pe("root"),t),...f(n,o),...a},r))});var it;(function(e){e[e.NONE=0]="NONE",e[e.SWIPE=1]="SWIPE",e[e.PULL=2]="PULL",e[e.ANIMATION=3]="ANIMATION"})(it||(it={}));function Qs(e,t,r,n,o){T.useEffect(()=>o?()=>{}:kr(e(Ss,t),e(_s,r),e(Es,n),e(Ts,n),e(Ns,n)),[e,t,r,n,o])}var Ut;(function(e){e[e.NONE=0]="NONE",e[e.SWIPE=1]="SWIPE",e[e.PULL=2]="PULL"})(Ut||(Ut={}));const jo=30;function wu({disableSwipeNavigation:e,closeOnBackdropClick:t},r,n,o,a,s,l,f,h,d,i,u,g,p,m,w){const x=T.useRef(0),O=T.useRef([]),y=T.useRef(void 0),E=T.useRef(0),M=T.useRef(Ut.NONE),_=T.useCallback(D=>{y.current===D.pointerId&&(y.current=void 0,M.current=Ut.NONE);const L=O.current;L.splice(0,L.length,...L.filter(U=>U.pointerId!==D.pointerId))},[]),I=T.useCallback(D=>{_(D),D.persist(),O.current.push(D)},[_]),C=T.useCallback(D=>O.current.find(({pointerId:L})=>D.pointerId===L),[]),v=Ie(D=>{I(D)}),N=(D,L)=>i&&D>L||d&&D<-L,A=Ie(D=>{const L=C(D);if(L)if(y.current===D.pointerId){const U=Date.now()-E.current,S=x.current;M.current===Ut.SWIPE?Math.abs(S)>.3*o||Math.abs(S)>5&&U{const L=C(D);if(L){const U=y.current===D.pointerId;if(D.buttons===0){U&&x.current!==0?A(D):_(L);return}const S=D.clientX-L.clientX,b=D.clientY-L.clientY;if(y.current===void 0){const $=F=>{I(D),y.current=D.pointerId,E.current=Date.now(),M.current=F};Math.abs(S)>Math.abs(b)&&Math.abs(S)>jo&&n(S)?e||($(Ut.SWIPE),s()):Math.abs(b)>Math.abs(S)&&N(b,jo)&&($(Ut.PULL),u())}else U&&(M.current===Ut.SWIPE?(x.current=S,l(S)):M.current===Ut.PULL&&(x.current=b,g(b)))}});Qs(r,v,P,A)}function xu({preventDefaultWheelX:e,preventDefaultWheelY:t}){const r=T.useRef(null),n=Ie(o=>{const a=Math.abs(o.deltaX)>Math.abs(o.deltaY);(a&&e||!a&&t||o.ctrlKey)&&o.preventDefault()});return T.useCallback(o=>{var a;o?o.addEventListener("wheel",n,{passive:!1}):(a=r.current)===null||a===void 0||a.removeEventListener("wheel",n),r.current=o},[n])}function ku(e,t,r,n,o,a,s,l,f){const h=T.useRef(0),d=T.useRef(0),i=T.useRef(void 0),u=T.useRef(void 0),g=T.useRef(0),p=T.useRef(void 0),m=T.useRef(0),{setTimeout:w,clearTimeout:x}=Zr(),O=T.useCallback(()=>{i.current&&(x(i.current),i.current=void 0)},[x]),y=T.useCallback(()=>{u.current&&(x(u.current),u.current=void 0)},[x]),E=Ie(()=>{e!==it.SWIPE&&(h.current=0,m.current=0,O(),y())});T.useEffect(E,[e,E]);const M=Ie(I=>{u.current=void 0,h.current===I&&f(h.current)}),_=Ie(I=>{if(I.ctrlKey||Math.abs(I.deltaY)>Math.abs(I.deltaX))return;const C=v=>{g.current=v,x(p.current),p.current=v>0?w(()=>{g.current=0,p.current=void 0},300):void 0};if(e===it.NONE){if(Math.abs(I.deltaX)<=1.2*Math.abs(g.current)){C(I.deltaX);return}if(!r(-I.deltaX))return;if(d.current+=I.deltaX,O(),Math.abs(d.current)>30)d.current=0,C(0),m.current=Date.now(),a();else{const v=d.current;i.current=w(()=>{i.current=void 0,v===d.current&&(d.current=0)},o)}}else if(e===it.SWIPE){let v=h.current-I.deltaX;if(v=Math.min(Math.abs(v),n)*Math.sign(v),h.current=v,s(v),y(),Math.abs(v)>.2*n){C(I.deltaX),l(v,Date.now()-m.current);return}u.current=w(()=>M(v),2*o)}else C(I.deltaX)});T.useEffect(()=>t(To,_),[t,_])}const Js=ar("container"),Rs=T.createContext(null),zt=At("useController","ControllerContext",Rs);function Cu({children:e,...t}){var r;const{carousel:n,animation:o,controller:a,on:s,styles:l,render:f}=t,{closeOnPullUp:h,closeOnPullDown:d,preventDefaultWheelX:i,preventDefaultWheelY:u}=a,[g,p]=T.useState(),m=Ot(),w=iu(),[x,O]=T.useState(it.NONE),y=T.useRef(0),E=T.useRef(0),M=T.useRef(1),{registerSensors:_,subscribeSensors:I}=qs(),{subscribe:C,publish:v}=_r(),N=Sn(),A=Sn(),P=Sn(),{containerRef:D,setContainerRef:L,containerRect:U}=Vs(),S=zo(xu({preventDefaultWheelX:i,preventDefaultWheelY:u}),L),b=T.useRef(null),$=zo(b,void 0),{getOwnerDocument:F}=Sr(),G=_n(),Y=K=>(G?-1:1)*(typeof K=="number"?K:1),B=Ie(()=>{var K;return(K=D.current)===null||K===void 0?void 0:K.focus()}),V=Ie(()=>t),j=Ie(()=>m),H=T.useCallback(K=>v(Rt,K),[v]),q=T.useCallback(K=>v(er,K),[v]),ue=T.useCallback(()=>v(xr),[v]),te=K=>!(n.finite&&(Y(K)>0&&m.currentIndex===0||Y(K)<0&&m.currentIndex===m.slides.length-1)),fe=K=>{var re;y.current=K,(re=D.current)===null||re===void 0||re.style.setProperty(We("swipe_offset"),`${Math.round(K)}px`)},R=K=>{var re,oe;E.current=K,M.current=(()=>{const xe=d&&K>0?K:h&&K<0?-K:0;return Math.min(Math.max(Ao(1-xe/60*(1-.5),2),.5),1)})(),(re=D.current)===null||re===void 0||re.style.setProperty(We("pull_offset"),`${Math.round(K)}px`),(oe=D.current)===null||oe===void 0||oe.style.setProperty(We("pull_opacity"),`${M.current}`)},{prepareAnimation:ke}=Uo(b,(K,re,oe)=>{if(b.current&&U)return{keyframes:[{transform:`translate(0, ${K.rect.y-re.y+oe.y}px)`,opacity:K.opacity},{transform:"translate(0, 0)",opacity:1}],duration:K.duration,easing:o.easing.fade}}),me=(K,re)=>{if(h||d){R(K);let oe=0;b.current&&(oe=o.fade*(re?2:1),ke({rect:b.current.getBoundingClientRect(),opacity:M.current,duration:oe})),P(()=>{R(0),O(it.NONE)},oe),O(it.ANIMATION),re||ue()}},{prepareAnimation:Ge,isAnimationPlaying:De}=Uo(b,(K,re,oe)=>{var ae;if(b.current&&U&&(!((ae=m.animation)===null||ae===void 0)&&ae.duration)){const be=kn(n.spacing),xe=(be.percent?be.percent*U.width/100:be.pixel)||0;return{keyframes:[{transform:`translate(${Y(m.globalIndex-K.index)*(U.width+xe)+K.rect.x-re.x+oe.x}px, 0)`},{transform:"translate(0, 0)"}],duration:m.animation.duration,easing:m.animation.easing}}}),ye=Ie(K=>{var re,oe;const ae=K.offset||0,be=ae?o.swipe:(re=o.navigation)!==null&&re!==void 0?re:o.swipe,xe=!ae&&!De()?o.easing.navigation:o.easing.swipe;let{direction:He}=K;const Pe=(oe=K.count)!==null&&oe!==void 0?oe:1;let Ke=it.ANIMATION,Oe=be*Pe;if(!He){const se=U?.width,ie=K.duration||0,le=se?be/se*Math.abs(ae):be;Pe!==0?(ie0?Rt:er):Oe=be/2}let X=0;He===Rt?te(Y(1))?X=-Pe:(Ke=it.NONE,Oe=be):He===er&&(te(Y(-1))?X=Pe:(Ke=it.NONE,Oe=be)),Oe=Math.round(Oe),A(()=>{fe(0),O(it.NONE)},Oe),b.current&&Ge({rect:b.current.getBoundingClientRect(),index:m.globalIndex}),O(Ke),v(_o,{type:"swipe",increment:X,duration:Oe,easing:xe})});T.useEffect(()=>{var K,re;!((K=m.animation)===null||K===void 0)&&K.increment&&(!((re=m.animation)===null||re===void 0)&&re.duration)&&N(()=>w({type:"swipe",increment:0}),m.animation.duration)},[m.animation,w,N]);const Me=[I,te,U?.width||0,o.swipe,()=>O(it.SWIPE),K=>fe(K),(K,re)=>ye({offset:K,duration:re,count:1}),K=>ye({offset:K,count:0})],Ce=[()=>{d&&O(it.PULL)},K=>R(K),K=>me(K),K=>me(K,!0)];wu(a,...Me,h,d,...Ce,ue),ku(x,...Me);const we=Ie(()=>{a.focus&&F().querySelector(`.${pe(ko)} .${pe(Js())}`)&&B()});T.useEffect(we,[we]);const $e=Ie(()=>{var K;(K=s.view)===null||K===void 0||K.call(s,{index:m.currentIndex})});T.useEffect($e,[m.globalIndex,$e]),T.useEffect(()=>kr(C(Rt,K=>ye({direction:Rt,...K})),C(er,K=>ye({direction:er,...K})),C(_o,K=>w(K))),[C,ye,w]);const Le=T.useMemo(()=>({prev:H,next:q,close:ue,focus:B,slideRect:U?Rd(U,n.padding):{width:0,height:0},containerRect:U||{width:0,height:0},subscribeSensors:I,containerRef:D,setCarouselRef:$,toolbarWidth:g,setToolbarWidth:p}),[H,q,ue,B,I,U,D,$,g,p,n.padding]);return T.useImperativeHandle(a.ref,()=>({prev:H,next:q,close:ue,focus:B,getLightboxProps:V,getLightboxState:j}),[H,q,ue,B,V,j]),T.createElement("div",{ref:S,className:lt(pe(Js()),pe(wr)),style:{...x===it.SWIPE?{[We("swipe_offset")]:`${Math.round(y.current)}px`}:null,...x===it.PULL?{[We("pull_offset")]:`${Math.round(E.current)}px`,[We("pull_opacity")]:`${M.current}`}:null,...a.touchAction!=="none"?{[We("controller_touch_action")]:a.touchAction}:null,...l.container},tabIndex:-1,..._},U&&T.createElement(Rs.Provider,{value:Le},e,(r=f.controls)===null||r===void 0?void 0:r.call(f)))}const Su=Mt(Wr,Cu);function cr(e){return or(bs,e)}function el(e){return or(So,e)}function _u({slide:e,offset:t}){const r=T.useRef(null),{currentIndex:n,slides:o}=Ot(),{slideRect:a,focus:s}=zt(),{render:l,carousel:{imageFit:f,imageProps:h},on:{click:d},styles:{slide:i},labels:u}=rt(),{getOwnerDocument:g}=Sr(),p=t!==0;T.useEffect(()=>{var w;p&&(!((w=r.current)===null||w===void 0)&&w.contains(g().activeElement))&&s()},[p,s,g]);const m=()=>{var w,x,O,y;let E=(w=l.slide)===null||w===void 0?void 0:w.call(l,{slide:e,offset:t,rect:a});return!E&&lr(e)&&(E=T.createElement(ir,{slide:e,offset:t,render:l,rect:a,imageFit:f,imageProps:h,onClick:p?void 0:()=>d?.({index:n})})),E?T.createElement(T.Fragment,null,(x=l.slideHeader)===null||x===void 0?void 0:x.call(l,{slide:e}),((O=l.slideContainer)!==null&&O!==void 0?O:(({children:M})=>M))({slide:e,children:E}),(y=l.slideFooter)===null||y===void 0?void 0:y.call(l,{slide:e})):null};return T.createElement("div",{ref:r,className:lt(pe(el()),!p&&pe(el("current")),pe(wr)),...ru(p),style:i,role:"group","aria-roledescription":sr(u,"Slide"),"aria-label":Ds(u,o,n+t)},m())}function Eu(){const e=rt().styles.slide;return T.createElement("div",{className:pe(So),style:e})}function Tu({carousel:e,labels:t}){const{slides:r,currentIndex:n,globalIndex:o}=Ot(),{setCarouselRef:a}=zt(),{autoPlaying:s,focusWithin:l}=Fo(),f=kn(e.spacing),h=kn(e.padding),d=Ps(e,r,1),i=[];if(Io(r))for(let u=n-d;u<=n+d;u+=1){const g=Do(r,u),p=o-n+u,m=e.finite&&(u<0||u>r.length-1);i.push(m?{key:p}:{key:[`${p}`,Ls(g)].filter(Boolean).join("|"),offset:u-n,slide:g})}return T.createElement("div",{ref:a,className:lt(pe(cr()),i.length>0&&pe(cr("with_slides"))),style:{[`${We(cr("slides_count"))}`]:i.length,[`${We(cr("spacing_px"))}`]:f.pixel||0,[`${We(cr("spacing_percent"))}`]:f.percent||0,[`${We(cr("padding_px"))}`]:h.pixel||0,[`${We(cr("padding_percent"))}`]:h.percent||0},role:"region","aria-live":s&&!l?"off":"polite","aria-roledescription":sr(t,"Carousel"),"aria-label":sr(t,"Photo gallery")},i.map(({key:u,slide:g,offset:p})=>g?T.createElement(_u,{key:u,slide:g,offset:p}):T.createElement(Eu,{key:u})))}const Nu=Mt(bs,Tu);function tl(){const{carousel:e}=rt(),{slides:t,currentIndex:r}=Ot(),n=t.length===0||e.finite&&r===0,o=t.length===0||e.finite&&r===t.length-1;return{prevDisabled:n,nextDisabled:o}}function rl(e){var t;const r=_n(),{publish:n}=_r(),{animation:o}=rt(),{prevDisabled:a,nextDisabled:s}=tl(),l=((t=o.navigation)!==null&&t!==void 0?t:o.swipe)/2,f=Zs(()=>n(Rt),l),h=Zs(()=>n(er),l),d=Ie(i=>{switch(i.key){case qd:n(xr);break;case Zd:(r?s:a)||(r?h:f)();break;case Qd:(r?a:s)||(r?f:h)();break}});T.useEffect(()=>e(Eo,d),[e,d])}function nl({label:e,icon:t,renderIcon:r,action:n,onClick:o,disabled:a,style:s}){return T.createElement(Er,{label:e,icon:t,renderIcon:r,className:pe(`navigation_${n}`),disabled:a,onClick:o,style:s,...Xs(zt().focus,a)})}function Au({render:{buttonPrev:e,buttonNext:t,iconPrev:r,iconNext:n},styles:o}){const{prev:a,next:s,subscribeSensors:l}=zt(),{prevDisabled:f,nextDisabled:h}=tl();return rl(l),T.createElement(T.Fragment,null,e?e():T.createElement(nl,{label:"Previous",action:Rt,icon:hu,renderIcon:r,style:o.navigationPrev,disabled:f,onClick:a}),t?t():T.createElement(nl,{label:"Next",action:er,icon:pu,renderIcon:n,style:o.navigationNext,disabled:h,onClick:s}))}const Mu=Mt($d,Au),ol=pe(Vd),Ou=pe(ks);function Iu(e){return"style"in e}function al(e,t,r){const n=window.getComputedStyle(e),o=r?"padding-left":"padding-right",a=r?n.paddingLeft:n.paddingRight,s=e.style.getPropertyValue(o);return e.style.setProperty(o,`${(xn(a)||0)+t}px`),()=>{s?e.style.setProperty(o,s):e.style.removeProperty(o)}}function Du({noScroll:{disabled:e},children:t}){const r=_n(),{getOwnerDocument:n,getOwnerWindow:o}=Sr();return T.useEffect(()=>{if(e)return()=>{};const a=[],s=o(),{body:l,documentElement:f}=n(),h=Math.round(s.innerWidth-f.clientWidth);if(h>0){a.push(al(l,h,r));const d=l.getElementsByTagName("*");for(let i=0;i{l.classList.remove(ol),a.forEach(d=>d())}},[r,e,n,o]),T.createElement(T.Fragment,null,t)}const Lu=Mt(Ud,Du);function sl(e){return or(ko,e)}function ll(e,t,r){const n=e.getAttribute(t);return e.setAttribute(t,r),()=>{n?e.setAttribute(t,n):e.removeAttribute(t)}}function Pu({children:e,animation:t,styles:r,className:n,on:o,portal:a,close:s,labels:l}){const[f,h]=T.useState(!1),[d,i]=T.useState(!1),u=T.useRef([]),g=T.useRef(null),{setTimeout:p}=Zr(),{subscribe:m}=_r(),x=$o()?0:t.fade;T.useEffect(()=>(h(!0),()=>{h(!1),i(!1)}),[]);const O=Ie(()=>{u.current.forEach(_=>_()),u.current=[]}),y=Ie(()=>{var _;i(!1),O(),(_=o.exiting)===null||_===void 0||_.call(o),p(()=>{var I;(I=o.exited)===null||I===void 0||I.call(o),s()},x)});T.useEffect(()=>m(xr,y),[m,y]);const E=Ie(_=>{var I,C,v;nu(_),i(!0),(I=o.entering)===null||I===void 0||I.call(o);const N=(v=(C=_.parentNode)===null||C===void 0?void 0:C.children)!==null&&v!==void 0?v:[];for(let A=0;A{var A,P;(P=(A=g.current)===null||A===void 0?void 0:A.focus)===null||P===void 0||P.call(A)}),p(()=>{var A;(A=o.entered)===null||A===void 0||A.call(o)},x)}),M=T.useCallback(_=>{_?E(_):O()},[E,O]);return f?Jt.createPortal(T.createElement(vu,{ref:M,className:lt(n,pe(sl()),pe(ks),d&&pe(sl("open"))),"aria-modal":!0,role:"dialog","aria-label":sr(l,"Lightbox"),style:{...t.fade!==Po.animation.fade?{[We("fade_animation_duration")]:`${x}ms`}:null,...t.easing.fade!==Po.animation.easing.fade?{[We("fade_animation_timing_function")]:t.easing.fade}:null,...r.root},onFocus:_=>{g.current||(g.current=_.relatedTarget)}},e),a.root||document.body):null}const Fu=Mt(ko,Pu);function $u({children:e}){return T.createElement(T.Fragment,null,e)}const Uu=Mt(zd,$u);function zu(e){return or(ys,e)}function Hu({toolbar:{buttons:e},render:{buttonClose:t,iconClose:r},styles:n}){const{close:o,setToolbarWidth:a}=zt(),{setContainerRef:s,containerRect:l}=Vs();$t(()=>{a(l?.width)},[a,l?.width]);const f=()=>t?t():T.createElement(Er,{key:xr,label:"Close",icon:gu,renderIcon:r,onClick:o});return T.createElement("div",{ref:s,style:n.toolbar,className:pe(zu())},e?.map(h=>h===xr?f():h))}const Gu=Mt(ys,Hu);function il(e,t){var r;return T.createElement(e.module.component,{key:e.module.name,...t},(r=e.children)===null||r===void 0?void 0:r.map(n=>il(n,t)))}function ju(e,t={}){const{easing:r,...n}=e,{easing:o,...a}=t;return{easing:{...r,...o},...n,...a}}function Bu({carousel:e,animation:t,render:r,toolbar:n,controller:o,noScroll:a,on:s,plugins:l,slides:f,index:h,...d}){const{animation:i,carousel:u,render:g,toolbar:p,controller:m,noScroll:w,on:x,slides:O,index:y,plugins:E,...M}=Po,{config:_,augmentation:I}=ou([tt(Fu,[tt(Lu,[tt(Su,[tt(Nu),tt(Gu),tt(Mu)])])])],l||E),C=I({animation:ju(i,t),carousel:{...u,...e},render:{...g,...r},toolbar:{...p,...n},controller:{...m,...o},noScroll:{...w,...a},on:{...x,...s},...M,...d});return C.open?T.createElement(Gs,{...C},T.createElement(du,{slides:f||O,index:xn(h||y)},T.createElement(uu,null,T.createElement(lu,null,T.createElement(au,null,il(tt(Uu,_),C)))))):null}const Wu={minZoom:1,maxZoomPixelRatio:1,zoomInMultiplier:2,doubleTapDelay:300,doubleClickDelay:500,doubleClickMaxStops:2,keyboardMoveDistance:50,wheelZoomDistanceFactor:100,pinchZoomDistanceFactor:100,pinchZoomV4:!1,scrollToZoom:!1};function Ku(e){return Math.min(Math.max(e,Number.EPSILON),1)}function cl(e){const{minZoom:t,...r}={...Wu,...e};return{minZoom:Ku(t),...r}}function Vu(e,t,r,n){const o=T.useRef(void 0),a=T.useRef(void 0),{zoom:s}=rt().animation,l=$o(),f=Ie(()=>{var h,d,i;if((h=o.current)===null||h===void 0||h.cancel(),o.current=void 0,a.current&&n?.current){try{o.current=(i=(d=n.current).animate)===null||i===void 0?void 0:i.call(d,[{transform:a.current},{transform:`scale(${e}) translateX(${t}px) translateY(${r}px)`}],{duration:l?0:s??500,easing:o.current?"ease-out":"ease-in-out"})}catch(u){console.error(u)}a.current=void 0,o.current&&(o.current.onfinish=()=>{o.current=void 0})}});return $t(f,[e,t,r,f]),T.useCallback(()=>{a.current=n?.current?window.getComputedStyle(n.current).transform:void 0},[n])}function Yu(e,t){const{on:r}=rt(),n=Ie(()=>{var o;t||(o=r.zoom)===null||o===void 0||o.call(r,{zoom:e})});T.useEffect(n,[e,n])}function En(){const{zoom:e}=rt();return cl(e)}function Xu(e,t){var r,n;let o={width:0,height:0},a={width:0,height:0};const{currentSlide:s}=Ot(),{imageFit:l}=rt().carousel,{maxZoomPixelRatio:f}=En();if(e&&s){const d={...s,...t};if(lr(d)){const i=Mo(d,l),u=Math.max(...(((r=d.srcSet)===null||r===void 0?void 0:r.map(p=>p.width))||[]).concat(d.width?[d.width]:[])),g=Math.max(...(((n=d.srcSet)===null||n===void 0?void 0:n.map(p=>p.height))||[]).concat(d.height?[d.height]:[]));u>0&&g>0&&e.width>0&&e.height>0&&(a=i?{width:Math.round(Math.min(u,e.width/e.height*g)),height:Math.round(Math.min(g,e.height/e.width*u))}:{width:u,height:g},a={width:a.width*f,height:a.height*f},o=i?{width:Math.min(e.width,a.width,u),height:Math.min(e.height,a.height,g)}:{width:Math.round(Math.min(e.width,e.height/g*u,u)),height:Math.round(Math.min(e.height,e.width/u*g,g))})}}const h=o.width?Math.max(Ao(a.width/o.width,5),1):1;return{imageRect:o,maxZoom:h}}function dl(e,t){return Math.hypot(e.clientX-t.clientX,e.clientY-t.clientY)}function ul(e,t,r=100,n=2){return e*Math.min(1+Math.abs(t/r),n)**Math.sign(t)}function qu(e,t,r,n,o,a,s,l,f){const h=T.useRef([]),d=T.useRef(0),i=T.useRef(void 0),{globalIndex:u}=Ot(),{getOwnerWindow:g}=Sr(),{containerRef:p,subscribeSensors:m}=zt(),{keyboardMoveDistance:w,zoomInMultiplier:x,wheelZoomDistanceFactor:O,scrollToZoom:y,doubleTapDelay:E,doubleClickDelay:M,doubleClickMaxStops:_,pinchZoomDistanceFactor:I,pinchZoomV4:C}=En(),v=T.useCallback($=>{if(p.current){const{pageX:F,pageY:G}=$,{scrollX:Y,scrollY:B}=g(),{left:V,top:j,width:H,height:q}=p.current.getBoundingClientRect();return[F-V-Y-H/2,G-j-B-q/2]}return[]},[p,g]),N=Ie($=>{const{key:F,metaKey:G,ctrlKey:Y}=$,B=G||Y,V=()=>{$.preventDefault(),$.stopPropagation()};if(e>1){const j=(H,q)=>{V(),l(H,q)};F==="ArrowDown"?j(0,w):F==="ArrowUp"?j(0,-w):F==="ArrowLeft"?j(-w,0):F==="ArrowRight"&&j(w,0)}F==="+"||B&&F==="="?(V(),o()):F==="-"||B&&F==="_"?(V(),a()):B&&F==="0"&&(V(),s(1))}),A=Ie($=>{if(($.ctrlKey||y)&&Math.abs($.deltaY)>Math.abs($.deltaX)){$.stopPropagation(),s(ul(e,-$.deltaY,O),!0,...v($));return}e>1&&($.stopPropagation(),y||l($.deltaX,$.deltaY))}),P=T.useCallback($=>{const F=h.current;F.splice(0,F.length,...F.filter(G=>G.pointerId!==$.pointerId))},[]),D=T.useCallback($=>{P($),$.persist(),h.current.push($)},[P]),L=Ie($=>{var F;const G=h.current;if($.pointerType==="mouse"&&$.buttons>1||!(!((F=f?.current)===null||F===void 0)&&F.contains($.target)))return;e>1&&$.stopPropagation();const{timeStamp:Y}=$;if(G.length===0&&Y-d.current<($.pointerType==="touch"?E:M)){d.current=0;const B=e>=1?e!==r?e*Math.max(r**(1/_),x):1:e!==t?e/Math.max(t**(-1/_),x):1;s(B,!1,...v($))}else d.current=Y;if(D($),G.length===2){const B=dl(G[0],G[1]);i.current={previousDistance:B,initialDistance:Math.max(B,1),initialZoom:e}}}),U=Ie($=>{const F=h.current,G=F.find(Y=>Y.pointerId===$.pointerId);if(F.length===2&&i.current){$.stopPropagation(),D($);const Y=dl(F[0],F[1]),B=C?i.current.initialZoom/i.current.initialDistance*Y:ul(e,Y-i.current.previousDistance,I);s(B,!0,...F.map(V=>v(V)).reduce((V,j)=>j.map((H,q)=>V[q]+H/2))),i.current.previousDistance=Y;return}e>1&&($.stopPropagation(),G&&(F.length===1&&l((G.clientX-$.clientX)/e,(G.clientY-$.clientY)/e),D($)))}),S=T.useCallback($=>{const F=h.current;F.length===2&&F.find(G=>G.pointerId===$.pointerId)&&(i.current=void 0),P($)},[P]),b=T.useCallback(()=>{const $=h.current;$.splice(0,$.length),d.current=0,i.current=void 0},[]);Qs(m,L,U,S,n),T.useEffect(b,[u,b]),T.useEffect(()=>n?()=>{}:kr(b,m(Eo,N),m(To,A)),[n,m,b,N,A])}function Zu(e,t,r){const[n,o]=T.useState(1),[a,s]=T.useState(0),[l,f]=T.useState(0),h=Vu(n,a,l,r),{currentSlide:d,globalIndex:i}=Ot(),{containerRect:u,slideRect:g}=zt(),{minZoom:p,zoomInMultiplier:m}=En(),w=d&&lr(d)?d.src:void 0,x=!w||!r?.current;$t(()=>{o(1),s(0),f(0)},[i,w]);const O=T.useCallback((I,C,v)=>{const N=v||n,A=a-(I||0),P=l-(C||0),D=(e.width*N-g.width)/2/N,L=(e.height*N-g.height)/2/N;s(Math.min(Math.abs(A),Math.max(D,0))*Math.sign(A)),f(Math.min(Math.abs(P),Math.max(L,0))*Math.sign(P))},[n,a,l,g,e.width,e.height]),y=T.useCallback((I,C,v,N)=>{const A=Ao(I+.01p?I:p:t,5);C||h(),O(v?v*(1/n-1/A):0,N?N*(1/n-1/A):0,A),o(A)},[n,p,t,O,h]),E=Ie(()=>{n>1&&(n>t&&y(t,!0),O())});$t(E,[u.width,u.height,E]);const M=T.useCallback(()=>{const I=n*m;y(n<1&&I>1?1:I)},[n,m,y]),_=T.useCallback(()=>{const I=n/m;y(n>1&&I<1?1:I)},[n,m,y]);return{zoom:n,offsetX:a,offsetY:l,disabled:x,changeOffsets:O,changeZoom:y,zoomIn:M,zoomOut:_}}const fl=T.createContext(null),Bo=At("useZoom","ZoomControllerContext",fl);function Qu({children:e}){const[t,r]=T.useState(),{slideRect:n}=zt(),{ref:o,minZoom:a}=En(),{imageRect:s,maxZoom:l}=Xu(n,t?.imageDimensions),{zoom:f,offsetX:h,offsetY:d,disabled:i,changeZoom:u,changeOffsets:g,zoomIn:p,zoomOut:m}=Zu(s,l,t?.zoomWrapperRef);Yu(f,i),qu(f,a,l,i,p,m,u,g,t?.zoomWrapperRef);const w=T.useMemo(()=>({zoom:f,minZoom:a,maxZoom:l,offsetX:h,offsetY:d,disabled:i,zoomIn:p,zoomOut:m,changeZoom:u}),[f,a,l,h,d,i,p,m,u]);T.useImperativeHandle(o,()=>w,[w]);const x=T.useMemo(()=>({...w,setZoomWrapper:r}),[w,r]);return T.createElement(fl.Provider,{value:x},e)}const Ju=mt("ZoomIn",T.createElement(T.Fragment,null,T.createElement("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"}),T.createElement("path",{d:"M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z"}))),Ru=mt("ZoomOut",T.createElement("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z"})),gl=T.forwardRef(function({zoomIn:t,onLoseFocus:r},n){const o=T.useRef(!1),a=T.useRef(!1),{zoom:s,minZoom:l,maxZoom:f,zoomIn:h,zoomOut:d,disabled:i}=Bo(),{render:u}=rt(),g=i||(t?s>=f:s<=l);return T.useEffect(()=>{g&&o.current&&a.current&&r(),g||(o.current=!0)},[g,r]),T.createElement(Er,{ref:n,disabled:g,label:t?"Zoom in":"Zoom out",icon:t?Ju:Ru,renderIcon:t?u.iconZoomIn:u.iconZoomOut,onClick:t?h:d,onFocus:()=>{a.current=!0},onBlur:()=>{a.current=!1}})});function ef(){const e=T.useRef(null),t=T.useRef(null),{focus:r}=zt(),n=T.useCallback(s=>{var l,f;!((l=s.current)===null||l===void 0)&&l.disabled?r():(f=s.current)===null||f===void 0||f.focus()},[r]),o=T.useCallback(()=>n(e),[n]),a=T.useCallback(()=>n(t),[n]);return T.createElement(T.Fragment,null,T.createElement(gl,{zoomIn:!0,ref:e,onLoseFocus:a}),T.createElement(gl,{ref:t,onLoseFocus:o}))}function tf(){const{render:e}=rt(),t=Bo();return e.buttonZoom?T.createElement(T.Fragment,null,e.buttonZoom(t)):T.createElement(ef,null)}function rf(e){var t;return(((t=e.srcSet)===null||t===void 0?void 0:t.length)||0)>0}function nf({current:e,preload:t},{type:r,source:n}){switch(r){case"fetch":return e?{current:e,preload:n}:{current:n};case"done":return n===t?{current:n}:{current:e,preload:t};default:throw new Error(Os)}}function of(e){var t,r;const[{current:n,preload:o},a]=T.useReducer(nf,{}),{slide:s,rect:l,imageFit:f,render:h,interactive:d}=e,i=s.srcSet.sort((M,_)=>M.width-_.width),u=(t=s.width)!==null&&t!==void 0?t:i[i.length-1].width,g=(r=s.height)!==null&&r!==void 0?r:i[i.length-1].height,p=Mo(s,f),m=Math.max(...i.map(M=>M.width)),w=Math.min((p?Math.max:Math.min)(l.width,u*(l.height/g)),m),x=eu(),O=Ie(()=>{var M;const _=(M=i.find(I=>I.width>=w*x))!==null&&M!==void 0?M:i[i.length-1];(!n||i.findIndex(I=>I.src===n)I===_))&&a({type:"fetch",source:_.src})});$t(O,[l.width,l.height,x,O]);const y=Ie(M=>a({type:"done",source:M})),E={WebkitTransform:d?"initial":"translateZ(0)"};return p||Object.assign(E,l.width/l.heighty(o),render:{...h,iconLoading:()=>null,iconError:()=>null}}),n&&T.createElement(ir,{key:"current",...e,slide:{...s,src:n,srcSet:void 0},style:E}))}function af({render:e,slide:t,offset:r,rect:n}){var o;const[a,s]=T.useState(),l=T.useRef(null),{zoom:f,maxZoom:h,offsetX:d,offsetY:i,setZoomWrapper:u}=Bo(),g=f>1,{carousel:p,on:m}=rt(),{currentIndex:w}=Ot();$t(()=>r===0?(u({zoomWrapperRef:l,imageDimensions:a}),()=>u(void 0)):()=>{},[r,a,u]);let x=(o=e.slide)===null||o===void 0?void 0:o.call(e,{slide:t,offset:r,rect:n,zoom:f,maxZoom:h});if(!x&&lr(t)){const O={slide:t,offset:r,rect:n,render:e,imageFit:p.imageFit,imageProps:p.imageProps,onClick:r===0?()=>{var y;return(y=m.click)===null||y===void 0?void 0:y.call(m,{index:w})}:void 0};x=rf(t)?T.createElement(of,{...O,slide:t,interactive:g,rect:r===0?{width:n.width*f,height:n.height*f}:n}):T.createElement(ir,{onLoad:y=>s({width:y.naturalWidth,height:y.naturalHeight}),...O})}return x?T.createElement("div",{ref:l,className:lt(pe(xs),pe(wr),pe(Cs),g&&pe(Yd)),style:r===0?{transform:`scale(${f}) translateX(${d}px) translateY(${i}px)`}:void 0},x):null}const sf=({augment:e,addModule:t})=>{e(({zoom:r,toolbar:n,render:o,controller:a,...s})=>{const l=cl(r);return{zoom:l,toolbar:Cn(n,ws,T.createElement(tf,null)),render:{...o,slide:f=>{var h;return lr(f.slide)?T.createElement(af,{render:o,...f}):(h=o.slide)===null||h===void 0?void 0:h.call(o,f)}},controller:{...a,preventDefaultWheelY:l.scrollToZoom},...s}}),t(Mt(ws,Qu))},lf={separator:"/",container:{}},hl=e=>({...lf,...e});function cf({counter:e}){const{slides:t,currentIndex:r}=Ot(),{separator:n,container:{className:o,...a},className:s,...l}=hl(e);return t.length===0?null:T.createElement("div",{className:lt(pe("counter"),o||s),...l,...a,"aria-hidden":!0},r+1," ",n," ",t.length)}function df({augment:e,addChild:t}){e(({counter:r,...n})=>({counter:hl(r),...n})),t(Wr,Mt(Hd,cf))}const uf={autoplay:!1,delay:3e3,ref:null},pl=e=>({...uf,...e}),ml=T.createContext(null),ff=At("useSlideshow","SlideshowContext",ml);function gf({slideshow:e,carousel:{finite:t},on:r,children:n}){const{autoplay:o,delay:a,ref:s}=pl(e),l=T.useRef(o),[f,h]=T.useState(o),d=T.useRef(void 0),i=T.useRef(void 0),{slides:u,currentIndex:g}=Ot(),{setTimeout:p,clearTimeout:m}=Zr(),{subscribe:w}=_r(),{next:x}=zt(),{setAutoPlaying:O}=Fo();T.useEffect(()=>O(f),[f,O]);const y=u.length===0||t&&g===u.length-1,E=T.useCallback(()=>{!f&&!y&&h(!0)},[f,y]),M=T.useCallback(()=>{f&&h(!1)},[f]),_=T.useCallback(()=>{m(d.current),d.current=void 0},[m]),I=Ie(()=>{_(),!(!f||y||i.current===vr||i.current===Co)&&(d.current=p(()=>{f&&(i.current=void 0,x())},a))});T.useEffect(I,[g,f,I]),T.useEffect(()=>{f&&y&&h(!1)},[g,f,y]);const C=Ie(()=>{var A;return(A=r.slideshowStart)===null||A===void 0?void 0:A.call(r)}),v=Ie(()=>{var A;return(A=r.slideshowStop)===null||A===void 0?void 0:A.call(r)});T.useEffect(()=>{f?C():l.current&&v(),l.current=f},[f,C,v]),T.useEffect(()=>kr(_,w(jd,()=>{i.current=vr,_()}),w(Bd,()=>{i.current=Co,_()}),w(Wd,()=>{i.current=Yr,I()}),w(Kd,()=>{i.current=Xr,I()})),[w,_,I]);const N=T.useMemo(()=>({playing:f,disabled:y,play:E,pause:M}),[f,y,E,M]);return T.useImperativeHandle(s,()=>N,[N]),T.createElement(ml.Provider,{value:N},n)}const hf=mt("Play",T.createElement("path",{d:"M8 5v14l11-7z"})),pf=mt("Pause",T.createElement("path",{d:"M6 19h4V5H6v14zm8-14v14h4V5h-4z"}));function mf(){const{playing:e,disabled:t,play:r,pause:n}=ff(),{render:o}=rt(),a=Xs(zt().focus,t);return o.buttonSlideshow?T.createElement(T.Fragment,null,o.buttonSlideshow({playing:e,disabled:t,play:r,pause:n})):T.createElement(Er,{label:e?"Pause":"Play",icon:e?pf:hf,renderIcon:e?o.iconSlideshowPause:o.iconSlideshowPlay,onClick:e?n:r,disabled:t,...a})}function bf({augment:e,addModule:t}){e(({slideshow:r,toolbar:n,...o})=>({toolbar:Cn(n,vs,T.createElement(mf,null)),slideshow:pl(r),...o})),t(Mt(vs,gf))}const yf={auto:!1,ref:null},bl=e=>({...yf,...e}),yl=T.createContext(null),vf=At("useFullscreen","FullscreenContext",yl);function wf({fullscreen:e,on:t,children:r}){const{auto:n,ref:o}=bl(e),a=T.useRef(null),[s,l]=T.useState(),[f,h]=T.useState(!1),d=T.useRef(!1),{getOwnerDocument:i}=Sr();$t(()=>{var y,E,M,_;const I=i();l(!((_=(M=(E=(y=I.fullscreenEnabled)!==null&&y!==void 0?y:I.webkitFullscreenEnabled)!==null&&E!==void 0?E:I.mozFullScreenEnabled)!==null&&M!==void 0?M:I.msFullscreenEnabled)!==null&&_!==void 0&&_))},[i]);const u=T.useCallback(()=>{var y;const E=i(),M=E.fullscreenElement||E.webkitFullscreenElement||E.mozFullScreenElement||E.msFullscreenElement;return((y=M?.shadowRoot)===null||y===void 0?void 0:y.fullscreenElement)||M},[i]),g=T.useCallback(()=>{const y=a.current;try{y.requestFullscreen?y.requestFullscreen().catch(()=>{}):y.webkitRequestFullscreen?y.webkitRequestFullscreen():y.mozRequestFullScreen?y.mozRequestFullScreen():y.msRequestFullscreen&&y.msRequestFullscreen()}catch{}},[]),p=T.useCallback(()=>{if(!u())return;const y=i();try{y.exitFullscreen?y.exitFullscreen().catch(()=>{}):y.webkitExitFullscreen?y.webkitExitFullscreen():y.mozCancelFullScreen?y.mozCancelFullScreen():y.msExitFullscreen&&y.msExitFullscreen()}catch{}},[u,i]);T.useEffect(()=>{const y=i(),E=()=>{h(u()===a.current)};return kr(...["fullscreenchange","webkitfullscreenchange","mozfullscreenchange","MSFullscreenChange"].map(M=>(y.addEventListener(M,E),()=>y.removeEventListener(M,E))))},[u,i]);const m=Ie(()=>{var y;return(y=t.enterFullscreen)===null||y===void 0?void 0:y.call(t)}),w=Ie(()=>{var y;return(y=t.exitFullscreen)===null||y===void 0?void 0:y.call(t)});T.useEffect(()=>{f&&(d.current=!0),d.current&&(f?m:w)()},[f,m,w]);const x=Ie(()=>{var y;return(y=n?g:null)===null||y===void 0||y(),p});T.useEffect(x,[x]);const O=T.useMemo(()=>({fullscreen:f,disabled:s,enter:g,exit:p}),[f,s,g,p]);return T.useImperativeHandle(o,()=>O,[O]),T.createElement("div",{ref:a,className:lt(pe(Kr),pe(xs))},T.createElement(yl.Provider,{value:O},r))}const xf=mt("EnterFullscreen",T.createElement("path",{d:"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"})),kf=mt("ExitFullscreen",T.createElement("path",{d:"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"}));function Cf(){var e;const{fullscreen:t,disabled:r,enter:n,exit:o}=vf(),{render:a}=rt();return r?null:a.buttonFullscreen?T.createElement(T.Fragment,null,(e=a.buttonFullscreen)===null||e===void 0?void 0:e.call(a,{fullscreen:t,disabled:r,enter:n,exit:o})):T.createElement(Er,{disabled:r,label:t?"Exit Fullscreen":"Enter Fullscreen",icon:t?kf:xf,renderIcon:t?a.iconExitFullscreen:a.iconEnterFullscreen,onClick:t?o:n})}function Sf({augment:e,contains:t,addParent:r}){e(({fullscreen:n,toolbar:o,...a})=>({toolbar:Cn(o,Kr,T.createElement(Cf,null)),fullscreen:bl(n),...a})),r(t(Vr)?Vr:Wr,Mt(Kr,wf))}const dr={ref:null,position:"bottom",width:120,height:80,border:1,borderRadius:4,padding:4,gap:16,imageFit:"contain",vignette:!0,hidden:!1,showToggle:!1},Wo=e=>({...dr,...e});function vl(){const{thumbnails:e}=rt();return Wo(e)}const ur=e=>or(Vr,e),nt=e=>ur(or("thumbnail",e)),_f=mt("VideoThumbnail",T.createElement("path",{d:"M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"})),Ef=mt("UnknownThumbnail",T.createElement("path",{d:"M23 18V6c0-1.1-.9-2-2-2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zM8.5 12.5l2.5 3.01L14.5 11l4.5 6H5l3.5-4.5z"}));function Tf({slide:e,render:t,rect:r,imageFit:n}){var o;const a=(o=t.thumbnail)===null||o===void 0?void 0:o.call(t,{slide:e,render:t,rect:r,imageFit:n});if(a)return a;const s={render:t,rect:r,imageFit:n};if(e.thumbnail)return T.createElement(ir,{slide:{src:e.thumbnail},...s});if(lr(e))return T.createElement(ir,{slide:e,...s});const l=pe(nt(wn));return e.type==="video"?T.createElement(T.Fragment,null,e.poster&&T.createElement(ir,{slide:{src:e.poster},...s}),T.createElement(_f,{className:l})):T.createElement(Ef,{className:l})}const Nf=ar("active"),Ko=ar("fadein"),Vo=ar("fadeout"),Af=ar("placeholder"),wl="delay",xl="duration";function Mf({slide:e,index:t,onClick:r,fadeIn:n,fadeOut:o,placeholder:a,onLoseFocus:s}){const l=T.useRef(null),{render:f,styles:h,labels:d}=rt(),{slides:i,globalIndex:u}=Ot(),{getOwnerDocument:g}=Sr(),{width:p,height:m,imageFit:w}=vl(),x={width:p,height:m},O=t===u,y=Ie(s);return T.useEffect(()=>{o&&g().activeElement===l.current&&y()},[o,y,g]),T.createElement("button",{ref:l,type:"button",className:lt(pe(wr),pe(nt()),O&&pe(nt(Nf())),n&&pe(nt(Ko())),o&&pe(nt(Vo())),a&&pe(nt(Af()))),style:{...n?{[We(nt(Ko(xl)))]:`${n.duration}ms`,[We(nt(Ko(wl)))]:`${n.delay}ms`}:null,...o?{[We(nt(Vo(xl)))]:`${o.duration}ms`,[We(nt(Vo(wl)))]:`${o.delay}ms`}:null,...h.thumbnail},onClick:r,"aria-current":O?!0:void 0,"aria-label":Ds(d,i,t)},e&&Tf({slide:e,render:f,rect:x,imageFit:w}))}function kl(e){return["top","bottom"].includes(e)}function Cl(e,t){return t+2*(e.border+e.padding)+e.gap}function Of(e){const{thumbnail:t,poster:r}=e||{thumbnail:"placeholder"};return typeof t=="string"&&t||typeof r=="string"&&r||e&&Ls(e)||void 0}function Sl({visible:e,containerRef:t}){const r=T.useRef(null),n=_n(),{publish:o,subscribe:a}=_r(),{carousel:s,styles:l,labels:f}=rt(),{slides:h,globalIndex:d,animation:i}=Ot(),{registerSensors:u,subscribeSensors:g}=qs();rl(g);const p=vl(),{position:m,width:w,height:x,border:O,borderStyle:y,borderColor:E,borderRadius:M,padding:_,gap:I,vignette:C}=p,v=i?.duration!==void 0&&i?.increment||0,N=i?.duration||0,{prepareAnimation:A}=Uo(r,S=>({keyframes:kl(m)?[{transform:`translateX(${(n?-1:1)*Cl(p,w)*v+S}px)`},{transform:"translateX(0)"}]:[{transform:`translateY(${Cl(p,x)*v+S}px)`},{transform:"translateY(0)"}],duration:N,easing:i?.easing})),P=Ie(()=>{let S=0;if(t.current&&r.current){const b=t.current.getBoundingClientRect(),$=r.current.getBoundingClientRect();S=kl(m)?$.left-b.left-(b.width-$.width)/2:$.top-b.top-(b.height-$.height)/2}A(S)});T.useEffect(()=>kr(a(_o,P)),[a,P]);const D=Ps(s,h),L=[];if(Io(h))for(let S=d-D-Math.abs(v);S<=d+D+Math.abs(v);S+=1){const $=s.finite&&(S<0||S>h.length-1)||v<0&&S0&&S>d+D?null:Do(h,S),F=[`${S}`,Of($)].filter(Boolean).join("|");L.push({key:F,index:S,slide:$})}const U=S=>()=>{S>d?o(er,{count:S-d}):S{const F=N/Math.abs(v||1),G=v>0&&b>d+D-v&&b<=d+D||v<0&&b=d-D?{duration:F,delay:((v>0?b-(d+D-v):d-D-v-b)-1)*F}:void 0,Y=v>0&&bd+D?{duration:F,delay:(v>0?v-(d-D-b):-v-(b-(d+D)))*F}:void 0;return T.createElement(Mf,{key:S,index:b,slide:$,fadeIn:G,fadeOut:Y,placeholder:!$,onClick:U(b),onLoseFocus:()=>{var B;return(B=r.current)===null||B===void 0?void 0:B.focus()}})})),C&&T.createElement("div",{className:pe(ur("vignette"))}))}const _l=T.createContext(null),If=At("useThumbnails","ThumbnailsContext",_l);function Df({children:e,...t}){const{ref:r,position:n,hidden:o}=Wo(t.thumbnails),[a,s]=T.useState(!o),l=T.useRef(null),f=T.useMemo(()=>({visible:a,show:()=>s(!0),hide:()=>s(!1)}),[a]);return T.useImperativeHandle(r,()=>f,[f]),T.createElement(Gs,{...t},T.createElement(_l.Provider,{value:f},T.createElement("div",{ref:l,className:lt(pe(ur()),pe(ur(`${n}`)))},["start","top"].includes(n)&&T.createElement(Sl,{containerRef:l,visible:a}),T.createElement("div",{className:pe(ur("wrapper"))},e),["end","bottom"].includes(n)&&T.createElement(Sl,{containerRef:l,visible:a}))))}const El=()=>T.createElement(T.Fragment,null,T.createElement("path",{strokeWidth:2,stroke:"currentColor",strokeLinejoin:"round",fill:"none",d:"M3 5l18 0l0 14l-18 0l0-14z"}),T.createElement("path",{d:"M5 14h4v3h-4zM10 14h4v3h-4zM15 14h4v3h-4z"})),Lf=mt("ThumbnailsVisible",El()),Pf=fu("ThumbnailsHidden",El());function Ff(){const{visible:e,show:t,hide:r}=If(),{render:n}=rt();return n.buttonThumbnails?T.createElement(T.Fragment,null,n.buttonThumbnails({visible:e,show:t,hide:r})):T.createElement(Er,{label:e?"Hide thumbnails":"Show thumbnails",icon:e?Lf:Pf,renderIcon:e?n.iconThumbnailsVisible:n.iconThumbnailsHidden,onClick:e?r:t})}function $f({augment:e,contains:t,append:r,addParent:n}){e(({thumbnails:a,toolbar:s,...l})=>{const f=Wo(a);return{toolbar:Cn(s,Vr,f.showToggle?T.createElement(Ff,null):null),thumbnails:f,...l}});const o=Mt(Vr,Df);t(Kr)?r(Kr,o):n(Wr,o)}const Ct=({className:e="",children:t,style:r,...n})=>c.jsx("i",{className:e,style:r,...n,children:t}),Yo=window.G7Core,Tn=(e,t)=>Yo?.t?.(e,t)??e,Uf=async(e,t)=>{try{const r=await Yo.api.get(e,{responseType:"blob"});if(r){const n=URL.createObjectURL(r),o=document.createElement("a");o.href=n,o.download=t,document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(n)}}catch(r){console.error("Failed to download file:",r),Yo?.toast?.error?.(Tn("common.download_failed"))}},zf=(e,t)=>{const r=document.createElement("a");r.href=e,r.download=t,r.target="_blank",document.body.appendChild(r),r.click(),document.body.removeChild(r)},Tl=async e=>{const t=e.downloadUrl||e.src,r=e.filename||e.title||"image";e.downloadRequiresAuth?await Uf(t,r):zf(t,r)},Hf=({image:e,index:t,onDownload:r})=>{const[n,o]=k.useState(!1),a=async s=>{if(s.stopPropagation(),r){r(e,t);return}o(!0);try{await Tl(e)}finally{o(!1)}};return c.jsx(Q,{type:"button",onClick:a,disabled:n,className:"yarl__button flex items-center justify-center","aria-label":Tn("common.download"),title:Tn("common.download"),children:n?c.jsx(Ct,{className:"fa-solid fa-spinner fa-spin text-white"}):c.jsx(Ct,{className:"fa-solid fa-download text-white"})})},Tr=({images:e,isOpen:t,onClose:r,startIndex:n=0,enableZoom:o=!0,enableSlideshow:a=!1,enableFullscreen:s=!0,showCounter:l=!0,showDownload:f=!0,showThumbnails:h=!0,onDownload:d,editorAttrs:i,id:u})=>{const[g,p]=k.useState(n),m=k.useRef(n),w=e.map(y=>({src:y.src,title:y.title,description:y.description})),x=[];o&&x.push(sf),a&&x.push(bf),s&&x.push(Sf),l&&x.push(df),h&&x.push($f);const O=e[g];if(k.useEffect(()=>{m.current=g},[g]),i){const y=(e??[]).slice(0,4);return c.jsx(W,{id:u,className:"grid grid-cols-2 gap-2 p-3 rounded-lg border border-dashed border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-800",...i,children:y.length>0?y.map((E,M)=>c.jsx(Lt,{src:E.thumbnail||E.src,alt:E.title||"",className:"w-full aspect-square object-cover rounded bg-gray-200 dark:bg-gray-700"},M)):c.jsxs(W,{className:"col-span-2 flex items-center justify-center py-6 text-sm text-gray-400 dark:text-gray-500",children:[c.jsx(Ct,{className:"fa-regular fa-images mr-2"}),Tn("editor.component.image_gallery")]})})}return c.jsx(Bu,{open:t,close:r,slides:w,index:g,plugins:x,on:{view:({index:y})=>{y!==m.current&&p(y)}},zoom:{maxZoomPixelRatio:3,zoomInMultiplier:2,doubleTapDelay:300,doubleClickDelay:300,doubleClickMaxStops:2,keyboardMoveDistance:50,wheelZoomDistanceFactor:100,pinchZoomDistanceFactor:100,scrollToZoom:!0},carousel:{finite:!0,preload:2,padding:"16px",spacing:"30%"},animation:{fade:250,swipe:500,easing:{fade:"ease",swipe:"ease-out",navigation:"ease-in-out"}},controller:{closeOnBackdropClick:!0,closeOnPullDown:!0,closeOnPullUp:!0},thumbnails:{position:"bottom",width:120,height:80,border:2,borderRadius:4,padding:4,gap:16,showToggle:!1,vignette:!0},toolbar:{buttons:[f&&O&&c.jsx(Hf,{image:O,index:g,onDownload:d},"download"),"close"].filter(Boolean)},styles:{container:{backgroundColor:"rgba(0, 0, 0, 0.9)"}}})},Nl=()=>{const[e,t]=k.useState(!1),[r,n]=k.useState([]),[o,a]=k.useState(0),s=k.useCallback((f,h=0)=>{n(f),a(h),t(!0)},[]),l=k.useCallback(()=>{t(!1)},[]);return{isOpen:e,openGallery:s,closeGallery:l,galleryProps:{images:r,isOpen:e,onClose:l,startIndex:o}}};Tr.displayName="ImageGallery";const Al=Object.freeze(Object.defineProperty({__proto__:null,ImageGallery:Tr,default:Tr,executeImageDownload:Tl,useImageGallery:Nl},Symbol.toStringTag,{value:"Module"})),Gf=window.G7Core,Xo=(e,t)=>Gf?.t?.(e,t)??e,Nn=e=>e.url??e.download_url,An=({images:e=[],className:t="",id:r,editorAttrs:n})=>{const[o,a]=k.useState(0),{openGallery:s,galleryProps:l}=Nl(),f=k.useMemo(()=>e.map(d=>({src:Nn(d),title:d.alt_text_current??"",thumbnail:Nn(d),downloadUrl:d.download_url,filename:d.alt_text_current??`image-${d.id}`})),[e]);if(!e||e.length===0)return c.jsx(W,{className:`flex items-center justify-center bg-gray-100 dark:bg-gray-700 rounded-lg aspect-square ${t}`,id:r,...n,children:c.jsxs(W,{className:"text-center text-gray-400 dark:text-gray-500",children:[c.jsx(de,{name:"image",size:"3x",className:"mb-3 opacity-50"}),c.jsx(W,{className:"text-sm",children:Xo("shop.no_image")})]})});const h=e[o]??e[0];return c.jsxs(W,{id:r,className:t,...n,children:[c.jsx(W,{className:"relative overflow-hidden rounded-lg bg-gray-100 dark:bg-gray-700 aspect-square mb-3",children:c.jsx(Q,{type:"button",className:"w-full h-full cursor-zoom-in block",onClick:()=>s(f,o),"aria-label":Xo("shop.view_image"),children:c.jsx(Lt,{src:Nn(h),alt:h.alt_text_current??"",className:"w-full h-full object-contain"})})}),e.length>1&&c.jsx(W,{className:"flex gap-2 overflow-x-auto pb-1",children:e.map((d,i)=>c.jsx(Q,{type:"button",className:`flex-shrink-0 w-16 h-16 rounded-md overflow-hidden border-2 transition-colors cursor-pointer ${i===o?"border-gray-900 dark:border-white":"border-gray-200 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-400"}`,onClick:()=>a(i),"aria-label":d.alt_text_current??`${Xo("shop.image")} ${i+1}`,children:c.jsx(Lt,{src:Nn(d),alt:d.alt_text_current??"",className:"w-full h-full object-cover"})},d.id))}),c.jsx(Tr,{...l})]})};An.displayName="ProductImageViewer";const jf=Object.freeze(Object.defineProperty({__proto__:null,ProductImageViewer:An,default:An},Symbol.toStringTag,{value:"Module"})),Ml=({value:e,min:t=1,max:r=999,onChange:n,size:o="md",disabled:a=!1,className:s="",id:l,editorAttrs:f})=>{const d={sm:{container:"h-8",button:"w-8 h-8 text-sm",input:"w-10 text-sm"},md:{container:"h-10",button:"w-10 h-10",input:"w-14"},lg:{container:"h-12",button:"w-12 h-12 text-lg",input:"w-16 text-lg"}}[o],i=()=>{e>t&&!a&&n(e-1)},u=()=>{e{const O=parseInt(x.target.value,10);if(!isNaN(O)){const y=Math.max(t,Math.min(r,O));n(y)}},p=x=>{const O=parseInt(x.target.value,10);isNaN(O)||Or&&n(r)},m=a||e<=t,w=a||e>=r;return c.jsxs(W,{className:`inline-flex items-center border border-gray-300 dark:border-gray-600 rounded-lg ${d.container} ${s}`,id:l,...f,children:[c.jsx(Q,{type:"button",onClick:i,disabled:m,className:`${d.button} flex items-center justify-center text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed rounded-l-lg transition-colors`,"aria-label":"수량 감소",children:c.jsx(de,{name:"minus",className:"w-4 h-4"})}),c.jsx(xt,{type:"number",value:e,onChange:g,onBlur:p,min:t,max:r,disabled:a,className:`${d.input} text-center border-x border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:outline-none disabled:opacity-50 disabled:cursor-not-allowed [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`,"aria-label":"수량"}),c.jsx(Q,{type:"button",onClick:u,disabled:w,className:`${d.button} flex items-center justify-center text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed rounded-r-lg transition-colors`,"aria-label":"수량 증가",children:c.jsx(de,{name:"plus",className:"w-4 h-4"})})]})},Bf=Object.freeze(Object.defineProperty({__proto__:null,default:Ml},Symbol.toStringTag,{value:"Module"})),Wf=window.G7Core?.createLogger?.("Comp:PostReactions")??{log:(...e)=>console.log("[Comp:PostReactions]",...e),warn:(...e)=>console.warn("[Comp:PostReactions]",...e),error:(...e)=>console.error("[Comp:PostReactions]",...e)},Ol=(e,t)=>window.G7Core?.t?.(e,t)??e,Kf=[{type:"like",emoji:"👍",labelKey:"board.reactions.like",activeColor:"bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400"},{type:"funny",emoji:"😂",labelKey:"board.reactions.funny",activeColor:"bg-yellow-100 dark:bg-yellow-900/30 text-yellow-600 dark:text-yellow-400"},{type:"agree",emoji:"👌",labelKey:"board.reactions.agree",activeColor:"bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400"},{type:"thanks",emoji:"🙏",labelKey:"board.reactions.thanks",activeColor:"bg-purple-100 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400"},{type:"wow",emoji:"😮",labelKey:"board.reactions.wow",activeColor:"bg-orange-100 dark:bg-orange-900/30 text-orange-600 dark:text-orange-400"}],Il=({reactions:e,userReaction:t,postId:r,onReact:n,size:o="md",className:a="",id:s,editorAttrs:l})=>{const f={sm:"px-2 py-1 text-xs gap-1",md:"px-3 py-1.5 text-sm gap-1.5",lg:"px-4 py-2 text-base gap-2"},h={sm:"text-sm",md:"text-base",lg:"text-lg"},d=u=>e.find(p=>p.type===u)?.count??0,i=async u=>{if(n){n(u);return}try{if(!(await fetch(`/api/posts/${r}/reactions`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:u}),credentials:"include"})).ok)throw new Error("리액션 처리 실패");window.location.reload()}catch(g){Wf.error("리액션 오류:",g)}};return c.jsx(W,{className:`flex flex-wrap gap-2 ${a}`,id:s,...l,children:Kf.map(u=>{const g=d(u.type),p=t===u.type;return c.jsxs(Q,{onClick:()=>i(u.type),className:` inline-flex items-center rounded-full border transition-colors ${f[o]} ${p?`${u.activeColor} border-transparent`:"border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"} - `,title:Ol(u.labelKey),children:[c.jsx(ee,{className:h[o],children:u.emoji}),c.jsx(ee,{children:Ol(u.labelKey)}),g>0&&c.jsx(ee,{className:"font-medium",children:g})]},u.type)})})},Vf=Object.freeze(Object.defineProperty({__proto__:null,default:Il},Symbol.toStringTag,{value:"Module"})),Mn=window.G7Core?.createLogger?.("Comp:RichTextEditor")??{log:(...e)=>console.log("[Comp:RichTextEditor]",...e),warn:(...e)=>console.warn("[Comp:RichTextEditor]",...e),error:(...e)=>console.error("[Comp:RichTextEditor]",...e)},St=(e,t)=>window.G7Core?.t?.(e,t)??e,Dl=({name:e,initialValue:t="",placeholder:r,onChange:n,imageUploadUrl:o="/api/upload/image",minHeight:a="300px",disabled:s=!1,className:l="",id:f,editorAttrs:h})=>{const d=k.useRef(null),[i,u]=k.useState(t),[g,p]=k.useState(!1),[m,w]=k.useState(!1),[x,A]=k.useState("");k.useEffect(()=>{d.current&&!d.current.innerHTML&&(d.current.innerHTML=t)},[t]),k.useEffect(()=>{n&&n(i)},[i,n]);const v=N=>{Mn.log("Apply format:",N)},E=async N=>{const M=new FormData;M.append("file",N);try{const P=await fetch(o,{method:"POST",body:M,credentials:"include"});if(!P.ok)throw new Error("업로드 실패");const D=await P.json();Mn.log("Image uploaded:",D.url)}catch(P){Mn.error("이미지 업로드 오류:",P)}},O=N=>{const M=N.target.files?.[0];M&&E(M)},_=()=>{x&&(Mn.log("Insert link:",x),w(!1),A(""))},I=[{format:"bold",icon:"B",title:St("editor.toolbar.bold")},{format:"italic",icon:"I",title:St("editor.toolbar.italic")},{format:"underline",icon:"U",title:St("editor.toolbar.underline")},{format:"strike",icon:"S",title:St("editor.toolbar.strike")},{format:"code",icon:"",title:St("editor.toolbar.code")}],C=[{format:"h1",label:"H1"},{format:"h2",label:"H2"},{format:"h3",label:"H3"}],y=[{format:"bulletList",icon:"•",title:St("editor.toolbar.bullet_list")},{format:"orderedList",icon:"1.",title:St("editor.toolbar.ordered_list")},{format:"blockquote",icon:"❝",title:St("editor.toolbar.blockquote")}];return c.jsxs(W,{className:`border border-gray-300 dark:border-gray-600 rounded-lg overflow-hidden ${l}`,id:f,...h,children:[c.jsxs(W,{className:"flex flex-wrap items-center gap-1 p-2 bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700",children:[c.jsx(W,{className:"flex items-center gap-1 pr-2 border-r border-gray-200 dark:border-gray-700",children:I.map(N=>c.jsx(Q,{type:"button",onClick:()=>v(N.format),disabled:s,className:"w-8 h-8 flex items-center justify-center text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50",title:N.title,children:N.icon},N.format))}),c.jsx(W,{className:"flex items-center gap-1 pr-2 border-r border-gray-200 dark:border-gray-700",children:C.map(N=>c.jsx(Q,{type:"button",onClick:()=>v(N.format),disabled:s,className:"px-2 h-8 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50",children:N.label},N.format))}),c.jsx(W,{className:"flex items-center gap-1 pr-2 border-r border-gray-200 dark:border-gray-700",children:y.map(N=>c.jsx(Q,{type:"button",onClick:()=>v(N.format),disabled:s,className:"w-8 h-8 flex items-center justify-center text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50",title:N.title,children:N.icon},N.format))}),c.jsxs(W,{className:"flex items-center gap-1 pr-2 border-r border-gray-200 dark:border-gray-700",children:[c.jsx(Q,{type:"button",onClick:()=>w(!0),disabled:s,className:"w-8 h-8 flex items-center justify-center text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50",title:St("editor.toolbar.link"),children:"🔗"}),c.jsxs(yr,{className:"w-8 h-8 flex items-center justify-center text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded cursor-pointer",children:["🖼",c.jsx(xt,{type:"file",accept:"image/*",onChange:O,disabled:s,className:"hidden"})]})]}),c.jsxs(Q,{type:"button",onClick:()=>p(!g),disabled:s,className:`px-2 h-8 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50 ${g?"bg-gray-200 dark:bg-gray-700":""}`,children:["",St("editor.toolbar.code_view")]})]}),g?c.jsx(no,{value:i,onChange:N=>u(N.target.value),placeholder:r,disabled:s,className:"w-full p-4 bg-gray-900 text-gray-100 font-mono text-sm focus:outline-none resize-none",style:{minHeight:a}}):c.jsx(W,{ref:d,contentEditable:!s,onInput:N=>u(N.currentTarget.innerHTML),className:"p-4 bg-white dark:bg-gray-900 text-gray-900 dark:text-white focus:outline-none prose dark:prose-invert max-w-none",style:{minHeight:a},"data-placeholder":r}),c.jsx(xt,{type:"hidden",name:e,value:i}),m&&c.jsx(W,{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:c.jsxs(W,{className:"bg-white dark:bg-gray-800 rounded-lg p-6 w-96",children:[c.jsx(gn,{className:"text-lg font-medium text-gray-900 dark:text-white mb-4",children:St("editor.link_modal.title")}),c.jsx(xt,{type:"url",value:x,onChange:N=>A(N.target.value),placeholder:"https://example.com",className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white mb-4"}),c.jsxs(W,{className:"flex justify-end gap-2",children:[c.jsx(Q,{type:"button",onClick:()=>{w(!1),A("")},className:"px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg",children:St("common.cancel")}),c.jsx(Q,{type:"button",onClick:_,className:"px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700",children:St("editor.link_modal.insert")})]})]})})]})},Yf=Object.freeze(Object.defineProperty({__proto__:null,default:Dl},Symbol.toStringTag,{value:"Module"})),Zo=({content:e,text:t,isHtml:r=!0,className:n="",purifyConfig:o,id:a,editorAttrs:s})=>{const l=t??e??"";if(!l||l.trim()==="")return null;if(!r){const i=` + `,title:Ol(u.labelKey),children:[c.jsx(ee,{className:h[o],children:u.emoji}),c.jsx(ee,{children:Ol(u.labelKey)}),g>0&&c.jsx(ee,{className:"font-medium",children:g})]},u.type)})})},Vf=Object.freeze(Object.defineProperty({__proto__:null,default:Il},Symbol.toStringTag,{value:"Module"})),Mn=window.G7Core?.createLogger?.("Comp:RichTextEditor")??{log:(...e)=>console.log("[Comp:RichTextEditor]",...e),warn:(...e)=>console.warn("[Comp:RichTextEditor]",...e),error:(...e)=>console.error("[Comp:RichTextEditor]",...e)},St=(e,t)=>window.G7Core?.t?.(e,t)??e,Dl=({name:e,initialValue:t="",placeholder:r,onChange:n,imageUploadUrl:o="/api/upload/image",minHeight:a="300px",disabled:s=!1,className:l="",id:f,editorAttrs:h})=>{const d=k.useRef(null),[i,u]=k.useState(t),[g,p]=k.useState(!1),[m,w]=k.useState(!1),[x,O]=k.useState("");k.useEffect(()=>{d.current&&!d.current.innerHTML&&(d.current.innerHTML=t)},[t]),k.useEffect(()=>{n&&n(i)},[i,n]);const y=N=>{Mn.log("Apply format:",N)},E=async N=>{const A=new FormData;A.append("file",N);try{const P=await fetch(o,{method:"POST",body:A,credentials:"include"});if(!P.ok)throw new Error("업로드 실패");const D=await P.json();Mn.log("Image uploaded:",D.url)}catch(P){Mn.error("이미지 업로드 오류:",P)}},M=N=>{const A=N.target.files?.[0];A&&E(A)},_=()=>{x&&(Mn.log("Insert link:",x),w(!1),O(""))},I=[{format:"bold",icon:"B",title:St("editor.toolbar.bold")},{format:"italic",icon:"I",title:St("editor.toolbar.italic")},{format:"underline",icon:"U",title:St("editor.toolbar.underline")},{format:"strike",icon:"S",title:St("editor.toolbar.strike")},{format:"code",icon:"",title:St("editor.toolbar.code")}],C=[{format:"h1",label:"H1"},{format:"h2",label:"H2"},{format:"h3",label:"H3"}],v=[{format:"bulletList",icon:"•",title:St("editor.toolbar.bullet_list")},{format:"orderedList",icon:"1.",title:St("editor.toolbar.ordered_list")},{format:"blockquote",icon:"❝",title:St("editor.toolbar.blockquote")}];return c.jsxs(W,{className:`border border-gray-300 dark:border-gray-600 rounded-lg overflow-hidden ${l}`,id:f,...h,children:[c.jsxs(W,{className:"flex flex-wrap items-center gap-1 p-2 bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700",children:[c.jsx(W,{className:"flex items-center gap-1 pr-2 border-r border-gray-200 dark:border-gray-700",children:I.map(N=>c.jsx(Q,{type:"button",onClick:()=>y(N.format),disabled:s,className:"w-8 h-8 flex items-center justify-center text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50",title:N.title,children:N.icon},N.format))}),c.jsx(W,{className:"flex items-center gap-1 pr-2 border-r border-gray-200 dark:border-gray-700",children:C.map(N=>c.jsx(Q,{type:"button",onClick:()=>y(N.format),disabled:s,className:"px-2 h-8 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50",children:N.label},N.format))}),c.jsx(W,{className:"flex items-center gap-1 pr-2 border-r border-gray-200 dark:border-gray-700",children:v.map(N=>c.jsx(Q,{type:"button",onClick:()=>y(N.format),disabled:s,className:"w-8 h-8 flex items-center justify-center text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50",title:N.title,children:N.icon},N.format))}),c.jsxs(W,{className:"flex items-center gap-1 pr-2 border-r border-gray-200 dark:border-gray-700",children:[c.jsx(Q,{type:"button",onClick:()=>w(!0),disabled:s,className:"w-8 h-8 flex items-center justify-center text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50",title:St("editor.toolbar.link"),children:"🔗"}),c.jsxs(yr,{className:"w-8 h-8 flex items-center justify-center text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded cursor-pointer",children:["🖼",c.jsx(xt,{type:"file",accept:"image/*",onChange:M,disabled:s,className:"hidden"})]})]}),c.jsxs(Q,{type:"button",onClick:()=>p(!g),disabled:s,className:`px-2 h-8 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700 rounded disabled:opacity-50 ${g?"bg-gray-200 dark:bg-gray-700":""}`,children:["",St("editor.toolbar.code_view")]})]}),g?c.jsx(no,{value:i,onChange:N=>u(N.target.value),placeholder:r,disabled:s,className:"w-full p-4 bg-gray-900 text-gray-100 font-mono text-sm focus:outline-none resize-none",style:{minHeight:a}}):c.jsx(W,{ref:d,contentEditable:!s,onInput:N=>u(N.currentTarget.innerHTML),className:"p-4 bg-white dark:bg-gray-900 text-gray-900 dark:text-white focus:outline-none prose dark:prose-invert max-w-none",style:{minHeight:a},"data-placeholder":r}),c.jsx(xt,{type:"hidden",name:e,value:i}),m&&c.jsx(W,{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:c.jsxs(W,{className:"bg-white dark:bg-gray-800 rounded-lg p-6 w-96",children:[c.jsx(gn,{className:"text-lg font-medium text-gray-900 dark:text-white mb-4",children:St("editor.link_modal.title")}),c.jsx(xt,{type:"url",value:x,onChange:N=>O(N.target.value),placeholder:"https://example.com",className:"w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white mb-4"}),c.jsxs(W,{className:"flex justify-end gap-2",children:[c.jsx(Q,{type:"button",onClick:()=>{w(!1),O("")},className:"px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg",children:St("common.cancel")}),c.jsx(Q,{type:"button",onClick:_,className:"px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700",children:St("editor.link_modal.insert")})]})]})})]})},Yf=Object.freeze(Object.defineProperty({__proto__:null,default:Dl},Symbol.toStringTag,{value:"Module"})),qo=({content:e,text:t,isHtml:r=!0,className:n="",purifyConfig:o,id:a,editorAttrs:s})=>{const l=t??e??"";if(!l||l.trim()==="")return null;if(!r){const i=` whitespace-pre-wrap text-gray-900 dark:text-gray-100 font-sans @@ -39,7 +39,7 @@ var SirsoftBasic=(function(J,c,k,Jt){"use strict";function Ic(e){const t=Object. [&_tr:hover]:bg-gray-50 dark:[&_tr:hover]:bg-gray-700/50 after:content-[''] after:block after:clear-both ${n} - `.trim().replace(/\s+/g," ");return c.jsx(W,{id:a,className:d,dangerouslySetInnerHTML:{__html:h},...s})},Xf=Object.freeze(Object.defineProperty({__proto__:null,HtmlContent:Zo},Symbol.toStringTag,{value:"Module"})),qo=()=>window.G7Core,Qo=(e,t)=>qo()?.t?.(e,t)??e,Ll=({content:e="",onChange:t,isHtml:r=!1,onIsHtmlChange:n,rows:o=15,placeholder:a="",label:s,showHtmlModeToggle:l=!0,contentClassName:f="",purifyConfig:h,className:d="",name:i="content",htmlFieldName:u="content_mode",readOnly:g=!1,id:p,editorAttrs:m})=>{const[w,x]=k.useState(r),[A,v]=k.useState(e),[E,O]=k.useState(!1);k.useEffect(()=>{x(r)},[r]),k.useEffect(()=>{v(e)},[e]);const _=k.useCallback(y=>{const N=y.target.value;if(v(N),t){const M=qo()?.createChangeEvent?.({value:N,name:i,type:"textarea"})??{target:{name:i,value:N}};t(M)}},[t,i]),I=k.useCallback(y=>{const N=y.target.checked;if(x(N),N||O(!1),n){const M=qo()?.createChangeEvent?.({checked:N,name:u,type:"checkbox"})??{target:{name:u,checked:N}};n(M)}},[n,u]),C=k.useCallback(()=>{O(y=>!y)},[]);return c.jsxs(W,{className:`space-y-2 ${d}`,id:p,...m,children:[c.jsxs(W,{className:"flex items-center justify-between",children:[s&&c.jsx(yr,{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:s}),c.jsxs(W,{className:"flex items-center gap-3",children:[w&&!g&&c.jsx(Q,{type:"button",onClick:C,className:`px-3 py-1.5 text-xs font-bold rounded-lg focus:outline-none focus:ring-2 ${E?"text-gray-700 dark:text-gray-200 bg-gray-200 dark:bg-gray-600 border border-gray-300 dark:border-gray-500 hover:bg-gray-300 dark:hover:bg-gray-500 focus:ring-gray-400 dark:focus:ring-gray-500":"text-blue-600 dark:text-blue-400 bg-white dark:bg-gray-700 border border-blue-300 dark:border-blue-600 hover:bg-blue-50 dark:hover:bg-gray-600 focus:ring-blue-500 dark:focus:ring-blue-600"}`,children:Qo(E?"common.preview_off":"common.preview")}),l&&c.jsxs(yr,{className:"flex items-center gap-2 p-2 cursor-pointer",children:[c.jsx(xt,{type:"checkbox",name:u,checked:w,onChange:I,disabled:g,className:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"}),c.jsx(W,{className:"text-sm font-medium text-gray-700 dark:text-gray-300",children:Qo("common.html_mode")})]})]})]}),!E&&c.jsx(no,{name:i,value:A,onChange:_,placeholder:a,rows:o,readOnly:g,className:`block w-full rounded-lg border px-3 py-2 text-sm placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-1 disabled:opacity-50 disabled:cursor-not-allowed ${w?"font-mono bg-white dark:bg-gray-800 border-blue-300 dark:border-blue-600 text-gray-800 dark:text-gray-200 focus:border-blue-500 focus:ring-blue-500":"bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-600 text-gray-900 dark:text-white focus:border-blue-500 focus:ring-blue-500"}`}),E&&c.jsx(W,{className:"p-4 bg-gray-50 dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-800 min-h-[400px]",children:c.jsx(Zo,{content:A,isHtml:!0,className:f||"prose dark:prose-invert max-w-none text-gray-900 dark:text-gray-100",purifyConfig:h})})]})},Zf=Object.freeze(Object.defineProperty({__proto__:null,HtmlEditor:Ll},Symbol.toStringTag,{value:"Module"})),Pl=e=>window.G7Core?.t?.(e)??e,Jo=({maxHeight:e=500,expandText:t,collapseText:r,className:n="",children:o,id:a,editorAttrs:s})=>{const[l,f]=k.useState(!1),[h,d]=k.useState(!1),i=k.useRef(null),u=k.useCallback(()=>{if(i.current){const w=i.current.scrollHeight;d(w>e)}},[e]);k.useEffect(()=>{u();const w=i.current;if(!w)return;const x=w.querySelectorAll("img");x.forEach(v=>{v.complete||v.addEventListener("load",u)});let A=null;return typeof ResizeObserver<"u"&&(A=new ResizeObserver(u),A.observe(w)),()=>{x.forEach(v=>{v.removeEventListener("load",u)}),A?.disconnect()}},[u,o]);const g=()=>{f(w=>!w)},p=t||Pl("sirsoft-ecommerce.shop.product.expand_detail"),m=r||Pl("sirsoft-ecommerce.shop.product.collapse_detail");return c.jsxs(W,{className:n,id:a,...s,children:[c.jsxs(W,{className:"relative",children:[c.jsx(W,{ref:i,className:!l&&h?"overflow-hidden transition-[max-height] duration-300 ease-in-out":"transition-[max-height] duration-300 ease-in-out",style:!l&&h?{maxHeight:`${e}px`}:void 0,children:o}),!l&&h&&c.jsx(W,{className:"absolute bottom-0 left-0 right-0 h-24 bg-gradient-to-t from-white dark:from-gray-900 to-transparent pointer-events-none"})]}),h&&c.jsxs(Q,{type:"button",onClick:g,className:"flex items-center justify-center w-full py-3.5 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors cursor-pointer gap-1.5",children:[c.jsx(ee,{className:"text-sm font-semibold text-gray-600 dark:text-gray-400",children:l?m:p}),c.jsx(de,{name:l?"chevron-up":"chevron-down",size:"sm"})]})]})},qf=Object.freeze(Object.defineProperty({__proto__:null,ExpandableContent:Jo,default:Jo},Symbol.toStringTag,{value:"Module"})),Qf=(e,t)=>window.G7Core?.t?.(e,t)??e,Ro=({isOpen:e,onClose:t,title:r,icon:n,iconClassName:o="text-gray-500 dark:text-gray-400",closeOnBackdropClick:a=!0,closeOnOverlayClick:s,showCloseButton:l=!0,closeOnEscape:f=!0,children:h,width:d="500px",className:i="",style:u})=>{const g=s!==void 0?s:a,p=k.useRef(null),m=k.useRef(null);if(k.useEffect(()=>{const x=A=>{A.key==="Escape"&&e&&f&&t()};if(e&&f)return document.addEventListener("keydown",x),()=>document.removeEventListener("keydown",x)},[e,t,f]),k.useEffect(()=>{if(e&&p.current){m.current=document.activeElement;const x=p.current.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),A=x[0],v=x[x.length-1];A?.focus();const E=O=>{O.key==="Tab"&&(O.shiftKey?document.activeElement===A&&(O.preventDefault(),v?.focus()):document.activeElement===v&&(O.preventDefault(),A?.focus()))};return document.addEventListener("keydown",E),()=>{document.removeEventListener("keydown",E),m.current?.focus()}}},[e]),k.useEffect(()=>{if(e)return document.body.style.overflow="hidden",()=>{document.body.style.overflow=""}},[e]),!e)return null;const w=u?.zIndex??50;return c.jsxs(W,{className:"fixed inset-0 flex items-center justify-center",style:{zIndex:w},onClick:g?t:void 0,children:[c.jsx(W,{className:"absolute inset-0 bg-black/50","aria-hidden":"true"}),c.jsxs(W,{ref:p,className:`relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-h-[90vh] max-w-[calc(100vw-2rem)] overflow-hidden ${i}`,style:{width:d,...u?{...u,zIndex:void 0}:{}},onClick:x=>x.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":r?"modal-title":void 0,children:[(r||n||l)&&c.jsxs(W,{className:"flex items-center justify-between p-4",children:[(r||n)&&c.jsxs(W,{id:"modal-title",className:"flex items-center gap-3 text-lg font-semibold text-gray-900 dark:text-white",children:[n&&c.jsx(de,{name:n,size:"md",className:o}),r]}),l&&c.jsx(Q,{onClick:t,className:"ml-auto text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 focus:outline-none","aria-label":Qf("common.close_modal"),children:c.jsx("svg",{className:"w-6 h-6",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),c.jsx(W,{className:"px-6 py-4 overflow-y-auto max-h-[calc(90vh-140px)]",children:h})]})]})},Jf=Object.freeze(Object.defineProperty({__proto__:null,Modal:Ro},Symbol.toStringTag,{value:"Module"})),ea=(e,t)=>window.G7Core?.t?.(e,t)??e,ta=({isOpen:e,onClose:t,title:r,message:n,confirmText:o,cancelText:a,onConfirm:s,onCancel:l,confirmButtonVariant:f="primary",cancelButtonVariant:h="secondary",width:d="500px",closeOnOverlay:i=!0,isLoading:u=!1,loadingText:g})=>{const p=o??ea("common.confirm"),m=a??ea("common.cancel"),w=g??ea("common.loading"),x=()=>{s()},A=()=>{u||(l?.(),t())},v=()=>{u||t()},E={primary:"bg-blue-600 text-white hover:bg-blue-700",secondary:"bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-gray-600",danger:"bg-red-600 text-white hover:bg-red-700",ghost:"bg-transparent text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"};return c.jsxs(Ro,{isOpen:e,onClose:v,title:r,width:d,children:[c.jsx(W,{className:"py-2",children:typeof n=="string"?c.jsx(Dt,{className:"text-gray-700 dark:text-gray-300",children:n}):n}),c.jsxs(W,{className:"flex justify-end gap-3 mt-6",children:[c.jsx(Q,{onClick:A,disabled:u,className:"px-4 py-2 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed",children:c.jsx(ee,{children:m})}),c.jsxs(Q,{onClick:x,disabled:u,className:`flex items-center gap-2 px-4 py-2 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed ${E[f]}`,children:[u&&c.jsx(Ct,{className:"fa-solid fa-spinner w-4 h-4 animate-spin"}),c.jsx(ee,{children:u?w:p})]})]})]})},Rf=Object.freeze(Object.defineProperty({__proto__:null,ConfirmDialog:ta},Symbol.toStringTag,{value:"Module"})),Fl=k.createContext(null),$l=({value:e,children:t})=>c.jsx(Fl.Provider,{value:e,children:t}),eg=()=>{const e=k.useContext(Fl);if(!e)throw new Error("useFileUploaderContext must be used within FileUploaderProvider");return e};function tg(e,t){return t.forEach((function(r){r&&typeof r!="string"&&!Array.isArray(r)&&Object.keys(r).forEach((function(n){if(n!=="default"&&!(n in e)){var o=Object.getOwnPropertyDescriptor(r,n);Object.defineProperty(e,n,o.get?o:{enumerable:!0,get:function(){return r[n]}})}}))})),Object.freeze(e)}function Ul(e,t){return new Promise((function(r,n){let o;return rg(e).then((function(a){try{return o=a,r(new Blob([t.slice(0,2),o,t.slice(2)],{type:"image/jpeg"}))}catch(s){return n(s)}}),n)}))}const rg=e=>new Promise(((t,r)=>{const n=new FileReader;n.addEventListener("load",(({target:{result:o}})=>{const a=new DataView(o);let s=0;if(a.getUint16(s)!==65496)return r("not a valid JPEG");for(s+=2;;){const l=a.getUint16(s);if(l===65498)break;const f=a.getUint16(s+2);if(l===65505&&a.getUint32(s+4)===1165519206){const h=s+10;let d;switch(a.getUint16(h)){case 18761:d=!0;break;case 19789:d=!1;break;default:return r("TIFF header contains invalid endian")}if(a.getUint16(h+2,d)!==42)return r("TIFF header contains invalid version");const i=a.getUint32(h+4,d),u=h+i+2+12*a.getUint16(h+i,d);for(let g=h+i+2;g>>24&255,l[s+1]=f>>>16&255,l[s+2]=f>>>8&255,l[s+3]=f>>>0&255,new Uint8Array(l.buffer,0,s+4)},n.deflateRaw=function(o,a){a==null&&(a={level:6});var s=new Uint8Array(50+Math.floor(1.1*o.length)),l=n.F.deflateRaw(o,s,l,a.level);return new Uint8Array(s.buffer,0,l)},n.encode=function(o,a){a==null&&(a=!1);var s=0,l=n.bin.writeUint,f=n.bin.writeUshort,h={};for(var d in o){var i=!n._noNeed(d)&&!a,u=o[d],g=n.crc.crc(u,0,u.length);h[d]={cpr:i,usize:u.length,crc:g,file:i?n.deflateRaw(u):u}}for(var d in h)s+=h[d].file.length+30+46+2*n.bin.sizeUTF8(d);s+=22;var p=new Uint8Array(s),m=0,w=[];for(var d in h){var x=h[d];w.push(m),m=n._writeHeader(p,m,d,x,0)}var A=0,v=m;for(var d in h)x=h[d],w.push(m),m=n._writeHeader(p,m,d,x,1,w[A++]);var E=m-v;return l(p,m,101010256),m+=4,f(p,m+=4,A),f(p,m+=2,A),l(p,m+=2,E),l(p,m+=4,v),m+=4,m+=2,p.buffer},n._noNeed=function(o){var a=o.split(".").pop().toLowerCase();return"png,jpg,jpeg,zip".indexOf(a)!=-1},n._writeHeader=function(o,a,s,l,f,h){var d=n.bin.writeUint,i=n.bin.writeUshort,u=l.file;return d(o,a,f==0?67324752:33639248),a+=4,f==1&&(a+=2),i(o,a,20),i(o,a+=2,0),i(o,a+=2,l.cpr?8:0),d(o,a+=2,0),d(o,a+=4,l.crc),d(o,a+=4,u.length),d(o,a+=4,l.usize),i(o,a+=4,n.bin.sizeUTF8(s)),i(o,a+=2,0),a+=2,f==1&&(a+=2,a+=2,d(o,a+=6,h),a+=4),a+=n.bin.writeUTF8(o,a,s),f==0&&(o.set(u,a),a+=u.length),a},n.crc={table:(function(){for(var o=new Uint32Array(256),a=0;a<256;a++){for(var s=a,l=0;l<8;l++)1&s?s=3988292384^s>>>1:s>>>=1;o[a]=s}return o})(),update:function(o,a,s,l){for(var f=0;f>>8;return o},crc:function(o,a,s){return 4294967295^n.crc.update(4294967295,o,a,s)}},n.adler=function(o,a,s){for(var l=1,f=0,h=a,d=a+s;h>8&255},readUint:function(o,a){return 16777216*o[a+3]+(o[a+2]<<16|o[a+1]<<8|o[a])},writeUint:function(o,a,s){o[a]=255&s,o[a+1]=s>>8&255,o[a+2]=s>>16&255,o[a+3]=s>>24&255},readASCII:function(o,a,s){for(var l="",f=0;f>6,o[a+f+1]=128|d>>0&63,f+=2;else if((4294901760&d)==0)o[a+f]=224|d>>12,o[a+f+1]=128|d>>6&63,o[a+f+2]=128|d>>0&63,f+=3;else{if((4292870144&d)!=0)throw"e";o[a+f]=240|d>>18,o[a+f+1]=128|d>>12&63,o[a+f+2]=128|d>>6&63,o[a+f+3]=128|d>>0&63,f+=4}}return f},sizeUTF8:function(o){for(var a=o.length,s=0,l=0;l>>3}var w=h.lits,x=h.strt,A=h.prev,v=0,E=0,O=0,_=0,I=0,C=0;for(m>2&&(x[C=n.F._hash(o,0)]=0),u=0;u14e3||E>26697)&&m-u>100&&(p>>16,P=65535&N;if(N!=0){P=65535&N;var D=d(M=N>>>16,h.of0);h.lhst[257+D]++;var L=d(P,h.df0);h.dhst[L]++,_+=h.exb[D]+h.dxb[L],w[v]=M<<23|u-p,w[v+1]=P<<16|D<<8|L,v+=2,p=u+M}else h.lhst[o[u]]++;E++}}for(O==u&&o.length!=0||(p>>3},n.F._bestMatch=function(o,a,s,l,f,h){var d=32767&a,i=s[d],u=d-i+32768&32767;if(i==d||l!=n.F._hash(o,a-u))return 0;for(var g=0,p=0,m=Math.min(32767,a);u<=m&&--h!=0&&i!=d;){if(g==0||o[a+g]==o[a+g-u]){var w=n.F._howLong(o,a,u);if(w>g){if(p=u,(g=w)>=f)break;u+2x&&(x=E,i=v)}}}u+=(d=i)-(i=s[d])+32768&32767}return g<<16|p},n.F._howLong=function(o,a,s){if(o[a]!=o[a-s]||o[a+1]!=o[a+1-s]||o[a+2]!=o[a+2-s])return 0;var l=a,f=Math.min(o.length,a+258);for(a+=3;a>>23,Y=b+(8388607&F);b>16,j=B>>8&255,H=255&B;C(i,u=n.F._writeLit(257+j,L,i,u),G-_.of0[j]),u+=_.exb[j],I(i,u=n.F._writeLit(H,U,i,u),V-_.df0[H]),u+=_.dxb[H],b+=G}}u=n.F._writeLit(256,L,i,u)}return u},n.F._copyExact=function(o,a,s,l,f){var h=f>>>3;return l[h]=s,l[h+1]=s>>>8,l[h+2]=255-l[h],l[h+3]=255-l[h+1],h+=4,l.set(new Uint8Array(o.buffer,a,s),h),f+(s+4<<3)},n.F.getTrees=function(){for(var o=n.F.U,a=n.F._hufTree(o.lhst,o.ltree,15),s=n.F._hufTree(o.dhst,o.dtree,15),l=[],f=n.F._lenCodes(o.ltree,l),h=[],d=n.F._lenCodes(o.dtree,h),i=0;i4&&o.itree[1+(o.ordr[g-1]<<1)]==0;)g--;return[a,s,u,f,d,g,l,h]},n.F.getSecond=function(o){for(var a=[],s=0;s>1)+",");return a},n.F.contSize=function(o,a){for(var s=0,l=0;l15&&(n.F._putsE(s,l,d,i),l+=i)}return l},n.F._lenCodes=function(o,a){for(var s=o.length;s!=2&&o[s-1]==0;)s-=2;for(var l=0;l>>1,138))<11?a.push(17,g-3):a.push(18,g-11),l+=2*g-2}else if(f==i&&h==f&&d==f){for(u=l+5;u+2>>1,6);a.push(16,g-3),l+=2*g-2}else a.push(f,0)}return s>>>1},n.F._hufTree=function(o,a,s){var l=[],f=o.length,h=a.length,d=0;for(d=0;ds&&(n.F.restrictDepth(u,s,v),v=s),d=0;da;l++){var d=o[l].d;o[l].d=a,h+=f-(1<>>=s-a;h>0;)(d=o[l].d)=0;l--)o[l].d==a&&h<0&&(o[l].d--,h++);h!=0&&console.log("debt left")},n.F._goodIndex=function(o,a){var s=0;return a[16|s]<=o&&(s|=16),a[8|s]<=o&&(s|=8),a[4|s]<=o&&(s|=4),a[2|s]<=o&&(s|=2),a[1|s]<=o&&(s|=1),s},n.F._writeLit=function(o,a,s,l){return n.F._putsF(s,l,a[o<<1]),l+a[1+(o<<1)]},n.F.inflate=function(o,a){var s=Uint8Array;if(o[0]==3&&o[1]==0)return a||new s(0);var l=n.F,f=l._bitsF,h=l._bitsE,d=l._decodeTiny,i=l.makeCodes,u=l.codes2map,g=l._get17,p=l.U,m=a==null;m&&(a=new s(o.length>>>2<<3));for(var w,x,A=0,v=0,E=0,O=0,_=0,I=0,C=0,y=0,N=0;A==0;)if(A=f(o,N,1),v=f(o,N+1,2),N+=3,v!=0){if(m&&(a=n.F._check(a,y+131072)),v==1&&(w=p.flmap,x=p.fdmap,I=511,C=31),v==2){E=h(o,N,5)+257,O=h(o,N+5,5)+1,_=h(o,N+10,4)+4,N+=14;for(var M=0;M<38;M+=2)p.itree[M]=0,p.itree[M+1]=0;var P=1;for(M=0;M<_;M++){var D=h(o,N+3*M,3);p.itree[1+(p.ordr[M]<<1)]=D,D>P&&(P=D)}N+=3*_,i(p.itree,P),u(p.itree,P,p.imap),w=p.lmap,x=p.dmap,N=d(p.imap,(1<>>4;if(!(b>>>8))a[y++]=b;else{if(b==256)break;var $=y+b-254;if(b>264){var F=p.ldef[b-257];$=y+(F>>>3)+h(o,N,7&F),N+=7&F}var G=x[g(o,N)&C];N+=15&G;var Y=G>>>4,B=p.ddef[Y],V=(B>>>4)+f(o,N,15&B);for(N+=15&B,m&&(a=n.F._check(a,y+131072));y<$;)a[y]=a[y++-V],a[y]=a[y++-V],a[y]=a[y++-V],a[y]=a[y++-V];y=$}}}else{(7&N)!=0&&(N+=8-(7&N));var j=4+(N>>>3),H=o[j-4]|o[j-3]<<8;m&&(a=n.F._check(a,y+H)),a.set(new s(o.buffer,o.byteOffset+j,H),y),N=j+H<<3,y+=H}return a.length==y?a:a.slice(0,y)},n.F._check=function(o,a){var s=o.length;if(a<=s)return o;var l=new Uint8Array(Math.max(s<<1,a));return l.set(o,0),l},n.F._decodeTiny=function(o,a,s,l,f,h){for(var d=n.F._bitsE,i=n.F._get17,u=0;u>>4;if(p<=15)h[u]=p,u++;else{var m=0,w=0;p==16?(w=3+d(l,f,2),f+=2,m=h[u-1]):p==17?(w=3+d(l,f,3),f+=3):p==18&&(w=11+d(l,f,7),f+=7);for(var x=u+w;u>>1;hf&&(f=i),h++}for(;h>1,i=o[h+1],u=d<<4|i,g=a-i,p=o[h]<>>15-a]=u,p++},n.F.revCodes=function(o,a){for(var s=n.F.U.rev15,l=15-a,f=0;f>>l}},n.F._putsE=function(o,a,s){s<<=7&a;var l=a>>>3;o[l]|=s,o[l+1]|=s>>>8},n.F._putsF=function(o,a,s){s<<=7&a;var l=a>>>3;o[l]|=s,o[l+1]|=s>>>8,o[l+2]|=s>>>16},n.F._bitsE=function(o,a,s){return(o[a>>>3]|o[1+(a>>>3)]<<8)>>>(7&a)&(1<>>3]|o[1+(a>>>3)]<<8|o[2+(a>>>3)]<<16)>>>(7&a)&(1<>>3]|o[1+(a>>>3)]<<8|o[2+(a>>>3)]<<16)>>>(7&a)},n.F._get25=function(o,a){return(o[a>>>3]|o[1+(a>>>3)]<<8|o[2+(a>>>3)]<<16|o[3+(a>>>3)]<<24)>>>(7&a)},n.F.U=(t=Uint16Array,r=Uint32Array,{next_code:new t(16),bl_count:new t(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new t(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new r(32),flmap:new t(512),fltree:[],fdmap:new t(32),fdtree:[],lmap:new t(32768),ltree:[],ttree:[],dmap:new t(32768),dtree:[],imap:new t(512),itree:[],rev15:new t(32768),lhst:new r(286),dhst:new r(30),ihst:new r(19),lits:new r(15e3),strt:new t(65536),prev:new t(32768)}),(function(){for(var o=n.F.U,a=0;a<32768;a++){var s=a;s=(4278255360&(s=(4042322160&(s=(3435973836&(s=(2863311530&s)>>>1|(1431655765&s)<<1))>>>2|(858993459&s)<<2))>>>4|(252645135&s)<<4))>>>8|(16711935&s)<<8,o.rev15[a]=(s>>>16|s<<16)>>>17}function l(f,h,d){for(;h--!=0;)f.push(0,d)}for(a=0;a<32;a++)o.ldef[a]=o.of0[a]<<3|o.exb[a],o.ddef[a]=o.df0[a]<<4|o.dxb[a];l(o.fltree,144,8),l(o.fltree,112,9),l(o.fltree,24,7),l(o.fltree,8,8),n.F.makeCodes(o.fltree,9),n.F.codes2map(o.fltree,9,o.flmap),n.F.revCodes(o.fltree,9),l(o.fdtree,32,5),n.F.makeCodes(o.fdtree,5),n.F.codes2map(o.fdtree,5,o.fdmap),n.F.revCodes(o.fdtree,5),l(o.itree,19,0),l(o.ltree,286,0),l(o.dtree,30,0),l(o.ttree,320,0)})()})();var og=tg({__proto__:null,default:On},[On]);const Ht=(function(){var e={nextZero(d,i){for(;d[i]!=0;)i++;return i},readUshort:(d,i)=>d[i]<<8|d[i+1],writeUshort(d,i,u){d[i]=u>>8&255,d[i+1]=255&u},readUint:(d,i)=>16777216*d[i]+(d[i+1]<<16|d[i+2]<<8|d[i+3]),writeUint(d,i,u){d[i]=u>>24&255,d[i+1]=u>>16&255,d[i+2]=u>>8&255,d[i+3]=255&u},readASCII(d,i,u){let g="";for(let p=0;pd.length<2?`0${d}`:d,readUTF8(d,i,u){let g,p="";for(let m=0;m>3)]>>7-((7&_)<<0)&1);x[y]=F[D],x[y+1]=F[D+1],x[y+2]=F[D+2],x[y+3]=L>2)]>>6-((3&_)<<1)&3),x[y]=F[D],x[y+1]=F[D+1],x[y+2]=F[D+2],x[y+3]=L>1)]>>4-((1&_)<<2)&15),x[y]=F[D],x[y+1]=F[D+1],x[y+2]=F[D+2],x[y+3]=L>>3)]>>>7-(7&b)&1))==255*C?0:255;A[G+b]=$<<24|U<<16|U<<8|U}else if(E==2)for(b=0;b>>2)]>>>6-((3&b)<<1)&3))==85*C?0:255,A[G+b]=$<<24|U<<16|U<<8|U;else if(E==4)for(b=0;b>>1)]>>>4-((1&b)<<2)&15))==17*C?0:255,A[G+b]=$<<24|U<<16|U<<8|U;else if(E==8)for(b=0;b>3,C=Math.ceil(E*_/8),y=new Uint8Array(O*C);let N=0;const M=[0,0,4,0,2,0,1],P=[0,4,0,2,0,1,0],D=[8,8,8,4,4,2,2],L=[8,8,4,4,2,2,1];let U=0;for(;U<7;){const b=D[U],$=L[U];let F=0,G=0,Y=M[U];for(;Y>3])>>7-(7&ue)&1,y[H*C+(Z>>3)]|=S<<7-((7&Z)<<0)),_==2&&(S=(S=A[ue>>3])>>6-(7&ue)&3,y[H*C+(Z>>2)]|=S<<6-((3&Z)<<1)),_==4&&(S=(S=A[ue>>3])>>4-(7&ue)&15,y[H*C+(Z>>1)]|=S<<4-((1&Z)<<2)),_>=8){const te=H*C+Z*I;for(let fe=0;fe>3)+fe]}ue+=_,Z+=$}j++,H+=b}F*G!=0&&(N+=G*(1+V)),U+=1}return y})(i,d)),i}function n(d,i){return o(new Uint8Array(d.buffer,2,d.length-6),i)}var o=(function(){const d={H:{}};return d.H.N=function(i,u){const g=Uint8Array;let p,m,w=0,x=0,A=0,v=0,E=0,O=0,_=0,I=0,C=0;if(i[0]==3&&i[1]==0)return u||new g(0);const y=d.H,N=y.b,M=y.e,P=y.R,D=y.n,L=y.A,U=y.Z,S=y.m,b=u==null;for(b&&(u=new g(i.length>>>2<<5));w==0;)if(w=N(i,C,1),x=N(i,C+1,2),C+=3,x!=0){if(b&&(u=d.H.W(u,I+(1<<17))),x==1&&(p=S.J,m=S.h,O=511,_=31),x==2){A=M(i,C,5)+257,v=M(i,C+5,5)+1,E=M(i,C+10,4)+4,C+=14;let F=1;for(var $=0;$<38;$+=2)S.Q[$]=0,S.Q[$+1]=0;for($=0;$F&&(F=B)}C+=3*E,D(S.Q,F),L(S.Q,F,S.u),p=S.w,m=S.d,C=P(S.u,(1<>>4;if(!(G>>>8))u[I++]=G;else{if(G==256)break;{let Y=I+G-254;if(G>264){const Z=S.q[G-257];Y=I+(Z>>>3)+M(i,C,7&Z),C+=7&Z}const B=m[U(i,C)&_];C+=15&B;const V=B>>>4,j=S.c[V],H=(j>>>4)+N(i,C,15&j);for(C+=15&j;I>>3),G=i[F-4]|i[F-3]<<8;b&&(u=d.H.W(u,I+G)),u.set(new g(i.buffer,i.byteOffset+F,G),I),C=F+G<<3,I+=G}return u.length==I?u:u.slice(0,I)},d.H.W=function(i,u){const g=i.length;if(u<=g)return i;const p=new Uint8Array(g<<1);return p.set(i,0),p},d.H.R=function(i,u,g,p,m,w){const x=d.H.e,A=d.H.Z;let v=0;for(;v>>4;if(O<=15)w[v]=O,v++;else{let _=0,I=0;O==16?(I=3+x(p,m,2),m+=2,_=w[v-1]):O==17?(I=3+x(p,m,3),m+=3):O==18&&(I=11+x(p,m,7),m+=7);const C=v+I;for(;v>>1;for(;wm&&(m=A),w++}for(;w>1,A=i[w+1],v=x<<4|A,E=u-A;let O=i[w]<>>15-u]=v,O++}},d.H.l=function(i,u){const g=d.H.m.r,p=15-u;for(let m=0;m>>p}},d.H.M=function(i,u,g){g<<=7&u;const p=u>>>3;i[p]|=g,i[p+1]|=g>>>8},d.H.I=function(i,u,g){g<<=7&u;const p=u>>>3;i[p]|=g,i[p+1]|=g>>>8,i[p+2]|=g>>>16},d.H.e=function(i,u,g){return(i[u>>>3]|i[1+(u>>>3)]<<8)>>>(7&u)&(1<>>3]|i[1+(u>>>3)]<<8|i[2+(u>>>3)]<<16)>>>(7&u)&(1<>>3]|i[1+(u>>>3)]<<8|i[2+(u>>>3)]<<16)>>>(7&u)},d.H.i=function(i,u){return(i[u>>>3]|i[1+(u>>>3)]<<8|i[2+(u>>>3)]<<16|i[3+(u>>>3)]<<24)>>>(7&u)},d.H.m=(function(){const i=Uint16Array,u=Uint32Array;return{K:new i(16),j:new i(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new i(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new u(32),J:new i(512),_:[],h:new i(32),$:[],w:new i(32768),C:[],v:[],d:new i(32768),D:[],u:new i(512),Q:[],r:new i(32768),s:new u(286),Y:new u(30),a:new u(19),t:new u(15e3),k:new i(65536),g:new i(32768)}})(),(function(){const i=d.H.m;for(var u=0;u<32768;u++){let p=u;p=(2863311530&p)>>>1|(1431655765&p)<<1,p=(3435973836&p)>>>2|(858993459&p)<<2,p=(4042322160&p)>>>4|(252645135&p)<<4,p=(4278255360&p)>>>8|(16711935&p)<<8,i.r[u]=(p>>>16|p<<16)>>>17}function g(p,m,w){for(;m--!=0;)p.push(0,w)}for(u=0;u<32;u++)i.q[u]=i.S[u]<<3|i.T[u],i.c[u]=i.p[u]<<4|i.z[u];g(i._,144,8),g(i._,112,9),g(i._,24,7),g(i._,8,8),d.H.n(i._,9),d.H.A(i._,9,i.J),d.H.l(i._,9),g(i.$,32,5),d.H.n(i.$,5),d.H.A(i.$,5,i.h),d.H.l(i.$,5),g(i.Q,19,0),g(i.C,286,0),g(i.D,30,0),g(i.v,320,0)})(),d.H.N})();function a(d){return[1,null,3,1,2,null,4][d.ctype]*d.depth}function s(d,i,u,g,p){let m=a(i);const w=Math.ceil(g*m/8);let x,A;m=Math.ceil(m/8);let v=d[u],E=0;if(v>1&&(d[u]=[0,0,1][v-2]),v==3)for(E=m;E>>1)&255;for(let O=0;O>>1);for(;E>>1)}else{for(;E=0&&x>=0?(O=U*i+S<<2,_=(x+U)*p+w+S<<2):(O=(-x+U)*i-w+S<<2,_=U*p+S<<2),A==0)g[_]=d[O],g[_+1]=d[O+1],g[_+2]=d[O+2],g[_+3]=d[O+3];else if(A==1){var I=d[O+3]*.00392156862745098,C=d[O]*I,y=d[O+1]*I,N=d[O+2]*I,M=g[_+3]*(1/255),P=g[_]*M,D=g[_+1]*M,L=g[_+2]*M;const b=1-I,$=I+M*b,F=$==0?0:1/$;g[_+3]=255*$,g[_+0]=(C+P*b)*F,g[_+1]=(y+D*b)*F,g[_+2]=(N+L*b)*F}else if(A==2)I=d[O+3],C=d[O],y=d[O+1],N=d[O+2],M=g[_+3],P=g[_],D=g[_+1],L=g[_+2],I==M&&C==P&&y==D&&N==L?(g[_]=0,g[_+1]=0,g[_+2]=0,g[_+3]=0):(g[_]=C,g[_+1]=y,g[_+2]=N,g[_+3]=I);else if(A==3){if(I=d[O+3],C=d[O],y=d[O+1],N=d[O+2],M=g[_+3],P=g[_],D=g[_+1],L=g[_+2],I==M&&C==P&&y==D&&N==L)continue;if(I<220&&M>20)return!1}return!0}return{decode:function(i){const u=new Uint8Array(i);let g=8;const p=e,m=p.readUshort,w=p.readUint,x={tabs:{},frames:[]},A=new Uint8Array(u.length);let v,E=0,O=0;const _=[137,80,78,71,13,10,26,10];for(var I=0;I<8;I++)if(u[I]!=_[I])throw"The input is not a PNG file!";for(;g>>1:N>>>=1;C[y]=N}return C})(),update(C,y,N,M){for(let P=0;P>>8;return C},crc:(C,y,N)=>4294967295^n.update(4294967295,C,y,N)};function o(C,y,N,M){y[N]+=C[0]*M>>4,y[N+1]+=C[1]*M>>4,y[N+2]+=C[2]*M>>4,y[N+3]+=C[3]*M>>4}function a(C){return Math.max(0,Math.min(255,C))}function s(C,y){const N=C[0]-y[0],M=C[1]-y[1],P=C[2]-y[2],D=C[3]-y[3];return N*N+M*M+P*P+D*D}function l(C,y,N,M,P,D,L){L==null&&(L=1);const U=M.length,S=[];for(var b=0;b>>0&255,H>>>8&255,H>>>16&255,H>>>24&255])}for(b=0;b>2]=$,Y[b>>2]=M[$]}}function f(C,y,N,M,P){P==null&&(P={});const{crc:D}=n,L=t.writeUint,U=t.writeUshort,S=t.writeASCII;let b=8;const $=C.frames.length>1;let F,G=!1,Y=33+($?20:0);if(P.sRGB!=null&&(Y+=13),P.pHYs!=null&&(Y+=21),P.iCCP!=null&&(F=pako.deflate(P.iCCP),Y+=21+F.length+4),C.ctype==3){for(var B=C.plte.length,V=0;V>>24!=255&&(G=!0);Y+=8+3*B+4+(G?8+1*B+4:0)}for(var j=0;j>>8&255,Ge=R>>>16&255;H[b+fe+0]=ke,H[b+fe+1]=me,H[b+fe+2]=Ge}if(b+=3*B,L(H,b,D(H,b-3*B-4,3*B+4)),b+=4,G){for(L(H,b,B),b+=4,S(H,b,"tRNS"),b+=4,V=0;V>>24&255;b+=B,L(H,b,D(H,b-B-4,B+4)),b+=4}}let ue=0;for(j=0;jNe&&(Ne=qe),BeVe&&(Ve=Be));Ne==-1&&(Ee=he=Ne=Ve=0),K&&((1&Ee)==1&&Ee--,(1&he)==1&&he--);const Fe=(Ne-Ee+1)*(Ve-he+1);Fe<_e&&(_e=Fe,Se=Ue,se=Ee,ie=he,le=Ne-Ee+1,ne=Ve-he+1)}xe=new Uint8Array(Ce[ae-1-Se]),Se==1&&(oe[ae-1].dispose=2),be=new Uint8Array(le*ne*4),e(xe,we,$e,be,le,ne,-se,-ie,0),Te=e(Oe,we,$e,be,le,ne,-se,-ie,3)?1:0,Te==1?u(Oe,we,$e,be,{x:se,y:ie,width:le,height:ne}):e(Oe,we,$e,be,le,ne,-se,-ie,0)}else be=Oe.slice(0);oe.push({rect:{x:se,y:ie,width:le,height:ne},img:be,blend:Te,dispose:0})}if(Le)for(ae=0;ae>2,Le>>2);fe.push(R);const K=new Uint8Array(we.abuf,$e,Le);$&&l(ke.img,ke.rect.width,ke.rect.height,te,K,R),ke.img.set(K),$e+=Le}}else for(B=0;Bme&&Ce==Me[j-me])R[j]=R[j-me];else{let we=ue[Ce];if(we==null&&(ue[Ce]=we=te.length,te.push(Ce),te.length>=300))break;R[j]=we}}}const Ge=te.length;for(Ge<=256&&b==0&&(G=Ge<=2?1:Ge<=4?2:Ge<=16?4:8,G=Math.max(G,S)),B=0;B>1)]|=Le[re+ye]<<4-4*(1&ye);else if(G==2)for(ye=0;ye>2)]|=Le[re+ye]<<6-2*(3&ye);else if(G==1)for(ye=0;ye>3)]|=Le[re+ye]<<7-1*(7&ye)}Ce=De,F=3,$e=1}else if(H==0&&Z.length==1){De=new Uint8Array(me*Me*3);const Le=me*Me;for(j=0;jj&&(j=fe),RH&&(H=R))}j==-1&&(B=V=j=H=0),L&&((1&B)==1&&B--,(1&V)==1&&V--),D={x:B,y:V,width:j-B+1,height:H-V+1};const Z=M[P];Z.rect=D,Z.blend=1,Z.img=new Uint8Array(D.width*D.height*4),M[P-1].dispose==0?(e(b,y,N,Z.img,D.width,D.height,-D.x,-D.y,0),u(G,y,N,Z.img,D)):e(G,y,N,Z.img,D.width,D.height,-D.x,-D.y,0)}function u(C,y,N,M,P){e(C,y,N,M,P.width,P.height,-P.x,-P.y,2)}function g(C,y,N,M,P,D,L){const U=[];let S,b=[0,1,2,3,4];D!=-1?b=[D]:(y*M>5e5||N==1)&&(b=[0]),L&&(S={level:0});const $=og;for(var F=0;F>1)+256&255;if(D==4)for(S=P;S>1)&255;for(S=P;S>1)&255}if(D==4){for(S=0;S>2);let $;if(N.length<2e7)for(var F=0;F>2]=$.ind,P[F>>2]=$.est.rgba;else for(F=0;F>2]=$.ind,P[F>>2]=$.est.rgba}return{abuf:M.buffer,inds:b,plte:U}}function w(C,y,N){N==null&&(N=1e-4);const M=new Uint32Array(C.buffer),P={i0:0,i1:C.length,bst:null,est:null,tdst:0,left:null,right:null};P.bst=O(C,P.i0,P.i1),P.est=_(P.bst);const D=[P];for(;D.lengthU&&(U=D[L].est.L,S=L);if(U=$||b.i1<=$){b.est.L=0;continue}const F={i0:b.i0,i1:$,bst:null,est:null,tdst:0,left:null,right:null};F.bst=O(C,F.i0,F.i1),F.est=_(F.bst);const G={i0:$,i1:b.i1,bst:null,est:null,tdst:0,left:null,right:null};for(G.bst={R:[],m:[],N:b.bst.N-F.bst.N},L=0;L<16;L++)G.bst.R[L]=b.bst.R[L]-F.bst.R[L];for(L=0;L<4;L++)G.bst.m[L]=b.bst.m[L]-F.bst.m[L];G.est=_(G.bst),b.left=F,b.right=G,D[S]=F,D.push(G)}for(D.sort(((U,S)=>S.bst.N-U.bst.N)),L=0;L0&&(L=C.right,U=C.left);const S=x(L,y,N,M,P);if(S.tdst<=D*D)return S;const b=x(U,y,N,M,P);return b.tdstD;)M-=4;if(N>=M)break;const L=y[N>>2];y[N>>2]=y[M>>2],y[M>>2]=L,N+=4,M-=4}for(;E(C,N,P)>D;)N-=4;return N+4}function E(C,y,N){return C[y]*N[0]+C[y+1]*N[1]+C[y+2]*N[2]+C[y+3]*N[3]}function O(C,y,N){const M=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],P=[0,0,0,0],D=N-y>>2;for(let L=y;L>>0}}var I={multVec:(C,y)=>[C[0]*y[0]+C[1]*y[1]+C[2]*y[2]+C[3]*y[3],C[4]*y[0]+C[5]*y[1]+C[6]*y[2]+C[7]*y[3],C[8]*y[0]+C[9]*y[1]+C[10]*y[2]+C[11]*y[3],C[12]*y[0]+C[13]*y[1]+C[14]*y[2]+C[15]*y[3]],dot:(C,y)=>C[0]*y[0]+C[1]*y[1]+C[2]*y[2]+C[3]*y[3],sml:(C,y)=>[C*y[0],C*y[1],C*y[2],C*y[3]]};Ht.encode=function(y,N,M,P,D,L,U){P==null&&(P=0),U==null&&(U=!1);const S=d(y,N,M,P,[!1,!1,!1,0,U,!1]);return h(S,-1),f(S,N,M,D,L)},Ht.encodeLL=function(y,N,M,P,D,L,U,S){const b={ctype:0+(P==1?0:2)+(D==0?0:4),depth:L,frames:[]},$=(P+D)*L,F=$*N;for(let G=0;G>>0),O(1),O(32),_(3),_(f),_(2835),_(2835),I(8),_(16711680),_(65280),_(255),_(4278190080),_(1466527264),(function C(){for(;A0;){for(w=122+A*l,g=0;g>>24,i.setUint32(w+g,p<<8|m),g+=4;A++}E{t(new Blob([r],{type:"image/bmp"}))}))},_dly:9};var bt={CHROME:"CHROME",FIREFOX:"FIREFOX",DESKTOP_SAFARI:"DESKTOP_SAFARI",IE:"IE",IOS:"IOS",ETC:"ETC"},ag={[bt.CHROME]:16384,[bt.FIREFOX]:11180,[bt.DESKTOP_SAFARI]:16384,[bt.IE]:8192,[bt.IOS]:4096,[bt.ETC]:8192};const ra=typeof window<"u",Hl=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope,In=ra&&window.cordova&&window.cordova.require&&window.cordova.require("cordova/modulemapper"),sg=(ra||Hl)&&(In&&In.getOriginalSymbol(window,"File")||typeof File<"u"&&File),Gl=(ra||Hl)&&(In&&In.getOriginalSymbol(window,"FileReader")||typeof FileReader<"u"&&FileReader);function na(e,t,r=Date.now()){return new Promise((n=>{const o=e.split(","),a=o[0].match(/:(.*?);/)[1],s=globalThis.atob(o[1]);let l=s.length;const f=new Uint8Array(l);for(;l--;)f[l]=s.charCodeAt(l);const h=new Blob([f],{type:a});h.name=t,h.lastModified=r,n(h)}))}function jl(e){return new Promise(((t,r)=>{const n=new Gl;n.onload=()=>t(n.result),n.onerror=o=>r(o),n.readAsDataURL(e)}))}function Bl(e){return new Promise(((t,r)=>{const n=new Image;n.onload=()=>t(n),n.onerror=o=>r(o),n.src=e}))}function fr(){if(fr.cachedResult!==void 0)return fr.cachedResult;let e=bt.ETC;const{userAgent:t}=navigator;return/Chrom(e|ium)/i.test(t)?e=bt.CHROME:/iP(ad|od|hone)/i.test(t)&&/WebKit/i.test(t)?e=bt.IOS:/Safari/i.test(t)?e=bt.DESKTOP_SAFARI:/Firefox/i.test(t)?e=bt.FIREFOX:(/MSIE/i.test(t)||document.documentMode)&&(e=bt.IE),fr.cachedResult=e,fr.cachedResult}function Wl(e,t){const r=fr(),n=ag[r];let o=e,a=t,s=o*a;const l=o>a?a/o:o/a;for(;s>n*n;){const f=(n+o)/2,h=(n+a)/2;fzl.toBlob(e,d))).then(function(d){try{return l=d,l.name=r,l.lastModified=n,h.call(this)}catch(i){return s(i)}}.bind(this),s);{let d=function(){return h.call(this)};if(typeof OffscreenCanvas=="function"&&e instanceof OffscreenCanvas)return e.convertToBlob({type:t,quality:o}).then(function(i){try{return l=i,l.name=r,l.lastModified=n,d.call(this)}catch(u){return s(u)}}.bind(this),s);{let i;return i=e.toDataURL(t,o),na(i,r,n).then(function(u){try{return l=u,d.call(this)}catch(g){return s(g)}}.bind(this),s)}}}function f(){return a(l)}}))}function Vt(e){e.width=0,e.height=0}function Nr(){return new Promise((function(e,t){let r,n,o,a;return Nr.cachedResult!==void 0?e(Nr.cachedResult):na("data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==","test.jpg",Date.now()).then((function(s){try{return r=s,Pn(r).then((function(l){try{return n=l[1],Fn(n,r.type,r.name,r.lastModified).then((function(f){try{return o=f,Vt(n),Pn(o).then((function(h){try{return a=h[0],Nr.cachedResult=a.width===1&&a.height===2,e(Nr.cachedResult)}catch(d){return t(d)}}),t)}catch(h){return t(h)}}),t)}catch(f){return t(f)}}),t)}catch(l){return t(l)}}),t)}))}function Vl(e){return new Promise(((t,r)=>{const n=new Gl;n.onload=o=>{const a=new DataView(o.target.result);if(a.getUint16(0,!1)!=65496)return t(-2);const s=a.byteLength;let l=2;for(;lr(o),n.readAsArrayBuffer(e)}))}function Yl(e,t){const{width:r}=e,{height:n}=e,{maxWidthOrHeight:o}=t;let a,s=e;return isFinite(o)&&(r>o||n>o)&&([s,a]=Dn(r,n),r>n?(s.width=o,s.height=n/r*o):(s.width=r/n*o,s.height=o),a.drawImage(e,0,0,s.width,s.height),Vt(e)),s}function Xl(e,t){const{width:r}=e,{height:n}=e,[o,a]=Dn(r,n);switch(t>4&&t<9?(o.width=n,o.height=r):(o.width=r,o.height=n),t){case 2:a.transform(-1,0,0,1,r,0);break;case 3:a.transform(-1,0,0,-1,r,n);break;case 4:a.transform(1,0,0,-1,0,n);break;case 5:a.transform(0,1,1,0,0,0);break;case 6:a.transform(0,1,-1,0,n,0);break;case 7:a.transform(0,-1,-1,0,n,r);break;case 8:a.transform(0,-1,1,0,0,r)}return a.drawImage(e,0,0,r,n),Vt(e),o}function Zl(e,t,r=0){return new Promise((function(n,o){let a,s,l,f,h,d,i,u,g,p,m,w,x,A,v,E,O,_,I,C;function y(M=5){if(t.signal&&t.signal.aborted)throw t.signal.reason;a+=M,t.onProgress(Math.min(a,100))}function N(M){if(t.signal&&t.signal.aborted)throw t.signal.reason;a=Math.min(Math.max(M,a),100),t.onProgress(a)}return a=r,s=t.maxIteration||10,l=1024*t.maxSizeMB*1024,y(),Pn(e,t).then(function(M){try{return[,f]=M,y(),h=Yl(f,t),y(),new Promise((function(P,D){var L;if(!(L=t.exifOrientation))return Vl(e).then(function(S){try{return L=S,U.call(this)}catch(b){return D(b)}}.bind(this),D);function U(){return P(L)}return U.call(this)})).then(function(P){try{return d=P,y(),Nr().then(function(D){try{return i=D?h:Xl(h,d),y(),u=t.initialQuality||1,g=t.fileType||e.type,Fn(i,g,e.name,e.lastModified,u).then(function(L){try{{let S=function(){if(s--&&(v>l||v>x)){let $,F;return $=C?.95*I.width:I.width,F=C?.95*I.height:I.height,[O,_]=Dn($,F),_.drawImage(I,0,0,$,F),u*=g==="image/png"?.85:.95,Fn(O,g,e.name,e.lastModified,u).then((function(G){try{return E=G,Vt(I),I=O,v=E.size,N(Math.min(99,Math.floor((A-v)/(A-l)*100))),S}catch(Y){return o(Y)}}),o)}return[1]},b=function(){return Vt(I),Vt(O),Vt(h),Vt(i),Vt(f),N(100),n(E)};if(p=L,y(),m=p.size>l,w=p.size>e.size,!m&&!w)return N(100),n(p);var U;return x=e.size,A=p.size,v=A,I=i,C=!t.alwaysKeepResolution&&m,(U=function($){for(;$;){if($.then)return void $.then(U,o);try{if($.pop){if($.length)return $.pop()?b.call(this):$;$=S}else $=$.call(this)}catch(F){return o(F)}}}.bind(this))(S)}}catch(S){return o(S)}}.bind(this),o)}catch(L){return o(L)}}.bind(this),o)}catch(D){return o(D)}}.bind(this),o)}catch(P){return o(P)}}.bind(this),o)}))}const lg=` + `.trim().replace(/\s+/g," ");return c.jsx(W,{id:a,className:d,dangerouslySetInnerHTML:{__html:h},...s})},Xf=Object.freeze(Object.defineProperty({__proto__:null,HtmlContent:qo},Symbol.toStringTag,{value:"Module"})),Zo=()=>window.G7Core,Qo=(e,t)=>Zo()?.t?.(e,t)??e,Ll=({content:e="",onChange:t,isHtml:r=!1,onIsHtmlChange:n,rows:o=15,placeholder:a="",label:s,showHtmlModeToggle:l=!0,contentClassName:f="",purifyConfig:h,className:d="",name:i="content",htmlFieldName:u="content_mode",readOnly:g=!1,id:p,editorAttrs:m})=>{const[w,x]=k.useState(r),[O,y]=k.useState(e),[E,M]=k.useState(!1);k.useEffect(()=>{x(r)},[r]),k.useEffect(()=>{y(e)},[e]);const _=k.useCallback(v=>{const N=v.target.value;if(y(N),t){const A=Zo()?.createChangeEvent?.({value:N,name:i,type:"textarea"})??{target:{name:i,value:N}};t(A)}},[t,i]),I=k.useCallback(v=>{const N=v.target.checked;if(x(N),N||M(!1),n){const A=Zo()?.createChangeEvent?.({checked:N,name:u,type:"checkbox"})??{target:{name:u,checked:N}};n(A)}},[n,u]),C=k.useCallback(()=>{M(v=>!v)},[]);return c.jsxs(W,{className:`space-y-2 ${d}`,id:p,...m,children:[c.jsxs(W,{className:"flex items-center justify-between",children:[s&&c.jsx(yr,{className:"block text-sm font-medium text-gray-500 dark:text-gray-400",children:s}),c.jsxs(W,{className:"flex items-center gap-3",children:[w&&!g&&c.jsx(Q,{type:"button",onClick:C,className:`px-3 py-1.5 text-xs font-bold rounded-lg focus:outline-none focus:ring-2 ${E?"text-gray-700 dark:text-gray-200 bg-gray-200 dark:bg-gray-600 border border-gray-300 dark:border-gray-500 hover:bg-gray-300 dark:hover:bg-gray-500 focus:ring-gray-400 dark:focus:ring-gray-500":"text-blue-600 dark:text-blue-400 bg-white dark:bg-gray-700 border border-blue-300 dark:border-blue-600 hover:bg-blue-50 dark:hover:bg-gray-600 focus:ring-blue-500 dark:focus:ring-blue-600"}`,children:Qo(E?"common.preview_off":"common.preview")}),l&&c.jsxs(yr,{className:"flex items-center gap-2 p-2 cursor-pointer",children:[c.jsx(xt,{type:"checkbox",name:u,checked:w,onChange:I,disabled:g,className:"w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"}),c.jsx(W,{className:"text-sm font-medium text-gray-700 dark:text-gray-300",children:Qo("common.html_mode")})]})]})]}),!E&&c.jsx(no,{name:i,value:O,onChange:_,placeholder:a,rows:o,readOnly:g,className:`block w-full rounded-lg border px-3 py-2 text-sm placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring-1 disabled:opacity-50 disabled:cursor-not-allowed ${w?"font-mono bg-white dark:bg-gray-800 border-blue-300 dark:border-blue-600 text-gray-800 dark:text-gray-200 focus:border-blue-500 focus:ring-blue-500":"bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-600 text-gray-900 dark:text-white focus:border-blue-500 focus:ring-blue-500"}`}),E&&c.jsx(W,{className:"p-4 bg-gray-50 dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-800 min-h-[400px]",children:c.jsx(qo,{content:O,isHtml:!0,className:f||"prose dark:prose-invert max-w-none text-gray-900 dark:text-gray-100",purifyConfig:h})})]})},qf=Object.freeze(Object.defineProperty({__proto__:null,HtmlEditor:Ll},Symbol.toStringTag,{value:"Module"})),Pl=e=>window.G7Core?.t?.(e)??e,Jo=({maxHeight:e=500,expandText:t,collapseText:r,className:n="",children:o,id:a,editorAttrs:s})=>{const[l,f]=k.useState(!1),[h,d]=k.useState(!1),i=k.useRef(null),u=k.useCallback(()=>{if(i.current){const w=i.current.scrollHeight;d(w>e)}},[e]);k.useEffect(()=>{u();const w=i.current;if(!w)return;const x=w.querySelectorAll("img");x.forEach(y=>{y.complete||y.addEventListener("load",u)});let O=null;return typeof ResizeObserver<"u"&&(O=new ResizeObserver(u),O.observe(w)),()=>{x.forEach(y=>{y.removeEventListener("load",u)}),O?.disconnect()}},[u,o]);const g=()=>{f(w=>!w)},p=t||Pl("sirsoft-ecommerce.shop.product.expand_detail"),m=r||Pl("sirsoft-ecommerce.shop.product.collapse_detail");return c.jsxs(W,{className:n,id:a,...s,children:[c.jsxs(W,{className:"relative",children:[c.jsx(W,{ref:i,className:!l&&h?"overflow-hidden transition-[max-height] duration-300 ease-in-out":"transition-[max-height] duration-300 ease-in-out",style:!l&&h?{maxHeight:`${e}px`}:void 0,children:o}),!l&&h&&c.jsx(W,{className:"absolute bottom-0 left-0 right-0 h-24 bg-gradient-to-t from-white dark:from-gray-900 to-transparent pointer-events-none"})]}),h&&c.jsxs(Q,{type:"button",onClick:g,className:"flex items-center justify-center w-full py-3.5 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors cursor-pointer gap-1.5",children:[c.jsx(ee,{className:"text-sm font-semibold text-gray-600 dark:text-gray-400",children:l?m:p}),c.jsx(de,{name:l?"chevron-up":"chevron-down",size:"sm"})]})]})},Zf=Object.freeze(Object.defineProperty({__proto__:null,ExpandableContent:Jo,default:Jo},Symbol.toStringTag,{value:"Module"})),Qf=(e,t)=>window.G7Core?.t?.(e,t)??e,Ro=({isOpen:e,onClose:t,title:r,icon:n,iconClassName:o="text-gray-500 dark:text-gray-400",closeOnBackdropClick:a=!0,closeOnOverlayClick:s,showCloseButton:l=!0,closeOnEscape:f=!0,children:h,width:d="500px",className:i="",style:u})=>{const g=s!==void 0?s:a,p=k.useRef(null),m=k.useRef(null);if(k.useEffect(()=>{const x=O=>{O.key==="Escape"&&e&&f&&t()};if(e&&f)return document.addEventListener("keydown",x),()=>document.removeEventListener("keydown",x)},[e,t,f]),k.useEffect(()=>{if(e&&p.current){m.current=document.activeElement;const x=p.current.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),O=x[0],y=x[x.length-1];O?.focus();const E=M=>{M.key==="Tab"&&(M.shiftKey?document.activeElement===O&&(M.preventDefault(),y?.focus()):document.activeElement===y&&(M.preventDefault(),O?.focus()))};return document.addEventListener("keydown",E),()=>{document.removeEventListener("keydown",E),m.current?.focus()}}},[e]),k.useEffect(()=>{if(e)return document.body.style.overflow="hidden",()=>{document.body.style.overflow=""}},[e]),!e)return null;const w=u?.zIndex??50;return c.jsxs(W,{className:"fixed inset-0 flex items-center justify-center",style:{zIndex:w},onClick:g?t:void 0,children:[c.jsx(W,{className:"absolute inset-0 bg-black/50","aria-hidden":"true"}),c.jsxs(W,{ref:p,className:`relative bg-white dark:bg-gray-800 rounded-lg shadow-xl max-h-[90vh] max-w-[calc(100vw-2rem)] overflow-hidden ${i}`,style:{width:d,...u?{...u,zIndex:void 0}:{}},onClick:x=>x.stopPropagation(),role:"dialog","aria-modal":"true","aria-labelledby":r?"modal-title":void 0,children:[(r||n||l)&&c.jsxs(W,{className:"flex items-center justify-between p-4",children:[(r||n)&&c.jsxs(W,{id:"modal-title",className:"flex items-center gap-3 text-lg font-semibold text-gray-900 dark:text-white",children:[n&&c.jsx(de,{name:n,size:"md",className:o}),r]}),l&&c.jsx(Q,{onClick:t,className:"ml-auto text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300 focus:outline-none","aria-label":Qf("common.close_modal"),children:c.jsx("svg",{className:"w-6 h-6",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:c.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})})})]}),c.jsx(W,{className:"px-6 py-4 overflow-y-auto max-h-[calc(90vh-140px)]",children:h})]})]})},Jf=Object.freeze(Object.defineProperty({__proto__:null,Modal:Ro},Symbol.toStringTag,{value:"Module"})),ea=(e,t)=>window.G7Core?.t?.(e,t)??e,ta=({isOpen:e,onClose:t,title:r,message:n,confirmText:o,cancelText:a,onConfirm:s,onCancel:l,confirmButtonVariant:f="primary",cancelButtonVariant:h="secondary",width:d="500px",closeOnOverlay:i=!0,isLoading:u=!1,loadingText:g})=>{const p=o??ea("common.confirm"),m=a??ea("common.cancel"),w=g??ea("common.loading"),x=()=>{s()},O=()=>{u||(l?.(),t())},y=()=>{u||t()},E={primary:"bg-blue-600 text-white hover:bg-blue-700",secondary:"bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200 hover:bg-gray-300 dark:hover:bg-gray-600",danger:"bg-red-600 text-white hover:bg-red-700",ghost:"bg-transparent text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"};return c.jsxs(Ro,{isOpen:e,onClose:y,title:r,width:d,children:[c.jsx(W,{className:"py-2",children:typeof n=="string"?c.jsx(Dt,{className:"text-gray-700 dark:text-gray-300",children:n}):n}),c.jsxs(W,{className:"flex justify-end gap-3 mt-6",children:[c.jsx(Q,{onClick:O,disabled:u,className:"px-4 py-2 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed",children:c.jsx(ee,{children:m})}),c.jsxs(Q,{onClick:x,disabled:u,className:`flex items-center gap-2 px-4 py-2 rounded-lg disabled:opacity-50 disabled:cursor-not-allowed ${E[f]}`,children:[u&&c.jsx(Ct,{className:"fa-solid fa-spinner w-4 h-4 animate-spin"}),c.jsx(ee,{children:u?w:p})]})]})]})},Rf=Object.freeze(Object.defineProperty({__proto__:null,ConfirmDialog:ta},Symbol.toStringTag,{value:"Module"})),Fl=k.createContext(null),$l=({value:e,children:t})=>c.jsx(Fl.Provider,{value:e,children:t}),eg=()=>{const e=k.useContext(Fl);if(!e)throw new Error("useFileUploaderContext must be used within FileUploaderProvider");return e};function tg(e,t){return t.forEach((function(r){r&&typeof r!="string"&&!Array.isArray(r)&&Object.keys(r).forEach((function(n){if(n!=="default"&&!(n in e)){var o=Object.getOwnPropertyDescriptor(r,n);Object.defineProperty(e,n,o.get?o:{enumerable:!0,get:function(){return r[n]}})}}))})),Object.freeze(e)}function Ul(e,t){return new Promise((function(r,n){let o;return rg(e).then((function(a){try{return o=a,r(new Blob([t.slice(0,2),o,t.slice(2)],{type:"image/jpeg"}))}catch(s){return n(s)}}),n)}))}const rg=e=>new Promise(((t,r)=>{const n=new FileReader;n.addEventListener("load",(({target:{result:o}})=>{const a=new DataView(o);let s=0;if(a.getUint16(s)!==65496)return r("not a valid JPEG");for(s+=2;;){const l=a.getUint16(s);if(l===65498)break;const f=a.getUint16(s+2);if(l===65505&&a.getUint32(s+4)===1165519206){const h=s+10;let d;switch(a.getUint16(h)){case 18761:d=!0;break;case 19789:d=!1;break;default:return r("TIFF header contains invalid endian")}if(a.getUint16(h+2,d)!==42)return r("TIFF header contains invalid version");const i=a.getUint32(h+4,d),u=h+i+2+12*a.getUint16(h+i,d);for(let g=h+i+2;g>>24&255,l[s+1]=f>>>16&255,l[s+2]=f>>>8&255,l[s+3]=f>>>0&255,new Uint8Array(l.buffer,0,s+4)},n.deflateRaw=function(o,a){a==null&&(a={level:6});var s=new Uint8Array(50+Math.floor(1.1*o.length)),l=n.F.deflateRaw(o,s,l,a.level);return new Uint8Array(s.buffer,0,l)},n.encode=function(o,a){a==null&&(a=!1);var s=0,l=n.bin.writeUint,f=n.bin.writeUshort,h={};for(var d in o){var i=!n._noNeed(d)&&!a,u=o[d],g=n.crc.crc(u,0,u.length);h[d]={cpr:i,usize:u.length,crc:g,file:i?n.deflateRaw(u):u}}for(var d in h)s+=h[d].file.length+30+46+2*n.bin.sizeUTF8(d);s+=22;var p=new Uint8Array(s),m=0,w=[];for(var d in h){var x=h[d];w.push(m),m=n._writeHeader(p,m,d,x,0)}var O=0,y=m;for(var d in h)x=h[d],w.push(m),m=n._writeHeader(p,m,d,x,1,w[O++]);var E=m-y;return l(p,m,101010256),m+=4,f(p,m+=4,O),f(p,m+=2,O),l(p,m+=2,E),l(p,m+=4,y),m+=4,m+=2,p.buffer},n._noNeed=function(o){var a=o.split(".").pop().toLowerCase();return"png,jpg,jpeg,zip".indexOf(a)!=-1},n._writeHeader=function(o,a,s,l,f,h){var d=n.bin.writeUint,i=n.bin.writeUshort,u=l.file;return d(o,a,f==0?67324752:33639248),a+=4,f==1&&(a+=2),i(o,a,20),i(o,a+=2,0),i(o,a+=2,l.cpr?8:0),d(o,a+=2,0),d(o,a+=4,l.crc),d(o,a+=4,u.length),d(o,a+=4,l.usize),i(o,a+=4,n.bin.sizeUTF8(s)),i(o,a+=2,0),a+=2,f==1&&(a+=2,a+=2,d(o,a+=6,h),a+=4),a+=n.bin.writeUTF8(o,a,s),f==0&&(o.set(u,a),a+=u.length),a},n.crc={table:(function(){for(var o=new Uint32Array(256),a=0;a<256;a++){for(var s=a,l=0;l<8;l++)1&s?s=3988292384^s>>>1:s>>>=1;o[a]=s}return o})(),update:function(o,a,s,l){for(var f=0;f>>8;return o},crc:function(o,a,s){return 4294967295^n.crc.update(4294967295,o,a,s)}},n.adler=function(o,a,s){for(var l=1,f=0,h=a,d=a+s;h>8&255},readUint:function(o,a){return 16777216*o[a+3]+(o[a+2]<<16|o[a+1]<<8|o[a])},writeUint:function(o,a,s){o[a]=255&s,o[a+1]=s>>8&255,o[a+2]=s>>16&255,o[a+3]=s>>24&255},readASCII:function(o,a,s){for(var l="",f=0;f>6,o[a+f+1]=128|d>>0&63,f+=2;else if((4294901760&d)==0)o[a+f]=224|d>>12,o[a+f+1]=128|d>>6&63,o[a+f+2]=128|d>>0&63,f+=3;else{if((4292870144&d)!=0)throw"e";o[a+f]=240|d>>18,o[a+f+1]=128|d>>12&63,o[a+f+2]=128|d>>6&63,o[a+f+3]=128|d>>0&63,f+=4}}return f},sizeUTF8:function(o){for(var a=o.length,s=0,l=0;l>>3}var w=h.lits,x=h.strt,O=h.prev,y=0,E=0,M=0,_=0,I=0,C=0;for(m>2&&(x[C=n.F._hash(o,0)]=0),u=0;u14e3||E>26697)&&m-u>100&&(p>>16,P=65535&N;if(N!=0){P=65535&N;var D=d(A=N>>>16,h.of0);h.lhst[257+D]++;var L=d(P,h.df0);h.dhst[L]++,_+=h.exb[D]+h.dxb[L],w[y]=A<<23|u-p,w[y+1]=P<<16|D<<8|L,y+=2,p=u+A}else h.lhst[o[u]]++;E++}}for(M==u&&o.length!=0||(p>>3},n.F._bestMatch=function(o,a,s,l,f,h){var d=32767&a,i=s[d],u=d-i+32768&32767;if(i==d||l!=n.F._hash(o,a-u))return 0;for(var g=0,p=0,m=Math.min(32767,a);u<=m&&--h!=0&&i!=d;){if(g==0||o[a+g]==o[a+g-u]){var w=n.F._howLong(o,a,u);if(w>g){if(p=u,(g=w)>=f)break;u+2x&&(x=E,i=y)}}}u+=(d=i)-(i=s[d])+32768&32767}return g<<16|p},n.F._howLong=function(o,a,s){if(o[a]!=o[a-s]||o[a+1]!=o[a+1-s]||o[a+2]!=o[a+2-s])return 0;var l=a,f=Math.min(o.length,a+258);for(a+=3;a>>23,Y=b+(8388607&F);b>16,j=B>>8&255,H=255&B;C(i,u=n.F._writeLit(257+j,L,i,u),G-_.of0[j]),u+=_.exb[j],I(i,u=n.F._writeLit(H,U,i,u),V-_.df0[H]),u+=_.dxb[H],b+=G}}u=n.F._writeLit(256,L,i,u)}return u},n.F._copyExact=function(o,a,s,l,f){var h=f>>>3;return l[h]=s,l[h+1]=s>>>8,l[h+2]=255-l[h],l[h+3]=255-l[h+1],h+=4,l.set(new Uint8Array(o.buffer,a,s),h),f+(s+4<<3)},n.F.getTrees=function(){for(var o=n.F.U,a=n.F._hufTree(o.lhst,o.ltree,15),s=n.F._hufTree(o.dhst,o.dtree,15),l=[],f=n.F._lenCodes(o.ltree,l),h=[],d=n.F._lenCodes(o.dtree,h),i=0;i4&&o.itree[1+(o.ordr[g-1]<<1)]==0;)g--;return[a,s,u,f,d,g,l,h]},n.F.getSecond=function(o){for(var a=[],s=0;s>1)+",");return a},n.F.contSize=function(o,a){for(var s=0,l=0;l15&&(n.F._putsE(s,l,d,i),l+=i)}return l},n.F._lenCodes=function(o,a){for(var s=o.length;s!=2&&o[s-1]==0;)s-=2;for(var l=0;l>>1,138))<11?a.push(17,g-3):a.push(18,g-11),l+=2*g-2}else if(f==i&&h==f&&d==f){for(u=l+5;u+2>>1,6);a.push(16,g-3),l+=2*g-2}else a.push(f,0)}return s>>>1},n.F._hufTree=function(o,a,s){var l=[],f=o.length,h=a.length,d=0;for(d=0;ds&&(n.F.restrictDepth(u,s,y),y=s),d=0;da;l++){var d=o[l].d;o[l].d=a,h+=f-(1<>>=s-a;h>0;)(d=o[l].d)=0;l--)o[l].d==a&&h<0&&(o[l].d--,h++);h!=0&&console.log("debt left")},n.F._goodIndex=function(o,a){var s=0;return a[16|s]<=o&&(s|=16),a[8|s]<=o&&(s|=8),a[4|s]<=o&&(s|=4),a[2|s]<=o&&(s|=2),a[1|s]<=o&&(s|=1),s},n.F._writeLit=function(o,a,s,l){return n.F._putsF(s,l,a[o<<1]),l+a[1+(o<<1)]},n.F.inflate=function(o,a){var s=Uint8Array;if(o[0]==3&&o[1]==0)return a||new s(0);var l=n.F,f=l._bitsF,h=l._bitsE,d=l._decodeTiny,i=l.makeCodes,u=l.codes2map,g=l._get17,p=l.U,m=a==null;m&&(a=new s(o.length>>>2<<3));for(var w,x,O=0,y=0,E=0,M=0,_=0,I=0,C=0,v=0,N=0;O==0;)if(O=f(o,N,1),y=f(o,N+1,2),N+=3,y!=0){if(m&&(a=n.F._check(a,v+131072)),y==1&&(w=p.flmap,x=p.fdmap,I=511,C=31),y==2){E=h(o,N,5)+257,M=h(o,N+5,5)+1,_=h(o,N+10,4)+4,N+=14;for(var A=0;A<38;A+=2)p.itree[A]=0,p.itree[A+1]=0;var P=1;for(A=0;A<_;A++){var D=h(o,N+3*A,3);p.itree[1+(p.ordr[A]<<1)]=D,D>P&&(P=D)}N+=3*_,i(p.itree,P),u(p.itree,P,p.imap),w=p.lmap,x=p.dmap,N=d(p.imap,(1<>>4;if(!(b>>>8))a[v++]=b;else{if(b==256)break;var $=v+b-254;if(b>264){var F=p.ldef[b-257];$=v+(F>>>3)+h(o,N,7&F),N+=7&F}var G=x[g(o,N)&C];N+=15&G;var Y=G>>>4,B=p.ddef[Y],V=(B>>>4)+f(o,N,15&B);for(N+=15&B,m&&(a=n.F._check(a,v+131072));v<$;)a[v]=a[v++-V],a[v]=a[v++-V],a[v]=a[v++-V],a[v]=a[v++-V];v=$}}}else{(7&N)!=0&&(N+=8-(7&N));var j=4+(N>>>3),H=o[j-4]|o[j-3]<<8;m&&(a=n.F._check(a,v+H)),a.set(new s(o.buffer,o.byteOffset+j,H),v),N=j+H<<3,v+=H}return a.length==v?a:a.slice(0,v)},n.F._check=function(o,a){var s=o.length;if(a<=s)return o;var l=new Uint8Array(Math.max(s<<1,a));return l.set(o,0),l},n.F._decodeTiny=function(o,a,s,l,f,h){for(var d=n.F._bitsE,i=n.F._get17,u=0;u>>4;if(p<=15)h[u]=p,u++;else{var m=0,w=0;p==16?(w=3+d(l,f,2),f+=2,m=h[u-1]):p==17?(w=3+d(l,f,3),f+=3):p==18&&(w=11+d(l,f,7),f+=7);for(var x=u+w;u>>1;hf&&(f=i),h++}for(;h>1,i=o[h+1],u=d<<4|i,g=a-i,p=o[h]<>>15-a]=u,p++},n.F.revCodes=function(o,a){for(var s=n.F.U.rev15,l=15-a,f=0;f>>l}},n.F._putsE=function(o,a,s){s<<=7&a;var l=a>>>3;o[l]|=s,o[l+1]|=s>>>8},n.F._putsF=function(o,a,s){s<<=7&a;var l=a>>>3;o[l]|=s,o[l+1]|=s>>>8,o[l+2]|=s>>>16},n.F._bitsE=function(o,a,s){return(o[a>>>3]|o[1+(a>>>3)]<<8)>>>(7&a)&(1<>>3]|o[1+(a>>>3)]<<8|o[2+(a>>>3)]<<16)>>>(7&a)&(1<>>3]|o[1+(a>>>3)]<<8|o[2+(a>>>3)]<<16)>>>(7&a)},n.F._get25=function(o,a){return(o[a>>>3]|o[1+(a>>>3)]<<8|o[2+(a>>>3)]<<16|o[3+(a>>>3)]<<24)>>>(7&a)},n.F.U=(t=Uint16Array,r=Uint32Array,{next_code:new t(16),bl_count:new t(16),ordr:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],of0:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],exb:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],ldef:new t(32),df0:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],dxb:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],ddef:new r(32),flmap:new t(512),fltree:[],fdmap:new t(32),fdtree:[],lmap:new t(32768),ltree:[],ttree:[],dmap:new t(32768),dtree:[],imap:new t(512),itree:[],rev15:new t(32768),lhst:new r(286),dhst:new r(30),ihst:new r(19),lits:new r(15e3),strt:new t(65536),prev:new t(32768)}),(function(){for(var o=n.F.U,a=0;a<32768;a++){var s=a;s=(4278255360&(s=(4042322160&(s=(3435973836&(s=(2863311530&s)>>>1|(1431655765&s)<<1))>>>2|(858993459&s)<<2))>>>4|(252645135&s)<<4))>>>8|(16711935&s)<<8,o.rev15[a]=(s>>>16|s<<16)>>>17}function l(f,h,d){for(;h--!=0;)f.push(0,d)}for(a=0;a<32;a++)o.ldef[a]=o.of0[a]<<3|o.exb[a],o.ddef[a]=o.df0[a]<<4|o.dxb[a];l(o.fltree,144,8),l(o.fltree,112,9),l(o.fltree,24,7),l(o.fltree,8,8),n.F.makeCodes(o.fltree,9),n.F.codes2map(o.fltree,9,o.flmap),n.F.revCodes(o.fltree,9),l(o.fdtree,32,5),n.F.makeCodes(o.fdtree,5),n.F.codes2map(o.fdtree,5,o.fdmap),n.F.revCodes(o.fdtree,5),l(o.itree,19,0),l(o.ltree,286,0),l(o.dtree,30,0),l(o.ttree,320,0)})()})();var og=tg({__proto__:null,default:On},[On]);const Ht=(function(){var e={nextZero(d,i){for(;d[i]!=0;)i++;return i},readUshort:(d,i)=>d[i]<<8|d[i+1],writeUshort(d,i,u){d[i]=u>>8&255,d[i+1]=255&u},readUint:(d,i)=>16777216*d[i]+(d[i+1]<<16|d[i+2]<<8|d[i+3]),writeUint(d,i,u){d[i]=u>>24&255,d[i+1]=u>>16&255,d[i+2]=u>>8&255,d[i+3]=255&u},readASCII(d,i,u){let g="";for(let p=0;pd.length<2?`0${d}`:d,readUTF8(d,i,u){let g,p="";for(let m=0;m>3)]>>7-((7&_)<<0)&1);x[v]=F[D],x[v+1]=F[D+1],x[v+2]=F[D+2],x[v+3]=L>2)]>>6-((3&_)<<1)&3),x[v]=F[D],x[v+1]=F[D+1],x[v+2]=F[D+2],x[v+3]=L>1)]>>4-((1&_)<<2)&15),x[v]=F[D],x[v+1]=F[D+1],x[v+2]=F[D+2],x[v+3]=L>>3)]>>>7-(7&b)&1))==255*C?0:255;O[G+b]=$<<24|U<<16|U<<8|U}else if(E==2)for(b=0;b>>2)]>>>6-((3&b)<<1)&3))==85*C?0:255,O[G+b]=$<<24|U<<16|U<<8|U;else if(E==4)for(b=0;b>>1)]>>>4-((1&b)<<2)&15))==17*C?0:255,O[G+b]=$<<24|U<<16|U<<8|U;else if(E==8)for(b=0;b>3,C=Math.ceil(E*_/8),v=new Uint8Array(M*C);let N=0;const A=[0,0,4,0,2,0,1],P=[0,4,0,2,0,1,0],D=[8,8,8,4,4,2,2],L=[8,8,4,4,2,2,1];let U=0;for(;U<7;){const b=D[U],$=L[U];let F=0,G=0,Y=A[U];for(;Y>3])>>7-(7&ue)&1,v[H*C+(q>>3)]|=S<<7-((7&q)<<0)),_==2&&(S=(S=O[ue>>3])>>6-(7&ue)&3,v[H*C+(q>>2)]|=S<<6-((3&q)<<1)),_==4&&(S=(S=O[ue>>3])>>4-(7&ue)&15,v[H*C+(q>>1)]|=S<<4-((1&q)<<2)),_>=8){const te=H*C+q*I;for(let fe=0;fe>3)+fe]}ue+=_,q+=$}j++,H+=b}F*G!=0&&(N+=G*(1+V)),U+=1}return v})(i,d)),i}function n(d,i){return o(new Uint8Array(d.buffer,2,d.length-6),i)}var o=(function(){const d={H:{}};return d.H.N=function(i,u){const g=Uint8Array;let p,m,w=0,x=0,O=0,y=0,E=0,M=0,_=0,I=0,C=0;if(i[0]==3&&i[1]==0)return u||new g(0);const v=d.H,N=v.b,A=v.e,P=v.R,D=v.n,L=v.A,U=v.Z,S=v.m,b=u==null;for(b&&(u=new g(i.length>>>2<<5));w==0;)if(w=N(i,C,1),x=N(i,C+1,2),C+=3,x!=0){if(b&&(u=d.H.W(u,I+(1<<17))),x==1&&(p=S.J,m=S.h,M=511,_=31),x==2){O=A(i,C,5)+257,y=A(i,C+5,5)+1,E=A(i,C+10,4)+4,C+=14;let F=1;for(var $=0;$<38;$+=2)S.Q[$]=0,S.Q[$+1]=0;for($=0;$F&&(F=B)}C+=3*E,D(S.Q,F),L(S.Q,F,S.u),p=S.w,m=S.d,C=P(S.u,(1<>>4;if(!(G>>>8))u[I++]=G;else{if(G==256)break;{let Y=I+G-254;if(G>264){const q=S.q[G-257];Y=I+(q>>>3)+A(i,C,7&q),C+=7&q}const B=m[U(i,C)&_];C+=15&B;const V=B>>>4,j=S.c[V],H=(j>>>4)+N(i,C,15&j);for(C+=15&j;I>>3),G=i[F-4]|i[F-3]<<8;b&&(u=d.H.W(u,I+G)),u.set(new g(i.buffer,i.byteOffset+F,G),I),C=F+G<<3,I+=G}return u.length==I?u:u.slice(0,I)},d.H.W=function(i,u){const g=i.length;if(u<=g)return i;const p=new Uint8Array(g<<1);return p.set(i,0),p},d.H.R=function(i,u,g,p,m,w){const x=d.H.e,O=d.H.Z;let y=0;for(;y>>4;if(M<=15)w[y]=M,y++;else{let _=0,I=0;M==16?(I=3+x(p,m,2),m+=2,_=w[y-1]):M==17?(I=3+x(p,m,3),m+=3):M==18&&(I=11+x(p,m,7),m+=7);const C=y+I;for(;y>>1;for(;wm&&(m=O),w++}for(;w>1,O=i[w+1],y=x<<4|O,E=u-O;let M=i[w]<>>15-u]=y,M++}},d.H.l=function(i,u){const g=d.H.m.r,p=15-u;for(let m=0;m>>p}},d.H.M=function(i,u,g){g<<=7&u;const p=u>>>3;i[p]|=g,i[p+1]|=g>>>8},d.H.I=function(i,u,g){g<<=7&u;const p=u>>>3;i[p]|=g,i[p+1]|=g>>>8,i[p+2]|=g>>>16},d.H.e=function(i,u,g){return(i[u>>>3]|i[1+(u>>>3)]<<8)>>>(7&u)&(1<>>3]|i[1+(u>>>3)]<<8|i[2+(u>>>3)]<<16)>>>(7&u)&(1<>>3]|i[1+(u>>>3)]<<8|i[2+(u>>>3)]<<16)>>>(7&u)},d.H.i=function(i,u){return(i[u>>>3]|i[1+(u>>>3)]<<8|i[2+(u>>>3)]<<16|i[3+(u>>>3)]<<24)>>>(7&u)},d.H.m=(function(){const i=Uint16Array,u=Uint32Array;return{K:new i(16),j:new i(16),X:[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],S:[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,999,999,999],T:[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0,0],q:new i(32),p:[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,65535,65535],z:[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,0,0],c:new u(32),J:new i(512),_:[],h:new i(32),$:[],w:new i(32768),C:[],v:[],d:new i(32768),D:[],u:new i(512),Q:[],r:new i(32768),s:new u(286),Y:new u(30),a:new u(19),t:new u(15e3),k:new i(65536),g:new i(32768)}})(),(function(){const i=d.H.m;for(var u=0;u<32768;u++){let p=u;p=(2863311530&p)>>>1|(1431655765&p)<<1,p=(3435973836&p)>>>2|(858993459&p)<<2,p=(4042322160&p)>>>4|(252645135&p)<<4,p=(4278255360&p)>>>8|(16711935&p)<<8,i.r[u]=(p>>>16|p<<16)>>>17}function g(p,m,w){for(;m--!=0;)p.push(0,w)}for(u=0;u<32;u++)i.q[u]=i.S[u]<<3|i.T[u],i.c[u]=i.p[u]<<4|i.z[u];g(i._,144,8),g(i._,112,9),g(i._,24,7),g(i._,8,8),d.H.n(i._,9),d.H.A(i._,9,i.J),d.H.l(i._,9),g(i.$,32,5),d.H.n(i.$,5),d.H.A(i.$,5,i.h),d.H.l(i.$,5),g(i.Q,19,0),g(i.C,286,0),g(i.D,30,0),g(i.v,320,0)})(),d.H.N})();function a(d){return[1,null,3,1,2,null,4][d.ctype]*d.depth}function s(d,i,u,g,p){let m=a(i);const w=Math.ceil(g*m/8);let x,O;m=Math.ceil(m/8);let y=d[u],E=0;if(y>1&&(d[u]=[0,0,1][y-2]),y==3)for(E=m;E>>1)&255;for(let M=0;M>>1);for(;E>>1)}else{for(;E=0&&x>=0?(M=U*i+S<<2,_=(x+U)*p+w+S<<2):(M=(-x+U)*i-w+S<<2,_=U*p+S<<2),O==0)g[_]=d[M],g[_+1]=d[M+1],g[_+2]=d[M+2],g[_+3]=d[M+3];else if(O==1){var I=d[M+3]*.00392156862745098,C=d[M]*I,v=d[M+1]*I,N=d[M+2]*I,A=g[_+3]*(1/255),P=g[_]*A,D=g[_+1]*A,L=g[_+2]*A;const b=1-I,$=I+A*b,F=$==0?0:1/$;g[_+3]=255*$,g[_+0]=(C+P*b)*F,g[_+1]=(v+D*b)*F,g[_+2]=(N+L*b)*F}else if(O==2)I=d[M+3],C=d[M],v=d[M+1],N=d[M+2],A=g[_+3],P=g[_],D=g[_+1],L=g[_+2],I==A&&C==P&&v==D&&N==L?(g[_]=0,g[_+1]=0,g[_+2]=0,g[_+3]=0):(g[_]=C,g[_+1]=v,g[_+2]=N,g[_+3]=I);else if(O==3){if(I=d[M+3],C=d[M],v=d[M+1],N=d[M+2],A=g[_+3],P=g[_],D=g[_+1],L=g[_+2],I==A&&C==P&&v==D&&N==L)continue;if(I<220&&A>20)return!1}return!0}return{decode:function(i){const u=new Uint8Array(i);let g=8;const p=e,m=p.readUshort,w=p.readUint,x={tabs:{},frames:[]},O=new Uint8Array(u.length);let y,E=0,M=0;const _=[137,80,78,71,13,10,26,10];for(var I=0;I<8;I++)if(u[I]!=_[I])throw"The input is not a PNG file!";for(;g>>1:N>>>=1;C[v]=N}return C})(),update(C,v,N,A){for(let P=0;P>>8;return C},crc:(C,v,N)=>4294967295^n.update(4294967295,C,v,N)};function o(C,v,N,A){v[N]+=C[0]*A>>4,v[N+1]+=C[1]*A>>4,v[N+2]+=C[2]*A>>4,v[N+3]+=C[3]*A>>4}function a(C){return Math.max(0,Math.min(255,C))}function s(C,v){const N=C[0]-v[0],A=C[1]-v[1],P=C[2]-v[2],D=C[3]-v[3];return N*N+A*A+P*P+D*D}function l(C,v,N,A,P,D,L){L==null&&(L=1);const U=A.length,S=[];for(var b=0;b>>0&255,H>>>8&255,H>>>16&255,H>>>24&255])}for(b=0;b>2]=$,Y[b>>2]=A[$]}}function f(C,v,N,A,P){P==null&&(P={});const{crc:D}=n,L=t.writeUint,U=t.writeUshort,S=t.writeASCII;let b=8;const $=C.frames.length>1;let F,G=!1,Y=33+($?20:0);if(P.sRGB!=null&&(Y+=13),P.pHYs!=null&&(Y+=21),P.iCCP!=null&&(F=pako.deflate(P.iCCP),Y+=21+F.length+4),C.ctype==3){for(var B=C.plte.length,V=0;V>>24!=255&&(G=!0);Y+=8+3*B+4+(G?8+1*B+4:0)}for(var j=0;j>>8&255,Ge=R>>>16&255;H[b+fe+0]=ke,H[b+fe+1]=me,H[b+fe+2]=Ge}if(b+=3*B,L(H,b,D(H,b-3*B-4,3*B+4)),b+=4,G){for(L(H,b,B),b+=4,S(H,b,"tRNS"),b+=4,V=0;V>>24&255;b+=B,L(H,b,D(H,b-B-4,B+4)),b+=4}}let ue=0;for(j=0;jNe&&(Ne=Ze),BeVe&&(Ve=Be));Ne==-1&&(Ee=he=Ne=Ve=0),K&&((1&Ee)==1&&Ee--,(1&he)==1&&he--);const Fe=(Ne-Ee+1)*(Ve-he+1);Fe<_e&&(_e=Fe,Se=Ue,se=Ee,ie=he,le=Ne-Ee+1,ne=Ve-he+1)}xe=new Uint8Array(Ce[ae-1-Se]),Se==1&&(oe[ae-1].dispose=2),be=new Uint8Array(le*ne*4),e(xe,we,$e,be,le,ne,-se,-ie,0),Te=e(Oe,we,$e,be,le,ne,-se,-ie,3)?1:0,Te==1?u(Oe,we,$e,be,{x:se,y:ie,width:le,height:ne}):e(Oe,we,$e,be,le,ne,-se,-ie,0)}else be=Oe.slice(0);oe.push({rect:{x:se,y:ie,width:le,height:ne},img:be,blend:Te,dispose:0})}if(Le)for(ae=0;ae>2,Le>>2);fe.push(R);const K=new Uint8Array(we.abuf,$e,Le);$&&l(ke.img,ke.rect.width,ke.rect.height,te,K,R),ke.img.set(K),$e+=Le}}else for(B=0;Bme&&Ce==Me[j-me])R[j]=R[j-me];else{let we=ue[Ce];if(we==null&&(ue[Ce]=we=te.length,te.push(Ce),te.length>=300))break;R[j]=we}}}const Ge=te.length;for(Ge<=256&&b==0&&(G=Ge<=2?1:Ge<=4?2:Ge<=16?4:8,G=Math.max(G,S)),B=0;B>1)]|=Le[re+ye]<<4-4*(1&ye);else if(G==2)for(ye=0;ye>2)]|=Le[re+ye]<<6-2*(3&ye);else if(G==1)for(ye=0;ye>3)]|=Le[re+ye]<<7-1*(7&ye)}Ce=De,F=3,$e=1}else if(H==0&&q.length==1){De=new Uint8Array(me*Me*3);const Le=me*Me;for(j=0;jj&&(j=fe),RH&&(H=R))}j==-1&&(B=V=j=H=0),L&&((1&B)==1&&B--,(1&V)==1&&V--),D={x:B,y:V,width:j-B+1,height:H-V+1};const q=A[P];q.rect=D,q.blend=1,q.img=new Uint8Array(D.width*D.height*4),A[P-1].dispose==0?(e(b,v,N,q.img,D.width,D.height,-D.x,-D.y,0),u(G,v,N,q.img,D)):e(G,v,N,q.img,D.width,D.height,-D.x,-D.y,0)}function u(C,v,N,A,P){e(C,v,N,A,P.width,P.height,-P.x,-P.y,2)}function g(C,v,N,A,P,D,L){const U=[];let S,b=[0,1,2,3,4];D!=-1?b=[D]:(v*A>5e5||N==1)&&(b=[0]),L&&(S={level:0});const $=og;for(var F=0;F>1)+256&255;if(D==4)for(S=P;S>1)&255;for(S=P;S>1)&255}if(D==4){for(S=0;S>2);let $;if(N.length<2e7)for(var F=0;F>2]=$.ind,P[F>>2]=$.est.rgba;else for(F=0;F>2]=$.ind,P[F>>2]=$.est.rgba}return{abuf:A.buffer,inds:b,plte:U}}function w(C,v,N){N==null&&(N=1e-4);const A=new Uint32Array(C.buffer),P={i0:0,i1:C.length,bst:null,est:null,tdst:0,left:null,right:null};P.bst=M(C,P.i0,P.i1),P.est=_(P.bst);const D=[P];for(;D.lengthU&&(U=D[L].est.L,S=L);if(U=$||b.i1<=$){b.est.L=0;continue}const F={i0:b.i0,i1:$,bst:null,est:null,tdst:0,left:null,right:null};F.bst=M(C,F.i0,F.i1),F.est=_(F.bst);const G={i0:$,i1:b.i1,bst:null,est:null,tdst:0,left:null,right:null};for(G.bst={R:[],m:[],N:b.bst.N-F.bst.N},L=0;L<16;L++)G.bst.R[L]=b.bst.R[L]-F.bst.R[L];for(L=0;L<4;L++)G.bst.m[L]=b.bst.m[L]-F.bst.m[L];G.est=_(G.bst),b.left=F,b.right=G,D[S]=F,D.push(G)}for(D.sort(((U,S)=>S.bst.N-U.bst.N)),L=0;L0&&(L=C.right,U=C.left);const S=x(L,v,N,A,P);if(S.tdst<=D*D)return S;const b=x(U,v,N,A,P);return b.tdstD;)A-=4;if(N>=A)break;const L=v[N>>2];v[N>>2]=v[A>>2],v[A>>2]=L,N+=4,A-=4}for(;E(C,N,P)>D;)N-=4;return N+4}function E(C,v,N){return C[v]*N[0]+C[v+1]*N[1]+C[v+2]*N[2]+C[v+3]*N[3]}function M(C,v,N){const A=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],P=[0,0,0,0],D=N-v>>2;for(let L=v;L>>0}}var I={multVec:(C,v)=>[C[0]*v[0]+C[1]*v[1]+C[2]*v[2]+C[3]*v[3],C[4]*v[0]+C[5]*v[1]+C[6]*v[2]+C[7]*v[3],C[8]*v[0]+C[9]*v[1]+C[10]*v[2]+C[11]*v[3],C[12]*v[0]+C[13]*v[1]+C[14]*v[2]+C[15]*v[3]],dot:(C,v)=>C[0]*v[0]+C[1]*v[1]+C[2]*v[2]+C[3]*v[3],sml:(C,v)=>[C*v[0],C*v[1],C*v[2],C*v[3]]};Ht.encode=function(v,N,A,P,D,L,U){P==null&&(P=0),U==null&&(U=!1);const S=d(v,N,A,P,[!1,!1,!1,0,U,!1]);return h(S,-1),f(S,N,A,D,L)},Ht.encodeLL=function(v,N,A,P,D,L,U,S){const b={ctype:0+(P==1?0:2)+(D==0?0:4),depth:L,frames:[]},$=(P+D)*L,F=$*N;for(let G=0;G>>0),M(1),M(32),_(3),_(f),_(2835),_(2835),I(8),_(16711680),_(65280),_(255),_(4278190080),_(1466527264),(function C(){for(;O0;){for(w=122+O*l,g=0;g>>24,i.setUint32(w+g,p<<8|m),g+=4;O++}E{t(new Blob([r],{type:"image/bmp"}))}))},_dly:9};var bt={CHROME:"CHROME",FIREFOX:"FIREFOX",DESKTOP_SAFARI:"DESKTOP_SAFARI",IE:"IE",IOS:"IOS",ETC:"ETC"},ag={[bt.CHROME]:16384,[bt.FIREFOX]:11180,[bt.DESKTOP_SAFARI]:16384,[bt.IE]:8192,[bt.IOS]:4096,[bt.ETC]:8192};const ra=typeof window<"u",Hl=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope,In=ra&&window.cordova&&window.cordova.require&&window.cordova.require("cordova/modulemapper"),sg=(ra||Hl)&&(In&&In.getOriginalSymbol(window,"File")||typeof File<"u"&&File),Gl=(ra||Hl)&&(In&&In.getOriginalSymbol(window,"FileReader")||typeof FileReader<"u"&&FileReader);function na(e,t,r=Date.now()){return new Promise((n=>{const o=e.split(","),a=o[0].match(/:(.*?);/)[1],s=globalThis.atob(o[1]);let l=s.length;const f=new Uint8Array(l);for(;l--;)f[l]=s.charCodeAt(l);const h=new Blob([f],{type:a});h.name=t,h.lastModified=r,n(h)}))}function jl(e){return new Promise(((t,r)=>{const n=new Gl;n.onload=()=>t(n.result),n.onerror=o=>r(o),n.readAsDataURL(e)}))}function Bl(e){return new Promise(((t,r)=>{const n=new Image;n.onload=()=>t(n),n.onerror=o=>r(o),n.src=e}))}function fr(){if(fr.cachedResult!==void 0)return fr.cachedResult;let e=bt.ETC;const{userAgent:t}=navigator;return/Chrom(e|ium)/i.test(t)?e=bt.CHROME:/iP(ad|od|hone)/i.test(t)&&/WebKit/i.test(t)?e=bt.IOS:/Safari/i.test(t)?e=bt.DESKTOP_SAFARI:/Firefox/i.test(t)?e=bt.FIREFOX:(/MSIE/i.test(t)||document.documentMode)&&(e=bt.IE),fr.cachedResult=e,fr.cachedResult}function Wl(e,t){const r=fr(),n=ag[r];let o=e,a=t,s=o*a;const l=o>a?a/o:o/a;for(;s>n*n;){const f=(n+o)/2,h=(n+a)/2;fzl.toBlob(e,d))).then(function(d){try{return l=d,l.name=r,l.lastModified=n,h.call(this)}catch(i){return s(i)}}.bind(this),s);{let d=function(){return h.call(this)};if(typeof OffscreenCanvas=="function"&&e instanceof OffscreenCanvas)return e.convertToBlob({type:t,quality:o}).then(function(i){try{return l=i,l.name=r,l.lastModified=n,d.call(this)}catch(u){return s(u)}}.bind(this),s);{let i;return i=e.toDataURL(t,o),na(i,r,n).then(function(u){try{return l=u,d.call(this)}catch(g){return s(g)}}.bind(this),s)}}}function f(){return a(l)}}))}function Vt(e){e.width=0,e.height=0}function Nr(){return new Promise((function(e,t){let r,n,o,a;return Nr.cachedResult!==void 0?e(Nr.cachedResult):na("data:image/jpeg;base64,/9j/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAYAAAAAAAD/2wCEAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAf/AABEIAAEAAgMBEQACEQEDEQH/xABKAAEAAAAAAAAAAAAAAAAAAAALEAEAAAAAAAAAAAAAAAAAAAAAAQEAAAAAAAAAAAAAAAAAAAAAEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwA/8H//2Q==","test.jpg",Date.now()).then((function(s){try{return r=s,Pn(r).then((function(l){try{return n=l[1],Fn(n,r.type,r.name,r.lastModified).then((function(f){try{return o=f,Vt(n),Pn(o).then((function(h){try{return a=h[0],Nr.cachedResult=a.width===1&&a.height===2,e(Nr.cachedResult)}catch(d){return t(d)}}),t)}catch(h){return t(h)}}),t)}catch(f){return t(f)}}),t)}catch(l){return t(l)}}),t)}))}function Vl(e){return new Promise(((t,r)=>{const n=new Gl;n.onload=o=>{const a=new DataView(o.target.result);if(a.getUint16(0,!1)!=65496)return t(-2);const s=a.byteLength;let l=2;for(;lr(o),n.readAsArrayBuffer(e)}))}function Yl(e,t){const{width:r}=e,{height:n}=e,{maxWidthOrHeight:o}=t;let a,s=e;return isFinite(o)&&(r>o||n>o)&&([s,a]=Dn(r,n),r>n?(s.width=o,s.height=n/r*o):(s.width=r/n*o,s.height=o),a.drawImage(e,0,0,s.width,s.height),Vt(e)),s}function Xl(e,t){const{width:r}=e,{height:n}=e,[o,a]=Dn(r,n);switch(t>4&&t<9?(o.width=n,o.height=r):(o.width=r,o.height=n),t){case 2:a.transform(-1,0,0,1,r,0);break;case 3:a.transform(-1,0,0,-1,r,n);break;case 4:a.transform(1,0,0,-1,0,n);break;case 5:a.transform(0,1,1,0,0,0);break;case 6:a.transform(0,1,-1,0,n,0);break;case 7:a.transform(0,-1,-1,0,n,r);break;case 8:a.transform(0,-1,1,0,0,r)}return a.drawImage(e,0,0,r,n),Vt(e),o}function ql(e,t,r=0){return new Promise((function(n,o){let a,s,l,f,h,d,i,u,g,p,m,w,x,O,y,E,M,_,I,C;function v(A=5){if(t.signal&&t.signal.aborted)throw t.signal.reason;a+=A,t.onProgress(Math.min(a,100))}function N(A){if(t.signal&&t.signal.aborted)throw t.signal.reason;a=Math.min(Math.max(A,a),100),t.onProgress(a)}return a=r,s=t.maxIteration||10,l=1024*t.maxSizeMB*1024,v(),Pn(e,t).then(function(A){try{return[,f]=A,v(),h=Yl(f,t),v(),new Promise((function(P,D){var L;if(!(L=t.exifOrientation))return Vl(e).then(function(S){try{return L=S,U.call(this)}catch(b){return D(b)}}.bind(this),D);function U(){return P(L)}return U.call(this)})).then(function(P){try{return d=P,v(),Nr().then(function(D){try{return i=D?h:Xl(h,d),v(),u=t.initialQuality||1,g=t.fileType||e.type,Fn(i,g,e.name,e.lastModified,u).then(function(L){try{{let S=function(){if(s--&&(y>l||y>x)){let $,F;return $=C?.95*I.width:I.width,F=C?.95*I.height:I.height,[M,_]=Dn($,F),_.drawImage(I,0,0,$,F),u*=g==="image/png"?.85:.95,Fn(M,g,e.name,e.lastModified,u).then((function(G){try{return E=G,Vt(I),I=M,y=E.size,N(Math.min(99,Math.floor((O-y)/(O-l)*100))),S}catch(Y){return o(Y)}}),o)}return[1]},b=function(){return Vt(I),Vt(M),Vt(h),Vt(i),Vt(f),N(100),n(E)};if(p=L,v(),m=p.size>l,w=p.size>e.size,!m&&!w)return N(100),n(p);var U;return x=e.size,O=p.size,y=O,I=i,C=!t.alwaysKeepResolution&&m,(U=function($){for(;$;){if($.then)return void $.then(U,o);try{if($.pop){if($.length)return $.pop()?b.call(this):$;$=S}else $=$.call(this)}catch(F){return o(F)}}}.bind(this))(S)}}catch(S){return o(S)}}.bind(this),o)}catch(L){return o(L)}}.bind(this),o)}catch(D){return o(D)}}.bind(this),o)}catch(P){return o(P)}}.bind(this),o)}))}const lg=` let scriptImported = false self.addEventListener('message', async (e) => { const { file, id, imageCompressionLibUrl, options } = e.data @@ -58,14 +58,14 @@ self.addEventListener('message', async (e) => { self.postMessage({ error: e.message + '\\n' + e.stack, id }) } }) -`;let oa;function ig(e,t){return new Promise(((r,n)=>{oa||(oa=(function(s){const l=[];return l.push(s),URL.createObjectURL(new Blob(l))})(lg));const o=new Worker(oa);o.addEventListener("message",(function(s){if(t.signal&&t.signal.aborted)o.terminate();else if(s.data.progress===void 0){if(s.data.error)return n(new Error(s.data.error)),void o.terminate();r(s.data.file),o.terminate()}else t.onProgress(s.data.progress)})),o.addEventListener("error",n),t.signal&&t.signal.addEventListener("abort",(()=>{n(t.signal.reason),o.terminate()})),o.postMessage({file:e,imageCompressionLibUrl:t.libURL,options:{...t,onProgress:void 0,signal:void 0}})}))}function ct(e,t){return new Promise((function(r,n){let o,a,s,l,f,h;if(o={...t},s=0,{onProgress:l}=o,o.maxSizeMB=o.maxSizeMB||Number.POSITIVE_INFINITY,f=typeof o.useWebWorker!="boolean"||o.useWebWorker,delete o.useWebWorker,o.onProgress=g=>{s=g,typeof l=="function"&&l(s)},!(e instanceof Blob||e instanceof sg))return n(new Error("The file given is not an instance of Blob or File"));if(!/^image/.test(e.type))return n(new Error("The file given is not an image"));if(h=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope,!f||typeof Worker!="function"||h)return Zl(e,o).then(function(g){try{return a=g,u.call(this)}catch(p){return n(p)}}.bind(this),n);var d=function(){try{return u.call(this)}catch(g){return n(g)}}.bind(this),i=function(g){try{return Zl(e,o).then((function(p){try{return a=p,d()}catch(m){return n(m)}}),n)}catch(p){return n(p)}};try{return o.libURL=o.libURL||"https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js",ig(e,o).then((function(g){try{return a=g,d()}catch{return i()}}),i)}catch{i()}function u(){try{a.name=e.name,a.lastModified=e.lastModified}catch{}try{o.preserveExif&&e.type==="image/jpeg"&&(!o.fileType||o.fileType&&o.fileType===e.type)&&(a=Ul(e,a))}catch{}return r(a)}}))}ct.getDataUrlFromFile=jl,ct.getFilefromDataUrl=na,ct.loadImage=Bl,ct.drawImageInCanvas=Kl,ct.drawFileInCanvas=Pn,ct.canvasToFile=Fn,ct.getExifOrientation=Vl,ct.handleMaxWidthOrHeight=Yl,ct.followExifOrientation=Xl,ct.cleanupCanvasMemory=Vt,ct.isAutoOrientationInBrowser=Nr,ct.approximateBelowMaximumCanvasSizeOfBrowser=Wl,ct.copyExifWithoutOrientation=Ul,ct.getBrowserName=fr,ct.version="2.0.2";const cg=window.G7Core,$n=e=>{const t=["B","KB","MB","GB"];let r=0,n=e;for(;n>=1024&&r{if(e&&typeof e=="object"){const t=e;if(t.response?.data?.message)return t.response.data.message;if(t.response?.data?.errors){const r=Object.values(t.response.data.errors)[0];if(Array.isArray(r)&&r[0])return r[0]}if(t.message)return t.message}return e instanceof Error?e.message:"업로드 실패"},Ql=e=>e?e.startsWith("image/")?"fa-file-image":e.startsWith("video/")?"fa-file-video":e.startsWith("audio/")?"fa-file-audio":e==="application/pdf"?"fa-file-pdf":e.includes("word")||e.includes("document")?"fa-file-word":e.includes("excel")||e.includes("spreadsheet")?"fa-file-excel":e.includes("zip")||e.includes("compressed")?"fa-file-zipper":"fa-file":"fa-file",Re=(e,t)=>cg?.t?.(e,t)??e,gr=window.G7Core;function Jl(e){const{attachmentableType:t,attachmentableId:r,collection:n,maxFiles:o,maxSize:a,maxConcurrentUploads:s,accept:l,imageCompression:f,roleIds:h,autoUpload:d,initialFiles:i,endpoints:u,onFilesChange:g,onUploadComplete:p,onUploadError:m,onRemove:w,onReorder:x,uploadTriggerEvent:A,confirmBeforeRemove:v,uploadParams:E}=e,[O,_]=k.useState(i),[I,C]=k.useState([]),[y,N]=k.useState(!1),M=k.useRef(null),P=k.useRef(0),D=k.useRef(new Set),L=k.useRef(new Map),[U,S]=k.useState(!1),[b,$]=k.useState(null),[F,G]=k.useState(!1),Y=k.useRef(!1),[B,V]=k.useState([]),j=k.useRef(i),[H,Z]=k.useState(!1),[ue,te]=k.useState(0),fe=k.useRef(0),[R,ke]=k.useState(new Map),me=k.useRef(new Map);k.useEffect(()=>{g?.(I)},[I,g]);const Ge=k.useMemo(()=>{const X=j.current;return X===i?X:X.length!==i.length?(j.current=i,i):X.length===0&&i.length===0?X:i.some((ie,le)=>ie.id!==X[le]?.id)?(j.current=i,i):X},[i]);k.useEffect(()=>{if(Y.current)return;const X=Ge.filter(le=>!D.current.has(le.id)&&(!le.hash||!D.current.has(le.hash))),se=new Set(X.map(le=>le.id)),ie=Array.from(L.current.values()).filter(le=>!se.has(le.id)&&!D.current.has(le.id));_([...X,...ie])},[Ge]);const De=k.useCallback(async X=>{const se={maxSizeMB:f?.maxSizeMB??1,maxWidthOrHeight:f?.maxWidthOrHeight??1920,useWebWorker:!0};return await ct(X,se)},[f]),ye=k.useCallback(async X=>{const se=O.length+I.length,ie=Math.max(0,o-se),le=Array.from(X).slice(0,ie);if(X.length>ie){const ne=Array.from(X).slice(ie),Te=Re("attachment.upload_limit_exceeded",{max:o});m?.(Te,ne[0]??X[0])}for(const ne of le){if(ne.size>a*1024*1024){m?.(`[${ne.name}] 파일 크기(${$n(ne.size)})가 최대 허용 크기(${a}MB)를 초과합니다.`,ne);continue}if(l){const ve="."+ne.name.split(".").pop()?.toLowerCase();if(!l.split(",").map(Ue=>Ue.trim().toLowerCase()).some(Ue=>{if(Ue.includes("/")){if(Ue.endsWith("/*")){const je=Ue.slice(0,-2);return ne.type.toLowerCase().startsWith(je+"/")}return ne.type.toLowerCase()===Ue}return ve===Ue})){m?.(`[${ne.name}] 허용되지 않는 파일 형식입니다. (허용: ${l})`,ne);continue}}const Te={id:`pending-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,file:ne,original_filename:ne.name,mime_type:ne.type,size:ne.size,size_formatted:$n(ne.size),status:"pending",progress:0};if(ne.type.startsWith("image/")&&(Te.preview=URL.createObjectURL(ne)),C(ve=>[...ve,Te]),ne.type.startsWith("image/")&&f){C(ve=>ve.map(Se=>Se.id===Te.id?{...Se,status:"compressing"}:Se));try{const ve=await De(ne);C(Se=>Se.map(_e=>_e.id===Te.id?{..._e,compressedBlob:ve,size:ve.size,size_formatted:$n(ve.size),status:"pending",progress:0}:_e))}catch{C(ve=>ve.map(Se=>Se.id===Te.id?{...Se,status:"error",error:"이미지 압축 실패"}:Se))}}}},[O.length,I.length,o,a,l,f,De,m]),Me=k.useCallback(async X=>{const se=new FormData,ie=X.compressedBlob?new File([X.compressedBlob],X.original_filename,{type:X.mime_type}):X.file;se.append("file",ie),t&&se.append("attachmentable_type",t),r&&se.append("attachmentable_id",String(r)),se.append("collection",n),h.forEach(le=>{se.append("role_ids[]",String(le))}),E&&Object.entries(E).forEach(([le,ne])=>{se.append(le,ne)});try{const le=await gr.api.post(u.upload,se,{headers:{"Content-Type":"multipart/form-data"},onUploadProgress:Te=>{const ve=Math.round(Te.loaded*100/(Te.total??1));C(Se=>Se.map(_e=>_e.id===X.id?{..._e,progress:ve}:_e))}});return le?.data?.data??le?.data}catch(le){const ne=ql(le);throw new Error(ne)}},[t,r,n,h,u.upload]),Ce=k.useCallback(async()=>{const X=I.filter(ve=>ve.status==="pending"||ve.status==="error");if(X.length===0)return[];const se=[],ie=new Map,le=[...X],ne=async()=>{for(;le.length>0&&P.currentSe.map(_e=>_e.id===ve.id?{..._e,status:"uploading",progress:0}:_e));try{const Se=await Me(ve);if(Se)se.push(Se),ie.set(String(ve.id),String(Se.hash)),L.current.set(Se.id,Se),C(_e=>_e.filter(Ue=>Ue.id!==ve.id)),_(_e=>[..._e,Se]),V(_e=>{if(_e.length===0)return _e;const Ue=String(ve.id);return _e.some(Ee=>String(Ee)===Ue)?_e.map(Ee=>String(Ee)===Ue?String(Se.hash):Ee):_e}),ve.preview&&URL.revokeObjectURL(ve.preview);else{const _e=Re("attachment.upload_response_invalid");C(Ue=>Ue.map(je=>je.id===ve.id?{...je,status:"error",error:_e}:je)),m?.(`[${ve.original_filename}] ${_e}`,ve.file)}}catch(Se){const _e=Se instanceof Error?Se.message:"업로드 실패";C(Ue=>Ue.map(je=>je.id===ve.id?{...je,status:"error",error:_e}:je)),m?.(`[${ve.original_filename}] ${_e}`,ve.file)}finally{P.current--}}},Te=Array(Math.min(s,X.length)).fill(null).map(()=>ne());if(await Promise.all(Te),se.length>0&&(p?.(se),u.reorder&&B.length>0&&x)){const ve=[...O,...se],Se=B.map(je=>ie.get(String(je))??je),_e=new Map(Se.map((je,Ee)=>[String(je),Ee])),Ue=[...ve].sort((je,Ee)=>{const he=_e.get(String(je.hash))??ve.length,Ne=_e.get(String(Ee.hash))??ve.length;return he-Ne}).map((je,Ee)=>({...je,sort_order:Ee,order:Ee+1}));x(Ue)}return se},[I,s,Me,p,m,B,O,x,u.reorder]);k.useEffect(()=>{if(!A)return;const X=gr.componentEvent.on(A,async()=>{const se=await Ce();return{uploadedAttachments:se,existingFiles:O,allFiles:[...O,...se]}});return()=>{X()}},[A,Ce,O]),k.useEffect(()=>{d&&I.some(X=>X.status==="pending")&&Ce()},[d,I,Ce]);const we=k.useCallback(async X=>{G(!0);try{if(X.id&&u.delete){const ie=u.delete.replace(":id",String(X.id));await gr.api.delete(ie)}const se=X.hash||X.id;X.id&&(D.current.add(X.id),L.current.delete(X.id)),X.hash&&D.current.add(X.hash),_(ie=>ie.filter(le=>(le.hash||le.id)!==se)),w?.(X.hash||X.id),S(!1),$(null)}catch{console.error("첨부파일 삭제 실패")}finally{G(!1)}},[w,u.delete]),$e=k.useCallback(async X=>{"hash"in X?v?($(X),S(!0)):await we(X):(X.preview&&URL.revokeObjectURL(X.preview),C(se=>se.filter(ie=>ie.id!==X.id)))},[v,we]),Le=k.useCallback(X=>{C(se=>se.map(ie=>ie.id===X.id?{...ie,status:"pending",error:void 0}:ie))},[]),K=k.useCallback(async X=>{const{arrayMove:se}=await Promise.resolve().then(()=>Wh),{active:ie,over:le}=X;if(!le||ie.id===le.id)return;const ne=[...O,...I];let Te;if(B.length===0)Te=ne;else{const he=new Map(B.map((Ne,Ve)=>[String(Ne),Ve]));Te=[...ne].sort((Ne,Ve)=>{const Fe="hash"in Ne?String(Ne.hash):String(Ne.id),Be="hash"in Ve?String(Ve.hash):String(Ve.id);return(he.get(Fe)??ne.length)-(he.get(Be)??ne.length)})}const ve=Te.findIndex(he=>"hash"in he?he.hash===ie.id:he.id===ie.id),Se=Te.findIndex(he=>"hash"in he?he.hash===le.id:he.id===le.id),_e=se(Te,ve,Se);V(_e.map(he=>"hash"in he?he.hash:he.id));const Ue=_e.filter(he=>"hash"in he),je=_e.filter(he=>!("hash"in he));Y.current=!0,_(Ue),C(je);const Ee=Ue.map((he,Ne)=>({...he,sort_order:Ne,order:Ne+1}));if(Ue.length>0&&u.reorder){const he=Ue.map((Ne,Ve)=>({id:Ne.id,order:Ve+1}));try{const Ne=await gr.api.patch(u.reorder,{order:he});gr.toast.success(Ne.message)}catch(Ne){const Ve=Ne instanceof Error?Ne.message:Re("attachment.reorder_failed");gr.toast.error(Ve)}}x?.(Ee)},[O,I,B,u.reorder,x]),re=k.useMemo(()=>[...O,...I].filter(X=>"is_image"in X?X.is_image:X.mime_type?.startsWith("image/")??!1),[O,I]),oe=k.useCallback(X=>{const se=re.findIndex(ie=>"hash"in X&&"hash"in ie?ie.hash===X.hash:"id"in X&&"id"in ie&&!("hash"in X)&&!("hash"in ie)?ie.id===X.id:!1);se!==-1&&(fe.current+=1,te(se),Z(!0))},[re]);k.useEffect(()=>{let X=!1;return(async()=>{const ie=O.filter(ne=>ne.is_image),le=new Set(ie.map(ne=>ne.id));for(const[ne,Te]of me.current)le.has(ne)||(URL.revokeObjectURL(Te),me.current.delete(ne));for(const ne of ie){if(X)break;if(!me.current.has(ne.id))try{const Te=await gr.api.get(ne.download_url,{responseType:"blob"});if(!X&&Te){const ve=URL.createObjectURL(Te);me.current.set(ne.id,ve),ke(new Map(me.current))}}catch(Te){console.error("Failed to load authenticated image:",Te)}}})(),()=>{X=!0}},[O]),k.useEffect(()=>()=>{me.current.forEach(X=>URL.revokeObjectURL(X)),me.current.clear()},[]);const ae=k.useCallback(async X=>{const{executeImageDownload:se}=await Promise.resolve().then(()=>Al);await se({src:X.download_url,downloadUrl:X.download_url,filename:X.original_filename,downloadRequiresAuth:!0})},[]),be=k.useMemo(()=>{const X=[...O,...I];if(B.length===0)return X;const se=new Map(B.map((ie,le)=>[String(ie),le]));return[...X].sort((ie,le)=>{const ne="hash"in ie?String(ie.hash):String(ie.id),Te="hash"in le?String(le.hash):String(le.id),ve=se.get(ne)??X.length,Se=se.get(Te)??X.length;return ve-Se})},[O,I,B]),xe=be.length,He=xe>0,Pe=xeC([]),[]),Oe=k.useCallback(()=>I,[I]);return{existingFiles:O,pendingFiles:I,isDragOver:y,setIsDragOver:N,isDeleting:F,totalCount:xe,hasFiles:He,canAddMore:Pe,allItems:be,imageFiles:re,handleFiles:ye,handleRemove:$e,handleRetry:Le,handleUploadAll:Ce,handleOpenGallery:oe,handleDownload:ae,handleDragEnd:K,inputRef:M,galleryOpen:H,setGalleryOpen:Z,galleryStartIndex:ue,galleryKeyRef:fe,confirmDialogOpen:U,setConfirmDialogOpen:S,itemToDelete:b,executeRemoveAttachment:we,authenticatedImageUrls:R,clear:Ke,getPendingFiles:Oe}}const Rl=({isDragOver:e,canAddMore:t,onFiles:r,setIsDragOver:n,inputRef:o,accept:a,maxFiles:s,maxSize:l,children:f})=>c.jsxs(W,{className:` +`;let oa;function ig(e,t){return new Promise(((r,n)=>{oa||(oa=(function(s){const l=[];return l.push(s),URL.createObjectURL(new Blob(l))})(lg));const o=new Worker(oa);o.addEventListener("message",(function(s){if(t.signal&&t.signal.aborted)o.terminate();else if(s.data.progress===void 0){if(s.data.error)return n(new Error(s.data.error)),void o.terminate();r(s.data.file),o.terminate()}else t.onProgress(s.data.progress)})),o.addEventListener("error",n),t.signal&&t.signal.addEventListener("abort",(()=>{n(t.signal.reason),o.terminate()})),o.postMessage({file:e,imageCompressionLibUrl:t.libURL,options:{...t,onProgress:void 0,signal:void 0}})}))}function ct(e,t){return new Promise((function(r,n){let o,a,s,l,f,h;if(o={...t},s=0,{onProgress:l}=o,o.maxSizeMB=o.maxSizeMB||Number.POSITIVE_INFINITY,f=typeof o.useWebWorker!="boolean"||o.useWebWorker,delete o.useWebWorker,o.onProgress=g=>{s=g,typeof l=="function"&&l(s)},!(e instanceof Blob||e instanceof sg))return n(new Error("The file given is not an instance of Blob or File"));if(!/^image/.test(e.type))return n(new Error("The file given is not an image"));if(h=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope,!f||typeof Worker!="function"||h)return ql(e,o).then(function(g){try{return a=g,u.call(this)}catch(p){return n(p)}}.bind(this),n);var d=function(){try{return u.call(this)}catch(g){return n(g)}}.bind(this),i=function(g){try{return ql(e,o).then((function(p){try{return a=p,d()}catch(m){return n(m)}}),n)}catch(p){return n(p)}};try{return o.libURL=o.libURL||"https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.2/dist/browser-image-compression.js",ig(e,o).then((function(g){try{return a=g,d()}catch{return i()}}),i)}catch{i()}function u(){try{a.name=e.name,a.lastModified=e.lastModified}catch{}try{o.preserveExif&&e.type==="image/jpeg"&&(!o.fileType||o.fileType&&o.fileType===e.type)&&(a=Ul(e,a))}catch{}return r(a)}}))}ct.getDataUrlFromFile=jl,ct.getFilefromDataUrl=na,ct.loadImage=Bl,ct.drawImageInCanvas=Kl,ct.drawFileInCanvas=Pn,ct.canvasToFile=Fn,ct.getExifOrientation=Vl,ct.handleMaxWidthOrHeight=Yl,ct.followExifOrientation=Xl,ct.cleanupCanvasMemory=Vt,ct.isAutoOrientationInBrowser=Nr,ct.approximateBelowMaximumCanvasSizeOfBrowser=Wl,ct.copyExifWithoutOrientation=Ul,ct.getBrowserName=fr,ct.version="2.0.2";const cg=window.G7Core,$n=e=>{const t=["B","KB","MB","GB"];let r=0,n=e;for(;n>=1024&&r{if(e&&typeof e=="object"){const t=e;if(t.response?.data?.message)return t.response.data.message;if(t.response?.data?.errors){const r=Object.values(t.response.data.errors)[0];if(Array.isArray(r)&&r[0])return r[0]}if(t.message)return t.message}return e instanceof Error?e.message:"업로드 실패"},Ql=e=>e?e.startsWith("image/")?"fa-file-image":e.startsWith("video/")?"fa-file-video":e.startsWith("audio/")?"fa-file-audio":e==="application/pdf"?"fa-file-pdf":e.includes("word")||e.includes("document")?"fa-file-word":e.includes("excel")||e.includes("spreadsheet")?"fa-file-excel":e.includes("zip")||e.includes("compressed")?"fa-file-zipper":"fa-file":"fa-file",Re=(e,t)=>cg?.t?.(e,t)??e,gr=window.G7Core;function Jl(e){const{attachmentableType:t,attachmentableId:r,collection:n,maxFiles:o,maxSize:a,maxConcurrentUploads:s,accept:l,imageCompression:f,roleIds:h,autoUpload:d,initialFiles:i,endpoints:u,onFilesChange:g,onUploadComplete:p,onUploadError:m,onRemove:w,onReorder:x,uploadTriggerEvent:O,confirmBeforeRemove:y,uploadParams:E}=e,[M,_]=k.useState(i),[I,C]=k.useState([]),[v,N]=k.useState(!1),A=k.useRef(null),P=k.useRef(0),D=k.useRef(new Set),L=k.useRef(new Map),[U,S]=k.useState(!1),[b,$]=k.useState(null),[F,G]=k.useState(!1),Y=k.useRef(!1),[B,V]=k.useState([]),j=k.useRef(i),[H,q]=k.useState(!1),[ue,te]=k.useState(0),fe=k.useRef(0),[R,ke]=k.useState(new Map),me=k.useRef(new Map);k.useEffect(()=>{g?.(I)},[I,g]);const Ge=k.useMemo(()=>{const X=j.current;return X===i?X:X.length!==i.length?(j.current=i,i):X.length===0&&i.length===0?X:i.some((ie,le)=>ie.id!==X[le]?.id)?(j.current=i,i):X},[i]);k.useEffect(()=>{if(Y.current)return;const X=Ge.filter(le=>!D.current.has(le.id)&&(!le.hash||!D.current.has(le.hash))),se=new Set(X.map(le=>le.id)),ie=Array.from(L.current.values()).filter(le=>!se.has(le.id)&&!D.current.has(le.id));_([...X,...ie])},[Ge]);const De=k.useCallback(async X=>{const se={maxSizeMB:f?.maxSizeMB??1,maxWidthOrHeight:f?.maxWidthOrHeight??1920,useWebWorker:!0};return await ct(X,se)},[f]),ye=k.useCallback(async X=>{const se=M.length+I.length,ie=Math.max(0,o-se),le=Array.from(X).slice(0,ie);if(X.length>ie){const ne=Array.from(X).slice(ie),Te=Re("attachment.upload_limit_exceeded",{max:o});m?.(Te,ne[0]??X[0])}for(const ne of le){if(ne.size>a*1024*1024){m?.(`[${ne.name}] 파일 크기(${$n(ne.size)})가 최대 허용 크기(${a}MB)를 초과합니다.`,ne);continue}if(l){const ve="."+ne.name.split(".").pop()?.toLowerCase();if(!l.split(",").map(Ue=>Ue.trim().toLowerCase()).some(Ue=>{if(Ue.includes("/")){if(Ue.endsWith("/*")){const je=Ue.slice(0,-2);return ne.type.toLowerCase().startsWith(je+"/")}return ne.type.toLowerCase()===Ue}return ve===Ue})){m?.(`[${ne.name}] 허용되지 않는 파일 형식입니다. (허용: ${l})`,ne);continue}}const Te={id:`pending-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,file:ne,original_filename:ne.name,mime_type:ne.type,size:ne.size,size_formatted:$n(ne.size),status:"pending",progress:0};if(ne.type.startsWith("image/")&&(Te.preview=URL.createObjectURL(ne)),C(ve=>[...ve,Te]),ne.type.startsWith("image/")&&f){C(ve=>ve.map(Se=>Se.id===Te.id?{...Se,status:"compressing"}:Se));try{const ve=await De(ne);C(Se=>Se.map(_e=>_e.id===Te.id?{..._e,compressedBlob:ve,size:ve.size,size_formatted:$n(ve.size),status:"pending",progress:0}:_e))}catch{C(ve=>ve.map(Se=>Se.id===Te.id?{...Se,status:"error",error:"이미지 압축 실패"}:Se))}}}},[M.length,I.length,o,a,l,f,De,m]),Me=k.useCallback(async X=>{const se=new FormData,ie=X.compressedBlob?new File([X.compressedBlob],X.original_filename,{type:X.mime_type}):X.file;se.append("file",ie),t&&se.append("attachmentable_type",t),r&&se.append("attachmentable_id",String(r)),se.append("collection",n),h.forEach(le=>{se.append("role_ids[]",String(le))}),E&&Object.entries(E).forEach(([le,ne])=>{se.append(le,ne)});try{const le=await gr.api.post(u.upload,se,{headers:{"Content-Type":"multipart/form-data"},onUploadProgress:Te=>{const ve=Math.round(Te.loaded*100/(Te.total??1));C(Se=>Se.map(_e=>_e.id===X.id?{..._e,progress:ve}:_e))}});return le?.data?.data??le?.data}catch(le){const ne=Zl(le);throw new Error(ne)}},[t,r,n,h,u.upload]),Ce=k.useCallback(async()=>{const X=I.filter(ve=>ve.status==="pending"||ve.status==="error");if(X.length===0)return[];const se=[],ie=new Map,le=[...X],ne=async()=>{for(;le.length>0&&P.currentSe.map(_e=>_e.id===ve.id?{..._e,status:"uploading",progress:0}:_e));try{const Se=await Me(ve);if(Se)se.push(Se),ie.set(String(ve.id),String(Se.hash)),L.current.set(Se.id,Se),C(_e=>_e.filter(Ue=>Ue.id!==ve.id)),_(_e=>[..._e,Se]),V(_e=>{if(_e.length===0)return _e;const Ue=String(ve.id);return _e.some(Ee=>String(Ee)===Ue)?_e.map(Ee=>String(Ee)===Ue?String(Se.hash):Ee):_e}),ve.preview&&URL.revokeObjectURL(ve.preview);else{const _e=Re("attachment.upload_response_invalid");C(Ue=>Ue.map(je=>je.id===ve.id?{...je,status:"error",error:_e}:je)),m?.(`[${ve.original_filename}] ${_e}`,ve.file)}}catch(Se){const _e=Se instanceof Error?Se.message:"업로드 실패";C(Ue=>Ue.map(je=>je.id===ve.id?{...je,status:"error",error:_e}:je)),m?.(`[${ve.original_filename}] ${_e}`,ve.file)}finally{P.current--}}},Te=Array(Math.min(s,X.length)).fill(null).map(()=>ne());if(await Promise.all(Te),se.length>0&&(p?.(se),u.reorder&&B.length>0&&x)){const ve=[...M,...se],Se=B.map(je=>ie.get(String(je))??je),_e=new Map(Se.map((je,Ee)=>[String(je),Ee])),Ue=[...ve].sort((je,Ee)=>{const he=_e.get(String(je.hash))??ve.length,Ne=_e.get(String(Ee.hash))??ve.length;return he-Ne}).map((je,Ee)=>({...je,sort_order:Ee,order:Ee+1}));x(Ue)}return se},[I,s,Me,p,m,B,M,x,u.reorder]);k.useEffect(()=>{if(!O)return;const X=gr.componentEvent.on(O,async()=>{const se=await Ce();return{uploadedAttachments:se,existingFiles:M,allFiles:[...M,...se]}});return()=>{X()}},[O,Ce,M]),k.useEffect(()=>{d&&I.some(X=>X.status==="pending")&&Ce()},[d,I,Ce]);const we=k.useCallback(async X=>{G(!0);try{if(X.id&&u.delete){const ie=u.delete.replace(":id",String(X.id));await gr.api.delete(ie)}const se=X.hash||X.id;X.id&&(D.current.add(X.id),L.current.delete(X.id)),X.hash&&D.current.add(X.hash),_(ie=>ie.filter(le=>(le.hash||le.id)!==se)),w?.(X.hash||X.id),S(!1),$(null)}catch{console.error("첨부파일 삭제 실패")}finally{G(!1)}},[w,u.delete]),$e=k.useCallback(async X=>{"hash"in X?y?($(X),S(!0)):await we(X):(X.preview&&URL.revokeObjectURL(X.preview),C(se=>se.filter(ie=>ie.id!==X.id)))},[y,we]),Le=k.useCallback(X=>{C(se=>se.map(ie=>ie.id===X.id?{...ie,status:"pending",error:void 0}:ie))},[]),K=k.useCallback(async X=>{const{arrayMove:se}=await Promise.resolve().then(()=>Wh),{active:ie,over:le}=X;if(!le||ie.id===le.id)return;const ne=[...M,...I];let Te;if(B.length===0)Te=ne;else{const he=new Map(B.map((Ne,Ve)=>[String(Ne),Ve]));Te=[...ne].sort((Ne,Ve)=>{const Fe="hash"in Ne?String(Ne.hash):String(Ne.id),Be="hash"in Ve?String(Ve.hash):String(Ve.id);return(he.get(Fe)??ne.length)-(he.get(Be)??ne.length)})}const ve=Te.findIndex(he=>"hash"in he?he.hash===ie.id:he.id===ie.id),Se=Te.findIndex(he=>"hash"in he?he.hash===le.id:he.id===le.id),_e=se(Te,ve,Se);V(_e.map(he=>"hash"in he?he.hash:he.id));const Ue=_e.filter(he=>"hash"in he),je=_e.filter(he=>!("hash"in he));Y.current=!0,_(Ue),C(je);const Ee=Ue.map((he,Ne)=>({...he,sort_order:Ne,order:Ne+1}));if(Ue.length>0&&u.reorder){const he=Ue.map((Ne,Ve)=>({id:Ne.id,order:Ve+1}));try{const Ne=await gr.api.patch(u.reorder,{order:he});gr.toast.success(Ne.message)}catch(Ne){const Ve=Ne instanceof Error?Ne.message:Re("attachment.reorder_failed");gr.toast.error(Ve)}}x?.(Ee)},[M,I,B,u.reorder,x]),re=k.useMemo(()=>[...M,...I].filter(X=>"is_image"in X?X.is_image:X.mime_type?.startsWith("image/")??!1),[M,I]),oe=k.useCallback(X=>{const se=re.findIndex(ie=>"hash"in X&&"hash"in ie?ie.hash===X.hash:"id"in X&&"id"in ie&&!("hash"in X)&&!("hash"in ie)?ie.id===X.id:!1);se!==-1&&(fe.current+=1,te(se),q(!0))},[re]);k.useEffect(()=>{let X=!1;return(async()=>{const ie=M.filter(ne=>ne.is_image),le=new Set(ie.map(ne=>ne.id));for(const[ne,Te]of me.current)le.has(ne)||(URL.revokeObjectURL(Te),me.current.delete(ne));for(const ne of ie){if(X)break;if(!me.current.has(ne.id))try{const Te=await gr.api.get(ne.download_url,{responseType:"blob"});if(!X&&Te){const ve=URL.createObjectURL(Te);me.current.set(ne.id,ve),ke(new Map(me.current))}}catch(Te){console.error("Failed to load authenticated image:",Te)}}})(),()=>{X=!0}},[M]),k.useEffect(()=>()=>{me.current.forEach(X=>URL.revokeObjectURL(X)),me.current.clear()},[]);const ae=k.useCallback(async X=>{const{executeImageDownload:se}=await Promise.resolve().then(()=>Al);await se({src:X.download_url,downloadUrl:X.download_url,filename:X.original_filename,downloadRequiresAuth:!0})},[]),be=k.useMemo(()=>{const X=[...M,...I];if(B.length===0)return X;const se=new Map(B.map((ie,le)=>[String(ie),le]));return[...X].sort((ie,le)=>{const ne="hash"in ie?String(ie.hash):String(ie.id),Te="hash"in le?String(le.hash):String(le.id),ve=se.get(ne)??X.length,Se=se.get(Te)??X.length;return ve-Se})},[M,I,B]),xe=be.length,He=xe>0,Pe=xeC([]),[]),Oe=k.useCallback(()=>I,[I]);return{existingFiles:M,pendingFiles:I,isDragOver:v,setIsDragOver:N,isDeleting:F,totalCount:xe,hasFiles:He,canAddMore:Pe,allItems:be,imageFiles:re,handleFiles:ye,handleRemove:$e,handleRetry:Le,handleUploadAll:Ce,handleOpenGallery:oe,handleDownload:ae,handleDragEnd:K,inputRef:A,galleryOpen:H,setGalleryOpen:q,galleryStartIndex:ue,galleryKeyRef:fe,confirmDialogOpen:U,setConfirmDialogOpen:S,itemToDelete:b,executeRemoveAttachment:we,authenticatedImageUrls:R,clear:Ke,getPendingFiles:Oe}}const Rl=({isDragOver:e,canAddMore:t,onFiles:r,setIsDragOver:n,inputRef:o,accept:a,maxFiles:s,maxSize:l,children:f})=>c.jsxs(W,{className:` relative border-2 border-dashed rounded-lg transition-colors ${e?"border-blue-500 bg-blue-50 dark:bg-blue-900/20":"border-gray-300 dark:border-gray-600"} `,onDragOver:h=>{h.preventDefault(),t&&n(!0)},onDragLeave:()=>n(!1),onDrop:h=>{h.preventDefault(),n(!1),t&&r(h.dataTransfer.files)},children:[c.jsx("input",{ref:o,type:"file",multiple:!0,accept:a,onChange:h=>h.target.files&&r(h.target.files),className:"hidden"}),!f&&c.jsxs(W,{className:"p-8 text-center cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors",onClick:()=>o.current?.click(),children:[c.jsx(Ct,{className:"fa-solid fa-cloud-arrow-up text-4xl text-gray-400 dark:text-gray-500 mb-4"}),c.jsx(Dt,{className:"text-sm text-gray-600 dark:text-gray-400",children:Re("attachment.drop_or_click")}),c.jsxs(Dt,{className:"text-xs text-gray-500 dark:text-gray-500 mt-2",children:[Re("attachment.upload_limit",{maxFiles:s,maxSize:l}),a&&` (${a})`]})]}),f]});function dg(){for(var e=arguments.length,t=new Array(e),r=0;rn=>{t.forEach(o=>o(n))},t)}const Un=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function Ar(e){const t=Object.prototype.toString.call(e);return t==="[object Window]"||t==="[object global]"}function aa(e){return"nodeType"in e}function yt(e){var t,r;return e?Ar(e)?e:aa(e)&&(t=(r=e.ownerDocument)==null?void 0:r.defaultView)!=null?t:window:window}function sa(e){const{Document:t}=yt(e);return e instanceof t}function Qr(e){return Ar(e)?!1:e instanceof yt(e).HTMLElement}function ei(e){return e instanceof yt(e).SVGElement}function Mr(e){return e?Ar(e)?e.document:aa(e)?sa(e)?e:Qr(e)||ei(e)?e.ownerDocument:document:document:document}const Yt=Un?k.useLayoutEffect:k.useEffect;function la(e){const t=k.useRef(e);return Yt(()=>{t.current=e}),k.useCallback(function(){for(var r=arguments.length,n=new Array(r),o=0;o{e.current=setInterval(n,o)},[]),r=k.useCallback(()=>{e.current!==null&&(clearInterval(e.current),e.current=null)},[]);return[t,r]}function Jr(e,t){t===void 0&&(t=[e]);const r=k.useRef(e);return Yt(()=>{r.current!==e&&(r.current=e)},t),r}function Rr(e,t){const r=k.useRef();return k.useMemo(()=>{const n=e(r.current);return r.current=n,n},[...t])}function zn(e){const t=la(e),r=k.useRef(null),n=k.useCallback(o=>{o!==r.current&&t?.(o,r.current),r.current=o},[]);return[r,n]}function ia(e){const t=k.useRef();return k.useEffect(()=>{t.current=e},[e]),t.current}let ca={};function en(e,t){return k.useMemo(()=>{if(t)return t;const r=ca[e]==null?0:ca[e]+1;return ca[e]=r,e+"-"+r},[e,t])}function ti(e){return function(t){for(var r=arguments.length,n=new Array(r>1?r-1:0),o=1;o{const l=Object.entries(s);for(const[f,h]of l){const d=a[f];d!=null&&(a[f]=d+e*h)}return a},{...t})}}const Or=ti(1),tn=ti(-1);function fg(e){return"clientX"in e&&"clientY"in e}function da(e){if(!e)return!1;const{KeyboardEvent:t}=yt(e.target);return t&&e instanceof t}function gg(e){if(!e)return!1;const{TouchEvent:t}=yt(e.target);return t&&e instanceof t}function ua(e){if(gg(e)){if(e.touches&&e.touches.length){const{clientX:t,clientY:r}=e.touches[0];return{x:t,y:r}}else if(e.changedTouches&&e.changedTouches.length){const{clientX:t,clientY:r}=e.changedTouches[0];return{x:t,y:r}}}return fg(e)?{x:e.clientX,y:e.clientY}:null}const rn=Object.freeze({Translate:{toString(e){if(!e)return;const{x:t,y:r}=e;return"translate3d("+(t?Math.round(t):0)+"px, "+(r?Math.round(r):0)+"px, 0)"}},Scale:{toString(e){if(!e)return;const{scaleX:t,scaleY:r}=e;return"scaleX("+t+") scaleY("+r+")"}},Transform:{toString(e){if(e)return[rn.Translate.toString(e),rn.Scale.toString(e)].join(" ")}},Transition:{toString(e){let{property:t,duration:r,easing:n}=e;return t+" "+r+"ms "+n}}}),ri="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function hg(e){return e.matches(ri)?e:e.querySelector(ri)}const pg={display:"none"};function mg(e){let{id:t,value:r}=e;return k.createElement("div",{id:t,style:pg},r)}function bg(e){let{id:t,announcement:r,ariaLiveType:n="assertive"}=e;const o={position:"fixed",top:0,left:0,width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0 0 0 0)",clipPath:"inset(100%)",whiteSpace:"nowrap"};return k.createElement("div",{id:t,style:o,role:"status","aria-live":n,"aria-atomic":!0},r)}function yg(){const[e,t]=k.useState("");return{announce:k.useCallback(n=>{n!=null&&t(n)},[]),announcement:e}}const ni=k.createContext(null);function vg(e){const t=k.useContext(ni);k.useEffect(()=>{if(!t)throw new Error("useDndMonitor must be used within a children of ");return t(e)},[e,t])}function wg(){const[e]=k.useState(()=>new Set),t=k.useCallback(n=>(e.add(n),()=>e.delete(n)),[e]);return[k.useCallback(n=>{let{type:o,event:a}=n;e.forEach(s=>{var l;return(l=s[o])==null?void 0:l.call(s,a)})},[e]),t]}const xg={draggable:` To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel. - `},kg={onDragStart(e){let{active:t}=e;return"Picked up draggable item "+t.id+"."},onDragOver(e){let{active:t,over:r}=e;return r?"Draggable item "+t.id+" was moved over droppable area "+r.id+".":"Draggable item "+t.id+" is no longer over a droppable area."},onDragEnd(e){let{active:t,over:r}=e;return r?"Draggable item "+t.id+" was dropped over droppable area "+r.id:"Draggable item "+t.id+" was dropped."},onDragCancel(e){let{active:t}=e;return"Dragging was cancelled. Draggable item "+t.id+" was dropped."}};function Cg(e){let{announcements:t=kg,container:r,hiddenTextDescribedById:n,screenReaderInstructions:o=xg}=e;const{announce:a,announcement:s}=yg(),l=en("DndLiveRegion"),[f,h]=k.useState(!1);if(k.useEffect(()=>{h(!0)},[]),vg(k.useMemo(()=>({onDragStart(i){let{active:u}=i;a(t.onDragStart({active:u}))},onDragMove(i){let{active:u,over:g}=i;t.onDragMove&&a(t.onDragMove({active:u,over:g}))},onDragOver(i){let{active:u,over:g}=i;a(t.onDragOver({active:u,over:g}))},onDragEnd(i){let{active:u,over:g}=i;a(t.onDragEnd({active:u,over:g}))},onDragCancel(i){let{active:u,over:g}=i;a(t.onDragCancel({active:u,over:g}))}}),[a,t])),!f)return null;const d=k.createElement(k.Fragment,null,k.createElement(mg,{id:n,value:o.draggable}),k.createElement(bg,{id:l,announcement:s}));return r?Jt.createPortal(d,r):d}var et;(function(e){e.DragStart="dragStart",e.DragMove="dragMove",e.DragEnd="dragEnd",e.DragCancel="dragCancel",e.DragOver="dragOver",e.RegisterDroppable="registerDroppable",e.SetDroppableDisabled="setDroppableDisabled",e.UnregisterDroppable="unregisterDroppable"})(et||(et={}));function Hn(){}function oi(e,t){return k.useMemo(()=>({sensor:e,options:t??{}}),[e,t])}function Sg(){for(var e=arguments.length,t=new Array(e),r=0;r[...t].filter(n=>n!=null),[...t])}const Gt=Object.freeze({x:0,y:0});function ai(e,t){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function si(e,t){let{data:{value:r}}=e,{data:{value:n}}=t;return r-n}function _g(e,t){let{data:{value:r}}=e,{data:{value:n}}=t;return n-r}function li(e){let{left:t,top:r,height:n,width:o}=e;return[{x:t,y:r},{x:t+o,y:r},{x:t,y:r+n},{x:t+o,y:r+n}]}function ii(e,t){if(!e||e.length===0)return null;const[r]=e;return r[t]}function ci(e,t,r){return t===void 0&&(t=e.left),r===void 0&&(r=e.top),{x:t+e.width*.5,y:r+e.height*.5}}const Eg=e=>{let{collisionRect:t,droppableRects:r,droppableContainers:n}=e;const o=ci(t,t.left,t.top),a=[];for(const s of n){const{id:l}=s,f=r.get(l);if(f){const h=ai(ci(f),o);a.push({id:l,data:{droppableContainer:s,value:h}})}}return a.sort(si)},Tg=e=>{let{collisionRect:t,droppableRects:r,droppableContainers:n}=e;const o=li(t),a=[];for(const s of n){const{id:l}=s,f=r.get(l);if(f){const h=li(f),d=o.reduce((u,g,p)=>u+ai(h[p],g),0),i=Number((d/4).toFixed(4));a.push({id:l,data:{droppableContainer:s,value:i}})}}return a.sort(si)};function Ng(e,t){const r=Math.max(t.top,e.top),n=Math.max(t.left,e.left),o=Math.min(t.left+t.width,e.left+e.width),a=Math.min(t.top+t.height,e.top+e.height),s=o-n,l=a-r;if(n{let{collisionRect:t,droppableRects:r,droppableContainers:n}=e;const o=[];for(const a of n){const{id:s}=a,l=r.get(s);if(l){const f=Ng(l,t);f>0&&o.push({id:s,data:{droppableContainer:a,value:f}})}}return o.sort(_g)};function Mg(e,t,r){return{...e,scaleX:t&&r?t.width/r.width:1,scaleY:t&&r?t.height/r.height:1}}function di(e,t){return e&&t?{x:e.left-t.left,y:e.top-t.top}:Gt}function Og(e){return function(r){for(var n=arguments.length,o=new Array(n>1?n-1:0),a=1;a({...s,top:s.top+e*l.y,bottom:s.bottom+e*l.y,left:s.left+e*l.x,right:s.right+e*l.x}),{...r})}}const Ig=Og(1);function Dg(e){if(e.startsWith("matrix3d(")){const t=e.slice(9,-1).split(/, /);return{x:+t[12],y:+t[13],scaleX:+t[0],scaleY:+t[5]}}else if(e.startsWith("matrix(")){const t=e.slice(7,-1).split(/, /);return{x:+t[4],y:+t[5],scaleX:+t[0],scaleY:+t[3]}}return null}function Lg(e,t,r){const n=Dg(t);if(!n)return e;const{scaleX:o,scaleY:a,x:s,y:l}=n,f=e.left-s-(1-o)*parseFloat(r),h=e.top-l-(1-a)*parseFloat(r.slice(r.indexOf(" ")+1)),d=o?e.width/o:e.width,i=a?e.height/a:e.height;return{width:d,height:i,top:h,right:f+d,bottom:h+i,left:f}}const Pg={ignoreTransform:!1};function Ir(e,t){t===void 0&&(t=Pg);let r=e.getBoundingClientRect();if(t.ignoreTransform){const{transform:h,transformOrigin:d}=yt(e).getComputedStyle(e);h&&(r=Lg(r,h,d))}const{top:n,left:o,width:a,height:s,bottom:l,right:f}=r;return{top:n,left:o,width:a,height:s,bottom:l,right:f}}function ui(e){return Ir(e,{ignoreTransform:!0})}function Fg(e){const t=e.innerWidth,r=e.innerHeight;return{top:0,left:0,right:t,bottom:r,width:t,height:r}}function $g(e,t){return t===void 0&&(t=yt(e).getComputedStyle(e)),t.position==="fixed"}function Ug(e,t){t===void 0&&(t=yt(e).getComputedStyle(e));const r=/(auto|scroll|overlay)/;return["overflow","overflowX","overflowY"].some(o=>{const a=t[o];return typeof a=="string"?r.test(a):!1})}function Gn(e,t){const r=[];function n(o){if(t!=null&&r.length>=t||!o)return r;if(sa(o)&&o.scrollingElement!=null&&!r.includes(o.scrollingElement))return r.push(o.scrollingElement),r;if(!Qr(o)||ei(o)||r.includes(o))return r;const a=yt(e).getComputedStyle(o);return o!==e&&Ug(o,a)&&r.push(o),$g(o,a)?r:n(o.parentNode)}return e?n(e):r}function fi(e){const[t]=Gn(e,1);return t??null}function fa(e){return!Un||!e?null:Ar(e)?e:aa(e)?sa(e)||e===Mr(e).scrollingElement?window:Qr(e)?e:null:null}function gi(e){return Ar(e)?e.scrollX:e.scrollLeft}function hi(e){return Ar(e)?e.scrollY:e.scrollTop}function ga(e){return{x:gi(e),y:hi(e)}}var ot;(function(e){e[e.Forward=1]="Forward",e[e.Backward=-1]="Backward"})(ot||(ot={}));function pi(e){return!Un||!e?!1:e===document.scrollingElement}function mi(e){const t={x:0,y:0},r=pi(e)?{height:window.innerHeight,width:window.innerWidth}:{height:e.clientHeight,width:e.clientWidth},n={x:e.scrollWidth-r.width,y:e.scrollHeight-r.height},o=e.scrollTop<=t.y,a=e.scrollLeft<=t.x,s=e.scrollTop>=n.y,l=e.scrollLeft>=n.x;return{isTop:o,isLeft:a,isBottom:s,isRight:l,maxScroll:n,minScroll:t}}const zg={x:.2,y:.2};function Hg(e,t,r,n,o){let{top:a,left:s,right:l,bottom:f}=r;n===void 0&&(n=10),o===void 0&&(o=zg);const{isTop:h,isBottom:d,isLeft:i,isRight:u}=mi(e),g={x:0,y:0},p={x:0,y:0},m={height:t.height*o.y,width:t.width*o.x};return!h&&a<=t.top+m.height?(g.y=ot.Backward,p.y=n*Math.abs((t.top+m.height-a)/m.height)):!d&&f>=t.bottom-m.height&&(g.y=ot.Forward,p.y=n*Math.abs((t.bottom-m.height-f)/m.height)),!u&&l>=t.right-m.width?(g.x=ot.Forward,p.x=n*Math.abs((t.right-m.width-l)/m.width)):!i&&s<=t.left+m.width&&(g.x=ot.Backward,p.x=n*Math.abs((t.left+m.width-s)/m.width)),{direction:g,speed:p}}function Gg(e){if(e===document.scrollingElement){const{innerWidth:a,innerHeight:s}=window;return{top:0,left:0,right:a,bottom:s,width:a,height:s}}const{top:t,left:r,right:n,bottom:o}=e.getBoundingClientRect();return{top:t,left:r,right:n,bottom:o,width:e.clientWidth,height:e.clientHeight}}function bi(e){return e.reduce((t,r)=>Or(t,ga(r)),Gt)}function jg(e){return e.reduce((t,r)=>t+gi(r),0)}function Bg(e){return e.reduce((t,r)=>t+hi(r),0)}function Wg(e,t){if(t===void 0&&(t=Ir),!e)return;const{top:r,left:n,bottom:o,right:a}=t(e);fi(e)&&(o<=0||a<=0||r>=window.innerHeight||n>=window.innerWidth)&&e.scrollIntoView({block:"center",inline:"center"})}const Kg=[["x",["left","right"],jg],["y",["top","bottom"],Bg]];class ha{constructor(t,r){this.rect=void 0,this.width=void 0,this.height=void 0,this.top=void 0,this.bottom=void 0,this.right=void 0,this.left=void 0;const n=Gn(r),o=bi(n);this.rect={...t},this.width=t.width,this.height=t.height;for(const[a,s,l]of Kg)for(const f of s)Object.defineProperty(this,f,{get:()=>{const h=l(n),d=o[a]-h;return this.rect[f]+d},enumerable:!0});Object.defineProperty(this,"rect",{enumerable:!1})}}class nn{constructor(t){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(r=>{var n;return(n=this.target)==null?void 0:n.removeEventListener(...r)})},this.target=t}add(t,r,n){var o;(o=this.target)==null||o.addEventListener(t,r,n),this.listeners.push([t,r,n])}}function Vg(e){const{EventTarget:t}=yt(e);return e instanceof t?e:Mr(e)}function pa(e,t){const r=Math.abs(e.x),n=Math.abs(e.y);return typeof t=="number"?Math.sqrt(r**2+n**2)>t:"x"in t&&"y"in t?r>t.x&&n>t.y:"x"in t?r>t.x:"y"in t?n>t.y:!1}var It;(function(e){e.Click="click",e.DragStart="dragstart",e.Keydown="keydown",e.ContextMenu="contextmenu",e.Resize="resize",e.SelectionChange="selectionchange",e.VisibilityChange="visibilitychange"})(It||(It={}));function yi(e){e.preventDefault()}function Yg(e){e.stopPropagation()}var ze;(function(e){e.Space="Space",e.Down="ArrowDown",e.Right="ArrowRight",e.Left="ArrowLeft",e.Up="ArrowUp",e.Esc="Escape",e.Enter="Enter",e.Tab="Tab"})(ze||(ze={}));const vi={start:[ze.Space,ze.Enter],cancel:[ze.Esc],end:[ze.Space,ze.Enter,ze.Tab]},Xg=(e,t)=>{let{currentCoordinates:r}=t;switch(e.code){case ze.Right:return{...r,x:r.x+25};case ze.Left:return{...r,x:r.x-25};case ze.Down:return{...r,y:r.y+25};case ze.Up:return{...r,y:r.y-25}}};class ma{constructor(t){this.props=void 0,this.autoScrollEnabled=!1,this.referenceCoordinates=void 0,this.listeners=void 0,this.windowListeners=void 0,this.props=t;const{event:{target:r}}=t;this.props=t,this.listeners=new nn(Mr(r)),this.windowListeners=new nn(yt(r)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(It.Resize,this.handleCancel),this.windowListeners.add(It.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(It.Keydown,this.handleKeyDown))}handleStart(){const{activeNode:t,onStart:r}=this.props,n=t.node.current;n&&Wg(n),r(Gt)}handleKeyDown(t){if(da(t)){const{active:r,context:n,options:o}=this.props,{keyboardCodes:a=vi,coordinateGetter:s=Xg,scrollBehavior:l="smooth"}=o,{code:f}=t;if(a.end.includes(f)){this.handleEnd(t);return}if(a.cancel.includes(f)){this.handleCancel(t);return}const{collisionRect:h}=n.current,d=h?{x:h.left,y:h.top}:Gt;this.referenceCoordinates||(this.referenceCoordinates=d);const i=s(t,{active:r,context:n.current,currentCoordinates:d});if(i){const u=tn(i,d),g={x:0,y:0},{scrollableAncestors:p}=n.current;for(const m of p){const w=t.code,{isTop:x,isRight:A,isLeft:v,isBottom:E,maxScroll:O,minScroll:_}=mi(m),I=Gg(m),C={x:Math.min(w===ze.Right?I.right-I.width/2:I.right,Math.max(w===ze.Right?I.left:I.left+I.width/2,i.x)),y:Math.min(w===ze.Down?I.bottom-I.height/2:I.bottom,Math.max(w===ze.Down?I.top:I.top+I.height/2,i.y))},y=w===ze.Right&&!A||w===ze.Left&&!v,N=w===ze.Down&&!E||w===ze.Up&&!x;if(y&&C.x!==i.x){const M=m.scrollLeft+u.x,P=w===ze.Right&&M<=O.x||w===ze.Left&&M>=_.x;if(P&&!u.y){m.scrollTo({left:M,behavior:l});return}P?g.x=m.scrollLeft-M:g.x=w===ze.Right?m.scrollLeft-O.x:m.scrollLeft-_.x,g.x&&m.scrollBy({left:-g.x,behavior:l});break}else if(N&&C.y!==i.y){const M=m.scrollTop+u.y,P=w===ze.Down&&M<=O.y||w===ze.Up&&M>=_.y;if(P&&!u.x){m.scrollTo({top:M,behavior:l});return}P?g.y=m.scrollTop-M:g.y=w===ze.Down?m.scrollTop-O.y:m.scrollTop-_.y,g.y&&m.scrollBy({top:-g.y,behavior:l});break}}this.handleMove(t,Or(tn(i,this.referenceCoordinates),g))}}}handleMove(t,r){const{onMove:n}=this.props;t.preventDefault(),n(r)}handleEnd(t){const{onEnd:r}=this.props;t.preventDefault(),this.detach(),r()}handleCancel(t){const{onCancel:r}=this.props;t.preventDefault(),this.detach(),r()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}}ma.activators=[{eventName:"onKeyDown",handler:(e,t,r)=>{let{keyboardCodes:n=vi,onActivation:o}=t,{active:a}=r;const{code:s}=e.nativeEvent;if(n.start.includes(s)){const l=a.activatorNode.current;return l&&e.target!==l?!1:(e.preventDefault(),o?.({event:e.nativeEvent}),!0)}return!1}}];function wi(e){return!!(e&&"distance"in e)}function xi(e){return!!(e&&"delay"in e)}class ba{constructor(t,r,n){var o;n===void 0&&(n=Vg(t.event.target)),this.props=void 0,this.events=void 0,this.autoScrollEnabled=!0,this.document=void 0,this.activated=!1,this.initialCoordinates=void 0,this.timeoutId=null,this.listeners=void 0,this.documentListeners=void 0,this.windowListeners=void 0,this.props=t,this.events=r;const{event:a}=t,{target:s}=a;this.props=t,this.events=r,this.document=Mr(s),this.documentListeners=new nn(this.document),this.listeners=new nn(n),this.windowListeners=new nn(yt(s)),this.initialCoordinates=(o=ua(a))!=null?o:Gt,this.handleStart=this.handleStart.bind(this),this.handleMove=this.handleMove.bind(this),this.handleEnd=this.handleEnd.bind(this),this.handleCancel=this.handleCancel.bind(this),this.handleKeydown=this.handleKeydown.bind(this),this.removeTextSelection=this.removeTextSelection.bind(this),this.attach()}attach(){const{events:t,props:{options:{activationConstraint:r,bypassActivationConstraint:n}}}=this;if(this.listeners.add(t.move.name,this.handleMove,{passive:!1}),this.listeners.add(t.end.name,this.handleEnd),t.cancel&&this.listeners.add(t.cancel.name,this.handleCancel),this.windowListeners.add(It.Resize,this.handleCancel),this.windowListeners.add(It.DragStart,yi),this.windowListeners.add(It.VisibilityChange,this.handleCancel),this.windowListeners.add(It.ContextMenu,yi),this.documentListeners.add(It.Keydown,this.handleKeydown),r){if(n!=null&&n({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(xi(r)){this.timeoutId=setTimeout(this.handleStart,r.delay),this.handlePending(r);return}if(wi(r)){this.handlePending(r);return}}this.handleStart()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll(),setTimeout(this.documentListeners.removeAll,50),this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}handlePending(t,r){const{active:n,onPending:o}=this.props;o(n,t,this.initialCoordinates,r)}handleStart(){const{initialCoordinates:t}=this,{onStart:r}=this.props;t&&(this.activated=!0,this.documentListeners.add(It.Click,Yg,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(It.SelectionChange,this.removeTextSelection),r(t))}handleMove(t){var r;const{activated:n,initialCoordinates:o,props:a}=this,{onMove:s,options:{activationConstraint:l}}=a;if(!o)return;const f=(r=ua(t))!=null?r:Gt,h=tn(o,f);if(!n&&l){if(wi(l)){if(l.tolerance!=null&&pa(h,l.tolerance))return this.handleCancel();if(pa(h,l.distance))return this.handleStart()}if(xi(l)&&pa(h,l.tolerance))return this.handleCancel();this.handlePending(l,h);return}t.cancelable&&t.preventDefault(),s(f)}handleEnd(){const{onAbort:t,onEnd:r}=this.props;this.detach(),this.activated||t(this.props.active),r()}handleCancel(){const{onAbort:t,onCancel:r}=this.props;this.detach(),this.activated||t(this.props.active),r()}handleKeydown(t){t.code===ze.Esc&&this.handleCancel()}removeTextSelection(){var t;(t=this.document.getSelection())==null||t.removeAllRanges()}}const Zg={cancel:{name:"pointercancel"},move:{name:"pointermove"},end:{name:"pointerup"}};class ya extends ba{constructor(t){const{event:r}=t,n=Mr(r.target);super(t,Zg,n)}}ya.activators=[{eventName:"onPointerDown",handler:(e,t)=>{let{nativeEvent:r}=e,{onActivation:n}=t;return!r.isPrimary||r.button!==0?!1:(n?.({event:r}),!0)}}];const qg={move:{name:"mousemove"},end:{name:"mouseup"}};var va;(function(e){e[e.RightClick=2]="RightClick"})(va||(va={}));class Qg extends ba{constructor(t){super(t,qg,Mr(t.event.target))}}Qg.activators=[{eventName:"onMouseDown",handler:(e,t)=>{let{nativeEvent:r}=e,{onActivation:n}=t;return r.button===va.RightClick?!1:(n?.({event:r}),!0)}}];const wa={cancel:{name:"touchcancel"},move:{name:"touchmove"},end:{name:"touchend"}};class Jg extends ba{constructor(t){super(t,wa)}static setup(){return window.addEventListener(wa.move.name,t,{capture:!1,passive:!1}),function(){window.removeEventListener(wa.move.name,t)};function t(){}}}Jg.activators=[{eventName:"onTouchStart",handler:(e,t)=>{let{nativeEvent:r}=e,{onActivation:n}=t;const{touches:o}=r;return o.length>1?!1:(n?.({event:r}),!0)}}];var on;(function(e){e[e.Pointer=0]="Pointer",e[e.DraggableRect=1]="DraggableRect"})(on||(on={}));var jn;(function(e){e[e.TreeOrder=0]="TreeOrder",e[e.ReversedTreeOrder=1]="ReversedTreeOrder"})(jn||(jn={}));function Rg(e){let{acceleration:t,activator:r=on.Pointer,canScroll:n,draggingRect:o,enabled:a,interval:s=5,order:l=jn.TreeOrder,pointerCoordinates:f,scrollableAncestors:h,scrollableAncestorRects:d,delta:i,threshold:u}=e;const g=th({delta:i,disabled:!a}),[p,m]=ug(),w=k.useRef({x:0,y:0}),x=k.useRef({x:0,y:0}),A=k.useMemo(()=>{switch(r){case on.Pointer:return f?{top:f.y,bottom:f.y,left:f.x,right:f.x}:null;case on.DraggableRect:return o}},[r,o,f]),v=k.useRef(null),E=k.useCallback(()=>{const _=v.current;if(!_)return;const I=w.current.x*x.current.x,C=w.current.y*x.current.y;_.scrollBy(I,C)},[]),O=k.useMemo(()=>l===jn.TreeOrder?[...h].reverse():h,[l,h]);k.useEffect(()=>{if(!a||!h.length||!A){m();return}for(const _ of O){if(n?.(_)===!1)continue;const I=h.indexOf(_),C=d[I];if(!C)continue;const{direction:y,speed:N}=Hg(_,C,A,t,u);for(const M of["x","y"])g[M][y[M]]||(N[M]=0,y[M]=0);if(N.x>0||N.y>0){m(),v.current=_,p(E,s),w.current=N,x.current=y;return}}w.current={x:0,y:0},x.current={x:0,y:0},m()},[t,E,n,m,a,s,JSON.stringify(A),JSON.stringify(g),p,h,O,d,JSON.stringify(u)])}const eh={x:{[ot.Backward]:!1,[ot.Forward]:!1},y:{[ot.Backward]:!1,[ot.Forward]:!1}};function th(e){let{delta:t,disabled:r}=e;const n=ia(t);return Rr(o=>{if(r||!n||!o)return eh;const a={x:Math.sign(t.x-n.x),y:Math.sign(t.y-n.y)};return{x:{[ot.Backward]:o.x[ot.Backward]||a.x===-1,[ot.Forward]:o.x[ot.Forward]||a.x===1},y:{[ot.Backward]:o.y[ot.Backward]||a.y===-1,[ot.Forward]:o.y[ot.Forward]||a.y===1}}},[r,t,n])}function rh(e,t){const r=t!=null?e.get(t):void 0,n=r?r.node.current:null;return Rr(o=>{var a;return t==null?null:(a=n??o)!=null?a:null},[n,t])}function nh(e,t){return k.useMemo(()=>e.reduce((r,n)=>{const{sensor:o}=n,a=o.activators.map(s=>({eventName:s.eventName,handler:t(s.handler,n)}));return[...r,...a]},[]),[e,t])}var an;(function(e){e[e.Always=0]="Always",e[e.BeforeDragging=1]="BeforeDragging",e[e.WhileDragging=2]="WhileDragging"})(an||(an={}));var xa;(function(e){e.Optimized="optimized"})(xa||(xa={}));const ki=new Map;function oh(e,t){let{dragging:r,dependencies:n,config:o}=t;const[a,s]=k.useState(null),{frequency:l,measure:f,strategy:h}=o,d=k.useRef(e),i=w(),u=Jr(i),g=k.useCallback(function(x){x===void 0&&(x=[]),!u.current&&s(A=>A===null?x:A.concat(x.filter(v=>!A.includes(v))))},[u]),p=k.useRef(null),m=Rr(x=>{if(i&&!r)return ki;if(!x||x===ki||d.current!==e||a!=null){const A=new Map;for(let v of e){if(!v)continue;if(a&&a.length>0&&!a.includes(v.id)&&v.rect.current){A.set(v.id,v.rect.current);continue}const E=v.node.current,O=E?new ha(f(E),E):null;v.rect.current=O,O&&A.set(v.id,O)}return A}return x},[e,a,r,i,f]);return k.useEffect(()=>{d.current=e},[e]),k.useEffect(()=>{i||g()},[r,i]),k.useEffect(()=>{a&&a.length>0&&s(null)},[JSON.stringify(a)]),k.useEffect(()=>{i||typeof l!="number"||p.current!==null||(p.current=setTimeout(()=>{g(),p.current=null},l))},[l,i,g,...n]),{droppableRects:m,measureDroppableContainers:g,measuringScheduled:a!=null};function w(){switch(h){case an.Always:return!1;case an.BeforeDragging:return r;default:return!r}}}function Ci(e,t){return Rr(r=>e?r||(typeof t=="function"?t(e):e):null,[t,e])}function ah(e,t){return Ci(e,t)}function sh(e){let{callback:t,disabled:r}=e;const n=la(t),o=k.useMemo(()=>{if(r||typeof window>"u"||typeof window.MutationObserver>"u")return;const{MutationObserver:a}=window;return new a(n)},[n,r]);return k.useEffect(()=>()=>o?.disconnect(),[o]),o}function Bn(e){let{callback:t,disabled:r}=e;const n=la(t),o=k.useMemo(()=>{if(r||typeof window>"u"||typeof window.ResizeObserver>"u")return;const{ResizeObserver:a}=window;return new a(n)},[r]);return k.useEffect(()=>()=>o?.disconnect(),[o]),o}function lh(e){return new ha(Ir(e),e)}function Si(e,t,r){t===void 0&&(t=lh);const[n,o]=k.useState(null);function a(){o(f=>{if(!e)return null;if(e.isConnected===!1){var h;return(h=f??r)!=null?h:null}const d=t(e);return JSON.stringify(f)===JSON.stringify(d)?f:d})}const s=sh({callback(f){if(e)for(const h of f){const{type:d,target:i}=h;if(d==="childList"&&i instanceof HTMLElement&&i.contains(e)){a();break}}}}),l=Bn({callback:a});return Yt(()=>{a(),e?(l?.observe(e),s?.observe(document.body,{childList:!0,subtree:!0})):(l?.disconnect(),s?.disconnect())},[e]),n}function ih(e){const t=Ci(e);return di(e,t)}const _i=[];function ch(e){const t=k.useRef(e),r=Rr(n=>e?n&&n!==_i&&e&&t.current&&e.parentNode===t.current.parentNode?n:Gn(e):_i,[e]);return k.useEffect(()=>{t.current=e},[e]),r}function dh(e){const[t,r]=k.useState(null),n=k.useRef(e),o=k.useCallback(a=>{const s=fa(a.target);s&&r(l=>l?(l.set(s,ga(s)),new Map(l)):null)},[]);return k.useEffect(()=>{const a=n.current;if(e!==a){s(a);const l=e.map(f=>{const h=fa(f);return h?(h.addEventListener("scroll",o,{passive:!0}),[h,ga(h)]):null}).filter(f=>f!=null);r(l.length?new Map(l):null),n.current=e}return()=>{s(e),s(a)};function s(l){l.forEach(f=>{const h=fa(f);h?.removeEventListener("scroll",o)})}},[o,e]),k.useMemo(()=>e.length?t?Array.from(t.values()).reduce((a,s)=>Or(a,s),Gt):bi(e):Gt,[e,t])}function Ei(e,t){t===void 0&&(t=[]);const r=k.useRef(null);return k.useEffect(()=>{r.current=null},t),k.useEffect(()=>{const n=e!==Gt;n&&!r.current&&(r.current=e),!n&&r.current&&(r.current=null)},[e]),r.current?tn(e,r.current):Gt}function uh(e){k.useEffect(()=>{if(!Un)return;const t=e.map(r=>{let{sensor:n}=r;return n.setup==null?void 0:n.setup()});return()=>{for(const r of t)r?.()}},e.map(t=>{let{sensor:r}=t;return r}))}function fh(e,t){return k.useMemo(()=>e.reduce((r,n)=>{let{eventName:o,handler:a}=n;return r[o]=s=>{a(s,t)},r},{}),[e,t])}function Ti(e){return k.useMemo(()=>e?Fg(e):null,[e])}const Ni=[];function gh(e,t){t===void 0&&(t=Ir);const[r]=e,n=Ti(r?yt(r):null),[o,a]=k.useState(Ni);function s(){a(()=>e.length?e.map(f=>pi(f)?n:new ha(t(f),f)):Ni)}const l=Bn({callback:s});return Yt(()=>{l?.disconnect(),s(),e.forEach(f=>l?.observe(f))},[e]),o}function hh(e){if(!e)return null;if(e.children.length>1)return e;const t=e.children[0];return Qr(t)?t:e}function ph(e){let{measure:t}=e;const[r,n]=k.useState(null),o=k.useCallback(h=>{for(const{target:d}of h)if(Qr(d)){n(i=>{const u=t(d);return i?{...i,width:u.width,height:u.height}:u});break}},[t]),a=Bn({callback:o}),s=k.useCallback(h=>{const d=hh(h);a?.disconnect(),d&&a?.observe(d),n(d?t(d):null)},[t,a]),[l,f]=zn(s);return k.useMemo(()=>({nodeRef:l,rect:r,setRef:f}),[r,l,f])}const mh=[{sensor:ya,options:{}},{sensor:ma,options:{}}],bh={current:{}},Wn={draggable:{measure:ui},droppable:{measure:ui,strategy:an.WhileDragging,frequency:xa.Optimized},dragOverlay:{measure:Ir}};class sn extends Map{get(t){var r;return t!=null&&(r=super.get(t))!=null?r:void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(t=>{let{disabled:r}=t;return!r})}getNodeFor(t){var r,n;return(r=(n=this.get(t))==null?void 0:n.node.current)!=null?r:void 0}}const yh={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new sn,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:Hn},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:Wn,measureDroppableContainers:Hn,windowRect:null,measuringScheduled:!1},vh={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:""},dispatch:Hn,draggableNodes:new Map,over:null,measureDroppableContainers:Hn},Kn=k.createContext(vh),Ai=k.createContext(yh);function wh(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new sn}}}function xh(e,t){switch(t.type){case et.DragStart:return{...e,draggable:{...e.draggable,initialCoordinates:t.initialCoordinates,active:t.active}};case et.DragMove:return e.draggable.active==null?e:{...e,draggable:{...e.draggable,translate:{x:t.coordinates.x-e.draggable.initialCoordinates.x,y:t.coordinates.y-e.draggable.initialCoordinates.y}}};case et.DragEnd:case et.DragCancel:return{...e,draggable:{...e.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case et.RegisterDroppable:{const{element:r}=t,{id:n}=r,o=new sn(e.droppable.containers);return o.set(n,r),{...e,droppable:{...e.droppable,containers:o}}}case et.SetDroppableDisabled:{const{id:r,key:n,disabled:o}=t,a=e.droppable.containers.get(r);if(!a||n!==a.key)return e;const s=new sn(e.droppable.containers);return s.set(r,{...a,disabled:o}),{...e,droppable:{...e.droppable,containers:s}}}case et.UnregisterDroppable:{const{id:r,key:n}=t,o=e.droppable.containers.get(r);if(!o||n!==o.key)return e;const a=new sn(e.droppable.containers);return a.delete(r),{...e,droppable:{...e.droppable,containers:a}}}default:return e}}function kh(e){let{disabled:t}=e;const{active:r,activatorEvent:n,draggableNodes:o}=k.useContext(Kn),a=ia(n),s=ia(r?.id);return k.useEffect(()=>{if(!t&&!n&&a&&s!=null){if(!da(a)||document.activeElement===a.target)return;const l=o.get(s);if(!l)return;const{activatorNode:f,node:h}=l;if(!f.current&&!h.current)return;requestAnimationFrame(()=>{for(const d of[f.current,h.current]){if(!d)continue;const i=hg(d);if(i){i.focus();break}}})}},[n,t,o,s,a]),null}function Ch(e,t){let{transform:r,...n}=t;return e!=null&&e.length?e.reduce((o,a)=>a({transform:o,...n}),r):r}function Sh(e){return k.useMemo(()=>({draggable:{...Wn.draggable,...e?.draggable},droppable:{...Wn.droppable,...e?.droppable},dragOverlay:{...Wn.dragOverlay,...e?.dragOverlay}}),[e?.draggable,e?.droppable,e?.dragOverlay])}function _h(e){let{activeNode:t,measure:r,initialRect:n,config:o=!0}=e;const a=k.useRef(!1),{x:s,y:l}=typeof o=="boolean"?{x:o,y:o}:o;Yt(()=>{if(!s&&!l||!t){a.current=!1;return}if(a.current||!n)return;const h=t?.node.current;if(!h||h.isConnected===!1)return;const d=r(h),i=di(d,n);if(s||(i.x=0),l||(i.y=0),a.current=!0,Math.abs(i.x)>0||Math.abs(i.y)>0){const u=fi(h);u&&u.scrollBy({top:i.y,left:i.x})}},[t,s,l,n,r])}const Mi=k.createContext({...Gt,scaleX:1,scaleY:1});var tr;(function(e){e[e.Uninitialized=0]="Uninitialized",e[e.Initializing=1]="Initializing",e[e.Initialized=2]="Initialized"})(tr||(tr={}));const Eh=k.memo(function(t){var r,n,o,a;let{id:s,accessibility:l,autoScroll:f=!0,children:h,sensors:d=mh,collisionDetection:i=Ag,measuring:u,modifiers:g,...p}=t;const m=k.useReducer(xh,void 0,wh),[w,x]=m,[A,v]=wg(),[E,O]=k.useState(tr.Uninitialized),_=E===tr.Initialized,{draggable:{active:I,nodes:C,translate:y},droppable:{containers:N}}=w,M=I!=null?C.get(I):null,P=k.useRef({initial:null,translated:null}),D=k.useMemo(()=>{var Ee;return I!=null?{id:I,data:(Ee=M?.data)!=null?Ee:bh,rect:P}:null},[I,M]),L=k.useRef(null),[U,S]=k.useState(null),[b,$]=k.useState(null),F=Jr(p,Object.values(p)),G=en("DndDescribedBy",s),Y=k.useMemo(()=>N.getEnabled(),[N]),B=Sh(u),{droppableRects:V,measureDroppableContainers:j,measuringScheduled:H}=oh(Y,{dragging:_,dependencies:[y.x,y.y],config:B.droppable}),Z=rh(C,I),ue=k.useMemo(()=>b?ua(b):null,[b]),te=je(),fe=ah(Z,B.draggable.measure);_h({activeNode:I!=null?C.get(I):null,config:te.layoutShiftCompensation,initialRect:fe,measure:B.draggable.measure});const R=Si(Z,B.draggable.measure,fe),ke=Si(Z?Z.parentElement:null),me=k.useRef({activatorEvent:null,active:null,activeNode:Z,collisionRect:null,collisions:null,droppableRects:V,draggableNodes:C,draggingNode:null,draggingNodeRect:null,droppableContainers:N,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),Ge=N.getNodeFor((r=me.current.over)==null?void 0:r.id),De=ph({measure:B.dragOverlay.measure}),ye=(n=De.nodeRef.current)!=null?n:Z,Me=_?(o=De.rect)!=null?o:R:null,Ce=!!(De.nodeRef.current&&De.rect),we=ih(Ce?null:R),$e=Ti(ye?yt(ye):null),Le=ch(_?Ge??Z:null),K=gh(Le),re=Ch(g,{transform:{x:y.x-we.x,y:y.y-we.y,scaleX:1,scaleY:1},activatorEvent:b,active:D,activeNodeRect:R,containerNodeRect:ke,draggingNodeRect:Me,over:me.current.over,overlayNodeRect:De.rect,scrollableAncestors:Le,scrollableAncestorRects:K,windowRect:$e}),oe=ue?Or(ue,y):null,ae=dh(Le),be=Ei(ae),xe=Ei(ae,[R]),He=Or(re,be),Pe=Me?Ig(Me,re):null,Ke=D&&Pe?i({active:D,collisionRect:Pe,droppableRects:V,droppableContainers:Y,pointerCoordinates:oe}):null,Oe=ii(Ke,"id"),[X,se]=k.useState(null),ie=Ce?re:Or(re,xe),le=Mg(ie,(a=X?.rect)!=null?a:null,R),ne=k.useRef(null),Te=k.useCallback((Ee,he)=>{let{sensor:Ne,options:Ve}=he;if(L.current==null)return;const Fe=C.get(L.current);if(!Fe)return;const Be=Ee.nativeEvent,qe=new Ne({active:L.current,activeNode:Fe,event:Be,options:Ve,context:me,onAbort(Ze){if(!C.get(Ze))return;const{onDragAbort:_t}=F.current,Bt={id:Ze};_t?.(Bt),A({type:"onDragAbort",event:Bt})},onPending(Ze,jt,_t,Bt){if(!C.get(Ze))return;const{onDragPending:Et}=F.current,Wt={id:Ze,constraint:jt,initialCoordinates:_t,offset:Bt};Et?.(Wt),A({type:"onDragPending",event:Wt})},onStart(Ze){const jt=L.current;if(jt==null)return;const _t=C.get(jt);if(!_t)return;const{onDragStart:Bt}=F.current,dt={activatorEvent:Be,active:{id:jt,data:_t.data,rect:P}};Jt.unstable_batchedUpdates(()=>{Bt?.(dt),O(tr.Initializing),x({type:et.DragStart,initialCoordinates:Ze,active:jt}),A({type:"onDragStart",event:dt}),S(ne.current),$(Be)})},onMove(Ze){x({type:et.DragMove,coordinates:Ze})},onEnd:Zt(et.DragEnd),onCancel:Zt(et.DragCancel)});ne.current=qe;function Zt(Ze){return async function(){const{active:_t,collisions:Bt,over:dt,scrollAdjustedTranslate:Et}=me.current;let Wt=null;if(_t&&Et){const{cancelDrop:nr}=F.current;Wt={activatorEvent:Be,active:_t,collisions:Bt,delta:Et,over:dt},Ze===et.DragEnd&&typeof nr=="function"&&await Promise.resolve(nr(Wt))&&(Ze=et.DragCancel)}L.current=null,Jt.unstable_batchedUpdates(()=>{x({type:Ze}),O(tr.Uninitialized),se(null),S(null),$(null),ne.current=null;const nr=Ze===et.DragEnd?"onDragEnd":"onDragCancel";if(Wt){const mr=F.current[nr];mr?.(Wt),A({type:nr,event:Wt})}})}}},[C]),ve=k.useCallback((Ee,he)=>(Ne,Ve)=>{const Fe=Ne.nativeEvent,Be=C.get(Ve);if(L.current!==null||!Be||Fe.dndKit||Fe.defaultPrevented)return;const qe={active:Be};Ee(Ne,he.options,qe)===!0&&(Fe.dndKit={capturedBy:he.sensor},L.current=Ve,Te(Ne,he))},[C,Te]),Se=nh(d,ve);uh(d),Yt(()=>{R&&E===tr.Initializing&&O(tr.Initialized)},[R,E]),k.useEffect(()=>{const{onDragMove:Ee}=F.current,{active:he,activatorEvent:Ne,collisions:Ve,over:Fe}=me.current;if(!he||!Ne)return;const Be={active:he,activatorEvent:Ne,collisions:Ve,delta:{x:He.x,y:He.y},over:Fe};Jt.unstable_batchedUpdates(()=>{Ee?.(Be),A({type:"onDragMove",event:Be})})},[He.x,He.y]),k.useEffect(()=>{const{active:Ee,activatorEvent:he,collisions:Ne,droppableContainers:Ve,scrollAdjustedTranslate:Fe}=me.current;if(!Ee||L.current==null||!he||!Fe)return;const{onDragOver:Be}=F.current,qe=Ve.get(Oe),Zt=qe&&qe.rect.current?{id:qe.id,rect:qe.rect.current,data:qe.data,disabled:qe.disabled}:null,Ze={active:Ee,activatorEvent:he,collisions:Ne,delta:{x:Fe.x,y:Fe.y},over:Zt};Jt.unstable_batchedUpdates(()=>{se(Zt),Be?.(Ze),A({type:"onDragOver",event:Ze})})},[Oe]),Yt(()=>{me.current={activatorEvent:b,active:D,activeNode:Z,collisionRect:Pe,collisions:Ke,droppableRects:V,draggableNodes:C,draggingNode:ye,draggingNodeRect:Me,droppableContainers:N,over:X,scrollableAncestors:Le,scrollAdjustedTranslate:He},P.current={initial:Me,translated:Pe}},[D,Z,Ke,Pe,C,ye,Me,V,N,X,Le,He]),Rg({...te,delta:y,draggingRect:Pe,pointerCoordinates:oe,scrollableAncestors:Le,scrollableAncestorRects:K});const _e=k.useMemo(()=>({active:D,activeNode:Z,activeNodeRect:R,activatorEvent:b,collisions:Ke,containerNodeRect:ke,dragOverlay:De,draggableNodes:C,droppableContainers:N,droppableRects:V,over:X,measureDroppableContainers:j,scrollableAncestors:Le,scrollableAncestorRects:K,measuringConfiguration:B,measuringScheduled:H,windowRect:$e}),[D,Z,R,b,Ke,ke,De,C,N,V,X,j,Le,K,B,H,$e]),Ue=k.useMemo(()=>({activatorEvent:b,activators:Se,active:D,activeNodeRect:R,ariaDescribedById:{draggable:G},dispatch:x,draggableNodes:C,over:X,measureDroppableContainers:j}),[b,Se,D,R,x,G,C,X,j]);return k.createElement(ni.Provider,{value:v},k.createElement(Kn.Provider,{value:Ue},k.createElement(Ai.Provider,{value:_e},k.createElement(Mi.Provider,{value:le},h)),k.createElement(kh,{disabled:l?.restoreFocus===!1})),k.createElement(Cg,{...l,hiddenTextDescribedById:G}));function je(){const Ee=U?.autoScrollEnabled===!1,he=typeof f=="object"?f.enabled===!1:f===!1,Ne=_&&!Ee&&!he;return typeof f=="object"?{...f,enabled:Ne}:{enabled:Ne}}}),Th=k.createContext(null),Oi="button",Nh="Draggable";function Ah(e){let{id:t,data:r,disabled:n=!1,attributes:o}=e;const a=en(Nh),{activators:s,activatorEvent:l,active:f,activeNodeRect:h,ariaDescribedById:d,draggableNodes:i,over:u}=k.useContext(Kn),{role:g=Oi,roleDescription:p="draggable",tabIndex:m=0}=o??{},w=f?.id===t,x=k.useContext(w?Mi:Th),[A,v]=zn(),[E,O]=zn(),_=fh(s,t),I=Jr(r);Yt(()=>(i.set(t,{id:t,key:a,node:A,activatorNode:E,data:I}),()=>{const y=i.get(t);y&&y.key===a&&i.delete(t)}),[i,t]);const C=k.useMemo(()=>({role:g,tabIndex:m,"aria-disabled":n,"aria-pressed":w&&g===Oi?!0:void 0,"aria-roledescription":p,"aria-describedby":d.draggable}),[n,g,m,w,p,d.draggable]);return{active:f,activatorEvent:l,activeNodeRect:h,attributes:C,isDragging:w,listeners:n?void 0:_,node:A,over:u,setNodeRef:v,setActivatorNodeRef:O,transform:x}}function Mh(){return k.useContext(Ai)}const Oh="Droppable",Ih={timeout:25};function Dh(e){let{data:t,disabled:r=!1,id:n,resizeObserverConfig:o}=e;const a=en(Oh),{active:s,dispatch:l,over:f,measureDroppableContainers:h}=k.useContext(Kn),d=k.useRef({disabled:r}),i=k.useRef(!1),u=k.useRef(null),g=k.useRef(null),{disabled:p,updateMeasurementsFor:m,timeout:w}={...Ih,...o},x=Jr(m??n),A=k.useCallback(()=>{if(!i.current){i.current=!0;return}g.current!=null&&clearTimeout(g.current),g.current=setTimeout(()=>{h(Array.isArray(x.current)?x.current:[x.current]),g.current=null},w)},[w]),v=Bn({callback:A,disabled:p||!s}),E=k.useCallback((C,y)=>{v&&(y&&(v.unobserve(y),i.current=!1),C&&v.observe(C))},[v]),[O,_]=zn(E),I=Jr(t);return k.useEffect(()=>{!v||!O.current||(v.disconnect(),i.current=!1,v.observe(O.current))},[O,v]),k.useEffect(()=>(l({type:et.RegisterDroppable,element:{id:n,key:a,disabled:r,node:O,rect:u,data:I}}),()=>l({type:et.UnregisterDroppable,key:a,id:n})),[n]),k.useEffect(()=>{r!==d.current.disabled&&(l({type:et.SetDroppableDisabled,id:n,key:a,disabled:r}),d.current.disabled=r)},[n,a,r,l]),{active:s,rect:u,isOver:f?.id===n,node:O,over:f,setNodeRef:_}}function ka(e,t,r){const n=e.slice();return n.splice(r<0?n.length+r:r,0,n.splice(t,1)[0]),n}function Lh(e,t){return e.reduce((r,n,o)=>{const a=t.get(n);return a&&(r[o]=a),r},Array(e.length))}function Vn(e){return e!==null&&e>=0}function Ph(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(let r=0;r{let{rects:t,activeIndex:r,overIndex:n,index:o}=e;const a=ka(t,n,r),s=t[o],l=a[o];return!l||!s?null:{x:l.left-s.left,y:l.top-s.top,scaleX:l.width/s.width,scaleY:l.height/s.height}},Ii="Sortable",Di=k.createContext({activeIndex:-1,containerId:Ii,disableTransforms:!1,items:[],overIndex:-1,useDragOverlay:!1,sortedRects:[],strategy:Yn,disabled:{draggable:!1,droppable:!1}});function Li(e){let{children:t,id:r,items:n,strategy:o=Yn,disabled:a=!1}=e;const{active:s,dragOverlay:l,droppableRects:f,over:h,measureDroppableContainers:d}=Mh(),i=en(Ii,r),u=l.rect!==null,g=k.useMemo(()=>n.map(_=>typeof _=="object"&&"id"in _?_.id:_),[n]),p=s!=null,m=s?g.indexOf(s.id):-1,w=h?g.indexOf(h.id):-1,x=k.useRef(g),A=!Ph(g,x.current),v=w!==-1&&m===-1||A,E=Fh(a);Yt(()=>{A&&p&&d(g)},[A,g,p,d]),k.useEffect(()=>{x.current=g},[g]);const O=k.useMemo(()=>({activeIndex:m,containerId:i,disabled:E,disableTransforms:v,items:g,overIndex:w,useDragOverlay:u,sortedRects:Lh(g,f),strategy:o}),[m,i,E.draggable,E.droppable,v,g,w,f,u,o]);return k.createElement(Di.Provider,{value:O},t)}const Pi=e=>{let{id:t,items:r,activeIndex:n,overIndex:o}=e;return ka(r,n,o).indexOf(t)},Fi=e=>{let{containerId:t,isSorting:r,wasDragging:n,index:o,items:a,newIndex:s,previousItems:l,previousContainerId:f,transition:h}=e;return!h||!n||l!==a&&o===s?!1:r?!0:s!==o&&t===f},$h={duration:200,easing:"ease"},$i="transform",Uh=rn.Transition.toString({property:$i,duration:0,easing:"linear"}),zh={roleDescription:"sortable"};function Hh(e){let{disabled:t,index:r,node:n,rect:o}=e;const[a,s]=k.useState(null),l=k.useRef(r);return Yt(()=>{if(!t&&r!==l.current&&n.current){const f=o.current;if(f){const h=Ir(n.current,{ignoreTransform:!0}),d={x:f.left-h.left,y:f.top-h.top,scaleX:f.width/h.width,scaleY:f.height/h.height};(d.x||d.y)&&s(d)}}r!==l.current&&(l.current=r)},[t,r,n,o]),k.useEffect(()=>{a&&s(null)},[a]),a}function Ui(e){let{animateLayoutChanges:t=Fi,attributes:r,disabled:n,data:o,getNewIndex:a=Pi,id:s,strategy:l,resizeObserverConfig:f,transition:h=$h}=e;const{items:d,containerId:i,activeIndex:u,disabled:g,disableTransforms:p,sortedRects:m,overIndex:w,useDragOverlay:x,strategy:A}=k.useContext(Di),v=Gh(n,g),E=d.indexOf(s),O=k.useMemo(()=>({sortable:{containerId:i,index:E,items:d},...o}),[i,o,E,d]),_=k.useMemo(()=>d.slice(d.indexOf(s)),[d,s]),{rect:I,node:C,isOver:y,setNodeRef:N}=Dh({id:s,data:O,disabled:v.droppable,resizeObserverConfig:{updateMeasurementsFor:_,...f}}),{active:M,activatorEvent:P,activeNodeRect:D,attributes:L,setNodeRef:U,listeners:S,isDragging:b,over:$,setActivatorNodeRef:F,transform:G}=Ah({id:s,data:O,attributes:{...zh,...r},disabled:v.draggable}),Y=dg(N,U),B=!!M,V=B&&!p&&Vn(u)&&Vn(w),j=!x&&b,H=j&&V?G:null,ue=V?H??(l??A)({rects:m,activeNodeRect:D,activeIndex:u,overIndex:w,index:E}):null,te=Vn(u)&&Vn(w)?a({id:s,items:d,activeIndex:u,overIndex:w}):E,fe=M?.id,R=k.useRef({activeId:fe,items:d,newIndex:te,containerId:i}),ke=d!==R.current.items,me=t({active:M,containerId:i,isDragging:b,isSorting:B,id:s,index:E,items:d,newIndex:R.current.newIndex,previousItems:R.current.items,previousContainerId:R.current.containerId,transition:h,wasDragging:R.current.activeId!=null}),Ge=Hh({disabled:!me,index:E,node:C,rect:I});return k.useEffect(()=>{B&&R.current.newIndex!==te&&(R.current.newIndex=te),i!==R.current.containerId&&(R.current.containerId=i),d!==R.current.items&&(R.current.items=d)},[B,te,i,d]),k.useEffect(()=>{if(fe===R.current.activeId)return;if(fe!=null&&R.current.activeId==null){R.current.activeId=fe;return}const ye=setTimeout(()=>{R.current.activeId=fe},50);return()=>clearTimeout(ye)},[fe]),{active:M,activeIndex:u,attributes:L,data:O,rect:I,index:E,newIndex:te,items:d,isOver:y,isSorting:B,isDragging:b,listeners:S,node:C,overIndex:w,over:$,setNodeRef:Y,setActivatorNodeRef:F,setDroppableNodeRef:N,setDraggableNodeRef:U,transform:Ge??ue,transition:De()};function De(){if(Ge||ke&&R.current.newIndex===E)return Uh;if(!(j&&!da(P)||!h)&&(B||me))return rn.Transition.toString({...h,property:$i})}}function Gh(e,t){var r,n;return typeof e=="boolean"?{draggable:e,droppable:!1}:{draggable:(r=e?.draggable)!=null?r:t.draggable,droppable:(n=e?.droppable)!=null?n:t.droppable}}function ln(e){if(!e)return!1;const t=e.data.current;return!!(t&&"sortable"in t&&typeof t.sortable=="object"&&"containerId"in t.sortable&&"items"in t.sortable&&"index"in t.sortable)}const jh=[ze.Down,ze.Right,ze.Up,ze.Left],zi=(e,t)=>{let{context:{active:r,collisionRect:n,droppableRects:o,droppableContainers:a,over:s,scrollableAncestors:l}}=t;if(jh.includes(e.code)){if(e.preventDefault(),!r||!n)return;const f=[];a.getEnabled().forEach(i=>{if(!i||i!=null&&i.disabled)return;const u=o.get(i.id);if(u)switch(e.code){case ze.Down:n.topu.top&&f.push(i);break;case ze.Left:n.left>u.left&&f.push(i);break;case ze.Right:n.left1&&(d=h[1].id),d!=null){const i=a.get(r.id),u=a.get(d),g=u?o.get(u.id):null,p=u?.node.current;if(p&&g&&i&&u){const w=Gn(p).some((_,I)=>l[I]!==_),x=Hi(i,u),A=Bh(i,u),v=w||!x?{x:0,y:0}:{x:A?n.width-g.width:0,y:A?n.height-g.height:0},E={x:g.left,y:g.top};return v.x&&v.y?E:tn(E,v)}}}};function Hi(e,t){return!ln(e)||!ln(t)?!1:e.data.current.sortable.containerId===t.data.current.sortable.containerId}function Bh(e,t){return!ln(e)||!ln(t)||!Hi(e,t)?!1:e.data.current.sortable.index{const{attributes:l,listeners:f,setNodeRef:h,transform:d,transition:i,isDragging:u}=Ui({id:"hash"in e?e.hash:e.id}),g={transform:rn.Transform.toString(d),transition:i,opacity:u?.5:1},p="status"in e&&e.status!==void 0,m=p?e.status:"done",w=m==="uploading",x=m==="compressing",A=m==="error",v=p?e.progress:100,E=p?e.preview:void 0,O=p?e.mime_type?.startsWith("image/")??!1:e.is_image,[_,I]=k.useState(void 0),C=!p&&O?e.download_url:void 0;k.useEffect(()=>{if(!C){I(void 0);return}let N=!0,M;return(async()=>{try{const D=await Kh.api.get(C,{responseType:"blob"});N&&D&&(M=URL.createObjectURL(D),I(M))}catch(D){console.error("Failed to load authenticated image:",D)}})(),()=>{N=!1,M&&URL.revokeObjectURL(M)}},[C]);const y=_;return c.jsxs(W,{ref:h,style:g,className:"relative group bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden",children:[c.jsxs(W,{className:`aspect-square w-full flex items-center justify-center bg-gray-50 dark:bg-gray-900 relative ${O||!p?"cursor-pointer":""}`,onClick:()=>{w||x||(O&&n?n():!p&&o&&o())},children:[E||y?c.jsx(Lt,{src:E||y,alt:e.original_filename,className:"w-full h-full object-cover"}):c.jsx(Ct,{className:`fa-solid ${Ql(e.mime_type)} text-4xl text-gray-400 dark:text-gray-500`}),(w||x)&&c.jsxs(W,{className:"absolute inset-0 bg-black/50 flex flex-col items-center justify-center",children:[c.jsx(W,{className:"w-3/4 h-2 bg-gray-700 rounded-full overflow-hidden",children:c.jsx(W,{className:"h-full bg-blue-500 transition-all",style:{width:`${v}%`}})}),c.jsxs(ee,{className:"text-white text-xs mt-1",children:[v,"%"]})]}),A&&c.jsx(W,{className:"absolute inset-0 bg-red-500/50 flex items-center justify-center",children:c.jsx(Ct,{className:"fa-solid fa-exclamation-triangle text-2xl text-white"})}),s&&c.jsx(Q,{type:"button",onClick:N=>{N.stopPropagation(),s()},className:`absolute top-1.5 left-1.5 z-10 p-1 rounded-full transition-colors ${a?"bg-yellow-500 text-white":"bg-gray-800/50 text-gray-300 hover:bg-yellow-500 hover:text-white opacity-0 group-hover:opacity-100"}`,title:Re(a?"attachment.primary_image":"attachment.set_as_primary"),children:c.jsx(Ct,{className:"fa-solid fa-star text-xs"})}),c.jsxs(W,{className:"absolute inset-0 bg-black/0 group-hover:bg-black/40 transition-colors flex items-start justify-end p-1 gap-1 opacity-0 group-hover:opacity-100",children:[c.jsx(Q,{type:"button",...l,...f,className:"p-1.5 bg-white/90 dark:bg-gray-800/90 rounded text-gray-600 dark:text-gray-300 hover:bg-white cursor-grab active:cursor-grabbing",title:Re("attachment.drag_to_reorder"),onClick:N=>N.stopPropagation(),children:c.jsx(Ct,{className:"fa-solid fa-grip-vertical text-sm"})}),!p&&o&&c.jsx(Q,{type:"button",onClick:N=>{N.stopPropagation(),o()},className:"p-1.5 bg-white/90 dark:bg-gray-800/90 rounded text-blue-500 hover:bg-white",title:Re("common.download"),children:c.jsx(Ct,{className:"fa-solid fa-download text-sm"})}),A&&r&&c.jsx(Q,{type:"button",onClick:N=>{N.stopPropagation(),r()},className:"p-1.5 bg-white/90 dark:bg-gray-800/90 rounded text-orange-500 hover:bg-white",title:Re("common.retry"),children:c.jsx(Ct,{className:"fa-solid fa-arrow-rotate-right text-sm"})}),c.jsx(Q,{type:"button",onClick:N=>{N.stopPropagation(),t()},disabled:w||x,className:"p-1.5 bg-white/90 dark:bg-gray-800/90 rounded text-red-500 hover:bg-white disabled:opacity-50",title:Re("common.delete"),children:c.jsx(Ct,{className:"fa-solid fa-times text-sm"})})]})]}),c.jsxs(W,{className:`p-2 ${!p&&o?"cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700":""}`,onClick:()=>{!p&&o&&o()},children:[c.jsx(Dt,{className:"text-xs font-medium text-gray-900 dark:text-white truncate",title:e.original_filename,children:e.original_filename}),c.jsx(Dt,{className:"text-xs text-gray-500 dark:text-gray-400",children:e.size_formatted})]})]})},ji=({allItems:e,canAddMore:t,totalCount:r,maxFiles:n,maxSize:o,accept:a,onRemove:s,onRetry:l,onImageClick:f,onDownload:h,onDragEnd:d,onAddClick:i,enablePrimarySelection:u,primaryFileId:g,onPrimaryChange:p})=>{const m=Sg(oi(ya,{activationConstraint:{distance:8}}),oi(ma,{coordinateGetter:zi}));return c.jsxs(W,{className:"p-3",children:[c.jsx(Eh,{sensors:m,collisionDetection:Eg,onDragEnd:d,children:c.jsx(Li,{items:e.map(w=>"hash"in w?w.hash:w.id),strategy:Yn,children:c.jsxs(W,{className:"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-3",children:[e.map(w=>{const x="hash"in w,A=x?w.is_image:w.mime_type?.startsWith("image/")??!1;return c.jsx(Gi,{file:w,onRemove:()=>s(w),onRetry:"status"in w&&w.status==="error"?()=>l(w):void 0,onImageClick:A?()=>f(w):void 0,onDownload:x?()=>h(w):void 0,isPrimary:u&&x&&(w.hash||w.id)===g,onPrimaryClick:u&&x?()=>p?.(w.hash||w.id):void 0},x?w.hash:w.id)}),t&&c.jsxs(W,{className:"aspect-square flex flex-col items-center justify-center border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg cursor-pointer hover:border-gray-400 dark:hover:border-gray-500 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors",onClick:i,children:[c.jsx(Ct,{className:"fa-solid fa-plus text-2xl text-gray-400 dark:text-gray-500 mb-1"}),c.jsx(ee,{className:"text-xs text-gray-500 dark:text-gray-400",children:Re("common.add")})]})]})})}),c.jsxs(W,{className:"mt-3 pt-3 border-t border-gray-200 dark:border-gray-700 flex justify-between items-center text-xs text-gray-500 dark:text-gray-400",children:[c.jsx(ee,{children:Re("attachment.attached_count",{count:r,max:n})}),c.jsxs(ee,{children:[Re("attachment.max_size",{size:o}),a&&` (${a})`]})]})]})},Vh=[],Yh=[],Xn=k.forwardRef(({uploadTriggerEvent:e,attachmentableType:t,attachmentableId:r,collection:n="default",maxFiles:o=10,maxSize:a=10,maxConcurrentUploads:s=3,accept:l,imageCompression:f,roleIds:h=Yh,autoUpload:d=!0,onFilesChange:i,onChange:u,onUploadComplete:g,onUploadError:p,onRemove:m,onReorder:w,initialFiles:x=Vh,className:A="",confirmBeforeRemove:v=!1,confirmRemoveTitle:E,confirmRemoveMessage:O,apiEndpoints:_,uploadParams:I,enablePrimarySelection:C=!1,primaryFileId:y,onPrimaryChange:N,id:M,editorAttrs:P},D)=>{const L={upload:_?.upload??"/api/attachments",delete:_?.delete??"/api/attachments/:id",reorder:_?.reorder??"/api/attachments/reorder"},U=k.useRef(u??i);U.current=u??i;const S=k.useCallback(G=>{const Y=U.current;if(!Y)return;Y({target:{value:G,files:G},preventDefault:()=>{},stopPropagation:()=>{}})},[]),b=Jl({attachmentableType:t,attachmentableId:r,collection:n,maxFiles:o,maxSize:a,maxConcurrentUploads:s,accept:l,imageCompression:f,roleIds:h,autoUpload:d,initialFiles:x,endpoints:L,onFilesChange:S,onUploadComplete:g,onUploadError:p,onRemove:m,onReorder:w,uploadTriggerEvent:e,confirmBeforeRemove:v,uploadParams:I});k.useImperativeHandle(D,()=>({uploadAll:b.handleUploadAll,clear:b.clear,getPendingFiles:b.getPendingFiles}));const $=k.useMemo(()=>b.imageFiles.map(G=>{const Y=!("hash"in G),B=G,V=G;return Y?{src:B.preview||"",filename:B.original_filename,title:B.original_filename,downloadRequiresAuth:!1}:{src:b.authenticatedImageUrls.get(V.id)||V.download_url,downloadUrl:V.download_url,filename:V.original_filename,title:V.original_filename,downloadRequiresAuth:!0}}),[b.imageFiles,b.authenticatedImageUrls]),F=k.useMemo(()=>({existingFiles:b.existingFiles,pendingFiles:b.pendingFiles,isDragOver:b.isDragOver,isDeleting:b.isDeleting,maxFiles:o,maxSize:a,accept:l,endpoints:L,confirmBeforeRemove:v,totalCount:b.totalCount,hasFiles:b.hasFiles,canAddMore:b.canAddMore,allItems:b.allItems,imageFiles:b.imageFiles,handleFiles:b.handleFiles,handleRemove:b.handleRemove,handleRetry:b.handleRetry,handleUploadAll:b.handleUploadAll,handleOpenGallery:b.handleOpenGallery,handleDownload:b.handleDownload,handleDragEnd:b.handleDragEnd,setIsDragOver:b.setIsDragOver,inputRef:b.inputRef,galleryOpen:b.galleryOpen,setGalleryOpen:b.setGalleryOpen,galleryStartIndex:b.galleryStartIndex,galleryKeyRef:b.galleryKeyRef,confirmDialogOpen:b.confirmDialogOpen,setConfirmDialogOpen:b.setConfirmDialogOpen,itemToDelete:b.itemToDelete,executeRemoveAttachment:b.executeRemoveAttachment,authenticatedImageUrls:b.authenticatedImageUrls}),[b,o,a,l,L,v]);return c.jsx($l,{value:F,children:c.jsxs(W,{id:M,className:A,...P,children:[c.jsx(Rl,{isDragOver:b.isDragOver,canAddMore:b.canAddMore,onFiles:b.handleFiles,setIsDragOver:b.setIsDragOver,inputRef:b.inputRef,accept:l,maxFiles:o,maxSize:a,children:b.hasFiles&&c.jsx(ji,{allItems:b.allItems,canAddMore:b.canAddMore,totalCount:b.totalCount,maxFiles:o,maxSize:a,accept:l,onRemove:b.handleRemove,onRetry:b.handleRetry,onImageClick:b.handleOpenGallery,onDownload:b.handleDownload,onDragEnd:b.handleDragEnd,onAddClick:()=>b.inputRef.current?.click(),enablePrimarySelection:C,primaryFileId:y,onPrimaryChange:N})}),v&&c.jsx(ta,{isOpen:b.confirmDialogOpen,onClose:()=>{b.isDeleting||b.setConfirmDialogOpen(!1)},title:E??Re("attachment.delete_confirm_title"),message:O??Re("attachment.delete_confirm_message"),confirmText:Re("common.delete"),confirmButtonVariant:"danger",onConfirm:()=>{b.itemToDelete&&b.executeRemoveAttachment(b.itemToDelete)},isLoading:b.isDeleting,loadingText:Re("attachment.deleting")}),$.length>0&&b.galleryOpen&&c.jsx(Tr,{images:$,isOpen:!0,onClose:()=>b.setGalleryOpen(!1),startIndex:b.galleryStartIndex,showDownload:!0},`gallery-${b.galleryKeyRef.current}`)]})})});Xn.displayName="FileUploader";const Xh=Object.freeze(Object.defineProperty({__proto__:null,FileDropZone:Rl,FileList:ji,FileUploader:Xn,FileUploaderProvider:$l,SortableThumbnailItem:Gi,default:Xn,extractErrorMessage:ql,fileUploaderT:Re,formatFileSize:$n,getFileIcon:Ql,useFileUploader:Jl,useFileUploaderContext:eg},Symbol.toStringTag,{value:"Module"})),Bi=({provider:e,className:t="w-5 h-5"})=>{switch(e){case"google":return c.jsxs("svg",{className:t,viewBox:"0 0 24 24",children:[c.jsx("path",{fill:"#4285F4",d:"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"}),c.jsx("path",{fill:"#34A853",d:"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"}),c.jsx("path",{fill:"#FBBC05",d:"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"}),c.jsx("path",{fill:"#EA4335",d:"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"})]});case"naver":return c.jsx("svg",{className:t,viewBox:"0 0 24 24",children:c.jsx("path",{fill:"currentColor",d:"M16.273 12.845L7.376 0H0v24h7.727V11.155L16.624 24H24V0h-7.727z"})});case"kakao":return c.jsx("svg",{className:t,viewBox:"0 0 24 24",children:c.jsx("path",{fill:"currentColor",d:"M12 3c5.799 0 10.5 3.664 10.5 8.185 0 4.52-4.701 8.184-10.5 8.184a13.5 13.5 0 0 1-1.727-.11l-4.408 2.883c-.501.265-.678.236-.472-.413l.892-3.678c-2.88-1.46-4.785-3.99-4.785-6.866C1.5 6.665 6.201 3 12 3zm5.519 8.625h-.634v2.916h-.97v-2.916h-.633v-.848h2.237v.848zm-3.294 2.916h-.97V10.77h.97v3.771zm-1.97 0h-.97v-2.77l-.658 1.53h-.629l-.665-1.53v2.77h-.97V10.77h1.13l.822 1.912.814-1.912h1.126v3.771zm-4.49 0h-.97V10.77h.97v3.771z"})});case"facebook":return c.jsx("svg",{className:t,viewBox:"0 0 24 24",children:c.jsx("path",{fill:"currentColor",d:"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"})});case"apple":return c.jsx("svg",{className:t,viewBox:"0 0 24 24",children:c.jsx("path",{fill:"currentColor",d:"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701"})});default:return null}},Wi=(e,t)=>window.G7Core?.t?.(e,t)??e,Zh=[{id:"google",name:"Google",color:"bg-white dark:bg-gray-800",textColor:"text-gray-700 dark:text-gray-300"},{id:"naver",name:"네이버",color:"bg-[#03C75A]",textColor:"text-white"},{id:"kakao",name:"카카오",color:"bg-[#FEE500]",textColor:"text-[#000000]/85"},{id:"facebook",name:"Facebook",color:"bg-[#1877F2]",textColor:"text-white"},{id:"apple",name:"Apple",color:"bg-black dark:bg-white",textColor:"text-white dark:text-black"}],Ki=({providers:e=["google","naver","kakao"],mode:t="login",variant:r="full",className:n="",id:o,editorAttrs:a})=>{const s=h=>{const d=encodeURIComponent(window.location.href);window.location.href=`/api/auth/${h}?redirect=${d}`},l=h=>t==="register"?Wi("auth.social.register_with",{provider:h}):Wi("auth.social.login_with",{provider:h}),f=Zh.filter(h=>e.includes(h.id));return r==="icon"?c.jsx(W,{className:`flex justify-center gap-4 ${n}`,id:o,...a,children:f.map(h=>c.jsx(Q,{onClick:()=>s(h.id),className:`w-12 h-12 flex items-center justify-center rounded-full ${h.color} ${h.textColor} border border-gray-200 dark:border-gray-700 hover:opacity-90 transition-opacity`,"aria-label":l(h.name),children:c.jsx(Bi,{provider:h.id,className:"w-5 h-5"})},h.id))}):c.jsx(W,{className:`space-y-3 ${n}`,id:o,...a,children:f.map(h=>c.jsxs(Q,{onClick:()=>s(h.id),className:`w-full flex items-center justify-center gap-3 px-4 py-3 rounded-lg font-medium border border-gray-200 dark:border-gray-700 ${h.color} ${h.textColor} hover:opacity-90 transition-opacity`,children:[c.jsx(Bi,{provider:h.id,className:"w-5 h-5"}),c.jsx(ee,{children:l(h.name)})]},h.id))})},qh=Object.freeze(Object.defineProperty({__proto__:null,default:Ki},Symbol.toStringTag,{value:"Module"})),Qh=(e,t)=>window.G7Core?.t?.(e,t)??e,Jh={success:Je.CheckCircle,error:Je.XCircle,warning:Je.ExclamationTriangle,info:Je.InfoCircle},Vi={success:{bg:"bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800",text:"text-green-800 dark:text-green-300"},error:{bg:"bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800",text:"text-red-800 dark:text-red-300"},warning:{bg:"bg-yellow-50 dark:bg-yellow-900/20 border-yellow-200 dark:border-yellow-800",text:"text-yellow-800 dark:text-yellow-300"},info:{bg:"bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800",text:"text-blue-800 dark:text-blue-300"}},Rh={"top-left":"top-4 left-4","top-center":"top-4 left-1/2 -translate-x-1/2","top-right":"top-4 right-4","bottom-left":"bottom-4 left-4","bottom-center":"bottom-4 left-1/2 -translate-x-1/2","bottom-right":"bottom-4 right-4"},Ca=({toasts:e,position:t="bottom-center",duration:r=3e3,onRemove:n})=>{const[o,a]=k.useState(new Map),s=k.useCallback(l=>{a(f=>{const h=new Map(f);return h.set(l,!1),h}),setTimeout(()=>{if(n)n(l);else{const f=window.G7Core;f?.state?.update&&f.state.update(h=>({toasts:(Array.isArray(h.toasts)?h.toasts:[]).filter(i=>i.id!==l)}))}},300)},[n]);return k.useEffect(()=>{!e||e.length===0||e.forEach(l=>{if(o.has(l.id))return;a(h=>{const d=new Map(h);return d.set(l.id,!0),d});const f=l.duration||r;f>0&&setTimeout(()=>{s(l.id)},f)})},[e,r,s,o]),!e||e.length===0?null:c.jsx(W,{className:`fixed z-[9999] flex flex-col gap-2 ${Rh[t]}`,"aria-live":"polite","aria-atomic":"true",children:e.map(l=>c.jsx(e0,{toast:l,position:t,isVisible:o.get(l.id)??!0,onClose:()=>s(l.id)},l.id))})},e0=({toast:e,position:t,isVisible:r,onClose:n})=>{const o=Vi[e.type]||Vi.info,a=e.icon?e.icon:Jh[e.type],s=t.startsWith("bottom")?"translate-y-2":"-translate-y-2";return c.jsxs(W,{className:` + `},kg={onDragStart(e){let{active:t}=e;return"Picked up draggable item "+t.id+"."},onDragOver(e){let{active:t,over:r}=e;return r?"Draggable item "+t.id+" was moved over droppable area "+r.id+".":"Draggable item "+t.id+" is no longer over a droppable area."},onDragEnd(e){let{active:t,over:r}=e;return r?"Draggable item "+t.id+" was dropped over droppable area "+r.id:"Draggable item "+t.id+" was dropped."},onDragCancel(e){let{active:t}=e;return"Dragging was cancelled. Draggable item "+t.id+" was dropped."}};function Cg(e){let{announcements:t=kg,container:r,hiddenTextDescribedById:n,screenReaderInstructions:o=xg}=e;const{announce:a,announcement:s}=yg(),l=en("DndLiveRegion"),[f,h]=k.useState(!1);if(k.useEffect(()=>{h(!0)},[]),vg(k.useMemo(()=>({onDragStart(i){let{active:u}=i;a(t.onDragStart({active:u}))},onDragMove(i){let{active:u,over:g}=i;t.onDragMove&&a(t.onDragMove({active:u,over:g}))},onDragOver(i){let{active:u,over:g}=i;a(t.onDragOver({active:u,over:g}))},onDragEnd(i){let{active:u,over:g}=i;a(t.onDragEnd({active:u,over:g}))},onDragCancel(i){let{active:u,over:g}=i;a(t.onDragCancel({active:u,over:g}))}}),[a,t])),!f)return null;const d=k.createElement(k.Fragment,null,k.createElement(mg,{id:n,value:o.draggable}),k.createElement(bg,{id:l,announcement:s}));return r?Jt.createPortal(d,r):d}var et;(function(e){e.DragStart="dragStart",e.DragMove="dragMove",e.DragEnd="dragEnd",e.DragCancel="dragCancel",e.DragOver="dragOver",e.RegisterDroppable="registerDroppable",e.SetDroppableDisabled="setDroppableDisabled",e.UnregisterDroppable="unregisterDroppable"})(et||(et={}));function Hn(){}function oi(e,t){return k.useMemo(()=>({sensor:e,options:t??{}}),[e,t])}function Sg(){for(var e=arguments.length,t=new Array(e),r=0;r[...t].filter(n=>n!=null),[...t])}const Gt=Object.freeze({x:0,y:0});function ai(e,t){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function si(e,t){let{data:{value:r}}=e,{data:{value:n}}=t;return r-n}function _g(e,t){let{data:{value:r}}=e,{data:{value:n}}=t;return n-r}function li(e){let{left:t,top:r,height:n,width:o}=e;return[{x:t,y:r},{x:t+o,y:r},{x:t,y:r+n},{x:t+o,y:r+n}]}function ii(e,t){if(!e||e.length===0)return null;const[r]=e;return r[t]}function ci(e,t,r){return t===void 0&&(t=e.left),r===void 0&&(r=e.top),{x:t+e.width*.5,y:r+e.height*.5}}const Eg=e=>{let{collisionRect:t,droppableRects:r,droppableContainers:n}=e;const o=ci(t,t.left,t.top),a=[];for(const s of n){const{id:l}=s,f=r.get(l);if(f){const h=ai(ci(f),o);a.push({id:l,data:{droppableContainer:s,value:h}})}}return a.sort(si)},Tg=e=>{let{collisionRect:t,droppableRects:r,droppableContainers:n}=e;const o=li(t),a=[];for(const s of n){const{id:l}=s,f=r.get(l);if(f){const h=li(f),d=o.reduce((u,g,p)=>u+ai(h[p],g),0),i=Number((d/4).toFixed(4));a.push({id:l,data:{droppableContainer:s,value:i}})}}return a.sort(si)};function Ng(e,t){const r=Math.max(t.top,e.top),n=Math.max(t.left,e.left),o=Math.min(t.left+t.width,e.left+e.width),a=Math.min(t.top+t.height,e.top+e.height),s=o-n,l=a-r;if(n{let{collisionRect:t,droppableRects:r,droppableContainers:n}=e;const o=[];for(const a of n){const{id:s}=a,l=r.get(s);if(l){const f=Ng(l,t);f>0&&o.push({id:s,data:{droppableContainer:a,value:f}})}}return o.sort(_g)};function Mg(e,t,r){return{...e,scaleX:t&&r?t.width/r.width:1,scaleY:t&&r?t.height/r.height:1}}function di(e,t){return e&&t?{x:e.left-t.left,y:e.top-t.top}:Gt}function Og(e){return function(r){for(var n=arguments.length,o=new Array(n>1?n-1:0),a=1;a({...s,top:s.top+e*l.y,bottom:s.bottom+e*l.y,left:s.left+e*l.x,right:s.right+e*l.x}),{...r})}}const Ig=Og(1);function Dg(e){if(e.startsWith("matrix3d(")){const t=e.slice(9,-1).split(/, /);return{x:+t[12],y:+t[13],scaleX:+t[0],scaleY:+t[5]}}else if(e.startsWith("matrix(")){const t=e.slice(7,-1).split(/, /);return{x:+t[4],y:+t[5],scaleX:+t[0],scaleY:+t[3]}}return null}function Lg(e,t,r){const n=Dg(t);if(!n)return e;const{scaleX:o,scaleY:a,x:s,y:l}=n,f=e.left-s-(1-o)*parseFloat(r),h=e.top-l-(1-a)*parseFloat(r.slice(r.indexOf(" ")+1)),d=o?e.width/o:e.width,i=a?e.height/a:e.height;return{width:d,height:i,top:h,right:f+d,bottom:h+i,left:f}}const Pg={ignoreTransform:!1};function Ir(e,t){t===void 0&&(t=Pg);let r=e.getBoundingClientRect();if(t.ignoreTransform){const{transform:h,transformOrigin:d}=yt(e).getComputedStyle(e);h&&(r=Lg(r,h,d))}const{top:n,left:o,width:a,height:s,bottom:l,right:f}=r;return{top:n,left:o,width:a,height:s,bottom:l,right:f}}function ui(e){return Ir(e,{ignoreTransform:!0})}function Fg(e){const t=e.innerWidth,r=e.innerHeight;return{top:0,left:0,right:t,bottom:r,width:t,height:r}}function $g(e,t){return t===void 0&&(t=yt(e).getComputedStyle(e)),t.position==="fixed"}function Ug(e,t){t===void 0&&(t=yt(e).getComputedStyle(e));const r=/(auto|scroll|overlay)/;return["overflow","overflowX","overflowY"].some(o=>{const a=t[o];return typeof a=="string"?r.test(a):!1})}function Gn(e,t){const r=[];function n(o){if(t!=null&&r.length>=t||!o)return r;if(sa(o)&&o.scrollingElement!=null&&!r.includes(o.scrollingElement))return r.push(o.scrollingElement),r;if(!Qr(o)||ei(o)||r.includes(o))return r;const a=yt(e).getComputedStyle(o);return o!==e&&Ug(o,a)&&r.push(o),$g(o,a)?r:n(o.parentNode)}return e?n(e):r}function fi(e){const[t]=Gn(e,1);return t??null}function fa(e){return!Un||!e?null:Ar(e)?e:aa(e)?sa(e)||e===Mr(e).scrollingElement?window:Qr(e)?e:null:null}function gi(e){return Ar(e)?e.scrollX:e.scrollLeft}function hi(e){return Ar(e)?e.scrollY:e.scrollTop}function ga(e){return{x:gi(e),y:hi(e)}}var ot;(function(e){e[e.Forward=1]="Forward",e[e.Backward=-1]="Backward"})(ot||(ot={}));function pi(e){return!Un||!e?!1:e===document.scrollingElement}function mi(e){const t={x:0,y:0},r=pi(e)?{height:window.innerHeight,width:window.innerWidth}:{height:e.clientHeight,width:e.clientWidth},n={x:e.scrollWidth-r.width,y:e.scrollHeight-r.height},o=e.scrollTop<=t.y,a=e.scrollLeft<=t.x,s=e.scrollTop>=n.y,l=e.scrollLeft>=n.x;return{isTop:o,isLeft:a,isBottom:s,isRight:l,maxScroll:n,minScroll:t}}const zg={x:.2,y:.2};function Hg(e,t,r,n,o){let{top:a,left:s,right:l,bottom:f}=r;n===void 0&&(n=10),o===void 0&&(o=zg);const{isTop:h,isBottom:d,isLeft:i,isRight:u}=mi(e),g={x:0,y:0},p={x:0,y:0},m={height:t.height*o.y,width:t.width*o.x};return!h&&a<=t.top+m.height?(g.y=ot.Backward,p.y=n*Math.abs((t.top+m.height-a)/m.height)):!d&&f>=t.bottom-m.height&&(g.y=ot.Forward,p.y=n*Math.abs((t.bottom-m.height-f)/m.height)),!u&&l>=t.right-m.width?(g.x=ot.Forward,p.x=n*Math.abs((t.right-m.width-l)/m.width)):!i&&s<=t.left+m.width&&(g.x=ot.Backward,p.x=n*Math.abs((t.left+m.width-s)/m.width)),{direction:g,speed:p}}function Gg(e){if(e===document.scrollingElement){const{innerWidth:a,innerHeight:s}=window;return{top:0,left:0,right:a,bottom:s,width:a,height:s}}const{top:t,left:r,right:n,bottom:o}=e.getBoundingClientRect();return{top:t,left:r,right:n,bottom:o,width:e.clientWidth,height:e.clientHeight}}function bi(e){return e.reduce((t,r)=>Or(t,ga(r)),Gt)}function jg(e){return e.reduce((t,r)=>t+gi(r),0)}function Bg(e){return e.reduce((t,r)=>t+hi(r),0)}function Wg(e,t){if(t===void 0&&(t=Ir),!e)return;const{top:r,left:n,bottom:o,right:a}=t(e);fi(e)&&(o<=0||a<=0||r>=window.innerHeight||n>=window.innerWidth)&&e.scrollIntoView({block:"center",inline:"center"})}const Kg=[["x",["left","right"],jg],["y",["top","bottom"],Bg]];class ha{constructor(t,r){this.rect=void 0,this.width=void 0,this.height=void 0,this.top=void 0,this.bottom=void 0,this.right=void 0,this.left=void 0;const n=Gn(r),o=bi(n);this.rect={...t},this.width=t.width,this.height=t.height;for(const[a,s,l]of Kg)for(const f of s)Object.defineProperty(this,f,{get:()=>{const h=l(n),d=o[a]-h;return this.rect[f]+d},enumerable:!0});Object.defineProperty(this,"rect",{enumerable:!1})}}class nn{constructor(t){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(r=>{var n;return(n=this.target)==null?void 0:n.removeEventListener(...r)})},this.target=t}add(t,r,n){var o;(o=this.target)==null||o.addEventListener(t,r,n),this.listeners.push([t,r,n])}}function Vg(e){const{EventTarget:t}=yt(e);return e instanceof t?e:Mr(e)}function pa(e,t){const r=Math.abs(e.x),n=Math.abs(e.y);return typeof t=="number"?Math.sqrt(r**2+n**2)>t:"x"in t&&"y"in t?r>t.x&&n>t.y:"x"in t?r>t.x:"y"in t?n>t.y:!1}var It;(function(e){e.Click="click",e.DragStart="dragstart",e.Keydown="keydown",e.ContextMenu="contextmenu",e.Resize="resize",e.SelectionChange="selectionchange",e.VisibilityChange="visibilitychange"})(It||(It={}));function yi(e){e.preventDefault()}function Yg(e){e.stopPropagation()}var ze;(function(e){e.Space="Space",e.Down="ArrowDown",e.Right="ArrowRight",e.Left="ArrowLeft",e.Up="ArrowUp",e.Esc="Escape",e.Enter="Enter",e.Tab="Tab"})(ze||(ze={}));const vi={start:[ze.Space,ze.Enter],cancel:[ze.Esc],end:[ze.Space,ze.Enter,ze.Tab]},Xg=(e,t)=>{let{currentCoordinates:r}=t;switch(e.code){case ze.Right:return{...r,x:r.x+25};case ze.Left:return{...r,x:r.x-25};case ze.Down:return{...r,y:r.y+25};case ze.Up:return{...r,y:r.y-25}}};class ma{constructor(t){this.props=void 0,this.autoScrollEnabled=!1,this.referenceCoordinates=void 0,this.listeners=void 0,this.windowListeners=void 0,this.props=t;const{event:{target:r}}=t;this.props=t,this.listeners=new nn(Mr(r)),this.windowListeners=new nn(yt(r)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(It.Resize,this.handleCancel),this.windowListeners.add(It.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(It.Keydown,this.handleKeyDown))}handleStart(){const{activeNode:t,onStart:r}=this.props,n=t.node.current;n&&Wg(n),r(Gt)}handleKeyDown(t){if(da(t)){const{active:r,context:n,options:o}=this.props,{keyboardCodes:a=vi,coordinateGetter:s=Xg,scrollBehavior:l="smooth"}=o,{code:f}=t;if(a.end.includes(f)){this.handleEnd(t);return}if(a.cancel.includes(f)){this.handleCancel(t);return}const{collisionRect:h}=n.current,d=h?{x:h.left,y:h.top}:Gt;this.referenceCoordinates||(this.referenceCoordinates=d);const i=s(t,{active:r,context:n.current,currentCoordinates:d});if(i){const u=tn(i,d),g={x:0,y:0},{scrollableAncestors:p}=n.current;for(const m of p){const w=t.code,{isTop:x,isRight:O,isLeft:y,isBottom:E,maxScroll:M,minScroll:_}=mi(m),I=Gg(m),C={x:Math.min(w===ze.Right?I.right-I.width/2:I.right,Math.max(w===ze.Right?I.left:I.left+I.width/2,i.x)),y:Math.min(w===ze.Down?I.bottom-I.height/2:I.bottom,Math.max(w===ze.Down?I.top:I.top+I.height/2,i.y))},v=w===ze.Right&&!O||w===ze.Left&&!y,N=w===ze.Down&&!E||w===ze.Up&&!x;if(v&&C.x!==i.x){const A=m.scrollLeft+u.x,P=w===ze.Right&&A<=M.x||w===ze.Left&&A>=_.x;if(P&&!u.y){m.scrollTo({left:A,behavior:l});return}P?g.x=m.scrollLeft-A:g.x=w===ze.Right?m.scrollLeft-M.x:m.scrollLeft-_.x,g.x&&m.scrollBy({left:-g.x,behavior:l});break}else if(N&&C.y!==i.y){const A=m.scrollTop+u.y,P=w===ze.Down&&A<=M.y||w===ze.Up&&A>=_.y;if(P&&!u.x){m.scrollTo({top:A,behavior:l});return}P?g.y=m.scrollTop-A:g.y=w===ze.Down?m.scrollTop-M.y:m.scrollTop-_.y,g.y&&m.scrollBy({top:-g.y,behavior:l});break}}this.handleMove(t,Or(tn(i,this.referenceCoordinates),g))}}}handleMove(t,r){const{onMove:n}=this.props;t.preventDefault(),n(r)}handleEnd(t){const{onEnd:r}=this.props;t.preventDefault(),this.detach(),r()}handleCancel(t){const{onCancel:r}=this.props;t.preventDefault(),this.detach(),r()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}}ma.activators=[{eventName:"onKeyDown",handler:(e,t,r)=>{let{keyboardCodes:n=vi,onActivation:o}=t,{active:a}=r;const{code:s}=e.nativeEvent;if(n.start.includes(s)){const l=a.activatorNode.current;return l&&e.target!==l?!1:(e.preventDefault(),o?.({event:e.nativeEvent}),!0)}return!1}}];function wi(e){return!!(e&&"distance"in e)}function xi(e){return!!(e&&"delay"in e)}class ba{constructor(t,r,n){var o;n===void 0&&(n=Vg(t.event.target)),this.props=void 0,this.events=void 0,this.autoScrollEnabled=!0,this.document=void 0,this.activated=!1,this.initialCoordinates=void 0,this.timeoutId=null,this.listeners=void 0,this.documentListeners=void 0,this.windowListeners=void 0,this.props=t,this.events=r;const{event:a}=t,{target:s}=a;this.props=t,this.events=r,this.document=Mr(s),this.documentListeners=new nn(this.document),this.listeners=new nn(n),this.windowListeners=new nn(yt(s)),this.initialCoordinates=(o=ua(a))!=null?o:Gt,this.handleStart=this.handleStart.bind(this),this.handleMove=this.handleMove.bind(this),this.handleEnd=this.handleEnd.bind(this),this.handleCancel=this.handleCancel.bind(this),this.handleKeydown=this.handleKeydown.bind(this),this.removeTextSelection=this.removeTextSelection.bind(this),this.attach()}attach(){const{events:t,props:{options:{activationConstraint:r,bypassActivationConstraint:n}}}=this;if(this.listeners.add(t.move.name,this.handleMove,{passive:!1}),this.listeners.add(t.end.name,this.handleEnd),t.cancel&&this.listeners.add(t.cancel.name,this.handleCancel),this.windowListeners.add(It.Resize,this.handleCancel),this.windowListeners.add(It.DragStart,yi),this.windowListeners.add(It.VisibilityChange,this.handleCancel),this.windowListeners.add(It.ContextMenu,yi),this.documentListeners.add(It.Keydown,this.handleKeydown),r){if(n!=null&&n({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(xi(r)){this.timeoutId=setTimeout(this.handleStart,r.delay),this.handlePending(r);return}if(wi(r)){this.handlePending(r);return}}this.handleStart()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll(),setTimeout(this.documentListeners.removeAll,50),this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}handlePending(t,r){const{active:n,onPending:o}=this.props;o(n,t,this.initialCoordinates,r)}handleStart(){const{initialCoordinates:t}=this,{onStart:r}=this.props;t&&(this.activated=!0,this.documentListeners.add(It.Click,Yg,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(It.SelectionChange,this.removeTextSelection),r(t))}handleMove(t){var r;const{activated:n,initialCoordinates:o,props:a}=this,{onMove:s,options:{activationConstraint:l}}=a;if(!o)return;const f=(r=ua(t))!=null?r:Gt,h=tn(o,f);if(!n&&l){if(wi(l)){if(l.tolerance!=null&&pa(h,l.tolerance))return this.handleCancel();if(pa(h,l.distance))return this.handleStart()}if(xi(l)&&pa(h,l.tolerance))return this.handleCancel();this.handlePending(l,h);return}t.cancelable&&t.preventDefault(),s(f)}handleEnd(){const{onAbort:t,onEnd:r}=this.props;this.detach(),this.activated||t(this.props.active),r()}handleCancel(){const{onAbort:t,onCancel:r}=this.props;this.detach(),this.activated||t(this.props.active),r()}handleKeydown(t){t.code===ze.Esc&&this.handleCancel()}removeTextSelection(){var t;(t=this.document.getSelection())==null||t.removeAllRanges()}}const qg={cancel:{name:"pointercancel"},move:{name:"pointermove"},end:{name:"pointerup"}};class ya extends ba{constructor(t){const{event:r}=t,n=Mr(r.target);super(t,qg,n)}}ya.activators=[{eventName:"onPointerDown",handler:(e,t)=>{let{nativeEvent:r}=e,{onActivation:n}=t;return!r.isPrimary||r.button!==0?!1:(n?.({event:r}),!0)}}];const Zg={move:{name:"mousemove"},end:{name:"mouseup"}};var va;(function(e){e[e.RightClick=2]="RightClick"})(va||(va={}));class Qg extends ba{constructor(t){super(t,Zg,Mr(t.event.target))}}Qg.activators=[{eventName:"onMouseDown",handler:(e,t)=>{let{nativeEvent:r}=e,{onActivation:n}=t;return r.button===va.RightClick?!1:(n?.({event:r}),!0)}}];const wa={cancel:{name:"touchcancel"},move:{name:"touchmove"},end:{name:"touchend"}};class Jg extends ba{constructor(t){super(t,wa)}static setup(){return window.addEventListener(wa.move.name,t,{capture:!1,passive:!1}),function(){window.removeEventListener(wa.move.name,t)};function t(){}}}Jg.activators=[{eventName:"onTouchStart",handler:(e,t)=>{let{nativeEvent:r}=e,{onActivation:n}=t;const{touches:o}=r;return o.length>1?!1:(n?.({event:r}),!0)}}];var on;(function(e){e[e.Pointer=0]="Pointer",e[e.DraggableRect=1]="DraggableRect"})(on||(on={}));var jn;(function(e){e[e.TreeOrder=0]="TreeOrder",e[e.ReversedTreeOrder=1]="ReversedTreeOrder"})(jn||(jn={}));function Rg(e){let{acceleration:t,activator:r=on.Pointer,canScroll:n,draggingRect:o,enabled:a,interval:s=5,order:l=jn.TreeOrder,pointerCoordinates:f,scrollableAncestors:h,scrollableAncestorRects:d,delta:i,threshold:u}=e;const g=th({delta:i,disabled:!a}),[p,m]=ug(),w=k.useRef({x:0,y:0}),x=k.useRef({x:0,y:0}),O=k.useMemo(()=>{switch(r){case on.Pointer:return f?{top:f.y,bottom:f.y,left:f.x,right:f.x}:null;case on.DraggableRect:return o}},[r,o,f]),y=k.useRef(null),E=k.useCallback(()=>{const _=y.current;if(!_)return;const I=w.current.x*x.current.x,C=w.current.y*x.current.y;_.scrollBy(I,C)},[]),M=k.useMemo(()=>l===jn.TreeOrder?[...h].reverse():h,[l,h]);k.useEffect(()=>{if(!a||!h.length||!O){m();return}for(const _ of M){if(n?.(_)===!1)continue;const I=h.indexOf(_),C=d[I];if(!C)continue;const{direction:v,speed:N}=Hg(_,C,O,t,u);for(const A of["x","y"])g[A][v[A]]||(N[A]=0,v[A]=0);if(N.x>0||N.y>0){m(),y.current=_,p(E,s),w.current=N,x.current=v;return}}w.current={x:0,y:0},x.current={x:0,y:0},m()},[t,E,n,m,a,s,JSON.stringify(O),JSON.stringify(g),p,h,M,d,JSON.stringify(u)])}const eh={x:{[ot.Backward]:!1,[ot.Forward]:!1},y:{[ot.Backward]:!1,[ot.Forward]:!1}};function th(e){let{delta:t,disabled:r}=e;const n=ia(t);return Rr(o=>{if(r||!n||!o)return eh;const a={x:Math.sign(t.x-n.x),y:Math.sign(t.y-n.y)};return{x:{[ot.Backward]:o.x[ot.Backward]||a.x===-1,[ot.Forward]:o.x[ot.Forward]||a.x===1},y:{[ot.Backward]:o.y[ot.Backward]||a.y===-1,[ot.Forward]:o.y[ot.Forward]||a.y===1}}},[r,t,n])}function rh(e,t){const r=t!=null?e.get(t):void 0,n=r?r.node.current:null;return Rr(o=>{var a;return t==null?null:(a=n??o)!=null?a:null},[n,t])}function nh(e,t){return k.useMemo(()=>e.reduce((r,n)=>{const{sensor:o}=n,a=o.activators.map(s=>({eventName:s.eventName,handler:t(s.handler,n)}));return[...r,...a]},[]),[e,t])}var an;(function(e){e[e.Always=0]="Always",e[e.BeforeDragging=1]="BeforeDragging",e[e.WhileDragging=2]="WhileDragging"})(an||(an={}));var xa;(function(e){e.Optimized="optimized"})(xa||(xa={}));const ki=new Map;function oh(e,t){let{dragging:r,dependencies:n,config:o}=t;const[a,s]=k.useState(null),{frequency:l,measure:f,strategy:h}=o,d=k.useRef(e),i=w(),u=Jr(i),g=k.useCallback(function(x){x===void 0&&(x=[]),!u.current&&s(O=>O===null?x:O.concat(x.filter(y=>!O.includes(y))))},[u]),p=k.useRef(null),m=Rr(x=>{if(i&&!r)return ki;if(!x||x===ki||d.current!==e||a!=null){const O=new Map;for(let y of e){if(!y)continue;if(a&&a.length>0&&!a.includes(y.id)&&y.rect.current){O.set(y.id,y.rect.current);continue}const E=y.node.current,M=E?new ha(f(E),E):null;y.rect.current=M,M&&O.set(y.id,M)}return O}return x},[e,a,r,i,f]);return k.useEffect(()=>{d.current=e},[e]),k.useEffect(()=>{i||g()},[r,i]),k.useEffect(()=>{a&&a.length>0&&s(null)},[JSON.stringify(a)]),k.useEffect(()=>{i||typeof l!="number"||p.current!==null||(p.current=setTimeout(()=>{g(),p.current=null},l))},[l,i,g,...n]),{droppableRects:m,measureDroppableContainers:g,measuringScheduled:a!=null};function w(){switch(h){case an.Always:return!1;case an.BeforeDragging:return r;default:return!r}}}function Ci(e,t){return Rr(r=>e?r||(typeof t=="function"?t(e):e):null,[t,e])}function ah(e,t){return Ci(e,t)}function sh(e){let{callback:t,disabled:r}=e;const n=la(t),o=k.useMemo(()=>{if(r||typeof window>"u"||typeof window.MutationObserver>"u")return;const{MutationObserver:a}=window;return new a(n)},[n,r]);return k.useEffect(()=>()=>o?.disconnect(),[o]),o}function Bn(e){let{callback:t,disabled:r}=e;const n=la(t),o=k.useMemo(()=>{if(r||typeof window>"u"||typeof window.ResizeObserver>"u")return;const{ResizeObserver:a}=window;return new a(n)},[r]);return k.useEffect(()=>()=>o?.disconnect(),[o]),o}function lh(e){return new ha(Ir(e),e)}function Si(e,t,r){t===void 0&&(t=lh);const[n,o]=k.useState(null);function a(){o(f=>{if(!e)return null;if(e.isConnected===!1){var h;return(h=f??r)!=null?h:null}const d=t(e);return JSON.stringify(f)===JSON.stringify(d)?f:d})}const s=sh({callback(f){if(e)for(const h of f){const{type:d,target:i}=h;if(d==="childList"&&i instanceof HTMLElement&&i.contains(e)){a();break}}}}),l=Bn({callback:a});return Yt(()=>{a(),e?(l?.observe(e),s?.observe(document.body,{childList:!0,subtree:!0})):(l?.disconnect(),s?.disconnect())},[e]),n}function ih(e){const t=Ci(e);return di(e,t)}const _i=[];function ch(e){const t=k.useRef(e),r=Rr(n=>e?n&&n!==_i&&e&&t.current&&e.parentNode===t.current.parentNode?n:Gn(e):_i,[e]);return k.useEffect(()=>{t.current=e},[e]),r}function dh(e){const[t,r]=k.useState(null),n=k.useRef(e),o=k.useCallback(a=>{const s=fa(a.target);s&&r(l=>l?(l.set(s,ga(s)),new Map(l)):null)},[]);return k.useEffect(()=>{const a=n.current;if(e!==a){s(a);const l=e.map(f=>{const h=fa(f);return h?(h.addEventListener("scroll",o,{passive:!0}),[h,ga(h)]):null}).filter(f=>f!=null);r(l.length?new Map(l):null),n.current=e}return()=>{s(e),s(a)};function s(l){l.forEach(f=>{const h=fa(f);h?.removeEventListener("scroll",o)})}},[o,e]),k.useMemo(()=>e.length?t?Array.from(t.values()).reduce((a,s)=>Or(a,s),Gt):bi(e):Gt,[e,t])}function Ei(e,t){t===void 0&&(t=[]);const r=k.useRef(null);return k.useEffect(()=>{r.current=null},t),k.useEffect(()=>{const n=e!==Gt;n&&!r.current&&(r.current=e),!n&&r.current&&(r.current=null)},[e]),r.current?tn(e,r.current):Gt}function uh(e){k.useEffect(()=>{if(!Un)return;const t=e.map(r=>{let{sensor:n}=r;return n.setup==null?void 0:n.setup()});return()=>{for(const r of t)r?.()}},e.map(t=>{let{sensor:r}=t;return r}))}function fh(e,t){return k.useMemo(()=>e.reduce((r,n)=>{let{eventName:o,handler:a}=n;return r[o]=s=>{a(s,t)},r},{}),[e,t])}function Ti(e){return k.useMemo(()=>e?Fg(e):null,[e])}const Ni=[];function gh(e,t){t===void 0&&(t=Ir);const[r]=e,n=Ti(r?yt(r):null),[o,a]=k.useState(Ni);function s(){a(()=>e.length?e.map(f=>pi(f)?n:new ha(t(f),f)):Ni)}const l=Bn({callback:s});return Yt(()=>{l?.disconnect(),s(),e.forEach(f=>l?.observe(f))},[e]),o}function hh(e){if(!e)return null;if(e.children.length>1)return e;const t=e.children[0];return Qr(t)?t:e}function ph(e){let{measure:t}=e;const[r,n]=k.useState(null),o=k.useCallback(h=>{for(const{target:d}of h)if(Qr(d)){n(i=>{const u=t(d);return i?{...i,width:u.width,height:u.height}:u});break}},[t]),a=Bn({callback:o}),s=k.useCallback(h=>{const d=hh(h);a?.disconnect(),d&&a?.observe(d),n(d?t(d):null)},[t,a]),[l,f]=zn(s);return k.useMemo(()=>({nodeRef:l,rect:r,setRef:f}),[r,l,f])}const mh=[{sensor:ya,options:{}},{sensor:ma,options:{}}],bh={current:{}},Wn={draggable:{measure:ui},droppable:{measure:ui,strategy:an.WhileDragging,frequency:xa.Optimized},dragOverlay:{measure:Ir}};class sn extends Map{get(t){var r;return t!=null&&(r=super.get(t))!=null?r:void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(t=>{let{disabled:r}=t;return!r})}getNodeFor(t){var r,n;return(r=(n=this.get(t))==null?void 0:n.node.current)!=null?r:void 0}}const yh={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new sn,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:Hn},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:Wn,measureDroppableContainers:Hn,windowRect:null,measuringScheduled:!1},vh={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:""},dispatch:Hn,draggableNodes:new Map,over:null,measureDroppableContainers:Hn},Kn=k.createContext(vh),Ai=k.createContext(yh);function wh(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new sn}}}function xh(e,t){switch(t.type){case et.DragStart:return{...e,draggable:{...e.draggable,initialCoordinates:t.initialCoordinates,active:t.active}};case et.DragMove:return e.draggable.active==null?e:{...e,draggable:{...e.draggable,translate:{x:t.coordinates.x-e.draggable.initialCoordinates.x,y:t.coordinates.y-e.draggable.initialCoordinates.y}}};case et.DragEnd:case et.DragCancel:return{...e,draggable:{...e.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case et.RegisterDroppable:{const{element:r}=t,{id:n}=r,o=new sn(e.droppable.containers);return o.set(n,r),{...e,droppable:{...e.droppable,containers:o}}}case et.SetDroppableDisabled:{const{id:r,key:n,disabled:o}=t,a=e.droppable.containers.get(r);if(!a||n!==a.key)return e;const s=new sn(e.droppable.containers);return s.set(r,{...a,disabled:o}),{...e,droppable:{...e.droppable,containers:s}}}case et.UnregisterDroppable:{const{id:r,key:n}=t,o=e.droppable.containers.get(r);if(!o||n!==o.key)return e;const a=new sn(e.droppable.containers);return a.delete(r),{...e,droppable:{...e.droppable,containers:a}}}default:return e}}function kh(e){let{disabled:t}=e;const{active:r,activatorEvent:n,draggableNodes:o}=k.useContext(Kn),a=ia(n),s=ia(r?.id);return k.useEffect(()=>{if(!t&&!n&&a&&s!=null){if(!da(a)||document.activeElement===a.target)return;const l=o.get(s);if(!l)return;const{activatorNode:f,node:h}=l;if(!f.current&&!h.current)return;requestAnimationFrame(()=>{for(const d of[f.current,h.current]){if(!d)continue;const i=hg(d);if(i){i.focus();break}}})}},[n,t,o,s,a]),null}function Ch(e,t){let{transform:r,...n}=t;return e!=null&&e.length?e.reduce((o,a)=>a({transform:o,...n}),r):r}function Sh(e){return k.useMemo(()=>({draggable:{...Wn.draggable,...e?.draggable},droppable:{...Wn.droppable,...e?.droppable},dragOverlay:{...Wn.dragOverlay,...e?.dragOverlay}}),[e?.draggable,e?.droppable,e?.dragOverlay])}function _h(e){let{activeNode:t,measure:r,initialRect:n,config:o=!0}=e;const a=k.useRef(!1),{x:s,y:l}=typeof o=="boolean"?{x:o,y:o}:o;Yt(()=>{if(!s&&!l||!t){a.current=!1;return}if(a.current||!n)return;const h=t?.node.current;if(!h||h.isConnected===!1)return;const d=r(h),i=di(d,n);if(s||(i.x=0),l||(i.y=0),a.current=!0,Math.abs(i.x)>0||Math.abs(i.y)>0){const u=fi(h);u&&u.scrollBy({top:i.y,left:i.x})}},[t,s,l,n,r])}const Mi=k.createContext({...Gt,scaleX:1,scaleY:1});var tr;(function(e){e[e.Uninitialized=0]="Uninitialized",e[e.Initializing=1]="Initializing",e[e.Initialized=2]="Initialized"})(tr||(tr={}));const Eh=k.memo(function(t){var r,n,o,a;let{id:s,accessibility:l,autoScroll:f=!0,children:h,sensors:d=mh,collisionDetection:i=Ag,measuring:u,modifiers:g,...p}=t;const m=k.useReducer(xh,void 0,wh),[w,x]=m,[O,y]=wg(),[E,M]=k.useState(tr.Uninitialized),_=E===tr.Initialized,{draggable:{active:I,nodes:C,translate:v},droppable:{containers:N}}=w,A=I!=null?C.get(I):null,P=k.useRef({initial:null,translated:null}),D=k.useMemo(()=>{var Ee;return I!=null?{id:I,data:(Ee=A?.data)!=null?Ee:bh,rect:P}:null},[I,A]),L=k.useRef(null),[U,S]=k.useState(null),[b,$]=k.useState(null),F=Jr(p,Object.values(p)),G=en("DndDescribedBy",s),Y=k.useMemo(()=>N.getEnabled(),[N]),B=Sh(u),{droppableRects:V,measureDroppableContainers:j,measuringScheduled:H}=oh(Y,{dragging:_,dependencies:[v.x,v.y],config:B.droppable}),q=rh(C,I),ue=k.useMemo(()=>b?ua(b):null,[b]),te=je(),fe=ah(q,B.draggable.measure);_h({activeNode:I!=null?C.get(I):null,config:te.layoutShiftCompensation,initialRect:fe,measure:B.draggable.measure});const R=Si(q,B.draggable.measure,fe),ke=Si(q?q.parentElement:null),me=k.useRef({activatorEvent:null,active:null,activeNode:q,collisionRect:null,collisions:null,droppableRects:V,draggableNodes:C,draggingNode:null,draggingNodeRect:null,droppableContainers:N,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),Ge=N.getNodeFor((r=me.current.over)==null?void 0:r.id),De=ph({measure:B.dragOverlay.measure}),ye=(n=De.nodeRef.current)!=null?n:q,Me=_?(o=De.rect)!=null?o:R:null,Ce=!!(De.nodeRef.current&&De.rect),we=ih(Ce?null:R),$e=Ti(ye?yt(ye):null),Le=ch(_?Ge??q:null),K=gh(Le),re=Ch(g,{transform:{x:v.x-we.x,y:v.y-we.y,scaleX:1,scaleY:1},activatorEvent:b,active:D,activeNodeRect:R,containerNodeRect:ke,draggingNodeRect:Me,over:me.current.over,overlayNodeRect:De.rect,scrollableAncestors:Le,scrollableAncestorRects:K,windowRect:$e}),oe=ue?Or(ue,v):null,ae=dh(Le),be=Ei(ae),xe=Ei(ae,[R]),He=Or(re,be),Pe=Me?Ig(Me,re):null,Ke=D&&Pe?i({active:D,collisionRect:Pe,droppableRects:V,droppableContainers:Y,pointerCoordinates:oe}):null,Oe=ii(Ke,"id"),[X,se]=k.useState(null),ie=Ce?re:Or(re,xe),le=Mg(ie,(a=X?.rect)!=null?a:null,R),ne=k.useRef(null),Te=k.useCallback((Ee,he)=>{let{sensor:Ne,options:Ve}=he;if(L.current==null)return;const Fe=C.get(L.current);if(!Fe)return;const Be=Ee.nativeEvent,Ze=new Ne({active:L.current,activeNode:Fe,event:Be,options:Ve,context:me,onAbort(qe){if(!C.get(qe))return;const{onDragAbort:_t}=F.current,Bt={id:qe};_t?.(Bt),O({type:"onDragAbort",event:Bt})},onPending(qe,jt,_t,Bt){if(!C.get(qe))return;const{onDragPending:Et}=F.current,Wt={id:qe,constraint:jt,initialCoordinates:_t,offset:Bt};Et?.(Wt),O({type:"onDragPending",event:Wt})},onStart(qe){const jt=L.current;if(jt==null)return;const _t=C.get(jt);if(!_t)return;const{onDragStart:Bt}=F.current,dt={activatorEvent:Be,active:{id:jt,data:_t.data,rect:P}};Jt.unstable_batchedUpdates(()=>{Bt?.(dt),M(tr.Initializing),x({type:et.DragStart,initialCoordinates:qe,active:jt}),O({type:"onDragStart",event:dt}),S(ne.current),$(Be)})},onMove(qe){x({type:et.DragMove,coordinates:qe})},onEnd:qt(et.DragEnd),onCancel:qt(et.DragCancel)});ne.current=Ze;function qt(qe){return async function(){const{active:_t,collisions:Bt,over:dt,scrollAdjustedTranslate:Et}=me.current;let Wt=null;if(_t&&Et){const{cancelDrop:nr}=F.current;Wt={activatorEvent:Be,active:_t,collisions:Bt,delta:Et,over:dt},qe===et.DragEnd&&typeof nr=="function"&&await Promise.resolve(nr(Wt))&&(qe=et.DragCancel)}L.current=null,Jt.unstable_batchedUpdates(()=>{x({type:qe}),M(tr.Uninitialized),se(null),S(null),$(null),ne.current=null;const nr=qe===et.DragEnd?"onDragEnd":"onDragCancel";if(Wt){const mr=F.current[nr];mr?.(Wt),O({type:nr,event:Wt})}})}}},[C]),ve=k.useCallback((Ee,he)=>(Ne,Ve)=>{const Fe=Ne.nativeEvent,Be=C.get(Ve);if(L.current!==null||!Be||Fe.dndKit||Fe.defaultPrevented)return;const Ze={active:Be};Ee(Ne,he.options,Ze)===!0&&(Fe.dndKit={capturedBy:he.sensor},L.current=Ve,Te(Ne,he))},[C,Te]),Se=nh(d,ve);uh(d),Yt(()=>{R&&E===tr.Initializing&&M(tr.Initialized)},[R,E]),k.useEffect(()=>{const{onDragMove:Ee}=F.current,{active:he,activatorEvent:Ne,collisions:Ve,over:Fe}=me.current;if(!he||!Ne)return;const Be={active:he,activatorEvent:Ne,collisions:Ve,delta:{x:He.x,y:He.y},over:Fe};Jt.unstable_batchedUpdates(()=>{Ee?.(Be),O({type:"onDragMove",event:Be})})},[He.x,He.y]),k.useEffect(()=>{const{active:Ee,activatorEvent:he,collisions:Ne,droppableContainers:Ve,scrollAdjustedTranslate:Fe}=me.current;if(!Ee||L.current==null||!he||!Fe)return;const{onDragOver:Be}=F.current,Ze=Ve.get(Oe),qt=Ze&&Ze.rect.current?{id:Ze.id,rect:Ze.rect.current,data:Ze.data,disabled:Ze.disabled}:null,qe={active:Ee,activatorEvent:he,collisions:Ne,delta:{x:Fe.x,y:Fe.y},over:qt};Jt.unstable_batchedUpdates(()=>{se(qt),Be?.(qe),O({type:"onDragOver",event:qe})})},[Oe]),Yt(()=>{me.current={activatorEvent:b,active:D,activeNode:q,collisionRect:Pe,collisions:Ke,droppableRects:V,draggableNodes:C,draggingNode:ye,draggingNodeRect:Me,droppableContainers:N,over:X,scrollableAncestors:Le,scrollAdjustedTranslate:He},P.current={initial:Me,translated:Pe}},[D,q,Ke,Pe,C,ye,Me,V,N,X,Le,He]),Rg({...te,delta:v,draggingRect:Pe,pointerCoordinates:oe,scrollableAncestors:Le,scrollableAncestorRects:K});const _e=k.useMemo(()=>({active:D,activeNode:q,activeNodeRect:R,activatorEvent:b,collisions:Ke,containerNodeRect:ke,dragOverlay:De,draggableNodes:C,droppableContainers:N,droppableRects:V,over:X,measureDroppableContainers:j,scrollableAncestors:Le,scrollableAncestorRects:K,measuringConfiguration:B,measuringScheduled:H,windowRect:$e}),[D,q,R,b,Ke,ke,De,C,N,V,X,j,Le,K,B,H,$e]),Ue=k.useMemo(()=>({activatorEvent:b,activators:Se,active:D,activeNodeRect:R,ariaDescribedById:{draggable:G},dispatch:x,draggableNodes:C,over:X,measureDroppableContainers:j}),[b,Se,D,R,x,G,C,X,j]);return k.createElement(ni.Provider,{value:y},k.createElement(Kn.Provider,{value:Ue},k.createElement(Ai.Provider,{value:_e},k.createElement(Mi.Provider,{value:le},h)),k.createElement(kh,{disabled:l?.restoreFocus===!1})),k.createElement(Cg,{...l,hiddenTextDescribedById:G}));function je(){const Ee=U?.autoScrollEnabled===!1,he=typeof f=="object"?f.enabled===!1:f===!1,Ne=_&&!Ee&&!he;return typeof f=="object"?{...f,enabled:Ne}:{enabled:Ne}}}),Th=k.createContext(null),Oi="button",Nh="Draggable";function Ah(e){let{id:t,data:r,disabled:n=!1,attributes:o}=e;const a=en(Nh),{activators:s,activatorEvent:l,active:f,activeNodeRect:h,ariaDescribedById:d,draggableNodes:i,over:u}=k.useContext(Kn),{role:g=Oi,roleDescription:p="draggable",tabIndex:m=0}=o??{},w=f?.id===t,x=k.useContext(w?Mi:Th),[O,y]=zn(),[E,M]=zn(),_=fh(s,t),I=Jr(r);Yt(()=>(i.set(t,{id:t,key:a,node:O,activatorNode:E,data:I}),()=>{const v=i.get(t);v&&v.key===a&&i.delete(t)}),[i,t]);const C=k.useMemo(()=>({role:g,tabIndex:m,"aria-disabled":n,"aria-pressed":w&&g===Oi?!0:void 0,"aria-roledescription":p,"aria-describedby":d.draggable}),[n,g,m,w,p,d.draggable]);return{active:f,activatorEvent:l,activeNodeRect:h,attributes:C,isDragging:w,listeners:n?void 0:_,node:O,over:u,setNodeRef:y,setActivatorNodeRef:M,transform:x}}function Mh(){return k.useContext(Ai)}const Oh="Droppable",Ih={timeout:25};function Dh(e){let{data:t,disabled:r=!1,id:n,resizeObserverConfig:o}=e;const a=en(Oh),{active:s,dispatch:l,over:f,measureDroppableContainers:h}=k.useContext(Kn),d=k.useRef({disabled:r}),i=k.useRef(!1),u=k.useRef(null),g=k.useRef(null),{disabled:p,updateMeasurementsFor:m,timeout:w}={...Ih,...o},x=Jr(m??n),O=k.useCallback(()=>{if(!i.current){i.current=!0;return}g.current!=null&&clearTimeout(g.current),g.current=setTimeout(()=>{h(Array.isArray(x.current)?x.current:[x.current]),g.current=null},w)},[w]),y=Bn({callback:O,disabled:p||!s}),E=k.useCallback((C,v)=>{y&&(v&&(y.unobserve(v),i.current=!1),C&&y.observe(C))},[y]),[M,_]=zn(E),I=Jr(t);return k.useEffect(()=>{!y||!M.current||(y.disconnect(),i.current=!1,y.observe(M.current))},[M,y]),k.useEffect(()=>(l({type:et.RegisterDroppable,element:{id:n,key:a,disabled:r,node:M,rect:u,data:I}}),()=>l({type:et.UnregisterDroppable,key:a,id:n})),[n]),k.useEffect(()=>{r!==d.current.disabled&&(l({type:et.SetDroppableDisabled,id:n,key:a,disabled:r}),d.current.disabled=r)},[n,a,r,l]),{active:s,rect:u,isOver:f?.id===n,node:M,over:f,setNodeRef:_}}function ka(e,t,r){const n=e.slice();return n.splice(r<0?n.length+r:r,0,n.splice(t,1)[0]),n}function Lh(e,t){return e.reduce((r,n,o)=>{const a=t.get(n);return a&&(r[o]=a),r},Array(e.length))}function Vn(e){return e!==null&&e>=0}function Ph(e,t){if(e===t)return!0;if(e.length!==t.length)return!1;for(let r=0;r{let{rects:t,activeIndex:r,overIndex:n,index:o}=e;const a=ka(t,n,r),s=t[o],l=a[o];return!l||!s?null:{x:l.left-s.left,y:l.top-s.top,scaleX:l.width/s.width,scaleY:l.height/s.height}},Ii="Sortable",Di=k.createContext({activeIndex:-1,containerId:Ii,disableTransforms:!1,items:[],overIndex:-1,useDragOverlay:!1,sortedRects:[],strategy:Yn,disabled:{draggable:!1,droppable:!1}});function Li(e){let{children:t,id:r,items:n,strategy:o=Yn,disabled:a=!1}=e;const{active:s,dragOverlay:l,droppableRects:f,over:h,measureDroppableContainers:d}=Mh(),i=en(Ii,r),u=l.rect!==null,g=k.useMemo(()=>n.map(_=>typeof _=="object"&&"id"in _?_.id:_),[n]),p=s!=null,m=s?g.indexOf(s.id):-1,w=h?g.indexOf(h.id):-1,x=k.useRef(g),O=!Ph(g,x.current),y=w!==-1&&m===-1||O,E=Fh(a);Yt(()=>{O&&p&&d(g)},[O,g,p,d]),k.useEffect(()=>{x.current=g},[g]);const M=k.useMemo(()=>({activeIndex:m,containerId:i,disabled:E,disableTransforms:y,items:g,overIndex:w,useDragOverlay:u,sortedRects:Lh(g,f),strategy:o}),[m,i,E.draggable,E.droppable,y,g,w,f,u,o]);return k.createElement(Di.Provider,{value:M},t)}const Pi=e=>{let{id:t,items:r,activeIndex:n,overIndex:o}=e;return ka(r,n,o).indexOf(t)},Fi=e=>{let{containerId:t,isSorting:r,wasDragging:n,index:o,items:a,newIndex:s,previousItems:l,previousContainerId:f,transition:h}=e;return!h||!n||l!==a&&o===s?!1:r?!0:s!==o&&t===f},$h={duration:200,easing:"ease"},$i="transform",Uh=rn.Transition.toString({property:$i,duration:0,easing:"linear"}),zh={roleDescription:"sortable"};function Hh(e){let{disabled:t,index:r,node:n,rect:o}=e;const[a,s]=k.useState(null),l=k.useRef(r);return Yt(()=>{if(!t&&r!==l.current&&n.current){const f=o.current;if(f){const h=Ir(n.current,{ignoreTransform:!0}),d={x:f.left-h.left,y:f.top-h.top,scaleX:f.width/h.width,scaleY:f.height/h.height};(d.x||d.y)&&s(d)}}r!==l.current&&(l.current=r)},[t,r,n,o]),k.useEffect(()=>{a&&s(null)},[a]),a}function Ui(e){let{animateLayoutChanges:t=Fi,attributes:r,disabled:n,data:o,getNewIndex:a=Pi,id:s,strategy:l,resizeObserverConfig:f,transition:h=$h}=e;const{items:d,containerId:i,activeIndex:u,disabled:g,disableTransforms:p,sortedRects:m,overIndex:w,useDragOverlay:x,strategy:O}=k.useContext(Di),y=Gh(n,g),E=d.indexOf(s),M=k.useMemo(()=>({sortable:{containerId:i,index:E,items:d},...o}),[i,o,E,d]),_=k.useMemo(()=>d.slice(d.indexOf(s)),[d,s]),{rect:I,node:C,isOver:v,setNodeRef:N}=Dh({id:s,data:M,disabled:y.droppable,resizeObserverConfig:{updateMeasurementsFor:_,...f}}),{active:A,activatorEvent:P,activeNodeRect:D,attributes:L,setNodeRef:U,listeners:S,isDragging:b,over:$,setActivatorNodeRef:F,transform:G}=Ah({id:s,data:M,attributes:{...zh,...r},disabled:y.draggable}),Y=dg(N,U),B=!!A,V=B&&!p&&Vn(u)&&Vn(w),j=!x&&b,H=j&&V?G:null,ue=V?H??(l??O)({rects:m,activeNodeRect:D,activeIndex:u,overIndex:w,index:E}):null,te=Vn(u)&&Vn(w)?a({id:s,items:d,activeIndex:u,overIndex:w}):E,fe=A?.id,R=k.useRef({activeId:fe,items:d,newIndex:te,containerId:i}),ke=d!==R.current.items,me=t({active:A,containerId:i,isDragging:b,isSorting:B,id:s,index:E,items:d,newIndex:R.current.newIndex,previousItems:R.current.items,previousContainerId:R.current.containerId,transition:h,wasDragging:R.current.activeId!=null}),Ge=Hh({disabled:!me,index:E,node:C,rect:I});return k.useEffect(()=>{B&&R.current.newIndex!==te&&(R.current.newIndex=te),i!==R.current.containerId&&(R.current.containerId=i),d!==R.current.items&&(R.current.items=d)},[B,te,i,d]),k.useEffect(()=>{if(fe===R.current.activeId)return;if(fe!=null&&R.current.activeId==null){R.current.activeId=fe;return}const ye=setTimeout(()=>{R.current.activeId=fe},50);return()=>clearTimeout(ye)},[fe]),{active:A,activeIndex:u,attributes:L,data:M,rect:I,index:E,newIndex:te,items:d,isOver:v,isSorting:B,isDragging:b,listeners:S,node:C,overIndex:w,over:$,setNodeRef:Y,setActivatorNodeRef:F,setDroppableNodeRef:N,setDraggableNodeRef:U,transform:Ge??ue,transition:De()};function De(){if(Ge||ke&&R.current.newIndex===E)return Uh;if(!(j&&!da(P)||!h)&&(B||me))return rn.Transition.toString({...h,property:$i})}}function Gh(e,t){var r,n;return typeof e=="boolean"?{draggable:e,droppable:!1}:{draggable:(r=e?.draggable)!=null?r:t.draggable,droppable:(n=e?.droppable)!=null?n:t.droppable}}function ln(e){if(!e)return!1;const t=e.data.current;return!!(t&&"sortable"in t&&typeof t.sortable=="object"&&"containerId"in t.sortable&&"items"in t.sortable&&"index"in t.sortable)}const jh=[ze.Down,ze.Right,ze.Up,ze.Left],zi=(e,t)=>{let{context:{active:r,collisionRect:n,droppableRects:o,droppableContainers:a,over:s,scrollableAncestors:l}}=t;if(jh.includes(e.code)){if(e.preventDefault(),!r||!n)return;const f=[];a.getEnabled().forEach(i=>{if(!i||i!=null&&i.disabled)return;const u=o.get(i.id);if(u)switch(e.code){case ze.Down:n.topu.top&&f.push(i);break;case ze.Left:n.left>u.left&&f.push(i);break;case ze.Right:n.left1&&(d=h[1].id),d!=null){const i=a.get(r.id),u=a.get(d),g=u?o.get(u.id):null,p=u?.node.current;if(p&&g&&i&&u){const w=Gn(p).some((_,I)=>l[I]!==_),x=Hi(i,u),O=Bh(i,u),y=w||!x?{x:0,y:0}:{x:O?n.width-g.width:0,y:O?n.height-g.height:0},E={x:g.left,y:g.top};return y.x&&y.y?E:tn(E,y)}}}};function Hi(e,t){return!ln(e)||!ln(t)?!1:e.data.current.sortable.containerId===t.data.current.sortable.containerId}function Bh(e,t){return!ln(e)||!ln(t)||!Hi(e,t)?!1:e.data.current.sortable.index{const{attributes:l,listeners:f,setNodeRef:h,transform:d,transition:i,isDragging:u}=Ui({id:"hash"in e?e.hash:e.id}),g={transform:rn.Transform.toString(d),transition:i,opacity:u?.5:1},p="status"in e&&e.status!==void 0,m=p?e.status:"done",w=m==="uploading",x=m==="compressing",O=m==="error",y=p?e.progress:100,E=p?e.preview:void 0,M=p?e.mime_type?.startsWith("image/")??!1:e.is_image,[_,I]=k.useState(void 0),C=!p&&M?e.download_url:void 0;k.useEffect(()=>{if(!C){I(void 0);return}let N=!0,A;return(async()=>{try{const D=await Kh.api.get(C,{responseType:"blob"});N&&D&&(A=URL.createObjectURL(D),I(A))}catch(D){console.error("Failed to load authenticated image:",D)}})(),()=>{N=!1,A&&URL.revokeObjectURL(A)}},[C]);const v=_;return c.jsxs(W,{ref:h,style:g,className:"relative group bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden",children:[c.jsxs(W,{className:`aspect-square w-full flex items-center justify-center bg-gray-50 dark:bg-gray-900 relative ${M||!p?"cursor-pointer":""}`,onClick:()=>{w||x||(M&&n?n():!p&&o&&o())},children:[E||v?c.jsx(Lt,{src:E||v,alt:e.original_filename,className:"w-full h-full object-cover"}):c.jsx(Ct,{className:`fa-solid ${Ql(e.mime_type)} text-4xl text-gray-400 dark:text-gray-500`}),(w||x)&&c.jsxs(W,{className:"absolute inset-0 bg-black/50 flex flex-col items-center justify-center",children:[c.jsx(W,{className:"w-3/4 h-2 bg-gray-700 rounded-full overflow-hidden",children:c.jsx(W,{className:"h-full bg-blue-500 transition-all",style:{width:`${y}%`}})}),c.jsxs(ee,{className:"text-white text-xs mt-1",children:[y,"%"]})]}),O&&c.jsx(W,{className:"absolute inset-0 bg-red-500/50 flex items-center justify-center",children:c.jsx(Ct,{className:"fa-solid fa-exclamation-triangle text-2xl text-white"})}),s&&c.jsx(Q,{type:"button",onClick:N=>{N.stopPropagation(),s()},className:`absolute top-1.5 left-1.5 z-10 p-1 rounded-full transition-colors ${a?"bg-yellow-500 text-white":"bg-gray-800/50 text-gray-300 hover:bg-yellow-500 hover:text-white opacity-0 group-hover:opacity-100"}`,title:Re(a?"attachment.primary_image":"attachment.set_as_primary"),children:c.jsx(Ct,{className:"fa-solid fa-star text-xs"})}),c.jsxs(W,{className:"absolute inset-0 bg-black/0 group-hover:bg-black/40 transition-colors flex items-start justify-end p-1 gap-1 opacity-0 group-hover:opacity-100",children:[c.jsx(Q,{type:"button",...l,...f,className:"p-1.5 bg-white/90 dark:bg-gray-800/90 rounded text-gray-600 dark:text-gray-300 hover:bg-white cursor-grab active:cursor-grabbing",title:Re("attachment.drag_to_reorder"),onClick:N=>N.stopPropagation(),children:c.jsx(Ct,{className:"fa-solid fa-grip-vertical text-sm"})}),!p&&o&&c.jsx(Q,{type:"button",onClick:N=>{N.stopPropagation(),o()},className:"p-1.5 bg-white/90 dark:bg-gray-800/90 rounded text-blue-500 hover:bg-white",title:Re("common.download"),children:c.jsx(Ct,{className:"fa-solid fa-download text-sm"})}),O&&r&&c.jsx(Q,{type:"button",onClick:N=>{N.stopPropagation(),r()},className:"p-1.5 bg-white/90 dark:bg-gray-800/90 rounded text-orange-500 hover:bg-white",title:Re("common.retry"),children:c.jsx(Ct,{className:"fa-solid fa-arrow-rotate-right text-sm"})}),c.jsx(Q,{type:"button",onClick:N=>{N.stopPropagation(),t()},disabled:w||x,className:"p-1.5 bg-white/90 dark:bg-gray-800/90 rounded text-red-500 hover:bg-white disabled:opacity-50",title:Re("common.delete"),children:c.jsx(Ct,{className:"fa-solid fa-times text-sm"})})]})]}),c.jsxs(W,{className:`p-2 ${!p&&o?"cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700":""}`,onClick:()=>{!p&&o&&o()},children:[c.jsx(Dt,{className:"text-xs font-medium text-gray-900 dark:text-white truncate",title:e.original_filename,children:e.original_filename}),c.jsx(Dt,{className:"text-xs text-gray-500 dark:text-gray-400",children:e.size_formatted})]})]})},ji=({allItems:e,canAddMore:t,totalCount:r,maxFiles:n,maxSize:o,accept:a,onRemove:s,onRetry:l,onImageClick:f,onDownload:h,onDragEnd:d,onAddClick:i,enablePrimarySelection:u,primaryFileId:g,onPrimaryChange:p})=>{const m=Sg(oi(ya,{activationConstraint:{distance:8}}),oi(ma,{coordinateGetter:zi}));return c.jsxs(W,{className:"p-3",children:[c.jsx(Eh,{sensors:m,collisionDetection:Eg,onDragEnd:d,children:c.jsx(Li,{items:e.map(w=>"hash"in w?w.hash:w.id),strategy:Yn,children:c.jsxs(W,{className:"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-3",children:[e.map(w=>{const x="hash"in w,O=x?w.is_image:w.mime_type?.startsWith("image/")??!1;return c.jsx(Gi,{file:w,onRemove:()=>s(w),onRetry:"status"in w&&w.status==="error"?()=>l(w):void 0,onImageClick:O?()=>f(w):void 0,onDownload:x?()=>h(w):void 0,isPrimary:u&&x&&(w.hash||w.id)===g,onPrimaryClick:u&&x?()=>p?.(w.hash||w.id):void 0},x?w.hash:w.id)}),t&&c.jsxs(W,{className:"aspect-square flex flex-col items-center justify-center border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg cursor-pointer hover:border-gray-400 dark:hover:border-gray-500 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors",onClick:i,children:[c.jsx(Ct,{className:"fa-solid fa-plus text-2xl text-gray-400 dark:text-gray-500 mb-1"}),c.jsx(ee,{className:"text-xs text-gray-500 dark:text-gray-400",children:Re("common.add")})]})]})})}),c.jsxs(W,{className:"mt-3 pt-3 border-t border-gray-200 dark:border-gray-700 flex justify-between items-center text-xs text-gray-500 dark:text-gray-400",children:[c.jsx(ee,{children:Re("attachment.attached_count",{count:r,max:n})}),c.jsxs(ee,{children:[Re("attachment.max_size",{size:o}),a&&` (${a})`]})]})]})},Vh=[],Yh=[],Xn=k.forwardRef(({uploadTriggerEvent:e,attachmentableType:t,attachmentableId:r,collection:n="default",maxFiles:o=10,maxSize:a=10,maxConcurrentUploads:s=3,accept:l,imageCompression:f,roleIds:h=Yh,autoUpload:d=!0,onFilesChange:i,onChange:u,onUploadComplete:g,onUploadError:p,onRemove:m,onReorder:w,initialFiles:x=Vh,className:O="",confirmBeforeRemove:y=!1,confirmRemoveTitle:E,confirmRemoveMessage:M,apiEndpoints:_,uploadParams:I,enablePrimarySelection:C=!1,primaryFileId:v,onPrimaryChange:N,id:A,editorAttrs:P},D)=>{const L={upload:_?.upload??"/api/attachments",delete:_?.delete??"/api/attachments/:id",reorder:_?.reorder??"/api/attachments/reorder"},U=k.useRef(u??i);U.current=u??i;const S=k.useCallback(G=>{const Y=U.current;if(!Y)return;Y({target:{value:G,files:G},preventDefault:()=>{},stopPropagation:()=>{}})},[]),b=Jl({attachmentableType:t,attachmentableId:r,collection:n,maxFiles:o,maxSize:a,maxConcurrentUploads:s,accept:l,imageCompression:f,roleIds:h,autoUpload:d,initialFiles:x,endpoints:L,onFilesChange:S,onUploadComplete:g,onUploadError:p,onRemove:m,onReorder:w,uploadTriggerEvent:e,confirmBeforeRemove:y,uploadParams:I});k.useImperativeHandle(D,()=>({uploadAll:b.handleUploadAll,clear:b.clear,getPendingFiles:b.getPendingFiles}));const $=k.useMemo(()=>b.imageFiles.map(G=>{const Y=!("hash"in G),B=G,V=G;return Y?{src:B.preview||"",filename:B.original_filename,title:B.original_filename,downloadRequiresAuth:!1}:{src:b.authenticatedImageUrls.get(V.id)||V.download_url,downloadUrl:V.download_url,filename:V.original_filename,title:V.original_filename,downloadRequiresAuth:!0}}),[b.imageFiles,b.authenticatedImageUrls]),F=k.useMemo(()=>({existingFiles:b.existingFiles,pendingFiles:b.pendingFiles,isDragOver:b.isDragOver,isDeleting:b.isDeleting,maxFiles:o,maxSize:a,accept:l,endpoints:L,confirmBeforeRemove:y,totalCount:b.totalCount,hasFiles:b.hasFiles,canAddMore:b.canAddMore,allItems:b.allItems,imageFiles:b.imageFiles,handleFiles:b.handleFiles,handleRemove:b.handleRemove,handleRetry:b.handleRetry,handleUploadAll:b.handleUploadAll,handleOpenGallery:b.handleOpenGallery,handleDownload:b.handleDownload,handleDragEnd:b.handleDragEnd,setIsDragOver:b.setIsDragOver,inputRef:b.inputRef,galleryOpen:b.galleryOpen,setGalleryOpen:b.setGalleryOpen,galleryStartIndex:b.galleryStartIndex,galleryKeyRef:b.galleryKeyRef,confirmDialogOpen:b.confirmDialogOpen,setConfirmDialogOpen:b.setConfirmDialogOpen,itemToDelete:b.itemToDelete,executeRemoveAttachment:b.executeRemoveAttachment,authenticatedImageUrls:b.authenticatedImageUrls}),[b,o,a,l,L,y]);return c.jsx($l,{value:F,children:c.jsxs(W,{id:A,className:O,...P,children:[c.jsx(Rl,{isDragOver:b.isDragOver,canAddMore:b.canAddMore,onFiles:b.handleFiles,setIsDragOver:b.setIsDragOver,inputRef:b.inputRef,accept:l,maxFiles:o,maxSize:a,children:b.hasFiles&&c.jsx(ji,{allItems:b.allItems,canAddMore:b.canAddMore,totalCount:b.totalCount,maxFiles:o,maxSize:a,accept:l,onRemove:b.handleRemove,onRetry:b.handleRetry,onImageClick:b.handleOpenGallery,onDownload:b.handleDownload,onDragEnd:b.handleDragEnd,onAddClick:()=>b.inputRef.current?.click(),enablePrimarySelection:C,primaryFileId:v,onPrimaryChange:N})}),y&&c.jsx(ta,{isOpen:b.confirmDialogOpen,onClose:()=>{b.isDeleting||b.setConfirmDialogOpen(!1)},title:E??Re("attachment.delete_confirm_title"),message:M??Re("attachment.delete_confirm_message"),confirmText:Re("common.delete"),confirmButtonVariant:"danger",onConfirm:()=>{b.itemToDelete&&b.executeRemoveAttachment(b.itemToDelete)},isLoading:b.isDeleting,loadingText:Re("attachment.deleting")}),$.length>0&&b.galleryOpen&&c.jsx(Tr,{images:$,isOpen:!0,onClose:()=>b.setGalleryOpen(!1),startIndex:b.galleryStartIndex,showDownload:!0},`gallery-${b.galleryKeyRef.current}`)]})})});Xn.displayName="FileUploader";const Xh=Object.freeze(Object.defineProperty({__proto__:null,FileDropZone:Rl,FileList:ji,FileUploader:Xn,FileUploaderProvider:$l,SortableThumbnailItem:Gi,default:Xn,extractErrorMessage:Zl,fileUploaderT:Re,formatFileSize:$n,getFileIcon:Ql,useFileUploader:Jl,useFileUploaderContext:eg},Symbol.toStringTag,{value:"Module"})),Bi=({provider:e,className:t="w-5 h-5"})=>{switch(e){case"google":return c.jsxs("svg",{className:t,viewBox:"0 0 24 24",children:[c.jsx("path",{fill:"#4285F4",d:"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"}),c.jsx("path",{fill:"#34A853",d:"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"}),c.jsx("path",{fill:"#FBBC05",d:"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"}),c.jsx("path",{fill:"#EA4335",d:"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"})]});case"naver":return c.jsx("svg",{className:t,viewBox:"0 0 24 24",children:c.jsx("path",{fill:"currentColor",d:"M16.273 12.845L7.376 0H0v24h7.727V11.155L16.624 24H24V0h-7.727z"})});case"kakao":return c.jsx("svg",{className:t,viewBox:"0 0 24 24",children:c.jsx("path",{fill:"currentColor",d:"M12 3c5.799 0 10.5 3.664 10.5 8.185 0 4.52-4.701 8.184-10.5 8.184a13.5 13.5 0 0 1-1.727-.11l-4.408 2.883c-.501.265-.678.236-.472-.413l.892-3.678c-2.88-1.46-4.785-3.99-4.785-6.866C1.5 6.665 6.201 3 12 3zm5.519 8.625h-.634v2.916h-.97v-2.916h-.633v-.848h2.237v.848zm-3.294 2.916h-.97V10.77h.97v3.771zm-1.97 0h-.97v-2.77l-.658 1.53h-.629l-.665-1.53v2.77h-.97V10.77h1.13l.822 1.912.814-1.912h1.126v3.771zm-4.49 0h-.97V10.77h.97v3.771z"})});case"facebook":return c.jsx("svg",{className:t,viewBox:"0 0 24 24",children:c.jsx("path",{fill:"currentColor",d:"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"})});case"apple":return c.jsx("svg",{className:t,viewBox:"0 0 24 24",children:c.jsx("path",{fill:"currentColor",d:"M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701"})});default:return null}},Wi=(e,t)=>window.G7Core?.t?.(e,t)??e,qh=[{id:"google",name:"Google",color:"bg-white dark:bg-gray-800",textColor:"text-gray-700 dark:text-gray-300"},{id:"naver",name:"네이버",color:"bg-[#03C75A]",textColor:"text-white"},{id:"kakao",name:"카카오",color:"bg-[#FEE500]",textColor:"text-[#000000]/85"},{id:"facebook",name:"Facebook",color:"bg-[#1877F2]",textColor:"text-white"},{id:"apple",name:"Apple",color:"bg-black dark:bg-white",textColor:"text-white dark:text-black"}],Ki=({providers:e=["google","naver","kakao"],mode:t="login",variant:r="full",className:n="",id:o,editorAttrs:a})=>{const s=h=>{const d=encodeURIComponent(window.location.href);window.location.href=`/api/auth/${h}?redirect=${d}`},l=h=>t==="register"?Wi("auth.social.register_with",{provider:h}):Wi("auth.social.login_with",{provider:h}),f=qh.filter(h=>e.includes(h.id));return r==="icon"?c.jsx(W,{className:`flex justify-center gap-4 ${n}`,id:o,...a,children:f.map(h=>c.jsx(Q,{onClick:()=>s(h.id),className:`w-12 h-12 flex items-center justify-center rounded-full ${h.color} ${h.textColor} border border-gray-200 dark:border-gray-700 hover:opacity-90 transition-opacity`,"aria-label":l(h.name),children:c.jsx(Bi,{provider:h.id,className:"w-5 h-5"})},h.id))}):c.jsx(W,{className:`space-y-3 ${n}`,id:o,...a,children:f.map(h=>c.jsxs(Q,{onClick:()=>s(h.id),className:`w-full flex items-center justify-center gap-3 px-4 py-3 rounded-lg font-medium border border-gray-200 dark:border-gray-700 ${h.color} ${h.textColor} hover:opacity-90 transition-opacity`,children:[c.jsx(Bi,{provider:h.id,className:"w-5 h-5"}),c.jsx(ee,{children:l(h.name)})]},h.id))})},Zh=Object.freeze(Object.defineProperty({__proto__:null,default:Ki},Symbol.toStringTag,{value:"Module"})),Qh=(e,t)=>window.G7Core?.t?.(e,t)??e,Jh={success:Je.CheckCircle,error:Je.XCircle,warning:Je.ExclamationTriangle,info:Je.InfoCircle},Vi={success:{bg:"bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800",text:"text-green-800 dark:text-green-300"},error:{bg:"bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800",text:"text-red-800 dark:text-red-300"},warning:{bg:"bg-yellow-50 dark:bg-yellow-900/20 border-yellow-200 dark:border-yellow-800",text:"text-yellow-800 dark:text-yellow-300"},info:{bg:"bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800",text:"text-blue-800 dark:text-blue-300"}},Rh={"top-left":"top-4 left-4","top-center":"top-4 left-1/2 -translate-x-1/2","top-right":"top-4 right-4","bottom-left":"bottom-4 left-4","bottom-center":"bottom-4 left-1/2 -translate-x-1/2","bottom-right":"bottom-4 right-4"},Ca=({toasts:e,position:t="bottom-center",duration:r=3e3,onRemove:n})=>{const[o,a]=k.useState(new Map),s=k.useCallback(l=>{a(f=>{const h=new Map(f);return h.set(l,!1),h}),setTimeout(()=>{if(n)n(l);else{const f=window.G7Core;f?.state?.update&&f.state.update(h=>({toasts:(Array.isArray(h.toasts)?h.toasts:[]).filter(i=>i.id!==l)}))}},300)},[n]);return k.useEffect(()=>{!e||e.length===0||e.forEach(l=>{if(o.has(l.id))return;a(h=>{const d=new Map(h);return d.set(l.id,!0),d});const f=l.duration||r;f>0&&setTimeout(()=>{s(l.id)},f)})},[e,r,s,o]),!e||e.length===0?null:c.jsx(W,{className:`fixed z-[9999] flex flex-col gap-2 ${Rh[t]}`,"aria-live":"polite","aria-atomic":"true",children:e.map(l=>c.jsx(e0,{toast:l,position:t,isVisible:o.get(l.id)??!0,onClose:()=>s(l.id)},l.id))})},e0=({toast:e,position:t,isVisible:r,onClose:n})=>{const o=Vi[e.type]||Vi.info,a=e.icon?e.icon:Jh[e.type],s=t.startsWith("bottom")?"translate-y-2":"-translate-y-2";return c.jsxs(W,{className:` flex items-center gap-3 p-4 rounded-lg border shadow-lg min-w-[300px] max-w-md transition-all duration-300 @@ -83,4 +83,5 @@ self.addEventListener('message', async (e) => { transform: translateX(-100%); } } - `})]}):null},n0=Object.freeze(Object.defineProperty({__proto__:null,PageTransitionIndicator:Sa,default:Sa},Symbol.toStringTag,{value:"Module"})),Yi=window.G7Core?.createLogger?.("Comp:PageTransitionBlur")??{log:(...e)=>console.log("[Comp:PageTransitionBlur]",...e),warn:(...e)=>console.warn("[Comp:PageTransitionBlur]",...e)},_a=({className:e="",style:t})=>{const[r,n]=k.useState(!1);return k.useEffect(()=>{const o=window.G7Core?.TransitionManager;if(!o){Yi.warn("TransitionManager를 찾을 수 없습니다.");return}return n(o.getIsPending()),o.subscribe(s=>{Yi.log("isPending changed:",s),n(s)})},[]),r?c.jsx(W,{className:`fixed inset-0 z-40 bg-white/30 dark:bg-gray-900/30 backdrop-blur-sm transition-opacity duration-150 pointer-events-none ${e}`,style:t,role:"status","aria-label":"페이지 전환 중","data-testid":"page-transition-blur"}):null},o0=Object.freeze(Object.defineProperty({__proto__:null,PageTransitionBlur:_a,default:_a},Symbol.toStringTag,{value:"Module"})),Xi={sm:640,md:768,lg:1024,xl:1280,"2xl":1536},Zi=new Set(["hidden","block","inline-block","inline","flex","inline-flex","grid","inline-grid","table","table-row","table-cell","contents","list-item","flow-root"]),a0=new Set(["Div","Flex","Grid","Section","Article","Nav","Aside","Main","Header","Footer","Fragment","Form","Container"]),s0=new Set(["H1","H2","H3","H4","H5","H6","P","Span","Label","A","Strong","Em","Small","Badge"]),l0=new Set(["Input","Textarea","Select","Checkbox","Radio","Toggle","DatePicker","TagInput","SearchBar"]),i0=new Set(["Img","Image","Avatar","AvatarUploader","ImageGallery","ProductImageViewer","FileUploader"]),qi={DataGrid:(e,t)=>c.jsxs("div",{className:"w-full border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden",children:[c.jsx("div",{className:`h-10 bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 ${e}`,children:c.jsxs("div",{className:"flex items-center h-full px-4 gap-8",children:[c.jsx("div",{className:"h-3 w-16 bg-gray-300 dark:bg-gray-600 rounded"}),c.jsx("div",{className:"h-3 w-24 bg-gray-300 dark:bg-gray-600 rounded"}),c.jsx("div",{className:"h-3 w-20 bg-gray-300 dark:bg-gray-600 rounded"}),c.jsx("div",{className:"h-3 w-16 bg-gray-300 dark:bg-gray-600 rounded"})]})}),Array.from({length:t},(r,n)=>c.jsx("div",{className:`h-12 border-b border-gray-100 dark:border-gray-800 ${e}`,style:{animationDelay:`${n*75}ms`},children:c.jsxs("div",{className:"flex items-center h-full px-4 gap-8",children:[c.jsx("div",{className:"h-3 w-12 bg-gray-200 dark:bg-gray-700 rounded"}),c.jsx("div",{className:"h-3 flex-1 bg-gray-200 dark:bg-gray-700 rounded"}),c.jsx("div",{className:"h-3 w-16 bg-gray-100 dark:bg-gray-800 rounded"}),c.jsx("div",{className:"h-3 w-14 bg-gray-100 dark:bg-gray-800 rounded"})]})},n))]}),Pagination:e=>c.jsx("div",{className:"flex justify-center gap-1.5 py-3",children:Array.from({length:5},(t,r)=>c.jsx("div",{className:`w-8 h-8 bg-gray-200 dark:bg-gray-700 rounded ${e}`},r))}),Tabs:e=>c.jsxs("div",{children:[c.jsx("div",{className:"flex gap-4 border-b border-gray-200 dark:border-gray-700 pb-2 mb-3",children:Array.from({length:3},(t,r)=>c.jsx("div",{className:`h-4 w-20 bg-gray-200 dark:bg-gray-700 rounded ${e}`},r))}),c.jsx("div",{className:`h-32 bg-gray-100 dark:bg-gray-800 rounded ${e}`})]}),TabNavigation:e=>c.jsx("div",{className:"flex gap-4 border-b border-gray-200 dark:border-gray-700 pb-2",children:Array.from({length:3},(t,r)=>c.jsx("div",{className:`h-4 w-20 bg-gray-200 dark:bg-gray-700 rounded ${e}`},r))}),ProductCard:e=>c.jsxs("div",{className:"rounded-lg overflow-hidden",children:[c.jsx("div",{className:`h-48 w-full bg-gray-200 dark:bg-gray-700 ${e}`}),c.jsxs("div",{className:"p-3 space-y-2",children:[c.jsx("div",{className:`h-3.5 w-3/4 bg-gray-200 dark:bg-gray-700 rounded ${e}`}),c.jsx("div",{className:`h-4 w-1/3 bg-gray-300 dark:bg-gray-600 rounded ${e}`})]})]}),UserInfo:e=>c.jsx("div",{className:`h-3 w-14 bg-gray-200 dark:bg-gray-700 rounded ${e}`}),QuantitySelector:e=>c.jsx("div",{className:`h-9 w-28 bg-gray-100 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 ${e}`}),Header:e=>c.jsx("header",{className:"bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700",children:c.jsx("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",children:c.jsxs("div",{className:"flex items-center justify-between h-16",children:[c.jsxs("div",{className:"flex items-center gap-8",children:[c.jsx("div",{className:`h-8 w-24 bg-gray-200 dark:bg-gray-700 rounded ${e}`}),c.jsx("div",{className:"hidden lg:flex items-center gap-6",children:Array.from({length:4},(t,r)=>c.jsx("div",{className:`h-3.5 w-16 bg-gray-200 dark:bg-gray-700 rounded ${e}`},r))})]}),c.jsx("div",{className:"flex items-center gap-4",children:Array.from({length:3},(t,r)=>c.jsx("div",{className:`h-8 w-8 bg-gray-200 dark:bg-gray-700 rounded-full ${e}`},r))})]})})}),Footer:e=>c.jsx("footer",{className:"bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 mt-auto",children:c.jsx("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8",children:c.jsxs("div",{className:"flex flex-col items-center gap-4",children:[c.jsx("div",{className:`h-4 w-32 bg-gray-200 dark:bg-gray-700 rounded ${e}`}),c.jsx("div",{className:`h-3 w-48 bg-gray-100 dark:bg-gray-800 rounded ${e}`}),c.jsx("div",{className:"flex gap-3",children:Array.from({length:3},(t,r)=>c.jsx("div",{className:`h-6 w-6 bg-gray-200 dark:bg-gray-700 rounded-full ${e}`},r))}),c.jsx("div",{className:`h-3 w-40 bg-gray-100 dark:bg-gray-800 rounded ${e}`})]})})}),Modal:()=>c.jsx(c.Fragment,{}),Toast:()=>c.jsx(c.Fragment,{}),ConfirmDialog:()=>c.jsx(c.Fragment,{})};function c0(e){if(!e||e.length===0)return[];const t=e.filter(n=>n.if),r=e.filter(n=>!n.if);if(r.length>0&&t.length>0){const n=t.filter(o=>!Qi(o.if));return n.length>1&&d0(n)?[...r,Ji(n)]:[...r,...n]}if(t.length>1&&r.length===0){const n=t.filter(o=>!Qi(o.if));return n.length===0?[]:n.length===1?n:[Ji(n)]}return e}function Qi(e){const t=e.replace(/^\{\{|\}\}$/g,"").trim();return t.startsWith("!")||/\b(hasError|isError|isLoading|error|Error)\b/.test(t)||/===\s*0\s*(\)|\}|$)/.test(t)}function d0(e){if(e.length<2)return!1;const t=[];for(const n of e){const o=(n.if||"").replace(/^\{\{|\}\}$/g,"").trim(),a=o.match(/^(.+?)\s*===\s*['"]/);if(a)t.push(a[1].trim());else{const s=o.match(/(.+?)\s*===\s*['"]/);if(!s)return!1;t.push(s[1].trim())}}const r=t[0];return t.every(n=>n===r)}function Ji(e){return e.reduce((t,r)=>Ea(r)>Ea(t)?r:t)}function Ea(e){return e.children?e.children.length+e.children.reduce((t,r)=>t+Ea(r),0):0}function u0(e){return e.includes("{{")?e.replace(/\{\{([^}]+)\}\}/g,(t,r)=>{const n=r.match(/\?[\s]*['"]([^'"]*)['"]\s*:\s*['"]/);return n?n[1]:""}):e}function Ta(e,t){if(!e)return"";let r=e;return r=r.replace(/\b(bg-\S+|text-\S+|border\b|border-\S+|shadow\S*|ring-\S+|outline-\S+|divide-\S+|opacity-\S+|font-\S+|tracking-\S+|leading-\S+|whitespace-\S+|truncate|line-clamp-\S+|underline|no-underline|decoration-\S+|cursor-\S+|hover:\S+|focus:\S+|active:\S+|group-hover:\S+|transition\S*|duration-\S+|ease-\S+|animate-\S+|dark:\S+)\b/g,"").replace(/\s{2,}/g," ").trim(),(t==="Grid"||/\bgrid-cols-\d/.test(r))&&(r=r.replace(/\bgrid-cols-(\d+)/g,(n,o)=>{const a=parseInt(o);return a>4?`grid-cols-${Math.ceil(a/2)}`:`grid-cols-${a}`})),r}function f0(e){const{name:t,props:r}=e;if(!r||!t)return"";const n=[];if(t==="Flex"){n.push("flex");const o=r.direction||"row",a={row:"flex-row","row-reverse":"flex-row-reverse",col:"flex-col","col-reverse":"flex-col-reverse"};a[o]&&n.push(a[o]);const s=r.justify||"start",l={start:"justify-start",end:"justify-end",center:"justify-center",between:"justify-between",around:"justify-around",evenly:"justify-evenly"};l[s]&&n.push(l[s]);const f=r.align||"stretch",h={start:"items-start",end:"items-end",center:"items-center",baseline:"items-baseline",stretch:"items-stretch"};h[f]&&n.push(h[f]);const d=r.wrap||"nowrap",i={wrap:"flex-wrap",nowrap:"flex-nowrap","wrap-reverse":"flex-wrap-reverse"};i[d]&&n.push(i[d]),r.gap&&r.gap>0&&n.push(`gap-${r.gap}`)}if(t==="Grid"){n.push("grid");const o=r.cols||1;if(n.push(`grid-cols-${o}`),r.responsive){const a=r.responsive;a.sm&&n.push(`sm:grid-cols-${a.sm}`),a.md&&n.push(`md:grid-cols-${a.md}`),a.lg&&n.push(`lg:grid-cols-${a.lg}`),a.xl&&n.push(`xl:grid-cols-${a.xl}`),a["2xl"]&&n.push(`2xl:grid-cols-${a["2xl"]}`)}r.gap!==void 0&&r.gap>0&&n.push(`gap-${r.gap}`),r.rowGap!==void 0&&r.rowGap>0&&n.push(`gap-y-${r.rowGap}`),r.colGap!==void 0&&r.colGap>0&&n.push(`gap-x-${r.colGap}`)}return n.join(" ")}function g0(e){switch(e){case"pulse":return"animate-pulse";case"wave":return"animate-pulse";case"none":return"";default:return"animate-pulse"}}function Zn(e,t,r,n){return!e||e.length===0?[]:c0(e).map((a,s)=>Ri(a,t,r,s,n))}function h0(e,t){const r=e.props?.className||e.className||"";return e.responsive?t>=1024&&e.responsive.desktop?.props?.className?e.responsive.desktop.props.className:t>=768&&e.responsive.tablet?.props?.className?e.responsive.tablet.props.className:r:r}function p0(e,t){const r=e.split(/\s+/).filter(Boolean),n=[],o=[];for(const f of r){const h=f.match(/^(sm|md|lg|xl|2xl):(.+)$/);if(h){const[,d,i]=h;if(Zi.has(i)){n.push({breakpoint:Xi[d]||0,display:i});continue}(Xi[d]||0)<=t&&o.push(i);continue}if(Zi.has(f)){n.push({breakpoint:0,display:f});continue}o.push(f)}if(n.length===0)return{visible:!0,className:e};n.sort((f,h)=>f.breakpoint-h.breakpoint);let a="";for(const f of n)f.breakpoint<=t&&(a=f.display);a||(a=n[0].display);const s=a!=="hidden",l=s?[a,...o].join(" "):"";return{visible:s,className:l}}function m0(e){const t=e.match(/\bgrid-cols-\[([^\]]+)\]/);if(!t)return{className:e};const r=t[1].replace(/_/g," ");return{className:e.replace(/\bgrid-cols-\[([^\]]+)\]/,"").replace(/\s{2,}/g," ").trim(),style:{gridTemplateColumns:r}}}function Ri(e,t,r,n,o){const{name:a,children:s,iteration:l}=e,f=h0(e,o),h=f0(e),d=h?`${h} ${f}`.trim():f,i=u0(d),u=p0(i,o);if(!a||!u.visible)return null;const g=u.className;if(l)return c.jsx(k.Fragment,{children:Array.from({length:r},(m,w)=>Ri({...e,iteration:void 0},t,r,w,o))},n);if(qi[a])return c.jsx("div",{className:g,children:qi[a](t,r)},n);if(a0.has(a)){const m=Ta(g,a);if(!s||s.length===0){const E=/\b(h-\S|w-\S)/.test(m)?`${m} bg-gray-200 dark:bg-gray-700 rounded ${t}`:`${m} h-3.5 w-full bg-gray-200 dark:bg-gray-700 rounded ${t}`.trim();return c.jsx("div",{className:E},n)}const w=Zn(s,t,r,o);if(!(w.length>0&&w.some(v=>v!==null)))return null;const A=m0(m);return c.jsx("div",{className:A.className,style:A.style,children:w},n)}const p=Ta(g,a);if(s0.has(a)){const m={H1:"h-7",H2:"h-6",H3:"h-5",H4:"h-5",H5:"h-4",H6:"h-4",P:"h-3.5",Span:"h-3",Label:"h-3",A:"h-3.5",Badge:"h-5 w-16"},w={H1:"w-3/5",H2:"w-2/5",H3:"w-1/3",H4:"w-1/3",H5:"w-1/4",H6:"w-1/4",P:"w-full",Span:"w-1/4",Label:"w-1/4",A:"w-1/3",Strong:"w-1/5",Em:"w-1/4",Small:"w-1/5",Badge:"w-16"},x=m[a]||"h-3.5",A=w[a]||"w-full",v=a.startsWith("H")?"mb-2 mt-1":"mb-1.5";return c.jsx("div",{className:`${x} ${A} bg-gray-200 dark:bg-gray-700 rounded ${t} ${v} ${p}`.trim()},n)}if(l0.has(a))return a==="Textarea"?c.jsx("div",{className:`h-20 w-full bg-gray-100 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 mb-2 ${t}`},n):a==="Checkbox"||a==="Radio"||a==="Toggle"?c.jsx("div",{className:`h-5 w-5 bg-gray-200 dark:bg-gray-700 rounded mb-1.5 ${t}`},n):c.jsx("div",{className:`h-9 w-full bg-gray-100 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 mb-2 ${t}`},n);if(i0.has(a))return a==="Avatar"||a==="AvatarUploader"?c.jsx("div",{className:`h-10 w-10 bg-gray-200 dark:bg-gray-700 rounded-full ${t}`},n):a==="ProductImageViewer"?c.jsx("div",{className:`h-80 w-full bg-gray-200 dark:bg-gray-700 rounded ${t}`},n):c.jsx("div",{className:`h-40 w-full bg-gray-200 dark:bg-gray-700 rounded mb-2 ${t}`},n);if(a==="Button"){if(s&&s.length>0){const m=Ta(g,a),w=Zn(s,t,r,o);if(!(w.length>0&&w.some(E=>E!==null)))return null;const v=/\b(border|rounded|px-\d|py-\d)/.test(f)?"border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50 rounded-lg":"";return c.jsx("div",{className:`${m} ${v}`.trim(),children:w},n)}return c.jsx("div",{className:`h-9 w-24 bg-gray-200 dark:bg-gray-700 rounded ${t}`},n)}return a==="Icon"?c.jsx("div",{className:`h-5 w-5 bg-gray-200 dark:bg-gray-700 rounded ${t}`},n):s&&s.length>0?c.jsx("div",{className:p,children:Zn(s,t,r,o)},n):c.jsx("div",{className:`h-3.5 w-full bg-gray-200 dark:bg-gray-700 rounded mb-1.5 ${t}`},n)}const Na=({components:e,options:t})=>{const r=g0(t.animation),o=window.G7Core?.useResponsive,a=o?.(),s=a?a.width:typeof window<"u"?window.innerWidth:1024;return c.jsx("div",{className:"w-full",role:"status","aria-busy":"true","aria-label":"Loading...",children:Zn(e,r,t.iteration_count,s)})},b0=Object.freeze(Object.defineProperty({__proto__:null,PageSkeleton:Na,default:Na},Symbol.toStringTag,{value:"Module"})),y0=(e,t)=>window.G7Core?.t?.(e,t)??e,ec=({options:e})=>{const t=document.documentElement.classList.contains("dark"),r=t?"rgb(17,24,39)":"rgb(249,250,251)",n=t?"#6b7280":"#9ca3af",o=t?"#9ca3af":"#6b7280";return c.jsxs("div",{style:{position:"absolute",inset:0,zIndex:2147483647,overflow:"hidden",background:r,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"flex-start",paddingTop:"15%",gap:"12px"},children:[c.jsx("div",{style:{width:"32px",height:"32px",border:`3px solid ${n}`,borderTopColor:"transparent",borderRadius:"50%",animation:"g7-spin 0.8s linear infinite"}}),c.jsx("span",{style:{color:o,fontSize:"14px"},children:e?.text||y0("nav.loading")})]})},v0=Object.freeze(Object.defineProperty({__proto__:null,default:ec},Symbol.toStringTag,{value:"Module"})),Dr=(e,t)=>window.G7Core?.t?.(e,t)??e,tc=({currentPage:e,totalPages:t,onPageChange:r,maxVisiblePages:n=5,showFirstLast:o=!0,className:a="",style:s,prevText:l,nextText:f,id:h,editorAttrs:d})=>{const i=k.useMemo(()=>{const m=[];if(t<=n+2)for(let w=1;w<=t;w++)m.push(w);else{const w=Math.floor(n/2);let x=Math.max(2,e-w),A=Math.min(t-1,e+w);e<=w+1?A=n:e>=t-w&&(x=t-n+1),m.push(1),x>2&&m.push("...");for(let v=x;v<=A;v++)m.push(v);A1&&m.push(t)}return m},[e,t,n]),u=m=>{m<1||m>t||m===e||r(m)},g=()=>{e>1&&r(e-1)},p=()=>{eu(1),disabled:e===1,className:"px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800","aria-label":Dr("common.first_page"),children:"«"}),c.jsx(Q,{onClick:g,disabled:e===1,className:"px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800","aria-label":Dr("common.prev_page"),children:l||c.jsx(c.Fragment,{children:"‹"})}),c.jsx(W,{className:"flex items-center gap-1",children:i.map((m,w)=>{if(m==="...")return c.jsx(ee,{className:"px-3 py-1 text-sm text-gray-500 dark:text-gray-400",children:"..."},`ellipsis-${w}`);const x=m,A=x===e;return c.jsx(Q,{onClick:()=>u(x),className:`px-3 py-1 text-sm border rounded ${A?"bg-blue-500 dark:bg-blue-600 text-white border-blue-500 dark:border-blue-600":"border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800"}`,"aria-label":Dr("common.page_n",{n:x}),"aria-current":A?"page":void 0,children:x},x)})}),c.jsx(Q,{onClick:p,disabled:e===t,className:"px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800","aria-label":Dr("common.next_page"),children:f||c.jsx(c.Fragment,{children:"›"})}),o&&c.jsx(Q,{onClick:()=>u(t),disabled:e===t,className:"px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800","aria-label":Dr("common.last_page"),children:"»"})]})},w0=Object.freeze(Object.defineProperty({__proto__:null,Pagination:tc},Symbol.toStringTag,{value:"Module"})),rc=(e,t)=>window.G7Core?.t?.(e,t)??e,nc=({name:e="search",placeholder:t,value:r,onChange:n,onSubmit:o,showButton:a=!1,suggestions:s=[],onSuggestionClick:l,showSuggestions:f=!1,className:h="",style:d,id:i,editorAttrs:u})=>{const g=t??rc("common.search_placeholder"),[p,m]=k.useState(""),[w,x]=k.useState(!1),A=k.useRef(null),v=k.useRef(""),E=r!==void 0?r:p,O=f&&w&&s.length>0&&E.length>0;k.useEffect(()=>{r!==void 0&&(v.current=r)},[r]);const _=y=>{const N=y.target.value;m(N),n?.(y),v.current!==""&&N===""&&!y.nativeEvent.inputType&&setTimeout(()=>{const M=A.current?.querySelector("form");M&&M.requestSubmit()},0),v.current=N},I=y=>{m(y.text);const N={target:{value:y.text,name:e}};n?.(N),l?.(y),x(!1)},C=y=>{y.preventDefault(),o?.(y)};return c.jsxs(W,{ref:A,className:`relative ${h}`,style:d,id:i,...u,children:[c.jsx(so,{onSubmit:C,className:"relative",children:c.jsxs(W,{className:`relative flex items-center ${a?"gap-2":""}`,children:[c.jsxs(W,{className:"relative flex-1",children:[c.jsx(W,{className:"absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",children:c.jsx(de,{name:Je.Search,className:"w-5 h-5 text-gray-400 dark:text-gray-500"})}),c.jsx(xt,{type:"search",name:e,value:E,onChange:_,onFocus:()=>x(!0),onBlur:()=>setTimeout(()=>x(!1),200),placeholder:g,className:"w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm"})]}),a&&c.jsx(Q,{type:"submit",className:"px-4 py-2 bg-gray-800 dark:bg-gray-600 text-white rounded-lg hover:bg-gray-900 dark:hover:bg-gray-500 transition-colors text-sm font-medium cursor-pointer h-[42px]",children:rc("common.search")})]})}),O&&c.jsx(W,{className:"absolute z-10 w-full mt-2 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg max-h-64 overflow-y-auto",children:s.map(y=>c.jsx(W,{className:"px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer border-b border-gray-100 dark:border-gray-700 last:border-b-0 transition-colors",onClick:()=>I(y),children:c.jsxs(W,{className:"flex items-center gap-2",children:[c.jsx(de,{name:Je.Search,className:"w-4 h-4 text-gray-400 dark:text-gray-500"}),c.jsx(ee,{className:"text-sm text-gray-700 dark:text-gray-300",children:y.text})]})},y.id))})]})},x0=Object.freeze(Object.defineProperty({__proto__:null,SearchBar:nc},Symbol.toStringTag,{value:"Module"})),vt=window.G7Core,k0={sm:"md",md:"lg",lg:"xl",xl:"2xl","2xl":"3xl"};function Aa({src:e,fallbackText:t="U",size:r="lg",uploadEndpoint:n="/api/me/avatar",deleteEndpoint:o="/api/me/avatar",onUploadSuccess:a,onUploadError:s,onDeleteSuccess:l,onDeleteError:f,showDeleteButton:h=!0,accept:d="image/*",maxSize:i=5,className:u="",uploadButtonText:g,deleteButtonText:p,readOnly:m=!1,confirmDelete:w=!0,deleteConfirmMessage:x,confirmUpload:A=!0,uploadConfirmMessage:v,uploadSuccessActions:E,uploadErrorActions:O,deleteSuccessActions:_,deleteErrorActions:I,id:C,editorAttrs:y}){const N=k.useRef(null),[M,P]=k.useState(!1),[D,L]=k.useState(!1),[U,S]=k.useState(void 0),[b,$]=k.useState(null),[F,G]=k.useState(!1),[Y,B]=k.useState(!1),[V,j]=k.useState(null),[H,Z]=k.useState(null),ue=k.useRef(`avatar-upload-${Math.random().toString(36).slice(2,11)}`).current;k.useEffect(()=>{if(V){const oe=URL.createObjectURL(V);return Z(oe),()=>URL.revokeObjectURL(oe)}else Z(null)},[V]);const te=k.useCallback(oe=>vt?.t?.(oe)??oe,[]),fe=k.useCallback(()=>{const oe=document.cookie.match(/XSRF-TOKEN=([^;]+)/);return oe?decodeURIComponent(oe[1]):null},[]),R=k.useCallback(()=>vt?.api?.getToken?.()??null,[]),ke=k.useCallback(async oe=>{B(!1),j(null),P(!0),$(null);try{const ae=new FormData;ae.append("avatar",oe);const be=fe(),xe=R(),He=await fetch(n,{method:"POST",headers:{Accept:"application/json",...be&&{"X-XSRF-TOKEN":be},...xe&&{Authorization:`Bearer ${xe}`}},credentials:"include",body:ae});if(!He.ok){const Oe=await He.json().catch(()=>({}));throw new Error(Oe.message||te("attachment.upload_failed"))}const Pe=await He.json(),Ke=Pe.data||Pe;Ke.avatar&&S(Ke.avatar),a?.(Ke),vt?.toast?.success?.(te("mypage.profile.avatar_uploaded")),E?.length?E.forEach(Oe=>vt?.dispatch?.(Oe)):vt?.refetchDataSource?.("user")}catch(ae){const be=ae instanceof Error?ae:new Error(String(ae));$(be.message),s?.(be),vt?.toast?.error?.(be.message),O?.length&&O.forEach(xe=>vt?.dispatch?.(xe))}finally{P(!1),N.current&&(N.current.value="")}},[n,a,s,fe,R,te]),me=k.useCallback(async oe=>{const ae=oe.target.files?.[0];if(!ae)return;$(null);const be=i*1024*1024;if(ae.size>be){const xe=new Error(te("attachment.file_too_large").replace(":max",`${i}MB`));$(xe.message),s?.(xe),vt?.toast?.error?.(xe.message);return}if(d&&!ae.type.match(d.replace("*",".*"))){const xe=new Error(te("attachment.invalid_file_type"));$(xe.message),s?.(xe),vt?.toast?.error?.(xe.message);return}A?(j(ae),B(!0)):ke(ae)},[i,d,s,A,ke,te]),Ge=k.useCallback(async()=>{G(!1),L(!0),$(null);try{const oe=fe(),ae=R(),be=await fetch(o,{method:"DELETE",headers:{Accept:"application/json","Content-Type":"application/json",...oe&&{"X-XSRF-TOKEN":oe},...ae&&{Authorization:`Bearer ${ae}`}},credentials:"include"});if(!be.ok){const xe=await be.json().catch(()=>({}));throw new Error(xe.message||te("attachment.delete_failed"))}S(null),l?.(),vt?.toast?.success?.(te("mypage.profile.avatar_deleted")),_?.length?_.forEach(xe=>vt?.dispatch?.(xe)):vt?.refetchDataSource?.("user")}catch(oe){const ae=oe instanceof Error?oe:new Error(String(oe));$(ae.message),f?.(ae),vt?.toast?.error?.(ae.message),I?.length&&I.forEach(be=>vt?.dispatch?.(be))}finally{L(!1)}},[o,l,f,fe,R,te]),De=k.useCallback(()=>{w?G(!0):Ge()},[w,Ge]),ye=k.useCallback(()=>{G(!1)},[]),Me=k.useCallback(()=>{B(!1),j(null),N.current&&(N.current.value="")},[]),Ce=k.useCallback(()=>{V&&ke(V)},[V,ke]),we=U===void 0?e:U,$e=!!we,Le=k0[r]||"lg",K=F||Y,re=()=>c.jsxs(W,{className:"flex items-center justify-center gap-2",children:[c.jsx(xt,{ref:N,id:ue,type:"file",accept:d,className:"hidden",onChange:me,disabled:M}),!$e&&c.jsxs(yr,{htmlFor:ue,className:`inline-flex items-center gap-2 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors cursor-pointer ${M?"opacity-50 cursor-not-allowed":""}`,children:[M?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"image",size:"sm"}),c.jsx(ee,{children:g||te("mypage.profile.register_avatar")})]}),$e&&c.jsxs(c.Fragment,{children:[c.jsxs(yr,{htmlFor:ue,className:`inline-flex items-center gap-2 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors cursor-pointer ${M?"opacity-50 cursor-not-allowed":""}`,children:[M?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"upload",size:"sm"}),c.jsx(ee,{children:g||te("common.change")})]}),h&&c.jsxs(Q,{type:"button",className:"inline-flex items-center gap-2 px-4 py-2 border border-red-300 dark:border-red-600 text-red-600 dark:text-red-400 rounded-lg text-sm font-medium hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",onClick:De,disabled:D,children:[D?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"trash-2",size:"sm"}),c.jsx(ee,{children:p||te("common.delete")})]})]})]});return c.jsxs(W,{className:`flex flex-col items-center gap-3 ${u}`,id:C,...y,children:[Y&&H?c.jsxs(W,{className:"relative",children:[c.jsx(Lt,{src:H,alt:"Preview",className:`rounded-full object-cover ${r==="sm"?"w-10 h-10":r==="md"?"w-12 h-12":r==="lg"?"w-16 h-16":r==="xl"?"w-24 h-24":"w-32 h-32"}`}),c.jsx(W,{className:"absolute inset-0 rounded-full bg-blue-500/20 border-2 border-blue-500 border-dashed"})]}):c.jsx(Ur,{avatar:we||void 0,name:t,size:Le}),!m&&c.jsxs(W,{className:"w-[220px] flex flex-col items-center gap-2",children:[Y&&V&&c.jsxs(W,{className:"w-full p-3 bg-blue-50 dark:bg-blue-950/50 border border-blue-200 dark:border-blue-800 rounded-lg",children:[c.jsxs(W,{className:"flex items-center gap-2 mb-2",children:[c.jsx(de,{name:"upload",size:"sm",className:"text-blue-600 dark:text-blue-400 shrink-0"}),c.jsx(ee,{className:"text-sm font-medium text-blue-800 dark:text-blue-300",children:v||te("mypage.profile.upload_avatar_confirm")})]}),c.jsxs(W,{className:"text-xs text-blue-600 dark:text-blue-400 truncate mb-3",title:V.name,children:[V.name," (",(V.size/1024/1024).toFixed(2),"MB)"]}),c.jsxs(W,{className:"grid grid-cols-2 gap-2",children:[c.jsxs(Q,{type:"button",className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md text-sm font-medium transition-colors disabled:opacity-50",onClick:Ce,disabled:M,children:[M?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"check",size:"sm"}),c.jsx(ee,{children:te("common.confirm")})]}),c.jsx(Q,{type:"button",className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-md text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors",onClick:Me,children:c.jsx(ee,{children:te("common.cancel")})})]})]}),F&&c.jsxs(W,{className:"w-full p-3 bg-red-50 dark:bg-red-950/50 border border-red-200 dark:border-red-800 rounded-lg",children:[c.jsxs(W,{className:"flex items-center gap-2 mb-2",children:[c.jsx(de,{name:"alert-triangle",size:"sm",className:"text-red-600 dark:text-red-400 shrink-0"}),c.jsx(ee,{className:"text-sm font-medium text-red-800 dark:text-red-300",children:x||te("mypage.profile.delete_avatar_confirm")})]}),c.jsxs(W,{className:"grid grid-cols-2 gap-2",children:[c.jsxs(Q,{type:"button",className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-red-600 hover:bg-red-700 text-white rounded-md text-sm font-medium transition-colors disabled:opacity-50",onClick:Ge,disabled:D,children:[D?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"trash-2",size:"sm"}),c.jsx(ee,{children:te("common.delete")})]}),c.jsx(Q,{type:"button",className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-md text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors",onClick:ye,children:c.jsx(ee,{children:te("common.cancel")})})]})]}),!K&&re()]}),b&&!K&&c.jsxs(W,{className:"flex items-center gap-2 text-sm text-red-600 dark:text-red-400",children:[c.jsx(de,{name:"alert-circle",size:"sm"}),c.jsx(ee,{children:b})]})]})}const C0=Object.freeze(Object.defineProperty({__proto__:null,AvatarUploader:Aa,default:Aa},Symbol.toStringTag,{value:"Module"})),oc=()=>window.G7Core,qn=(e,t)=>window.G7Core?.t?.(e,t)??e,ac={horizontal:"flex items-center gap-1.5",vertical:"flex flex-col items-start"},S0=()=>[{key:"view_profile",label:qn("userinfo.view_profile"),icon:"user",path:"/users/{{userId}}"},{key:"view_posts",label:qn("userinfo.view_posts"),icon:"file-lines",path:"/users/{{userId}}/posts"}],Ma=({text:e,title:t})=>e?c.jsx(ee,{className:"text-sm text-gray-500 dark:text-gray-400",title:t,children:e}):null,sc=({author:e,name:t,userId:r,subText:n,subTextTitle:o,isGuest:a=!1,isWithdrawn:s=!1,showDropdown:l=!0,clickable:f=!0,profilePath:h="/users/{userId}",className:d="",layout:i="vertical",text:u,stopPropagation:g=!1,menuItems:p,hideMenuItems:m=[],appendMenuItems:w=[],id:x,editorAttrs:A})=>{const v=r??e?.uuid,E=a||e?.is_guest||!1,O=s||e?.status==="withdrawn",_=O?qn("userinfo.withdrawn_user"):u??t??e?.name??"",[I,C]=k.useState(!1),[y,N]=k.useState({top:0,left:0}),M=k.useRef(null),P=k.useRef(null),D=k.useRef(null),L=h.replace("{userId}",String(v??"")),U=`${ac[i]} ${d}`;k.useEffect(()=>{if(!I)return;const j=Z=>{const ue=Z.target,te=M.current?.contains(ue),fe=P.current?.contains(ue);!te&&!fe&&C(!1)},H=()=>C(!1);return document.addEventListener("mousedown",j),window.addEventListener("scroll",H,!0),window.addEventListener("resize",H),()=>{document.removeEventListener("mousedown",j),window.removeEventListener("scroll",H,!0),window.removeEventListener("resize",H)}},[I]);const S=k.useCallback(()=>{if(p&&p.length>0)return p.filter(Z=>Z.show!==!1);let H=S0().filter(Z=>!m.includes(Z.key)&&Z.show!==!1);return w&&w.length>0&&(H=[...H,...w.filter(Z=>Z.show!==!1)]),H},[p,m,w]),b=k.useCallback(()=>{if(D.current){const j=D.current.getBoundingClientRect();N({top:j.bottom+4,left:j.left})}},[]),$=k.useCallback((j,H)=>{if(H.stopPropagation(),H.preventDefault(),C(!1),j.onClick)j.onClick();else if(j.path){const Z=j.path.replace(/\{\{userId\}\}/g,String(v??"")),ue=oc();ue?.navigate?ue.navigate(Z):window.location.href=Z}},[v]),F=k.useCallback(j=>{j.preventDefault(),g&&j.stopPropagation(),!(E||!v)&&(l?(I||b(),C(H=>!H)):f&&oc()?.navigate?.(L))},[g,E,v,l,I,b,f,L]);if(E||!v)return c.jsxs(W,{className:U,id:x,...A,children:[c.jsxs(W,{className:"flex items-center gap-1.5 text-gray-400 dark:text-gray-500",children:[c.jsx(ee,{children:_}),c.jsx(ee,{className:"text-xs px-1.5 py-0.5 bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 rounded",children:qn("userinfo.guest_badge")})]}),c.jsx(Ma,{text:n,title:o})]});if(O)return c.jsxs(W,{className:U,id:x,...A,children:[c.jsx(ee,{className:"text-gray-400 dark:text-gray-500 line-through",children:_}),c.jsx(Ma,{text:n,title:o})]});const G=S(),B=/\btext-\S+/.test(d)?"":"text-gray-900 dark:text-white",V=l||f?`${B} hover:text-blue-600 dark:hover:text-blue-400 cursor-pointer font-medium`.trim():`${B} font-medium`.trim();return c.jsxs(W,{ref:M,className:`relative inline-block ${d}`,id:x,...A,children:[c.jsxs(W,{className:ac[i],children:[c.jsx(Q,{ref:D,onClick:F,className:V,children:_}),c.jsx(Ma,{text:n,title:o})]}),l&&I&&G.length>0&&Jt.createPortal(c.jsx(W,{ref:P,className:"fixed w-40 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg py-1 z-[9999]",style:{top:y.top,left:y.left},"data-testid":"author-dropdown-menu",children:G.map(j=>c.jsxs(Q,{onClick:H=>$(j,H),className:"flex items-center justify-start gap-2 w-full text-left px-3 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer","data-testid":`menu-item-${j.key}`,children:[j.icon&&c.jsx(de,{name:j.icon,className:"w-4 h-4"}),c.jsx(ee,{children:j.label})]},j.key))}),document.body)]})},_0=Object.freeze(Object.defineProperty({__proto__:null,UserInfo:sc},Symbol.toStringTag,{value:"Module"})),lc=({tabs:e,activeTabId:t,onTabChange:r,variant:n="underline",className:o="",style:a,hiddenTabIds:s=[],mobileBreakpoint:l=768,id:f,editorAttrs:h})=>{const i=window.G7Core?.useResponsive,u=i?.(),g=u?u.width{!v.disabled&&v.id!==t&&r?.(v.id)},m=v=>{const E=v.target.value,O=Number(E),_=typeof E=="string"&&E!==""&&!Number.isNaN(O)?O:E,I=e.find(C=>String(C.id)===String(_));I&&p(I)},w=s.length>0?e.filter(v=>!s.includes(v.id)):e;if(g)return c.jsx(W,{className:`relative ${o}`,style:a,id:f,...h,children:c.jsx(Xa,{value:t!==void 0?String(t):"",onChange:m,options:w.map(v=>({value:String(v.id),label:v.badge!==void 0?`${v.label} (${v.badge})`:v.label,disabled:v.disabled})),className:"w-full"})});const x=v=>{const E=v.id===t,O="flex items-center gap-2 px-3 py-2 font-medium text-sm transition-all shrink-0 whitespace-nowrap";if(v.disabled)return`${O} opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-600`;switch(n){case"pills":return E?`${O} bg-blue-600 dark:bg-blue-500 text-white rounded-lg`:`${O} text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg`;case"underline":return E?`${O} text-gray-900 dark:text-white border-b-2 border-gray-900 dark:border-white`:`${O} text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 border-b-2 border-transparent hover:border-gray-300 dark:hover:border-gray-600`;default:return E?`${O} text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 border-b-2 border-blue-600 dark:border-blue-400`:`${O} text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 border-b-2 border-transparent`}},A=n==="underline"?"flex gap-0 border-b border-gray-200 dark:border-gray-700":"flex gap-2";return c.jsx(W,{className:`relative ${o}`,style:a,id:f,...h,children:c.jsx($r,{className:A,children:w.map(v=>c.jsxs(Q,{type:"button",onClick:()=>p(v),disabled:v.disabled,className:x(v),children:[v.iconName&&c.jsx(de,{name:v.iconName,size:"sm"}),c.jsx(ee,{children:v.label}),v.badge!==void 0&&c.jsx(W,{className:"flex items-center justify-center min-w-5 h-5 px-1.5 bg-red-500 text-white text-xs font-bold rounded-full",children:c.jsx(ee,{children:v.badge})})]},v.id))})})},E0=Object.freeze(Object.defineProperty({__proto__:null,TabNavigation:lc},Symbol.toStringTag,{value:"Module"})),T0={Header:()=>Promise.resolve().then(()=>od),Footer:()=>Promise.resolve().then(()=>id),MobileNav:()=>Promise.resolve().then(()=>cd),SlotContainer:()=>Promise.resolve().then(()=>rd),NotificationCenter:()=>Promise.resolve().then(()=>nd),ProductCard:()=>Promise.resolve().then(()=>Ld),BrandMark:()=>Promise.resolve().then(()=>Fd),ImageGallery:()=>Promise.resolve().then(()=>Al),ProductImageViewer:()=>Promise.resolve().then(()=>jf),QuantitySelector:()=>Promise.resolve().then(()=>Bf),PostReactions:()=>Promise.resolve().then(()=>Vf),RichTextEditor:()=>Promise.resolve().then(()=>Yf),HtmlContent:()=>Promise.resolve().then(()=>Xf),HtmlEditor:()=>Promise.resolve().then(()=>Zf),ExpandableContent:()=>Promise.resolve().then(()=>qf),FileUploader:()=>Promise.resolve().then(()=>Xh),ConfirmDialog:()=>Promise.resolve().then(()=>Rf),SocialLoginButtons:()=>Promise.resolve().then(()=>qh),Toast:()=>Promise.resolve().then(()=>t0),PageTransitionIndicator:()=>Promise.resolve().then(()=>n0),PageTransitionBlur:()=>Promise.resolve().then(()=>o0),PageSkeleton:()=>Promise.resolve().then(()=>b0),PageLoading:()=>Promise.resolve().then(()=>v0),ThemeToggle:()=>Promise.resolve().then(()=>Qc),Pagination:()=>Promise.resolve().then(()=>w0),SearchBar:()=>Promise.resolve().then(()=>x0),Avatar:()=>Promise.resolve().then(()=>ed),AvatarUploader:()=>Promise.resolve().then(()=>C0),UserInfo:()=>Promise.resolve().then(()=>_0),Modal:()=>Promise.resolve().then(()=>Jf),TabNavigation:()=>Promise.resolve().then(()=>E0)},N0=({id:e,className:t,style:r,children:n,editorAttrs:o})=>c.jsx(W,{id:e,className:t,style:r,...o,children:n}),A0=({id:e,children:t,cols:r=1,responsive:n,gap:o,rowGap:a,colGap:s,autoRows:l,autoCols:f,flow:h="row",className:d="",style:i,onClick:u,editorAttrs:g})=>{const p=["grid"];if(r&&p.push(`grid-cols-${r}`),n&&(n.sm&&p.push(`sm:grid-cols-${n.sm}`),n.md&&p.push(`md:grid-cols-${n.md}`),n.lg&&p.push(`lg:grid-cols-${n.lg}`),n.xl&&p.push(`xl:grid-cols-${n.xl}`),n["2xl"]&&p.push(`2xl:grid-cols-${n["2xl"]}`)),o!==void 0&&o>0&&p.push(`gap-${o}`),a!==void 0&&a>0&&p.push(`gap-y-${a}`),s!==void 0&&s>0&&p.push(`gap-x-${s}`),l){const w={auto:"auto-rows-auto",min:"auto-rows-min",max:"auto-rows-max",fr:"auto-rows-fr"};p.push(w[l])}if(f){const w={auto:"auto-cols-auto",min:"auto-cols-min",max:"auto-cols-max",fr:"auto-cols-fr"};p.push(w[f])}const m={row:"grid-flow-row",col:"grid-flow-col",dense:"grid-flow-dense","row-dense":"grid-flow-row-dense","col-dense":"grid-flow-col-dense"};return p.push(m[h]),d&&p.push(d),c.jsx(W,{id:e,className:p.join(" "),style:i,onClick:u,...g,children:t})},M0=({id:e,children:t,direction:r="row",justify:n="start",align:o="stretch",wrap:a="nowrap",gap:s=0,grow:l=!1,shrink:f=!0,className:h="",style:d,onClick:i,editorAttrs:u})=>{const g=["flex"],p={row:"flex-row","row-reverse":"flex-row-reverse",col:"flex-col","col-reverse":"flex-col-reverse"};g.push(p[r]);const m={wrap:"flex-wrap",nowrap:"flex-nowrap","wrap-reverse":"flex-wrap-reverse"};g.push(m[a]);const w={start:"justify-start",end:"justify-end",center:"justify-center",between:"justify-between",around:"justify-around",evenly:"justify-evenly"};g.push(w[n]);const x={start:"items-start",end:"items-end",center:"items-center",baseline:"items-baseline",stretch:"items-stretch"};return g.push(x[o]),s>0&&g.push(`gap-${s}`),l===!0?g.push("flex-grow"):typeof l=="number"&&l>0&&g.push(`flex-grow-${l}`),f===!1?g.push("shrink-0"):f===!0?g.push("flex-shrink"):typeof f=="number"&&f>0&&g.push(`flex-shrink-${f}`),h&&g.push(h),c.jsx(W,{id:e,className:g.join(" "),style:d,onClick:i,...u,children:t})},O0=({id:e,title:t,subtitle:r,children:n,padding:o="md",background:a="none",maxWidth:s,centered:l=!1,border:f=!1,shadow:h="none",rounded:d=!1,className:i="",style:u,onClick:g,editorAttrs:p})=>{const m=[],w={none:"p-0",sm:"p-2",md:"p-4",lg:"p-6",xl:"p-8"};m.push(w[o]);const x={none:"",white:"bg-white dark:bg-gray-700",gray:"bg-gray-50 dark:bg-gray-800",primary:"bg-blue-50 dark:bg-blue-900/20",secondary:"bg-gray-50 dark:bg-gray-800"};if(a!=="none"&&m.push(x[a]),s){const v={sm:"max-w-sm",md:"max-w-md",lg:"max-w-lg",xl:"max-w-xl","2xl":"max-w-2xl","4xl":"max-w-4xl","6xl":"max-w-6xl","7xl":"max-w-7xl",full:"max-w-full"};m.push(v[s])}l&&m.push("mx-auto"),f&&m.push("border","border-gray-200","dark:border-gray-700");const A={none:"",sm:"shadow-sm",md:"shadow-md",lg:"shadow-lg",xl:"shadow-xl"};return h!=="none"&&m.push(A[h]),d&&m.push("rounded-lg"),i&&m.push(i),c.jsxs(qa,{id:e,className:m.join(" "),style:u,onClick:g,...p,children:[(t||r)&&c.jsxs(W,{className:"mb-4",children:[t&&c.jsx(Va,{className:"text-2xl font-bold text-gray-900 dark:text-white",children:t}),r&&c.jsx(Dt,{className:"mt-1 text-sm text-gray-600 dark:text-gray-400",children:r})]}),n]})},I0=({id:e,leftWidth:t="250px",rightWidth:r="300px",leftSlot:n,centerSlot:o,rightSlot:a,className:s="",style:l,editorAttrs:f})=>{const h=`flex flex-row w-full h-full ${s}`.trim(),d={width:t,flexShrink:0},i={flex:1,minWidth:0},u={width:r,flexShrink:0};return c.jsxs(W,{id:e,className:h,style:l,...f,children:[c.jsx(W,{className:"flex flex-col",style:d,children:n}),c.jsx(W,{className:"flex flex-col",style:i,children:o}),c.jsx(W,{className:"flex flex-col",style:u,children:a})]})},D0={identifier:"sirsoft-basic",vendor:"sirsoft",name:{ko:"Basic",en:"Basic"},version:"1.0.3",license:"MIT",description:{ko:"그누보드7 기본 사용자 템플릿",en:"Gnuboard7 default user template"},type:"user",locales:["ko","en"],author:{name:"sirsoft",email:"contact@sirsoft.com",url:"https://sirsoft.com"},release_date:"2026-01-07",g7_version:">=7.0.0",dependencies:{modules:{"sirsoft-board":">=1.0.0","sirsoft-ecommerce":">=1.0.2","sirsoft-page":">=1.0.0"},plugins:{"sirsoft-daum_postcode":">=1.0.0"}},assets:{css:["dist/css/components.css"],js:["dist/js/components.iife.js"],fonts:[],images:[]},components:{basic:["a","button","checkbox","div","form","h1","h2","h3","h4","hr","icon","img","input","label","li","nav","p","section","select","span","svg","table","tbody","td","textarea","th","thead","tr","ul"],composite:["header","footer","mobile-nav","product-card","rich-text-editor","image-gallery","quantity-selector","post-reactions","social-login-buttons","file-uploader","card","modal","toast","pagination","stat-card","status-badge","tab-navigation","empty-state","loading-spinner","breadcrumb","search-bar","dropdown"],layout:["container","flex","grid","section"]},preview:{thumbnail:"preview/thumbnail.png",screenshots:["preview/screenshot1.png","preview/screenshot2.png"]},error_config:{layouts:{401:"errors/401",403:"errors/403",404:"errors/404",500:"errors/500",503:"errors/503",maintenance:"errors/maintenance"}},features:{dark_mode:!0,responsive:!0,multi_language:!0,multi_currency:!0},github_url:"https://github.com/gnuboard/g7-template-sirsoft-basic",github_changelog_url:"https://github.com/gnuboard/g7-template-sirsoft-basic/blob/main/CHANGELOG.md",externals:[{id:"fontawesome",type:"style",url:"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css",preconnect:"https://cdnjs.cloudflare.com"},{id:"pretendard",type:"webfont",url:"https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css",preconnect:"https://cdn.jsdelivr.net",crossorigin:"anonymous"}]},ic={KRW:{locale:"ko-KR",decimals:0},USD:{locale:"en-US",decimals:2},JPY:{locale:"ja-JP",decimals:0},CNY:{locale:"zh-CN",decimals:2},EUR:{locale:"de-DE",decimals:2}};function Lr(e,t="KRW"){if(!Number.isFinite(e))return"0";const r=ic[t]||ic.KRW;try{return new Intl.NumberFormat(r.locale,{style:"currency",currency:t,minimumFractionDigits:r.decimals,maximumFractionDigits:r.decimals}).format(e)}catch{return e.toLocaleString()+(t==="KRW"?"원":"")}}function Qn(e,t,r=0){if(!e)return;const n=e.KRW?.value??e.KRW?.price??0,o={};for(const[a,s]of Object.entries(e)){const l=s?.value??s?.price??0;let f=0;r>0&&(a==="KRW"?f=r:n>0&&(f=r*l/n));const h=(l+f)*t;o[a]={value:h,formatted:Lr(h,a)}}return o}function Jn(e){const t={};for(const n of e){const o=n?.multiCurrencyTotalPrice;if(o)for(const[a,s]of Object.entries(o)){const l=s?.value??s?.price??0;t[a]=(t[a]??0)+l}}const r={};for(const[n,o]of Object.entries(t))r[n]={value:o,formatted:Lr(o,n)};return r}function cc(e,t){if(!e||!t?.length)return 0;let r=0;for(const n of t){const o=e[n.id];if(o==null)continue;const a=n.values?.find(s=>s.id===Number(o));a&&(r+=a.price_adjustment??0)}return r}function Rn(e){return e.name_localized?e.name_localized:typeof e.name=="string"?e.name:e.name?.ko??""}function L0(e,t,r){if(t&&r in t)return t[r];if(Array.isArray(e)){const n=e.find(o=>typeof o.key=="string"?o.key===r:o.key?.ko===r||Object.values(o.key).includes(r));return n?typeof n.value=="string"?n.value:n.value?.ko??Object.values(n.value)[0]:void 0}return e[r]}function P0(e,t){if(t)return t;if(!Array.isArray(e))return e;const r={};for(const n of e){const o=typeof n.key=="string"?n.key:n.key?.ko??Object.values(n.key)[0]??"",a=typeof n.value=="string"?n.value:n.value?.ko??Object.values(n.value)[0]??"";o&&(r[o]=a)}return r}function F0(e,t,r){return r.find(n=>!n?.option_values||!n?.is_active?!1:e.every(o=>{const a=Rn(o),s=t?.[a];return L0(n.option_values,n.option_values_localized,a)===s}))}function $0(e,t){const r=e.params;if(!r)return;const{optionGroups:n,options:o,selectedOptionItems:a,preferredCurrency:s}=r;let l;if(r.newGroupName&&r.newValue?l={...r.currentSelection??{},[r.newGroupName]:r.newValue}:l=r.currentSelection??{},!n?.every(O=>{const _=Rn(O);return l?.[_]}))return;const h=F0(n,l,o??[]);if(!h){t.setState?.({currentSelection:{},__mergeMode:"shallow"});return}const d=n.map(O=>l[Rn(O)]).join("_"),i=a??[];if(i.find(O=>O.id===d)){const O=window.G7Core;O?.toast?.warning?.(O?.t?.("sirsoft-ecommerce.shop.already_added_option")??"이미 추가된 옵션입니다."),t.setState?.({currentSelection:{},__mergeMode:"shallow"});return}const g=h.selling_price??0,p={};n.forEach(O=>{const _=Rn(O);p[_]=l[_]});const m=r.additionalOptionGroups??[],w={};for(const O of m){if(!O.is_required)continue;const _=O.values?.find(I=>I.is_default);_&&(w[O.id]=_.id)}const x=cc(w,m),A=g+x,v={id:d,optionId:h.id,options:p,optionValues:P0(h.option_values,h.option_values_localized),quantity:1,stock:h.stock_quantity??999,unitPrice:g,unitPriceFormatted:Lr(g,s),totalPrice:A,totalPriceFormatted:Lr(A,s),multiCurrencyUnitPrice:h.multi_currency_selling_price,multiCurrencyTotalPrice:Qn(h.multi_currency_selling_price,1,x),additionalOptionSelections:w,additionalOptionsTotal:x},E=[...i,v];t.setState?.({selectedOptionItems:E,selectedTotalMultiCurrency:Jn(E),currentSelection:{},__mergeMode:"shallow"})}function U0(e,t){const r=e.params;if(!r)return;const{selectedOptionItems:n,preferredCurrency:o}=r,a=Number(r.itemIndex)||0,s=Number(r.newQuantity)||1,l=(n??[]).map((f,h)=>{if(h!==a)return f;const d=f?.unitPrice??0,i=f?.additionalOptionsTotal??0,u=(d+i)*s;return{...f,quantity:s,totalPrice:u,totalPriceFormatted:Lr(u,o),multiCurrencyTotalPrice:Qn(f?.multiCurrencyUnitPrice,s,i)}});t.setState?.({selectedOptionItems:l,selectedTotalMultiCurrency:Jn(l)})}function z0(e,t){const r=e.params;if(!r)return;const{selectedOptionItems:n,additionalOptionGroups:o,preferredCurrency:a}=r,s=Number(r.itemIndex)||0,l=Number(r.additionalOptionId),f=Object.prototype.hasOwnProperty.call(r,"customText"),h=r.valueId===""||r.valueId==null?null:Number(r.valueId),d=(n??[]).map((i,u)=>{if(u!==s)return i;const g={...i.additionalOptionSelections??{}},p={...i.additionalOptionCustomTexts??{}};if(f){const v=String(r.customText??"");v.trim()===""?delete p[l]:p[l]=v}else h==null?(delete g[l],delete p[l]):(g[l]=h,(o??[]).find(O=>O.id===l)?.values?.find(O=>O.id===h)?.allow_custom_text||delete p[l]);const m=cc(g,o),w=i?.unitPrice??0,x=i?.quantity??1,A=(w+m)*x;return{...i,additionalOptionSelections:g,additionalOptionCustomTexts:p,additionalOptionsTotal:m,totalPrice:A,totalPriceFormatted:Lr(A,a),multiCurrencyTotalPrice:Qn(i?.multiCurrencyUnitPrice,x,m)}});t.setState?.({selectedOptionItems:d,selectedTotalMultiCurrency:Jn(d)})}function H0(e,t){const r=e.params;if(!r)return;const n=Number(r.itemIndex)||0,o=(r.selectedOptionItems??[]).filter((a,s)=>s!==n);t.setState?.({selectedOptionItems:o,selectedTotalMultiCurrency:Jn(o)})}function G0(e,t){const r=e.params;if(!r)return;const n=Math.max(1,Number(r.newQuantity)||1);t.setState?.({noOptionQuantity:n,noOptionTotalMultiCurrency:Qn(r.multiCurrencyUnitPrice,n)})}const cn=window.G7Core?.createLogger?.("Handler:Cart")??{log:(...e)=>console.log("[Handler:Cart]",...e),warn:(...e)=>console.warn("[Handler:Cart]",...e),error:(...e)=>console.error("[Handler:Cart]",...e)};function hr(e){const t=window.G7Core;t?.state?.setLocal?(t.state.setLocal(e),cn.log("Local state updated:",e)):cn.warn("G7Core.state.setLocal not available")}function dc(){return window.G7Core?.state?.getLocal?.()||{}}function j0(){return window.G7Core?.state?.get?.()||{}}function B0(e,t="info"){const r=window.G7Core;r?.toast?.show?r.toast.show(e,t):cn.warn("G7Core.toast.show not available, message:",e)}function W0(e){const t=window.G7Core;return t?.t?t.t(e):e}function uc(){const e=window.G7Core;if(e?.dispatch){const r=dc().selectedItems||[];e.dispatch({handler:"refetchDataSource",params:{dataSourceId:"cartItems"}}),cn.log("Refetching cartItems with selected_ids:",r)}else cn.warn("G7Core.dispatch not available")}function K0(e,t){const{itemId:r,selectedItems:n}=e?.params||{},o=n||[];let a;o.includes(r)?a=o.filter(h=>h!==r):a=[...o,r];const l=j0().cartItems?.data?.items||[],f=l.length>0&&a.length===l.length;hr({selectedItems:a,allSelected:f,selectedCount:a.length}),uc()}function V0(e,t){const{allItemIds:r,isSelected:n}=e?.params||{};hr({selectedItems:n?r:[],allSelected:n,selectedCount:n?r.length:0}),uc()}function Y0(e,t){const{optionName:r,optionValue:n}=e?.params||{},a=dc().selectedOptions||{};hr({selectedOptions:{...a,[r]:n}})}function X0(e,t){const{targetIds:r}=e?.params||{};if(!r||r.length===0){B0(W0("shop.cart.select_items_to_delete"),"warning");return}hr({deleteModal:{visible:!0,targetIds:r}})}function Z0(e,t){const{targetItem:r}=e?.params||{};hr({optionModal:{visible:!0,targetItem:r},selectedOptions:r?.options||{},selectedQuantity:r?.quantity})}function q0(e,t){const{selectedItems:r}=e?.params||{};if(!r||r.length===0){hr({isCalculating:!1});return}hr({isCalculating:!0})}const pr=window.G7Core?.createLogger?.("Handler:CartOptionChange")??{log:(...e)=>console.log("[Handler:CartOptionChange]",...e),warn:(...e)=>console.warn("[Handler:CartOptionChange]",...e),error:(...e)=>console.error("[Handler:CartOptionChange]",...e)};function Oa(e){return e.name_localized?e.name_localized:typeof e.name=="string"?e.name:e.name?.ko??""}function Q0(e,t,r){if(t&&r in t)return t[r];if(Array.isArray(e)){const n=e.find(o=>typeof o.key=="string"?o.key===r:o.key?.ko===r||Object.values(o.key).includes(r));return n?typeof n.value=="string"?n.value:n.value?.ko??Object.values(n.value)[0]:void 0}return e[r]}function fc(e,t,r){return!e||!t?.length?null:t.every(a=>{const s=Oa(a);return e[s]})?r?.find(a=>t.every(s=>{const l=Oa(s);return Q0(a.option_values,a.option_values_localized,l)===e[l]}))||null:(pr.log("Not all options selected yet"),null)}function J0(e,t){const{selectedOptions:r,optionGroups:n,options:o}=e?.params||{};pr.log("findMatchingOption called:",{selectedOptions:r,optionGroups:n,optionsCount:o?.length});const a=fc(r,n,o);return pr.log("Matched option:",a),{matchedOption:a}}function R0(e,t){const{currentOptionValues:r,optionGroups:n,options:o}=e?.params||{};if(pr.log("initCartOptionSelection called:",{currentOptionValues:r,optionGroups:n,optionsCount:o?.length}),!n?.length||!r)return pr.log("No option groups or current values, returning empty"),{selectedOptions:{},matchedOption:null};const a={};for(const l of n){const f=Oa(l),h=r[f],d=l.values_localized??(Array.isArray(l.values)?l.values.map(i=>typeof i=="string"?i:i?.ko??""):[]);h&&d.includes(h)&&(a[f]=h)}pr.log("Initial selectedOptions:",a);const s=fc(a,n,o||[]);return pr.log("Matched option:",s),{selectedOptions:a,matchedOption:s}}const dn="g7_cart_key",ep="/api/modules/sirsoft-ecommerce/cart/key",Ia="g7_guest_order_token",gc="g7_guest_order_number",Da="g7_guest_order_expires_at",at=window.G7Core?.createLogger?.("Handler:Storage")??{log:(...e)=>console.log("[Handler:Storage]",...e),warn:(...e)=>console.warn("[Handler:Storage]",...e),error:(...e)=>console.error("[Handler:Storage]",...e)};async function hc(){try{const e=await fetch(ep,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"}});return e.ok?(await e.json()).data?.cart_key||null:(at.error("Failed to issue cartKey from API:",e.status),null)}catch(e){return at.error("Error issuing cartKey from API:",e),null}}function rr(e){const t=window.G7Core;t?.state?.set?(t.state.set(e),at.log("Global state updated:",e)):at.warn("G7Core.state.set not available")}function tp(){try{const e=window.G7Config;return e?.user?e.user:(window.G7Core?.state?.get?.()||{}).currentUser||null}catch{return null}}async function rp(e,t){let r=null;try{r=localStorage.getItem(dn)}catch{}if(r)at.log("Existing cartKey loaded:",r);else if(r=await hc(),r)try{localStorage.setItem(dn,r),at.log("New cartKey issued from API:",r)}catch{}else at.error("Failed to issue cartKey from API");rr({cartKey:r})}function np(e,t){try{return localStorage.getItem(dn)}catch{return null}}function pc(e,t){try{localStorage.removeItem(dn),at.log("cartKey removed from localStorage")}catch{}rr({cartKey:null})}async function op(e,t){if(tp()){pc();return}const n=await hc();if(n){try{localStorage.setItem(dn,n),at.log("New cartKey regenerated from API:",n)}catch{}rr({cartKey:n})}else at.error("Failed to regenerate cartKey from API")}function ap(e,t){const{key:r,value:n}=e?.params||{};if(!r){at.warn("saveToStorage: key is required");return}try{localStorage.setItem(r,n),at.log("Saved to storage:",r,n)}catch{}}function sp(e,t){const{key:r,defaultValue:n}=e?.params||{};if(!r)return at.warn("loadFromStorage: key is required"),n||null;try{return localStorage.getItem(r)||n||null}catch{return n||null}}function La(){try{sessionStorage.removeItem(Ia),sessionStorage.removeItem(gc),sessionStorage.removeItem(Da)}catch{}}function lp(e,t){let r=null,n=null;try{r=sessionStorage.getItem(Ia),n=sessionStorage.getItem(Da)}catch{}let o=!1;if(r){const a=n?new Date(n).getTime():NaN;(isNaN(a)||a<=Date.now())&&(La(),r=null,o=!0)}if(r){rr({guestOrderToken:r}),at.log("Guest order token loaded from sessionStorage");return}if(!o){const s=window.G7Core?.state?.get?.("_global")?.guestOrderToken;if(typeof s=="string"&&s!==""){at.log("Guest order token preserved from in-memory _global (sessionStorage empty)");return}}rr({guestOrderToken:null}),at.log("No guest order token (visitor not authenticated)")}function ip(e,t){const{token:r,orderNumber:n,expiresAt:o}=e?.params||{};if(!r||!n||!o){at.warn("saveGuestOrderToken: token, orderNumber, expiresAt are required");return}try{sessionStorage.setItem(Ia,r),sessionStorage.setItem(gc,n),sessionStorage.setItem(Da,o)}catch{}rr({guestOrderToken:r})}function cp(e,t){La(),rr({guestOrderToken:null})}function dp(e,t){La(),rr({guestOrderToken:null})}function up(e,t){const{product:r,priceField:n,currencyCode:o}=e,a=o||t.getState("_global.preferredCurrency")||"KRW",s=`multi_currency_${n}`,l=r[s];if(l&&l[a])return l[a].formatted;const f=`${n}_formatted`;return r[f]||String(r[n])}const Pa={KRW:{code:"KRW",symbol:"₩",locale:"ko-KR",decimals:0},USD:{code:"USD",symbol:"$",locale:"en-US",decimals:2},JPY:{code:"JPY",symbol:"¥",locale:"ja-JP",decimals:0},CNY:{code:"CNY",symbol:"¥",locale:"zh-CN",decimals:2},EUR:{code:"EUR",symbol:"€",locale:"de-DE",decimals:2}};function fp(e,t){const{value:r,currencyCode:n,locale:o}=e,a=n||t.getState("_global.preferredCurrency")||"KRW",s=Pa[a]||Pa.KRW,l=o||s.locale;try{return new Intl.NumberFormat(l,{style:"currency",currency:s.code,minimumFractionDigits:s.decimals,maximumFractionDigits:s.decimals}).format(r)}catch{const f=r.toLocaleString(void 0,{minimumFractionDigits:s.decimals,maximumFractionDigits:s.decimals});return`${s.symbol}${f}`}}function gp(e){return Pa[e]?.symbol||e}const Fa=window.G7Core?.createLogger?.("Handler:Currency")??{log:(...e)=>console.log("[Handler:Currency]",...e),warn:(...e)=>console.warn("[Handler:Currency]",...e),error:(...e)=>console.error("[Handler:Currency]",...e)},mc="g7_preferred_currency",hp="KRW";function pp(e,t){const{defaultCurrency:r=hp}=e;let n=r;try{if(typeof window<"u"&&window.localStorage){const o=localStorage.getItem(mc);o&&bc(o)&&(n=o)}}catch{Fa.warn("localStorage 접근 불가, 기본 통화 사용:",r)}return t.setState("global",{preferredCurrency:n}),n}function mp(e,t){const{currencyCode:r}=e;if(!bc(r)){Fa.warn("유효하지 않은 통화 코드:",r);return}try{typeof window<"u"&&window.localStorage&&localStorage.setItem(mc,r)}catch{Fa.warn("localStorage 저장 실패")}t.setState("global",{preferredCurrency:r})}function bc(e){return typeof e=="string"&&/^[A-Z]{3}$/.test(e)}const Pr=window.G7Core?.createLogger?.("Handler:SetTheme")??{log:(...e)=>console.log("[Handler:SetTheme]",...e),warn:(...e)=>console.warn("[Handler:SetTheme]",...e),error:(...e)=>console.error("[Handler:SetTheme]",...e)},$a=["auto","light","dark"],yc="g7_color_scheme",bp=e=>e==="auto"?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e,eo=e=>{const t=bp(e);document.documentElement.setAttribute("data-theme",t),t==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")};function yp(){try{const e=localStorage.getItem(yc),t=e&&$a.includes(e)?e:"auto";eo(t),Pr.log("Initial theme applied:",t)}catch(e){Pr.warn("Failed to load initial theme:",e),eo("auto")}}async function vp(e,t){const r=e?.target;if(r&&typeof r=="string"&&$a.includes(r)){eo(r);return}yp()}async function wp(e,t){let r;if(e?.target&&typeof e.target=="string"&&!e.target.includes("{{")&&(r=e.target),!r||typeof r!="string"){Pr.warn("Invalid theme:",r);return}if(!$a.includes(r)){Pr.warn("Unsupported theme:",r);return}const n=r;try{localStorage.setItem(yc,n)}catch(o){Pr.error("Failed to save theme to localStorage:",o);return}eo(n),Pr.log("Theme changed to:",n)}const xp=window.G7Core?.createLogger?.("Handler:RedirectToLoginWithReturn")??{log:(...e)=>console.log("[Handler:RedirectToLoginWithReturn]",...e),warn:(...e)=>console.warn("[Handler:RedirectToLoginWithReturn]",...e),error:(...e)=>console.error("[Handler:RedirectToLoginWithReturn]",...e)};async function kp(e,t){const r=window.G7Core;if(!r?.dispatch){xp.error("G7Core.dispatch 가 초기화되지 않아 로그인 리다이렉트를 실행할 수 없습니다.");return}const n=window.location.pathname+window.location.search;await r.dispatch({handler:"navigate",params:{path:"/login",query:{redirect:n}}})}const Ua=window.G7Core?.createLogger?.("Handler:DownloadAttachment")??{log:(...e)=>console.log("[Handler:DownloadAttachment]",...e),warn:(...e)=>console.warn("[Handler:DownloadAttachment]",...e),error:(...e)=>console.error("[Handler:DownloadAttachment]",...e)};async function Cp(e,t){const r=window.G7Core,{url:n,filename:o}=e?.params||{};if(!n){Ua.warn("다운로드 URL 이 없어 요청을 건너뜁니다.");return}if(!r?.api?.get){Ua.error("G7Core.api.get 이 초기화되지 않아 다운로드를 실행할 수 없습니다.");return}try{const a=await r.api.get(n,{responseType:"blob"});if(a){const s=URL.createObjectURL(a),l=document.createElement("a");l.href=s,l.download=o||"",document.body.appendChild(l),l.click(),document.body.removeChild(l),URL.revokeObjectURL(s)}}catch(a){Ua.error("첨부파일 다운로드 실패",a),r?.toast?.error?.(r?.t?.("common.download_failed")??"Download failed")}}const to={"sirsoft-basic.addSelectedItemIfComplete":$0,"sirsoft-basic.updateSelectedItemQuantity":U0,"sirsoft-basic.removeSelectedItem":H0,"sirsoft-basic.updateNoOptionQuantity":G0,"sirsoft-basic.setBlockAdditionalOption":z0,"sirsoft-basic.getDisplayPrice":up,"sirsoft-basic.formatCurrency":fp,"sirsoft-basic.getCurrencySymbol":gp,"sirsoft-basic.loadPreferredCurrency":pp,"sirsoft-basic.savePreferredCurrency":mp,setTheme:wp,initTheme:vp,redirectToLoginWithReturn:kp,downloadAttachment:Cp,toggleCartItemSelection:K0,selectAllCartItems:V0,setCartOption:Y0,openCartDeleteModal:X0,openCartOptionModal:Z0,recalculateCart:q0,findMatchingOption:J0,initCartOptionSelection:R0,initCartKey:rp,getCartKey:np,clearCartKey:pc,regenerateCartKey:op,saveToStorage:ap,loadFromStorage:sp,initGuestOrderToken:lp,saveGuestOrderToken:ip,clearGuestOrderToken:cp,clearGuestTokenOnEntry:dp},un=window.G7Core?.createLogger?.("Template:sirsoft-basic:IdentityLauncher")??{log:(...e)=>console.log("[Template:sirsoft-basic:IdentityLauncher]",...e),warn:(...e)=>console.warn("[Template:sirsoft-basic:IdentityLauncher]",...e),error:(...e)=>console.error("[Template:sirsoft-basic:IdentityLauncher]",...e)};function Sp(e){const t=window.G7Core,r=t?.state?.getLocal?.()??{},n=t?.state?.getGlobal?.()??t?.state?.get?.()??{},o=(...f)=>f.find(h=>typeof h=="string"&&h.length>0),a=o(e.target?.email,n?.currentUser?.email,n?.user?.email,n?.auth?.user?.email,e.purpose==="signup"?r?.registerForm?.email:void 0,e.purpose==="password_reset"?r?.passwordResetForm?.email:void 0,e.purpose==="password_reset"?r?.email:void 0),s=o(e.target?.phone,n?.currentUser?.phone,n?.user?.phone,n?.auth?.user?.phone);if(!a&&!s)return null;const l={};return a&&(l.email=a),s&&(l.phone=s),l}function _p(){const t=window.G7Core?.api?.getToken?.()??null;return t?{Authorization:`Bearer ${t}`}:{}}function Ep(){try{const e=typeof window<"u"?window.localStorage?.getItem("g7_locale"):null;return e?{"Accept-Language":e}:{}}catch{return{}}}async function Tp(e,t){const r={purpose:e.purpose};e.provider_id&&(r.provider_id=e.provider_id),t&&(r.target=t);const n=e.challenge_start_url||"/api/identity/challenges",o=await fetch(n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",Accept:"application/json",...Ep(),..._p()},body:JSON.stringify(r)}),a=await o.json().catch(()=>null);if(!o.ok||!a?.success){const l=a?.message??`Challenge 시작 실패 (HTTP ${o.status})`;throw new Error(l)}const s=a.data??a;return{id:s.id,expires_at:s.expires_at,render_hint:s.render_hint??e.render_hint??"text_code",public_payload:s.public_payload,redirect_url:s.redirect_url,max_attempts:typeof s.max_attempts=="number"?s.max_attempts:void 0}}async function Np(e){const t=window.G7Core,r=t?.identity;if(!t?.dispatch||!t?.state||!r)return un.error("G7Core 또는 G7Core.identity 가 초기화되지 않아 launcher 를 실행할 수 없습니다."),{status:"failed",failureCode:"G7_NOT_READY"};if(e.render_hint==="external_redirect"||e.redirect_url)return r.redirectExternally(e);const n=Sp(e);let o;try{o=await Tp(e,n)}catch(p){un.error("Challenge 시작 실패:",p);try{await t.dispatch({handler:"toast",params:{type:"error",message:p instanceof Error?p.message:"본인인증 시작에 실패했습니다."}})}catch{}return{status:"failed",failureCode:"CHALLENGE_START_FAILED",reason:p instanceof Error?p.message:String(p)}}if(o.redirect_url)return r.redirectExternally({...e,render_hint:"external_redirect",redirect_url:o.redirect_url});const a=o.expires_at?new Date(o.expires_at).getTime():0,s=a>0?Math.max(0,Math.floor((a-Date.now())/1e3)):0,l=typeof o.max_attempts=="number"?o.max_attempts:0;t.state.set({identityChallenge:{policy_key:e.policy_key,purpose:e.purpose,provider_id:e.provider_id??null,render_hint:o.render_hint,challenge_id:o.id,expires_at:o.expires_at,public_payload:o.public_payload??{},target:n??null,code:"",error:null,attempts:0,maxAttempts:l,remainingSeconds:s,resendCooldown:0}});let f=a,h=0;const d=window.setInterval(()=>{const p=f>0?Math.max(0,Math.floor((f-Date.now())/1e3)):0;h=Math.max(0,h-1),t.state.set({identityChallenge:{remainingSeconds:p,resendCooldown:h}})},1e3);let i=null;try{i=t.state.subscribe?.(p=>{const m=p?.identityChallenge?.expires_at;if(typeof m=="string"){const x=new Date(m).getTime();Number.isFinite(x)&&x!==f&&(f=x)}const w=p?.identityChallenge?.resendCooldown;typeof w=="number"&&w>h&&(h=w)})??null}catch{}const u=r.createDeferred();try{await t.dispatch({handler:"openModal",target:"identity-challenge-modal"})}catch(p){return un.error("openModal 실패 — 풀페이지로 폴백:",p),window.clearInterval(d),i?.(),r.redirectExternally({...e,render_hint:"external_redirect",redirect_url:`/identity/challenge?challenge_id=${encodeURIComponent(o.id)}&return=${encodeURIComponent(window.location.href)}`})}const g=await u;return window.clearInterval(d),i?.(),g}function Ap(){const e=window.G7Core?.identity;if(!e?.setLauncher){un.warn("G7Core.identity 가 아직 초기화되지 않아 launcher 등록을 건너뜁니다. 코어 부트스트랩 순서를 확인하세요.");return}e.setLauncher(Np),un.log("IDV launcher registered (sirsoft-basic)")}const vc=window.G7Core?.createLogger?.("Template:sirsoft-basic:device")??{log:(...e)=>console.log("[Template:sirsoft-basic:device]",...e),warn:(...e)=>console.warn("[Template:sirsoft-basic:device]",...e)};function Mp(){if(typeof navigator>"u")return!1;const e=navigator,t=(e.userAgent||"").toLowerCase(),r=((e.userAgentData?.platform??e.platform)||"").toLowerCase(),n=e.maxTouchPoints??0;return/iphone|ipad|ipod/.test(t)||/iphone|ipad|ipod|ios/.test(r)?!0:/macintosh|mac os x/.test(t)&&n>1}function Op(){const e=window.G7Core;if(!e?.state?.get||!e?.state?.set){vc.warn("G7Core.state not available; skip iOS device correction");return}if(!Mp())return;const r=(e.state.get()||{}).appConfig||{};r.isIos!==!0&&(e.state.set({appConfig:{...r,isIos:!0}}),vc.log("appConfig.isIos corrected to true by client signals (iPadOS desktop-UA)"))}function Ip(e){const t=e.icons;return Array.isArray(t)?t.filter(r=>!!r&&typeof r=="object"&&typeof r.value=="string"):[]}function Dp(e,t){const r=e.label;return typeof r=="string"?r.startsWith("$t:")?t(r.slice(3)):r:e.value}function Lp(e,t,r){if(r==="")return!0;const n=r.toLowerCase();return e.value.toLowerCase().includes(n)||t.toLowerCase().includes(n)?!0:(e.keywords??[]).some(o=>o.toLowerCase().includes(n))}function Pp({entry:e}){const t=e.preview;return t?.html?c.jsx("span",{className:"g7le-icon-preview",dangerouslySetInnerHTML:{__html:t.html},style:Ha}):t?.className?c.jsx("span",{className:`g7le-icon-preview ${t.className}`,style:Ha}):c.jsx("i",{className:`fas fa-${e.value}`,style:Ha,"aria-hidden":"true"})}function Fp({control:e,value:t,onChange:r,t:n}){const o=Ip(e),a=t==null?"":String(t),s=typeof e.iconColumns=="number"?e.iconColumns:6,l=e.iconSearchPlaceholder,f=typeof l=="string"&&l.startsWith("$t:")?n(l.slice(3)):n("layout_editor.icon_picker.search_placeholder"),[h,d]=k.useState("");if(o.length===0)return c.jsx("div",{className:"g7le-widget g7le-widget--icon-picker","data-testid":"g7le-widget-icon-picker",style:wc,children:c.jsx("input",{type:"text",className:"g7le-widget g7le-widget--icon-free","data-testid":"g7le-widget-icon-picker-free",value:a,placeholder:n("layout_editor.icon_picker.free_input_hint"),onChange:g=>r(g.target.value===""?void 0:g.target.value),style:xc})});const i=g=>Dp(g,n),u=o.filter(g=>Lp(g,i(g),h));return c.jsxs("div",{className:"g7le-widget g7le-widget--icon-picker","data-testid":"g7le-widget-icon-picker",style:wc,children:[c.jsx("input",{type:"text",className:"g7le-widget g7le-widget--icon-search","data-testid":"g7le-widget-icon-picker-search",value:h,placeholder:f,onChange:g=>d(g.target.value),style:xc}),c.jsxs("div",{className:"g7le-icon-grid","data-testid":"g7le-widget-icon-picker-grid",style:{...$p,gridTemplateColumns:`repeat(${s}, minmax(0, 1fr))`},children:[c.jsx("button",{type:"button","data-testid":"g7le-icon-cell-none",title:n("layout_editor.icon_picker.none"),onClick:()=>r(void 0),"aria-pressed":a==="",style:a===""?kc:za,children:c.jsx("span",{style:Up,children:"—"})}),u.map(g=>{const p=g.value===a;return c.jsx("button",{type:"button","data-testid":`g7le-icon-cell-${g.value}`,title:i(g),"aria-pressed":p,onClick:()=>r(g.value),style:p?kc:za,children:c.jsx(Pp,{entry:g})},g.value)})]}),u.length===0&&c.jsx("div",{"data-testid":"g7le-widget-icon-picker-empty",style:zp,children:n("layout_editor.icon_picker.no_results")})]})}const wc={display:"flex",flexDirection:"column",gap:6,width:"100%"},xc={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,width:"100%"},$p={display:"grid",gap:4,maxHeight:220,overflowY:"auto",padding:2},za={display:"flex",alignItems:"center",justifyContent:"center",minHeight:34,padding:4,border:"1px solid #e2e8f0",borderRadius:6,background:"#fff",cursor:"pointer"},kc={...za,border:"2px solid #2563eb",background:"#eff6ff"},Ha={display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:16,lineHeight:1},Up={fontSize:10,color:"#475569",fontFamily:"monospace",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:"100%"},zp={fontSize:11,color:"#94a3b8",fontStyle:"italic",padding:"4px 2px"},Cc=window.G7Core?.createLogger?.("Template:sirsoft-basic:EditorWidgets")??{log:(...e)=>console.log("[Template:sirsoft-basic:EditorWidgets]",...e),warn:(...e)=>console.warn("[Template:sirsoft-basic:EditorWidgets]",...e)};function Hp(){if(typeof window>"u")return;const e=window.G7Core?.layoutEditor;if(!e?.registerWidget){Cc.warn("G7Core.layoutEditor 미노출 — icon-picker 위젯 등록 보류");return}e.registerWidget("icon-picker",Fp),Cc.log("편집기 위젯 'icon-picker' 등록됨(Font Awesome 검색 그리드)")}const Ga=window.G7Core?.createLogger?.("Template:sirsoft-basic")??{log:(...e)=>console.log("[Template:sirsoft-basic]",...e),warn:(...e)=>console.warn("[Template:sirsoft-basic]",...e),error:(...e)=>console.error("[Template:sirsoft-basic]",...e)};typeof window<"u"&&(window.G7TemplateHandlers=to);function Sc(){if(typeof window<"u"){let e=0;const t=50,r=()=>{const n=window.G7Core?.getActionDispatcher?.();n?(Object.entries(to).forEach(([o,a])=>{n.registerHandler(o,a)}),Ga.log(`${Object.keys(to).length} custom handler(s) registered:`,Object.keys(to)),Ap(),Op()):(e++,e<=t?(Ga.warn(`ActionDispatcher not found, retrying... (${e}/${t})`),setTimeout(r,100)):Ga.error("Failed to register handlers: ActionDispatcher not available after maximum retries"))};document.readyState==="complete"?r():window.addEventListener("load",r)}}return Hp(),Sc(),J.A=ao,J.Avatar=Ur,J.AvatarUploader=Aa,J.BrandMark=xo,J.Button=Q,J.Checkbox=Za,J.Code=Xc,J.ConfirmDialog=ta,J.Container=N0,J.Div=W,J.ExpandableContent=Jo,J.FileInput=Ba,J.FileUploader=Xn,J.Flex=M0,J.Footer=rs,J.Form=so,J.Grid=A0,J.H1=Fc,J.H2=Va,J.H3=gn,J.H4=Ya,J.Header=es,J.Hr=lo,J.HtmlContent=Zo,J.HtmlEditor=Ll,J.Icon=de,J.IconName=Je,J.ImageGallery=Tr,J.Img=Lt,J.Input=xt,J.Label=yr,J.Li=Xt,J.MobileNav=ns,J.Modal=Ro,J.Nav=$r,J.NotificationCenter=mn,J.Ol=$c,J.Optgroup=Gc,J.Option=Hc,J.P=Dt,J.PageLoading=ec,J.PageSkeleton=Na,J.PageTransitionBlur=_a,J.PageTransitionIndicator=Sa,J.Pagination=tc,J.PasswordInput=Ka,J.PostReactions=Il,J.ProductCard=ms,J.ProductImageViewer=An,J.QuantitySelector=Ml,J.RichTextEditor=Dl,J.SearchBar=nc,J.Section=qa,J.SectionLayout=O0,J.Select=Xa,J.SlotContainer=pn,J.SocialLoginButtons=Ki,J.Span=ee,J.Svg=fn,J.TabNavigation=lc,J.Table=jc,J.Tbody=Wc,J.Td=Yc,J.Textarea=no,J.Th=Vc,J.Thead=Bc,J.ThemeToggle=hn,J.ThreeColumnLayout=I0,J.Toast=Ca,J.Tr=Kc,J.Ul=oo,J.UserInfo=sc,J.availablePasswordRules=ro,J.compositeComponents=T0,J.defaultPasswordRules=Wa,J.initTemplate=Sc,J.templateMetadata=D0,Object.defineProperty(J,Symbol.toStringTag,{value:"Module"}),J})({},ReactJSXRuntime,React,ReactDOM); + `})]}):null},n0=Object.freeze(Object.defineProperty({__proto__:null,PageTransitionIndicator:Sa,default:Sa},Symbol.toStringTag,{value:"Module"})),Yi=window.G7Core?.createLogger?.("Comp:PageTransitionBlur")??{log:(...e)=>console.log("[Comp:PageTransitionBlur]",...e),warn:(...e)=>console.warn("[Comp:PageTransitionBlur]",...e)},_a=({className:e="",style:t})=>{const[r,n]=k.useState(!1);return k.useEffect(()=>{const o=window.G7Core?.TransitionManager;if(!o){Yi.warn("TransitionManager를 찾을 수 없습니다.");return}return n(o.getIsPending()),o.subscribe(s=>{Yi.log("isPending changed:",s),n(s)})},[]),r?c.jsx(W,{className:`fixed inset-0 z-40 bg-white/30 dark:bg-gray-900/30 backdrop-blur-sm transition-opacity duration-150 pointer-events-none ${e}`,style:t,role:"status","aria-label":"페이지 전환 중","data-testid":"page-transition-blur"}):null},o0=Object.freeze(Object.defineProperty({__proto__:null,PageTransitionBlur:_a,default:_a},Symbol.toStringTag,{value:"Module"})),Xi={sm:640,md:768,lg:1024,xl:1280,"2xl":1536},qi=new Set(["hidden","block","inline-block","inline","flex","inline-flex","grid","inline-grid","table","table-row","table-cell","contents","list-item","flow-root"]),a0=new Set(["Div","Flex","Grid","Section","Article","Nav","Aside","Main","Header","Footer","Fragment","Form","Container"]),s0=new Set(["H1","H2","H3","H4","H5","H6","P","Span","Label","A","Strong","Em","Small","Badge"]),l0=new Set(["Input","Textarea","Select","Checkbox","Radio","Toggle","DatePicker","TagInput","SearchBar"]),i0=new Set(["Img","Image","Avatar","AvatarUploader","ImageGallery","ProductImageViewer","FileUploader"]),Zi={DataGrid:(e,t)=>c.jsxs("div",{className:"w-full border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden",children:[c.jsx("div",{className:`h-10 bg-gray-100 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 ${e}`,children:c.jsxs("div",{className:"flex items-center h-full px-4 gap-8",children:[c.jsx("div",{className:"h-3 w-16 bg-gray-300 dark:bg-gray-600 rounded"}),c.jsx("div",{className:"h-3 w-24 bg-gray-300 dark:bg-gray-600 rounded"}),c.jsx("div",{className:"h-3 w-20 bg-gray-300 dark:bg-gray-600 rounded"}),c.jsx("div",{className:"h-3 w-16 bg-gray-300 dark:bg-gray-600 rounded"})]})}),Array.from({length:t},(r,n)=>c.jsx("div",{className:`h-12 border-b border-gray-100 dark:border-gray-800 ${e}`,style:{animationDelay:`${n*75}ms`},children:c.jsxs("div",{className:"flex items-center h-full px-4 gap-8",children:[c.jsx("div",{className:"h-3 w-12 bg-gray-200 dark:bg-gray-700 rounded"}),c.jsx("div",{className:"h-3 flex-1 bg-gray-200 dark:bg-gray-700 rounded"}),c.jsx("div",{className:"h-3 w-16 bg-gray-100 dark:bg-gray-800 rounded"}),c.jsx("div",{className:"h-3 w-14 bg-gray-100 dark:bg-gray-800 rounded"})]})},n))]}),Pagination:e=>c.jsx("div",{className:"flex justify-center gap-1.5 py-3",children:Array.from({length:5},(t,r)=>c.jsx("div",{className:`w-8 h-8 bg-gray-200 dark:bg-gray-700 rounded ${e}`},r))}),Tabs:e=>c.jsxs("div",{children:[c.jsx("div",{className:"flex gap-4 border-b border-gray-200 dark:border-gray-700 pb-2 mb-3",children:Array.from({length:3},(t,r)=>c.jsx("div",{className:`h-4 w-20 bg-gray-200 dark:bg-gray-700 rounded ${e}`},r))}),c.jsx("div",{className:`h-32 bg-gray-100 dark:bg-gray-800 rounded ${e}`})]}),TabNavigation:e=>c.jsx("div",{className:"flex gap-4 border-b border-gray-200 dark:border-gray-700 pb-2",children:Array.from({length:3},(t,r)=>c.jsx("div",{className:`h-4 w-20 bg-gray-200 dark:bg-gray-700 rounded ${e}`},r))}),ProductCard:e=>c.jsxs("div",{className:"rounded-lg overflow-hidden",children:[c.jsx("div",{className:`h-48 w-full bg-gray-200 dark:bg-gray-700 ${e}`}),c.jsxs("div",{className:"p-3 space-y-2",children:[c.jsx("div",{className:`h-3.5 w-3/4 bg-gray-200 dark:bg-gray-700 rounded ${e}`}),c.jsx("div",{className:`h-4 w-1/3 bg-gray-300 dark:bg-gray-600 rounded ${e}`})]})]}),UserInfo:e=>c.jsx("div",{className:`h-3 w-14 bg-gray-200 dark:bg-gray-700 rounded ${e}`}),QuantitySelector:e=>c.jsx("div",{className:`h-9 w-28 bg-gray-100 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 ${e}`}),Header:e=>c.jsx("header",{className:"bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700",children:c.jsx("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8",children:c.jsxs("div",{className:"flex items-center justify-between h-16",children:[c.jsxs("div",{className:"flex items-center gap-8",children:[c.jsx("div",{className:`h-8 w-24 bg-gray-200 dark:bg-gray-700 rounded ${e}`}),c.jsx("div",{className:"hidden lg:flex items-center gap-6",children:Array.from({length:4},(t,r)=>c.jsx("div",{className:`h-3.5 w-16 bg-gray-200 dark:bg-gray-700 rounded ${e}`},r))})]}),c.jsx("div",{className:"flex items-center gap-4",children:Array.from({length:3},(t,r)=>c.jsx("div",{className:`h-8 w-8 bg-gray-200 dark:bg-gray-700 rounded-full ${e}`},r))})]})})}),Footer:e=>c.jsx("footer",{className:"bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 mt-auto",children:c.jsx("div",{className:"max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8",children:c.jsxs("div",{className:"flex flex-col items-center gap-4",children:[c.jsx("div",{className:`h-4 w-32 bg-gray-200 dark:bg-gray-700 rounded ${e}`}),c.jsx("div",{className:`h-3 w-48 bg-gray-100 dark:bg-gray-800 rounded ${e}`}),c.jsx("div",{className:"flex gap-3",children:Array.from({length:3},(t,r)=>c.jsx("div",{className:`h-6 w-6 bg-gray-200 dark:bg-gray-700 rounded-full ${e}`},r))}),c.jsx("div",{className:`h-3 w-40 bg-gray-100 dark:bg-gray-800 rounded ${e}`})]})})}),Modal:()=>c.jsx(c.Fragment,{}),Toast:()=>c.jsx(c.Fragment,{}),ConfirmDialog:()=>c.jsx(c.Fragment,{})};function c0(e){if(!e||e.length===0)return[];const t=e.filter(n=>n.if),r=e.filter(n=>!n.if);if(r.length>0&&t.length>0){const n=t.filter(o=>!Qi(o.if));return n.length>1&&d0(n)?[...r,Ji(n)]:[...r,...n]}if(t.length>1&&r.length===0){const n=t.filter(o=>!Qi(o.if));return n.length===0?[]:n.length===1?n:[Ji(n)]}return e}function Qi(e){const t=e.replace(/^\{\{|\}\}$/g,"").trim();return t.startsWith("!")||/\b(hasError|isError|isLoading|error|Error)\b/.test(t)||/===\s*0\s*(\)|\}|$)/.test(t)}function d0(e){if(e.length<2)return!1;const t=[];for(const n of e){const o=(n.if||"").replace(/^\{\{|\}\}$/g,"").trim(),a=o.match(/^(.+?)\s*===\s*['"]/);if(a)t.push(a[1].trim());else{const s=o.match(/(.+?)\s*===\s*['"]/);if(!s)return!1;t.push(s[1].trim())}}const r=t[0];return t.every(n=>n===r)}function Ji(e){return e.reduce((t,r)=>Ea(r)>Ea(t)?r:t)}function Ea(e){return e.children?e.children.length+e.children.reduce((t,r)=>t+Ea(r),0):0}function u0(e){return e.includes("{{")?e.replace(/\{\{([^}]+)\}\}/g,(t,r)=>{const n=r.match(/\?[\s]*['"]([^'"]*)['"]\s*:\s*['"]/);return n?n[1]:""}):e}function Ta(e,t){if(!e)return"";let r=e;return r=r.replace(/\b(bg-\S+|text-\S+|border\b|border-\S+|shadow\S*|ring-\S+|outline-\S+|divide-\S+|opacity-\S+|font-\S+|tracking-\S+|leading-\S+|whitespace-\S+|truncate|line-clamp-\S+|underline|no-underline|decoration-\S+|cursor-\S+|hover:\S+|focus:\S+|active:\S+|group-hover:\S+|transition\S*|duration-\S+|ease-\S+|animate-\S+|dark:\S+)\b/g,"").replace(/\s{2,}/g," ").trim(),(t==="Grid"||/\bgrid-cols-\d/.test(r))&&(r=r.replace(/\bgrid-cols-(\d+)/g,(n,o)=>{const a=parseInt(o);return a>4?`grid-cols-${Math.ceil(a/2)}`:`grid-cols-${a}`})),r}function f0(e){const{name:t,props:r}=e;if(!r||!t)return"";const n=[];if(t==="Flex"){n.push("flex");const o=r.direction||"row",a={row:"flex-row","row-reverse":"flex-row-reverse",col:"flex-col","col-reverse":"flex-col-reverse"};a[o]&&n.push(a[o]);const s=r.justify||"start",l={start:"justify-start",end:"justify-end",center:"justify-center",between:"justify-between",around:"justify-around",evenly:"justify-evenly"};l[s]&&n.push(l[s]);const f=r.align||"stretch",h={start:"items-start",end:"items-end",center:"items-center",baseline:"items-baseline",stretch:"items-stretch"};h[f]&&n.push(h[f]);const d=r.wrap||"nowrap",i={wrap:"flex-wrap",nowrap:"flex-nowrap","wrap-reverse":"flex-wrap-reverse"};i[d]&&n.push(i[d]),r.gap&&r.gap>0&&n.push(`gap-${r.gap}`)}if(t==="Grid"){n.push("grid");const o=r.cols||1;if(n.push(`grid-cols-${o}`),r.responsive){const a=r.responsive;a.sm&&n.push(`sm:grid-cols-${a.sm}`),a.md&&n.push(`md:grid-cols-${a.md}`),a.lg&&n.push(`lg:grid-cols-${a.lg}`),a.xl&&n.push(`xl:grid-cols-${a.xl}`),a["2xl"]&&n.push(`2xl:grid-cols-${a["2xl"]}`)}r.gap!==void 0&&r.gap>0&&n.push(`gap-${r.gap}`),r.rowGap!==void 0&&r.rowGap>0&&n.push(`gap-y-${r.rowGap}`),r.colGap!==void 0&&r.colGap>0&&n.push(`gap-x-${r.colGap}`)}return n.join(" ")}function g0(e){switch(e){case"pulse":return"animate-pulse";case"wave":return"animate-pulse";case"none":return"";default:return"animate-pulse"}}function qn(e,t,r,n){return!e||e.length===0?[]:c0(e).map((a,s)=>Ri(a,t,r,s,n))}function h0(e,t){const r=e.props?.className||e.className||"";return e.responsive?t>=1024&&e.responsive.desktop?.props?.className?e.responsive.desktop.props.className:t>=768&&e.responsive.tablet?.props?.className?e.responsive.tablet.props.className:r:r}function p0(e,t){const r=e.split(/\s+/).filter(Boolean),n=[],o=[];for(const f of r){const h=f.match(/^(sm|md|lg|xl|2xl):(.+)$/);if(h){const[,d,i]=h;if(qi.has(i)){n.push({breakpoint:Xi[d]||0,display:i});continue}(Xi[d]||0)<=t&&o.push(i);continue}if(qi.has(f)){n.push({breakpoint:0,display:f});continue}o.push(f)}if(n.length===0)return{visible:!0,className:e};n.sort((f,h)=>f.breakpoint-h.breakpoint);let a="";for(const f of n)f.breakpoint<=t&&(a=f.display);a||(a=n[0].display);const s=a!=="hidden",l=s?[a,...o].join(" "):"";return{visible:s,className:l}}function m0(e){const t=e.match(/\bgrid-cols-\[([^\]]+)\]/);if(!t)return{className:e};const r=t[1].replace(/_/g," ");return{className:e.replace(/\bgrid-cols-\[([^\]]+)\]/,"").replace(/\s{2,}/g," ").trim(),style:{gridTemplateColumns:r}}}function Ri(e,t,r,n,o){const{name:a,children:s,iteration:l}=e,f=h0(e,o),h=f0(e),d=h?`${h} ${f}`.trim():f,i=u0(d),u=p0(i,o);if(!a||!u.visible)return null;const g=u.className;if(l)return c.jsx(k.Fragment,{children:Array.from({length:r},(m,w)=>Ri({...e,iteration:void 0},t,r,w,o))},n);if(Zi[a])return c.jsx("div",{className:g,children:Zi[a](t,r)},n);if(a0.has(a)){const m=Ta(g,a);if(!s||s.length===0){const E=/\b(h-\S|w-\S)/.test(m)?`${m} bg-gray-200 dark:bg-gray-700 rounded ${t}`:`${m} h-3.5 w-full bg-gray-200 dark:bg-gray-700 rounded ${t}`.trim();return c.jsx("div",{className:E},n)}const w=qn(s,t,r,o);if(!(w.length>0&&w.some(y=>y!==null)))return null;const O=m0(m);return c.jsx("div",{className:O.className,style:O.style,children:w},n)}const p=Ta(g,a);if(s0.has(a)){const m={H1:"h-7",H2:"h-6",H3:"h-5",H4:"h-5",H5:"h-4",H6:"h-4",P:"h-3.5",Span:"h-3",Label:"h-3",A:"h-3.5",Badge:"h-5 w-16"},w={H1:"w-3/5",H2:"w-2/5",H3:"w-1/3",H4:"w-1/3",H5:"w-1/4",H6:"w-1/4",P:"w-full",Span:"w-1/4",Label:"w-1/4",A:"w-1/3",Strong:"w-1/5",Em:"w-1/4",Small:"w-1/5",Badge:"w-16"},x=m[a]||"h-3.5",O=w[a]||"w-full",y=a.startsWith("H")?"mb-2 mt-1":"mb-1.5";return c.jsx("div",{className:`${x} ${O} bg-gray-200 dark:bg-gray-700 rounded ${t} ${y} ${p}`.trim()},n)}if(l0.has(a))return a==="Textarea"?c.jsx("div",{className:`h-20 w-full bg-gray-100 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 mb-2 ${t}`},n):a==="Checkbox"||a==="Radio"||a==="Toggle"?c.jsx("div",{className:`h-5 w-5 bg-gray-200 dark:bg-gray-700 rounded mb-1.5 ${t}`},n):c.jsx("div",{className:`h-9 w-full bg-gray-100 dark:bg-gray-800 rounded border border-gray-200 dark:border-gray-700 mb-2 ${t}`},n);if(i0.has(a))return a==="Avatar"||a==="AvatarUploader"?c.jsx("div",{className:`h-10 w-10 bg-gray-200 dark:bg-gray-700 rounded-full ${t}`},n):a==="ProductImageViewer"?c.jsx("div",{className:`h-80 w-full bg-gray-200 dark:bg-gray-700 rounded ${t}`},n):c.jsx("div",{className:`h-40 w-full bg-gray-200 dark:bg-gray-700 rounded mb-2 ${t}`},n);if(a==="Button"){if(s&&s.length>0){const m=Ta(g,a),w=qn(s,t,r,o);if(!(w.length>0&&w.some(E=>E!==null)))return null;const y=/\b(border|rounded|px-\d|py-\d)/.test(f)?"border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50 rounded-lg":"";return c.jsx("div",{className:`${m} ${y}`.trim(),children:w},n)}return c.jsx("div",{className:`h-9 w-24 bg-gray-200 dark:bg-gray-700 rounded ${t}`},n)}return a==="Icon"?c.jsx("div",{className:`h-5 w-5 bg-gray-200 dark:bg-gray-700 rounded ${t}`},n):s&&s.length>0?c.jsx("div",{className:p,children:qn(s,t,r,o)},n):c.jsx("div",{className:`h-3.5 w-full bg-gray-200 dark:bg-gray-700 rounded mb-1.5 ${t}`},n)}const Na=({components:e,options:t})=>{const r=g0(t.animation),o=window.G7Core?.useResponsive,a=o?.(),s=a?a.width:typeof window<"u"?window.innerWidth:1024;return c.jsx("div",{className:"w-full",role:"status","aria-busy":"true","aria-label":"Loading...",children:qn(e,r,t.iteration_count,s)})},b0=Object.freeze(Object.defineProperty({__proto__:null,PageSkeleton:Na,default:Na},Symbol.toStringTag,{value:"Module"})),y0=(e,t)=>window.G7Core?.t?.(e,t)??e,ec=({options:e})=>{const t=document.documentElement.classList.contains("dark"),r=t?"rgb(17,24,39)":"rgb(249,250,251)",n=t?"#6b7280":"#9ca3af",o=t?"#9ca3af":"#6b7280";return c.jsxs("div",{style:{position:"absolute",inset:0,zIndex:2147483647,overflow:"hidden",background:r,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"flex-start",paddingTop:"15%",gap:"12px"},children:[c.jsx("div",{style:{width:"32px",height:"32px",border:`3px solid ${n}`,borderTopColor:"transparent",borderRadius:"50%",animation:"g7-spin 0.8s linear infinite"}}),c.jsx("span",{style:{color:o,fontSize:"14px"},children:e?.text||y0("nav.loading")})]})},v0=Object.freeze(Object.defineProperty({__proto__:null,default:ec},Symbol.toStringTag,{value:"Module"})),Dr=(e,t)=>window.G7Core?.t?.(e,t)??e,tc=({currentPage:e,totalPages:t,onPageChange:r,maxVisiblePages:n=5,showFirstLast:o=!0,className:a="",style:s,prevText:l,nextText:f,id:h,editorAttrs:d})=>{const i=k.useMemo(()=>{const m=[];if(t<=n+2)for(let w=1;w<=t;w++)m.push(w);else{const w=Math.floor(n/2);let x=Math.max(2,e-w),O=Math.min(t-1,e+w);e<=w+1?O=n:e>=t-w&&(x=t-n+1),m.push(1),x>2&&m.push("...");for(let y=x;y<=O;y++)m.push(y);O1&&m.push(t)}return m},[e,t,n]),u=m=>{m<1||m>t||m===e||r(m)},g=()=>{e>1&&r(e-1)},p=()=>{eu(1),disabled:e===1,className:"px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800","aria-label":Dr("common.first_page"),children:"«"}),c.jsx(Q,{onClick:g,disabled:e===1,className:"px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800","aria-label":Dr("common.prev_page"),children:l||c.jsx(c.Fragment,{children:"‹"})}),c.jsx(W,{className:"flex items-center gap-1",children:i.map((m,w)=>{if(m==="...")return c.jsx(ee,{className:"px-3 py-1 text-sm text-gray-500 dark:text-gray-400",children:"..."},`ellipsis-${w}`);const x=m,O=x===e;return c.jsx(Q,{onClick:()=>u(x),className:`px-3 py-1 text-sm border rounded ${O?"bg-blue-500 dark:bg-blue-600 text-white border-blue-500 dark:border-blue-600":"border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800"}`,"aria-label":Dr("common.page_n",{n:x}),"aria-current":O?"page":void 0,children:x},x)})}),c.jsx(Q,{onClick:p,disabled:e===t,className:"px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800","aria-label":Dr("common.next_page"),children:f||c.jsx(c.Fragment,{children:"›"})}),o&&c.jsx(Q,{onClick:()=>u(t),disabled:e===t,className:"px-3 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-100 dark:hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800","aria-label":Dr("common.last_page"),children:"»"})]})},w0=Object.freeze(Object.defineProperty({__proto__:null,Pagination:tc},Symbol.toStringTag,{value:"Module"})),rc=(e,t)=>window.G7Core?.t?.(e,t)??e,nc=({name:e="search",placeholder:t,value:r,onChange:n,onSubmit:o,showButton:a=!1,suggestions:s=[],onSuggestionClick:l,showSuggestions:f=!1,className:h="",style:d,id:i,editorAttrs:u})=>{const g=t??rc("common.search_placeholder"),[p,m]=k.useState(""),[w,x]=k.useState(!1),O=k.useRef(null),y=k.useRef(""),E=r!==void 0?r:p,M=f&&w&&s.length>0&&E.length>0;k.useEffect(()=>{r!==void 0&&(y.current=r)},[r]);const _=v=>{const N=v.target.value;m(N),n?.(v),y.current!==""&&N===""&&!v.nativeEvent.inputType&&setTimeout(()=>{const A=O.current?.querySelector("form");A&&A.requestSubmit()},0),y.current=N},I=v=>{m(v.text);const N={target:{value:v.text,name:e}};n?.(N),l?.(v),x(!1)},C=v=>{v.preventDefault(),o?.(v)};return c.jsxs(W,{ref:O,className:`relative ${h}`,style:d,id:i,...u,children:[c.jsx(so,{onSubmit:C,className:"relative",children:c.jsxs(W,{className:`relative flex items-center ${a?"gap-2":""}`,children:[c.jsxs(W,{className:"relative flex-1",children:[c.jsx(W,{className:"absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",children:c.jsx(de,{name:Je.Search,className:"w-5 h-5 text-gray-400 dark:text-gray-500"})}),c.jsx(xt,{type:"search",name:e,value:E,onChange:_,onFocus:()=>x(!0),onBlur:()=>setTimeout(()=>x(!1),200),placeholder:g,className:"w-full pl-10 pr-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white text-sm"})]}),a&&c.jsx(Q,{type:"submit",className:"px-4 py-2 bg-gray-800 dark:bg-gray-600 text-white rounded-lg hover:bg-gray-900 dark:hover:bg-gray-500 transition-colors text-sm font-medium cursor-pointer h-[42px]",children:rc("common.search")})]})}),M&&c.jsx(W,{className:"absolute z-10 w-full mt-2 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg max-h-64 overflow-y-auto",children:s.map(v=>c.jsx(W,{className:"px-4 py-3 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer border-b border-gray-100 dark:border-gray-700 last:border-b-0 transition-colors",onClick:()=>I(v),children:c.jsxs(W,{className:"flex items-center gap-2",children:[c.jsx(de,{name:Je.Search,className:"w-4 h-4 text-gray-400 dark:text-gray-500"}),c.jsx(ee,{className:"text-sm text-gray-700 dark:text-gray-300",children:v.text})]})},v.id))})]})},x0=Object.freeze(Object.defineProperty({__proto__:null,SearchBar:nc},Symbol.toStringTag,{value:"Module"})),vt=window.G7Core,k0={sm:"md",md:"lg",lg:"xl",xl:"2xl","2xl":"3xl"};function Aa({src:e,fallbackText:t="U",size:r="lg",uploadEndpoint:n="/api/me/avatar",deleteEndpoint:o="/api/me/avatar",onUploadSuccess:a,onUploadError:s,onDeleteSuccess:l,onDeleteError:f,showDeleteButton:h=!0,accept:d="image/*",maxSize:i=5,className:u="",uploadButtonText:g,deleteButtonText:p,readOnly:m=!1,confirmDelete:w=!0,deleteConfirmMessage:x,confirmUpload:O=!0,uploadConfirmMessage:y,uploadSuccessActions:E,uploadErrorActions:M,deleteSuccessActions:_,deleteErrorActions:I,id:C,editorAttrs:v}){const N=k.useRef(null),[A,P]=k.useState(!1),[D,L]=k.useState(!1),[U,S]=k.useState(void 0),[b,$]=k.useState(null),[F,G]=k.useState(!1),[Y,B]=k.useState(!1),[V,j]=k.useState(null),[H,q]=k.useState(null),ue=k.useRef(`avatar-upload-${Math.random().toString(36).slice(2,11)}`).current;k.useEffect(()=>{if(V){const oe=URL.createObjectURL(V);return q(oe),()=>URL.revokeObjectURL(oe)}else q(null)},[V]);const te=k.useCallback(oe=>vt?.t?.(oe)??oe,[]),fe=k.useCallback(()=>{const oe=document.cookie.match(/XSRF-TOKEN=([^;]+)/);return oe?decodeURIComponent(oe[1]):null},[]),R=k.useCallback(()=>vt?.api?.getToken?.()??null,[]),ke=k.useCallback(async oe=>{B(!1),j(null),P(!0),$(null);try{const ae=new FormData;ae.append("avatar",oe);const be=fe(),xe=R(),He=await fetch(n,{method:"POST",headers:{Accept:"application/json",...be&&{"X-XSRF-TOKEN":be},...xe&&{Authorization:`Bearer ${xe}`}},credentials:"include",body:ae});if(!He.ok){const Oe=await He.json().catch(()=>({}));throw new Error(Oe.message||te("attachment.upload_failed"))}const Pe=await He.json(),Ke=Pe.data||Pe;Ke.avatar&&S(Ke.avatar),a?.(Ke),vt?.toast?.success?.(te("mypage.profile.avatar_uploaded")),E?.length?E.forEach(Oe=>vt?.dispatch?.(Oe)):vt?.refetchDataSource?.("user")}catch(ae){const be=ae instanceof Error?ae:new Error(String(ae));$(be.message),s?.(be),vt?.toast?.error?.(be.message),M?.length&&M.forEach(xe=>vt?.dispatch?.(xe))}finally{P(!1),N.current&&(N.current.value="")}},[n,a,s,fe,R,te]),me=k.useCallback(async oe=>{const ae=oe.target.files?.[0];if(!ae)return;$(null);const be=i*1024*1024;if(ae.size>be){const xe=new Error(te("attachment.file_too_large").replace(":max",`${i}MB`));$(xe.message),s?.(xe),vt?.toast?.error?.(xe.message);return}if(d&&!ae.type.match(d.replace("*",".*"))){const xe=new Error(te("attachment.invalid_file_type"));$(xe.message),s?.(xe),vt?.toast?.error?.(xe.message);return}O?(j(ae),B(!0)):ke(ae)},[i,d,s,O,ke,te]),Ge=k.useCallback(async()=>{G(!1),L(!0),$(null);try{const oe=fe(),ae=R(),be=await fetch(o,{method:"DELETE",headers:{Accept:"application/json","Content-Type":"application/json",...oe&&{"X-XSRF-TOKEN":oe},...ae&&{Authorization:`Bearer ${ae}`}},credentials:"include"});if(!be.ok){const xe=await be.json().catch(()=>({}));throw new Error(xe.message||te("attachment.delete_failed"))}S(null),l?.(),vt?.toast?.success?.(te("mypage.profile.avatar_deleted")),_?.length?_.forEach(xe=>vt?.dispatch?.(xe)):vt?.refetchDataSource?.("user")}catch(oe){const ae=oe instanceof Error?oe:new Error(String(oe));$(ae.message),f?.(ae),vt?.toast?.error?.(ae.message),I?.length&&I.forEach(be=>vt?.dispatch?.(be))}finally{L(!1)}},[o,l,f,fe,R,te]),De=k.useCallback(()=>{w?G(!0):Ge()},[w,Ge]),ye=k.useCallback(()=>{G(!1)},[]),Me=k.useCallback(()=>{B(!1),j(null),N.current&&(N.current.value="")},[]),Ce=k.useCallback(()=>{V&&ke(V)},[V,ke]),we=U===void 0?e:U,$e=!!we,Le=k0[r]||"lg",K=F||Y,re=()=>c.jsxs(W,{className:"flex items-center justify-center gap-2",children:[c.jsx(xt,{ref:N,id:ue,type:"file",accept:d,className:"hidden",onChange:me,disabled:A}),!$e&&c.jsxs(yr,{htmlFor:ue,className:`inline-flex items-center gap-2 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors cursor-pointer ${A?"opacity-50 cursor-not-allowed":""}`,children:[A?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"image",size:"sm"}),c.jsx(ee,{children:g||te("mypage.profile.register_avatar")})]}),$e&&c.jsxs(c.Fragment,{children:[c.jsxs(yr,{htmlFor:ue,className:`inline-flex items-center gap-2 px-4 py-2 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-lg text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors cursor-pointer ${A?"opacity-50 cursor-not-allowed":""}`,children:[A?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"upload",size:"sm"}),c.jsx(ee,{children:g||te("common.change")})]}),h&&c.jsxs(Q,{type:"button",className:"inline-flex items-center gap-2 px-4 py-2 border border-red-300 dark:border-red-600 text-red-600 dark:text-red-400 rounded-lg text-sm font-medium hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors disabled:opacity-50 disabled:cursor-not-allowed",onClick:De,disabled:D,children:[D?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"trash-2",size:"sm"}),c.jsx(ee,{children:p||te("common.delete")})]})]})]});return c.jsxs(W,{className:`flex flex-col items-center gap-3 ${u}`,id:C,...v,children:[Y&&H?c.jsxs(W,{className:"relative",children:[c.jsx(Lt,{src:H,alt:"Preview",className:`rounded-full object-cover ${r==="sm"?"w-10 h-10":r==="md"?"w-12 h-12":r==="lg"?"w-16 h-16":r==="xl"?"w-24 h-24":"w-32 h-32"}`}),c.jsx(W,{className:"absolute inset-0 rounded-full bg-blue-500/20 border-2 border-blue-500 border-dashed"})]}):c.jsx(Ur,{avatar:we||void 0,name:t,size:Le}),!m&&c.jsxs(W,{className:"w-[220px] flex flex-col items-center gap-2",children:[Y&&V&&c.jsxs(W,{className:"w-full p-3 bg-blue-50 dark:bg-blue-950/50 border border-blue-200 dark:border-blue-800 rounded-lg",children:[c.jsxs(W,{className:"flex items-center gap-2 mb-2",children:[c.jsx(de,{name:"upload",size:"sm",className:"text-blue-600 dark:text-blue-400 shrink-0"}),c.jsx(ee,{className:"text-sm font-medium text-blue-800 dark:text-blue-300",children:y||te("mypage.profile.upload_avatar_confirm")})]}),c.jsxs(W,{className:"text-xs text-blue-600 dark:text-blue-400 truncate mb-3",title:V.name,children:[V.name," (",(V.size/1024/1024).toFixed(2),"MB)"]}),c.jsxs(W,{className:"grid grid-cols-2 gap-2",children:[c.jsxs(Q,{type:"button",className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-md text-sm font-medium transition-colors disabled:opacity-50",onClick:Ce,disabled:A,children:[A?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"check",size:"sm"}),c.jsx(ee,{children:te("common.confirm")})]}),c.jsx(Q,{type:"button",className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-md text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors",onClick:Me,children:c.jsx(ee,{children:te("common.cancel")})})]})]}),F&&c.jsxs(W,{className:"w-full p-3 bg-red-50 dark:bg-red-950/50 border border-red-200 dark:border-red-800 rounded-lg",children:[c.jsxs(W,{className:"flex items-center gap-2 mb-2",children:[c.jsx(de,{name:"alert-triangle",size:"sm",className:"text-red-600 dark:text-red-400 shrink-0"}),c.jsx(ee,{className:"text-sm font-medium text-red-800 dark:text-red-300",children:x||te("mypage.profile.delete_avatar_confirm")})]}),c.jsxs(W,{className:"grid grid-cols-2 gap-2",children:[c.jsxs(Q,{type:"button",className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-red-600 hover:bg-red-700 text-white rounded-md text-sm font-medium transition-colors disabled:opacity-50",onClick:Ge,disabled:D,children:[D?c.jsx(de,{name:"spinner",size:"sm",className:"animate-spin"}):c.jsx(de,{name:"trash-2",size:"sm"}),c.jsx(ee,{children:te("common.delete")})]}),c.jsx(Q,{type:"button",className:"inline-flex items-center justify-center gap-1.5 px-3 py-2 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 rounded-md text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors",onClick:ye,children:c.jsx(ee,{children:te("common.cancel")})})]})]}),!K&&re()]}),b&&!K&&c.jsxs(W,{className:"flex items-center gap-2 text-sm text-red-600 dark:text-red-400",children:[c.jsx(de,{name:"alert-circle",size:"sm"}),c.jsx(ee,{children:b})]})]})}const C0=Object.freeze(Object.defineProperty({__proto__:null,AvatarUploader:Aa,default:Aa},Symbol.toStringTag,{value:"Module"})),oc=()=>window.G7Core,Zn=(e,t)=>window.G7Core?.t?.(e,t)??e,ac={horizontal:"flex items-center gap-1.5",vertical:"flex flex-col items-start"},S0=()=>[{key:"view_profile",label:Zn("userinfo.view_profile"),icon:"user",path:"/users/{{userId}}"},{key:"view_posts",label:Zn("userinfo.view_posts"),icon:"file-lines",path:"/users/{{userId}}/posts"}],Ma=({text:e,title:t})=>e?c.jsx(ee,{className:"text-sm text-gray-500 dark:text-gray-400",title:t,children:e}):null,sc=({author:e,name:t,userId:r,subText:n,subTextTitle:o,isGuest:a=!1,isWithdrawn:s=!1,showDropdown:l=!0,clickable:f=!0,profilePath:h="/users/{userId}",className:d="",layout:i="vertical",text:u,stopPropagation:g=!1,menuItems:p,hideMenuItems:m=[],appendMenuItems:w=[],id:x,editorAttrs:O})=>{const y=r??e?.uuid,E=a||e?.is_guest||!1,M=s||e?.status==="withdrawn",_=M?Zn("userinfo.withdrawn_user"):u??t??e?.name??"",[I,C]=k.useState(!1),[v,N]=k.useState({top:0,left:0}),A=k.useRef(null),P=k.useRef(null),D=k.useRef(null),L=h.replace("{userId}",String(y??"")),U=`${ac[i]} ${d}`;k.useEffect(()=>{if(!I)return;const j=q=>{const ue=q.target,te=A.current?.contains(ue),fe=P.current?.contains(ue);!te&&!fe&&C(!1)},H=()=>C(!1);return document.addEventListener("mousedown",j),window.addEventListener("scroll",H,!0),window.addEventListener("resize",H),()=>{document.removeEventListener("mousedown",j),window.removeEventListener("scroll",H,!0),window.removeEventListener("resize",H)}},[I]);const S=k.useCallback(()=>{if(p&&p.length>0)return p.filter(q=>q.show!==!1);let H=S0().filter(q=>!m.includes(q.key)&&q.show!==!1);return w&&w.length>0&&(H=[...H,...w.filter(q=>q.show!==!1)]),H},[p,m,w]),b=k.useCallback(()=>{if(D.current){const j=D.current.getBoundingClientRect();N({top:j.bottom+4,left:j.left})}},[]),$=k.useCallback((j,H)=>{if(H.stopPropagation(),H.preventDefault(),C(!1),j.onClick)j.onClick();else if(j.path){const q=j.path.replace(/\{\{userId\}\}/g,String(y??"")),ue=oc();ue?.navigate?ue.navigate(q):window.location.href=q}},[y]),F=k.useCallback(j=>{j.preventDefault(),g&&j.stopPropagation(),!(E||!y)&&(l?(I||b(),C(H=>!H)):f&&oc()?.navigate?.(L))},[g,E,y,l,I,b,f,L]);if(E||!y)return c.jsxs(W,{className:U,id:x,...O,children:[c.jsxs(W,{className:"flex items-center gap-1.5 text-gray-400 dark:text-gray-500",children:[c.jsx(ee,{children:_}),c.jsx(ee,{className:"text-xs px-1.5 py-0.5 bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 rounded",children:Zn("userinfo.guest_badge")})]}),c.jsx(Ma,{text:n,title:o})]});if(M)return c.jsxs(W,{className:U,id:x,...O,children:[c.jsx(ee,{className:"text-gray-400 dark:text-gray-500 line-through",children:_}),c.jsx(Ma,{text:n,title:o})]});const G=S(),B=/\btext-\S+/.test(d)?"":"text-gray-900 dark:text-white",V=l||f?`${B} hover:text-blue-600 dark:hover:text-blue-400 cursor-pointer font-medium`.trim():`${B} font-medium`.trim();return c.jsxs(W,{ref:A,className:`relative inline-block ${d}`,id:x,...O,children:[c.jsxs(W,{className:ac[i],children:[c.jsx(Q,{ref:D,onClick:F,className:V,children:_}),c.jsx(Ma,{text:n,title:o})]}),l&&I&&G.length>0&&Jt.createPortal(c.jsx(W,{ref:P,className:"fixed w-40 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg py-1 z-[9999]",style:{top:v.top,left:v.left},"data-testid":"author-dropdown-menu",children:G.map(j=>c.jsxs(Q,{onClick:H=>$(j,H),className:"flex items-center justify-start gap-2 w-full text-left px-3 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 cursor-pointer","data-testid":`menu-item-${j.key}`,children:[j.icon&&c.jsx(de,{name:j.icon,className:"w-4 h-4"}),c.jsx(ee,{children:j.label})]},j.key))}),document.body)]})},_0=Object.freeze(Object.defineProperty({__proto__:null,UserInfo:sc},Symbol.toStringTag,{value:"Module"})),lc=({tabs:e,activeTabId:t,onTabChange:r,variant:n="underline",className:o="",style:a,hiddenTabIds:s=[],mobileBreakpoint:l=768,id:f,editorAttrs:h})=>{const i=window.G7Core?.useResponsive,u=i?.(),g=u?u.width{!y.disabled&&y.id!==t&&r?.(y.id)},m=y=>{const E=y.target.value,M=Number(E),_=typeof E=="string"&&E!==""&&!Number.isNaN(M)?M:E,I=e.find(C=>String(C.id)===String(_));I&&p(I)},w=s.length>0?e.filter(y=>!s.includes(y.id)):e;if(g)return c.jsx(W,{className:`relative ${o}`,style:a,id:f,...h,children:c.jsx(Xa,{value:t!==void 0?String(t):"",onChange:m,options:w.map(y=>({value:String(y.id),label:y.badge!==void 0?`${y.label} (${y.badge})`:y.label,disabled:y.disabled})),className:"w-full"})});const x=y=>{const E=y.id===t,M="flex items-center gap-2 px-3 py-2 font-medium text-sm transition-all shrink-0 whitespace-nowrap";if(y.disabled)return`${M} opacity-50 cursor-not-allowed text-gray-400 dark:text-gray-600`;switch(n){case"pills":return E?`${M} bg-blue-600 dark:bg-blue-500 text-white rounded-lg`:`${M} text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg`;case"underline":return E?`${M} text-gray-900 dark:text-white border-b-2 border-gray-900 dark:border-white`:`${M} text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 border-b-2 border-transparent hover:border-gray-300 dark:hover:border-gray-600`;default:return E?`${M} text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 border-b-2 border-blue-600 dark:border-blue-400`:`${M} text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 border-b-2 border-transparent`}},O=n==="underline"?"flex gap-0 border-b border-gray-200 dark:border-gray-700":"flex gap-2";return c.jsx(W,{className:`relative ${o}`,style:a,id:f,...h,children:c.jsx($r,{className:O,children:w.map(y=>c.jsxs(Q,{type:"button",onClick:()=>p(y),disabled:y.disabled,className:x(y),children:[y.iconName&&c.jsx(de,{name:y.iconName,size:"sm"}),c.jsx(ee,{children:y.label}),y.badge!==void 0&&c.jsx(W,{className:"flex items-center justify-center min-w-5 h-5 px-1.5 bg-red-500 text-white text-xs font-bold rounded-full",children:c.jsx(ee,{children:y.badge})})]},y.id))})})},E0=Object.freeze(Object.defineProperty({__proto__:null,TabNavigation:lc},Symbol.toStringTag,{value:"Module"})),T0={Header:()=>Promise.resolve().then(()=>od),Footer:()=>Promise.resolve().then(()=>id),MobileNav:()=>Promise.resolve().then(()=>cd),SlotContainer:()=>Promise.resolve().then(()=>rd),NotificationCenter:()=>Promise.resolve().then(()=>nd),ProductCard:()=>Promise.resolve().then(()=>Ld),BrandMark:()=>Promise.resolve().then(()=>Fd),ImageGallery:()=>Promise.resolve().then(()=>Al),ProductImageViewer:()=>Promise.resolve().then(()=>jf),QuantitySelector:()=>Promise.resolve().then(()=>Bf),PostReactions:()=>Promise.resolve().then(()=>Vf),RichTextEditor:()=>Promise.resolve().then(()=>Yf),HtmlContent:()=>Promise.resolve().then(()=>Xf),HtmlEditor:()=>Promise.resolve().then(()=>qf),ExpandableContent:()=>Promise.resolve().then(()=>Zf),FileUploader:()=>Promise.resolve().then(()=>Xh),ConfirmDialog:()=>Promise.resolve().then(()=>Rf),SocialLoginButtons:()=>Promise.resolve().then(()=>Zh),Toast:()=>Promise.resolve().then(()=>t0),PageTransitionIndicator:()=>Promise.resolve().then(()=>n0),PageTransitionBlur:()=>Promise.resolve().then(()=>o0),PageSkeleton:()=>Promise.resolve().then(()=>b0),PageLoading:()=>Promise.resolve().then(()=>v0),ThemeToggle:()=>Promise.resolve().then(()=>Qc),Pagination:()=>Promise.resolve().then(()=>w0),SearchBar:()=>Promise.resolve().then(()=>x0),Avatar:()=>Promise.resolve().then(()=>ed),AvatarUploader:()=>Promise.resolve().then(()=>C0),UserInfo:()=>Promise.resolve().then(()=>_0),Modal:()=>Promise.resolve().then(()=>Jf),TabNavigation:()=>Promise.resolve().then(()=>E0)},N0=({id:e,className:t,style:r,children:n,editorAttrs:o})=>c.jsx(W,{id:e,className:t,style:r,...o,children:n}),A0=({id:e,children:t,cols:r=1,responsive:n,gap:o,rowGap:a,colGap:s,autoRows:l,autoCols:f,flow:h="row",className:d="",style:i,onClick:u,editorAttrs:g})=>{const p=["grid"];if(r&&p.push(`grid-cols-${r}`),n&&(n.sm&&p.push(`sm:grid-cols-${n.sm}`),n.md&&p.push(`md:grid-cols-${n.md}`),n.lg&&p.push(`lg:grid-cols-${n.lg}`),n.xl&&p.push(`xl:grid-cols-${n.xl}`),n["2xl"]&&p.push(`2xl:grid-cols-${n["2xl"]}`)),o!==void 0&&o>0&&p.push(`gap-${o}`),a!==void 0&&a>0&&p.push(`gap-y-${a}`),s!==void 0&&s>0&&p.push(`gap-x-${s}`),l){const w={auto:"auto-rows-auto",min:"auto-rows-min",max:"auto-rows-max",fr:"auto-rows-fr"};p.push(w[l])}if(f){const w={auto:"auto-cols-auto",min:"auto-cols-min",max:"auto-cols-max",fr:"auto-cols-fr"};p.push(w[f])}const m={row:"grid-flow-row",col:"grid-flow-col",dense:"grid-flow-dense","row-dense":"grid-flow-row-dense","col-dense":"grid-flow-col-dense"};return p.push(m[h]),d&&p.push(d),c.jsx(W,{id:e,className:p.join(" "),style:i,onClick:u,...g,children:t})},M0=({id:e,children:t,direction:r="row",justify:n="start",align:o="stretch",wrap:a="nowrap",gap:s=0,grow:l=!1,shrink:f=!0,className:h="",style:d,onClick:i,editorAttrs:u})=>{const g=["flex"],p={row:"flex-row","row-reverse":"flex-row-reverse",col:"flex-col","col-reverse":"flex-col-reverse"};g.push(p[r]);const m={wrap:"flex-wrap",nowrap:"flex-nowrap","wrap-reverse":"flex-wrap-reverse"};g.push(m[a]);const w={start:"justify-start",end:"justify-end",center:"justify-center",between:"justify-between",around:"justify-around",evenly:"justify-evenly"};g.push(w[n]);const x={start:"items-start",end:"items-end",center:"items-center",baseline:"items-baseline",stretch:"items-stretch"};return g.push(x[o]),s>0&&g.push(`gap-${s}`),l===!0?g.push("flex-grow"):typeof l=="number"&&l>0&&g.push(`flex-grow-${l}`),f===!1?g.push("shrink-0"):f===!0?g.push("flex-shrink"):typeof f=="number"&&f>0&&g.push(`flex-shrink-${f}`),h&&g.push(h),c.jsx(W,{id:e,className:g.join(" "),style:d,onClick:i,...u,children:t})},O0=({id:e,title:t,subtitle:r,children:n,padding:o="md",background:a="none",maxWidth:s,centered:l=!1,border:f=!1,shadow:h="none",rounded:d=!1,className:i="",style:u,onClick:g,editorAttrs:p})=>{const m=[],w={none:"p-0",sm:"p-2",md:"p-4",lg:"p-6",xl:"p-8"};m.push(w[o]);const x={none:"",white:"bg-white dark:bg-gray-700",gray:"bg-gray-50 dark:bg-gray-800",primary:"bg-blue-50 dark:bg-blue-900/20",secondary:"bg-gray-50 dark:bg-gray-800"};if(a!=="none"&&m.push(x[a]),s){const y={sm:"max-w-sm",md:"max-w-md",lg:"max-w-lg",xl:"max-w-xl","2xl":"max-w-2xl","4xl":"max-w-4xl","6xl":"max-w-6xl","7xl":"max-w-7xl",full:"max-w-full"};m.push(y[s])}l&&m.push("mx-auto"),f&&m.push("border","border-gray-200","dark:border-gray-700");const O={none:"",sm:"shadow-sm",md:"shadow-md",lg:"shadow-lg",xl:"shadow-xl"};return h!=="none"&&m.push(O[h]),d&&m.push("rounded-lg"),i&&m.push(i),c.jsxs(Za,{id:e,className:m.join(" "),style:u,onClick:g,...p,children:[(t||r)&&c.jsxs(W,{className:"mb-4",children:[t&&c.jsx(Va,{className:"text-2xl font-bold text-gray-900 dark:text-white",children:t}),r&&c.jsx(Dt,{className:"mt-1 text-sm text-gray-600 dark:text-gray-400",children:r})]}),n]})},I0=({id:e,leftWidth:t="250px",rightWidth:r="300px",leftSlot:n,centerSlot:o,rightSlot:a,className:s="",style:l,editorAttrs:f})=>{const h=`flex flex-row w-full h-full ${s}`.trim(),d={width:t,flexShrink:0},i={flex:1,minWidth:0},u={width:r,flexShrink:0};return c.jsxs(W,{id:e,className:h,style:l,...f,children:[c.jsx(W,{className:"flex flex-col",style:d,children:n}),c.jsx(W,{className:"flex flex-col",style:i,children:o}),c.jsx(W,{className:"flex flex-col",style:u,children:a})]})},D0={identifier:"sirsoft-basic",vendor:"sirsoft",name:{ko:"Basic",en:"Basic"},version:"1.0.4",license:"MIT",description:{ko:"그누보드7 기본 사용자 템플릿",en:"Gnuboard7 default user template"},type:"user",locales:["ko","en"],author:{name:"sirsoft",email:"contact@sirsoft.com",url:"https://sirsoft.com"},release_date:"2026-01-07",g7_version:">=7.0.0",dependencies:{modules:{"sirsoft-board":">=1.0.0","sirsoft-ecommerce":">=1.0.5","sirsoft-page":">=1.0.0"},plugins:{"sirsoft-daum_postcode":">=1.0.0"}},assets:{css:["dist/css/components.css"],js:["dist/js/components.iife.js"],fonts:[],images:[]},components:{basic:["a","button","checkbox","div","form","h1","h2","h3","h4","hr","icon","img","input","label","li","nav","p","section","select","span","svg","table","tbody","td","textarea","th","thead","tr","ul"],composite:["header","footer","mobile-nav","product-card","rich-text-editor","image-gallery","quantity-selector","post-reactions","social-login-buttons","file-uploader","card","modal","toast","pagination","stat-card","status-badge","tab-navigation","empty-state","loading-spinner","breadcrumb","search-bar","dropdown"],layout:["container","flex","grid","section"]},preview:{thumbnail:"preview/thumbnail.png",screenshots:["preview/screenshot1.png","preview/screenshot2.png"]},error_config:{layouts:{401:"errors/401",403:"errors/403",404:"errors/404",500:"errors/500",503:"errors/503",maintenance:"errors/maintenance"}},features:{dark_mode:!0,responsive:!0,multi_language:!0,multi_currency:!0},github_url:"https://github.com/gnuboard/g7-template-sirsoft-basic",github_changelog_url:"https://github.com/gnuboard/g7-template-sirsoft-basic/blob/main/CHANGELOG.md",externals:[{id:"fontawesome",type:"style",url:"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css",preconnect:"https://cdnjs.cloudflare.com"},{id:"pretendard",type:"webfont",url:"https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css",preconnect:"https://cdn.jsdelivr.net",crossorigin:"anonymous"}]},ic={KRW:{locale:"ko-KR",decimals:0},USD:{locale:"en-US",decimals:2},JPY:{locale:"ja-JP",decimals:0},CNY:{locale:"zh-CN",decimals:2},EUR:{locale:"de-DE",decimals:2}};function Lr(e,t="KRW"){if(!Number.isFinite(e))return"0";const r=ic[t]||ic.KRW;try{return new Intl.NumberFormat(r.locale,{style:"currency",currency:t,minimumFractionDigits:r.decimals,maximumFractionDigits:r.decimals}).format(e)}catch{return e.toLocaleString()+(t==="KRW"?"원":"")}}function Qn(e,t,r=0){if(!e)return;const n=e.KRW?.value??e.KRW?.price??0,o={};for(const[a,s]of Object.entries(e)){const l=s?.value??s?.price??0;let f=0;r>0&&(a==="KRW"?f=r:n>0&&(f=r*l/n));const h=(l+f)*t;o[a]={value:h,formatted:Lr(h,a)}}return o}function Jn(e){const t={};for(const n of e){const o=n?.multiCurrencyTotalPrice;if(o)for(const[a,s]of Object.entries(o)){const l=s?.value??s?.price??0;t[a]=(t[a]??0)+l}}const r={};for(const[n,o]of Object.entries(t))r[n]={value:o,formatted:Lr(o,n)};return r}function cc(e,t){if(!e||!t?.length)return 0;let r=0;for(const n of t){const o=e[n.id];if(o==null)continue;const a=n.values?.find(s=>s.id===Number(o));a&&(r+=a.price_adjustment??0)}return r}function Rn(e){return e.name_localized?e.name_localized:typeof e.name=="string"?e.name:e.name?.ko??""}function L0(e,t,r){if(t&&r in t)return t[r];if(Array.isArray(e)){const n=e.find(o=>typeof o.key=="string"?o.key===r:o.key?.ko===r||Object.values(o.key).includes(r));return n?typeof n.value=="string"?n.value:n.value?.ko??Object.values(n.value)[0]:void 0}return e[r]}function P0(e,t){if(t)return t;if(!Array.isArray(e))return e;const r={};for(const n of e){const o=typeof n.key=="string"?n.key:n.key?.ko??Object.values(n.key)[0]??"",a=typeof n.value=="string"?n.value:n.value?.ko??Object.values(n.value)[0]??"";o&&(r[o]=a)}return r}function F0(e,t,r){return r.find(n=>!n?.option_values||!n?.is_active?!1:e.every(o=>{const a=Rn(o),s=t?.[a];return L0(n.option_values,n.option_values_localized,a)===s}))}function $0(e,t){const r=e.params;if(!r)return;const{optionGroups:n,options:o,selectedOptionItems:a,preferredCurrency:s}=r;let l;if(r.newGroupName&&r.newValue?l={...r.currentSelection??{},[r.newGroupName]:r.newValue}:l=r.currentSelection??{},!n?.every(M=>{const _=Rn(M);return l?.[_]}))return;const h=F0(n,l,o??[]);if(!h){t.setState?.({currentSelection:{},__mergeMode:"shallow"});return}const d=n.map(M=>l[Rn(M)]).join("_"),i=a??[];if(i.find(M=>M.id===d)){const M=window.G7Core;M?.toast?.warning?.(M?.t?.("sirsoft-ecommerce.shop.already_added_option")??"이미 추가된 옵션입니다."),t.setState?.({currentSelection:{},__mergeMode:"shallow"});return}const g=h.selling_price??0,p={};n.forEach(M=>{const _=Rn(M);p[_]=l[_]});const m=r.additionalOptionGroups??[],w={};for(const M of m){if(!M.is_required)continue;const _=M.values?.find(I=>I.is_default);_&&(w[M.id]=_.id)}const x=cc(w,m),O=g+x,y={id:d,optionId:h.id,options:p,optionValues:P0(h.option_values,h.option_values_localized),quantity:1,stock:h.stock_quantity??999,unitPrice:g,unitPriceFormatted:Lr(g,s),totalPrice:O,totalPriceFormatted:Lr(O,s),multiCurrencyUnitPrice:h.multi_currency_selling_price,multiCurrencyTotalPrice:Qn(h.multi_currency_selling_price,1,x),additionalOptionSelections:w,additionalOptionsTotal:x},E=[...i,y];t.setState?.({selectedOptionItems:E,selectedTotalMultiCurrency:Jn(E),currentSelection:{},__mergeMode:"shallow"})}function U0(e,t){const r=e.params;if(!r)return;const{selectedOptionItems:n,preferredCurrency:o}=r,a=Number(r.itemIndex)||0,s=Number(r.newQuantity)||1,l=(n??[]).map((f,h)=>{if(h!==a)return f;const d=f?.unitPrice??0,i=f?.additionalOptionsTotal??0,u=(d+i)*s;return{...f,quantity:s,totalPrice:u,totalPriceFormatted:Lr(u,o),multiCurrencyTotalPrice:Qn(f?.multiCurrencyUnitPrice,s,i)}});t.setState?.({selectedOptionItems:l,selectedTotalMultiCurrency:Jn(l)})}function z0(e,t){const r=e.params;if(!r)return;const{selectedOptionItems:n,additionalOptionGroups:o,preferredCurrency:a}=r,s=Number(r.itemIndex)||0,l=Number(r.additionalOptionId),f=Object.prototype.hasOwnProperty.call(r,"customText"),h=r.valueId===""||r.valueId==null?null:Number(r.valueId),d=(n??[]).map((i,u)=>{if(u!==s)return i;const g={...i.additionalOptionSelections??{}},p={...i.additionalOptionCustomTexts??{}};if(f){const y=String(r.customText??"");y.trim()===""?delete p[l]:p[l]=y}else h==null?(delete g[l],delete p[l]):(g[l]=h,(o??[]).find(M=>M.id===l)?.values?.find(M=>M.id===h)?.allow_custom_text||delete p[l]);const m=cc(g,o),w=i?.unitPrice??0,x=i?.quantity??1,O=(w+m)*x;return{...i,additionalOptionSelections:g,additionalOptionCustomTexts:p,additionalOptionsTotal:m,totalPrice:O,totalPriceFormatted:Lr(O,a),multiCurrencyTotalPrice:Qn(i?.multiCurrencyUnitPrice,x,m)}});t.setState?.({selectedOptionItems:d,selectedTotalMultiCurrency:Jn(d)})}function H0(e,t){const r=e.params;if(!r)return;const n=Number(r.itemIndex)||0,o=(r.selectedOptionItems??[]).filter((a,s)=>s!==n);t.setState?.({selectedOptionItems:o,selectedTotalMultiCurrency:Jn(o)})}function G0(e,t){const r=e.params;if(!r)return;const n=Math.max(1,Number(r.newQuantity)||1);t.setState?.({noOptionQuantity:n,noOptionTotalMultiCurrency:Qn(r.multiCurrencyUnitPrice,n)})}const cn=window.G7Core?.createLogger?.("Handler:Cart")??{log:(...e)=>console.log("[Handler:Cart]",...e),warn:(...e)=>console.warn("[Handler:Cart]",...e),error:(...e)=>console.error("[Handler:Cart]",...e)};function hr(e){const t=window.G7Core;t?.state?.setLocal?(t.state.setLocal(e),cn.log("Local state updated:",e)):cn.warn("G7Core.state.setLocal not available")}function dc(){return window.G7Core?.state?.getLocal?.()||{}}function j0(){return window.G7Core?.state?.get?.()||{}}function B0(e,t="info"){const r=window.G7Core;r?.toast?.show?r.toast.show(e,t):cn.warn("G7Core.toast.show not available, message:",e)}function W0(e){const t=window.G7Core;return t?.t?t.t(e):e}function uc(){const e=window.G7Core;if(e?.dispatch){const r=dc().selectedItems||[];e.dispatch({handler:"refetchDataSource",params:{dataSourceId:"cartItems"}}),cn.log("Refetching cartItems with selected_ids:",r)}else cn.warn("G7Core.dispatch not available")}function K0(e,t){const{itemId:r,selectedItems:n}=e?.params||{},o=n||[];let a;o.includes(r)?a=o.filter(h=>h!==r):a=[...o,r];const l=j0().cartItems?.data?.items||[],f=l.length>0&&a.length===l.length;hr({selectedItems:a,allSelected:f,selectedCount:a.length}),uc()}function V0(e,t){const{allItemIds:r,isSelected:n}=e?.params||{};hr({selectedItems:n?r:[],allSelected:n,selectedCount:n?r.length:0}),uc()}function Y0(e,t){const{optionName:r,optionValue:n}=e?.params||{},a=dc().selectedOptions||{};hr({selectedOptions:{...a,[r]:n}})}function X0(e,t){const{targetIds:r}=e?.params||{};if(!r||r.length===0){B0(W0("shop.cart.select_items_to_delete"),"warning");return}hr({deleteModal:{visible:!0,targetIds:r}})}function q0(e,t){const{targetItem:r}=e?.params||{};hr({optionModal:{visible:!0,targetItem:r},selectedOptions:r?.options||{},selectedQuantity:r?.quantity})}function Z0(e,t){const{selectedItems:r}=e?.params||{};if(!r||r.length===0){hr({isCalculating:!1});return}hr({isCalculating:!0})}const pr=window.G7Core?.createLogger?.("Handler:CartOptionChange")??{log:(...e)=>console.log("[Handler:CartOptionChange]",...e),warn:(...e)=>console.warn("[Handler:CartOptionChange]",...e),error:(...e)=>console.error("[Handler:CartOptionChange]",...e)};function Oa(e){return e.name_localized?e.name_localized:typeof e.name=="string"?e.name:e.name?.ko??""}function Q0(e,t,r){if(t&&r in t)return t[r];if(Array.isArray(e)){const n=e.find(o=>typeof o.key=="string"?o.key===r:o.key?.ko===r||Object.values(o.key).includes(r));return n?typeof n.value=="string"?n.value:n.value?.ko??Object.values(n.value)[0]:void 0}return e[r]}function fc(e,t,r){return!e||!t?.length?null:t.every(a=>{const s=Oa(a);return e[s]})?r?.find(a=>t.every(s=>{const l=Oa(s);return Q0(a.option_values,a.option_values_localized,l)===e[l]}))||null:(pr.log("Not all options selected yet"),null)}function J0(e,t){const{selectedOptions:r,optionGroups:n,options:o}=e?.params||{};pr.log("findMatchingOption called:",{selectedOptions:r,optionGroups:n,optionsCount:o?.length});const a=fc(r,n,o);return pr.log("Matched option:",a),{matchedOption:a}}function R0(e,t){const{currentOptionValues:r,optionGroups:n,options:o}=e?.params||{};if(pr.log("initCartOptionSelection called:",{currentOptionValues:r,optionGroups:n,optionsCount:o?.length}),!n?.length||!r)return pr.log("No option groups or current values, returning empty"),{selectedOptions:{},matchedOption:null};const a={};for(const l of n){const f=Oa(l),h=r[f],d=l.values_localized??(Array.isArray(l.values)?l.values.map(i=>typeof i=="string"?i:i?.ko??""):[]);h&&d.includes(h)&&(a[f]=h)}pr.log("Initial selectedOptions:",a);const s=fc(a,n,o||[]);return pr.log("Matched option:",s),{selectedOptions:a,matchedOption:s}}const dn="g7_cart_key",ep="/api/modules/sirsoft-ecommerce/cart/key",Ia="g7_guest_order_token",gc="g7_guest_order_number",Da="g7_guest_order_expires_at",at=window.G7Core?.createLogger?.("Handler:Storage")??{log:(...e)=>console.log("[Handler:Storage]",...e),warn:(...e)=>console.warn("[Handler:Storage]",...e),error:(...e)=>console.error("[Handler:Storage]",...e)};async function hc(){try{const e=await fetch(ep,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"}});return e.ok?(await e.json()).data?.cart_key||null:(at.error("Failed to issue cartKey from API:",e.status),null)}catch(e){return at.error("Error issuing cartKey from API:",e),null}}function rr(e){const t=window.G7Core;t?.state?.set?(t.state.set(e),at.log("Global state updated:",e)):at.warn("G7Core.state.set not available")}function tp(){try{const e=window.G7Config;return e?.user?e.user:(window.G7Core?.state?.get?.()||{}).currentUser||null}catch{return null}}async function rp(e,t){let r=null;try{r=localStorage.getItem(dn)}catch{}if(r)at.log("Existing cartKey loaded:",r);else if(r=await hc(),r)try{localStorage.setItem(dn,r),at.log("New cartKey issued from API:",r)}catch{}else at.error("Failed to issue cartKey from API");rr({cartKey:r})}function np(e,t){try{return localStorage.getItem(dn)}catch{return null}}function pc(e,t){try{localStorage.removeItem(dn),at.log("cartKey removed from localStorage")}catch{}rr({cartKey:null})}async function op(e,t){if(tp()){pc();return}const n=await hc();if(n){try{localStorage.setItem(dn,n),at.log("New cartKey regenerated from API:",n)}catch{}rr({cartKey:n})}else at.error("Failed to regenerate cartKey from API")}function ap(e,t){const{key:r,value:n}=e?.params||{};if(!r){at.warn("saveToStorage: key is required");return}try{localStorage.setItem(r,n),at.log("Saved to storage:",r,n)}catch{}}function sp(e,t){const{key:r,defaultValue:n}=e?.params||{};if(!r)return at.warn("loadFromStorage: key is required"),n||null;try{return localStorage.getItem(r)||n||null}catch{return n||null}}function La(){try{sessionStorage.removeItem(Ia),sessionStorage.removeItem(gc),sessionStorage.removeItem(Da)}catch{}}function lp(e,t){let r=null,n=null;try{r=sessionStorage.getItem(Ia),n=sessionStorage.getItem(Da)}catch{}let o=!1;if(r){const a=n?new Date(n).getTime():NaN;(isNaN(a)||a<=Date.now())&&(La(),r=null,o=!0)}if(r){rr({guestOrderToken:r}),at.log("Guest order token loaded from sessionStorage");return}if(!o){const s=window.G7Core?.state?.get?.("_global")?.guestOrderToken;if(typeof s=="string"&&s!==""){at.log("Guest order token preserved from in-memory _global (sessionStorage empty)");return}}rr({guestOrderToken:null}),at.log("No guest order token (visitor not authenticated)")}function ip(e,t){const{token:r,orderNumber:n,expiresAt:o}=e?.params||{};if(!r||!n||!o){at.warn("saveGuestOrderToken: token, orderNumber, expiresAt are required");return}try{sessionStorage.setItem(Ia,r),sessionStorage.setItem(gc,n),sessionStorage.setItem(Da,o)}catch{}rr({guestOrderToken:r})}function cp(e,t){La(),rr({guestOrderToken:null})}function dp(e,t){La(),rr({guestOrderToken:null})}function up(e,t){const{product:r,priceField:n,currencyCode:o}=e,a=o||t.getState("_global.preferredCurrency")||"KRW",s=`multi_currency_${n}`,l=r[s];if(l&&l[a])return l[a].formatted;const f=`${n}_formatted`;return r[f]||String(r[n])}const Pa={KRW:{code:"KRW",symbol:"₩",locale:"ko-KR",decimals:0},USD:{code:"USD",symbol:"$",locale:"en-US",decimals:2},JPY:{code:"JPY",symbol:"¥",locale:"ja-JP",decimals:0},CNY:{code:"CNY",symbol:"¥",locale:"zh-CN",decimals:2},EUR:{code:"EUR",symbol:"€",locale:"de-DE",decimals:2}};function fp(e,t){const{value:r,currencyCode:n,locale:o}=e,a=n||t.getState("_global.preferredCurrency")||"KRW",s=Pa[a]||Pa.KRW,l=o||s.locale;try{return new Intl.NumberFormat(l,{style:"currency",currency:s.code,minimumFractionDigits:s.decimals,maximumFractionDigits:s.decimals}).format(r)}catch{const f=r.toLocaleString(void 0,{minimumFractionDigits:s.decimals,maximumFractionDigits:s.decimals});return`${s.symbol}${f}`}}function gp(e){return Pa[e]?.symbol||e}const Fa=window.G7Core?.createLogger?.("Handler:Currency")??{log:(...e)=>console.log("[Handler:Currency]",...e),warn:(...e)=>console.warn("[Handler:Currency]",...e),error:(...e)=>console.error("[Handler:Currency]",...e)},mc="g7_preferred_currency",hp="KRW";function pp(e,t){const{defaultCurrency:r=hp}=e;let n=r;try{if(typeof window<"u"&&window.localStorage){const o=localStorage.getItem(mc);o&&bc(o)&&(n=o)}}catch{Fa.warn("localStorage 접근 불가, 기본 통화 사용:",r)}return t.setState("global",{preferredCurrency:n}),n}function mp(e,t){const{currencyCode:r}=e;if(!bc(r)){Fa.warn("유효하지 않은 통화 코드:",r);return}try{typeof window<"u"&&window.localStorage&&localStorage.setItem(mc,r)}catch{Fa.warn("localStorage 저장 실패")}t.setState("global",{preferredCurrency:r})}function bc(e){return typeof e=="string"&&/^[A-Z]{3}$/.test(e)}const Pr=window.G7Core?.createLogger?.("Handler:SetTheme")??{log:(...e)=>console.log("[Handler:SetTheme]",...e),warn:(...e)=>console.warn("[Handler:SetTheme]",...e),error:(...e)=>console.error("[Handler:SetTheme]",...e)},$a=["auto","light","dark"],yc="g7_color_scheme",bp=e=>e==="auto"?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e,eo=e=>{const t=bp(e);document.documentElement.setAttribute("data-theme",t),t==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")};function yp(){try{const e=localStorage.getItem(yc),t=e&&$a.includes(e)?e:"auto";eo(t),Pr.log("Initial theme applied:",t)}catch(e){Pr.warn("Failed to load initial theme:",e),eo("auto")}}async function vp(e,t){const r=e?.target;if(r&&typeof r=="string"&&$a.includes(r)){eo(r);return}yp()}async function wp(e,t){let r;if(e?.target&&typeof e.target=="string"&&!e.target.includes("{{")&&(r=e.target),!r||typeof r!="string"){Pr.warn("Invalid theme:",r);return}if(!$a.includes(r)){Pr.warn("Unsupported theme:",r);return}const n=r;try{localStorage.setItem(yc,n)}catch(o){Pr.error("Failed to save theme to localStorage:",o);return}eo(n),Pr.log("Theme changed to:",n)}const xp=window.G7Core?.createLogger?.("Handler:RedirectToLoginWithReturn")??{log:(...e)=>console.log("[Handler:RedirectToLoginWithReturn]",...e),warn:(...e)=>console.warn("[Handler:RedirectToLoginWithReturn]",...e),error:(...e)=>console.error("[Handler:RedirectToLoginWithReturn]",...e)};async function kp(e,t){const r=window.G7Core;if(!r?.dispatch){xp.error("G7Core.dispatch 가 초기화되지 않아 로그인 리다이렉트를 실행할 수 없습니다.");return}const n=window.location.pathname+window.location.search;await r.dispatch({handler:"navigate",params:{path:"/login",query:{redirect:n}}})}const Ua=window.G7Core?.createLogger?.("Handler:DownloadAttachment")??{log:(...e)=>console.log("[Handler:DownloadAttachment]",...e),warn:(...e)=>console.warn("[Handler:DownloadAttachment]",...e),error:(...e)=>console.error("[Handler:DownloadAttachment]",...e)};async function Cp(e,t){const r=window.G7Core,{url:n,filename:o}=e?.params||{};if(!n){Ua.warn("다운로드 URL 이 없어 요청을 건너뜁니다.");return}if(!r?.api?.get){Ua.error("G7Core.api.get 이 초기화되지 않아 다운로드를 실행할 수 없습니다.");return}try{const a=await r.api.get(n,{responseType:"blob"});if(a){const s=URL.createObjectURL(a),l=document.createElement("a");l.href=s,l.download=o||"",document.body.appendChild(l),l.click(),document.body.removeChild(l),URL.revokeObjectURL(s)}}catch(a){Ua.error("첨부파일 다운로드 실패",a),r?.toast?.error?.(r?.t?.("common.download_failed")??"Download failed")}}const to={"sirsoft-basic.addSelectedItemIfComplete":$0,"sirsoft-basic.updateSelectedItemQuantity":U0,"sirsoft-basic.removeSelectedItem":H0,"sirsoft-basic.updateNoOptionQuantity":G0,"sirsoft-basic.setBlockAdditionalOption":z0,"sirsoft-basic.getDisplayPrice":up,"sirsoft-basic.formatCurrency":fp,"sirsoft-basic.getCurrencySymbol":gp,"sirsoft-basic.loadPreferredCurrency":pp,"sirsoft-basic.savePreferredCurrency":mp,setTheme:wp,initTheme:vp,redirectToLoginWithReturn:kp,downloadAttachment:Cp,toggleCartItemSelection:K0,selectAllCartItems:V0,setCartOption:Y0,openCartDeleteModal:X0,openCartOptionModal:q0,recalculateCart:Z0,findMatchingOption:J0,initCartOptionSelection:R0,initCartKey:rp,getCartKey:np,clearCartKey:pc,regenerateCartKey:op,saveToStorage:ap,loadFromStorage:sp,initGuestOrderToken:lp,saveGuestOrderToken:ip,clearGuestOrderToken:cp,clearGuestTokenOnEntry:dp},un=window.G7Core?.createLogger?.("Template:sirsoft-basic:IdentityLauncher")??{log:(...e)=>console.log("[Template:sirsoft-basic:IdentityLauncher]",...e),warn:(...e)=>console.warn("[Template:sirsoft-basic:IdentityLauncher]",...e),error:(...e)=>console.error("[Template:sirsoft-basic:IdentityLauncher]",...e)};function Sp(e){const t=window.G7Core,r=t?.state?.getLocal?.()??{},n=t?.state?.getGlobal?.()??t?.state?.get?.()??{},o=(...f)=>f.find(h=>typeof h=="string"&&h.length>0),a=o(e.target?.email,n?.currentUser?.email,n?.user?.email,n?.auth?.user?.email,e.purpose==="signup"?r?.registerForm?.email:void 0,e.purpose==="password_reset"?r?.passwordResetForm?.email:void 0,e.purpose==="password_reset"?r?.email:void 0),s=o(e.target?.phone,n?.currentUser?.phone,n?.user?.phone,n?.auth?.user?.phone);if(!a&&!s)return null;const l={};return a&&(l.email=a),s&&(l.phone=s),l}function _p(){const t=window.G7Core?.api?.getToken?.()??null;return t?{Authorization:`Bearer ${t}`}:{}}function Ep(){try{const e=typeof window<"u"?window.localStorage?.getItem("g7_locale"):null;return e?{"Accept-Language":e}:{}}catch{return{}}}async function Tp(e,t){const r={purpose:e.purpose};e.provider_id&&(r.provider_id=e.provider_id),t&&(r.target=t);const n=e.challenge_start_url||"/api/identity/challenges",o=await fetch(n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",Accept:"application/json",...Ep(),..._p()},body:JSON.stringify(r)}),a=await o.json().catch(()=>null);if(!o.ok||!a?.success){const l=a?.message??`Challenge 시작 실패 (HTTP ${o.status})`;throw new Error(l)}const s=a.data??a;return{id:s.id,expires_at:s.expires_at,render_hint:s.render_hint??e.render_hint??"text_code",public_payload:s.public_payload,redirect_url:s.redirect_url,max_attempts:typeof s.max_attempts=="number"?s.max_attempts:void 0}}async function Np(e){const t=window.G7Core,r=t?.identity;if(!t?.dispatch||!t?.state||!r)return un.error("G7Core 또는 G7Core.identity 가 초기화되지 않아 launcher 를 실행할 수 없습니다."),{status:"failed",failureCode:"G7_NOT_READY"};if(e.render_hint==="external_redirect"||e.redirect_url)return r.redirectExternally(e);const n=Sp(e);let o;try{o=await Tp(e,n)}catch(p){un.error("Challenge 시작 실패:",p);try{await t.dispatch({handler:"toast",params:{type:"error",message:p instanceof Error?p.message:"본인인증 시작에 실패했습니다."}})}catch{}return{status:"failed",failureCode:"CHALLENGE_START_FAILED",reason:p instanceof Error?p.message:String(p)}}if(o.redirect_url)return r.redirectExternally({...e,render_hint:"external_redirect",redirect_url:o.redirect_url});const a=o.expires_at?new Date(o.expires_at).getTime():0,s=a>0?Math.max(0,Math.floor((a-Date.now())/1e3)):0,l=typeof o.max_attempts=="number"?o.max_attempts:0;t.state.set({identityChallenge:{policy_key:e.policy_key,purpose:e.purpose,provider_id:e.provider_id??null,render_hint:o.render_hint,challenge_id:o.id,expires_at:o.expires_at,public_payload:o.public_payload??{},target:n??null,code:"",error:null,attempts:0,maxAttempts:l,remainingSeconds:s,resendCooldown:0}});let f=a,h=0;const d=window.setInterval(()=>{const p=f>0?Math.max(0,Math.floor((f-Date.now())/1e3)):0;h=Math.max(0,h-1),t.state.set({identityChallenge:{remainingSeconds:p,resendCooldown:h}})},1e3);let i=null;try{i=t.state.subscribe?.(p=>{const m=p?.identityChallenge?.expires_at;if(typeof m=="string"){const x=new Date(m).getTime();Number.isFinite(x)&&x!==f&&(f=x)}const w=p?.identityChallenge?.resendCooldown;typeof w=="number"&&w>h&&(h=w)})??null}catch{}const u=r.createDeferred();try{await t.dispatch({handler:"openModal",target:"identity-challenge-modal"})}catch(p){return un.error("openModal 실패 — 풀페이지로 폴백:",p),window.clearInterval(d),i?.(),r.redirectExternally({...e,render_hint:"external_redirect",redirect_url:`/identity/challenge?challenge_id=${encodeURIComponent(o.id)}&return=${encodeURIComponent(window.location.href)}`})}const g=await u;return window.clearInterval(d),i?.(),g}function Ap(){const e=window.G7Core?.identity;if(!e?.setLauncher){un.warn("G7Core.identity 가 아직 초기화되지 않아 launcher 등록을 건너뜁니다. 코어 부트스트랩 순서를 확인하세요.");return}e.setLauncher(Np),un.log("IDV launcher registered (sirsoft-basic)")}const vc=window.G7Core?.createLogger?.("Template:sirsoft-basic:device")??{log:(...e)=>console.log("[Template:sirsoft-basic:device]",...e),warn:(...e)=>console.warn("[Template:sirsoft-basic:device]",...e)};function Mp(){if(typeof navigator>"u")return!1;const e=navigator,t=(e.userAgent||"").toLowerCase(),r=((e.userAgentData?.platform??e.platform)||"").toLowerCase(),n=e.maxTouchPoints??0;return/iphone|ipad|ipod/.test(t)||/iphone|ipad|ipod|ios/.test(r)?!0:/macintosh|mac os x/.test(t)&&n>1}function Op(){const e=window.G7Core;if(!e?.state?.get||!e?.state?.set){vc.warn("G7Core.state not available; skip iOS device correction");return}if(!Mp())return;const r=(e.state.get()||{}).appConfig||{};r.isIos!==!0&&(e.state.set({appConfig:{...r,isIos:!0}}),vc.log("appConfig.isIos corrected to true by client signals (iPadOS desktop-UA)"))}function Ip(e){const t=e.icons;return Array.isArray(t)?t.filter(r=>!!r&&typeof r=="object"&&typeof r.value=="string"):[]}function Dp(e,t){const r=e.label;return typeof r=="string"?r.startsWith("$t:")?t(r.slice(3)):r:e.value}function Lp(e,t,r){if(r==="")return!0;const n=r.toLowerCase();return e.value.toLowerCase().includes(n)||t.toLowerCase().includes(n)?!0:(e.keywords??[]).some(o=>o.toLowerCase().includes(n))}function Pp({entry:e}){const t=e.preview;return t?.html?c.jsx("span",{className:"g7le-icon-preview",dangerouslySetInnerHTML:{__html:t.html},style:Ha}):t?.className?c.jsx("span",{className:`g7le-icon-preview ${t.className}`,style:Ha}):c.jsx("i",{className:`fas fa-${e.value}`,style:Ha,"aria-hidden":"true"})}function Fp({control:e,value:t,onChange:r,t:n}){const o=Ip(e),a=t==null?"":String(t),s=typeof e.iconColumns=="number"?e.iconColumns:6,l=e.iconSearchPlaceholder,f=typeof l=="string"&&l.startsWith("$t:")?n(l.slice(3)):n("layout_editor.icon_picker.search_placeholder"),[h,d]=k.useState("");if(o.length===0)return c.jsx("div",{className:"g7le-widget g7le-widget--icon-picker","data-testid":"g7le-widget-icon-picker",style:wc,children:c.jsx("input",{type:"text",className:"g7le-widget g7le-widget--icon-free","data-testid":"g7le-widget-icon-picker-free",value:a,placeholder:n("layout_editor.icon_picker.free_input_hint"),onChange:g=>r(g.target.value===""?void 0:g.target.value),style:xc})});const i=g=>Dp(g,n),u=o.filter(g=>Lp(g,i(g),h));return c.jsxs("div",{className:"g7le-widget g7le-widget--icon-picker","data-testid":"g7le-widget-icon-picker",style:wc,children:[c.jsx("input",{type:"text",className:"g7le-widget g7le-widget--icon-search","data-testid":"g7le-widget-icon-picker-search",value:h,placeholder:f,onChange:g=>d(g.target.value),style:xc}),c.jsxs("div",{className:"g7le-icon-grid","data-testid":"g7le-widget-icon-picker-grid",style:{...$p,gridTemplateColumns:`repeat(${s}, minmax(0, 1fr))`},children:[c.jsx("button",{type:"button","data-testid":"g7le-icon-cell-none",title:n("layout_editor.icon_picker.none"),onClick:()=>r(void 0),"aria-pressed":a==="",style:a===""?kc:za,children:c.jsx("span",{style:Up,children:"—"})}),u.map(g=>{const p=g.value===a;return c.jsx("button",{type:"button","data-testid":`g7le-icon-cell-${g.value}`,title:i(g),"aria-pressed":p,onClick:()=>r(g.value),style:p?kc:za,children:c.jsx(Pp,{entry:g})},g.value)})]}),u.length===0&&c.jsx("div",{"data-testid":"g7le-widget-icon-picker-empty",style:zp,children:n("layout_editor.icon_picker.no_results")})]})}const wc={display:"flex",flexDirection:"column",gap:6,width:"100%"},xc={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,width:"100%"},$p={display:"grid",gap:4,maxHeight:220,overflowY:"auto",padding:2},za={display:"flex",alignItems:"center",justifyContent:"center",minHeight:34,padding:4,border:"1px solid #e2e8f0",borderRadius:6,background:"#fff",cursor:"pointer"},kc={...za,border:"2px solid #2563eb",background:"#eff6ff"},Ha={display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:16,lineHeight:1},Up={fontSize:10,color:"#475569",fontFamily:"monospace",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:"100%"},zp={fontSize:11,color:"#94a3b8",fontStyle:"italic",padding:"4px 2px"},Cc=window.G7Core?.createLogger?.("Template:sirsoft-basic:EditorWidgets")??{log:(...e)=>console.log("[Template:sirsoft-basic:EditorWidgets]",...e),warn:(...e)=>console.warn("[Template:sirsoft-basic:EditorWidgets]",...e)};function Hp(){if(typeof window>"u")return;const e=window.G7Core?.layoutEditor;if(!e?.registerWidget){Cc.warn("G7Core.layoutEditor 미노출 — icon-picker 위젯 등록 보류");return}e.registerWidget("icon-picker",Fp),Cc.log("편집기 위젯 'icon-picker' 등록됨(Font Awesome 검색 그리드)")}const Ga=window.G7Core?.createLogger?.("Template:sirsoft-basic")??{log:(...e)=>console.log("[Template:sirsoft-basic]",...e),warn:(...e)=>console.warn("[Template:sirsoft-basic]",...e),error:(...e)=>console.error("[Template:sirsoft-basic]",...e)};typeof window<"u"&&(window.G7TemplateHandlers=to);function Sc(){if(typeof window<"u"){let e=0;const t=50,r=()=>{const n=window.G7Core?.getActionDispatcher?.();n?(Object.entries(to).forEach(([o,a])=>{n.registerHandler(o,a)}),Ga.log(`${Object.keys(to).length} custom handler(s) registered:`,Object.keys(to)),Ap(),Op()):(e++,e<=t?(Ga.warn(`ActionDispatcher not found, retrying... (${e}/${t})`),setTimeout(r,100)):Ga.error("Failed to register handlers: ActionDispatcher not available after maximum retries"))};document.readyState==="complete"?r():window.addEventListener("load",r)}}return Hp(),Sc(),J.A=ao,J.Avatar=Ur,J.AvatarUploader=Aa,J.BrandMark=xo,J.Button=Q,J.Checkbox=qa,J.Code=Xc,J.ConfirmDialog=ta,J.Container=N0,J.Div=W,J.ExpandableContent=Jo,J.FileInput=Ba,J.FileUploader=Xn,J.Flex=M0,J.Footer=rs,J.Form=so,J.Grid=A0,J.H1=Fc,J.H2=Va,J.H3=gn,J.H4=Ya,J.Header=es,J.Hr=lo,J.HtmlContent=qo,J.HtmlEditor=Ll,J.Icon=de,J.IconName=Je,J.ImageGallery=Tr,J.Img=Lt,J.Input=xt,J.Label=yr,J.Li=Xt,J.MobileNav=ns,J.Modal=Ro,J.Nav=$r,J.NotificationCenter=mn,J.Ol=$c,J.Optgroup=Gc,J.Option=Hc,J.P=Dt,J.PageLoading=ec,J.PageSkeleton=Na,J.PageTransitionBlur=_a,J.PageTransitionIndicator=Sa,J.Pagination=tc,J.PasswordInput=Ka,J.PostReactions=Il,J.ProductCard=ms,J.ProductImageViewer=An,J.QuantitySelector=Ml,J.RichTextEditor=Dl,J.SearchBar=nc,J.Section=Za,J.SectionLayout=O0,J.Select=Xa,J.SlotContainer=pn,J.SocialLoginButtons=Ki,J.Span=ee,J.Svg=fn,J.TabNavigation=lc,J.Table=jc,J.Tbody=Wc,J.Td=Yc,J.Textarea=no,J.Th=Vc,J.Thead=Bc,J.ThemeToggle=hn,J.ThreeColumnLayout=I0,J.Toast=Ca,J.Tr=Kc,J.Ul=oo,J.UserInfo=sc,J.availablePasswordRules=ro,J.compositeComponents=T0,J.defaultPasswordRules=Wa,J.initTemplate=Sc,J.templateMetadata=D0,Object.defineProperty(J,Symbol.toStringTag,{value:"Module"}),J})({},ReactJSXRuntime,React,ReactDOM); +//# sourceMappingURL=components.iife.js.map diff --git a/templates/_bundled/sirsoft-basic/dist/src/components/composite/ProductCard.d.ts b/templates/_bundled/sirsoft-basic/dist/src/components/composite/ProductCard.d.ts index 6c744fde..af2230f4 100644 --- a/templates/_bundled/sirsoft-basic/dist/src/components/composite/ProductCard.d.ts +++ b/templates/_bundled/sirsoft-basic/dist/src/components/composite/ProductCard.d.ts @@ -47,6 +47,17 @@ interface ProductCardProps { onClick?: (productId: number) => void; /** 쇼핑몰 base 경로 (예: '/shop', '/store', '/') */ shopBase?: string; + /** + * 목록 컨텍스트 왕복 보존 여부 (#75). + * + * 상품 목록 그리드처럼 이 카드가 페이지네이션 목록의 일부인 자리에서만 true 로 켠다. + * 켜면 상세로 이동할 때 현재 URL 의 page/sort/keyword/category 를 상세 URL 로 승계해, + * 상세의 '뒤로가기' 가 보던 목록 위치로 정확히 되돌아간다. + * + * 찜 목록·검색 결과처럼 다른 목록에서 상품 상세로 나가는 이동은 기본값(false)을 유지한다 — + * 그 목록의 페이지 상태를 상품 목록으로 옮기면 엉뚱한 위치로 복귀한다. + */ + preserveListQuery?: boolean; /** 추가 CSS 클래스 */ className?: string; /** diff --git a/templates/_bundled/sirsoft-basic/layouts/mypage/orders/show.json b/templates/_bundled/sirsoft-basic/layouts/mypage/orders/show.json index 32b28a4b..d848c58c 100644 --- a/templates/_bundled/sirsoft-basic/layouts/mypage/orders/show.json +++ b/templates/_bundled/sirsoft-basic/layouts/mypage/orders/show.json @@ -115,7 +115,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/mypage/orders" + "path": "/mypage/orders", + "mergeQuery": true, + "query": {} } } ], @@ -196,6 +198,7 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 쇼핑 계속하기 — 주문 목록이 아니라 상품 목록으로 나가는 이동이다.", "type": "click", "handler": "navigate", "params": { @@ -229,6 +232,7 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 재주문 — 주문서 작성 흐름으로 넘어가는 이동이므로 주문 목록 상태를 물려주지 않는다.", "type": "click", "handler": "navigate", "params": { diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/form/_password_verify_modal.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/form/_password_verify_modal.json index de231cfe..67fe18ed 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/form/_password_verify_modal.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/form/_password_verify_modal.json @@ -21,7 +21,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/board/{{route.slug}}/{{route.id}}" + "path": "/board/{{route.slug}}/{{route.id}}", + "mergeQuery": true, + "query": {} } } ], @@ -124,7 +126,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/board/{{route.slug}}/{{route.id}}" + "path": "/board/{{route.slug}}/{{route.id}}", + "mergeQuery": true, + "query": {} } } ], diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/form/_post_form.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/form/_post_form.json index 9500fbe1..43f0340b 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/form/_post_form.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/form/_post_form.json @@ -740,7 +740,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "{{route.id ? '/board/' + route.slug + '/' + route.id : '/board/' + route.slug}}" + "path": "{{route.id ? '/board/' + route.slug + '/' + route.id : '/board/' + route.slug}}", + "mergeQuery": true, + "query": {} } } ], @@ -801,7 +803,9 @@ { "handler": "navigate", "params": { - "path": "/board/{{route?.slug}}/{{result?.data?.id}}" + "path": "/board/{{route?.slug}}/{{result?.data?.id}}", + "mergeQuery": true, + "query": {} } } ], diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/index/_empty_states.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/index/_empty_states.json index b5db84f6..77841cf8 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/index/_empty_states.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/index/_empty_states.json @@ -40,10 +40,15 @@ "text": "$t:board.go_to_first_page", "actions": [ { + "comment": "페이지만 되돌린다 — 검색어/분류/필터는 그대로 유지 (#75). page: \"\" 는 파라미터 제거 = 1페이지.", "type": "click", "handler": "navigate", "params": { - "path": "/board/{{route.slug}}" + "path": "/board/{{route.slug}}", + "mergeQuery": true, + "query": { + "page": "" + } } } ] @@ -112,10 +117,12 @@ "text": "$t:board.clear_search", "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 검색 초기화 — 목록 상태를 전부 비우는 것이 이 버튼의 목적이므로 병합하지 않는다.", "type": "click", "handler": "navigate", "params": { - "path": "/board/{{route.slug}}" + "path": "/board/{{route.slug}}", + "mergeQuery": false } } ] diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/index/_write_button.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/index/_write_button.json index 920ec44c..9748df10 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/index/_write_button.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/index/_write_button.json @@ -21,7 +21,9 @@ "allowed": { "handler": "navigate", "params": { - "path": "/board/{{route.slug}}/write" + "path": "/board/{{route.slug}}/write", + "mergeQuery": true, + "query": {} } }, "no_permission": { diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/show/_navigation.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/show/_navigation.json index 78a8b15b..a8aefd7a 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/show/_navigation.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/show/_navigation.json @@ -74,7 +74,7 @@ }, "children": [ { - "comment": "이전글 버튼 - 아이콘 + 텍스트", + "comment": "이전글 버튼 - 아이콘 + 텍스트. 목록 상태(page/search/category/del/filters)를 형제 상세로 그대로 승계한다 (#75).", "type": "basic", "name": "Button", "if": "{{navigation?.data?.prev?.id}}", @@ -87,9 +87,8 @@ "handler": "navigate", "params": { "path": "/board/{{route.slug}}/{{navigation.data.prev.id}}", - "query": { - "del": "{{query.del ?? ''}}" - } + "mergeQuery": true, + "query": {} } } ], @@ -110,7 +109,7 @@ ] }, { - "comment": "다음글 버튼 - 아이콘 + 텍스트", + "comment": "다음글 버튼 - 아이콘 + 텍스트. 목록 상태(page/search/category/del/filters)를 형제 상세로 그대로 승계한다 (#75).", "type": "basic", "name": "Button", "if": "{{navigation?.data?.next?.id}}", @@ -123,9 +122,8 @@ "handler": "navigate", "params": { "path": "/board/{{route.slug}}/{{navigation.data.next.id}}", - "query": { - "del": "{{query.del ?? ''}}" - } + "mergeQuery": true, + "query": {} } } ], diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/show/modals/_modal_delete.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/show/modals/_modal_delete.json index 87536fbe..46f87364 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/show/modals/_modal_delete.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/show/modals/_modal_delete.json @@ -223,10 +223,13 @@ } }, { + "comment": "삭제 후 목록 복귀 — 보고 있던 목록 상태(page/search/category/del)를 그대로 되돌린다 (#75). del(삭제글 포함 보기)은 사용자가 직접 켠 보기 모드이므로 삭제를 이유로 해제하지 않는다.", "if": "{{_global.deleteModal.type !== 'comment'}}", "handler": "navigate", "params": { - "path": "/board/{{route.slug}}" + "path": "/board/{{route.slug}}", + "mergeQuery": true, + "query": {} } }, { diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/show/modals/_password_verify_modal.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/show/modals/_password_verify_modal.json index 0a24e7b9..3f3366cb 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/show/modals/_password_verify_modal.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/show/modals/_password_verify_modal.json @@ -212,7 +212,7 @@ } }, { - "comment": "페이지 이동 (redirectPath가 있는 경우)", + "comment": "페이지 이동 (redirectPath가 있는 경우). audit:allow layout-list-context-navigate-merge-query — redirectPath 는 모달을 연 쪽이 지정하는 임의 경로라 목적지를 정적으로 알 수 없다 (현재 저장소의 유일한 설정처인 _comment_item.json 은 null 을 넣어 이 분기를 쓰지 않는다).", "if": "{{_global.guestPasswordModal.redirectPath}}", "handler": "navigate", "params": { diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/form.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/form.json index c3c3357f..0da78fc9 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/form.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/form.json @@ -34,7 +34,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "{{route.id ? '/board/' + route.slug + '/' + route.id : '/board/' + route.slug}}" + "path": "{{route.id ? '/board/' + route.slug + '/' + route.id : '/board/' + route.slug}}", + "mergeQuery": true, + "query": {} } } ], diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/show.json b/templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/show.json index f64cbba0..afa2e6e7 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/show.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/board/types/basic/show.json @@ -949,7 +949,11 @@ "type": "click", "handler": "navigate", "params": { - "path": "/board/{{route.slug}}/write?parent_id={{route.id}}" + "path": "/board/{{route.slug}}/write", + "mergeQuery": true, + "query": { + "parent_id": "{{route.id}}" + } } } ], @@ -1066,7 +1070,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "/board/{{route.slug}}/{{route.id}}/edit" + "path": "/board/{{route.slug}}/{{route.id}}/edit", + "mergeQuery": true, + "query": {} } } ], diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/_tab_navigation.json b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/_tab_navigation.json index 3305ae02..ef4962cc 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/_tab_navigation.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/_tab_navigation.json @@ -56,6 +56,7 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 마이페이지 탭 전환 — 탭마다 다루는 목록이 달라 이전 탭의 페이지·필터를 물려받으면 잘못된 화면이 된다.", "event": "onTabChange", "type": "change", "handler": "navigate", diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/inquiries/_list.json b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/inquiries/_list.json index 0daa8194..3824d06f 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/inquiries/_list.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/inquiries/_list.json @@ -152,7 +152,12 @@ "className": "shrink-0 w-16 h-16 rounded-lg overflow-hidden bg-gray-100 dark:bg-gray-700" }, "actions": [ - { "type": "click", "handler": "navigate", "params": { "path": "{{item.product?.url ?? '/'}}" } } + { + "comment": "audit:allow layout-list-context-navigate-merge-query 문의 대상 상품으로 이동 — 문의 목록과 다른 클러스터(상품 상세)로 나가는 이동이다.", + "type": "click", + "handler": "navigate", + "params": { "path": "{{item.product?.url ?? '/'}}" } + } ], "children": [ { @@ -195,7 +200,12 @@ }, "text": "{{item.product_name ?? ''}}", "actions": [ - { "type": "click", "handler": "navigate", "params": { "path": "{{item.product?.url ?? '/'}}" } } + { + "comment": "audit:allow layout-list-context-navigate-merge-query 문의 대상 상품으로 이동 — 문의 목록과 다른 클러스터(상품 상세)로 나가는 이동이다.", + "type": "click", + "handler": "navigate", + "params": { "path": "{{item.product?.url ?? '/'}}" } + } ] }, { diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/mileage/_list.json b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/mileage/_list.json index 35a7e932..97b5814d 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/mileage/_list.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/mileage/_list.json @@ -207,7 +207,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "mileageCategory": "", "mileagePage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/mileage", "replace": true, "query": { "category": "", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/mileage", "mergeQuery": true, "query": { "category": "", "page": "1" }, "replace": true } } ] } ], @@ -231,7 +231,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "mileageCategory": "earn", "mileagePage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/mileage", "replace": true, "query": { "category": "earn", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/mileage", "mergeQuery": true, "query": { "category": "earn", "page": "1" }, "replace": true } } ] } ], @@ -255,7 +255,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "mileageCategory": "use", "mileagePage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/mileage", "replace": true, "query": { "category": "use", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/mileage", "mergeQuery": true, "query": { "category": "use", "page": "1" }, "replace": true } } ] } ], @@ -279,7 +279,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "mileageCategory": "expire", "mileagePage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/mileage", "replace": true, "query": { "category": "expire", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/mileage", "mergeQuery": true, "query": { "category": "expire", "page": "1" }, "replace": true } } ] } ], @@ -303,7 +303,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "mileageCategory": "adjust", "mileagePage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/mileage", "replace": true, "query": { "category": "adjust", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/mileage", "mergeQuery": true, "query": { "category": "adjust", "page": "1" }, "replace": true } } ] } ], @@ -577,7 +577,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "mileagePage": "{{$args[0]}}" } }, - { "handler": "navigate", "params": { "path": "/mypage/mileage", "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" } } } + { "handler": "navigate", "params": { "path": "/mypage/mileage", "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, "replace": true } } ] } ] diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/notifications/_list.json b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/notifications/_list.json index 260da8b2..42e2cda9 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/notifications/_list.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/notifications/_list.json @@ -193,6 +193,7 @@ ] }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 알림 대상으로 이동 — 목적지는 알림이 지정한 임의 화면이므로 알림 목록 클러스터 밖이다.", "handler": "navigate", "if": "{{notification.url}}", "params": { "path": "{{notification.url}}" } diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/orders/_items.json b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/orders/_items.json index 8168b00d..d1f32073 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/orders/_items.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/orders/_items.json @@ -182,6 +182,7 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 주문 항목 → 상품 상세 이동 — 주문 목록과 다른 클러스터(상품)로 나가는 이동이다.", "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products/{{item.product_snapshot?.product_code ?? item.product_id}}" } @@ -221,6 +222,7 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 주문 항목 → 상품 상세 이동 — 주문 목록과 다른 클러스터(상품)로 나가는 이동이다.", "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products/{{item.product_snapshot?.product_code ?? item.product_id}}" } diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/orders/_list.json b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/orders/_list.json index d3ecf52c..60cfbb02 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/orders/_list.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/orders/_list.json @@ -49,7 +49,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "ordersStatus": "pending_payment", "ordersPage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/orders", "replace": true, "query": { "status": "pending_payment", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/orders", "mergeQuery": true, "query": { "status": "pending_payment", "page": "1" }, "replace": true } } ] } ], @@ -135,7 +135,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "ordersStatus": "payment_complete", "ordersPage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/orders", "replace": true, "query": { "status": "payment_complete", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/orders", "mergeQuery": true, "query": { "status": "payment_complete", "page": "1" }, "replace": true } } ] } ], @@ -221,7 +221,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "ordersStatus": "preparing", "ordersPage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/orders", "replace": true, "query": { "status": "preparing", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/orders", "mergeQuery": true, "query": { "status": "preparing", "page": "1" }, "replace": true } } ] } ], @@ -307,7 +307,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "ordersStatus": "shipping", "ordersPage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/orders", "replace": true, "query": { "status": "shipping", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/orders", "mergeQuery": true, "query": { "status": "shipping", "page": "1" }, "replace": true } } ] } ], @@ -393,7 +393,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "ordersStatus": "delivered", "ordersPage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/orders", "replace": true, "query": { "status": "delivered", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/orders", "mergeQuery": true, "query": { "status": "delivered", "page": "1" }, "replace": true } } ] } ], @@ -479,7 +479,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "ordersStatus": "confirmed", "ordersPage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/orders", "replace": true, "query": { "status": "confirmed", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/orders", "mergeQuery": true, "query": { "status": "confirmed", "page": "1" }, "replace": true } } ] } ], @@ -586,7 +586,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "ordersStatus": "{{$event.target.value}}", "ordersPage": 1 } }, - { "handler": "navigate", "params": { "path": "/mypage/orders", "replace": true, "query": { "status": "{{$event.target.value}}", "page": "1" } } } + { "handler": "navigate", "params": { "path": "/mypage/orders", "mergeQuery": true, "query": { "status": "{{$event.target.value}}", "page": "1" }, "replace": true } } ] } ] @@ -957,7 +957,7 @@ { "type": "click", "handler": "navigate", - "params": { "path": "/mypage/orders/{{order.order_number}}" } + "params": { "path": "/mypage/orders/{{order.order_number}}", "mergeQuery": true, "query": {} } } ], "children": [ @@ -1021,6 +1021,7 @@ }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 쇼핑하러 가기 — 주문 내역이 비었을 때 상품 목록으로 내보내는 이동이다.", "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products" } @@ -1055,7 +1056,7 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "local", "ordersPage": "{{$args[0]}}" } }, - { "handler": "navigate", "params": { "path": "/mypage/orders", "replace": true, "mergeQuery": true, "query": { "page": "{{$args[0]}}" } } } + { "handler": "navigate", "params": { "path": "/mypage/orders", "mergeQuery": true, "query": { "page": "{{$args[0]}}" }, "replace": true } } ] } ] diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/wishlist/_list.json b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/wishlist/_list.json index ec121a39..3cd89697 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/mypage/wishlist/_list.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/mypage/wishlist/_list.json @@ -132,6 +132,7 @@ "props": { "className": "inline-block mt-4 px-4 py-2 bg-gray-900 dark:bg-white text-white dark:text-gray-900 rounded-lg cursor-pointer" }, "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 쇼핑하러 가기 — 찜 목록이 비었을 때 상품 목록으로 내보내는 이동이다.", "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products" } diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/search/_search_input.json b/templates/_bundled/sirsoft-basic/layouts/partials/search/_search_input.json index 831fd956..0aa6ae41 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/search/_search_input.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/search/_search_input.json @@ -31,6 +31,7 @@ "params": { "target": "local", "q": "{{$event.target.value}}" } }, { + "comment": "audit:allow layout-list-context-navigate-merge-query 새 검색 실행 — 검색어를 바꾸면 결과 집합 자체가 달라지므로 이전 페이지·필터를 물려받지 않는다.", "type": "keydown", "key": "Enter", "handler": "navigate", @@ -51,7 +52,11 @@ "handler": "sequence", "actions": [ { "handler": "setState", "params": { "target": "global", "searchPage": 1 } }, - { "handler": "navigate", "params": { "path": "/search", "query": { "q": "{{_local.q ?? ''}}" } } } + { + "comment": "audit:allow layout-list-context-navigate-merge-query 새 검색 실행 — 검색어를 바꾸면 결과 집합 자체가 달라지므로 이전 페이지·필터를 물려받지 않는다.", + "handler": "navigate", + "params": { "path": "/search", "query": { "q": "{{_local.q ?? ''}}" } } + } ] } ] diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/search/pages/_section.json b/templates/_bundled/sirsoft-basic/layouts/partials/search/pages/_section.json index 44003e50..d75b88fc 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/search/pages/_section.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/search/pages/_section.json @@ -62,7 +62,14 @@ "type": "basic", "name": "Button", "props": { "className": "block w-full text-left p-4 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors cursor-pointer" }, - "actions": [{ "type": "click", "handler": "navigate", "params": { "path": "{{page.url}}" } }], + "actions": [ + { + "comment": "audit:allow layout-list-context-navigate-merge-query 검색 결과 → 원문(페이지) 이동 — 검색 목록과 다른 클러스터로 나가는 이동이다.", + "type": "click", + "handler": "navigate", + "params": { "path": "{{page.url}}" } + } + ], "children": [ { "type": "composite", diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/search/posts/_list.json b/templates/_bundled/sirsoft-basic/layouts/partials/search/posts/_list.json index 21827561..3ffe910f 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/search/posts/_list.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/search/posts/_list.json @@ -22,7 +22,14 @@ "type": "basic", "name": "Button", "props": { "className": "block w-full text-left p-4 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors cursor-pointer" }, - "actions": [{ "type": "click", "handler": "navigate", "params": { "path": "{{post?.url}}" } }], + "actions": [ + { + "comment": "audit:allow layout-list-context-navigate-merge-query 검색 결과 → 원문(게시글) 이동 — 검색 목록과 다른 클러스터로 나가는 이동이다.", + "type": "click", + "handler": "navigate", + "params": { "path": "{{post?.url}}" } + } + ], "children": [ { "comment": "제목 라인 (게시판명 + 제목)", diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/search/posts/_section.json b/templates/_bundled/sirsoft-basic/layouts/partials/search/posts/_section.json index 1920492f..3014c5e2 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/search/posts/_section.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/search/posts/_section.json @@ -61,7 +61,14 @@ "type": "basic", "name": "Button", "props": { "className": "block w-full text-left p-4 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors cursor-pointer" }, - "actions": [{ "type": "click", "handler": "navigate", "params": { "path": "{{post?.url}}" } }], + "actions": [ + { + "comment": "audit:allow layout-list-context-navigate-merge-query 검색 결과 → 원문(게시글) 이동 — 검색 목록과 다른 클러스터로 나가는 이동이다.", + "type": "click", + "handler": "navigate", + "params": { "path": "{{post?.url}}" } + } + ], "children": [ { "comment": "제목 라인 (게시판명 + 제목)", diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/shop/_product_purchase_card.json b/templates/_bundled/sirsoft-basic/layouts/partials/shop/_product_purchase_card.json index d65555c3..34e66561 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/shop/_product_purchase_card.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/shop/_product_purchase_card.json @@ -290,9 +290,10 @@ "text": "$t:shop.buy_now", "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 주문서로 나가는 이동이다 — 상품 목록의 페이지·정렬을 물려주지 않는다.", "type": "click", "handler": "navigate", - "params": { "url": "{{_global.shopBase}}/checkout?items={{encodeURIComponent(JSON.stringify(_local.selectedItems))}}" } + "params": { "path": "{{_global.shopBase}}/checkout?items={{encodeURIComponent(JSON.stringify(_local.selectedItems))}}" } } ] }, diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/shop/detail/_modal_cart_added.json b/templates/_bundled/sirsoft-basic/layouts/partials/shop/detail/_modal_cart_added.json index a3e1b067..251270c4 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/shop/detail/_modal_cart_added.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/shop/detail/_modal_cart_added.json @@ -88,7 +88,11 @@ "actions": [ { "handler": "setState", "params": { "target": "global", "isNavigatingToCart": true } }, { "handler": "closeModal" }, - { "handler": "navigate", "params": { "path": "{{_global.shopBase}}/cart" } } + { + "comment": "audit:allow layout-list-context-navigate-merge-query 장바구니로 이동 — 상품 목록/상세와 다른 클러스터로 나가는 이동이다.", + "handler": "navigate", + "params": { "path": "{{_global.shopBase}}/cart" } + } ] } ] diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/shop/detail/_purchase_card.json b/templates/_bundled/sirsoft-basic/layouts/partials/shop/detail/_purchase_card.json index be8dbc39..b62db551 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/shop/detail/_purchase_card.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/shop/detail/_purchase_card.json @@ -516,7 +516,11 @@ "conditions": [ { "if": "{{_global.currentUser?.uuid}}", - "then": { "handler": "navigate", "params": { "path": "{{_global.shopBase}}/checkout" } } + "then": { + "comment": "audit:allow layout-list-context-navigate-merge-query 주문서로 이동 — 상품 목록/상세와 다른 클러스터(주문 흐름)로 나가는 이동이다.", + "handler": "navigate", + "params": { "path": "{{_global.shopBase}}/checkout" } + } }, { "then": { diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/shop/list/_product_grid.json b/templates/_bundled/sirsoft-basic/layouts/partials/shop/list/_product_grid.json index 1ca2dbc6..35027b1a 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/shop/list/_product_grid.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/shop/list/_product_grid.json @@ -27,7 +27,8 @@ "name": "ProductCard", "props": { "product": "{{product}}", - "shopBase": "{{_global.shopBase ?? '/shop'}}" + "shopBase": "{{_global.shopBase ?? '/shop'}}", + "preserveListQuery": true } } ] diff --git a/templates/_bundled/sirsoft-basic/layouts/partials/shop/list/_search_filter_bar.json b/templates/_bundled/sirsoft-basic/layouts/partials/shop/list/_search_filter_bar.json index b0071e9c..dd1db464 100644 --- a/templates/_bundled/sirsoft-basic/layouts/partials/shop/list/_search_filter_bar.json +++ b/templates/_bundled/sirsoft-basic/layouts/partials/shop/list/_search_filter_bar.json @@ -94,6 +94,7 @@ "text": "$t:shop.reset_all", "actions": [ { + "comment": "audit:allow layout-list-context-navigate-merge-query 필터 초기화 — 검색어·카테고리·정렬·페이지를 모두 비우는 의도적 리셋이므로 병합하지 않는다", "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products", "query": {} } diff --git a/templates/_bundled/sirsoft-basic/layouts/shop/category.json b/templates/_bundled/sirsoft-basic/layouts/shop/category.json index 11f4a80e..dc06a8ad 100644 --- a/templates/_bundled/sirsoft-basic/layouts/shop/category.json +++ b/templates/_bundled/sirsoft-basic/layouts/shop/category.json @@ -323,7 +323,7 @@ }, "text": "{{sub?.name_localized}}", "actions": [ - { "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/category/{{sub?.slug}}" } } + { "comment": "audit:allow layout-list-context-navigate-merge-query 하위 카테고리 이동 — 다른 목록으로의 이동이라 상위 카테고리의 검색·정렬·페이지를 승계하지 않는다", "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/category/{{sub?.slug}}" } } ] } ] diff --git a/templates/_bundled/sirsoft-basic/layouts/shop/index.json b/templates/_bundled/sirsoft-basic/layouts/shop/index.json index b813781e..42c3c6ee 100644 --- a/templates/_bundled/sirsoft-basic/layouts/shop/index.json +++ b/templates/_bundled/sirsoft-basic/layouts/shop/index.json @@ -231,7 +231,7 @@ }, "text": "$t:shop.category.all", "actions": [ - { "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products", "query": {} } } + { "comment": "audit:allow layout-list-context-navigate-merge-query 카테고리 '전체' 선택 — 카테고리 필터를 푸는 의도적 리셋이므로 병합하지 않는다", "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products", "query": {} } } ] }, { @@ -247,7 +247,7 @@ }, "text": "{{cat?.name_localized}}", "actions": [ - { "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products", "query": { "category": "{{cat?.id}}", "page": "1" } } } + { "comment": "audit:allow layout-list-context-navigate-merge-query 카테고리 전환 — 다른 목록으로의 이동이라 이전 카테고리의 검색·정렬 상태를 승계하지 않는다", "type": "click", "handler": "navigate", "params": { "path": "{{_global.shopBase}}/products", "query": { "category": "{{cat?.id}}", "page": "1" } } } ] } ] diff --git a/templates/_bundled/sirsoft-basic/layouts/shop/show.json b/templates/_bundled/sirsoft-basic/layouts/shop/show.json index b6645644..41c15aad 100644 --- a/templates/_bundled/sirsoft-basic/layouts/shop/show.json +++ b/templates/_bundled/sirsoft-basic/layouts/shop/show.json @@ -292,7 +292,9 @@ "type": "click", "handler": "navigate", "params": { - "path": "{{_global.shopBase}}/products" + "path": "{{_global.shopBase}}/products", + "mergeQuery": true, + "query": {} } } ] @@ -471,8 +473,10 @@ } }, { + "comment": "탭은 이 화면 안에서만 바뀌는 값이다 — 목록에서 실어 온 page·정렬·검색어·분류는 그대로 두고 tab 만 얹는다. 병합하지 않으면 탭을 한 번 누르는 순간 목록 상태가 사라져 '상품 목록' 버튼이 1페이지로 되돌아간다 (#75).", "handler": "replaceUrl", "params": { + "mergeQuery": true, "query": { "tab": "{{$args[0]}}" } diff --git a/templates/_bundled/sirsoft-basic/src/__tests__/components/ProductCard.list-context.test.tsx b/templates/_bundled/sirsoft-basic/src/__tests__/components/ProductCard.list-context.test.tsx new file mode 100644 index 00000000..a4d6194e --- /dev/null +++ b/templates/_bundled/sirsoft-basic/src/__tests__/components/ProductCard.list-context.test.tsx @@ -0,0 +1,92 @@ +/** + * @file ProductCard.list-context.test.tsx + * @description 상품 카드 클릭이 목록 컨텍스트를 상세 URL 로 나르는지 회귀 (#75) + * + * 결함: 상품 목록(`/shop/products?page=2&sort=price_asc`) 에서 카드를 클릭하면 + * `ProductCard` 가 `G7Core.dispatch({ handler: 'navigate', params: { path } })` 만 호출해 + * `mergeQuery` 없이 이동했다. 그 결과 상세 URL 에서 목록 상태가 통째로 사라지고, + * 상세의 '뒤로가기'(`mergeQuery: true`)는 복원할 상태가 없어 1페이지로 되돌아갔다. + * 레이아웃 JSON 이 아니라 컴포넌트 코드에 있던 leg 이라 audit 룰의 스캔 표면 밖이었다. + * + * 정정: 목록 클러스터 안에서 쓰는 자리만 `preserveListQuery` 로 옵트인한다. + * 찜 목록·검색 결과에서 상품 상세로 나가는 이동은 다른 도메인으로의 이동이므로 + * 기본값(false)을 유지해 목록 상태를 승계하지 않는다. + * + * @scenario surface=product_grid|wishlist|search + * @effects navigation_preserves_list_query + * + * @vitest-environment jsdom + */ + +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import { render, screen, cleanup } from '@testing-library/react'; +import React from 'react'; + +import ProductCard from '../../components/composite/ProductCard'; + +const product = { + id: 23, + product_code: 'O58FN04YPDRSA20C', + name: '기본 양말 5족', + thumbnail_url: '/img/socks.png', +}; + +let dispatched: Array>; + +beforeEach(() => { + dispatched = []; + (window as unknown as Record).G7Core = { + dispatch: (action: Record) => { + dispatched.push(action); + }, + }; +}); + +afterEach(() => { + cleanup(); + vi.restoreAllMocks(); +}); + +/** + * 카드를 클릭하고 발행된 navigate 액션을 돌려줍니다. + * + * @returns navigate 액션 (없으면 undefined) + */ +function clickCardAndGetNav(): Record | undefined { + const card = screen.getAllByRole('button')[0]; + card.click(); + return dispatched.find((a) => a.handler === 'navigate'); +} + +describe('#75 상품 카드 클릭이 목록 컨텍스트를 상세로 나른다', () => { + it('preserveListQuery 면 mergeQuery: true 와 빈 query 로 이동한다', () => { + render(); + + const nav = clickCardAndGetNav(); + + expect(nav, 'navigate 액션이 발행되지 않음').toBeTruthy(); + expect((nav?.params as Record).path).toBe('/shop/products/O58FN04YPDRSA20C'); + expect((nav?.params as Record).mergeQuery).toBe(true); + expect((nav?.params as Record).query).toEqual({}); + }); + + it('기본값(찜 목록·검색 결과)은 목록 상태를 승계하지 않는다', () => { + render(); + + const nav = clickCardAndGetNav(); + + expect(nav).toBeTruthy(); + expect((nav?.params as Record).path).toBe('/shop/products/O58FN04YPDRSA20C'); + expect((nav?.params as Record).mergeQuery).toBeUndefined(); + }); + + it('onClick 콜백이 주어지면 navigate 를 발행하지 않는다 (기존 동작 유지)', () => { + const onClick = vi.fn(); + render(); + + screen.getAllByRole('button')[0].click(); + + expect(onClick).toHaveBeenCalledWith(23); + expect(dispatched.find((a) => a.handler === 'navigate')).toBeUndefined(); + }); +}); diff --git a/templates/_bundled/sirsoft-basic/src/__tests__/layouts/board-post-navigation-list-return.test.tsx b/templates/_bundled/sirsoft-basic/src/__tests__/layouts/board-post-navigation-list-return.test.tsx index 1db15182..d62ccbbb 100644 --- a/templates/_bundled/sirsoft-basic/src/__tests__/layouts/board-post-navigation-list-return.test.tsx +++ b/templates/_bundled/sirsoft-basic/src/__tests__/layouts/board-post-navigation-list-return.test.tsx @@ -1,12 +1,17 @@ /** * @file board-post-navigation-list-return.test.tsx - * @description 게시판 목록 복귀 상태 보존(45-1) + 답글 상세 이전/다음 버튼 미렌더(47-4) 렌더링 회귀 테스트 + * @description 게시판 목록 컨텍스트 왕복 보존(45-1, #75) + 답글 상세 이전/다음 버튼 미렌더(47-4) 렌더링 회귀 테스트 * * 검증 항목: * 1. 행 클릭(basic/card/gallery) navigate 가 mergeQuery:true 로 현재 목록 query(category/search/page/del/filters)를 * 상세 URL 에 부착한다. (45-1) * 2. 상세 '목록' 버튼 navigate 가 mergeQuery:true 로 상세 URL 에 실린 목록 상태를 그대로 목록으로 복귀한다. (45-1) - * 3. 답글 상세(navigation prev/next null) 에서는 이전/다음 버튼이 미렌더링된다. (47-4) + * 3. 상세 이전글/다음글 navigate 가 목록 상태를 형제 상세 URL 로 이어 나른다. (#75) + * 4. 답글 상세(navigation prev/next null) 에서는 이전/다음 버튼이 미렌더링된다. (47-4) + * + * 1~3 은 테스트 안에 손으로 쓴 조각이 아니라 **실제 레이아웃 JSON 을 import** 해서 그 안의 액션 + * params 를 그대로 실행한다. 실파일이 규약을 어기면 반드시 red 가 되어야 하기 때문이다 + * (#75 는 손으로 쓴 조각만 검증하던 기존 테스트가 green 인 채로 유출된 결함이다). */ import React from 'react'; @@ -14,6 +19,75 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { createLayoutTest, screen } from '@/core/template-engine/__tests__/utils/layoutTestUtils'; import { ComponentRegistry } from '@/core/template-engine/ComponentRegistry'; +// 실제 레이아웃 JSON — 액션 params 회귀 고정 +import navigationPartial from '../../../layouts/partials/board/show/_navigation.json'; +import basicIndexPartial from '../../../layouts/partials/board/types/basic/index.json'; +import cardIndexPartial from '../../../layouts/partials/board/types/card/index.json'; +import galleryIndexPartial from '../../../layouts/partials/board/types/gallery/index.json'; + +// ============================================================ +// 실 JSON 에서 액션을 뽑아내는 헬퍼 +// ============================================================ + +type NavAction = { type?: string; handler: string; params: Record }; + +/** + * 레이아웃 JSON 트리에서 navigate/replaceUrl 액션을 모두 수집합니다. + * + * @param node 순회 시작 노드 + * @returns 수집된 액션 목록 (문서 순서) + */ +function collectNavActions(node: unknown): NavAction[] { + const out: NavAction[] = []; + const walk = (n: unknown): void => { + if (Array.isArray(n)) { + n.forEach(walk); + return; + } + if (!n || typeof n !== 'object') return; + const obj = n as Record; + if ( + (obj.handler === 'navigate' || obj.handler === 'replaceUrl') && + obj.params && + typeof obj.params === 'object' + ) { + out.push(obj as unknown as NavAction); + } + Object.values(obj).forEach(walk); + }; + walk(node); + return out; +} + +/** + * 목적지 경로가 주어진 접두사로 시작하는 첫 navigate 액션을 찾습니다. + * + * @param root 레이아웃 JSON + * @param pathPrefix 목적지 경로 접두사 + * @returns 찾은 액션 + * @throws 액션이 없으면 예외 (레이아웃 구조 변경을 조용히 통과시키지 않기 위함) + */ +function findNavAction(root: unknown, pathPrefix: string): NavAction { + const hit = collectNavActions(root).find((a) => + String((a.params as { path?: string }).path ?? '').startsWith(pathPrefix) + ); + if (!hit) { + throw new Error(`레이아웃 JSON 에서 "${pathPrefix}" 로 시작하는 navigate 액션을 찾지 못했습니다.`); + } + return hit; +} + +/** + * navigate 결과 경로의 쿼리스트링을 파싱합니다. + * + * @param dest navigate 목적지 (경로 + 쿼리) + * @returns 쿼리 파라미터 + */ +function queryOf(dest: string): URLSearchParams { + const idx = dest.indexOf('?'); + return new URLSearchParams(idx === -1 ? '' : dest.slice(idx + 1)); +} + // ============================================================ // 테스트용 컴포넌트 정의 // ============================================================ @@ -80,11 +154,31 @@ function setUrl(search: string): void { // 45-1: 행 클릭 → 상세 URL 에 목록 상태 부착 (mergeQuery) // ============================================================ +/** + * 실 JSON 액션을 현재 URL 상태에서 실행하고 목적지를 돌려줍니다. + * + * @param action 실 레이아웃 JSON 에서 뽑은 navigate 액션 + * @returns navigate 목적지 + */ +async function runNav(action: NavAction): Promise { + const testUtils = createLayoutTest({ + version: '1.0.0', + layout_name: 'nav_action_probe', + data_sources: [], + components: [{ type: 'basic', name: 'Div', props: { 'data-testid': 'probe' } }], + }); + await testUtils.render(); + await testUtils.triggerAction({ type: 'click', ...action } as any); + const dest = testUtils.getNavigationHistory()[0]; + testUtils.cleanup(); + return dest; +} + /** * @scenario post_kind=original * @effects list_return_preserves_query */ -describe('45-1 행 클릭 시 목록 상태(query)를 상세 URL 에 부착', () => { +describe('45-1 행 클릭 시 목록 상태(query)를 상세 URL 에 부착 (실 JSON)', () => { beforeEach(() => { setupTestRegistry(); }); @@ -92,76 +186,50 @@ describe('45-1 행 클릭 시 목록 상태(query)를 상세 URL 에 부착', () window.history.replaceState({}, '', '/'); }); - const rowClickLayout = { - version: '1.0.0', - layout_name: 'board_row_click_test', - data_sources: [], - components: [ - { - comment: '행 클릭 시 현재 목록 상태를 상세 URL 에 부착 (45-1)', - type: 'basic', - name: 'Button', - props: { 'data-testid': 'row' }, - actions: [ - { - type: 'click', - handler: 'navigate', - params: { path: '/board/free/77', mergeQuery: true, query: {} }, - }, - ], - text: 'row', - }, - ], - }; + const rowClickCases: Array<[string, unknown]> = [ + ['basic', basicIndexPartial], + ['card', cardIndexPartial], + ['gallery', galleryIndexPartial], + ]; - it('목록 query(category/search/page)가 상세 navigate 경로에 보존된다', async () => { - setUrl('?category=공지&search=테스트&page=2'); + it.each(rowClickCases)( + '%s 타입 행 클릭이 목록 query(category/search/page)를 상세로 나른다', + async (_type, partial) => { + setUrl('?category=공지&search=테스트&page=2'); - const testUtils = createLayoutTest(rowClickLayout); - await testUtils.render(); + // 실파일의 행 클릭 액션 — 상세(`/board/{slug}/{id}`)로 가는 첫 navigate + const action = collectNavActions(partial).find((a) => { + const p = String((a.params as { path?: string }).path ?? ''); + return /^\/board\/\{\{route\??\.slug\}\}\/\{\{post/.test(p); + }); + expect(action, '행 클릭 navigate 액션을 실 JSON 에서 찾지 못함').toBeTruthy(); - await testUtils.triggerAction({ - type: 'click', - handler: 'navigate', - params: { path: '/board/free/77', mergeQuery: true, query: {} }, - } as any); - - const history = testUtils.getNavigationHistory(); - expect(history.length).toBe(1); - const dest = history[0]; - expect(dest.startsWith('/board/free/77')).toBe(true); - expect(dest).toContain('category=%EA%B3%B5%EC%A7%80'); // '공지' URL 인코딩 - expect(dest).toContain('search=%ED%85%8C%EC%8A%A4%ED%8A%B8'); // '테스트' - expect(dest).toContain('page=2'); - - testUtils.cleanup(); - }); + const q = queryOf(await runNav(action as NavAction)); + expect(q.get('category')).toBe('공지'); + expect(q.get('search')).toBe('테스트'); + expect(q.get('page')).toBe('2'); + } + ); it('del=1(권한자 토글)도 상세 URL 로 함께 전달된다', async () => { setUrl('?del=1&page=3'); - const testUtils = createLayoutTest(rowClickLayout); - await testUtils.render(); + const action = collectNavActions(basicIndexPartial).find((a) => { + const p = String((a.params as { path?: string }).path ?? ''); + return /^\/board\/\{\{route\??\.slug\}\}\/\{\{post/.test(p); + }); - await testUtils.triggerAction({ - type: 'click', - handler: 'navigate', - params: { path: '/board/free/77', mergeQuery: true, query: {} }, - } as any); - - const dest = testUtils.getNavigationHistory()[0]; - expect(dest).toContain('del=1'); - expect(dest).toContain('page=3'); - - testUtils.cleanup(); + const q = queryOf(await runNav(action as NavAction)); + expect(q.get('del')).toBe('1'); + expect(q.get('page')).toBe('3'); }); }); // ============================================================ -// 45-1: 상세 '목록' 버튼 → 목록 상태 복귀 +// 45-1: 상세 '목록' 버튼 → 목록 상태 복귀 (실 _navigation.json) // ============================================================ -describe("45-1 '목록' 버튼이 상세 URL 의 목록 상태를 목록으로 복귀", () => { +describe("45-1 '목록' 버튼이 상세 URL 의 목록 상태를 목록으로 복귀 (실 JSON)", () => { beforeEach(() => { setupTestRegistry(); }); @@ -173,44 +241,73 @@ describe("45-1 '목록' 버튼이 상세 URL 의 목록 상태를 목록으로 // 상세 화면 URL 에 목록 상태가 실려 있음 window.history.replaceState({}, '', '/board/free/77?category=공지&search=테스트&page=2'); - const listButtonLayout = { - version: '1.0.0', - layout_name: 'board_list_button_test', - data_sources: [], - components: [ - { - comment: '목록으로 버튼 (45-1)', - type: 'basic', - name: 'Button', - props: { 'data-testid': 'back-to-list' }, - actions: [ - { - type: 'click', - handler: 'navigate', - params: { path: '/board/free', mergeQuery: true, query: {} }, - }, - ], - text: 'list', - }, - ], - }; + // 실 _navigation.json 의 '목록으로' 버튼 액션 + const action = collectNavActions(navigationPartial).find( + (a) => String((a.params as { path?: string }).path ?? '') === '/board/{{route.slug}}' + ); + expect(action, "'목록으로' navigate 액션을 실 JSON 에서 찾지 못함").toBeTruthy(); - const testUtils = createLayoutTest(listButtonLayout); - await testUtils.render(); + const q = queryOf(await runNav(action as NavAction)); + expect(q.get('category')).toBe('공지'); + expect(q.get('search')).toBe('테스트'); + expect(q.get('page')).toBe('2'); + }); +}); - await testUtils.triggerAction({ - type: 'click', - handler: 'navigate', - params: { path: '/board/free', mergeQuery: true, query: {} }, - } as any); +// ============================================================ +// #75: 이전글/다음글 → 목록 상태를 형제 상세로 승계 (실 _navigation.json) +// ============================================================ - const dest = testUtils.getNavigationHistory()[0]; - expect(dest.startsWith('/board/free?')).toBe(true); - expect(dest).toContain('category=%EA%B3%B5%EC%A7%80'); - expect(dest).toContain('search=%ED%85%8C%EC%8A%A4%ED%8A%B8'); - expect(dest).toContain('page=2'); +/** + * @scenario leg=prev|next + * @effects navigation_preserves_list_query + */ +describe('#75 이전글/다음글 버튼이 목록 상태를 형제 상세로 승계 (실 JSON)', () => { + beforeEach(() => { + setupTestRegistry(); + }); + afterEach(() => { + window.history.replaceState({}, '', '/'); + }); - testUtils.cleanup(); + const legs: Array<[string, string]> = [ + ['이전글', '/board/{{route.slug}}/{{navigation.data.prev.id}}'], + ['다음글', '/board/{{route.slug}}/{{navigation.data.next.id}}'], + ]; + + it.each(legs)('%s 클릭 시 page/search/category 가 모두 살아남는다', async (_label, destPath) => { + window.history.replaceState( + {}, + '', + '/board/free/45?page=2&search=테스트&category=공지&del=1' + ); + + const action = findNavAction(navigationPartial, destPath); + const q = queryOf(await runNav(action)); + + expect(q.get('page')).toBe('2'); + expect(q.get('search')).toBe('테스트'); + expect(q.get('category')).toBe('공지'); + expect(q.get('del')).toBe('1'); + }); + + it('이전글 → 목록 순서로 이어가도 목록 페이지가 복원된다', async () => { + window.history.replaceState({}, '', '/board/free/45?page=2&search=테스트'); + + // ① 이전글로 이동 + const prev = findNavAction(navigationPartial, '/board/{{route.slug}}/{{navigation.data.prev.id}}'); + const afterPrev = await runNav(prev); + // 이동 결과 URL 을 실제 브라우저 상태로 반영 (다음 leg 의 mergeQuery 입력) + window.history.replaceState({}, '', afterPrev); + + // ② '목록으로' 이동 + const toList = collectNavActions(navigationPartial).find( + (a) => String((a.params as { path?: string }).path ?? '') === '/board/{{route.slug}}' + ) as NavAction; + const q = queryOf(await runNav(toList)); + + expect(q.get('page')).toBe('2'); + expect(q.get('search')).toBe('테스트'); }); }); diff --git a/templates/_bundled/sirsoft-basic/src/__tests__/layouts/shop-list-context-round-trip.test.ts b/templates/_bundled/sirsoft-basic/src/__tests__/layouts/shop-list-context-round-trip.test.ts new file mode 100644 index 00000000..5a668d5d --- /dev/null +++ b/templates/_bundled/sirsoft-basic/src/__tests__/layouts/shop-list-context-round-trip.test.ts @@ -0,0 +1,177 @@ +/** + * @file shop-list-context-round-trip.test.ts + * @description 상품 목록 컨텍스트 왕복 시 URL 목록 상태 보존 회귀 (#75) + * + * 결함: 상품 목록(`/shop/products`)에서 상품을 열면 `preserveListQuery` 덕에 page·정렬· + * 검색어가 상세 URL 까지 따라오지만, 상세 화면의 탭(상세정보/리뷰/문의)을 한 번 누르는 + * 순간 `replaceUrl` 이 쿼리를 `tab=…` 하나로 통째 대체해 전부 사라졌다. 그 뒤 '상품 목록' + * 버튼은 이미 비워진 쿼리를 병합하므로 1페이지로 되돌아간다. + * + * 이 액션은 `params.path` 가 없다 — "현재 주소를 유지한 채 쿼리만 바꾼다" 는 형태라 + * 목적지 경로 문자열이 존재하지 않고, 그래서 경로 기반 검사망을 그대로 통과했다. + * + * @scenario leg=enter|tab_switch|back + * @effects navigation_preserves_list_query + * + * @vitest-environment jsdom + */ + +import { describe, it, expect, afterEach } from 'vitest'; +import fs from 'fs'; +import path from 'path'; + +import { + createLayoutTest, + createMockComponentRegistryWithBasics, +} from '@core/template-engine/__tests__/utils/layoutTestUtils'; + +const LAYOUTS_ROOT = path.resolve(__dirname, '../../../layouts'); + +/** 상품 목록 클러스터에 속하는 레이아웃 파일 */ +const CLUSTER_FILES = [ + 'shop/show.json', + 'shop/index.json', + 'partials/shop/list/_product_grid.json', + 'partials/shop/detail/_purchase_card.json', +]; + +type NavAction = { + handler: string; + comment?: string; + params: { path?: string; mergeQuery?: unknown; query?: unknown }; +}; + +/** + * JSON 트리에서 navigate/replaceUrl 액션을 모두 수집합니다. + * + * @param node 순회 시작 노드 + * @returns 액션 목록 + */ +function collectNavActions(node: unknown): NavAction[] { + const out: NavAction[] = []; + const walk = (n: unknown): void => { + if (Array.isArray(n)) { + n.forEach(walk); + return; + } + if (!n || typeof n !== 'object') return; + const obj = n as Record; + if ( + (obj.handler === 'navigate' || obj.handler === 'replaceUrl') && + obj.params && + typeof obj.params === 'object' + ) { + out.push(obj as unknown as NavAction); + } + Object.values(obj).forEach(walk); + }; + walk(node); + return out; +} + +/** + * 레이아웃 파일을 읽어 파싱합니다. + * + * @param rel 레이아웃 루트 기준 상대 경로 + * @returns 파싱된 JSON + */ +function readLayout(rel: string): unknown { + return JSON.parse(fs.readFileSync(path.join(LAYOUTS_ROOT, rel), 'utf8')); +} + +/** + * 실 JSON 액션을 현재 URL 상태에서 실행합니다. + * + * @param action 실 레이아웃 JSON 에서 뽑은 navigate/replaceUrl 액션 + * @returns navigate 목적지 경로 (replaceUrl 이면 undefined) + */ +async function runAction(action: NavAction): Promise { + const utils = createLayoutTest( + { + version: '1.0.0', + layout_name: 'nav_action_probe', + data_sources: [], + components: [{ type: 'basic', name: 'Div', props: { 'data-testid': 'probe' } }], + } as never, + { componentRegistry: createMockComponentRegistryWithBasics() as never, locale: 'ko' } + ); + await utils.render(); + await utils.triggerAction({ type: 'click', ...action } as never); + const dest = utils.getNavigationHistory()[0]; + utils.cleanup(); + return dest; +} + +describe('#75 목적지가 자기 자신인 액션도 목록 상태를 유지한다', () => { + it.each(CLUSTER_FILES)('%s 의 path 없는 navigate/replaceUrl 은 mergeQuery: true', (rel) => { + const offenders = collectNavActions(readLayout(rel)) + .filter((a) => { + if (typeof a.comment === 'string' && a.comment.includes('audit:allow')) return false; + if (typeof a.params.path === 'string' && a.params.path !== '') return false; + return a.params.mergeQuery !== true; + }) + .map((a) => `${a.handler} query=${JSON.stringify(a.params.query)}`); + + expect( + offenders, + `현재 URL 의 목록 상태를 통째로 덮어쓰는 액션: \n ${offenders.join('\n ')}` + ).toEqual([]); + }); +}); + +describe('#75 상품 상세 탭 전환이 목록 상태를 지우지 않는다', () => { + afterEach(() => { + window.history.replaceState({}, '', '/'); + }); + + /** 목록에서 상세로 넘어온 직후의 URL — `preserveListQuery` 가 실어 온 상태 */ + const DETAIL_URL = '/shop/products/12?page=2&sort=price_asc&keyword=신발&category=3'; + + it('탭을 눌러도 page·정렬·검색어·분류가 URL 에 남는다', async () => { + window.history.replaceState({}, '', DETAIL_URL); + + const action = collectNavActions(readLayout('shop/show.json')).find( + (a) => + a.handler === 'replaceUrl' && + a.params.query !== null && + typeof a.params.query === 'object' && + 'tab' in (a.params.query as Record) + ); + expect(action, '상세 탭 전환 replaceUrl 을 찾지 못했습니다.').toBeTruthy(); + + await runAction(action as NavAction); + const q = new URLSearchParams(window.location.search); + + expect(q.get('page')).toBe('2'); + expect(q.get('sort')).toBe('price_asc'); + expect(q.get('keyword')).toBe('신발'); + expect(q.get('category')).toBe('3'); + expect(q.get('tab')).toBeTruthy(); + }); + + it("탭을 누른 뒤 '상품 목록' 으로 돌아가도 보던 페이지가 복원된다", async () => { + window.history.replaceState({}, '', DETAIL_URL); + + const tabAction = collectNavActions(readLayout('shop/show.json')).find( + (a) => + a.handler === 'replaceUrl' && + a.params.query !== null && + typeof a.params.query === 'object' && + 'tab' in (a.params.query as Record) + ); + await runAction(tabAction as NavAction); + + const backAction = collectNavActions(readLayout('shop/show.json')).find((a) => + String(a.params.path ?? '').endsWith('/products') + ); + expect(backAction, "상세의 '상품 목록' navigate 를 찾지 못했습니다.").toBeTruthy(); + + const dest = (await runAction(backAction as NavAction)) as string; + const q = new URLSearchParams(dest.includes('?') ? dest.slice(dest.indexOf('?')) : ''); + + expect(q.get('page')).toBe('2'); + expect(q.get('sort')).toBe('price_asc'); + expect(q.get('keyword')).toBe('신발'); + expect(q.get('category')).toBe('3'); + }); +}); diff --git a/templates/_bundled/sirsoft-basic/src/components/composite/ProductCard.tsx b/templates/_bundled/sirsoft-basic/src/components/composite/ProductCard.tsx index 1fbb6cf2..b1679600 100644 --- a/templates/_bundled/sirsoft-basic/src/components/composite/ProductCard.tsx +++ b/templates/_bundled/sirsoft-basic/src/components/composite/ProductCard.tsx @@ -51,10 +51,11 @@ const usePreferredCurrency = (): string => { }; // G7Core.dispatch() navigate 헬퍼 -const navigate = (path: string) => { +// preserveListQuery 면 목록 컨텍스트 왕복 규약(#75)에 따라 현재 URL 의 목록 상태를 승계한다. +const navigate = (path: string, preserveListQuery = false) => { (window as any).G7Core?.dispatch?.({ handler: 'navigate', - params: { path }, + params: preserveListQuery ? { path, mergeQuery: true, query: {} } : { path }, }); }; @@ -107,6 +108,17 @@ interface ProductCardProps { onClick?: (productId: number) => void; /** 쇼핑몰 base 경로 (예: '/shop', '/store', '/') */ shopBase?: string; + /** + * 목록 컨텍스트 왕복 보존 여부 (#75). + * + * 상품 목록 그리드처럼 이 카드가 페이지네이션 목록의 일부인 자리에서만 true 로 켠다. + * 켜면 상세로 이동할 때 현재 URL 의 page/sort/keyword/category 를 상세 URL 로 승계해, + * 상세의 '뒤로가기' 가 보던 목록 위치로 정확히 되돌아간다. + * + * 찜 목록·검색 결과처럼 다른 목록에서 상품 상세로 나가는 이동은 기본값(false)을 유지한다 — + * 그 목록의 페이지 상태를 상품 목록으로 옮기면 엉뚱한 위치로 복귀한다. + */ + preserveListQuery?: boolean; /** 추가 CSS 클래스 */ className?: string; /** @@ -170,6 +182,7 @@ const ProductCard: React.FC = ({ product, onClick, shopBase = '/shop', + preserveListQuery = false, className = '', id, editorAttrs, @@ -222,7 +235,7 @@ const ProductCard: React.FC = ({ const base = shopBase === '/' ? '' : shopBase; // 상세 페이지는 product_code 기준 라우팅. code 미제공 시 id 로 폴백(하위호환). const identifier = product.product_code ?? product.id; - navigate(`${base}/products/${identifier}`); + navigate(`${base}/products/${identifier}`, preserveListQuery); } }; diff --git a/tests/Playwright/specs/datagrid-cellchildren-pipe.spec.ts b/tests/Playwright/specs/datagrid-cellchildren-pipe.spec.ts new file mode 100644 index 00000000..9ffd9b05 --- /dev/null +++ b/tests/Playwright/specs/datagrid-cellchildren-pipe.spec.ts @@ -0,0 +1,111 @@ +/** + * E2E: 반복 렌더 컨텍스트(DataGrid cellChildren 등)의 파이프 표현식 해석 + * + * 회귀(#87): `renderItemChildren` 이 단일 바인딩을 해석할 때 `|` 를 복잡 표현식 + * 문자로 분류해 `evaluateExpression`(JS 비트 OR)으로 보냈다. 그 결과 + * `{{row.created_at | datetime('YYYY-MM-DD HH:mm')}}` 는 예외로 값이 사라져 셀이 + * 비었고, `{{row.code | uppercase}}` 는 `0` 이라는 조용한 오답이 되었다. 같은 + * 표현식이 일반 컴포넌트 `text`(DynamicRenderer 경로)에서는 정상이라 재현 + * 위치를 특정하기 어려웠다. + * + * 단위 테스트(renderItemChildren-pipe.test.ts)가 소스 레벨을 잠그지만, 실제 + * 결함은 빌드된 번들이 브라우저에서 그리는 결과였으므로 브라우저 레벨에서도 + * 잠근다 — 셀에 파이프를 넣은 화면이 코어 기본 레이아웃에 없으므로, 배포된 + * 번들의 `G7Core.renderItemChildren` 를 그대로 호출해 결과를 검증한다. + * + * @scenario cellchildren_pipe_with_args + cellchildren_pipe_without_args + cellchildren_props_pipe + * @effects pipe_formatted_value_rendered + */ +import { test, expect } from '../fixtures/auth'; + +/** 반복 렌더 경로에 넘길 컴포넌트 정의 + 컨텍스트를 브라우저에서 해석한다. */ +async function resolveViaItemRenderer( + page: import('@playwright/test').Page, + defs: unknown[], + context: Record +) { + return page.evaluate( + ({ defs, context }) => { + const g7 = (window as any).G7Core; + if (!g7?.renderItemChildren) { + return { available: false, results: [] as any[] }; + } + // 템플릿 컴포넌트 레지스트리 등록 시점에 의존하지 않도록 검증 전용 맵을 넘긴다. + // renderItemChildren 이 내부에서 createElement 하므로 반환 노드의 props 로 + // 해석 결과를 그대로 읽을 수 있다(컴포넌트 구현 자체는 무관). + const Span = function Span() { + return null; + }; + const nodes = g7.renderItemChildren(defs, context, { Span }, 'e2e-pipe'); + return { + available: true, + results: (nodes as any[]).map((n) => ({ + children: n?.props?.children ?? null, + title: n?.props?.title ?? null, + })), + }; + }, + { defs, context } + ); +} + +test.describe('반복 렌더 컨텍스트의 파이프 표현식', () => { + test.beforeEach(async ({ page }) => { + // 코어 번들이 로드된 임의 화면이면 충분하다(로그인 화면도 엔진을 부팅한다). + await page.goto('/admin/login'); + await page.waitForFunction(() => Boolean((window as any).G7Core?.renderItemChildren), null, { + timeout: 30_000, + }); + }); + + // @scenario cellchildren_pipe_with_args + // @effects pipe_formatted_value_rendered + test('인자 있는 파이프(datetime)가 포맷된 값을 그린다', async ({ page }) => { + const { available, results } = await resolveViaItemRenderer( + page, + [ + { + type: 'basic', + name: 'Span', + text: "{{row.created_at | datetime('YYYY-MM-DD HH:mm')}}", + }, + ], + { row: { created_at: '2026-07-26T05:42:00.000000Z' } } + ); + + expect(available).toBe(true); + // 수정 전에는 예외로 undefined 가 되어 셀이 비었다. + expect(String(results[0].children)).toMatch(/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/); + }); + + // @scenario cellchildren_pipe_without_args + // @effects pipe_formatted_value_rendered + test('인자 없는 파이프(number/uppercase)가 비트 연산으로 오염되지 않는다', async ({ page }) => { + const { available, results } = await resolveViaItemRenderer( + page, + [ + { type: 'basic', name: 'Span', text: '{{row.price | number}}' }, + { type: 'basic', name: 'Span', text: '{{row.code | uppercase}}' }, + ], + { row: { price: 1234567, code: 'abc' } } + ); + + expect(available).toBe(true); + // 수정 전: 1234567(구분자 없음) / 0(문자열이 비트 연산으로 붕괴) + expect(results[0].children).toBe('1,234,567'); + expect(results[1].children).toBe('ABC'); + }); + + // @scenario cellchildren_props_pipe + // @effects pipe_formatted_value_rendered + test('props 값의 파이프도 해석된다', async ({ page }) => { + const { available, results } = await resolveViaItemRenderer( + page, + [{ type: 'basic', name: 'Span', text: 'x', props: { title: '{{row.price | number}}' } }], + { row: { price: 12345 } } + ); + + expect(available).toBe(true); + expect(results[0].title).toBe('12,345'); + }); +}); diff --git a/tests/scenarios/layout-editor-prop-controls.yaml b/tests/scenarios/layout-editor-prop-controls.yaml index 5f9e158f..07b6585e 100644 --- a/tests/scenarios/layout-editor-prop-controls.yaml +++ b/tests/scenarios/layout-editor-prop-controls.yaml @@ -47,7 +47,7 @@ exclusions: - { widget: select, prop_value_kind: boolean, reason: "동일" } - { widget: toggle, prop_value_kind: string, reason: "불리언" } - { widget: toggle, prop_value_kind: array, reason: "동일" } - - { widget: binding_expression, prop_value_kind: string, reason: "binding 은 options-list 디그레이드 전용 — 다른 위젯은 정적값" } + - { prop_value_kind: binding_expression, widget: [icon-picker, text, i18n-text, select, toggle], reason: "binding 은 options-list 디그레이드 전용 — 다른 위젯은 정적값" } # 칸 종류별 진입 위젯/키화 정책 상호 배제 - { expr_chip_target: prop_value_text, expr_chip_op: keyify_zero_for_value_target, expr_chip_value_shape: single_binding, reason: "값 전용 칸 + 데이터칩 = 키화 0 이 본질 — plain shape 에서 대표 검증(단일축 중복 배제)" } - { expr_chip_target: data_source_label_key, expr_chip_value_shape: settings_ref, reason: "label_key 는 다국어 라벨 키 — 설정참조 값은 비주류(데이터 칩/표현식만 대표 검증)" } @@ -105,8 +105,8 @@ test_files: validation: note: | - 단계 1-a 는 위젯/컨트롤 정의만으로 라이브 편집기에 속성 탭이 아직 등장하지 않는다 - (capability 부착이 단계 1-b/1-c). 라이브 E2E(추가→편집→사용자반영)는 1-b/1-c 의 spec 이 + 단계 1-a 는 위젯/컨트롤 정의만으로 라이브 편집기에 속성 탭이 아직 등장하지 않는다 + (capability 부착이 단계 1-b/1-c). 라이브 E2E(추가→편집→사용자반영)는 1-b/1-c 의 spec 이 작성하며, 본 매니페스트의 effects(capability_attachment_*, prop_edit_reflects_*)를 그 spec 의 @scenario layout-editor-prop-controls / @effects 로 매칭한다. e2e_spec_pending: tests/Playwright/specs/layout-editor/property-edit-propcontrols.spec.ts # 단계 1-b/1-c diff --git a/tests/scenarios/layout-semantic-asset-mapping-408-seo-tab.yaml b/tests/scenarios/layout-semantic-asset-mapping-408-seo-tab.yaml index 7688dd94..c0de0897 100644 --- a/tests/scenarios/layout-semantic-asset-mapping-408-seo-tab.yaml +++ b/tests/scenarios/layout-semantic-asset-mapping-408-seo-tab.yaml @@ -32,12 +32,27 @@ axes: - form-label - form-error - form-hint + # 도메인 구분은 layout_file 축이 이미 담당하므로 값은 평면으로 두고, + # 어느 도메인에 속하는지는 아래 exclusions 로 짝지운다. page_card: - board: [boards_page_card, board_page_card, post_page_card] - ecommerce: [category_page_card, search_page_card, product_page_card, shop_index_page_card] + - boards_page_card + - board_page_card + - post_page_card + - category_page_card + - search_page_card + - product_page_card + - shop_index_page_card viewport: [desktop, portable] theme: [light, dark] +exclusions: + - { layout_file: modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_settings/_tab_seo.json, + page_card: [category_page_card, search_page_card, product_page_card, shop_index_page_card], + reason: "이커머스 전용 페이지 카드 — 게시판 SEO 탭에는 존재하지 않는다" } + - { layout_file: modules/_bundled/sirsoft-ecommerce/resources/layouts/admin/partials/admin_ecommerce_settings/_tab_seo.json, + page_card: [boards_page_card, board_page_card, post_page_card], + reason: "게시판 전용 페이지 카드 — 이커머스 SEO 탭에는 존재하지 않는다" } + effects: - board_seo_tab_meta_settings_header_uses_section_header_asset - board_seo_tab_replaces_card_accordion_with_admin_card_for_three_page_types