From f9c4c025cb6f185cfffdf34d23fbb949e10f2bca Mon Sep 17 00:00:00 2001 From: HeuJung Date: Fri, 7 Aug 2026 11:58:26 +0900 Subject: [PATCH] =?UTF-8?q?fix(ecommerce,board,tosspayments,pay=5Fkginicis?= =?UTF-8?q?,pay=5Fnhnkcp,pay=5Fnicepayments,core,basic):=20=EA=B3=B5?= =?UTF-8?q?=EA=B0=9C=20=EC=9D=B4=EC=8A=88=20=EC=9E=94=EC=97=AC=20=EA=B2=B0?= =?UTF-8?q?=ED=95=A8=205=EA=B1=B4=20=ED=95=B4=EC=86=8C=20=E2=80=94=20?= =?UTF-8?q?=EC=83=81=EC=A0=90=20=EC=A3=BC=EC=86=8C=20SSoT=C2=B7=EA=B2=8C?= =?UTF-8?q?=EC=8B=9C=ED=8C=90=20=EA=B3=84=EC=95=BD/=EC=95=88=EB=82=B4/?= =?UTF-8?q?=EC=83=81=ED=95=9C/=EC=83=89=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 공개 이슈(gnuboard/g7) 17건 전수 대조에서 "진짜 누락"으로 판정된 5건을 해소한다. — 서버가 만들어 내보내는 상점 주소가 각 지점에서 `/shop` 리터럴이나 `"/{$routePath}/..."` 조립으로 흩어져 있었다. 기본값이 아닌 상점에서는 그 주소가 존재하지 않는 화면을 가리키는데, 서버는 문자열을 만들어 내려보냈을 뿐이라 예외도 404 로그도 남지 않는다 — 링크만 조용히 죽는다. `ShopPathResolver` 를 단일 해석 지점으로 두고 주문 완료 이동·비회원 조회 안내·알림 메일·통합검색·상품문의·SEO 캐시·사이트맵 전 지점을 경유시켰다. 같은 값에 종속된 PG 4종 리다이렉트는 `{shopBase}` 자리표시자로, 편집기 상태 scope 는 선택 세그먼트 토큰 `/*?` (engine-v1.58.0)로 해소했다. 기설치본은 업그레이드 스텝이 백필한다. M-02 — 답변 깊이 상한이 config 는 1~10 인데 컬럼 comment 만 1~5 로 남아, comment 에서 자동 생성되는 계약 문서 4곳이 실제보다 좁은 상한을 공개하고 있었다. L-01 — 관리자 게시글 폼에 첨부 안내가 아예 없었고, 대신 사장된 고정 문구 ("최대 5개 파일, 각 10MB")가 남아 있었다. 게시판마다 다른 실제 설정값을 렌더한다. — 목록 1페이지가 공지 전량을 상한 없이 읽던 것에 안전상한을 두고(구조 무변경, limit 부가만), 조회수 정렬 목록 술어를 덮는 복합 색인을 신설했다. 브라우저 실측 검수에서 발견한 사전 결함 1건(사용자 게시판 목록이 URL 정렬 파라미터를 데이터소스로 전달하지 않던 문제)도 함께 고쳤다. 폴백을 빈 문자열로 둬 URL 에 정렬이 없을 때 게시판 설정을 덮어쓰지 않게 했다. --- CHANGELOG.md | 4 + .../Repositories/UserRepositoryInterface.php | 11 ++ app/Repositories/UserRepository.php | 18 ++ .../g7-module-sirsoft-board-ja/CHANGELOG.md | 10 + .../frontend/partial/admin.json | 5 +- .../frontend/partial/admin/posts.json | 3 +- .../frontend/partial/admin/settings.json | 1 - .../language-pack.json | 2 +- .../CHANGELOG.md | 6 + .../frontend/ja.json | 4 +- .../language-pack.json | 2 +- .../CHANGELOG.md | 6 + .../frontend/ja.json | 4 +- .../language-pack.json | 2 +- .../CHANGELOG.md | 6 + .../frontend/ja.json | 4 +- .../language-pack.json | 2 +- .../CHANGELOG.md | 6 + .../frontend/ja.json | 4 +- .../language-pack.json | 2 +- .../g7-template-sirsoft-basic-ja/CHANGELOG.md | 6 + .../frontend/partial/editor.json | 4 +- .../language-pack.json | 2 +- modules/_bundled/sirsoft-board/CHANGELOG.md | 4 + .../2026_04_01_000002_create_boards_table.php | 2 +- ...ax_reply_depth_comment_in_boards_table.php | 57 ++++++ ..._count_sort_index_to_board_posts_table.php | 68 +++++++ .../_bundled/sirsoft-board/docs/api/boards.md | 8 +- modules/_bundled/sirsoft-board/module.php | 20 ++ ...-board-post-form-attachments-desc.test.tsx | 142 ++++++++++++++ .../resources/lang/partial/en/admin.json | 5 +- .../lang/partial/en/admin/posts.json | 3 +- .../lang/partial/en/admin/settings.json | 1 - .../resources/lang/partial/ko/admin.json | 5 +- .../lang/partial/ko/admin/posts.json | 3 +- .../lang/partial/ko/admin/settings.json | 1 - .../admin_board_post_form/_attachments.json | 9 + .../src/Repositories/PostRepository.php | 10 + .../tests/Feature/NoticeResultCapTest.php | 175 ++++++++++++++++++ .../PostListViewCountIndexUpgradeTest.php | 151 +++++++++++++++ .../board-post-form-attachments-desc.spec.ts | 61 ++++++ .../06_AddPostListViewCountIndex.php | 74 ++++++++ .../_bundled/sirsoft-ecommerce/CHANGELOG.md | 3 + .../sirsoft-ecommerce/docs/api/orders.md | 20 +- .../sirsoft-ecommerce/editor-spec.json | 18 +- .../layouts/checkoutNormalStateMarker.test.ts | 2 +- .../layouts/guestOrderFormStates.test.ts | 21 ++- .../layouts/productDomainSampleData.test.ts | 4 +- .../layouts/shopStateScopeRouteParity.test.ts | 110 +++++++++++ .../Controllers/Public/OrderController.php | 5 +- .../Traits/HandlesOrderCreation.php | 5 +- .../EcommerceNotificationDataListener.php | 9 +- .../src/Listeners/SearchProductsListener.php | 4 +- .../Listeners/SeoCategoryCacheListener.php | 4 +- .../src/Listeners/SeoProductCacheListener.php | 11 +- .../src/Seo/EcommerceSitemapContributor.php | 11 +- .../src/Services/ProductInquiryService.php | 129 ++++++------- .../src/Support/ShopPathResolver.php | 79 ++++++++ .../Public/OrderControllerTest.php | 81 ++++++++ .../PublicProductInquiryControllerTest.php | 53 ++++++ .../Public/UserInquiryControllerTest.php | 67 +++++-- .../Search/ProductSearchIntegrationTest.php | 45 ++++- .../EcommerceNotificationDataListenerTest.php | 17 ++ .../SeoCategoryCacheListenerTest.php | 71 +++++++ .../Listeners/SeoProductCacheListenerTest.php | 30 +++ .../Seo/EcommerceSitemapContributorTest.php | 20 ++ .../Unit/Support/ShopPathResolverTest.php | 99 ++++++++++ .../shop-route-path-server-urls.yaml | 84 +++++++++ .../sirsoft-pay_kginicis/CHANGELOG.md | 2 + .../config/settings/defaults.json | 4 +- .../sirsoft-pay_kginicis/docs/api/cbt.md | 2 +- .../sirsoft-pay_kginicis/docs/api/payment.md | 20 +- .../_bundled/sirsoft-pay_kginicis/plugin.php | 12 +- .../resources/lang/en.json | 2 +- .../resources/lang/ko.json | 2 +- .../AdminCbtTestProductController.php | 4 +- .../src/Controllers/CbtCallbackController.php | 9 +- .../Controllers/MobileCallbackController.php | 144 +++++++------- .../Controllers/PaymentCallbackController.php | 7 +- .../src/Support/ShopRedirectUrl.php | 46 +++++ .../Unit/Support/ShopRedirectUrlTest.php | 79 ++++++++ .../BackfillShopBaseRedirectUrlsTest.php | 93 ++++++++++ .../upgrades/Upgrade_1_1_0.php | 18 ++ .../BackfillShopBaseRedirectUrls.php | 122 ++++++++++++ .../_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md | 5 + .../config/settings/defaults.json | 4 +- .../_bundled/sirsoft-pay_nhnkcp/plugin.json | 2 +- .../_bundled/sirsoft-pay_nhnkcp/plugin.php | 12 +- .../sirsoft-pay_nhnkcp/resources/lang/en.json | 2 +- .../sirsoft-pay_nhnkcp/resources/lang/ko.json | 2 +- .../Controllers/PaymentCallbackController.php | 7 +- .../src/Http/Requests/AuthCallbackRequest.php | 5 +- .../src/Support/ShopRedirectUrl.php | 46 +++++ .../Unit/Support/ShopRedirectUrlTest.php | 79 ++++++++ .../BackfillShopBaseRedirectUrlsTest.php | 93 ++++++++++ .../upgrades/Upgrade_1_0_1.php | 18 ++ .../BackfillShopBaseRedirectUrls.php | 122 ++++++++++++ .../sirsoft-pay_nicepayments/CHANGELOG.md | 5 + .../config/settings/defaults.json | 4 +- .../sirsoft-pay_nicepayments/plugin.json | 2 +- .../sirsoft-pay_nicepayments/plugin.php | 12 +- .../resources/lang/en.json | 2 +- .../resources/lang/ko.json | 2 +- .../Controllers/PaymentCallbackController.php | 7 +- .../src/Http/Requests/AuthCallbackRequest.php | 5 +- .../src/Support/ShopRedirectUrl.php | 46 +++++ .../Unit/Support/ShopRedirectUrlTest.php | 79 ++++++++ .../BackfillShopBaseRedirectUrlsTest.php | 93 ++++++++++ .../upgrades/Upgrade_1_0_1.php | 18 ++ .../BackfillShopBaseRedirectUrls.php | 122 ++++++++++++ .../sirsoft-tosspayments/CHANGELOG.md | 4 + .../config/settings/defaults.json | 4 +- .../_bundled/sirsoft-tosspayments/plugin.php | 16 +- .../resources/lang/en.json | 4 +- .../resources/lang/ko.json | 4 +- .../Controllers/PaymentCallbackController.php | 7 +- .../Http/Requests/SuccessCallbackRequest.php | 6 +- .../src/Support/ShopRedirectUrl.php | 46 +++++ .../PaymentCallbackControllerTest.php | 83 ++++++++- .../Unit/Support/ShopRedirectUrlTest.php | 79 ++++++++ .../BackfillShopBaseRedirectUrlsTest.php | 93 ++++++++++ .../payment-redirect-shop-route-path.yaml | 69 +++++++ .../upgrades/Upgrade_1_0_0.php | 18 ++ .../BackfillShopBaseRedirectUrls.php | 122 ++++++++++++ public/build/core/layout-editor.min.js | 2 +- public/build/core/template-engine.min.js | 38 ++-- .../js/core/template-engine/CHANGELOG.md | 11 ++ .../__tests__/utils/matchStateScope.test.ts | 55 ++++++ .../layout-editor/utils/matchStateScope.ts | 22 ++- templates/_bundled/sirsoft-basic/CHANGELOG.md | 2 + .../layouts/board-list-sort-params.test.ts | 115 ++++++++++++ .../layouts/orderDomainSampleData.test.ts | 9 +- .../layouts/stageEGateStates.test.ts | 8 +- .../sirsoft-basic/lang/partial/en/editor.json | 4 +- .../sirsoft-basic/lang/partial/ko/editor.json | 4 +- .../sirsoft-basic/layouts/board/index.json | 2 + .../specs/board-list-sort-query.spec.ts | 103 +++++++++++ .../state-scope-optional-segment.spec.ts | 63 +++++++ 138 files changed, 3907 insertions(+), 361 deletions(-) create mode 100644 modules/_bundled/sirsoft-board/database/migrations/2026_08_06_000001_update_max_reply_depth_comment_in_boards_table.php create mode 100644 modules/_bundled/sirsoft-board/database/migrations/2026_08_06_000002_add_view_count_sort_index_to_board_posts_table.php create mode 100644 modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-board-post-form-attachments-desc.test.tsx create mode 100644 modules/_bundled/sirsoft-board/tests/Feature/NoticeResultCapTest.php create mode 100644 modules/_bundled/sirsoft-board/tests/Feature/Upgrade/PostListViewCountIndexUpgradeTest.php create mode 100644 modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-post-form-attachments-desc.spec.ts create mode 100644 modules/_bundled/sirsoft-board/upgrades/data/1.0.3/migrations/06_AddPostListViewCountIndex.php create mode 100644 modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/shopStateScopeRouteParity.test.ts create mode 100644 modules/_bundled/sirsoft-ecommerce/src/Support/ShopPathResolver.php create mode 100644 modules/_bundled/sirsoft-ecommerce/tests/Unit/Support/ShopPathResolverTest.php create mode 100644 modules/_bundled/sirsoft-ecommerce/tests/scenarios/shop-route-path-server-urls.yaml create mode 100644 plugins/_bundled/sirsoft-pay_kginicis/src/Support/ShopRedirectUrl.php create mode 100644 plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Support/ShopRedirectUrlTest.php create mode 100644 plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php create mode 100644 plugins/_bundled/sirsoft-pay_kginicis/upgrades/Upgrade_1_1_0.php create mode 100644 plugins/_bundled/sirsoft-pay_kginicis/upgrades/data/1.1.0/migrations/BackfillShopBaseRedirectUrls.php create mode 100644 plugins/_bundled/sirsoft-pay_nhnkcp/src/Support/ShopRedirectUrl.php create mode 100644 plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Support/ShopRedirectUrlTest.php create mode 100644 plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php create mode 100644 plugins/_bundled/sirsoft-pay_nhnkcp/upgrades/Upgrade_1_0_1.php create mode 100644 plugins/_bundled/sirsoft-pay_nhnkcp/upgrades/data/1.0.1/migrations/BackfillShopBaseRedirectUrls.php create mode 100644 plugins/_bundled/sirsoft-pay_nicepayments/src/Support/ShopRedirectUrl.php create mode 100644 plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Support/ShopRedirectUrlTest.php create mode 100644 plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php create mode 100644 plugins/_bundled/sirsoft-pay_nicepayments/upgrades/Upgrade_1_0_1.php create mode 100644 plugins/_bundled/sirsoft-pay_nicepayments/upgrades/data/1.0.1/migrations/BackfillShopBaseRedirectUrls.php create mode 100644 plugins/_bundled/sirsoft-tosspayments/src/Support/ShopRedirectUrl.php create mode 100644 plugins/_bundled/sirsoft-tosspayments/tests/Unit/Support/ShopRedirectUrlTest.php create mode 100644 plugins/_bundled/sirsoft-tosspayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php create mode 100644 plugins/_bundled/sirsoft-tosspayments/tests/scenarios/payment-redirect-shop-route-path.yaml create mode 100644 plugins/_bundled/sirsoft-tosspayments/upgrades/Upgrade_1_0_0.php create mode 100644 plugins/_bundled/sirsoft-tosspayments/upgrades/data/1.0.0/migrations/BackfillShopBaseRedirectUrls.php create mode 100644 templates/_bundled/sirsoft-basic/__tests__/layouts/board-list-sort-params.test.ts create mode 100644 templates/_bundled/sirsoft-basic/tests/Playwright/specs/board-list-sort-query.spec.ts create mode 100644 tests/Playwright/specs/layout-editor/state-scope-optional-segment.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 759e052e..7f79b159 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -111,6 +111,10 @@ - 레이아웃 코드 편집 화면이 파일 목록을 불러올 때 편집하지 않는 레이아웃의 본문까지 전부 내려받던 문제를 수정했습니다. 레이아웃이 많은 템플릿에서는 목록을 여는 것만으로 수십 MB가 브라우저에 쌓여 화면이 크게 느려지거나, 디버그 모드에서는 탭이 메모리 부족으로 종료됐습니다. 이제 목록에는 이름·설명·크기·수정일만 실리고 본문은 선택한 파일만 불러옵니다. +#### 화면 편집기 + +- 화면 편집기가 주소 일부를 설정으로 바꿀 수 있는 화면도 알아보도록 화면 인식 방식을 넓혔습니다. 예를 들어 쇼핑몰은 주소를 바꾸거나 주소 없이 운영할 수 있는데, 편집기는 주소가 한 토막 있는 경우만 인식해 그 외의 사이트에서는 해당 화면의 상태 미리보기 전환이 표시되지 않았습니다. 이제 확장이 "이 토막은 있을 수도 없을 수도 있다"고 알려 줄 수 있으며, 함께 배포되는 쇼핑몰에 이미 적용되어 있습니다. + #### 설정 화면 입력 - 설정 화면에서 여러 입력칸을 고친 뒤 다른 탭에 갔다 돌아오면, 먼저 고친 칸에 입력했던 값이 그대로 남던 문제를 수정했습니다. 저장된 값은 원래 값이라 화면에 보이는 값과 실제 값이 어긋났고, 새로고침해야 드러났습니다. 이제 탭을 오갈 때 모든 입력칸이 저장된 값으로 함께 돌아옵니다. diff --git a/app/Contracts/Repositories/UserRepositoryInterface.php b/app/Contracts/Repositories/UserRepositoryInterface.php index a3fc7bbe..d6726dbf 100644 --- a/app/Contracts/Repositories/UserRepositoryInterface.php +++ b/app/Contracts/Repositories/UserRepositoryInterface.php @@ -191,6 +191,17 @@ interface UserRepositoryInterface */ public function getIdsByUuids(array $uuids): array; + /** + * 사용자 ID 목록에 해당하는 이름을 ID 로 색인해 반환합니다. + * + * 목록 화면이 작성자 이름을 행마다 조회하면 N+1 이 되므로, 표시에 필요한 + * 이름만 한 번에 모아 오기 위한 배치 조회입니다. + * + * @param array $ids 사용자 ID 배열 + * @return array 사용자 ID => 이름 + */ + public function getNamesByIds(array $ids): array; + /** * 사용자 ID 목록의 지정 컬럼을 일괄 갱신합니다. * diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index 14f29798..f76f248c 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -406,6 +406,24 @@ class UserRepository implements UserRepositoryInterface return User::whereIn('uuid', $uuids)->pluck('id')->all(); } + /** + * 사용자 ID 목록에 해당하는 이름을 ID 로 색인해 반환합니다. + * + * 목록 화면이 작성자 이름을 행마다 조회하면 N+1 이 되므로, 표시에 필요한 + * 이름만 한 번에 모아 옵니다. + * + * @param array $ids 사용자 ID 배열 + * @return array 사용자 ID => 이름 + */ + public function getNamesByIds(array $ids): array + { + if (empty($ids)) { + return []; + } + + return User::whereIn('id', $ids)->pluck('name', 'id')->all(); + } + /** * 사용자 ID 목록의 지정 컬럼을 일괄 갱신합니다. * diff --git a/lang-packs/_bundled/g7-module-sirsoft-board-ja/CHANGELOG.md b/lang-packs/_bundled/g7-module-sirsoft-board-ja/CHANGELOG.md index 8437ac34..deda70b4 100644 --- a/lang-packs/_bundled/g7-module-sirsoft-board-ja/CHANGELOG.md +++ b/lang-packs/_bundled/g7-module-sirsoft-board-ja/CHANGELOG.md @@ -4,6 +4,16 @@ 형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며, [Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다. +## [1.0.5] - 2026-08-06 + +### Added + +- 관리자 게시글 작성·수정 화면의 첨부 안내 문구 일본어 번역 추가 — 게시판에 설정된 첨부 개수·용량이 일본어 로케일에서도 그대로 표시됩니다. + +### Removed + +- 화면에서 쓰이지 않던 첨부 안내(고정 5개·10MB)와 답변글 깊이 안내(1~5) 번역을 제거했습니다. 실제 상한과 다른 값이라 남겨 둘 이유가 없습니다. + ## [1.0.4] - 2026-07-22 ### Added diff --git a/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin.json b/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin.json index 0a1fe7d8..0610e730 100644 --- a/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin.json +++ b/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin.json @@ -717,12 +717,11 @@ "html_preview_warning": "HTMLレンダリングの注意", "no_content_preview": "内容を入力するとプレビューが表示されます", "attachments": "添付ファイル", + "attachments_desc": "最大{{maxFiles}}個、各{{maxSize}}MB以下", "attached_files": "添付されたファイル", "confirm_remove_attachment_title": "添付ファイルを削除", "confirm_remove_attachment_message": "ファイルはすぐに削除されます。投稿の保存に関係なく、復元することはできません。", - "attachments_limit": "最大5個のファイル、各10MB以下 (jpg、jpeg、png、gif、pdf、zip)", "drop_files_or_click": "クリックしてアップロード、またはドラッグ&ドロップ", - "max_10mb": "最大10MB", "file_upload_component_needed": "FileUploadコンポーネント開発が必要です", "uploading": "アップロード中...", "reply_to": "以下の投稿に対する回答です", @@ -902,7 +901,6 @@ "max_content_length": "最大投稿文字数", "use_reply": "返信機能", "max_reply_depth": "返信の最大深さ", - "max_reply_depth_hint": "1~5の間の値を入力してください", "use_comment": "コメント機能", "comment_order": "コメント並べ替え順序", "min_comment_length": "最小コメント文字数", @@ -974,7 +972,6 @@ "min_content_length": "投稿本文の最小文字数を設定します", "max_content_length": "投稿本文の最大文字数を設定します", "use_reply": "ONに設定する必要があります新しい掲示板に返信機能が適用されます。", - "max_reply_depth": "返信の最大ネスト深さを設定します (1~5)", "blocked_keywords": "登録されたキーワードを含む投稿/コメントは作成がブロックされます", "use_comment": "ONに設定する必要があります新しい掲示板にコメント機能が適用されます。以下のコメント詳細設定も同時に適用されます。", "comment_order": "コメントの基本並べ替え方向を設定します", diff --git a/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin/posts.json b/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin/posts.json index 9abc52f1..2094991b 100644 --- a/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin/posts.json +++ b/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin/posts.json @@ -174,12 +174,11 @@ "html_preview_warning": "HTMLレンダリング注意", "no_content_preview": "内容を入力するとプレビューが表示されます", "attachments": "添付ファイル", + "attachments_desc": "最大{{maxFiles}}個、各{{maxSize}}MB以下", "attached_files": "添付ファイル", "confirm_remove_attachment_title": "添付ファイル削除", "confirm_remove_attachment_message": "ファイルは即座に削除されます。投稿の保存とは関係なく、復元できません。", - "attachments_limit": "最大5個のファイル、各10MB以下 (jpg、jpeg、png、gif、pdf、zip)", "drop_files_or_click": "クリックしてアップロード、またはドラッグアンドドロップ", - "max_10mb": "最大10MB", "file_upload_component_needed": "FileUploadコンポーネント開発が必要です", "uploading": "アップロード中...", "reply_to": "次の投稿への返信です", diff --git a/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin/settings.json b/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin/settings.json index 01784659..6d77036f 100644 --- a/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin/settings.json +++ b/lang-packs/_bundled/g7-module-sirsoft-board-ja/frontend/partial/admin/settings.json @@ -78,7 +78,6 @@ "max_content_length": "最大投稿文字数", "use_reply": "回答投稿の使用", "max_reply_depth": "回答投稿の最大深さ", - "max_reply_depth_hint": "1~5の間の値を入力してください", "use_comment": "コメントの使用", "comment_order": "コメント並べ替え順序", "min_comment_length": "最小コメント文字数", diff --git a/lang-packs/_bundled/g7-module-sirsoft-board-ja/language-pack.json b/lang-packs/_bundled/g7-module-sirsoft-board-ja/language-pack.json index 576369f7..4dd9c4b7 100644 --- a/lang-packs/_bundled/g7-module-sirsoft-board-ja/language-pack.json +++ b/lang-packs/_bundled/g7-module-sirsoft-board-ja/language-pack.json @@ -12,7 +12,7 @@ "en": "G7 module (sirsoft-board) Japanese language pack (bundled)", "ja": "G7 モジュール (sirsoft-board) 日本語 言語パック(バンドル)" }, - "version": "1.0.4", + "version": "1.0.5", "license": "MIT", "scope": "module", "target_identifier": "sirsoft-board", diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/CHANGELOG.md b/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/CHANGELOG.md index 2075d43a..0df34857 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/CHANGELOG.md +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/CHANGELOG.md @@ -4,6 +4,12 @@ 형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며, [Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다. +## [1.1.1] - 2026-08-07 + +### Changed + +- 결제 성공·실패 리다이렉트 주소 안내 문구를 갱신했습니다 — 상점 주소 설정을 따라 자동으로 채워지는 `{shopBase}` 자리표시자 설명으로 바뀌었습니다. + ## [1.1.0] - 2026-08-06 ### Added diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/frontend/ja.json b/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/frontend/ja.json index d04eaa3d..94ad8119 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/frontend/ja.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/frontend/ja.json @@ -316,9 +316,9 @@ "use_escrow_hint": "有効化時にPCはacceptmethodにuseescrowが追加され、モバイルはP_RESERVEDにuseescrow=Yが追加されます。", "section_redirect": "リダイレクト URL", "redirect_success_url": "決済成功リダイレクト URL", - "redirect_success_url_hint": "相対パス(/shop/...)または完全なURL両方が可能です。{orderId}は注文番号に自動置換されます。", + "redirect_success_url_hint": "{shopBase}はストア住所設定に従って自動的に入力されます。完全URL(https://...)を直接入力することもできます。{orderId}は実際の注文番号に自動置換されます。", "redirect_fail_url": "決済失敗リダイレクト URL", - "redirect_fail_url_hint": "相対パスまたは完全なURL両方が可能です。エラー情報はクエリパラメーターとして自動追加されます。", + "redirect_fail_url_hint": "{shopBase}はストア住所設定に従って自動的に入力されます。完全URLを直接入力することもできます。エラー情報はクエリパラメーターとして自動追加されます。", "section_vbank_notify": "仮想口座入金通知 URL (PC)", "vbank_notify_hint": "KGイニシス加盟店管理画面でこのURLをPC仮想口座入金通知URLとして登録する必要があります。", "vbank_notify_copied": "URLがクリップボードにコピーされました。", diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/language-pack.json b/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/language-pack.json index 1e5be7a0..b01d3975 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/language-pack.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_kginicis-ja/language-pack.json @@ -12,7 +12,7 @@ "en": "G7 plugin (sirsoft-pay_kginicis) Japanese language pack (bundled)", "ja": "G7 プラグイン (sirsoft-pay_kginicis) 日本語 言語パック(バンドル)" }, - "version": "1.1.0", + "version": "1.1.1", "license": "MIT", "scope": "plugin", "target_identifier": "sirsoft-pay_kginicis", diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/CHANGELOG.md b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/CHANGELOG.md index 7825e04a..7246fc80 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/CHANGELOG.md +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/CHANGELOG.md @@ -4,6 +4,12 @@ 형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며, [Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다. +## [1.0.2] - 2026-08-07 + +### Changed + +- 결제 성공·실패 리다이렉트 주소 안내 문구를 갱신했습니다 — 상점 주소 설정을 따라 자동으로 채워지는 `{shopBase}` 자리표시자 설명으로 바뀌었습니다. + ## [1.0.1] - 2026-07-16 ### Added diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/frontend/ja.json b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/frontend/ja.json index 52e22b53..80e17850 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/frontend/ja.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/frontend/ja.json @@ -113,9 +113,9 @@ "easy_pay_applepay_hint": "iOS Safariでのみ使用可能です", "section_redirect": "リダイレクトURL", "redirect_success_url": "決済成功リダイレクトURL", - "redirect_success_url_hint": "相対パス(/shop/...)または完全URLの両方が可能です。{orderId}は注文番号に自動置換されます。", + "redirect_success_url_hint": "{shopBase}はストア住所設定に従って自動的に入力されます。完全URL(https://...)を直接入力することもできます。{orderId}は実際の注文番号に自動置換されます。", "redirect_fail_url": "決済失敗リダイレクトURL", - "redirect_fail_url_hint": "相対パスまたは完全URLの両方が可能です。エラー情報はクエリパラメータとして自動追加されます。", + "redirect_fail_url_hint": "{shopBase}はストア住所設定に従って自動的に入力されます。完全URLを直接入力することもできます。エラー情報はクエリパラメータとして自動追加されます。", "section_vbank": "仮想口座設定", "section_vbank_hint": "仮想口座決済に関する設定です。", "vbank_expire_days": "入金有効期限", diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/language-pack.json b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/language-pack.json index 4285e495..2e0e1338 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/language-pack.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nhnkcp-ja/language-pack.json @@ -12,7 +12,7 @@ "en": "G7 plugin (sirsoft-pay_nhnkcp) Japanese language pack (bundled)", "ja": "G7 プラグイン (sirsoft-pay_nhnkcp) 日本語 言語パック(バンドル)" }, - "version": "1.0.1", + "version": "1.0.2", "license": "MIT", "scope": "plugin", "target_identifier": "sirsoft-pay_nhnkcp", diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/CHANGELOG.md b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/CHANGELOG.md index b4bf2011..7158a2c5 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/CHANGELOG.md +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/CHANGELOG.md @@ -4,6 +4,12 @@ 형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며, [Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다. +## [1.0.2] - 2026-08-07 + +### Changed + +- 결제 성공·실패 리다이렉트 주소 안내 문구를 갱신했습니다 — 상점 주소 설정을 따라 자동으로 채워지는 `{shopBase}` 자리표시자 설명으로 바뀌었습니다. + ## [1.0.1] - 2026-07-16 ### Added diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/frontend/ja.json b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/frontend/ja.json index 50cb2574..1160ee4a 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/frontend/ja.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/frontend/ja.json @@ -34,9 +34,9 @@ "copy": "コピー", "section_redirect": "リダイレクトURL", "redirect_success_url": "決済成功リダイレクトURL", - "redirect_success_url_hint": "相対パス(/shop/...)または完全URL(https://...)の両方が可能です。{orderId}は注文番号に自動置換されます。", + "redirect_success_url_hint": "{shopBase}はストア住所設定に従って自動的に入力されます。完全URL(https://...)を直接入力することもできます。{orderId}は実際の注文番号に自動置換されます。", "redirect_fail_url": "決済失敗リダイレクトURL", - "redirect_fail_url_hint": "相対パスまたは完全URL両方が可能です。エラー情報はクエリパラメーターとして自動追加されます。", + "redirect_fail_url_hint": "{shopBase}はストア住所設定に従って自動的に入力されます。完全URLを直接入力することもできます。エラー情報はクエリパラメーターとして自動追加されます。", "use_escrow": "エスクロー決済使用", "use_escrow_hint": "実物商品販売時に購入者保護のためのエスクロー決済を有効化します。エスクロー決済後の配送登録が必要です。", "section_easy_pay": "簡易決済設定", diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/language-pack.json b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/language-pack.json index bbe7abca..0cd3fc7a 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/language-pack.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-pay_nicepayments-ja/language-pack.json @@ -12,7 +12,7 @@ "en": "G7 plugin (sirsoft-pay_nicepayments) Japanese language pack (bundled)", "ja": "G7 プラグイン (sirsoft-pay_nicepayments) 日本語 言語パック(バンドル)" }, - "version": "1.0.1", + "version": "1.0.2", "license": "MIT", "scope": "plugin", "target_identifier": "sirsoft-pay_nicepayments", diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/CHANGELOG.md b/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/CHANGELOG.md index 3e9b3486..43595ab5 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/CHANGELOG.md +++ b/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/CHANGELOG.md @@ -4,6 +4,12 @@ 형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며, [Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다. +## [1.0.1] - 2026-08-07 + +### Changed + +- 결제 성공·실패 리다이렉트 주소 안내 문구를 갱신했습니다 — 상점 주소 설정을 따라 자동으로 채워지는 `{shopBase}` 자리표시자 설명으로 바뀌었습니다. + ## [1.0.0] - 2026-07-13 ### Added diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/frontend/ja.json b/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/frontend/ja.json index d2335902..ad0c9fd2 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/frontend/ja.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/frontend/ja.json @@ -22,9 +22,9 @@ "section_live_keys": "ライブAPI キー", "section_redirect": "リダイレクト設定", "redirect_success_url": "決済成功リダイレクトURL", - "redirect_success_url_hint": "相対パス(/shop/...) または完全URL(https://...) の両方が可能です。{orderId}は実際の注文番号に自動置換されます。", + "redirect_success_url_hint": "{shopBase}はストア住所設定に従って自動的に入力されます。完全URL(https://...)を直接入力することもできます。{orderId}は実際の注文番号に自動置換されます。", "redirect_fail_url": "決済失敗リダイレクトURL", - "redirect_fail_url_hint": "相対パス または完全URL の両方が可能です。エラー情報(error, message, orderId)はクエリパラメーターとして自動追加されます。", + "redirect_fail_url_hint": "{shopBase}はストア住所設定に従って自動的に入力されます。完全URLを直接入力することもできます。エラー情報(error, message, orderId)はクエリパラメーターとして自動追加されます。", "save": "保存", "saved": "設定が保存されました。", "section_payment_methods": "決済方法", diff --git a/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/language-pack.json b/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/language-pack.json index fa473df9..10faf0d2 100644 --- a/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/language-pack.json +++ b/lang-packs/_bundled/g7-plugin-sirsoft-tosspayments-ja/language-pack.json @@ -12,7 +12,7 @@ "en": "G7 plugin (sirsoft-tosspayments) Japanese language pack (bundled)", "ja": "G7 プラグイン (sirsoft-tosspayments) 日本語 言語パック(バンドル)" }, - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "scope": "plugin", "target_identifier": "sirsoft-tosspayments", diff --git a/lang-packs/_bundled/g7-template-sirsoft-basic-ja/CHANGELOG.md b/lang-packs/_bundled/g7-template-sirsoft-basic-ja/CHANGELOG.md index 8861490a..2f2dabb9 100644 --- a/lang-packs/_bundled/g7-template-sirsoft-basic-ja/CHANGELOG.md +++ b/lang-packs/_bundled/g7-template-sirsoft-basic-ja/CHANGELOG.md @@ -4,6 +4,12 @@ 형식은 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/)를 따르며, [Semantic Versioning](https://semver.org/lang/ko/)을 준수합니다. +## [1.1.1] - 2026-08-07 + +### Changed + +- 화면 편집기 상품 상세의 상태 미리보기 라벨(`editor.state.out_of_stock`, `editor.state.sold_out`)을 서로 구분되도록 정정했습니다. 두 상태 모두 "品切れ" 로 표시되어 목록에서 어느 쪽인지 구별할 수 없었습니다. + ## [1.1.0] - 2026-08-06 ### Added diff --git a/lang-packs/_bundled/g7-template-sirsoft-basic-ja/frontend/partial/editor.json b/lang-packs/_bundled/g7-template-sirsoft-basic-ja/frontend/partial/editor.json index a0f5d373..fe2a8905 100644 --- a/lang-packs/_bundled/g7-template-sirsoft-basic-ja/frontend/partial/editor.json +++ b/lang-packs/_bundled/g7-template-sirsoft-basic-ja/frontend/partial/editor.json @@ -887,7 +887,7 @@ "with_data": "データあり", "empty_data": "データなし", "in_stock": "在庫あり", - "out_of_stock": "品切れ", + "out_of_stock": "在庫切れ (販売中)", "cart_with_items": "商品が追加されました", "cart_empty": "カートが空です", "read_normal": "一般投稿", @@ -924,7 +924,7 @@ "board_create": "新規投稿", "board_edit": "投稿編集", "shop_access_denied": "アクセス制限", - "sold_out": "品切れ", + "sold_out": "品切れ設定", "suspended": "販売停止", "coming_soon": "販売予定", "cart_ordering": "注文処理中", diff --git a/lang-packs/_bundled/g7-template-sirsoft-basic-ja/language-pack.json b/lang-packs/_bundled/g7-template-sirsoft-basic-ja/language-pack.json index 450ac498..70dc6acc 100644 --- a/lang-packs/_bundled/g7-template-sirsoft-basic-ja/language-pack.json +++ b/lang-packs/_bundled/g7-template-sirsoft-basic-ja/language-pack.json @@ -12,7 +12,7 @@ "en": "G7 template (sirsoft-basic) Japanese language pack (bundled)", "ja": "G7 テンプレート (sirsoft-basic) 日本語 言語パック(バンドル)" }, - "version": "1.1.0", + "version": "1.1.1", "license": "MIT", "scope": "template", "target_identifier": "sirsoft-basic", diff --git a/modules/_bundled/sirsoft-board/CHANGELOG.md b/modules/_bundled/sirsoft-board/CHANGELOG.md index 81fda7fb..9f4f743f 100644 --- a/modules/_bundled/sirsoft-board/CHANGELOG.md +++ b/modules/_bundled/sirsoft-board/CHANGELOG.md @@ -26,6 +26,9 @@ - 게시글 목록을 뒤쪽 페이지에서도 빠르게 열 수 있도록 조회 방식을 바꿨습니다. 예전에는 페이지가 뒤로 갈수록 건너뛰는 게시글의 본문 앞부분까지 함께 읽어 느려졌지만, 이제 현재 페이지의 게시글만 본문 미리보기를 읽습니다. 공지 노출·답글 표시·다음 페이지 버튼은 이전과 동일하게 동작합니다. (#74 @jiwonpapa 님께서 제보해주셨습니다.) - 신고 관리 목록도 같은 방식으로 개선했습니다. 신고 건수·대상 글 상태처럼 목록에 함께 표시되는 정보를 예전에는 건너뛰는 신고까지 모두 계산했지만, 이제 현재 페이지의 신고에 대해서만 계산합니다. 신고가 많이 쌓인 사이트에서 목록 페이지 이동이 빨라집니다. (#74 @jiwonpapa 님께서 제보해주셨습니다.) - 마이페이지의 「내가 쓴 댓글」·「내가 댓글 단 글」 목록도 같은 방식으로 개선했습니다. 각 글의 최근 댓글을 예전에는 건너뛰는 글까지 모두 찾아봤지만, 이제 현재 페이지의 글에 대해서만 찾습니다. 댓글 활동이 많은 회원의 목록 페이지 이동이 빨라집니다. (#74 @jiwonpapa 님께서 제보해주셨습니다.) +- 게시글 목록을 조회순으로 볼 때도 뒤쪽 페이지가 빠르게 열리도록 색인을 정비했습니다. 게시판 설정의 기본 정렬을 조회순으로 두었거나 목록에서 조회순으로 바꿔 보는 경우가 해당됩니다. 기존 사이트도 업데이트 시 자동으로 반영되며, 게시글이 아주 많은 경우 이 과정에 수 분이 걸리고 그동안 글쓰기가 잠시 대기할 수 있습니다. (#74 @jiwonpapa 님께서 제보해주셨습니다.) +- 목록 첫 페이지의 공지를 개수 제한 없이 모두 읽던 것에 안전 상한을 두었습니다. 공지는 관리자가 등록하는 글이라 보통 문제가 되지 않지만, 어떤 이유로든 공지가 많이 쌓인 게시판에서 목록을 여는 것만으로 부담이 커지던 여지를 없앴습니다. 상한에 걸리면 최근 공지가 우선 표시됩니다. (#74 @jiwonpapa 님께서 제보해주셨습니다.) +- 답변글 최대 깊이의 안내 상한 표기를 실제 설정 가능 범위(1~10)에 맞게 정정했습니다. 실제로는 10까지 설정할 수 있는데 일부 안내에만 5까지로 적혀 있었습니다. (#81 @jiwonpapa 님께서 제보해주셨습니다.) - 게시글이 많은 게시판에서 목록 정렬이 더 빨라지도록 색인을 정비했습니다. 신고 관리 목록에도 같은 정비를 적용했습니다. 같은 시각에 등록된 게시글이 많은 구간에서 순서를 정하느라 생기던 추가 작업이 사라집니다. 기존 사이트도 업데이트 시 자동으로 반영되며, 게시글이 아주 많은 경우 이 과정에 수 분이 걸리고 그동안 글쓰기가 잠시 대기할 수 있습니다. - 관리자 게시판 목록이 게시판마다 매니저·스텝 역할과 그 역할에 속한 회원 명단(이름·이메일)을 함께 내려주지 않습니다. 목록 화면이 쓰지 않는 값이라 게시판 수만큼 늘어나던 조회와 전송량이 사라집니다. 역할 지정은 종전대로 게시판 상세·설정 화면에서 하며, 목록에 보이는 항목은 이전과 동일합니다. (#76 @jordy-bitree 님께서 제보해주셨습니다.) - 한 글의 댓글이 아주 많아 목록이 일정 수에서 끊긴 경우, 끊겼다는 사실과 전체 건수를 함께 알려 줍니다. 예전에는 조용히 잘려 "댓글이 그만큼뿐" 으로 보였습니다. @@ -43,6 +46,7 @@ ### Fixed - 게시판 알림 설정 화면에서 모든 알림의 제목·수신자·활성 여부가 비어 보이고 「이 채널에 대한 템플릿이 없습니다」로만 표시되던 문제를 수정했습니다. 편집 창을 열어도 내용이 채워지지 않았습니다. 채널을 전환하거나 새로고침해도 마찬가지였습니다. (#76 @jordy-bitree 님께서 제보해주셨습니다.) +- 관리자 게시글 작성·수정 화면의 첨부 영역에 첨부 가능한 개수와 파일당 용량 안내가 표시됩니다. 안내는 그 게시판에 설정된 값을 그대로 보여 주므로, 게시판마다 다른 제한이 화면에 정확히 나타납니다. 이전에는 안내가 아예 없어 저장을 시도한 뒤에야 제한을 알 수 있었습니다. (#81 @jiwonpapa 님께서 제보해주셨습니다.) - 게시판 설정의 '새 글 표시 시간'이 저장 직후에는 숫자가 아닌 형태로 다뤄져, 조회 시점에 따라 값의 형태가 달라지던 문제를 수정했습니다. 새 글 표시 여부 판정에 쓰이는 값이므로 항상 숫자로 처리합니다. - 게시글이 아주 많은 게시판에서 목록의 글 번호가 0 이나 음수로 표시되던 문제를 수정했습니다. 총 건수를 끝까지 세지 못하는 경우에는 번호를 지어내지 않고 「-」로 표시합니다. - 통합 검색 결과에서 작성자 자리에 번역되지 않은 내부 문구가 그대로 보이던 문제를 수정했습니다. 이제 「비회원」으로 표시됩니다. diff --git a/modules/_bundled/sirsoft-board/database/migrations/2026_04_01_000002_create_boards_table.php b/modules/_bundled/sirsoft-board/database/migrations/2026_04_01_000002_create_boards_table.php index 46b2638a..b6a89044 100644 --- a/modules/_bundled/sirsoft-board/database/migrations/2026_04_01_000002_create_boards_table.php +++ b/modules/_bundled/sirsoft-board/database/migrations/2026_04_01_000002_create_boards_table.php @@ -29,7 +29,7 @@ return new class extends Migration $table->enum('secret_mode', ['disabled', 'enabled', 'always'])->default('disabled')->comment('비밀글 설정 (disabled: 사용안함, enabled: 사용함, always: 고정)'); $table->boolean('use_comment')->default(true)->comment('댓글 기능 사용'); $table->boolean('use_reply')->default(true)->comment('게시글 답변 기능 사용 (댓글에 대한 답글 아님)'); - $table->unsignedSmallInteger('max_reply_depth')->default(5)->comment('답변글 최대 깊이 (1~5)'); + $table->unsignedSmallInteger('max_reply_depth')->default(5)->comment('답변글 최대 깊이 (1~10)'); $table->boolean('use_report')->default(false)->comment('게시글/댓글 신고 기능 사용'); $table->unsignedInteger('new_display_hours')->default(24)->comment('신규 게시글 표시 기간 (시간 단위)'); $table->unsignedInteger('min_title_length')->default(2)->comment('최소 제목 글자 수'); diff --git a/modules/_bundled/sirsoft-board/database/migrations/2026_08_06_000001_update_max_reply_depth_comment_in_boards_table.php b/modules/_bundled/sirsoft-board/database/migrations/2026_08_06_000001_update_max_reply_depth_comment_in_boards_table.php new file mode 100644 index 00000000..dd5f0dc0 --- /dev/null +++ b/modules/_bundled/sirsoft-board/database/migrations/2026_08_06_000001_update_max_reply_depth_comment_in_boards_table.php @@ -0,0 +1,57 @@ + */ + private const INDEX_COLUMNS = ['board_id', 'is_notice', 'parent_id', 'deleted_at', 'view_count', 'id']; + + /** + * Run the migrations. + */ + public function up(): void + { + if (! Schema::hasTable(self::TABLE)) { + return; + } + + $existing = array_column(Schema::getIndexes(self::TABLE), 'name'); + + Schema::table(self::TABLE, function (Blueprint $table) use ($existing) { + if (! in_array(self::INDEX_NAME, $existing, true)) { + $table->index(self::INDEX_COLUMNS, self::INDEX_NAME); + } + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + if (! Schema::hasTable(self::TABLE)) { + return; + } + + $existing = array_column(Schema::getIndexes(self::TABLE), 'name'); + + Schema::table(self::TABLE, function (Blueprint $table) use ($existing) { + if (in_array(self::INDEX_NAME, $existing, true)) { + $table->dropIndex(self::INDEX_NAME); + } + }); + } +}; diff --git a/modules/_bundled/sirsoft-board/docs/api/boards.md b/modules/_bundled/sirsoft-board/docs/api/boards.md index 17709bf2..55f2117b 100644 --- a/modules/_bundled/sirsoft-board/docs/api/boards.md +++ b/modules/_bundled/sirsoft-board/docs/api/boards.md @@ -389,7 +389,7 @@ _단건 응답: `data` 객체의 필드._ | secret_mode | string | `disabled` | 비밀글 설정 (disabled: 사용안함, enabled: 사용함, always: 고정) | | use_comment | boolean | `true` | 댓글 기능 사용 | | use_reply | boolean | `true` | 게시글 답변 기능 사용 (댓글에 대한 답글 아님) | -| max_reply_depth | integer | `5` | 답변글 최대 깊이 (1~5) | +| max_reply_depth | integer | `5` | 답변글 최대 깊이 (1~10) | | max_comment_depth | integer | `10` | 대댓글 최대 깊이 (1~10) | | comment_order | string | `ASC` | 댓글 정렬 순서 (ASC: 오름차순, DESC: 내림차순) | | show_view_count | boolean | `true` | 조회수 노출 | @@ -754,7 +754,7 @@ _단건 응답: `data` 객체의 필드._ | secret_mode | string | `disabled` | 비밀글 설정 (disabled: 사용안함, enabled: 사용함, always: 고정) | | use_comment | boolean | `true` | 댓글 기능 사용 | | use_reply | boolean | `true` | 게시글 답변 기능 사용 (댓글에 대한 답글 아님) | -| max_reply_depth | integer | `5` | 답변글 최대 깊이 (1~5) | +| max_reply_depth | integer | `5` | 답변글 최대 깊이 (1~10) | | use_report | boolean | `true` | 게시글/댓글 신고 기능 사용 | | comment_order | string | `ASC` | 댓글 정렬 순서 (ASC: 오름차순, DESC: 내림차순) | | max_comment_depth | integer | `10` | 대댓글 최대 깊이 (1~10) | @@ -972,7 +972,7 @@ _단건 응답: `data` 객체의 필드._ | secret_mode | string | `disabled` | 비밀글 설정 (disabled: 사용안함, enabled: 사용함, always: 고정) | | use_comment | boolean | `true` | 댓글 기능 사용 | | use_reply | boolean | `true` | 게시글 답변 기능 사용 (댓글에 대한 답글 아님) | -| max_reply_depth | integer | `5` | 답변글 최대 깊이 (1~5) | +| max_reply_depth | integer | `5` | 답변글 최대 깊이 (1~10) | | use_report | boolean | `true` | 게시글/댓글 신고 기능 사용 | | comment_order | string | `ASC` | 댓글 정렬 순서 (ASC: 오름차순, DESC: 내림차순) | | max_comment_depth | integer | `10` | 대댓글 최대 깊이 (1~10) | @@ -1979,7 +1979,7 @@ _단건 응답: `data` 객체의 필드._ | secret_mode | string | `disabled` | 비밀글 설정 (disabled: 사용안함, enabled: 사용함, always: 고정) | | use_comment | boolean | `true` | 댓글 기능 사용 | | use_reply | boolean | `true` | 게시글 답변 기능 사용 (댓글에 대한 답글 아님) | -| max_reply_depth | integer | `5` | 답변글 최대 깊이 (1~5) | +| max_reply_depth | integer | `5` | 답변글 최대 깊이 (1~10) | | use_report | boolean | `true` | 게시글/댓글 신고 기능 사용 | | comment_order | string | `ASC` | 댓글 정렬 순서 (ASC: 오름차순, DESC: 내림차순) | | max_comment_depth | integer | `10` | 대댓글 최대 깊이 (1~10) | diff --git a/modules/_bundled/sirsoft-board/module.php b/modules/_bundled/sirsoft-board/module.php index 22fd34a3..bd478cd0 100644 --- a/modules/_bundled/sirsoft-board/module.php +++ b/modules/_bundled/sirsoft-board/module.php @@ -880,6 +880,26 @@ class Module extends AbstractModule 'seed_overrides' => ['board_id' => 1, 'is_notice' => 0, 'parent_id' => null], 'soft_delete' => true, ], + 'board_posts_by_view_count' => [ + 'type' => 'list', + 'label' => '게시글 목록 (조회순)', + 'table' => 'board_posts', + 'columns' => [ + 'id', 'board_id', 'user_id', 'parent_id', 'category', + 'title', 'author_name', 'content_mode', + 'is_notice', 'is_secret', 'status', 'depth', + 'view_count', 'comments_count', 'replies_count', 'attachments_count', + 'trigger_type', 'ip_address', 'created_at', 'updated_at', 'deleted_at', + ], + // 조회수 정렬은 화면에서 실제로 도달 가능한 경로다 — 게시판 설정 + // `order_by='view_count'` 와 목록 URL `?sort_by=view_count` 둘 다 있고, + // 저장소 정렬 화이트리스트에도 들어 있다. 작성일 정렬과 같은 술어에 + // 정렬 축만 다르므로 별도 프로파일로 재야 인덱스 커버리지가 판정된다. + 'order' => [['view_count', 'desc'], ['id', 'desc']], + 'filters' => ['board_id' => 1, 'is_notice' => 0, 'parent_id' => null], + 'seed_overrides' => ['board_id' => 1, 'is_notice' => 0, 'parent_id' => null], + 'soft_delete' => true, + ], // 댓글은 계측 프로파일을 두지 않는다. 페이지네이션되는 댓글 목록은 회원 본인 댓글 // 목록뿐이고(CommentRepository), 그 쿼리에는 회원 스코프 · 삭제 게시글 제외 // (whereExists 서브쿼리) · 비활성 게시판 제외가 무조건 붙는다. 선언형 필터로 diff --git a/modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-board-post-form-attachments-desc.test.tsx b/modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-board-post-form-attachments-desc.test.tsx new file mode 100644 index 00000000..99f83fa4 --- /dev/null +++ b/modules/_bundled/sirsoft-board/resources/js/__tests__/layouts/admin-board-post-form-attachments-desc.test.tsx @@ -0,0 +1,142 @@ +/** + * @file admin-board-post-form-attachments-desc.test.tsx + * @description 관리자 게시글 폼 첨부 안내가 게시판 설정값으로 렌더되는지 검증 (공개 #81 L-01) + * + * 결함: 관리자 게시글 폼의 첨부 영역에는 안내 문구가 아예 없었고, 대신 사장된 lang 키 + * ("최대 5개 파일, 각 10MB 이하")가 남아 있었다. 그 문구는 어디에도 렌더되지 않는데, + * 설령 렌더되었어도 게시판마다 다른 실제 제한과 무관한 고정 숫자였다. + * + * 운영자는 게시판 설정에서 첨부 개수·용량을 바꿀 수 있으므로, 안내는 반드시 + * `form_meta.data.board.max_file_count/max_file_size` 를 파라미터로 받아야 한다. + * 유저 폼(`_post_form.json` 의 `board.form.attachments_desc`)이 이미 그 형태다. + * + * @scenario surface=admin_post_form, source=board_settings + * @effects admin_attachment_hint_renders_board_limits + * + * @vitest-environment jsdom + */ + +import { describe, it, expect, afterEach } from 'vitest'; + +import { + createLayoutTest, + createMockComponentRegistryWithBasics, + screen, +} from '@core/template-engine/__tests__/utils/layoutTestUtils'; + +import attachmentsPartial from '../../../layouts/admin/partials/admin_board_post_form/_attachments.json'; +import koPosts from '../../../lang/partial/ko/admin/posts.json'; + +/** 안내 노드 id (레이아웃 JSON) */ +const DESC_ID = 'attachments_desc'; + +/** + * partial 트리에서 id 로 노드를 찾습니다. + * + * @param node 순회 시작 노드 + * @param id 찾을 노드 id + * @returns 찾은 노드 (없으면 null) + */ +function findById(node: any, id: string): any | null { + if (!node || typeof node !== 'object') return null; + if (node.id === id) return node; + for (const child of node.children ?? []) { + const found = findById(child, id); + if (found) return found; + } + return null; +} + +describe('관리자 첨부 안내 — 선언 (#81 L-01)', () => { + it('안내 노드가 존재하고 게시판 설정값을 파라미터로 넘긴다', () => { + const node = findById(attachmentsPartial, DESC_ID); + + expect(node, '첨부 안내 노드가 없다').not.toBeNull(); + expect(node.text).toContain('$t:sirsoft-board.admin.posts.form.attachments_desc'); + expect(node.text).toContain('maxFiles={{form_meta?.data?.board?.max_file_count'); + expect(node.text).toContain('maxSize={{form_meta?.data?.board?.max_file_size'); + }); + + it('다크 모드 variant 를 함께 지정한다', () => { + const node = findById(attachmentsPartial, DESC_ID); + + expect(node.props.className).toMatch(/text-gray-\d+/); + expect(node.props.className).toMatch(/dark:text-gray-\d+/); + }); + + it('lang 키가 ko 에 정의되어 있고 파라미터를 포함한다', () => { + const value = (koPosts as any).form?.attachments_desc; + + expect(value, 'attachments_desc 키가 없다').toBeTruthy(); + expect(value).toContain('{{maxFiles}}'); + expect(value).toContain('{{maxSize}}'); + }); + + it('사장된 고정 숫자 안내 키가 남아 있지 않다', () => { + expect((koPosts as any).form?.attachments_limit).toBeUndefined(); + expect((koPosts as any).form?.max_10mb).toBeUndefined(); + }); +}); + +describe('관리자 첨부 안내 — 렌더 결과 (#81 L-01)', () => { + afterEach(() => { + window.history.replaceState({}, '', '/'); + }); + + /** + * 안내 노드만 떼어내 게시판 설정값과 함께 렌더합니다. + * + * FileUploader 는 composite 라 mock 레지스트리에 없으므로, 검증 대상인 안내 노드만 + * 실제 레이아웃 JSON 에서 가져와 렌더한다 (문구 자체는 실 JSON 선언 그대로다). + * + * @param board 게시판 설정 (max_file_count / max_file_size) + * @returns 렌더 유틸 + */ + async function renderDesc(board: { max_file_count: number; max_file_size: number }) { + const node = findById(attachmentsPartial, DESC_ID); + + const utils = createLayoutTest( + { + version: '1.0.0', + layout_name: 'admin_attachments_desc_probe', + data_sources: [], + components: [{ ...node, props: { ...node.props, 'data-testid': DESC_ID } }], + } as never, + { + componentRegistry: createMockComponentRegistryWithBasics() as never, + locale: 'ko', + templateId: 'test-template', + translations: { + 'sirsoft-board': { admin: { posts: { form: { attachments_desc: (koPosts as any).form.attachments_desc } } } }, + }, + initialData: { form_meta: { data: { board } } }, + } + ); + + await utils.render(); + + return utils; + } + + it('게시판이 3개·50MB 로 설정되어 있으면 그 값이 안내에 나온다', async () => { + const utils = await renderDesc({ max_file_count: 3, max_file_size: 50 }); + + // 존재를 먼저 확정한 뒤에야 문구를 단언한다 (부재 단언은 렌더 전에도 통과한다) + const el = await screen.findByTestId(DESC_ID); + expect(document.body.contains(el)).toBe(true); + expect(el.textContent).toBe('최대 3개, 각 50MB 이하'); + + utils.cleanup(); + }); + + it('게시판 설정이 바뀌면 안내도 따라 바뀐다 (고정 문구가 아니다)', async () => { + const utils = await renderDesc({ max_file_count: 10, max_file_size: 2 }); + + const el = await screen.findByTestId(DESC_ID); + expect(el.textContent).toBe('최대 10개, 각 2MB 이하'); + // 종전 사장 키의 고정 숫자가 다시 새어 나오지 않는다 + expect(el.textContent).not.toContain('5개'); + + utils.cleanup(); + }); +}); diff --git a/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin.json b/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin.json index 3d20bea6..1fa0071b 100644 --- a/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin.json +++ b/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin.json @@ -716,12 +716,11 @@ "html_preview_warning": "HTML Rendering Warning", "no_content_preview": "Preview will appear when you enter content", "attachments": "Attachments", + "attachments_desc": "Max {{maxFiles}} files, {{maxSize}}MB each", "attached_files": "Attached Files", "confirm_remove_attachment_title": "Delete Attachment", "confirm_remove_attachment_message": "The file will be deleted immediately. This action cannot be undone regardless of saving the post.", - "attachments_limit": "Max 5 files, 10MB each (jpg, jpeg, png, gif, pdf, zip)", "drop_files_or_click": "Click to upload or drag and drop", - "max_10mb": "Max 10MB", "file_upload_component_needed": "FileUpload component needed", "uploading": "Uploading...", "reply_to": "Reply to the following post", @@ -902,7 +901,6 @@ "max_content_length": "Maximum Content Length", "use_reply": "Enable Reply Posts", "max_reply_depth": "Max Reply Depth", - "max_reply_depth_hint": "Enter a value between 1 and 5", "use_comment": "Enable Comments", "comment_order": "Comment Sort Order", "min_comment_length": "Min Comment Length", @@ -974,7 +972,6 @@ "min_content_length": "Set the minimum character count for post content", "max_content_length": "Set the maximum character count for post content", "use_reply": "Must be ON to apply reply post feature to new boards.", - "max_reply_depth": "Set the maximum nesting depth for replies (1-5)", "blocked_keywords": "Posts or comments containing registered keywords will be blocked", "use_comment": "Must be ON to apply comment feature to new boards. Comment detail settings below will also apply.", "comment_order": "Set the default sort direction for comments", diff --git a/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin/posts.json b/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin/posts.json index 184140fc..9d09f362 100644 --- a/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin/posts.json +++ b/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin/posts.json @@ -173,12 +173,11 @@ "html_preview_warning": "HTML Rendering Warning", "no_content_preview": "Preview will appear when you enter content", "attachments": "Attachments", + "attachments_desc": "Max {{maxFiles}} files, {{maxSize}}MB each", "attached_files": "Attached Files", "confirm_remove_attachment_title": "Delete Attachment", "confirm_remove_attachment_message": "The file will be deleted immediately. This action cannot be undone regardless of saving the post.", - "attachments_limit": "Max 5 files, 10MB each (jpg, jpeg, png, gif, pdf, zip)", "drop_files_or_click": "Click to upload or drag and drop", - "max_10mb": "Max 10MB", "file_upload_component_needed": "FileUpload component needed", "uploading": "Uploading...", "reply_to": "Reply to the following post", diff --git a/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin/settings.json b/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin/settings.json index c1d23d1c..c29062c4 100644 --- a/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin/settings.json +++ b/modules/_bundled/sirsoft-board/resources/lang/partial/en/admin/settings.json @@ -78,7 +78,6 @@ "max_content_length": "Maximum Content Length", "use_reply": "Enable Reply Posts", "max_reply_depth": "Max Reply Depth", - "max_reply_depth_hint": "Enter a value between 1 and 5", "use_comment": "Enable Comments", "comment_order": "Comment Sort Order", "min_comment_length": "Min Comment Length", diff --git a/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin.json b/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin.json index 21135a08..7ae527d5 100644 --- a/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin.json +++ b/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin.json @@ -717,12 +717,11 @@ "html_preview_warning": "HTML 렌더링 주의", "no_content_preview": "내용을 입력하면 미리보기가 표시됩니다", "attachments": "첨부파일", + "attachments_desc": "최대 {{maxFiles}}개, 각 {{maxSize}}MB 이하", "attached_files": "첨부된 파일", "confirm_remove_attachment_title": "첨부파일 삭제", "confirm_remove_attachment_message": "파일이 즉시 삭제됩니다. 게시글 저장과 관계없이 되돌릴 수 없습니다.", - "attachments_limit": "최대 5개 파일, 각 10MB 이하 (jpg, jpeg, png, gif, pdf, zip)", "drop_files_or_click": "클릭하여 업로드 또는 드래그 앤 드롭", - "max_10mb": "최대 10MB", "file_upload_component_needed": "FileUpload 컴포넌트 개발 필요", "uploading": "업로드 중...", "reply_to": "다음 글에 대한 답변입니다", @@ -902,7 +901,6 @@ "max_content_length": "최대 게시글 글자 수", "use_reply": "답변글 사용", "max_reply_depth": "답변글 최대 깊이", - "max_reply_depth_hint": "1~5 사이의 값을 입력하세요", "use_comment": "댓글 사용", "comment_order": "댓글 정렬 순서", "min_comment_length": "최소 댓글 글자 수", @@ -974,7 +972,6 @@ "min_content_length": "게시글 본문의 최소 글자 수를 설정합니다", "max_content_length": "게시글 본문의 최대 글자 수를 설정합니다", "use_reply": "ON으로 설정해야 새 게시판에 답변글 기능이 적용됩니다.", - "max_reply_depth": "답변글의 최대 중첩 깊이를 설정합니다 (1~5)", "blocked_keywords": "등록된 키워드가 포함된 게시글/댓글은 작성이 차단됩니다", "use_comment": "ON으로 설정해야 새 게시판에 댓글 기능이 적용됩니다. 아래 댓글 세부 설정도 함께 적용됩니다.", "comment_order": "댓글의 기본 정렬 방향을 설정합니다", diff --git a/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin/posts.json b/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin/posts.json index e27da1f1..1e2c1dc1 100644 --- a/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin/posts.json +++ b/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin/posts.json @@ -174,12 +174,11 @@ "html_preview_warning": "HTML 렌더링 주의", "no_content_preview": "내용을 입력하면 미리보기가 표시됩니다", "attachments": "첨부파일", + "attachments_desc": "최대 {{maxFiles}}개, 각 {{maxSize}}MB 이하", "attached_files": "첨부된 파일", "confirm_remove_attachment_title": "첨부파일 삭제", "confirm_remove_attachment_message": "파일이 즉시 삭제됩니다. 게시글 저장과 관계없이 되돌릴 수 없습니다.", - "attachments_limit": "최대 5개 파일, 각 10MB 이하 (jpg, jpeg, png, gif, pdf, zip)", "drop_files_or_click": "클릭하여 업로드 또는 드래그 앤 드롭", - "max_10mb": "최대 10MB", "file_upload_component_needed": "FileUpload 컴포넌트 개발 필요", "uploading": "업로드 중...", "reply_to": "다음 글에 대한 답변입니다", diff --git a/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin/settings.json b/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin/settings.json index 4821f2b8..473ef297 100644 --- a/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin/settings.json +++ b/modules/_bundled/sirsoft-board/resources/lang/partial/ko/admin/settings.json @@ -78,7 +78,6 @@ "max_content_length": "최대 게시글 글자 수", "use_reply": "답변글 사용", "max_reply_depth": "답변글 최대 깊이", - "max_reply_depth_hint": "1~5 사이의 값을 입력하세요", "use_comment": "댓글 사용", "comment_order": "댓글 정렬 순서", "min_comment_length": "최소 댓글 글자 수", diff --git a/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_form/_attachments.json b/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_form/_attachments.json index ec77486a..66b5b4a2 100644 --- a/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_form/_attachments.json +++ b/modules/_bundled/sirsoft-board/resources/layouts/admin/partials/admin_board_post_form/_attachments.json @@ -47,6 +47,15 @@ "type": "basic", "name": "Div", "children": [ + { + "id": "attachments_desc", + "type": "basic", + "name": "P", + "props": { + "className": "text-xs text-gray-500 dark:text-gray-400 mb-2" + }, + "text": "$t:sirsoft-board.admin.posts.form.attachments_desc|maxFiles={{form_meta?.data?.board?.max_file_count ?? 5}}|maxSize={{form_meta?.data?.board?.max_file_size ?? 10}}" + }, { "type": "composite", "name": "FileUploader", diff --git a/modules/_bundled/sirsoft-board/src/Repositories/PostRepository.php b/modules/_bundled/sirsoft-board/src/Repositories/PostRepository.php index 58b4b0b3..83614e87 100644 --- a/modules/_bundled/sirsoft-board/src/Repositories/PostRepository.php +++ b/modules/_bundled/sirsoft-board/src/Repositories/PostRepository.php @@ -803,6 +803,16 @@ class PostRepository implements PostRepositoryInterface $noticeQuery->with($relations); } + // 공지는 운영자가 등록하는 데이터라 통상 소수지만, 개수를 막는 장치가 없으면 + // 잘못 늘어난 게시판에서 한 페이지를 여는 것만으로 전량이 메모리에 올라온다. + // `created_at desc` 정렬이므로 상한에 걸릴 때 최신 공지가 우선 보존된다 — + // 잘린 공지는 후속 페이지에 노출될 경로가 없어 이 순서가 유일한 안전판이다. + // 조정은 코어 필터 훅 `core.pagination.filter_result_cap` (context: board.notices). + $noticeCap = PaginationLimits::resultCap('board.notices'); + if ($noticeCap !== null) { + $noticeQuery->limit($noticeCap); + } + $notices = $noticeQuery->get($columns); } diff --git a/modules/_bundled/sirsoft-board/tests/Feature/NoticeResultCapTest.php b/modules/_bundled/sirsoft-board/tests/Feature/NoticeResultCapTest.php new file mode 100644 index 00000000..043d94ee --- /dev/null +++ b/modules/_bundled/sirsoft-board/tests/Feature/NoticeResultCapTest.php @@ -0,0 +1,175 @@ +capFilter !== null) { + HookManager::removeFilter('core.pagination.filter_result_cap', $this->capFilter); + $this->capFilter = null; + } + + parent::tearDown(); + } + + /** + * 공지 컨텍스트에만 적용되는 상한 필터를 등록합니다. + * + * 다른 컨텍스트(예: 답글 트리)는 원값을 그대로 통과시켜, 상한이 컨텍스트별로 + * 분리되어 해석되는지도 함께 확인한다. + * + * @param int $cap 공지 컨텍스트에 적용할 상한 + */ + private function capNoticesAt(int $cap): void + { + $this->capFilter = function ($value, $context = null) use ($cap) { + return $context === self::CONTEXT ? $cap : $value; + }; + + HookManager::addFilter('core.pagination.filter_result_cap', $this->capFilter, priority: 1); + } + + /** + * 게시글을 생성합니다. + * + * @param string $title 제목 + * @param bool $isNotice 공지 여부 + * @param int $minutesAgo 작성 시각 (분 단위 과거) + */ + private function makePost(string $title, bool $isNotice, int $minutesAgo): Post + { + $post = Post::create([ + 'board_id' => $this->board->id, + 'user_id' => null, + 'parent_id' => null, + 'title' => $title, + 'content' => $title.' 본문', + 'author_name' => '작성자', + 'is_notice' => $isNotice, + 'status' => 'published', + 'depth' => 0, + 'ip_address' => '127.0.0.1', + ]); + + // created_at 은 $fillable 이 아니라 create() 로는 들어가지 않는다. + // 전부 같은 초로 저장되면 정렬 축이 사라져 "최신 우선 보존" 을 검증할 수 없다. + $post->forceFill([ + 'created_at' => now()->subMinutes($minutesAgo), + 'updated_at' => now()->subMinutes($minutesAgo), + ])->saveQuietly(); + + return $post; + } + + public function test_공지_조회가_설정된_안전상한을_넘지_않는다(): void + { + // 공지 5건 (오래된 것부터 1..5 — 5번이 가장 최신) + for ($i = 1; $i <= 5; $i++) { + $this->makePost("공지 {$i}", true, 100 - $i); + } + + $this->capNoticesAt(3); + + $result = app(PostRepository::class)->paginate($this->board->slug, ['page' => 1], 15, false, $this->board); + $notices = collect($result->items())->filter(fn ($p) => (bool) $p->is_notice); + + $this->assertCount(3, $notices, '공지 상한이 조회에 반영되지 않았다'); + } + + public function test_상한에_걸리면_최신_공지가_남는다(): void + { + for ($i = 1; $i <= 5; $i++) { + $this->makePost("공지 {$i}", true, 100 - $i); + } + + $this->capNoticesAt(2); + + $result = app(PostRepository::class)->paginate($this->board->slug, ['page' => 1], 15, false, $this->board); + $titles = collect($result->items()) + ->filter(fn ($p) => (bool) $p->is_notice) + ->pluck('title') + ->values() + ->all(); + + // created_at desc 정렬이므로 최신 2건(공지 5, 공지 4)이 남는다. + // 잘린 공지는 후속 페이지에 노출될 경로가 없으므로 최신 우선 보존이 유일한 안전판이다. + $this->assertSame(['공지 5', '공지 4'], $titles); + } + + public function test_공지_상한이_일반_게시글_목록과_총건수를_바꾸지_않는다(): void + { + for ($i = 1; $i <= 5; $i++) { + $this->makePost("공지 {$i}", true, 100 - $i); + } + for ($i = 1; $i <= 4; $i++) { + $this->makePost("일반글 {$i}", false, 50 - $i); + } + + $repository = app(PostRepository::class); + + $uncapped = $repository->paginate($this->board->slug, ['page' => 1], 15, false, $this->board); + $normalBefore = collect($uncapped->items())->reject(fn ($p) => (bool) $p->is_notice)->pluck('title')->values()->all(); + $totalBefore = $repository->countNormalPosts($this->board->slug); + + $this->capNoticesAt(2); + + $capped = $repository->paginate($this->board->slug, ['page' => 1], 15, false, $this->board); + $normalAfter = collect($capped->items())->reject(fn ($p) => (bool) $p->is_notice)->pluck('title')->values()->all(); + $totalAfter = $repository->countNormalPosts($this->board->slug); + + $this->assertSame($normalBefore, $normalAfter, '공지 상한이 일반 게시글 목록을 바꿨다'); + $this->assertCount(4, $normalAfter); + + // 화면이 보여주는 총 건수는 이 목록과 별개 술어(countNormalPosts)로 세어진다. + // 공지 상한이 그 경로까지 새면 페이저 끝이 줄어 뒤쪽 게시글에 도달할 수 없게 된다. + // 잘린 값과 정확한 값을 구분해야 하므로 건수뿐 아니라 정확도까지 비교한다. + $this->assertSame($totalBefore->total(), $totalAfter->total(), '공지 상한이 목록 총 건수를 바꿨다'); + $this->assertSame($totalBefore->totalRelation(), $totalAfter->totalRelation(), '공지 상한이 총 건수의 정확도를 바꿨다'); + + // 다음 페이지 존재 여부도 공지 상한과 무관해야 한다 (per_page + 1 실측 경로). + $this->assertSame($uncapped->hasMorePages(), $capped->hasMorePages(), '공지 상한이 페이지 이동 범위를 바꿨다'); + } + + public function test_다른_컨텍스트는_자기_상한을_유지한다(): void + { + $this->capNoticesAt(2); + + $this->assertSame(2, PaginationLimits::resultCap(self::CONTEXT)); + $this->assertNotSame(2, PaginationLimits::resultCap('board.reply_tree')); + } +} diff --git a/modules/_bundled/sirsoft-board/tests/Feature/Upgrade/PostListViewCountIndexUpgradeTest.php b/modules/_bundled/sirsoft-board/tests/Feature/Upgrade/PostListViewCountIndexUpgradeTest.php new file mode 100644 index 00000000..3874dd2f --- /dev/null +++ b/modules/_bundled/sirsoft-board/tests/Feature/Upgrade/PostListViewCountIndexUpgradeTest.php @@ -0,0 +1,151 @@ + $slug, + 'name' => ['ko' => '조회수 색인 게시판', 'en' => 'View Count Index Board'], + 'is_active' => true, + ]; + } + + /** + * 색인이 없는 기설치본에서 업그레이드 스텝이 색인을 만든다 + * + * @scenario case=post_list_view_count_index_upgrade + * + * @effects view_count_list_index_created_on_existing_site + */ + public function test_색인이_없으면_업그레이드_스텝이_생성한다(): void + { + $this->dropIndexIfExists(); + $this->assertFalse($this->hasIndex(self::INDEX_NAME), '사전 조건: 색인이 없어야 한다'); + + $this->runUpgrade(); + + $this->assertTrue( + $this->hasIndex(self::INDEX_NAME), + '업그레이드 스텝이 조회수 정렬 색인을 만들어야 한다' + ); + } + + /** + * 재실행해도 예외 없이 결과가 같다 (멱등) + * + * @scenario case=post_list_view_count_index_upgrade + * + * @effects view_count_list_index_upgrade_is_idempotent + */ + public function test_이미_있으면_재실행해도_결과가_같다(): void + { + $this->dropIndexIfExists(); + $this->runUpgrade(); + $this->assertTrue($this->hasIndex(self::INDEX_NAME)); + + // 색인이 이미 있는 상태에서 한 번 더 — 중복 생성 예외가 나면 실패한다. + $this->runUpgrade(); + + $this->assertTrue( + $this->hasIndex(self::INDEX_NAME), + '재실행 후에도 색인이 그대로 있어야 한다' + ); + } + + /** + * 인기글 조회가 쓰는 기존 색인을 건드리지 않는다 + * + * @scenario case=post_list_view_count_index_upgrade + * + * @effects legacy_popular_posts_index_preserved + */ + public function test_기존_인기글_색인을_보존한다(): void + { + $legacyBefore = $this->hasIndex(self::LEGACY_INDEX_NAME); + + $this->dropIndexIfExists(); + $this->runUpgrade(); + + $this->assertSame( + $legacyBefore, + $this->hasIndex(self::LEGACY_INDEX_NAME), + '조회수 목록 색인 추가가 인기글 색인의 존재 여부를 바꾸면 안 된다' + ); + } + + /** + * 1.0.3 업그레이드 스텝을 실행합니다. + */ + private function runUpgrade(): void + { + $context = new UpgradeContext('1.0.2', '1.0.3', '1.0.3', 'extension-upgrade'); + + (new Upgrade_1_0_3)->run($context); + } + + /** + * 대상 색인이 존재하면 제거합니다 (기설치본 모사). + */ + private function dropIndexIfExists(): void + { + if (! $this->hasIndex(self::INDEX_NAME)) { + return; + } + + Schema::table(self::TABLE, function ($table) { + $table->dropIndex(self::INDEX_NAME); + }); + } + + /** + * 색인 존재 여부를 조회합니다. + * + * @param string $name 색인 이름 + * @return bool 존재 여부 + */ + private function hasIndex(string $name): bool + { + if (! Schema::hasTable(self::TABLE)) { + return false; + } + + return in_array($name, array_column(Schema::getIndexes(self::TABLE), 'name'), true); + } +} diff --git a/modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-post-form-attachments-desc.spec.ts b/modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-post-form-attachments-desc.spec.ts new file mode 100644 index 00000000..b3698310 --- /dev/null +++ b/modules/_bundled/sirsoft-board/tests/Playwright/specs/admin/board-post-form-attachments-desc.spec.ts @@ -0,0 +1,61 @@ +/** + * 관리자 게시글 폼 — 첨부 안내가 게시판 설정값으로 렌더 (공개 #81 L-01). + * + * 관리자 게시글 폼의 첨부 영역에는 안내 문구가 없었고, 대신 사장된 lang 키 + * ("최대 5개 파일, 각 10MB 이하")만 남아 있었다. 그 문구는 어디에도 렌더되지 않는데 + * 설령 렌더되었어도 게시판마다 다른 실제 제한과 무관한 고정 숫자였다. + * + * 안내는 `form_meta.data.board.max_file_count/max_file_size` 를 파라미터로 받아야 한다. + * 단위(Vitest admin-board-post-form-attachments-desc) 는 안내 노드만 떼어 렌더하므로, + * 실제 폼에서 form_meta 데이터소스가 도착한 뒤의 치환 결과는 브라우저로만 확인 가능하다 + * (위지윅 발행 회귀 #238 교훈). + * + * @scenario board-post-form-attachments-desc + * @effects admin_attachment_hint_renders_board_limits, + * admin_attachment_hint_placeholders_not_raw + * + * 활성화 절차: PlaywrightIssueToken 발급이 가능한 환경에서 test.describe.skip → test.describe. + */ +import { test, expect, authenticatePage } from '../../fixtures/board-auth'; + +/** 첨부 기능이 켜진 게시판의 관리자 글쓰기 화면 */ +const WRITE_URL = '/admin/board/free/write'; + +test.describe.skip('관리자 게시글 폼 — 첨부 안내 (#81 L-01)', () => { + test('첨부 안내가 게시판 설정의 개수·용량으로 렌더된다', async ({ page, settingsToken }) => { + await authenticatePage(page, settingsToken); + await page.goto(WRITE_URL); + await page.waitForLoadState('domcontentloaded', { timeout: 30_000 }); + + // form_meta 도착 후 안내가 채워질 때까지 대기 — 숫자는 게시판 설정에서 온다 + const hint = page.getByText(/^최대 \d+개, 각 \d+MB 이하$/); + await expect(hint).toBeVisible({ timeout: 10_000 }); + }); + + test('raw 플레이스홀더({{maxFiles}}/{{maxSize}})가 노출되지 않는다', async ({ + page, + settingsToken, + }) => { + await authenticatePage(page, settingsToken); + await page.goto(WRITE_URL); + await page.waitForLoadState('domcontentloaded', { timeout: 30_000 }); + + await expect(page.getByText(/^최대 \d+개, 각 \d+MB 이하$/)).toBeVisible({ timeout: 10_000 }); + + await expect(page.getByText('{{maxFiles}}', { exact: false })).toHaveCount(0); + await expect(page.getByText('{{maxSize}}', { exact: false })).toHaveCount(0); + }); + + test('사장된 고정 숫자 안내가 다시 나타나지 않는다', async ({ page, settingsToken }) => { + await authenticatePage(page, settingsToken); + await page.goto(WRITE_URL); + await page.waitForLoadState('domcontentloaded', { timeout: 30_000 }); + + await expect(page.getByText(/^최대 \d+개, 각 \d+MB 이하$/)).toBeVisible({ timeout: 10_000 }); + + // 종전 사장 키의 고정 문구 (jpg, jpeg, ... 확장자 나열 포함) 는 제거되었다 + await expect( + page.getByText('최대 5개 파일, 각 10MB 이하', { exact: false }), + ).toHaveCount(0); + }); +}); diff --git a/modules/_bundled/sirsoft-board/upgrades/data/1.0.3/migrations/06_AddPostListViewCountIndex.php b/modules/_bundled/sirsoft-board/upgrades/data/1.0.3/migrations/06_AddPostListViewCountIndex.php new file mode 100644 index 00000000..170930fa --- /dev/null +++ b/modules/_bundled/sirsoft-board/upgrades/data/1.0.3/migrations/06_AddPostListViewCountIndex.php @@ -0,0 +1,74 @@ + */ + private const INDEX_COLUMNS = ['board_id', 'is_notice', 'parent_id', 'deleted_at', 'view_count', 'id']; + + /** + * 마이그레이션 식별자를 반환합니다. + * + * @return string 마이그레이션 이름 + */ + public function name(): string + { + return 'AddPostListViewCountIndex'; + } + + /** + * 게시글 목록 조회수 정렬 색인을 추가합니다. + * + * @param UpgradeContext $context 업그레이드 컨텍스트 + */ + public function run(UpgradeContext $context): void + { + if (! Schema::hasTable(self::TABLE)) { + $context->logger->info('[board:1.0.3] 게시글 테이블 부재 — 조회수 정렬 색인 추가 스킵'); + + return; + } + + $existing = array_column(Schema::getIndexes(self::TABLE), 'name'); + + if (in_array(self::INDEX_NAME, $existing, true)) { + $context->logger->info('[board:1.0.3] 이미 존재하는 색인 — 스킵: '.self::INDEX_NAME); + + return; + } + + $context->logger->info('[board:1.0.3] 게시글 목록 조회수 정렬 색인 추가 시작 (게시글이 많으면 수 분 걸릴 수 있고 그동안 글쓰기가 대기합니다)'); + + Schema::table(self::TABLE, function ($table) { + $table->index(self::INDEX_COLUMNS, self::INDEX_NAME); + }); + + $context->logger->info('[board:1.0.3] 게시글 목록 조회수 정렬 색인 추가 완료: '.self::INDEX_NAME); + } +} diff --git a/modules/_bundled/sirsoft-ecommerce/CHANGELOG.md b/modules/_bundled/sirsoft-ecommerce/CHANGELOG.md index 8b85c83f..8d2909a5 100644 --- a/modules/_bundled/sirsoft-ecommerce/CHANGELOG.md +++ b/modules/_bundled/sirsoft-ecommerce/CHANGELOG.md @@ -98,6 +98,9 @@ ### Fixed +- 쇼핑몰 주소를 기본값이 아닌 값으로 바꾸거나 주소 없이 운영하는 상점에서, 서버가 만들어 보내는 상점 주소가 기본 주소로 잘못 만들어지던 문제를 수정했습니다. 주문 완료 후 이동, 비회원 주문 조회 안내, 알림 메일의 주문 조회 주소, 통합검색·상품문의 목록의 상품 링크, 검색엔진용 주소(사이트맵·봇 화면 캐시)가 모두 해당됐습니다. 링크가 만들어지기는 해서 오류로 드러나지 않고 없는 페이지로만 이어졌습니다. 기본 주소를 쓰는 상점은 이전과 동일합니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) +- 쇼핑몰 주소를 바꾸거나 주소 없이 운영하는 상점에서 화면 편집기의 상품·장바구니·주문서 등 상점 화면을 편집할 때 상태 미리보기 전환(품절/재고 있음 등)이 표시되지 않던 문제를 수정했습니다. 편집기가 기본 주소인 상점만 알아보던 탓이며, 이제 어떤 주소로 바꾸어도 — 주소 없이 운영하는 상점까지 — 동일하게 표시됩니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) +- 상품 상세 화면에서만 상태 미리보기 전환(재고 있음/품절/판매중지/판매예정)이 어떤 쇼핑몰 주소에서도 표시되지 않던 문제를 수정했습니다. 편집기가 찾는 화면 주소와 실제 상품 상세 주소의 표기가 서로 달라 끝내 연결되지 않았습니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) - "최근 본 상품" 과 찜 목록의 상품 카드가 리뷰가 달린 상품도 별점 0 개 · 리뷰 0건으로 표시하던 문제를 수정했습니다. 두 조회만 리뷰를 세지 않아 값이 비어 있었고, 빈 값이 0 으로 표기되어 실제 평점과 다르게 보였습니다. 이제 다른 상품 목록과 동일하게 실제 평점·리뷰 수가 표시됩니다. - 리뷰를 세지 않는 조회 경로(관리자 상품 목록 등)에서는 평점·리뷰 수 항목을 아예 싣지 않도록 바꿨습니다. 종전에는 세지 않았을 뿐인데 0 이 실려 "리뷰 없음" 과 구분되지 않았습니다. 리뷰가 실제로 0건이면 종전대로 0 으로 표시됩니다. - 모바일·태블릿 화면에서 쿠폰 목록의 카드 보기가 내용 없이 나오던 문제를 수정했습니다. 목록의 각 쿠폰 정보가 카드에 전달되지 않아, 쿠폰이 있어도 빈 카드만 표시됐습니다. diff --git a/modules/_bundled/sirsoft-ecommerce/docs/api/orders.md b/modules/_bundled/sirsoft-ecommerce/docs/api/orders.md index 327f6884..b7ed4b81 100644 --- a/modules/_bundled/sirsoft-ecommerce/docs/api/orders.md +++ b/modules/_bundled/sirsoft-ecommerce/docs/api/orders.md @@ -1382,18 +1382,18 @@ _목록 응답: `data.data[]` 배열 항목의 필드._ | 필드 | 타입 | 실측 예시값 | 용도/설명 | | --- | --- | --- | --- | | id | integer | `27789` | 기본 키 (내부 식별자) | -| log_type | string | `admin` | | +| log_type | string | `admin` | 로그 분류 (`ActivityLogType` Enum 값 — 관리자/사용자/시스템 등 활동 주체 구분) | | log_type_label | string | `관리자` | `log_type` 값의 사람이 읽는 라벨 (현지화/Enum 파생) | -| loggable_type | string | `Modules\Sirsoft\Ecommerce\Models\Orde…` | | -| loggable_type_display | string | `OrderOption` | | +| loggable_type | string | `Modules\Sirsoft\Ecommerce\Models\Orde…` | 로그 대상 모델의 FQCN (다형 관계 타입 — 표시용 짧은 이름은 `loggable_type_display`) | +| loggable_type_display | string | `OrderOption` | `loggable_type` 의 표시용 짧은 이름 (네임스페이스를 제외한 클래스명) | | loggable_id | integer | `1264` | loggable 식별자 (연관 리소스 참조) | -| action | string | `order_option.partial_cancel` | | +| action | string | `order_option.partial_cancel` | 수행된 활동의 식별 키 (`{대상}.{행위}` 형식 — 라벨은 `action_label`) | | action_label | string | `부분 취소` | `action` 값의 사람이 읽는 라벨 (현지화/Enum 파생) | | localized_description | string | `주문 옵션 부분 취소 (옵션 ID: 1264)` | `description` 의 현재 로케일 해석 값 (다국어 필드를 표시용 문자열로 해석) | -| description_key | string | `sirsoft-ecommerce::activity_log.descr…` | | -| properties | object | `{"order_id":1316,"product_name":{"ko":"신제품 출시 예정 #21","en…` | | -| changes | null | `null` | | -| bulk_changes | null | `null` | | +| description_key | string | `sirsoft-ecommerce::activity_log.descr…` | 설명 문구의 다국어 키 (`localized_description` 은 이 키를 현재 로케일로 해석한 값) | +| properties | object | `{"order_id":1316,"product_name":{"ko":"신제품 출시 예정 #21","en…` | 활동 시점의 부가 정보 (설명 문구의 치환 파라미터 및 참조 식별자 — 활동 종류마다 키가 다름) | +| changes | null | `null` | 단건 수정의 변경 내역 `[{field, old, new}, …]`. 일괄 수정이거나 변경 추적 대상이 아니면 `null` | +| bulk_changes | null | `null` | 일괄 수정의 변경 내역 `[{model_id, changes[]}, …]`. 단건 수정이면 `null` (`changes` 와 동시에 채워지지 않음) | | has_changes | boolean | `false` | changes 여부 | | actor_name | string | `시스템` | 행위를 수행한 주체(사용자/시스템)의 이름 | | user | object | `{"name":"시스템"}` | 대상 사용자 정보 객체 (uuid/name/email 등 — user 관계 파생) | @@ -2073,7 +2073,7 @@ _단건 응답: `data` 객체의 필드 (HTTP 201). 회원은 `order` 에 `Order | 필드 | 타입 | 실측 예시값 | 용도/설명 | | --- | --- | --- | --- | | order | object | `{"id":181,"order_number":"20260711-0210001234", …}` | 생성된 주문 (회원: `OrderResource` / 비회원: `GuestOrderResource`) | -| redirect_url | string | `/shop/orders/20260711-0210001234/complete` | 주문완료 페이지 경로 (프론트가 이동할 URL) | +| redirect_url | string | `/shop/orders/20260711-0210001234/complete` | 주문완료 페이지 경로 (프론트가 이동할 URL). 앞의 상점 경로는 상점 주소 설정을 반영한다 — `basic_info.route_path` 를 바꾸면 그 값이(`/store/orders/…`), `basic_info.no_route` 를 켜면 세그먼트 없이(`/orders/…`) 내려간다 | | requires_pg_payment | boolean | `true` | PG 결제창 호출이 필요한지 여부 (무통장·전액 마일리지 등 non-PG 는 `false`) | | pg_provider | string | `sirsoft-tosspayments` | PG 플러그인 식별자 (`requires_pg_payment=true` 일 때만 포함) | | pg_payment_handler | string | `sirsoft-tosspayments.requestPayment` | 프론트가 dispatch 할 결제 진입 핸들러 풀네임 (provider 가 선언한 경우에만 포함) | @@ -3221,7 +3221,7 @@ HTTP/1.1 200 | 상태코드 | 의미 | 발생 조건 | | --- | --- | --- | -| 404 | Not Found | 주문이 없거나 접근 권한이 없는 경우 — 회원: 본인 주문 아님(`errors.redirect_to = /mypage/orders`), 비회원: `X-Guest-Order-Token` 부재·만료·위조(`errors.redirect_to = /shop/guest/orders`). 정보 노출 방지를 위해 모든 실패를 동일 404 로 처리 | +| 404 | Not Found | 주문이 없거나 접근 권한이 없는 경우 — 회원: 본인 주문 아님(`errors.redirect_to = /mypage/orders`), 비회원: `X-Guest-Order-Token` 부재·만료·위조(`errors.redirect_to = /shop/guest/orders` — 상점 주소 설정 `basic_info.route_path`/`no_route` 반영). 정보 노출 방지를 위해 모든 실패를 동일 404 로 처리 | diff --git a/modules/_bundled/sirsoft-ecommerce/editor-spec.json b/modules/_bundled/sirsoft-ecommerce/editor-spec.json index cad3f219..324b47d0 100644 --- a/modules/_bundled/sirsoft-ecommerce/editor-spec.json +++ b/modules/_bundled/sirsoft-ecommerce/editor-spec.json @@ -4729,13 +4729,13 @@ } }, "states": { - "comment": "이커머스 도메인 변종. 사용자 shop/* 라우트(템플릿 sirsoft-basic 소속이나 코어 concat 으로 일원화)와 관리자 라우트(*/admin/ecommerce/*) 변종을 모두 포함한다. shop/* scope.match 는 편집기가 동적 path 를 'shop' 으로 평가한 selectedRoute.path 와 일치한다(Chrome MCP 실측).", + "comment": "이커머스 도메인 변종. 사용자 상점 라우트(템플릿 sirsoft-basic 소속이나 코어 concat 으로 일원화)와 관리자 라우트(*/admin/ecommerce/*) 변종을 모두 포함한다. 상점 주소는 운영자 설정이라 편집기가 평가한 selectedRoute.path 의 첫 세그먼트가 사이트마다 다르다 — 기본 'shop', basic_info.route_path 로 바꾸면 그 값, basic_info.no_route 를 켜면 세그먼트가 아예 없다(`/products`). 그래서 scope.match 는 선택 세그먼트 토큰 '/*?'(0개 또는 1개, engine-v1.58.0)를 써 세 경우를 모두 매칭한다. '/*' 로 쓰면 no_route 상점에서만 매칭이 실패해 상태 토글이 조용히 사라진다. 파라미터 토큰(:id 등)은 리터럴로 대조되므로 routes.json 이 쓴 이름을 그대로 적어야 한다 — 이름이 다르면 세그먼트 토큰과 무관하게 세 축 모두에서 매칭되지 않는다.", "groups": [ { - "comment": "shop/show — product.data.sales_status 값(on_sale/sold_out/suspended/coming_soon)으로 판매 상태 배지·버튼을 if 분기한다(본문 line 388/406). 재고는 stock 으로 분기.", + "comment": "shop/show — product.data.sales_status 값(on_sale/sold_out/suspended/coming_soon)으로 판매 상태 배지·버튼을 if 분기한다(본문 line 388/406). 재고는 stock 으로 분기. 파라미터 토큰은 routes.json 의 ':product_code' 를 그대로 쓴다 — ':id' 로 적으면 리터럴 대조라 어떤 상점 주소에서도 매칭되지 않는다.", "scope": { "kind": "route", - "match": "/shop/products/:id" + "match": "/*?/products/:product_code" }, "items": [ { @@ -7099,7 +7099,7 @@ "comment": "shop/index — 목록 유무 + 접근 제한. _local.productAccessDenied=true 시 접근 제한 화면을 if 분기한다(본문 line 192).", "scope": { "kind": "route", - "match": "/shop/products" + "match": "/*?/products" }, "items": [ { @@ -7140,7 +7140,7 @@ "comment": "shop/cart — 담긴 상품 유무 + 주문 처리 중(_local.isOrdering 시 오버레이 잠금, 본문 line 115).", "scope": { "kind": "route", - "match": "/shop/cart" + "match": "/*?/cart" }, "items": [ { @@ -7222,7 +7222,7 @@ "comment": "shop/checkout — 정상/결제오류(_local.orderError·query.error, 본문 line 45/194)/구매불가(_local.unavailableModal, line 102)/입력검증실패 분기. 검증 실패는 주문자/배송지 입력칸별 인라인 에러를 _local.errors 의 점 포함 flat 키(예 'orderer.name')로 읽는다(_checkout_orderer.json line 99/101, _checkout_shipping.json) — formErrors 키를 대괄호 표기로 지정한다.", "scope": { "kind": "route", - "match": "/shop/checkout" + "match": "/*?/checkout" }, "items": [ { @@ -7291,7 +7291,7 @@ "comment": "shop/order_complete — orderData.data.payment.payment_method 값(card/vbank/dbank)으로 결제수단별 안내를 if 분기한다(본문 line 52/95/138/229). card 는 base sampleData(=card)가 흐르므로 오버라이드 없음, vbank/dbank 는 byDataSourceId.orderData 통째 교체.", "scope": { "kind": "route", - "match": "/shop/orders/:id/complete" + "match": "/*?/orders/:id/complete" }, "items": [ { @@ -7747,7 +7747,7 @@ "comment": "shop/reorder — _local.status 값(pending/success/error)으로 재주문 진행 화면을 if 분기한다(본문 line 72/99/225).", "scope": { "kind": "route", - "match": "/shop/reorder/:id" + "match": "/*?/reorder/:id" }, "items": [ { @@ -8394,7 +8394,7 @@ "comment": "shop/guest_order_form — 비회원 주문 조회 폼. 본문이 _global.currentUser.uuid 유무로 양분된다(slots.content[0] 회원→마이페이지 리다이렉트 안내 / content[1] 비회원→조회 폼). 편집기 sampleGlobal 은 로그인 상태(currentUser 시드)라 비회원 조회 폼이 기본 미표시이므로, currentUser 를 null 로 패치한 비회원 상태를 기본으로 노출해 폼을 편집 가능하게 한다.", "scope": { "kind": "route", - "match": "/shop/guest/orders" + "match": "/*?/guest/orders" }, "items": [ { diff --git a/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/checkoutNormalStateMarker.test.ts b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/checkoutNormalStateMarker.test.ts index daab64b0..d8874038 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/checkoutNormalStateMarker.test.ts +++ b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/checkoutNormalStateMarker.test.ts @@ -28,7 +28,7 @@ const spec = JSON.parse( fs.readFileSync(path.join(REPO_ROOT, 'modules/_bundled/sirsoft-ecommerce/editor-spec.json'), 'utf-8'), ); const checkoutGroup = spec.states.groups.find( - (g: any) => g.scope?.kind === 'route' && g.scope?.match === '/shop/checkout', + (g: any) => g.scope?.kind === 'route' && g.scope?.match === '/*?/checkout', ); const normal = checkoutGroup?.items.find((i: any) => i.id === 'normal'); diff --git a/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/guestOrderFormStates.test.ts b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/guestOrderFormStates.test.ts index 5361de5f..120decd8 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/guestOrderFormStates.test.ts +++ b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/guestOrderFormStates.test.ts @@ -8,7 +8,7 @@ * 그룹이 없으면 비회원 조회 폼이 캔버스에 영영 미표시되어 편집 불가였다. * * 본 테스트는 develop 신규 화면에 대응해 추가한 상태 그룹의 계약을 가드한다: - * - scope.match 가 정규화 라우트 path(`/shop/guest/orders`)와 일치 + * - scope.match 가 상점 주소 설정과 무관하게 정규화 라우트 path 와 일치 (공개 #85) * - 기본(guest) 상태가 `global.currentUser: null` 패치로 비회원 폼을 노출 * - 회원(member) 상태가 `global.currentUser.uuid` 명시 시드로 마이페이지 안내 분기를 노출 * - 두 상태 라벨이 `$t:` 친화 키 @@ -25,6 +25,8 @@ import { describe, it, expect } from 'vitest'; import * as fs from 'node:fs'; import * as path from 'node:path'; +import { matchStateItems } from '../../../../../../../resources/js/core/template-engine/layout-editor/utils/matchStateScope'; + function findProjectRoot(startDir: string): string { let dir = startDir; while (dir !== path.dirname(dir)) { @@ -39,18 +41,31 @@ const spec = JSON.parse( fs.readFileSync(path.join(REPO_ROOT, 'modules/_bundled/sirsoft-ecommerce/editor-spec.json'), 'utf-8'), ); const group = spec.states.groups.find( - (g: any) => g.scope?.kind === 'route' && g.scope?.match === '/shop/guest/orders', + (g: any) => g.scope?.kind === 'route' && g.scope?.match === '/*?/guest/orders', ); const guest = group?.items.find((i: any) => i.id === 'guest'); const member = group?.items.find((i: any) => i.id === 'member'); describe('guest_order_form 상태 그룹', () => { - it('정규화 라우트 path(`/shop/guest/orders`)에 상태 그룹이 존재한다', () => { + it('정규화 라우트 path 에 상태 그룹이 존재한다', () => { expect(group).toBeTruthy(); // items 2개 이상이어야 편집기 캔버스에 상태 드롭다운(PageStateSwitcher)이 표시된다. expect(group.items.length).toBeGreaterThanOrEqual(2); }); + // 공개 #85 — 상점 주소는 운영자 설정이라 편집기가 평가한 라우트 path 의 첫 세그먼트가 + // 사이트마다 다르다. scope.match 를 `/shop/...` 리터럴로 두면 주소를 바꾼 상점에서 + // 상태 그룹이 매칭되지 않아 상태 토글이 조용히 사라진다(예외·경고 없음). + // 실제 소비자(matchStateItems)로 판정해 정규식 의미까지 고정한다. + it.each([ + ['기본 상점 주소', '/shop/guest/orders'], + ['운영자가 바꾼 주소', '/store/guest/orders'], + ['주소 없이 운영하는 상점(no_route)', '/guest/orders'], + ])('%s 라우트에서 상태 그룹이 매칭된다', (_label, routePath) => { + const items = matchStateItems(spec.states.groups, { kind: 'route', match: routePath }); + expect(items.map((i) => i.id)).toEqual(expect.arrayContaining(['guest', 'member'])); + }); + it('기본(guest) 상태가 currentUser 를 null 로 패치해 비회원 조회 폼을 노출한다', () => { expect(guest?.default).toBe(true); // global.currentUser === null → `_global.currentUser?.uuid` undefined → content[1] 폼 활성. diff --git a/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/productDomainSampleData.test.ts b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/productDomainSampleData.test.ts index 3600dcb5..85834486 100644 --- a/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/productDomainSampleData.test.ts +++ b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/productDomainSampleData.test.ts @@ -238,13 +238,13 @@ describe('상품 도메인 편집기 샘플 — sirsoft-ecommerce admin', () => }); }); - describe('/shop/products/:id 상태 override — 통째 교체이므로 충실 shape 유지', () => { + describe('상품 상세 상태 override — 통째 교체이므로 충실 shape 유지', () => { // Chrome MCP 실측 회귀(2026-06-03): 비-기본 상태 override 가 빈약 stub(name:"샘플 상품 1", // price, stock_status, images:[], options:[])이라 캔버스가 붕괴(277자)했다. override 는 // base sampleData 를 "통째 교체"(pageStateSimulator.resolveSampleOverride)하므로 // 누락 필드는 undefined → 렌더 붕괴. base 와 동일 충실 shape 를 유지해야 한다. const group = spec.states.groups.find( - (g: any) => g.scope?.kind === 'route' && g.scope?.match === '/shop/products/:id', + (g: any) => g.scope?.kind === 'route' && g.scope?.match === '/*?/products/:product_code', ); const PRODUCT_EP = '/api/modules/sirsoft-ecommerce/products/*'; const stateOf = (id: string) => diff --git a/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/shopStateScopeRouteParity.test.ts b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/shopStateScopeRouteParity.test.ts new file mode 100644 index 00000000..3eb6ca1b --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/resources/js/__tests__/layouts/shopStateScopeRouteParity.test.ts @@ -0,0 +1,110 @@ +// e2e:allow 편집기 상태 스코프 ↔ 라우트 토큰 정합만 검사하는 정적 계약 테스트 — 런타임 동작 무변경, 해당 화면 E2E 는 기존 spec 으로 커버됨 +/** + * 상점 상태 그룹 scope ↔ routes.json 라우트 패리티 계약 테스트 + * + * 편집기는 템플릿 routes.json 의 동적 path 표현식을 평가해 `selectedRoute.path` 를 + * 만들고, 그 값을 editor-spec 의 `scope.match` 와 대조해 상태 토글을 띄운다. 따라서 + * scope 는 **routes.json 이 실제로 만들어 내는 path 문자열**과 일치해야 한다. + * + * 이 테스트가 막는 회귀는 두 축이다: + * + * 1. 세그먼트 축 — 상점 주소는 운영자 설정이라 첫 세그먼트가 사이트마다 다르다 + * (기본 `shop` / `route_path` 로 바꾼 값 / `no_route` 면 세그먼트 없음). + * `/*` 로 쓰면 no_route 상점에서만 매칭이 깨진다 (공개 #85, engine-v1.58.0 `/*?`). + * + * 2. 파라미터 토큰 축 — `matchRoutePattern` 은 `:param` 을 리터럴로 취급한다. + * scope 에 `:id` 라 적었는데 routes.json 이 `:product_code` 를 쓰면 세그먼트 + * 토큰을 아무리 고쳐도 **세 축 모두에서** 영영 매칭되지 않는다. 예외도 경고도 + * 없이 그 화면의 상태 토글만 사라지므로 정적 대조가 유일한 발견 경로다. + * + * scope 목록을 손으로 열거하지 않고 editor-spec 과 routes.json 양쪽에서 도출한다 — + * 나중에 상점 화면이 늘어도 이 테스트가 그 화면까지 자동으로 검사한다. + */ +import { describe, it, expect } from 'vitest'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +import { matchStateItems } from '../../../../../../../resources/js/core/template-engine/layout-editor/utils/matchStateScope'; + +function findProjectRoot(startDir: string): string { + let dir = startDir; + while (dir !== path.dirname(dir)) { + if (fs.existsSync(path.join(dir, 'artisan'))) return dir; + dir = path.dirname(dir); + } + return path.resolve(startDir, '../../../../../../..'); +} + +const REPO_ROOT = findProjectRoot(__dirname); + +const spec = JSON.parse( + fs.readFileSync(path.join(REPO_ROOT, 'modules/_bundled/sirsoft-ecommerce/editor-spec.json'), 'utf-8'), +); +const routesJson = JSON.parse( + fs.readFileSync(path.join(REPO_ROOT, 'templates/_bundled/sirsoft-basic/routes.json'), 'utf-8'), +); + +/** routes.json 의 상점 주소 prefix 표현식 (`no_route ? '' : route_path ?? 'shop'`) */ +const SHOP_PREFIX_EXPR = /^\/\{\{[^}]*?no_route[\s\S]*?\}\}/; + +/** 편집기가 상점 주소 설정을 평가했을 때 나올 수 있는 세 가지 첫 세그먼트 */ +const AXES: ReadonlyArray<[label: string, base: string]> = [ + ['기본 상점 주소(shop)', '/shop'], + ['운영자가 바꾼 주소(store)', '/store'], + ['주소 없이 운영하는 상점(no_route)', ''], +]; + +/** 상점 주소에 종속된 라우트를 축별로 평가한 path 목록 */ +function shopRoutePaths(base: string): string[] { + return (routesJson.routes ?? []) + .map((r: { path?: string }) => r.path) + .filter((p: unknown): p is string => typeof p === 'string' && SHOP_PREFIX_EXPR.test(p)) + .map((p: string) => p.replace(SHOP_PREFIX_EXPR, base)); +} + +/** + * editor-spec 의 상점 route scope 목록 (그룹의 첫 상태 id 를 식별자로 함께 들고 간다). + * 관리자 라우트(`*​/admin/...`)는 상점 주소와 무관하므로 제외한다. + */ +const shopScopes: Array<{ match: string; probeItemId: string }> = (spec.states?.groups ?? []) + .filter( + (g: { scope?: { kind?: string; match?: unknown }; items?: unknown[] }) => + g.scope?.kind === 'route' && + typeof g.scope?.match === 'string' && + !g.scope.match.includes('/admin/') && + Array.isArray(g.items) && + g.items.length > 0, + ) + .map((g: { scope: { match: string }; items: Array<{ id: string }> }) => ({ + match: g.scope.match, + probeItemId: g.items[0].id, + })); + +describe('상점 상태 그룹 scope ↔ routes.json 라우트 패리티', () => { + it('검사 모집단이 비어 있지 않다 (빈 모집단으로 통과하는 것을 막는다)', () => { + expect(shopScopes.length).toBeGreaterThan(0); + expect(shopRoutePaths('/shop').length).toBeGreaterThan(0); + }); + + describe.each(AXES)('%s', (_label, base) => { + it.each(shopScopes.map((s) => [s.match, s.probeItemId]))( + 'scope %s 의 상태가 실제 라우트에서 노출된다', + (scopeMatch: string, probeItemId: string) => { + const candidates = shopRoutePaths(base); + + // 실제 소비자(matchStateItems)로 판정해 정규식 의미까지 함께 고정한다. + const hit = candidates.find((routePath) => + matchStateItems(spec.states.groups, { kind: 'route', match: routePath }).some( + (i) => i.id === probeItemId, + ), + ); + + expect( + hit, + `scope "${scopeMatch}" 가 이 축의 어떤 라우트와도 매칭되지 않는다.\n` + + ` 후보 라우트: ${candidates.join(', ')}`, + ).toBeDefined(); + }, + ); + }); +}); diff --git a/modules/_bundled/sirsoft-ecommerce/src/Http/Controllers/Public/OrderController.php b/modules/_bundled/sirsoft-ecommerce/src/Http/Controllers/Public/OrderController.php index 049207aa..e26f2e03 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Http/Controllers/Public/OrderController.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Http/Controllers/Public/OrderController.php @@ -26,6 +26,7 @@ use Modules\Sirsoft\Ecommerce\Services\OrderService; use Modules\Sirsoft\Ecommerce\Services\StockService; use Modules\Sirsoft\Ecommerce\Services\TempOrderService; use Modules\Sirsoft\Ecommerce\Services\UserAddressService; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * 주문 공유 컨트롤러 (회원/비회원 공용 + 비회원 토큰 후속 액션) @@ -193,7 +194,9 @@ class OrderController extends PublicBaseController return ResponseHelper::error( 'sirsoft-ecommerce::exceptions.order_not_found', 404, - ['redirect_to' => '/shop/guest/orders'] + // 상점 주소 설정(route_path/no_route)을 반영해야 주소를 바꾼 상점에서도 + // 실제 존재하는 비회원 조회 화면으로 안내된다 (공개 #85). + ['redirect_to' => ShopPathResolver::path('guest/orders')] ); } diff --git a/modules/_bundled/sirsoft-ecommerce/src/Http/Controllers/Traits/HandlesOrderCreation.php b/modules/_bundled/sirsoft-ecommerce/src/Http/Controllers/Traits/HandlesOrderCreation.php index c1b70d96..0bd32da5 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Http/Controllers/Traits/HandlesOrderCreation.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Http/Controllers/Traits/HandlesOrderCreation.php @@ -19,6 +19,7 @@ use Modules\Sirsoft\Ecommerce\Models\Order; use Modules\Sirsoft\Ecommerce\Models\TempOrder; use Modules\Sirsoft\Ecommerce\Services\CurrencyConversionService; use Modules\Sirsoft\Ecommerce\Services\EcommerceSettingsService; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * 주문 생성 공통 흐름 Trait @@ -218,7 +219,9 @@ trait HandlesOrderCreation { $responseData = [ 'order' => $orderResource, - 'redirect_url' => "/shop/orders/{$order->order_number}/complete", + // 상점 주소는 운영자 설정이다 — 기본값 리터럴을 내려보내면 주소를 바꾼 상점에서 + // 결제를 마친 손님이 존재하지 않는 화면으로 이동한다 (공개 #85). + 'redirect_url' => ShopPathResolver::path("orders/{$order->order_number}/complete"), 'requires_pg_payment' => $requiresPg, ]; diff --git a/modules/_bundled/sirsoft-ecommerce/src/Listeners/EcommerceNotificationDataListener.php b/modules/_bundled/sirsoft-ecommerce/src/Listeners/EcommerceNotificationDataListener.php index c3e5cc74..8f8cd21b 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Listeners/EcommerceNotificationDataListener.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Listeners/EcommerceNotificationDataListener.php @@ -11,6 +11,7 @@ use Modules\Sirsoft\Ecommerce\Models\ProductInquiry; use Modules\Sirsoft\Ecommerce\Module; use Modules\Sirsoft\Ecommerce\Repositories\Contracts\OrderCancelRepositoryInterface; use Modules\Sirsoft\Ecommerce\Services\CurrencyConversionService; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * 이커머스 알림 데이터 필터 리스너 @@ -418,16 +419,18 @@ class EcommerceNotificationDataListener implements HookListenerInterface // ────────────────────────────────────────────── /** - * 비회원 주문 조회 화면 경로 + * 비회원 주문 조회 화면의 기준 경로 (상점 주소 설정 하위) * * 후속 이메일 발송 이슈가 비회원 주문 조회 URL을 만들 때 사용하는 경로 기준이다. * 비회원 본인 확인은 주문번호 + 전화번호 + 조회 비밀번호 입력을 전제로 하므로 * 주문번호를 쿼리에 노출하지 않고 순수 경로만 제공한다. * + * 앞의 상점 주소는 운영자 설정이므로 ShopPathResolver 가 붙인다 — 상수로 `/shop` 을 + * 박아 두면 주소를 바꾼 상점의 안내 메일이 존재하지 않는 화면을 가리킨다 (공개 #85). * 경로는 비회원 주문 조회 라우트(templates/sirsoft-basic/routes.json) 및 * OrderController::showByOrderNumber 의 비회원 redirect_to 와 동일하게 유지한다. */ - private const GUEST_ORDER_LOOKUP_PATH = '/shop/guest/orders'; + private const GUEST_ORDER_LOOKUP_SUFFIX = 'guest/orders'; /** * 주문 알림 데이터 배열을 구성합니다. @@ -445,7 +448,7 @@ class EcommerceNotificationDataListener implements HookListenerInterface if ($order->isGuestOrder()) { $name = $order->getOrdererName() ?? ''; - $orderUrl = "{$baseUrl}".self::GUEST_ORDER_LOOKUP_PATH; + $orderUrl = "{$baseUrl}".ShopPathResolver::path(self::GUEST_ORDER_LOOKUP_SUFFIX); } else { $name = $order->user?->name ?? ''; $orderUrl = "{$baseUrl}/mypage/orders/{$order->order_number}"; diff --git a/modules/_bundled/sirsoft-ecommerce/src/Listeners/SearchProductsListener.php b/modules/_bundled/sirsoft-ecommerce/src/Listeners/SearchProductsListener.php index ac995828..c0e35c5d 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Listeners/SearchProductsListener.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Listeners/SearchProductsListener.php @@ -10,6 +10,7 @@ use App\Support\Query\BoundedCount; use Illuminate\Support\Facades\Log; use Modules\Sirsoft\Ecommerce\Http\Resources\Traits\HasMultiCurrencyPrices; use Modules\Sirsoft\Ecommerce\Services\ProductService; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * 통합 검색에 상품 검색 결과를 제공하는 리스너 @@ -268,7 +269,8 @@ class SearchProductsListener implements HookListenerInterface 'multi_currency_selling_price' => $this->buildMultiCurrencyPrices($product->selling_price), 'multi_currency_list_price' => $this->buildMultiCurrencyPrices($product->list_price), 'labels' => $labels, - 'url' => '/shop/products/'.$product->product_code, + // 상점 주소는 운영자 설정 — 기본값 리터럴은 주소를 바꾼 상점에서 죽은 링크가 된다 (공개 #85) + 'url' => ShopPathResolver::path('products/'.$product->product_code), 'review_count' => (int) ($product->review_count ?? 0), 'rating_avg' => $product->rating_avg !== null ? round((float) $product->rating_avg, 1) : 0.0, ]; diff --git a/modules/_bundled/sirsoft-ecommerce/src/Listeners/SeoCategoryCacheListener.php b/modules/_bundled/sirsoft-ecommerce/src/Listeners/SeoCategoryCacheListener.php index e43aba68..d591a8e3 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Listeners/SeoCategoryCacheListener.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Listeners/SeoCategoryCacheListener.php @@ -9,6 +9,7 @@ use App\Jobs\GenerateSitemapJob; use App\Seo\Contracts\SeoCacheManagerInterface; use App\Seo\SitemapIndexer; use Illuminate\Support\Facades\Log; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * 카테고리 변경 시 SEO 캐시 무효화 리스너 @@ -142,9 +143,8 @@ class SeoCategoryCacheListener implements HookListenerInterface && (bool) g7_module_settings('sirsoft-ecommerce', 'seo.seo_category', true); if ($visible) { - $routePath = g7_module_settings('sirsoft-ecommerce', 'basic_info.route_path', 'shop'); $indexer->indexResource('category', $category->id, 'sirsoft-ecommerce', [[ - 'url' => "/{$routePath}/category/{$category->slug}", + 'url' => ShopPathResolver::path("category/{$category->slug}"), 'lastmod' => $category->updated_at?->toW3cString(), 'changefreq' => SitemapChangeFreq::Weekly->value, 'priority' => 0.6, diff --git a/modules/_bundled/sirsoft-ecommerce/src/Listeners/SeoProductCacheListener.php b/modules/_bundled/sirsoft-ecommerce/src/Listeners/SeoProductCacheListener.php index 97ad9d90..92ad476b 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Listeners/SeoProductCacheListener.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Listeners/SeoProductCacheListener.php @@ -11,6 +11,7 @@ use App\Seo\SeoCacheRegenerator; use App\Seo\SitemapIndexer; use Illuminate\Support\Facades\Log; use Modules\Sirsoft\Ecommerce\Enums\ProductDisplayStatus; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * 상품 변경 시 SEO 캐시 무효화 리스너 @@ -160,9 +161,8 @@ class SeoProductCacheListener implements HookListenerInterface && (bool) g7_module_settings('sirsoft-ecommerce', 'seo.seo_product_detail', true); if ($visible) { - $routePath = g7_module_settings('sirsoft-ecommerce', 'basic_info.route_path', 'shop'); $indexer->indexResource('product', $product->id, 'sirsoft-ecommerce', [[ - 'url' => "/{$routePath}/products/{$product->id}", + 'url' => ShopPathResolver::path("products/{$product->id}"), 'lastmod' => $product->updated_at?->toW3cString(), 'changefreq' => SitemapChangeFreq::Weekly->value, 'priority' => 0.8, @@ -184,8 +184,8 @@ class SeoProductCacheListener implements HookListenerInterface /** * 상품 상세 페이지의 SEO 캐시를 즉시 재생성합니다. * - * URL 구성: /{route_path}/products/{id} - * route_path는 이커머스 모듈 설정에서 조회합니다. + * URL 구성: {상점 기준 경로}/products/{id} + * 기준 경로는 상점 주소 설정(route_path / no_route)을 ShopPathResolver 가 해석한 값입니다. * * @param array $args 훅 인자 배열 */ @@ -199,8 +199,7 @@ class SeoProductCacheListener implements HookListenerInterface try { $regenerator = app(SeoCacheRegenerator::class); - $routePath = g7_module_settings('sirsoft-ecommerce', 'basic_info.route_path', 'shop'); - $url = "/{$routePath}/products/{$product->id}"; + $url = ShopPathResolver::path("products/{$product->id}"); $regenerator->renderAndCache($url); Log::debug('[SEO] Product detail cache regenerated', [ diff --git a/modules/_bundled/sirsoft-ecommerce/src/Seo/EcommerceSitemapContributor.php b/modules/_bundled/sirsoft-ecommerce/src/Seo/EcommerceSitemapContributor.php index c4c5b996..79274218 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Seo/EcommerceSitemapContributor.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Seo/EcommerceSitemapContributor.php @@ -7,6 +7,7 @@ use App\Seo\AbstractSitemapContributor; use Illuminate\Support\Facades\Log; use Modules\Sirsoft\Ecommerce\Repositories\Contracts\CategoryRepositoryInterface; use Modules\Sirsoft\Ecommerce\Repositories\Contracts\ProductRepositoryInterface; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * Ecommerce 모듈 Sitemap 기여자 @@ -74,12 +75,12 @@ class EcommerceSitemapContributor extends AbstractSitemapContributor */ private function collectUrls(): iterable { - $routePath = g7_module_settings('sirsoft-ecommerce', 'basic_info.route_path') ?? 'shop'; - + // 상점 주소 설정(route_path / no_route)을 반영한다 — 주소를 바꾼 상점의 사이트맵이 + // 기본값 주소를 싣고 나가면 검색엔진이 존재하지 않는 URL 을 수집한다 (공개 #85). // 상품 목록 페이지 — 'SEO 제공 페이지' 토글 OFF 시 제외 if ((bool) g7_module_settings('sirsoft-ecommerce', 'seo.seo_shop_index', true)) { yield [ - 'url' => "/{$routePath}/products", + 'url' => ShopPathResolver::path('products'), 'changefreq' => SitemapChangeFreq::Daily->value, 'priority' => 0.7, 'resource_type' => 'shop_index', @@ -91,7 +92,7 @@ class EcommerceSitemapContributor extends AbstractSitemapContributor if ((bool) g7_module_settings('sirsoft-ecommerce', 'seo.seo_category', true)) { foreach ($this->categoryRepository->streamActiveForSitemap() as $category) { yield [ - 'url' => "/{$routePath}/category/{$category->slug}", + 'url' => ShopPathResolver::path("category/{$category->slug}"), 'lastmod' => $category->updated_at?->toW3cString(), 'changefreq' => SitemapChangeFreq::Weekly->value, 'priority' => 0.6, @@ -105,7 +106,7 @@ class EcommerceSitemapContributor extends AbstractSitemapContributor if ((bool) g7_module_settings('sirsoft-ecommerce', 'seo.seo_product_detail', true)) { foreach ($this->productRepository->streamVisibleForSitemap() as $product) { yield [ - 'url' => "/{$routePath}/products/{$product->id}", + 'url' => ShopPathResolver::path("products/{$product->id}"), 'lastmod' => $product->updated_at?->toW3cString(), 'changefreq' => SitemapChangeFreq::Weekly->value, 'priority' => 0.8, diff --git a/modules/_bundled/sirsoft-ecommerce/src/Services/ProductInquiryService.php b/modules/_bundled/sirsoft-ecommerce/src/Services/ProductInquiryService.php index f0409868..922db4c8 100644 --- a/modules/_bundled/sirsoft-ecommerce/src/Services/ProductInquiryService.php +++ b/modules/_bundled/sirsoft-ecommerce/src/Services/ProductInquiryService.php @@ -2,15 +2,17 @@ namespace Modules\Sirsoft\Ecommerce\Services; +use App\Contracts\Repositories\UserRepositoryInterface; use App\Extension\HookManager; use App\Helpers\PermissionHelper; -use App\Models\User; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Modules\Sirsoft\Ecommerce\Models\ProductInquiry; use Modules\Sirsoft\Ecommerce\Repositories\Contracts\ProductInquiryRepositoryInterface; use Modules\Sirsoft\Ecommerce\Repositories\Contracts\ProductRepositoryInterface; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * 상품 1:1 문의 서비스 @@ -26,11 +28,13 @@ class ProductInquiryService * @param ProductInquiryRepositoryInterface $repository 문의 리포지토리 * @param ProductRepositoryInterface $productRepository 상품 리포지토리 * @param EcommerceSettingsService $settingsService 이커머스 설정 서비스 + * @param UserRepositoryInterface $userRepository 사용자 리포지토리 (작성자 이름 배치 조회) */ public function __construct( protected ProductInquiryRepositoryInterface $repository, protected ProductRepositoryInterface $productRepository, - protected EcommerceSettingsService $settingsService + protected EcommerceSettingsService $settingsService, + protected UserRepositoryInterface $userRepository ) {} /** @@ -63,13 +67,13 @@ class ProductInquiryService if (! $boardSlug) { return [ 'items' => [], - 'meta' => [ - 'board_settings' => $this->defaultBoardSettings(), + 'meta' => [ + 'board_settings' => $this->defaultBoardSettings(), 'inquiry_available' => false, - 'total' => 0, - 'current_page' => $page, - 'per_page' => $perPage, - 'last_page' => 1, + 'total' => 0, + 'current_page' => $page, + 'per_page' => $perPage, + 'last_page' => 1, ], ]; } @@ -118,7 +122,7 @@ class ProductInquiryService // user_id 일괄 조회 (N+1 방지) $userIds = $pagePivots->map(fn ($pivot) => $posts[$pivot->inquirable_id]['user_id'] ?? null) ->filter()->unique()->values()->all(); - $userMap = User::whereIn('id', $userIds)->pluck('name', 'id'); + $userMap = $this->userRepository->getNamesByIds($userIds); $items = $pagePivots->map(function ($pivot) use ($posts, $currentUserId, $userMap) { $post = $posts[$pivot->inquirable_id] ?? null; @@ -128,19 +132,19 @@ class ProductInquiryService $name = $userId ? ($userMap[$userId] ?? $post['author_name'] ?? null) : ($post['author_name'] ?? null); return [ - 'id' => $pivot->id, - 'post_id' => $pivot->inquirable_id, - 'user_id' => $userId, + 'id' => $pivot->id, + 'post_id' => $pivot->inquirable_id, + 'user_id' => $userId, 'author_name' => $this->maskAuthorName($name), - 'title' => $post['title'] ?? null, - 'category' => $post['category'] ?? null, - 'content' => $post['content'] ?? null, - 'is_secret' => $post['is_secret'] ?? false, - 'is_owner' => $isOwner, + 'title' => $post['title'] ?? null, + 'category' => $post['category'] ?? null, + 'content' => $post['content'] ?? null, + 'is_secret' => $post['is_secret'] ?? false, + 'is_owner' => $isOwner, 'is_answered' => $pivot->is_answered ?? false, 'answered_at' => $pivot->answered_at?->toIso8601String(), - 'created_at' => $pivot->created_at?->toIso8601String(), - 'reply' => $post['reply'] ?? null, + 'created_at' => $pivot->created_at?->toIso8601String(), + 'reply' => $post['reply'] ?? null, 'attachments' => $post['attachments'] ?? [], ]; })->values()->all(); @@ -149,14 +153,14 @@ class ProductInquiryService return [ 'items' => $items, - 'meta' => [ - 'board_settings' => $boardSettings, + 'meta' => [ + 'board_settings' => $boardSettings, 'inquiry_available' => (bool) $boardSlug, - 'current_page' => $page, - 'per_page' => $perPage, - 'total' => $total, - 'last_page' => max(1, $lastPage), - 'abilities' => [ + 'current_page' => $page, + 'per_page' => $perPage, + 'total' => $total, + 'last_page' => max(1, $lastPage), + 'abilities' => [ 'can_update' => PermissionHelper::check('sirsoft-ecommerce.inquiries.update', Auth::user()), 'can_delete' => PermissionHelper::check('sirsoft-ecommerce.inquiries.delete', Auth::user()), ], @@ -172,14 +176,14 @@ class ProductInquiryService private function defaultBoardSettings(): array { return [ - 'secret_mode' => 'disabled', - 'categories' => [], - 'use_file_upload' => false, - 'max_file_count' => 5, - 'max_file_size' => 10485760, + 'secret_mode' => 'disabled', + 'categories' => [], + 'use_file_upload' => false, + 'max_file_count' => 5, + 'max_file_size' => 10485760, 'allowed_extensions' => [], - 'min_title_length' => 2, - 'max_title_length' => 200, + 'min_title_length' => 2, + 'max_title_length' => 200, 'min_content_length' => 10, 'max_content_length' => 10000, ]; @@ -209,7 +213,7 @@ class ProductInquiryService $product = $this->productRepository->find($productId); if (! $product) { - throw new \Illuminate\Database\Eloquent\ModelNotFoundException( + throw new ModelNotFoundException( __('sirsoft-ecommerce::messages.products.not_found') ); } @@ -312,41 +316,42 @@ class ProductInquiryService $post = $posts[$inquiry->inquirable_id] ?? null; return [ - 'id' => $inquiry->id, - 'product_id' => $inquiry->product_id, - 'product' => $inquiry->product ? [ - 'id' => $inquiry->product->id, - 'product_code' => $inquiry->product->product_code, - 'name' => $inquiry->product->getLocalizedName(), + 'id' => $inquiry->id, + 'product_id' => $inquiry->product_id, + 'product' => $inquiry->product ? [ + 'id' => $inquiry->product->id, + 'product_code' => $inquiry->product->product_code, + 'name' => $inquiry->product->getLocalizedName(), 'thumbnail_url' => $inquiry->product->getThumbnailUrl(), - 'url' => '/' . ltrim($this->settingsService->getSetting('basic_info.route_path', 'shop'), '/') . '/products/' . $inquiry->product->product_code, + // 주소 없이 운영하는 상점(no_route)까지 반영해야 실제 상품 화면을 가리킨다 (공개 #85) + 'url' => ShopPathResolver::path('products/'.$inquiry->product->product_code), ] : null, - 'product_name' => $this->localizeProductName($inquiry->product_name_snapshot), - 'is_answered' => $inquiry->is_answered, - 'answered_at' => $inquiry->answered_at?->toIso8601String(), - 'created_at' => $inquiry->created_at?->toIso8601String(), - 'updated_at' => $inquiry->updated_at?->toIso8601String(), + 'product_name' => $this->localizeProductName($inquiry->product_name_snapshot), + 'is_answered' => $inquiry->is_answered, + 'answered_at' => $inquiry->answered_at?->toIso8601String(), + 'created_at' => $inquiry->created_at?->toIso8601String(), + 'updated_at' => $inquiry->updated_at?->toIso8601String(), // 게시판 Post 데이터 (게시판 미연동 시 null) - 'title' => $post['title'] ?? null, - 'category' => $post['category'] ?? null, - 'content' => $post['content'] ?? null, - 'is_secret' => $post['is_secret'] ?? false, - 'reply' => $post['reply'] ?? null, - 'attachments' => $post['attachments'] ?? [], + 'title' => $post['title'] ?? null, + 'category' => $post['category'] ?? null, + 'content' => $post['content'] ?? null, + 'is_secret' => $post['is_secret'] ?? false, + 'reply' => $post['reply'] ?? null, + 'attachments' => $post['attachments'] ?? [], ]; })->values()->all(); return [ 'items' => $items, - 'meta' => [ - 'current_page' => $paginator->currentPage(), - 'per_page' => $paginator->perPage(), - 'total' => $paginator->total(), - 'last_page' => $paginator->lastPage(), - 'from' => $paginator->firstItem(), - 'to' => $paginator->lastItem(), + 'meta' => [ + 'current_page' => $paginator->currentPage(), + 'per_page' => $paginator->perPage(), + 'total' => $paginator->total(), + 'last_page' => $paginator->lastPage(), + 'from' => $paginator->firstItem(), + 'to' => $paginator->lastItem(), 'inquiry_available' => (bool) $boardSlug, - 'abilities' => [ + 'abilities' => [ 'can_update' => PermissionHelper::check('sirsoft-ecommerce.inquiries.update', Auth::user()), 'can_delete' => PermissionHelper::check('sirsoft-ecommerce.inquiries.delete', Auth::user()), ], @@ -394,7 +399,7 @@ class ProductInquiryService Log::info('상품 문의 수정 완료', [ 'inquiry_id' => $inquiryId, - 'user_id' => Auth::id(), + 'user_id' => Auth::id(), ]); } @@ -442,7 +447,7 @@ class ProductInquiryService Log::info('상품 문의 삭제 완료', [ 'inquiry_id' => $inquiryId, - 'user_id' => Auth::id(), + 'user_id' => Auth::id(), ]); } diff --git a/modules/_bundled/sirsoft-ecommerce/src/Support/ShopPathResolver.php b/modules/_bundled/sirsoft-ecommerce/src/Support/ShopPathResolver.php new file mode 100644 index 00000000..26464ab6 --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/src/Support/ShopPathResolver.php @@ -0,0 +1,79 @@ +=1.1.0` 이상으로 선언해야 한다. + * + * 시그니처를 바꾸거나 제거할 때는 위 소비 확장을 전수 확인하고 각 확장의 최소 버전 + * 제약을 함께 올린다 (CLAUDE.md "버전 동기화 의무" ②). + * + * @since 1.1.0 + */ +class ShopPathResolver +{ + /** 상점 주소 설정 키 */ + public const ROUTE_PATH_KEY = 'basic_info.route_path'; + + /** 주소 없이 운영 여부 설정 키 */ + public const NO_ROUTE_KEY = 'basic_info.no_route'; + + /** 기본 상점 주소 (설정 미지정·빈 값 시 폴백) */ + public const DEFAULT_ROUTE_PATH = 'shop'; + + /** + * 상점 화면의 기준 경로를 반환합니다. + * + * `no_route` 가 켜져 있으면 빈 문자열이다 — 상점이 루트에 붙어 있어 앞에 붙일 + * 세그먼트가 없다는 뜻이며, `path()` 가 이를 이중 슬래시 없이 이어 붙인다. + * + * @return string 앞에만 슬래시가 붙은 기준 경로 (예: `/shop`), 주소 미사용 시 빈 문자열 + */ + public static function base(): string + { + if (g7_module_settings('sirsoft-ecommerce', self::NO_ROUTE_KEY)) { + return ''; + } + + $routePath = trim((string) g7_module_settings('sirsoft-ecommerce', self::ROUTE_PATH_KEY, self::DEFAULT_ROUTE_PATH), '/'); + + return '/'.($routePath !== '' ? $routePath : self::DEFAULT_ROUTE_PATH); + } + + /** + * 기준 경로에 하위 경로를 이어 붙인 상점 화면 경로를 반환합니다. + * + * 슬래시 중복은 한 겹으로 정규화한다 (`no_route` + 앞 슬래시 붙은 하위 경로 조합에서 + * `//products` 가 만들어지는 것을 막는다). 코어 라우트 해석기가 같은 이유로 같은 + * 정규화를 수행한다 (`app/Seo/TemplateRouteResolver.php`). + * + * @param string $suffix 기준 경로 하위의 화면 경로 (앞 슬래시 유무 무관) + * @return string 정규화된 상점 화면 경로 + */ + public static function path(string $suffix): string + { + return (string) preg_replace('#/+#', '/', self::base().'/'.ltrim($suffix, '/')); + } +} diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/OrderControllerTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/OrderControllerTest.php index 68f2a5ad..6ebe0f52 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/OrderControllerTest.php +++ b/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/OrderControllerTest.php @@ -3,6 +3,7 @@ namespace Modules\Sirsoft\Ecommerce\Tests\Feature\Http\Controllers\Public; use App\Extension\HookManager; +use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; use Modules\Sirsoft\Ecommerce\Enums\OrderStatusEnum; @@ -18,6 +19,7 @@ use Modules\Sirsoft\Ecommerce\Models\TempOrder; use Modules\Sirsoft\Ecommerce\Services\EcommerceSettingsService; use Modules\Sirsoft\Ecommerce\Services\PaymentMethodResolver; use Modules\Sirsoft\Ecommerce\Tests\ModuleTestCase; +use PHPUnit\Framework\Attributes\DataProvider; /** * 회원/비회원 공유 주문 (Public\OrderController) 테스트 @@ -184,6 +186,51 @@ class OrderControllerTest extends ModuleTestCase ]); } + /** + * 1-1. 주문 완료 이동 주소는 상점 주소 설정을 따른다 (공개 #85) + * + * 기본값 상점(`/shop`) · 운영자가 바꾼 주소(`/store`) · 주소 없이 운영(no_route) 3축. + * 서버가 기본값을 리터럴로 내려보내면 뒤의 두 상점에서는 결제를 마친 손님이 + * 존재하지 않는 페이지로 이동한다. + * + * @param array $basicInfo 상점 기본 설정 + */ + #[DataProvider('shopRoutePathProvider')] + public function test_주문_완료_이동주소가_상점_주소_설정을_따른다(array $basicInfo, string $expectedPrefix): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', $basicInfo); + + $this->createGuestTempOrder(); + + $response = $this->postJson( + '/api/modules/sirsoft-ecommerce/user/orders', + $this->guestOrderPayload(), + ['X-Cart-Key' => $this->cartKey] + ); + + $response->assertStatus(201); + + $orderNumber = $response->json('data.order.order_number'); + $this->assertSame( + "{$expectedPrefix}/orders/{$orderNumber}/complete", + $response->json('data.redirect_url') + ); + } + + /** + * 상점 주소 3축 (기본 / 변경 / 주소 없음) + * + * @return array, 1: string}> + */ + public static function shopRoutePathProvider(): array + { + return [ + '기본 상점 주소' => [['route_path' => 'shop'], '/shop'], + '운영자가 바꾼 주소' => [['route_path' => 'store'], '/store'], + '주소 없이 운영' => [['route_path' => 'shop', 'no_route' => true], ''], + ]; + } + /** * 2. 비회원 주문은 is_first_order = false 로 저장된다 (이슈 #55 정책) */ @@ -1165,6 +1212,40 @@ class OrderControllerTest extends ModuleTestCase ->assertJsonPath('errors.redirect_to', '/shop/guest/orders'); } + /** + * 20-1. 상점 주소를 바꾼 상점에서는 비회원 조회 안내도 그 주소를 가리킨다 (공개 #85) + * + * 기본값 `/shop` 을 리터럴로 내려보내면 주소를 바꾼 상점에서는 존재하지 않는 화면으로 + * 안내한다. 서버는 문자열을 만들어 보냈을 뿐이라 예외도 404 로그도 남지 않는다. + */ + public function test_상점_주소_변경시_비회원_lookup_redirect도_따라간다(): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', ['route_path' => 'store']); + + [$orderNumber] = $this->placeGuestOrderAndToken(); + + $this->getJson("/api/modules/sirsoft-ecommerce/user/orders/{$orderNumber}") + ->assertStatus(404) + ->assertJsonPath('errors.redirect_to', '/store/guest/orders'); + } + + /** + * 20-2. 주소 없이 운영하는 상점(no_route)에서는 세그먼트 없이 루트에 붙는다 (공개 #85) + */ + public function test_주소_없는_상점은_비회원_lookup_redirect가_루트_경로다(): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', [ + 'route_path' => 'shop', + 'no_route' => true, + ]); + + [$orderNumber] = $this->placeGuestOrderAndToken(); + + $this->getJson("/api/modules/sirsoft-ecommerce/user/orders/{$orderNumber}") + ->assertStatus(404) + ->assertJsonPath('errors.redirect_to', '/guest/orders'); + } + /** * 21. 토큰으로 주문 취소 성공 (결제완료 상태) */ diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/PublicProductInquiryControllerTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/PublicProductInquiryControllerTest.php index 0dfe183b..4efa496f 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/PublicProductInquiryControllerTest.php +++ b/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/PublicProductInquiryControllerTest.php @@ -4,6 +4,7 @@ namespace Modules\Sirsoft\Ecommerce\Tests\Feature\Http\Controllers\Public; use App\Extension\HookManager; use Modules\Sirsoft\Ecommerce\Models\Product; +use Modules\Sirsoft\Ecommerce\Models\ProductInquiry; use Modules\Sirsoft\Ecommerce\Services\EcommerceSettingsService; use Modules\Sirsoft\Ecommerce\Tests\ModuleTestCase; use PHPUnit\Framework\Attributes\Test; @@ -75,6 +76,58 @@ class PublicProductInquiryControllerTest extends ModuleTestCase ]); } + /** + * 작성자 이름은 회원 계정에서 배치로 모아 온 뒤 마스킹되어 내려간다. + * + * 이름은 행마다 조회하면 N+1 이 되므로 표시할 ID 만 모아 한 번에 읽는다 + * (`UserRepositoryInterface::getNamesByIds`). 이 경로가 비면 목록의 작성자 + * 칸이 게시글 스냅샷 이름으로 조용히 대체되어, 개명 후에도 옛 이름이 남는다. + */ + #[Test] + public function 문의_목록의_작성자_이름은_회원_계정에서_읽어_마스킹된다(): void + { + app(EcommerceSettingsService::class)->setSetting('inquiry.board_slug', 'test-board'); + + $user = $this->createUser(); + $user->forceFill(['name' => '홍길동'])->save(); + + $pivot = ProductInquiry::create([ + 'product_id' => $this->product->id, + 'inquirable_type' => 'board_post', + 'inquirable_id' => 777, + 'user_id' => $user->id, + ]); + + HookManager::addFilter( + 'sirsoft-ecommerce.inquiry.get_settings', + fn ($defaults) => $defaults, + priority: 1 + ); + HookManager::addFilter( + 'sirsoft-ecommerce.inquiry.get_by_ids', + fn () => [[ + 'id' => $pivot->inquirable_id, + 'user_id' => $user->id, + // 게시글 스냅샷에는 다른 이름이 들어 있다 — 회원 계정 이름이 이겨야 한다. + 'author_name' => '스냅샷이름', + 'title' => '문의 제목', + 'is_secret' => false, + ]], + priority: 1 + ); + + $response = $this->getJson( + "/api/modules/sirsoft-ecommerce/products/{$this->product->id}/inquiries" + ); + + $response->assertOk(); + + // 존재 확정 후 값 비교 — 항목이 비면 이름 비교는 아무것도 증명하지 못한다. + $items = $response->json('data.items'); + $this->assertCount(1, $items); + $this->assertSame('홍*동', $items[0]['author_name']); + } + #[Test] public function board_slug_미설정_시_빈_목록과_inquiry_available_false를_반환한다(): void { diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/UserInquiryControllerTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/UserInquiryControllerTest.php index b0cf3c08..ddf341fb 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/UserInquiryControllerTest.php +++ b/modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/UserInquiryControllerTest.php @@ -3,6 +3,8 @@ namespace Modules\Sirsoft\Ecommerce\Tests\Feature\Http\Controllers\Public; use App\Extension\HookManager; +use App\Models\User; +use Illuminate\Support\Facades\Config; use Modules\Sirsoft\Ecommerce\Models\Product; use Modules\Sirsoft\Ecommerce\Models\ProductInquiry; use Modules\Sirsoft\Ecommerce\Tests\ModuleTestCase; @@ -18,7 +20,7 @@ use PHPUnit\Framework\Attributes\Test; */ class UserInquiryControllerTest extends ModuleTestCase { - private \App\Models\User $user; + private User $user; protected function setUp(): void { @@ -58,7 +60,7 @@ class UserInquiryControllerTest extends ModuleTestCase { $product = Product::factory()->create(); ProductInquiry::factory()->create([ - 'user_id' => $this->user->id, + 'user_id' => $this->user->id, 'product_id' => $product->id, 'is_answered' => false, ]); @@ -73,13 +75,44 @@ class UserInquiryControllerTest extends ModuleTestCase $this->assertCount(1, $data['items']); } + /** + * 문의 목록의 상품 링크가 상점 주소 설정을 따르는지 확인 (공개 #85) + * + * 종전에는 route_path 만 읽고 no_route 를 무시해, 주소 없이 운영하는 상점의 + * 문의 목록이 `/shop/products/...` 라는 존재하지 않는 화면을 가리켰다. + */ + #[Test] + public function 문의_목록의_상품_링크가_상점_주소_설정을_따른다(): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', [ + 'route_path' => 'shop', + 'no_route' => true, + ]); + + $product = Product::factory()->create(); + ProductInquiry::factory()->create([ + 'user_id' => $this->user->id, + 'product_id' => $product->id, + 'is_answered' => false, + ]); + + $response = $this->actingAs($this->user) + ->getJson('/api/modules/sirsoft-ecommerce/user/inquiries'); + + $response->assertOk(); + $this->assertSame( + "/products/{$product->product_code}", + $response->json('data.items.0.product.url') + ); + } + #[Test] public function 다른_사용자의_문의는_조회되지_않는다(): void { $otherUser = $this->createUser(); $product = Product::factory()->create(); ProductInquiry::factory()->create([ - 'user_id' => $otherUser->id, + 'user_id' => $otherUser->id, 'product_id' => $product->id, ]); @@ -99,13 +132,13 @@ class UserInquiryControllerTest extends ModuleTestCase { $product = Product::factory()->create(); ProductInquiry::factory()->create([ - 'user_id' => $this->user->id, - 'product_id' => $product->id, + 'user_id' => $this->user->id, + 'product_id' => $product->id, 'is_answered' => true, ]); ProductInquiry::factory()->create([ - 'user_id' => $this->user->id, - 'product_id' => $product->id, + 'user_id' => $this->user->id, + 'product_id' => $product->id, 'is_answered' => false, ]); @@ -123,13 +156,13 @@ class UserInquiryControllerTest extends ModuleTestCase { $product = Product::factory()->create(); ProductInquiry::factory()->create([ - 'user_id' => $this->user->id, - 'product_id' => $product->id, + 'user_id' => $this->user->id, + 'product_id' => $product->id, 'is_answered' => true, ]); ProductInquiry::factory()->create([ - 'user_id' => $this->user->id, - 'product_id' => $product->id, + 'user_id' => $this->user->id, + 'product_id' => $product->id, 'is_answered' => false, ]); @@ -151,13 +184,13 @@ class UserInquiryControllerTest extends ModuleTestCase { $product = Product::factory()->create(); ProductInquiry::factory()->create([ - 'user_id' => $this->user->id, - 'product_id' => $product->id, + 'user_id' => $this->user->id, + 'product_id' => $product->id, 'product_name_snapshot' => ['ko' => '사과 1박스', 'en' => 'Apple Box'], ]); ProductInquiry::factory()->create([ - 'user_id' => $this->user->id, - 'product_id' => $product->id, + 'user_id' => $this->user->id, + 'product_id' => $product->id, 'product_name_snapshot' => ['ko' => 'USB 충전 케이블', 'en' => 'USB Cable'], ]); @@ -181,7 +214,7 @@ class UserInquiryControllerTest extends ModuleTestCase { $product = Product::factory()->create(); ProductInquiry::factory()->count(3)->create([ - 'user_id' => $this->user->id, + 'user_id' => $this->user->id, 'product_id' => $product->id, ]); @@ -201,7 +234,7 @@ class UserInquiryControllerTest extends ModuleTestCase { $product = Product::factory()->create(); ProductInquiry::factory()->create([ - 'user_id' => $this->user->id, + 'user_id' => $this->user->id, 'product_id' => $product->id, ]); diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Feature/Search/ProductSearchIntegrationTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Feature/Search/ProductSearchIntegrationTest.php index 69f40c89..54e0cd7f 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Feature/Search/ProductSearchIntegrationTest.php +++ b/modules/_bundled/sirsoft-ecommerce/tests/Feature/Search/ProductSearchIntegrationTest.php @@ -2,6 +2,11 @@ namespace Modules\Sirsoft\Ecommerce\Tests\Feature\Search; +use App\Extension\HookListenerRegistrar; +use App\Extension\HookManager; +use App\Extension\ModuleManager; +use Illuminate\Support\Facades\Config; +use Illuminate\Support\Facades\DB; use Modules\Sirsoft\Ecommerce\Enums\ProductDisplayStatus; use Modules\Sirsoft\Ecommerce\Models\Product; use Modules\Sirsoft\Ecommerce\Tests\ModuleTestCase; @@ -46,7 +51,7 @@ class ProductSearchIntegrationTest extends ModuleTestCase { parent::setUp(); - $module = app(\App\Extension\ModuleManager::class)->getModule('sirsoft-ecommerce'); + $module = app(ModuleManager::class)->getModule('sirsoft-ecommerce'); if ($module === null) { return; } @@ -57,7 +62,7 @@ class ProductSearchIntegrationTest extends ModuleTestCase // filter 큐에 중복 추가되어 searchProducts 가 한 요청에서 2회 실행되어 두 번째 // 호출이 첫 번째 결과를 빈 결과로 덮어쓰는 문제 발생. // - registrar dedup 캐시도 함께 비워 register() 가 실제 동작하도록 한다. - \App\Extension\HookListenerRegistrar::clear(); + HookListenerRegistrar::clear(); foreach ($module->getHookListeners() as $listenerClass) { if (! class_exists($listenerClass)) { @@ -66,10 +71,10 @@ class ProductSearchIntegrationTest extends ModuleTestCase try { $subscribed = $listenerClass::getSubscribedHooks(); foreach (array_keys($subscribed) as $hookName) { - \App\Extension\HookManager::clearFilter($hookName); - \App\Extension\HookManager::clearAction($hookName); + HookManager::clearFilter($hookName); + HookManager::clearAction($hookName); } - \App\Extension\HookListenerRegistrar::register($listenerClass, 'sirsoft-ecommerce'); + HookListenerRegistrar::register($listenerClass, 'sirsoft-ecommerce'); } catch (\Throwable $e) { // skip individual listener failures } @@ -88,7 +93,7 @@ class ProductSearchIntegrationTest extends ModuleTestCase */ protected function flushProductFulltextIndex(): void { - \Illuminate\Support\Facades\DB::statement('ALTER TABLE g7_ecommerce_products ENGINE=InnoDB'); + DB::statement('ALTER TABLE g7_ecommerce_products ENGINE=InnoDB'); } /** @@ -249,6 +254,31 @@ class ProductSearchIntegrationTest extends ModuleTestCase } } + /** + * 통합검색 상품 링크가 상점 주소 설정을 따르는지 확인 (공개 #85) + * + * 기본값 리터럴을 내려보내면 상점 주소를 바꾼 사이트의 검색 결과가 전부 + * 존재하지 않는 상품 화면을 가리킨다 — 링크는 만들어졌으므로 오류가 남지 않는다. + */ + public function test_search_product_url_follows_shop_route_path_setting(): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', ['route_path' => 'store']); + + $keyword = 'routepathurlkeyword'; + $product = Product::factory()->create([ + 'name' => ['ko' => '주소확인용 상품', 'en' => "{$keyword} Route Path"], + 'display_status' => ProductDisplayStatus::VISIBLE, + ]); + $this->flushProductFulltextIndex(); + + $response = $this->getJson("/api/search?q={$keyword}&type=products"); + $response->assertStatus(200); + + $products = $response->json('data.products') ?? []; + $this->assertNotEmpty($products, '검색 결과가 비어 URL 축을 검증할 수 없다'); + $this->assertSame("/store/products/{$product->product_code}", $products[0]['url']); + } + /** * 품절/판매중단 상품이 검색 결과에 포함되는지 확인 * @@ -326,5 +356,4 @@ class ProductSearchIntegrationTest extends ModuleTestCase $ids = collect($data['products'] ?? [])->pluck('id')->toArray(); $this->assertContains($product->id, $ids); } - -} \ No newline at end of file +} diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/EcommerceNotificationDataListenerTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/EcommerceNotificationDataListenerTest.php index e5b8c0c7..0d25156f 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/EcommerceNotificationDataListenerTest.php +++ b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/EcommerceNotificationDataListenerTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Modules\Sirsoft\Ecommerce\Tests\Unit\Listeners; use App\Models\User; +use Illuminate\Support\Facades\Config; use Modules\Sirsoft\Ecommerce\Database\Factories\OrderFactory; use Modules\Sirsoft\Ecommerce\Listeners\EcommerceNotificationDataListener; use Modules\Sirsoft\Ecommerce\Models\Order; @@ -123,6 +124,22 @@ class EcommerceNotificationDataListenerTest extends ModuleTestCase $this->assertStringNotContainsString('ORD-GUEST-1', $result['data']['order_url']); } + /** + * 비회원 주문 안내 메일의 조회 주소는 상점 주소 설정을 따른다 (공개 #85). + * + * 상수로 `/shop` 을 박아 두면 주소를 바꾼 상점의 손님이 받은 메일이 존재하지 않는 + * 화면을 가리킨다 — 메일은 정상 발송되므로 아무 오류도 남지 않는다. + */ + public function test_guest_lookup_url_follows_shop_route_path_setting(): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', ['route_path' => 'store']); + + $order = $this->makeGuestOrder('비회원주문자', 'guest@example.com', 'ORD-GUEST-2'); + $result = $this->listener->extractData($this->emptyDefault(), 'order_confirmed', [$order]); + + $this->assertStringEndsWith('/store/guest/orders', $result['data']['order_url']); + } + /** * 비회원 주문 컨텍스트 → 코어 알림 표준 키 guest_recipient 제공 (회원과 동일 발송 경로). */ diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoCategoryCacheListenerTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoCategoryCacheListenerTest.php index 1aeabfdb..d9dd6a81 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoCategoryCacheListenerTest.php +++ b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoCategoryCacheListenerTest.php @@ -6,6 +6,7 @@ use App\Jobs\GenerateSitemapJob; use App\Seo\Contracts\SeoCacheManagerInterface; use App\Seo\SitemapIndexer; use Illuminate\Support\Facades\Bus; +use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Log; use Mockery; use Modules\Sirsoft\Ecommerce\Listeners\SeoCategoryCacheListener; @@ -218,6 +219,76 @@ class SeoCategoryCacheListenerTest extends ModuleTestCase $this->addToAssertionCount(1); } + // ======================================== + // syncSitemapIndex() — 상점 주소 설정 반영 (공개 #85) + // ======================================== + + /** + * 사이트맵 색인 URL 이 기본 상점 주소를 따르는지 확인 + */ + public function test_sitemap_index_url_uses_default_shop_path(): void + { + $this->assertSitemapIndexUrl([], '/shop/category/outer'); + } + + /** + * 운영자가 상점 주소를 바꾸면 사이트맵 색인 URL 도 그 주소를 따르는지 확인 + */ + public function test_sitemap_index_url_follows_custom_route_path(): void + { + $this->assertSitemapIndexUrl(['route_path' => 'store'], '/store/category/outer'); + } + + /** + * 주소 없이 운영하는 상점(no_route)의 사이트맵 색인 URL 은 세그먼트 없이 루트에 붙는다 + * + * 종전에는 route_path 만 읽고 no_route 를 무시해 `/shop/category/outer` 를 색인했다 — + * 실제 화면 주소는 `/category/outer` 이므로 사이트맵이 없는 주소를 검색엔진에 알린다. + */ + public function test_sitemap_index_url_omits_route_segment_when_no_route(): void + { + $this->assertSitemapIndexUrl( + ['route_path' => 'shop', 'no_route' => true], + '/category/outer' + ); + } + + /** + * 주어진 상점 주소 설정에서 색인된 카테고리 URL 이 기대값과 같은지 검증합니다. + * + * @param array $basicInfo 주입할 `basic_info` 설정 + * @param string $expectedUrl 기대하는 색인 URL + */ + private function assertSitemapIndexUrl(array $basicInfo, string $expectedUrl): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', $basicInfo); + + $indexedUrl = null; + $indexer = Mockery::mock(SitemapIndexer::class); + $indexer->shouldReceive('indexResource') + ->once() + ->andReturnUsing(function (string $type, int $id, string $owner, array $urls) use (&$indexedUrl) { + $indexedUrl = $urls[0]['url'] ?? null; + }); + $this->app->instance(SitemapIndexer::class, $indexer); + + $this->app->instance(SeoCacheManagerInterface::class, $this->createMock(SeoCacheManagerInterface::class)); + Log::shouldReceive('debug')->atLeast()->once(); + + $category = (object) [ + 'id' => 42, + 'slug' => 'outer', + 'is_active' => true, + 'updated_at' => null, + ]; + + $this->listener->onCategoryChange($category); + + // 존재 확정 후 값 비교 — 색인 자체가 일어나지 않으면 URL 비교는 의미가 없다 + $this->assertNotNull($indexedUrl, '카테고리 사이트맵 색인이 수행되지 않았다'); + $this->assertSame($expectedUrl, $indexedUrl); + } + // ======================================== // handle() 메서드 테스트 // ======================================== diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoProductCacheListenerTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoProductCacheListenerTest.php index f40539b5..e169cfd7 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoProductCacheListenerTest.php +++ b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoProductCacheListenerTest.php @@ -7,6 +7,7 @@ use App\Seo\Contracts\SeoCacheManagerInterface; use App\Seo\SeoCacheRegenerator; use App\Seo\SitemapIndexer; use Illuminate\Support\Facades\Bus; +use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Log; use Mockery; use Modules\Sirsoft\Ecommerce\Listeners\SeoProductCacheListener; @@ -120,6 +121,35 @@ class SeoProductCacheListenerTest extends ModuleTestCase $this->addToAssertionCount(1); } + /** + * 주소 없이 운영하는 상점(no_route)의 SEO 캐시 경로는 세그먼트 없이 루트에 붙는다 (공개 #85) + * + * 종전에는 route_path 만 읽고 no_route 를 무시해 `/shop/products/7` 을 재생성했다 — + * 실제 화면 주소는 `/products/7` 이므로 봇이 받는 캐시가 영원히 채워지지 않는다. + */ + public function test_on_product_update_regenerates_root_path_when_no_route(): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', [ + 'route_path' => 'shop', + 'no_route' => true, + ]); + + $product = (object) ['id' => 7]; + + $this->expectCommonInvalidations($product); + + $this->regeneratorMock->shouldReceive('renderAndCache') + ->once() + ->with('/products/7') + ->andReturn(true); + + Log::shouldReceive('debug')->atLeast()->once(); + + $this->listener->onProductUpdate($product); + + $this->addToAssertionCount(1); + } + /** * 상품 수정 시 home과 search/index 캐시도 무효화되는지 확인 */ diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Seo/EcommerceSitemapContributorTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Seo/EcommerceSitemapContributorTest.php index f754ceb2..bb152419 100644 --- a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Seo/EcommerceSitemapContributorTest.php +++ b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Seo/EcommerceSitemapContributorTest.php @@ -82,6 +82,26 @@ class EcommerceSitemapContributorTest extends ModuleTestCase $this->assertContains('/shop/products', $urlPaths); } + /** + * getUrls: 주소 없이 운영하는 상점(no_route)은 세그먼트 없이 루트 경로를 싣는다 (공개 #85) + * + * route_path 만 읽고 no_route 를 무시하면 사이트맵이 `/shop/...` 을 검색엔진에 + * 제출하지만 실제 화면은 `/...` 이다 — 색인된 URL 전부가 404 로 수집된다. + */ + public function test_get_urls_omits_route_segment_when_no_route(): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', [ + 'route_path' => 'shop', + 'no_route' => true, + ]); + + $contributor = $this->app->make(EcommerceSitemapContributor::class); + $urlPaths = array_column($contributor->getUrls(), 'url'); + + $this->assertContains('/products', $urlPaths); + $this->assertNotContains('/shop/products', $urlPaths); + } + /** * getUrls: 정적/카테고리/상품 URL 항목이 각각 올바른 키 구조를 가진다 */ diff --git a/modules/_bundled/sirsoft-ecommerce/tests/Unit/Support/ShopPathResolverTest.php b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Support/ShopPathResolverTest.php new file mode 100644 index 00000000..8df6fd1d --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/tests/Unit/Support/ShopPathResolverTest.php @@ -0,0 +1,99 @@ + $basicInfo basic_info 설정 값 + */ + private function setBasicInfo(array $basicInfo): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', $basicInfo); + } + + #[Test] + public function 설정이_없으면_기본_상점_주소로_폴백한다(): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce', []); + + $this->assertSame('/shop', ShopPathResolver::base()); + $this->assertSame('/shop/products/A1', ShopPathResolver::path('products/A1')); + } + + #[Test] + public function 운영자가_바꾼_주소를_반영한다(): void + { + $this->setBasicInfo(['route_path' => 'store']); + + $this->assertSame('/store', ShopPathResolver::base()); + $this->assertSame('/store/orders/20260806-0001/complete', ShopPathResolver::path('orders/20260806-0001/complete')); + } + + #[Test] + public function 주소_없이_운영하면_루트에_붙는다(): void + { + $this->setBasicInfo(['route_path' => 'shop', 'no_route' => true]); + + $this->assertSame('', ShopPathResolver::base()); + $this->assertSame('/products/A1', ShopPathResolver::path('products/A1')); + $this->assertSame('/', ShopPathResolver::path('')); + } + + #[Test] + public function 주소가_빈_문자열이면_기본값으로_폴백한다(): void + { + $this->setBasicInfo(['route_path' => '']); + + $this->assertSame('/shop', ShopPathResolver::base()); + $this->assertSame('/shop/guest/orders', ShopPathResolver::path('guest/orders')); + } + + #[Test] + public function 앞뒤_슬래시가_붙은_주소도_한_겹으로_정규화한다(): void + { + $this->setBasicInfo(['route_path' => '/store/']); + + $this->assertSame('/store', ShopPathResolver::base()); + $this->assertSame('/store/products', ShopPathResolver::path('/products')); + $this->assertSame('/store/products', ShopPathResolver::path('products')); + } + + #[Test] + public function no_route_가_꺼져_있으면_주소를_유지한다(): void + { + $this->setBasicInfo(['route_path' => 'store', 'no_route' => false]); + + $this->assertSame('/store', ShopPathResolver::base()); + $this->assertSame('/store/category/tops', ShopPathResolver::path('category/tops')); + } +} diff --git a/modules/_bundled/sirsoft-ecommerce/tests/scenarios/shop-route-path-server-urls.yaml b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/shop-route-path-server-urls.yaml new file mode 100644 index 00000000..c0d6d31f --- /dev/null +++ b/modules/_bundled/sirsoft-ecommerce/tests/scenarios/shop-route-path-server-urls.yaml @@ -0,0 +1,84 @@ +# audit:allow test-scenario-coverage reason: | +# cross product 자동 전개는 audit 실행 환경에 js-yaml 이 없어 fallback YAML 파서가 +# nested axes 배열을 읽지 못하는 한계로 검출되지 않는다(동일 한계로 다른 번들 시나리오도 +# audit:allow 처리됨). 아래 조합은 PHPUnit 5종(해석기 단위 / 주문 생성 Feature / +# 비회원 조회 안내 / 알림 메일 / 통합검색 / SEO·사이트맵)으로 전수 커버되어 green 이다. +# 프론트는 서버 값 우선 + 폴백 구조라 변경이 없어 레이아웃·E2E 축을 두지 않는다. +feature: 서버가 만드는 상점 주소의 route_path/no_route 반영 (공개 #85) + +description: | + 상점 주소는 운영자 설정이다 — `basic_info.route_path` 로 바꿀 수 있고, + `basic_info.no_route` 를 켜면 주소 세그먼트 없이 루트에 붙는다. 그런데 서버가 만들어 + 내보내던 상점 주소는 각 지점에서 `/shop` 리터럴이나 `"/{$routePath}/..."` 조립으로 + 흩어져 있었다. + + 기본값이 아닌 상점에서는 그 주소가 존재하지 않는 화면을 가리키는데, 서버는 문자열을 + 만들어 내려보냈을 뿐이라 예외도 404 로그도 남지 않는다 — 링크만 조용히 죽는다. + + ShopPathResolver 를 단일 해석 지점으로 두고 서버 생성 주소 전 지점을 경유시킨다. + 프론트 소비처(_checkout_summary.json)는 서버 값 우선 + `_global.shopBase` 폴백 + 구조라 변경하지 않는다. + + 범위 제외: PG 플러그인 4종의 `redirect_success_url` 설정 기본값 (후속 이슈 분리). + +axes: + route_setting: + - default # route_path 미설정/기본값 'shop' + - custom # 운영자가 바꾼 주소 (예: 'store') + - no_route # 주소 없이 루트 운영 + - empty_value # route_path 빈 문자열 → 기본값 폴백 + - slashed_value # 앞뒤 슬래시 포함 값 → 한 겹 정규화 + surface: + - order_complete_redirect # 주문 생성 응답 redirect_url + - guest_lookup_redirect # 비회원 주문 404 응답 redirect_to + - notification_order_url # 알림 메일 비회원 주문 조회 URL + - search_product_url # 통합검색 상품 링크 + - inquiry_product_url # 상품문의 목록의 상품 링크 + - seo_detail_cache # 상품 상세 SEO 캐시 재생성 경로 + - seo_sitemap_index # 사이트맵 상품/카테고리/목록 URL + order_actor: + - guest + - member + +exclusions: + - { surface: guest_lookup_redirect, order_actor: member, reason: "회원 분기는 /mypage/orders 로 상점 주소와 무관" } + - { surface: notification_order_url, order_actor: member, reason: "회원 알림은 마이페이지 URL 사용" } + - { surface: search_product_url, order_actor: member, reason: "검색 링크는 주문 주체와 무관" } + - { surface: inquiry_product_url, order_actor: member, reason: "문의 링크는 주문 주체와 무관" } + - { surface: seo_detail_cache, order_actor: member, reason: "봇 렌더 경로라 주문 주체 없음" } + - { surface: seo_sitemap_index, order_actor: member, reason: "봇 렌더 경로라 주문 주체 없음" } + +effects: + # 해석 규칙 (SSoT) + - resolver_falls_back_to_default_shop_when_unset # 설정 없음 → /shop + - resolver_reflects_custom_route_path # 변경 주소 반영 + - resolver_returns_empty_base_when_no_route # no_route → 기준 경로 빈 문자열 + - resolver_falls_back_when_route_path_is_blank # 빈 문자열 → 기본값 + - resolver_normalizes_duplicate_slashes # 슬래시 중복 한 겹 정규화 + - resolver_keeps_route_when_no_route_is_false # no_route=false 는 주소 유지 + # 소비 지점 + - order_complete_redirect_follows_route_path # 주문 완료 이동 주소 + - order_complete_redirect_drops_segment_when_no_route # no_route 시 루트 경로 + - guest_lookup_redirect_follows_route_path # 비회원 조회 안내 404 응답 + - guest_lookup_redirect_drops_segment_when_no_route + - notification_guest_order_url_follows_route_path # 알림 메일 조회 링크 + - search_product_url_follows_route_path # 통합검색 상품 링크 + - inquiry_product_url_follows_no_route # 상품문의 목록의 상품 링크 + - seo_detail_cache_path_follows_no_route # SEO 캐시 재생성 경로 + - sitemap_urls_omit_segment_when_no_route # 사이트맵 URL + - category_sitemap_index_url_follows_route_path # 카테고리 사이트맵 증분 색인 URL + # 회귀 + - default_shop_urls_unchanged # 기본값 상점의 주소는 종전과 동일 + +test_files: + - modules/_bundled/sirsoft-ecommerce/tests/Unit/Support/ShopPathResolverTest.php + - modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/OrderControllerTest.php + - modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/EcommerceNotificationDataListenerTest.php + - modules/_bundled/sirsoft-ecommerce/tests/Feature/Search/ProductSearchIntegrationTest.php + - modules/_bundled/sirsoft-ecommerce/tests/Feature/Http/Controllers/Public/UserInquiryControllerTest.php + - modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoProductCacheListenerTest.php + - modules/_bundled/sirsoft-ecommerce/tests/Unit/Listeners/SeoCategoryCacheListenerTest.php + - modules/_bundled/sirsoft-ecommerce/tests/Unit/Seo/EcommerceSitemapContributorTest.php + +validation: + audit_rule: test-scenario-coverage diff --git a/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md b/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md index e18a9b3c..08f2f0ca 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-pay_kginicis/CHANGELOG.md @@ -22,6 +22,8 @@ ### Fixed + +- 쇼핑몰 주소를 기본값이 아닌 값으로 바꾸거나 주소 없이 운영하는 상점에서, 결제를 마치거나 결제에 실패한 구매자가 존재하지 않는 페이지로 이동하던 문제를 수정했습니다. 이동 주소가 기본 주소로 고정돼 있었기 때문이며, 이제 상점 주소 설정을 따라갑니다. 이미 운영 중인 사이트도 업데이트 시 자동으로 반영되며, 이동 주소를 직접 입력해 두었다면 그 값은 그대로 유지됩니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) - 안내 메시지가 번역되지 않고 내부 코드 그대로 표시되던 문제를 수정했습니다. 일본 편의점결제(CVS) 입금 통보 테스트·입금기한 만료 처리뿐 아니라 에스크로 배송 등록·구매확인 거부, 거래 조회, 정산 마감 등 이 플러그인의 모든 처리 결과에서 사용 중인 언어에 맞는 안내가 표시됩니다. - 일본(CBT) 설정을 운영 모드로 전환할 때 상점 정보나 서명키가 비어 있어도 저장되던 문제를 수정했습니다. 필수값이 비었거나 샘플값이 그대로면 저장이 중단되고 안내 메시지가 표시됩니다. - 이 플러그인이 설치된 사이트에서 관리자 주문 목록의 '일부취소' 표시와 적립예정 포인트·마일리지 사용 금액, 주문상품의 추가옵션 요약이 보이지 않던 문제를 수정했습니다. 결제 정보 칸에 테스트결제 표시를 덧붙이는 과정에서 목록 표 구성 전체를 옛 버전으로 되돌려 놓고 있었습니다. diff --git a/plugins/_bundled/sirsoft-pay_kginicis/config/settings/defaults.json b/plugins/_bundled/sirsoft-pay_kginicis/config/settings/defaults.json index 882af8bd..06967229 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/config/settings/defaults.json +++ b/plugins/_bundled/sirsoft-pay_kginicis/config/settings/defaults.json @@ -29,8 +29,8 @@ "japan_contact_email": "support@example.com", "japan_contact_phone": "0120-123-456", "japan_contact_opening_hours": "10:00-18:00", - "redirect_success_url": "/shop/orders/{orderId}/complete", - "redirect_fail_url": "/shop/checkout", + "redirect_success_url": "{shopBase}/orders/{orderId}/complete", + "redirect_fail_url": "{shopBase}/checkout", "easy_pay_allow_with_other_pg": false, "easy_pay_samsung_pay": false, "easy_pay_naverpay": false, diff --git a/plugins/_bundled/sirsoft-pay_kginicis/docs/api/cbt.md b/plugins/_bundled/sirsoft-pay_kginicis/docs/api/cbt.md index 69b9118d..52901f52 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/docs/api/cbt.md +++ b/plugins/_bundled/sirsoft-pay_kginicis/docs/api/cbt.md @@ -125,7 +125,7 @@ _단건 응답: `data` 객체의 필드._ | product_id | integer | `114` | product 식별자 (연관 리소스 참조) | | product_code | string | `CBT-TEST-20260712085816` | 생성된 테스트 상품의 상품코드. `CBT-TEST-` 접두사에 생성 시각(YmdHis)을 붙여 자동 부여되며, SKU는 여기에 `KGINICIS-` 접두사를 더해 만들어진다. | | admin_url | string | `/admin/ecommerce/products/114/edit` | admin URL | -| shop_url | string | `/shop/products/114?locale=ja` | shop URL | +| shop_url | string | `/shop/products/114?locale=ja` | 생성된 테스트 상품의 상점 화면 주소. 앞부분은 상점 주소 설정을 따른다 — 기본은 `/shop`, 이커머스 모듈 설정 `basic_info.route_path` 를 바꾸면 그 값(`/store/...`), `basic_info.no_route` 를 켜면 세그먼트 없이 루트에 붙는다(`/products/114?locale=ja`). 예시는 기본 설정 기준. | **응답 예시** diff --git a/plugins/_bundled/sirsoft-pay_kginicis/docs/api/payment.md b/plugins/_bundled/sirsoft-pay_kginicis/docs/api/payment.md index 951648f0..a75bb675 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/docs/api/payment.md +++ b/plugins/_bundled/sirsoft-pay_kginicis/docs/api/payment.md @@ -392,8 +392,8 @@ _이 엔드포인트는 JSON `data` 를 반환하지 않습니다. 브라우저 | 리다이렉트 대상 | 조건 | 쿼리 파라미터 | | --- | --- | --- | -| 성공 URL (`redirect_success_url`, 기본 `/shop/orders/{orderId}/complete`) | 서버 승인 성공(결제완료 또는 가상계좌 발급), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | -| 실패 URL (`redirect_fail_url`, 기본 `/shop/checkout`) | 인증 실패·검증 실패·승인 실패 | `error` (`invalid_params` \| `missing_fields` \| `auth_url_invalid` \| `order_not_found` \| `amount_mismatch` 등), `message` (PG 결과 메시지), `orderId` | +| 성공 URL (`redirect_success_url`, 기본 `{shopBase}/orders/{orderId}/complete`) | 서버 승인 성공(결제완료 또는 가상계좌 발급), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | +| 실패 URL (`redirect_fail_url`, 기본 `{shopBase}/checkout`) | 인증 실패·검증 실패·승인 실패 | `error` (`invalid_params` \| `missing_fields` \| `auth_url_invalid` \| `order_not_found` \| `amount_mismatch` 등), `message` (PG 결과 메시지), `orderId` | | 실패 URL (쿼리 없음) | 사용자가 결제창을 닫은 취소(`2001` / `0021` / `0022` / 빈값, 또는 결과 메시지에 '취소'·'사용자' 포함) | 없음 (조용한 복귀) | **응답 예시** @@ -461,8 +461,8 @@ _이 엔드포인트는 JSON `data` 를 반환하지 않습니다. 브라우저 | 리다이렉트 대상 | 조건 | 쿼리 파라미터 | | --- | --- | --- | -| 성공 URL (`redirect_success_url`, 기본 `/shop/orders/{orderId}/complete`) | CBT 서버 승인 성공(결제완료 또는 편의점 입금대기 등록), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | -| 실패 URL (`redirect_fail_url`, 기본 `/shop/checkout`) | 인증 실패·MID 불일치·검증 실패·승인 실패 | `error` (`invalid_params` \| `mid_mismatch` \| `order_not_found` \| `cbt_failed` 등), `message` (PG 결과 메시지), `orderId` | +| 성공 URL (`redirect_success_url`, 기본 `{shopBase}/orders/{orderId}/complete`) | CBT 서버 승인 성공(결제완료 또는 편의점 입금대기 등록), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | +| 실패 URL (`redirect_fail_url`, 기본 `{shopBase}/checkout`) | 인증 실패·MID 불일치·검증 실패·승인 실패 | `error` (`invalid_params` \| `mid_mismatch` \| `order_not_found` \| `cbt_failed` 등), `message` (PG 결과 메시지), `orderId` | | 실패 URL (쿼리 없음) | 사용자 취소(취소 코드 또는 일본어·한국어 취소 문구) | 없음 (조용한 복귀) | **응답 예시** @@ -543,8 +543,8 @@ _이 엔드포인트는 JSON `data` 를 반환하지 않습니다. 브라우저 | 리다이렉트 대상 | 조건 | 쿼리 파라미터 | | --- | --- | --- | -| 성공 URL (`redirect_success_url`, 기본 `/shop/orders/{orderId}/complete`) | CBT 서버 승인 성공(결제완료 또는 편의점 입금대기 등록), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | -| 실패 URL (`redirect_fail_url`, 기본 `/shop/checkout`) | 인증 실패·MID 불일치·검증 실패·승인 실패 | `error` (`invalid_params` \| `mid_mismatch` \| `order_not_found` \| `cbt_failed` 등), `message` (PG 결과 메시지), `orderId` | +| 성공 URL (`redirect_success_url`, 기본 `{shopBase}/orders/{orderId}/complete`) | CBT 서버 승인 성공(결제완료 또는 편의점 입금대기 등록), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | +| 실패 URL (`redirect_fail_url`, 기본 `{shopBase}/checkout`) | 인증 실패·MID 불일치·검증 실패·승인 실패 | `error` (`invalid_params` \| `mid_mismatch` \| `order_not_found` \| `cbt_failed` 등), `message` (PG 결과 메시지), `orderId` | | 실패 URL (쿼리 없음) | 사용자 취소(취소 코드 또는 일본어·한국어 취소 문구) | 없음 (조용한 복귀) | **응답 예시** @@ -968,8 +968,8 @@ _이 엔드포인트는 JSON `data` 를 반환하지 않습니다. 브라우저 | 리다이렉트 대상 | 조건 | 쿼리 파라미터 | | --- | --- | --- | -| 성공 URL (`redirect_success_url`, 기본 `/shop/orders/{orderId}/complete`) | 서버 승인 성공(결제완료 또는 가상계좌 발급), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | -| 실패 URL (`redirect_fail_url`, 기본 `/shop/checkout`) | 인증 실패·검증 실패·승인 실패 | `error` (`order_id_missing` \| `missing_fields` \| `req_url_invalid` \| `order_not_found` \| `amount_mismatch` 등), `message` (`P_RMESG1` 결과 메시지), `orderId` | +| 성공 URL (`redirect_success_url`, 기본 `{shopBase}/orders/{orderId}/complete`) | 서버 승인 성공(결제완료 또는 가상계좌 발급), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | +| 실패 URL (`redirect_fail_url`, 기본 `{shopBase}/checkout`) | 인증 실패·검증 실패·승인 실패 | `error` (`order_id_missing` \| `missing_fields` \| `req_url_invalid` \| `order_not_found` \| `amount_mismatch` 등), `message` (`P_RMESG1` 결과 메시지), `orderId` | | 실패 URL (쿼리 없음) | 사용자가 결제창을 닫은 취소(`P_RMESG1` 에 '사용자가 결제를 취소' 등 취소 문구 포함) | 없음 (조용한 복귀) | **응답 예시** @@ -1046,8 +1046,8 @@ _이 엔드포인트는 JSON `data` 를 반환하지 않습니다. 브라우저 | 리다이렉트 대상 | 조건 | 쿼리 파라미터 | | --- | --- | --- | -| 성공 URL (`redirect_success_url`, 기본 `/shop/orders/{orderId}/complete`) | 서버 승인 성공(결제완료 또는 가상계좌 발급), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | -| 실패 URL (`redirect_fail_url`, 기본 `/shop/checkout`) | 인증 실패·검증 실패·승인 실패 | `error` (`order_id_missing` \| `missing_fields` \| `req_url_invalid` \| `order_not_found` \| `amount_mismatch` 등), `message` (`P_RMESG1` 결과 메시지), `orderId` | +| 성공 URL (`redirect_success_url`, 기본 `{shopBase}/orders/{orderId}/complete`) | 서버 승인 성공(결제완료 또는 가상계좌 발급), 이미 결제완료된 거래(재전송) | 없음 (주문번호는 경로에 치환) | +| 실패 URL (`redirect_fail_url`, 기본 `{shopBase}/checkout`) | 인증 실패·검증 실패·승인 실패 | `error` (`order_id_missing` \| `missing_fields` \| `req_url_invalid` \| `order_not_found` \| `amount_mismatch` 등), `message` (`P_RMESG1` 결과 메시지), `orderId` | | 실패 URL (쿼리 없음) | 사용자가 결제창을 닫은 취소(`P_RMESG1` 에 취소 문구 포함) | 없음 (조용한 복귀) | **응답 예시** diff --git a/plugins/_bundled/sirsoft-pay_kginicis/plugin.php b/plugins/_bundled/sirsoft-pay_kginicis/plugin.php index 6b136fd0..44679b73 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/plugin.php +++ b/plugins/_bundled/sirsoft-pay_kginicis/plugin.php @@ -204,16 +204,16 @@ class Plugin extends AbstractPlugin ], 'redirect_success_url' => [ 'type' => 'string', - 'default' => '/shop/orders/{orderId}/complete', + 'default' => '{shopBase}/orders/{orderId}/complete', 'label' => ['ko' => '결제 성공 리다이렉트 URL', 'en' => 'Payment Success Redirect URL'], 'hint' => [ - 'ko' => '상대 경로(/shop/...) 또는 전체 URL(https://...) 모두 가능합니다. {orderId}는 주문번호로 자동 치환됩니다.', - 'en' => 'Supports relative paths or full URLs. {orderId} will be replaced with the actual order number.', + 'ko' => '{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL(https://...)을 직접 넣어도 됩니다. {orderId}는 주문번호로 자동 치환됩니다.', + 'en' => '{shopBase} is filled in from the storefront address setting. You may also enter a full URL (https://...). {orderId} will be replaced with the actual order number.', ], ], 'redirect_fail_url' => [ 'type' => 'string', - 'default' => '/shop/checkout', + 'default' => '{shopBase}/checkout', 'label' => ['ko' => '결제 실패 리다이렉트 URL', 'en' => 'Payment Failure Redirect URL'], 'hint' => [ 'ko' => '상대 경로 또는 전체 URL 모두 가능합니다. 오류 정보는 쿼리 파라미터로 자동 추가됩니다.', @@ -290,8 +290,8 @@ class Plugin extends AbstractPlugin 'japan_contact_email' => 'support@example.com', 'japan_contact_phone' => '0120-123-456', 'japan_contact_opening_hours' => '10:00-18:00', - 'redirect_success_url' => '/shop/orders/{orderId}/complete', - 'redirect_fail_url' => '/shop/checkout', + 'redirect_success_url' => '{shopBase}/orders/{orderId}/complete', + 'redirect_fail_url' => '{shopBase}/checkout', 'easy_pay_allow_with_other_pg' => false, 'easy_pay_samsung_pay' => false, 'easy_pay_naverpay' => false, diff --git a/plugins/_bundled/sirsoft-pay_kginicis/resources/lang/en.json b/plugins/_bundled/sirsoft-pay_kginicis/resources/lang/en.json index ba04b3f7..403495e3 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/resources/lang/en.json +++ b/plugins/_bundled/sirsoft-pay_kginicis/resources/lang/en.json @@ -301,7 +301,7 @@ "use_escrow_hint": "When enabled, PC payments append useescrow to acceptmethod and mobile payments append useescrow=Y to P_RESERVED.", "section_redirect": "Redirect URLs", "redirect_success_url": "Payment Success Redirect URL", - "redirect_success_url_hint": "Supports relative paths or full URLs. {orderId} will be replaced with the actual order number.", + "redirect_success_url_hint": "{shopBase} is filled in from the storefront address setting. You may also enter a full URL (https://...). {orderId} will be replaced with the actual order number.", "redirect_fail_url": "Payment Failure Redirect URL", "redirect_fail_url_hint": "Supports relative paths or full URLs. Error details are appended as query parameters.", "section_vbank_notify": "Virtual Account Deposit Notification URL (PC)", diff --git a/plugins/_bundled/sirsoft-pay_kginicis/resources/lang/ko.json b/plugins/_bundled/sirsoft-pay_kginicis/resources/lang/ko.json index 0e36451b..c6b64e78 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/resources/lang/ko.json +++ b/plugins/_bundled/sirsoft-pay_kginicis/resources/lang/ko.json @@ -304,7 +304,7 @@ "use_escrow_hint": "활성화 시 PC는 acceptmethod에 useescrow가 추가되고, 모바일은 P_RESERVED에 useescrow=Y가 추가됩니다.", "section_redirect": "리다이렉트 URL", "redirect_success_url": "결제 성공 리다이렉트 URL", - "redirect_success_url_hint": "상대 경로(/shop/...) 또는 전체 URL 모두 가능합니다. {orderId}는 주문번호로 자동 치환됩니다.", + "redirect_success_url_hint": "{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL(https://...)을 직접 넣어도 됩니다. {orderId}는 주문번호로 자동 치환됩니다.", "redirect_fail_url": "결제 실패 리다이렉트 URL", "redirect_fail_url_hint": "상대 경로 또는 전체 URL 모두 가능합니다. 오류 정보는 쿼리 파라미터로 자동 추가됩니다.", "section_vbank_notify": "가상계좌 입금통보 URL (PC)", diff --git a/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/AdminCbtTestProductController.php b/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/AdminCbtTestProductController.php index c3096ec4..cf8629a0 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/AdminCbtTestProductController.php +++ b/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/AdminCbtTestProductController.php @@ -9,6 +9,7 @@ use App\Http\Controllers\Api\Base\AdminBaseController; use Illuminate\Http\JsonResponse; use Illuminate\Support\Facades\Log; use Modules\Sirsoft\Ecommerce\Services\ProductService; +use Modules\Sirsoft\Ecommerce\Support\ShopPathResolver; /** * KG 이니시스 CBT (일본 결제) 테스트용 상품 자동 생성 컨트롤러 @@ -80,7 +81,8 @@ class AdminCbtTestProductController extends AdminBaseController 'product_id' => $product->id, 'product_code' => $product->product_code, 'admin_url' => '/admin/ecommerce/products/'.$product->id.'/edit', - 'shop_url' => '/shop/products/'.$product->id.'?locale=ja', + // 상점 주소는 운영자 설정이라 리터럴로 두면 주소를 바꾼 상점에서 없는 페이지를 가리킨다. + 'shop_url' => ShopPathResolver::path('products/'.$product->id).'?locale=ja', ]); } catch (\Throwable $e) { Log::error('KG Inicis CBT: test product creation failed', [ diff --git a/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/CbtCallbackController.php b/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/CbtCallbackController.php index af5ce159..49cee8c8 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/CbtCallbackController.php +++ b/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/CbtCallbackController.php @@ -14,10 +14,11 @@ use Modules\Sirsoft\Ecommerce\Services\OrderProcessingService; use Plugins\Sirsoft\PayKginicis\Concerns\IssuesReceiptCookie; use Plugins\Sirsoft\PayKginicis\Concerns\PreventsReplayCallback; use Plugins\Sirsoft\PayKginicis\Concerns\SerializesPaymentCallbacks; -use Plugins\Sirsoft\PayKginicis\Http\Requests\CbtCallbackRequest; use Plugins\Sirsoft\PayKginicis\Concerns\ValidatesCbtOrderContext; +use Plugins\Sirsoft\PayKginicis\Http\Requests\CbtCallbackRequest; use Plugins\Sirsoft\PayKginicis\Services\CbtReconciliationService; use Plugins\Sirsoft\PayKginicis\Services\KgInicisApiService; +use Plugins\Sirsoft\PayKginicis\Support\ShopRedirectUrl; /** * KG 이니시스 CBT (Cross Border Trade) 일본 결제 콜백 컨트롤러 @@ -693,15 +694,15 @@ class CbtCallbackController private function resolveSuccessUrl(string $orderId): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $urlTemplate = $settings['redirect_success_url'] ?? '/shop/orders/{orderId}/complete'; + $urlTemplate = $settings['redirect_success_url'] ?? ShopRedirectUrl::DEFAULT_SUCCESS_URL; - return $this->absolutize(str_replace('{orderId}', $orderId, $urlTemplate)); + return $this->absolutize(ShopRedirectUrl::resolve($urlTemplate, ['{orderId}' => $orderId])); } private function resolveFailUrl(array $queryParams = []): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $baseUrl = $this->absolutize($settings['redirect_fail_url'] ?? '/shop/checkout'); + $baseUrl = $this->absolutize(ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL)); if (empty($queryParams)) { return $baseUrl; diff --git a/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/MobileCallbackController.php b/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/MobileCallbackController.php index 79ffd303..91ec975f 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/MobileCallbackController.php +++ b/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/MobileCallbackController.php @@ -6,6 +6,7 @@ namespace Plugins\Sirsoft\PayKginicis\Controllers; use App\Services\PluginSettingsService; use Carbon\Carbon; +use Illuminate\Http\RedirectResponse; use Illuminate\Support\Facades\Log; use Modules\Sirsoft\Ecommerce\Enums\PaymentStatusEnum; use Modules\Sirsoft\Ecommerce\Exceptions\PaymentAmountMismatchException; @@ -19,6 +20,7 @@ use Plugins\Sirsoft\PayKginicis\Concerns\SerializesPaymentCallbacks; use Plugins\Sirsoft\PayKginicis\Concerns\ValidatesCbtOrderContext; use Plugins\Sirsoft\PayKginicis\Http\Requests\MobileCallbackRequest; use Plugins\Sirsoft\PayKginicis\Services\KgInicisApiService; +use Plugins\Sirsoft\PayKginicis\Support\ShopRedirectUrl; /** * KG 이니시스 모바일 결제 콜백 컨트롤러 @@ -90,23 +92,23 @@ class MobileCallbackController * handle * * @param MobileCallbackRequest $request - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function handle(MobileCallbackRequest $request): \Illuminate\Http\RedirectResponse + public function handle(MobileCallbackRequest $request): RedirectResponse { $validated = $request->validated(); $selectedEasyPayMethod = $this->resolveSelectedEasyPayMethod($request); - $pStatus = $validated['P_STATUS']; + $pStatus = $validated['P_STATUS']; // KG 이니시스 모바일 메뉴얼(STEP 2) 표준 응답에는 P_OID 가 없으므로 P_NEXT_URL 쿼리스트링의 // orderId 를 fallback 으로 사용한다. 일부 PG 환경에서 P_OID 를 echo 하면 우선 채택. - $moid = $validated['P_OID'] ?? $request->query('orderId') ?? null; - $pAmt = $validated['P_AMT'] ?? null; + $moid = $validated['P_OID'] ?? $request->query('orderId') ?? null; + $pAmt = $validated['P_AMT'] ?? null; Log::info('KG Inicis mobile: callback received', [ - 'order_id' => $moid, - 'P_STATUS' => $pStatus, - 'idc_name' => $validated['idc_name'] ?? null, + 'order_id' => $moid, + 'P_STATUS' => $pStatus, + 'idc_name' => $validated['idc_name'] ?? null, 'P_REQ_URL' => $validated['P_REQ_URL'] ?? null, 'input_keys' => array_keys($request->all()), 'query_keys' => array_keys($request->query()), @@ -127,9 +129,9 @@ class MobileCallbackController $isUserCancel = $this->isUserCancelMessage($pMesg); Log::info('KG Inicis mobile: auth not success', [ - 'P_OID' => $moid, - 'P_STATUS' => $pStatus, - 'P_RMESG1' => $pMesg, + 'P_OID' => $moid, + 'P_STATUS' => $pStatus, + 'P_RMESG1' => $pMesg, 'is_user_cancel' => $isUserCancel, ]); @@ -139,21 +141,21 @@ class MobileCallbackController } return redirect($this->resolveFailUrl([ - 'error' => $pStatus, + 'error' => $pStatus, 'message' => $pMesg, 'orderId' => $moid, ])); } - $pTid = $validated['P_TID'] ?? null; + $pTid = $validated['P_TID'] ?? null; $idcName = $validated['idc_name'] ?? null; - $reqUrl = $validated['P_REQ_URL'] ?? null; + $reqUrl = $validated['P_REQ_URL'] ?? null; if (! $pTid || ! $idcName || ! $reqUrl) { Log::error('KG Inicis mobile: missing required fields', [ - 'P_OID' => $moid, + 'P_OID' => $moid, 'idc_name' => $idcName, - 'P_TID' => $pTid, + 'P_TID' => $pTid, 'P_REQ_URL' => $reqUrl, ]); @@ -163,7 +165,7 @@ class MobileCallbackController // P_REQ_URL 화이트리스트 검증 (모바일 IDC URL, SSRF 방어) if (! $this->apiService->isValidIdcAuthUrl($idcName, $reqUrl)) { Log::error('KG Inicis mobile: P_REQ_URL not in whitelist (possible SSRF attempt)', [ - 'P_OID' => $moid, + 'P_OID' => $moid, 'idc_name' => $idcName, 'received' => $reqUrl, ]); @@ -196,7 +198,7 @@ class MobileCallbackController if ($resultStatus !== '00') { Log::warning('KG Inicis mobile: server approve failed', [ - 'P_OID' => $moid, + 'P_OID' => $moid, 'P_STATUS' => $resultStatus, 'P_RMESG1' => $result['P_RMESG1'] ?? '', ]); @@ -204,15 +206,15 @@ class MobileCallbackController $this->orderService->failPayment($order, $resultStatus, $result['P_RMESG1'] ?? ''); return redirect($this->resolveFailUrl([ - 'error' => $resultStatus, + 'error' => $resultStatus, 'message' => $result['P_RMESG1'] ?? '', 'orderId' => $moid, ])); } - $tid = $result['P_TID'] ?? $pTid; + $tid = $result['P_TID'] ?? $pTid; $totPrice = (int) ($result['P_AMT'] ?? $pAmt ?? 0); - $payType = (string) ($result['P_TYPE'] ?? ''); + $payType = (string) ($result['P_TYPE'] ?? ''); // 가상계좌: completePayment 없이 발급 정보만 저장 (입금 통보 시점에 completePayment) if (strcasecmp($payType, 'VBank') === 0) { @@ -258,24 +260,24 @@ class MobileCallbackController ]); $this->orderService->completePayment($order, [ - 'transaction_id' => $tid, - 'card_approval_number' => $result['P_APPL_NUM'] ?? null, - 'card_number_masked' => $result['P_CARD_NUM'] ?? null, - 'card_name' => $result['P_CARD_ISSUER_NAME'] ?? null, + 'transaction_id' => $tid, + 'card_approval_number' => $result['P_APPL_NUM'] ?? null, + 'card_number_masked' => $result['P_CARD_NUM'] ?? null, + 'card_name' => $result['P_CARD_ISSUER_NAME'] ?? null, 'card_installment_months' => (int) ($result['P_CARD_QUOTA'] ?? 0), - 'is_interest_free' => false, - 'embedded_pg_provider' => $embeddedPgProvider, - 'receipt_url' => null, - 'payment_meta' => array_merge([ - 'result_code' => $resultStatus, - 'pay_method' => $payType ?: null, - 'auth_date' => $result['P_AUTH_DT'] ?? null, - 'mid' => $this->apiService->getMid(), - 'is_test_mode' => $this->apiService->isTestMode(), + 'is_interest_free' => false, + 'embedded_pg_provider' => $embeddedPgProvider, + 'receipt_url' => null, + 'payment_meta' => array_merge([ + 'result_code' => $resultStatus, + 'pay_method' => $payType ?: null, + 'auth_date' => $result['P_AUTH_DT'] ?? null, + 'mid' => $this->apiService->getMid(), + 'is_test_mode' => $this->apiService->isTestMode(), 'pg_response_sanitized' => true, 'pg_raw_response' => $this->sanitizePgResponse($result, self::MOBILE_APPROVE_RESPONSE_KEYS), ], $this->buildEasyPayPaymentMeta($selectedEasyPayMethod)), - 'payment_device' => 'mobile', + 'payment_device' => 'mobile', ], $totPrice); $order->payment()->update(['pg_provider' => 'kginicis']); @@ -285,9 +287,9 @@ class MobileCallbackController } catch (PaymentAmountMismatchException $e) { Log::error('KG Inicis mobile: amount mismatch', [ - 'P_OID' => $moid, + 'P_OID' => $moid, 'expected' => $e->getExpectedAmount(), - 'actual' => $e->getActualAmount(), + 'actual' => $e->getActualAmount(), ]); $this->autoCancelIfApproved($approvedTid, $moid, $approvedTotPrice, 'amount_mismatch'); @@ -316,7 +318,7 @@ class MobileCallbackController $this->autoCancelIfApproved($approvedTid, $moid, $approvedTotPrice, 'approve_failed'); return redirect($this->resolveFailUrl([ - 'error' => 'approve_failed', + 'error' => 'approve_failed', 'message' => $e->getMessage(), 'orderId' => $moid, ])); @@ -350,24 +352,24 @@ class MobileCallbackController $tid, 'Card', null, - 'auto-cancel: ' . $reason, + 'auto-cancel: '.$reason, $totPrice > 0 ? $totPrice : null, ); Log::warning('KG Inicis mobile: auto-cancel after post-approve failure', [ - 'tid' => $tid, - 'P_OID' => $moid, - 'amount' => $totPrice, - 'reason' => $reason, + 'tid' => $tid, + 'P_OID' => $moid, + 'amount' => $totPrice, + 'reason' => $reason, 'pg_result' => $result, ]); } catch (\Throwable $e) { Log::error('KG Inicis mobile: auto-cancel FAILED — manual reconciliation required', [ - 'tid' => $tid, - 'P_OID' => $moid, + 'tid' => $tid, + 'P_OID' => $moid, 'amount' => $totPrice, 'reason' => $reason, - 'error' => $e->getMessage(), + 'error' => $e->getMessage(), ]); } } @@ -387,38 +389,38 @@ class MobileCallbackController if ($vactDate && strlen((string) $vactDate) === 8) { try { - $vbankDueAt = Carbon::createFromFormat('YmdHis', $vactDate . $vactTime); + $vbankDueAt = Carbon::createFromFormat('YmdHis', $vactDate.$vactTime); } catch (\Exception) { $vbankDueAt = null; } } $order->payment()->update(array_filter([ - 'pg_provider' => 'kginicis', - 'payment_status' => PaymentStatusEnum::WAITING_DEPOSIT, - 'transaction_id' => $tid ?: null, - 'vbank_code' => $result['P_VACT_BANK_CODE'] ?? $result['P_FN_CD1'] ?? null, - 'vbank_name' => $result['P_VACT_BANK_NAME'] ?? $result['P_FN_NM'] ?? null, - 'vbank_number' => $result['P_VACT_NUM'] ?? null, - 'vbank_holder' => $result['P_VACT_NAME'] ?? $result['P_RVACTNM'] ?? null, - 'vbank_due_at' => $vbankDueAt, + 'pg_provider' => 'kginicis', + 'payment_status' => PaymentStatusEnum::WAITING_DEPOSIT, + 'transaction_id' => $tid ?: null, + 'vbank_code' => $result['P_VACT_BANK_CODE'] ?? $result['P_FN_CD1'] ?? null, + 'vbank_name' => $result['P_VACT_BANK_NAME'] ?? $result['P_FN_NM'] ?? null, + 'vbank_number' => $result['P_VACT_NUM'] ?? null, + 'vbank_holder' => $result['P_VACT_NAME'] ?? $result['P_RVACTNM'] ?? null, + 'vbank_due_at' => $vbankDueAt, 'vbank_issued_at' => now(), - 'payment_device' => 'mobile', - 'payment_meta' => [ - 'result_code' => $result['P_STATUS'] ?? '00', - 'pay_method' => 'VBank', - 'auth_date' => $result['P_AUTH_DT'] ?? null, - 'mid' => $this->apiService->getMid(), - 'is_test_mode' => $this->apiService->isTestMode(), + 'payment_device' => 'mobile', + 'payment_meta' => [ + 'result_code' => $result['P_STATUS'] ?? '00', + 'pay_method' => 'VBank', + 'auth_date' => $result['P_AUTH_DT'] ?? null, + 'mid' => $this->apiService->getMid(), + 'is_test_mode' => $this->apiService->isTestMode(), 'pg_response_sanitized' => true, 'pg_raw_response' => $this->sanitizePgResponse($result, self::MOBILE_VBANK_ISSUE_RESPONSE_KEYS), ], ], fn ($v) => $v !== null)); Log::info('KG Inicis mobile: vbank account issued', [ - 'P_OID' => $order->order_number, - 'P_TID' => $tid, - 'vbank_name' => $result['P_VACT_BANK_NAME'] ?? $result['P_FN_NM'] ?? null, + 'P_OID' => $order->order_number, + 'P_TID' => $tid, + 'vbank_name' => $result['P_VACT_BANK_NAME'] ?? $result['P_FN_NM'] ?? null, 'vbank_number' => $result['P_VACT_NUM'] ?? null, 'vbank_due_at' => $vbankDueAt?->toDateTimeString(), ]); @@ -427,15 +429,15 @@ class MobileCallbackController private function resolveSuccessUrl(string $orderId): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $urlTemplate = $settings['redirect_success_url'] ?? '/shop/orders/{orderId}/complete'; + $urlTemplate = $settings['redirect_success_url'] ?? ShopRedirectUrl::DEFAULT_SUCCESS_URL; - return $this->absolutize(str_replace('{orderId}', $orderId, $urlTemplate)); + return $this->absolutize(ShopRedirectUrl::resolve($urlTemplate, ['{orderId}' => $orderId])); } private function resolveFailUrl(array $queryParams = []): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $baseUrl = $this->absolutize($settings['redirect_fail_url'] ?? '/shop/checkout'); + $baseUrl = $this->absolutize(ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL)); if (empty($queryParams)) { return $baseUrl; @@ -444,7 +446,7 @@ class MobileCallbackController $query = http_build_query(array_filter($queryParams, fn ($v) => $v !== null && $v !== '')); $separator = str_contains($baseUrl, '?') ? '&' : '?'; - return $baseUrl . $separator . $query; + return $baseUrl.$separator.$query; } /** @@ -483,8 +485,8 @@ class MobileCallbackController } $base = rtrim((string) config('app.url'), '/'); - $path = $url === '' ? '/' : ($url[0] === '/' ? $url : '/' . $url); + $path = $url === '' ? '/' : ($url[0] === '/' ? $url : '/'.$url); - return $base . $path; + return $base.$path; } } diff --git a/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/PaymentCallbackController.php b/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/PaymentCallbackController.php index b359c92c..8872d5ad 100644 --- a/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/PaymentCallbackController.php +++ b/plugins/_bundled/sirsoft-pay_kginicis/src/Controllers/PaymentCallbackController.php @@ -27,6 +27,7 @@ use Plugins\Sirsoft\PayKginicis\Http\Requests\AuthCallbackRequest; use Plugins\Sirsoft\PayKginicis\Http\Requests\MobileVbankNotifyRequest; use Plugins\Sirsoft\PayKginicis\Http\Requests\VbankNotifyRequest; use Plugins\Sirsoft\PayKginicis\Services\KgInicisApiService; +use Plugins\Sirsoft\PayKginicis\Support\ShopRedirectUrl; /** * KG 이니시스 결제 콜백 컨트롤러 @@ -691,15 +692,15 @@ class PaymentCallbackController private function resolveSuccessUrl(string $orderId): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $urlTemplate = $settings['redirect_success_url'] ?? '/shop/orders/{orderId}/complete'; + $urlTemplate = $settings['redirect_success_url'] ?? ShopRedirectUrl::DEFAULT_SUCCESS_URL; - return $this->absolutize(str_replace('{orderId}', $orderId, $urlTemplate)); + return $this->absolutize(ShopRedirectUrl::resolve($urlTemplate, ['{orderId}' => $orderId])); } private function resolveFailUrl(array $queryParams = []): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $baseUrl = $this->absolutize($settings['redirect_fail_url'] ?? '/shop/checkout'); + $baseUrl = $this->absolutize(ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL)); if (empty($queryParams)) { return $baseUrl; diff --git a/plugins/_bundled/sirsoft-pay_kginicis/src/Support/ShopRedirectUrl.php b/plugins/_bundled/sirsoft-pay_kginicis/src/Support/ShopRedirectUrl.php new file mode 100644 index 00000000..7c38b7c5 --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_kginicis/src/Support/ShopRedirectUrl.php @@ -0,0 +1,46 @@ + $tokens 추가 치환 토큰 (예: `['{orderId}' => '20260807-0001']`) + * @return string 치환이 끝난 주소 + */ + public static function resolve(string $template, array $tokens = []): string + { + return strtr($template, ['{shopBase}' => ShopPathResolver::base()] + $tokens); + } +} diff --git a/plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Support/ShopRedirectUrlTest.php b/plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Support/ShopRedirectUrlTest.php new file mode 100644 index 00000000..97b02af6 --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Support/ShopRedirectUrlTest.php @@ -0,0 +1,79 @@ + $basicInfo `basic_info` 하위 설정 + */ + private function setShopSettings(array $basicInfo): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', $basicInfo); + } + + public function test_설정이_없으면_기본_상점_주소를_쓴다(): void + { + $this->setShopSettings([]); + + $this->assertSame( + '/shop/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/shop/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_운영자가_바꾼_상점_주소를_따른다(): void + { + $this->setShopSettings(['route_path' => 'store']); + + $this->assertSame( + '/store/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/store/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_주소_없이_운영하면_루트에_붙는다(): void + { + $this->setShopSettings(['no_route' => true]); + + $this->assertSame( + '/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_운영자가_직접_넣은_주소는_그대로_쓴다(): void + { + $this->setShopSettings(['route_path' => 'store']); + + // 자리표시자가 없으면 손대지 않는다 — 절대 URL 의 '//' 도 보존되어야 한다. + $this->assertSame( + 'https://pay.example.com/done/20260807-0001', + ShopRedirectUrl::resolve('https://pay.example.com/done/{orderId}', ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/my/custom/checkout', ShopRedirectUrl::resolve('/my/custom/checkout')); + } +} diff --git a/plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php b/plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php new file mode 100644 index 00000000..fbfad385 --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php @@ -0,0 +1,93 @@ + '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => '/shop/checkout', + ]); + + $this->assertSame('{shopBase}/orders/{orderId}/complete', $settings['redirect_success_url']); + $this->assertSame('{shopBase}/checkout', $settings['redirect_fail_url']); + $this->assertSame(['redirect_success_url', 'redirect_fail_url'], $updated); + } + + public function test_운영자가_직접_넣은_주소는_건드리지_않는다(): void + { + $custom = [ + 'redirect_success_url' => 'https://pay.example.com/done/{orderId}', + 'redirect_fail_url' => '/my/custom/checkout', + ]; + + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply($custom); + + $this->assertSame($custom, $settings); + $this->assertSame([], $updated); + } + + public function test_한쪽만_예전_기본값이면_그쪽만_바꾼다(): void + { + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply([ + 'redirect_success_url' => '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => 'https://pay.example.com/fail', + ]); + + $this->assertSame('{shopBase}/orders/{orderId}/complete', $settings['redirect_success_url']); + $this->assertSame('https://pay.example.com/fail', $settings['redirect_fail_url']); + $this->assertSame(['redirect_success_url'], $updated); + } + + public function test_재실행해도_변화가_없다(): void + { + [$once] = BackfillShopBaseRedirectUrls::apply([ + 'redirect_success_url' => '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => '/shop/checkout', + ]); + + [$twice, $updated] = BackfillShopBaseRedirectUrls::apply($once); + + $this->assertSame($once, $twice); + $this->assertSame([], $updated); + } + + public function test_키가_없으면_추가하지_않는다(): void + { + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply(['is_test_mode' => true]); + + $this->assertSame(['is_test_mode' => true], $settings); + $this->assertSame([], $updated); + } +} diff --git a/plugins/_bundled/sirsoft-pay_kginicis/upgrades/Upgrade_1_1_0.php b/plugins/_bundled/sirsoft-pay_kginicis/upgrades/Upgrade_1_1_0.php new file mode 100644 index 00000000..3b983694 --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_kginicis/upgrades/Upgrade_1_1_0.php @@ -0,0 +1,18 @@ + 새 기본값. 저장값이 좌변과 정확히 같을 때만 우변으로 바꾼다. + * + * @var array + */ + private const REPLACEMENTS = [ + 'redirect_success_url' => ['/shop/orders/{orderId}/complete', '{shopBase}/orders/{orderId}/complete'], + 'redirect_fail_url' => ['/shop/checkout', '{shopBase}/checkout'], + ]; + + /** + * 마이그레이션 식별자 (로그용). + * + * @return string 사람이 읽을 수 있는 짧은 식별자 + */ + public function name(): string + { + return 'BackfillShopBaseRedirectUrls'; + } + + /** + * 저장된 리다이렉트 주소를 자리표시자 형태로 백필한다. idempotent. + * + * @param UpgradeContext $context 업그레이드 컨텍스트 (로거 등) + */ + public function run(UpgradeContext $context): void + { + $path = storage_path(self::SETTINGS_PATH); + + if (! File::exists($path)) { + $context->logger->info('[kginicis] 설정 파일 없음 — 새 기본값으로 동작하므로 skip'); + + return; + } + + $settings = json_decode(File::get($path), true); + if (! is_array($settings)) { + $context->logger->warning('[kginicis] 설정 JSON 형식 비정상 — 리다이렉트 주소 백필 skip'); + + return; + } + + [$settings, $updated] = self::apply($settings); + + if ($updated === []) { + $context->logger->info('[kginicis] 리다이렉트 주소가 예전 기본값이 아님 — 운영자 설정 보존, 변경 없음'); + + return; + } + + File::put($path, json_encode($settings, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); + FilePermissionHelper::inheritOwnershipFromParent($path); + + $context->logger->info('[kginicis] 결제 리다이렉트 주소를 상점 주소 설정 기준으로 백필 완료', [ + 'updated_keys' => $updated, + ]); + } + + /** + * 저장된 설정 배열에 백필을 적용한 결과를 반환합니다. + * + * 파일 I/O 와 분리한 순수 함수다 — 실제 설정 파일을 건드리지 않고 판단 규칙 + * (예전 기본값과 **정확히 같을 때만** 교체)을 검증할 수 있다. + * + * @param array $settings 저장된 설정 + * @return array{0: array, 1: array} [갱신된 설정, 바뀐 키 목록] + */ + public static function apply(array $settings): array + { + $updated = []; + + foreach (self::REPLACEMENTS as $key => [$legacy, $replacement]) { + if (($settings[$key] ?? null) === $legacy) { + $settings[$key] = $replacement; + $updated[] = $key; + } + } + + return [$settings, $updated]; + } +} diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md b/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md index 2b27a455..54a0b045 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/CHANGELOG.md @@ -6,8 +6,13 @@ ## [1.0.1] - 2026-07-22 +### Changed + +- 이커머스 모듈 최소 버전을 1.1.0으로 상향했습니다. + ### Fixed +- 쇼핑몰 주소를 기본값이 아닌 값으로 바꾸거나 주소 없이 운영하는 상점에서, 결제를 마치거나 결제에 실패한 구매자가 존재하지 않는 페이지로 이동하던 문제를 수정했습니다. 이동 주소가 기본 주소로 고정돼 있었기 때문이며, 이제 상점 주소 설정을 따라갑니다. 이미 운영 중인 사이트도 업데이트 시 자동으로 반영되며, 이동 주소를 직접 입력해 두었다면 그 값은 그대로 유지됩니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) - 이 플러그인이 설치된 사이트에서 관리자 주문 목록의 '일부취소' 표시와 적립예정 포인트·마일리지 사용 금액, 주문상품의 추가옵션 요약이 보이지 않던 문제를 수정했습니다. 결제 정보 칸에 테스트결제 표시를 덧붙이는 과정에서 목록 표 구성 전체를 옛 버전으로 되돌려 놓고 있었습니다. - 관리자 결제수단 설정에서 가상계좌·계좌이체·휴대폰결제에 PG사를 지정할 수 없던 문제를 수정했습니다. 해당 결제수단의 PG사 목록이 항상 비어 있어 기본 PG사만 사용할 수 있었고, 결제수단별로 다른 PG사를 지정하는 설정이 화면에서 불가능했습니다. - 관리자 주문 목록에서 주문번호를 눌러 상세로 들어갈 때 걸어 둔 필터와 페이지가 사라지던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/config/settings/defaults.json b/plugins/_bundled/sirsoft-pay_nhnkcp/config/settings/defaults.json index 34c629e5..dd17e3a5 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/config/settings/defaults.json +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/config/settings/defaults.json @@ -9,8 +9,8 @@ "test_site_key": "", "live_site_cd": "", "live_site_key": "", - "redirect_success_url": "/shop/orders/{orderId}/complete", - "redirect_fail_url": "/shop/checkout" + "redirect_success_url": "{shopBase}/orders/{orderId}/complete", + "redirect_fail_url": "{shopBase}/checkout" }, "frontend_schema": { "is_test_mode": { "expose": false }, diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/plugin.json b/plugins/_bundled/sirsoft-pay_nhnkcp/plugin.json index 0debcf1b..e84f7a9a 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/plugin.json +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/plugin.json @@ -16,7 +16,7 @@ "g7_version": ">=7.0.5", "dependencies": { "modules": { - "sirsoft-ecommerce": ">=1.0.0-beta.5" + "sirsoft-ecommerce": ">=1.1.0" }, "plugins": {} }, diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/plugin.php b/plugins/_bundled/sirsoft-pay_nhnkcp/plugin.php index 5c6f9ba6..3eb59b4b 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/plugin.php +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/plugin.php @@ -74,16 +74,16 @@ class Plugin extends AbstractPlugin ], 'redirect_success_url' => [ 'type' => 'string', - 'default' => '/shop/orders/{orderId}/complete', + 'default' => '{shopBase}/orders/{orderId}/complete', 'label' => ['ko' => '결제 성공 리다이렉트 URL', 'en' => 'Payment Success Redirect URL'], 'hint' => [ - 'ko' => '상대 경로(/shop/...) 또는 전체 URL(https://...) 모두 가능합니다. {orderId}는 주문번호로 자동 치환됩니다.', - 'en' => 'Supports relative paths (/shop/...) or full URLs (https://...). {orderId} will be replaced with the actual order number.', + 'ko' => '{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL(https://...)을 직접 넣어도 됩니다. {orderId}는 주문번호로 자동 치환됩니다.', + 'en' => '{shopBase} is filled in from the storefront address setting. You may also enter a full URL (https://...). {orderId} will be replaced with the actual order number.', ], ], 'redirect_fail_url' => [ 'type' => 'string', - 'default' => '/shop/checkout', + 'default' => '{shopBase}/checkout', 'label' => ['ko' => '결제 실패 리다이렉트 URL', 'en' => 'Payment Failure Redirect URL'], 'hint' => [ 'ko' => '상대 경로 또는 전체 URL 모두 가능합니다. 오류 정보는 쿼리 파라미터로 자동 추가됩니다.', @@ -136,8 +136,8 @@ class Plugin extends AbstractPlugin 'test_site_key' => '', 'live_site_cd' => '', 'live_site_key' => '', - 'redirect_success_url' => '/shop/orders/{orderId}/complete', - 'redirect_fail_url' => '/shop/checkout', + 'redirect_success_url' => '{shopBase}/orders/{orderId}/complete', + 'redirect_fail_url' => '{shopBase}/checkout', 'use_escrow' => false, 'escrow_test_site_cd' => '', 'vbank_expire_days' => 3, diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/resources/lang/en.json b/plugins/_bundled/sirsoft-pay_nhnkcp/resources/lang/en.json index 8493b708..812c9f13 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/resources/lang/en.json +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/resources/lang/en.json @@ -129,7 +129,7 @@ "easy_pay_applepay_hint": "Available on iOS Safari only", "section_redirect": "Redirect URLs", "redirect_success_url": "Payment Success Redirect URL", - "redirect_success_url_hint": "Supports relative paths or full URLs. {orderId} will be replaced with the actual order number.", + "redirect_success_url_hint": "{shopBase} is filled in from the storefront address setting. You may also enter a full URL (https://...). {orderId} will be replaced with the actual order number.", "redirect_fail_url": "Payment Failure Redirect URL", "redirect_fail_url_hint": "Supports relative paths or full URLs. Error details are appended as query parameters.", "section_vbank": "Virtual Account Settings", diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/resources/lang/ko.json b/plugins/_bundled/sirsoft-pay_nhnkcp/resources/lang/ko.json index 2fbe7a66..ac178219 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/resources/lang/ko.json +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/resources/lang/ko.json @@ -129,7 +129,7 @@ "easy_pay_applepay_hint": "iOS Safari에서만 사용 가능", "section_redirect": "리다이렉트 URL", "redirect_success_url": "결제 성공 리다이렉트 URL", - "redirect_success_url_hint": "상대 경로(/shop/...) 또는 전체 URL 모두 가능합니다. {orderId}는 주문번호로 자동 치환됩니다.", + "redirect_success_url_hint": "{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL(https://...)을 직접 넣어도 됩니다. {orderId}는 주문번호로 자동 치환됩니다.", "redirect_fail_url": "결제 실패 리다이렉트 URL", "redirect_fail_url_hint": "상대 경로 또는 전체 URL 모두 가능합니다. 오류 정보는 쿼리 파라미터로 자동 추가됩니다.", "section_vbank": "가상계좌 설정", diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/src/Controllers/PaymentCallbackController.php b/plugins/_bundled/sirsoft-pay_nhnkcp/src/Controllers/PaymentCallbackController.php index aa6590a0..7200253c 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/src/Controllers/PaymentCallbackController.php +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/src/Controllers/PaymentCallbackController.php @@ -27,6 +27,7 @@ use Plugins\Sirsoft\PayNhnkcp\Concerns\SerializesPaymentCallbacks; use Plugins\Sirsoft\PayNhnkcp\Http\Requests\AuthCallbackRequest; use Plugins\Sirsoft\PayNhnkcp\Http\Requests\VbankNotifyRequest; use Plugins\Sirsoft\PayNhnkcp\Services\NhnKcpApiService; +use Plugins\Sirsoft\PayNhnkcp\Support\ShopRedirectUrl; /** * KCP 결제 콜백 컨트롤러 @@ -834,9 +835,9 @@ class PaymentCallbackController private function resolveSuccessUrl(string $orderId): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $urlTemplate = $settings['redirect_success_url'] ?? '/shop/orders/{orderId}/complete'; + $urlTemplate = $settings['redirect_success_url'] ?? ShopRedirectUrl::DEFAULT_SUCCESS_URL; - return $this->absolutize(str_replace('{orderId}', $orderId, $urlTemplate)); + return $this->absolutize(ShopRedirectUrl::resolve($urlTemplate, ['{orderId}' => $orderId])); } /** @@ -889,7 +890,7 @@ class PaymentCallbackController private function resolveFailUrl(array $queryParams = []): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $baseUrl = $this->absolutize($settings['redirect_fail_url'] ?? '/shop/checkout'); + $baseUrl = $this->absolutize(ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL)); if (empty($queryParams)) { return $baseUrl; diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/src/Http/Requests/AuthCallbackRequest.php b/plugins/_bundled/sirsoft-pay_nhnkcp/src/Http/Requests/AuthCallbackRequest.php index cdb5c6d0..2f853df5 100644 --- a/plugins/_bundled/sirsoft-pay_nhnkcp/src/Http/Requests/AuthCallbackRequest.php +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/src/Http/Requests/AuthCallbackRequest.php @@ -8,6 +8,7 @@ use Illuminate\Contracts\Validation\Validator; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Http\Exceptions\HttpResponseException; use Illuminate\Support\Facades\Log; +use Plugins\Sirsoft\PayNhnkcp\Support\ShopRedirectUrl; /** * KCP 결제 승인 콜백 요청 검증 @@ -68,11 +69,11 @@ class AuthCallbackRequest extends FormRequest ]); $settings = plugin_settings(self::PLUGIN_IDENTIFIER); - $baseUrl = $settings['redirect_fail_url'] ?? '/shop/checkout'; + $baseUrl = ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL); $separator = str_contains($baseUrl, '?') ? '&' : '?'; throw new HttpResponseException( - redirect($baseUrl . $separator . http_build_query(['error' => 'invalid_params'])) + redirect($baseUrl.$separator.http_build_query(['error' => 'invalid_params'])) ); } } diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/src/Support/ShopRedirectUrl.php b/plugins/_bundled/sirsoft-pay_nhnkcp/src/Support/ShopRedirectUrl.php new file mode 100644 index 00000000..a8a6276a --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/src/Support/ShopRedirectUrl.php @@ -0,0 +1,46 @@ + $tokens 추가 치환 토큰 (예: `['{orderId}' => '20260807-0001']`) + * @return string 치환이 끝난 주소 + */ + public static function resolve(string $template, array $tokens = []): string + { + return strtr($template, ['{shopBase}' => ShopPathResolver::base()] + $tokens); + } +} diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Support/ShopRedirectUrlTest.php b/plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Support/ShopRedirectUrlTest.php new file mode 100644 index 00000000..1522e241 --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Support/ShopRedirectUrlTest.php @@ -0,0 +1,79 @@ + $basicInfo `basic_info` 하위 설정 + */ + private function setShopSettings(array $basicInfo): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', $basicInfo); + } + + public function test_설정이_없으면_기본_상점_주소를_쓴다(): void + { + $this->setShopSettings([]); + + $this->assertSame( + '/shop/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/shop/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_운영자가_바꾼_상점_주소를_따른다(): void + { + $this->setShopSettings(['route_path' => 'store']); + + $this->assertSame( + '/store/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/store/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_주소_없이_운영하면_루트에_붙는다(): void + { + $this->setShopSettings(['no_route' => true]); + + $this->assertSame( + '/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_운영자가_직접_넣은_주소는_그대로_쓴다(): void + { + $this->setShopSettings(['route_path' => 'store']); + + // 자리표시자가 없으면 손대지 않는다 — 절대 URL 의 '//' 도 보존되어야 한다. + $this->assertSame( + 'https://pay.example.com/done/20260807-0001', + ShopRedirectUrl::resolve('https://pay.example.com/done/{orderId}', ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/my/custom/checkout', ShopRedirectUrl::resolve('/my/custom/checkout')); + } +} diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php b/plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php new file mode 100644 index 00000000..4140fa5d --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php @@ -0,0 +1,93 @@ + '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => '/shop/checkout', + ]); + + $this->assertSame('{shopBase}/orders/{orderId}/complete', $settings['redirect_success_url']); + $this->assertSame('{shopBase}/checkout', $settings['redirect_fail_url']); + $this->assertSame(['redirect_success_url', 'redirect_fail_url'], $updated); + } + + public function test_운영자가_직접_넣은_주소는_건드리지_않는다(): void + { + $custom = [ + 'redirect_success_url' => 'https://pay.example.com/done/{orderId}', + 'redirect_fail_url' => '/my/custom/checkout', + ]; + + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply($custom); + + $this->assertSame($custom, $settings); + $this->assertSame([], $updated); + } + + public function test_한쪽만_예전_기본값이면_그쪽만_바꾼다(): void + { + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply([ + 'redirect_success_url' => '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => 'https://pay.example.com/fail', + ]); + + $this->assertSame('{shopBase}/orders/{orderId}/complete', $settings['redirect_success_url']); + $this->assertSame('https://pay.example.com/fail', $settings['redirect_fail_url']); + $this->assertSame(['redirect_success_url'], $updated); + } + + public function test_재실행해도_변화가_없다(): void + { + [$once] = BackfillShopBaseRedirectUrls::apply([ + 'redirect_success_url' => '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => '/shop/checkout', + ]); + + [$twice, $updated] = BackfillShopBaseRedirectUrls::apply($once); + + $this->assertSame($once, $twice); + $this->assertSame([], $updated); + } + + public function test_키가_없으면_추가하지_않는다(): void + { + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply(['is_test_mode' => true]); + + $this->assertSame(['is_test_mode' => true], $settings); + $this->assertSame([], $updated); + } +} diff --git a/plugins/_bundled/sirsoft-pay_nhnkcp/upgrades/Upgrade_1_0_1.php b/plugins/_bundled/sirsoft-pay_nhnkcp/upgrades/Upgrade_1_0_1.php new file mode 100644 index 00000000..5168ed3d --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_nhnkcp/upgrades/Upgrade_1_0_1.php @@ -0,0 +1,18 @@ + 새 기본값. 저장값이 좌변과 정확히 같을 때만 우변으로 바꾼다. + * + * @var array + */ + private const REPLACEMENTS = [ + 'redirect_success_url' => ['/shop/orders/{orderId}/complete', '{shopBase}/orders/{orderId}/complete'], + 'redirect_fail_url' => ['/shop/checkout', '{shopBase}/checkout'], + ]; + + /** + * 마이그레이션 식별자 (로그용). + * + * @return string 사람이 읽을 수 있는 짧은 식별자 + */ + public function name(): string + { + return 'BackfillShopBaseRedirectUrls'; + } + + /** + * 저장된 리다이렉트 주소를 자리표시자 형태로 백필한다. idempotent. + * + * @param UpgradeContext $context 업그레이드 컨텍스트 (로거 등) + */ + public function run(UpgradeContext $context): void + { + $path = storage_path(self::SETTINGS_PATH); + + if (! File::exists($path)) { + $context->logger->info('[nhnkcp] 설정 파일 없음 — 새 기본값으로 동작하므로 skip'); + + return; + } + + $settings = json_decode(File::get($path), true); + if (! is_array($settings)) { + $context->logger->warning('[nhnkcp] 설정 JSON 형식 비정상 — 리다이렉트 주소 백필 skip'); + + return; + } + + [$settings, $updated] = self::apply($settings); + + if ($updated === []) { + $context->logger->info('[nhnkcp] 리다이렉트 주소가 예전 기본값이 아님 — 운영자 설정 보존, 변경 없음'); + + return; + } + + File::put($path, json_encode($settings, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); + FilePermissionHelper::inheritOwnershipFromParent($path); + + $context->logger->info('[nhnkcp] 결제 리다이렉트 주소를 상점 주소 설정 기준으로 백필 완료', [ + 'updated_keys' => $updated, + ]); + } + + /** + * 저장된 설정 배열에 백필을 적용한 결과를 반환합니다. + * + * 파일 I/O 와 분리한 순수 함수다 — 실제 설정 파일을 건드리지 않고 판단 규칙 + * (예전 기본값과 **정확히 같을 때만** 교체)을 검증할 수 있다. + * + * @param array $settings 저장된 설정 + * @return array{0: array, 1: array} [갱신된 설정, 바뀐 키 목록] + */ + public static function apply(array $settings): array + { + $updated = []; + + foreach (self::REPLACEMENTS as $key => [$legacy, $replacement]) { + if (($settings[$key] ?? null) === $legacy) { + $settings[$key] = $replacement; + $updated[] = $key; + } + } + + return [$settings, $updated]; + } +} diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/CHANGELOG.md b/plugins/_bundled/sirsoft-pay_nicepayments/CHANGELOG.md index e3fa1625..c0a45999 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-pay_nicepayments/CHANGELOG.md @@ -6,8 +6,13 @@ ## [1.0.1] - 2026-07-22 +### Changed + +- 이커머스 모듈 최소 버전을 1.1.0으로 상향했습니다. + ### Fixed +- 쇼핑몰 주소를 기본값이 아닌 값으로 바꾸거나 주소 없이 운영하는 상점에서, 결제를 마치거나 결제에 실패한 구매자가 존재하지 않는 페이지로 이동하던 문제를 수정했습니다. 이동 주소가 기본 주소로 고정돼 있었기 때문이며, 이제 상점 주소 설정을 따라갑니다. 이미 운영 중인 사이트도 업데이트 시 자동으로 반영되며, 이동 주소를 직접 입력해 두었다면 그 값은 그대로 유지됩니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) - 이 플러그인이 설치된 사이트에서 관리자 주문 목록의 '일부취소' 표시와 적립예정 포인트·마일리지 사용 금액, 주문상품의 추가옵션 요약이 보이지 않던 문제를 수정했습니다. 결제 정보 칸에 테스트결제 표시를 덧붙이는 과정에서 목록 표 구성 전체를 옛 버전으로 되돌려 놓고 있었습니다. - 관리자 결제수단 설정에서 가상계좌·계좌이체·휴대폰결제에 PG사를 지정할 수 없던 문제를 수정했습니다. 해당 결제수단의 PG사 목록이 항상 비어 있어 기본 PG사만 사용할 수 있었고, 결제수단별로 다른 PG사를 지정하는 설정이 화면에서 불가능했습니다. - 관리자 주문 목록에서 주문번호를 눌러 상세로 들어갈 때 걸어 둔 필터와 페이지가 사라지던 문제를 수정했습니다. (#75 @jiwonpapa 님께서 제보해주셨습니다.) diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/config/settings/defaults.json b/plugins/_bundled/sirsoft-pay_nicepayments/config/settings/defaults.json index f46b1963..4227df41 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/config/settings/defaults.json +++ b/plugins/_bundled/sirsoft-pay_nicepayments/config/settings/defaults.json @@ -9,8 +9,8 @@ "test_merchant_key": "EYzu8jGGMfqaDEp76gSckuvnaHHu+bC4opsSN6lHv3b2lurNYkVXrZ7Z1AoqQnXI3eLuaUFyoRNC6FkrzVjceg==", "live_mid": "", "live_merchant_key": "", - "redirect_success_url": "/shop/orders/{orderId}/complete", - "redirect_fail_url": "/shop/checkout" + "redirect_success_url": "{shopBase}/orders/{orderId}/complete", + "redirect_fail_url": "{shopBase}/checkout" }, "frontend_schema": { "is_test_mode": { "expose": false }, diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/plugin.json b/plugins/_bundled/sirsoft-pay_nicepayments/plugin.json index af7b8fae..f5e1e019 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/plugin.json +++ b/plugins/_bundled/sirsoft-pay_nicepayments/plugin.json @@ -16,7 +16,7 @@ "g7_version": ">=7.0.5", "dependencies": { "modules": { - "sirsoft-ecommerce": ">=1.0.0-beta.5" + "sirsoft-ecommerce": ">=1.1.0" }, "plugins": {} }, diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/plugin.php b/plugins/_bundled/sirsoft-pay_nicepayments/plugin.php index 30da524b..4bc9d1ba 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/plugin.php +++ b/plugins/_bundled/sirsoft-pay_nicepayments/plugin.php @@ -70,16 +70,16 @@ class Plugin extends AbstractPlugin ], 'redirect_success_url' => [ 'type' => 'string', - 'default' => '/shop/orders/{orderId}/complete', + 'default' => '{shopBase}/orders/{orderId}/complete', 'label' => ['ko' => '결제 성공 리다이렉트 URL', 'en' => 'Payment Success Redirect URL'], 'hint' => [ - 'ko' => '상대 경로(/shop/...) 또는 전체 URL(https://...) 모두 가능합니다. {orderId}는 주문번호로 자동 치환됩니다.', - 'en' => 'Supports relative paths (/shop/...) or full URLs (https://...). {orderId} will be replaced with the actual order number.', + 'ko' => '{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL(https://...)을 직접 넣어도 됩니다. {orderId}는 주문번호로 자동 치환됩니다.', + 'en' => '{shopBase} is filled in from the storefront address setting. You may also enter a full URL (https://...). {orderId} will be replaced with the actual order number.', ], ], 'redirect_fail_url' => [ 'type' => 'string', - 'default' => '/shop/checkout', + 'default' => '{shopBase}/checkout', 'label' => ['ko' => '결제 실패 리다이렉트 URL', 'en' => 'Payment Failure Redirect URL'], 'hint' => [ 'ko' => '상대 경로 또는 전체 URL 모두 가능합니다. 오류 정보는 쿼리 파라미터로 자동 추가됩니다.', @@ -163,8 +163,8 @@ class Plugin extends AbstractPlugin 'test_merchant_key' => 'EYzu8jGGMfqaDEp76gSckuvnaHHu+bC4opsSN6lHv3b2lurNYkVXrZ7Z1AoqQnXI3eLuaUFyoRNC6FkrzVjceg==', 'live_mid' => '', 'live_merchant_key' => '', - 'redirect_success_url' => '/shop/orders/{orderId}/complete', - 'redirect_fail_url' => '/shop/checkout', + 'redirect_success_url' => '{shopBase}/orders/{orderId}/complete', + 'redirect_fail_url' => '{shopBase}/checkout', 'use_escrow' => false, 'easy_pay_allow_with_other_pg' => false, 'easy_pay_naverpay' => false, diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/resources/lang/en.json b/plugins/_bundled/sirsoft-pay_nicepayments/resources/lang/en.json index e644cfcc..f1cc23b4 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/resources/lang/en.json +++ b/plugins/_bundled/sirsoft-pay_nicepayments/resources/lang/en.json @@ -34,7 +34,7 @@ "copy": "Copy", "section_redirect": "Redirect URLs", "redirect_success_url": "Payment Success Redirect URL", - "redirect_success_url_hint": "Supports relative paths (/shop/...) or full URLs (https://...). {orderId} will be replaced with the actual order number.", + "redirect_success_url_hint": "{shopBase} is filled in from the storefront address setting. You may also enter a full URL (https://...). {orderId} will be replaced with the actual order number.", "redirect_fail_url": "Payment Failure Redirect URL", "redirect_fail_url_hint": "Supports relative paths or full URLs. Error details are appended as query parameters.", "use_escrow": "Enable Escrow Payment", diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/resources/lang/ko.json b/plugins/_bundled/sirsoft-pay_nicepayments/resources/lang/ko.json index cb748fb1..25b68ab0 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/resources/lang/ko.json +++ b/plugins/_bundled/sirsoft-pay_nicepayments/resources/lang/ko.json @@ -34,7 +34,7 @@ "copy": "복사", "section_redirect": "리다이렉트 URL", "redirect_success_url": "결제 성공 리다이렉트 URL", - "redirect_success_url_hint": "상대 경로(/shop/...) 또는 전체 URL(https://...) 모두 가능합니다. {orderId}는 주문번호로 자동 치환됩니다.", + "redirect_success_url_hint": "{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL(https://...)을 직접 넣어도 됩니다. {orderId}는 주문번호로 자동 치환됩니다.", "redirect_fail_url": "결제 실패 리다이렉트 URL", "redirect_fail_url_hint": "상대 경로 또는 전체 URL 모두 가능합니다. 오류 정보는 쿼리 파라미터로 자동 추가됩니다.", "use_escrow": "에스크로 결제 사용", diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/src/Controllers/PaymentCallbackController.php b/plugins/_bundled/sirsoft-pay_nicepayments/src/Controllers/PaymentCallbackController.php index 3bcb2101..92ffe36a 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/src/Controllers/PaymentCallbackController.php +++ b/plugins/_bundled/sirsoft-pay_nicepayments/src/Controllers/PaymentCallbackController.php @@ -31,6 +31,7 @@ use Plugins\Sirsoft\PayNicepayments\Concerns\SanitizesPgResponse; use Plugins\Sirsoft\PayNicepayments\Http\Requests\AuthCallbackRequest; use Plugins\Sirsoft\PayNicepayments\Http\Requests\VbankNotifyRequest; use Plugins\Sirsoft\PayNicepayments\Services\NicePaymentsApiService; +use Plugins\Sirsoft\PayNicepayments\Support\ShopRedirectUrl; use Plugins\Sirsoft\PayNicepayments\Support\UrlHelper; /** @@ -995,8 +996,8 @@ class PaymentCallbackController private function resolveSuccessUrl(string $orderId): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $urlTemplate = $settings['redirect_success_url'] ?? '/shop/orders/{orderId}/complete'; - $url = str_replace('{orderId}', $orderId, $urlTemplate); + $urlTemplate = $settings['redirect_success_url'] ?? ShopRedirectUrl::DEFAULT_SUCCESS_URL; + $url = ShopRedirectUrl::resolve($urlTemplate, ['{orderId}' => $orderId]); return UrlHelper::toAbsolute($url); } @@ -1004,7 +1005,7 @@ class PaymentCallbackController private function resolveFailUrl(array $queryParams = []): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $baseUrl = $settings['redirect_fail_url'] ?? '/shop/checkout'; + $baseUrl = ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL); if (! empty($queryParams)) { $query = http_build_query(array_filter($queryParams)); diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/src/Http/Requests/AuthCallbackRequest.php b/plugins/_bundled/sirsoft-pay_nicepayments/src/Http/Requests/AuthCallbackRequest.php index ccb5a958..1f6b553a 100644 --- a/plugins/_bundled/sirsoft-pay_nicepayments/src/Http/Requests/AuthCallbackRequest.php +++ b/plugins/_bundled/sirsoft-pay_nicepayments/src/Http/Requests/AuthCallbackRequest.php @@ -7,6 +7,7 @@ namespace Plugins\Sirsoft\PayNicepayments\Http\Requests; use Illuminate\Contracts\Validation\Validator; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Http\Exceptions\HttpResponseException; +use Plugins\Sirsoft\PayNicepayments\Support\ShopRedirectUrl; use Plugins\Sirsoft\PayNicepayments\Support\UrlHelper; /** @@ -78,9 +79,9 @@ class AuthCallbackRequest extends FormRequest protected function failedValidation(Validator $validator): void { $settings = plugin_settings(self::PLUGIN_IDENTIFIER); - $baseUrl = $settings['redirect_fail_url'] ?? '/shop/checkout'; + $baseUrl = ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL); $separator = str_contains($baseUrl, '?') ? '&' : '?'; - $url = $baseUrl . $separator . http_build_query(['error' => 'invalid_params']); + $url = $baseUrl.$separator.http_build_query(['error' => 'invalid_params']); throw new HttpResponseException( redirect(UrlHelper::toAbsolute($url)) diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/src/Support/ShopRedirectUrl.php b/plugins/_bundled/sirsoft-pay_nicepayments/src/Support/ShopRedirectUrl.php new file mode 100644 index 00000000..7ccf432b --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_nicepayments/src/Support/ShopRedirectUrl.php @@ -0,0 +1,46 @@ + $tokens 추가 치환 토큰 (예: `['{orderId}' => '20260807-0001']`) + * @return string 치환이 끝난 주소 + */ + public static function resolve(string $template, array $tokens = []): string + { + return strtr($template, ['{shopBase}' => ShopPathResolver::base()] + $tokens); + } +} diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Support/ShopRedirectUrlTest.php b/plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Support/ShopRedirectUrlTest.php new file mode 100644 index 00000000..9a761e0e --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Support/ShopRedirectUrlTest.php @@ -0,0 +1,79 @@ + $basicInfo `basic_info` 하위 설정 + */ + private function setShopSettings(array $basicInfo): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', $basicInfo); + } + + public function test_설정이_없으면_기본_상점_주소를_쓴다(): void + { + $this->setShopSettings([]); + + $this->assertSame( + '/shop/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/shop/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_운영자가_바꾼_상점_주소를_따른다(): void + { + $this->setShopSettings(['route_path' => 'store']); + + $this->assertSame( + '/store/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/store/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_주소_없이_운영하면_루트에_붙는다(): void + { + $this->setShopSettings(['no_route' => true]); + + $this->assertSame( + '/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_운영자가_직접_넣은_주소는_그대로_쓴다(): void + { + $this->setShopSettings(['route_path' => 'store']); + + // 자리표시자가 없으면 손대지 않는다 — 절대 URL 의 '//' 도 보존되어야 한다. + $this->assertSame( + 'https://pay.example.com/done/20260807-0001', + ShopRedirectUrl::resolve('https://pay.example.com/done/{orderId}', ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/my/custom/checkout', ShopRedirectUrl::resolve('/my/custom/checkout')); + } +} diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php b/plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php new file mode 100644 index 00000000..f7d30b0d --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php @@ -0,0 +1,93 @@ + '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => '/shop/checkout', + ]); + + $this->assertSame('{shopBase}/orders/{orderId}/complete', $settings['redirect_success_url']); + $this->assertSame('{shopBase}/checkout', $settings['redirect_fail_url']); + $this->assertSame(['redirect_success_url', 'redirect_fail_url'], $updated); + } + + public function test_운영자가_직접_넣은_주소는_건드리지_않는다(): void + { + $custom = [ + 'redirect_success_url' => 'https://pay.example.com/done/{orderId}', + 'redirect_fail_url' => '/my/custom/checkout', + ]; + + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply($custom); + + $this->assertSame($custom, $settings); + $this->assertSame([], $updated); + } + + public function test_한쪽만_예전_기본값이면_그쪽만_바꾼다(): void + { + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply([ + 'redirect_success_url' => '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => 'https://pay.example.com/fail', + ]); + + $this->assertSame('{shopBase}/orders/{orderId}/complete', $settings['redirect_success_url']); + $this->assertSame('https://pay.example.com/fail', $settings['redirect_fail_url']); + $this->assertSame(['redirect_success_url'], $updated); + } + + public function test_재실행해도_변화가_없다(): void + { + [$once] = BackfillShopBaseRedirectUrls::apply([ + 'redirect_success_url' => '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => '/shop/checkout', + ]); + + [$twice, $updated] = BackfillShopBaseRedirectUrls::apply($once); + + $this->assertSame($once, $twice); + $this->assertSame([], $updated); + } + + public function test_키가_없으면_추가하지_않는다(): void + { + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply(['is_test_mode' => true]); + + $this->assertSame(['is_test_mode' => true], $settings); + $this->assertSame([], $updated); + } +} diff --git a/plugins/_bundled/sirsoft-pay_nicepayments/upgrades/Upgrade_1_0_1.php b/plugins/_bundled/sirsoft-pay_nicepayments/upgrades/Upgrade_1_0_1.php new file mode 100644 index 00000000..18511e54 --- /dev/null +++ b/plugins/_bundled/sirsoft-pay_nicepayments/upgrades/Upgrade_1_0_1.php @@ -0,0 +1,18 @@ + 새 기본값. 저장값이 좌변과 정확히 같을 때만 우변으로 바꾼다. + * + * @var array + */ + private const REPLACEMENTS = [ + 'redirect_success_url' => ['/shop/orders/{orderId}/complete', '{shopBase}/orders/{orderId}/complete'], + 'redirect_fail_url' => ['/shop/checkout', '{shopBase}/checkout'], + ]; + + /** + * 마이그레이션 식별자 (로그용). + * + * @return string 사람이 읽을 수 있는 짧은 식별자 + */ + public function name(): string + { + return 'BackfillShopBaseRedirectUrls'; + } + + /** + * 저장된 리다이렉트 주소를 자리표시자 형태로 백필한다. idempotent. + * + * @param UpgradeContext $context 업그레이드 컨텍스트 (로거 등) + */ + public function run(UpgradeContext $context): void + { + $path = storage_path(self::SETTINGS_PATH); + + if (! File::exists($path)) { + $context->logger->info('[nicepayments] 설정 파일 없음 — 새 기본값으로 동작하므로 skip'); + + return; + } + + $settings = json_decode(File::get($path), true); + if (! is_array($settings)) { + $context->logger->warning('[nicepayments] 설정 JSON 형식 비정상 — 리다이렉트 주소 백필 skip'); + + return; + } + + [$settings, $updated] = self::apply($settings); + + if ($updated === []) { + $context->logger->info('[nicepayments] 리다이렉트 주소가 예전 기본값이 아님 — 운영자 설정 보존, 변경 없음'); + + return; + } + + File::put($path, json_encode($settings, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); + FilePermissionHelper::inheritOwnershipFromParent($path); + + $context->logger->info('[nicepayments] 결제 리다이렉트 주소를 상점 주소 설정 기준으로 백필 완료', [ + 'updated_keys' => $updated, + ]); + } + + /** + * 저장된 설정 배열에 백필을 적용한 결과를 반환합니다. + * + * 파일 I/O 와 분리한 순수 함수다 — 실제 설정 파일을 건드리지 않고 판단 규칙 + * (예전 기본값과 **정확히 같을 때만** 교체)을 검증할 수 있다. + * + * @param array $settings 저장된 설정 + * @return array{0: array, 1: array} [갱신된 설정, 바뀐 키 목록] + */ + public static function apply(array $settings): array + { + $updated = []; + + foreach (self::REPLACEMENTS as $key => [$legacy, $replacement]) { + if (($settings[$key] ?? null) === $legacy) { + $settings[$key] = $replacement; + $updated[] = $key; + } + } + + return [$settings, $updated]; + } +} diff --git a/plugins/_bundled/sirsoft-tosspayments/CHANGELOG.md b/plugins/_bundled/sirsoft-tosspayments/CHANGELOG.md index 5004aac6..ce8e63ba 100644 --- a/plugins/_bundled/sirsoft-tosspayments/CHANGELOG.md +++ b/plugins/_bundled/sirsoft-tosspayments/CHANGELOG.md @@ -45,6 +45,8 @@ ### Fixed + +- 쇼핑몰 주소를 기본값이 아닌 값으로 바꾸거나 주소 없이 운영하는 상점에서, 결제를 마치거나 결제에 실패한 구매자가 존재하지 않는 페이지로 이동하던 문제를 수정했습니다. 이동 주소가 기본 주소로 고정돼 있었기 때문이며, 이제 상점 주소 설정을 따라갑니다. 이미 운영 중인 사이트도 업데이트 시 자동으로 반영되며, 이동 주소를 직접 입력해 두었다면 그 값은 그대로 유지됩니다. (#85 @hwaryeon1234 님께서 제보해주셨습니다.) - 전액 환불이 부분취소로 잘못 요청되던 문제를 수정했습니다. 이미 부분취소한 이력이 있는 주문의 잔액 취소도 정확한 금액으로 처리됩니다. - 면세 상품이 포함된 주문을 환불할 때 면세 금액이 함께 전달되지 않아 부가세가 잘못 계산되던 문제를 수정했습니다. - 가상계좌 결제를 취소할 때 환불받을 계좌 정보가 전달되지 않아 취소가 실패하던 문제를 수정했습니다. 계좌 정보가 없으면 취소 전에 안내합니다. @@ -119,11 +121,13 @@ ## [0.1.1] - 2026-02-24 ### Changed + - 버전 체계 조정 (정식 출시 전 0.x 체계로 변경) ## [0.1.0] - 2026-02-23 ### Added + - 토스페이먼츠 결제 플러그인 초기 구현 - 카드/계좌이체/가상계좌/무통장입금 결제 지원 - 결제 위젯 (TossPayments SDK) 통합 diff --git a/plugins/_bundled/sirsoft-tosspayments/config/settings/defaults.json b/plugins/_bundled/sirsoft-tosspayments/config/settings/defaults.json index 3cad2226..75e315a9 100644 --- a/plugins/_bundled/sirsoft-tosspayments/config/settings/defaults.json +++ b/plugins/_bundled/sirsoft-tosspayments/config/settings/defaults.json @@ -9,8 +9,8 @@ "test_secret_key": "", "live_client_key": "", "live_secret_key": "", - "redirect_success_url": "/shop/orders/{orderId}/complete", - "redirect_fail_url": "/shop/checkout", + "redirect_success_url": "{shopBase}/orders/{orderId}/complete", + "redirect_fail_url": "{shopBase}/checkout", "order_sheet_mode": false, "method_card": true, "method_virtual_account": false, diff --git a/plugins/_bundled/sirsoft-tosspayments/plugin.php b/plugins/_bundled/sirsoft-tosspayments/plugin.php index 64cfdc2d..3cddb933 100644 --- a/plugins/_bundled/sirsoft-tosspayments/plugin.php +++ b/plugins/_bundled/sirsoft-tosspayments/plugin.php @@ -80,20 +80,20 @@ class Plugin extends AbstractPlugin ], 'redirect_success_url' => [ 'type' => 'string', - 'default' => '/shop/orders/{orderId}/complete', + 'default' => '{shopBase}/orders/{orderId}/complete', 'label' => ['ko' => '결제 성공 리다이렉트 URL', 'en' => 'Payment Success Redirect URL'], 'hint' => [ - 'ko' => '상대 경로(/shop/...) 또는 전체 URL(https://...) 모두 가능합니다. {orderId}는 주문번호로 자동 치환됩니다.', - 'en' => 'Supports relative paths (/shop/...) or full URLs (https://...). {orderId} will be replaced with the actual order number.', + 'ko' => '{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL(https://...)을 직접 넣어도 됩니다. {orderId}는 주문번호로 자동 치환됩니다.', + 'en' => '{shopBase} is filled in from the storefront address setting. You may also enter a full URL (https://...). {orderId} will be replaced with the actual order number.', ], ], 'redirect_fail_url' => [ 'type' => 'string', - 'default' => '/shop/checkout', + 'default' => '{shopBase}/checkout', 'label' => ['ko' => '결제 실패 리다이렉트 URL', 'en' => 'Payment Failure Redirect URL'], 'hint' => [ - 'ko' => '상대 경로 또는 전체 URL 모두 가능합니다. 오류 정보는 쿼리 파라미터로 자동 추가됩니다.', - 'en' => 'Supports relative paths or full URLs. Error details are appended as query parameters.', + 'ko' => '{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL 을 직접 넣어도 됩니다. 오류 정보는 쿼리 파라미터로 자동 추가됩니다.', + 'en' => '{shopBase} is filled in from the storefront address setting. You may also enter a full URL. Error details are appended as query parameters.', ], ], @@ -212,8 +212,8 @@ class Plugin extends AbstractPlugin 'test_secret_key' => '', 'live_client_key' => '', 'live_secret_key' => '', - 'redirect_success_url' => '/shop/orders/{orderId}/complete', - 'redirect_fail_url' => '/shop/checkout', + 'redirect_success_url' => '{shopBase}/orders/{orderId}/complete', + 'redirect_fail_url' => '{shopBase}/checkout', 'order_sheet_mode' => false, 'method_card' => true, 'method_virtual_account' => false, diff --git a/plugins/_bundled/sirsoft-tosspayments/resources/lang/en.json b/plugins/_bundled/sirsoft-tosspayments/resources/lang/en.json index 31b318a5..f356e67a 100644 --- a/plugins/_bundled/sirsoft-tosspayments/resources/lang/en.json +++ b/plugins/_bundled/sirsoft-tosspayments/resources/lang/en.json @@ -22,9 +22,9 @@ "section_live_keys": "Live API Keys", "section_redirect": "Redirect Settings", "redirect_success_url": "Payment Success Redirect URL", - "redirect_success_url_hint": "Supports relative paths (/shop/...) or full URLs (https://...). {orderId} will be replaced with the actual order number.", + "redirect_success_url_hint": "{shopBase} is filled in from the storefront address setting. You may also enter a full URL (https://...). {orderId} will be replaced with the actual order number.", "redirect_fail_url": "Payment Failure Redirect URL", - "redirect_fail_url_hint": "Supports relative paths or full URLs. Error details (error, message, orderId) are appended as query parameters.", + "redirect_fail_url_hint": "{shopBase} is filled in from the storefront address setting. You may also enter a full URL. Error details (error, message, orderId) are appended as query parameters.", "save": "Save", "saved": "Settings saved.", "section_payment_methods": "Payment Methods", diff --git a/plugins/_bundled/sirsoft-tosspayments/resources/lang/ko.json b/plugins/_bundled/sirsoft-tosspayments/resources/lang/ko.json index 177d8f43..b131838f 100644 --- a/plugins/_bundled/sirsoft-tosspayments/resources/lang/ko.json +++ b/plugins/_bundled/sirsoft-tosspayments/resources/lang/ko.json @@ -22,9 +22,9 @@ "section_live_keys": "라이브 API 키", "section_redirect": "리다이렉트 설정", "redirect_success_url": "결제 성공 리다이렉트 URL", - "redirect_success_url_hint": "상대 경로(/shop/...) 또는 전체 URL(https://...) 모두 가능합니다. {orderId}는 실제 주문번호로 자동 치환됩니다.", + "redirect_success_url_hint": "{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL(https://...)을 직접 넣어도 됩니다. {orderId}는 실제 주문번호로 자동 치환됩니다.", "redirect_fail_url": "결제 실패 리다이렉트 URL", - "redirect_fail_url_hint": "상대 경로 또는 전체 URL 모두 가능합니다. 오류 정보(error, message, orderId)는 쿼리 파라미터로 자동 추가됩니다.", + "redirect_fail_url_hint": "{shopBase}는 상점 주소 설정을 따라 자동으로 채워집니다. 전체 URL 을 직접 넣어도 됩니다. 오류 정보(error, message, orderId)는 쿼리 파라미터로 자동 추가됩니다.", "save": "저장", "saved": "설정이 저장되었습니다.", "section_payment_methods": "결제 방식", diff --git a/plugins/_bundled/sirsoft-tosspayments/src/Controllers/PaymentCallbackController.php b/plugins/_bundled/sirsoft-tosspayments/src/Controllers/PaymentCallbackController.php index 44235bb8..7589540e 100644 --- a/plugins/_bundled/sirsoft-tosspayments/src/Controllers/PaymentCallbackController.php +++ b/plugins/_bundled/sirsoft-tosspayments/src/Controllers/PaymentCallbackController.php @@ -16,6 +16,7 @@ use Modules\Sirsoft\Ecommerce\Services\OrderProcessingService; use Plugins\Sirsoft\Tosspayments\Http\Requests\FailCallbackRequest; use Plugins\Sirsoft\Tosspayments\Http\Requests\SuccessCallbackRequest; use Plugins\Sirsoft\Tosspayments\Services\TossPaymentsApiService; +use Plugins\Sirsoft\Tosspayments\Support\ShopRedirectUrl; /** * 토스페이먼츠 결제 콜백 컨트롤러 @@ -273,9 +274,9 @@ class PaymentCallbackController private function resolveSuccessUrl(string $orderId): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $urlTemplate = $settings['redirect_success_url'] ?? '/shop/orders/{orderId}/complete'; + $urlTemplate = $settings['redirect_success_url'] ?? ShopRedirectUrl::DEFAULT_SUCCESS_URL; - return str_replace('{orderId}', $orderId, $urlTemplate); + return ShopRedirectUrl::resolve($urlTemplate, ['{orderId}' => $orderId]); } /** @@ -287,7 +288,7 @@ class PaymentCallbackController private function resolveFailUrl(array $queryParams = []): string { $settings = $this->pluginSettingsService->get(self::PLUGIN_IDENTIFIER) ?? []; - $baseUrl = $settings['redirect_fail_url'] ?? '/shop/checkout'; + $baseUrl = ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL); if (empty($queryParams)) { return $baseUrl; diff --git a/plugins/_bundled/sirsoft-tosspayments/src/Http/Requests/SuccessCallbackRequest.php b/plugins/_bundled/sirsoft-tosspayments/src/Http/Requests/SuccessCallbackRequest.php index bd5520ef..db25f8fd 100644 --- a/plugins/_bundled/sirsoft-tosspayments/src/Http/Requests/SuccessCallbackRequest.php +++ b/plugins/_bundled/sirsoft-tosspayments/src/Http/Requests/SuccessCallbackRequest.php @@ -5,6 +5,7 @@ namespace Plugins\Sirsoft\Tosspayments\Http\Requests; use Illuminate\Contracts\Validation\Validator; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Http\Exceptions\HttpResponseException; +use Plugins\Sirsoft\Tosspayments\Support\ShopRedirectUrl; /** * 토스페이먼츠 결제 성공 콜백 요청 검증 @@ -45,14 +46,15 @@ class SuccessCallbackRequest extends FormRequest * * PG 콜백은 브라우저 리다이렉트이므로 422 대신 실패 페이지로 이동합니다. * - * @param Validator $validator 검증기 인스턴스 + * @param Validator $validator 검증기 인스턴스 * @return void + * * @throws HttpResponseException */ protected function failedValidation(Validator $validator): void { $settings = plugin_settings(self::PLUGIN_IDENTIFIER); - $baseUrl = $settings['redirect_fail_url'] ?? '/shop/checkout'; + $baseUrl = ShopRedirectUrl::resolve($settings['redirect_fail_url'] ?? ShopRedirectUrl::DEFAULT_FAIL_URL); $separator = str_contains($baseUrl, '?') ? '&' : '?'; throw new HttpResponseException( diff --git a/plugins/_bundled/sirsoft-tosspayments/src/Support/ShopRedirectUrl.php b/plugins/_bundled/sirsoft-tosspayments/src/Support/ShopRedirectUrl.php new file mode 100644 index 00000000..d68d3c7d --- /dev/null +++ b/plugins/_bundled/sirsoft-tosspayments/src/Support/ShopRedirectUrl.php @@ -0,0 +1,46 @@ + $tokens 추가 치환 토큰 (예: `['{orderId}' => '20260807-0001']`) + * @return string 치환이 끝난 주소 + */ + public static function resolve(string $template, array $tokens = []): string + { + return strtr($template, ['{shopBase}' => ShopPathResolver::base()] + $tokens); + } +} diff --git a/plugins/_bundled/sirsoft-tosspayments/tests/Feature/Controllers/PaymentCallbackControllerTest.php b/plugins/_bundled/sirsoft-tosspayments/tests/Feature/Controllers/PaymentCallbackControllerTest.php index 6e59b40e..b2a6fa33 100644 --- a/plugins/_bundled/sirsoft-tosspayments/tests/Feature/Controllers/PaymentCallbackControllerTest.php +++ b/plugins/_bundled/sirsoft-tosspayments/tests/Feature/Controllers/PaymentCallbackControllerTest.php @@ -4,6 +4,7 @@ namespace Plugins\Sirsoft\Tosspayments\Tests\Feature\Controllers; use App\Models\User; use App\Services\PluginSettingsService; +use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Http; use Modules\Sirsoft\Ecommerce\Database\Factories\OrderFactory; use Modules\Sirsoft\Ecommerce\Database\Factories\OrderPaymentFactory; @@ -11,6 +12,7 @@ use Modules\Sirsoft\Ecommerce\Enums\OrderStatusEnum; use Modules\Sirsoft\Ecommerce\Enums\PaymentMethodEnum; use Modules\Sirsoft\Ecommerce\Enums\PaymentStatusEnum; use Modules\Sirsoft\Ecommerce\Models\Order; +use Plugins\Sirsoft\Tosspayments\Support\ShopRedirectUrl; use Plugins\Sirsoft\Tosspayments\Tests\PluginTestCase; /** @@ -70,6 +72,25 @@ class PaymentCallbackControllerTest extends PluginTestCase */ private static int $orderSequence = 0; + /** + * 주문 통화 고정값. + * + * 팩토리 기본값은 이커머스 통화 설정에서 읽으므로 앞서 실행된 다른 스위트가 남긴 + * 설정 상태에 따라 통화가 달라진다. 더 중요한 것은 **소수 자릿수**다 — + * `resolveSnapshotPaymentCharge` 는 스냅샷에 `decimal_places` 가 없으면 상점 통화 + * 설정에서 조회하는데, 그 설정이 비어 있으면 KRW(0자리)가 2자리로 해석되어 청구액이 + * 최소단위 환산으로 100배가 된다. 그러면 콜백 금액 검증이 `amount_mismatch` 로 갈라져 + * 이 파일의 리다이렉트 단언이 성공 분기가 아닌 실패 분기를 본다. + * (실측: 게시판 스위트 직후 expected 5,000,000 vs 콜백 amount 50,000) + * + * 이 파일은 리다이렉트 주소를 검증하는 것이지 통화 환산을 검증하지 않으므로, + * 통화와 자릿수를 스냅샷에 못박아 선행 스위트와 무관하게 결정적으로 동작하게 한다. + */ + private const TEST_CURRENCY = 'KRW'; + + /** 원화 소수 자릿수 — 스냅샷에 명시해 상점 설정 조회로 떨어지지 않게 한다. */ + private const TEST_CURRENCY_DECIMALS = 0; + private function createTestOrder(int $totalAmount = 50000): Order { $user = User::factory()->create(); @@ -78,6 +99,24 @@ class PaymentCallbackControllerTest extends PluginTestCase 'user_id' => $user->id, 'order_number' => 'ORD-TEST-'.(++self::$orderSequence), 'order_status' => OrderStatusEnum::PENDING_ORDER, + 'currency' => self::TEST_CURRENCY, + 'currency_snapshot' => [ + 'base_currency' => self::TEST_CURRENCY, + 'order_currency' => self::TEST_CURRENCY, + 'exchange_rate' => 1.0, + // 환율을 단순 float 로 두면 `resolveSnapshotPaymentCharge` 가 자릿수를 + // 상점 설정에서 조회한다. 배열 형태로 `decimal_places` 를 명시해야 + // 설정 상태와 무관하게 원화 0 자리로 고정된다. + 'exchange_rates' => [ + self::TEST_CURRENCY => [ + 'rate' => 1.0, + 'decimal_places' => self::TEST_CURRENCY_DECIMALS, + 'rounding_unit' => '1', + 'rounding_method' => 'round', + ], + ], + 'snapshot_at' => now()->toIso8601String(), + ], 'subtotal_amount' => $totalAmount, 'total_discount_amount' => 0, 'total_coupon_discount_amount' => 0, @@ -100,6 +139,8 @@ class PaymentCallbackControllerTest extends PluginTestCase 'payment_status' => PaymentStatusEnum::READY, 'payment_method' => PaymentMethodEnum::CARD, 'pg_provider' => 'tosspayments', + 'currency' => self::TEST_CURRENCY, + 'currency_snapshot' => [self::TEST_CURRENCY => 1.0], 'paid_amount_local' => 0, 'paid_at' => null, 'transaction_id' => null, @@ -120,8 +161,8 @@ class PaymentCallbackControllerTest extends PluginTestCase 'is_test_mode' => true, 'test_secret_key' => 'test_sk_mock_key', 'test_client_key' => 'test_ck_mock_key', - 'redirect_success_url' => '/shop/orders/{orderId}/complete', - 'redirect_fail_url' => '/shop/checkout', + 'redirect_success_url' => ShopRedirectUrl::DEFAULT_SUCCESS_URL, + 'redirect_fail_url' => ShopRedirectUrl::DEFAULT_FAIL_URL, ]; $settingsMock = $this->createMock(PluginSettingsService::class); @@ -131,6 +172,44 @@ class PaymentCallbackControllerTest extends PluginTestCase $this->app->instance(PluginSettingsService::class, $settingsMock); } + /** + * 상점 주소를 바꾼 상점에서도 결제 완료 이동 주소가 그 주소를 따르는지 확인 (공개 #85) + * + * 기본값이 `/shop/...` 리터럴이던 시절에는 주소를 바꾼 상점의 구매자가 결제를 마치고 + * 존재하지 않는 페이지로 떨어졌다. 리다이렉트라 예외도 404 로그도 남지 않는다. + * + * @scenario case=payment_redirect_follows_shop_route_path + * + * @effects payment_redirect_follows_route_path + */ + public function test_success_redirect_follows_shop_route_path_setting(): void + { + Config::set( + 'g7_settings.modules.sirsoft-ecommerce.basic_info', + ['route_path' => 'store'] + ); + + $order = $this->createTestOrder(50000); + $paymentKey = 'pk_test_route_path'; + + $this->mockPluginSettings(); + + Http::fake([ + 'api.tosspayments.com/v1/payments/confirm' => Http::response( + $this->makeMockConfirmResponse($paymentKey, $order->order_number, 50000), + 200 + ), + ]); + + $response = $this->get('/plugins/sirsoft-tosspayments/payment/success?'.http_build_query([ + 'paymentKey' => $paymentKey, + 'orderId' => $order->order_number, + 'amount' => 50000, + ])); + + $response->assertRedirect("/store/orders/{$order->order_number}/complete"); + } + // ===== Success 콜백 테스트 ===== /** diff --git a/plugins/_bundled/sirsoft-tosspayments/tests/Unit/Support/ShopRedirectUrlTest.php b/plugins/_bundled/sirsoft-tosspayments/tests/Unit/Support/ShopRedirectUrlTest.php new file mode 100644 index 00000000..d7c33587 --- /dev/null +++ b/plugins/_bundled/sirsoft-tosspayments/tests/Unit/Support/ShopRedirectUrlTest.php @@ -0,0 +1,79 @@ + $basicInfo `basic_info` 하위 설정 + */ + private function setShopSettings(array $basicInfo): void + { + Config::set('g7_settings.modules.sirsoft-ecommerce.basic_info', $basicInfo); + } + + public function test_설정이_없으면_기본_상점_주소를_쓴다(): void + { + $this->setShopSettings([]); + + $this->assertSame( + '/shop/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/shop/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_운영자가_바꾼_상점_주소를_따른다(): void + { + $this->setShopSettings(['route_path' => 'store']); + + $this->assertSame( + '/store/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/store/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_주소_없이_운영하면_루트에_붙는다(): void + { + $this->setShopSettings(['no_route' => true]); + + $this->assertSame( + '/orders/20260807-0001/complete', + ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_SUCCESS_URL, ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/checkout', ShopRedirectUrl::resolve(ShopRedirectUrl::DEFAULT_FAIL_URL)); + } + + public function test_운영자가_직접_넣은_주소는_그대로_쓴다(): void + { + $this->setShopSettings(['route_path' => 'store']); + + // 자리표시자가 없으면 손대지 않는다 — 절대 URL 의 '//' 도 보존되어야 한다. + $this->assertSame( + 'https://pay.example.com/done/20260807-0001', + ShopRedirectUrl::resolve('https://pay.example.com/done/{orderId}', ['{orderId}' => '20260807-0001']) + ); + $this->assertSame('/my/custom/checkout', ShopRedirectUrl::resolve('/my/custom/checkout')); + } +} diff --git a/plugins/_bundled/sirsoft-tosspayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php b/plugins/_bundled/sirsoft-tosspayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php new file mode 100644 index 00000000..41381280 --- /dev/null +++ b/plugins/_bundled/sirsoft-tosspayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php @@ -0,0 +1,93 @@ + '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => '/shop/checkout', + ]); + + $this->assertSame('{shopBase}/orders/{orderId}/complete', $settings['redirect_success_url']); + $this->assertSame('{shopBase}/checkout', $settings['redirect_fail_url']); + $this->assertSame(['redirect_success_url', 'redirect_fail_url'], $updated); + } + + public function test_운영자가_직접_넣은_주소는_건드리지_않는다(): void + { + $custom = [ + 'redirect_success_url' => 'https://pay.example.com/done/{orderId}', + 'redirect_fail_url' => '/my/custom/checkout', + ]; + + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply($custom); + + $this->assertSame($custom, $settings); + $this->assertSame([], $updated); + } + + public function test_한쪽만_예전_기본값이면_그쪽만_바꾼다(): void + { + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply([ + 'redirect_success_url' => '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => 'https://pay.example.com/fail', + ]); + + $this->assertSame('{shopBase}/orders/{orderId}/complete', $settings['redirect_success_url']); + $this->assertSame('https://pay.example.com/fail', $settings['redirect_fail_url']); + $this->assertSame(['redirect_success_url'], $updated); + } + + public function test_재실행해도_변화가_없다(): void + { + [$once] = BackfillShopBaseRedirectUrls::apply([ + 'redirect_success_url' => '/shop/orders/{orderId}/complete', + 'redirect_fail_url' => '/shop/checkout', + ]); + + [$twice, $updated] = BackfillShopBaseRedirectUrls::apply($once); + + $this->assertSame($once, $twice); + $this->assertSame([], $updated); + } + + public function test_키가_없으면_추가하지_않는다(): void + { + [$settings, $updated] = BackfillShopBaseRedirectUrls::apply(['is_test_mode' => true]); + + $this->assertSame(['is_test_mode' => true], $settings); + $this->assertSame([], $updated); + } +} diff --git a/plugins/_bundled/sirsoft-tosspayments/tests/scenarios/payment-redirect-shop-route-path.yaml b/plugins/_bundled/sirsoft-tosspayments/tests/scenarios/payment-redirect-shop-route-path.yaml new file mode 100644 index 00000000..7b81d147 --- /dev/null +++ b/plugins/_bundled/sirsoft-tosspayments/tests/scenarios/payment-redirect-shop-route-path.yaml @@ -0,0 +1,69 @@ +# audit:allow test-scenario-coverage reason: 축이 서로 다른 계층에 격리 검증된다 — route_setting 은 +# 해석기 단위 테스트(플러그인 4종 ShopRedirectUrlTest + 모듈 ShopPathResolverTest)가, stored_value 는 +# 업그레이드 백필 단위 테스트(플러그인 4종 BackfillShopBaseRedirectUrlsTest)가, redirect_kind 는 양쪽이 +# 성공·실패 키를 각각 단언한다. 한 메서드가 3축 조합을 동시에 재현하지 않으므로 cross product 18조합을 +# docblock @scenario 로 나열하면 거짓 매핑이 된다(같은 플러그인의 S4·S5 매니페스트 선례 동일). +# effects 는 전부 실제 검증 메서드에 @effects 로 매핑되어 있으며 그것이 실질 커버리지다. +# 시나리오 매니페스트 — 결제 리다이렉트 주소가 상점 주소 설정을 따른다 (공개 #85) +# 참조: docs/testing-guide.md "기능 단위 시나리오 매트릭스" + +feature: payment_redirect_follows_shop_route_path + +description: >- + 상점 주소는 운영자 설정이다 — 쇼핑몰 모듈의 `basic_info.route_path` 로 바꿀 수 있고 + `basic_info.no_route` 를 켜면 세그먼트 없이 루트에 붙는다. 그런데 결제 플러그인 4종의 + 결제 완료·실패 리다이렉트 기본값은 `/shop/...` 리터럴이라, 주소를 바꾼 상점에서는 결제를 + 마친 구매자가 존재하지 않는 페이지로 떨어졌다. 리다이렉트라 예외도 404 로그도 남지 않아 + 증상이 드러나지 않는다. + + 기본값에 `{shopBase}` 자리표시자를 두고 이동 직전에 쇼핑몰 모듈의 해석기(SSoT)가 계산한 + 기준 경로로 바꾼다. 운영자가 직접 넣은 주소는 자리표시자가 없으므로 그대로 쓰인다. + 이미 설치를 마친 사이트는 예전 리터럴이 설정 파일에 저장돼 있으므로, 저장값이 예전 + 기본값과 정확히 같을 때만 업그레이드 시점에 자리표시자 형태로 백필한다. + +test_files: + - plugins/_bundled/sirsoft-tosspayments/tests/Unit/Support/ShopRedirectUrlTest.php + - plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Support/ShopRedirectUrlTest.php + - plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Support/ShopRedirectUrlTest.php + - plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Support/ShopRedirectUrlTest.php + - plugins/_bundled/sirsoft-tosspayments/tests/Feature/Controllers/PaymentCallbackControllerTest.php + # 기설치본 백필 판단 규칙 (stored_value 축) + - plugins/_bundled/sirsoft-tosspayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php + - plugins/_bundled/sirsoft-pay_kginicis/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php + - plugins/_bundled/sirsoft-pay_nhnkcp/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php + - plugins/_bundled/sirsoft-pay_nicepayments/tests/Unit/Upgrade/BackfillShopBaseRedirectUrlsTest.php + # 상점 주소 해석기 자체(SSoT)의 축 검증 + - modules/_bundled/sirsoft-ecommerce/tests/Unit/Support/ShopPathResolverTest.php + +axes: + route_setting: + - default # route_path 미설정/기본값 'shop' + - custom # 운영자가 바꾼 주소 (예: 'store') + - no_route # 주소 없이 루트 운영 + + redirect_kind: + - success # 결제 완료 후 이동 + - fail # 결제 실패 후 이동 + + stored_value: + - legacy_default # 예전 기본값 리터럴이 저장돼 있음 (기설치본) + - placeholder # 새 기본값(자리표시자) + - operator_custom # 운영자가 직접 넣은 절대 URL/자기 경로 + +exclusions: + - { stored_value: operator_custom, route_setting: no_route, reason: "운영자 지정 주소는 상점 주소 설정과 무관하게 그대로 쓰인다 — route_setting 축이 결과에 영향을 주지 않음" } + +effects: + # 해석 규칙 + - payment_redirect_follows_route_path # 변경 주소 반영 (성공·실패 양쪽) + - payment_redirect_drops_segment_when_no_route # no_route → 루트 경로 + - operator_supplied_redirect_url_is_preserved # 자리표시자 없는 입력은 무변경 (절대 URL 의 '//' 보존) + # 기설치본 백필 + - legacy_default_redirect_is_backfilled # 예전 기본값 == 저장값일 때만 자리표시자로 갱신 + - operator_custom_redirect_survives_backfill # 운영자 입력값은 백필이 건드리지 않음 + - redirect_backfill_is_idempotent # 재실행해도 변화 없음 + # 회귀 + - default_shop_redirect_unchanged # 기본 주소 상점의 이동 주소는 종전과 동일 + +validation: + audit_rule: test-scenario-coverage diff --git a/plugins/_bundled/sirsoft-tosspayments/upgrades/Upgrade_1_0_0.php b/plugins/_bundled/sirsoft-tosspayments/upgrades/Upgrade_1_0_0.php new file mode 100644 index 00000000..c781ab47 --- /dev/null +++ b/plugins/_bundled/sirsoft-tosspayments/upgrades/Upgrade_1_0_0.php @@ -0,0 +1,18 @@ + 새 기본값. 저장값이 좌변과 정확히 같을 때만 우변으로 바꾼다. + * + * @var array + */ + private const REPLACEMENTS = [ + 'redirect_success_url' => ['/shop/orders/{orderId}/complete', '{shopBase}/orders/{orderId}/complete'], + 'redirect_fail_url' => ['/shop/checkout', '{shopBase}/checkout'], + ]; + + /** + * 마이그레이션 식별자 (로그용). + * + * @return string 사람이 읽을 수 있는 짧은 식별자 + */ + public function name(): string + { + return 'BackfillShopBaseRedirectUrls'; + } + + /** + * 저장된 리다이렉트 주소를 자리표시자 형태로 백필한다. idempotent. + * + * @param UpgradeContext $context 업그레이드 컨텍스트 (로거 등) + */ + public function run(UpgradeContext $context): void + { + $path = storage_path(self::SETTINGS_PATH); + + if (! File::exists($path)) { + $context->logger->info('[tosspayments] 설정 파일 없음 — 새 기본값으로 동작하므로 skip'); + + return; + } + + $settings = json_decode(File::get($path), true); + if (! is_array($settings)) { + $context->logger->warning('[tosspayments] 설정 JSON 형식 비정상 — 리다이렉트 주소 백필 skip'); + + return; + } + + [$settings, $updated] = self::apply($settings); + + if ($updated === []) { + $context->logger->info('[tosspayments] 리다이렉트 주소가 예전 기본값이 아님 — 운영자 설정 보존, 변경 없음'); + + return; + } + + File::put($path, json_encode($settings, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); + FilePermissionHelper::inheritOwnershipFromParent($path); + + $context->logger->info('[tosspayments] 결제 리다이렉트 주소를 상점 주소 설정 기준으로 백필 완료', [ + 'updated_keys' => $updated, + ]); + } + + /** + * 저장된 설정 배열에 백필을 적용한 결과를 반환합니다. + * + * 파일 I/O 와 분리한 순수 함수다 — 실제 설정 파일을 건드리지 않고 판단 규칙 + * (예전 기본값과 **정확히 같을 때만** 교체)을 검증할 수 있다. + * + * @param array $settings 저장된 설정 + * @return array{0: array, 1: array} [갱신된 설정, 바뀐 키 목록] + */ + public static function apply(array $settings): array + { + $updated = []; + + foreach (self::REPLACEMENTS as $key => [$legacy, $replacement]) { + if (($settings[$key] ?? null) === $legacy) { + $settings[$key] = $replacement; + $updated[] = $key; + } + } + + return [$settings, $updated]; + } +} diff --git a/public/build/core/layout-editor.min.js b/public/build/core/layout-editor.min.js index 6bfcb407..bb4e0c1a 100644 --- a/public/build/core/layout-editor.min.js +++ b/public/build/core/layout-editor.min.js @@ -10,5 +10,5 @@ var dM=Object.defineProperty;var cM=(dn,i,u)=>i in dn?dM(dn,i,{enumerable:!0,con 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. `},O7={onDragStart(e){let{active:t}=e;return"Picked up draggable item "+t.id+"."},onDragOver(e){let{active:t,over:n}=e;return n?"Draggable item "+t.id+" was moved over droppable area "+n.id+".":"Draggable item "+t.id+" is no longer over a droppable area."},onDragEnd(e){let{active:t,over:n}=e;return n?"Draggable item "+t.id+" was dropped over droppable area "+n.id:"Draggable item "+t.id+" was dropped."},onDragCancel(e){let{active:t}=e;return"Dragging was cancelled. Draggable item "+t.id+" was dropped."}};function B7(e){let{announcements:t=O7,container:n,hiddenTextDescribedById:o,screenReaderInstructions:r=P7}=e;const{announce:s,announcement:a}=z7(),l=ei("DndLiveRegion"),[d,c]=u.useState(!1);if(u.useEffect(()=>{c(!0)},[]),M7(u.useMemo(()=>({onDragStart(f){let{active:y}=f;s(t.onDragStart({active:y}))},onDragMove(f){let{active:y,over:g}=f;t.onDragMove&&s(t.onDragMove({active:y,over:g}))},onDragOver(f){let{active:y,over:g}=f;s(t.onDragOver({active:y,over:g}))},onDragEnd(f){let{active:y,over:g}=f;s(t.onDragEnd({active:y,over:g}))},onDragCancel(f){let{active:y,over:g}=f;s(t.onDragCancel({active:y,over:g}))}}),[s,t])),!d)return null;const p=u.createElement(u.Fragment,null,u.createElement(D7,{id:o,value:r.draggable}),u.createElement(N7,{id:l,announcement:a}));return n?Cn.createPortal(p,n):p}var it;(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"})(it||(it={}));function oi(){}function W7(e,t){return u.useMemo(()=>({sensor:e,options:t??{}}),[e,t])}function j7(){for(var e=arguments.length,t=new Array(e),n=0;n[...t].filter(o=>o!=null),[...t])}const Ht=Object.freeze({x:0,y:0});function H7(e,t){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function F7(e,t){const n=ni(e);if(!n)return"0 0";const o={x:(n.x-t.left)/t.width*100,y:(n.y-t.top)/t.height*100};return o.x+"% "+o.y+"%"}function K7(e,t){let{data:{value:n}}=e,{data:{value:o}}=t;return n-o}function V7(e,t){let{data:{value:n}}=e,{data:{value:o}}=t;return o-n}function U7(e){let{left:t,top:n,height:o,width:r}=e;return[{x:t,y:n},{x:t+r,y:n},{x:t,y:n+o},{x:t+r,y:n+o}]}function q7(e,t){if(!e||e.length===0)return null;const[n]=e;return n[t]}function G7(e,t){const n=Math.max(t.top,e.top),o=Math.max(t.left,e.left),r=Math.min(t.left+t.width,e.left+e.width),s=Math.min(t.top+t.height,e.top+e.height),a=r-o,l=s-n;if(o{let{collisionRect:t,droppableRects:n,droppableContainers:o}=e;const r=[];for(const s of o){const{id:a}=s,l=n.get(a);if(l){const d=G7(l,t);d>0&&r.push({id:a,data:{droppableContainer:s,value:d}})}}return r.sort(V7)};function X7(e,t){const{top:n,left:o,bottom:r,right:s}=t;return n<=e.y&&e.y<=r&&o<=e.x&&e.x<=s}const J7=e=>{let{droppableContainers:t,droppableRects:n,pointerCoordinates:o}=e;if(!o)return[];const r=[];for(const s of t){const{id:a}=s,l=n.get(a);if(l&&X7(o,l)){const c=U7(l).reduce((f,y)=>f+H7(o,y),0),p=Number((c/4).toFixed(4));r.push({id:a,data:{droppableContainer:s,value:p}})}}return r.sort(K7)};function Z7(e,t,n){return{...e,scaleX:t&&n?t.width/n.width:1,scaleY:t&&n?t.height/n.height:1}}function Kp(e,t){return e&&t?{x:e.left-t.left,y:e.top-t.top}:Ht}function Q7(e){return function(n){for(var o=arguments.length,r=new Array(o>1?o-1:0),s=1;s({...a,top:a.top+e*l.y,bottom:a.bottom+e*l.y,left:a.left+e*l.x,right:a.right+e*l.x}),{...n})}}const R7=Q7(1);function Vp(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 e2(e,t,n){const o=Vp(t);if(!o)return e;const{scaleX:r,scaleY:s,x:a,y:l}=o,d=e.left-a-(1-r)*parseFloat(n),c=e.top-l-(1-s)*parseFloat(n.slice(n.indexOf(" ")+1)),p=r?e.width/r:e.width,f=s?e.height/s:e.height;return{width:p,height:f,top:c,right:d+p,bottom:c+f,left:d}}const t2={ignoreTransform:!1};function Ho(e,t){t===void 0&&(t=t2);let n=e.getBoundingClientRect();if(t.ignoreTransform){const{transform:c,transformOrigin:p}=_t(e).getComputedStyle(e);c&&(n=e2(n,c,p))}const{top:o,left:r,width:s,height:a,bottom:l,right:d}=n;return{top:o,left:r,width:s,height:a,bottom:l,right:d}}function Up(e){return Ho(e,{ignoreTransform:!0})}function n2(e){const t=e.innerWidth,n=e.innerHeight;return{top:0,left:0,right:t,bottom:n,width:t,height:n}}function o2(e,t){return t===void 0&&(t=_t(e).getComputedStyle(e)),t.position==="fixed"}function r2(e,t){t===void 0&&(t=_t(e).getComputedStyle(e));const n=/(auto|scroll|overlay)/;return["overflow","overflowX","overflowY"].some(r=>{const s=t[r];return typeof s=="string"?n.test(s):!1})}function da(e,t){const n=[];function o(r){if(t!=null&&n.length>=t||!r)return n;if(sa(r)&&r.scrollingElement!=null&&!n.includes(r.scrollingElement))return n.push(r.scrollingElement),n;if(!Oo(r)||Wp(r)||n.includes(r))return n;const s=_t(e).getComputedStyle(r);return r!==e&&r2(r,s)&&n.push(r),o2(r,s)?n:o(r.parentNode)}return e?o(e):n}function qp(e){const[t]=da(e,1);return t??null}function ca(e){return!Jr||!e?null:lo(e)?e:ia(e)?sa(e)||e===co(e).scrollingElement?window:Oo(e)?e:null:null}function Gp(e){return lo(e)?e.scrollX:e.scrollLeft}function Yp(e){return lo(e)?e.scrollY:e.scrollTop}function ua(e){return{x:Gp(e),y:Yp(e)}}var lt;(function(e){e[e.Forward=1]="Forward",e[e.Backward=-1]="Backward"})(lt||(lt={}));function Xp(e){return!Jr||!e?!1:e===document.scrollingElement}function Jp(e){const t={x:0,y:0},n=Xp(e)?{height:window.innerHeight,width:window.innerWidth}:{height:e.clientHeight,width:e.clientWidth},o={x:e.scrollWidth-n.width,y:e.scrollHeight-n.height},r=e.scrollTop<=t.y,s=e.scrollLeft<=t.x,a=e.scrollTop>=o.y,l=e.scrollLeft>=o.x;return{isTop:r,isLeft:s,isBottom:a,isRight:l,maxScroll:o,minScroll:t}}const i2={x:.2,y:.2};function s2(e,t,n,o,r){let{top:s,left:a,right:l,bottom:d}=n;o===void 0&&(o=10),r===void 0&&(r=i2);const{isTop:c,isBottom:p,isLeft:f,isRight:y}=Jp(e),g={x:0,y:0},m={x:0,y:0},h={height:t.height*r.y,width:t.width*r.x};return!c&&s<=t.top+h.height?(g.y=lt.Backward,m.y=o*Math.abs((t.top+h.height-s)/h.height)):!p&&d>=t.bottom-h.height&&(g.y=lt.Forward,m.y=o*Math.abs((t.bottom-h.height-d)/h.height)),!y&&l>=t.right-h.width?(g.x=lt.Forward,m.x=o*Math.abs((t.right-h.width-l)/h.width)):!f&&a<=t.left+h.width&&(g.x=lt.Backward,m.x=o*Math.abs((t.left+h.width-a)/h.width)),{direction:g,speed:m}}function a2(e){if(e===document.scrollingElement){const{innerWidth:s,innerHeight:a}=window;return{top:0,left:0,right:s,bottom:a,width:s,height:a}}const{top:t,left:n,right:o,bottom:r}=e.getBoundingClientRect();return{top:t,left:n,right:o,bottom:r,width:e.clientWidth,height:e.clientHeight}}function Zp(e){return e.reduce((t,n)=>uo(t,ua(n)),Ht)}function l2(e){return e.reduce((t,n)=>t+Gp(n),0)}function d2(e){return e.reduce((t,n)=>t+Yp(n),0)}function Qp(e,t){if(t===void 0&&(t=Ho),!e)return;const{top:n,left:o,bottom:r,right:s}=t(e);qp(e)&&(r<=0||s<=0||n>=window.innerHeight||o>=window.innerWidth)&&e.scrollIntoView({block:"center",inline:"center"})}const c2=[["x",["left","right"],l2],["y",["top","bottom"],d2]];class pa{constructor(t,n){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 o=da(n),r=Zp(o);this.rect={...t},this.width=t.width,this.height=t.height;for(const[s,a,l]of c2)for(const d of a)Object.defineProperty(this,d,{get:()=>{const c=l(o),p=r[s]-c;return this.rect[d]+p},enumerable:!0});Object.defineProperty(this,"rect",{enumerable:!1})}}class Fo{constructor(t){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(n=>{var o;return(o=this.target)==null?void 0:o.removeEventListener(...n)})},this.target=t}add(t,n,o){var r;(r=this.target)==null||r.addEventListener(t,n,o),this.listeners.push([t,n,o])}}function u2(e){const{EventTarget:t}=_t(e);return e instanceof t?e:co(e)}function fa(e,t){const n=Math.abs(e.x),o=Math.abs(e.y);return typeof t=="number"?Math.sqrt(n**2+o**2)>t:"x"in t&&"y"in t?n>t.x&&o>t.y:"x"in t?n>t.x:"y"in t?o>t.y:!1}var At;(function(e){e.Click="click",e.DragStart="dragstart",e.Keydown="keydown",e.ContextMenu="contextmenu",e.Resize="resize",e.SelectionChange="selectionchange",e.VisibilityChange="visibilitychange"})(At||(At={}));function Rp(e){e.preventDefault()}function p2(e){e.stopPropagation()}var Ke;(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"})(Ke||(Ke={}));const ef={start:[Ke.Space,Ke.Enter],cancel:[Ke.Esc],end:[Ke.Space,Ke.Enter,Ke.Tab]},f2=(e,t)=>{let{currentCoordinates:n}=t;switch(e.code){case Ke.Right:return{...n,x:n.x+25};case Ke.Left:return{...n,x:n.x-25};case Ke.Down:return{...n,y:n.y+25};case Ke.Up:return{...n,y:n.y-25}}};class tf{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:n}}=t;this.props=t,this.listeners=new Fo(co(n)),this.windowListeners=new Fo(_t(n)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(At.Resize,this.handleCancel),this.windowListeners.add(At.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(At.Keydown,this.handleKeyDown))}handleStart(){const{activeNode:t,onStart:n}=this.props,o=t.node.current;o&&Qp(o),n(Ht)}handleKeyDown(t){if(la(t)){const{active:n,context:o,options:r}=this.props,{keyboardCodes:s=ef,coordinateGetter:a=f2,scrollBehavior:l="smooth"}=r,{code:d}=t;if(s.end.includes(d)){this.handleEnd(t);return}if(s.cancel.includes(d)){this.handleCancel(t);return}const{collisionRect:c}=o.current,p=c?{x:c.left,y:c.top}:Ht;this.referenceCoordinates||(this.referenceCoordinates=p);const f=a(t,{active:n,context:o.current,currentCoordinates:p});if(f){const y=ti(f,p),g={x:0,y:0},{scrollableAncestors:m}=o.current;for(const h of m){const v=t.code,{isTop:b,isRight:x,isLeft:k,isBottom:w,maxScroll:_,minScroll:C}=Jp(h),E=a2(h),S={x:Math.min(v===Ke.Right?E.right-E.width/2:E.right,Math.max(v===Ke.Right?E.left:E.left+E.width/2,f.x)),y:Math.min(v===Ke.Down?E.bottom-E.height/2:E.bottom,Math.max(v===Ke.Down?E.top:E.top+E.height/2,f.y))},T=v===Ke.Right&&!x||v===Ke.Left&&!k,$=v===Ke.Down&&!w||v===Ke.Up&&!b;if(T&&S.x!==f.x){const A=h.scrollLeft+y.x,z=v===Ke.Right&&A<=_.x||v===Ke.Left&&A>=C.x;if(z&&!y.y){h.scrollTo({left:A,behavior:l});return}z?g.x=h.scrollLeft-A:g.x=v===Ke.Right?h.scrollLeft-_.x:h.scrollLeft-C.x,g.x&&h.scrollBy({left:-g.x,behavior:l});break}else if($&&S.y!==f.y){const A=h.scrollTop+y.y,z=v===Ke.Down&&A<=_.y||v===Ke.Up&&A>=C.y;if(z&&!y.x){h.scrollTo({top:A,behavior:l});return}z?g.y=h.scrollTop-A:g.y=v===Ke.Down?h.scrollTop-_.y:h.scrollTop-C.y,g.y&&h.scrollBy({top:-g.y,behavior:l});break}}this.handleMove(t,uo(ti(f,this.referenceCoordinates),g))}}}handleMove(t,n){const{onMove:o}=this.props;t.preventDefault(),o(n)}handleEnd(t){const{onEnd:n}=this.props;t.preventDefault(),this.detach(),n()}handleCancel(t){const{onCancel:n}=this.props;t.preventDefault(),this.detach(),n()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}}tf.activators=[{eventName:"onKeyDown",handler:(e,t,n)=>{let{keyboardCodes:o=ef,onActivation:r}=t,{active:s}=n;const{code:a}=e.nativeEvent;if(o.start.includes(a)){const l=s.activatorNode.current;return l&&e.target!==l?!1:(e.preventDefault(),r?.({event:e.nativeEvent}),!0)}return!1}}];function nf(e){return!!(e&&"distance"in e)}function of(e){return!!(e&&"delay"in e)}class ga{constructor(t,n,o){var r;o===void 0&&(o=u2(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=n;const{event:s}=t,{target:a}=s;this.props=t,this.events=n,this.document=co(a),this.documentListeners=new Fo(this.document),this.listeners=new Fo(o),this.windowListeners=new Fo(_t(a)),this.initialCoordinates=(r=ni(s))!=null?r:Ht,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:n,bypassActivationConstraint:o}}}=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(At.Resize,this.handleCancel),this.windowListeners.add(At.DragStart,Rp),this.windowListeners.add(At.VisibilityChange,this.handleCancel),this.windowListeners.add(At.ContextMenu,Rp),this.documentListeners.add(At.Keydown,this.handleKeydown),n){if(o!=null&&o({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(of(n)){this.timeoutId=setTimeout(this.handleStart,n.delay),this.handlePending(n);return}if(nf(n)){this.handlePending(n);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,n){const{active:o,onPending:r}=this.props;r(o,t,this.initialCoordinates,n)}handleStart(){const{initialCoordinates:t}=this,{onStart:n}=this.props;t&&(this.activated=!0,this.documentListeners.add(At.Click,p2,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(At.SelectionChange,this.removeTextSelection),n(t))}handleMove(t){var n;const{activated:o,initialCoordinates:r,props:s}=this,{onMove:a,options:{activationConstraint:l}}=s;if(!r)return;const d=(n=ni(t))!=null?n:Ht,c=ti(r,d);if(!o&&l){if(nf(l)){if(l.tolerance!=null&&fa(c,l.tolerance))return this.handleCancel();if(fa(c,l.distance))return this.handleStart()}if(of(l)&&fa(c,l.tolerance))return this.handleCancel();this.handlePending(l,c);return}t.cancelable&&t.preventDefault(),a(d)}handleEnd(){const{onAbort:t,onEnd:n}=this.props;this.detach(),this.activated||t(this.props.active),n()}handleCancel(){const{onAbort:t,onCancel:n}=this.props;this.detach(),this.activated||t(this.props.active),n()}handleKeydown(t){t.code===Ke.Esc&&this.handleCancel()}removeTextSelection(){var t;(t=this.document.getSelection())==null||t.removeAllRanges()}}const g2={cancel:{name:"pointercancel"},move:{name:"pointermove"},end:{name:"pointerup"}};class ha extends ga{constructor(t){const{event:n}=t,o=co(n.target);super(t,g2,o)}}ha.activators=[{eventName:"onPointerDown",handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:o}=t;return!n.isPrimary||n.button!==0?!1:(o?.({event:n}),!0)}}];const h2={move:{name:"mousemove"},end:{name:"mouseup"}};var ya;(function(e){e[e.RightClick=2]="RightClick"})(ya||(ya={}));class y2 extends ga{constructor(t){super(t,h2,co(t.event.target))}}y2.activators=[{eventName:"onMouseDown",handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:o}=t;return n.button===ya.RightClick?!1:(o?.({event:n}),!0)}}];const ba={cancel:{name:"touchcancel"},move:{name:"touchmove"},end:{name:"touchend"}};class b2 extends ga{constructor(t){super(t,ba)}static setup(){return window.addEventListener(ba.move.name,t,{capture:!1,passive:!1}),function(){window.removeEventListener(ba.move.name,t)};function t(){}}}b2.activators=[{eventName:"onTouchStart",handler:(e,t)=>{let{nativeEvent:n}=e,{onActivation:o}=t;const{touches:r}=n;return r.length>1?!1:(o?.({event:n}),!0)}}];var Ko;(function(e){e[e.Pointer=0]="Pointer",e[e.DraggableRect=1]="DraggableRect"})(Ko||(Ko={}));var ri;(function(e){e[e.TreeOrder=0]="TreeOrder",e[e.ReversedTreeOrder=1]="ReversedTreeOrder"})(ri||(ri={}));function m2(e){let{acceleration:t,activator:n=Ko.Pointer,canScroll:o,draggingRect:r,enabled:s,interval:a=5,order:l=ri.TreeOrder,pointerCoordinates:d,scrollableAncestors:c,scrollableAncestorRects:p,delta:f,threshold:y}=e;const g=_2({delta:f,disabled:!s}),[m,h]=$7(),v=u.useRef({x:0,y:0}),b=u.useRef({x:0,y:0}),x=u.useMemo(()=>{switch(n){case Ko.Pointer:return d?{top:d.y,bottom:d.y,left:d.x,right:d.x}:null;case Ko.DraggableRect:return r}},[n,r,d]),k=u.useRef(null),w=u.useCallback(()=>{const C=k.current;if(!C)return;const E=v.current.x*b.current.x,S=v.current.y*b.current.y;C.scrollBy(E,S)},[]),_=u.useMemo(()=>l===ri.TreeOrder?[...c].reverse():c,[l,c]);u.useEffect(()=>{if(!s||!c.length||!x){h();return}for(const C of _){if(o?.(C)===!1)continue;const E=c.indexOf(C),S=p[E];if(!S)continue;const{direction:T,speed:$}=s2(C,S,x,t,y);for(const A of["x","y"])g[A][T[A]]||($[A]=0,T[A]=0);if($.x>0||$.y>0){h(),k.current=C,m(w,a),v.current=$,b.current=T;return}}v.current={x:0,y:0},b.current={x:0,y:0},h()},[t,w,o,h,s,a,JSON.stringify(x),JSON.stringify(g),m,c,_,p,JSON.stringify(y)])}const v2={x:{[lt.Backward]:!1,[lt.Forward]:!1},y:{[lt.Backward]:!1,[lt.Forward]:!1}};function _2(e){let{delta:t,disabled:n}=e;const o=Rr(t);return Wo(r=>{if(n||!o||!r)return v2;const s={x:Math.sign(t.x-o.x),y:Math.sign(t.y-o.y)};return{x:{[lt.Backward]:r.x[lt.Backward]||s.x===-1,[lt.Forward]:r.x[lt.Forward]||s.x===1},y:{[lt.Backward]:r.y[lt.Backward]||s.y===-1,[lt.Forward]:r.y[lt.Forward]||s.y===1}}},[n,t,o])}function x2(e,t){const n=t!=null?e.get(t):void 0,o=n?n.node.current:null;return Wo(r=>{var s;return t==null?null:(s=o??r)!=null?s:null},[o,t])}function w2(e,t){return u.useMemo(()=>e.reduce((n,o)=>{const{sensor:r}=o,s=r.activators.map(a=>({eventName:a.eventName,handler:t(a.handler,o)}));return[...n,...s]},[]),[e,t])}var Vo;(function(e){e[e.Always=0]="Always",e[e.BeforeDragging=1]="BeforeDragging",e[e.WhileDragging=2]="WhileDragging"})(Vo||(Vo={}));var ma;(function(e){e.Optimized="optimized"})(ma||(ma={}));const rf=new Map;function k2(e,t){let{dragging:n,dependencies:o,config:r}=t;const[s,a]=u.useState(null),{frequency:l,measure:d,strategy:c}=r,p=u.useRef(e),f=v(),y=Bo(f),g=u.useCallback(function(b){b===void 0&&(b=[]),!y.current&&a(x=>x===null?b:x.concat(b.filter(k=>!x.includes(k))))},[y]),m=u.useRef(null),h=Wo(b=>{if(f&&!n)return rf;if(!b||b===rf||p.current!==e||s!=null){const x=new Map;for(let k of e){if(!k)continue;if(s&&s.length>0&&!s.includes(k.id)&&k.rect.current){x.set(k.id,k.rect.current);continue}const w=k.node.current,_=w?new pa(d(w),w):null;k.rect.current=_,_&&x.set(k.id,_)}return x}return b},[e,s,n,f,d]);return u.useEffect(()=>{p.current=e},[e]),u.useEffect(()=>{f||g()},[n,f]),u.useEffect(()=>{s&&s.length>0&&a(null)},[JSON.stringify(s)]),u.useEffect(()=>{f||typeof l!="number"||m.current!==null||(m.current=setTimeout(()=>{g(),m.current=null},l))},[l,f,g,...o]),{droppableRects:h,measureDroppableContainers:g,measuringScheduled:s!=null};function v(){switch(c){case Vo.Always:return!1;case Vo.BeforeDragging:return n;default:return!n}}}function va(e,t){return Wo(n=>e?n||(typeof t=="function"?t(e):e):null,[t,e])}function S2(e,t){return va(e,t)}function C2(e){let{callback:t,disabled:n}=e;const o=Zr(t),r=u.useMemo(()=>{if(n||typeof window>"u"||typeof window.MutationObserver>"u")return;const{MutationObserver:s}=window;return new s(o)},[o,n]);return u.useEffect(()=>()=>r?.disconnect(),[r]),r}function ii(e){let{callback:t,disabled:n}=e;const o=Zr(t),r=u.useMemo(()=>{if(n||typeof window>"u"||typeof window.ResizeObserver>"u")return;const{ResizeObserver:s}=window;return new s(o)},[n]);return u.useEffect(()=>()=>r?.disconnect(),[r]),r}function $2(e){return new pa(Ho(e),e)}function sf(e,t,n){t===void 0&&(t=$2);const[o,r]=u.useState(null);function s(){r(d=>{if(!e)return null;if(e.isConnected===!1){var c;return(c=d??n)!=null?c:null}const p=t(e);return JSON.stringify(d)===JSON.stringify(p)?d:p})}const a=C2({callback(d){if(e)for(const c of d){const{type:p,target:f}=c;if(p==="childList"&&f instanceof HTMLElement&&f.contains(e)){s();break}}}}),l=ii({callback:s});return sn(()=>{s(),e?(l?.observe(e),a?.observe(document.body,{childList:!0,subtree:!0})):(l?.disconnect(),a?.disconnect())},[e]),o}function E2(e){const t=va(e);return Kp(e,t)}const af=[];function I2(e){const t=u.useRef(e),n=Wo(o=>e?o&&o!==af&&e&&t.current&&e.parentNode===t.current.parentNode?o:da(e):af,[e]);return u.useEffect(()=>{t.current=e},[e]),n}function A2(e){const[t,n]=u.useState(null),o=u.useRef(e),r=u.useCallback(s=>{const a=ca(s.target);a&&n(l=>l?(l.set(a,ua(a)),new Map(l)):null)},[]);return u.useEffect(()=>{const s=o.current;if(e!==s){a(s);const l=e.map(d=>{const c=ca(d);return c?(c.addEventListener("scroll",r,{passive:!0}),[c,ua(c)]):null}).filter(d=>d!=null);n(l.length?new Map(l):null),o.current=e}return()=>{a(e),a(s)};function a(l){l.forEach(d=>{const c=ca(d);c?.removeEventListener("scroll",r)})}},[r,e]),u.useMemo(()=>e.length?t?Array.from(t.values()).reduce((s,a)=>uo(s,a),Ht):Zp(e):Ht,[e,t])}function lf(e,t){t===void 0&&(t=[]);const n=u.useRef(null);return u.useEffect(()=>{n.current=null},t),u.useEffect(()=>{const o=e!==Ht;o&&!n.current&&(n.current=e),!o&&n.current&&(n.current=null)},[e]),n.current?ti(e,n.current):Ht}function T2(e){u.useEffect(()=>{if(!Jr)return;const t=e.map(n=>{let{sensor:o}=n;return o.setup==null?void 0:o.setup()});return()=>{for(const n of t)n?.()}},e.map(t=>{let{sensor:n}=t;return n}))}function D2(e,t){return u.useMemo(()=>e.reduce((n,o)=>{let{eventName:r,handler:s}=o;return n[r]=a=>{s(a,t)},n},{}),[e,t])}function df(e){return u.useMemo(()=>e?n2(e):null,[e])}const cf=[];function N2(e,t){t===void 0&&(t=Ho);const[n]=e,o=df(n?_t(n):null),[r,s]=u.useState(cf);function a(){s(()=>e.length?e.map(d=>Xp(d)?o:new pa(t(d),d)):cf)}const l=ii({callback:a});return sn(()=>{l?.disconnect(),a(),e.forEach(d=>l?.observe(d))},[e]),r}function uf(e){if(!e)return null;if(e.children.length>1)return e;const t=e.children[0];return Oo(t)?t:e}function z2(e){let{measure:t}=e;const[n,o]=u.useState(null),r=u.useCallback(c=>{for(const{target:p}of c)if(Oo(p)){o(f=>{const y=t(p);return f?{...f,width:y.width,height:y.height}:y});break}},[t]),s=ii({callback:r}),a=u.useCallback(c=>{const p=uf(c);s?.disconnect(),p&&s?.observe(p),o(p?t(p):null)},[t,s]),[l,d]=Qr(a);return u.useMemo(()=>({nodeRef:l,rect:n,setRef:d}),[n,l,d])}const M2=[{sensor:ha,options:{}},{sensor:tf,options:{}}],L2={current:{}},si={draggable:{measure:Up},droppable:{measure:Up,strategy:Vo.WhileDragging,frequency:ma.Optimized},dragOverlay:{measure:Ho}};class Uo extends Map{get(t){var n;return t!=null&&(n=super.get(t))!=null?n:void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(t=>{let{disabled:n}=t;return!n})}getNodeFor(t){var n,o;return(n=(o=this.get(t))==null?void 0:o.node.current)!=null?n:void 0}}const P2={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new Uo,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:oi},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:si,measureDroppableContainers:oi,windowRect:null,measuringScheduled:!1},pf={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:""},dispatch:oi,draggableNodes:new Map,over:null,measureDroppableContainers:oi},qo=u.createContext(pf),ff=u.createContext(P2);function O2(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new Uo}}}function B2(e,t){switch(t.type){case it.DragStart:return{...e,draggable:{...e.draggable,initialCoordinates:t.initialCoordinates,active:t.active}};case it.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 it.DragEnd:case it.DragCancel:return{...e,draggable:{...e.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case it.RegisterDroppable:{const{element:n}=t,{id:o}=n,r=new Uo(e.droppable.containers);return r.set(o,n),{...e,droppable:{...e.droppable,containers:r}}}case it.SetDroppableDisabled:{const{id:n,key:o,disabled:r}=t,s=e.droppable.containers.get(n);if(!s||o!==s.key)return e;const a=new Uo(e.droppable.containers);return a.set(n,{...s,disabled:r}),{...e,droppable:{...e.droppable,containers:a}}}case it.UnregisterDroppable:{const{id:n,key:o}=t,r=e.droppable.containers.get(n);if(!r||o!==r.key)return e;const s=new Uo(e.droppable.containers);return s.delete(n),{...e,droppable:{...e.droppable,containers:s}}}default:return e}}function W2(e){let{disabled:t}=e;const{active:n,activatorEvent:o,draggableNodes:r}=u.useContext(qo),s=Rr(o),a=Rr(n?.id);return u.useEffect(()=>{if(!t&&!o&&s&&a!=null){if(!la(s)||document.activeElement===s.target)return;const l=r.get(a);if(!l)return;const{activatorNode:d,node:c}=l;if(!d.current&&!c.current)return;requestAnimationFrame(()=>{for(const p of[d.current,c.current]){if(!p)continue;const f=A7(p);if(f){f.focus();break}}})}},[o,t,r,a,s]),null}function gf(e,t){let{transform:n,...o}=t;return e!=null&&e.length?e.reduce((r,s)=>s({transform:r,...o}),n):n}function j2(e){return u.useMemo(()=>({draggable:{...si.draggable,...e?.draggable},droppable:{...si.droppable,...e?.droppable},dragOverlay:{...si.dragOverlay,...e?.dragOverlay}}),[e?.draggable,e?.droppable,e?.dragOverlay])}function H2(e){let{activeNode:t,measure:n,initialRect:o,config:r=!0}=e;const s=u.useRef(!1),{x:a,y:l}=typeof r=="boolean"?{x:r,y:r}:r;sn(()=>{if(!a&&!l||!t){s.current=!1;return}if(s.current||!o)return;const c=t?.node.current;if(!c||c.isConnected===!1)return;const p=n(c),f=Kp(p,o);if(a||(f.x=0),l||(f.y=0),s.current=!0,Math.abs(f.x)>0||Math.abs(f.y)>0){const y=qp(c);y&&y.scrollBy({top:f.y,left:f.x})}},[t,a,l,o,n])}const ai=u.createContext({...Ht,scaleX:1,scaleY:1});var hn;(function(e){e[e.Uninitialized=0]="Uninitialized",e[e.Initializing=1]="Initializing",e[e.Initialized=2]="Initialized"})(hn||(hn={}));const F2=u.memo(function(t){var n,o,r,s;let{id:a,accessibility:l,autoScroll:d=!0,children:c,sensors:p=M2,collisionDetection:f=Y7,measuring:y,modifiers:g,...m}=t;const h=u.useReducer(B2,void 0,O2),[v,b]=h,[x,k]=L7(),[w,_]=u.useState(hn.Uninitialized),C=w===hn.Initialized,{draggable:{active:E,nodes:S,translate:T},droppable:{containers:$}}=v,A=E!=null?S.get(E):null,z=u.useRef({initial:null,translated:null}),D=u.useMemo(()=>{var J;return E!=null?{id:E,data:(J=A?.data)!=null?J:L2,rect:z}:null},[E,A]),O=u.useRef(null),[M,B]=u.useState(null),[N,H]=u.useState(null),L=Bo(m,Object.values(m)),I=ei("DndDescribedBy",a),P=u.useMemo(()=>$.getEnabled(),[$]),F=j2(y),{droppableRects:G,measureDroppableContainers:V,measuringScheduled:Y}=k2(P,{dragging:C,dependencies:[T.x,T.y],config:F.droppable}),Z=x2(S,E),se=u.useMemo(()=>N?ni(N):null,[N]),re=ue(),U=S2(Z,F.draggable.measure);H2({activeNode:E!=null?S.get(E):null,config:re.layoutShiftCompensation,initialRect:U,measure:F.draggable.measure});const ee=sf(Z,F.draggable.measure,U),fe=sf(Z?Z.parentElement:null),K=u.useRef({activatorEvent:null,active:null,activeNode:Z,collisionRect:null,collisions:null,droppableRects:G,draggableNodes:S,draggingNode:null,draggingNodeRect:null,droppableContainers:$,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),ne=$.getNodeFor((n=K.current.over)==null?void 0:n.id),me=z2({measure:F.dragOverlay.measure}),Ce=(o=me.nodeRef.current)!=null?o:Z,ze=C?(r=me.rect)!=null?r:ee:null,Se=!!(me.nodeRef.current&&me.rect),qe=E2(Se?null:ee),De=df(Ce?_t(Ce):null),Pe=I2(C?ne??Z:null),Qe=N2(Pe),Me=gf(g,{transform:{x:T.x-qe.x,y:T.y-qe.y,scaleX:1,scaleY:1},activatorEvent:N,active:D,activeNodeRect:ee,containerNodeRect:fe,draggingNodeRect:ze,over:K.current.over,overlayNodeRect:me.rect,scrollableAncestors:Pe,scrollableAncestorRects:Qe,windowRect:De}),Re=se?uo(se,T):null,ve=A2(Pe),te=lf(ve),he=lf(ve,[ee]),Q=uo(Me,te),ie=ze?R7(ze,Me):null,_e=D&&ie?f({active:D,collisionRect:ie,droppableRects:G,droppableContainers:P,pointerCoordinates:Re}):null,ge=q7(_e,"id"),[Ae,Ne]=u.useState(null),Le=Se?Me:uo(Me,he),q=Z7(Le,(s=Ae?.rect)!=null?s:null,ee),ae=u.useRef(null),pe=u.useCallback((J,le)=>{let{sensor:Ie,options:dt}=le;if(O.current==null)return;const pt=S.get(O.current);if(!pt)return;const ot=J.nativeEvent,Oe=new Ie({active:O.current,activeNode:pt,event:ot,options:dt,context:K,onAbort(Ye){if(!S.get(Ye))return;const{onDragAbort:Dt}=L.current,Nt={id:Ye};Dt?.(Nt),x({type:"onDragAbort",event:Nt})},onPending(Ye,Tt,Dt,Nt){if(!S.get(Ye))return;const{onDragPending:wn}=L.current,Zt={id:Ye,constraint:Tt,initialCoordinates:Dt,offset:Nt};wn?.(Zt),x({type:"onDragPending",event:Zt})},onStart(Ye){const Tt=O.current;if(Tt==null)return;const Dt=S.get(Tt);if(!Dt)return;const{onDragStart:Nt}=L.current,xn={activatorEvent:ot,active:{id:Tt,data:Dt.data,rect:z}};Cn.unstable_batchedUpdates(()=>{Nt?.(xn),_(hn.Initializing),b({type:it.DragStart,initialCoordinates:Ye,active:Tt}),x({type:"onDragStart",event:xn}),B(ae.current),H(ot)})},onMove(Ye){b({type:it.DragMove,coordinates:Ye})},onEnd:He(it.DragEnd),onCancel:He(it.DragCancel)});ae.current=Oe;function He(Ye){return async function(){const{active:Dt,collisions:Nt,over:xn,scrollAdjustedTranslate:wn}=K.current;let Zt=null;if(Dt&&wn){const{cancelDrop:Hn}=L.current;Zt={activatorEvent:ot,active:Dt,collisions:Nt,delta:wn,over:xn},Ye===it.DragEnd&&typeof Hn=="function"&&await Promise.resolve(Hn(Zt))&&(Ye=it.DragCancel)}O.current=null,Cn.unstable_batchedUpdates(()=>{b({type:Ye}),_(hn.Uninitialized),Ne(null),B(null),H(null),ae.current=null;const Hn=Ye===it.DragEnd?"onDragEnd":"onDragCancel";if(Zt){const ln=L.current[Hn];ln?.(Zt),x({type:Hn,event:Zt})}})}}},[S]),$e=u.useCallback((J,le)=>(Ie,dt)=>{const pt=Ie.nativeEvent,ot=S.get(dt);if(O.current!==null||!ot||pt.dndKit||pt.defaultPrevented)return;const Oe={active:ot};J(Ie,le.options,Oe)===!0&&(pt.dndKit={capturedBy:le.sensor},O.current=dt,pe(Ie,le))},[S,pe]),be=w2(p,$e);T2(p),sn(()=>{ee&&w===hn.Initializing&&_(hn.Initialized)},[ee,w]),u.useEffect(()=>{const{onDragMove:J}=L.current,{active:le,activatorEvent:Ie,collisions:dt,over:pt}=K.current;if(!le||!Ie)return;const ot={active:le,activatorEvent:Ie,collisions:dt,delta:{x:Q.x,y:Q.y},over:pt};Cn.unstable_batchedUpdates(()=>{J?.(ot),x({type:"onDragMove",event:ot})})},[Q.x,Q.y]),u.useEffect(()=>{const{active:J,activatorEvent:le,collisions:Ie,droppableContainers:dt,scrollAdjustedTranslate:pt}=K.current;if(!J||O.current==null||!le||!pt)return;const{onDragOver:ot}=L.current,Oe=dt.get(ge),He=Oe&&Oe.rect.current?{id:Oe.id,rect:Oe.rect.current,data:Oe.data,disabled:Oe.disabled}:null,Ye={active:J,activatorEvent:le,collisions:Ie,delta:{x:pt.x,y:pt.y},over:He};Cn.unstable_batchedUpdates(()=>{Ne(He),ot?.(Ye),x({type:"onDragOver",event:Ye})})},[ge]),sn(()=>{K.current={activatorEvent:N,active:D,activeNode:Z,collisionRect:ie,collisions:_e,droppableRects:G,draggableNodes:S,draggingNode:Ce,draggingNodeRect:ze,droppableContainers:$,over:Ae,scrollableAncestors:Pe,scrollAdjustedTranslate:Q},z.current={initial:ze,translated:ie}},[D,Z,_e,ie,S,Ce,ze,G,$,Ae,Pe,Q]),m2({...re,delta:T,draggingRect:ie,pointerCoordinates:Re,scrollableAncestors:Pe,scrollableAncestorRects:Qe});const j=u.useMemo(()=>({active:D,activeNode:Z,activeNodeRect:ee,activatorEvent:N,collisions:_e,containerNodeRect:fe,dragOverlay:me,draggableNodes:S,droppableContainers:$,droppableRects:G,over:Ae,measureDroppableContainers:V,scrollableAncestors:Pe,scrollableAncestorRects:Qe,measuringConfiguration:F,measuringScheduled:Y,windowRect:De}),[D,Z,ee,N,_e,fe,me,S,$,G,Ae,V,Pe,Qe,F,Y,De]),oe=u.useMemo(()=>({activatorEvent:N,activators:be,active:D,activeNodeRect:ee,ariaDescribedById:{draggable:I},dispatch:b,draggableNodes:S,over:Ae,measureDroppableContainers:V}),[N,be,D,ee,b,I,S,Ae,V]);return u.createElement(Fp.Provider,{value:k},u.createElement(qo.Provider,{value:oe},u.createElement(ff.Provider,{value:j},u.createElement(ai.Provider,{value:q},c)),u.createElement(W2,{disabled:l?.restoreFocus===!1})),u.createElement(B7,{...l,hiddenTextDescribedById:I}));function ue(){const J=M?.autoScrollEnabled===!1,le=typeof d=="object"?d.enabled===!1:d===!1,Ie=C&&!J&&!le;return typeof d=="object"?{...d,enabled:Ie}:{enabled:Ie}}}),K2=u.createContext(null),hf="button",V2="Draggable";function U2(e){let{id:t,data:n,disabled:o=!1,attributes:r}=e;const s=ei(V2),{activators:a,activatorEvent:l,active:d,activeNodeRect:c,ariaDescribedById:p,draggableNodes:f,over:y}=u.useContext(qo),{role:g=hf,roleDescription:m="draggable",tabIndex:h=0}=r??{},v=d?.id===t,b=u.useContext(v?ai:K2),[x,k]=Qr(),[w,_]=Qr(),C=D2(a,t),E=Bo(n);sn(()=>(f.set(t,{id:t,key:s,node:x,activatorNode:w,data:E}),()=>{const T=f.get(t);T&&T.key===s&&f.delete(t)}),[f,t]);const S=u.useMemo(()=>({role:g,tabIndex:h,"aria-disabled":o,"aria-pressed":v&&g===hf?!0:void 0,"aria-roledescription":m,"aria-describedby":p.draggable}),[o,g,h,v,m,p.draggable]);return{active:d,activatorEvent:l,activeNodeRect:c,attributes:S,isDragging:v,listeners:o?void 0:C,node:x,over:y,setNodeRef:k,setActivatorNodeRef:_,transform:b}}function q2(){return u.useContext(ff)}const G2="Droppable",Y2={timeout:25};function X2(e){let{data:t,disabled:n=!1,id:o,resizeObserverConfig:r}=e;const s=ei(G2),{active:a,dispatch:l,over:d,measureDroppableContainers:c}=u.useContext(qo),p=u.useRef({disabled:n}),f=u.useRef(!1),y=u.useRef(null),g=u.useRef(null),{disabled:m,updateMeasurementsFor:h,timeout:v}={...Y2,...r},b=Bo(h??o),x=u.useCallback(()=>{if(!f.current){f.current=!0;return}g.current!=null&&clearTimeout(g.current),g.current=setTimeout(()=>{c(Array.isArray(b.current)?b.current:[b.current]),g.current=null},v)},[v]),k=ii({callback:x,disabled:m||!a}),w=u.useCallback((S,T)=>{k&&(T&&(k.unobserve(T),f.current=!1),S&&k.observe(S))},[k]),[_,C]=Qr(w),E=Bo(t);return u.useEffect(()=>{!k||!_.current||(k.disconnect(),f.current=!1,k.observe(_.current))},[_,k]),u.useEffect(()=>(l({type:it.RegisterDroppable,element:{id:o,key:s,disabled:n,node:_,rect:y,data:E}}),()=>l({type:it.UnregisterDroppable,key:s,id:o})),[o]),u.useEffect(()=>{n!==p.current.disabled&&(l({type:it.SetDroppableDisabled,id:o,key:s,disabled:n}),p.current.disabled=n)},[o,s,n,l]),{active:a,rect:y,isOver:d?.id===o,node:_,over:d,setNodeRef:C}}function J2(e){let{animation:t,children:n}=e;const[o,r]=u.useState(null),[s,a]=u.useState(null),l=Rr(n);return!n&&!o&&l&&r(l),sn(()=>{if(!s)return;const d=o?.key,c=o?.props.id;if(d==null||c==null){r(null);return}Promise.resolve(t(c,s)).then(()=>{r(null)})},[t,o,s]),u.createElement(u.Fragment,null,n,o?u.cloneElement(o,{ref:a}):null)}const Z2={x:0,y:0,scaleX:1,scaleY:1};function Q2(e){let{children:t}=e;return u.createElement(qo.Provider,{value:pf},u.createElement(ai.Provider,{value:Z2},t))}const R2={position:"fixed",touchAction:"none"},eI=e=>la(e)?"transform 250ms ease":void 0,tI=u.forwardRef((e,t)=>{let{as:n,activatorEvent:o,adjustScale:r,children:s,className:a,rect:l,style:d,transform:c,transition:p=eI}=e;if(!l)return null;const f=r?c:{...c,scaleX:1,scaleY:1},y={...R2,width:l.width,height:l.height,top:l.top,left:l.left,transform:jo.Transform.toString(f),transformOrigin:r&&o?F7(o,l):void 0,transition:typeof p=="function"?p(o):p,...d};return u.createElement(n,{className:a,style:y,ref:t},s)}),nI={duration:250,easing:"ease",keyframes:e=>{let{transform:{initial:t,final:n}}=e;return[{transform:jo.Transform.toString(t)},{transform:jo.Transform.toString(n)}]},sideEffects:(e=>t=>{let{active:n,dragOverlay:o}=t;const r={},{styles:s,className:a}=e;if(s!=null&&s.active)for(const[l,d]of Object.entries(s.active))d!==void 0&&(r[l]=n.node.style.getPropertyValue(l),n.node.style.setProperty(l,d));if(s!=null&&s.dragOverlay)for(const[l,d]of Object.entries(s.dragOverlay))d!==void 0&&o.node.style.setProperty(l,d);return a!=null&&a.active&&n.node.classList.add(a.active),a!=null&&a.dragOverlay&&o.node.classList.add(a.dragOverlay),function(){for(const[d,c]of Object.entries(r))n.node.style.setProperty(d,c);a!=null&&a.active&&n.node.classList.remove(a.active)}})({styles:{active:{opacity:"0"}}})};function oI(e){let{config:t,draggableNodes:n,droppableContainers:o,measuringConfiguration:r}=e;return Zr((s,a)=>{if(t===null)return;const l=n.get(s);if(!l)return;const d=l.node.current;if(!d)return;const c=uf(a);if(!c)return;const{transform:p}=_t(a).getComputedStyle(a),f=Vp(p);if(!f)return;const y=typeof t=="function"?t:rI(t);return Qp(d,r.draggable.measure),y({active:{id:s,data:l.data,node:d,rect:r.draggable.measure(d)},draggableNodes:n,dragOverlay:{node:a,rect:r.dragOverlay.measure(c)},droppableContainers:o,measuringConfiguration:r,transform:f})})}function rI(e){const{duration:t,easing:n,sideEffects:o,keyframes:r}={...nI,...e};return s=>{let{active:a,dragOverlay:l,transform:d,...c}=s;if(!t)return;const p={x:l.rect.left-a.rect.left,y:l.rect.top-a.rect.top},f={scaleX:d.scaleX!==1?a.rect.width*d.scaleX/l.rect.width:1,scaleY:d.scaleY!==1?a.rect.height*d.scaleY/l.rect.height:1},y={x:d.x-p.x,y:d.y-p.y,...f},g=r({...c,active:a,dragOverlay:l,transform:{initial:d,final:y}}),[m]=g,h=g[g.length-1];if(JSON.stringify(m)===JSON.stringify(h))return;const v=o?.({active:a,dragOverlay:l,...c}),b=l.node.animate(g,{duration:t,easing:n,fill:"forwards"});return new Promise(x=>{b.onfinish=()=>{v?.(),x()}})}}let yf=0;function iI(e){return u.useMemo(()=>{if(e!=null)return yf++,yf},[e])}const sI=u.memo(e=>{let{adjustScale:t=!1,children:n,dropAnimation:o,style:r,transition:s,modifiers:a,wrapperElement:l="div",className:d,zIndex:c=999}=e;const{activatorEvent:p,active:f,activeNodeRect:y,containerNodeRect:g,draggableNodes:m,droppableContainers:h,dragOverlay:v,over:b,measuringConfiguration:x,scrollableAncestors:k,scrollableAncestorRects:w,windowRect:_}=q2(),C=u.useContext(ai),E=iI(f?.id),S=gf(a,{activatorEvent:p,active:f,activeNodeRect:y,containerNodeRect:g,draggingNodeRect:v.rect,over:b,overlayNodeRect:v.rect,scrollableAncestors:k,scrollableAncestorRects:w,transform:C,windowRect:_}),T=va(y),$=oI({config:o,draggableNodes:m,droppableContainers:h,measuringConfiguration:x}),A=T?v.setRef:void 0;return u.createElement(Q2,null,u.createElement(J2,{animation:$},f&&E?u.createElement(tI,{key:E,id:f.id,ref:A,as:l,activatorEvent:p,adjustScale:t,className:d,transition:s,rect:T,style:{zIndex:c,...r},transform:S},n):null))});function Go(e,t){return!t||!Array.isArray(t.draggable)?!1:t.draggable.includes(e)}function aI({draggedComponentName:e,targetContainerName:t,nesting:n}){if(!n||!Go(e,n))return!1;const o=n.containers;if(!o||typeof o!="object")return!1;const r=o[t];return!r||!Array.isArray(r.accepts)?!1:r.accepts.includes(e)}function bf(e,t){if(!t?.containers)return!1;const n=t.containers[e];return!!(n&&Array.isArray(n.accepts)&&n.accepts.length>0)}function lI(e,t,n,o,r){if(!n||n.length===0)return{parentPath:[],index:r};if(e&&bf(e,o))return{parentPath:n,index:t};const s=n.slice(0,-1),a=n[n.length-1]??0;return{parentPath:s,index:a+1}}function mf(e,t){return e===t||e.startsWith(`${t}.`)}function vf(e,t){if(e==="")return/^\d+$/.test(t)?Number(t):null;const n=`${e}.children.`;if(!t.startsWith(n))return null;const o=t.slice(n.length);return/^\d+$/.test(o)?Number(o):null}function dI(e,t){const n=[];return e.querySelectorAll("[data-editor-path]").forEach(o=>{if(o.hasAttribute("data-dnd-placeholder")||o.closest("[data-dnd-placeholder]"))return;const r=o.dataset.editorPath;typeof r=="string"&&n.push({path:t(r),domPath:r,rect:o.getBoundingClientRect()})}),n}const cI=16;function uI(e){const{frameEl:t,draggedPath:n,acceptsContainer:o,allowsNestSlot:r,includeContainer:s}=e,a=e.normalizeContainerPath??(g=>g),l=t.getBoundingClientRect(),d=dI(t,a),c=new Map;for(const g of d)c.has(g.path)||c.set(g.path,g.domPath);const p=a(n),f=new Set([""]);for(const g of d){const m=fI(g.path);m!==null&&f.add(m)}for(const g of d)f.add(g.path);const y=[];for(const g of f){const m=g==="",h=m?null:c.get(g)??g,v=m?t:t.querySelector(`[data-editor-path="${wf(h)}"]`);if(!v&&!m||!m&&mf(g,p))continue;const b=g;if(!m&&s&&!s(b))continue;const x=C=>{const E=c.get(C);if(!E||typeof window>"u")return!1;const S=t.querySelector(`[data-editor-path="${wf(E)}"]`);return S?(window.getComputedStyle(S).display??"").toLowerCase()==="contents":!1},k=d.filter(C=>vf(g,C.path)!==null).filter(C=>!mf(C.path,p)).filter(C=>!x(C.path)).map(C=>({origIndex:vf(g,C.path),rect:pI(C.rect,C.path,d)})).filter(C=>C.rect.width>0||C.rect.height>0).sort((C,E)=>C.origIndex-E.origIndex),w=Dp(m?t:v).kind,_=w==="flex_row_single"||w==="flex_row_wrap"||w==="grid_single_row"||w==="grid_2d";if(k.length>0){if(o(b)){k.forEach(E=>{y.push(_f(b,E.origIndex,E.rect,l,_,"before"))});const C=k[k.length-1];y.push(_f(b,C.origIndex+1,C.rect,l,_,"after"))}}else if(!m&&r(b)&&v){const C=v.getBoundingClientRect();C.width>0&&C.height>0&&y.push({id:`slot:${b}:0`,kind:"nest",containerPath:b,index:0,box:xf(C,l),orientation:"area"})}else m&&y.push({id:"slot::0",kind:"gap",containerPath:"",index:0,box:xf(l,l),orientation:"area"})}return y.filter(g=>ao(g.box,t))}function _f(e,t,n,o,r,s){const a=cI;let l;if(r)l={left:(s==="before"?n.left:n.right)-a/2,top:n.top,width:a,height:n.height};else{const d=s==="before"?n.top:n.bottom;l={left:n.left,top:d-a/2,width:n.width,height:a}}return{id:`slot:${e}:${t}`,kind:"gap",containerPath:e,index:t,box:{left:l.left-o.left,top:l.top-o.top,width:l.width,height:l.height,scale:1},orientation:r?"vertical":"horizontal"}}function pI(e,t,n){if(e.width>0||e.height>0)return e;const o=`${t}.children.`;let r=1/0,s=1/0,a=-1/0,l=-1/0;for(const d of n)d.path.startsWith(o)&&(d.rect.width===0&&d.rect.height===0||(r=Math.min(r,d.rect.left),s=Math.min(s,d.rect.top),a=Math.max(a,d.rect.right),l=Math.max(l,d.rect.bottom)));return r===1/0?e:{left:r,top:s,width:a-r,height:l-s,right:a,bottom:l,x:r,y:s,toJSON:()=>({})}}function xf(e,t){return{left:e.left-t.left,top:e.top-t.top,width:e.width,height:e.height,scale:1}}function fI(e){if(e==="")return null;const t=e.lastIndexOf(".children.");return t<0?"":e.slice(0,t)}function gI(e){if(!e.startsWith("slot:"))return null;const t=e.slice(5),n=t.lastIndexOf(":");if(n<0)return null;const o=t.slice(0,n),r=Number(t.slice(n+1));return Number.isFinite(r)?{containerPath:o,index:r}:null}function wf(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/[^a-zA-Z0-9_\-.]/g,t=>`\\${t}`)}function _a(e){return typeof e=="string"&&e.length>0?e:null}function xa(e,t){return t&&e.startsWith(`${t}.`)?t:e}function kf(e){if(typeof e!="string")return null;const t=gI(e);return t?{containerPath:t.containerPath,index:t.index}:null}function wa(e,t){return t?e.startsWith(`${t}.iteration.`):!1}function ka(e,t,n){return t?n==="iteration_item"?wa(e,t):e===t||e.startsWith(`${t}.`):!1}function hI(e){const{frameEl:t,nesting:n,editMode:o,currentExtensionId:r,editableRootPath:s,components:a,patchLayout:l,pushHistory:d,onMovePath:c,selectedPath:p,showBranchBoundaryHint:f}=e,y=(o==="iteration_item"||o==="modal")&&s&&s.length>0?at(s):null,[g,m]=u.useState(null),[h,v]=u.useState(null),[b,x]=u.useState(null),k=u.useRef({components:a,nesting:n,editMode:o,currentExtensionId:r,selectedPath:p,editableRootSourcePath:y});k.current={components:a,nesting:n,editMode:o,currentExtensionId:r,selectedPath:p,editableRootSourcePath:y};const w=u.useRef(null),_=u.useCallback(M=>({children:M}),[]),C=u.useCallback((M,B)=>{const N=We(_(M),B);return N?typeof N.name=="string"?N.name:typeof N.type=="string"?N.type:null:null},[_]),E=u.useCallback(M=>B=>{const N=k.current;if(B==="")return Go(M,N.nesting);const H=Ze(B),L=We(_(N.components),H);if(!L)return!1;const I=typeof L.name=="string"?L.name:typeof L.type=="string"?L.type:"";if(!I)return!1;const P=!!N.editableRootSourcePath&&(B===N.editableRootSourcePath||B.startsWith(`${N.editableRootSourcePath}.`));if(N.editableRootSourcePath&&!P)return!1;if(!P){const F=Sa(_(N.components),H);if(gn(L,N.editMode,N.currentExtensionId,F)!=="none")return!1}return bf(I,N.nesting)?aI({draggedComponentName:M,targetContainerName:I,nesting:N.nesting}):!1},[_]),S=u.useCallback(M=>{if(M==="")return!0;const B=k.current,N=Ze(M),H=w.current;if(H&&H.length>0){const P=H.slice(0,-1);if(li(N,P))return!0}const L=We(_(B.components),N);return L?(typeof L.name=="string"?L.name:typeof L.type=="string"?L.type:"").length>0:!1},[_]),T=u.useCallback(M=>{const B=E(M),N=k.current,H=w.current,L=H?H.slice(0,-1):null,I=new Set;if(L)for(let V=L.length;V>=0;V--)I.add(di(L.slice(0,V)));const P=di(H??[]),F=V=>!!H&&(V===P||V.startsWith(`${P}.`)),G=(V,Y)=>{for(let Z=0;ZV===""?!0:F(V)?!1:I.has(V),allowsNestSlot:V=>{if(!B(V))return!1;if(L){const Y=Ze(V);if(li(Y,L))return!1}return S(V)}}},[E,S,_]),$=u.useCallback(M=>{const B=_a(M.active.id),N=k.current;if(!B)return;const H=xa(B,N.selectedPath),L=Ze(H),I=We(_(N.components),L),P=I&&typeof I.name=="string"?I.name:I&&typeof I.type=="string"?I.type:null;m(H),v(P),x(null),w.current=I?L:null;let F="allowed";if(!P||!Go(P,N.nesting))F="denied_no_draggable";else if(I){const G=Sa(_(N.components),L),V=gn(I,N.editMode,N.currentExtensionId,G);N.editableRootSourcePath&&!ka(H,N.editableRootSourcePath,N.editMode)||Xi(G)&&!wa(H,N.editableRootSourcePath)?F="denied_data_bound":V==="base"||V==="partial"?F="denied_base_locked":(V==="extension"||V==="extension_point")&&(F="denied_extension_locked")}$n({source:"drag",draggedComponentName:P,targetContainerName:null,targetContainerPath:null,decision:F,result:F==="allowed"?"completed":"denied",timestamp:Date.now()})},[_]),A=u.useCallback(M=>{if(!t)return;const B=_a(M.active.id);if(!B)return;const N=h;if(!N){x(null);return}const H=k.current,L=xa(B,H.selectedPath),I=Ze(L),P=We(_(H.components),I);if(!P||!Go(N,H.nesting)){x(null);return}const F=Sa(_(H.components),I);if(H.editableRootSourcePath&&!ka(L,H.editableRootSourcePath,H.editMode)){x(null);return}const G=gn(P,H.editMode,H.currentExtensionId,F),V=wa(L,H.editableRootSourcePath);if(Xi(F)&&!V||G!=="none"&&G!=="data_bound"&&!V){x(null);return}x(kf(M.over?.id))},[t,h,_]),z=u.useCallback(()=>{m(null),v(null),x(null),w.current=null},[]),D=u.useCallback(M=>{const B=_a(M.active.id),N=h,H=k.current,L=B?xa(B,H.selectedPath):null;if(!t||!L||!N){z();return}const I=kf(M.over?.id),P=Ze(L);if(!I){$n({source:"drag",draggedComponentName:N,targetContainerName:null,targetContainerPath:null,decision:"denied_no_accepts",result:"cancelled",timestamp:Date.now()}),z();return}const F=I.containerPath===""?[]:Ze(I.containerPath),G=I.containerPath===""?null:C(H.components,F);if(!yI(P.slice(0,-1),F)){$n({source:"drag",draggedComponentName:N,targetContainerName:G,targetContainerPath:I.containerPath||null,decision:"denied_responsive_branch_boundary",result:"denied",timestamp:Date.now()}),f?.(),z();return}if(H.editableRootSourcePath&&!ka(I.containerPath,H.editableRootSourcePath,H.editMode)){$n({source:"drag",draggedComponentName:N,targetContainerName:G,targetContainerPath:I.containerPath||null,decision:"denied_data_bound",result:"denied",timestamp:Date.now()}),z();return}const V=P.slice(0,-1),Y=P[P.length-1]??-1;if(li(V,F)&&(I.index===Y||I.index===Y+1)){$n({source:"drag",draggedComponentName:N,targetContainerName:G,targetContainerPath:I.containerPath||null,decision:"allowed",insertionIndex:I.index,result:"cancelled",timestamp:Date.now()}),z();return}const re=li(V,F),U=I.index;let ee=[];l(me=>{const Se=Db({children:me},P,F,U).children??[];return ee=Se,Se}),d(ee,`move ${N}`);const fe=id(F,P),K=re&&Y{z()},[z]);return{activeDragPath:g,activeDragName:h,activeDropZone:b,onDragStart:$,onDragMove:A,onDragEnd:D,onDragCancel:O,buildSlotPredicates:T}}function Sa(e,t){const n=[];let o=e,r=Array.isArray(e.children)?e.children:[];for(let s=0;s0?at(s):null,{t:m}=tt(),[h,v]=u.useState(!1),b=u.useRef(null),x=u.useCallback(()=>{v(!0),b.current&&clearTimeout(b.current),b.current=setTimeout(()=>v(!1),2600)},[]);u.useEffect(()=>()=>{b.current&&clearTimeout(b.current)},[]);const k=hI({frameEl:t,nesting:n,editMode:o,currentExtensionId:r,editableRootPath:s,components:a,patchLayout:l,pushHistory:d,onMovePath:p,selectedPath:y,showBranchBoundaryHint:x}),w=j7(W7(ha,{activationConstraint:{distance:8}})),[_,C]=u.useState([]),E=u.useCallback(()=>{if(!t){C([]);return}if(k.activeDragPath!==null)return;const L={children:a},I=t.querySelectorAll("[data-editor-path]"),P=[],F=new Map;I.forEach(G=>{const V=G.dataset.editorPath;if(typeof V!="string"||o!=="iteration_item"&&g&&!vI(V,g,o))return;const Y=bI(V);if(Y!==null&&!Yo(V,g)){if(/\.iteration\.\d+$/.test(V)){const K=so(G,t);if(K&&ao(K,t)){const ne=F.get(Y)??[];ne.push(K),F.set(Y,ne)}}return}if(Yo(V,g)&&/\.iteration\.\d+$/.test(V))return;const Z=Ze(V),se=We(L,Z);if(!se||se.iteration&&se.iteration.source!==void 0)return;const re=typeof se.name=="string"?se.name:typeof se.type=="string"?se.type:null;if(!re||!Go(re,n))return;const U=Cf(L,Z);if(Xi(U)&&!Yo(V,g))return;const ee=gn(se,o,r,U);if(ee!=="none"&&ee!=="data_bound"&&!Yo(V,g))return;const fe=so(G,t);fe&&ao(fe,t)&&P.push({path:V,name:re,box:fe})});for(const[G,V]of F){const Y=Ze(G),Z=We(L,Y);if(!Z)continue;const se=typeof Z.name=="string"?Z.name:typeof Z.type=="string"?Z.type:null;if(!se)continue;const re=Cf(L,Y),U=gn(Z,o,r,re);if(U!=="none"&&U!=="data_bound")continue;const ee=_I(V);ee&&ao(ee,t)&&P.push({path:G,name:se,box:ee,isIterationGroup:!0})}C(P)},[t,a,n,o,r,g,k.activeDragPath]);u.useEffect(()=>{E()},[E]),u.useEffect(()=>{if(t)return $p(E,t)},[t,E]);const S=k.activeDragPath!==null,T=k.activeDragName,$=k.activeDragPath,[A,z]=u.useState(null),D=u.useRef(null);u.useEffect(()=>{if(!$||!t){$||(D.current=null,z(null));return}if(D.current===$)return;D.current=$;const L=t.querySelector(`[data-editor-path="${Sf($)}"]`);if(L){const re=L.getBoundingClientRect();z({node:L.cloneNode(!0),width:re.width,height:re.height});return}const I=Array.from(t.querySelectorAll(`[data-editor-path^="${Sf($)}.iteration."]`)).filter(re=>/\.iteration\.\d+$/.test(re.dataset.editorPath??""));if(I.length===0){z(null);return}let P=1/0,F=1/0,G=-1/0,V=-1/0;for(const re of I){const U=re.getBoundingClientRect();P=Math.min(P,U.left),F=Math.min(F,U.top),G=Math.max(G,U.right),V=Math.max(V,U.bottom)}const Y=G-P,Z=V-F,se=document.createElement("div");se.style.position="relative",se.style.width=`${Y}px`,se.style.height=`${Z}px`;for(const re of I){const U=re.getBoundingClientRect(),ee=re.cloneNode(!0);ee.style.position="absolute",ee.style.left=`${U.left-P}px`,ee.style.top=`${U.top-F}px`,ee.style.width=`${U.width}px`,ee.style.height=`${U.height}px`,ee.style.margin="0",se.appendChild(ee)}z({node:se,width:Y,height:Z})},[$,t]);const[O,M]=u.useState([]),B=u.useRef(null),N=u.useRef(k.buildSlotPredicates);if(N.current=k.buildSlotPredicates,u.useEffect(()=>{if(!$||!T||!t){B.current=null,M(F=>F.length===0?F:[]);return}if(B.current===$)return;B.current=$;const{acceptsContainer:L,allowsNestSlot:I,includeContainer:P}=N.current(T);M(uI({frameEl:t,draggedPath:$,acceptsContainer:L,allowsNestSlot:I,includeContainer:P,normalizeContainerPath:F=>mI(F)}))},[$,T,t]),!t)return null;const H=k.activeDropZone?`slot:${k.activeDropZone.containerPath}:${k.activeDropZone.index}`:null;return i.jsxs(F2,{sensors:w,collisionDetection:J7,onDragStart:k.onDragStart,onDragMove:k.onDragMove,onDragEnd:k.onDragEnd,onDragCancel:k.onDragCancel,children:[_.map(L=>i.jsx(SI,{path:L.path,name:L.name,box:L.box,dimmed:S&&k.activeDragPath!==L.path,isIterationGroup:L.isIterationGroup,onSelect:c,onRequestInlineEdit:f},L.path)),S&&O.map(L=>i.jsx(kI,{slot:L,active:L.id===H},L.id)),Cn.createPortal(i.jsx(sI,{dropAnimation:null,zIndex:Pp,children:T?A?i.jsx(wI,{name:T,node:A.node,width:A.width,height:A.height}):i.jsx("div",{className:"g7le-dnd-drag-ghost","data-testid":"g7le-dnd-drag-ghost",style:{padding:"4px 10px",background:"rgba(79,70,229,0.95)",color:"#fff",fontSize:12,fontWeight:600,borderRadius:4,pointerEvents:"none",whiteSpace:"nowrap"},children:`<${T}>`}):null}),document.body),h&&Cn.createPortal(i.jsxs("div",{"data-testid":"g7le-branch-boundary-hint",role:"status",style:{position:"absolute",left:"50%",top:12,transform:"translateX(-50%)",background:"rgba(245,158,11,0.97)",color:"#fff",fontSize:13,fontWeight:600,padding:"8px 16px",borderRadius:8,boxShadow:"0 4px 14px rgba(0,0,0,0.2)",pointerEvents:"none",whiteSpace:"nowrap",zIndex:Pp},children:["⚠️ ",m("layout_editor.overlay.branch_boundary_denied")]}),t)]})}function wI(e){const{node:t,width:n,height:o}=e,r=u.useRef(null);return u.useEffect(()=>{const s=r.current;if(s)return s.replaceChildren(),s.appendChild(t.cloneNode(!0)),()=>{s.replaceChildren()}},[t]),i.jsx("div",{ref:r,className:"g7le-dnd-drag-ghost","data-testid":"g7le-dnd-drag-ghost",style:{width:n,height:o,opacity:.7,pointerEvents:"none",boxShadow:"0 6px 18px rgba(0,0,0,0.25)",borderRadius:4,overflow:"hidden",cursor:"grabbing"}})}function kI(e){const{slot:t,active:n}=e,{setNodeRef:o}=X2({id:t.id}),r=t.orientation!=="area";return i.jsx("div",{ref:o,"data-testid":`g7le-dnd-slot-${t.id}`,"data-dnd-slot-id":t.id,style:{position:"absolute",left:t.box.left,top:t.box.top,width:t.box.width,height:t.box.height,pointerEvents:"auto",zIndex:h7,boxSizing:"border-box",...r?{background:n?"rgba(79,70,229,0.15)":"transparent",...n?t.orientation==="vertical"?{borderLeft:"2px solid #4f46e5"}:{borderTop:"2px solid #4f46e5"}:{}}:{border:n?"2px dashed #4f46e5":"1px dashed transparent",background:n?"rgba(79,70,229,0.08)":"transparent",borderRadius:4}}})}function Sf(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/[^a-zA-Z0-9_\-.]/g,t=>`\\${t}`)}function SI(e){const{path:t,box:n,dimmed:o,isIterationGroup:r,onSelect:s,onRequestInlineEdit:a}=e,{attributes:l,listeners:d,setNodeRef:c,isDragging:p}=U2({id:t}),f=(t.match(/\.children\./g)||[]).length,y=y7(f);return i.jsx("div",{ref:c,"data-testid":`g7le-dnd-handle-${t}`,"data-dnd-handle-path":t,"data-dnd-iteration-group":r?"true":void 0,...d,...l,onClick:g=>{if(g.stopPropagation(),!r&&typeof document<"u"&&typeof document.elementsFromPoint=="function"){const m=document.elementsFromPoint(g.clientX,g.clientY);for(const h of m){const b=h.closest?.("[data-editor-path]")?.dataset?.editorPath;if(typeof b=="string"&&(b===t||b.startsWith(`${t}.`))){s(b);return}}}s(t)},onDoubleClick:g=>{g.stopPropagation(),g.preventDefault(),a?.(t)},style:{position:"absolute",left:n.left,top:n.top,width:n.width,height:n.height,cursor:"grab",pointerEvents:"auto",background:p?"rgba(79,70,229,0.06)":"transparent",...r?{border:"1px dashed rgba(79,70,229,0.5)",borderRadius:4}:{},opacity:o?.6:1,zIndex:y,touchAction:"none"}})}function Cf(e,t){const n=[];let o=e,r=Array.isArray(e.children)?e.children:[];for(let s=0;s0?[o]:[];const r=[],s=(a,l)=>{a.forEach((d,c)=>{const p=[...l,c];if(!Ji(d,t,n)){r.push(p);return}const y=Array.isArray(d.children)?d.children:[];y.length>0&&s(y,p)})};return s(e,[]),r}function $I(e){return at(e)}function ci(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/["\\]/g,"\\$&")}function EI({frameEl:e,components:t,editMode:n,currentExtensionId:o,editableRootPath:r}){const[s,a]=u.useState(null),[l]=u.useState(()=>`g7le-dim-mask-${Math.floor(Math.random()*1e9)}`);if(u.useEffect(()=>{if(!e){a(null);return}let g=0;const m=()=>{const x=CI(t,n,o,r);if(x.length===0){a(null);return}const k=e.getBoundingClientRect(),w={left:0,top:0,width:k.width,height:k.height},_=[];for(const C of x){const E=$I(C),S=e.querySelector(`[data-editor-path="${ci(E)}"]`);let T=null;if(S){const $=S.getBoundingClientRect();$.width>0&&$.height>0&&(T={left:$.left,top:$.top,width:$.width,height:$.height})}if(!T){const $=Array.from(e.querySelectorAll(`[data-editor-path^="${ci(E)}.iteration."], [data-editor-path^="${ci(E)}.sortable."], [data-editor-path^="${ci(E)}.children."]`));let A=1/0,z=1/0,D=-1/0,O=-1/0;for(const M of $){const B=M.getBoundingClientRect();B.width<=0||B.height<=0||(A=Math.min(A,B.left),z=Math.min(z,B.top),D=Math.max(D,B.right),O=Math.max(O,B.bottom))}if(D>A&&O>z&&(T={left:A,top:z,width:D-A,height:O-z}),T&&$.length>0){const M=$[0].closest('[role="dialog"]');if(M&&e.contains(M)){const B=M.getBoundingClientRect();B.width>0&&B.height>0&&(T={left:B.left,top:B.top,width:B.width,height:B.height})}}}T&&_.push({left:T.left-k.left,top:T.top-k.top,width:T.width,height:T.height})}if(_.length===0){a(null);return}a({frame:w,holes:_})},h=()=>{g&&cancelAnimationFrame(g),g=requestAnimationFrame(m)};h();const v=typeof ResizeObserver<"u"?new ResizeObserver(h):null;v?.observe(e);const b=typeof MutationObserver<"u"?new MutationObserver(h):null;return b?.observe(e,{childList:!0,subtree:!0,attributes:!0}),window.addEventListener("scroll",h,!0),window.addEventListener("resize",h),()=>{g&&cancelAnimationFrame(g),v?.disconnect(),b?.disconnect(),window.removeEventListener("scroll",h,!0),window.removeEventListener("resize",h)}},[e,t,n,o,r?.join(".")??""]),!s||s.holes.length===0)return null;const{frame:d,holes:c}=s,p=n==="modal"||n==="iteration_item";let f=[];if(p){let g=1/0,m=1/0,h=-1/0,v=-1/0;for(const C of c)g=Math.min(g,C.left),m=Math.min(m,C.top),h=Math.max(h,C.left+C.width),v=Math.max(v,C.top+C.height);const b=(C,E,S)=>Math.max(E,Math.min(S,C)),x=b(g,0,d.width),k=b(m,0,d.height),w=b(h,0,d.width),_=b(v,0,d.height);f=[{left:0,top:0,width:d.width,height:k},{left:0,top:_,width:d.width,height:d.height-_},{left:0,top:k,width:x,height:_-k},{left:w,top:k,width:d.width-w,height:_-k}].filter(C=>C.width>0&&C.height>0)}const y=g=>{g.preventDefault(),g.stopPropagation()};return i.jsxs(i.Fragment,{children:[f.map((g,m)=>i.jsx("div",{className:"g7le-source-lock-block","data-testid":"g7le-source-lock-block",onClickCapture:y,onPointerDownCapture:y,onMouseDownCapture:y,onDragStartCapture:y,style:{position:"absolute",left:g.left,top:g.top,width:g.width,height:g.height,zIndex:Lp,pointerEvents:"auto",cursor:"not-allowed",background:"transparent"}},m)),i.jsxs("svg",{className:"g7le-source-lock-dim","data-testid":"g7le-source-lock-dim",width:d.width,height:d.height,style:{position:"absolute",left:0,top:0,width:d.width,height:d.height,zIndex:Lp,pointerEvents:"none"},children:[i.jsx("defs",{children:i.jsxs("mask",{id:l,children:[i.jsx("rect",{x:0,y:0,width:d.width,height:d.height,fill:"white"}),c.map((g,m)=>i.jsx("rect",{"data-testid":"g7le-source-lock-dim-hole",x:g.left,y:g.top,width:g.width,height:g.height,rx:4,fill:"black"},m))]})}),i.jsx("rect",{"data-testid":"g7le-source-lock-dim-box",x:0,y:0,width:d.width,height:d.height,fill:"rgba(15, 23, 42, 0.45)",mask:`url(#${l})`})]})]})}function $f(e){const t={type:e.type??"basic",name:e.name},n={};if(e.props)for(const[o,r]of Object.entries(e.props))o!=="children"&&r?.default!==void 0&&(n[o]=r.default);return Object.keys(n).length>0&&(t.props=n),t}function II(e){if(!e?.components)return[];const t=[];for(const[n,o]of Object.entries(e.components))if(Array.isArray(o))for(const r of o)t.push({...r,type:r.type??n});return t}function AI(e,t,n,o,r){const s=II(e);let a=null;if(n&&t?.containers){const l=t.containers[n];l&&Array.isArray(l.accepts)?a=new Set(l.accepts):a=new Set}else!n&&t?.draggable&&(a=new Set(t.draggable));return s.filter(l=>{if(a&&!a.has(l.name))return!1;if(o){const d=o.toLowerCase(),c=r(l).toLowerCase(),p=l.name.toLowerCase();if(!c.includes(d)&&!p.includes(d)&&!`<${p}>`.includes(d)&&!(l.description??"").toLowerCase().includes(d))return!1}return!0})}function TI(e,t){const n={key:"all",label:"layout_editor.palette.category.all",entries:e,isI18nKey:!0};if(t?.groups&&t.groups.length>0){const a=new Map(e.map(p=>[p.name,p])),l=new Set,d=[];for(const p of t.groups){const f=[];for(const y of p.components??[]){const g=a.get(y);g&&(f.push(g),l.add(y))}f.length!==0&&d.push({key:p.kind??p.label,label:p.label,entries:f,isI18nKey:p.label.startsWith("$t:")||/^[a-z_.]+$/i.test(p.label)})}const c=e.filter(p=>!l.has(p.name));return c.length>0&&d.push({key:"other",label:"layout_editor.palette.category.other",entries:c,isI18nKey:!0}),[n,...d]}const o=new Map;for(const a of e){const l=(a.type??"basic").toLowerCase(),d=o.get(l)??[];d.push(a),o.set(l,d)}const r=["basic","composite","layout"],s=[];for(const a of r){const l=o.get(a);l&&l.length>0&&(s.push({key:a,label:`layout_editor.palette.category.fallback.${a}`,entries:l,isI18nKey:!0}),o.delete(a))}for(const[a,l]of o.entries())s.push({key:a,label:a,entries:l,isI18nKey:!1});return[n,...s]}function Ef(e){const{manifest:t,nesting:n,componentPalette:o,targetParentPath:r,targetContainerName:s,onInsert:a,insertionIndex:l,onClose:d,editorTemplateId:c,editorLocale:p}=e,{t:f,translationEngine:y}=tt(),g=u.useMemo(()=>{if(!c||!y)return f;const A=p??null;return z=>{const D={templateId:c,locale:A??"ko"},O=y.translate(z,D);return O!==z?O:f(z)}},[c,p,y,f]),[m,h]=u.useState(""),[v,b]=u.useState("all"),x=o?.entries??null,k=u.useMemo(()=>A=>{const z=x?.[A.name];return z?.label?ui(z.label,g):A.description??A.name},[x,g]),w=u.useMemo(()=>AI(t,n,s,m,k),[t,n,s,m,k]),_=u.useMemo(()=>TI(w,o??null),[w,o]),C=_.find(A=>A.key===v)??_[0]??null,E=!n||!n.draggable&&!n.containers,S=w.length===0,T=C?.entries??[],$=A=>{const z=x?.[A.name],D=!!z?.defaultNode&&typeof z.defaultNode=="object";if(z?.requiresDefaultNode&&!D)return;const O=D?JSON.parse(JSON.stringify(z.defaultNode)):$f(A),M=r??[];a(O,M,l),$n({source:"palette",draggedComponentName:A.name,targetContainerName:s,targetContainerPath:M.length===0?null:M.join("/"),decision:"allowed",insertionIndex:l,result:"completed",timestamp:Date.now()}),d()};return i.jsxs("div",{className:"g7le-palette","data-testid":"g7le-palette",style:MI,children:[i.jsxs("div",{style:LI,children:[i.jsx("strong",{style:{fontSize:16},children:f("layout_editor.palette.title")}),i.jsx("button",{type:"button",onClick:d,"aria-label":"close","data-testid":"g7le-palette-close",style:PI,children:"×"})]}),i.jsxs("div",{style:OI,children:[i.jsx("aside",{style:BI,"data-testid":"g7le-palette-sidebar",children:i.jsx("nav",{children:i.jsx("ul",{style:WI,children:_.map(A=>{const z=C?.key===A.key,D=A.isI18nKey?ui(A.label,g):A.label;return i.jsx("li",{children:i.jsxs("button",{type:"button","data-testid":`g7le-palette-category-${A.key}`,"data-active":z?"true":"false",onClick:()=>b(A.key),style:{...jI,background:z?"#eff6ff":"transparent",color:z?"#1d4ed8":"#334155",fontWeight:z?600:500},children:[i.jsx("span",{children:D}),i.jsx("span",{style:VI,children:A.entries.length})]})},A.key)})})})}),i.jsxs("main",{style:HI,children:[i.jsx("input",{type:"text",placeholder:f("layout_editor.palette.search_placeholder"),value:m,onChange:A=>h(A.target.value),"data-testid":"g7le-palette-search",style:FI}),i.jsx("div",{style:KI,children:E?i.jsx("div",{style:If,"data-testid":"g7le-palette-spec-missing",children:f("layout_editor.palette.spec_missing")}):S||T.length===0?i.jsx("div",{style:If,"data-testid":"g7le-palette-empty",children:f("layout_editor.palette.empty")}):i.jsx("div",{"data-testid":`g7le-palette-group-${C?.key??"all"}`,style:{marginBottom:16},children:i.jsx("div",{style:UI,children:T.map(A=>i.jsx(DI,{entry:A,entrySpec:x?.[A.name]??null,onClick:$,t:f,entryT:g},A.name))})})})]})]})]})}function DI(e){const{entry:t,entrySpec:n,onClick:o,t:r,entryT:s}=e,a=n?.label?ui(n.label,s):t.description??t.name,l=(t.type??"").toLowerCase(),d=l==="basic"||l==="composite"||l==="layout",c=!!n?.defaultNode&&typeof n.defaultNode=="object",p=!!n?.requiresDefaultNode&&!c,f=!c,y=p?r("layout_editor.palette.requires_default_node_missing"):n?.label?ui(n.label,s):t.name;return i.jsxs("button",{type:"button",onClick:()=>o(t),disabled:p,"aria-disabled":p||void 0,"data-testid":`g7le-palette-item-${t.name}`,"data-component-type":l||void 0,"data-blocked":p?"true":void 0,"data-default-node-missing":f?"true":void 0,title:y,style:p?GI:qI,children:[i.jsx("div",{style:XI,"aria-hidden":"true",children:zI(t)}),i.jsx("div",{style:JI,children:a}),i.jsx("div",{"data-testid":`g7le-palette-item-${t.name}-tag`,style:ZI,children:`<${t.name}>`}),d&&i.jsx("div",{"data-testid":`g7le-palette-item-${t.name}-badge`,style:NI(l),children:l}),f&&i.jsx("div",{"data-testid":`g7le-palette-item-${t.name}-default-missing-badge`,style:YI,children:r("layout_editor.palette.default_node_missing_badge")})]})}function ui(e,t){return e.startsWith("$t:")?t(e.slice(3)):t(e)}function NI(e){const n={basic:{bg:"#dbeafe",fg:"#1e40af"},composite:{bg:"#dcfce7",fg:"#14532d"},layout:{bg:"#fef3c7",fg:"#854d0e"}}[e]??{bg:"#e2e8f0",fg:"#334155"};return{fontSize:9,fontWeight:600,color:n.fg,background:n.bg,padding:"1px 6px",borderRadius:999,textTransform:"uppercase",letterSpacing:.4,lineHeight:1.6}}function zI(e){const t=e.name;return{Button:"🔘",A:"🔗",Img:"🖼",Icon:"✨",Hr:"➖",P:"📄",Span:"T",H1:"H₁",H2:"H₂",H3:"H₃",H4:"H₄",Ul:"☰",Li:"•",Nav:"🧭",Div:"▢",Container:"▢",Flex:"⇆",Grid:"▦",SectionLayout:"▤",ThreeColumnLayout:"⫼",Form:"📝",Input:"⎕",Textarea:"▭",Select:"⏷",Checkbox:"☑",PasswordInput:"🔒",Label:"🏷",DataGrid:"▦",Pagination:"↔",SearchBar:"🔍",ProductCard:"🛍",ImageGallery:"🖼",Avatar:"👤",UserInfo:"👥",HtmlContent:"⟨/⟩",HtmlEditor:"✏",RichTextEditor:"✏",TabNavigation:"◰",QuantitySelector:"#",ProductImageViewer:"🖼",FileUploader:"📎",AvatarUploader:"📷",SocialLoginButtons:"🌐",PostReactions:"❤"}[t]??"◻"}const MI={display:"flex",flexDirection:"column",width:"100%",height:"100%",minHeight:0,fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple SD Gothic Neo", "Noto Sans KR", sans-serif'},LI={display:"flex",justifyContent:"space-between",alignItems:"center",padding:"14px 20px",borderBottom:"1px solid #e2e8f0",flexShrink:0},PI={background:"transparent",border:"none",fontSize:24,cursor:"pointer",lineHeight:1,color:"#64748b",padding:"0 4px"},OI={display:"flex",flex:1,minHeight:0},BI={width:180,flexShrink:0,borderRight:"1px solid #e2e8f0",padding:"14px 8px",background:"#f8fafc",overflowY:"auto"},WI={listStyle:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:4},jI={display:"flex",width:"100%",alignItems:"center",justifyContent:"space-between",textAlign:"left",padding:"8px 12px",border:"none",borderRadius:6,fontSize:13,cursor:"pointer",transition:"background-color 120ms"},HI={flex:1,display:"flex",flexDirection:"column",minHeight:0,padding:"14px 20px"},FI={width:"100%",padding:"8px 10px",border:"1px solid #cbd5e1",borderRadius:6,marginBottom:12,fontSize:13,flexShrink:0,boxSizing:"border-box"},KI={flex:1,overflowY:"auto",minHeight:0},VI={fontSize:11,color:"#94a3b8",marginLeft:8,fontWeight:500},UI={display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(96px, 1fr))",gap:10},qI={display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:6,padding:"14px 6px",background:"#fff",border:"1px solid #e2e8f0",borderRadius:8,cursor:"pointer",fontSize:12,minHeight:84,transition:"border-color 120ms, box-shadow 120ms"},GI={display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:6,padding:"14px 6px",background:"#f8fafc",border:"1px dashed #cbd5e1",borderRadius:8,cursor:"not-allowed",fontSize:12,minHeight:84,color:"#94a3b8",opacity:.65},YI={fontSize:9,fontWeight:600,color:"#92400e",background:"#fef3c7",padding:"1px 6px",borderRadius:999,textTransform:"none",letterSpacing:0,lineHeight:1.6},XI={fontSize:22,lineHeight:1,color:"#475569"},JI={fontSize:12,fontWeight:500,color:"#0f172a",textAlign:"center",wordBreak:"break-word"},ZI={fontFamily:'ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace',fontSize:10,color:"#64748b",textAlign:"center",wordBreak:"break-all"},If={padding:24,color:"#64748b",fontSize:13,textAlign:"center"};function QI(e){const t=[],n=r=>{if(Array.isArray(r))for(const s of r)s&&typeof s=="object"&&t.push(s)};n(e.children);const o=e.responsive;if(o&&typeof o=="object")for(const r of Object.values(o))r&&typeof r=="object"&&n(r.children);return t}function Af(e){const t=[],n=o=>{const r="isolatedState"in o&&o.isolatedState!=null,s=o.isolatedScopeId;(r||typeof s=="string"&&s.length>0)&&t.push({scopeId:typeof s=="string"?s:void 0,initialState:o.isolatedState&&typeof o.isolatedState=="object"?o.isolatedState:void 0});for(const a of QI(o))n(a)};if(Array.isArray(e))for(const o of e)o&&typeof o=="object"&&n(o);return t}const RI=["scroll","selector","wizard","slider"];function eA(e,t){const n=new Set;for(const o of e)o.scopeId&&n.add(o.scopeId);for(const o of t){n.add(o);for(const r of RI)n.add(`${o}-${r}`)}return Array.from(n)}function tA(e,t,n){const o=t.label;return typeof o=="string"?o.startsWith("$t:")?n(o.slice(3)):o:e}function pi({controlKey:e,control:t,node:n,t:o,onPatch:r,candidates:s,bindingCandidates:a,scope:l=Wt}){const d=Tn(t.widget),c=tA(e,t,o),p=u.useMemo(()=>Do(n,t,l),[n,t,l]),f=t.widget==="i18n-text"&&t.apply?.type==="propValue",y=t.widget==="text"&&t.apply?.type==="propValue",g=p.darkReadonly===!0||l.colorScheme==="dark"&&t.apply!==void 0&&!Us(t.apply),m=t.apply,h=l.colorScheme==="dark"&&!g&&m?.type==="classToken"&&typeof m.tokenTemplate=="string"&&m.tokenTemplate.includes("{value}"),v=p.scopedValue===void 0&&p.baseFallback!==void 0,b=u.useCallback(x=>{if(g)return;const k=fn(n,t,x,l);r(k)},[n,t,r,l,g]);return i.jsxs("div",{className:"g7le-control-row","data-testid":`g7le-control-${e}`,style:nA,children:[i.jsxs("span",{className:"g7le-control-label",style:oA,children:[c,p.conflict&&i.jsx("span",{"data-testid":`g7le-control-conflict-${e}`,title:o("layout_editor.property_modal.value_conflict"),style:rA,children:"!"})]}),i.jsx("div",{className:"g7le-control-widget",style:{flex:1,minWidth:0,opacity:v?.45:1},"data-placeholder":v?"true":void 0,children:f?i.jsx(vt,{value:typeof p.value=="string"?p.value:"",onChange:x=>b(x),t:o,testidPrefix:`g7le-prop-i18n-${e}`,candidates:a,enableExpressionTree:!0,expressionTreeCollapsible:!0}):y?i.jsx(Ve,{value:typeof p.value=="string"?p.value:"",onChange:x=>b(x===""?void 0:x),t:o,testidPrefix:`g7le-prop-value-${e}`,candidates:a}):g?i.jsx("span",{"data-testid":`g7le-control-dark-readonly-${e}`,style:sA,children:o("layout_editor.property_modal.dark_code_only")}):d?i.jsx(d,{control:t,value:p.value,onChange:b,t:o,candidates:s,bindingCandidates:a,freeValueDisabled:h}):i.jsx("span",{"data-testid":`g7le-control-unsupported-${e}`,style:iA,children:o("layout_editor.property_modal.unsupported_widget")})})]})}const nA={display:"flex",alignItems:"center",gap:12,padding:"6px 0",minHeight:32,minWidth:0},oA={fontSize:12,color:"#475569",minWidth:88,display:"inline-flex",alignItems:"center",gap:4},rA={display:"inline-flex",width:14,height:14,borderRadius:7,background:"#f59e0b",color:"#fff",fontSize:10,alignItems:"center",justifyContent:"center",fontWeight:700},iA={fontSize:11,color:"#94a3b8",fontStyle:"italic"},sA={fontSize:11,color:"#94a3b8",fontStyle:"italic"};function fi(e,t,n){return typeof e=="string"?e.startsWith("$t:")?n(e.slice(3)):e:t}function aA(e,t){const n=e.props??{};return t.key in n?n[t.key]:t.default}function lA({spec:e,node:t,t:n,onPatchProp:o}){const r=e.groups??[];return i.jsx("div",{className:"g7le-composite-settings","data-testid":"g7le-composite-settings",style:cA,children:r.map((s,a)=>i.jsxs("div",{className:"g7le-settings-group",style:uA,children:[i.jsx("div",{style:pA,children:fi(s.label,n("layout_editor.property_modal.settings_group",{index:a+1}),n)}),(s.fields??[]).map(l=>i.jsxs("div",{className:"g7le-settings-field","data-testid":`g7le-setting-${l.key}`,style:fA,children:[i.jsx("span",{style:gA,children:fi(l.label,l.key,n)}),i.jsx("div",{style:{flex:1},children:dA(l,t,n,o)})]},l.key))]},a))})}function dA(e,t,n,o){const r=aA(t,e);switch(e.type){case"number":return i.jsx("input",{type:"number","data-testid":`g7le-setting-input-${e.key}`,value:typeof r=="number"?r:"",min:e.min,max:e.max,onChange:s=>o(e.key,s.target.value===""?void 0:Number(s.target.value)),style:Ca});case"text":return i.jsx("input",{type:"text","data-testid":`g7le-setting-input-${e.key}`,value:typeof r=="string"?r:"",onChange:s=>o(e.key,s.target.value===""?void 0:s.target.value),style:Ca});case"toggle":return i.jsx("input",{type:"checkbox","data-testid":`g7le-setting-input-${e.key}`,checked:r===!0,onChange:s=>o(e.key,s.target.checked)});case"checkbox-group":{const s=Array.isArray(r)?r:[];return i.jsx("div",{style:hA,"data-testid":`g7le-setting-input-${e.key}`,children:(e.options??[]).map(a=>{const l=s.includes(a.value);return i.jsxs("label",{style:yA,children:[i.jsx("input",{type:"checkbox",checked:l,onChange:d=>{const c=d.target.checked?[...s,a.value]:s.filter(p=>p!==a.value);o(e.key,c)}}),fi(a.label,String(a.value),n)]},String(a.value))})})}default:return i.jsxs("select",{"data-testid":`g7le-setting-input-${e.key}`,value:r==null?"":String(r),onChange:s=>{const a=s.target.value;if(a===""){o(e.key,void 0);return}const l=(e.options??[]).find(d=>String(d.value)===a);o(e.key,l?l.value:a)},style:Ca,children:[i.jsx("option",{value:"",children:"—"}),(e.options??[]).map(s=>i.jsx("option",{value:String(s.value),children:fi(s.label,String(s.value),n)},String(s.value)))]})}}const cA={display:"flex",flexDirection:"column",gap:16},uA={display:"flex",flexDirection:"column",gap:6},pA={fontSize:12,fontWeight:700,color:"#0f172a",borderBottom:"1px solid #e2e8f0",paddingBottom:4},fA={display:"flex",alignItems:"center",gap:12,minHeight:30},gA={fontSize:12,color:"#475569",minWidth:96},Ca={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,width:"100%",boxSizing:"border-box"},hA={display:"flex",flexWrap:"wrap",gap:10},yA={display:"inline-flex",alignItems:"center",gap:4,fontSize:12,color:"#0f172a"},bA=["data_binding","isolatedScopeId","parentFormContextProp","skipBindingKeys","isolatedState","component_layout","sortable","itemTemplate"],mA=/\{\{|\$switch|\$get|\|\s*(date|number|truncate|currency|relative)\b/;function gi(e,t=0){return t>6?!1:typeof e=="string"?mA.test(e):Array.isArray(e)?e.some(n=>gi(n,t+1)):e&&typeof e=="object"?Object.values(e).some(n=>gi(n,t+1)):!1}function vA(e){if(Zl(e))return!1;const t=Fl(e);return t.length===0?!1:t.some(n=>n.isComplex)}function Tf(e){const t=[],n=e.props??{};for(const o of bA)o in e&&e[o]!==void 0?t.push({key:o,kind:"developer_prop"}):o in n&&n[o]!==void 0&&t.push({key:`props.${o}`,kind:"developer_prop"});typeof e.text=="string"?vA(e.text)&&t.push({key:"text",kind:"complex_expression"}):gi(e.text)&&t.push({key:"text",kind:"complex_expression"});for(const[o,r]of Object.entries(n))o==="style"||o==="className"||gi(r)&&t.push({key:`props.${o}`,kind:"complex_expression"});return t}function _A(e){return Tf(e).length>0}const xA=new Set(["permissions","blur_until_loaded","comment"]);function wA({node:e,advanced:t,t:n,onPatch:o,permissionCandidates:r}){const s=u.useMemo(()=>Tf(e),[e]),a=(l,d)=>{const c={...e};d===void 0?delete c[l]:c[l]=d,o(c)};return i.jsxs("div",{className:"g7le-advanced-props","data-testid":"g7le-advanced-props",style:kA,children:[t.map(l=>{if(!xA.has(l))return i.jsxs("div",{"data-testid":`g7le-advanced-deferred-${l}`,style:CA,children:[n("layout_editor.property_modal.advanced_deferred"),":",l]},l);if(l==="permissions")return i.jsxs("div",{className:"g7le-advanced-group","data-testid":"g7le-advanced-permissions",style:$a,children:[i.jsx("div",{style:Ea,children:n("layout_editor.property_modal.advanced.permissions")}),i.jsx(ys,{control:{widget:"tag-input"},value:e.permissions,onChange:d=>a("permissions",d),t:n,candidates:r})]},l);if(l==="blur_until_loaded"){const d=e.blur_until_loaded===!0||e.blur_until_loaded!=null&&e.blur_until_loaded!==!1;return i.jsxs("div",{className:"g7le-advanced-group","data-testid":"g7le-advanced-blur",style:$a,children:[i.jsx("div",{style:Ea,children:n("layout_editor.property_modal.advanced.blur_until_loaded")}),i.jsxs("label",{style:{display:"inline-flex",alignItems:"center",gap:6,fontSize:12},children:[i.jsx("input",{type:"checkbox","data-testid":"g7le-advanced-blur-toggle",checked:!!d,onChange:c=>a("blur_until_loaded",c.target.checked?!0:void 0)}),n("layout_editor.property_modal.advanced.blur_hint")]})]},l)}return i.jsxs("div",{className:"g7le-advanced-group","data-testid":"g7le-advanced-comment",style:$a,children:[i.jsx("div",{style:Ea,children:n("layout_editor.property_modal.advanced.comment")}),i.jsx("input",{type:"text","data-testid":"g7le-advanced-comment-input",value:typeof e.comment=="string"?e.comment:"",onChange:d=>a("comment",d.target.value===""?void 0:d.target.value),style:SA})]},l)}),s.length>0&&i.jsxs("div",{className:"g7le-advanced-preserved","data-testid":"g7le-advanced-preserved",style:$A,children:[i.jsx("div",{style:EA,children:n("layout_editor.property_modal.advanced_preserved_title",{count:s.length})}),i.jsx("ul",{style:IA,children:s.map(l=>i.jsxs("li",{"data-testid":`g7le-advanced-preserved-${l.key}`,style:AA,children:[i.jsx("code",{style:{fontSize:11},children:l.key}),i.jsx("span",{style:{fontSize:11,color:"#94a3b8"},children:l.kind==="developer_prop"?n("layout_editor.property_modal.advanced_kind_developer"):n("layout_editor.property_modal.advanced_kind_expression")})]},l.key))})]})]})}const kA={display:"flex",flexDirection:"column",gap:14},$a={display:"flex",flexDirection:"column",gap:6},Ea={fontSize:12,fontWeight:700,color:"#0f172a"},SA={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,width:"100%",boxSizing:"border-box"},CA={fontSize:11,color:"#94a3b8",fontStyle:"italic"},$A={borderTop:"1px dashed #cbd5e1",paddingTop:10,marginTop:4},EA={fontSize:11,color:"#b45309",marginBottom:6},IA={listStyle:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:4},AA={display:"flex",justifyContent:"space-between",gap:8,padding:"3px 0"},TA={onClick:"click",onHover:"mouseenter",onChange:"change",onSubmit:"submit",onMount:"mount",onUnmount:"unmount",onFocus:"focus",onBlur:"blur"};function Ia(e){return TA[e]??e.replace(/^on/,"").toLowerCase()}function Df(e){const t=e.actions;if(Array.isArray(t))return t.filter(r=>!!r&&typeof r=="object");const n=e.props??{};if(Array.isArray(n.actions))return n.actions.filter(r=>!!r&&typeof r=="object");const o=n.events;if(o&&typeof o=="object"){const r=[];for(const[s,a]of Object.entries(o)){if(!Array.isArray(a))continue;const l=Ia(s);for(const d of a)d&&typeof d=="object"&&r.push("type"in d?d:{type:l,...d})}return r}return[]}function DA(e,t){const n=Ia(t);return Df(e).filter(o=>o.type===n||t==="onClick"&&o.type===void 0)}function NA(e,t,n){const o=Ia(t),r=Df(e).filter(d=>!(d.type===o||t==="onClick"&&d.type===void 0)),s=n.map(d=>"type"in d?d:{type:o,...d}),a={...e};if(a.props&&typeof a.props=="object"){const d={...a.props};let c=!1;"actions"in d&&(delete d.actions,c=!0),"events"in d&&(delete d.events,c=!0),c&&(a.props=d)}const l=[...r,...s];return l.length===0?delete a.actions:a.actions=l,a}function zA({node:e,spec:t,capability:n,t:o,onPatchNode:r,pageCandidates:s,dataSourceCandidates:a,stateKeyCandidates:l,bindingCandidates:d}){const c=t?.actionRecipes,p=u.useMemo(()=>({pageCandidates:s,dataSourceCandidates:a,stateKeyCandidates:l,bindingCandidates:d}),[s,a,l,d]),f=Array.isArray(n?.events)?n.events:[];return f.length===0?i.jsx("div",{"data-testid":"g7le-action-no-events",style:Nf,children:o("layout_editor.action.no_events")}):!c||Object.keys(c).length===0?i.jsx("div",{"data-testid":"g7le-action-no-recipes",style:Nf,children:o("layout_editor.action.no_recipes")}):i.jsx("div",{className:"g7le-action-editor","data-testid":"g7le-action-editor",style:{display:"flex",flexDirection:"column",gap:14},children:f.map(y=>i.jsxs("div",{className:"g7le-action-event-slot","data-testid":`g7le-action-event-${y}`,children:[i.jsx("div",{style:MA,children:o(`layout_editor.action.event.${y}`)}),i.jsx(Gt,{actions:DA(e,y),onChange:g=>r(NA(e,y,g)),t:o,recipes:c,candidatePools:p,actionChipCandidates:t?.actionChipCandidates??null,addContext:"component",showSourceBadge:!0,testIdPrefix:`g7le-action-slot-${y}`})]},y))})}const Nf={fontSize:12,color:"#94a3b8",padding:"16px 0",textAlign:"center"},MA={fontSize:12,fontWeight:700,color:"#475569",marginBottom:6};function Aa(e,t,n){if(!t)return n;const o=e(t);return!o||o===t||o.startsWith("$t:")?n:o}function LA(e,t){return Aa(t,e.labelKey,e.path||e.sourceId)}function PA({node:e,spec:t,candidates:n,t:o,onPatchNode:r}){const a=(e.props??{})[t.propKey],l=typeof a=="string"?a:void 0,d=u.useMemo(()=>Kt(a),[a]),c=l!==void 0&&l!==""&&d===null,[p,f]=u.useState(!1),[y,g]=u.useState(""),m=Aa(o,t.label,t.propKey),h=o(t.shape==="array"?"layout_editor.binding.shape_array":t.shape==="object"?"layout_editor.binding.shape_object":"layout_editor.binding.shape_scalar"),v=u.useMemo(()=>Fi(n,t.shape).map(_=>({..._,resolvedLabel:LA(_,o)})),[n,t.shape,o]),b=u.useMemo(()=>Ki(v,y),[v,y]),x=w=>{const _={...e.props??{}};w===void 0?delete _[t.propKey]:_[t.propKey]=w,r({...e,props:_})},k=w=>{x(En(w.sourceId,w.path,t.shape)),f(!1),g("")};return i.jsxs("div",{"data-testid":`g7le-binding-row-${t.propKey}`,style:jA,children:[i.jsxs("div",{style:HA,children:[i.jsx("span",{style:{fontWeight:600,fontSize:12},children:m}),i.jsx("span",{style:FA,children:h}),t.required&&i.jsx("span",{"data-testid":`g7le-binding-required-${t.propKey}`,style:KA,children:o("layout_editor.binding.required")})]}),c?i.jsxs("div",{"data-testid":`g7le-binding-complex-${t.propKey}`,style:GA,children:[o("layout_editor.binding.complex"),i.jsx("code",{style:zf,children:l})]}):d?i.jsxs("div",{style:VA,children:[i.jsx("code",{"data-testid":`g7le-binding-expr-${t.propKey}`,style:zf,children:l}),i.jsx("button",{type:"button","data-testid":`g7le-binding-clear-${t.propKey}`,onClick:()=>x(void 0),style:qA,children:o("layout_editor.binding.clear")})]}):i.jsx("div",{"data-testid":`g7le-binding-empty-${t.propKey}`,style:UA,children:o("layout_editor.binding.not_connected")}),d&&(t.shape==="array"||t.shape==="object")&&t.itemFields&&t.itemFields.length>0&&i.jsxs("div",{style:YA,children:[o("layout_editor.binding.item_fields"),": ",t.itemFields.join(", ")]}),!c&&i.jsxs("div",{style:{marginTop:4},children:[i.jsxs("button",{type:"button","data-testid":`g7le-binding-search-toggle-${t.propKey}`,onClick:()=>f(w=>!w),style:XA,children:["🔍 ",o("layout_editor.binding.search")]}),p&&i.jsxs("div",{"data-testid":`g7le-binding-picker-${t.propKey}`,style:JA,children:[i.jsx("input",{type:"text",autoFocus:!0,"data-testid":`g7le-binding-search-input-${t.propKey}`,value:y,placeholder:o("layout_editor.binding.search_placeholder"),onChange:w=>g(w.target.value),style:ZA}),i.jsx("div",{style:QA,children:b.length===0?i.jsx("div",{style:RA,children:o("layout_editor.binding.no_results")}):b.map(w=>i.jsxs("button",{type:"button","data-testid":`g7le-binding-candidate-${w.expression}`,onClick:()=>k(w),style:e6,children:[i.jsxs("span",{style:{display:"flex",flexDirection:"column",alignItems:"flex-start"},children:[i.jsx("span",{style:{fontSize:12},children:w.resolvedLabel}),i.jsxs("span",{style:t6,children:[Aa(o,w.groupLabelKey,w.sourceId)," · ",w.path||w.sourceId]})]}),i.jsx("span",{style:n6,children:w.preview})]},w.expression))})]})]})]})}function OA({node:e,dataProps:t,candidates:n,t:o,onPatchNode:r}){return!Array.isArray(t)||t.length===0?null:i.jsxs("div",{"data-testid":"g7le-data-binding-section",style:BA,children:[i.jsxs("div",{style:WA,children:["🔗 ",o("layout_editor.binding.section_title")]}),t.map(s=>i.jsx(PA,{node:e,spec:s,candidates:n,t:o,onPatchNode:r},s.propKey)),i.jsx("div",{style:o6})]})}const BA={display:"flex",flexDirection:"column",marginBottom:8},WA={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:6},jA={display:"flex",flexDirection:"column",gap:4,padding:"8px 0"},HA={display:"flex",alignItems:"center",gap:6},FA={fontSize:10,padding:"1px 6px",borderRadius:4,background:"#e0e7ff",color:"#3730a3"},KA={fontSize:10,padding:"1px 6px",borderRadius:4,background:"#fef3c7",color:"#92400e"},VA={display:"flex",alignItems:"center",gap:6},UA={fontSize:11,color:"#94a3b8"},zf={fontSize:11,fontFamily:"monospace",background:"#f1f5f9",padding:"2px 6px",borderRadius:4,color:"#0f172a",wordBreak:"break-all"},qA={fontSize:11,border:"1px solid #e2e8f0",borderRadius:4,background:"#fff",color:"#dc2626",padding:"2px 8px",cursor:"pointer"},GA={display:"flex",flexDirection:"column",gap:2,fontSize:11,color:"#64748b"},YA={fontSize:10,color:"#94a3b8"},XA={fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#334155",padding:"4px 10px",cursor:"pointer",textAlign:"left",width:"100%"},JA={marginTop:4,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",padding:6},ZA={width:"100%",padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,boxSizing:"border-box"},QA={marginTop:4,maxHeight:200,overflowY:"auto",display:"flex",flexDirection:"column",gap:2},RA={fontSize:11,color:"#94a3b8",padding:"8px 0",textAlign:"center"},e6={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,border:"none",background:"transparent",cursor:"pointer",padding:"6px 8px",borderRadius:4,textAlign:"left"},t6={fontSize:10,color:"#94a3b8"},n6={fontSize:10,color:"#64748b",fontFamily:"monospace",whiteSpace:"nowrap"},o6={borderTop:"1px solid #e2e8f0",marginTop:4};function r6({node:e,candidates:t,t:n,onPatchNode:o,templateIdentifier:r}){const s=typeof e.text=="string"?e.text:"",{state:a}=Je(),l=r??a.templateIdentifier,d=a.selectedRoute?.layoutName??null,c=a.locale,[p,f]=u.useState(!1),y=/^\s*\$t:custom\.[A-Za-z0-9._-]+\s*$/.test(s),m=Zl(s)&&(mt(s)?.key.startsWith("custom.")??!1)||y,h=u.useMemo(()=>m?mt(s):null,[m,s]),v=u.useMemo(()=>m?[]:Fl(s),[m,s]),b=T=>{o({...e,text:T})},x=()=>{if(!(typeof window>"u"))try{window.dispatchEvent(new CustomEvent(kt,{detail:{templateIdentifier:l,locale:c}}))}catch{}},k=(T,$)=>{const A=En($.sourceId,$.path,"scalar");b(wb(s,T,A))},w=T=>{const $=mt(s);b(mo(s,T));const A=$?.key;l&&A&&Fd(l,A,T).then(x)},_=T=>{const $=n(T);return $&&$!==T&&!$.startsWith("$t:")?$:""},C=T=>T.replace(/\$t:[a-zA-Z0-9._-]+/g,$=>_($.slice(3))).replace(/\s+/g," ").trim(),E=T=>{p||(f(!0),ls(l,d,c,s,s.length,T.sourceId,T.path,"scalar",C,$=>n($)).then($=>{$.kind==="ok"&&(b($.text),x())}).finally(()=>f(!1)))},S=T=>{p||!h&&!y||(f(!0),wr(l,c,s,Number.MAX_SAFE_INTEGER,T.sourceId,T.path,"scalar").then($=>{$.kind==="ok"&&(b($.text),x())}).finally(()=>f(!1)))};if(m){const T=h?.params??[];return i.jsxs("div",{"data-testid":"g7le-inline-binding-section",style:Mf,children:[i.jsxs("div",{style:Lf,children:["🔗 ",n("layout_editor.inline_binding.section_title")]}),T.length===0?i.jsx("div",{"data-testid":"g7le-inline-binding-none",style:Bf,children:n("layout_editor.inline_binding.none")}):T.map($=>i.jsx("div",{"data-testid":`g7le-inline-binding-param-${$.name}`,style:Pf,children:$.parsed===null?i.jsxs("div",{"data-testid":`g7le-inline-binding-param-complex-${$.name}`,style:s6,children:[n("layout_editor.inline_binding.complex"),i.jsx("code",{style:Ta,children:$.expression})]}):i.jsxs(i.Fragment,{children:[i.jsxs("div",{style:Of,children:[i.jsx("code",{"data-testid":`g7le-inline-binding-param-expr-${$.name}`,style:Ta,children:$.expression}),i.jsx("button",{type:"button","data-testid":`g7le-inline-binding-param-clear-${$.name}`,onClick:()=>w($.name),style:i6,children:n("layout_editor.inline_binding.clear")})]}),i.jsx($t,{candidates:t,t:n,onSelect:A=>k($.name,A),testIdSuffix:`param-${$.name}`})]})},$.name)),i.jsxs("div",{"data-testid":"g7le-inline-binding-param-append",style:Wf,children:[i.jsx("div",{style:Da,children:n("layout_editor.inline_binding.append_hint")}),i.jsx($t,{candidates:t,t:n,onSelect:S,testIdSuffix:"param-append"})]}),i.jsx("div",{"data-testid":"g7le-inline-binding-param-hint",style:Da,children:n("layout_editor.inline_binding.param_hint")}),i.jsx("div",{style:jf})]})}return i.jsxs("div",{"data-testid":"g7le-inline-binding-section",style:Mf,children:[i.jsxs("div",{style:Lf,children:["🔗 ",n("layout_editor.inline_binding.section_title")]}),v.length===0?i.jsx("div",{"data-testid":"g7le-inline-binding-none",style:Bf,children:n("layout_editor.inline_binding.none")}):v.map(T=>i.jsx("div",{"data-testid":`g7le-inline-binding-row-${T.bindingIndex}`,style:Pf,children:i.jsx("div",{style:Of,children:i.jsx("code",{"data-testid":`g7le-inline-binding-expr-${T.bindingIndex}`,style:Ta,children:T.expression})})},T.bindingIndex)),i.jsxs("div",{"data-testid":"g7le-inline-binding-append",style:Wf,children:[i.jsx("div",{style:Da,children:n("layout_editor.inline_binding.append_hint")}),i.jsx($t,{candidates:t,t:n,onSelect:E,testIdSuffix:"append"})]}),i.jsx("div",{style:jf})]})}const Mf={display:"flex",flexDirection:"column",marginBottom:8},Lf={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:6},Pf={display:"flex",flexDirection:"column",gap:4,padding:"8px 0"},Of={display:"flex",alignItems:"center",gap:6},Bf={fontSize:11,color:"#94a3b8"},Ta={fontSize:11,fontFamily:"monospace",background:"#f1f5f9",padding:"2px 6px",borderRadius:4,color:"#0f172a",wordBreak:"break-all"},i6={fontSize:11,border:"1px solid #e2e8f0",borderRadius:4,background:"#fff",color:"#dc2626",padding:"2px 8px",cursor:"pointer"},s6={display:"flex",flexDirection:"column",gap:2,fontSize:11,color:"#64748b"},Wf={display:"flex",flexDirection:"column",gap:2,padding:"8px 0 0"},Da={fontSize:11,color:"#475569",fontWeight:600},jf={borderTop:"1px solid #e2e8f0",marginTop:4};function Hf(e,t,n){if(!t)return n;const o=e(t);return!o||o===t||o.startsWith("$t:")?n:o}function a6(e,t){return Hf(t,e.labelKey,e.path||e.sourceId)}function l6(e){const t=e.iteration;return t&&typeof t=="object"?t:null}function d6({node:e,candidates:t,t:n,onPatchNode:o}){const r=l6(e),s=r?.source,a=typeof s=="string"?s:void 0,l=u.useMemo(()=>Kt(s),[s]),d=a!==void 0&&a!==""&&l===null,[c,p]=u.useState(!1),[f,y]=u.useState(""),g=u.useMemo(()=>Fi(t,"array").map(w=>({...w,resolvedLabel:a6(w,n)})),[t,n]),m=u.useMemo(()=>Ki(g,f),[g,f]);if(!r)return null;const h=typeof r.item_var=="string"?r.item_var:void 0,v=typeof r.index_var=="string"?r.index_var:void 0,b=k=>{const w={...r};k===void 0?delete w.source:w.source=k,o({...e,iteration:w})},x=k=>{b(En(k.sourceId,k.path,"array")),p(!1),y("")};return i.jsxs("div",{"data-testid":"g7le-iteration-binding-section",style:c6,children:[i.jsxs("div",{style:u6,children:["🔁 ",n("layout_editor.binding.iteration_title")]}),i.jsx("div",{style:p6,children:n("layout_editor.binding.iteration_hint")}),i.jsxs("div",{style:f6,children:[i.jsxs("div",{style:g6,children:[i.jsx("span",{style:{fontWeight:600,fontSize:12},children:n("layout_editor.binding.iteration_label")}),i.jsx("span",{style:h6,children:n("layout_editor.binding.shape_array")})]}),d?i.jsxs("div",{"data-testid":"g7le-iteration-binding-complex",style:v6,children:[n("layout_editor.binding.complex"),i.jsx("code",{style:Ff,children:a})]}):l?i.jsxs("div",{style:y6,children:[i.jsx("code",{"data-testid":"g7le-iteration-binding-expr",style:Ff,children:a}),i.jsx("button",{type:"button","data-testid":"g7le-iteration-binding-clear",onClick:()=>b(void 0),style:m6,children:n("layout_editor.binding.clear")})]}):i.jsx("div",{"data-testid":"g7le-iteration-binding-empty",style:b6,children:n("layout_editor.binding.not_connected")}),(h||v)&&i.jsxs("div",{"data-testid":"g7le-iteration-vars",style:_6,children:[h&&i.jsxs("span",{children:[n("layout_editor.binding.iteration_item_var"),": ",i.jsx("code",{style:Kf,children:h})]}),v&&i.jsxs("span",{children:[n("layout_editor.binding.iteration_index_var"),": ",i.jsx("code",{style:Kf,children:v})]})]}),!d&&i.jsxs("div",{style:{marginTop:4},children:[i.jsxs("button",{type:"button","data-testid":"g7le-iteration-binding-search-toggle",onClick:()=>p(k=>!k),style:x6,children:["🔍 ",n("layout_editor.binding.search")]}),c&&i.jsxs("div",{"data-testid":"g7le-iteration-binding-picker",style:w6,children:[i.jsx("input",{type:"text",autoFocus:!0,"data-testid":"g7le-iteration-binding-search-input",value:f,placeholder:n("layout_editor.binding.search_placeholder"),onChange:k=>y(k.target.value),style:k6}),i.jsx("div",{style:S6,children:m.length===0?i.jsx("div",{style:C6,children:n("layout_editor.binding.no_results")}):m.map(k=>i.jsxs("button",{type:"button","data-testid":`g7le-iteration-binding-candidate-${k.expression}`,onClick:()=>x(k),style:$6,children:[i.jsxs("span",{style:{display:"flex",flexDirection:"column",alignItems:"flex-start"},children:[i.jsx("span",{style:{fontSize:12},children:k.resolvedLabel}),i.jsxs("span",{style:E6,children:[Hf(n,k.groupLabelKey,k.sourceId)," · ",k.path||k.sourceId]})]}),i.jsx("span",{style:I6,children:k.preview})]},k.expression))})]})]})]}),i.jsx("div",{style:A6})]})}const c6={display:"flex",flexDirection:"column",marginBottom:8},u6={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:4},p6={fontSize:10,color:"#94a3b8",marginBottom:6,lineHeight:1.4},f6={display:"flex",flexDirection:"column",gap:4,padding:"8px 0"},g6={display:"flex",alignItems:"center",gap:6},h6={fontSize:10,padding:"1px 6px",borderRadius:4,background:"#e0e7ff",color:"#3730a3"},y6={display:"flex",alignItems:"center",gap:6},b6={fontSize:11,color:"#94a3b8"},Ff={fontSize:11,fontFamily:"monospace",background:"#f1f5f9",padding:"2px 6px",borderRadius:4,color:"#0f172a",wordBreak:"break-all"},m6={fontSize:11,border:"1px solid #e2e8f0",borderRadius:4,background:"#fff",color:"#dc2626",padding:"2px 8px",cursor:"pointer"},v6={display:"flex",flexDirection:"column",gap:2,fontSize:11,color:"#64748b"},_6={display:"flex",gap:12,fontSize:10,color:"#94a3b8",marginTop:2},Kf={fontSize:10,fontFamily:"monospace",background:"#f1f5f9",padding:"1px 4px",borderRadius:3,color:"#475569"},x6={fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#334155",padding:"4px 10px",cursor:"pointer",textAlign:"left",width:"100%"},w6={marginTop:4,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",padding:6},k6={width:"100%",padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,boxSizing:"border-box"},S6={marginTop:4,maxHeight:200,overflowY:"auto",display:"flex",flexDirection:"column",gap:2},C6={fontSize:11,color:"#94a3b8",padding:"8px 0",textAlign:"center"},$6={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8,border:"none",background:"transparent",cursor:"pointer",padding:"6px 8px",borderRadius:4,textAlign:"left"},E6={fontSize:10,color:"#94a3b8"},I6={fontSize:10,color:"#64748b",fontFamily:"monospace",whiteSpace:"nowrap"},A6={borderTop:"1px solid #e2e8f0",marginTop:4},T6=new Set(["Span","P","H1","H2","H3","H4","H5","H6","A","Button","Li","Label"]);function D6(e,t){if(!e||e.iteration&&typeof e.iteration=="object")return!1;const n=t?.textBinding;if(n===!1)return!1;if(n===!0)return!0;const o=typeof e.name=="string"?e.name:"";return T6.has(o)?!0:typeof e.text=="string"}const yn={direction:"flexDirection",justify:"flexJustify",align:"flexAlign",wrap:"flexWrap",gap:"flexGap",enable:"flexEnable"},hi={grow:"flexItemGrow",selfAlign:"flexItemAlign",order:"flexItemOrder"};function Vf(e){const t=e?.flexEditor;return t==="container"||t==="item"||t==="auto"?t:null}function N6(e){if(!e||typeof window>"u"||typeof window.getComputedStyle!="function")return!1;const t=(window.getComputedStyle(e).display??"").toLowerCase();return t==="flex"||t==="inline-flex"}function z6(e,t,n=Wt){if(!e||!t)return!1;const o=Do(e,t,n),r=t.options,s=Array.isArray(r)?t.onValue??r[0]?.value:void 0,a=l=>s!==void 0?l===s:l!==void 0&&l!==!1;return n.breakpoint!=="base"?a(o.scopedRawValue):o.matched&&a(o.value)}function M6(e,t,n=!1,o=!1,r=Wt){if(e==="container")return{showContainer:!0,showEnableButton:!1,showDisableButton:!1};if(e==="item")return{showContainer:!1,showEnableButton:!1,showDisableButton:!1};if(e==="auto"){const s=r.breakpoint==="base";return!o&&!s?{showContainer:!1,showEnableButton:!1,showDisableButton:!1}:(o?n:N6(t))?{showContainer:!0,showEnableButton:!1,showDisableButton:o}:{showContainer:!1,showEnableButton:!0,showDisableButton:!1}}return{showContainer:!1,showEnableButton:!1,showDisableButton:!1}}const L6={[yn.direction]:"layout_editor.flex.direction",[yn.justify]:"layout_editor.flex.justify",[yn.align]:"layout_editor.flex.align",[yn.wrap]:"layout_editor.flex.wrap",[yn.gap]:"layout_editor.flex.gap"},P6={[hi.grow]:"layout_editor.flex.item_grow",[hi.selfAlign]:"layout_editor.flex.item_align",[hi.order]:"layout_editor.flex.item_order"};function O6({node:e,spec:t,capability:n,t:o,onPatchNode:r,liveElement:s,scope:a=Wt}){const l=Vf(n),d=Ct(t,yn.enable),c=z6(e,d,a),{showContainer:p,showEnableButton:f,showDisableButton:y}=M6(l,s,c,!!d,a),g=Object.values(yn).filter(_=>_!==yn.enable&&Ct(t,_)),m=Object.values(hi).filter(_=>Ct(t,_)),h=d?.options,v=d?.onValue??h?.[0]?.value??!0,b=Array.isArray(h)&&h.length>=2?h[1].value:void 0,x=()=>{if(!d)return;const _=fn(e,d,v,a);r(_)},k=()=>{if(!d)return;const _=a.breakpoint!=="base"&&b!==void 0?b:void 0,C=fn(e,d,_,a);r(C)},w=(_,C,E)=>i.jsx("div",{"data-testid":E,style:{display:"flex",flexDirection:"column"},children:_.map(S=>{const T=Ct(t,S);if(!T)return null;const $=T.label?T:{...T,label:`$t:${C[S]}`};return i.jsx(pi,{controlKey:S,control:$,node:e,t:o,onPatch:r,scope:a},S)})});return i.jsxs("div",{className:"g7le-flex-editor","data-testid":"g7le-flex-editor",style:{display:"flex",flexDirection:"column",gap:12},children:[f&&i.jsx("button",{type:"button","data-testid":"g7le-flex-enable",onClick:x,style:B6,children:o("layout_editor.flex.make_flex")}),p&&g.length>0&&i.jsxs("div",{className:"g7le-flex-container-section","data-testid":"g7le-flex-container-section",children:[i.jsx("div",{style:Uf,children:o("layout_editor.flex.container_title")}),w(g,L6,"g7le-flex-container-controls"),y&&i.jsx("button",{type:"button","data-testid":"g7le-flex-disable",onClick:k,style:W6,children:o("layout_editor.flex.unmake_flex")})]}),l==="item"&&m.length>0&&i.jsxs("div",{className:"g7le-flex-item-section","data-testid":"g7le-flex-item-section",children:[i.jsx("div",{style:Uf,children:o("layout_editor.flex.item_title")}),w(m,P6,"g7le-flex-item-controls")]}),!p&&!f&&l!=="item"&&i.jsx("div",{"data-testid":"g7le-flex-empty",style:j6,children:o("layout_editor.flex.not_flex")})]})}const Uf={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:6},B6={padding:"8px 12px",fontSize:12,border:"1px dashed #2563eb",borderRadius:6,background:"#eff6ff",color:"#2563eb",cursor:"pointer"},W6={marginTop:8,padding:"6px 10px",fontSize:12,border:"1px solid #e2e8f0",borderRadius:6,background:"#f8fafc",color:"#64748b",cursor:"pointer"},j6={fontSize:12,color:"#94a3b8",padding:"16px 0",textAlign:"center"},qf=["desktop","tablet","mobile","portable"],Na=1280,H6=820,F6=390,K6=1920,V6=320;function U6(e){const t=[],n=new Set,o=r=>{if(!r||typeof r!="object")return;const s=r.responsive;if(s&&typeof s=="object")for(const a of Object.keys(s)){n.has(a)||(n.add(a),t.push(a));const l=s[a]?.children;if(Array.isArray(l))for(const d of l)o(d)}if(Array.isArray(r.children))for(const a of r.children)o(a)};if(Array.isArray(e))for(const r of e)o(r);return t}function q6(e){const t=[...qf],n=new Set(qf);for(const o of U6(e))!n.has(o)&&!t.includes(o)&&t.push(o);return t}function G6(e,t){const n=e?.responsive;if(!n||typeof n!="object")return[];const o=[];for(const r of Object.keys(n)){const s=n[r];!s||!Array.isArray(s.children)||r!==t&&o.push(r)}return o}function Y6(e){switch(e){case"desktop":return Na;case"tablet":return H6;case"mobile":return F6}const t=e in To?To[e]:Mn.parseRange(e);return!t||!Number.isFinite(t.max)?Na:Math.round(Math.max(V6,Math.min(K6,t.max)))}function Gf(){const t=Ft()?.document?.raw?.components;return u.useMemo(()=>q6(t??null),[t])}const X6={desktop:"layout_editor.property_modal.scope.device_desktop",tablet:"layout_editor.property_modal.scope.device_tablet",mobile:"layout_editor.property_modal.scope.device_mobile",portable:"layout_editor.property_modal.scope.device_portable"},J6=[{key:"base",labelKey:"layout_editor.property_modal.scope.scheme_light"},{key:"dark",labelKey:"layout_editor.property_modal.scope.scheme_dark"}];function Yf({scope:e,onChange:t,node:n,t:o,showColorScheme:r=!0,onClearScope:s}){const[a,l]=u.useState(!1),[d,c]=u.useState(""),[p,f]=u.useState(""),[y,g]=u.useState(null),m=Gf(),h=u.useMemo(()=>{const k=["base",...m],w=new Set(k);for(const _ of Object.keys(n.responsive??{}))_!=="base"&&!w.has(_)&&(w.add(_),k.push(_));return e.breakpoint!=="base"&&!w.has(e.breakpoint)&&k.push(e.breakpoint),k},[m,n.responsive,e.breakpoint]),v=k=>t({...e,colorScheme:k}),b=k=>t({...e,breakpoint:k}),x=()=>{const k=d.trim(),w=p.trim();if(k===""&&w===""){g(o("layout_editor.property_modal.scope.custom_invalid"));return}const _=`${k}-${w}`;if(!gC(_)){g(o("layout_editor.property_modal.scope.custom_invalid"));return}g(null),l(!1),c(""),f(""),b(_)};return i.jsxs("div",{className:"g7le-style-scope-tabs","data-testid":"g7le-style-scope-tabs",style:Z6,children:[r&&i.jsx("div",{className:"g7le-style-scope-scheme","data-testid":"g7le-style-scope-scheme",role:"tablist","aria-label":o("layout_editor.property_modal.scope.scheme_light"),style:Xf,children:J6.map(k=>{const w=e.colorScheme===k.key;return i.jsxs("button",{type:"button",role:"tab","aria-selected":w,"data-testid":`g7le-style-scheme-${k.key}`,"data-active":w?"true":"false",onClick:()=>v(k.key),style:Jf(w),children:[o(k.labelKey),k.key==="dark"&&Gs(n,{colorScheme:"dark",breakpoint:e.breakpoint})&&i.jsx("span",{"data-testid":"g7le-style-scheme-dark-dot",style:Zf})]},k.key)})}),i.jsxs("div",{className:"g7le-style-scope-device","data-testid":"g7le-style-scope-device",role:"tablist","aria-label":o("layout_editor.property_modal.scope.device_base"),style:Xf,children:[h.map(k=>{const w=e.breakpoint===k,_=k==="base"||wu(k),C=k==="base"?"layout_editor.property_modal.scope.device_base":X6[k],E=C?o(C):k,S=_?`g7le-style-bp-${k}`:`g7le-style-bp-custom-${k}`;return i.jsxs("button",{type:"button",role:"tab","aria-selected":w,"data-testid":S,"data-active":w?"true":"false",onClick:()=>b(k),style:Jf(w),children:[E,Gs(n,{colorScheme:"base",breakpoint:k})&&i.jsx("span",{"data-testid":`${S}-dot`,style:Zf})]},String(k))}),i.jsxs("button",{type:"button","data-testid":"g7le-style-bp-add-custom",onClick:()=>l(k=>!k),style:eT,children:["+ ",o("layout_editor.property_modal.scope.add_custom")]})]}),a&&i.jsxs("div",{className:"g7le-style-scope-custom-input","data-testid":"g7le-style-scope-custom-input",style:Q6,children:[i.jsx("input",{type:"number","data-testid":"g7le-style-custom-min",placeholder:o("layout_editor.property_modal.scope.custom_min"),value:d,onChange:k=>c(k.target.value),style:Qf}),i.jsx("span",{style:{color:"#94a3b8"},children:"—"}),i.jsx("input",{type:"number","data-testid":"g7le-style-custom-max",placeholder:o("layout_editor.property_modal.scope.custom_max"),value:p,onChange:k=>f(k.target.value),style:Qf}),i.jsx("button",{type:"button","data-testid":"g7le-style-custom-confirm",onClick:x,style:tT,children:o("layout_editor.property_modal.scope.add_custom")})]}),y&&i.jsx("div",{"data-testid":"g7le-style-custom-error",style:nT,children:y}),e.breakpoint!=="base"&&!wu(e.breakpoint)&&i.jsx("div",{"data-testid":"g7le-style-custom-priority-note",style:oT,children:o("layout_editor.property_modal.scope.custom_priority_note")}),s&&Gs(n,e)&&i.jsxs("button",{type:"button","data-testid":"g7le-style-scope-reset",onClick:s,style:R6,children:["↺ ",o("layout_editor.property_modal.scope.reset_to_base")]})]})}const Z6={display:"flex",flexDirection:"column",gap:0,padding:"0 0 8px",borderBottom:"1px solid #e2e8f0",marginBottom:8},Q6={display:"flex",gap:6,alignItems:"center",marginTop:4},Xf={display:"flex",gap:2,flexWrap:"wrap",borderBottom:"1px solid #e2e8f0",margin:"0 -16px",padding:"0 12px"};function Jf(e){return{display:"inline-flex",alignItems:"center",gap:4,padding:"6px 12px",fontSize:12,border:"none",borderBottom:`2px solid ${e?"#2563eb":"transparent"}`,background:"transparent",color:e?"#2563eb":"#64748b",cursor:"pointer",fontWeight:e?700:500,marginBottom:-1}}const Zf={display:"inline-block",width:5,height:5,borderRadius:3,background:"#f59e0b"},R6={alignSelf:"flex-start",marginTop:2,padding:"3px 8px",fontSize:10,border:"1px solid #cbd5e1",borderRadius:6,background:"#f8fafc",color:"#475569",cursor:"pointer"},eT={padding:"6px 12px",fontSize:11,border:"none",borderBottom:"2px dashed #cbd5e1",background:"transparent",color:"#475569",cursor:"pointer",marginBottom:-1},Qf={width:70,padding:"4px 6px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6},tT={padding:"4px 10px",fontSize:11,border:"none",borderRadius:6,background:"#2563eb",color:"#fff",cursor:"pointer"},nT={fontSize:11,color:"#dc2626"},oT={fontSize:10,color:"#94a3b8"},Rf=new Map;function Pn(e,t){Rf.set(e,t)}function rT(e){return e?Rf.get(e)??null:null}const za={id:{label:"$t:layout_editor.core_props.id.label",widget:"core-id",placeholder:"$t:layout_editor.core_props.id.placeholder",apply:{type:"propValue",propKey:"id"}},dataKey:{label:"$t:layout_editor.core_props.dataKey.label",widget:"core-datakey",placeholder:"$t:layout_editor.core_props.dataKey.placeholder",apply:{type:"nodeKey",nodeKey:"dataKey"}},isolatedState:{label:"$t:layout_editor.core_props.isolatedState.label",widget:"toggle",apply:{type:"nodeKey",nodeKey:"isolatedState"}},isolatedScopeId:{label:"$t:layout_editor.core_props.isolatedScopeId.label",widget:"core-scopeid",placeholder:"$t:layout_editor.core_props.isolatedScopeId.placeholder",apply:{type:"nodeKey",nodeKey:"isolatedScopeId"}}},iT=["id"];function sT(e){return e===!1?[]:Array.isArray(e)?e.filter(t=>t in za):[...iT]}function eg(e){const t=e.props?.id??e.id;return typeof t=="string"&&t.length>0?`${t}-scope`:"scope"}function aT({node:e,onPatchNode:t,t:n,scopeIdCandidates:o=[],usedScopeIds:r=[]}){const s=e,a="isolatedState"in s&&s.isolatedState!=null,l=typeof s.isolatedScopeId=="string"?s.isolatedScopeId:"",[d,c]=u.useState(""),p=()=>{const h={...e};a?(delete h.isolatedState,delete h.isolatedScopeId):(h.isolatedState={},h.isolatedScopeId=eg(e)),t(h)},f=h=>{const v={...e};v.isolatedScopeId=h.trim()===""?eg(e):h,t(v)},y=h=>{const v={...e};v.isolatedState=h,t(v)},g=u.useMemo(()=>{const h=d.trim().toLowerCase();return o.filter(v=>!h||v.toLowerCase().includes(h))},[o,d]),m=l!==""&&r.includes(l);return i.jsxs("div",{className:"g7le-isolated-scope","data-testid":"g7le-isolated-scope-control",style:lT,children:[i.jsx("div",{style:dT,children:n("layout_editor.core_props.isolatedState.label")}),i.jsxs("div",{style:cT,children:[i.jsx("button",{type:"button","data-testid":"g7le-isolated-toggle",role:"switch","aria-checked":a,onClick:p,style:uT(a),children:n(a?"layout_editor.overlay.on":"layout_editor.overlay.off")}),a?null:i.jsx("span",{"data-testid":"g7le-isolated-off-hint",style:pT,children:n("layout_editor.core_props.isolatedState.off_hint")})]}),a?i.jsxs(i.Fragment,{children:[i.jsxs("div",{style:tg,children:[i.jsx("label",{style:ng,children:n("layout_editor.core_props.isolatedScopeId.label")}),i.jsx("input",{type:"text","data-testid":"g7le-isolated-scopeid-input",value:l,placeholder:n("layout_editor.core_props.isolatedScopeId.placeholder"),onChange:h=>f(h.target.value),style:fT}),g.length>0?i.jsxs("div",{"data-testid":"g7le-isolated-scopeid-picker",style:gT,children:[i.jsx("input",{type:"text","data-testid":"g7le-isolated-scopeid-search",value:d,placeholder:n("layout_editor.core_props.isolatedScopeId.search"),onChange:h=>c(h.target.value),style:hT}),i.jsx("div",{style:yT,children:g.map(h=>i.jsx("button",{type:"button","data-testid":`g7le-isolated-scopeid-candidate-${h}`,onClick:()=>{f(h),c("")},style:bT,children:h},h))})]}):null,m?i.jsxs("p",{"data-testid":"g7le-isolated-scopeid-dup",style:mT,children:["ⓘ ",n("layout_editor.core_props.isolatedScopeId.duplicate")]}):null]}),i.jsxs("div",{style:tg,children:[i.jsx("label",{style:ng,children:n("layout_editor.core_props.isolatedState.initial_label")}),i.jsx("div",{"data-testid":"g7le-isolated-initial-value",children:i.jsx(Nn,{value:s.isolatedState??{},onChange:y,t:n,path:"isolatedState",scope:"isolated-node"})})]})]}):null]})}const lT={display:"flex",flexDirection:"column",gap:8,padding:10,border:"1px solid #e2e8f0",borderRadius:8,minWidth:0},dT={fontSize:12,fontWeight:700,color:"#0f172a"},cT={display:"flex",gap:8,alignItems:"center"},uT=e=>({padding:"4px 12px",fontSize:11,border:`1px solid ${e?"#3b82f6":"#cbd5e1"}`,borderRadius:14,background:e?"#eff6ff":"#fff",color:e?"#1d4ed8":"#64748b",cursor:"pointer"}),pT={fontSize:11,color:"#94a3b8"},tg={display:"flex",flexDirection:"column",gap:4,minWidth:0},ng={fontSize:11,color:"#64748b"},fT={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,boxSizing:"border-box",width:"100%"},gT={border:"1px solid #e2e8f0",borderRadius:6,padding:4,background:"#fff"},hT={width:"100%",padding:"4px 6px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,marginBottom:4,boxSizing:"border-box"},yT={display:"flex",flexDirection:"column",maxHeight:120,overflowY:"auto"},bT={textAlign:"left",padding:"4px 6px",fontSize:12,border:"none",background:"transparent",cursor:"pointer",borderRadius:4,color:"#0f172a"},mT={margin:0,fontSize:11,color:"#64748b"},vT={borderTop:"2px solid #c7d2fe",background:"#eef2ff",padding:"10px 12px",display:"flex",flexDirection:"column",gap:8},og={fontSize:13,fontWeight:700,color:"#3730a3",display:"flex",alignItems:"center",gap:6},_T={fontSize:11,fontWeight:600,color:"#4338ca",background:"#e0e7ff",border:"1px solid #c7d2fe",borderRadius:4,padding:"1px 6px"},Ma={fontSize:11,color:"#6366f1"},xT={alignSelf:"flex-start",fontSize:12,fontWeight:600,color:"#fff",background:"#4f46e5",border:"none",borderRadius:4,padding:"4px 10px",cursor:"pointer"},wT={opacity:.5,cursor:"not-allowed"},kT={fontSize:11,color:"#dc2626"};function ST({entry:e,t,onSave:n}){const[o,r]=u.useState(()=>e.props),[s,a]=u.useState(!0),[l,d]=u.useState(null),[c,p]=u.useState(!1),[f,y]=u.useState(!1),g=e.extensionName??e.extensionIdentifier??`#${e.extensionId}`,m=async()=>{if(!s){d(t("layout_editor.property_modal.injected_props.invalid_json"));return}d(null),p(!0),y(!1);try{await n(o),y(!0)}catch(h){d(h instanceof Error?h.message:String(h))}finally{p(!1)}};return i.jsxs("div",{"data-testid":`g7le-injected-props-entry-${e.extensionId}`,style:{display:"flex",flexDirection:"column",gap:6},children:[i.jsx("div",{style:og,children:i.jsx("span",{style:_T,"data-testid":"g7le-injected-props-origin-badge",children:t("layout_editor.property_modal.injected_props.origin",{source:g})})}),i.jsx(Bs,{value:o,shape:"object",emptyValue:{},testidPrefix:"g7le-injected-props-json",minHeight:80,invalidErrorKey:"layout_editor.property_modal.injected_props.invalid_json",shapeErrorKey:"layout_editor.property_modal.injected_props.invalid_json",t,onChange:h=>{r(h??{}),y(!1)},onValidityChange:h=>{a(h),h&&d(null),y(!1)}}),l&&i.jsx("div",{style:kT,"data-testid":"g7le-injected-props-error",children:l}),f&&i.jsx("div",{style:{...Ma,color:"#16a34a"},"data-testid":"g7le-injected-props-saved",children:t("layout_editor.property_modal.injected_props.saved")}),i.jsx("div",{style:Ma,children:t("layout_editor.property_modal.injected_props.save_target")}),i.jsx("button",{type:"button","data-testid":"g7le-injected-props-save",style:{...xT,...c||!s?wT:null},disabled:c||!s,onClick:m,children:c?t("layout_editor.property_modal.injected_props.saving"):t("layout_editor.property_modal.injected_props.save_button",{source:g})})]})}function CT({injectedProps:e,t,onSaveInjectedProps:n}){return!Array.isArray(e)||e.length===0?null:i.jsxs("div",{style:vT,"data-testid":"g7le-injected-props-section",children:[i.jsxs("div",{style:og,children:["🧩 ",t("layout_editor.property_modal.injected_props.title")]}),i.jsx("div",{style:Ma,children:t("layout_editor.property_modal.injected_props.help")}),e.map(o=>i.jsx(ST,{entry:o,t,onSave:r=>n(o.extensionId,r)},o.extensionId))]})}function $T(e,t){const n=e?.components??{};for(const o of Object.values(n)){const r=o?.find(s=>s.name===t);if(r)return r}return null}function ET({node:e,spec:t,manifest:n,t:o,onPatchNode:r,onClose:s,onDelete:a,permissionCandidates:l,pageCandidates:d,dataSourceCandidates:c,stateKeyCandidates:p,bindingCandidates:f,liveElement:y,scope:g=Wt,onScopeChange:m,templateIdentifier:h,initialTab:v,onSaveInjectedProps:b,branchLabel:x,isolatedScopeIdCandidates:k,usedScopeIds:w}){const _=e.__injectedProps,C=Array.isArray(_)&&_.length>0&&!!b,E=ve=>{m?.(ve)},S=()=>{r(xC(e,g))},T=typeof e.name=="string"?e.name:"",$=Oi(t,T),z=$T(n,T)?.settings,D=!!(z?.groups&&z.groups.length>0),O=Array.isArray($?.propControls)?$.propControls:[],M=sT($?.coreProps),B=new Set(M.map(ve=>za[ve].apply?.propKey)),N=O.filter(ve=>{const he=Ct(t,ve)?.apply?.propKey;return!(he!==void 0&&B.has(he))}),H=typeof $?.nodeEditor?.kind=="string"?$.nodeEditor.kind:void 0,L=$?.nodeEditor?.params,I=H?rT(H):null,P=!!I,F=Array.isArray($?.dataProps)?$.dataProps:[],G=F.length>0,V=!!(e.iteration&&typeof e.iteration=="object"),Y=D6(e,$),Z=M.length>0||N.length>0||P||G||Y||V,se=Array.isArray($?.styleControls)?$.styleControls:[],re=Array.isArray($?.advanced)?$.advanced:[],ee=(Array.isArray($?.events)?$.events:[]).length>0,fe=Vf($),K=se.length>0||fe!==null,me=!($?.visibilityCondition===!1)&&(Z||K||ee||D||re.length>0),Ce=u.useMemo(()=>{const ve=[];return D&&ve.push("settings"),Z&&ve.push("props"),K&&ve.push("style"),ee&&ve.push("action"),me&&ve.push("visibility"),ve.push("translation"),re.length>0&&ve.push("advanced"),ve},[D,Z,K,ee,me,re.length]),ze=N.length>0||P||G||V,[Se,qe]=u.useState(v&&Ce.includes(v)?v:D?"settings":ze?"props":K?"style":Z?"props":Ce[0]??"style"),De=_A(e),Pe=!Z&&!K&&!D&&!ee&&!me&&re.length===0,Qe=$?.label?$.label.startsWith("$t:")?o($.label.slice(3)):$.label:T||o("layout_editor.property_modal.element"),Me=(ve,te)=>{const he={...e.props??{}};te===void 0?delete he[ve]:he[ve]=te,r({...e,props:he})},Re={settings:o("layout_editor.property_modal.tab.settings"),props:o("layout_editor.property_modal.tab.props"),style:o("layout_editor.property_modal.tab.style"),action:o("layout_editor.property_modal.tab.action"),visibility:o("layout_editor.property_modal.tab.visibility"),translation:o("layout_editor.property_modal.tab.translation"),advanced:o("layout_editor.property_modal.tab.advanced")};return i.jsxs("div",{className:"g7le-property-modal","data-testid":"g7le-property-modal",style:IT,children:[i.jsxs("div",{"data-modal-drag-handle":!0,"data-testid":"g7le-property-modal-header",style:AT,children:[i.jsx("span",{"data-testid":"g7le-property-modal-title",style:{fontSize:14,fontWeight:700},children:D&&Se==="settings"?o("layout_editor.property_modal.settings_title",{name:Qe}):o("layout_editor.property_modal.title",{name:Qe})}),i.jsx("button",{type:"button","data-testid":"g7le-property-modal-close","aria-label":"close",onClick:s,style:TT,children:"✕"})]}),De&&i.jsx("div",{"data-testid":"g7le-property-modal-advanced-badge",style:DT,children:o("layout_editor.property_modal.advanced_badge")}),x&&i.jsx("div",{"data-testid":"g7le-property-modal-branch-badge",style:NT,children:o("layout_editor.property_modal.branch_badge",{device:x})}),i.jsx("div",{style:zT,role:"tablist",children:Ce.map(ve=>i.jsx("button",{type:"button",role:"tab","aria-selected":Se===ve,"data-testid":`g7le-property-tab-${ve}`,"data-active":Se===ve?"true":"false",onClick:()=>qe(ve),style:{...MT,color:Se===ve?"#2563eb":"#64748b",borderBottomColor:Se===ve?"#2563eb":"transparent"},children:Re[ve]},ve))}),i.jsxs("div",{style:LT,"data-testid":"g7le-property-modal-body",children:[Pe&&!C&&i.jsx("div",{"data-testid":"g7le-property-modal-no-editable",style:ig,children:o("layout_editor.property_modal.no_editable_props")}),C&&i.jsx(CT,{injectedProps:_,t:o,onSaveInjectedProps:b}),Se==="settings"&&z&&i.jsx(lA,{spec:z,node:e,t:o,onPatchProp:Me}),Se==="props"&&i.jsxs("div",{"data-testid":"g7le-property-props-tab",style:{display:"flex",flexDirection:"column"},children:[V&&i.jsx(d6,{node:e,candidates:f??[],t:o,onPatchNode:r}),G&&i.jsx(OA,{node:e,dataProps:F,candidates:f??[],t:o,onPatchNode:r}),Y&&i.jsx(r6,{node:e,candidates:f??[],t:o,onPatchNode:r,templateIdentifier:h}),P&&I&&i.jsx(I,{node:e,params:L,spec:t,manifest:n,t:o,onPatchNode:r,templateIdentifier:h,candidates:f}),M.map(ve=>i.jsx(pi,{controlKey:`core-${ve}`,control:za[ve],node:e,t:o,onPatch:r,scope:Wt,bindingCandidates:f},`core-${ve}`)),N.map(ve=>{const te=Ct(t,ve);return te?i.jsx(pi,{controlKey:ve,control:te,node:e,t:o,onPatch:r,scope:Wt,bindingCandidates:f},ve):null}),i.jsx(aT,{node:e,onPatchNode:r,t:o,scopeIdCandidates:k,usedScopeIds:w})]}),Se==="style"&&i.jsxs("div",{"data-testid":"g7le-property-style-tab",style:{display:"flex",flexDirection:"column"},children:[i.jsx("div",{style:rg,children:i.jsx(Yf,{scope:g,onChange:E,node:e,t:o,onClearScope:S})}),fe!==null&&i.jsx(O6,{node:e,spec:t,capability:$,t:o,onPatchNode:r,liveElement:y,scope:g}),se.map(ve=>{const te=Ct(t,ve);return te?i.jsx(pi,{controlKey:ve,control:te,node:e,t:o,onPatch:r,scope:g},ve):null})]}),Se==="action"&&i.jsx(zA,{node:e,spec:t,capability:$,t:o,onPatchNode:r,pageCandidates:d,dataSourceCandidates:c,stateKeyCandidates:p,bindingCandidates:f}),Se==="visibility"&&i.jsxs("div",{"data-testid":"g7le-property-visibility-tab",style:{display:"flex",flexDirection:"column"},children:[i.jsx("div",{style:rg,children:i.jsx(Yf,{scope:g,onChange:E,node:e,t:o,showColorScheme:!1})}),i.jsx(Eu,{node:e,spec:t,t:o,onPatchNode:r,dataSourceCandidates:c,stateKeyCandidates:p,scope:g})]}),Se==="translation"&&(h?i.jsx(Ud,{customKey:Vd(e),templateIdentifier:h,t:o,paramLabels:hv(e),onRemoveParam:ve=>{const te=typeof e.text=="string"?e.text:"";r({...e,text:mo(te,ve)});const he=Vd(e);h&&he&&kr(h,he,ve)}}):i.jsx("div",{"data-testid":"g7le-property-translation-deferred",style:ig,children:o("layout_editor.translation.not_a_key")})),Se==="advanced"&&i.jsx(wA,{node:e,advanced:re,t:o,onPatch:r,permissionCandidates:l})]}),i.jsxs("div",{style:PT,children:[i.jsx("span",{"data-testid":"g7le-property-modal-node-id",style:{fontSize:11,color:"#94a3b8"},children:typeof e.id=="string"||typeof e.id=="number"?`ID: ${e.id}`:""}),i.jsxs("div",{style:{display:"flex",gap:8},children:[i.jsx("button",{type:"button","data-testid":"g7le-property-modal-delete",onClick:a,style:OT,children:o("layout_editor.property_modal.delete_element")}),i.jsx("button",{type:"button","data-testid":"g7le-property-modal-done",onClick:s,style:BT,children:o("layout_editor.property_modal.close")})]})]})]})}const IT={display:"flex",flexDirection:"column",width:420,maxWidth:"92vw"},AT={display:"flex",alignItems:"center",justifyContent:"space-between",padding:"12px 16px",borderBottom:"1px solid #e2e8f0",cursor:"move",userSelect:"none"},TT={border:"none",background:"transparent",fontSize:14,cursor:"pointer",color:"#64748b"},DT={margin:"8px 16px 0",padding:"6px 10px",fontSize:11,background:"#fef3c7",color:"#92400e",borderRadius:6},NT={margin:"8px 16px 0",padding:"6px 10px",fontSize:11,background:"#dbeafe",color:"#1e40af",borderRadius:6},zT={display:"flex",gap:2,padding:"0 12px",borderBottom:"1px solid #e2e8f0",overflowX:"auto"},MT={padding:"8px 10px",fontSize:12,border:"none",borderBottom:"2px solid transparent",background:"transparent",cursor:"pointer",whiteSpace:"nowrap"},LT={padding:16,overflowY:"auto",maxHeight:"60vh"},rg={position:"sticky",top:-16,zIndex:2,background:"#fff",margin:"-16px -16px 0",padding:"6px 16px 0"},ig={fontSize:12,color:"#94a3b8",padding:"16px 0",textAlign:"center"},PT={display:"flex",alignItems:"center",justifyContent:"space-between",padding:"12px 16px",borderTop:"1px solid #e2e8f0"},OT={padding:"6px 12px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},BT={padding:"6px 12px",fontSize:12,border:"none",borderRadius:6,background:"#2563eb",color:"#fff",cursor:"pointer"},La="g7le:component-target-picked",Pa="g7le:component-target-pick-request";let WT=1;function jT({value:e,onChange:t,t:n,control:o}){const r=yo(),s=e==null?"":String(e),a=o?.allowManualInput!==!1,l=u.useCallback(()=>{if(typeof window>"u")return;const d=`pick-${WT++}`,p=r.stack[r.stack.length-1]?.id;p&&r.minimize(p,n("layout_editor.target_picker.minimized_hint"));const f=y=>{const g=y.detail;g?.requestId===d&&(window.removeEventListener(La,f),p&&r.restore(p),!g.cancelled&&typeof g.id=="string"&&t(g.id))};window.addEventListener(La,f),window.dispatchEvent(new CustomEvent(Pa,{detail:{requestId:d}}))},[r,t,n]);return i.jsx("div",{className:"g7le-component-target-picker","data-testid":"g7le-component-target-picker",children:i.jsxs("div",{style:{display:"flex",gap:6,alignItems:"center"},children:[a?i.jsx("input",{type:"text",className:"g7le-widget g7le-widget--text","data-testid":"g7le-component-target-input",value:s,placeholder:n("layout_editor.target_picker.id_placeholder"),onChange:d=>t(d.target.value===""?void 0:d.target.value),style:{flex:1,minWidth:0,padding:"6px 8px",border:"1px solid #cbd5e1",borderRadius:6,fontSize:13}}):i.jsx("span",{"data-testid":"g7le-component-target-value",style:{flex:1,minWidth:0},children:s||n("layout_editor.target_picker.none")}),i.jsxs("button",{type:"button","data-testid":"g7le-component-target-pick",onClick:l,style:{display:"flex",alignItems:"center",gap:4,padding:"6px 10px",background:"#1e293b",color:"#fff",border:"none",borderRadius:6,cursor:"pointer",fontSize:13,whiteSpace:"nowrap"},children:[i.jsx("span",{"aria-hidden":"true",children:"🎯"}),n("layout_editor.target_picker.select_area")]})]})})}async function HT(e,t,n,o,r=fetch){const s=`/api/admin/templates/${encodeURIComponent(e)}/layout-extensions/${t}`;let a;try{a=await r(s,{headers:je(),credentials:"same-origin"})}catch(b){return{kind:"error",message:b instanceof Error?b.message:String(b)}}if(a.status===404)return{kind:"not_found"};if(!a.ok)return{kind:"error",message:`HTTP ${a.status}`};const l=await a.json().catch(()=>null),d=(l&&(l.data||l))??{};let c={};const p=d.content;if(typeof p=="string")try{c=JSON.parse(p)}catch{return{kind:"error",message:"invalid extension content"}}else p&&typeof p=="object"&&(c=p);const f=typeof d.lock_version=="number"?d.lock_version:0,y=Array.isArray(c.injections)?[...c.injections]:[],g=y.findIndex(b=>b&&b.position==="inject_props"&&b.target_id===n);if(g<0)return{kind:"injection_not_found"};y[g]={...y[g],props:o};const m={...c,injections:y};let h;try{h=await r(s,{method:"PUT",headers:je({"Content-Type":"application/json"}),credentials:"same-origin",body:JSON.stringify({content:m,expected_lock_version:f})})}catch(b){return{kind:"error",message:b instanceof Error?b.message:String(b)}}const v=await h.json().catch(()=>null);return h.ok?{kind:"success",newLockVersion:typeof v?.data?.lock_version=="number"?v.data.lock_version:f+1}:h.status===409?{kind:"conflict",currentVersion:v?.current_version??-1,yourVersion:v?.your_version??f}:{kind:"error",message:v?.message??`HTTP ${h.status}`}}const sg=new Map;function Oa(e,t){sg.set(e,t)}function FT(e){return e?sg.get(e)??null:null}const ag="g7le.clipboard";function lg(){try{return typeof window>"u"||!window.sessionStorage?null:window.sessionStorage}catch{return null}}function KT(e){const t=JSON.parse(JSON.stringify(e)),n=o=>{for(const r of Object.keys(o))r.startsWith("__")&&delete o[r];Array.isArray(o.children)&&o.children.forEach(n)};return n(t),t}function dg(e,t=0){const n=lg();if(!n)return!1;try{const o={node:KT(e),copiedAt:t};return n.setItem(ag,JSON.stringify(o)),!0}catch{return!1}}function VT(){const e=lg();if(!e)return null;try{const t=e.getItem(ag);if(!t)return null;const n=JSON.parse(t);return!n||typeof n.node!="object"||n.node===null?null:JSON.parse(JSON.stringify(n.node))}catch{return null}}const Xo={nw:{width:-1,height:-1},n:{width:0,height:-1},ne:{width:1,height:-1},e:{width:1,height:0},se:{width:1,height:1},s:{width:0,height:1},sw:{width:-1,height:1},w:{width:-1,height:0}};function Ba(e){if(typeof e=="number")return e;if(typeof e=="string"){const t=e.match(/^(-?\d+(?:\.\d+)?)px$/);if(t)return Number(t[1])}return null}function UT(e,t){const n=Array.isArray(e.options)?e.options:[],o=Array.isArray(e.scale)?e.scale:[],r=n.length>0?n.map(l=>l.value):o;if(r.length===0)return;let s=r[0],a=1/0;return r.forEach((l,d)=>{const c=Ba(l)??d*40,p=Math.abs(c-t);p{if(!t)return;const m=Xo[y];if(m.width!==0&&!n||m.height!==0&&!o)return;const h=t.props?.style??{},v=s?.()??null,b=Ba(h.width)??(v?Math.round(v.width):0),x=Ba(h.height)??(v?Math.round(v.height):0);p.current={handle:y,startX:g.clientX,startY:g.clientY,startW:b,startH:x,node:t};const k=m.width!==0&&m.height!==0?"both":m.width!==0?"width":"height";d?.(k);let w=null;const _=E=>{const S=p.current;if(!S)return;const T=r||1,$=(E.clientX-S.startX)/T*Xo[S.handle].width,A=(E.clientY-S.startY)/T*Xo[S.handle].height;let z=S.node;if(Xo[S.handle].width!==0&&n){const D=cg(n,S.startW+$);z=fn(z,n,D)}if(Xo[S.handle].height!==0&&o){const D=cg(o,S.startH+A);z=fn(z,o,D)}w=z,a(z,k)},C=()=>{p.current=null,d?.(null),window.removeEventListener("pointermove",_),window.removeEventListener("pointerup",C),w&&l?.(w,k)};window.addEventListener("pointermove",_),window.addEventListener("pointerup",C)},[t,n,o,r,a,l,d]);return{enabledAxes:c,onHandlePointerDown:f}}const ug=320,pg=1920,YT=1024;function Wa(e){return Number.isFinite(e)?Math.round(Math.max(ug,Math.min(pg,e))):YT}function ja(e={}){const{state:t,dispatch:n}=Je(),{previewDevice:o,previewZoom:r,previewCustomWidth:s,previewColorScheme:a}=t,l=o==="custom"?Wa(s):Y6(o),d=u.useMemo(()=>{const g=e.availableWidth??l,m=l*r;return r>=1||m<=g?r:Math.min(r,g/l)},[l,r,e.availableWidth]),c=u.useCallback(g=>{n({type:"SET_PREVIEW_DEVICE",device:g})},[n]),p=u.useCallback(g=>{const m=Math.max(.5,Math.min(1,g));n({type:"SET_PREVIEW_ZOOM",zoom:m})},[n]),f=u.useCallback(g=>{n({type:"SET_PREVIEW_CUSTOM_WIDTH",width:Wa(g)})},[n]),y=u.useCallback(g=>{n({type:"SET_PREVIEW_COLOR_SCHEME",scheme:g})},[n]);return{device:o,deviceWidth:l,zoom:r,scale:d,customWidth:Wa(s),setDevice:c,setZoom:p,setCustomWidth:f,colorScheme:a,setColorScheme:y}}const yi="g7le-dnd-handle-";function XT(e){if(typeof e!="string"||!e.startsWith(yi))return null;const t=e.slice(yi.length);return t.length>0?t:null}function JT(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/["\\\]]/g,"\\$&")}function ZT(e,t,n,o){const r=o?.handleFallback??!1;if(e instanceof HTMLElement){const s=e.closest("[data-editor-path]");if(s)return s;const a=e.closest('[data-testid^="g7le-"]');if(a&&!(a.getAttribute("data-testid")??"").startsWith(yi))return null;if(r){const l=e.closest(`[data-testid^="${yi}"]`);if(l&&t){const d=XT(l.getAttribute("data-testid"));if(d){const c=t.querySelector(`[data-editor-path="${JT(d)}"]`);if(c)return c}}}}if(r&&n&&typeof document<"u"&&typeof document.elementsFromPoint=="function")for(const s of document.elementsFromPoint(n.x,n.y)){const a=s.closest?.("[data-editor-path]");if(a)return a}return null}function QT(e,t,n){if(typeof e=="string"&&e.trim().length>0)return{color:e};const o=typeof n?.color=="string"&&n.color.length>0,r=typeof t=="string"&&t.trim().length>0;return o||r?{}:{color:"#0f172a"}}const RT="#ffffff",e4="#0f172a";function t4(e){const t=e.trim(),n=t.match(/^rgba?\(\s*([\d.]+)[\s,]+([\d.]+)[\s,]+([\d.]+)/i);if(n)return[Number(n[1]),Number(n[2]),Number(n[3])];const o=t.replace(/^#/,"");return/^[0-9a-f]{3}$/i.test(o)?[parseInt(o[0]+o[0],16),parseInt(o[1]+o[1],16),parseInt(o[2]+o[2],16)]:/^[0-9a-f]{6}$/i.test(o)?[parseInt(o.slice(0,2),16),parseInt(o.slice(2,4),16),parseInt(o.slice(4,6),16)]:null}function n4(e){if(!e||/transparent/i.test(e))return!1;const t=e.trim().match(/^oklch\(\s*([\d.]+)(%?)/i);if(t)return(t[2]==="%"?Number(t[1])/100:Number(t[1]))>=.62;const n=t4(e);if(!n)return!1;const[o,r,s]=n;return .299*o+.587*r+.114*s>=180}function o4(e,t,n){const o=typeof n?.color=="string"?n.color:null;return n4(e??o??t)?e4:RT}function r4({box:e,initialValue:t,isCustomKey:n,t:o,onCommit:r,onCancel:s,mirrorClassName:a,mirrorStyle:l,nodeEffectiveColor:d,onOpenTranslations:c}){const p=u.useRef(null),f=u.useRef(!1),[y,g]=u.useState(t.trim().length>0),[m,h]=u.useState(null);u.useEffect(()=>{const w=p.current;if(w){w.textContent=t,w.focus();try{const _=window.document.createRange();_.selectNodeContents(w);const C=window.getSelection();C?.removeAllRanges(),C?.addRange(_)}catch{}f.current=!1}},[t]),u.useEffect(()=>{const w=p.current;if(!w||typeof window.getComputedStyle!="function"){h(null);return}try{h(window.getComputedStyle(w).color||null)}catch{h(null)}},[a,l]);const v=()=>(p.current?.textContent??"").trim(),b=()=>{f.current||(f.current=!0,r(v()))},x=()=>{f.current||(f.current=!0,s())},k=w=>{w.key==="Enter"&&!w.shiftKey?(w.preventDefault(),b()):w.key==="Escape"&&(w.preventDefault(),x())};return i.jsxs("div",{className:"g7le-inline-text-editor","data-testid":"g7le-inline-text-editor","data-custom-key":n?"true":"false",style:{position:"absolute",left:e.left,top:e.top,minWidth:Math.max(e.width,60),minHeight:e.height,pointerEvents:"auto",zIndex:1e4},children:[i.jsx("div",{ref:p,role:"textbox","aria-label":o("layout_editor.inline_edit.aria_label"),"aria-multiline":"false","data-testid":"g7le-inline-text-editable",className:a,contentEditable:!0,suppressContentEditableWarning:!0,spellCheck:!1,onInput:()=>g(v().length>0),onKeyDown:k,onBlur:b,style:{outline:"2px solid #2563eb",outlineOffset:1,borderRadius:3,background:o4(d,m,l),padding:"2px 4px",minHeight:e.height,whiteSpace:"pre-wrap",wordBreak:"break-word",boxShadow:"0 2px 8px rgba(37, 99, 235, 0.25)",...l??{},...QT(d,a,l)}}),i.jsxs("div",{className:"g7le-inline-text-editor__hint","data-testid":"g7le-inline-text-editor-hint",style:{marginTop:2,display:"inline-flex",alignItems:"center",gap:4,whiteSpace:"nowrap"},children:[c?i.jsxs("button",{type:"button","data-testid":"g7le-inline-text-editor-open-translations",onMouseDown:w=>w.preventDefault(),onClick:w=>{w.preventDefault(),w.stopPropagation(),c()},title:o("layout_editor.inline_edit.open_translations"),style:{padding:"2px 8px",fontSize:11,background:n?"#eff6ff":"#f0fdf4",color:n?"#1d4ed8":"#15803d",border:`1px solid ${n?"#bfdbfe":"#bbf7d0"}`,borderRadius:4,display:"inline-flex",alignItems:"center",gap:4,cursor:"pointer",whiteSpace:"nowrap"},children:[i.jsx("span",{"aria-hidden":"true",children:"🌐"}),i.jsx("span",{children:o(n?"layout_editor.inline_edit.existing_key_hint":"layout_editor.inline_edit.new_key_hint")}),i.jsxs("span",{"aria-hidden":"true",style:{opacity:.7},children:["· ",o("layout_editor.inline_edit.open_translations")," ›"]})]}):i.jsx("span",{style:{padding:"2px 6px",fontSize:11,background:n?"#eff6ff":"#f0fdf4",color:n?"#1d4ed8":"#15803d",border:`1px solid ${n?"#bfdbfe":"#bbf7d0"}`,borderRadius:4,display:"inline-flex",alignItems:"center",gap:4,whiteSpace:"nowrap"},children:n?i.jsxs(i.Fragment,{children:["⌐ ",o("layout_editor.inline_edit.existing_key_hint")]}):i.jsxs(i.Fragment,{children:["✎ ",o("layout_editor.inline_edit.new_key_hint")]})}),!y&&i.jsx("span",{"data-testid":"g7le-inline-text-editor-empty-warn",style:{color:"#b91c1c",marginLeft:4},children:o("layout_editor.inline_edit.empty_warning")})]})]})}function i4({box:e,node:t,customKey:n,initialChipValue:o,chipParamLabels:r,onKeyify:s,templateIdentifier:a,locale:l,t:d,candidates:c,onInsertBinding:p,onRemoveBinding:f,onCommit:y,onCancel:g}){const[m,h]=u.useState(null),v=u.useRef(""),[b,x]=u.useState(!1),k=u.useRef(!1),w=u.useRef(null),_=Ft(),C=u.useRef(()=>{}),[E,S]=u.useState(null),[T,$]=u.useState(!1),A=u.useRef(n??null);u.useEffect(()=>{n&&A.current!==n&&(A.current=n)},[n]);const z=u.useMemo(()=>{if(!n&&r)return r;const L={},I=mt(typeof t.text=="string"?t.text:"");for(const P of I?.params??[])L[P.name]=Vt(P.expression);return L},[t.text,n,r]);u.useEffect(()=>{let L=!1;if(!n){const I=o??"";return v.current=I,h(I),()=>{L=!0}}return(async()=>{const I=It(n,l);if(I!==void 0){v.current=I,h(I);return}const P=await cn(a,n);if(L)return;const F=P?.values?.[l]??"";v.current=F,h(F)})(),()=>{L=!0}},[a,n,l,o]);const D=async()=>{if(k.current)return;k.current=!0;const L=m??"";if(L===v.current){y();return}x(!0);let I=A.current;if(!I){if(!s){x(!1),k.current=!1;return}if(I=await s(L),x(!1),!I){k.current=!1;return}A.current=I,y();return}const P=await ko(a,I,l,L);if(x(!1),P.kind==="error"){k.current=!1;return}_?.markDirty?.(),y()},O=()=>{k.current||(k.current=!0,g())},M=L=>{S(L)},B=async L=>{if(!(E===null||!p||T)){$(!0);try{const I=A.current;I&&m!==null&&m!==v.current&&(await ko(a,I,l,m),v.current=m);const P=await p(E,L);P!==null&&(h(P),v.current=P,_?.markDirty?.())}finally{$(!1),S(null)}}},N=async L=>{if(!(!f||T)){$(!0);try{const I=A.current;I&&m!==null&&m!==v.current&&(await ko(a,I,l,m),v.current=m);const P=await f(L);P!==null&&(h(P),v.current=P,_?.markDirty?.())}finally{$(!1)}}},H=L=>{L.key==="Enter"&&!L.shiftKey?(L.preventDefault(),D()):L.key==="Escape"&&(L.preventDefault(),O())};return C.current=()=>{D()},u.useEffect(()=>{const L=P=>{const F=w.current;if(!F)return;const G=P.target;if(G&&F.contains(G))return;const V=G;V&&V.closest&&V.closest('[data-testid="g7le-inline-toolbar"], .g7le-inline-toolbar')||C.current()},I=w.current?.ownerDocument??document;return I.addEventListener("pointerdown",L,!0),()=>I.removeEventListener("pointerdown",L,!0)},[]),i.jsxs("div",{ref:w,className:"g7le-inline-param-chip-editor","data-testid":"g7le-inline-param-chip-editor",onKeyDown:H,style:{position:"absolute",left:e.left,top:e.top,minWidth:Math.max(e.width,120),pointerEvents:"auto",zIndex:1e4,background:"#fff",border:"2px solid #2563eb",borderRadius:4,boxShadow:"0 2px 8px rgba(37,99,235,0.25)",padding:4},children:[m===null?i.jsx("div",{"data-testid":"g7le-inline-param-chip-loading",style:{fontSize:12,color:"#94a3b8",padding:4},children:d("layout_editor.translation.loading")}):i.jsx(mr,{value:m,onChange:h,t:d,paramLabels:z,testIdSuffix:"inline",onRequestInsert:p?M:void 0,onRemoveChip:f?L=>{N(L)}:void 0}),E!==null&&p&&i.jsx("div",{"data-testid":"g7le-inline-param-chip-insert-picker",style:{marginTop:4},children:i.jsx($t,{candidates:c??[],t:d,onSelect:L=>{B(L)},testIdSuffix:"inline-insert",defaultOpen:!0,floating:!1})}),i.jsxs("div",{style:{display:"flex",alignItems:"center",gap:6,marginTop:4},children:[i.jsx("button",{type:"button","data-testid":"g7le-inline-param-chip-save",disabled:b,onMouseDown:L=>L.preventDefault(),onClick:()=>{D()},style:{fontSize:11,border:"none",borderRadius:6,background:"#2563eb",color:"#fff",padding:"4px 12px",cursor:"pointer"},children:d(b?"layout_editor.translation.saving":"layout_editor.translation.save")}),i.jsx("span",{style:{fontSize:10,color:"#94a3b8"},children:d("layout_editor.translation.placeholder_locked")})]})]})}const s4=["fontWeight","fontBold","fontStyle","fontItalic","textDecoration","textUnderline","textAlign","fontSize","textColor"],a4={fontWeight:"B",fontBold:"B",fontStyle:"I",fontItalic:"I",textDecoration:"U",textUnderline:"U",textAlign:"≡",fontSize:"T",textColor:"A"},l4=[["fontWeight","fontBold"],["fontItalic","fontStyle"],["textUnderline","textDecoration"]];function fg({node:e,spec:t,t:n,onApplyControl:o,box:r,scope:s=Wt}){const a=typeof e.name=="string"?e.name:"",l=Oi(t,a),d=Array.isArray(l?.styleControls)?l.styleControls:[];let c=s4.filter(p=>d.includes(p)&&Ct(t,p)!==null);for(const p of l4){const f=p.filter(y=>c.includes(y));if(f.length>1){const y=f[0];c=c.filter(g=>!p.includes(g)||g===y)}}return c.length===0?null:i.jsx("div",{className:"g7le-inline-toolbar","data-testid":"g7le-inline-toolbar",role:"toolbar","aria-label":n("layout_editor.inline_edit.toolbar_label"),style:{position:"absolute",left:r.left,top:r.top-40,display:"inline-flex",gap:2,padding:4,background:"#0f172a",borderRadius:8,boxShadow:"0 4px 12px rgba(15, 23, 42, 0.35)",pointerEvents:"auto",zIndex:10001},children:c.map(p=>i.jsx(c4,{controlKey:p,node:e,spec:t,t:n,scope:s,onApplyControl:o},p))})}const d4={fontWeight:"bold",fontBold:"bold",fontStyle:"italic",fontItalic:"italic",textDecoration:"underline",textUnderline:"underline"};function gg(e,t){const n=r=>(r.split(/[-\s]/).pop()??r)===t||r===t;return e.find(r=>{const s=typeof r.value=="string"?r.value:"",a=Array.isArray(r.apply?.tokens)?r.apply.tokens:[];return n(s)||a.some(n)})?.value}function c4({controlKey:e,node:t,spec:n,t:o,scope:r,onApplyControl:s}){const[a,l]=u.useState(!1),d=Ct(n,e);if(!d)return null;const c=d.options,p=Array.isArray(c),f=Do(t,d,r),y=d4[e],g=y&&Array.isArray(c)?gg(c,y):void 0,m=!y,h=g!==void 0?f.value===g:p&&f.matched&&f.value!==void 0&&f.value!=="",v=o(`layout_editor.inline_edit.format.${e}`),b=_=>typeof _.label=="string"?_.label.startsWith("$t:")?o(_.label.slice(3)):_.label:String(_.value??""),x=()=>{s(e,_=>{const C=Do(_,d,r),E=Array.isArray(c)?gg(c,y):void 0,S=E!==void 0&&C.value===E?void 0:E;return fn(_,d,S,r)})},k=_=>{s(e,C=>{const S=Do(C,d,r).value===_?void 0:_;return fn(C,d,S,r)}),l(!1)},w=_=>{if(_.preventDefault(),_.stopPropagation(),!m&&Array.isArray(c)){x();return}l(C=>!C)};return i.jsxs("div",{style:{position:"relative",display:"inline-flex"},children:[i.jsxs("button",{type:"button","data-testid":`g7le-inline-format-${e}`,"data-active":h?"true":"false","aria-label":v,"aria-pressed":p?h:void 0,title:v,onMouseDown:_=>_.preventDefault(),onClick:w,style:{display:"inline-flex",alignItems:"center",gap:5,height:28,padding:"0 9px",fontSize:12,border:"none",borderRadius:5,cursor:"pointer",background:h?"#2563eb":"transparent",color:"#ffffff",whiteSpace:"nowrap"},children:[i.jsx("span",{"aria-hidden":"true",style:{fontWeight:e==="fontWeight"||e==="fontBold"?700:600,fontStyle:e==="fontStyle"||e==="fontItalic"?"italic":"normal",textDecoration:e==="textDecoration"||e==="textUnderline"?"underline":"none"},children:a4[e]}),i.jsx("span",{children:v}),m&&i.jsx("span",{"aria-hidden":"true",style:{fontSize:9,opacity:.8},children:"▾"})]}),m&&a&&i.jsx("div",{"data-testid":`g7le-inline-popover-${e}`,role:"listbox",onMouseDown:_=>_.preventDefault(),style:{position:"absolute",top:32,left:0,minWidth:140,maxHeight:240,overflowY:"auto",background:"#0f172a",border:"1px solid #334155",borderRadius:8,boxShadow:"0 8px 24px rgba(15,23,42,0.45)",padding:4,zIndex:10002},children:Array.isArray(c)&&c.length>0?c.map((_,C)=>{const E=f.value===_.value;return i.jsxs("button",{type:"button",role:"option","aria-selected":E,"data-testid":`g7le-inline-option-${e}-${String(_.value??C)}`,onMouseDown:S=>S.preventDefault(),onClick:S=>{S.preventDefault(),S.stopPropagation(),k(_.value)},style:{display:"flex",alignItems:"center",gap:8,width:"100%",padding:"6px 8px",fontSize:12,textAlign:"left",border:"none",borderRadius:5,cursor:"pointer",background:E?"#2563eb":"transparent",color:"#ffffff"},children:[typeof _.swatch=="string"&&i.jsx("span",{"aria-hidden":"true",style:{width:14,height:14,borderRadius:3,background:_.swatch,border:"1px solid rgba(255,255,255,0.3)"}}),i.jsx("span",{children:b(_)}),E&&i.jsx("span",{"aria-hidden":"true",style:{marginLeft:"auto"},children:"✓"})]},String(_.value??C))}):i.jsx(u4,{testid:`g7le-inline-freeinput-${e}`,placeholder:o(`layout_editor.inline_edit.prompt.${e}`),initial:typeof f.value=="string"?f.value:"",onSubmit:_=>{s(e,C=>fn(C,d,_,r)),l(!1)}})})]})}function u4({testid:e,placeholder:t,initial:n,onSubmit:o}){const[r,s]=u.useState(n);return i.jsx("input",{type:"text","data-testid":e,value:r,placeholder:t,autoFocus:!0,onMouseDown:a=>a.stopPropagation(),onChange:a=>s(a.currentTarget.value),onKeyDown:a=>{a.key==="Enter"&&(a.preventDefault(),o(r.trim()))},style:{width:130,padding:"6px 8px",fontSize:12,border:"1px solid #334155",borderRadius:5,background:"#1e293b",color:"#ffffff"}})}function p4(e){const{frameEl:t,manifest:n,nesting:o,componentPalette:r,spec:s=null,permissionCandidates:a,resolveRouteMatch:l,onNavigateToDestination:d,onSessionAddedPathsChange:c,onEditProps:p}=e,{state:f,dispatch:y}=Je(),{t:g}=tt(),m=ja(),h=u.useCallback((W,X)=>{const R=window.G7Core;if(R&&typeof R.t=="function"){const de=R.t(W,X);if(de&&de!==W&&!de.startsWith("$t:"))return de}return g(W,X)},[g]),v=Ft(),b=d7(50),x=yo(),k=u.useRef([]),w=u.useMemo(()=>v?.document?.raw?.components??[],[v?.document?.raw?.components]),_=u.useMemo(()=>w.length===0?null:{children:w},[w]),C=u.useMemo(()=>{if(f.editMode!=="extension")return;const W=/^__extension__\/(\d+)/.exec(f.selectedRoute?.path??"");return W?Number(W[1]):void 0},[f.editMode,f.selectedRoute?.path]),E=u.useMemo(()=>{if(f.editMode==="iteration_item"){const W=v?.document?.iterationContext?.sourceIndexPath;return Array.isArray(W)&&W.length>0?W:null}if(f.editMode==="modal"){const W=v?.document?.modalContext?.editIndexPath;return Array.isArray(W)&&W.length>0?W:null}return null},[f.editMode,v?.document?.iterationContext?.sourceIndexPath,v?.document?.modalContext?.editIndexPath]),S=e7({rootNode:_,editMode:f.editMode,currentExtensionId:C,editableRootPath:E,pathParser:Ze,resolveRouteMatch:l}),[T,$]=u.useState(null),[A,z]=u.useState(null),[D,O]=u.useState(null),M=u.useRef(null);M.current=D;const[B,N]=u.useState(null),H=u.useRef(null),L=u.useRef(null);L.current=S.selectedPath;const I=Wb(),[P,F]=u.useState(null),G=u.useCallback(W=>{if(!t)return;const X=Ze(W);if(!X)return;const R={children:Me.current.components},de=We(R,X),ye=I.classify(de);if(!ye.editable){Et({op:"inline_edit_blocked_binding",sourceState:ye.sourceState,componentPath:at(X),timestamp:Date.now()});return}const we=po(t,W);if(!we)return;const Te=de?.props??{},ke=yg(t,W);F({path:X,domPath:W,box:we,initialValue:ye.displayValue,isCustomKey:ye.sourceState==="custom_key",isParamKey:ye.isParamKey===!0,customKey:ye.customKey,chipValue:ye.chipValue,chipParamLabels:ye.chipParamLabels,mirrorClassName:typeof Te.className=="string"?Te.className:void 0,mirrorStyle:Te.style??void 0,nodeEffectiveColor:ke}),Et({op:"inline_edit_enter",sourceState:ye.sourceState,componentPath:at(X),timestamp:Date.now()})},[t,I]),V=u.useCallback(()=>{if(!t){$(null),z(null);return}z(po(t,S.selectedPath)),$(po(t,S.hoverPath))},[t,S.selectedPath,S.hoverPath,w]);u.useEffect(()=>{if(V(),typeof window<"u"&&typeof window.requestAnimationFrame=="function"){const W=window.requestAnimationFrame(()=>V());return()=>window.cancelAnimationFrame(W)}},[V]),u.useEffect(()=>{if(t)return $p(V,t)},[t,V]);const Y=u.useCallback((W,X)=>{if(typeof window>"u")return;window.dispatchEvent(new CustomEvent(La,{detail:X===null?{requestId:W,cancelled:!0}:{requestId:W,id:X}})),O(null),N(null);const R=H.current;R?S.handleSelect("",{dataset:{editorPath:R}}):S.clearSelection(),H.current=null},[S]);u.useEffect(()=>{if(typeof window>"u")return;const W=X=>{const R=X.detail;if(typeof R?.requestId!="string")return;const de=M.current;de&&de!==R.requestId&&Y(de,null),H.current=L.current,O(R.requestId)};return window.addEventListener(Pa,W),()=>window.removeEventListener(Pa,W)},[Y]),u.useEffect(()=>{if(!D)return;const W=X=>{X.key==="Escape"&&(X.preventDefault(),Y(D,null))};return window.addEventListener("keydown",W,!0),()=>window.removeEventListener("keydown",W,!0)},[D,Y]),u.useEffect(()=>{if(!t)return;const W=f.editMode==="iteration_item"||f.editMode==="modal",X=(xe,Ee)=>ZT(xe,t,Ee?{x:Ee.clientX,y:Ee.clientY}:void 0,{handleFallback:W}),R=xe=>{const Ee=xe.dataset.editorPath??"",Fe=Ee?Ze(Ee):null,zt={children:Me.current.components},gt=Fe?We(zt,Fe):null,Mt=gt&&typeof gt.props?.id=="string"?gt.props.id:typeof gt?.id=="string"?gt.id:"";return Mt.startsWith("auto_")?"":Mt},de=xe=>{const Ee=X(xe.target,xe);if(!Ee)return;const Fe=M.current;if(Fe){xe.preventDefault(),xe.stopPropagation();const zt=R(Ee);zt&&Y(Fe,zt);return}xe.preventDefault(),xe.stopPropagation(),S.handleSelect(Ee.dataset.editorId??"",{currentTarget:Ee,dataset:Ee.dataset})},ye=xe=>{const Ee=X(xe.target,xe);if(M.current){if(!Ee){N(null);return}const Fe=po(t,Ee.dataset.editorPath??null);if(!Fe){N(null);return}N({box:Fe,hasId:R(Ee)!==""});return}if(!Ee){S.handleHover(null,{});return}S.handleHover(Ee.dataset.editorId??"",{currentTarget:Ee,dataset:Ee.dataset})},we=()=>{if(M.current){N(null);return}S.handleHover(null,{})},Te=xe=>{const Ee=X(xe.target,xe);if(!Ee)return;const Fe=Ee.dataset.editorPath??"";Fe&&(xe.preventDefault(),xe.stopPropagation(),G(Fe))},ke=t.parentElement??t;return ke.addEventListener("click",de,!0),ke.addEventListener("mousemove",ye,!0),ke.addEventListener("mouseleave",we,!0),ke.addEventListener("dblclick",Te,!0),()=>{ke.removeEventListener("click",de,!0),ke.removeEventListener("mousemove",ye,!0),ke.removeEventListener("mouseleave",we,!0),ke.removeEventListener("dblclick",Te,!0)}},[t,S,G,f.editMode,Y]);const Z=u.useMemo(()=>{const W=S.selectedPath;if(!W)return null;const X=W.match(/^(.*)\.children\.\d+$/);return X?X[1]:null},[S.selectedPath]),se=u.useCallback(()=>{Z&&S.handleSelect("",{dataset:{editorPath:Z}})},[Z,S]),re=u.useMemo(()=>!t||!S.selectedPath?null:t.querySelector(`[data-editor-path="${an(S.selectedPath)}"]`),[t,S.selectedPath]),U=u.useMemo(()=>S.selectedPath?Ze(S.selectedPath):null,[S.selectedPath]),ee=u.useMemo(()=>{if(!U)return null;const W=U.find(et);if(!W)return null;const{i18nKey:X,raw:R}=bC(W.responsive);return X?g(X):g("layout_editor.overlay.branch_custom",{range:R})},[U,g]),fe=u.useMemo(()=>S.selectedPath?S.selectedIsIteration&&S.selectedIterationSourcePath?S.selectedIterationSourcePath:S.selectedPath:null,[S.selectedPath,S.selectedIsIteration,S.selectedIterationSourcePath]),K=u.useMemo(()=>fe?Ze(fe):null,[fe]),ne=u.useMemo(()=>!t||!fe?null:t.querySelector(`[data-editor-path="${an(fe)}"]`),[t,fe]),me=u.useMemo(()=>{if(ne?.parentElement)return ne.parentElement;if(!t||!fe)return null;const W=fe.match(/^(.*)\.children\.\d+$/);return W?t.querySelector(`[data-editor-path="${an(W[1])}"]`):null},[ne,t,fe]),Ce=u.useMemo(()=>{const W=S.selectedNode;return W&&(typeof W.name=="string"?W.name:typeof W.type=="string"?W.type:"")||null},[S.selectedNode]),ze=u.useMemo(()=>{if(S.selectedLockKind!=="extension")return null;const W=S.selectedNode?.__source;if(!W||W.kind!=="extension")return null;const X=W.extensionName?.trim(),R=W.extensionIdentifier?.trim();return X&&R?`${X} (${R})`:X||R||W.extensionSourceType||null},[S.selectedLockKind,S.selectedNode]),Se=s7({parentEl:me,selectedPath:K,selectedEl:ne}),qe=u.useMemo(()=>!t||!fe||fe===S.selectedPath?A:po(t,fe),[t,fe,A,S.selectedPath,w]),De=u.useRef(null),Pe=u.useCallback(()=>{const W=De.current;W&&(x.close(W),De.current=null)},[x]),Qe=u.useRef(()=>{}),Me=u.useRef({manifest:n,nesting:o,componentPalette:r,components:w});Me.current={manifest:n,nesting:o,componentPalette:r,components:w};const Re=u.useCallback(W=>{const X=W.insertion?.parentPath??[],R=W.insertion?.index??0,de=Me.current,ye=hg(de.components,X);Pe();const we=x.open({ariaLabel:h("layout_editor.palette.title"),width:880,maxHeightRatio:.82,content:u.createElement(Ef,{manifest:de.manifest,nesting:de.nesting,componentPalette:de.componentPalette??null,targetParentPath:X,targetContainerName:ye,onInsert:(Te,ke,xe)=>{Qe.current(Te,ke,xe)},insertionIndex:R,onClose:()=>Pe(),editorTemplateId:f.templateIdentifier,editorLocale:f.locale}),onClose:()=>{De.current=null}});De.current=we},[x,Pe]),ve=u.useMemo(()=>{if(!f.isPaletteOpen)return null;if(!U)return{parentPath:[],index:w.length};if(S.selectedLockKind!=="none"){const de=K;return!de||de.length===0?{parentPath:[],index:w.length}:{parentPath:de.slice(0,-1),index:(de[de.length-1]??0)+1}}const X=S.selectedNode,R=Array.isArray(X?.children)?X.children.length:0;return lI(X?.name,R,U,o,w.length)},[f.isPaletteOpen,U,K,S.selectedLockKind,S.selectedNode,w.length,o]),te=u.useCallback(()=>{y({type:"SET_PALETTE_OPEN",open:!1})},[y]),he=u.useRef(null);u.useEffect(()=>{if(!f.isPaletteOpen){const ye=he.current;ye&&(x.close(ye),he.current=null);return}if(!ve||he.current)return;const W=ve,X=Me.current,R=hg(X.components,W.parentPath),de=x.open({ariaLabel:h("layout_editor.palette.title"),width:880,maxHeightRatio:.82,content:u.createElement(Ef,{manifest:X.manifest,nesting:X.nesting,componentPalette:X.componentPalette??null,targetParentPath:W.parentPath,targetContainerName:R,onInsert:(ye,we,Te)=>{Qe.current(ye,we,Te),te()},insertionIndex:W.index,onClose:()=>te(),editorTemplateId:f.templateIdentifier,editorLocale:f.locale}),onClose:()=>{he.current=null,y({type:"SET_PALETTE_OPEN",open:!1})}});he.current=de},[f.isPaletteOpen,ve,x,te,y]);const Q=u.useRef({layoutName:null,pushed:!1});u.useEffect(()=>{const W=v?.document?.layoutName??null;if(!W){Q.current={layoutName:null,pushed:!1};return}Q.current.layoutName!==W&&(b.clear(),b.push({actionKind:"inline_text_edit",label:"baseline",snapshot:w}),Q.current={layoutName:W,pushed:!0})},[v?.document?.layoutName,w,b]);const ie=u.useRef(0);u.useEffect(()=>{const W=v?.saveSuccessCounter??0;W!==ie.current&&(ie.current=W,W!==0&&(b.clear(),b.push({actionKind:"inline_text_edit",label:"save_baseline",snapshot:w}),k.current=[],c?.([])))},[v?.saveSuccessCounter,w,b,c]);const _e=u.useRef(0);u.useEffect(()=>{const W=v?.reloadCounter??0;W!==_e.current&&(_e.current=W,W!==0&&(Q.current={layoutName:null,pushed:!1},k.current=[],c?.([])))},[v?.reloadCounter,c]);const ge=u.useCallback((W,X,R)=>{if(!v)return;let de=[];v.patchLayout(ke=>{const xe={children:ke},Ee=Ha(xe,X),Fe=R<0?Array.isArray(Ee?.children)?Ee.children.length:0:R,gt=Qi(xe,X,Fe,W).children??[];return de=gt,gt}),b.push({actionKind:"insert",label:`insert ${W.name??W.type??""}`,snapshot:de});const ye=Ha({children:de},X),we=R<0?Array.isArray(ye?.children)?ye.children.length-1:0:R,Te=at([...X,we]);if(k.current=[...k.current,Te],c?.(k.current),t){const ke=`[data-editor-path="${an(Te)}"]`,xe=()=>{const Ee=t.querySelector(ke);Ee&&typeof Ee.scrollIntoView=="function"&&Ee.scrollIntoView({behavior:"smooth",block:"center",inline:"nearest"})};typeof window<"u"&&typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame(()=>window.requestAnimationFrame(xe)):setTimeout(xe,32)}},[v,b,c,t]);Qe.current=ge;const Ae=u.useCallback(()=>{if(!v||!S.selectedNode||!U)return;const W=es(S.selectedNode);let X=[];v.patchLayout(R=>{const de={children:R},ye=U.slice(0,-1),we=U[U.length-1]??0,ke=Qi(de,ye,we+1,W).children??[];return X=ke,ke}),b.push({actionKind:"insert",label:"duplicate",snapshot:X})},[v,S.selectedNode,U,b]),Ne=u.useCallback(()=>{if(!v||!U)return;let W=[];v.patchLayout(X=>{const ye=Ri({children:X},U).children??[];return W=ye,ye}),b.push({actionKind:"remove",label:"remove",snapshot:W}),S.clearSelection()},[v,U,b,S]),Le=u.useMemo(()=>{if(!S.selectedNode||!U||U.some(et))return null;const W=S.selectedNode;if(!Array.isArray(W.children))return null;const X=yC(f.previewDevice,W,f.previewCustomWidth);return{mode:X.mode,key:X.key,sourceKey:X.sourceKey}},[S.selectedNode,U,f.previewDevice,f.previewCustomWidth]),q=u.useCallback(()=>{if(!v||!U||Le?.mode!=="separate")return;const W=Le.key,X=Le.sourceKey;let R=[];v.patchLayout(de=>(R=Ab({children:de},U,W,X).children??[],R)),b.push({actionKind:"insert",label:"separate_branch",snapshot:R})},[v,U,Le,b]),ae=u.useCallback(()=>{if(!v||!U||Le?.mode!=="merge")return;const W=Le.key;let X=[];v.patchLayout(R=>(X=Tb({children:R},U,W).children??[],X)),b.push({actionKind:"remove",label:"merge_branch",snapshot:X})},[v,U,Le,b]),pe=u.useCallback(W=>{switch(W){case"mobile":return g("layout_editor.context_menu.device_mobile");case"portable":return g("layout_editor.context_menu.device_portable");case"tablet":return g("layout_editor.context_menu.device_tablet");case"desktop":return g("layout_editor.context_menu.device_desktop");default:return g("layout_editor.context_menu.device_custom",{range:W})}},[g]),$e=u.useMemo(()=>{if(!Le)return null;const W=pe(Le.key);return{separate:g("layout_editor.context_menu.separate_branch_device",{device:W}),merge:g("layout_editor.context_menu.merge_branch_device",{device:W})}},[Le,g,pe]),be=u.useMemo(()=>{if(!S.selectedNode||!U)return[];if(U.some(et))return[];const W=Ur(f.previewDevice,S.selectedNode,f.previewCustomWidth);return G6(S.selectedNode,W).map(X=>({key:X,label:pe(X)}))},[S.selectedNode,U,f.previewDevice,f.previewCustomWidth,pe]),j=u.useCallback(W=>{if(W==="desktop"||W==="tablet"||W==="mobile"||W==="portable"){m.setDevice(W);return}m.setDevice(W)},[m]),oe=u.useCallback(()=>{S.selectedNode&&dg(S.selectedNode)},[S.selectedNode]),ue=u.useCallback(()=>{S.selectedNode&&(dg(S.selectedNode),Ne())},[S.selectedNode,Ne]),J=u.useCallback(()=>{if(!v)return;const W=VT();if(!W)return;const X=es(W);if(U&&U.length>0){const R=U.slice(0,-1),de=(U[U.length-1]??0)+1;ge(X,R,de)}else ge(X,[],w.length)},[v,U,ge,w.length]),le=u.useCallback((W,X)=>{b.push({actionKind:"move",label:X,snapshot:W})},[b]),Ie=u.useCallback(()=>{if(S.selectedNavAffordance==="route_in_tree"&&S.selectedNavTargetPath){if(d){d(S.selectedNavTargetPath);return}y({type:"SELECT_ROUTE",route:{path:S.selectedNavTargetPath,layoutName:null}})}},[S.selectedNavAffordance,S.selectedNavTargetPath,d,y]),dt=u.useCallback(()=>{const W=Eb(S.selectedBaseLayout,f.selectedRoute?.layoutName);W&&y({type:"ENTER_BASE_EDIT",layoutName:W})},[S.selectedBaseLayout,f.selectedRoute?.layoutName,y]),pt=u.useCallback(()=>{const W=S.selectedNode?.__source?.extensionId;W!=null&&y({type:"ENTER_EXTENSION_EDIT",extensionId:String(W)})},[S.selectedNode,y]),ot=u.useCallback(()=>{const W=S.selectedIterationSourcePath;W&&y({type:"ENTER_ITERATION_ITEM_EDIT",sourcePath:W})},[S.selectedIterationSourcePath,y]),Oe=u.useRef(null),He=u.useRef(null),Ye=u.useRef(null),Tt=u.useRef({colorScheme:"base",breakpoint:"base"}),Dt=Oe.current!==null?x.stack.some(W=>W.id===Oe.current):!1,Nt=u.useMemo(()=>zd(f.routeTree,h),[f.routeTree,h]),xn=u.useMemo(()=>Md(v?.document?.raw),[v?.document?.raw]),wn=u.useMemo(()=>Ld(s),[s?.states]),Zt=u.useMemo(()=>{const W=v?.document?.raw,X=Af(W?.components),R=W?.initIsolated,de=R&&typeof R=="object"&&!Array.isArray(R)?Object.keys(R):[];return eA(X,de)},[v?.document?.raw]),Hn=u.useMemo(()=>{const W=v?.document?.raw;return Af(W?.components).map(X=>X.scopeId).filter(X=>typeof X=="string"&&X.length>0)},[v?.document?.raw]),ln=Nd({raw:v?.document?.raw,spec:s}),Ii=u.useCallback((W,X)=>{if(!v)return;const R={children:Me.current.components},de=We(R,W);if(!de)return;Tt.current={colorScheme:f.previewColorScheme==="dark"?"dark":"base",breakpoint:Ur(f.previewDevice,de,f.previewCustomWidth)};const ye=t?.getBoundingClientRect(),we=A&&ye?{left:ye.left+A.left,top:ye.top+A.top,width:A.width,height:A.height}:void 0,Te=re,ke=W.find(et),xe=ke?pe(ke.responsive):null,Ee=W.filter(kn=>typeof kn=="number"),Fe=cb({children:Me.current.components},Ee,ub(ln)),zt=Fe.length>0?[...ji({iterationVars:Fe}),...ln]:ln,gt=(kn,lM)=>u.createElement(ET,{key:`pem-${at(He.current??[])}`,node:kn,spec:s,manifest:Me.current.manifest,t:h,permissionCandidates:a,pageCandidates:Nt,dataSourceCandidates:xn,stateKeyCandidates:wn,bindingCandidates:zt,liveElement:Te,templateIdentifier:f.templateIdentifier,initialTab:lM,branchLabel:xe,isolatedScopeIdCandidates:Zt,usedScopeIds:Hn,onSaveInjectedProps:async(bt,Sn)=>{const Ai=typeof kn.id=="string"?kn.id:"",Fn=await HT(f.templateIdentifier,bt,Ai,Sn);if(st({op:"save",layoutName:`extension:${bt}`,editMode:f.editMode,saveTarget:"layout_extension",endpoint:`/api/admin/templates/${f.templateIdentifier}/layout-extensions/${bt}`,isDirty:!0,timestamp:Date.now()}),Fn.kind!=="success")throw new Error(Fn.kind==="conflict"?h("layout_editor.save.conflict"):Fn.kind==="injection_not_found"?"injection not found":Fn.kind==="not_found"?"extension not found":Fn.message??"save failed")},scope:Tt.current,onScopeChange:bt=>{Tt.current=bt;const Sn=Oe.current;Sn&&x.open({id:Sn,ariaLabel:h("layout_editor.property_modal.title"),width:420,draggable:!0,avoidRect:we,content:gt(kn),onClose:()=>{Oe.current=null,He.current=null}})},onPatchNode:bt=>{let Sn=[];v.patchLayout(Fn=>(Sn=Ot({children:Fn},W,()=>bt).children??[],Sn)),b.push({actionKind:"inline_text_edit",label:"edit_props",snapshot:Sn}),sr({source:"style_control",componentPath:at(W),componentName:typeof bt.name=="string"?bt.name:null,patchKey:null,timestamp:Date.now()});const Ai=Oe.current;Ai&&x.open({id:Ai,ariaLabel:h("layout_editor.property_modal.title"),width:420,draggable:!0,avoidRect:we,content:gt(bt),onClose:()=>{Oe.current=null,He.current=null}})},onDelete:()=>{const bt=Oe.current;bt&&x.close(bt),Ne()},onClose:()=>{const bt=Oe.current;bt&&x.close(bt)}});He.current=W;const Mt=x.open({ariaLabel:h("layout_editor.property_modal.title"),width:420,draggable:!0,avoidRect:we,content:gt(de,X),onClose:()=>{Oe.current=null,He.current=null,Ye.current=null}});Oe.current=Mt,Ye.current=kn=>{x.open({id:Mt,ariaLabel:h("layout_editor.property_modal.title"),width:420,draggable:!0,avoidRect:we,content:gt(kn),onClose:()=>{Oe.current=null,He.current=null,Ye.current=null}})}},[v,s,h,a,Nt,xn,wn,ln,re,b,x,Ne,t,A,f.previewColorScheme,f.previewDevice,f.previewCustomWidth,pe]);u.useEffect(()=>{const W=Ye.current,X=He.current;if(!W||!X)return;const R={children:Me.current.components},de=We(R,X);de?W(de):Oe.current&&x.close(Oe.current)},[w]);const Uz=()=>{if(!Dt)return null;const X={position:"absolute",background:"rgba(15, 23, 42, 0.45)",pointerEvents:"auto",zIndex:f7},R=ke=>{ke.preventDefault(),ke.stopPropagation()};if(!A)return i.jsx("div",{"data-testid":"g7le-edit-lock-full",onClick:R,onMouseMove:R,style:{...X,inset:0}});const{left:de,top:ye,width:we,height:Te}=A;return i.jsxs("div",{"data-testid":"g7le-edit-lock",style:{position:"absolute",inset:0,pointerEvents:"none"},children:[i.jsx("div",{"data-testid":"g7le-edit-lock-top",onClick:R,onMouseMove:R,style:{...X,left:0,top:0,right:0,height:Math.max(0,ye)}}),i.jsx("div",{"data-testid":"g7le-edit-lock-bottom",onClick:R,onMouseMove:R,style:{...X,left:0,top:ye+Te,right:0,bottom:0}}),i.jsx("div",{"data-testid":"g7le-edit-lock-left",onClick:R,onMouseMove:R,style:{...X,left:0,top:ye,width:Math.max(0,de),height:Te}}),i.jsx("div",{"data-testid":"g7le-edit-lock-right",onClick:R,onMouseMove:R,style:{...X,left:de+we,top:ye,right:0,height:Te}})]})},ml=u.useCallback(()=>{if(U&&_p(S.selectedLockKind)){if(p&&S.selectedPath){p(S.selectedPath);return}Ii(U)}},[U,S.selectedPath,S.selectedLockKind,p,Ii]),{scale:vl}=m,_l=typeof S.selectedNode?.name=="string"?S.selectedNode.name:"",Bh=s?.componentCapabilities?.[_l]??null,Wh=Array.isArray(Bh?.styleControls)?Bh.styleControls:[],qz=Wh.includes("width")?Ct(s,"width"):null,Gz=Wh.includes("height")?Ct(s,"height"):null,Yz=u.useCallback((W,X)=>{if(!v||!U)return;let R=[];v.patchLayout(de=>(R=Ot({children:de},U,()=>W).children??[],R)),sr({source:"resize",componentPath:at(U),componentName:_l||null,patchKey:X==="height"?"height":"width",resizeAxis:X,timestamp:Date.now()})},[v,U,_l]),Xz=u.useCallback((W,X)=>{if(!v||!U)return;let R=[];v.patchLayout(de=>(R=Ot({children:de},U,()=>W).children??[],R)),b.push({actionKind:"inline_text_edit",label:`resize ${X}`,snapshot:R})},[v,U,b]),Jz=u.useCallback(()=>{if(!re)return null;const W=re.getBoundingClientRect(),X=vl||1;return{width:W.width/X,height:W.height/X}},[re,vl]),ir=GT({node:S.selectedNode,widthControl:qz,heightControl:Gz,scale:vl,measureStartSize:Jz,onResize:Yz,onResizeEnd:Xz}),Zz=u.useCallback((W,X)=>{ir.onHandlePointerDown(W,X)},[ir]),xl=u.useCallback(()=>{const W=b.undo();!W||!v||v.setLayoutComponents(W.snapshot)},[b,v]),wl=u.useCallback(()=>{const W=b.redo();!W||!v||v.setLayoutComponents(W.snapshot)},[b,v]);u7({onUndo:xl,onRedo:wl});const Qz=u.useMemo(()=>({copy:oe,cut:ue,paste:J,delete:Ne,openProps:ml,selectParent:Z?se:void 0,deselect:S.clearSelection}),[oe,ue,J,Ne,ml,Z,se,S.clearSelection]);np({handlers:Qz,hasSelection:!!S.selectedPath}),u.useEffect(()=>(window.__g7LayoutEditorHasSelection=!!S.selectedPath,()=>{try{delete window.__g7LayoutEditorHasSelection}catch{}}),[S.selectedPath]),u.useEffect(()=>(window.__g7LayoutEditorHistory={undo:xl,redo:wl,canUndo:b.canUndo,canRedo:b.canRedo},()=>{try{delete window.__g7LayoutEditorHistory}catch{}}),[xl,wl,b.canUndo,b.canRedo]);const Rz=u.useCallback(W=>{const X=P;F(null),X&&(async()=>{if((await I.commit(X.path,W)).kind==="created"&&v){const de=v.document?.raw?.components??[];b.push({actionKind:"inline_text_edit",label:"inline_create_key",snapshot:de})}})()},[P,I,v,b]),jh=u.useCallback(()=>{const W=P;F(null),I.trackCancel(W?.path??null)},[P,I]),eM=u.useCallback(()=>{F(null)},[]),tM=u.useCallback(async W=>{const X=P;if(!X)return null;const R=await I.keyifyChipValue(X.path,W);if(R.kind!=="created"||!R.translationKey)return null;const de=v?.document?.raw?.components??[];return b.push({actionKind:"inline_text_edit",label:"inline_keyify_chip",snapshot:de}),R.translationKey},[P,I,v,b]),nM=u.useCallback(()=>{const W=P;W&&(F(null),S.handleSelect("",{dataset:{editorPath:W.domPath}}),Ii(W.path,"translation"))},[P,S,Ii]),xt=u.useMemo(()=>{if(!P)return null;const W=v?.document?.raw?.components??w;return We({children:W},P.path)},[P,v?.document,w]),oM=u.useCallback(async(W,X)=>{const R=P;if(!v||!R)return null;const de=typeof xt?.text=="string"?xt.text:"";let ye;if(R.isParamKey)ye=await wr(f.templateIdentifier,f.locale,de,W,X.sourceId,X.path,"scalar");else{const Fe=zt=>zt.replace(/\$t:[a-zA-Z0-9._-]+/g,gt=>{const Mt=h(gt.slice(3));return Mt&&Mt!==gt.slice(3)&&!Mt.startsWith("$t:")?Mt:""}).replace(/\s+/g," ").trim();ye=await ls(f.templateIdentifier,f.selectedRoute?.layoutName??null,f.locale,de,W,X.sourceId,X.path,"scalar",Fe,h)}if(ye.kind==="error")return null;const we=R.path;let Te=[];v.patchLayout(Fe=>(Te=Ot({children:Fe},we,Mt=>({...Mt,text:ye.text})).children??[],Te)),b.push({actionKind:"inline_text_edit",label:"inline_insert_binding",snapshot:Te});const ke=ye.kind==="ok"&&"key"in ye?ye.key:void 0;!R.isParamKey&&ke&&F(Fe=>Fe&&Fe.path===we?{...Fe,isParamKey:!0,customKey:ke,chipValue:void 0,chipParamLabels:void 0}:Fe);try{window.dispatchEvent(new CustomEvent(kt,{detail:{templateIdentifier:f.templateIdentifier,locale:f.locale}}))}catch{}const xe=mt(ye.text),Ee=R.customKey??xe?.key??"";return Ee?It(Ee,f.locale)??null:null},[v,P,xt,f.templateIdentifier,f.locale,f.selectedRoute,b,h]),rM=u.useCallback(async W=>{const X=P;if(!v||!X)return null;const R=typeof xt?.text=="string"?xt.text:"",de=mt(R),ye=X.customKey??de?.key??null,we=mo(R,W),Te=X.path;let ke=[];return v.patchLayout(xe=>(ke=Ot({children:xe},Te,zt=>({...zt,text:we})).children??[],ke)),b.push({actionKind:"inline_text_edit",label:"inline_remove_binding",snapshot:ke}),ye&&await kr(f.templateIdentifier,ye,W,f.locale),ye?It(ye,f.locale)??null:null},[v,P,xt,f.templateIdentifier,f.locale,b]),[kl,Hh]=u.useState({}),iM=["fontSize","color","fontStyle","textDecoration","textAlign","letterSpacing","lineHeight","fontFamily"];u.useEffect(()=>{if(!P||!t||typeof MutationObserver>"u"){Hh({});return}const W=`[data-editor-path="${an(P.domPath)}"]`,X=()=>{const ye=t.querySelector(W);if(!ye)return;const we={};for(const ke of iM){const xe=ye.style.getPropertyValue(ke.replace(/([A-Z])/g,"-$1").toLowerCase());xe&&(we[ke]=xe)}const Te=yg(t,P.domPath)??void 0;Hh({className:ye.className,style:we,effectiveColor:Te})};X();const R=t.querySelector(W);if(!R)return;const de=new MutationObserver(X);return de.observe(R,{attributes:!0,attributeFilter:["class","style"]}),de.observe(t,{childList:!0,subtree:!0}),()=>de.disconnect()},[P?.path?at(P.path):null,t]);const Fh=u.useCallback((W,X)=>{if(!v||!P)return;const R=P.path;let de=[],ye=null;v.patchLayout(we=>(de=Ot({children:we},R,xe=>{const Ee=X(xe);return ye=typeof Ee.name=="string"?Ee.name:null,Ee}).children??[],de)),b.push({actionKind:"inline_text_edit",label:`inline_format ${W}`,snapshot:de}),sr({source:"style_control",componentPath:at(R),componentName:ye,patchKey:W,timestamp:Date.now()})},[v,P,b]),ft=u.useMemo(()=>{const W=S.selectedPath;if(!W||!_)return null;const X=[];let R=W;for(;R;){X.push(R);const de=R.match(/^(.*)\.children\.\d+$/);R=de?de[1]:null}for(const de of X){const ye=Ze(de);if(!ye)continue;const we=We(_,ye),Te=typeof we?.name=="string"?we.name:null;if(!Te)continue;const ke=Oi(s,Te),xe=ke?.canvasOverlay?.kind;if(typeof xe!="string"||!xe||!we)continue;const Ee=ke.canvasOverlay.params&&typeof ke.canvasOverlay.params=="object"?ke.canvasOverlay.params:void 0,Fe=de===W?null:W.slice(de.length+1);return{kind:xe,params:Ee,tablePath:de,tableNode:we,selectedCellRel:Fe}}return null},[S.selectedPath,_,s]),ho=ft?FT(ft.kind):null,Kh=u.useMemo(()=>!ho||!t||!ft?null:po(t,ft.tablePath),[ho,t,ft,A,w]),sM=u.useMemo(()=>{if(!ho||!t||!ft)return[];const W=ft.tablePath,X=an(W),R=[];return t.querySelectorAll(`[data-editor-path^="${X}.children."]`).forEach(we=>{const Te=we.dataset.editorPath??"";if(!Te.startsWith(W+"."))return;const ke=Te.slice(W.length+1),xe=so(we,t);xe&&R.push({path:ke,top:xe.top,left:xe.left,width:xe.width,height:xe.height})}),t.querySelectorAll(`[data-editor-item-path^="${X}."]`).forEach(we=>{const Te=we.dataset.editorItemPath??"";if(!Te.startsWith(W+"."))return;const ke=Te.slice(W.length+1),xe=so(we,t);xe&&R.push({path:ke,top:xe.top,left:xe.left,width:xe.width,height:xe.height})}),R},[ho,t,ft,A,w]),aM=u.useCallback(W=>{const X=ft?Ze(ft.tablePath):null;if(!v||!X)return;let R=[];v.patchLayout(de=>(R=Ot({children:de},X,()=>W).children??[],R)),b.push({actionKind:"inline_text_edit",label:"inplace_edit",snapshot:R}),sr({source:"style_control",componentPath:ft?.tablePath??"",componentName:typeof W.name=="string"?W.name:null,patchKey:"canvas_inplace",timestamp:Date.now()})},[v,U,b]);return t?i.jsxs("div",{className:"g7le-editor-canvas-overlay","data-testid":"g7le-editor-canvas-overlay",style:{position:"absolute",inset:0,pointerEvents:"none"},children:[!D&&Uz(),D&&i.jsxs("div",{"data-testid":"g7le-canvas-pick-banner",style:{position:"absolute",top:8,left:"50%",transform:"translateX(-50%)",zIndex:9999,display:"flex",alignItems:"center",gap:12,padding:"8px 14px",background:"#1e293b",color:"#fff",borderRadius:8,fontSize:13,boxShadow:"0 4px 12px rgba(0,0,0,0.25)",pointerEvents:"auto"},children:[i.jsxs("span",{children:["🎯 ",h("layout_editor.target_picker.canvas_pick_hint")]}),i.jsx("button",{type:"button","data-testid":"g7le-canvas-pick-cancel",onClick:()=>Y(D,null),style:{border:"1px solid #475569",borderRadius:6,background:"transparent",color:"#cbd5e1",cursor:"pointer",fontSize:12,padding:"3px 10px"},children:h("layout_editor.target_picker.cancel")})]}),f.editMode!=="route"&&i.jsx(EI,{frameEl:t,components:w,editMode:f.editMode,currentExtensionId:C,editableRootPath:E}),P&&((P.isParamKey&&P.customKey||P.chipValue)&&xt?i.jsxs(i.Fragment,{children:[xt&&i.jsx(fg,{node:xt,spec:s,t:h,onApplyControl:Fh,box:P.box,scope:{colorScheme:f.previewColorScheme==="dark"?"dark":"base",breakpoint:Ur(f.previewDevice,xt,f.previewCustomWidth)}}),i.jsx(i4,{box:P.box,node:xt,customKey:P.customKey??null,initialChipValue:P.chipValue,chipParamLabels:P.chipParamLabels,onKeyify:tM,templateIdentifier:f.templateIdentifier,locale:f.locale,t:h,candidates:ln,onInsertBinding:oM,onRemoveBinding:rM,onCommit:eM,onCancel:jh})]}):i.jsxs(i.Fragment,{children:[xt&&i.jsx(fg,{node:xt,spec:s,t:h,onApplyControl:Fh,box:P.box,scope:{colorScheme:f.previewColorScheme==="dark"?"dark":"base",breakpoint:xt?Ur(f.previewDevice,xt,f.previewCustomWidth):"base"}}),i.jsx(r4,{box:P.box,initialValue:P.initialValue,isCustomKey:P.isCustomKey,t:h,onCommit:Rz,onCancel:jh,mirrorClassName:kl.className,mirrorStyle:kl.style,nodeEffectiveColor:kl.effectiveColor??P.nodeEffectiveColor,onOpenTranslations:nM})]})),!D&&i.jsx(v7,{hoverBox:T,selectedBox:A,lockKind:S.selectedLockKind,navAffordance:S.selectedNavAffordance,onEditProps:ml,onDuplicate:Ae,onDelete:Ne,onSeparateBranch:Le?.mode==="separate"?q:void 0,separateBranchLabel:$e?.separate,onMergeBranch:Le?.mode==="merge"?ae:void 0,mergeBranchLabel:$e?.merge,definedDeviceBranches:be,onJumpToDevice:be.length>0?j:void 0,onLinkEditDestination:Ie,onEditBase:dt,onEditExtension:pt,extensionLabel:ze,baseLayoutLabel:S.selectedBaseLayout,dataSourceLabel:S.selectedDataSourceId,branchLabel:ee,onEditIteration:S.selectedIsIteration&&f.editMode!=="iteration_item"?ot:void 0,resizeEnabledAxes:ir.enabledAxes,onResizeHandlePointerDown:ir.enabledAxes.width||ir.enabledAxes.height?Zz:void 0,selectedName:Ce,onSelectParent:Z?se:void 0}),D&&B&&i.jsx("div",{"data-testid":"g7le-canvas-pick-hover","data-pick-has-id":B.hasId?"true":"false",style:{position:"absolute",left:B.box.left,top:B.box.top,width:B.box.width,height:B.box.height,pointerEvents:"none",zIndex:9998,boxSizing:"border-box",border:B.hasId?"2px solid #2563eb":"2px dashed #94a3b8",background:B.hasId?"rgba(37,99,235,0.10)":"repeating-linear-gradient(45deg, rgba(148,163,184,0.18) 0, rgba(148,163,184,0.18) 6px, transparent 6px, transparent 12px)",cursor:B.hasId?"pointer":"not-allowed"},children:!B.hasId&&i.jsx("span",{"data-testid":"g7le-canvas-pick-hover-hint",style:{position:"absolute",top:0,left:0,transform:"translateY(-100%)",background:"#475569",color:"#fff",fontSize:11,lineHeight:1.4,padding:"2px 6px",borderRadius:4,whiteSpace:"nowrap"},children:h("layout_editor.target_picker.needs_id")})}),!D&&i.jsx(C7,{selectedBox:qe,points:Se.points,onAddRequest:Re}),ho&&ft&&Kh&&S.selectedLockKind==="none"&&i.jsx(ho,{node:ft.tableNode,params:ft.params,nodeBox:Kh,cellBoxes:sM,selectedCellPath:ft.selectedCellRel??void 0,colorScheme:f.previewColorScheme==="dark"?"dark":"light",t:h,onPatchNode:aM,onInsertChild:ge,onRemoveChild:W=>{const X=Ze(W);if(!v||!X)return;let R=[];v.patchLayout(de=>(R=Ri({children:de},X).children??[],R)),b.push({actionKind:"remove",label:"inplace_remove",snapshot:R})},onRequestInlineEdit:W=>{ft&&G(`${ft.tablePath}.${W}`)}}),v&&i.jsx(xI,{frameEl:t,nesting:o,editMode:f.editMode,currentExtensionId:C,editableRootPath:E,components:w,patchLayout:v.patchLayout,pushHistory:le,selectedPath:S.selectedPath,onSelectPath:W=>S.handleSelect("",{dataset:{editorPath:W}}),onMovePath:W=>S.handleSelect("",{dataset:{editorPath:W}}),onRequestInlineEdit:G})]}):null}function hg(e,t){if(t.length===0)return null;const o=Ha({children:e},t);return o&&typeof o.name=="string"?o.name:null}function Ha(e,t){return We(e,t)}function an(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/[^a-zA-Z0-9_\-.]/g,t=>`\\${t}`)}function yg(e,t){if(!t)return null;const n=e.querySelector(`[data-editor-path="${an(t)}"]`);if(!n||typeof window.getComputedStyle!="function")return null;let o=n;const r=n.ownerDocument.createTreeWalker(n,NodeFilter.SHOW_TEXT);let s=r.nextNode();for(;s;){if((s.textContent??"").trim().length>0){const a=s.parentElement;if(a&&n.contains(a)){o=a;break}}s=r.nextNode()}try{return window.getComputedStyle(o).color||null}catch{return null}}function po(e,t){if(!t)return null;const n=e.querySelector(`[data-editor-path="${an(t)}"]`);if(n){const c=so(n,e);return c&&ao(c,e)?c:null}const o=e.querySelectorAll(`[data-editor-path^="${an(t)}.iteration."]`);let r=1/0,s=1/0,a=-1/0,l=-1/0,d=!1;return o.forEach(c=>{const p=c.dataset.editorPath??"";if(!new RegExp("\\.iteration\\.\\d+$").test(p))return;const f=so(c,e);f&&ao(f,e)&&(d=!0,r=Math.min(r,f.left),s=Math.min(s,f.top),a=Math.max(a,f.left+f.width),l=Math.max(l,f.top+f.height))}),d?{left:r,top:s,width:a-r,height:l-s,scale:1}:null}function f4({isEditMode:e,editorSpec:t,sampleOverride:n}){const o=t?.sampleData;return u.useMemo(()=>Pm({spec:o,overrideSpec:n,onMatch:r=>{Uh(r)}}),[e,o,n])}const g4=Lt().ComponentRegistry;function h4(e){return e.split(/[-_]/).map(t=>t.charAt(0).toUpperCase()+t.slice(1).toLowerCase()).join("")}async function y4(e){const t=typeof window<"u"?window.localStorage?.getItem("auth_token"):null,n={Accept:"application/json"};t&&(n.Authorization=`Bearer ${t}`);const o=await fetch(`/api/admin/templates/${encodeURIComponent(e)}/editor-assets`,{headers:n,credentials:"same-origin"});if(!o.ok){const s=await o.json().catch(()=>null);throw Gr(o.status,s,"assets")}const r=await o.json();return r.data||r}async function b4(e){try{if(typeof fetch!="function")return 0;const t=await fetch(en(`/api/templates/${encodeURIComponent(e)}/config`,"json"),{credentials:"same-origin",headers:{Accept:"application/json"}});if(!t.ok)return 0;const n=await t.json().catch(()=>null),o=n?.data?.cache_version??n?.cache_version;return typeof o=="number"&&o>0?o:0}catch{return 0}}function m4(e){return new Promise((t,n)=>{if(typeof document>"u"){n(new Error("document undefined"));return}if(document.querySelector(`script[data-g7le-asset="${e}"]`)){t();return}const r=document.createElement("script");r.src=e,r.async=!1,r.setAttribute("data-g7le-asset",e),r.addEventListener("load",()=>t()),r.addEventListener("error",()=>n(new Error(`script load failed: ${e}`))),document.head.appendChild(r)})}async function v4(e){if(typeof document>"u")return;const t=`[data-g7le-asset="${e}"]`;if(document.querySelector(`link${t}, style${t}`))return;if(e.includes("/api/admin/"))try{const r=typeof window<"u"?window.localStorage?.getItem("auth_token"):null,s={Accept:"text/css"};r&&(s.Authorization=`Bearer ${r}`);const a=await fetch(e,{headers:s,credentials:"same-origin"});if(a.ok){const l=await a.text(),d=document.createElement("style");d.textContent=l,d.setAttribute("data-g7le-asset",e),document.head.appendChild(d);return}}catch{}const o=document.createElement("link");o.rel="stylesheet",o.href=e,o.setAttribute("data-g7le-asset",e),document.head.appendChild(o)}function _4(e,t,n="user"){const[o,r]=u.useState({componentRegistry:null,translationEngine:null,isReady:!1,error:null});return u.useEffect(()=>{let s=!1;return(async()=>{r(a=>({...a,isReady:!1,error:null}));try{const a=await y4(e);if(s)return;for(const y of a.css??[])if(await v4(y),s)return;const l=h4(e);if(!(typeof window<"u"&&typeof window[l]=="object")){for(const y of a.js??[])if(await m4(y),s)return}const c=g4.createIsolatedInstance();if(await c.loadComponents(e,n),s)return;const p=await b4(e);if(s)return;const f=new Pt({defaultLocale:t});if(p>0&&f.setCacheVersion(p),await f.loadTranslations(e,t),s)return;cd(f,e);try{const y=Pt.getInstance();p>y.getCacheVersion()&&y.setCacheVersion(p),await y.loadTranslations(e,t),cd(y,e)}catch{}if(s)return;r({componentRegistry:c,translationEngine:f,isReady:!0,error:null})}catch(a){if(s)return;const l=hp(a)?a:io(a,"assets");r({componentRegistry:null,translationEngine:null,isReady:!1,error:l})}})(),()=>{s=!0}},[e,t,n]),o}const bg=Lt().AuthManager;function x4(e){switch(e){case"unauthorized":return{icon:"🔒",tone:"blue",titleKey:"layout_editor.access_error.unauthorized.title",messageKey:"layout_editor.access_error.unauthorized.message",showRequiredPermissions:!0};case"forbidden":return{icon:"⛔",tone:"rose",titleKey:"layout_editor.access_error.forbidden.title",messageKey:"layout_editor.access_error.forbidden.message",showRequiredPermissions:!0};case"not_found":return{icon:"🗂️",tone:"slate",titleKey:"layout_editor.access_error.not_found.title",messageKey:"layout_editor.access_error.not_found.message",showRequiredPermissions:!1};case"server_error":return{icon:"🛠️",tone:"amber",titleKey:"layout_editor.access_error.server_error.title",messageKey:"layout_editor.access_error.server_error.message",showRequiredPermissions:!1};case"network":return{icon:"📡",tone:"amber",titleKey:"layout_editor.access_error.network.title",messageKey:"layout_editor.access_error.network.message",showRequiredPermissions:!1};default:return{icon:"⚠️",tone:"slate",titleKey:"layout_editor.access_error.unknown.title",messageKey:"layout_editor.access_error.unknown.message",showRequiredPermissions:!1}}}const w4={blue:{bg:"#eff6ff",border:"#bfdbfe",iconBg:"#dbeafe"},rose:{bg:"#fff1f2",border:"#fecdd3",iconBg:"#ffe4e6"},amber:{bg:"#fffbeb",border:"#fde68a",iconBg:"#fef3c7"},slate:{bg:"#f8fafc",border:"#e2e8f0",iconBg:"#f1f5f9"}};function k4({error:e}){return u.useEffect(()=>{if(e.kind!=="unauthorized"||typeof window>"u")return;const t=bg.getInstance(),n=`${window.location.pathname}${window.location.search}`,o=t.getLoginRedirectUrl("admin",n,"session_expired"),r=window.setTimeout(()=>{window.location.href=o},600);return()=>window.clearTimeout(r)},[e.kind]),null}function Fa({error:e}){const{t}=tt(),n=x4(e.kind),o=w4[n.tone],r=()=>{typeof window<"u"&&(window.location.href="/admin")},s=()=>{typeof window<"u"&&window.location.reload()},a=()=>{if(typeof window>"u")return;const l=bg.getInstance(),d=`${window.location.pathname}${window.location.search}`;window.location.href=l.getLoginRedirectUrl("admin",d)};return i.jsxs("div",{className:"g7le-access-error","data-testid":"g7le-access-error","data-error-kind":e.kind,style:{flex:1,display:"flex",alignItems:"center",justifyContent:"center",padding:24,background:"#f1f5f9"},children:[i.jsx(k4,{error:e}),i.jsxs("div",{style:{maxWidth:480,width:"100%",background:o.bg,border:`1px solid ${o.border}`,borderRadius:12,padding:"28px 32px",boxShadow:"0 2px 8px rgba(15, 23, 42, 0.05)",textAlign:"center"},children:[i.jsx("div",{style:{width:64,height:64,margin:"0 auto 16px",borderRadius:"50%",background:o.iconBg,display:"flex",alignItems:"center",justifyContent:"center",fontSize:32,lineHeight:1},"aria-hidden":"true",children:n.icon}),i.jsx("h2",{"data-testid":"g7le-access-error-title",style:{margin:"0 0 8px",fontSize:18,fontWeight:700,color:"#0f172a"},children:t(n.titleKey)}),i.jsx("p",{"data-testid":"g7le-access-error-message",style:{margin:"0 0 16px",fontSize:13,lineHeight:1.6,color:"#475569"},children:t(n.messageKey)}),n.showRequiredPermissions&&e.requiredPermissions&&i.jsxs("div",{"data-testid":"g7le-access-error-permissions",style:{display:"inline-flex",flexWrap:"wrap",gap:6,justifyContent:"center",padding:"8px 12px",marginBottom:16,background:"rgba(15, 23, 42, 0.04)",borderRadius:8,fontSize:12,color:"#475569"},children:[i.jsx("span",{style:{fontWeight:600},children:t("layout_editor.access_error.required_permission_label")}),e.requiredPermissions.split(/[,\s]+/).filter(Boolean).map(l=>i.jsx("code",{style:{padding:"2px 6px",background:"#fff",border:"1px solid #e2e8f0",borderRadius:4,fontFamily:"ui-monospace, SFMono-Regular, Menlo, monospace",fontSize:11,color:"#1e293b"},children:l},l))]}),e.message&&i.jsxs("details",{"data-testid":"g7le-access-error-detail",style:{marginBottom:16,fontSize:11,color:"#94a3b8"},children:[i.jsx("summary",{style:{cursor:"pointer"},children:t("layout_editor.access_error.detail_summary")}),i.jsxs("pre",{style:{marginTop:8,padding:8,background:"#fff",border:"1px solid #e2e8f0",borderRadius:6,overflowX:"auto",whiteSpace:"pre-wrap",wordBreak:"break-word",textAlign:"left",fontSize:11,color:"#475569"},children:[e.status>0?`HTTP ${e.status} -`:"",e.message]})]}),i.jsxs("div",{style:{display:"flex",justifyContent:"center",gap:8,flexWrap:"wrap"},children:[e.kind==="unauthorized"&&i.jsx("button",{type:"button","data-testid":"g7le-access-error-action-signin",onClick:a,style:Ka,children:t("layout_editor.access_error.action.sign_in")}),e.kind==="forbidden"&&i.jsx("button",{type:"button","data-testid":"g7le-access-error-action-home",onClick:r,style:Ka,children:t("layout_editor.access_error.action.go_home")}),(e.kind==="not_found"||e.kind==="server_error"||e.kind==="network"||e.kind==="unknown")&&i.jsx("button",{type:"button","data-testid":"g7le-access-error-action-retry",onClick:s,style:Ka,children:t("layout_editor.access_error.action.retry")}),e.kind!=="unauthorized"&&i.jsx("button",{type:"button","data-testid":"g7le-access-error-action-home-secondary",onClick:r,style:S4,children:t("layout_editor.access_error.action.go_admin_home")})]})]})]})}const Ka={padding:"8px 16px",background:"#2563eb",color:"#fff",border:"1px solid #1d4ed8",borderRadius:6,fontSize:13,fontWeight:600,cursor:"pointer"},S4={padding:"8px 16px",background:"#fff",color:"#475569",border:"1px solid #cbd5e1",borderRadius:6,fontSize:13,fontWeight:500,cursor:"pointer"};function C4(e){const t=window;if(typeof t>"u")return{getSnapshot:()=>({globalState:{},localState:{}}),restore:()=>{}};const n=t.G7Core||{},o={templateApp:t.__templateApp,g7CoreState:n.state,g7CoreDispatch:n.dispatch,g7CoreData:n.data,g7CoreModal:n.modal,g7CoreToast:n.toast};let r={...e.initialGlobalState??{}};r._local||(r._local={});const s=[],a=()=>{const c={globalState:{...r},localState:{...r._local??{}}};for(const p of s)try{p(r)}catch{}e.onChange?.(c)},l={},d={getGlobalState:()=>r,setGlobalState:(c,p)=>{typeof c=="function"?r=c(r):r={...r,...c},a()},onGlobalStateChange:c=>(s.push(c),()=>{const p=s.indexOf(c);p>=0&&s.splice(p,1)}),get globalState(){return r},getActionDispatcher:()=>e.actionDispatcher,getDataSource:c=>l[c]??null,setDataSource:(c,p)=>{l[c]=p},refetchDataSource:async c=>null,updateDataSourceItem:(c,p,f)=>l[c]??null,getLocale:()=>e.locale,changeLocale:c=>{},getRouter:()=>({navigate:()=>{},replace:()=>{},push:()=>{}}),updateQueryParams:()=>{}};return t.__templateApp=d,n&&typeof n.dispatch=="function"&&(n.dispatch=(c,p)=>{try{return e.actionDispatcher.executeAction(c,p??{})}catch{return}}),n&&typeof n.modal=="object"&&n.modal!==null&&(n.modal={...n.modal,open:()=>{},close:()=>{},closeAll:()=>{}}),n&&typeof n.toast=="object"&&n.toast!==null&&(n.toast={...n.toast,push:()=>{},dismiss:()=>{}}),{getSnapshot:()=>({globalState:{...r},localState:{...r._local??{}}}),restore:()=>{t.__templateApp===d&&(t.__templateApp=o.templateApp),t.G7Core&&(o.g7CoreState!==void 0&&(t.G7Core.state=o.g7CoreState),o.g7CoreDispatch!==void 0&&(t.G7Core.dispatch=o.g7CoreDispatch),o.g7CoreData!==void 0&&(t.G7Core.data=o.g7CoreData),o.g7CoreModal!==void 0&&(t.G7Core.modal=o.g7CoreModal),o.g7CoreToast!==void 0&&(t.G7Core.toast=o.g7CoreToast)),s.length=0}}}const $4=new Set(["id","userId","postId","orderId","productId","categoryId","commentId","noticeId","inquiryId","addressId","wishlistId","notificationId","roleId","menuId"]);function E4(e){if(!e)return{};const t={},n=/:([a-zA-Z_][a-zA-Z0-9_]*)/g;let o;for(;(o=n.exec(e))!==null;){const r=o[1];t[r]=I4(r)}return t}function I4(e){return $4.has(e)||/Id$|_id$/.test(e)?"1":"sample"}const A4=bo("LayoutEditor");function Jo(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function bi(e){if(Array.isArray(e))return e.map(t=>bi(t));if(Jo(e)){const t={};for(const[n,o]of Object.entries(e))t[n]=bi(o);return t}return e}function mg(e,t="",n=new Set){for(const[o,r]of Object.entries(e)){const s=t?`${t}.${o}`:o;Jo(r)?mg(r,s,n):n.add(s)}return n}function vg(e,t,n,o,r,s=""){for(const[a,l]of Object.entries(t)){const d=s?`${s}.${a}`:a;if(n.has(d)){r(`[LayoutEditor] sampleGlobal key conflict: extension '${o}' override of core key '${d}' ignored`);continue}const c=e[a];Jo(l)&&Jo(c)?vg(c,l,n,o,r,d):e[a]=bi(l)}}function Va(e){const t=e.warn??(r=>A4.warn(r)),n=bi(e.coreSeed??{});e.isGuestOnly&&"currentUser"in n&&delete n.currentUser;const o=mg(n);for(const r of e.sources)Jo(r.sampleGlobal)&&vg(n,r.sampleGlobal,o,r.id,t);return e.isGuestOnly&&"currentUser"in n&&delete n.currentUser,n}function T4(e){const t={};if(!e||typeof e!="object"||Array.isArray(e))return t;for(const[n,o]of Object.entries(e))n.startsWith("$")&&(t[n]=o);return t}function D4(e){const t={};if(!e||typeof e!="object"||Array.isArray(e))return t;for(const[n,o]of Object.entries(e))n.startsWith("$")||(t[n]=o);return t}function N4(e){if(typeof e!="string")return null;const t=/^\s*\{\{\s*([\s\S]*?)\s*\}\}\s*$/.exec(e);if(!t)return null;let n=t[1];const o=n.indexOf("??");return o>=0&&(n=n.slice(0,o)),n=n.replace(/\?\./g,".").replace(/\s+/g,""),n===""||!/^[A-Za-z_$][A-Za-z0-9_$]*(\.[A-Za-z_$][A-Za-z0-9_$]*)*$/.test(n)?null:n.split(".")}function z4(e,t){const n=N4(t);if(!n||n.length===0)return e;let o=e;for(let a=0;ao.map(r=>{if(!r||typeof r!="object")return r;const s=r;let a=s;if(typeof s.slot=="string"&&!t.has(s.slot)){const{slot:l,...d}=s;a={...d,__editorSlotName:l}}if(Array.isArray(a.children)){const l=n(a.children);l!==a.children&&(a={...a,children:l})}return a});return n(e)}function St(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Xt(e){if(Array.isArray(e))return e.map(t=>Xt(t));if(St(e)){const t={};for(const[n,o]of Object.entries(e))t[n]=Xt(o);return t}return e}function mi(e,t){for(const[n,o]of Object.entries(t)){const r=e[n];St(o)&&St(r)?mi(r,o):e[n]=Xt(o)}}function P4(e){const t=[];let n="";for(let o=0;o0&&(t.push(n),n="");const s=e[o+1];if(s==="'"||s==='"'){const l=e.indexOf(`${s}]`,o+2);if(l!==-1){t.push(e.slice(o+2,l)),o=l+1;continue}}const a=e.indexOf("]",o+1);if(a!==-1){t.push(e.slice(o+1,a)),o=a;continue}n+=r}else r==="."?n.length>0&&(t.push(n),n=""):n+=r}return n.length>0&&t.push(n),t.filter(o=>o.length>0)}function Ua(e,t,n){const o=P4(t);if(o.length===0)return;let r=e;for(let s=0;s0?t:void 0}const Ga="g7le:editor-t-ready",wg="data-g7le-vh-expanded";function B4(e,t){if(!e||!t)return;const n=t;e.querySelectorAll("*").forEach(r=>{const s=window.getComputedStyle(r),a=parseFloat(s.height),l=Number.isFinite(a)&&Math.abs(a-n)<=2,d=parseFloat(s.minHeight),c=Number.isFinite(d)&&Math.abs(d-n)<=2,p=s.overflowY==="auto"||s.overflowY==="scroll"||s.overflowY==="hidden"||s.overflow==="auto"||s.overflow==="scroll"||s.overflow==="hidden";l&&p?(r.style.setProperty("height","auto","important"),c&&r.style.setProperty("min-height","0","important"),r.style.setProperty("overflow","visible","important"),r.setAttribute(wg,"1")):(s.overflowY==="auto"||s.overflowY==="scroll")&&r.scrollHeight>r.clientHeight+4&&r.clientHeight>120&&(r.style.setProperty("overflow","visible","important"),r.style.setProperty("height","auto","important"),r.setAttribute(wg,"1"))})}const W4=[];function j4(e={}){const{manifest:t=null,nesting:n=null,componentPalette:o=null,spec:r=null,permissionCandidates:s,sampleGlobalSources:a=W4,resolveRouteMatch:l,onNavigateToDestination:d,onSessionAddedPathsChange:c}=e,{state:p}=Je(),f=Ft(),y=Cp(),{document:g,isLoading:m,error:h}=f??y,v=u.useRef(null),[b,x]=u.useState(null),{deviceWidth:k,scale:w,colorScheme:_}=ja(),C=u.useMemo(()=>p.activeStateId?p.availableStates.find(Q=>Q.id===p.activeStateId)??null:null,[p.activeStateId,p.availableStates]),E=u.useMemo(()=>xg(C),[C]),S=f4({isEditMode:!0,editorSpec:r??void 0,sampleOverride:E}),{t:T}=tt(),{componentRegistry:$,translationEngine:A,isReady:z,error:D}=_4(p.templateIdentifier,p.locale),O=u.useRef(null);O.current===null&&(O.current=new vd);const M=u.useRef(null);if(M.current===null){M.current=new VE({navigate:()=>{}}),M.current.setPreviewMode(!0);try{const ie=window.__templateApp?.getActionDispatcher?.();if(ie&&typeof ie.getRegisteredHandlers=="function"){const _e=ie.getRegisteredHandlers();for(const ge of _e){if(!ge.includes("."))continue;const Ae=typeof ie.getHandler=="function"?ie.getHandler(ge):void 0;typeof Ae=="function"&&M.current.registerHandler(ge,Ae,{category:"plugin",source:"preview-canvas-cloned-from-host"})}}}catch{}}u.useEffect(()=>{if(!z)return;const Q=M.current;if(Q)try{const ie=window.G7Core?.getActionDispatcher?.();if(!ie||typeof ie.getRegisteredHandlers!="function")return;const _e=ie.getRegisteredHandlers();for(const ge of _e){if(!ge.includes(".")||typeof Q.getHandler=="function"&&Q.getHandler(ge))continue;const Ae=typeof ie.getHandler=="function"?ie.getHandler(ge):void 0;typeof Ae=="function"&&Q.registerHandler(ge,Ae,{category:"plugin",source:"preview-canvas-iife-reclone"})}}catch{}},[z]);const B=u.useMemo(()=>new UE({sampleProvider:S,actionDispatcher:M.current}),[S]),N=u.useMemo(()=>g?.raw?.meta?.guest_only===!0,[g]),H=u.useMemo(()=>Va({sources:a,isGuestOnly:N}),[a,N]),L=u.useMemo(()=>{const Q=H4(qa(C),A,{templateId:p.templateIdentifier,locale:p.locale}),ie=H._local,{global:_e,local:ge}=O4({globalBaseline:H,localBaseline:ie??{},patch:C?.initialState??null,formErrors:Q});return{..._e,_local:ge}},[H,C,A,p.templateIdentifier,p.locale]),I=u.useMemo(()=>!C||!(!!C.initialState?.local||!!qa(C))?null:{...L._local??{},_forceLocalInit:C.id,_merge:"deep"},[C,L]),P=Q=>typeof Q=="object"&&Q!==null&&!Array.isArray(Q),F=u.useMemo(()=>P(C?.initialState?.query)?C.initialState.query:null,[C]),G=u.useMemo(()=>P(C?.initialState?.route)?C.initialState.route:null,[C]),[V,Y]=u.useState(()=>Va({sources:[],isGuestOnly:!1})),Z=u.useRef(null);u.useEffect(()=>{const Q={...L},ie=C4({actionDispatcher:M.current,locale:p.locale,initialGlobalState:Q,onChange:ge=>{Y(ge.globalState)}});Z.current=ie;const _e=window.__templateApp;return _e?.setGlobalState&&M.current.setGlobalStateUpdater((ge,Ae)=>{_e.setGlobalState(ge,Ae)}),Y(Q),$l({kind:"applyPatch",activeStateId:p.activeStateId,routePath:p.selectedRoute?.path??null,hasInitialPatch:!!C?.initialState,hasFormErrors:!!qa(C),hasSampleOverride:!!xg(C)}),()=>{ie.restore(),Z.current=null}},[p.locale,L]),u.useEffect(()=>{if(!A)return;const Q=window.G7Core;if(!Q||typeof Q.t!="function")return;const ie=Q.t,_e=p.templateIdentifier,ge=p.locale;return Q.t=(Ae,Ne)=>{try{const Le=Ne?"|"+Object.entries(Ne).map(([ae,pe])=>`${ae}=${pe}`).join("|"):void 0,q=A.translate(Ae,{templateId:_e,locale:ge},Le);if(q!==Ae&&!q.startsWith("$t:"))return q}catch{}return ie(Ae,Ne)},typeof window<"u"&&window.dispatchEvent(new CustomEvent(Ga)),()=>{window.G7Core?.t&&window.G7Core.t!==ie&&(window.G7Core.t=ie)}},[A,p.templateIdentifier,p.locale]);const se=u.useMemo(()=>{const Q=g?.raw?.components??[];return p.editMode!=="base"?Q:L4(Q)},[g,p.editMode]),re=g?.raw?.__editability,U=g?.raw?.__extensionId,ee=u.useMemo(()=>p.editMode!=="extension"||re!=="ok"?[]:typeof U!="number"?[]:F4(se,U),[p.editMode,re,U,se]),[fe,K]=u.useState(null),[ne,me]=u.useState(!1),Ce=g?.layoutName??null,ze=u.useMemo(()=>{const Q=g?.raw?.scripts??[];return Array.isArray(Q)?Q.map(ie=>ie&&typeof ie.src=="string"?ie.src:"").join("|"):""},[g]);u.useEffect(()=>{me(!1)},[Ce,ze]),u.useEffect(()=>{let Q=!1;const ie=g?.raw?.scripts??[];if(!Array.isArray(ie)||ie.length===0){me(!0);return}const _e=[];for(const ge of ie){if(!ge?.src||typeof ge.src!="string")continue;const Ae=ge.id?`script#${CSS.escape(ge.id)}, script[data-g7le-canvas-script="${ge.src}"]`:`script[data-g7le-canvas-script="${ge.src}"], script[src="${ge.src}"]`,Ne=window.document.querySelector(Ae);if(Ne){const Le=Ne.hasAttribute("data-g7le-canvas-script");if(Ne.hasAttribute("data-g7le-script-loaded")||!Le)continue;_e.push(new Promise(ae=>{if(Ne.hasAttribute("data-g7le-script-loaded")){ae();return}Ne.addEventListener("load",()=>ae()),Ne.addEventListener("error",()=>ae())}));continue}_e.push(new Promise(Le=>{const q=window.document.createElement("script");q.src=ge.src,q.async=!1,ge.id&&(q.id=ge.id),q.setAttribute("data-g7le-canvas-script",ge.src);const ae=()=>{q.setAttribute("data-g7le-script-loaded","1"),Le()};q.addEventListener("load",ae),q.addEventListener("error",ae),window.document.head.appendChild(q)}))}if(_e.length===0){me(!0);return}return Promise.all(_e).then(()=>{Q||requestAnimationFrame(()=>{requestAnimationFrame(()=>{Q||me(!0)})})}),()=>{Q=!0}},[g]);const Se=u.useMemo(()=>g?.raw?.data_sources??[],[g]),qe=u.useMemo(()=>g?.raw?.computed??{},[g]),[De,Pe]=u.useState({}),Qe=u.useMemo(()=>{if(p.editMode!=="iteration_item")return De;const Q=g?.iterationContext;if(!Q)return De;const ie=g?.raw?.components??[],_e=We({children:ie},Q.sourceIndexPath),ge=_e&&_e.iteration&&typeof _e.iteration.source=="string"?_e.iteration.source:null;return ge?z4(De,ge):De},[p.editMode,De,g]),[Me,Re]=u.useState(0);u.useEffect(()=>{if(typeof window>"u")return;const Q=()=>Re(ie=>ie+1);return window.addEventListener(kt,Q),()=>window.removeEventListener(kt,Q)},[]);const ve=u.useMemo(()=>E4(p.selectedRoute?.path??null),[p.selectedRoute?.path]);if(u.useEffect(()=>{let Q=!1;return(async()=>{if(Se.length===0){Q||Pe({});return}try{const ie=await B.fetchDataSources(Se,ve,new URLSearchParams,void 0,void 0);Q||Pe(ie)}catch{Q||Pe({})}})(),()=>{Q=!0}},[Se,B,ve]),u.useEffect(()=>{const Q=b;if(!Q||typeof window>"u")return;let ie=0,_e=0,ge=0;const Ae=()=>B4(Q,window.innerHeight);ie=window.requestAnimationFrame(()=>{_e=window.requestAnimationFrame(Ae)});let Ne=null;return typeof MutationObserver<"u"&&(Ne=new MutationObserver(()=>{ge||(ge=window.requestAnimationFrame(()=>{ge=0,Ae()}))}),Ne.observe(Q,{childList:!0,subtree:!0})),()=>{window.cancelAnimationFrame(ie),window.cancelAnimationFrame(_e),ge&&window.cancelAnimationFrame(ge),Ne&&Ne.disconnect()}},[b,se,ne,k,De]),u.useEffect(()=>{const Q=b;if(!Q||typeof window>"u"||p.editMode!=="extension"||re!=="ok"||ee.length===0){K(null);return}let ie=0,_e=0;const ge=ae=>{if(!ae)return!1;const pe=ae.getBoundingClientRect();return pe.width>0&&pe.height>0},Ae=ae=>{const pe=Q.querySelector(`[data-editor-path="${ae}"]`);if(ge(pe))return!0;const $e=Q.querySelectorAll(`[data-editor-path^="${ae}.children."]`);for(const be of Array.from($e))if(ge(be))return!0;return!1},Ne=()=>{K(ee.some(Ae))};ie=window.requestAnimationFrame(()=>{_e=window.requestAnimationFrame(Ne)});let Le=null,q=0;return typeof MutationObserver<"u"&&(Le=new MutationObserver(()=>{q||(q=window.requestAnimationFrame(()=>{q=0,Ne()}))}),Le.observe(Q,{childList:!0,subtree:!0})),()=>{window.cancelAnimationFrame(ie),window.cancelAnimationFrame(_e),q&&window.cancelAnimationFrame(q),Le&&Le.disconnect()}},[b,p.editMode,re,ee,ne,De]),u.useEffect(()=>{if(typeof window>"u"||p.editMode!=="base")return;const Q=window.document,ie="g7le-base-slot-style";if(Q.getElementById(ie))return;const _e=Q.createElement("style");_e.id=ie;const ge=T("layout_editor.preview.slot_area_label");return _e.textContent=`.g7le-preview-frame [data-editor-slot]{position:relative;min-height:96px;outline:2px dashed #94a3b8;outline-offset:-2px;}.g7le-preview-frame [data-editor-slot]::after{content:'${ge.replace(/'/g,"\\'")} · ' attr(data-editor-slot);position:absolute;top:8px;left:50%;transform:translateX(-50%);font-size:12px;line-height:1;color:#64748b;background:rgba(241,245,249,0.92);border:1px solid #cbd5e1;border-radius:9999px;padding:4px 12px;pointer-events:none;white-space:nowrap;}`,Q.head.appendChild(_e),()=>{Q.getElementById(ie)?.remove()}},[p.editMode,T]),!(p.editMode==="extension"||p.editMode==="iteration_item")&&(p.selectedRoute?.layoutName===null||p.selectedRoute===null))return i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--empty","data-testid":"g7le-preview-empty",style:Zo,children:T("layout_editor.preview.empty")});if(m)return i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--loading","data-testid":"g7le-preview-loading",style:Zo,children:T("layout_editor.preview.loading")});if(h)return i.jsx(Fa,{error:h});if(D)return i.jsx(Fa,{error:D});if(!z||$===null||A===null)return i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--assets-loading","data-testid":"g7le-preview-assets-loading",style:Zo,children:T("layout_editor.preview.assets_loading")});if(se.length===0)return i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--empty-layout","data-testid":"g7le-preview-empty-layout",style:Zo,children:T("layout_editor.preview.empty_layout")});const he=p.editMode==="extension"?re==="no-injection"?"no-injection":re==="ok"&&ee.length>0&&fe!==!0?"gated-no-state":null:null;return ne?i.jsx("div",{className:"g7le-preview-canvas","data-testid":"g7le-preview-canvas",style:{overflow:"visible",background:"#f1f5f9",padding:24,display:"flex",justifyContent:"center",alignItems:"flex-start",minHeight:"calc(100vh - var(--g7le-header-h, 0px))",boxSizing:"border-box"},children:i.jsxs("div",{className:"g7le-preview-frame-wrapper","data-testid":"g7le-preview-frame-wrapper",style:{position:"relative",width:k,transform:`scale(${w})`,transformOrigin:"top center"},children:[i.jsx("div",{className:_==="dark"?"g7le-preview-frame g7le-preview-dark":"g7le-preview-frame","data-testid":"g7le-preview-frame","data-color-scheme":_,ref:Q=>{v.current=Q,x(Q)},style:{width:k,background:"#fff",border:"1px solid #cbd5e1",boxShadow:"0 1px 3px rgba(0,0,0,0.05)",minHeight:400,position:"relative",transform:"translateZ(0)",overflow:"hidden"},children:i.jsx(KE,{overrideWidth:k,children:se.map((Q,ie)=>i.jsx(FE,{componentDef:Q,dataContext:{...Qe,...T4(V),_global:D4(V),_computedDefinitions:qe,...I?{_localInit:I,_local:{...De._local??{},...V._local??{}}}:{},route:K4({...De.route??{},...ve,path:p.selectedRoute?.path??""},G),query:{...De.query??{},...F??{}}},translationContext:{templateId:p.templateIdentifier,locale:p.locale},registry:$,bindingEngine:O.current,translationEngine:Pt.getInstance(),actionDispatcher:M.current,isEditMode:!0,isRootRenderer:ie===0,componentPath:`${ie}`,onComponentSelect:(_e,ge)=>{},onComponentHover:(_e,ge)=>{}},`${Q.id??`preview-${ie}`}:t${Me}${p.editMode==="extension"?`:s${ne?1:0}`:""}`))})}),i.jsx("div",{className:"g7le-overlay-layer","data-testid":"g7le-overlay-layer",style:{position:"absolute",left:0,top:0,width:k,height:b?b.getBoundingClientRect().height/(w||1):"100%",overflow:"visible",pointerEvents:"none"},children:i.jsx(p4,{frameEl:b,manifest:t,nesting:n,componentPalette:o,spec:r,permissionCandidates:s,resolveRouteMatch:l,onNavigateToDestination:d,onSessionAddedPathsChange:c})}),he!==null&&i.jsx("div",{className:"g7le-preview-canvas--extension-fallback","data-testid":"g7le-preview-extension-fallback","data-fallback-reason":he,style:{position:"absolute",left:0,top:0,right:0,bottom:0,minHeight:b?b.getBoundingClientRect().height/(w||1):400,background:"#f1f5f9",display:"flex",alignItems:"flex-start",justifyContent:"center",padding:24,boxSizing:"border-box",pointerEvents:"auto",zIndex:50},children:i.jsxs("div",{className:"g7le-extension-fallback-card",style:{maxWidth:440,textAlign:"center",position:"sticky",top:"calc(40vh - var(--g7le-header-h, 0px))"},children:[i.jsx("p",{className:"g7le-extension-fallback-title",style:{fontWeight:600,marginBottom:8,color:"#0f172a"},children:T(he==="no-injection"?"layout_editor.preview.extension_no_injection_title":"layout_editor.preview.extension_gated_title")}),i.jsx("p",{className:"g7le-extension-fallback-desc",style:{color:"#475569",lineHeight:1.6},children:he==="no-injection"?T("layout_editor.preview.extension_no_injection_desc"):p.availableStates.length>1?T("layout_editor.preview.extension_gated_desc_with_states"):T("layout_editor.preview.extension_gated_desc")})]})})]})}):i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--scripts-loading","data-testid":"g7le-preview-scripts-loading",style:Zo,children:T("layout_editor.preview.loading")})}function H4(e,t,n){if(!e)return;if(!t)return e;const o=s=>{if(typeof s=="string"&&s.startsWith("$t:"))try{const a=s.slice(3),l=a.indexOf("|");if(l===-1)return t.translate(a,n);const d=a.slice(0,l),c=a.slice(l);return t.translate(d,n,c)}catch{return s}return Array.isArray(s)?s.map(o):s},r={};for(const[s,a]of Object.entries(e))r[s]=o(a);return r}function F4(e,t){const n=[],o=(r,s)=>{Array.isArray(r)&&r.forEach((a,l)=>{if(!a||typeof a!="object")return;const d=s?`${s}.children.${l}`:`${l}`,c=a.__source;if(c?.kind==="extension"&&c.extensionId===t){n.push(d);return}Array.isArray(a.children)&&o(a.children,d)})};return o(e,""),n}function K4(e,t){if(!t)return e;const n={...e};for(const[o,r]of Object.entries(t))r===null?delete n[o]:n[o]=r;return n}const Zo={flex:1,display:"flex",alignItems:"center",justifyContent:"center",padding:24,background:"#f1f5f9",color:"#64748b",fontSize:13},V4={desktop:"layout_editor.device.desktop",tablet:"layout_editor.device.tablet",mobile:"layout_editor.device.mobile",portable:"layout_editor.device.portable"};function U4(){const{device:e,zoom:t,customWidth:n,setDevice:o,setZoom:r,setCustomWidth:s,colorScheme:a,setColorScheme:l}=ja(),{t:d}=tt(),c=Gf();return i.jsxs("div",{className:"g7le-device-toolbar","data-testid":"g7le-device-toolbar",style:{display:"inline-flex",alignItems:"center",gap:8,padding:"4px 8px",background:"#fff",border:"1px solid #cbd5e1",borderRadius:6},children:[i.jsxs("div",{role:"group","aria-label":d("layout_editor.device.group_label"),children:[c.map(p=>{const f=e===p,y=V4[p],g=y?d(y):p;return i.jsx("button",{type:"button","data-testid":`g7le-device-${p}`,"aria-pressed":f,onClick:()=>o(p),style:{padding:"2px 8px",marginRight:2,fontSize:12,cursor:"pointer",background:f?"#0f172a":"#f8fafc",color:f?"#fff":"#0f172a",border:"1px solid #cbd5e1",borderRadius:4},children:g},p)}),(()=>{const p=e==="custom";return i.jsx("button",{type:"button","data-testid":"g7le-device-custom","aria-pressed":p,onClick:()=>o("custom"),style:{padding:"2px 8px",marginRight:2,fontSize:12,cursor:"pointer",background:p?"#0f172a":"#f8fafc",color:p?"#fff":"#0f172a",border:"1px solid #cbd5e1",borderRadius:4},children:d("layout_editor.device.custom")})})()]}),e==="custom"&&i.jsxs("div",{style:{display:"inline-flex",alignItems:"center",gap:4},children:[i.jsx("label",{htmlFor:"g7le-custom-width-input",style:{fontSize:11,color:"#475569"},children:d("layout_editor.device.custom_width_label")}),i.jsx("input",{id:"g7le-custom-width-input",type:"number",min:ug,max:pg,step:10,value:n,"data-testid":"g7le-custom-width-input","aria-label":d("layout_editor.device.custom_width_label"),onChange:p=>{const f=parseInt(p.currentTarget.value,10);Number.isFinite(f)&&s(f)},style:{width:72,padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:4}}),i.jsx("span",{style:{fontSize:11,color:"#475569"},children:"px"})]}),i.jsx("div",{role:"group","aria-label":d("layout_editor.toolbar.color_scheme_group"),style:{display:"inline-flex",gap:2},children:["light","dark"].map(p=>{const f=a===p;return i.jsx("button",{type:"button","data-testid":`g7le-toolbar-scheme-${p}`,"aria-pressed":f,onClick:()=>l(p),style:{padding:"2px 8px",fontSize:12,cursor:"pointer",background:f?"#0f172a":"#f8fafc",color:f?"#fff":"#0f172a",border:"1px solid #cbd5e1",borderRadius:4},children:d(p==="light"?"layout_editor.toolbar.color_scheme_light":"layout_editor.toolbar.color_scheme_dark")},p)})}),i.jsxs("div",{style:{display:"inline-flex",alignItems:"center",gap:4},children:[i.jsx("span",{style:{fontSize:11,color:"#475569"},children:d("layout_editor.zoom.label")}),i.jsx("input",{type:"range",min:.5,max:1,step:.05,value:t,"data-testid":"g7le-zoom-slider","aria-label":d("layout_editor.zoom.aria_label"),onChange:p=>r(parseFloat(p.currentTarget.value)),style:{width:100}}),i.jsxs("span",{style:{fontSize:11,color:"#475569",minWidth:36,textAlign:"right"},children:[Math.round(t*100),"%"]})]}),i.jsx(Kb,{})]})}function q4(){const{t:e}=tt(),{state:t,dispatch:n}=Je(),{availableStates:o,activeStateId:r}=t,[,s]=u.useState(0);u.useEffect(()=>{if(typeof window>"u")return;const p=()=>s(y=>y+1),f=window.requestAnimationFrame(p);return window.addEventListener(Ga,p),()=>{window.cancelAnimationFrame(f),window.removeEventListener(Ga,p)}},[]);const a=u.useCallback((p,f)=>{if(!p)return f;if(!p.startsWith("$t:"))return p;const y=p.slice(3),g=window.G7Core;if(g&&typeof g.t=="function"){const h=g.t(y);if(h&&h!==y&&!h.startsWith("$t:"))return h}const m=e(y);return m&&m!==y?m:f},[e]);if(!Array.isArray(o)||o.length<=1)return null;const l=p=>{const f=p.target.value;n({type:"SET_ACTIVE_STATE",activeStateId:f}),$l({kind:"change",activeStateId:f,routePath:t.selectedRoute?.path??null,availableCount:o.length})},d=o.find(p=>p.id===r)??o[0],c=d?.description?a(d.description,""):"";return i.jsxs("div",{className:"g7le-state-switcher","data-testid":"g7le-state-switcher","data-active-state":r??"",style:{display:"inline-flex",alignItems:"center",gap:6,padding:"4px 8px",background:"#fff",border:"1px solid #cbd5e1",borderRadius:6},children:[i.jsx("span",{style:{fontSize:12,fontWeight:600,color:"#475569",whiteSpace:"nowrap"},children:e("layout_editor.toolbar.state")}),i.jsx("select",{"data-testid":"g7le-state-switcher-select","aria-label":e("layout_editor.toolbar.state"),value:r??o[0].id,onChange:l,style:{fontSize:12,padding:"2px 6px",border:"1px solid #cbd5e1",borderRadius:4,background:"#fff",color:"#0f172a",cursor:"pointer",outline:"none"},children:o.map(p=>i.jsx("option",{value:p.id,children:a(p.label,p.id)},p.id))}),c&&i.jsx("span",{"data-testid":"g7le-state-switcher-description",style:{fontSize:11,color:"#94a3b8",whiteSpace:"nowrap"},children:c})]})}function G4(e,t,n){if(e==="extension"){if(typeof n=="string"&&n.length>0){const o=Ya(n,"__base__/");return o?{kind:"base",match:o}:{kind:"route",match:n}}return null}if(!t)return null;switch(e){case"route":return{kind:"route",match:t};case"base":{const o=Ya(t,"__base__/");return o?{kind:"base",match:o}:null}case"modal":{const o=Ya(t,"__modal__/");return o?{kind:"modal",match:o}:null}default:return null}}function Y4(e,t){if(!t||!Array.isArray(e)||e.length===0)return[];const n=[];for(const o of e)if(J4(o.scope,t))for(const r of o.items??[])r&&typeof r.id=="string"&&r.id.length>0&&n.push(r);return n}function X4(e){if(e.length===0)return null;const t=e.find(n=>n.default===!0);return t?t.id:e[0].id}function J4(e,t){if(!e||e.kind!==t.kind)return!1;const n=e.match;return typeof n!="string"||n.length===0?!1:t.kind==="route"?Z4(t.match,n):n===t.match}function Z4(e,t){if(t===e)return!0;if(!t.includes("*"))return!1;const n=t.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]+");return new RegExp(`^${n}$`).test(e)}function Ya(e,t){return e.startsWith(t)?e.slice(t.length):""}const Q4="__conngroup__/modals/",R4="__conngroup__/extensions/";function eD(e){return e.meta?.editor_label?{label:e.meta.editor_label,labelSource:"editor_label"}:e.meta?.title?{label:e.meta.title,labelSource:"title"}:{label:e.path,labelSource:"path"}}function tD(e){switch(e.source.kind){case"template":return"template";case"module":return`module:${e.source.identifier??""}`;case"plugin":return`plugin:${e.source.identifier??""}`;case"core":return null;default:return null}}function nD(e,t){if(e.meta?.parent&&t.has(e.meta.parent))return e.meta.parent;const n=e.path.split("/").filter(Boolean);for(let o=n.length-1;o>=1;o--){const r="/"+n.slice(0,o).join("/");if(r!==e.path&&t.has(r))return r}return null}function oD(e){const t=new Map;for(const n of e)n.layout&&t.set(n.layout,(t.get(n.layout)??0)+1);return t}function rD(e){const t=new Map;for(const n of e){if(!n.hostLayout)continue;const o=t.get(n.hostLayout)??[];o.push(n),t.set(n.hostLayout,o)}return t}function iD(e){const t=new Map;for(const n of e)for(const o of n.extensions)for(const r of o.hostLayouts??[]){if(!r)continue;const s=t.get(r)??[];s.push({extension:o,group:n}),t.set(r,s)}return t}function sD(e,t){return{path:`__modal__/${e.hostLayout}/${e.modalId}`,layoutName:e.hostLayout,label:e.label??e.modalId,labelSource:e.label?"editor_label":"path",source:{kind:"core",identifier:null},kind:"modal",modalId:e.modalId,modalHostLayout:e.hostLayout,connectedHostRoutePath:t,children:[]}}function aD(e,t){const{extension:n,group:o}=e,r=o.sourceType==="plugin"?"🔌":"🧩";return{path:`__extension__/${n.id}`,layoutName:null,label:`${r} ${o.sourceLabel} · ${n.targetName}`,labelSource:"path",source:{kind:o.sourceType,identifier:o.sourceIdentifier},kind:"extension",extensionId:String(n.id),extensionType:n.extensionType,extensionPriority:n.priority,extensionTargetName:n.targetName,isModified:n.isModified,isInactive:!n.isActive,connectedHostRoutePath:t,children:[]}}function kg(e,t,n){if(e.kind!=="route"&&e.kind!=="base"||!e.layoutName)return;const o=[],r=t.get(e.layoutName)??[];r.length>0&&o.push({path:`${Q4}${e.path}`,layoutName:null,label:`$t:layout_editor.chrome.route_tree.connected.modals|count=${r.length}`,labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:r.map(a=>sD(a,e.path))});const s=n.get(e.layoutName)??[];s.length>0&&o.push({path:`${R4}${e.path}`,layoutName:null,label:`$t:layout_editor.chrome.route_tree.connected.extensions|count=${s.length}`,labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:s.map(a=>aD(a,e.path))}),o.length>0&&(e.children=[...o,...e.children??[]])}function lD(e){const t=[],n=new Set(e.routes.map(o=>o.path));for(const o of e.routes){const r=tD(o);if(!r)continue;const{label:s,labelSource:a}=eD(o),l=nD(o,n),d={path:o.path,layoutName:o.layout??null,label:s,labelSource:a,icon:o.meta?.icon??null,source:o.source,isRedirect:!!o.redirect,isHidden:!!o.meta?.hidden,kind:"route",children:[]};t.push({node:d,parentKey:l,groupKey:r})}return t}function dD(e,t){if(e==="template")return"$t:layout_editor.chrome.route_tree.group.template";if(e.startsWith("module:")){const n=e.slice(7);return`$t:layout_editor.chrome.route_tree.group.module|name=${t.moduleDisplayNames[n]??n}`}if(e.startsWith("plugin:")){const n=e.slice(7);return`$t:layout_editor.chrome.route_tree.group.plugin|name=${t.pluginDisplayNames[n]??n}`}return e}function cD(e,t){oD(e.routes);const n=rD(e.modals),o=iD(e.extensionGroups??[]),r=new Map;for(const d of t)r.has(d.groupKey)||r.set(d.groupKey,[]),r.get(d.groupKey).push(d);const s=Array.from(r.keys()).sort((d,c)=>{const p=g=>g==="template"?1:g.startsWith("module:")?2:g.startsWith("plugin:")?3:4,f=p(d),y=p(c);return f!==y?f-y:d.localeCompare(c)}),a=[];if(e.baseLayouts.length>0){const d=e.baseLayouts.map(c=>({path:`__base__/${c.layoutName}`,layoutName:c.layoutName,label:c.label??c.layoutName,labelSource:c.label?"editor_label":"path",source:{kind:"core",identifier:null},kind:"base",children:[]}));for(const c of d)kg(c,n,o);a.push({path:"__group__/base",layoutName:null,label:"$t:layout_editor.chrome.route_tree.group.base",labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:d})}for(const d of s){const c=r.get(d),p=new Map;for(const y of c)p.set(y.node.path,y);const f=[];for(const y of c)if(y.parentKey&&p.has(y.parentKey)){const g=p.get(y.parentKey);g.node.children=g.node.children??[],g.node.children.push(y.node)}else f.push(y.node);for(const y of c)kg(y.node,n,o);a.push({path:`__group__/${d}`,layoutName:null,label:dD(d,e),labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:f})}if(e.modals.length>0){const d=e.modals.map(c=>({path:`__modal__/${c.hostLayout}/${c.modalId}`,layoutName:c.hostLayout,label:c.label??c.modalId,labelSource:c.label?"editor_label":"path",source:{kind:"core",identifier:null},kind:"modal",modalId:c.modalId,modalHostLayout:c.hostLayout,children:[]}));a.push({path:"__group__/modal",layoutName:null,label:"$t:layout_editor.chrome.route_tree.group.modal",labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:d})}const l=e.extensionGroups??[];if(l.length>0){const d=l.map(c=>{const p=c.sourceType==="plugin"?"🔌":"🧩",f=c.extensions.map(y=>({path:`__extension__/${y.id}`,layoutName:null,label:`${c.sourceLabel} · ${y.targetName}`,labelSource:"path",source:{kind:c.sourceType,identifier:c.sourceIdentifier},kind:"extension",extensionId:String(y.id),extensionType:y.extensionType,extensionPriority:y.priority,extensionTargetName:y.targetName,isModified:y.isModified,isInactive:!y.isActive,children:[]}));return{path:`__extgroup__/${c.sourceType}/${c.sourceIdentifier}`,layoutName:null,label:`${p} ${c.sourceLabel}`,labelSource:"path",source:{kind:c.sourceType,identifier:c.sourceIdentifier},kind:"route",children:f}});a.push({path:"__group__/extension",layoutName:null,label:"$t:layout_editor.chrome.route_tree.group.extension",labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:d})}return a}function uD(e){const t=lD(e);return cD(e,t)}const On=bo("useEditorRoutes");function pD(e,t){if(typeof e=="string")return e.length>0?e:null;if(e&&typeof e=="object"){const n=e[t];if(typeof n=="string"&&n.length>0)return n;if(typeof e.en=="string"&&e.en.length>0)return e.en;for(const o of Object.values(e))if(typeof o=="string"&&o.length>0)return o}return null}function Sg(e,t){const n={};if(typeof window>"u")return n;const r=window.G7Config?.[e];if(!Array.isArray(r))return n;for(const s of r)s&&typeof s.identifier=="string"&&(n[s.identifier]=pD(s.display_name,t)??s.identifier);return n}function fD(e){const t=new vd,n=typeof window<"u"?window.G7Config:void 0,o={_global:{settings:n?.settings??{},plugins:n?.plugins??{},modules:n?.modules??{},appConfig:n?.appConfig??{}}};return e.map(r=>{const s={...r};if(typeof s.path=="string"&&s.path.includes("{{")){const a=s.path;let l=t.resolveBindings(s.path,o);l=l.replace(/\/\/+/g,"/")||"/",l.includes("{{")&&(On.warn("편집기 route path 표현식 평가 실패 — fallback 적용",{originalPath:a}),l=a.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/"),s.path=l}if(typeof s.redirect=="string"&&s.redirect.includes("{{")){const a=s.redirect;let l=t.resolveBindings(a,o);l=l.replace(/\/\/+/g,"/")||"/",l.includes("{{")&&(On.warn("편집기 route redirect 표현식 평가 실패 — fallback 적용",{originalRedirect:a}),l=a.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/"),s.redirect=l}return s})}function gD(e){const{dispatch:t}=Je(),{translationEngine:n,translationContext:o}=tt(),{templateIdentifier:r,cacheVersion:s}=e;u.useEffect(()=>{let a=!1;const l=s??(typeof window<"u"?window.G7Config?.cache_version:void 0)??"",d=l!==""?`?v=${encodeURIComponent(String(l))}`:"",c=en(`/api/admin/templates/${encodeURIComponent(r)}/editor/routes`,"json",null,d.replace(/^[?&]+/,"")),p=o?.locale??"ko",f=n&&r!==o?.templateId?n.loadTranslations(r,p).then(()=>{On.log("편집 대상 lang 로드 완료",{targetTemplate:r,locale:p})}).catch(h=>{On.warn("편집 대상 lang 로드 실패 — 라우트 라벨 fallback 사용",h)}):Promise.resolve(),y=(()=>{if(typeof fetch!="function")return Promise.reject(io(new Error("fetch unavailable"),"routes"));try{const h=fetch(c,{credentials:"same-origin",headers:je()});return!h||typeof h.then!="function"?Promise.reject(io(new Error("fetch returned non-Promise (test stub?)"),"routes")):h.then(async v=>{if(!v.ok){const b=await v.json().catch(()=>null);throw Gr(v.status,b,"routes")}return v.json()})}catch(h){return Promise.reject(h)}})(),g=`/api/admin/templates/${encodeURIComponent(r)}/layout-extensions${d}`,m=(()=>{if(typeof fetch!="function")return Promise.resolve(null);try{const h=fetch(g,{credentials:"same-origin",headers:je()});return!h||typeof h.then!="function"?Promise.resolve(null):h.then(async v=>v.ok?await v.json():null).catch(()=>null)}catch{return Promise.resolve(null)}})();return Promise.all([y,f,m]).then(([h,,v])=>{if(a)return;if(!h||!h.success||!Array.isArray(h.data?.routes)){On.warn("routes 응답 형식이 비정상 — empty tree 로 둠",h),t({type:"SET_ROUTES_ERROR",error:{kind:"unknown",status:200,message:"routes 응답 형식이 비정상입니다.",source:"routes"}});return}const b=fD(h.data.routes),x=Sg("activeModules",p),k=Sg("activePlugins",p),w=(h.data.base_layouts??[]).map(A=>({layoutName:A.layout_name,label:A.label??void 0})),_=(h.data.modals??[]).map(A=>({modalId:A.modal_id,hostLayout:A.host_layout,label:A.label??void 0})),C=(v?.success&&Array.isArray(v.data)?v.data:[]).map(A=>({sourceIdentifier:A.source_identifier,sourceType:A.source_type,sourceLabel:A.source_label,extensions:(A.extensions??[]).map(z=>({id:z.id,extensionType:z.extension_type,targetName:z.target_name,priority:z.priority,isActive:z.is_active,isModified:z.is_modified,hostLayouts:Array.isArray(z.host_layouts)?z.host_layouts:[],currentVersion:typeof z.current_version=="number"?z.current_version:void 0}))})),E=uD({routes:b,modals:_,baseLayouts:w,extensionGroups:C,moduleDisplayNames:x,pluginDisplayNames:k});t({type:"SET_ROUTE_TREE",tree:E});const S=h.data.layout_versions,T={};if(S&&typeof S=="object"&&!Array.isArray(S))for(const[A,z]of Object.entries(S))typeof z=="number"&&Number.isFinite(z)&&(T[A]=z);t({type:"SET_LAYOUT_VERSIONS",versions:T});const $={};for(const A of C)for(const z of A.extensions){const D=z.currentVersion;typeof D=="number"&&Number.isFinite(D)&&($[String(z.id)]=D)}t({type:"SET_EXTENSION_VERSIONS",versions:$}),On.log("routes 로드 완료",{count:b.length,groups:E.length})}).catch(h=>{if(a)return;On.error("routes 로드 실패",h);const v=hp(h)?h:io(h,"routes");t({type:"SET_ROUTES_ERROR",error:v})}),()=>{a=!0}},[r,s,t,n,o?.locale,o?.templateId])}function Cg(e,t,n,o=[]){const r=t?$g(o,t):null,s=r!==null?{path:r.path,layoutName:r.layoutName}:void 0;if(e.startsWith("__base__/")){const a=e.slice(9);if(a)return n({type:"ENTER_BASE_EDIT",layoutName:a,returnRoute:s}),!0}else if(e.startsWith("__modal__/")){const a=e.slice(10);return a&&!a.includes("/")&&t?(n({type:"ENTER_MODAL_EDIT",modalId:a,hostLayout:t,returnRoute:s}),!0):!1}else if(e.startsWith("__extension__/")){const a=e.slice(14);if(a&&!a.includes("/"))return n({type:"ENTER_EXTENSION_EDIT",extensionId:a,returnRoute:s}),!0}else if(e.startsWith("__iteration__/")){const a=e.slice(14);return a&&t?(n({type:"ENTER_ITERATION_ITEM_EDIT",sourcePath:a,hostLayout:t,returnRoute:s}),!0):!1}return!1}function $g(e,t){for(const n of e){if(n.kind==="route"&&n.layoutName===t)return n;if(n.children&&n.children.length>0){const o=$g(n.children,t);if(o)return o}}return null}function Xa(e,t){for(const n of e){if(n.kind==="route"&&n.path===t)return n;if(n.children&&n.children.length>0){const o=Xa(n.children,t);if(o)return o}}return null}function hD(e){const{state:t,dispatch:n}=Je(),o=u.useRef(!1),r=u.useRef(t.editMode);r.current=t.editMode,u.useEffect(()=>{if(o.current||t.routeTree.length===0||typeof window>"u")return;const a=ap(window.location.search);if(a){const c=sp(window.location.search),p=Cg(a,c,n,t.routeTree);if(o.current=!0,p)return}const l=ip(window.location.search);if(!l){o.current=!0;return}const d=Xa(t.routeTree,l);d&&n({type:"SELECT_ROUTE",route:{path:d.path,layoutName:d.layoutName}}),o.current=!0},[t.routeTree,n]),u.useEffect(()=>{if(typeof window>"u")return;const a=()=>{const l=ap(window.location.search);if(l){const p=sp(window.location.search);if(Cg(l,p,n,t.routeTree))return}if(r.current!=="route")switch(r.current){case"base":n({type:"EXIT_BASE_EDIT"});return;case"modal":n({type:"EXIT_MODAL_EDIT"});return;case"extension":n({type:"EXIT_EXTENSION_EDIT"});return;case"iteration_item":n({type:"EXIT_ITERATION_ITEM_EDIT"});return}const d=ip(window.location.search);if(!d){n({type:"SELECT_ROUTE",route:null});return}const c=Xa(t.routeTree,d);c&&n({type:"SELECT_ROUTE",route:{path:c.path,layoutName:c.layoutName}})};return window.addEventListener("popstate",a),()=>{window.removeEventListener("popstate",a)}},[t.routeTree,n]);const s=u.useRef("route");u.useEffect(()=>{if(typeof window>"u"||!window.history?.replaceState||t.routeTree.length===0)return;const a=Zs(e,t.selectedRoute?.path??null,t.selectedRoute?.layoutName??null),l=`${window.location.pathname}${window.location.search}`,d=s.current;if(s.current=t.editMode,l===a)return;d==="route"&&t.editMode!=="route"&&window.history.pushState?window.history.pushState(window.history.state,"",a):window.history.replaceState(window.history.state,"",a)},[t.selectedRoute,t.editMode,t.routeTree,e])}function yD(){u.useEffect(()=>{if(typeof document>"u")return;const e=document.documentElement;let t=e.classList.contains("dark");const n=()=>{e.classList.contains("dark")&&(t=!0,e.classList.remove("dark"))};n();let o=null;return typeof MutationObserver<"u"&&(o=new MutationObserver(n),o.observe(e,{attributes:!0,attributeFilter:["class"]})),()=>{o?.disconnect(),t&&e.classList.add("dark")}},[])}function bD(){u.useEffect(()=>{if(typeof document>"u"||!document.body)return;const e=document.body,t=()=>{e.style.overflow==="hidden"&&(e.style.overflow=""),e.style.overflowY==="hidden"&&(e.style.overflowY="")};t();let n=null;return typeof MutationObserver<"u"&&(n=new MutationObserver(t),n.observe(e,{attributes:!0,attributeFilter:["style"]})),()=>{n?.disconnect()}},[])}function mD(e){if(typeof e!="string")return null;const t="__extension__/";if(!e.startsWith(t))return null;const n=e.slice(t.length);return n===""||n.includes("/")?null:n}function vD(e){if(Array.isArray(e.components))return e.components;if(Array.isArray(e.injections)){const t=[];return e.injections.forEach((n,o)=>{if(n&&Array.isArray(n.components))for(const r of n.components)t.push({...r,__injectionIndex:o})}),t}return[]}function _D(e,t){if(Array.isArray(e.components)){const n=t.map(o=>Ja(o));return{...e,components:n}}if(Array.isArray(e.injections)){const n=e.injections.map(o=>({...o}));n.forEach(o=>{Array.isArray(o.components)&&(o.components=[])});for(const o of t){const r=o.__injectionIndex,s=typeof r=="number"&&r>=0&&rJa(n))),t}function Eg(e,t){const n=[],o=r=>{if(Array.isArray(r))for(const s of r){if(!s||typeof s!="object")continue;const a=s.__source;if(a?.kind==="extension"&&a.extensionId===t){n.push(s);continue}Array.isArray(s.children)&&o(s.children)}};return o(e),n}function Ig(e,t){const o=Eg(e,t)[0]?.__source;return o&&o.kind==="extension"&&o.extensionId===t?o:{kind:"extension",extensionId:t}}function Za(e,t){for(const n of e){const o=n?.__source;if(o?.kind==="extension"&&o.extensionId===t||Array.isArray(n.children)&&Za(n.children,t))return!0}return!1}function xD(){const{state:e}=Je(),t=e.templateIdentifier,n=e.editMode==="extension"?mD(e.selectedRoute?.path):null,o=e.editMode==="extension"&&typeof e.selectedRoute?.layoutName=="string"?e.selectedRoute.layoutName:null,[r,s]=u.useState(null),[a,l]=u.useState(!1),[d,c]=u.useState(null),[p,f]=u.useState(!1),[y,g]=u.useState(0),[m,h]=u.useState(null),v=u.useRef({}),b=u.useRef({kind:"extension",extensionId:0}),x=u.useRef(null);u.useEffect(()=>{x.current=r},[r]),u.useEffect(()=>{h(null)},[n]);const k=u.useCallback(async A=>{const z=window.G7Config?.cache_version??0,D=en(`/api/layouts/${encodeURIComponent(t)}/${A}`,"json",`${z}.${Sp()}`,"with_source_meta=1"),O=ar(),M={Accept:"application/json"};O&&(M.Authorization=`Bearer ${O}`);const B=await fetch(D,{headers:M,credentials:"same-origin"});if(!B.ok)return null;const N=await B.json().catch(()=>null);return(N&&(N.data||N))??{}},[t]),w=u.useCallback(async()=>{if(!n){s(null),c(null),f(!1);return}l(!0),c(null);try{const A=window.G7Config?.cache_version??0,z=`/api/admin/templates/${encodeURIComponent(t)}/layout-extensions/${encodeURIComponent(n)}?v=${A}`,D=await fetch(z,{headers:je(),credentials:"same-origin"}),O=await D.json().catch(()=>null);if(!D.ok){c(Gr(D.status,O,"layout")),s(null),f(!1);return}const M=(O&&(O.data||O))??{};let B={};const N=M.content;if(typeof N=="string")try{B=JSON.parse(N)}catch{B={}}else N&&typeof N=="object"&&(B=N);const H=M.extension_type==="overlay"?"overlay":"extension_point",L=typeof M.lock_version=="number"?M.lock_version:0,I=Array.isArray(M?.host_layouts)?M.host_layouts.filter(re=>typeof re=="string"):[],P=o??(I.length===1?I[0]:m&&I.includes(m)?m:null),F=Number(n);v.current=B;let V=vD(B),Y={},Z="pending";const se={kind:"extension",extensionId:F};if(b.current=se,P){const re=await k(P);if(re){Y=re;const U=Array.isArray(re.components)?re.components:[],ee=Ig(U,F);if(b.current=ee,Za(U,F))V=U,Z="ok";else{const K=(Array.isArray(re.modals)?re.modals:[]).filter(ne=>ne&&typeof ne=="object"&&Za([ne],F));if(K.length>0){const ne=K.map(me=>({...me,props:{...me.props??{},isOpen:!0}}));V=[...U,...ne],b.current=Ig(K,F),Z="ok"}else V=U,Z="no-injection"}}}s({extensionId:F,content:B,extensionType:H,components:V,lockVersion:L,hostLayouts:I,hostLayoutName:P,hostRaw:Y,editability:Z}),f(!1),st({op:"load",layoutName:`extension:${n}`,editMode:"extension",statusCode:D.status,timestamp:Date.now()})}catch(A){c(io(A,"layout")),s(null),f(!1)}finally{l(!1)}},[t,n,m,o,k]);u.useEffect(()=>{w()},[w]);const _=u.useCallback(A=>{h(A)},[]),C=u.useCallback(A=>{s(z=>z&&{...z,components:A}),f(!0),st({op:"patch",layoutName:`extension:${x.current?.extensionId??""}`,editMode:"extension",isDirty:!0,timestamp:Date.now()})},[]),E=u.useCallback(A=>{s(z=>z&&{...z,components:A(z.components)}),f(!0)},[]),S=u.useCallback(async()=>{const A=x.current;if(!A)return{kind:"guard_no_document"};const z=`/api/admin/templates/${encodeURIComponent(t)}/layout-extensions/${A.extensionId}`,D=Eg(A.components,A.extensionId),O=D.length>0?D:A.components,M=_D(v.current,O);st({op:"save",layoutName:`extension:${A.extensionId}`,editMode:"extension",saveTarget:"layout_extension",endpoint:z,isDirty:p,timestamp:Date.now()});let B;try{B=await fetch(z,{method:"PUT",headers:je({"Content-Type":"application/json"}),credentials:"same-origin",body:JSON.stringify({content:M,expected_lock_version:A.lockVersion})})}catch(H){return{kind:"network_error",message:H instanceof Error?H.message:"network error"}}const N=await B.json().catch(()=>null);if(st({op:"save_response",layoutName:`extension:${A.extensionId}`,editMode:"extension",endpoint:z,statusCode:B.status,conflict:B.status===409?{currentVersion:N?.errors?.current_version??N?.current_version,yourVersion:N?.errors?.your_version??N?.your_version}:void 0,timestamp:Date.now()}),B.ok){const H=N?.data??{},L=typeof H.lock_version=="number"?H.lock_version:A.lockVersion+1;s(P=>P&&{...P,lockVersion:L}),f(!1),g(P=>P+1);const I=typeof H.current_version=="number"?H.current_version:void 0;return{kind:"success",newLockVersion:L,newContentVersion:I,savedExtensionId:String(A.extensionId)}}return B.status===409?{kind:"concurrent_modification",currentVersion:N?.current_version??-1,yourVersion:N?.your_version??A.lockVersion}:B.status===422?{kind:"validation_failed",status:422,errors:N?.errors??null}:{kind:"network_error",message:N?.message??`HTTP ${B.status}`}},[t,p]),T=u.useCallback(async()=>{na(),await w()},[w]),$=!!r&&r.hostLayouts.length>1&&r.hostLayoutName===null;return{document:r,isLoading:a,error:d,isDirty:p,saveSuccessCounter:y,setLayoutComponents:C,patchLayout:E,save:S,reload:T,needsHostPicker:$,selectHost:_}}const Ag=new Set;function wD(e,t,n){const r=e&&Object.keys(e).length>0?e:t,s=Array.isArray(r.data_sources)?r.data_sources:[],a=Array.isArray(t.data_sources)?t.data_sources:[],l=new Set,d=[];for(const c of[...s,...a]){const p=c&&typeof c=="object"?c.id:void 0,f=typeof p=="string"?p:`__anon_${d.length}`;l.has(f)||(l.add(f),d.push(c))}return{...r,components:n,...d.length>0?{data_sources:d}:{},lock_version:void 0}}function kD(e){return{document:e.document?{layoutName:`extension:${e.document.extensionId}`,raw:{...wD(e.document.hostRaw,e.document.content,e.document.components),__editability:e.document.editability,__extensionId:e.document.extensionId},lockVersion:e.document.lockVersion}:null,isLoading:e.isLoading,error:e.error,isDirty:e.isDirty,saveSuccessCounter:e.saveSuccessCounter,reload:e.reload,patchLayout:e.patchLayout,setLayoutComponents:e.setLayoutComponents,patchDocumentRaw:()=>{},dirtyKeys:Ag,dirtyLayoutNames:Ag,invalidateCurrentCache:()=>{},reloadCounter:0,save:()=>e.save(),markDirty:()=>{}}}function SD({hostLayouts:e,extensionLabel:t,onSelect:n}){const{t:o}=tt();return i.jsx("div",{className:"g7le-host-picker__backdrop","data-testid":"g7le-host-picker",role:"dialog","aria-modal":"true","aria-label":o("layout_editor.host_picker.title"),style:{position:"fixed",inset:0,zIndex:9500,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(15, 23, 42, 0.55)"},children:i.jsxs("div",{className:"g7le-host-picker__panel",style:{width:"min(520px, 92vw)",maxHeight:"80vh",overflow:"auto",background:"#ffffff",color:"#0f172a",borderRadius:12,boxShadow:"0 20px 48px rgba(15, 23, 42, 0.28)",padding:"20px 22px"},children:[i.jsx("h2",{className:"g7le-host-picker__title",style:{margin:"0 0 6px",fontSize:16,fontWeight:700},children:o("layout_editor.host_picker.title")}),i.jsx("p",{className:"g7le-host-picker__desc",style:{margin:"0 0 16px",fontSize:13,color:"#475569",lineHeight:1.6},children:t?o("layout_editor.host_picker.description_with_label",{label:t}):o("layout_editor.host_picker.description")}),i.jsx("ul",{className:"g7le-host-picker__list",style:{listStyle:"none",margin:0,padding:0,display:"grid",gap:8},children:e.map(r=>i.jsx("li",{children:i.jsxs("button",{type:"button",className:"g7le-host-picker__item","data-testid":"g7le-host-picker-item","data-host":r,onClick:()=>n(r),style:{width:"100%",textAlign:"left",padding:"12px 14px",border:"1px solid #e2e8f0",borderRadius:8,background:"#f8fafc",cursor:"pointer",fontSize:13,fontWeight:600,color:"#0f172a",display:"flex",alignItems:"center",gap:8},children:[i.jsx("span",{"aria-hidden":!0,style:{fontSize:14},children:"🖼"}),i.jsx("span",{style:{flex:1,minWidth:0,overflow:"hidden",textOverflow:"ellipsis"},children:r}),i.jsx("span",{"aria-hidden":!0,style:{color:"#94a3b8"},children:"→"})]})},r))})]})})}function CD(e,t){const[n,o]=u.useState(!1),[r,s]=u.useState(null),a=u.useCallback(async l=>{if(!t||!l)return{kind:"no_document"};o(!0),s(null);try{const d=vo(l),c=`/api/admin/templates/${encodeURIComponent(e)}/layouts/${t}/preview`,p=await fetch(c,{method:"POST",credentials:"same-origin",headers:je({"Content-Type":"application/json"}),body:JSON.stringify({content:JSON.stringify(d)})}),f=await p.json().catch(()=>null);if(!p.ok){const h=f?.message??`HTTP ${p.status}`;return s(h),{kind:"network_error",message:h}}const y=f?.data,g=typeof y?.token=="string"?y.token:"",m=typeof y?.preview_url=="string"&&y.preview_url?y.preview_url:g?`/preview/${g}`:"";return m?(window.G7Core?.dispatch?.({handler:"openWindow",params:{path:m}}),{kind:"success",previewUrl:m,token:g}):(s("invalid preview response"),{kind:"network_error",message:"invalid preview response"})}catch(d){const c=d instanceof Error?d.message:"network error";return s(c),{kind:"network_error",message:c}}finally{o(!1)}},[e,t]);return{isCreating:n,error:r,createPreview:a}}const ce="layout_editor.action_recipe",bn={setState:{label:`$t:${ce}.set_state.label`,params:[{key:"target",label:`$t:${ce}.set_state.param_target`,widget:"select",options:[{value:"local"},{value:"global"}]},{key:"state",label:`$t:${ce}.set_state.param_state`,widget:"state-key-value"},{key:"merge",label:`$t:${ce}.set_state.param_merge`,widget:"toggle"}],build:{handler:"setState",params:{target:"{{target}}",merge:"{{merge}}","...":"{{state}}"}}},loadFromLocalStorage:{label:`$t:${ce}.load_local.label`,params:[{key:"key",label:`$t:${ce}.load_local.param_key`,widget:"text",required:!0},{key:"stateKey",label:`$t:${ce}.load_local.param_state_key`,widget:"state-key-picker"},{key:"defaultValue",label:`$t:${ce}.load_local.param_default`,widget:"text"}],build:{handler:"loadFromLocalStorage",params:{key:"{{key}}",stateKey:"{{stateKey}}",defaultValue:"{{defaultValue}}"}}},saveToLocalStorage:{label:`$t:${ce}.save_local.label`,params:[{key:"key",label:`$t:${ce}.save_local.param_key`,widget:"text",required:!0},{key:"value",label:`$t:${ce}.save_local.param_value`,widget:"data-chip"}],build:{handler:"saveToLocalStorage",params:{key:"{{key}}",value:"{{value}}"}}},navigate:{label:`$t:${ce}.navigate.label`,params:[{key:"path",label:`$t:${ce}.navigate.param_path`,widget:"page-picker",required:!0},{key:"query",label:`$t:${ce}.navigate.param_query`,widget:"key-value"},{key:"mergeQuery",label:`$t:${ce}.navigate.param_merge_query`,widget:"toggle"},{key:"scroll",label:`$t:${ce}.navigate.param_scroll`,widget:"select",options:[{value:"top"},{value:"preserve"},{value:"none"}]},{key:"replace",label:`$t:${ce}.navigate.param_replace`,widget:"toggle"},{key:"transition_overlay_target",label:`$t:${ce}.navigate.param_overlay_target`,widget:"component-target-picker",dependsOn:{param:"replace",equals:!0}}],build:{handler:"navigate",params:{path:"{{path}}",query:"{{query}}",mergeQuery:"{{mergeQuery}}",scroll:"{{scroll}}",replace:"{{replace}}",transition_overlay_target:"{{transition_overlay_target}}"}}},openWindow:{label:`$t:${ce}.open_window.label`,params:[{key:"target",label:`$t:${ce}.open_window.param_target`,widget:"page-picker",required:!0},{key:"windowTarget",label:`$t:${ce}.open_window.param_window_target`,widget:"select",options:[{value:"_blank"},{value:"_self"}]}],build:{handler:"openWindow",target:"{{target}}",params:{windowTarget:"{{windowTarget}}"}}},navigateBack:{label:`$t:${ce}.navigate_back.label`,params:[],build:{handler:"navigateBack"}},navigateForward:{label:`$t:${ce}.navigate_forward.label`,params:[],build:{handler:"navigateForward"}},replaceUrl:{label:`$t:${ce}.replace_url.label`,params:[{key:"path",label:`$t:${ce}.replace_url.param_path`,widget:"page-picker"},{key:"query",label:`$t:${ce}.replace_url.param_query`,widget:"key-value"}],build:{handler:"replaceUrl",params:{path:"{{path}}",query:"{{query}}"}}},toast:{label:`$t:${ce}.toast.label`,params:[{key:"message",label:`$t:${ce}.toast.param_message`,widget:"i18n-text",required:!0},{key:"type",label:`$t:${ce}.toast.param_type`,widget:"select",options:[{value:"info"},{value:"success"},{value:"warning"},{value:"error"}]},{key:"duration",label:`$t:${ce}.toast.param_duration`,widget:"number"},{key:"icon",label:`$t:${ce}.toast.param_icon`,widget:"text"}],build:{handler:"toast",params:{message:"{{message}}",type:"{{type}}",duration:"{{duration}}",icon:"{{icon}}"}}},openModal:{label:`$t:${ce}.open_modal.label`,params:[{key:"target",label:`$t:${ce}.open_modal.param_target`,widget:"modal-picker",required:!0}],build:{handler:"openModal",target:"{{target}}"}},closeModal:{label:`$t:${ce}.close_modal.label`,params:[],build:{handler:"closeModal"}},showAlert:{label:`$t:${ce}.show_alert.label`,params:[{key:"target",label:`$t:${ce}.show_alert.param_message`,widget:"i18n-text",required:!0}],build:{handler:"showAlert",target:"{{target}}"}},setError:{label:`$t:${ce}.set_error.label`,params:[{key:"target",label:`$t:${ce}.set_error.param_message`,widget:"i18n-text"},{key:"stateTarget",label:`$t:${ce}.set_error.param_state_target`,widget:"select",options:[{value:"local"},{value:"global"}]}],build:{handler:"setError",target:"{{target}}",params:{stateTarget:"{{stateTarget}}"}}},refetchDataSource:{label:`$t:${ce}.refetch.label`,params:[{key:"dataSourceId",label:`$t:${ce}.refetch.param_data_source`,widget:"datasource-picker",required:!0},{key:"sync",label:`$t:${ce}.refetch.param_sync`,widget:"toggle"}],build:{handler:"refetchDataSource",params:{dataSourceId:"{{dataSourceId}}",sync:"{{sync}}"}}},appendDataSource:{label:`$t:${ce}.append_data.label`,params:[{key:"dataSourceId",label:`$t:${ce}.append_data.param_data_source`,widget:"datasource-picker",required:!0},{key:"dataPath",label:`$t:${ce}.append_data.param_data_path`,widget:"text"},{key:"newData",label:`$t:${ce}.append_data.param_new_data`,widget:"data-chip"}],build:{handler:"appendDataSource",params:{dataSourceId:"{{dataSourceId}}",dataPath:"{{dataPath}}",newData:"{{newData}}"}}},updateDataSource:{label:`$t:${ce}.update_data.label`,params:[{key:"dataSourceId",label:`$t:${ce}.update_data.param_data_source`,widget:"datasource-picker",required:!0},{key:"data",label:`$t:${ce}.update_data.param_data`,widget:"data-chip"},{key:"merge",label:`$t:${ce}.update_data.param_merge`,widget:"toggle"}],build:{handler:"updateDataSource",params:{dataSourceId:"{{dataSourceId}}",data:"{{data}}",merge:"{{merge}}"}}},scrollIntoView:{label:`$t:${ce}.scroll.label`,params:[{key:"selector",label:`$t:${ce}.scroll.param_selector`,widget:"text",required:!0},{key:"behavior",label:`$t:${ce}.scroll.param_behavior`,widget:"select",options:[{value:"smooth"},{value:"auto"}]},{key:"block",label:`$t:${ce}.scroll.param_block`,widget:"select",options:[{value:"start"},{value:"center"},{value:"end"},{value:"nearest"}]}],build:{handler:"scrollIntoView",params:{selector:"{{selector}}",behavior:"{{behavior}}",block:"{{block}}"}}},login:{label:`$t:${ce}.login.label`,params:[{key:"body",label:`$t:${ce}.login.param_body`,widget:"key-value"}],build:{handler:"login",params:{body:"{{body}}"}}},logout:{label:`$t:${ce}.logout.label`,params:[{key:"target",label:`$t:${ce}.logout.param_target`,widget:"text"}],build:{handler:"logout",target:"{{target}}"}},setLocale:{label:`$t:${ce}.set_locale.label`,params:[{key:"target",label:`$t:${ce}.set_locale.param_target`,widget:"locale-picker",required:!0}],build:{handler:"setLocale",target:"{{target}}"}},emitEvent:{label:`$t:${ce}.emit_event.label`,params:[{key:"event",label:`$t:${ce}.emit_event.param_event`,widget:"text",required:!0},{key:"data",label:`$t:${ce}.emit_event.param_data`,widget:"data-chip"}],build:{handler:"emitEvent",params:{event:"{{event}}",data:"{{data}}"}}},apiCall:{label:`$t:${ce}.api_call.label`,params:[{key:"target",label:`$t:${ce}.api_call.param_target`,widget:"page-picker",required:!0},{key:"method",label:`$t:${ce}.api_call.param_method`,widget:"select",options:[{value:"GET"},{value:"POST"},{value:"PUT"},{value:"PATCH"},{value:"DELETE"}]},{key:"body",label:`$t:${ce}.api_call.param_body`,widget:"key-value"},{key:"query",label:`$t:${ce}.api_call.param_query`,widget:"key-value"},{key:"identity_target_email",label:`$t:${ce}.api_call.param_identity_target_email`,widget:"data-chip"},{key:"identity_target_phone",label:`$t:${ce}.api_call.param_identity_target_phone`,widget:"data-chip"},{key:"onSuccess",label:`$t:${ce}.api_call.param_on_success`,widget:"action-list"},{key:"onError",label:`$t:${ce}.api_call.param_on_error`,widget:"action-list"}],build:{handler:"apiCall",target:"{{target}}",identity_target:{email:"{{identity_target_email}}",phone:"{{identity_target_phone}}"},onSuccess:"{{onSuccess}}",onError:"{{onError}}",params:{method:"{{method}}",body:"{{body}}",query:"{{query}}"}}},conditions:{label:`$t:${ce}.conditions.label`,params:[{key:"branches",label:`$t:${ce}.conditions.param_branches`,widget:"branch-list"}],build:{handler:"conditions",conditions:"{{branches}}"}},sequence:{label:`$t:${ce}.sequence.label`,params:[{key:"actions",label:`$t:${ce}.sequence.param_actions`,widget:"action-list"}],build:{handler:"sequence",params:{actions:"{{actions}}"}}},parallel:{label:`$t:${ce}.parallel.label`,params:[{key:"actions",label:`$t:${ce}.parallel.param_actions`,widget:"action-list"}],build:{handler:"parallel",params:{actions:"{{actions}}"}}},switch:{label:`$t:${ce}.switch.label`,params:[{key:"value",label:`$t:${ce}.switch.param_value`,widget:"data-chip"},{key:"cases",label:`$t:${ce}.switch.param_cases`,widget:"action-list",advanced:!0}],build:{handler:"switch",params:{value:"{{value}}",cases:"{{cases}}"}}},suppress:{label:`$t:${ce}.suppress.label`,params:[],build:{handler:"suppress"}}};function $D(){return{actionRecipes:bn,initActionRecipes:bn,errorRecipes:{navigate:bn.navigate,openModal:bn.openModal,toast:bn.toast,setState:bn.setState,sequence:bn.sequence,parallel:bn.parallel,showErrorPage:{label:`$t:${ce}.show_error_page.label`,params:[{key:"target",label:`$t:${ce}.show_error_page.param_target`,widget:"select",options:[{value:"content"},{value:"full"}]}],build:{handler:"showErrorPage",params:{target:"{{target}}"}}}}}}function Qa(e,t){return typeof e.label=="string"?e.label.startsWith("$t:")?t(e.label.slice(3)):e.label:String(e.value)}function vi(e){return Array.isArray(e.options)?e.options:[]}function ED({control:e,value:t,onChange:n,t:o}){const r=vi(e);return i.jsx("div",{className:"g7le-widget g7le-widget--segmented","data-testid":"g7le-widget-segmented",style:WD,children:r.map(s=>{const a=s.value===t;return i.jsx("button",{type:"button","data-testid":`g7le-segment-${String(s.value)}`,"data-active":a?"true":"false",onClick:()=>n(a?void 0:s.value),style:{...GD,background:a?"#2563eb":"#fff",color:a?"#fff":"#0f172a",borderColor:a?"#2563eb":"#cbd5e1"},children:Qa(s,o)},String(s.value))})})}function ID({control:e,value:t,onChange:n,t:o}){const r=Array.isArray(e.scale)?e.scale:[],s=r.findIndex(l=>l===t),a=t!=null;return i.jsxs("div",{className:"g7le-widget g7le-widget--slider","data-testid":"g7le-widget-slider",style:Dg,children:[i.jsxs("label",{style:Ra,children:[i.jsx("input",{type:"checkbox","data-testid":"g7le-slider-enabled",checked:a,onChange:l=>{l.target.checked?n(r.length>0?r[Math.max(0,s===-1?0:s)]:void 0):n(void 0)}}),i.jsx("span",{style:{fontSize:12,color:"#64748b"},children:o("layout_editor.control.use")})]}),i.jsx("input",{type:"range","data-testid":"g7le-slider-range",min:0,max:Math.max(0,r.length-1),step:1,disabled:!a||r.length===0,value:s===-1?0:s,onChange:l=>{const d=Number(l.target.value);n(r[d])},style:{flex:1}}),i.jsx("span",{"data-testid":"g7le-slider-value",style:{fontSize:12,color:"#0f172a",minWidth:48,textAlign:"right"},children:a?String(t):o("layout_editor.control.default")})]})}function AD({control:e,value:t,onChange:n,t:o}){const r=vi(e);return i.jsxs("select",{className:"g7le-widget g7le-widget--select","data-testid":"g7le-widget-select",value:t==null?"":String(t),onChange:s=>{const a=s.target.value;if(a===""){n(void 0);return}const l=r.find(d=>String(d.value)===a);n(l?l.value:a)},style:YD,children:[i.jsx("option",{value:"",children:o("layout_editor.control.default")}),r.map(s=>i.jsx("option",{value:String(s.value),children:Qa(s,o)},String(s.value)))]})}function TD({control:e,value:t,onChange:n}){const o=vi(e),r=o[1]?.value??!0,s=o[0]?.value??void 0,a=t===r;return i.jsx("button",{type:"button",className:"g7le-widget g7le-widget--toggle","data-testid":"g7le-widget-toggle",role:"switch","aria-checked":a,onClick:()=>n(a?s:r),style:{...XD,background:a?"#2563eb":"#cbd5e1"},children:i.jsx("span",{style:{...JD,transform:a?"translateX(18px)":"translateX(0)"}})})}function DD({control:e,value:t,onChange:n,t:o,freeValueDisabled:r}){const s=vi(e),a=t==null?"":String(t),[l,d]=u.useState(a);u.useEffect(()=>{d(a)},[a]);const c=p=>{const f=p.trim();if(f===""){n(void 0);return}n(f)};return i.jsxs("div",{className:"g7le-widget g7le-widget--dimension","data-testid":"g7le-widget-dimension",style:jD,children:[r?i.jsx("div",{"data-testid":"g7le-dimension-free-disabled",style:UD,children:o("layout_editor.property_modal.dark_preset_only")}):i.jsxs("div",{style:HD,children:[i.jsx("input",{type:"text","data-testid":"g7le-dimension-input",value:l,placeholder:o("layout_editor.control.dimension.placeholder"),onChange:p=>d(p.target.value),onBlur:p=>c(p.target.value),onKeyDown:p=>{p.key==="Enter"&&(p.preventDefault(),c(p.target.value))},style:FD}),i.jsx("button",{type:"button","data-testid":"g7le-dimension-clear",title:o("layout_editor.control.default"),onClick:()=>{d(""),n(void 0)},style:KD,children:o("layout_editor.control.default")})]}),s.length>0&&i.jsx("div",{style:VD,"data-testid":"g7le-dimension-chips",children:s.map(p=>{const f=String(p.value),y=f===a;return i.jsx("button",{type:"button","data-testid":`g7le-dimension-chip-${f}`,"data-active":y?"true":"false",onClick:()=>{d(f),n(f)},style:{...qD,background:y?"#2563eb":"#fff",color:y?"#fff":"#0f172a",borderColor:y?"#2563eb":"#cbd5e1"},children:Qa(p,o)},f)})})]})}function ND(e){return[{key:"t",infix:`${e}t-`,labelKey:"layout_editor.control.spacing.top"},{key:"r",infix:`${e}r-`,labelKey:"layout_editor.control.spacing.right"},{key:"b",infix:`${e}b-`,labelKey:"layout_editor.control.spacing.bottom"},{key:"l",infix:`${e}l-`,labelKey:"layout_editor.control.spacing.left"}]}function zD(e,t,n,o){const r={all:-1,sides:{}};if(typeof e!="string"||e.trim()==="")return r;const s=e.split(/\s+/).filter(a=>a.length>0);for(const a of s){const l=n.find(d=>a.startsWith(d.infix));if(l){r.sides[l.key]=o.indexOf(a.slice(l.infix.length));continue}if(a.startsWith(`${t}x-`)){const d=o.indexOf(a.slice(`${t}x-`.length));r.sides.l=d,r.sides.r=d;continue}if(a.startsWith(`${t}y-`)){const d=o.indexOf(a.slice(`${t}y-`.length));r.sides.t=d,r.sides.b=d;continue}a.startsWith(`${t}-`)&&(r.all=o.indexOf(a.slice(`${t}-`.length)))}return r}function MD({control:e,value:t,onChange:n,t:o}){const r=typeof e.spacingPrefix=="string"?e.spacingPrefix:"p",s=(Array.isArray(e.scale)?e.scale:[]).map(b=>String(b)),a=ND(r),l=zD(t,r,a,s),d=Object.values(l.sides).some(b=>b>=0),c=l.all>=0||d,[p,f]=u.useState(d);u.useEffect(()=>{d&&f(!0)},[d]);const y=Math.min(4,Math.max(0,s.length-1)),g=b=>{const x=[];for(const k of a){const w=b[k.key];w!==void 0&&w>=0&&x.push(`${k.infix}${s[w]}`)}n(x.length>0?x.join(" "):void 0)},m=b=>{n(b>=0?`${r}-${s[Math.max(0,Math.min(b,s.length-1))]}`:void 0)},h=()=>({...l.sides}),v=(b,x,k,w,_)=>{const C=k>=0;return i.jsxs("div",{style:BD,"data-testid":b,children:[i.jsxs("label",{style:{...Ra,minWidth:64},children:[i.jsx("input",{type:"checkbox","data-testid":`${b}-enabled`,checked:C,onChange:E=>_(E.target.checked)}),i.jsx("span",{style:{fontSize:12,color:"#0f172a"},children:o(x)})]}),i.jsx("input",{type:"range","data-testid":`${b}-range`,min:0,max:Math.max(0,s.length-1),step:1,disabled:!C||s.length===0,value:k<0?0:k,onChange:E=>w(Number(E.target.value)),style:{flex:1}}),i.jsx("span",{"data-testid":`${b}-value`,style:{fontSize:12,color:C?"#0f172a":"#94a3b8",minWidth:28,textAlign:"right"},children:C?s[k]:"–"})]},b)};return i.jsxs("div",{className:"g7le-widget g7le-widget--spacing","data-testid":"g7le-widget-spacing",style:LD,children:[i.jsxs("div",{style:PD,children:[i.jsxs("div",{style:OD,"data-testid":"g7le-spacing-mode",children:[i.jsx("button",{type:"button","data-testid":"g7le-spacing-mode-all","data-active":p?"false":"true",onClick:()=>{f(!1),d&&n(void 0)},style:{...Tg,background:p?"#fff":"#2563eb",color:p?"#0f172a":"#fff",borderColor:p?"#cbd5e1":"#2563eb"},children:o("layout_editor.control.spacing.mode_all")}),i.jsx("button",{type:"button","data-testid":"g7le-spacing-mode-sides","data-active":p?"true":"false",onClick:()=>{if(f(!0),l.all>=0){const b={};for(const x of a)b[x.key]=l.all;g(b)}},style:{...Tg,background:p?"#2563eb":"#fff",color:p?"#fff":"#0f172a",borderColor:p?"#2563eb":"#cbd5e1"},children:o("layout_editor.control.spacing.mode_sides")})]}),i.jsx("span",{"data-testid":"g7le-spacing-value",style:{fontSize:11,color:"#64748b",minWidth:80,textAlign:"right"},children:c?String(t):o("layout_editor.control.default")})]}),p?i.jsx("div",{"data-testid":"g7le-spacing-sides",style:{display:"flex",flexDirection:"column",gap:4},children:a.map(b=>v(`g7le-spacing-side-${b.key}`,b.labelKey,l.sides[b.key]??-1,x=>{const k=h();k[b.key]=x,g(k)},x=>{const k=h();x?k[b.key]=l.sides[b.key]>=0?l.sides[b.key]:y:delete k[b.key],g(k)}))}):i.jsxs("div",{style:Dg,children:[i.jsxs("label",{style:{...Ra,minWidth:64},children:[i.jsx("input",{type:"checkbox","data-testid":"g7le-spacing-all-enabled",checked:l.all>=0,onChange:b=>m(b.target.checked?y:-1)}),i.jsx("span",{style:{fontSize:12,color:"#64748b"},children:o("layout_editor.control.spacing.all")})]}),i.jsx("input",{type:"range","data-testid":"g7le-spacing-all-range",min:0,max:Math.max(0,s.length-1),step:1,disabled:l.all<0||s.length===0,value:l.all<0?0:l.all,onChange:b=>m(Number(b.target.value)),style:{flex:1}}),i.jsx("span",{"data-testid":"g7le-spacing-all-value",style:{fontSize:12,color:l.all>=0?"#0f172a":"#94a3b8",minWidth:28,textAlign:"right"},children:l.all>=0?s[l.all]:"–"})]})]})}const LD={display:"flex",flexDirection:"column",gap:6,width:"100%"},PD={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},OD={display:"inline-flex",gap:0,border:"1px solid #cbd5e1",borderRadius:6,overflow:"hidden"},Tg={padding:"3px 10px",fontSize:11,border:"none",borderRight:"1px solid #e2e8f0",cursor:"pointer"},BD={display:"flex",alignItems:"center",gap:8,width:"100%"},WD={display:"inline-flex",gap:0,border:"1px solid #cbd5e1",borderRadius:6,overflow:"hidden"},jD={display:"flex",flexDirection:"column",gap:6,width:"100%"},HD={display:"flex",gap:6,alignItems:"center"},FD={flex:1,padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,minWidth:80},KD={padding:"4px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#64748b",cursor:"pointer",whiteSpace:"nowrap"},VD={display:"flex",flexWrap:"wrap",gap:4},UD={fontSize:11,color:"#94a3b8",fontStyle:"italic",padding:"2px 0"},qD={padding:"3px 9px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:999,background:"#fff",cursor:"pointer"},GD={padding:"4px 10px",fontSize:12,border:"none",borderRight:"1px solid #e2e8f0",cursor:"pointer"},Dg={display:"flex",alignItems:"center",gap:8,width:"100%"},Ra={display:"inline-flex",alignItems:"center",gap:4},YD={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",minWidth:120},XD={position:"relative",width:38,height:20,borderRadius:10,border:"none",cursor:"pointer",padding:2,display:"inline-flex",alignItems:"center",transition:"background 120ms ease"},JD={display:"block",width:16,height:16,borderRadius:8,background:"#fff",transition:"transform 120ms ease"},ZD=["#0f172a","#334155","#64748b","#94a3b8","#e2e8f0","#ffffff","#dc2626","#ea580c","#d97706","#16a34a","#0891b2","#2563eb","#7c3aed","#db2777"],Ng=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function QD(e){return Array.isArray(e.options)?e.options.filter(t=>typeof t.value=="string").map(t=>({value:t.value,swatch:typeof t.swatch=="string"?t.swatch:void 0,label:typeof t.label=="string"?t.label:void 0})):[]}function RD({control:e,value:t,onChange:n,t:o,freeValueDisabled:r}){const s=QD(e),a=s.length>0,l=typeof t=="string"&&s.some(g=>g.value===t)?t:"",d=typeof t=="string"&&Ng.test(t)?t:"",[c,p]=u.useState(d);u.useEffect(()=>{p(d)},[d]);const f=g=>{const m=g.trim();if(m===""){n(void 0);return}const h=m.startsWith("#")?m:`#${m}`;Ng.test(h)&&n(h)},y=ZD;return i.jsxs("div",{className:"g7le-widget g7le-widget--color","data-testid":"g7le-widget-color",style:eN,children:[r?i.jsx("div",{"data-testid":"g7le-color-free-disabled",style:sN,children:o("layout_editor.property_modal.dark_preset_only")}):i.jsxs("div",{style:tN,children:[i.jsxs("label",{style:nN,children:[i.jsx("span",{"data-testid":"g7le-color-swatch",style:{...oN,background:d||"transparent",backgroundImage:d?void 0:"linear-gradient(45deg,#e2e8f0 25%,transparent 25%,transparent 75%,#e2e8f0 75%),linear-gradient(45deg,#e2e8f0 25%,#fff 25%,#fff 75%,#e2e8f0 75%)",backgroundSize:"8px 8px",backgroundPosition:"0 0, 4px 4px"}}),i.jsx("input",{type:"color","data-testid":"g7le-color-native",value:d||"#000000",onChange:g=>n(g.target.value),style:{width:0,height:0,opacity:0,position:"absolute"}})]}),i.jsx("input",{type:"text","data-testid":"g7le-color-hex",value:c,placeholder:o("layout_editor.control.color_hex_placeholder"),onChange:g=>p(g.target.value),onBlur:g=>f(g.target.value),onKeyDown:g=>{g.key==="Enter"&&f(g.target.value)},style:rN}),i.jsx("button",{type:"button","data-testid":"g7le-color-clear",onClick:()=>n(void 0),style:iN,children:o("layout_editor.control.default")})]}),a?i.jsx("div",{style:zg,"data-testid":"g7le-color-token-presets",children:s.map(g=>{const m=l===g.value,h=g.label?g.label.startsWith("$t:")?o(g.label.slice(3)):g.label:g.value;return i.jsx("button",{type:"button","aria-label":h,title:h,"data-testid":`g7le-color-token-${g.value}`,"data-active":m?"true":"false",onClick:()=>n(m?void 0:g.value),style:{...Mg,background:g.swatch||"#e2e8f0",outline:m?"2px solid #2563eb":"none"}},g.value)})}):!r&&i.jsx("div",{style:zg,"data-testid":"g7le-color-presets",children:y.map(g=>i.jsx("button",{type:"button","aria-label":g,"data-testid":`g7le-color-preset-${g}`,onClick:()=>n(g),style:{...Mg,background:g,outline:d.toLowerCase()===g.toLowerCase()?"2px solid #2563eb":"none"}},g))})]})}const eN={display:"flex",flexDirection:"column",gap:8},tN={display:"flex",alignItems:"center",gap:6},nN={position:"relative",display:"inline-flex",cursor:"pointer"},oN={width:24,height:24,borderRadius:4,border:"1px solid #cbd5e1",display:"inline-block"},rN={flex:1,padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,fontFamily:"monospace"},iN={padding:"4px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",cursor:"pointer",color:"#64748b"},zg={display:"grid",gridTemplateColumns:"repeat(7, 1fr)",gap:4},Mg={width:"100%",height:18,borderRadius:4,border:"1px solid #cbd5e1",cursor:"pointer",padding:0},sN={fontSize:11,color:"#94a3b8",fontStyle:"italic",padding:"2px 0"},Qo=[{value:"fill",labelKey:"layout_editor.control.background_image.mode_fill",size:"cover",repeat:"no-repeat"},{value:"fit",labelKey:"layout_editor.control.background_image.mode_fit",size:"contain",repeat:"no-repeat"},{value:"tile",labelKey:"layout_editor.control.background_image.mode_tile",size:"auto",repeat:"repeat"}];function aN(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function Lg(e){return Qo.find(n=>n.size===e.size&&n.repeat===e.repeat)?.value??"fill"}function lN({value:e,onChange:t,t:n}){const o=aN(e),{state:r}=Je(),s=yo(),[a,l]=u.useState(!1),[d,c]=u.useState(null),[p,f]=u.useState(o.url??""),[y,g]=u.useState([]),m=u.useRef(null),h=r.templateIdentifier,v=r.selectedRoute?.layoutName??"";u.useEffect(()=>{f(o.url??"")},[o.url]);const b=u.useCallback(async()=>{if(!h||!v){g([]);return}const E=await Dl(h,v);E.ok&&g(E.data)},[h,v]);u.useEffect(()=>{b()},[b]);const x=E=>{if(!E){t(void 0);return}const S=Qo.find(T=>T.value===Lg(o))??Qo[0];t({url:E,size:o.size??S.size,repeat:o.repeat??S.repeat,position:o.position??"center"})},k=E=>{const S=Qo.find(T=>T.value===E);!S||!o.url||t({url:o.url,size:S.size,repeat:S.repeat,position:o.position??"center"})},w=async E=>{const S=E.target.files?.[0];if(!S)return;l(!0),c(null);const T=await Nl(h,v,S);T.ok?(x(T.data.url),b()):c(n("layout_editor.control.background_image.upload_failed")),l(!1),m.current&&(m.current.value="")},_=async E=>{(await zl(E.id)).ok&&g(T=>T.filter($=>$.id!==E.id))},C=()=>{const E=s.open({ariaLabel:n("layout_editor.attachment_manager.title"),width:720,maxHeightRatio:.82,content:u.createElement(Ml,{templateIdentifier:h,layoutName:v,t:n,onSelect:S=>{x(S),s.close(E)},onChanged:()=>{b()},onClose:()=>s.close(E)})})};return i.jsxs("div",{className:"g7le-widget g7le-widget--image","data-testid":"g7le-widget-image",style:dN,children:[o.url&&i.jsx("div",{"data-testid":"g7le-image-preview",style:{...cN,backgroundImage:`url(${o.url})`,backgroundSize:o.size??"cover",backgroundRepeat:o.repeat??"no-repeat",backgroundPosition:o.position??"center"}}),i.jsxs("div",{style:uN,children:[i.jsxs("label",{style:pN,children:[a?"…":n("layout_editor.control.background_image.upload"),i.jsx("input",{ref:m,type:"file",accept:"image/*","data-testid":"g7le-image-file",onChange:w,disabled:a,style:{display:"none"}})]}),i.jsx("button",{type:"button","data-testid":"g7le-image-clear",onClick:()=>t(void 0),style:fN,children:n("layout_editor.control.background_image.clear")})]}),i.jsx("input",{type:"text","data-testid":"g7le-image-url",placeholder:"https://… / URL",value:p,onChange:E=>f(E.target.value),onBlur:E=>x(E.target.value.trim()||void 0),style:gN}),i.jsx("div",{style:hN,"data-testid":"g7le-image-modes",children:Qo.map(E=>{const S=Lg(o)===E.value;return i.jsx("button",{type:"button","data-testid":`g7le-image-mode-${E.value}`,"data-active":S?"true":"false",disabled:!o.url,onClick:()=>k(E.value),style:{...yN,background:S&&o.url?"#2563eb":"#fff",color:S&&o.url?"#fff":"#0f172a"},children:n(E.labelKey)},E.value)})}),i.jsxs("div",{style:bN,"data-testid":"g7le-image-gallery",children:[i.jsxs("div",{style:mN,children:[i.jsx("span",{style:{fontSize:11,color:"#64748b"},children:n("layout_editor.attachment_manager.recent")}),i.jsxs("button",{type:"button","data-testid":"g7le-image-manage",onClick:C,style:vN,children:["🖼 ",n("layout_editor.attachment_manager.manage_link")]})]}),y.length>0?i.jsx("div",{style:_N,"data-testid":"g7le-image-thumbs",children:y.slice(0,8).map(E=>i.jsxs("div",{style:xN,"data-testid":`g7le-image-thumb-${E.id}`,children:[i.jsx("button",{type:"button",title:E.original_name,onClick:()=>x(E.url),style:{...wN,backgroundImage:`url(${E.url})`},"data-testid":`g7le-image-thumb-use-${E.id}`}),i.jsx("button",{type:"button",title:n("layout_editor.attachment_manager.delete"),onClick:()=>_(E),style:kN,"data-testid":`g7le-image-thumb-del-${E.id}`,children:"✕"})]},E.id))}):i.jsx("span",{style:{fontSize:11,color:"#94a3b8"},children:n("layout_editor.attachment_manager.empty")})]}),d&&i.jsx("span",{"data-testid":"g7le-image-error",style:{fontSize:11,color:"#dc2626"},children:d})]})}const dN={display:"flex",flexDirection:"column",gap:6},cN={width:"100%",height:80,borderRadius:6,border:"1px solid #cbd5e1"},uN={display:"flex",gap:6},pN={padding:"5px 10px",fontSize:12,border:"1px solid #2563eb",borderRadius:6,background:"#fff",color:"#2563eb",cursor:"pointer",display:"inline-flex",alignItems:"center"},fN={padding:"5px 10px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#64748b",cursor:"pointer"},gN={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},hN={display:"inline-flex",border:"1px solid #cbd5e1",borderRadius:6,overflow:"hidden"},yN={padding:"4px 10px",fontSize:12,border:"none",borderRight:"1px solid #e2e8f0",cursor:"pointer"},bN={display:"flex",flexDirection:"column",gap:4,border:"1px solid #e2e8f0",borderRadius:6,padding:6,marginTop:2},mN={display:"flex",alignItems:"center",justifyContent:"space-between"},vN={fontSize:11,color:"#2563eb",background:"transparent",border:"none",cursor:"pointer",padding:0},_N={display:"flex",gap:6,flexWrap:"wrap"},xN={position:"relative",width:44,height:44},wN={width:44,height:44,borderRadius:6,border:"1px solid #cbd5e1",backgroundSize:"cover",backgroundPosition:"center",cursor:"pointer",padding:0},kN={position:"absolute",top:-6,right:-6,width:16,height:16,borderRadius:"50%",border:"none",background:"#dc2626",color:"#fff",fontSize:9,lineHeight:"16px",cursor:"pointer",padding:0};function SN(e){return Array.isArray(e)&&e.every(t=>t!==null&&typeof t=="object"&&!Array.isArray(t))}function CN(e){return typeof e=="string"&&/\{\{.*\}\}/.test(e)}function $N({value:e,onChange:t,t:n,bindingCandidates:o}){if(CN(e))return i.jsx("div",{className:"g7le-widget g7le-widget--options-list","data-testid":"g7le-widget-options-list-bound",style:MN,children:n("layout_editor.list_editor.bound_degraded")});const r=SN(e)?e:[],s=y=>{t(y.length===0?void 0:y)},a=(y,g)=>{const m=r.map((h,v)=>v===y?{...h,...g}:h);s(m)},l=y=>{s(r.filter((g,m)=>m!==y))},d=(y,g)=>{const m=y+g;if(m<0||m>=r.length)return;const h=[...r];[h[y],h[m]]=[h[m],h[y]],s(h)},c=()=>{s([...r,{value:"",label:""}])},p=y=>typeof y.label=="string"?y.label:y.label==null?"":String(y.label),f=y=>y.value===void 0||y.value===null?"":String(y.value);return i.jsxs("div",{className:"g7le-widget g7le-widget--options-list","data-testid":"g7le-widget-options-list",style:EN,children:[r.length===0&&i.jsx("div",{"data-testid":"g7le-options-empty",style:zN,children:n("layout_editor.list_editor.empty")}),r.map((y,g)=>i.jsxs("div",{"data-testid":`g7le-options-row-${g}`,style:IN,children:[i.jsxs("div",{style:Pg,children:[i.jsx("span",{style:Og,children:n("layout_editor.list_editor.option_value")}),i.jsx("input",{type:"text","data-testid":`g7le-options-value-${g}`,value:f(y),placeholder:n("layout_editor.list_editor.option_value"),onChange:m=>a(g,{value:m.target.value}),style:TN})]}),i.jsxs("div",{style:Pg,children:[i.jsx("span",{style:Og,children:n("layout_editor.list_editor.option_label")}),i.jsx("div",{"data-testid":`g7le-options-label-${g}`,style:{flex:1,minWidth:0},children:i.jsx(vt,{value:p(y),onChange:m=>a(g,{label:m??""}),t:n,placeholder:n("layout_editor.list_editor.option_label"),testidPrefix:`g7le-options-label-i18n-${g}`,candidates:o,enableExpressionTree:!0,expressionTreeCollapsible:!0})})]}),i.jsxs("div",{style:AN,children:[i.jsx("button",{type:"button","data-testid":`g7le-options-up-${g}`,title:n("layout_editor.list_editor.move_up"),disabled:g===0,onClick:()=>d(g,-1),style:Bg,children:"↑"}),i.jsx("button",{type:"button","data-testid":`g7le-options-down-${g}`,title:n("layout_editor.list_editor.move_down"),disabled:g===r.length-1,onClick:()=>d(g,1),style:Bg,children:"↓"}),i.jsx("button",{type:"button","data-testid":`g7le-options-remove-${g}`,title:n("layout_editor.list_editor.remove"),onClick:()=>l(g),style:DN,children:"✕"})]})]},g)),i.jsx("button",{type:"button","data-testid":"g7le-options-add",onClick:c,style:NN,children:n("layout_editor.list_editor.add")})]})}const EN={display:"flex",flexDirection:"column",gap:8,width:"100%"},IN={display:"flex",flexDirection:"column",gap:4,width:"100%",minWidth:0,paddingBottom:6,borderBottom:"1px solid #f1f5f9"},Pg={display:"flex",gap:6,alignItems:"center",width:"100%",minWidth:0},Og={flexShrink:0,width:36,fontSize:11,color:"#94a3b8",textAlign:"right"},AN={display:"flex",gap:4,alignItems:"center",justifyContent:"flex-end"},TN={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},Bg={padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},DN={padding:"2px 6px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},NN={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},zN={fontSize:11,color:"#94a3b8",fontStyle:"italic"},MN={fontSize:11,color:"#b45309",fontStyle:"italic",padding:"4px 2px"},Wg=/[^A-Za-z0-9\-_:.]/g;function LN(e){return typeof e=="string"&&Ui(e)}function jg(e){return Ui(e)?In(e).map(t=>t.kind==="binding"?t.raw:t.raw.replace(Wg,"")).join(""):e.replace(Wg,"")}const PN={width:"100%",padding:"6px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:4,fontFamily:"monospace"},ON={marginTop:4,fontSize:11,color:"#94a3b8"},BN={display:"flex",gap:6,alignItems:"center"},WN={flexShrink:0,padding:"5px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:4,background:"#f8fafc",cursor:"pointer",whiteSpace:"nowrap"};function jN({value:e,onChange:t,t:n,bindingCandidates:o}){const r=e==null?"":String(e),s=LN(e),a=!!o&&o.length>0,[l,d]=u.useState(!1),c=p=>{const f=jg(p);t(f===""?void 0:f)};return s||l?i.jsxs("div",{"data-testid":"g7le-core-id-chip",children:[i.jsx(bs,{value:r,onChange:c,t:n,candidates:o,onDone:()=>d(!1),testidPrefix:"g7le-core-id-chip-input"}),i.jsx("div",{style:ON,children:n("layout_editor.core_props.id.binding_hint")})]}):i.jsx("div",{children:i.jsxs("div",{style:BN,children:[i.jsx("input",{type:"text",className:"g7le-widget g7le-widget--core-id","data-testid":"g7le-widget-core-id",value:r,onChange:p=>{const f=jg(p.target.value);t(f===""?void 0:f)},spellCheck:!1,autoComplete:"off",style:PN}),a&&i.jsxs("button",{type:"button","data-testid":"g7le-core-id-add-data",onClick:()=>d(!0),style:WN,title:n("layout_editor.core_props.id.add_data"),children:["🔗 ",n("layout_editor.core_props.id.add_data")]})]})})}const HN=/[^A-Za-z0-9.\-_]/g;function FN(e){return typeof e=="string"&&/\{\{[\s\S]*?\}\}/.test(e)}function KN(e){return e.replace(HN,"")}const Hg={width:"100%",padding:"6px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:4,fontFamily:"monospace",boxSizing:"border-box"},VN={...Hg,background:"#f1f5f9",color:"#64748b",cursor:"not-allowed"},Fg={marginTop:4,fontSize:11,color:"#94a3b8"};function UN({value:e,onChange:t,t:n}){const o=e==null?"":String(e);return FN(e)?i.jsxs("div",{"data-testid":"g7le-core-datakey-bound",children:[i.jsx("input",{type:"text",className:"g7le-widget g7le-widget--core-datakey-bound","data-testid":"g7le-widget-core-datakey",value:o,readOnly:!0,disabled:!0,style:VN}),i.jsx("div",{style:Fg,children:n("layout_editor.core_props.dataKey.bound_degraded")})]}):i.jsxs("div",{children:[i.jsx("input",{type:"text",className:"g7le-widget g7le-widget--core-datakey","data-testid":"g7le-widget-core-datakey",value:o,placeholder:n("layout_editor.core_props.dataKey.placeholder"),onChange:s=>{const a=KN(s.target.value);t(a===""?void 0:a)},spellCheck:!1,autoComplete:"off",style:Hg}),i.jsx("div",{style:Fg,children:n("layout_editor.core_props.dataKey.hint")})]})}let Kg=!1;function qN(){Kg||(Xe("segmented",ED),Xe("slider",ID),Xe("select",AD),Xe("dimension",DD),Xe("spacing",MD),Xe("toggle",TD),Xe("color",RD),Xe("image",lN),Xe("tag-input",ys),Xe("page-picker",Aw),Xe("datasource-picker",Bc),Xe("binding-picker",Bc),Xe("binding-list",Nw),Xe("state-key-picker",Es),Xe("modal-picker",Tw),Xe("i18n-text",Dw),Xe("text",zw),Xe("options-list",$N),Xe("core-id",jN),Xe("core-datakey",UN),Xe("component-target-picker",jT),Kg=!0)}function Ro(e){return Array.isArray(e.children)?e.children:[]}function er(e){if(typeof e.text=="string")return[];let t=null;const n=(o,r)=>{const s=Ro(o);for(let a=0;ad===o?tr(l,r,n):l);return{...e,children:a}}function Vg(e,t){const n=r=>typeof r.props?.[t]=="string";if(n(e))return[];const o=(r,s)=>{const a=Ro(r);for(let l=0;lc===r?Ug(d,s,n,o):d);return{...e,children:l}}function GN(e){return Array.isArray(e.children)?e.children:[]}function YN(e){const t=e?.itemFields;if(!Array.isArray(t))return[{kind:"text"}];const n=[];for(const o of t){if(!o||typeof o!="object")continue;const r=o;r.kind==="text"?n.push({kind:"text",label:typeof r.label=="string"?r.label:void 0}):r.kind==="prop"&&typeof r.prop=="string"&&r.prop.length>0&&n.push({kind:"prop",prop:r.prop,label:typeof r.label=="string"?r.label:void 0})}return n.length>0?n:[{kind:"text"}]}function el(e,t){if(!(typeof e!="string"||e.length===0))return e.startsWith("$t:")?t(e.slice(3)):e}function qg({node:e,params:t,spec:n,manifest:o,t:r,onPatchNode:s,templateIdentifier:a,candidates:l}){const d=typeof t?.childComponent=="string"?t.childComponent:null,c=t?.childTemplate&&typeof t.childTemplate=="object"?t.childTemplate:null,p=YN(t),f=el(typeof t?.childLabel=="string"?t.childLabel:void 0,r)??d??"",y=GN(e),g=u.useCallback(_=>{s({...e,children:_})},[e,s]),m=u.useCallback(()=>{if(c)return JSON.parse(JSON.stringify(c));if(!d)return null;const _=n?.componentPalette?.entries?.[d];if(_?.defaultNode&&typeof _.defaultNode=="object")return JSON.parse(JSON.stringify(_.defaultNode));const C=o?.components??{};let E=null;for(const S of Object.values(C))if(Array.isArray(S)){const T=S.find($=>$.name===d);if(T){E=T;break}}return E?$f(E):{type:"basic",name:d}},[c,d,n,o]),h=u.useCallback(()=>{const _=m();if(_){if(_.text==="")_.text=r("layout_editor.list_editor.new_item");else{const C=er(_);if(C!==null&&C.length>0){const E=_i(_,C);if(E&&E.text===""){const S=tr(_,C,r("layout_editor.list_editor.new_item"));g([...y,S]);return}}}g([...y,_])}},[m,g,y,r]),v=u.useCallback(_=>{g(y.filter((C,E)=>E!==_))},[g,y]),b=u.useCallback((_,C)=>{const E=_+C;if(E<0||E>=y.length)return;const S=[...y];[S[_],S[E]]=[S[E],S[_]],g(S)},[g,y]),x=u.useCallback((_,C)=>{if(typeof C!="string"||C.length===0)return;const E=y[_];if(!E)return;const S=er(E);if(S===null)return;const T=y.map(($,A)=>A===_?tr($,S,C):$);g(T)},[y,g]),k=u.useCallback((_,C,E)=>{if(typeof E!="string"||E.length===0)return;const S=y[_];if(!S)return;const T=Vg(S,C);if(T===null)return;const $=y.map((A,z)=>z===_?Ug(A,T,C,E):A);g($)},[y,g]);if(!d&&!c)return i.jsx("div",{className:"g7le-node-editor g7le-node-editor--children","data-testid":"g7le-children-editor-misconfigured",style:Xg,children:r("layout_editor.list_editor.no_child_component")});const w=p.length>1||p.some(_=>_.label);return i.jsxs("div",{className:"g7le-node-editor g7le-node-editor--children","data-testid":"g7le-children-editor",style:XN,children:[i.jsx("div",{style:JN,children:r("layout_editor.list_editor.items_title")}),y.length===0&&i.jsx("div",{"data-testid":"g7le-children-empty",style:Xg,children:r("layout_editor.list_editor.empty")}),y.map((_,C)=>{const E=[];for(const T of p)if(T.kind==="text"){const $=er(_),A=$!==null?_i(_,$):null;A&&typeof A.text=="string"&&E.push({key:"text",caption:el(T.label,r)??(w?r("layout_editor.list_editor.item_label"):void 0),value:A.text,onChange:z=>x(C,z),testid:`g7le-children-i18n-${C}`})}else if(T.kind==="prop"&&T.prop){const $=Vg(_,T.prop);if($!==null){const z=_i(_,$)?.props?.[T.prop];E.push({key:`prop-${T.prop}`,caption:el(T.label,r)??T.prop,value:typeof z=="string"?z:"",onChange:D=>k(C,T.prop,D),testid:`g7le-children-prop-${T.prop}-${C}`})}}const S=typeof _?.name=="string"?_.name:r("layout_editor.list_editor.item");return i.jsxs("div",{"data-testid":`g7le-children-row-${C}`,style:ZN,children:[E.length>0?E.map(T=>i.jsx("div",{style:Gg,children:i.jsxs("div",{"data-testid":T.key==="text"?`g7le-children-text-${C}`:`g7le-children-field-${T.key}-${C}`,style:QN,children:[T.caption!==void 0&&i.jsx("div",{"data-testid":`g7le-children-caption-${T.key}-${C}`,style:RN,children:T.caption}),i.jsx(vt,{value:T.value,onChange:T.onChange,t:r,placeholder:r("layout_editor.list_editor.item_text"),testidPrefix:T.testid,candidates:l,enableExpressionTree:!0,expressionTreeCollapsible:!0})]})},T.key)):i.jsx("div",{style:Gg,children:i.jsx("span",{"data-testid":`g7le-children-label-${C}`,style:t8,children:S})}),i.jsxs("div",{style:e8,children:[i.jsx("button",{type:"button","data-testid":`g7le-children-up-${C}`,title:r("layout_editor.list_editor.move_up"),disabled:C===0,onClick:()=>b(C,-1),style:Yg,children:"↑"}),i.jsx("button",{type:"button","data-testid":`g7le-children-down-${C}`,title:r("layout_editor.list_editor.move_down"),disabled:C===y.length-1,onClick:()=>b(C,1),style:Yg,children:"↓"}),i.jsx("button",{type:"button","data-testid":`g7le-children-remove-${C}`,title:r("layout_editor.list_editor.remove"),onClick:()=>v(C),style:n8,children:"✕"})]})]},C)}),i.jsx("button",{type:"button","data-testid":"g7le-children-add",onClick:h,style:o8,children:r("layout_editor.list_editor.add_child",{component:f})})]})}const XN={display:"flex",flexDirection:"column",gap:6,width:"100%",marginBottom:12},JN={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:2},ZN={display:"flex",flexDirection:"column",gap:4,width:"100%",minWidth:0,paddingBottom:6,borderBottom:"1px solid #f1f5f9"},Gg={display:"flex",gap:4,alignItems:"flex-start",width:"100%",minWidth:0},QN={flex:1,minWidth:0},RN={fontSize:11,color:"#64748b",marginBottom:2},e8={display:"flex",gap:4,alignItems:"center",justifyContent:"flex-end"},t8={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,color:"#475569",fontStyle:"italic",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},Yg={padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},n8={padding:"2px 6px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},o8={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},Xg={fontSize:11,color:"#94a3b8",fontStyle:"italic"},fo={rowContainer:"Tbody",row:"Tr",cell:"Td",headerCell:"Th",colSpanProp:"colSpan",rowSpanProp:"rowSpan"};function ht(e){return{rowContainer:e?.rowContainer??fo.rowContainer,row:e?.row??fo.row,cell:e?.cell??fo.cell,headerCell:e?.headerCell??fo.headerCell,colSpanProp:e?.colSpanProp??fo.colSpanProp,rowSpanProp:e?.rowSpanProp??fo.rowSpanProp}}function Bn(e){return e?Array.isArray(e.children)?e.children:[]:[]}function Jg(e,t){const n=e.props?.[t],o=typeof n=="number"?n:typeof n=="string"?parseInt(n,10):NaN;return Number.isFinite(o)&&o>=1?Math.floor(o):1}function Be(e,t){const n=ht(t),o=[],r=Bn(e),s=[];r.forEach((f,y)=>{(Bn(f).some(h=>h.name===n.row)||f.name===n.rowContainer||f.name==="Thead"||f.name==="Tfoot")&&s.push({container:f,containerIndex:y,isHeader:f.name==="Thead"})}),s.length===0&&r.some(f=>f.name===n.row)&&s.push({container:e,containerIndex:-1,isHeader:!1});const a=[],l=[];let d=0,c=0;const p=f=>{for(;a.length<=f;)a.push([]);return a[f]};s.forEach((f,y)=>{Bn(f.container).filter(m=>m.name===n.row).forEach((m,h)=>{const v=[],b=p(d);let x=0;Bn(m).filter(w=>w.name===n.cell||w.name===n.headerCell).forEach((w,_)=>{for(;b[x];)x++;const C=Jg(w,n.colSpanProp),E=Jg(w,n.rowSpanProp),S={cell:w,sectionIndex:y,rowIndexInSection:h,cellIndexInRow:_,gridRow:d,gridCol:x,colSpan:C,rowSpan:E,isHeader:w.name===n.headerCell};v.push(S);for(let T=0;T=0?(a.push(s.containerIndex),l=Bn(e)[s.containerIndex]??e):l=e;let d=-1,c=-1,p=null;const f=Bn(l);for(let m=0;m=r.gridRow&&t=r.gridCol&&nr){s=!0;break}if(s)break}s||t.add(r)}const n=Array.from(t).sort((r,s)=>r-s),o=[];for(let r=0;re.rows.find(l=>(l.cells[0]?.gridRow??-1)===a)?.sectionIndex??e.rows[a]?.sectionIndex??0,o=new Set([0,t]);for(let a=1;aa){l=!0;break}if(l)break}l||o.add(a)}const r=Array.from(o).sort((a,l)=>a-l),s=[];for(let a=0;at>=a.start&&t=o.length?{ok:!1,reason:"boundary"}:o[r].sectionIndex!==o[s].sectionIndex?{ok:!1,reason:"section"}:{ok:!0}}function wi(e,t,n){const o=Zg(e),r=o.findIndex(a=>t>=a.start&&t=o.length?{ok:!1,reason:"boundary"}:{ok:!0}}function Ge(e){return e?Array.isArray(e.children)?e.children:[]:[]}function mn(e,t,n){const o={...e.props??{}};n<=1?delete o[t]:o[t]=n;const r={...e,props:o};return Object.keys(o).length===0&&delete r.props,r}function ki(e,t,n=!1){const o={type:"basic",name:n?e.headerCell:e.cell},r=t?.props?.className;return typeof r=="string"&&r&&(o.props={className:r}),o.text="",o}function nr(e,t){return e.name===t.cell||e.name===t.headerCell}function nt(e,t,n,o){const r=t.sections[n];if(!r)return e;if(r.containerIndex===-1)return o(e);const s=Ge(e).map((a,l)=>l===r.containerIndex?o(a):a);return{...e,children:s}}function yt(e,t,n,o){let r=-1;const s=Ge(e).map(a=>a.name===t&&(r++,r===n)?o(a):a);return{...e,children:s}}function Si(e,t,n){let o=-1;const r=Ge(e);for(let s=0;s0?nt(e,r,r.sections.length-1,x=>({...x,children:[...Ge(x),b]})):{...e,children:[...Ge(e),b]}}const s=Math.max(-1,Math.min(n,r.rows.length-1)),a=s<0?r.rows[0]:r.rows[s],l=a.cells[0]?.gridRow??s,d=s<0?0:l+1,c=a.sectionIndex,p=s<0?0:a.rowIndexInSection+1,f=[],y=[];let g=0;for(;g0?Ue(r,d-1,g):null;b&&b.gridRow+b.rowSpan>d&&b.rowSpan>1?(y.push(b),g+=b.colSpan):(f.push(ki(o)),g+=1)}let m=e;for(const b of y)m=nt(m,r,b.sectionIndex,x=>yt(x,o.row,b.rowIndexInSection,k=>({...k,children:Ge(k).map((w,_)=>_===b.cellIndexInRow?mn(w,o.rowSpanProp,b.rowSpan+1):w)})));const h={type:"basic",name:o.row,children:f},v=Be(m,t);return m=nt(m,v,c,b=>{const x=Ge(b);let k=0,w=x.length;for(let _=0;_=r.rows.length||r.rows.length<=1)return e;const s=r.rows[n],a=s.cells[0]?.gridRow??n;let l=e;const d=new Set;for(let p=0;pyt(y,o.row,f.rowIndexInSection,g=>({...g,children:Ge(g).map((m,h)=>h===f.cellIndexInRow?mn(m,o.rowSpanProp,f.rowSpan-1):m)})))),p+=f?f.colSpan:1}const c=Be(l,t);return l=nt(l,c,s.sectionIndex,p=>{let f=-1;const y=Ge(p).filter(g=>g.name===o.row?(f++,f!==s.rowIndexInSection):!0);return{...p,children:y}}),l}function eh(e,t,n,o){const r=ht(t),s=Be(e,t);if(!xi(s,n,o).ok)return e;const a=Qg(s),l=a.findIndex(h=>n>=h.start&&ns.rows.filter(v=>{const b=v.cells[0]?.gridRow??-1;return v.sectionIndex===f&&b>=h.start&&bv.rowIndexInSection),g=y(c),m=y(p);return g.length===0||m.length===0?e:nt(e,s,f,h=>{const v=[...Ge(h)],b=[];v.forEach((M,B)=>{M.name===r.row&&b.push(B)});const x=g.map(M=>b[M]).filter(M=>M!==void 0),k=m.map(M=>b[M]).filter(M=>M!==void 0);if(x.length===0||k.length===0)return h;const w=x.map(M=>v[M]),_=k.map(M=>v[M]),C=Math.min(...x)n>=m.start&&nw.gridCol>=f.start&&w.gridColw.gridCol>=y.start&&w.gridColw.cellIndexInRow),x=v.map(w=>w.cellIndexInRow),k=Be(g,t);g=nt(g,k,m.sectionIndex,w=>yt(w,r.row,m.rowIndexInSection,_=>{const C=[...Ge(_)],E=b.map(M=>Si(_,r,M)).filter(M=>M>=0),S=x.map(M=>Si(_,r,M)).filter(M=>M>=0);if(E.length===0||S.length===0)return _;const T=E.map(M=>C[M]),$=S.map(M=>C[M]),A=Math.min(...E,...S),z=Math.max(...E,...S),D=[...$,...T],O=[...C.slice(0,A),...D,...C.slice(z+1)];return{..._,children:O}}))}return g}function nh(e,t,n){const o=ht(t),r=Be(e,t);if(r.rows.length===0||r.colCount===0)return nl(e,t,-1);const s=Math.max(0,Math.min(n+1,r.colCount));let a=e;const l=new Set;for(const d of r.rows){const c=d.cells[0]?.gridRow??0,p=s>0?Ue(r,c,s-1):null,f=s1){if(!l.has(p.cell)){l.add(p.cell);const h=Be(a,t);a=nt(a,h,p.sectionIndex,v=>yt(v,o.row,p.rowIndexInSection,b=>({...b,children:Ge(b).map((x,k)=>k===p.cellIndexInRow?mn(x,o.colSpanProp,p.colSpan+1):x)})))}continue}if(p&&p.gridRow0&&d.cells.every(h=>h.isHeader),m=Be(a,t);a=nt(a,m,d.sectionIndex,h=>yt(h,o.row,d.rowIndexInSection,v=>{const b=[...Ge(v)];let x;if(y<0)x=b.findIndex(k=>nr(k,o)),x<0&&(x=b.length);else{const k=Si(v,o,y);x=k<0?b.length:k+1}return b.splice(x,0,ki(o,void 0,g)),{...v,children:b}}))}return a}function oh(e,t,n){const o=ht(t),r=Be(e,t);if(n<0||n>=r.colCount||r.colCount<=1)return e;let s=e;const a=new Set;for(const l of r.rows){const d=l.cells[0]?.gridRow??0,c=Ue(r,d,n);if(!(!c||a.has(c.cell)||c.gridRow1){const p=Be(s,t);s=nt(s,p,c.sectionIndex,f=>yt(f,o.row,c.rowIndexInSection,y=>({...y,children:Ge(y).map((g,m)=>m===c.cellIndexInRow?mn(g,o.colSpanProp,c.colSpan-1):g)})))}else{const p=Be(s,t);s=nt(s,p,c.sectionIndex,f=>yt(f,o.row,c.rowIndexInSection,y=>{let g=-1;const m=Ge(y).filter(h=>nr(h,o)?(g++,g!==c.cellIndexInRow):!0);return{...y,children:m}}))}}return s}function ol(e,t,n,o,r,s){const a=ht(t),l=Be(e,t),d=Math.min(n,r),c=Math.max(n,r),p=Math.min(o,s),f=Math.max(o,s);if(d===c&&p===f)return{table:e,ok:!1,reason:"single"};if(!l.valid)return{table:e,ok:!1,reason:"invalid-grid"};const y=new Set;for(let b=d;b<=c;b++)for(let x=p;x<=f;x++){const k=Ue(l,b,x);if(!k)return{table:e,ok:!1,reason:"hole"};if(k.gridRowc||k.gridCol+k.colSpan-1>f)return{table:e,ok:!1,reason:"not-rectangular"};y.add(k)}const g=Ue(l,d,p),m=Array.from(y).filter(b=>b!==g);let h=nt(e,l,g.sectionIndex,b=>yt(b,a.row,g.rowIndexInSection,x=>({...x,children:Ge(x).map((k,w)=>{if(w!==g.cellIndexInRow)return k;let _=mn(k,a.colSpanProp,f-p+1);return _=mn(_,a.rowSpanProp,c-d+1),_})})));const v=new Map;for(const b of m){const x=`${b.sectionIndex}:${b.rowIndexInSection}`,k=v.get(x)??[];k.push(b),v.set(x,k)}for(const[b,x]of v){const k=parseInt(b.split(":")[0],10),w=x[0].rowIndexInSection,_=new Set(x.map(E=>E.cellIndexInRow)),C=Be(h,t);h=nt(h,C,k,E=>yt(E,a.row,w,S=>{let T=-1;const $=Ge(S).filter(A=>nr(A,a)?(T++,!_.has(T)):!0);return{...S,children:$}}))}return{table:h,ok:!0}}function rh(e,t,n,o){const r=ht(t),s=Be(e,t),a=Ue(s,n,o);if(!a||a.colSpan<=1&&a.rowSpan<=1)return e;const l=a.gridRow,d=a.gridCol,c=a.gridRow+a.rowSpan-1,p=a.gridCol+a.colSpan-1,f=a.isHeader,y=typeof a.cell.props?.className=="string"?a.cell.props.className:void 0;let g=nt(e,s,a.sectionIndex,m=>yt(m,r.row,a.rowIndexInSection,h=>({...h,children:Ge(h).map((v,b)=>{if(b!==a.cellIndexInRow)return v;let x=mn(v,r.colSpanProp,1);return x=mn(x,r.rowSpanProp,1),x})})));for(let m=l;m<=c;m++)for(let h=d;h<=p;h++){if(m===l&&h===d)continue;const v=Be(g,t),b=v.rows.find(w=>w.cells.some(_=>_.gridRow===m))??v.rows[m];if(!b)continue;let x=-1;for(const w of b.cells)w.gridRow===m&&w.gridColyt(w,r.row,b.rowIndexInSection,_=>{const C=[...Ge(_)];let E;if(x<0)E=C.findIndex(S=>nr(S,r)),E<0&&(E=C.length);else{const S=Si(_,r,x);E=S<0?C.length:S+1}return C.splice(E,0,ki(r,k,f)),{..._,children:C}}))}return g}function Ci(e,t,n,o,r){const s=ht(t),a=Be(e,t),l=Ue(a,n,o);return l?nt(e,a,l.sectionIndex,d=>yt(d,s.row,l.rowIndexInSection,c=>({...c,children:Ge(c).map((p,f)=>{if(f!==l.cellIndexInRow)return p;const y={...p.props??{}};r.trim()===""?delete y.className:y.className=r;const g={...p,props:y};return Object.keys(y).length===0&&delete g.props,g})}))):e}function Jt(e,t,n,o,r,s){const a=ht(t),l=Be(e,t),d=Ue(l,n,o);return d?nt(e,l,d.sectionIndex,c=>yt(c,a.row,d.rowIndexInSection,p=>({...p,children:Ge(p).map((f,y)=>{if(y!==d.cellIndexInRow)return f;const g={...f.props??{}},m={...g.style??{}};!s||s.trim()===""?delete m[r]:m[r]=s,Object.keys(m).length===0?delete g.style:g.style=m;const h={...f,props:g};return Object.keys(g).length===0&&delete h.props,h})}))):e}function go(e,t,n,o,r,s,a){const l=ht(t),d=Be(e,t),c=Ue(d,n,o);if(!c)return e;const p=a==="dark";return nt(e,d,c.sectionIndex,f=>yt(f,l.row,c.rowIndexInSection,y=>({...y,children:Ge(y).map((g,m)=>{if(m!==c.cellIndexInRow)return g;const h={...g.props??{}},v=typeof h.className=="string"?h.className:"",b=uC(v,s,r,p);b===""?delete h.className:h.className=b;const x={...g,props:h};return Object.keys(h).length===0&&delete x.props,x})})))}function ih(e,t,n,o,r){const s=ht(t),a=Be(e,t),l=Ue(a,n,o);return l?nt(e,a,l.sectionIndex,d=>yt(d,s.row,l.rowIndexInSection,c=>({...c,children:Ge(c).map((p,f)=>f===l.cellIndexInRow?{...p,text:r}:p)}))):e}function sh(e,t,n,o,r){const s=ht(t),a=Be(e,t),l=Ue(a,n,o);return l?nt(e,a,l.sectionIndex,d=>yt(d,s.row,l.rowIndexInSection,c=>({...c,children:Ge(c).map((p,f)=>f===l.cellIndexInRow?r:p)}))):e}const ah=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function r8(e){return e.split(/\s+/).filter(Boolean)}function lh(e,t){for(const n of t)if(e===n||/^-?\d+$/.test(e.slice(n.length+1))&&e.startsWith(n+"-"))return!0;return!1}function dh({className:e,catalog:t,t:n,onChange:o,colorScheme:r="light",onPresetToken:s,colorStyle:a,onColorStyle:l,disabled:d}){const c=t?.sides??[],p=t?.widths??[],f=t?.colors??[],y=r==="dark",g=u.useMemo(()=>c.map($=>$.prefix),[c]),m=u.useMemo(()=>new Set(f.map($=>$.token)),[f]),h=u.useMemo(()=>r8(e),[e]),v=u.useMemo(()=>Vr(e,y),[e,y]),b=u.useMemo(()=>v.find($=>m.has($))??null,[v,m]),x=u.useMemo(()=>{const $=new Set;for(const A of c)h.some(D=>D===A.prefix||D.startsWith(A.prefix+"-")&&/^-?\d+$/.test(D.slice(A.prefix.length+1)))&&$.add(A.value);return $},[h,c]),k=u.useMemo(()=>{const $=h.find(z=>lh(z,g));if(!$)return"none";const A=p.filter(z=>z.value!=="none");for(const z of c){if($===z.prefix)return A.find(D=>(D.suffix??"")==="")?.value??"thin";if($.startsWith(z.prefix+"-")){const D=$.slice(z.prefix.length),O=A.find(M=>(M.suffix??"")===D);if(O)return O.value}}return"thin"},[h,g,c,p]);if(!t||c.length===0||p.length===0)return null;function w($){return $.filter(A=>!lh(A,g))}function _($,A){const z=w(h),D=p.find(B=>B.value===A);if(!D||A==="none"||$.size===0)return z.join(" ").trim();const O=D.suffix??"",M=[...z];for(const B of c)$.has(B.value)&&M.push(O?`${B.prefix}${O}`:B.prefix);return M.join(" ").trim()}const C=$=>{const A=new Set(x);A.has($)?A.delete($):($==="all"?A.clear():A.delete("all"),A.add($));const z=k==="none"?p.find(D=>D.value!=="none")?.value??"thin":k;o(_(A,z))},E=$=>{const A=x.size===0?new Set(["all"]):x;o(_(A,$))},S=$=>{s?.($)},T=($,A)=>$&&$.startsWith("$t:")?n($.slice(3)):$||A;return i.jsxs("div",{className:"g7le-cell-border","data-testid":"g7le-cell-border",style:i8,children:[i.jsx("div",{style:s8,children:i.jsx("span",{style:a8,children:n("layout_editor.table_editor.cell_border")})}),i.jsx("div",{style:rl,"data-testid":"g7le-cell-border-widths",children:p.map($=>i.jsx("button",{type:"button",disabled:d,"data-testid":`g7le-cell-border-width-${$.value}`,"aria-pressed":k===$.value,onClick:()=>E($.value),style:k===$.value?ch:il,children:T($.label,$.value)},$.value))}),k!=="none"&&i.jsx("div",{style:rl,"data-testid":"g7le-cell-border-sides",children:c.map($=>i.jsx("button",{type:"button",disabled:d,"data-testid":`g7le-cell-border-side-${$.value}`,"aria-pressed":x.has($.value),onClick:()=>C($.value),style:x.has($.value)?ch:il,children:T($.label,$.value)},$.value))}),k!=="none"&&(f.length>0||l)&&i.jsx(i.Fragment,{children:i.jsxs("div",{style:rl,"data-testid":"g7le-cell-border-colors",children:[f.map($=>{const A=b===$.token;return i.jsx("button",{type:"button",disabled:d,title:T($.label,$.value),"data-testid":`g7le-cell-border-color-${$.value}`,"aria-pressed":A,onClick:()=>S($.token),style:{...uh,background:$.swatch??"#fff",outline:A?"2px solid #2563eb":"1px solid #cbd5e1"}},$.value)}),l&&(()=>{const $=!!a&&f.some(z=>z.swatch&&z.swatch.toLowerCase()===a.toLowerCase()),A=!y&&!!a&&!$;return i.jsx("label",{title:n(y?"layout_editor.table_editor.dark_free_color_hint":"layout_editor.table_inplace.custom_color"),"data-testid":"g7le-cell-border-color-custom",style:{...uh,position:"relative",overflow:"hidden",display:"inline-flex",alignItems:"center",justifyContent:"center",background:A&&ah.test(a)?a:"conic-gradient(red, yellow, lime, aqua, blue, magenta, red)",outline:A?"2px solid #2563eb":"1px solid #cbd5e1",opacity:y?.4:1,cursor:y?"not-allowed":"pointer"},children:i.jsx("input",{type:"color",disabled:d||y,"data-testid":"g7le-cell-border-color-picker",value:a&&ah.test(a)?a:"#000000",onChange:z=>l(z.target.value),style:{position:"absolute",width:0,height:0,opacity:0}})})})()]})})]})}const i8={display:"flex",flexDirection:"column",gap:6},s8={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},a8={fontSize:12,fontWeight:600,color:"#475569"},rl={display:"flex",gap:4,flexWrap:"wrap",alignItems:"center"},il={padding:"3px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},ch={...il,border:"1px solid #2563eb",background:"#eff6ff",color:"#1d4ed8",fontWeight:600},uh={width:22,height:22,borderRadius:5,padding:0,cursor:"pointer",boxSizing:"border-box"},ph=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function fh({colorStyle:e,className:t,catalog:n,t:o,colorScheme:r="light",onPresetToken:s,onCustomColor:a,onClear:l,disabled:d}){const c=n?.colors??[],p=r==="dark",f=e??"",y=Vr(t??"",p),g=c.find(x=>x.token&&y.includes(x.token))?.token??null,m=(x,k)=>x&&x.startsWith("$t:")?o(x.slice(3)):x||k,h=!g&&(p||f.trim()===""),v=!!f&&c.some(x=>x.swatch&&x.swatch.toLowerCase()===f.toLowerCase()),b=!p&&!!f&&!v;return i.jsxs("div",{className:"g7le-cell-fill","data-testid":"g7le-cell-fill",style:l8,children:[i.jsx("div",{style:d8,children:i.jsx("span",{style:c8,children:o("layout_editor.table_editor.cell_fill")})}),i.jsxs("div",{style:u8,"data-testid":"g7le-cell-fill-colors",children:[i.jsx("button",{type:"button",disabled:d,title:o("layout_editor.table_editor.cell_fill_none"),"data-testid":"g7le-cell-fill-none","aria-pressed":h,onClick:()=>l?.(),style:{...sl,background:"repeating-conic-gradient(#e2e8f0 0% 25%, #ffffff 0% 50%) 50% / 10px 10px",outline:h?"2px solid #2563eb":"1px solid #cbd5e1"}}),c.map(x=>{const k=!!x.token&&g===x.token,w=!p&&!!x.swatch&&f.toLowerCase()===(x.swatch??"").toLowerCase(),_=k||w,C=d||p&&!x.token;return i.jsx("button",{type:"button",disabled:C,title:m(x.label,x.value),"data-testid":`g7le-cell-fill-color-${x.value}`,"aria-pressed":_,onClick:()=>{x.token&&s?s(x.token):!p&&x.swatch&&a&&a(x.swatch)},style:{...sl,background:x.swatch??"#fff",outline:_?"2px solid #2563eb":"1px solid #cbd5e1",opacity:C?.4:1,cursor:C?"not-allowed":"pointer"}},x.value)}),a&&i.jsx("label",{title:o(p?"layout_editor.table_editor.dark_free_color_hint":"layout_editor.table_editor.cell_fill_custom"),"data-testid":"g7le-cell-fill-custom",style:{...sl,position:"relative",overflow:"hidden",display:"inline-flex",alignItems:"center",justifyContent:"center",background:b&&ph.test(f)?f:"conic-gradient(red, yellow, lime, aqua, blue, magenta, red)",outline:b?"2px solid #2563eb":"1px solid #cbd5e1",opacity:p?.4:1,cursor:p?"not-allowed":"pointer"},children:i.jsx("input",{type:"color",disabled:d||p,"data-testid":"g7le-cell-fill-color-picker",value:f&&ph.test(f)?f:"#ffffff",onChange:x=>a(x.target.value),style:{position:"absolute",width:0,height:0,opacity:0}})})]})]})}const l8={display:"flex",flexDirection:"column",gap:6},d8={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},c8={fontSize:12,fontWeight:600,color:"#475569"},u8={display:"flex",gap:4,flexWrap:"wrap",alignItems:"center"},sl={width:22,height:22,borderRadius:5,padding:0,cursor:"pointer",boxSizing:"border-box"};function p8(e){const t=/^(\d+)px$/.exec(e.trim());return t?parseInt(t[1],10):null}function gh({paddingStyle:e,catalog:t,t:n,onChange:o,disabled:r}){const s=t?.steps??[],a=e??"",l=p8(a),d=(h,v)=>h&&h.startsWith("$t:")?n(h.slice(3)):h||v,c=s.some(h=>(h.px??0)===(l??-1)),p=l!==null&&!c?String(l):"",[f,y]=u.useState(p);u.useEffect(()=>{y(p)},[e]);const g=h=>{o(h&&h>0?`${h}px`:""),y("")},m=h=>{const v=parseInt(h,10);Number.isFinite(v)&&v>=0&&o(v>0?`${v}px`:"")};return i.jsxs("div",{className:"g7le-cell-padding","data-testid":"g7le-cell-padding",style:f8,children:[i.jsx("div",{style:g8,children:n("layout_editor.table_editor.cell_padding")}),i.jsxs("div",{style:h8,"data-testid":"g7le-cell-padding-steps",children:[s.map(h=>{const v=(h.px??0)===(l??-1)||!h.px&&a.trim()==="";return i.jsx("button",{type:"button",disabled:r,"data-testid":`g7le-cell-padding-step-${h.value}`,"aria-pressed":v,onClick:()=>g(h.px),style:v?y8:hh,children:d(h.label,h.value)},h.value)}),i.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:3},children:[i.jsx("input",{type:"number",min:0,disabled:r,"data-testid":"g7le-cell-padding-free",value:f,placeholder:n("layout_editor.table_editor.cell_padding_custom"),onChange:h=>y(h.target.value),onBlur:()=>f.trim()!==""&&m(f),onKeyDown:h=>{h.key==="Enter"&&f.trim()!==""&&m(f)},style:b8}),i.jsx("span",{style:{fontSize:11,color:"#94a3b8"},children:"px"})]})]})]})}const f8={display:"flex",flexDirection:"column",gap:6},g8={fontSize:12,fontWeight:600,color:"#475569"},h8={display:"flex",gap:4,flexWrap:"wrap",alignItems:"center"},hh={padding:"3px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},y8={...hh,border:"1px solid #2563eb",background:"#eff6ff",color:"#1d4ed8",fontWeight:600},b8={width:48,padding:"3px 5px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,boxSizing:"border-box"};function yh({colorScheme:e,onChange:t,t:n,disabled:o}){const r=e==="dark";return i.jsxs("div",{className:"g7le-color-scheme-tabs","data-testid":"g7le-color-scheme-tabs",style:m8,children:[i.jsxs("div",{style:v8,children:[i.jsx("span",{style:_8,children:n("layout_editor.table_editor.cell_color")}),i.jsxs("div",{style:x8,children:[i.jsx("button",{type:"button",disabled:o,"data-testid":"g7le-color-scheme-light","aria-pressed":!r,onClick:()=>t("light"),style:r?al:bh,children:n("layout_editor.property_modal.scope.scheme_light")}),i.jsx("button",{type:"button",disabled:o,"data-testid":"g7le-color-scheme-dark","aria-pressed":r,onClick:()=>t("dark"),style:r?bh:al,children:n("layout_editor.property_modal.scope.scheme_dark")})]})]}),r&&i.jsx("div",{style:w8,"data-testid":"g7le-color-scheme-dark-hint",children:n("layout_editor.table_editor.dark_free_color_hint")})]})}const m8={display:"flex",flexDirection:"column",gap:3},v8={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},_8={fontSize:12,fontWeight:700,color:"#0f172a"},x8={display:"flex",gap:2},al={padding:"2px 9px",fontSize:11,border:"none",borderBottom:"2px solid transparent",background:"transparent",color:"#94a3b8",cursor:"pointer"},bh={...al,color:"#1d4ed8",borderBottom:"2px solid #2563eb",fontWeight:600},w8={fontSize:10,color:"#94a3b8",fontStyle:"italic"},ll="dark:";function mh(e){return typeof e=="string"?e.split(/\s+/).filter(Boolean):[]}function vh(e,t){return t==="dark"?e.filter(n=>n.startsWith(ll)).map(n=>n.slice(ll.length)):e.filter(n=>!n.startsWith(ll))}const k8={none:0,thin:1,medium:2,thick:4},_h={top:{w:"borderTopWidth",s:"borderTopStyle",c:"borderTopColor"},bottom:{w:"borderBottomWidth",s:"borderBottomStyle",c:"borderBottomColor"},left:{w:"borderLeftWidth",s:"borderLeftStyle",c:"borderLeftColor"},right:{w:"borderRightWidth",s:"borderRightStyle",c:"borderRightColor"}},xh=["top","bottom","left","right"];function S8(e,t,n="light"){if(!e||!t)return{};const o=t.sides??[],r=t.widths??[],s=t.colors??[],a=mh(e.props?.className);if(a.length===0&&!e.props?.style)return{};const l=[...r].filter(b=>b.value!=="none").sort((b,x)=>(x.suffix??"").length-(b.suffix??"").length),d={};for(const b of o)for(const x of l){const k=x.suffix?`${b.prefix}${x.suffix}`:b.prefix;if(a.includes(k)){d[b.value]=x.value;break}}const c=e.props?.style??{},p=vh(a,n),f=s.find(b=>p.includes(b.token))?.swatch??"",g=(n==="light"&&typeof c.borderColor=="string"?c.borderColor:"")||f||"#94a3b8",m=b=>{const x=_h[b]?.c,k=x?c[x]:void 0;return typeof k=="string"&&k?k:g},h={},v=(b,x)=>{const k=_h[b];if(!k)return;const w=k8[x]??1;h[k.w]=`${w}px`,h[k.s]=w>0?"solid":"none",w>0&&(h[k.c]=m(b))};if(d.all)for(const b of xh)v(b,d.all);for(const b of xh)d[b]&&v(b,d[b]);return h}function C8(e,t,n="light"){if(!e?.props)return{};const o=e.props.style??{},r={},s=mh(e.props.className),a=t?.colors?.find(c=>c.token&&vh(s,n).includes(c.token))?.swatch??"",d=(n==="light"&&typeof o.backgroundColor=="string"?o.backgroundColor:"")||a;return d&&(r.backgroundColor=d),typeof o.padding=="string"&&o.padding&&(r.padding=o.padding),r}const $8=/^\s*\$t:(custom\.[a-zA-Z0-9._-]+)\s*$/,E8=/^\s*\$t:([a-zA-Z0-9._-]+)\s*$/,I8=/\{\{.*?\}\}/;function wh(e,t,n){const o=e?.text;if(typeof o!="string")return{display:"",editable:!1,isKey:!1};const r=mt(o);if(r&&r.key.startsWith("custom.")){let a="";try{const l=Pt.getInstance().translate(r.key,{templateId:t,locale:n});a=l&&l!==r.key?l:""}catch{a=""}return{display:a,editable:!0,isKey:!0}}if(I8.test(o))return{display:o,editable:!1,isKey:!1};const s=E8.exec(o);if(s){const a=s[1];let l="";try{const d=Pt.getInstance().translate(a,{templateId:t,locale:n});l=d&&d!==a?d:""}catch{l=""}return{display:l,editable:!0,isKey:!0}}return{display:o,editable:!0,isKey:!1}}function dl(e){const t=er(e);return t===null?{node:null,path:null}:{node:_i(e,t),path:t}}function A8(e){if(!e||typeof e.text!="string")return null;const t=$8.exec(e.text);if(t)return t[1];const n=mt(e.text);return n&&n.key.startsWith("custom.")?n.key:null}function T8({node:e,params:t,t:n,onPatchNode:o,templateIdentifier:r,candidates:s}){const{state:a}=Je(),l=a.selectedRoute?.layoutName??null,d=a.locale,c=r??a.templateIdentifier,p=u.useMemo(()=>t&&typeof t=="object"?t:null,[t]);u.useMemo(()=>ht(p),[p]);const f=u.useMemo(()=>Be(e,p),[e,p]),y=u.useMemo(()=>{const q=p?.cellBorder;return q&&typeof q=="object"?q:null},[p]),g=u.useMemo(()=>{const q=p?.cellBackground;return q&&typeof q=="object"?q:null},[p]),m=u.useMemo(()=>{const q=p?.cellPadding;return q&&typeof q=="object"?q:null},[p]),[h,v]=u.useState(null),[b,x]=u.useState(null),[k,w]=u.useState({}),[_,C]=u.useState(!1),[E,S]=u.useState(null),[T,$]=u.useState(null),[A,z]=u.useState("light"),D=u.useCallback(q=>o(q),[o]),O=u.useMemo(()=>h?Ue(f,h.r,h.c):null,[f,h]),M=T!==null?T:h?.c??null,B=E!==null?E:h?.r??null,N=u.useMemo(()=>{const q=(y?.sides??[]).find($e=>$e.value==="all")??(y?.sides??[])[0],ae=(y?.widths??[]).find($e=>$e.value!=="none");if(!q||!ae)return[];const pe=ae.suffix??"";return[pe?`${q.prefix}${pe}`:q.prefix]},[y]),H=u.useCallback((q,ae,pe)=>{if(N.length===0)return q;const $e=(y?.sides??[]).map(J=>J.prefix),be=Ue(Be(q,p),ae,pe),oe=(typeof be?.cell?.props?.className=="string"?be.cell.props.className:"").split(/\s+/).filter(Boolean);return oe.some(J=>$e.some(le=>J===le||J.startsWith(le+"-")&&/^-?\d+$/.test(J.slice(le.length+1))))?q:Ci(q,p,ae,pe,[...oe,...N].join(" ").trim())},[N,y,p]),L=u.useCallback(q=>{if(!h)return;const ae=Math.min(h.r,b?.r??h.r),pe=Math.max(h.r,b?.r??h.r),$e=Math.min(h.c,b?.c??h.c),be=Math.max(h.c,b?.c??h.c),j=new Set,oe=[];for(let J=ae;J<=pe;J++)for(let le=$e;le<=be;le++)j.add(`${J}:${le}`),oe.push({r:J,c:le});let ue=e;for(const J of oe){if(ue=H(ue,J.r,J.c),ue=Jt(ue,p,J.r,J.c,"borderColor",q),J.r>0&&!j.has(`${J.r-1}:${J.c}`)){const le=Ue(Be(ue,p),J.r-1,J.c);le&&(ue=Jt(ue,p,le.gridRow,le.gridCol,"borderBottomColor",q))}if(J.c>0&&!j.has(`${J.r}:${J.c-1}`)){const le=Ue(Be(ue,p),J.r,J.c-1);le&&(ue=Jt(ue,p,le.gridRow,le.gridCol,"borderRightColor",q))}}D(ue)},[h,b,e,p,D,H]),I=u.useCallback(q=>L(q),[L]),P=u.useMemo(()=>(y?.colors??[]).map(q=>q.token).filter(Boolean),[y]),F=u.useCallback(q=>{if(!h||P.length===0)return;const ae=Math.min(h.r,b?.r??h.r),pe=Math.max(h.r,b?.r??h.r),$e=Math.min(h.c,b?.c??h.c),be=Math.max(h.c,b?.c??h.c);let j=e;for(let oe=ae;oe<=pe;oe++)for(let ue=$e;ue<=be;ue++)j=H(j,oe,ue),j=go(j,p,oe,ue,q,P,A);D(j)},[h,b,e,p,D,H,P,A]),G=u.useMemo(()=>{if(A==="dark")return"";const q=O?.cell.props?.style;return typeof q?.borderColor=="string"?q.borderColor:""},[O,A]),V=u.useCallback((q,ae)=>{if(!h)return;const pe=Math.min(h.r,b?.r??h.r),$e=Math.max(h.r,b?.r??h.r),be=Math.min(h.c,b?.c??h.c),j=Math.max(h.c,b?.c??h.c);let oe=e;for(let ue=pe;ue<=$e;ue++)for(let J=be;J<=j;J++)oe=Jt(oe,p,ue,J,q,ae);D(oe)},[h,b,e,p,D]),Y=u.useMemo(()=>(g?.colors??[]).map(q=>q.token).filter(q=>!!q),[g]),Z=u.useCallback(()=>h?{r0:Math.min(h.r,b?.r??h.r),r1:Math.max(h.r,b?.r??h.r),c0:Math.min(h.c,b?.c??h.c),c1:Math.max(h.c,b?.c??h.c)}:null,[h,b]),se=u.useCallback(q=>{const ae=Z();if(!ae||Y.length===0)return;let pe=e;for(let $e=ae.r0;$e<=ae.r1;$e++)for(let be=ae.c0;be<=ae.c1;be++)pe=go(pe,p,$e,be,q,Y,A);D(pe)},[Z,e,p,D,Y,A]),re=u.useCallback(q=>V("backgroundColor",q),[V]),U=u.useCallback(()=>{const q=Z();if(!q)return;let ae=e;for(let pe=q.r0;pe<=q.r1;pe++)for(let $e=q.c0;$e<=q.c1;$e++)ae=go(ae,p,pe,$e,void 0,Y,A),A==="light"&&(ae=Jt(ae,p,pe,$e,"backgroundColor",void 0));D(ae)},[Z,e,p,D,Y,A]),ee=u.useCallback(q=>V("padding",q),[V]),fe=u.useMemo(()=>{if(A==="dark")return"";const q=O?.cell.props?.style;return typeof q?.backgroundColor=="string"?q.backgroundColor:""},[O,A]),K=u.useMemo(()=>typeof O?.cell.props?.className=="string"?O.cell.props.className:"",[O]),ne=u.useMemo(()=>{const q=O?.cell.props?.style;return typeof q?.padding=="string"?q.padding:""},[O]),me=u.useCallback(q=>q==="section"?n("layout_editor.table_editor.move_blocked_section"):"",[n]),Ce=u.useCallback((q,ae)=>xi(f,q,ae),[f]),ze=u.useCallback((q,ae)=>wi(f,q,ae),[f]),Se=u.useCallback(q=>D(nl(e,p,q)),[e,p,D]),qe=u.useCallback(q=>{D(Rg(e,p,q)),v(null),x(null)},[e,p,D]),De=u.useCallback((q,ae)=>D(eh(e,p,q,ae)),[e,p,D]),Pe=u.useCallback(q=>D(nh(e,p,q)),[e,p,D]),Qe=u.useCallback(q=>{D(oh(e,p,q)),v(null),x(null)},[e,p,D]),Me=u.useCallback((q,ae)=>D(th(e,p,q,ae)),[e,p,D]),Re=u.useCallback(()=>{if(!h||!b)return;const q=ol(e,p,h.r,h.c,b.r,b.c);q.ok&&(D(q.table),v({r:Math.min(h.r,b.r),c:Math.min(h.c,b.c)}),x(null))},[e,p,h,b,D]),ve=u.useCallback(()=>{h&&(D(rh(e,p,h.r,h.c)),x(null))},[e,p,h,D]),te=u.useCallback(q=>{if(!h)return;const ae=Math.min(h.r,b?.r??h.r),pe=Math.max(h.r,b?.r??h.r),$e=Math.min(h.c,b?.c??h.c),be=Math.max(h.c,b?.c??h.c);let j=e;for(let oe=ae;oe<=pe;oe++)for(let ue=$e;ue<=be;ue++)j=Ci(j,p,oe,ue,q);D(j)},[e,p,h,b,D]),he=u.useCallback(async(q,ae)=>{const pe=`${q}:${ae}`,$e=k[pe];if($e===void 0)return;const be=Ue(f,q,ae);if(!be)return;const{node:j,path:oe}=dl(be.cell);if(oe===null)return;const ue=wh(j,c,d);if(ue.editable){if($e===ue.display){w(J=>{const le={...J};return delete le[pe],le});return}C(!0);try{const J=A8(j);if(J)await yr(c,J,d,$e),await tn(c,d);else{const le=await qn(c,l,d,$e);if(le.kind==="ok"&&le.resource){const Ie=`$t:${le.resource.translation_key}`;if(oe.length===0)D(ih(e,p,q,ae,Ie));else{const dt=tr(be.cell,oe,Ie);D(sh(e,p,q,ae,dt))}await tn(c,d)}}}finally{C(!1),w(J=>{const le={...J};return delete le[pe],le})}}},[k,f,c,d,l,e,p,D]),Q=u.useMemo(()=>{if(!O)return null;const{node:q,path:ae}=dl(O.cell);return ae===null?null:{value:typeof q?.text=="string"?q.text:"",editable:!0}},[O]),ie=u.useCallback(q=>{if(typeof q!="string"||q.length===0||!h)return;const ae=Ue(f,h.r,h.c);if(!ae)return;const pe=er(ae.cell);if(pe!==null)if(pe.length===0)D(ih(e,p,h.r,h.c,q));else{const $e=tr(ae.cell,pe,q);D(sh(e,p,h.r,h.c,$e))}},[h,f,e,p,D]),_e=u.useCallback((q,ae,pe)=>{pe?x({r:q,c:ae}):(v({r:q,c:ae}),x(null))},[]),ge=u.useMemo(()=>Array.from({length:f.colCount},(q,ae)=>ae),[f.colCount]),Ae=!!(h&&b&&(h.r!==b.r||h.c!==b.c)),Ne=!!(O&&(O.colSpan>1||O.rowSpan>1)),Le=O&&typeof O.cell.props?.className=="string"?O.cell.props.className:"";return i.jsxs("div",{className:"g7le-node-editor g7le-node-editor--table","data-testid":"g7le-table-editor",style:D8,children:[i.jsx("div",{style:N8,children:n("layout_editor.table_editor.title")}),i.jsx("div",{style:{overflowX:"auto"},children:i.jsxs("table",{"data-testid":"g7le-table-editor-grid",style:z8,children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{style:M8}),ge.map(q=>{const ae=ze(q,-1),pe=ze(q,1),$e=M===q;return i.jsx("th",{style:L8,"data-testid":`g7le-table-colgutter-${q}`,onMouseEnter:()=>$(q),onMouseLeave:()=>$(be=>be===q?null:be),children:i.jsxs("div",{style:{...O8,visibility:$e?"visible":"hidden"},children:[i.jsx("button",{type:"button",title:ae.ok?n("layout_editor.table_editor.move_col_left"):me(ae.reason)||n("layout_editor.table_editor.move_col_left"),disabled:!ae.ok||_,onClick:()=>Me(q,-1),"data-testid":`g7le-table-col-left-${q}`,style:ae.ok?vn:$i,children:"←"}),i.jsx("button",{type:"button",title:n("layout_editor.table_editor.add_col"),disabled:_,onClick:()=>Pe(q),"data-testid":`g7le-table-col-add-${q}`,style:vn,children:"+"}),i.jsx("button",{type:"button",title:n("layout_editor.table_editor.remove_col"),disabled:f.colCount<=1||_,onClick:()=>Qe(q),"data-testid":`g7le-table-col-remove-${q}`,style:kh,children:"✕"}),i.jsx("button",{type:"button",title:pe.ok?n("layout_editor.table_editor.move_col_right"):me(pe.reason)||n("layout_editor.table_editor.move_col_right"),disabled:!pe.ok||_,onClick:()=>Me(q,1),"data-testid":`g7le-table-col-right-${q}`,style:pe.ok?vn:$i,children:"→"})]})},q)})]})}),i.jsx("tbody",{children:f.rows.map((q,ae)=>{const pe=q.cells[0]?.gridRow??ae,$e=B===pe;return i.jsxs("tr",{"data-testid":`g7le-table-row-${pe}`,onMouseEnter:()=>S(pe),onMouseLeave:()=>S(be=>be===pe?null:be),children:[i.jsx("td",{style:P8,"data-testid":`g7le-table-rowgutter-${pe}`,children:(()=>{const be=Ce(pe,-1),j=Ce(pe,1);return i.jsxs("div",{style:{...B8,visibility:$e?"visible":"hidden"},children:[i.jsx("button",{type:"button",title:be.ok?n("layout_editor.table_editor.move_row_up"):me(be.reason)||n("layout_editor.table_editor.move_row_up"),disabled:!be.ok||_,onClick:()=>De(pe,-1),"data-testid":`g7le-table-row-up-${pe}`,style:be.ok?vn:$i,children:"↑"}),i.jsx("button",{type:"button",title:n("layout_editor.table_editor.add_row"),disabled:_,onClick:()=>Se(pe),"data-testid":`g7le-table-row-add-${pe}`,style:vn,children:"+"}),i.jsx("button",{type:"button",title:n("layout_editor.table_editor.remove_row"),disabled:f.rows.length<=1||_,onClick:()=>qe(pe),"data-testid":`g7le-table-row-remove-${pe}`,style:kh,children:"✕"}),i.jsx("button",{type:"button",title:j.ok?n("layout_editor.table_editor.move_row_down"):me(j.reason)||n("layout_editor.table_editor.move_row_down"),disabled:!j.ok||_,onClick:()=>De(pe,1),"data-testid":`g7le-table-row-down-${pe}`,style:j.ok?vn:$i,children:"↓"})]})})()}),q.cells.map(be=>{const j=`${be.gridRow}:${be.gridCol}`,{node:oe,path:ue}=dl(be.cell),J=wh(oe,c,d),le=ue!==null&&J.editable,Ie=ue===null,dt=k[j],pt=dt!==void 0?dt:J.display,ot=h&&h.r===be.gridRow&&h.c===be.gridCol,Oe=h&&b&&be.gridRow>=Math.min(h.r,b.r)&&be.gridRow<=Math.max(h.r,b.r)&&be.gridCol>=Math.min(h.c,b.c)&&be.gridCol<=Math.max(h.c,b.c);return i.jsx("td",{colSpan:be.colSpan,rowSpan:be.rowSpan,"data-testid":`g7le-table-cell-${be.gridRow}-${be.gridCol}`,onClick:He=>_e(be.gridRow,be.gridCol,He.shiftKey),style:{...W8,...S8(be.cell,y,A),...C8(be.cell,g,A),...be.isHeader?j8:{},...ot?H8:{},...Oe&&!ot?F8:{}},children:le?i.jsx("input",{type:"text","data-testid":`g7le-table-cell-input-${be.gridRow}-${be.gridCol}`,value:pt,placeholder:n("layout_editor.table_editor.cell_text"),disabled:_,onMouseDown:He=>{He.shiftKey&&He.preventDefault(),_e(be.gridRow,be.gridCol,He.shiftKey)},onClick:He=>He.stopPropagation(),onChange:He=>w(Ye=>({...Ye,[j]:He.target.value})),onBlur:()=>{he(be.gridRow,be.gridCol)},style:K8}):Ie?i.jsx("span",{"data-testid":`g7le-table-cell-struct-${be.gridRow}-${be.gridCol}`,style:Sh,children:n("layout_editor.table_editor.structural_cell")}):i.jsx("span",{style:Sh,children:J.display})},j)})]},ae)})})]})}),i.jsxs("button",{type:"button","data-testid":"g7le-table-add-row-bottom",onClick:()=>Se(f.rows.length-1),disabled:_,style:V8,children:["+ ",n("layout_editor.table_editor.add_row")]}),i.jsxs("div",{style:U8,"data-testid":"g7le-table-cell-tools",children:[i.jsx("button",{type:"button","data-testid":"g7le-table-merge",onClick:Re,disabled:!Ae||_,style:Ch,children:n("layout_editor.table_editor.merge_cells")}),i.jsx("button",{type:"button","data-testid":"g7le-table-unmerge",onClick:ve,disabled:!Ne||_,style:Ch,children:n("layout_editor.table_editor.unmerge_cells")})]}),O&&Q&&i.jsxs("div",{style:G8,"data-testid":"g7le-table-cell-i18n-section",children:[i.jsx("div",{style:Y8,children:n("layout_editor.table_editor.cell_i18n_label")}),i.jsx(vt,{value:Q.value,onChange:ie,t:n,placeholder:n("layout_editor.table_editor.cell_text"),testidPrefix:"g7le-table-cell-i18n",candidates:s,enableExpressionTree:!0,expressionTreeCollapsible:!0})]}),O&&i.jsxs("div",{style:q8,"data-testid":"g7le-table-cell-color-section",children:[i.jsx(yh,{colorScheme:A,onChange:z,t:n,disabled:_}),y&&i.jsx("div",{style:cl,"data-testid":"g7le-table-cell-border-row",children:i.jsx(dh,{className:Le,catalog:y,t:n,onChange:te,colorScheme:A,onPresetToken:F,colorStyle:G,onColorStyle:I,disabled:_})}),i.jsx("div",{style:cl,"data-testid":"g7le-table-cell-fill-row",children:i.jsx(fh,{colorStyle:fe,className:K,catalog:g,t:n,colorScheme:A,onPresetToken:se,onCustomColor:re,onClear:U,disabled:_})})]}),O&&i.jsx("div",{style:cl,"data-testid":"g7le-table-cell-padding-row",children:i.jsx(gh,{paddingStyle:ne,catalog:m,t:n,onChange:ee,disabled:_})}),O&&!y&&i.jsxs("label",{style:X8,"data-testid":"g7le-table-cell-border-row",children:[i.jsx("span",{style:J8,children:n("layout_editor.table_editor.cell_border")}),i.jsx("input",{type:"text","data-testid":"g7le-table-cell-border-input",value:Le,placeholder:n("layout_editor.table_editor.cell_class_placeholder"),onChange:q=>te(q.target.value),disabled:_,style:Z8})]}),!f.valid&&i.jsx("div",{"data-testid":"g7le-table-grid-warning",style:Q8,children:n("layout_editor.table_editor.grid_invalid")}),i.jsx("div",{style:R8,children:n("layout_editor.table_editor.select_hint")})]})}const D8={display:"flex",flexDirection:"column",gap:8,width:"100%",marginBottom:12},N8={fontSize:12,fontWeight:700,color:"#0f172a"},z8={borderCollapse:"collapse",width:"auto"},M8={width:28,background:"transparent",border:"none"},L8={padding:2,border:"none",background:"transparent"},P8={padding:2,border:"none",background:"transparent",verticalAlign:"middle"},O8={display:"flex",gap:2,justifyContent:"center"},B8={display:"grid",gridTemplateColumns:"repeat(2, 16px)",gap:2,justifyContent:"center"},vn={width:16,height:16,lineHeight:"14px",padding:0,fontSize:10,border:"1px solid #cbd5e1",borderRadius:4,background:"#fff",color:"#475569",cursor:"pointer"},kh={...vn,border:"1px solid #fecaca",color:"#dc2626"},$i={...vn,cursor:"not-allowed",opacity:.4,color:"#94a3b8",borderColor:"#e2e8f0"},W8={border:"1px solid #cbd5e1",padding:0,width:64,minWidth:64,maxWidth:120,height:24,background:"#fff",cursor:"pointer"},j8={background:"#f1f5f9",fontWeight:600},H8={outline:"2px solid #2563eb",outlineOffset:-2},F8={background:"#dbeafe"},K8={width:"100%",boxSizing:"border-box",padding:"2px 5px",fontSize:11,height:22,lineHeight:"18px",border:"none",background:"transparent",outline:"none"},Sh={display:"block",padding:"2px 5px",fontSize:10,color:"#64748b",fontStyle:"italic",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:110},V8={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},U8={display:"flex",gap:6},Ch={padding:"4px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},q8={display:"flex",flexDirection:"column",gap:8,borderTop:"1px solid #f1f5f9",paddingTop:8},G8={display:"flex",flexDirection:"column",gap:6,borderTop:"1px solid #f1f5f9",paddingTop:8},Y8={fontSize:12,fontWeight:700,color:"#0f172a"},cl={display:"flex",flexDirection:"column",gap:6},X8={display:"flex",alignItems:"center",gap:6},J8={fontSize:12,color:"#475569",minWidth:60},Z8={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},Q8={fontSize:11,color:"#b45309",background:"#fffbeb",border:"1px solid #fde68a",borderRadius:6,padding:"4px 6px"},R8={fontSize:11,color:"#94a3b8"},ez=/\{\{.*?\}\}/;function tz(e,t,n){const r=(e.props??{})[t];return Array.isArray(r)?r:r===void 0&&n?JSON.parse(JSON.stringify(n)):[]}function nz(e){return typeof e=="string"&&ez.test(e)}function ul(e,t,n){return e?e.startsWith("$t:")?t(e.slice(3)):e:n}function oz(e,t,n){return typeof e=="object"&&e!==null?e[t.key]:n?e:void 0}function rz(e,t,n,o){if(typeof e=="object"&&e!==null){const r={...e};return o===void 0?delete r[t.key]:r[t.key]=o,r}return n?o:{[t.key]:o}}function $h({node:e,params:t,t:n,onPatchNode:o,templateIdentifier:r,candidates:s}){const a=typeof t?.arrayProp=="string"?t.arrayProp:null,l=Array.isArray(t?.fields)?t.fields:[],d=ul(typeof t?.itemLabel=="string"?t.itemLabel:void 0,n,n("layout_editor.array_editor.item")),c=t?.newItem,p=c&&typeof c=="object"?c:null,f=typeof c=="string"||typeof c=="number"?c:null,y=(l.find(C=>C.primary)??l[0])?.key,g=(e.props??{})[a??""],m=Array.isArray(t?.defaultItems)?t.defaultItems:null,h=a?tz(e,a,m):[],v=u.useCallback(C=>{if(!a)return;const E={...e.props??{}};E[a]=C,o({...e,props:E})},[a,e,o]),b=u.useCallback(()=>{if(p)return JSON.parse(JSON.stringify(p));if(f!==null)return f;const C={};for(const E of l)(E.widget??"text")==="boolean"?C[E.key]=!1:C[E.key]="";return C},[p,f,l]),x=u.useCallback(()=>{v([...h,b()])},[v,h,b]),k=u.useCallback(C=>{v(h.filter((E,S)=>S!==C))},[v,h]),w=u.useCallback((C,E)=>{const S=C+E;if(S<0||S>=h.length)return;const T=[...h];[T[C],T[S]]=[T[S],T[C]],v(T)},[v,h]),_=u.useCallback((C,E,S)=>{const T=E.key===y,$=h.map((A,z)=>z===C?rz(A,E,T,S):A);v($)},[h,v,y]);return a?nz(g)||g!==void 0&&!Array.isArray(g)?i.jsx("div",{className:"g7le-node-editor g7le-node-editor--array","data-testid":"g7le-array-editor-bound",style:fz,children:n("layout_editor.array_editor.bound_degraded")}):i.jsxs("div",{className:"g7le-node-editor g7le-node-editor--array","data-testid":"g7le-array-editor",style:iz,children:[i.jsx("div",{style:sz,children:n("layout_editor.array_editor.items_title")}),h.length===0&&i.jsx("div",{"data-testid":"g7le-array-empty",style:Ih,children:n("layout_editor.array_editor.empty")}),h.map((C,E)=>i.jsxs("div",{"data-testid":`g7le-array-row-${E}`,style:az,children:[i.jsxs("div",{style:lz,children:[i.jsxs("span",{style:dz,children:["#",E+1]}),i.jsx("div",{style:{flex:1}}),i.jsx("button",{type:"button","data-testid":`g7le-array-up-${E}`,title:n("layout_editor.array_editor.move_up"),disabled:E===0,onClick:()=>w(E,-1),style:Eh,children:"↑"}),i.jsx("button",{type:"button","data-testid":`g7le-array-down-${E}`,title:n("layout_editor.array_editor.move_down"),disabled:E===h.length-1,onClick:()=>w(E,1),style:Eh,children:"↓"}),i.jsx("button",{type:"button","data-testid":`g7le-array-remove-${E}`,title:n("layout_editor.array_editor.remove"),onClick:()=>k(E),style:uz,children:"✕"})]}),l.map(S=>{const T=S.widget??"text",$=S.key===y,A=ul(S.label,n,S.key),z=oz(C,S,$),D=`g7le-array-field-${E}-${S.key}`;if(T==="boolean")return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"checkbox","data-testid":D,checked:z===!0,onChange:M=>_(E,S,M.target.checked)})]},S.key);if(T==="select"){const M=Array.isArray(S.options)?S.options:[];return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsxs("select",{"data-testid":D,value:z==null?"":String(z),onChange:B=>_(E,S,B.target.value===""?void 0:B.target.value),style:or,children:[i.jsx("option",{value:"",children:"—"}),M.map((B,N)=>i.jsx("option",{value:String(B.value),children:ul(B.label,n,String(B.value))},N))]})]},S.key)}if(T==="i18n-text"){const M=typeof z=="string"?z:z==null?"":String(z);return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("div",{"data-testid":D,style:{flex:1,minWidth:0},children:i.jsx(vt,{value:M,onChange:B=>_(E,S,B===""?void 0:B),t:n,placeholder:A,testidPrefix:`${D}-i18n`,candidates:s,enableExpressionTree:!0,expressionTreeCollapsible:!0})})]},S.key)}if(T==="number"){const M=z==null?"":String(z);return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"number","data-testid":D,value:M,onChange:B=>{const N=B.target.value;_(E,S,N===""?void 0:Number(N))},style:or})]},S.key)}if(T==="color"){const M=typeof z=="string"?z:"",B=/^#[0-9a-fA-F]{6}$/.test(M)?M:"#000000";return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"color","data-testid":`${D}-swatch`,value:B,onChange:N=>_(E,S,N.target.value),style:cz}),i.jsx("input",{type:"text","data-testid":D,value:M,placeholder:"#7C3AED",onChange:N=>_(E,S,N.target.value===""?void 0:N.target.value),style:or})]},S.key)}if(T==="number-list"){const M=Array.isArray(z)?z.join(", "):"";return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"text","data-testid":D,value:M,placeholder:n("layout_editor.array_editor.number_list_placeholder"),onChange:B=>{const N=B.target.value.split(",").map(H=>H.trim()).filter(H=>H!=="").map(H=>Number(H)).filter(H=>!Number.isNaN(H));_(E,S,N)},style:or})]},S.key)}const O=z==null?"":String(z);return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"text","data-testid":D,value:O,placeholder:T==="icon"?n("layout_editor.array_editor.icon_placeholder"):A,onChange:M=>_(E,S,M.target.value===""?void 0:M.target.value),style:or})]},S.key)})]},E)),i.jsx("button",{type:"button","data-testid":"g7le-array-add",onClick:x,style:pz,children:n("layout_editor.array_editor.add",{item:d})})]}):i.jsx("div",{className:"g7le-node-editor g7le-node-editor--array","data-testid":"g7le-array-editor-misconfigured",style:Ih,children:n("layout_editor.array_editor.no_array_prop")})}const iz={display:"flex",flexDirection:"column",gap:8,width:"100%",marginBottom:12},sz={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:2},az={display:"flex",flexDirection:"column",gap:4,padding:8,border:"1px solid #e2e8f0",borderRadius:8,background:"#f8fafc"},lz={display:"flex",gap:4,alignItems:"center"},dz={fontSize:11,fontWeight:700,color:"#64748b"},Wn={display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"},jn={fontSize:11,color:"#475569",minWidth:64,flexShrink:0},or={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},cz={width:32,height:28,padding:0,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",cursor:"pointer",flexShrink:0},Eh={padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},uz={padding:"2px 6px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},pz={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},Ih={fontSize:11,color:"#94a3b8",fontStyle:"italic"},fz={fontSize:11,color:"#b45309",fontStyle:"italic",padding:"4px 2px"};function gz(e,t){return e?e.startsWith("$t:")?t(e.slice(3)):e:null}function hz(e){const{params:t,t:n}=e,o=Array.isArray(t?.groups)?t.groups:[];return o.length===0?i.jsx("div",{className:"g7le-node-editor g7le-node-editor--array-group","data-testid":"g7le-array-group-misconfigured",style:vz,children:n("layout_editor.array_editor.no_array_prop")}):i.jsx("div",{className:"g7le-node-editor g7le-node-editor--array-group","data-testid":"g7le-array-group-editor",style:yz,children:o.map((r,s)=>{const a=gz(r.title,n),{title:l,...d}=r;return i.jsxs("div",{"data-testid":`g7le-array-group-${r.arrayProp??s}`,style:bz,children:[a&&i.jsx("div",{style:mz,children:a}),i.jsx($h,{...e,params:d})]},r.arrayProp??s)})})}const yz={display:"flex",flexDirection:"column",gap:16,width:"100%",marginBottom:12},bz={display:"flex",flexDirection:"column",gap:4},mz={fontSize:12,fontWeight:700,color:"#1e293b",borderBottom:"1px solid #e2e8f0",paddingBottom:4},vz={fontSize:11,color:"#94a3b8",fontStyle:"italic"},_z=/\{\{.*?\}\}/;function xz(e){return typeof e=="string"&&_z.test(e)}function wz(e,t,n){return e?e.startsWith("$t:")?t(e.slice(3)):e:n}function kz(e){const{node:t,params:n,t:o,onPatchNode:r}=e,s=typeof n?.arrayProp=="string"?n.arrayProp:null,a=typeof n?.idField=="string"?n.idField:"id",l=typeof n?.cellChildrenProp=="string"?n.cellChildrenProp:"cellChildren",d=typeof n?.cellChildComponent=="string"?n.cellChildComponent:"Div",c=wz(typeof n?.itemLabel=="string"?n.itemLabel:void 0,o,o("layout_editor.array_editor.item")),[p,f]=u.useState(null),y=s?(t.props??{})[s]:void 0,g=Array.isArray(y)?y:[],m=u.useCallback(C=>{if(!s)return;const E={...t.props??{}};E[s]=C,r({...t,props:E})},[s,t,r]),h=u.useCallback(()=>{const C=n?.newItem;return C&&typeof C=="object"?JSON.parse(JSON.stringify(C)):{[a]:"",[l]:[]}},[n,a,l]),v=u.useCallback(()=>{m([...g,h()])},[m,g,h]),b=u.useCallback(C=>{m(g.filter((E,S)=>S!==C)),f(null)},[m,g]),x=u.useCallback((C,E)=>{const S=C+E;if(S<0||S>=g.length)return;const T=[...g];[T[C],T[S]]=[T[S],T[C]],m(T)},[m,g]),k=u.useCallback((C,E)=>{const S=g.map((T,$)=>$===C?{...T,[a]:E}:T);m(S)},[g,m,a]),w=u.useCallback(C=>({type:"composite",name:"CardGridCell",children:Array.isArray(C[l])?C[l]:[]}),[l]),_=u.useCallback(C=>E=>{const S=Array.isArray(E.children)?E.children:[],T=g.map(($,A)=>A===C?{...$,[l]:S}:$);m(T)},[g,m,l]);return s?xz(y)||y!==void 0&&!Array.isArray(y)?i.jsx("div",{className:"g7le-node-editor g7le-node-editor--cell-tree","data-testid":"g7le-cell-tree-bound",style:Mz,children:o("layout_editor.array_editor.bound_degraded")}):i.jsxs("div",{className:"g7le-node-editor g7le-node-editor--cell-tree","data-testid":"g7le-cell-tree-editor",style:Sz,children:[i.jsx("div",{style:Cz,children:o("layout_editor.cell_tree_editor.columns_title")}),g.length===0&&i.jsx("div",{"data-testid":"g7le-cell-tree-empty",style:Th,children:o("layout_editor.array_editor.empty")}),g.map((C,E)=>{const S=typeof C[a]=="string"?C[a]:"",T=p===E;return i.jsxs("div",{"data-testid":`g7le-cell-tree-row-${E}`,style:$z,children:[i.jsxs("div",{style:Ez,children:[i.jsxs("span",{style:Iz,children:["#",E+1]}),i.jsx("input",{type:"text","data-testid":`g7le-cell-tree-id-${E}`,value:S,placeholder:o("layout_editor.cell_tree_editor.id_placeholder"),onChange:$=>k(E,$.target.value),style:Az}),i.jsx("button",{type:"button","data-testid":`g7le-cell-tree-up-${E}`,title:o("layout_editor.array_editor.move_up"),disabled:E===0,onClick:()=>x(E,-1),style:Ah,children:"↑"}),i.jsx("button",{type:"button","data-testid":`g7le-cell-tree-down-${E}`,title:o("layout_editor.array_editor.move_down"),disabled:E===g.length-1,onClick:()=>x(E,1),style:Ah,children:"↓"}),i.jsx("button",{type:"button","data-testid":`g7le-cell-tree-remove-${E}`,title:o("layout_editor.array_editor.remove"),onClick:()=>b(E),style:Tz,children:"✕"})]}),i.jsx("button",{type:"button","data-testid":`g7le-cell-tree-toggle-${E}`,onClick:()=>f(T?null:E),style:Dz,children:o(T?"layout_editor.cell_tree_editor.collapse_cells":"layout_editor.cell_tree_editor.expand_cells")}),T&&i.jsx("div",{"data-testid":`g7le-cell-tree-cells-${E}`,style:Nz,children:i.jsx(qg,{...e,node:w(C),params:{childComponent:d},onPatchNode:_(E)})})]},E)}),i.jsx("button",{type:"button","data-testid":"g7le-cell-tree-add",onClick:v,style:zz,children:o("layout_editor.cell_tree_editor.add_column",{item:c})})]}):i.jsx("div",{className:"g7le-node-editor g7le-node-editor--cell-tree","data-testid":"g7le-cell-tree-misconfigured",style:Th,children:o("layout_editor.array_editor.no_array_prop")})}const Sz={display:"flex",flexDirection:"column",gap:8,width:"100%",marginBottom:12},Cz={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:2},$z={display:"flex",flexDirection:"column",gap:6,padding:8,border:"1px solid #e2e8f0",borderRadius:8,background:"#f8fafc"},Ez={display:"flex",gap:4,alignItems:"center"},Iz={fontSize:11,fontWeight:700,color:"#64748b",flexShrink:0},Az={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},Ah={padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},Tz={padding:"2px 6px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},Dz={padding:"3px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#2563eb",cursor:"pointer",alignSelf:"flex-start"},Nz={paddingLeft:8,borderLeft:"2px solid #e2e8f0"},zz={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},Th={fontSize:11,color:"#94a3b8",fontStyle:"italic"},Mz={fontSize:11,color:"#b45309",fontStyle:"italic",padding:"4px 2px"};function Lz(e,t,n){const o=Be(e,t);if(!n||n.length===0)return{measured:[],grid:o};const r=[];for(const s of o.rows)for(const a of s.cells){const d=tl(e,a,t).map(p=>`children.${p}`).join("."),c=n.find(p=>p.path===d||p.path.endsWith("."+d));c&&r.push({ref:a,box:{top:c.top,left:c.left,width:c.width,height:c.height}})}return{measured:r,grid:o}}const pl=26,fl=50,gl=6,Dh=44,Nh=18,zh="g7le-table-inplace-empty-cell-style";function Pz(){if(typeof document>"u"||document.getElementById(zh))return;const e=document.createElement("style");e.id=zh,e.textContent=".g7le-preview-frame td[data-editor-name],.g7le-preview-frame th[data-editor-name]{min-width:56px;height:38px;}.g7le-preview-frame table[data-editor-name]{min-width:120px;}",document.head.appendChild(e)}function Oz({node:e,params:t,nodeBox:n,cellBoxes:o,selectedCellPath:r,colorScheme:s,t:a,onPatchNode:l,onRequestInlineEdit:d}){const c=u.useMemo(()=>t&&typeof t=="object"?t:null,[t]),{measured:p,grid:f}=u.useMemo(()=>Lz(e,c,o),[e,c,o]),[y,g]=u.useState(null),[m,h]=u.useState(null),v=u.useMemo(()=>{if(!r)return null;for(const j of f.rows)for(const oe of j.cells){const ue=tl(e,oe,c).map(J=>`children.${J}`).join(".");if(r===ue||r.startsWith(ue+"."))return{r:oe.gridRow,c:oe.gridCol}}return null},[r,f,e,c]),b=u.useMemo(()=>y&&Ue(f,y.r,y.c)?y:v,[y,v,f]),[x,k]=u.useState(!1),[w,_]=u.useState(s==="dark"?"dark":"light"),[C,E]=u.useState(null),[S,T]=u.useState(null),$=u.useRef(null),A=u.useCallback(()=>{$.current!==null&&(clearTimeout($.current),$.current=null)},[]),z=u.useCallback(()=>{A(),$.current=setTimeout(()=>{E(null),T(null),$.current=null},240)},[A]);u.useEffect(()=>()=>A(),[A]),u.useEffect(()=>{Pz()},[]);const D=u.useCallback(j=>l(j),[l]),O=u.useMemo(()=>b?Ue(f,b.r,b.c):null,[f,b]),M=u.useMemo(()=>O&&typeof O.cell.props?.className=="string"?O.cell.props.className:"",[O]),B=u.useCallback(j=>D(nl(e,c,j)),[e,c,D]),N=u.useCallback(j=>D(Rg(e,c,j)),[e,c,D]),H=u.useCallback((j,oe)=>D(eh(e,c,j,oe)),[e,c,D]),L=u.useCallback(j=>D(nh(e,c,j)),[e,c,D]),I=u.useCallback(j=>D(oh(e,c,j)),[e,c,D]),P=u.useCallback((j,oe)=>D(th(e,c,j,oe)),[e,c,D]),F=u.useCallback(j=>{if(!O)return;const oe=O.gridRow,ue=O.gridCol,J=j==="down"?oe+O.rowSpan:oe+O.rowSpan-1,le=j==="right"?ue+O.colSpan:ue+O.colSpan-1;if(J>=f.rows.length||le>=f.colCount)return;const Ie=ol(e,c,oe,ue,J,le);Ie.ok&&D(Ie.table)},[O,f,e,c,D]),G=!!(O&&O.gridCol+O.colSpan!b||!m||!Ue(f,m.r,m.c)?null:{r0:Math.min(b.r,m.r),c0:Math.min(b.c,m.c),r1:Math.max(b.r,m.r),c1:Math.max(b.c,m.c)},[b,m,f]),Z=u.useMemo(()=>{if(!Y)return[];const j=new Set,oe=[];for(const ue of f.rows)for(const J of ue.cells)if(J.gridRow>=Y.r0&&J.gridRow<=Y.r1&&J.gridCol>=Y.c0&&J.gridCol<=Y.c1){const le=`${J.gridRow}:${J.gridCol}`;j.has(le)||(j.add(le),oe.push({r:J.gridRow,c:J.gridCol}))}return oe},[Y,f]),se=Z.length>1,re=u.useCallback(()=>{if(!Y)return;const j=ol(e,c,Y.r0,Y.c0,Y.r1,Y.c1);j.ok&&(D(j.table),h(null))},[Y,e,c,D]),U=u.useCallback(()=>{b&&D(rh(e,c,b.r,b.c))},[e,c,b,D]),ee=u.useMemo(()=>{const j=c?.cellBorder;return j&&typeof j=="object"?j:null},[c]),fe=u.useMemo(()=>{const j=c?.cellBackground;return j&&typeof j=="object"?j:null},[c]),K=u.useMemo(()=>{const j=c?.cellPadding;return j&&typeof j=="object"?j:null},[c]),ne=u.useMemo(()=>{if(x){const j=new Set,oe=[];for(const ue of f.rows)for(const J of ue.cells){const le=`${J.gridRow}:${J.gridCol}`;j.has(le)||(j.add(le),oe.push({r:J.gridRow,c:J.gridCol}))}return oe}return se?Z:b?[{r:b.r,c:b.c}]:[]},[x,se,Z,b,f]),me=u.useCallback(j=>{if(ne.length===0)return;let oe=e;for(const ue of ne){const J=(ee?.colors??[]).map(Ie=>Ie.token),le=j.split(/\s+/).filter(Ie=>Ie&&!J.includes(Ie)).join(" ");oe=Ci(oe,c,ue.r,ue.c,le)}D(oe)},[e,c,ne,ee,D]),Ce=u.useMemo(()=>{const j=(ee?.sides??[]).find(J=>J.value==="all")??(ee?.sides??[])[0],oe=(ee?.widths??[]).find(J=>J.value!=="none");if(!j||!oe)return[];const ue=oe.suffix??"";return[ue?`${j.prefix}${ue}`:j.prefix]},[ee]),ze=u.useCallback((j,oe,ue)=>{if(Ce.length===0)return j;const J=(ee?.sides??[]).map(Oe=>Oe.prefix),le=Ue(Be(j,c),oe,ue),dt=(typeof le?.cell?.props?.className=="string"?le.cell.props.className:"").split(/\s+/).filter(Boolean);if(dt.some(Oe=>J.some(He=>Oe===He||Oe.startsWith(He+"-")&&/^-?\d+$/.test(Oe.slice(He.length+1)))))return j;const ot=[...dt,...Ce].join(" ").trim();return Ci(j,c,oe,ue,ot)},[Ce,ee,c]),Se=u.useCallback((j,oe)=>{if(j.length===0)return;const ue=new Set(j.map(le=>`${le.r}:${le.c}`));let J=e;for(const le of j){if(J=ze(J,le.r,le.c),J=Jt(J,c,le.r,le.c,"borderColor",oe),le.r>0&&!ue.has(`${le.r-1}:${le.c}`)){const Ie=Ue(Be(J,c),le.r-1,le.c);Ie&&(J=Jt(J,c,Ie.gridRow,Ie.gridCol,"borderBottomColor",oe))}if(le.c>0&&!ue.has(`${le.r}:${le.c-1}`)){const Ie=Ue(Be(J,c),le.r,le.c-1);Ie&&(J=Jt(J,c,Ie.gridRow,Ie.gridCol,"borderRightColor",oe))}}D(J)},[e,c,D,ze]),qe=u.useMemo(()=>(ee?.colors??[]).map(j=>j.token).filter(Boolean),[ee]),De=u.useCallback(j=>{if(ne.length===0||qe.length===0)return;let oe=e;for(const ue of ne)oe=ze(oe,ue.r,ue.c),oe=go(oe,c,ue.r,ue.c,j,qe,w);D(oe)},[ne,e,c,D,ze,qe,w]),Pe=u.useCallback(j=>Se(ne,j),[Se,ne]),Qe=u.useMemo(()=>{if(w==="dark")return"";const j=O?.cell.props?.style;return typeof j?.borderColor=="string"?j.borderColor:""},[O,w]),Me=u.useCallback((j,oe)=>{if(ne.length===0)return;let ue=e;for(const J of ne)ue=Jt(ue,c,J.r,J.c,j,oe);D(ue)},[ne,e,c,D]),Re=u.useMemo(()=>(fe?.colors??[]).map(j=>j.token).filter(j=>!!j),[fe]),ve=u.useCallback(j=>{if(ne.length===0||Re.length===0)return;let oe=e;for(const ue of ne)oe=go(oe,c,ue.r,ue.c,j,Re,w);D(oe)},[ne,e,c,D,Re,w]),te=u.useCallback(j=>Me("backgroundColor",j),[Me]),he=u.useCallback(()=>{if(ne.length===0)return;let j=e;for(const oe of ne)j=go(j,c,oe.r,oe.c,void 0,Re,w),w==="light"&&(j=Jt(j,c,oe.r,oe.c,"backgroundColor",void 0));D(j)},[ne,e,c,D,Re,w]),Q=u.useCallback(j=>Me("padding",j),[Me]),ie=u.useMemo(()=>{if(w==="dark")return"";const j=O?.cell.props?.style;return typeof j?.backgroundColor=="string"?j.backgroundColor:""},[O,w]),_e=u.useMemo(()=>typeof O?.cell.props?.className=="string"?O.cell.props.className:"",[O]),ge=u.useMemo(()=>{const j=O?.cell.props?.style;return typeof j?.padding=="string"?j.padding:""},[O]),Ae=u.useCallback(j=>{const oe=j.currentTarget,ue=oe.style.pointerEvents;oe.style.pointerEvents="none";const J=document.elementFromPoint(j.clientX,j.clientY);oe.style.pointerEvents=ue;const le=J?.closest?.("[data-dnd-handle-path]");le&&le.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0,cancelable:!0,clientX:j.clientX,clientY:j.clientY,pointerId:j.pointerId,pointerType:j.pointerType,button:j.button,isPrimary:!0}))},[]),Ne=u.useMemo(()=>{const j=new Map;for(const oe of p)j.has(oe.ref.gridCol)||j.set(oe.ref.gridCol,oe.box);return j},[p]),Le=u.useMemo(()=>{const j=new Map;for(const oe of p)j.has(oe.ref.gridRow)||j.set(oe.ref.gridRow,oe.box);return j},[p]);if(p.length===0)return null;const q=!!(O&&(O.colSpan>1||O.rowSpan>1)),ae=S!==null?S:b?.c??null,pe=C!==null?C:b?.r??null,$e=n.top-pl-gl-Dh,be=n.left-fl-gl-Dh;return i.jsxs("div",{className:"g7le-table-inplace","data-testid":"g7le-table-inplace",style:{position:"absolute",inset:0,pointerEvents:"none",zIndex:g7},children:[p.map(j=>{const oe=b&&b.r===j.ref.gridRow&&b.c===j.ref.gridCol,ue=Y&&j.ref.gridRow>=Y.r0&&j.ref.gridRow<=Y.r1&&j.ref.gridCol>=Y.c0&&j.ref.gridCol<=Y.c1;return i.jsx("div",{"data-testid":`g7le-inplace-cell-${j.ref.gridRow}-${j.ref.gridCol}`,role:"button",tabIndex:-1,"aria-label":a("layout_editor.table_inplace.select_cell"),onMouseEnter:()=>{A(),E(j.ref.gridRow),T(j.ref.gridCol)},onMouseLeave:()=>{z()},onPointerDown:J=>Ae(J),onClick:J=>{if(J.stopPropagation(),J.shiftKey&&(y||b))h({r:j.ref.gridRow,c:j.ref.gridCol});else{g({r:j.ref.gridRow,c:j.ref.gridCol}),h(null);const le=tl(e,j.ref,c).map(Ie=>`children.${Ie}`).join(".");d?.(le)}},style:{position:"absolute",top:j.box.top,left:j.box.left,width:j.box.width,height:j.box.height,minWidth:Nh,minHeight:Nh,boxSizing:"border-box",pointerEvents:"auto",cursor:"pointer",outline:oe?"2px solid #2563eb":"none",outlineOffset:-2,background:ue&&!oe?"rgba(37,99,235,0.14)":"transparent"}},`cell-${j.ref.gridRow}-${j.ref.gridCol}`)}),i.jsx("div",{"data-testid":"g7le-inplace-col-rail",onMouseEnter:A,onMouseLeave:z,style:{position:"absolute",top:$e,left:n.left,width:n.width,height:pl,pointerEvents:"none"},children:ae!==null&&Ne.has(ae)&&(()=>{const j=ae,oe=Ne.get(j),ue=wi(f,j,-1),J=wi(f,j,1),le=oe.left-n.left;return i.jsxs("div",{"data-testid":`g7le-inplace-colgutter-${j}`,onMouseEnter:()=>{A(),T(j)},onMouseLeave:z,style:{position:"absolute",top:0,left:le,width:oe.width,minWidth:96,height:pl,display:"flex",gap:3,justifyContent:"center",alignItems:"center",pointerEvents:"auto"},children:[i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.move_col_left"),disabled:!ue.ok,onClick:()=>P(j,-1),"data-testid":`g7le-inplace-col-left-${j}`,style:ue.ok?_n:Ei,children:"←"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.add_col"),onClick:()=>L(j),"data-testid":`g7le-inplace-col-add-${j}`,style:_n,children:"+"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.remove_col"),disabled:f.colCount<=1,onClick:()=>I(j),"data-testid":`g7le-inplace-col-remove-${j}`,style:Mh,children:"✕"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.move_col_right"),disabled:!J.ok,onClick:()=>P(j,1),"data-testid":`g7le-inplace-col-right-${j}`,style:J.ok?_n:Ei,children:"→"})]},`colgut-${j}`)})()}),i.jsx("div",{"data-testid":"g7le-inplace-row-rail",style:{position:"absolute",top:n.top,left:be,width:fl,height:n.height,pointerEvents:"none"},children:pe!==null&&Le.has(pe)&&(()=>{const j=pe,oe=Le.get(j),ue=xi(f,j,-1),J=xi(f,j,1),le=oe.top-n.top;return i.jsxs("div",{"data-testid":`g7le-inplace-rowgutter-${j}`,onMouseEnter:()=>{A(),E(j)},onMouseLeave:z,style:{position:"absolute",top:le,left:0,width:fl,height:oe.height,minHeight:48,display:"grid",gridTemplateColumns:"repeat(2, 22px)",gridAutoRows:"22px",gap:3,justifyContent:"center",alignContent:"center",pointerEvents:"auto"},children:[i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.move_row_up"),disabled:!ue.ok,onClick:()=>H(j,-1),"data-testid":`g7le-inplace-row-up-${j}`,style:ue.ok?_n:Ei,children:"↑"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.add_row"),onClick:()=>B(j),"data-testid":`g7le-inplace-row-add-${j}`,style:_n,children:"+"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.remove_row"),disabled:f.rows.length<=1,onClick:()=>N(j),"data-testid":`g7le-inplace-row-remove-${j}`,style:Mh,children:"✕"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.move_row_down"),disabled:!J.ok,onClick:()=>H(j,1),"data-testid":`g7le-inplace-row-down-${j}`,style:J.ok?_n:Ei,children:"↓"})]},`rowgut-${j}`)})()}),i.jsxs("div",{"data-testid":"g7le-inplace-corner-add",style:{position:"absolute",top:n.top+n.height+gl,left:n.left,display:"flex",flexDirection:"column",gap:6,pointerEvents:"auto",minWidth:200,maxWidth:Math.max(240,n.width),background:"#fff",border:"1px solid #e2e8f0",borderRadius:8,padding:8,boxShadow:"0 2px 8px rgba(0,0,0,0.12)"},children:[i.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap"},children:[i.jsxs("button",{type:"button","data-testid":"g7le-inplace-add-row-bottom",onClick:()=>B(f.rows.length-1),style:Lh,children:["+ ",a("layout_editor.table_inplace.add_row")]}),i.jsxs("button",{type:"button","data-testid":"g7le-inplace-add-col-right",onClick:()=>L(f.colCount-1),style:Lh,children:["+ ",a("layout_editor.table_inplace.add_col")]})]}),!b&&i.jsx("div",{"data-testid":"g7le-inplace-select-hint",style:{fontSize:11,color:"#94a3b8",borderTop:"1px solid #f1f5f9",paddingTop:6},children:a("layout_editor.table_inplace.select_cell_hint")}),b&&i.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6,borderTop:"1px solid #f1f5f9",paddingTop:6},children:[se&&i.jsx("div",{"data-testid":"g7le-inplace-range-count",style:{fontSize:11,color:"#2563eb"},children:a("layout_editor.table_inplace.range_selected",{count:Z.length})}),i.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap",alignItems:"center"},children:[se?i.jsx("button",{type:"button","data-testid":"g7le-inplace-merge-range",onClick:re,style:rr,children:a("layout_editor.table_inplace.merge_range")}):i.jsxs(i.Fragment,{children:[i.jsx("button",{type:"button","data-testid":"g7le-inplace-merge-right",disabled:!G,onClick:()=>F("right"),style:G?rr:hl,children:a("layout_editor.table_inplace.merge_right")}),i.jsx("button",{type:"button","data-testid":"g7le-inplace-merge-down",disabled:!V,onClick:()=>F("down"),style:V?rr:hl,children:a("layout_editor.table_inplace.merge_down")})]}),i.jsx("button",{type:"button","data-testid":"g7le-inplace-unmerge",disabled:!q,onClick:U,style:q?rr:hl,children:a("layout_editor.table_inplace.unmerge")})]}),i.jsxs("div",{"data-testid":"g7le-inplace-cell-color",style:{borderTop:"1px solid #f1f5f9",paddingTop:6,display:"flex",flexDirection:"column",gap:6},children:[i.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:11,color:"#475569",cursor:"pointer"},children:[i.jsx("input",{type:"checkbox","data-testid":"g7le-inplace-border-all-toggle",checked:x,onChange:j=>k(j.target.checked)}),a("layout_editor.table_inplace.border_apply_all")]}),i.jsx(yh,{colorScheme:w,onChange:_,t:a}),ee&&i.jsx("div",{"data-testid":"g7le-inplace-cell-border",children:i.jsx(dh,{className:x?"":M,catalog:ee,t:a,onChange:me,colorScheme:w,onPresetToken:De,colorStyle:x?"":Qe,onColorStyle:Pe})}),i.jsx("div",{"data-testid":"g7le-inplace-cell-fill",children:i.jsx(fh,{colorStyle:x?"":ie,className:x?"":_e,catalog:fe,t:a,colorScheme:w,onPresetToken:ve,onCustomColor:te,onClear:he})})]}),i.jsx("div",{"data-testid":"g7le-inplace-cell-padding",style:{borderTop:"1px solid #f1f5f9",paddingTop:6},children:i.jsx(gh,{paddingStyle:x?"":ge,catalog:K,t:a,onChange:Q})})]})]})]})}const _n={width:22,height:22,lineHeight:"20px",padding:0,fontSize:13,border:"1px solid #cbd5e1",borderRadius:5,background:"#fff",color:"#475569",cursor:"pointer",boxShadow:"0 1px 3px rgba(0,0,0,0.18)"},Mh={..._n,border:"1px solid #fecaca",color:"#dc2626"},Ei={..._n,cursor:"not-allowed",opacity:.4,color:"#94a3b8",borderColor:"#e2e8f0"},rr={padding:"4px 10px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",boxShadow:"0 1px 2px rgba(0,0,0,0.12)"},hl={...rr,cursor:"not-allowed",opacity:.4},Lh={padding:"3px 8px",fontSize:11,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"};let Ph=!1;function Bz(){Ph||(Pn("children",qg),Pn("table",T8),Pn("array",$h),Pn("array-group",hz),Pn("array-cell-tree",kz),Oa("table",Oz),Ph=!0)}function Wz(){if(typeof window>"u")return;const e=window.G7Core;if(!e)return;const t=e.layoutEditor,n=Array.isArray(t?.__queue)?t.__queue:[],o=Array.isArray(t?.__readyCallbacks)?t.__readyCallbacks:[];e.layoutEditor={registerWidget:Xe,registerNodeEditor:Pn,registerCanvasOverlay:Oa,onReady:r=>{typeof r=="function"&&r()}};for(const r of n){const[s,...a]=r;try{s==="widget"?Xe(a[0],a[1]):s==="nodeEditor"?Pn(a[0],a[1]):s==="canvasOverlay"&&Oa(a[0],a[1])}catch{}}for(const r of o)try{r()}catch{}}const jz=1280;qN(),Bz(),Wz();async function Hz(e){if(typeof fetch!="function")return[];try{const t=await fetch(en(`/api/admin/templates/${encodeURIComponent(e)}/editor/permission-candidates`,"json"),{credentials:"same-origin",headers:je()});if(!t.ok)return[];const o=(await t.json().catch(()=>null))?.data?.permissions;if(!Array.isArray(o))return[];const r=[];for(const s of o)if(s&&typeof s=="object"){const a=s.key,l=s.name;typeof a=="string"&&a.length>0&&r.push({value:a,label:typeof l=="string"&&l?l:a})}return r}catch{return[]}}function Fz({templateIdentifier:e}){gD({templateIdentifier:e}),hD(e);const{state:t,dispatch:n}=Je(),{t:o}=tt(),r=yo(),s=Cp(),a=xD(),l=t.selectedRoute?.layoutName??null,d=CD(e,l),c=t.editMode==="extension",p=u.useMemo(()=>c?kD(a):s,[c,a,s]),[f,y]=u.useState(null),[g,m]=u.useState(null),[h,v]=u.useState([]),[b,x]=u.useState("user"),[k,w]=u.useState(null),[_,C]=u.useState(null),[E,S]=u.useState([]);u.useEffect(()=>{let te=!1;return(async()=>{try{const he=await fetch(en(`/api/templates/${encodeURIComponent(e)}/components`,"json"),{credentials:"same-origin",headers:{Accept:"application/json"}});if(!he.ok)return;const Q=await he.json().catch(()=>null);!te&&Q&&typeof Q=="object"&&y(Q)}catch{}})(),()=>{te=!0}},[e]),u.useEffect(()=>{let te=!1;return(async()=>{const{spec:he,sampleGlobalSources:Q}=await eb({templateIdentifier:e,coreSeed:$D()});te||(m(he),v(Q),Vz(e,he,Q))})(),()=>{te=!0}},[e]),u.useEffect(()=>{let te=!1;return(async()=>{if(typeof fetch=="function")try{const he=await fetch(`/api/admin/templates/${encodeURIComponent(e)}`,{credentials:"same-origin",headers:je()});if(!he.ok)return;const ie=(await he.json().catch(()=>null))?.data,_e=ie?.type;te||((_e==="admin"||_e==="user")&&x(_e),typeof ie?.name=="string"&&ie.name&&w(ie.name),typeof ie?.version=="string"&&ie.version&&C(ie.version))}catch{}})(),()=>{te=!0}},[e]),u.useEffect(()=>{let te=!1;return(async()=>{if(typeof fetch=="function")try{const he=await fetch("/api/admin/templates/?per_page=100&page=1",{credentials:"same-origin",headers:je()});if(!he.ok)return;const ie=(await he.json().catch(()=>null))?.data?.data;if(!te&&Array.isArray(ie)){const _e=[];for(const ge of ie){if(!ge||typeof ge!="object")continue;const Ae=ge.identifier;if(typeof Ae!="string"||!Ae||ge.is_pending===!0)continue;const Le=ge.type==="admin"?"admin":"user",q=ge.name,ae=ge.version;_e.push({identifier:Ae,name:typeof q=="string"?q:Ae,version:typeof ae=="string"?ae:"",type:Le})}S(_e)}}catch{}})(),()=>{te=!0}},[e]);const T=g?.nesting??null,$=t.selectedRoute?.path??null,A=t.editMode,z=t.selectedRoute?.layoutName??(c?a.document?.hostLayoutName??null:null),D=t.routeTree,O=u.useMemo(()=>{if(A!=="extension"||!z)return null;const te=bl(D,z);return te||`__base__/${z}`},[A,z,D]),M=c&&t.returnRoute===null&&!!z;u.useEffect(()=>{if(!M||!z)return;const te=bl(D,z);te&&n({type:"SET_RETURN_ROUTE",route:{path:te,layoutName:z}})},[M,z,D,n]),u.useEffect(()=>{const te=G4(A,$,O),he=Y4(g?.states?.groups,te);n({type:"SET_AVAILABLE_STATES",states:he,activeStateId:X4(he)})},[g,A,$,O,n]);const[B,N]=u.useState([]);u.useEffect(()=>{let te=!1;return(async()=>{const he=await Hz(e);te||N(he)})(),()=>{te=!0}},[e]),yD(),bD();const H=u.useCallback(te=>{const he=t.routeTree,Q=te.split("?")[0]?.split("#")[0]??te;return Kz(he,Q)?"route_in_tree":"route_not_in_tree"},[t.routeTree]),L=u.useCallback(te=>{const he=te.split("?")[0]?.split("#")[0]??te,Q=yl(t.routeTree,he);Q&&(p.isDirty&&!(!(typeof window<"u")||window.confirm(o("layout_editor.chrome.dirty_guard.message")))||n({type:"SELECT_ROUTE",route:{path:Q.path,layoutName:Q.layoutName}}))},[t.routeTree,p.isDirty,n]),I=u.useRef([]),P=u.useCallback(te=>{I.current=te},[]),[F,G]=u.useState(null),V=u.useCallback(()=>G(null),[]),Y=u.useRef(null),Z=u.useRef(null);u.useEffect(()=>{const te=Z.current,he=Y.current;if(!te||!he||typeof ResizeObserver>"u")return;const Q=()=>{he.style.setProperty("--g7le-header-h",`${Math.round(te.getBoundingClientRect().height)}px`)};Q();const ie=new ResizeObserver(Q);return ie.observe(te),()=>ie.disconnect()},[]);const se=u.useCallback(()=>{p.reload()},[p]),re=u.useCallback(()=>{p.isDirty&&!(!(typeof window<"u")||window.confirm(o("layout_editor.chrome.dirty_guard.message")))||window.G7Core?.dispatch?.({handler:"openWindow",params:{path:`/admin/templates/${b}`,target:"_self"}})},[p.isDirty,o,b]),U=u.useCallback(te=>{if(!te||te===e||p.isDirty&&!(typeof window<"u"?window.confirm(o("layout_editor.chrome.dirty_guard.message")):!0))return;const he=Zs(te);window.G7Core?.dispatch?.({handler:"openWindow",params:{path:he,target:"_self"}})},[e,p.isDirty,o]),ee=u.useCallback(()=>{const te=ME(e,t.selectedRoute?.path??null);window.G7Core?.dispatch?.({handler:"openWindow",params:{path:te}})},[e,t.selectedRoute]),fe=u.useCallback(()=>{const te=t.selectedRoute?.layoutName??"";if(!te)return;const he=r.open({ariaLabel:o("layout_editor.attachment_manager.title"),width:720,maxHeightRatio:.82,content:u.createElement(Ml,{templateIdentifier:e,layoutName:te,t:o,onClose:()=>r.close(he)})})},[r,e,t.selectedRoute,o]),K=u.useCallback(()=>{const te=t.selectedRoute?.layoutName??"";if(!te)return;const he=Hy(s.document?.raw??{}),Q=r.open({ariaLabel:o("layout_editor.translation_manager.title"),width:720,maxHeightRatio:.82,content:u.createElement(dm,{templateIdentifier:e,layoutName:te,t:o,referencedKeys:he,onClose:()=>r.close(Q)})})},[r,e,t.selectedRoute,o,s.document]),ne=u.useCallback((te,he)=>{const Q=window.G7Core;if(Q&&typeof Q.t=="function"){const ie=Q.t(te,he);if(ie&&ie!==te&&!ie.startsWith("$t:"))return ie}return o(te,he)},[o]),me=u.useCallback(()=>{if(!t.selectedRoute||t.editMode==="extension"||t.editMode==="iteration_item")return;const te=r.open({ariaLabel:o("layout_editor.page_settings.title",{name:t.selectedRoute.path??""}),width:1080,maxHeightRatio:.88,closeOnEscape:!1,content:u.createElement(u$,{templateIdentifier:e,spec:g,t:o,resolveLabel:ne,permissionCandidates:B,onClose:()=>r.close(te)})})},[r,t.selectedRoute,t.editMode,o,ne,e,g,B]),Ce=u.useCallback(async()=>{const te=await d.createPreview(s.document?.raw??null);if(te.kind!=="success"){const he=te.kind==="network_error"?te.message:o("layout_editor.preview_action.no_document");typeof window<"u"&&window.alert(he)}},[d,s.document,o]),ze=u.useCallback(()=>{const te=t.selectedRoute?.layoutName??"",he=t.selectedRoute?.path??"",Q=t.editMode==="extension"&&he.startsWith("__extension__/")?he.slice(14):null,ie=Q?{kind:"extension",extensionId:Q}:te?{kind:"layout",layoutName:te}:null;if(!ie)return;const _e=r.open({ariaLabel:o("layout_editor.version_history.title"),width:640,maxHeightRatio:.82,content:u.createElement(X$,{templateIdentifier:e,target:ie,t:o,onRestored:async ge=>{typeof ge=="number"&&(ie.kind==="extension"?n({type:"SET_EXTENSION_VERSION",extensionId:ie.extensionId,version:ge}):n({type:"SET_LAYOUT_VERSION",layoutName:ie.layoutName,version:ge})),await p.reload()},onClose:()=>r.close(_e)})})},[r,e,t.selectedRoute,t.editMode,o,p,n]),Se=p.dirtyKeys.size>0||p.isDirty;u.useEffect(()=>{if(!Se)return;const te=he=>{he.preventDefault(),he.returnValue=""};return window.addEventListener("beforeunload",te),()=>window.removeEventListener("beforeunload",te)},[Se]);const qe=u.useCallback(()=>{!p.isDirty||!(!(typeof window<"u")||window.confirm(o("layout_editor.chrome.reset_guard.message")))||p.reload()},[p,o]),De=u.useCallback(async()=>{const te=await p.save({sessionAddedPaths:I.current});G(te),te.kind==="success"&&typeof te.newContentVersion=="number"&&(te.savedExtensionId?n({type:"SET_EXTENSION_VERSION",extensionId:te.savedExtensionId,version:te.newContentVersion}):te.savedLayoutName&&n({type:"SET_LAYOUT_VERSION",layoutName:te.savedLayoutName,version:te.newContentVersion}))},[p,n]),Pe=u.useCallback(()=>{const te=r.open({ariaLabel:o("layout_editor.shortcuts.title"),width:560,maxHeightRatio:.85,content:u.createElement(iE,{t:o,onClose:()=>r.close(te)})})},[r,o]),Qe=u.useMemo(()=>({save:()=>{De()},exit:re,editCode:ee,reset:qe,translations:K,addElement:()=>{t.selectedRoute&&n({type:"TOGGLE_PALETTE"})},help:Pe,preview:()=>{t.selectedRoute?.layoutName&&Ce()}}),[De,re,ee,qe,K,t.selectedRoute,n,Pe,Ce]),[Me,Re]=u.useState(!1);u.useEffect(()=>{const te=window.setInterval(()=>{Re(!!window.__g7LayoutEditorHasSelection)},200);return()=>window.clearInterval(te)},[]),np({handlers:Qe,hasSelection:Me});const ve=p;return t.routesError?i.jsx("div",{className:"g7le-chrome g7le-chrome--routes-error","data-testid":"g7le-chrome-routes-error",style:{position:"fixed",inset:0,display:"flex",background:"#f8fafc",color:"#0f172a",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple SD Gothic Neo", "Noto Sans KR", sans-serif',fontSize:13,lineHeight:1.5,zIndex:9e3},children:i.jsx(Fa,{error:t.routesError})}):i.jsx("div",{className:"g7le-chrome","data-testid":"g7le-chrome",ref:Y,style:{position:"static",minHeight:"100vh",minWidth:jz,background:"#f8fafc",color:"#0f172a",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple SD Gothic Neo", "Noto Sans KR", sans-serif',fontSize:13,lineHeight:1.5,zIndex:9e3},children:i.jsxs(dy,{value:ve,children:[c&&a.needsHostPicker&&a.document&&i.jsx(SD,{hostLayouts:a.document.hostLayouts,extensionLabel:null,onSelect:a.selectHost}),i.jsxs("div",{className:"g7le-chrome__header","data-testid":"g7le-chrome-header",ref:Z,style:{position:"sticky",top:0,zIndex:20,background:"#f8fafc"},children:[i.jsx(by,{onSave:()=>{De()},isDirty:p.isDirty,onExit:re,onEditCode:ee,onManageImages:fe,onManageTranslations:K,onPageSettings:me,onReset:qe,onShowShortcuts:Pe,onPreview:Ce,onShowVersions:ze,templateName:k,templateVersion:_,templateList:E,onSwitchTemplate:U}),i.jsx(xE,{result:F,onDismiss:V,onLoadLatest:se}),i.jsxs("div",{className:"g7le-chrome__device-toolbar","data-testid":"g7le-chrome-device-toolbar",style:{display:"flex",justifyContent:"center",padding:"6px 12px",background:"#f1f5f9",borderBottom:"1px solid #e2e8f0"},children:[i.jsx(U4,{}),i.jsx(q4,{})]})]}),i.jsxs("div",{className:"g7le-chrome__body",style:{display:"grid",gridTemplateColumns:"auto 1fr",alignItems:"stretch"},children:[i.jsx(HE,{}),i.jsx(j4,{manifest:f,nesting:T,componentPalette:g?.componentPalette??null,spec:g,permissionCandidates:B,sampleGlobalSources:h,resolveRouteMatch:H,onNavigateToDestination:L,onSessionAddedPathsChange:P})]}),i.jsx(py,{})]})})}function yl(e,t){for(const n of e){if(n.kind==="route"&&n.path===t)return n;if(n.children&&n.children.length>0){const o=yl(n.children,t);if(o)return o}}return null}function Kz(e,t){return yl(e,t)!==null}function bl(e,t){for(const n of e){if(n.kind==="route"&&n.layoutName===t&&typeof n.path=="string")return n.path;if(n.children&&n.children.length>0){const o=bl(n.children,t);if(o)return o}}return null}function Vz(e,t,n){const o=[];Va({sources:n,isGuestOnly:!1,warn:s=>{const a=/extension '([^']+)' override of core key '([^']+)'/.exec(s);a&&o.push(`${a[1]}:${a[2]}`)}});const r=t?.sampleData?.byDataSourceId?Object.keys(t.sampleData.byDataSourceId).length:0;Qh({templateIdentifier:e,mergedSources:[...n.map(s=>({kind:s.kind,id:s.id}))],blockCounts:{controls:t?.controls?Object.keys(t.controls).length:0,componentCapabilities:t?.componentCapabilities?Object.keys(t.componentCapabilities).length:0,actionRecipes:t?.actionRecipes?Object.keys(t.actionRecipes).length:0,conditionRecipes:t?.conditionRecipes?Object.keys(t.conditionRecipes).length:0,paletteGroups:t?.componentPalette?.groups?.length??0,stateGroups:t?.states?.groups?.length??0,sampleDataIds:r},sampleGlobalSourceCount:n.length,sampleGlobalConflicts:o,timestamp:Date.now()})}function Oh({templateIdentifier:e,initialLocale:t}){return u.useEffect(()=>()=>{Vh(),qh(),Yh(),Xh(),Jh(),Zh(),Rh(),ey(),ty()},[]),i.jsx(ly,{templateIdentifier:e,initialLocale:t,children:i.jsx(uy,{children:i.jsx(Fz,{templateIdentifier:e})})})}if(typeof window<"u"){const e=window.G7Core||(window.G7Core={});if(e.__LayoutEditorChrome=Oh,typeof e.__onChromeReady=="function")try{e.__onChromeReady()}catch{}}dn.LayoutEditorChrome=Oh,Object.defineProperty(dn,Symbol.toStringTag,{value:"Module"})})(this.G7LayoutEditor=this.G7LayoutEditor||{},ReactJSXRuntime,React,ReactDOM); +`:"",e.message]})]}),i.jsxs("div",{style:{display:"flex",justifyContent:"center",gap:8,flexWrap:"wrap"},children:[e.kind==="unauthorized"&&i.jsx("button",{type:"button","data-testid":"g7le-access-error-action-signin",onClick:a,style:Ka,children:t("layout_editor.access_error.action.sign_in")}),e.kind==="forbidden"&&i.jsx("button",{type:"button","data-testid":"g7le-access-error-action-home",onClick:r,style:Ka,children:t("layout_editor.access_error.action.go_home")}),(e.kind==="not_found"||e.kind==="server_error"||e.kind==="network"||e.kind==="unknown")&&i.jsx("button",{type:"button","data-testid":"g7le-access-error-action-retry",onClick:s,style:Ka,children:t("layout_editor.access_error.action.retry")}),e.kind!=="unauthorized"&&i.jsx("button",{type:"button","data-testid":"g7le-access-error-action-home-secondary",onClick:r,style:S4,children:t("layout_editor.access_error.action.go_admin_home")})]})]})]})}const Ka={padding:"8px 16px",background:"#2563eb",color:"#fff",border:"1px solid #1d4ed8",borderRadius:6,fontSize:13,fontWeight:600,cursor:"pointer"},S4={padding:"8px 16px",background:"#fff",color:"#475569",border:"1px solid #cbd5e1",borderRadius:6,fontSize:13,fontWeight:500,cursor:"pointer"};function C4(e){const t=window;if(typeof t>"u")return{getSnapshot:()=>({globalState:{},localState:{}}),restore:()=>{}};const n=t.G7Core||{},o={templateApp:t.__templateApp,g7CoreState:n.state,g7CoreDispatch:n.dispatch,g7CoreData:n.data,g7CoreModal:n.modal,g7CoreToast:n.toast};let r={...e.initialGlobalState??{}};r._local||(r._local={});const s=[],a=()=>{const c={globalState:{...r},localState:{...r._local??{}}};for(const p of s)try{p(r)}catch{}e.onChange?.(c)},l={},d={getGlobalState:()=>r,setGlobalState:(c,p)=>{typeof c=="function"?r=c(r):r={...r,...c},a()},onGlobalStateChange:c=>(s.push(c),()=>{const p=s.indexOf(c);p>=0&&s.splice(p,1)}),get globalState(){return r},getActionDispatcher:()=>e.actionDispatcher,getDataSource:c=>l[c]??null,setDataSource:(c,p)=>{l[c]=p},refetchDataSource:async c=>null,updateDataSourceItem:(c,p,f)=>l[c]??null,getLocale:()=>e.locale,changeLocale:c=>{},getRouter:()=>({navigate:()=>{},replace:()=>{},push:()=>{}}),updateQueryParams:()=>{}};return t.__templateApp=d,n&&typeof n.dispatch=="function"&&(n.dispatch=(c,p)=>{try{return e.actionDispatcher.executeAction(c,p??{})}catch{return}}),n&&typeof n.modal=="object"&&n.modal!==null&&(n.modal={...n.modal,open:()=>{},close:()=>{},closeAll:()=>{}}),n&&typeof n.toast=="object"&&n.toast!==null&&(n.toast={...n.toast,push:()=>{},dismiss:()=>{}}),{getSnapshot:()=>({globalState:{...r},localState:{...r._local??{}}}),restore:()=>{t.__templateApp===d&&(t.__templateApp=o.templateApp),t.G7Core&&(o.g7CoreState!==void 0&&(t.G7Core.state=o.g7CoreState),o.g7CoreDispatch!==void 0&&(t.G7Core.dispatch=o.g7CoreDispatch),o.g7CoreData!==void 0&&(t.G7Core.data=o.g7CoreData),o.g7CoreModal!==void 0&&(t.G7Core.modal=o.g7CoreModal),o.g7CoreToast!==void 0&&(t.G7Core.toast=o.g7CoreToast)),s.length=0}}}const $4=new Set(["id","userId","postId","orderId","productId","categoryId","commentId","noticeId","inquiryId","addressId","wishlistId","notificationId","roleId","menuId"]);function E4(e){if(!e)return{};const t={},n=/:([a-zA-Z_][a-zA-Z0-9_]*)/g;let o;for(;(o=n.exec(e))!==null;){const r=o[1];t[r]=I4(r)}return t}function I4(e){return $4.has(e)||/Id$|_id$/.test(e)?"1":"sample"}const A4=bo("LayoutEditor");function Jo(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function bi(e){if(Array.isArray(e))return e.map(t=>bi(t));if(Jo(e)){const t={};for(const[n,o]of Object.entries(e))t[n]=bi(o);return t}return e}function mg(e,t="",n=new Set){for(const[o,r]of Object.entries(e)){const s=t?`${t}.${o}`:o;Jo(r)?mg(r,s,n):n.add(s)}return n}function vg(e,t,n,o,r,s=""){for(const[a,l]of Object.entries(t)){const d=s?`${s}.${a}`:a;if(n.has(d)){r(`[LayoutEditor] sampleGlobal key conflict: extension '${o}' override of core key '${d}' ignored`);continue}const c=e[a];Jo(l)&&Jo(c)?vg(c,l,n,o,r,d):e[a]=bi(l)}}function Va(e){const t=e.warn??(r=>A4.warn(r)),n=bi(e.coreSeed??{});e.isGuestOnly&&"currentUser"in n&&delete n.currentUser;const o=mg(n);for(const r of e.sources)Jo(r.sampleGlobal)&&vg(n,r.sampleGlobal,o,r.id,t);return e.isGuestOnly&&"currentUser"in n&&delete n.currentUser,n}function T4(e){const t={};if(!e||typeof e!="object"||Array.isArray(e))return t;for(const[n,o]of Object.entries(e))n.startsWith("$")&&(t[n]=o);return t}function D4(e){const t={};if(!e||typeof e!="object"||Array.isArray(e))return t;for(const[n,o]of Object.entries(e))n.startsWith("$")||(t[n]=o);return t}function N4(e){if(typeof e!="string")return null;const t=/^\s*\{\{\s*([\s\S]*?)\s*\}\}\s*$/.exec(e);if(!t)return null;let n=t[1];const o=n.indexOf("??");return o>=0&&(n=n.slice(0,o)),n=n.replace(/\?\./g,".").replace(/\s+/g,""),n===""||!/^[A-Za-z_$][A-Za-z0-9_$]*(\.[A-Za-z_$][A-Za-z0-9_$]*)*$/.test(n)?null:n.split(".")}function z4(e,t){const n=N4(t);if(!n||n.length===0)return e;let o=e;for(let a=0;ao.map(r=>{if(!r||typeof r!="object")return r;const s=r;let a=s;if(typeof s.slot=="string"&&!t.has(s.slot)){const{slot:l,...d}=s;a={...d,__editorSlotName:l}}if(Array.isArray(a.children)){const l=n(a.children);l!==a.children&&(a={...a,children:l})}return a});return n(e)}function St(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Xt(e){if(Array.isArray(e))return e.map(t=>Xt(t));if(St(e)){const t={};for(const[n,o]of Object.entries(e))t[n]=Xt(o);return t}return e}function mi(e,t){for(const[n,o]of Object.entries(t)){const r=e[n];St(o)&&St(r)?mi(r,o):e[n]=Xt(o)}}function P4(e){const t=[];let n="";for(let o=0;o0&&(t.push(n),n="");const s=e[o+1];if(s==="'"||s==='"'){const l=e.indexOf(`${s}]`,o+2);if(l!==-1){t.push(e.slice(o+2,l)),o=l+1;continue}}const a=e.indexOf("]",o+1);if(a!==-1){t.push(e.slice(o+1,a)),o=a;continue}n+=r}else r==="."?n.length>0&&(t.push(n),n=""):n+=r}return n.length>0&&t.push(n),t.filter(o=>o.length>0)}function Ua(e,t,n){const o=P4(t);if(o.length===0)return;let r=e;for(let s=0;s0?t:void 0}const Ga="g7le:editor-t-ready",wg="data-g7le-vh-expanded";function B4(e,t){if(!e||!t)return;const n=t;e.querySelectorAll("*").forEach(r=>{const s=window.getComputedStyle(r),a=parseFloat(s.height),l=Number.isFinite(a)&&Math.abs(a-n)<=2,d=parseFloat(s.minHeight),c=Number.isFinite(d)&&Math.abs(d-n)<=2,p=s.overflowY==="auto"||s.overflowY==="scroll"||s.overflowY==="hidden"||s.overflow==="auto"||s.overflow==="scroll"||s.overflow==="hidden";l&&p?(r.style.setProperty("height","auto","important"),c&&r.style.setProperty("min-height","0","important"),r.style.setProperty("overflow","visible","important"),r.setAttribute(wg,"1")):(s.overflowY==="auto"||s.overflowY==="scroll")&&r.scrollHeight>r.clientHeight+4&&r.clientHeight>120&&(r.style.setProperty("overflow","visible","important"),r.style.setProperty("height","auto","important"),r.setAttribute(wg,"1"))})}const W4=[];function j4(e={}){const{manifest:t=null,nesting:n=null,componentPalette:o=null,spec:r=null,permissionCandidates:s,sampleGlobalSources:a=W4,resolveRouteMatch:l,onNavigateToDestination:d,onSessionAddedPathsChange:c}=e,{state:p}=Je(),f=Ft(),y=Cp(),{document:g,isLoading:m,error:h}=f??y,v=u.useRef(null),[b,x]=u.useState(null),{deviceWidth:k,scale:w,colorScheme:_}=ja(),C=u.useMemo(()=>p.activeStateId?p.availableStates.find(Q=>Q.id===p.activeStateId)??null:null,[p.activeStateId,p.availableStates]),E=u.useMemo(()=>xg(C),[C]),S=f4({isEditMode:!0,editorSpec:r??void 0,sampleOverride:E}),{t:T}=tt(),{componentRegistry:$,translationEngine:A,isReady:z,error:D}=_4(p.templateIdentifier,p.locale),O=u.useRef(null);O.current===null&&(O.current=new vd);const M=u.useRef(null);if(M.current===null){M.current=new VE({navigate:()=>{}}),M.current.setPreviewMode(!0);try{const ie=window.__templateApp?.getActionDispatcher?.();if(ie&&typeof ie.getRegisteredHandlers=="function"){const _e=ie.getRegisteredHandlers();for(const ge of _e){if(!ge.includes("."))continue;const Ae=typeof ie.getHandler=="function"?ie.getHandler(ge):void 0;typeof Ae=="function"&&M.current.registerHandler(ge,Ae,{category:"plugin",source:"preview-canvas-cloned-from-host"})}}}catch{}}u.useEffect(()=>{if(!z)return;const Q=M.current;if(Q)try{const ie=window.G7Core?.getActionDispatcher?.();if(!ie||typeof ie.getRegisteredHandlers!="function")return;const _e=ie.getRegisteredHandlers();for(const ge of _e){if(!ge.includes(".")||typeof Q.getHandler=="function"&&Q.getHandler(ge))continue;const Ae=typeof ie.getHandler=="function"?ie.getHandler(ge):void 0;typeof Ae=="function"&&Q.registerHandler(ge,Ae,{category:"plugin",source:"preview-canvas-iife-reclone"})}}catch{}},[z]);const B=u.useMemo(()=>new UE({sampleProvider:S,actionDispatcher:M.current}),[S]),N=u.useMemo(()=>g?.raw?.meta?.guest_only===!0,[g]),H=u.useMemo(()=>Va({sources:a,isGuestOnly:N}),[a,N]),L=u.useMemo(()=>{const Q=H4(qa(C),A,{templateId:p.templateIdentifier,locale:p.locale}),ie=H._local,{global:_e,local:ge}=O4({globalBaseline:H,localBaseline:ie??{},patch:C?.initialState??null,formErrors:Q});return{..._e,_local:ge}},[H,C,A,p.templateIdentifier,p.locale]),I=u.useMemo(()=>!C||!(!!C.initialState?.local||!!qa(C))?null:{...L._local??{},_forceLocalInit:C.id,_merge:"deep"},[C,L]),P=Q=>typeof Q=="object"&&Q!==null&&!Array.isArray(Q),F=u.useMemo(()=>P(C?.initialState?.query)?C.initialState.query:null,[C]),G=u.useMemo(()=>P(C?.initialState?.route)?C.initialState.route:null,[C]),[V,Y]=u.useState(()=>Va({sources:[],isGuestOnly:!1})),Z=u.useRef(null);u.useEffect(()=>{const Q={...L},ie=C4({actionDispatcher:M.current,locale:p.locale,initialGlobalState:Q,onChange:ge=>{Y(ge.globalState)}});Z.current=ie;const _e=window.__templateApp;return _e?.setGlobalState&&M.current.setGlobalStateUpdater((ge,Ae)=>{_e.setGlobalState(ge,Ae)}),Y(Q),$l({kind:"applyPatch",activeStateId:p.activeStateId,routePath:p.selectedRoute?.path??null,hasInitialPatch:!!C?.initialState,hasFormErrors:!!qa(C),hasSampleOverride:!!xg(C)}),()=>{ie.restore(),Z.current=null}},[p.locale,L]),u.useEffect(()=>{if(!A)return;const Q=window.G7Core;if(!Q||typeof Q.t!="function")return;const ie=Q.t,_e=p.templateIdentifier,ge=p.locale;return Q.t=(Ae,Ne)=>{try{const Le=Ne?"|"+Object.entries(Ne).map(([ae,pe])=>`${ae}=${pe}`).join("|"):void 0,q=A.translate(Ae,{templateId:_e,locale:ge},Le);if(q!==Ae&&!q.startsWith("$t:"))return q}catch{}return ie(Ae,Ne)},typeof window<"u"&&window.dispatchEvent(new CustomEvent(Ga)),()=>{window.G7Core?.t&&window.G7Core.t!==ie&&(window.G7Core.t=ie)}},[A,p.templateIdentifier,p.locale]);const se=u.useMemo(()=>{const Q=g?.raw?.components??[];return p.editMode!=="base"?Q:L4(Q)},[g,p.editMode]),re=g?.raw?.__editability,U=g?.raw?.__extensionId,ee=u.useMemo(()=>p.editMode!=="extension"||re!=="ok"?[]:typeof U!="number"?[]:F4(se,U),[p.editMode,re,U,se]),[fe,K]=u.useState(null),[ne,me]=u.useState(!1),Ce=g?.layoutName??null,ze=u.useMemo(()=>{const Q=g?.raw?.scripts??[];return Array.isArray(Q)?Q.map(ie=>ie&&typeof ie.src=="string"?ie.src:"").join("|"):""},[g]);u.useEffect(()=>{me(!1)},[Ce,ze]),u.useEffect(()=>{let Q=!1;const ie=g?.raw?.scripts??[];if(!Array.isArray(ie)||ie.length===0){me(!0);return}const _e=[];for(const ge of ie){if(!ge?.src||typeof ge.src!="string")continue;const Ae=ge.id?`script#${CSS.escape(ge.id)}, script[data-g7le-canvas-script="${ge.src}"]`:`script[data-g7le-canvas-script="${ge.src}"], script[src="${ge.src}"]`,Ne=window.document.querySelector(Ae);if(Ne){const Le=Ne.hasAttribute("data-g7le-canvas-script");if(Ne.hasAttribute("data-g7le-script-loaded")||!Le)continue;_e.push(new Promise(ae=>{if(Ne.hasAttribute("data-g7le-script-loaded")){ae();return}Ne.addEventListener("load",()=>ae()),Ne.addEventListener("error",()=>ae())}));continue}_e.push(new Promise(Le=>{const q=window.document.createElement("script");q.src=ge.src,q.async=!1,ge.id&&(q.id=ge.id),q.setAttribute("data-g7le-canvas-script",ge.src);const ae=()=>{q.setAttribute("data-g7le-script-loaded","1"),Le()};q.addEventListener("load",ae),q.addEventListener("error",ae),window.document.head.appendChild(q)}))}if(_e.length===0){me(!0);return}return Promise.all(_e).then(()=>{Q||requestAnimationFrame(()=>{requestAnimationFrame(()=>{Q||me(!0)})})}),()=>{Q=!0}},[g]);const Se=u.useMemo(()=>g?.raw?.data_sources??[],[g]),qe=u.useMemo(()=>g?.raw?.computed??{},[g]),[De,Pe]=u.useState({}),Qe=u.useMemo(()=>{if(p.editMode!=="iteration_item")return De;const Q=g?.iterationContext;if(!Q)return De;const ie=g?.raw?.components??[],_e=We({children:ie},Q.sourceIndexPath),ge=_e&&_e.iteration&&typeof _e.iteration.source=="string"?_e.iteration.source:null;return ge?z4(De,ge):De},[p.editMode,De,g]),[Me,Re]=u.useState(0);u.useEffect(()=>{if(typeof window>"u")return;const Q=()=>Re(ie=>ie+1);return window.addEventListener(kt,Q),()=>window.removeEventListener(kt,Q)},[]);const ve=u.useMemo(()=>E4(p.selectedRoute?.path??null),[p.selectedRoute?.path]);if(u.useEffect(()=>{let Q=!1;return(async()=>{if(Se.length===0){Q||Pe({});return}try{const ie=await B.fetchDataSources(Se,ve,new URLSearchParams,void 0,void 0);Q||Pe(ie)}catch{Q||Pe({})}})(),()=>{Q=!0}},[Se,B,ve]),u.useEffect(()=>{const Q=b;if(!Q||typeof window>"u")return;let ie=0,_e=0,ge=0;const Ae=()=>B4(Q,window.innerHeight);ie=window.requestAnimationFrame(()=>{_e=window.requestAnimationFrame(Ae)});let Ne=null;return typeof MutationObserver<"u"&&(Ne=new MutationObserver(()=>{ge||(ge=window.requestAnimationFrame(()=>{ge=0,Ae()}))}),Ne.observe(Q,{childList:!0,subtree:!0})),()=>{window.cancelAnimationFrame(ie),window.cancelAnimationFrame(_e),ge&&window.cancelAnimationFrame(ge),Ne&&Ne.disconnect()}},[b,se,ne,k,De]),u.useEffect(()=>{const Q=b;if(!Q||typeof window>"u"||p.editMode!=="extension"||re!=="ok"||ee.length===0){K(null);return}let ie=0,_e=0;const ge=ae=>{if(!ae)return!1;const pe=ae.getBoundingClientRect();return pe.width>0&&pe.height>0},Ae=ae=>{const pe=Q.querySelector(`[data-editor-path="${ae}"]`);if(ge(pe))return!0;const $e=Q.querySelectorAll(`[data-editor-path^="${ae}.children."]`);for(const be of Array.from($e))if(ge(be))return!0;return!1},Ne=()=>{K(ee.some(Ae))};ie=window.requestAnimationFrame(()=>{_e=window.requestAnimationFrame(Ne)});let Le=null,q=0;return typeof MutationObserver<"u"&&(Le=new MutationObserver(()=>{q||(q=window.requestAnimationFrame(()=>{q=0,Ne()}))}),Le.observe(Q,{childList:!0,subtree:!0})),()=>{window.cancelAnimationFrame(ie),window.cancelAnimationFrame(_e),q&&window.cancelAnimationFrame(q),Le&&Le.disconnect()}},[b,p.editMode,re,ee,ne,De]),u.useEffect(()=>{if(typeof window>"u"||p.editMode!=="base")return;const Q=window.document,ie="g7le-base-slot-style";if(Q.getElementById(ie))return;const _e=Q.createElement("style");_e.id=ie;const ge=T("layout_editor.preview.slot_area_label");return _e.textContent=`.g7le-preview-frame [data-editor-slot]{position:relative;min-height:96px;outline:2px dashed #94a3b8;outline-offset:-2px;}.g7le-preview-frame [data-editor-slot]::after{content:'${ge.replace(/'/g,"\\'")} · ' attr(data-editor-slot);position:absolute;top:8px;left:50%;transform:translateX(-50%);font-size:12px;line-height:1;color:#64748b;background:rgba(241,245,249,0.92);border:1px solid #cbd5e1;border-radius:9999px;padding:4px 12px;pointer-events:none;white-space:nowrap;}`,Q.head.appendChild(_e),()=>{Q.getElementById(ie)?.remove()}},[p.editMode,T]),!(p.editMode==="extension"||p.editMode==="iteration_item")&&(p.selectedRoute?.layoutName===null||p.selectedRoute===null))return i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--empty","data-testid":"g7le-preview-empty",style:Zo,children:T("layout_editor.preview.empty")});if(m)return i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--loading","data-testid":"g7le-preview-loading",style:Zo,children:T("layout_editor.preview.loading")});if(h)return i.jsx(Fa,{error:h});if(D)return i.jsx(Fa,{error:D});if(!z||$===null||A===null)return i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--assets-loading","data-testid":"g7le-preview-assets-loading",style:Zo,children:T("layout_editor.preview.assets_loading")});if(se.length===0)return i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--empty-layout","data-testid":"g7le-preview-empty-layout",style:Zo,children:T("layout_editor.preview.empty_layout")});const he=p.editMode==="extension"?re==="no-injection"?"no-injection":re==="ok"&&ee.length>0&&fe!==!0?"gated-no-state":null:null;return ne?i.jsx("div",{className:"g7le-preview-canvas","data-testid":"g7le-preview-canvas",style:{overflow:"visible",background:"#f1f5f9",padding:24,display:"flex",justifyContent:"center",alignItems:"flex-start",minHeight:"calc(100vh - var(--g7le-header-h, 0px))",boxSizing:"border-box"},children:i.jsxs("div",{className:"g7le-preview-frame-wrapper","data-testid":"g7le-preview-frame-wrapper",style:{position:"relative",width:k,transform:`scale(${w})`,transformOrigin:"top center"},children:[i.jsx("div",{className:_==="dark"?"g7le-preview-frame g7le-preview-dark":"g7le-preview-frame","data-testid":"g7le-preview-frame","data-color-scheme":_,ref:Q=>{v.current=Q,x(Q)},style:{width:k,background:"#fff",border:"1px solid #cbd5e1",boxShadow:"0 1px 3px rgba(0,0,0,0.05)",minHeight:400,position:"relative",transform:"translateZ(0)",overflow:"hidden"},children:i.jsx(KE,{overrideWidth:k,children:se.map((Q,ie)=>i.jsx(FE,{componentDef:Q,dataContext:{...Qe,...T4(V),_global:D4(V),_computedDefinitions:qe,...I?{_localInit:I,_local:{...De._local??{},...V._local??{}}}:{},route:K4({...De.route??{},...ve,path:p.selectedRoute?.path??""},G),query:{...De.query??{},...F??{}}},translationContext:{templateId:p.templateIdentifier,locale:p.locale},registry:$,bindingEngine:O.current,translationEngine:Pt.getInstance(),actionDispatcher:M.current,isEditMode:!0,isRootRenderer:ie===0,componentPath:`${ie}`,onComponentSelect:(_e,ge)=>{},onComponentHover:(_e,ge)=>{}},`${Q.id??`preview-${ie}`}:t${Me}${p.editMode==="extension"?`:s${ne?1:0}`:""}`))})}),i.jsx("div",{className:"g7le-overlay-layer","data-testid":"g7le-overlay-layer",style:{position:"absolute",left:0,top:0,width:k,height:b?b.getBoundingClientRect().height/(w||1):"100%",overflow:"visible",pointerEvents:"none"},children:i.jsx(p4,{frameEl:b,manifest:t,nesting:n,componentPalette:o,spec:r,permissionCandidates:s,resolveRouteMatch:l,onNavigateToDestination:d,onSessionAddedPathsChange:c})}),he!==null&&i.jsx("div",{className:"g7le-preview-canvas--extension-fallback","data-testid":"g7le-preview-extension-fallback","data-fallback-reason":he,style:{position:"absolute",left:0,top:0,right:0,bottom:0,minHeight:b?b.getBoundingClientRect().height/(w||1):400,background:"#f1f5f9",display:"flex",alignItems:"flex-start",justifyContent:"center",padding:24,boxSizing:"border-box",pointerEvents:"auto",zIndex:50},children:i.jsxs("div",{className:"g7le-extension-fallback-card",style:{maxWidth:440,textAlign:"center",position:"sticky",top:"calc(40vh - var(--g7le-header-h, 0px))"},children:[i.jsx("p",{className:"g7le-extension-fallback-title",style:{fontWeight:600,marginBottom:8,color:"#0f172a"},children:T(he==="no-injection"?"layout_editor.preview.extension_no_injection_title":"layout_editor.preview.extension_gated_title")}),i.jsx("p",{className:"g7le-extension-fallback-desc",style:{color:"#475569",lineHeight:1.6},children:he==="no-injection"?T("layout_editor.preview.extension_no_injection_desc"):p.availableStates.length>1?T("layout_editor.preview.extension_gated_desc_with_states"):T("layout_editor.preview.extension_gated_desc")})]})})]})}):i.jsx("div",{className:"g7le-preview-canvas g7le-preview-canvas--scripts-loading","data-testid":"g7le-preview-scripts-loading",style:Zo,children:T("layout_editor.preview.loading")})}function H4(e,t,n){if(!e)return;if(!t)return e;const o=s=>{if(typeof s=="string"&&s.startsWith("$t:"))try{const a=s.slice(3),l=a.indexOf("|");if(l===-1)return t.translate(a,n);const d=a.slice(0,l),c=a.slice(l);return t.translate(d,n,c)}catch{return s}return Array.isArray(s)?s.map(o):s},r={};for(const[s,a]of Object.entries(e))r[s]=o(a);return r}function F4(e,t){const n=[],o=(r,s)=>{Array.isArray(r)&&r.forEach((a,l)=>{if(!a||typeof a!="object")return;const d=s?`${s}.children.${l}`:`${l}`,c=a.__source;if(c?.kind==="extension"&&c.extensionId===t){n.push(d);return}Array.isArray(a.children)&&o(a.children,d)})};return o(e,""),n}function K4(e,t){if(!t)return e;const n={...e};for(const[o,r]of Object.entries(t))r===null?delete n[o]:n[o]=r;return n}const Zo={flex:1,display:"flex",alignItems:"center",justifyContent:"center",padding:24,background:"#f1f5f9",color:"#64748b",fontSize:13},V4={desktop:"layout_editor.device.desktop",tablet:"layout_editor.device.tablet",mobile:"layout_editor.device.mobile",portable:"layout_editor.device.portable"};function U4(){const{device:e,zoom:t,customWidth:n,setDevice:o,setZoom:r,setCustomWidth:s,colorScheme:a,setColorScheme:l}=ja(),{t:d}=tt(),c=Gf();return i.jsxs("div",{className:"g7le-device-toolbar","data-testid":"g7le-device-toolbar",style:{display:"inline-flex",alignItems:"center",gap:8,padding:"4px 8px",background:"#fff",border:"1px solid #cbd5e1",borderRadius:6},children:[i.jsxs("div",{role:"group","aria-label":d("layout_editor.device.group_label"),children:[c.map(p=>{const f=e===p,y=V4[p],g=y?d(y):p;return i.jsx("button",{type:"button","data-testid":`g7le-device-${p}`,"aria-pressed":f,onClick:()=>o(p),style:{padding:"2px 8px",marginRight:2,fontSize:12,cursor:"pointer",background:f?"#0f172a":"#f8fafc",color:f?"#fff":"#0f172a",border:"1px solid #cbd5e1",borderRadius:4},children:g},p)}),(()=>{const p=e==="custom";return i.jsx("button",{type:"button","data-testid":"g7le-device-custom","aria-pressed":p,onClick:()=>o("custom"),style:{padding:"2px 8px",marginRight:2,fontSize:12,cursor:"pointer",background:p?"#0f172a":"#f8fafc",color:p?"#fff":"#0f172a",border:"1px solid #cbd5e1",borderRadius:4},children:d("layout_editor.device.custom")})})()]}),e==="custom"&&i.jsxs("div",{style:{display:"inline-flex",alignItems:"center",gap:4},children:[i.jsx("label",{htmlFor:"g7le-custom-width-input",style:{fontSize:11,color:"#475569"},children:d("layout_editor.device.custom_width_label")}),i.jsx("input",{id:"g7le-custom-width-input",type:"number",min:ug,max:pg,step:10,value:n,"data-testid":"g7le-custom-width-input","aria-label":d("layout_editor.device.custom_width_label"),onChange:p=>{const f=parseInt(p.currentTarget.value,10);Number.isFinite(f)&&s(f)},style:{width:72,padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:4}}),i.jsx("span",{style:{fontSize:11,color:"#475569"},children:"px"})]}),i.jsx("div",{role:"group","aria-label":d("layout_editor.toolbar.color_scheme_group"),style:{display:"inline-flex",gap:2},children:["light","dark"].map(p=>{const f=a===p;return i.jsx("button",{type:"button","data-testid":`g7le-toolbar-scheme-${p}`,"aria-pressed":f,onClick:()=>l(p),style:{padding:"2px 8px",fontSize:12,cursor:"pointer",background:f?"#0f172a":"#f8fafc",color:f?"#fff":"#0f172a",border:"1px solid #cbd5e1",borderRadius:4},children:d(p==="light"?"layout_editor.toolbar.color_scheme_light":"layout_editor.toolbar.color_scheme_dark")},p)})}),i.jsxs("div",{style:{display:"inline-flex",alignItems:"center",gap:4},children:[i.jsx("span",{style:{fontSize:11,color:"#475569"},children:d("layout_editor.zoom.label")}),i.jsx("input",{type:"range",min:.5,max:1,step:.05,value:t,"data-testid":"g7le-zoom-slider","aria-label":d("layout_editor.zoom.aria_label"),onChange:p=>r(parseFloat(p.currentTarget.value)),style:{width:100}}),i.jsxs("span",{style:{fontSize:11,color:"#475569",minWidth:36,textAlign:"right"},children:[Math.round(t*100),"%"]})]}),i.jsx(Kb,{})]})}function q4(){const{t:e}=tt(),{state:t,dispatch:n}=Je(),{availableStates:o,activeStateId:r}=t,[,s]=u.useState(0);u.useEffect(()=>{if(typeof window>"u")return;const p=()=>s(y=>y+1),f=window.requestAnimationFrame(p);return window.addEventListener(Ga,p),()=>{window.cancelAnimationFrame(f),window.removeEventListener(Ga,p)}},[]);const a=u.useCallback((p,f)=>{if(!p)return f;if(!p.startsWith("$t:"))return p;const y=p.slice(3),g=window.G7Core;if(g&&typeof g.t=="function"){const h=g.t(y);if(h&&h!==y&&!h.startsWith("$t:"))return h}const m=e(y);return m&&m!==y?m:f},[e]);if(!Array.isArray(o)||o.length<=1)return null;const l=p=>{const f=p.target.value;n({type:"SET_ACTIVE_STATE",activeStateId:f}),$l({kind:"change",activeStateId:f,routePath:t.selectedRoute?.path??null,availableCount:o.length})},d=o.find(p=>p.id===r)??o[0],c=d?.description?a(d.description,""):"";return i.jsxs("div",{className:"g7le-state-switcher","data-testid":"g7le-state-switcher","data-active-state":r??"",style:{display:"inline-flex",alignItems:"center",gap:6,padding:"4px 8px",background:"#fff",border:"1px solid #cbd5e1",borderRadius:6},children:[i.jsx("span",{style:{fontSize:12,fontWeight:600,color:"#475569",whiteSpace:"nowrap"},children:e("layout_editor.toolbar.state")}),i.jsx("select",{"data-testid":"g7le-state-switcher-select","aria-label":e("layout_editor.toolbar.state"),value:r??o[0].id,onChange:l,style:{fontSize:12,padding:"2px 6px",border:"1px solid #cbd5e1",borderRadius:4,background:"#fff",color:"#0f172a",cursor:"pointer",outline:"none"},children:o.map(p=>i.jsx("option",{value:p.id,children:a(p.label,p.id)},p.id))}),c&&i.jsx("span",{"data-testid":"g7le-state-switcher-description",style:{fontSize:11,color:"#94a3b8",whiteSpace:"nowrap"},children:c})]})}function G4(e,t,n){if(e==="extension"){if(typeof n=="string"&&n.length>0){const o=Ya(n,"__base__/");return o?{kind:"base",match:o}:{kind:"route",match:n}}return null}if(!t)return null;switch(e){case"route":return{kind:"route",match:t};case"base":{const o=Ya(t,"__base__/");return o?{kind:"base",match:o}:null}case"modal":{const o=Ya(t,"__modal__/");return o?{kind:"modal",match:o}:null}default:return null}}function Y4(e,t){if(!t||!Array.isArray(e)||e.length===0)return[];const n=[];for(const o of e)if(J4(o.scope,t))for(const r of o.items??[])r&&typeof r.id=="string"&&r.id.length>0&&n.push(r);return n}function X4(e){if(e.length===0)return null;const t=e.find(n=>n.default===!0);return t?t.id:e[0].id}function J4(e,t){if(!e||e.kind!==t.kind)return!1;const n=e.match;return typeof n!="string"||n.length===0?!1:t.kind==="route"?Z4(t.match,n):n===t.match}function Z4(e,t){if(t===e)return!0;if(!t.includes("*"))return!1;const n=t.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\/\*\\\?/g,"(?:/[^/]+)?").replace(/\*/g,"[^/]+");return new RegExp(`^${n}$`).test(e)}function Ya(e,t){return e.startsWith(t)?e.slice(t.length):""}const Q4="__conngroup__/modals/",R4="__conngroup__/extensions/";function eD(e){return e.meta?.editor_label?{label:e.meta.editor_label,labelSource:"editor_label"}:e.meta?.title?{label:e.meta.title,labelSource:"title"}:{label:e.path,labelSource:"path"}}function tD(e){switch(e.source.kind){case"template":return"template";case"module":return`module:${e.source.identifier??""}`;case"plugin":return`plugin:${e.source.identifier??""}`;case"core":return null;default:return null}}function nD(e,t){if(e.meta?.parent&&t.has(e.meta.parent))return e.meta.parent;const n=e.path.split("/").filter(Boolean);for(let o=n.length-1;o>=1;o--){const r="/"+n.slice(0,o).join("/");if(r!==e.path&&t.has(r))return r}return null}function oD(e){const t=new Map;for(const n of e)n.layout&&t.set(n.layout,(t.get(n.layout)??0)+1);return t}function rD(e){const t=new Map;for(const n of e){if(!n.hostLayout)continue;const o=t.get(n.hostLayout)??[];o.push(n),t.set(n.hostLayout,o)}return t}function iD(e){const t=new Map;for(const n of e)for(const o of n.extensions)for(const r of o.hostLayouts??[]){if(!r)continue;const s=t.get(r)??[];s.push({extension:o,group:n}),t.set(r,s)}return t}function sD(e,t){return{path:`__modal__/${e.hostLayout}/${e.modalId}`,layoutName:e.hostLayout,label:e.label??e.modalId,labelSource:e.label?"editor_label":"path",source:{kind:"core",identifier:null},kind:"modal",modalId:e.modalId,modalHostLayout:e.hostLayout,connectedHostRoutePath:t,children:[]}}function aD(e,t){const{extension:n,group:o}=e,r=o.sourceType==="plugin"?"🔌":"🧩";return{path:`__extension__/${n.id}`,layoutName:null,label:`${r} ${o.sourceLabel} · ${n.targetName}`,labelSource:"path",source:{kind:o.sourceType,identifier:o.sourceIdentifier},kind:"extension",extensionId:String(n.id),extensionType:n.extensionType,extensionPriority:n.priority,extensionTargetName:n.targetName,isModified:n.isModified,isInactive:!n.isActive,connectedHostRoutePath:t,children:[]}}function kg(e,t,n){if(e.kind!=="route"&&e.kind!=="base"||!e.layoutName)return;const o=[],r=t.get(e.layoutName)??[];r.length>0&&o.push({path:`${Q4}${e.path}`,layoutName:null,label:`$t:layout_editor.chrome.route_tree.connected.modals|count=${r.length}`,labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:r.map(a=>sD(a,e.path))});const s=n.get(e.layoutName)??[];s.length>0&&o.push({path:`${R4}${e.path}`,layoutName:null,label:`$t:layout_editor.chrome.route_tree.connected.extensions|count=${s.length}`,labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:s.map(a=>aD(a,e.path))}),o.length>0&&(e.children=[...o,...e.children??[]])}function lD(e){const t=[],n=new Set(e.routes.map(o=>o.path));for(const o of e.routes){const r=tD(o);if(!r)continue;const{label:s,labelSource:a}=eD(o),l=nD(o,n),d={path:o.path,layoutName:o.layout??null,label:s,labelSource:a,icon:o.meta?.icon??null,source:o.source,isRedirect:!!o.redirect,isHidden:!!o.meta?.hidden,kind:"route",children:[]};t.push({node:d,parentKey:l,groupKey:r})}return t}function dD(e,t){if(e==="template")return"$t:layout_editor.chrome.route_tree.group.template";if(e.startsWith("module:")){const n=e.slice(7);return`$t:layout_editor.chrome.route_tree.group.module|name=${t.moduleDisplayNames[n]??n}`}if(e.startsWith("plugin:")){const n=e.slice(7);return`$t:layout_editor.chrome.route_tree.group.plugin|name=${t.pluginDisplayNames[n]??n}`}return e}function cD(e,t){oD(e.routes);const n=rD(e.modals),o=iD(e.extensionGroups??[]),r=new Map;for(const d of t)r.has(d.groupKey)||r.set(d.groupKey,[]),r.get(d.groupKey).push(d);const s=Array.from(r.keys()).sort((d,c)=>{const p=g=>g==="template"?1:g.startsWith("module:")?2:g.startsWith("plugin:")?3:4,f=p(d),y=p(c);return f!==y?f-y:d.localeCompare(c)}),a=[];if(e.baseLayouts.length>0){const d=e.baseLayouts.map(c=>({path:`__base__/${c.layoutName}`,layoutName:c.layoutName,label:c.label??c.layoutName,labelSource:c.label?"editor_label":"path",source:{kind:"core",identifier:null},kind:"base",children:[]}));for(const c of d)kg(c,n,o);a.push({path:"__group__/base",layoutName:null,label:"$t:layout_editor.chrome.route_tree.group.base",labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:d})}for(const d of s){const c=r.get(d),p=new Map;for(const y of c)p.set(y.node.path,y);const f=[];for(const y of c)if(y.parentKey&&p.has(y.parentKey)){const g=p.get(y.parentKey);g.node.children=g.node.children??[],g.node.children.push(y.node)}else f.push(y.node);for(const y of c)kg(y.node,n,o);a.push({path:`__group__/${d}`,layoutName:null,label:dD(d,e),labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:f})}if(e.modals.length>0){const d=e.modals.map(c=>({path:`__modal__/${c.hostLayout}/${c.modalId}`,layoutName:c.hostLayout,label:c.label??c.modalId,labelSource:c.label?"editor_label":"path",source:{kind:"core",identifier:null},kind:"modal",modalId:c.modalId,modalHostLayout:c.hostLayout,children:[]}));a.push({path:"__group__/modal",layoutName:null,label:"$t:layout_editor.chrome.route_tree.group.modal",labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:d})}const l=e.extensionGroups??[];if(l.length>0){const d=l.map(c=>{const p=c.sourceType==="plugin"?"🔌":"🧩",f=c.extensions.map(y=>({path:`__extension__/${y.id}`,layoutName:null,label:`${c.sourceLabel} · ${y.targetName}`,labelSource:"path",source:{kind:c.sourceType,identifier:c.sourceIdentifier},kind:"extension",extensionId:String(y.id),extensionType:y.extensionType,extensionPriority:y.priority,extensionTargetName:y.targetName,isModified:y.isModified,isInactive:!y.isActive,children:[]}));return{path:`__extgroup__/${c.sourceType}/${c.sourceIdentifier}`,layoutName:null,label:`${p} ${c.sourceLabel}`,labelSource:"path",source:{kind:c.sourceType,identifier:c.sourceIdentifier},kind:"route",children:f}});a.push({path:"__group__/extension",layoutName:null,label:"$t:layout_editor.chrome.route_tree.group.extension",labelSource:"editor_label",source:{kind:"core",identifier:null},kind:"route",children:d})}return a}function uD(e){const t=lD(e);return cD(e,t)}const On=bo("useEditorRoutes");function pD(e,t){if(typeof e=="string")return e.length>0?e:null;if(e&&typeof e=="object"){const n=e[t];if(typeof n=="string"&&n.length>0)return n;if(typeof e.en=="string"&&e.en.length>0)return e.en;for(const o of Object.values(e))if(typeof o=="string"&&o.length>0)return o}return null}function Sg(e,t){const n={};if(typeof window>"u")return n;const r=window.G7Config?.[e];if(!Array.isArray(r))return n;for(const s of r)s&&typeof s.identifier=="string"&&(n[s.identifier]=pD(s.display_name,t)??s.identifier);return n}function fD(e){const t=new vd,n=typeof window<"u"?window.G7Config:void 0,o={_global:{settings:n?.settings??{},plugins:n?.plugins??{},modules:n?.modules??{},appConfig:n?.appConfig??{}}};return e.map(r=>{const s={...r};if(typeof s.path=="string"&&s.path.includes("{{")){const a=s.path;let l=t.resolveBindings(s.path,o);l=l.replace(/\/\/+/g,"/")||"/",l.includes("{{")&&(On.warn("편집기 route path 표현식 평가 실패 — fallback 적용",{originalPath:a}),l=a.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/"),s.path=l}if(typeof s.redirect=="string"&&s.redirect.includes("{{")){const a=s.redirect;let l=t.resolveBindings(a,o);l=l.replace(/\/\/+/g,"/")||"/",l.includes("{{")&&(On.warn("편집기 route redirect 표현식 평가 실패 — fallback 적용",{originalRedirect:a}),l=a.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/"),s.redirect=l}return s})}function gD(e){const{dispatch:t}=Je(),{translationEngine:n,translationContext:o}=tt(),{templateIdentifier:r,cacheVersion:s}=e;u.useEffect(()=>{let a=!1;const l=s??(typeof window<"u"?window.G7Config?.cache_version:void 0)??"",d=l!==""?`?v=${encodeURIComponent(String(l))}`:"",c=en(`/api/admin/templates/${encodeURIComponent(r)}/editor/routes`,"json",null,d.replace(/^[?&]+/,"")),p=o?.locale??"ko",f=n&&r!==o?.templateId?n.loadTranslations(r,p).then(()=>{On.log("편집 대상 lang 로드 완료",{targetTemplate:r,locale:p})}).catch(h=>{On.warn("편집 대상 lang 로드 실패 — 라우트 라벨 fallback 사용",h)}):Promise.resolve(),y=(()=>{if(typeof fetch!="function")return Promise.reject(io(new Error("fetch unavailable"),"routes"));try{const h=fetch(c,{credentials:"same-origin",headers:je()});return!h||typeof h.then!="function"?Promise.reject(io(new Error("fetch returned non-Promise (test stub?)"),"routes")):h.then(async v=>{if(!v.ok){const b=await v.json().catch(()=>null);throw Gr(v.status,b,"routes")}return v.json()})}catch(h){return Promise.reject(h)}})(),g=`/api/admin/templates/${encodeURIComponent(r)}/layout-extensions${d}`,m=(()=>{if(typeof fetch!="function")return Promise.resolve(null);try{const h=fetch(g,{credentials:"same-origin",headers:je()});return!h||typeof h.then!="function"?Promise.resolve(null):h.then(async v=>v.ok?await v.json():null).catch(()=>null)}catch{return Promise.resolve(null)}})();return Promise.all([y,f,m]).then(([h,,v])=>{if(a)return;if(!h||!h.success||!Array.isArray(h.data?.routes)){On.warn("routes 응답 형식이 비정상 — empty tree 로 둠",h),t({type:"SET_ROUTES_ERROR",error:{kind:"unknown",status:200,message:"routes 응답 형식이 비정상입니다.",source:"routes"}});return}const b=fD(h.data.routes),x=Sg("activeModules",p),k=Sg("activePlugins",p),w=(h.data.base_layouts??[]).map(A=>({layoutName:A.layout_name,label:A.label??void 0})),_=(h.data.modals??[]).map(A=>({modalId:A.modal_id,hostLayout:A.host_layout,label:A.label??void 0})),C=(v?.success&&Array.isArray(v.data)?v.data:[]).map(A=>({sourceIdentifier:A.source_identifier,sourceType:A.source_type,sourceLabel:A.source_label,extensions:(A.extensions??[]).map(z=>({id:z.id,extensionType:z.extension_type,targetName:z.target_name,priority:z.priority,isActive:z.is_active,isModified:z.is_modified,hostLayouts:Array.isArray(z.host_layouts)?z.host_layouts:[],currentVersion:typeof z.current_version=="number"?z.current_version:void 0}))})),E=uD({routes:b,modals:_,baseLayouts:w,extensionGroups:C,moduleDisplayNames:x,pluginDisplayNames:k});t({type:"SET_ROUTE_TREE",tree:E});const S=h.data.layout_versions,T={};if(S&&typeof S=="object"&&!Array.isArray(S))for(const[A,z]of Object.entries(S))typeof z=="number"&&Number.isFinite(z)&&(T[A]=z);t({type:"SET_LAYOUT_VERSIONS",versions:T});const $={};for(const A of C)for(const z of A.extensions){const D=z.currentVersion;typeof D=="number"&&Number.isFinite(D)&&($[String(z.id)]=D)}t({type:"SET_EXTENSION_VERSIONS",versions:$}),On.log("routes 로드 완료",{count:b.length,groups:E.length})}).catch(h=>{if(a)return;On.error("routes 로드 실패",h);const v=hp(h)?h:io(h,"routes");t({type:"SET_ROUTES_ERROR",error:v})}),()=>{a=!0}},[r,s,t,n,o?.locale,o?.templateId])}function Cg(e,t,n,o=[]){const r=t?$g(o,t):null,s=r!==null?{path:r.path,layoutName:r.layoutName}:void 0;if(e.startsWith("__base__/")){const a=e.slice(9);if(a)return n({type:"ENTER_BASE_EDIT",layoutName:a,returnRoute:s}),!0}else if(e.startsWith("__modal__/")){const a=e.slice(10);return a&&!a.includes("/")&&t?(n({type:"ENTER_MODAL_EDIT",modalId:a,hostLayout:t,returnRoute:s}),!0):!1}else if(e.startsWith("__extension__/")){const a=e.slice(14);if(a&&!a.includes("/"))return n({type:"ENTER_EXTENSION_EDIT",extensionId:a,returnRoute:s}),!0}else if(e.startsWith("__iteration__/")){const a=e.slice(14);return a&&t?(n({type:"ENTER_ITERATION_ITEM_EDIT",sourcePath:a,hostLayout:t,returnRoute:s}),!0):!1}return!1}function $g(e,t){for(const n of e){if(n.kind==="route"&&n.layoutName===t)return n;if(n.children&&n.children.length>0){const o=$g(n.children,t);if(o)return o}}return null}function Xa(e,t){for(const n of e){if(n.kind==="route"&&n.path===t)return n;if(n.children&&n.children.length>0){const o=Xa(n.children,t);if(o)return o}}return null}function hD(e){const{state:t,dispatch:n}=Je(),o=u.useRef(!1),r=u.useRef(t.editMode);r.current=t.editMode,u.useEffect(()=>{if(o.current||t.routeTree.length===0||typeof window>"u")return;const a=ap(window.location.search);if(a){const c=sp(window.location.search),p=Cg(a,c,n,t.routeTree);if(o.current=!0,p)return}const l=ip(window.location.search);if(!l){o.current=!0;return}const d=Xa(t.routeTree,l);d&&n({type:"SELECT_ROUTE",route:{path:d.path,layoutName:d.layoutName}}),o.current=!0},[t.routeTree,n]),u.useEffect(()=>{if(typeof window>"u")return;const a=()=>{const l=ap(window.location.search);if(l){const p=sp(window.location.search);if(Cg(l,p,n,t.routeTree))return}if(r.current!=="route")switch(r.current){case"base":n({type:"EXIT_BASE_EDIT"});return;case"modal":n({type:"EXIT_MODAL_EDIT"});return;case"extension":n({type:"EXIT_EXTENSION_EDIT"});return;case"iteration_item":n({type:"EXIT_ITERATION_ITEM_EDIT"});return}const d=ip(window.location.search);if(!d){n({type:"SELECT_ROUTE",route:null});return}const c=Xa(t.routeTree,d);c&&n({type:"SELECT_ROUTE",route:{path:c.path,layoutName:c.layoutName}})};return window.addEventListener("popstate",a),()=>{window.removeEventListener("popstate",a)}},[t.routeTree,n]);const s=u.useRef("route");u.useEffect(()=>{if(typeof window>"u"||!window.history?.replaceState||t.routeTree.length===0)return;const a=Zs(e,t.selectedRoute?.path??null,t.selectedRoute?.layoutName??null),l=`${window.location.pathname}${window.location.search}`,d=s.current;if(s.current=t.editMode,l===a)return;d==="route"&&t.editMode!=="route"&&window.history.pushState?window.history.pushState(window.history.state,"",a):window.history.replaceState(window.history.state,"",a)},[t.selectedRoute,t.editMode,t.routeTree,e])}function yD(){u.useEffect(()=>{if(typeof document>"u")return;const e=document.documentElement;let t=e.classList.contains("dark");const n=()=>{e.classList.contains("dark")&&(t=!0,e.classList.remove("dark"))};n();let o=null;return typeof MutationObserver<"u"&&(o=new MutationObserver(n),o.observe(e,{attributes:!0,attributeFilter:["class"]})),()=>{o?.disconnect(),t&&e.classList.add("dark")}},[])}function bD(){u.useEffect(()=>{if(typeof document>"u"||!document.body)return;const e=document.body,t=()=>{e.style.overflow==="hidden"&&(e.style.overflow=""),e.style.overflowY==="hidden"&&(e.style.overflowY="")};t();let n=null;return typeof MutationObserver<"u"&&(n=new MutationObserver(t),n.observe(e,{attributes:!0,attributeFilter:["style"]})),()=>{n?.disconnect()}},[])}function mD(e){if(typeof e!="string")return null;const t="__extension__/";if(!e.startsWith(t))return null;const n=e.slice(t.length);return n===""||n.includes("/")?null:n}function vD(e){if(Array.isArray(e.components))return e.components;if(Array.isArray(e.injections)){const t=[];return e.injections.forEach((n,o)=>{if(n&&Array.isArray(n.components))for(const r of n.components)t.push({...r,__injectionIndex:o})}),t}return[]}function _D(e,t){if(Array.isArray(e.components)){const n=t.map(o=>Ja(o));return{...e,components:n}}if(Array.isArray(e.injections)){const n=e.injections.map(o=>({...o}));n.forEach(o=>{Array.isArray(o.components)&&(o.components=[])});for(const o of t){const r=o.__injectionIndex,s=typeof r=="number"&&r>=0&&rJa(n))),t}function Eg(e,t){const n=[],o=r=>{if(Array.isArray(r))for(const s of r){if(!s||typeof s!="object")continue;const a=s.__source;if(a?.kind==="extension"&&a.extensionId===t){n.push(s);continue}Array.isArray(s.children)&&o(s.children)}};return o(e),n}function Ig(e,t){const o=Eg(e,t)[0]?.__source;return o&&o.kind==="extension"&&o.extensionId===t?o:{kind:"extension",extensionId:t}}function Za(e,t){for(const n of e){const o=n?.__source;if(o?.kind==="extension"&&o.extensionId===t||Array.isArray(n.children)&&Za(n.children,t))return!0}return!1}function xD(){const{state:e}=Je(),t=e.templateIdentifier,n=e.editMode==="extension"?mD(e.selectedRoute?.path):null,o=e.editMode==="extension"&&typeof e.selectedRoute?.layoutName=="string"?e.selectedRoute.layoutName:null,[r,s]=u.useState(null),[a,l]=u.useState(!1),[d,c]=u.useState(null),[p,f]=u.useState(!1),[y,g]=u.useState(0),[m,h]=u.useState(null),v=u.useRef({}),b=u.useRef({kind:"extension",extensionId:0}),x=u.useRef(null);u.useEffect(()=>{x.current=r},[r]),u.useEffect(()=>{h(null)},[n]);const k=u.useCallback(async A=>{const z=window.G7Config?.cache_version??0,D=en(`/api/layouts/${encodeURIComponent(t)}/${A}`,"json",`${z}.${Sp()}`,"with_source_meta=1"),O=ar(),M={Accept:"application/json"};O&&(M.Authorization=`Bearer ${O}`);const B=await fetch(D,{headers:M,credentials:"same-origin"});if(!B.ok)return null;const N=await B.json().catch(()=>null);return(N&&(N.data||N))??{}},[t]),w=u.useCallback(async()=>{if(!n){s(null),c(null),f(!1);return}l(!0),c(null);try{const A=window.G7Config?.cache_version??0,z=`/api/admin/templates/${encodeURIComponent(t)}/layout-extensions/${encodeURIComponent(n)}?v=${A}`,D=await fetch(z,{headers:je(),credentials:"same-origin"}),O=await D.json().catch(()=>null);if(!D.ok){c(Gr(D.status,O,"layout")),s(null),f(!1);return}const M=(O&&(O.data||O))??{};let B={};const N=M.content;if(typeof N=="string")try{B=JSON.parse(N)}catch{B={}}else N&&typeof N=="object"&&(B=N);const H=M.extension_type==="overlay"?"overlay":"extension_point",L=typeof M.lock_version=="number"?M.lock_version:0,I=Array.isArray(M?.host_layouts)?M.host_layouts.filter(re=>typeof re=="string"):[],P=o??(I.length===1?I[0]:m&&I.includes(m)?m:null),F=Number(n);v.current=B;let V=vD(B),Y={},Z="pending";const se={kind:"extension",extensionId:F};if(b.current=se,P){const re=await k(P);if(re){Y=re;const U=Array.isArray(re.components)?re.components:[],ee=Ig(U,F);if(b.current=ee,Za(U,F))V=U,Z="ok";else{const K=(Array.isArray(re.modals)?re.modals:[]).filter(ne=>ne&&typeof ne=="object"&&Za([ne],F));if(K.length>0){const ne=K.map(me=>({...me,props:{...me.props??{},isOpen:!0}}));V=[...U,...ne],b.current=Ig(K,F),Z="ok"}else V=U,Z="no-injection"}}}s({extensionId:F,content:B,extensionType:H,components:V,lockVersion:L,hostLayouts:I,hostLayoutName:P,hostRaw:Y,editability:Z}),f(!1),st({op:"load",layoutName:`extension:${n}`,editMode:"extension",statusCode:D.status,timestamp:Date.now()})}catch(A){c(io(A,"layout")),s(null),f(!1)}finally{l(!1)}},[t,n,m,o,k]);u.useEffect(()=>{w()},[w]);const _=u.useCallback(A=>{h(A)},[]),C=u.useCallback(A=>{s(z=>z&&{...z,components:A}),f(!0),st({op:"patch",layoutName:`extension:${x.current?.extensionId??""}`,editMode:"extension",isDirty:!0,timestamp:Date.now()})},[]),E=u.useCallback(A=>{s(z=>z&&{...z,components:A(z.components)}),f(!0)},[]),S=u.useCallback(async()=>{const A=x.current;if(!A)return{kind:"guard_no_document"};const z=`/api/admin/templates/${encodeURIComponent(t)}/layout-extensions/${A.extensionId}`,D=Eg(A.components,A.extensionId),O=D.length>0?D:A.components,M=_D(v.current,O);st({op:"save",layoutName:`extension:${A.extensionId}`,editMode:"extension",saveTarget:"layout_extension",endpoint:z,isDirty:p,timestamp:Date.now()});let B;try{B=await fetch(z,{method:"PUT",headers:je({"Content-Type":"application/json"}),credentials:"same-origin",body:JSON.stringify({content:M,expected_lock_version:A.lockVersion})})}catch(H){return{kind:"network_error",message:H instanceof Error?H.message:"network error"}}const N=await B.json().catch(()=>null);if(st({op:"save_response",layoutName:`extension:${A.extensionId}`,editMode:"extension",endpoint:z,statusCode:B.status,conflict:B.status===409?{currentVersion:N?.errors?.current_version??N?.current_version,yourVersion:N?.errors?.your_version??N?.your_version}:void 0,timestamp:Date.now()}),B.ok){const H=N?.data??{},L=typeof H.lock_version=="number"?H.lock_version:A.lockVersion+1;s(P=>P&&{...P,lockVersion:L}),f(!1),g(P=>P+1);const I=typeof H.current_version=="number"?H.current_version:void 0;return{kind:"success",newLockVersion:L,newContentVersion:I,savedExtensionId:String(A.extensionId)}}return B.status===409?{kind:"concurrent_modification",currentVersion:N?.current_version??-1,yourVersion:N?.your_version??A.lockVersion}:B.status===422?{kind:"validation_failed",status:422,errors:N?.errors??null}:{kind:"network_error",message:N?.message??`HTTP ${B.status}`}},[t,p]),T=u.useCallback(async()=>{na(),await w()},[w]),$=!!r&&r.hostLayouts.length>1&&r.hostLayoutName===null;return{document:r,isLoading:a,error:d,isDirty:p,saveSuccessCounter:y,setLayoutComponents:C,patchLayout:E,save:S,reload:T,needsHostPicker:$,selectHost:_}}const Ag=new Set;function wD(e,t,n){const r=e&&Object.keys(e).length>0?e:t,s=Array.isArray(r.data_sources)?r.data_sources:[],a=Array.isArray(t.data_sources)?t.data_sources:[],l=new Set,d=[];for(const c of[...s,...a]){const p=c&&typeof c=="object"?c.id:void 0,f=typeof p=="string"?p:`__anon_${d.length}`;l.has(f)||(l.add(f),d.push(c))}return{...r,components:n,...d.length>0?{data_sources:d}:{},lock_version:void 0}}function kD(e){return{document:e.document?{layoutName:`extension:${e.document.extensionId}`,raw:{...wD(e.document.hostRaw,e.document.content,e.document.components),__editability:e.document.editability,__extensionId:e.document.extensionId},lockVersion:e.document.lockVersion}:null,isLoading:e.isLoading,error:e.error,isDirty:e.isDirty,saveSuccessCounter:e.saveSuccessCounter,reload:e.reload,patchLayout:e.patchLayout,setLayoutComponents:e.setLayoutComponents,patchDocumentRaw:()=>{},dirtyKeys:Ag,dirtyLayoutNames:Ag,invalidateCurrentCache:()=>{},reloadCounter:0,save:()=>e.save(),markDirty:()=>{}}}function SD({hostLayouts:e,extensionLabel:t,onSelect:n}){const{t:o}=tt();return i.jsx("div",{className:"g7le-host-picker__backdrop","data-testid":"g7le-host-picker",role:"dialog","aria-modal":"true","aria-label":o("layout_editor.host_picker.title"),style:{position:"fixed",inset:0,zIndex:9500,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(15, 23, 42, 0.55)"},children:i.jsxs("div",{className:"g7le-host-picker__panel",style:{width:"min(520px, 92vw)",maxHeight:"80vh",overflow:"auto",background:"#ffffff",color:"#0f172a",borderRadius:12,boxShadow:"0 20px 48px rgba(15, 23, 42, 0.28)",padding:"20px 22px"},children:[i.jsx("h2",{className:"g7le-host-picker__title",style:{margin:"0 0 6px",fontSize:16,fontWeight:700},children:o("layout_editor.host_picker.title")}),i.jsx("p",{className:"g7le-host-picker__desc",style:{margin:"0 0 16px",fontSize:13,color:"#475569",lineHeight:1.6},children:t?o("layout_editor.host_picker.description_with_label",{label:t}):o("layout_editor.host_picker.description")}),i.jsx("ul",{className:"g7le-host-picker__list",style:{listStyle:"none",margin:0,padding:0,display:"grid",gap:8},children:e.map(r=>i.jsx("li",{children:i.jsxs("button",{type:"button",className:"g7le-host-picker__item","data-testid":"g7le-host-picker-item","data-host":r,onClick:()=>n(r),style:{width:"100%",textAlign:"left",padding:"12px 14px",border:"1px solid #e2e8f0",borderRadius:8,background:"#f8fafc",cursor:"pointer",fontSize:13,fontWeight:600,color:"#0f172a",display:"flex",alignItems:"center",gap:8},children:[i.jsx("span",{"aria-hidden":!0,style:{fontSize:14},children:"🖼"}),i.jsx("span",{style:{flex:1,minWidth:0,overflow:"hidden",textOverflow:"ellipsis"},children:r}),i.jsx("span",{"aria-hidden":!0,style:{color:"#94a3b8"},children:"→"})]})},r))})]})})}function CD(e,t){const[n,o]=u.useState(!1),[r,s]=u.useState(null),a=u.useCallback(async l=>{if(!t||!l)return{kind:"no_document"};o(!0),s(null);try{const d=vo(l),c=`/api/admin/templates/${encodeURIComponent(e)}/layouts/${t}/preview`,p=await fetch(c,{method:"POST",credentials:"same-origin",headers:je({"Content-Type":"application/json"}),body:JSON.stringify({content:JSON.stringify(d)})}),f=await p.json().catch(()=>null);if(!p.ok){const h=f?.message??`HTTP ${p.status}`;return s(h),{kind:"network_error",message:h}}const y=f?.data,g=typeof y?.token=="string"?y.token:"",m=typeof y?.preview_url=="string"&&y.preview_url?y.preview_url:g?`/preview/${g}`:"";return m?(window.G7Core?.dispatch?.({handler:"openWindow",params:{path:m}}),{kind:"success",previewUrl:m,token:g}):(s("invalid preview response"),{kind:"network_error",message:"invalid preview response"})}catch(d){const c=d instanceof Error?d.message:"network error";return s(c),{kind:"network_error",message:c}}finally{o(!1)}},[e,t]);return{isCreating:n,error:r,createPreview:a}}const ce="layout_editor.action_recipe",bn={setState:{label:`$t:${ce}.set_state.label`,params:[{key:"target",label:`$t:${ce}.set_state.param_target`,widget:"select",options:[{value:"local"},{value:"global"}]},{key:"state",label:`$t:${ce}.set_state.param_state`,widget:"state-key-value"},{key:"merge",label:`$t:${ce}.set_state.param_merge`,widget:"toggle"}],build:{handler:"setState",params:{target:"{{target}}",merge:"{{merge}}","...":"{{state}}"}}},loadFromLocalStorage:{label:`$t:${ce}.load_local.label`,params:[{key:"key",label:`$t:${ce}.load_local.param_key`,widget:"text",required:!0},{key:"stateKey",label:`$t:${ce}.load_local.param_state_key`,widget:"state-key-picker"},{key:"defaultValue",label:`$t:${ce}.load_local.param_default`,widget:"text"}],build:{handler:"loadFromLocalStorage",params:{key:"{{key}}",stateKey:"{{stateKey}}",defaultValue:"{{defaultValue}}"}}},saveToLocalStorage:{label:`$t:${ce}.save_local.label`,params:[{key:"key",label:`$t:${ce}.save_local.param_key`,widget:"text",required:!0},{key:"value",label:`$t:${ce}.save_local.param_value`,widget:"data-chip"}],build:{handler:"saveToLocalStorage",params:{key:"{{key}}",value:"{{value}}"}}},navigate:{label:`$t:${ce}.navigate.label`,params:[{key:"path",label:`$t:${ce}.navigate.param_path`,widget:"page-picker",required:!0},{key:"query",label:`$t:${ce}.navigate.param_query`,widget:"key-value"},{key:"mergeQuery",label:`$t:${ce}.navigate.param_merge_query`,widget:"toggle"},{key:"scroll",label:`$t:${ce}.navigate.param_scroll`,widget:"select",options:[{value:"top"},{value:"preserve"},{value:"none"}]},{key:"replace",label:`$t:${ce}.navigate.param_replace`,widget:"toggle"},{key:"transition_overlay_target",label:`$t:${ce}.navigate.param_overlay_target`,widget:"component-target-picker",dependsOn:{param:"replace",equals:!0}}],build:{handler:"navigate",params:{path:"{{path}}",query:"{{query}}",mergeQuery:"{{mergeQuery}}",scroll:"{{scroll}}",replace:"{{replace}}",transition_overlay_target:"{{transition_overlay_target}}"}}},openWindow:{label:`$t:${ce}.open_window.label`,params:[{key:"target",label:`$t:${ce}.open_window.param_target`,widget:"page-picker",required:!0},{key:"windowTarget",label:`$t:${ce}.open_window.param_window_target`,widget:"select",options:[{value:"_blank"},{value:"_self"}]}],build:{handler:"openWindow",target:"{{target}}",params:{windowTarget:"{{windowTarget}}"}}},navigateBack:{label:`$t:${ce}.navigate_back.label`,params:[],build:{handler:"navigateBack"}},navigateForward:{label:`$t:${ce}.navigate_forward.label`,params:[],build:{handler:"navigateForward"}},replaceUrl:{label:`$t:${ce}.replace_url.label`,params:[{key:"path",label:`$t:${ce}.replace_url.param_path`,widget:"page-picker"},{key:"query",label:`$t:${ce}.replace_url.param_query`,widget:"key-value"}],build:{handler:"replaceUrl",params:{path:"{{path}}",query:"{{query}}"}}},toast:{label:`$t:${ce}.toast.label`,params:[{key:"message",label:`$t:${ce}.toast.param_message`,widget:"i18n-text",required:!0},{key:"type",label:`$t:${ce}.toast.param_type`,widget:"select",options:[{value:"info"},{value:"success"},{value:"warning"},{value:"error"}]},{key:"duration",label:`$t:${ce}.toast.param_duration`,widget:"number"},{key:"icon",label:`$t:${ce}.toast.param_icon`,widget:"text"}],build:{handler:"toast",params:{message:"{{message}}",type:"{{type}}",duration:"{{duration}}",icon:"{{icon}}"}}},openModal:{label:`$t:${ce}.open_modal.label`,params:[{key:"target",label:`$t:${ce}.open_modal.param_target`,widget:"modal-picker",required:!0}],build:{handler:"openModal",target:"{{target}}"}},closeModal:{label:`$t:${ce}.close_modal.label`,params:[],build:{handler:"closeModal"}},showAlert:{label:`$t:${ce}.show_alert.label`,params:[{key:"target",label:`$t:${ce}.show_alert.param_message`,widget:"i18n-text",required:!0}],build:{handler:"showAlert",target:"{{target}}"}},setError:{label:`$t:${ce}.set_error.label`,params:[{key:"target",label:`$t:${ce}.set_error.param_message`,widget:"i18n-text"},{key:"stateTarget",label:`$t:${ce}.set_error.param_state_target`,widget:"select",options:[{value:"local"},{value:"global"}]}],build:{handler:"setError",target:"{{target}}",params:{stateTarget:"{{stateTarget}}"}}},refetchDataSource:{label:`$t:${ce}.refetch.label`,params:[{key:"dataSourceId",label:`$t:${ce}.refetch.param_data_source`,widget:"datasource-picker",required:!0},{key:"sync",label:`$t:${ce}.refetch.param_sync`,widget:"toggle"}],build:{handler:"refetchDataSource",params:{dataSourceId:"{{dataSourceId}}",sync:"{{sync}}"}}},appendDataSource:{label:`$t:${ce}.append_data.label`,params:[{key:"dataSourceId",label:`$t:${ce}.append_data.param_data_source`,widget:"datasource-picker",required:!0},{key:"dataPath",label:`$t:${ce}.append_data.param_data_path`,widget:"text"},{key:"newData",label:`$t:${ce}.append_data.param_new_data`,widget:"data-chip"}],build:{handler:"appendDataSource",params:{dataSourceId:"{{dataSourceId}}",dataPath:"{{dataPath}}",newData:"{{newData}}"}}},updateDataSource:{label:`$t:${ce}.update_data.label`,params:[{key:"dataSourceId",label:`$t:${ce}.update_data.param_data_source`,widget:"datasource-picker",required:!0},{key:"data",label:`$t:${ce}.update_data.param_data`,widget:"data-chip"},{key:"merge",label:`$t:${ce}.update_data.param_merge`,widget:"toggle"}],build:{handler:"updateDataSource",params:{dataSourceId:"{{dataSourceId}}",data:"{{data}}",merge:"{{merge}}"}}},scrollIntoView:{label:`$t:${ce}.scroll.label`,params:[{key:"selector",label:`$t:${ce}.scroll.param_selector`,widget:"text",required:!0},{key:"behavior",label:`$t:${ce}.scroll.param_behavior`,widget:"select",options:[{value:"smooth"},{value:"auto"}]},{key:"block",label:`$t:${ce}.scroll.param_block`,widget:"select",options:[{value:"start"},{value:"center"},{value:"end"},{value:"nearest"}]}],build:{handler:"scrollIntoView",params:{selector:"{{selector}}",behavior:"{{behavior}}",block:"{{block}}"}}},login:{label:`$t:${ce}.login.label`,params:[{key:"body",label:`$t:${ce}.login.param_body`,widget:"key-value"}],build:{handler:"login",params:{body:"{{body}}"}}},logout:{label:`$t:${ce}.logout.label`,params:[{key:"target",label:`$t:${ce}.logout.param_target`,widget:"text"}],build:{handler:"logout",target:"{{target}}"}},setLocale:{label:`$t:${ce}.set_locale.label`,params:[{key:"target",label:`$t:${ce}.set_locale.param_target`,widget:"locale-picker",required:!0}],build:{handler:"setLocale",target:"{{target}}"}},emitEvent:{label:`$t:${ce}.emit_event.label`,params:[{key:"event",label:`$t:${ce}.emit_event.param_event`,widget:"text",required:!0},{key:"data",label:`$t:${ce}.emit_event.param_data`,widget:"data-chip"}],build:{handler:"emitEvent",params:{event:"{{event}}",data:"{{data}}"}}},apiCall:{label:`$t:${ce}.api_call.label`,params:[{key:"target",label:`$t:${ce}.api_call.param_target`,widget:"page-picker",required:!0},{key:"method",label:`$t:${ce}.api_call.param_method`,widget:"select",options:[{value:"GET"},{value:"POST"},{value:"PUT"},{value:"PATCH"},{value:"DELETE"}]},{key:"body",label:`$t:${ce}.api_call.param_body`,widget:"key-value"},{key:"query",label:`$t:${ce}.api_call.param_query`,widget:"key-value"},{key:"identity_target_email",label:`$t:${ce}.api_call.param_identity_target_email`,widget:"data-chip"},{key:"identity_target_phone",label:`$t:${ce}.api_call.param_identity_target_phone`,widget:"data-chip"},{key:"onSuccess",label:`$t:${ce}.api_call.param_on_success`,widget:"action-list"},{key:"onError",label:`$t:${ce}.api_call.param_on_error`,widget:"action-list"}],build:{handler:"apiCall",target:"{{target}}",identity_target:{email:"{{identity_target_email}}",phone:"{{identity_target_phone}}"},onSuccess:"{{onSuccess}}",onError:"{{onError}}",params:{method:"{{method}}",body:"{{body}}",query:"{{query}}"}}},conditions:{label:`$t:${ce}.conditions.label`,params:[{key:"branches",label:`$t:${ce}.conditions.param_branches`,widget:"branch-list"}],build:{handler:"conditions",conditions:"{{branches}}"}},sequence:{label:`$t:${ce}.sequence.label`,params:[{key:"actions",label:`$t:${ce}.sequence.param_actions`,widget:"action-list"}],build:{handler:"sequence",params:{actions:"{{actions}}"}}},parallel:{label:`$t:${ce}.parallel.label`,params:[{key:"actions",label:`$t:${ce}.parallel.param_actions`,widget:"action-list"}],build:{handler:"parallel",params:{actions:"{{actions}}"}}},switch:{label:`$t:${ce}.switch.label`,params:[{key:"value",label:`$t:${ce}.switch.param_value`,widget:"data-chip"},{key:"cases",label:`$t:${ce}.switch.param_cases`,widget:"action-list",advanced:!0}],build:{handler:"switch",params:{value:"{{value}}",cases:"{{cases}}"}}},suppress:{label:`$t:${ce}.suppress.label`,params:[],build:{handler:"suppress"}}};function $D(){return{actionRecipes:bn,initActionRecipes:bn,errorRecipes:{navigate:bn.navigate,openModal:bn.openModal,toast:bn.toast,setState:bn.setState,sequence:bn.sequence,parallel:bn.parallel,showErrorPage:{label:`$t:${ce}.show_error_page.label`,params:[{key:"target",label:`$t:${ce}.show_error_page.param_target`,widget:"select",options:[{value:"content"},{value:"full"}]}],build:{handler:"showErrorPage",params:{target:"{{target}}"}}}}}}function Qa(e,t){return typeof e.label=="string"?e.label.startsWith("$t:")?t(e.label.slice(3)):e.label:String(e.value)}function vi(e){return Array.isArray(e.options)?e.options:[]}function ED({control:e,value:t,onChange:n,t:o}){const r=vi(e);return i.jsx("div",{className:"g7le-widget g7le-widget--segmented","data-testid":"g7le-widget-segmented",style:WD,children:r.map(s=>{const a=s.value===t;return i.jsx("button",{type:"button","data-testid":`g7le-segment-${String(s.value)}`,"data-active":a?"true":"false",onClick:()=>n(a?void 0:s.value),style:{...GD,background:a?"#2563eb":"#fff",color:a?"#fff":"#0f172a",borderColor:a?"#2563eb":"#cbd5e1"},children:Qa(s,o)},String(s.value))})})}function ID({control:e,value:t,onChange:n,t:o}){const r=Array.isArray(e.scale)?e.scale:[],s=r.findIndex(l=>l===t),a=t!=null;return i.jsxs("div",{className:"g7le-widget g7le-widget--slider","data-testid":"g7le-widget-slider",style:Dg,children:[i.jsxs("label",{style:Ra,children:[i.jsx("input",{type:"checkbox","data-testid":"g7le-slider-enabled",checked:a,onChange:l=>{l.target.checked?n(r.length>0?r[Math.max(0,s===-1?0:s)]:void 0):n(void 0)}}),i.jsx("span",{style:{fontSize:12,color:"#64748b"},children:o("layout_editor.control.use")})]}),i.jsx("input",{type:"range","data-testid":"g7le-slider-range",min:0,max:Math.max(0,r.length-1),step:1,disabled:!a||r.length===0,value:s===-1?0:s,onChange:l=>{const d=Number(l.target.value);n(r[d])},style:{flex:1}}),i.jsx("span",{"data-testid":"g7le-slider-value",style:{fontSize:12,color:"#0f172a",minWidth:48,textAlign:"right"},children:a?String(t):o("layout_editor.control.default")})]})}function AD({control:e,value:t,onChange:n,t:o}){const r=vi(e);return i.jsxs("select",{className:"g7le-widget g7le-widget--select","data-testid":"g7le-widget-select",value:t==null?"":String(t),onChange:s=>{const a=s.target.value;if(a===""){n(void 0);return}const l=r.find(d=>String(d.value)===a);n(l?l.value:a)},style:YD,children:[i.jsx("option",{value:"",children:o("layout_editor.control.default")}),r.map(s=>i.jsx("option",{value:String(s.value),children:Qa(s,o)},String(s.value)))]})}function TD({control:e,value:t,onChange:n}){const o=vi(e),r=o[1]?.value??!0,s=o[0]?.value??void 0,a=t===r;return i.jsx("button",{type:"button",className:"g7le-widget g7le-widget--toggle","data-testid":"g7le-widget-toggle",role:"switch","aria-checked":a,onClick:()=>n(a?s:r),style:{...XD,background:a?"#2563eb":"#cbd5e1"},children:i.jsx("span",{style:{...JD,transform:a?"translateX(18px)":"translateX(0)"}})})}function DD({control:e,value:t,onChange:n,t:o,freeValueDisabled:r}){const s=vi(e),a=t==null?"":String(t),[l,d]=u.useState(a);u.useEffect(()=>{d(a)},[a]);const c=p=>{const f=p.trim();if(f===""){n(void 0);return}n(f)};return i.jsxs("div",{className:"g7le-widget g7le-widget--dimension","data-testid":"g7le-widget-dimension",style:jD,children:[r?i.jsx("div",{"data-testid":"g7le-dimension-free-disabled",style:UD,children:o("layout_editor.property_modal.dark_preset_only")}):i.jsxs("div",{style:HD,children:[i.jsx("input",{type:"text","data-testid":"g7le-dimension-input",value:l,placeholder:o("layout_editor.control.dimension.placeholder"),onChange:p=>d(p.target.value),onBlur:p=>c(p.target.value),onKeyDown:p=>{p.key==="Enter"&&(p.preventDefault(),c(p.target.value))},style:FD}),i.jsx("button",{type:"button","data-testid":"g7le-dimension-clear",title:o("layout_editor.control.default"),onClick:()=>{d(""),n(void 0)},style:KD,children:o("layout_editor.control.default")})]}),s.length>0&&i.jsx("div",{style:VD,"data-testid":"g7le-dimension-chips",children:s.map(p=>{const f=String(p.value),y=f===a;return i.jsx("button",{type:"button","data-testid":`g7le-dimension-chip-${f}`,"data-active":y?"true":"false",onClick:()=>{d(f),n(f)},style:{...qD,background:y?"#2563eb":"#fff",color:y?"#fff":"#0f172a",borderColor:y?"#2563eb":"#cbd5e1"},children:Qa(p,o)},f)})})]})}function ND(e){return[{key:"t",infix:`${e}t-`,labelKey:"layout_editor.control.spacing.top"},{key:"r",infix:`${e}r-`,labelKey:"layout_editor.control.spacing.right"},{key:"b",infix:`${e}b-`,labelKey:"layout_editor.control.spacing.bottom"},{key:"l",infix:`${e}l-`,labelKey:"layout_editor.control.spacing.left"}]}function zD(e,t,n,o){const r={all:-1,sides:{}};if(typeof e!="string"||e.trim()==="")return r;const s=e.split(/\s+/).filter(a=>a.length>0);for(const a of s){const l=n.find(d=>a.startsWith(d.infix));if(l){r.sides[l.key]=o.indexOf(a.slice(l.infix.length));continue}if(a.startsWith(`${t}x-`)){const d=o.indexOf(a.slice(`${t}x-`.length));r.sides.l=d,r.sides.r=d;continue}if(a.startsWith(`${t}y-`)){const d=o.indexOf(a.slice(`${t}y-`.length));r.sides.t=d,r.sides.b=d;continue}a.startsWith(`${t}-`)&&(r.all=o.indexOf(a.slice(`${t}-`.length)))}return r}function MD({control:e,value:t,onChange:n,t:o}){const r=typeof e.spacingPrefix=="string"?e.spacingPrefix:"p",s=(Array.isArray(e.scale)?e.scale:[]).map(b=>String(b)),a=ND(r),l=zD(t,r,a,s),d=Object.values(l.sides).some(b=>b>=0),c=l.all>=0||d,[p,f]=u.useState(d);u.useEffect(()=>{d&&f(!0)},[d]);const y=Math.min(4,Math.max(0,s.length-1)),g=b=>{const x=[];for(const k of a){const w=b[k.key];w!==void 0&&w>=0&&x.push(`${k.infix}${s[w]}`)}n(x.length>0?x.join(" "):void 0)},m=b=>{n(b>=0?`${r}-${s[Math.max(0,Math.min(b,s.length-1))]}`:void 0)},h=()=>({...l.sides}),v=(b,x,k,w,_)=>{const C=k>=0;return i.jsxs("div",{style:BD,"data-testid":b,children:[i.jsxs("label",{style:{...Ra,minWidth:64},children:[i.jsx("input",{type:"checkbox","data-testid":`${b}-enabled`,checked:C,onChange:E=>_(E.target.checked)}),i.jsx("span",{style:{fontSize:12,color:"#0f172a"},children:o(x)})]}),i.jsx("input",{type:"range","data-testid":`${b}-range`,min:0,max:Math.max(0,s.length-1),step:1,disabled:!C||s.length===0,value:k<0?0:k,onChange:E=>w(Number(E.target.value)),style:{flex:1}}),i.jsx("span",{"data-testid":`${b}-value`,style:{fontSize:12,color:C?"#0f172a":"#94a3b8",minWidth:28,textAlign:"right"},children:C?s[k]:"–"})]},b)};return i.jsxs("div",{className:"g7le-widget g7le-widget--spacing","data-testid":"g7le-widget-spacing",style:LD,children:[i.jsxs("div",{style:PD,children:[i.jsxs("div",{style:OD,"data-testid":"g7le-spacing-mode",children:[i.jsx("button",{type:"button","data-testid":"g7le-spacing-mode-all","data-active":p?"false":"true",onClick:()=>{f(!1),d&&n(void 0)},style:{...Tg,background:p?"#fff":"#2563eb",color:p?"#0f172a":"#fff",borderColor:p?"#cbd5e1":"#2563eb"},children:o("layout_editor.control.spacing.mode_all")}),i.jsx("button",{type:"button","data-testid":"g7le-spacing-mode-sides","data-active":p?"true":"false",onClick:()=>{if(f(!0),l.all>=0){const b={};for(const x of a)b[x.key]=l.all;g(b)}},style:{...Tg,background:p?"#2563eb":"#fff",color:p?"#fff":"#0f172a",borderColor:p?"#2563eb":"#cbd5e1"},children:o("layout_editor.control.spacing.mode_sides")})]}),i.jsx("span",{"data-testid":"g7le-spacing-value",style:{fontSize:11,color:"#64748b",minWidth:80,textAlign:"right"},children:c?String(t):o("layout_editor.control.default")})]}),p?i.jsx("div",{"data-testid":"g7le-spacing-sides",style:{display:"flex",flexDirection:"column",gap:4},children:a.map(b=>v(`g7le-spacing-side-${b.key}`,b.labelKey,l.sides[b.key]??-1,x=>{const k=h();k[b.key]=x,g(k)},x=>{const k=h();x?k[b.key]=l.sides[b.key]>=0?l.sides[b.key]:y:delete k[b.key],g(k)}))}):i.jsxs("div",{style:Dg,children:[i.jsxs("label",{style:{...Ra,minWidth:64},children:[i.jsx("input",{type:"checkbox","data-testid":"g7le-spacing-all-enabled",checked:l.all>=0,onChange:b=>m(b.target.checked?y:-1)}),i.jsx("span",{style:{fontSize:12,color:"#64748b"},children:o("layout_editor.control.spacing.all")})]}),i.jsx("input",{type:"range","data-testid":"g7le-spacing-all-range",min:0,max:Math.max(0,s.length-1),step:1,disabled:l.all<0||s.length===0,value:l.all<0?0:l.all,onChange:b=>m(Number(b.target.value)),style:{flex:1}}),i.jsx("span",{"data-testid":"g7le-spacing-all-value",style:{fontSize:12,color:l.all>=0?"#0f172a":"#94a3b8",minWidth:28,textAlign:"right"},children:l.all>=0?s[l.all]:"–"})]})]})}const LD={display:"flex",flexDirection:"column",gap:6,width:"100%"},PD={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},OD={display:"inline-flex",gap:0,border:"1px solid #cbd5e1",borderRadius:6,overflow:"hidden"},Tg={padding:"3px 10px",fontSize:11,border:"none",borderRight:"1px solid #e2e8f0",cursor:"pointer"},BD={display:"flex",alignItems:"center",gap:8,width:"100%"},WD={display:"inline-flex",gap:0,border:"1px solid #cbd5e1",borderRadius:6,overflow:"hidden"},jD={display:"flex",flexDirection:"column",gap:6,width:"100%"},HD={display:"flex",gap:6,alignItems:"center"},FD={flex:1,padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,minWidth:80},KD={padding:"4px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#64748b",cursor:"pointer",whiteSpace:"nowrap"},VD={display:"flex",flexWrap:"wrap",gap:4},UD={fontSize:11,color:"#94a3b8",fontStyle:"italic",padding:"2px 0"},qD={padding:"3px 9px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:999,background:"#fff",cursor:"pointer"},GD={padding:"4px 10px",fontSize:12,border:"none",borderRight:"1px solid #e2e8f0",cursor:"pointer"},Dg={display:"flex",alignItems:"center",gap:8,width:"100%"},Ra={display:"inline-flex",alignItems:"center",gap:4},YD={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",minWidth:120},XD={position:"relative",width:38,height:20,borderRadius:10,border:"none",cursor:"pointer",padding:2,display:"inline-flex",alignItems:"center",transition:"background 120ms ease"},JD={display:"block",width:16,height:16,borderRadius:8,background:"#fff",transition:"transform 120ms ease"},ZD=["#0f172a","#334155","#64748b","#94a3b8","#e2e8f0","#ffffff","#dc2626","#ea580c","#d97706","#16a34a","#0891b2","#2563eb","#7c3aed","#db2777"],Ng=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function QD(e){return Array.isArray(e.options)?e.options.filter(t=>typeof t.value=="string").map(t=>({value:t.value,swatch:typeof t.swatch=="string"?t.swatch:void 0,label:typeof t.label=="string"?t.label:void 0})):[]}function RD({control:e,value:t,onChange:n,t:o,freeValueDisabled:r}){const s=QD(e),a=s.length>0,l=typeof t=="string"&&s.some(g=>g.value===t)?t:"",d=typeof t=="string"&&Ng.test(t)?t:"",[c,p]=u.useState(d);u.useEffect(()=>{p(d)},[d]);const f=g=>{const m=g.trim();if(m===""){n(void 0);return}const h=m.startsWith("#")?m:`#${m}`;Ng.test(h)&&n(h)},y=ZD;return i.jsxs("div",{className:"g7le-widget g7le-widget--color","data-testid":"g7le-widget-color",style:eN,children:[r?i.jsx("div",{"data-testid":"g7le-color-free-disabled",style:sN,children:o("layout_editor.property_modal.dark_preset_only")}):i.jsxs("div",{style:tN,children:[i.jsxs("label",{style:nN,children:[i.jsx("span",{"data-testid":"g7le-color-swatch",style:{...oN,background:d||"transparent",backgroundImage:d?void 0:"linear-gradient(45deg,#e2e8f0 25%,transparent 25%,transparent 75%,#e2e8f0 75%),linear-gradient(45deg,#e2e8f0 25%,#fff 25%,#fff 75%,#e2e8f0 75%)",backgroundSize:"8px 8px",backgroundPosition:"0 0, 4px 4px"}}),i.jsx("input",{type:"color","data-testid":"g7le-color-native",value:d||"#000000",onChange:g=>n(g.target.value),style:{width:0,height:0,opacity:0,position:"absolute"}})]}),i.jsx("input",{type:"text","data-testid":"g7le-color-hex",value:c,placeholder:o("layout_editor.control.color_hex_placeholder"),onChange:g=>p(g.target.value),onBlur:g=>f(g.target.value),onKeyDown:g=>{g.key==="Enter"&&f(g.target.value)},style:rN}),i.jsx("button",{type:"button","data-testid":"g7le-color-clear",onClick:()=>n(void 0),style:iN,children:o("layout_editor.control.default")})]}),a?i.jsx("div",{style:zg,"data-testid":"g7le-color-token-presets",children:s.map(g=>{const m=l===g.value,h=g.label?g.label.startsWith("$t:")?o(g.label.slice(3)):g.label:g.value;return i.jsx("button",{type:"button","aria-label":h,title:h,"data-testid":`g7le-color-token-${g.value}`,"data-active":m?"true":"false",onClick:()=>n(m?void 0:g.value),style:{...Mg,background:g.swatch||"#e2e8f0",outline:m?"2px solid #2563eb":"none"}},g.value)})}):!r&&i.jsx("div",{style:zg,"data-testid":"g7le-color-presets",children:y.map(g=>i.jsx("button",{type:"button","aria-label":g,"data-testid":`g7le-color-preset-${g}`,onClick:()=>n(g),style:{...Mg,background:g,outline:d.toLowerCase()===g.toLowerCase()?"2px solid #2563eb":"none"}},g))})]})}const eN={display:"flex",flexDirection:"column",gap:8},tN={display:"flex",alignItems:"center",gap:6},nN={position:"relative",display:"inline-flex",cursor:"pointer"},oN={width:24,height:24,borderRadius:4,border:"1px solid #cbd5e1",display:"inline-block"},rN={flex:1,padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,fontFamily:"monospace"},iN={padding:"4px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",cursor:"pointer",color:"#64748b"},zg={display:"grid",gridTemplateColumns:"repeat(7, 1fr)",gap:4},Mg={width:"100%",height:18,borderRadius:4,border:"1px solid #cbd5e1",cursor:"pointer",padding:0},sN={fontSize:11,color:"#94a3b8",fontStyle:"italic",padding:"2px 0"},Qo=[{value:"fill",labelKey:"layout_editor.control.background_image.mode_fill",size:"cover",repeat:"no-repeat"},{value:"fit",labelKey:"layout_editor.control.background_image.mode_fit",size:"contain",repeat:"no-repeat"},{value:"tile",labelKey:"layout_editor.control.background_image.mode_tile",size:"auto",repeat:"repeat"}];function aN(e){return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}function Lg(e){return Qo.find(n=>n.size===e.size&&n.repeat===e.repeat)?.value??"fill"}function lN({value:e,onChange:t,t:n}){const o=aN(e),{state:r}=Je(),s=yo(),[a,l]=u.useState(!1),[d,c]=u.useState(null),[p,f]=u.useState(o.url??""),[y,g]=u.useState([]),m=u.useRef(null),h=r.templateIdentifier,v=r.selectedRoute?.layoutName??"";u.useEffect(()=>{f(o.url??"")},[o.url]);const b=u.useCallback(async()=>{if(!h||!v){g([]);return}const E=await Dl(h,v);E.ok&&g(E.data)},[h,v]);u.useEffect(()=>{b()},[b]);const x=E=>{if(!E){t(void 0);return}const S=Qo.find(T=>T.value===Lg(o))??Qo[0];t({url:E,size:o.size??S.size,repeat:o.repeat??S.repeat,position:o.position??"center"})},k=E=>{const S=Qo.find(T=>T.value===E);!S||!o.url||t({url:o.url,size:S.size,repeat:S.repeat,position:o.position??"center"})},w=async E=>{const S=E.target.files?.[0];if(!S)return;l(!0),c(null);const T=await Nl(h,v,S);T.ok?(x(T.data.url),b()):c(n("layout_editor.control.background_image.upload_failed")),l(!1),m.current&&(m.current.value="")},_=async E=>{(await zl(E.id)).ok&&g(T=>T.filter($=>$.id!==E.id))},C=()=>{const E=s.open({ariaLabel:n("layout_editor.attachment_manager.title"),width:720,maxHeightRatio:.82,content:u.createElement(Ml,{templateIdentifier:h,layoutName:v,t:n,onSelect:S=>{x(S),s.close(E)},onChanged:()=>{b()},onClose:()=>s.close(E)})})};return i.jsxs("div",{className:"g7le-widget g7le-widget--image","data-testid":"g7le-widget-image",style:dN,children:[o.url&&i.jsx("div",{"data-testid":"g7le-image-preview",style:{...cN,backgroundImage:`url(${o.url})`,backgroundSize:o.size??"cover",backgroundRepeat:o.repeat??"no-repeat",backgroundPosition:o.position??"center"}}),i.jsxs("div",{style:uN,children:[i.jsxs("label",{style:pN,children:[a?"…":n("layout_editor.control.background_image.upload"),i.jsx("input",{ref:m,type:"file",accept:"image/*","data-testid":"g7le-image-file",onChange:w,disabled:a,style:{display:"none"}})]}),i.jsx("button",{type:"button","data-testid":"g7le-image-clear",onClick:()=>t(void 0),style:fN,children:n("layout_editor.control.background_image.clear")})]}),i.jsx("input",{type:"text","data-testid":"g7le-image-url",placeholder:"https://… / URL",value:p,onChange:E=>f(E.target.value),onBlur:E=>x(E.target.value.trim()||void 0),style:gN}),i.jsx("div",{style:hN,"data-testid":"g7le-image-modes",children:Qo.map(E=>{const S=Lg(o)===E.value;return i.jsx("button",{type:"button","data-testid":`g7le-image-mode-${E.value}`,"data-active":S?"true":"false",disabled:!o.url,onClick:()=>k(E.value),style:{...yN,background:S&&o.url?"#2563eb":"#fff",color:S&&o.url?"#fff":"#0f172a"},children:n(E.labelKey)},E.value)})}),i.jsxs("div",{style:bN,"data-testid":"g7le-image-gallery",children:[i.jsxs("div",{style:mN,children:[i.jsx("span",{style:{fontSize:11,color:"#64748b"},children:n("layout_editor.attachment_manager.recent")}),i.jsxs("button",{type:"button","data-testid":"g7le-image-manage",onClick:C,style:vN,children:["🖼 ",n("layout_editor.attachment_manager.manage_link")]})]}),y.length>0?i.jsx("div",{style:_N,"data-testid":"g7le-image-thumbs",children:y.slice(0,8).map(E=>i.jsxs("div",{style:xN,"data-testid":`g7le-image-thumb-${E.id}`,children:[i.jsx("button",{type:"button",title:E.original_name,onClick:()=>x(E.url),style:{...wN,backgroundImage:`url(${E.url})`},"data-testid":`g7le-image-thumb-use-${E.id}`}),i.jsx("button",{type:"button",title:n("layout_editor.attachment_manager.delete"),onClick:()=>_(E),style:kN,"data-testid":`g7le-image-thumb-del-${E.id}`,children:"✕"})]},E.id))}):i.jsx("span",{style:{fontSize:11,color:"#94a3b8"},children:n("layout_editor.attachment_manager.empty")})]}),d&&i.jsx("span",{"data-testid":"g7le-image-error",style:{fontSize:11,color:"#dc2626"},children:d})]})}const dN={display:"flex",flexDirection:"column",gap:6},cN={width:"100%",height:80,borderRadius:6,border:"1px solid #cbd5e1"},uN={display:"flex",gap:6},pN={padding:"5px 10px",fontSize:12,border:"1px solid #2563eb",borderRadius:6,background:"#fff",color:"#2563eb",cursor:"pointer",display:"inline-flex",alignItems:"center"},fN={padding:"5px 10px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#64748b",cursor:"pointer"},gN={padding:"5px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},hN={display:"inline-flex",border:"1px solid #cbd5e1",borderRadius:6,overflow:"hidden"},yN={padding:"4px 10px",fontSize:12,border:"none",borderRight:"1px solid #e2e8f0",cursor:"pointer"},bN={display:"flex",flexDirection:"column",gap:4,border:"1px solid #e2e8f0",borderRadius:6,padding:6,marginTop:2},mN={display:"flex",alignItems:"center",justifyContent:"space-between"},vN={fontSize:11,color:"#2563eb",background:"transparent",border:"none",cursor:"pointer",padding:0},_N={display:"flex",gap:6,flexWrap:"wrap"},xN={position:"relative",width:44,height:44},wN={width:44,height:44,borderRadius:6,border:"1px solid #cbd5e1",backgroundSize:"cover",backgroundPosition:"center",cursor:"pointer",padding:0},kN={position:"absolute",top:-6,right:-6,width:16,height:16,borderRadius:"50%",border:"none",background:"#dc2626",color:"#fff",fontSize:9,lineHeight:"16px",cursor:"pointer",padding:0};function SN(e){return Array.isArray(e)&&e.every(t=>t!==null&&typeof t=="object"&&!Array.isArray(t))}function CN(e){return typeof e=="string"&&/\{\{.*\}\}/.test(e)}function $N({value:e,onChange:t,t:n,bindingCandidates:o}){if(CN(e))return i.jsx("div",{className:"g7le-widget g7le-widget--options-list","data-testid":"g7le-widget-options-list-bound",style:MN,children:n("layout_editor.list_editor.bound_degraded")});const r=SN(e)?e:[],s=y=>{t(y.length===0?void 0:y)},a=(y,g)=>{const m=r.map((h,v)=>v===y?{...h,...g}:h);s(m)},l=y=>{s(r.filter((g,m)=>m!==y))},d=(y,g)=>{const m=y+g;if(m<0||m>=r.length)return;const h=[...r];[h[y],h[m]]=[h[m],h[y]],s(h)},c=()=>{s([...r,{value:"",label:""}])},p=y=>typeof y.label=="string"?y.label:y.label==null?"":String(y.label),f=y=>y.value===void 0||y.value===null?"":String(y.value);return i.jsxs("div",{className:"g7le-widget g7le-widget--options-list","data-testid":"g7le-widget-options-list",style:EN,children:[r.length===0&&i.jsx("div",{"data-testid":"g7le-options-empty",style:zN,children:n("layout_editor.list_editor.empty")}),r.map((y,g)=>i.jsxs("div",{"data-testid":`g7le-options-row-${g}`,style:IN,children:[i.jsxs("div",{style:Pg,children:[i.jsx("span",{style:Og,children:n("layout_editor.list_editor.option_value")}),i.jsx("input",{type:"text","data-testid":`g7le-options-value-${g}`,value:f(y),placeholder:n("layout_editor.list_editor.option_value"),onChange:m=>a(g,{value:m.target.value}),style:TN})]}),i.jsxs("div",{style:Pg,children:[i.jsx("span",{style:Og,children:n("layout_editor.list_editor.option_label")}),i.jsx("div",{"data-testid":`g7le-options-label-${g}`,style:{flex:1,minWidth:0},children:i.jsx(vt,{value:p(y),onChange:m=>a(g,{label:m??""}),t:n,placeholder:n("layout_editor.list_editor.option_label"),testidPrefix:`g7le-options-label-i18n-${g}`,candidates:o,enableExpressionTree:!0,expressionTreeCollapsible:!0})})]}),i.jsxs("div",{style:AN,children:[i.jsx("button",{type:"button","data-testid":`g7le-options-up-${g}`,title:n("layout_editor.list_editor.move_up"),disabled:g===0,onClick:()=>d(g,-1),style:Bg,children:"↑"}),i.jsx("button",{type:"button","data-testid":`g7le-options-down-${g}`,title:n("layout_editor.list_editor.move_down"),disabled:g===r.length-1,onClick:()=>d(g,1),style:Bg,children:"↓"}),i.jsx("button",{type:"button","data-testid":`g7le-options-remove-${g}`,title:n("layout_editor.list_editor.remove"),onClick:()=>l(g),style:DN,children:"✕"})]})]},g)),i.jsx("button",{type:"button","data-testid":"g7le-options-add",onClick:c,style:NN,children:n("layout_editor.list_editor.add")})]})}const EN={display:"flex",flexDirection:"column",gap:8,width:"100%"},IN={display:"flex",flexDirection:"column",gap:4,width:"100%",minWidth:0,paddingBottom:6,borderBottom:"1px solid #f1f5f9"},Pg={display:"flex",gap:6,alignItems:"center",width:"100%",minWidth:0},Og={flexShrink:0,width:36,fontSize:11,color:"#94a3b8",textAlign:"right"},AN={display:"flex",gap:4,alignItems:"center",justifyContent:"flex-end"},TN={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},Bg={padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},DN={padding:"2px 6px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},NN={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},zN={fontSize:11,color:"#94a3b8",fontStyle:"italic"},MN={fontSize:11,color:"#b45309",fontStyle:"italic",padding:"4px 2px"},Wg=/[^A-Za-z0-9\-_:.]/g;function LN(e){return typeof e=="string"&&Ui(e)}function jg(e){return Ui(e)?In(e).map(t=>t.kind==="binding"?t.raw:t.raw.replace(Wg,"")).join(""):e.replace(Wg,"")}const PN={width:"100%",padding:"6px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:4,fontFamily:"monospace"},ON={marginTop:4,fontSize:11,color:"#94a3b8"},BN={display:"flex",gap:6,alignItems:"center"},WN={flexShrink:0,padding:"5px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:4,background:"#f8fafc",cursor:"pointer",whiteSpace:"nowrap"};function jN({value:e,onChange:t,t:n,bindingCandidates:o}){const r=e==null?"":String(e),s=LN(e),a=!!o&&o.length>0,[l,d]=u.useState(!1),c=p=>{const f=jg(p);t(f===""?void 0:f)};return s||l?i.jsxs("div",{"data-testid":"g7le-core-id-chip",children:[i.jsx(bs,{value:r,onChange:c,t:n,candidates:o,onDone:()=>d(!1),testidPrefix:"g7le-core-id-chip-input"}),i.jsx("div",{style:ON,children:n("layout_editor.core_props.id.binding_hint")})]}):i.jsx("div",{children:i.jsxs("div",{style:BN,children:[i.jsx("input",{type:"text",className:"g7le-widget g7le-widget--core-id","data-testid":"g7le-widget-core-id",value:r,onChange:p=>{const f=jg(p.target.value);t(f===""?void 0:f)},spellCheck:!1,autoComplete:"off",style:PN}),a&&i.jsxs("button",{type:"button","data-testid":"g7le-core-id-add-data",onClick:()=>d(!0),style:WN,title:n("layout_editor.core_props.id.add_data"),children:["🔗 ",n("layout_editor.core_props.id.add_data")]})]})})}const HN=/[^A-Za-z0-9.\-_]/g;function FN(e){return typeof e=="string"&&/\{\{[\s\S]*?\}\}/.test(e)}function KN(e){return e.replace(HN,"")}const Hg={width:"100%",padding:"6px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:4,fontFamily:"monospace",boxSizing:"border-box"},VN={...Hg,background:"#f1f5f9",color:"#64748b",cursor:"not-allowed"},Fg={marginTop:4,fontSize:11,color:"#94a3b8"};function UN({value:e,onChange:t,t:n}){const o=e==null?"":String(e);return FN(e)?i.jsxs("div",{"data-testid":"g7le-core-datakey-bound",children:[i.jsx("input",{type:"text",className:"g7le-widget g7le-widget--core-datakey-bound","data-testid":"g7le-widget-core-datakey",value:o,readOnly:!0,disabled:!0,style:VN}),i.jsx("div",{style:Fg,children:n("layout_editor.core_props.dataKey.bound_degraded")})]}):i.jsxs("div",{children:[i.jsx("input",{type:"text",className:"g7le-widget g7le-widget--core-datakey","data-testid":"g7le-widget-core-datakey",value:o,placeholder:n("layout_editor.core_props.dataKey.placeholder"),onChange:s=>{const a=KN(s.target.value);t(a===""?void 0:a)},spellCheck:!1,autoComplete:"off",style:Hg}),i.jsx("div",{style:Fg,children:n("layout_editor.core_props.dataKey.hint")})]})}let Kg=!1;function qN(){Kg||(Xe("segmented",ED),Xe("slider",ID),Xe("select",AD),Xe("dimension",DD),Xe("spacing",MD),Xe("toggle",TD),Xe("color",RD),Xe("image",lN),Xe("tag-input",ys),Xe("page-picker",Aw),Xe("datasource-picker",Bc),Xe("binding-picker",Bc),Xe("binding-list",Nw),Xe("state-key-picker",Es),Xe("modal-picker",Tw),Xe("i18n-text",Dw),Xe("text",zw),Xe("options-list",$N),Xe("core-id",jN),Xe("core-datakey",UN),Xe("component-target-picker",jT),Kg=!0)}function Ro(e){return Array.isArray(e.children)?e.children:[]}function er(e){if(typeof e.text=="string")return[];let t=null;const n=(o,r)=>{const s=Ro(o);for(let a=0;ad===o?tr(l,r,n):l);return{...e,children:a}}function Vg(e,t){const n=r=>typeof r.props?.[t]=="string";if(n(e))return[];const o=(r,s)=>{const a=Ro(r);for(let l=0;lc===r?Ug(d,s,n,o):d);return{...e,children:l}}function GN(e){return Array.isArray(e.children)?e.children:[]}function YN(e){const t=e?.itemFields;if(!Array.isArray(t))return[{kind:"text"}];const n=[];for(const o of t){if(!o||typeof o!="object")continue;const r=o;r.kind==="text"?n.push({kind:"text",label:typeof r.label=="string"?r.label:void 0}):r.kind==="prop"&&typeof r.prop=="string"&&r.prop.length>0&&n.push({kind:"prop",prop:r.prop,label:typeof r.label=="string"?r.label:void 0})}return n.length>0?n:[{kind:"text"}]}function el(e,t){if(!(typeof e!="string"||e.length===0))return e.startsWith("$t:")?t(e.slice(3)):e}function qg({node:e,params:t,spec:n,manifest:o,t:r,onPatchNode:s,templateIdentifier:a,candidates:l}){const d=typeof t?.childComponent=="string"?t.childComponent:null,c=t?.childTemplate&&typeof t.childTemplate=="object"?t.childTemplate:null,p=YN(t),f=el(typeof t?.childLabel=="string"?t.childLabel:void 0,r)??d??"",y=GN(e),g=u.useCallback(_=>{s({...e,children:_})},[e,s]),m=u.useCallback(()=>{if(c)return JSON.parse(JSON.stringify(c));if(!d)return null;const _=n?.componentPalette?.entries?.[d];if(_?.defaultNode&&typeof _.defaultNode=="object")return JSON.parse(JSON.stringify(_.defaultNode));const C=o?.components??{};let E=null;for(const S of Object.values(C))if(Array.isArray(S)){const T=S.find($=>$.name===d);if(T){E=T;break}}return E?$f(E):{type:"basic",name:d}},[c,d,n,o]),h=u.useCallback(()=>{const _=m();if(_){if(_.text==="")_.text=r("layout_editor.list_editor.new_item");else{const C=er(_);if(C!==null&&C.length>0){const E=_i(_,C);if(E&&E.text===""){const S=tr(_,C,r("layout_editor.list_editor.new_item"));g([...y,S]);return}}}g([...y,_])}},[m,g,y,r]),v=u.useCallback(_=>{g(y.filter((C,E)=>E!==_))},[g,y]),b=u.useCallback((_,C)=>{const E=_+C;if(E<0||E>=y.length)return;const S=[...y];[S[_],S[E]]=[S[E],S[_]],g(S)},[g,y]),x=u.useCallback((_,C)=>{if(typeof C!="string"||C.length===0)return;const E=y[_];if(!E)return;const S=er(E);if(S===null)return;const T=y.map(($,A)=>A===_?tr($,S,C):$);g(T)},[y,g]),k=u.useCallback((_,C,E)=>{if(typeof E!="string"||E.length===0)return;const S=y[_];if(!S)return;const T=Vg(S,C);if(T===null)return;const $=y.map((A,z)=>z===_?Ug(A,T,C,E):A);g($)},[y,g]);if(!d&&!c)return i.jsx("div",{className:"g7le-node-editor g7le-node-editor--children","data-testid":"g7le-children-editor-misconfigured",style:Xg,children:r("layout_editor.list_editor.no_child_component")});const w=p.length>1||p.some(_=>_.label);return i.jsxs("div",{className:"g7le-node-editor g7le-node-editor--children","data-testid":"g7le-children-editor",style:XN,children:[i.jsx("div",{style:JN,children:r("layout_editor.list_editor.items_title")}),y.length===0&&i.jsx("div",{"data-testid":"g7le-children-empty",style:Xg,children:r("layout_editor.list_editor.empty")}),y.map((_,C)=>{const E=[];for(const T of p)if(T.kind==="text"){const $=er(_),A=$!==null?_i(_,$):null;A&&typeof A.text=="string"&&E.push({key:"text",caption:el(T.label,r)??(w?r("layout_editor.list_editor.item_label"):void 0),value:A.text,onChange:z=>x(C,z),testid:`g7le-children-i18n-${C}`})}else if(T.kind==="prop"&&T.prop){const $=Vg(_,T.prop);if($!==null){const z=_i(_,$)?.props?.[T.prop];E.push({key:`prop-${T.prop}`,caption:el(T.label,r)??T.prop,value:typeof z=="string"?z:"",onChange:D=>k(C,T.prop,D),testid:`g7le-children-prop-${T.prop}-${C}`})}}const S=typeof _?.name=="string"?_.name:r("layout_editor.list_editor.item");return i.jsxs("div",{"data-testid":`g7le-children-row-${C}`,style:ZN,children:[E.length>0?E.map(T=>i.jsx("div",{style:Gg,children:i.jsxs("div",{"data-testid":T.key==="text"?`g7le-children-text-${C}`:`g7le-children-field-${T.key}-${C}`,style:QN,children:[T.caption!==void 0&&i.jsx("div",{"data-testid":`g7le-children-caption-${T.key}-${C}`,style:RN,children:T.caption}),i.jsx(vt,{value:T.value,onChange:T.onChange,t:r,placeholder:r("layout_editor.list_editor.item_text"),testidPrefix:T.testid,candidates:l,enableExpressionTree:!0,expressionTreeCollapsible:!0})]})},T.key)):i.jsx("div",{style:Gg,children:i.jsx("span",{"data-testid":`g7le-children-label-${C}`,style:t8,children:S})}),i.jsxs("div",{style:e8,children:[i.jsx("button",{type:"button","data-testid":`g7le-children-up-${C}`,title:r("layout_editor.list_editor.move_up"),disabled:C===0,onClick:()=>b(C,-1),style:Yg,children:"↑"}),i.jsx("button",{type:"button","data-testid":`g7le-children-down-${C}`,title:r("layout_editor.list_editor.move_down"),disabled:C===y.length-1,onClick:()=>b(C,1),style:Yg,children:"↓"}),i.jsx("button",{type:"button","data-testid":`g7le-children-remove-${C}`,title:r("layout_editor.list_editor.remove"),onClick:()=>v(C),style:n8,children:"✕"})]})]},C)}),i.jsx("button",{type:"button","data-testid":"g7le-children-add",onClick:h,style:o8,children:r("layout_editor.list_editor.add_child",{component:f})})]})}const XN={display:"flex",flexDirection:"column",gap:6,width:"100%",marginBottom:12},JN={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:2},ZN={display:"flex",flexDirection:"column",gap:4,width:"100%",minWidth:0,paddingBottom:6,borderBottom:"1px solid #f1f5f9"},Gg={display:"flex",gap:4,alignItems:"flex-start",width:"100%",minWidth:0},QN={flex:1,minWidth:0},RN={fontSize:11,color:"#64748b",marginBottom:2},e8={display:"flex",gap:4,alignItems:"center",justifyContent:"flex-end"},t8={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,color:"#475569",fontStyle:"italic",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},Yg={padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},n8={padding:"2px 6px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},o8={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},Xg={fontSize:11,color:"#94a3b8",fontStyle:"italic"},fo={rowContainer:"Tbody",row:"Tr",cell:"Td",headerCell:"Th",colSpanProp:"colSpan",rowSpanProp:"rowSpan"};function ht(e){return{rowContainer:e?.rowContainer??fo.rowContainer,row:e?.row??fo.row,cell:e?.cell??fo.cell,headerCell:e?.headerCell??fo.headerCell,colSpanProp:e?.colSpanProp??fo.colSpanProp,rowSpanProp:e?.rowSpanProp??fo.rowSpanProp}}function Bn(e){return e?Array.isArray(e.children)?e.children:[]:[]}function Jg(e,t){const n=e.props?.[t],o=typeof n=="number"?n:typeof n=="string"?parseInt(n,10):NaN;return Number.isFinite(o)&&o>=1?Math.floor(o):1}function Be(e,t){const n=ht(t),o=[],r=Bn(e),s=[];r.forEach((f,y)=>{(Bn(f).some(h=>h.name===n.row)||f.name===n.rowContainer||f.name==="Thead"||f.name==="Tfoot")&&s.push({container:f,containerIndex:y,isHeader:f.name==="Thead"})}),s.length===0&&r.some(f=>f.name===n.row)&&s.push({container:e,containerIndex:-1,isHeader:!1});const a=[],l=[];let d=0,c=0;const p=f=>{for(;a.length<=f;)a.push([]);return a[f]};s.forEach((f,y)=>{Bn(f.container).filter(m=>m.name===n.row).forEach((m,h)=>{const v=[],b=p(d);let x=0;Bn(m).filter(w=>w.name===n.cell||w.name===n.headerCell).forEach((w,_)=>{for(;b[x];)x++;const C=Jg(w,n.colSpanProp),E=Jg(w,n.rowSpanProp),S={cell:w,sectionIndex:y,rowIndexInSection:h,cellIndexInRow:_,gridRow:d,gridCol:x,colSpan:C,rowSpan:E,isHeader:w.name===n.headerCell};v.push(S);for(let T=0;T=0?(a.push(s.containerIndex),l=Bn(e)[s.containerIndex]??e):l=e;let d=-1,c=-1,p=null;const f=Bn(l);for(let m=0;m=r.gridRow&&t=r.gridCol&&nr){s=!0;break}if(s)break}s||t.add(r)}const n=Array.from(t).sort((r,s)=>r-s),o=[];for(let r=0;re.rows.find(l=>(l.cells[0]?.gridRow??-1)===a)?.sectionIndex??e.rows[a]?.sectionIndex??0,o=new Set([0,t]);for(let a=1;aa){l=!0;break}if(l)break}l||o.add(a)}const r=Array.from(o).sort((a,l)=>a-l),s=[];for(let a=0;at>=a.start&&t=o.length?{ok:!1,reason:"boundary"}:o[r].sectionIndex!==o[s].sectionIndex?{ok:!1,reason:"section"}:{ok:!0}}function wi(e,t,n){const o=Zg(e),r=o.findIndex(a=>t>=a.start&&t=o.length?{ok:!1,reason:"boundary"}:{ok:!0}}function Ge(e){return e?Array.isArray(e.children)?e.children:[]:[]}function mn(e,t,n){const o={...e.props??{}};n<=1?delete o[t]:o[t]=n;const r={...e,props:o};return Object.keys(o).length===0&&delete r.props,r}function ki(e,t,n=!1){const o={type:"basic",name:n?e.headerCell:e.cell},r=t?.props?.className;return typeof r=="string"&&r&&(o.props={className:r}),o.text="",o}function nr(e,t){return e.name===t.cell||e.name===t.headerCell}function nt(e,t,n,o){const r=t.sections[n];if(!r)return e;if(r.containerIndex===-1)return o(e);const s=Ge(e).map((a,l)=>l===r.containerIndex?o(a):a);return{...e,children:s}}function yt(e,t,n,o){let r=-1;const s=Ge(e).map(a=>a.name===t&&(r++,r===n)?o(a):a);return{...e,children:s}}function Si(e,t,n){let o=-1;const r=Ge(e);for(let s=0;s0?nt(e,r,r.sections.length-1,x=>({...x,children:[...Ge(x),b]})):{...e,children:[...Ge(e),b]}}const s=Math.max(-1,Math.min(n,r.rows.length-1)),a=s<0?r.rows[0]:r.rows[s],l=a.cells[0]?.gridRow??s,d=s<0?0:l+1,c=a.sectionIndex,p=s<0?0:a.rowIndexInSection+1,f=[],y=[];let g=0;for(;g0?Ue(r,d-1,g):null;b&&b.gridRow+b.rowSpan>d&&b.rowSpan>1?(y.push(b),g+=b.colSpan):(f.push(ki(o)),g+=1)}let m=e;for(const b of y)m=nt(m,r,b.sectionIndex,x=>yt(x,o.row,b.rowIndexInSection,k=>({...k,children:Ge(k).map((w,_)=>_===b.cellIndexInRow?mn(w,o.rowSpanProp,b.rowSpan+1):w)})));const h={type:"basic",name:o.row,children:f},v=Be(m,t);return m=nt(m,v,c,b=>{const x=Ge(b);let k=0,w=x.length;for(let _=0;_=r.rows.length||r.rows.length<=1)return e;const s=r.rows[n],a=s.cells[0]?.gridRow??n;let l=e;const d=new Set;for(let p=0;pyt(y,o.row,f.rowIndexInSection,g=>({...g,children:Ge(g).map((m,h)=>h===f.cellIndexInRow?mn(m,o.rowSpanProp,f.rowSpan-1):m)})))),p+=f?f.colSpan:1}const c=Be(l,t);return l=nt(l,c,s.sectionIndex,p=>{let f=-1;const y=Ge(p).filter(g=>g.name===o.row?(f++,f!==s.rowIndexInSection):!0);return{...p,children:y}}),l}function eh(e,t,n,o){const r=ht(t),s=Be(e,t);if(!xi(s,n,o).ok)return e;const a=Qg(s),l=a.findIndex(h=>n>=h.start&&ns.rows.filter(v=>{const b=v.cells[0]?.gridRow??-1;return v.sectionIndex===f&&b>=h.start&&bv.rowIndexInSection),g=y(c),m=y(p);return g.length===0||m.length===0?e:nt(e,s,f,h=>{const v=[...Ge(h)],b=[];v.forEach((M,B)=>{M.name===r.row&&b.push(B)});const x=g.map(M=>b[M]).filter(M=>M!==void 0),k=m.map(M=>b[M]).filter(M=>M!==void 0);if(x.length===0||k.length===0)return h;const w=x.map(M=>v[M]),_=k.map(M=>v[M]),C=Math.min(...x)n>=m.start&&nw.gridCol>=f.start&&w.gridColw.gridCol>=y.start&&w.gridColw.cellIndexInRow),x=v.map(w=>w.cellIndexInRow),k=Be(g,t);g=nt(g,k,m.sectionIndex,w=>yt(w,r.row,m.rowIndexInSection,_=>{const C=[...Ge(_)],E=b.map(M=>Si(_,r,M)).filter(M=>M>=0),S=x.map(M=>Si(_,r,M)).filter(M=>M>=0);if(E.length===0||S.length===0)return _;const T=E.map(M=>C[M]),$=S.map(M=>C[M]),A=Math.min(...E,...S),z=Math.max(...E,...S),D=[...$,...T],O=[...C.slice(0,A),...D,...C.slice(z+1)];return{..._,children:O}}))}return g}function nh(e,t,n){const o=ht(t),r=Be(e,t);if(r.rows.length===0||r.colCount===0)return nl(e,t,-1);const s=Math.max(0,Math.min(n+1,r.colCount));let a=e;const l=new Set;for(const d of r.rows){const c=d.cells[0]?.gridRow??0,p=s>0?Ue(r,c,s-1):null,f=s1){if(!l.has(p.cell)){l.add(p.cell);const h=Be(a,t);a=nt(a,h,p.sectionIndex,v=>yt(v,o.row,p.rowIndexInSection,b=>({...b,children:Ge(b).map((x,k)=>k===p.cellIndexInRow?mn(x,o.colSpanProp,p.colSpan+1):x)})))}continue}if(p&&p.gridRow0&&d.cells.every(h=>h.isHeader),m=Be(a,t);a=nt(a,m,d.sectionIndex,h=>yt(h,o.row,d.rowIndexInSection,v=>{const b=[...Ge(v)];let x;if(y<0)x=b.findIndex(k=>nr(k,o)),x<0&&(x=b.length);else{const k=Si(v,o,y);x=k<0?b.length:k+1}return b.splice(x,0,ki(o,void 0,g)),{...v,children:b}}))}return a}function oh(e,t,n){const o=ht(t),r=Be(e,t);if(n<0||n>=r.colCount||r.colCount<=1)return e;let s=e;const a=new Set;for(const l of r.rows){const d=l.cells[0]?.gridRow??0,c=Ue(r,d,n);if(!(!c||a.has(c.cell)||c.gridRow1){const p=Be(s,t);s=nt(s,p,c.sectionIndex,f=>yt(f,o.row,c.rowIndexInSection,y=>({...y,children:Ge(y).map((g,m)=>m===c.cellIndexInRow?mn(g,o.colSpanProp,c.colSpan-1):g)})))}else{const p=Be(s,t);s=nt(s,p,c.sectionIndex,f=>yt(f,o.row,c.rowIndexInSection,y=>{let g=-1;const m=Ge(y).filter(h=>nr(h,o)?(g++,g!==c.cellIndexInRow):!0);return{...y,children:m}}))}}return s}function ol(e,t,n,o,r,s){const a=ht(t),l=Be(e,t),d=Math.min(n,r),c=Math.max(n,r),p=Math.min(o,s),f=Math.max(o,s);if(d===c&&p===f)return{table:e,ok:!1,reason:"single"};if(!l.valid)return{table:e,ok:!1,reason:"invalid-grid"};const y=new Set;for(let b=d;b<=c;b++)for(let x=p;x<=f;x++){const k=Ue(l,b,x);if(!k)return{table:e,ok:!1,reason:"hole"};if(k.gridRowc||k.gridCol+k.colSpan-1>f)return{table:e,ok:!1,reason:"not-rectangular"};y.add(k)}const g=Ue(l,d,p),m=Array.from(y).filter(b=>b!==g);let h=nt(e,l,g.sectionIndex,b=>yt(b,a.row,g.rowIndexInSection,x=>({...x,children:Ge(x).map((k,w)=>{if(w!==g.cellIndexInRow)return k;let _=mn(k,a.colSpanProp,f-p+1);return _=mn(_,a.rowSpanProp,c-d+1),_})})));const v=new Map;for(const b of m){const x=`${b.sectionIndex}:${b.rowIndexInSection}`,k=v.get(x)??[];k.push(b),v.set(x,k)}for(const[b,x]of v){const k=parseInt(b.split(":")[0],10),w=x[0].rowIndexInSection,_=new Set(x.map(E=>E.cellIndexInRow)),C=Be(h,t);h=nt(h,C,k,E=>yt(E,a.row,w,S=>{let T=-1;const $=Ge(S).filter(A=>nr(A,a)?(T++,!_.has(T)):!0);return{...S,children:$}}))}return{table:h,ok:!0}}function rh(e,t,n,o){const r=ht(t),s=Be(e,t),a=Ue(s,n,o);if(!a||a.colSpan<=1&&a.rowSpan<=1)return e;const l=a.gridRow,d=a.gridCol,c=a.gridRow+a.rowSpan-1,p=a.gridCol+a.colSpan-1,f=a.isHeader,y=typeof a.cell.props?.className=="string"?a.cell.props.className:void 0;let g=nt(e,s,a.sectionIndex,m=>yt(m,r.row,a.rowIndexInSection,h=>({...h,children:Ge(h).map((v,b)=>{if(b!==a.cellIndexInRow)return v;let x=mn(v,r.colSpanProp,1);return x=mn(x,r.rowSpanProp,1),x})})));for(let m=l;m<=c;m++)for(let h=d;h<=p;h++){if(m===l&&h===d)continue;const v=Be(g,t),b=v.rows.find(w=>w.cells.some(_=>_.gridRow===m))??v.rows[m];if(!b)continue;let x=-1;for(const w of b.cells)w.gridRow===m&&w.gridColyt(w,r.row,b.rowIndexInSection,_=>{const C=[...Ge(_)];let E;if(x<0)E=C.findIndex(S=>nr(S,r)),E<0&&(E=C.length);else{const S=Si(_,r,x);E=S<0?C.length:S+1}return C.splice(E,0,ki(r,k,f)),{..._,children:C}}))}return g}function Ci(e,t,n,o,r){const s=ht(t),a=Be(e,t),l=Ue(a,n,o);return l?nt(e,a,l.sectionIndex,d=>yt(d,s.row,l.rowIndexInSection,c=>({...c,children:Ge(c).map((p,f)=>{if(f!==l.cellIndexInRow)return p;const y={...p.props??{}};r.trim()===""?delete y.className:y.className=r;const g={...p,props:y};return Object.keys(y).length===0&&delete g.props,g})}))):e}function Jt(e,t,n,o,r,s){const a=ht(t),l=Be(e,t),d=Ue(l,n,o);return d?nt(e,l,d.sectionIndex,c=>yt(c,a.row,d.rowIndexInSection,p=>({...p,children:Ge(p).map((f,y)=>{if(y!==d.cellIndexInRow)return f;const g={...f.props??{}},m={...g.style??{}};!s||s.trim()===""?delete m[r]:m[r]=s,Object.keys(m).length===0?delete g.style:g.style=m;const h={...f,props:g};return Object.keys(g).length===0&&delete h.props,h})}))):e}function go(e,t,n,o,r,s,a){const l=ht(t),d=Be(e,t),c=Ue(d,n,o);if(!c)return e;const p=a==="dark";return nt(e,d,c.sectionIndex,f=>yt(f,l.row,c.rowIndexInSection,y=>({...y,children:Ge(y).map((g,m)=>{if(m!==c.cellIndexInRow)return g;const h={...g.props??{}},v=typeof h.className=="string"?h.className:"",b=uC(v,s,r,p);b===""?delete h.className:h.className=b;const x={...g,props:h};return Object.keys(h).length===0&&delete x.props,x})})))}function ih(e,t,n,o,r){const s=ht(t),a=Be(e,t),l=Ue(a,n,o);return l?nt(e,a,l.sectionIndex,d=>yt(d,s.row,l.rowIndexInSection,c=>({...c,children:Ge(c).map((p,f)=>f===l.cellIndexInRow?{...p,text:r}:p)}))):e}function sh(e,t,n,o,r){const s=ht(t),a=Be(e,t),l=Ue(a,n,o);return l?nt(e,a,l.sectionIndex,d=>yt(d,s.row,l.rowIndexInSection,c=>({...c,children:Ge(c).map((p,f)=>f===l.cellIndexInRow?r:p)}))):e}const ah=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function r8(e){return e.split(/\s+/).filter(Boolean)}function lh(e,t){for(const n of t)if(e===n||/^-?\d+$/.test(e.slice(n.length+1))&&e.startsWith(n+"-"))return!0;return!1}function dh({className:e,catalog:t,t:n,onChange:o,colorScheme:r="light",onPresetToken:s,colorStyle:a,onColorStyle:l,disabled:d}){const c=t?.sides??[],p=t?.widths??[],f=t?.colors??[],y=r==="dark",g=u.useMemo(()=>c.map($=>$.prefix),[c]),m=u.useMemo(()=>new Set(f.map($=>$.token)),[f]),h=u.useMemo(()=>r8(e),[e]),v=u.useMemo(()=>Vr(e,y),[e,y]),b=u.useMemo(()=>v.find($=>m.has($))??null,[v,m]),x=u.useMemo(()=>{const $=new Set;for(const A of c)h.some(D=>D===A.prefix||D.startsWith(A.prefix+"-")&&/^-?\d+$/.test(D.slice(A.prefix.length+1)))&&$.add(A.value);return $},[h,c]),k=u.useMemo(()=>{const $=h.find(z=>lh(z,g));if(!$)return"none";const A=p.filter(z=>z.value!=="none");for(const z of c){if($===z.prefix)return A.find(D=>(D.suffix??"")==="")?.value??"thin";if($.startsWith(z.prefix+"-")){const D=$.slice(z.prefix.length),O=A.find(M=>(M.suffix??"")===D);if(O)return O.value}}return"thin"},[h,g,c,p]);if(!t||c.length===0||p.length===0)return null;function w($){return $.filter(A=>!lh(A,g))}function _($,A){const z=w(h),D=p.find(B=>B.value===A);if(!D||A==="none"||$.size===0)return z.join(" ").trim();const O=D.suffix??"",M=[...z];for(const B of c)$.has(B.value)&&M.push(O?`${B.prefix}${O}`:B.prefix);return M.join(" ").trim()}const C=$=>{const A=new Set(x);A.has($)?A.delete($):($==="all"?A.clear():A.delete("all"),A.add($));const z=k==="none"?p.find(D=>D.value!=="none")?.value??"thin":k;o(_(A,z))},E=$=>{const A=x.size===0?new Set(["all"]):x;o(_(A,$))},S=$=>{s?.($)},T=($,A)=>$&&$.startsWith("$t:")?n($.slice(3)):$||A;return i.jsxs("div",{className:"g7le-cell-border","data-testid":"g7le-cell-border",style:i8,children:[i.jsx("div",{style:s8,children:i.jsx("span",{style:a8,children:n("layout_editor.table_editor.cell_border")})}),i.jsx("div",{style:rl,"data-testid":"g7le-cell-border-widths",children:p.map($=>i.jsx("button",{type:"button",disabled:d,"data-testid":`g7le-cell-border-width-${$.value}`,"aria-pressed":k===$.value,onClick:()=>E($.value),style:k===$.value?ch:il,children:T($.label,$.value)},$.value))}),k!=="none"&&i.jsx("div",{style:rl,"data-testid":"g7le-cell-border-sides",children:c.map($=>i.jsx("button",{type:"button",disabled:d,"data-testid":`g7le-cell-border-side-${$.value}`,"aria-pressed":x.has($.value),onClick:()=>C($.value),style:x.has($.value)?ch:il,children:T($.label,$.value)},$.value))}),k!=="none"&&(f.length>0||l)&&i.jsx(i.Fragment,{children:i.jsxs("div",{style:rl,"data-testid":"g7le-cell-border-colors",children:[f.map($=>{const A=b===$.token;return i.jsx("button",{type:"button",disabled:d,title:T($.label,$.value),"data-testid":`g7le-cell-border-color-${$.value}`,"aria-pressed":A,onClick:()=>S($.token),style:{...uh,background:$.swatch??"#fff",outline:A?"2px solid #2563eb":"1px solid #cbd5e1"}},$.value)}),l&&(()=>{const $=!!a&&f.some(z=>z.swatch&&z.swatch.toLowerCase()===a.toLowerCase()),A=!y&&!!a&&!$;return i.jsx("label",{title:n(y?"layout_editor.table_editor.dark_free_color_hint":"layout_editor.table_inplace.custom_color"),"data-testid":"g7le-cell-border-color-custom",style:{...uh,position:"relative",overflow:"hidden",display:"inline-flex",alignItems:"center",justifyContent:"center",background:A&&ah.test(a)?a:"conic-gradient(red, yellow, lime, aqua, blue, magenta, red)",outline:A?"2px solid #2563eb":"1px solid #cbd5e1",opacity:y?.4:1,cursor:y?"not-allowed":"pointer"},children:i.jsx("input",{type:"color",disabled:d||y,"data-testid":"g7le-cell-border-color-picker",value:a&&ah.test(a)?a:"#000000",onChange:z=>l(z.target.value),style:{position:"absolute",width:0,height:0,opacity:0}})})})()]})})]})}const i8={display:"flex",flexDirection:"column",gap:6},s8={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},a8={fontSize:12,fontWeight:600,color:"#475569"},rl={display:"flex",gap:4,flexWrap:"wrap",alignItems:"center"},il={padding:"3px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},ch={...il,border:"1px solid #2563eb",background:"#eff6ff",color:"#1d4ed8",fontWeight:600},uh={width:22,height:22,borderRadius:5,padding:0,cursor:"pointer",boxSizing:"border-box"},ph=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function fh({colorStyle:e,className:t,catalog:n,t:o,colorScheme:r="light",onPresetToken:s,onCustomColor:a,onClear:l,disabled:d}){const c=n?.colors??[],p=r==="dark",f=e??"",y=Vr(t??"",p),g=c.find(x=>x.token&&y.includes(x.token))?.token??null,m=(x,k)=>x&&x.startsWith("$t:")?o(x.slice(3)):x||k,h=!g&&(p||f.trim()===""),v=!!f&&c.some(x=>x.swatch&&x.swatch.toLowerCase()===f.toLowerCase()),b=!p&&!!f&&!v;return i.jsxs("div",{className:"g7le-cell-fill","data-testid":"g7le-cell-fill",style:l8,children:[i.jsx("div",{style:d8,children:i.jsx("span",{style:c8,children:o("layout_editor.table_editor.cell_fill")})}),i.jsxs("div",{style:u8,"data-testid":"g7le-cell-fill-colors",children:[i.jsx("button",{type:"button",disabled:d,title:o("layout_editor.table_editor.cell_fill_none"),"data-testid":"g7le-cell-fill-none","aria-pressed":h,onClick:()=>l?.(),style:{...sl,background:"repeating-conic-gradient(#e2e8f0 0% 25%, #ffffff 0% 50%) 50% / 10px 10px",outline:h?"2px solid #2563eb":"1px solid #cbd5e1"}}),c.map(x=>{const k=!!x.token&&g===x.token,w=!p&&!!x.swatch&&f.toLowerCase()===(x.swatch??"").toLowerCase(),_=k||w,C=d||p&&!x.token;return i.jsx("button",{type:"button",disabled:C,title:m(x.label,x.value),"data-testid":`g7le-cell-fill-color-${x.value}`,"aria-pressed":_,onClick:()=>{x.token&&s?s(x.token):!p&&x.swatch&&a&&a(x.swatch)},style:{...sl,background:x.swatch??"#fff",outline:_?"2px solid #2563eb":"1px solid #cbd5e1",opacity:C?.4:1,cursor:C?"not-allowed":"pointer"}},x.value)}),a&&i.jsx("label",{title:o(p?"layout_editor.table_editor.dark_free_color_hint":"layout_editor.table_editor.cell_fill_custom"),"data-testid":"g7le-cell-fill-custom",style:{...sl,position:"relative",overflow:"hidden",display:"inline-flex",alignItems:"center",justifyContent:"center",background:b&&ph.test(f)?f:"conic-gradient(red, yellow, lime, aqua, blue, magenta, red)",outline:b?"2px solid #2563eb":"1px solid #cbd5e1",opacity:p?.4:1,cursor:p?"not-allowed":"pointer"},children:i.jsx("input",{type:"color",disabled:d||p,"data-testid":"g7le-cell-fill-color-picker",value:f&&ph.test(f)?f:"#ffffff",onChange:x=>a(x.target.value),style:{position:"absolute",width:0,height:0,opacity:0}})})]})]})}const l8={display:"flex",flexDirection:"column",gap:6},d8={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},c8={fontSize:12,fontWeight:600,color:"#475569"},u8={display:"flex",gap:4,flexWrap:"wrap",alignItems:"center"},sl={width:22,height:22,borderRadius:5,padding:0,cursor:"pointer",boxSizing:"border-box"};function p8(e){const t=/^(\d+)px$/.exec(e.trim());return t?parseInt(t[1],10):null}function gh({paddingStyle:e,catalog:t,t:n,onChange:o,disabled:r}){const s=t?.steps??[],a=e??"",l=p8(a),d=(h,v)=>h&&h.startsWith("$t:")?n(h.slice(3)):h||v,c=s.some(h=>(h.px??0)===(l??-1)),p=l!==null&&!c?String(l):"",[f,y]=u.useState(p);u.useEffect(()=>{y(p)},[e]);const g=h=>{o(h&&h>0?`${h}px`:""),y("")},m=h=>{const v=parseInt(h,10);Number.isFinite(v)&&v>=0&&o(v>0?`${v}px`:"")};return i.jsxs("div",{className:"g7le-cell-padding","data-testid":"g7le-cell-padding",style:f8,children:[i.jsx("div",{style:g8,children:n("layout_editor.table_editor.cell_padding")}),i.jsxs("div",{style:h8,"data-testid":"g7le-cell-padding-steps",children:[s.map(h=>{const v=(h.px??0)===(l??-1)||!h.px&&a.trim()==="";return i.jsx("button",{type:"button",disabled:r,"data-testid":`g7le-cell-padding-step-${h.value}`,"aria-pressed":v,onClick:()=>g(h.px),style:v?y8:hh,children:d(h.label,h.value)},h.value)}),i.jsxs("span",{style:{display:"inline-flex",alignItems:"center",gap:3},children:[i.jsx("input",{type:"number",min:0,disabled:r,"data-testid":"g7le-cell-padding-free",value:f,placeholder:n("layout_editor.table_editor.cell_padding_custom"),onChange:h=>y(h.target.value),onBlur:()=>f.trim()!==""&&m(f),onKeyDown:h=>{h.key==="Enter"&&f.trim()!==""&&m(f)},style:b8}),i.jsx("span",{style:{fontSize:11,color:"#94a3b8"},children:"px"})]})]})]})}const f8={display:"flex",flexDirection:"column",gap:6},g8={fontSize:12,fontWeight:600,color:"#475569"},h8={display:"flex",gap:4,flexWrap:"wrap",alignItems:"center"},hh={padding:"3px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},y8={...hh,border:"1px solid #2563eb",background:"#eff6ff",color:"#1d4ed8",fontWeight:600},b8={width:48,padding:"3px 5px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,boxSizing:"border-box"};function yh({colorScheme:e,onChange:t,t:n,disabled:o}){const r=e==="dark";return i.jsxs("div",{className:"g7le-color-scheme-tabs","data-testid":"g7le-color-scheme-tabs",style:m8,children:[i.jsxs("div",{style:v8,children:[i.jsx("span",{style:_8,children:n("layout_editor.table_editor.cell_color")}),i.jsxs("div",{style:x8,children:[i.jsx("button",{type:"button",disabled:o,"data-testid":"g7le-color-scheme-light","aria-pressed":!r,onClick:()=>t("light"),style:r?al:bh,children:n("layout_editor.property_modal.scope.scheme_light")}),i.jsx("button",{type:"button",disabled:o,"data-testid":"g7le-color-scheme-dark","aria-pressed":r,onClick:()=>t("dark"),style:r?bh:al,children:n("layout_editor.property_modal.scope.scheme_dark")})]})]}),r&&i.jsx("div",{style:w8,"data-testid":"g7le-color-scheme-dark-hint",children:n("layout_editor.table_editor.dark_free_color_hint")})]})}const m8={display:"flex",flexDirection:"column",gap:3},v8={display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},_8={fontSize:12,fontWeight:700,color:"#0f172a"},x8={display:"flex",gap:2},al={padding:"2px 9px",fontSize:11,border:"none",borderBottom:"2px solid transparent",background:"transparent",color:"#94a3b8",cursor:"pointer"},bh={...al,color:"#1d4ed8",borderBottom:"2px solid #2563eb",fontWeight:600},w8={fontSize:10,color:"#94a3b8",fontStyle:"italic"},ll="dark:";function mh(e){return typeof e=="string"?e.split(/\s+/).filter(Boolean):[]}function vh(e,t){return t==="dark"?e.filter(n=>n.startsWith(ll)).map(n=>n.slice(ll.length)):e.filter(n=>!n.startsWith(ll))}const k8={none:0,thin:1,medium:2,thick:4},_h={top:{w:"borderTopWidth",s:"borderTopStyle",c:"borderTopColor"},bottom:{w:"borderBottomWidth",s:"borderBottomStyle",c:"borderBottomColor"},left:{w:"borderLeftWidth",s:"borderLeftStyle",c:"borderLeftColor"},right:{w:"borderRightWidth",s:"borderRightStyle",c:"borderRightColor"}},xh=["top","bottom","left","right"];function S8(e,t,n="light"){if(!e||!t)return{};const o=t.sides??[],r=t.widths??[],s=t.colors??[],a=mh(e.props?.className);if(a.length===0&&!e.props?.style)return{};const l=[...r].filter(b=>b.value!=="none").sort((b,x)=>(x.suffix??"").length-(b.suffix??"").length),d={};for(const b of o)for(const x of l){const k=x.suffix?`${b.prefix}${x.suffix}`:b.prefix;if(a.includes(k)){d[b.value]=x.value;break}}const c=e.props?.style??{},p=vh(a,n),f=s.find(b=>p.includes(b.token))?.swatch??"",g=(n==="light"&&typeof c.borderColor=="string"?c.borderColor:"")||f||"#94a3b8",m=b=>{const x=_h[b]?.c,k=x?c[x]:void 0;return typeof k=="string"&&k?k:g},h={},v=(b,x)=>{const k=_h[b];if(!k)return;const w=k8[x]??1;h[k.w]=`${w}px`,h[k.s]=w>0?"solid":"none",w>0&&(h[k.c]=m(b))};if(d.all)for(const b of xh)v(b,d.all);for(const b of xh)d[b]&&v(b,d[b]);return h}function C8(e,t,n="light"){if(!e?.props)return{};const o=e.props.style??{},r={},s=mh(e.props.className),a=t?.colors?.find(c=>c.token&&vh(s,n).includes(c.token))?.swatch??"",d=(n==="light"&&typeof o.backgroundColor=="string"?o.backgroundColor:"")||a;return d&&(r.backgroundColor=d),typeof o.padding=="string"&&o.padding&&(r.padding=o.padding),r}const $8=/^\s*\$t:(custom\.[a-zA-Z0-9._-]+)\s*$/,E8=/^\s*\$t:([a-zA-Z0-9._-]+)\s*$/,I8=/\{\{.*?\}\}/;function wh(e,t,n){const o=e?.text;if(typeof o!="string")return{display:"",editable:!1,isKey:!1};const r=mt(o);if(r&&r.key.startsWith("custom.")){let a="";try{const l=Pt.getInstance().translate(r.key,{templateId:t,locale:n});a=l&&l!==r.key?l:""}catch{a=""}return{display:a,editable:!0,isKey:!0}}if(I8.test(o))return{display:o,editable:!1,isKey:!1};const s=E8.exec(o);if(s){const a=s[1];let l="";try{const d=Pt.getInstance().translate(a,{templateId:t,locale:n});l=d&&d!==a?d:""}catch{l=""}return{display:l,editable:!0,isKey:!0}}return{display:o,editable:!0,isKey:!1}}function dl(e){const t=er(e);return t===null?{node:null,path:null}:{node:_i(e,t),path:t}}function A8(e){if(!e||typeof e.text!="string")return null;const t=$8.exec(e.text);if(t)return t[1];const n=mt(e.text);return n&&n.key.startsWith("custom.")?n.key:null}function T8({node:e,params:t,t:n,onPatchNode:o,templateIdentifier:r,candidates:s}){const{state:a}=Je(),l=a.selectedRoute?.layoutName??null,d=a.locale,c=r??a.templateIdentifier,p=u.useMemo(()=>t&&typeof t=="object"?t:null,[t]);u.useMemo(()=>ht(p),[p]);const f=u.useMemo(()=>Be(e,p),[e,p]),y=u.useMemo(()=>{const q=p?.cellBorder;return q&&typeof q=="object"?q:null},[p]),g=u.useMemo(()=>{const q=p?.cellBackground;return q&&typeof q=="object"?q:null},[p]),m=u.useMemo(()=>{const q=p?.cellPadding;return q&&typeof q=="object"?q:null},[p]),[h,v]=u.useState(null),[b,x]=u.useState(null),[k,w]=u.useState({}),[_,C]=u.useState(!1),[E,S]=u.useState(null),[T,$]=u.useState(null),[A,z]=u.useState("light"),D=u.useCallback(q=>o(q),[o]),O=u.useMemo(()=>h?Ue(f,h.r,h.c):null,[f,h]),M=T!==null?T:h?.c??null,B=E!==null?E:h?.r??null,N=u.useMemo(()=>{const q=(y?.sides??[]).find($e=>$e.value==="all")??(y?.sides??[])[0],ae=(y?.widths??[]).find($e=>$e.value!=="none");if(!q||!ae)return[];const pe=ae.suffix??"";return[pe?`${q.prefix}${pe}`:q.prefix]},[y]),H=u.useCallback((q,ae,pe)=>{if(N.length===0)return q;const $e=(y?.sides??[]).map(J=>J.prefix),be=Ue(Be(q,p),ae,pe),oe=(typeof be?.cell?.props?.className=="string"?be.cell.props.className:"").split(/\s+/).filter(Boolean);return oe.some(J=>$e.some(le=>J===le||J.startsWith(le+"-")&&/^-?\d+$/.test(J.slice(le.length+1))))?q:Ci(q,p,ae,pe,[...oe,...N].join(" ").trim())},[N,y,p]),L=u.useCallback(q=>{if(!h)return;const ae=Math.min(h.r,b?.r??h.r),pe=Math.max(h.r,b?.r??h.r),$e=Math.min(h.c,b?.c??h.c),be=Math.max(h.c,b?.c??h.c),j=new Set,oe=[];for(let J=ae;J<=pe;J++)for(let le=$e;le<=be;le++)j.add(`${J}:${le}`),oe.push({r:J,c:le});let ue=e;for(const J of oe){if(ue=H(ue,J.r,J.c),ue=Jt(ue,p,J.r,J.c,"borderColor",q),J.r>0&&!j.has(`${J.r-1}:${J.c}`)){const le=Ue(Be(ue,p),J.r-1,J.c);le&&(ue=Jt(ue,p,le.gridRow,le.gridCol,"borderBottomColor",q))}if(J.c>0&&!j.has(`${J.r}:${J.c-1}`)){const le=Ue(Be(ue,p),J.r,J.c-1);le&&(ue=Jt(ue,p,le.gridRow,le.gridCol,"borderRightColor",q))}}D(ue)},[h,b,e,p,D,H]),I=u.useCallback(q=>L(q),[L]),P=u.useMemo(()=>(y?.colors??[]).map(q=>q.token).filter(Boolean),[y]),F=u.useCallback(q=>{if(!h||P.length===0)return;const ae=Math.min(h.r,b?.r??h.r),pe=Math.max(h.r,b?.r??h.r),$e=Math.min(h.c,b?.c??h.c),be=Math.max(h.c,b?.c??h.c);let j=e;for(let oe=ae;oe<=pe;oe++)for(let ue=$e;ue<=be;ue++)j=H(j,oe,ue),j=go(j,p,oe,ue,q,P,A);D(j)},[h,b,e,p,D,H,P,A]),G=u.useMemo(()=>{if(A==="dark")return"";const q=O?.cell.props?.style;return typeof q?.borderColor=="string"?q.borderColor:""},[O,A]),V=u.useCallback((q,ae)=>{if(!h)return;const pe=Math.min(h.r,b?.r??h.r),$e=Math.max(h.r,b?.r??h.r),be=Math.min(h.c,b?.c??h.c),j=Math.max(h.c,b?.c??h.c);let oe=e;for(let ue=pe;ue<=$e;ue++)for(let J=be;J<=j;J++)oe=Jt(oe,p,ue,J,q,ae);D(oe)},[h,b,e,p,D]),Y=u.useMemo(()=>(g?.colors??[]).map(q=>q.token).filter(q=>!!q),[g]),Z=u.useCallback(()=>h?{r0:Math.min(h.r,b?.r??h.r),r1:Math.max(h.r,b?.r??h.r),c0:Math.min(h.c,b?.c??h.c),c1:Math.max(h.c,b?.c??h.c)}:null,[h,b]),se=u.useCallback(q=>{const ae=Z();if(!ae||Y.length===0)return;let pe=e;for(let $e=ae.r0;$e<=ae.r1;$e++)for(let be=ae.c0;be<=ae.c1;be++)pe=go(pe,p,$e,be,q,Y,A);D(pe)},[Z,e,p,D,Y,A]),re=u.useCallback(q=>V("backgroundColor",q),[V]),U=u.useCallback(()=>{const q=Z();if(!q)return;let ae=e;for(let pe=q.r0;pe<=q.r1;pe++)for(let $e=q.c0;$e<=q.c1;$e++)ae=go(ae,p,pe,$e,void 0,Y,A),A==="light"&&(ae=Jt(ae,p,pe,$e,"backgroundColor",void 0));D(ae)},[Z,e,p,D,Y,A]),ee=u.useCallback(q=>V("padding",q),[V]),fe=u.useMemo(()=>{if(A==="dark")return"";const q=O?.cell.props?.style;return typeof q?.backgroundColor=="string"?q.backgroundColor:""},[O,A]),K=u.useMemo(()=>typeof O?.cell.props?.className=="string"?O.cell.props.className:"",[O]),ne=u.useMemo(()=>{const q=O?.cell.props?.style;return typeof q?.padding=="string"?q.padding:""},[O]),me=u.useCallback(q=>q==="section"?n("layout_editor.table_editor.move_blocked_section"):"",[n]),Ce=u.useCallback((q,ae)=>xi(f,q,ae),[f]),ze=u.useCallback((q,ae)=>wi(f,q,ae),[f]),Se=u.useCallback(q=>D(nl(e,p,q)),[e,p,D]),qe=u.useCallback(q=>{D(Rg(e,p,q)),v(null),x(null)},[e,p,D]),De=u.useCallback((q,ae)=>D(eh(e,p,q,ae)),[e,p,D]),Pe=u.useCallback(q=>D(nh(e,p,q)),[e,p,D]),Qe=u.useCallback(q=>{D(oh(e,p,q)),v(null),x(null)},[e,p,D]),Me=u.useCallback((q,ae)=>D(th(e,p,q,ae)),[e,p,D]),Re=u.useCallback(()=>{if(!h||!b)return;const q=ol(e,p,h.r,h.c,b.r,b.c);q.ok&&(D(q.table),v({r:Math.min(h.r,b.r),c:Math.min(h.c,b.c)}),x(null))},[e,p,h,b,D]),ve=u.useCallback(()=>{h&&(D(rh(e,p,h.r,h.c)),x(null))},[e,p,h,D]),te=u.useCallback(q=>{if(!h)return;const ae=Math.min(h.r,b?.r??h.r),pe=Math.max(h.r,b?.r??h.r),$e=Math.min(h.c,b?.c??h.c),be=Math.max(h.c,b?.c??h.c);let j=e;for(let oe=ae;oe<=pe;oe++)for(let ue=$e;ue<=be;ue++)j=Ci(j,p,oe,ue,q);D(j)},[e,p,h,b,D]),he=u.useCallback(async(q,ae)=>{const pe=`${q}:${ae}`,$e=k[pe];if($e===void 0)return;const be=Ue(f,q,ae);if(!be)return;const{node:j,path:oe}=dl(be.cell);if(oe===null)return;const ue=wh(j,c,d);if(ue.editable){if($e===ue.display){w(J=>{const le={...J};return delete le[pe],le});return}C(!0);try{const J=A8(j);if(J)await yr(c,J,d,$e),await tn(c,d);else{const le=await qn(c,l,d,$e);if(le.kind==="ok"&&le.resource){const Ie=`$t:${le.resource.translation_key}`;if(oe.length===0)D(ih(e,p,q,ae,Ie));else{const dt=tr(be.cell,oe,Ie);D(sh(e,p,q,ae,dt))}await tn(c,d)}}}finally{C(!1),w(J=>{const le={...J};return delete le[pe],le})}}},[k,f,c,d,l,e,p,D]),Q=u.useMemo(()=>{if(!O)return null;const{node:q,path:ae}=dl(O.cell);return ae===null?null:{value:typeof q?.text=="string"?q.text:"",editable:!0}},[O]),ie=u.useCallback(q=>{if(typeof q!="string"||q.length===0||!h)return;const ae=Ue(f,h.r,h.c);if(!ae)return;const pe=er(ae.cell);if(pe!==null)if(pe.length===0)D(ih(e,p,h.r,h.c,q));else{const $e=tr(ae.cell,pe,q);D(sh(e,p,h.r,h.c,$e))}},[h,f,e,p,D]),_e=u.useCallback((q,ae,pe)=>{pe?x({r:q,c:ae}):(v({r:q,c:ae}),x(null))},[]),ge=u.useMemo(()=>Array.from({length:f.colCount},(q,ae)=>ae),[f.colCount]),Ae=!!(h&&b&&(h.r!==b.r||h.c!==b.c)),Ne=!!(O&&(O.colSpan>1||O.rowSpan>1)),Le=O&&typeof O.cell.props?.className=="string"?O.cell.props.className:"";return i.jsxs("div",{className:"g7le-node-editor g7le-node-editor--table","data-testid":"g7le-table-editor",style:D8,children:[i.jsx("div",{style:N8,children:n("layout_editor.table_editor.title")}),i.jsx("div",{style:{overflowX:"auto"},children:i.jsxs("table",{"data-testid":"g7le-table-editor-grid",style:z8,children:[i.jsx("thead",{children:i.jsxs("tr",{children:[i.jsx("th",{style:M8}),ge.map(q=>{const ae=ze(q,-1),pe=ze(q,1),$e=M===q;return i.jsx("th",{style:L8,"data-testid":`g7le-table-colgutter-${q}`,onMouseEnter:()=>$(q),onMouseLeave:()=>$(be=>be===q?null:be),children:i.jsxs("div",{style:{...O8,visibility:$e?"visible":"hidden"},children:[i.jsx("button",{type:"button",title:ae.ok?n("layout_editor.table_editor.move_col_left"):me(ae.reason)||n("layout_editor.table_editor.move_col_left"),disabled:!ae.ok||_,onClick:()=>Me(q,-1),"data-testid":`g7le-table-col-left-${q}`,style:ae.ok?vn:$i,children:"←"}),i.jsx("button",{type:"button",title:n("layout_editor.table_editor.add_col"),disabled:_,onClick:()=>Pe(q),"data-testid":`g7le-table-col-add-${q}`,style:vn,children:"+"}),i.jsx("button",{type:"button",title:n("layout_editor.table_editor.remove_col"),disabled:f.colCount<=1||_,onClick:()=>Qe(q),"data-testid":`g7le-table-col-remove-${q}`,style:kh,children:"✕"}),i.jsx("button",{type:"button",title:pe.ok?n("layout_editor.table_editor.move_col_right"):me(pe.reason)||n("layout_editor.table_editor.move_col_right"),disabled:!pe.ok||_,onClick:()=>Me(q,1),"data-testid":`g7le-table-col-right-${q}`,style:pe.ok?vn:$i,children:"→"})]})},q)})]})}),i.jsx("tbody",{children:f.rows.map((q,ae)=>{const pe=q.cells[0]?.gridRow??ae,$e=B===pe;return i.jsxs("tr",{"data-testid":`g7le-table-row-${pe}`,onMouseEnter:()=>S(pe),onMouseLeave:()=>S(be=>be===pe?null:be),children:[i.jsx("td",{style:P8,"data-testid":`g7le-table-rowgutter-${pe}`,children:(()=>{const be=Ce(pe,-1),j=Ce(pe,1);return i.jsxs("div",{style:{...B8,visibility:$e?"visible":"hidden"},children:[i.jsx("button",{type:"button",title:be.ok?n("layout_editor.table_editor.move_row_up"):me(be.reason)||n("layout_editor.table_editor.move_row_up"),disabled:!be.ok||_,onClick:()=>De(pe,-1),"data-testid":`g7le-table-row-up-${pe}`,style:be.ok?vn:$i,children:"↑"}),i.jsx("button",{type:"button",title:n("layout_editor.table_editor.add_row"),disabled:_,onClick:()=>Se(pe),"data-testid":`g7le-table-row-add-${pe}`,style:vn,children:"+"}),i.jsx("button",{type:"button",title:n("layout_editor.table_editor.remove_row"),disabled:f.rows.length<=1||_,onClick:()=>qe(pe),"data-testid":`g7le-table-row-remove-${pe}`,style:kh,children:"✕"}),i.jsx("button",{type:"button",title:j.ok?n("layout_editor.table_editor.move_row_down"):me(j.reason)||n("layout_editor.table_editor.move_row_down"),disabled:!j.ok||_,onClick:()=>De(pe,1),"data-testid":`g7le-table-row-down-${pe}`,style:j.ok?vn:$i,children:"↓"})]})})()}),q.cells.map(be=>{const j=`${be.gridRow}:${be.gridCol}`,{node:oe,path:ue}=dl(be.cell),J=wh(oe,c,d),le=ue!==null&&J.editable,Ie=ue===null,dt=k[j],pt=dt!==void 0?dt:J.display,ot=h&&h.r===be.gridRow&&h.c===be.gridCol,Oe=h&&b&&be.gridRow>=Math.min(h.r,b.r)&&be.gridRow<=Math.max(h.r,b.r)&&be.gridCol>=Math.min(h.c,b.c)&&be.gridCol<=Math.max(h.c,b.c);return i.jsx("td",{colSpan:be.colSpan,rowSpan:be.rowSpan,"data-testid":`g7le-table-cell-${be.gridRow}-${be.gridCol}`,onClick:He=>_e(be.gridRow,be.gridCol,He.shiftKey),style:{...W8,...S8(be.cell,y,A),...C8(be.cell,g,A),...be.isHeader?j8:{},...ot?H8:{},...Oe&&!ot?F8:{}},children:le?i.jsx("input",{type:"text","data-testid":`g7le-table-cell-input-${be.gridRow}-${be.gridCol}`,value:pt,placeholder:n("layout_editor.table_editor.cell_text"),disabled:_,onMouseDown:He=>{He.shiftKey&&He.preventDefault(),_e(be.gridRow,be.gridCol,He.shiftKey)},onClick:He=>He.stopPropagation(),onChange:He=>w(Ye=>({...Ye,[j]:He.target.value})),onBlur:()=>{he(be.gridRow,be.gridCol)},style:K8}):Ie?i.jsx("span",{"data-testid":`g7le-table-cell-struct-${be.gridRow}-${be.gridCol}`,style:Sh,children:n("layout_editor.table_editor.structural_cell")}):i.jsx("span",{style:Sh,children:J.display})},j)})]},ae)})})]})}),i.jsxs("button",{type:"button","data-testid":"g7le-table-add-row-bottom",onClick:()=>Se(f.rows.length-1),disabled:_,style:V8,children:["+ ",n("layout_editor.table_editor.add_row")]}),i.jsxs("div",{style:U8,"data-testid":"g7le-table-cell-tools",children:[i.jsx("button",{type:"button","data-testid":"g7le-table-merge",onClick:Re,disabled:!Ae||_,style:Ch,children:n("layout_editor.table_editor.merge_cells")}),i.jsx("button",{type:"button","data-testid":"g7le-table-unmerge",onClick:ve,disabled:!Ne||_,style:Ch,children:n("layout_editor.table_editor.unmerge_cells")})]}),O&&Q&&i.jsxs("div",{style:G8,"data-testid":"g7le-table-cell-i18n-section",children:[i.jsx("div",{style:Y8,children:n("layout_editor.table_editor.cell_i18n_label")}),i.jsx(vt,{value:Q.value,onChange:ie,t:n,placeholder:n("layout_editor.table_editor.cell_text"),testidPrefix:"g7le-table-cell-i18n",candidates:s,enableExpressionTree:!0,expressionTreeCollapsible:!0})]}),O&&i.jsxs("div",{style:q8,"data-testid":"g7le-table-cell-color-section",children:[i.jsx(yh,{colorScheme:A,onChange:z,t:n,disabled:_}),y&&i.jsx("div",{style:cl,"data-testid":"g7le-table-cell-border-row",children:i.jsx(dh,{className:Le,catalog:y,t:n,onChange:te,colorScheme:A,onPresetToken:F,colorStyle:G,onColorStyle:I,disabled:_})}),i.jsx("div",{style:cl,"data-testid":"g7le-table-cell-fill-row",children:i.jsx(fh,{colorStyle:fe,className:K,catalog:g,t:n,colorScheme:A,onPresetToken:se,onCustomColor:re,onClear:U,disabled:_})})]}),O&&i.jsx("div",{style:cl,"data-testid":"g7le-table-cell-padding-row",children:i.jsx(gh,{paddingStyle:ne,catalog:m,t:n,onChange:ee,disabled:_})}),O&&!y&&i.jsxs("label",{style:X8,"data-testid":"g7le-table-cell-border-row",children:[i.jsx("span",{style:J8,children:n("layout_editor.table_editor.cell_border")}),i.jsx("input",{type:"text","data-testid":"g7le-table-cell-border-input",value:Le,placeholder:n("layout_editor.table_editor.cell_class_placeholder"),onChange:q=>te(q.target.value),disabled:_,style:Z8})]}),!f.valid&&i.jsx("div",{"data-testid":"g7le-table-grid-warning",style:Q8,children:n("layout_editor.table_editor.grid_invalid")}),i.jsx("div",{style:R8,children:n("layout_editor.table_editor.select_hint")})]})}const D8={display:"flex",flexDirection:"column",gap:8,width:"100%",marginBottom:12},N8={fontSize:12,fontWeight:700,color:"#0f172a"},z8={borderCollapse:"collapse",width:"auto"},M8={width:28,background:"transparent",border:"none"},L8={padding:2,border:"none",background:"transparent"},P8={padding:2,border:"none",background:"transparent",verticalAlign:"middle"},O8={display:"flex",gap:2,justifyContent:"center"},B8={display:"grid",gridTemplateColumns:"repeat(2, 16px)",gap:2,justifyContent:"center"},vn={width:16,height:16,lineHeight:"14px",padding:0,fontSize:10,border:"1px solid #cbd5e1",borderRadius:4,background:"#fff",color:"#475569",cursor:"pointer"},kh={...vn,border:"1px solid #fecaca",color:"#dc2626"},$i={...vn,cursor:"not-allowed",opacity:.4,color:"#94a3b8",borderColor:"#e2e8f0"},W8={border:"1px solid #cbd5e1",padding:0,width:64,minWidth:64,maxWidth:120,height:24,background:"#fff",cursor:"pointer"},j8={background:"#f1f5f9",fontWeight:600},H8={outline:"2px solid #2563eb",outlineOffset:-2},F8={background:"#dbeafe"},K8={width:"100%",boxSizing:"border-box",padding:"2px 5px",fontSize:11,height:22,lineHeight:"18px",border:"none",background:"transparent",outline:"none"},Sh={display:"block",padding:"2px 5px",fontSize:10,color:"#64748b",fontStyle:"italic",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",maxWidth:110},V8={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},U8={display:"flex",gap:6},Ch={padding:"4px 8px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},q8={display:"flex",flexDirection:"column",gap:8,borderTop:"1px solid #f1f5f9",paddingTop:8},G8={display:"flex",flexDirection:"column",gap:6,borderTop:"1px solid #f1f5f9",paddingTop:8},Y8={fontSize:12,fontWeight:700,color:"#0f172a"},cl={display:"flex",flexDirection:"column",gap:6},X8={display:"flex",alignItems:"center",gap:6},J8={fontSize:12,color:"#475569",minWidth:60},Z8={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},Q8={fontSize:11,color:"#b45309",background:"#fffbeb",border:"1px solid #fde68a",borderRadius:6,padding:"4px 6px"},R8={fontSize:11,color:"#94a3b8"},ez=/\{\{.*?\}\}/;function tz(e,t,n){const r=(e.props??{})[t];return Array.isArray(r)?r:r===void 0&&n?JSON.parse(JSON.stringify(n)):[]}function nz(e){return typeof e=="string"&&ez.test(e)}function ul(e,t,n){return e?e.startsWith("$t:")?t(e.slice(3)):e:n}function oz(e,t,n){return typeof e=="object"&&e!==null?e[t.key]:n?e:void 0}function rz(e,t,n,o){if(typeof e=="object"&&e!==null){const r={...e};return o===void 0?delete r[t.key]:r[t.key]=o,r}return n?o:{[t.key]:o}}function $h({node:e,params:t,t:n,onPatchNode:o,templateIdentifier:r,candidates:s}){const a=typeof t?.arrayProp=="string"?t.arrayProp:null,l=Array.isArray(t?.fields)?t.fields:[],d=ul(typeof t?.itemLabel=="string"?t.itemLabel:void 0,n,n("layout_editor.array_editor.item")),c=t?.newItem,p=c&&typeof c=="object"?c:null,f=typeof c=="string"||typeof c=="number"?c:null,y=(l.find(C=>C.primary)??l[0])?.key,g=(e.props??{})[a??""],m=Array.isArray(t?.defaultItems)?t.defaultItems:null,h=a?tz(e,a,m):[],v=u.useCallback(C=>{if(!a)return;const E={...e.props??{}};E[a]=C,o({...e,props:E})},[a,e,o]),b=u.useCallback(()=>{if(p)return JSON.parse(JSON.stringify(p));if(f!==null)return f;const C={};for(const E of l)(E.widget??"text")==="boolean"?C[E.key]=!1:C[E.key]="";return C},[p,f,l]),x=u.useCallback(()=>{v([...h,b()])},[v,h,b]),k=u.useCallback(C=>{v(h.filter((E,S)=>S!==C))},[v,h]),w=u.useCallback((C,E)=>{const S=C+E;if(S<0||S>=h.length)return;const T=[...h];[T[C],T[S]]=[T[S],T[C]],v(T)},[v,h]),_=u.useCallback((C,E,S)=>{const T=E.key===y,$=h.map((A,z)=>z===C?rz(A,E,T,S):A);v($)},[h,v,y]);return a?nz(g)||g!==void 0&&!Array.isArray(g)?i.jsx("div",{className:"g7le-node-editor g7le-node-editor--array","data-testid":"g7le-array-editor-bound",style:fz,children:n("layout_editor.array_editor.bound_degraded")}):i.jsxs("div",{className:"g7le-node-editor g7le-node-editor--array","data-testid":"g7le-array-editor",style:iz,children:[i.jsx("div",{style:sz,children:n("layout_editor.array_editor.items_title")}),h.length===0&&i.jsx("div",{"data-testid":"g7le-array-empty",style:Ih,children:n("layout_editor.array_editor.empty")}),h.map((C,E)=>i.jsxs("div",{"data-testid":`g7le-array-row-${E}`,style:az,children:[i.jsxs("div",{style:lz,children:[i.jsxs("span",{style:dz,children:["#",E+1]}),i.jsx("div",{style:{flex:1}}),i.jsx("button",{type:"button","data-testid":`g7le-array-up-${E}`,title:n("layout_editor.array_editor.move_up"),disabled:E===0,onClick:()=>w(E,-1),style:Eh,children:"↑"}),i.jsx("button",{type:"button","data-testid":`g7le-array-down-${E}`,title:n("layout_editor.array_editor.move_down"),disabled:E===h.length-1,onClick:()=>w(E,1),style:Eh,children:"↓"}),i.jsx("button",{type:"button","data-testid":`g7le-array-remove-${E}`,title:n("layout_editor.array_editor.remove"),onClick:()=>k(E),style:uz,children:"✕"})]}),l.map(S=>{const T=S.widget??"text",$=S.key===y,A=ul(S.label,n,S.key),z=oz(C,S,$),D=`g7le-array-field-${E}-${S.key}`;if(T==="boolean")return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"checkbox","data-testid":D,checked:z===!0,onChange:M=>_(E,S,M.target.checked)})]},S.key);if(T==="select"){const M=Array.isArray(S.options)?S.options:[];return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsxs("select",{"data-testid":D,value:z==null?"":String(z),onChange:B=>_(E,S,B.target.value===""?void 0:B.target.value),style:or,children:[i.jsx("option",{value:"",children:"—"}),M.map((B,N)=>i.jsx("option",{value:String(B.value),children:ul(B.label,n,String(B.value))},N))]})]},S.key)}if(T==="i18n-text"){const M=typeof z=="string"?z:z==null?"":String(z);return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("div",{"data-testid":D,style:{flex:1,minWidth:0},children:i.jsx(vt,{value:M,onChange:B=>_(E,S,B===""?void 0:B),t:n,placeholder:A,testidPrefix:`${D}-i18n`,candidates:s,enableExpressionTree:!0,expressionTreeCollapsible:!0})})]},S.key)}if(T==="number"){const M=z==null?"":String(z);return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"number","data-testid":D,value:M,onChange:B=>{const N=B.target.value;_(E,S,N===""?void 0:Number(N))},style:or})]},S.key)}if(T==="color"){const M=typeof z=="string"?z:"",B=/^#[0-9a-fA-F]{6}$/.test(M)?M:"#000000";return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"color","data-testid":`${D}-swatch`,value:B,onChange:N=>_(E,S,N.target.value),style:cz}),i.jsx("input",{type:"text","data-testid":D,value:M,placeholder:"#7C3AED",onChange:N=>_(E,S,N.target.value===""?void 0:N.target.value),style:or})]},S.key)}if(T==="number-list"){const M=Array.isArray(z)?z.join(", "):"";return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"text","data-testid":D,value:M,placeholder:n("layout_editor.array_editor.number_list_placeholder"),onChange:B=>{const N=B.target.value.split(",").map(H=>H.trim()).filter(H=>H!=="").map(H=>Number(H)).filter(H=>!Number.isNaN(H));_(E,S,N)},style:or})]},S.key)}const O=z==null?"":String(z);return i.jsxs("label",{style:Wn,children:[i.jsx("span",{style:jn,children:A}),i.jsx("input",{type:"text","data-testid":D,value:O,placeholder:T==="icon"?n("layout_editor.array_editor.icon_placeholder"):A,onChange:M=>_(E,S,M.target.value===""?void 0:M.target.value),style:or})]},S.key)})]},E)),i.jsx("button",{type:"button","data-testid":"g7le-array-add",onClick:x,style:pz,children:n("layout_editor.array_editor.add",{item:d})})]}):i.jsx("div",{className:"g7le-node-editor g7le-node-editor--array","data-testid":"g7le-array-editor-misconfigured",style:Ih,children:n("layout_editor.array_editor.no_array_prop")})}const iz={display:"flex",flexDirection:"column",gap:8,width:"100%",marginBottom:12},sz={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:2},az={display:"flex",flexDirection:"column",gap:4,padding:8,border:"1px solid #e2e8f0",borderRadius:8,background:"#f8fafc"},lz={display:"flex",gap:4,alignItems:"center"},dz={fontSize:11,fontWeight:700,color:"#64748b"},Wn={display:"flex",flexWrap:"wrap",gap:6,alignItems:"center"},jn={fontSize:11,color:"#475569",minWidth:64,flexShrink:0},or={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},cz={width:32,height:28,padding:0,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",cursor:"pointer",flexShrink:0},Eh={padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},uz={padding:"2px 6px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},pz={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},Ih={fontSize:11,color:"#94a3b8",fontStyle:"italic"},fz={fontSize:11,color:"#b45309",fontStyle:"italic",padding:"4px 2px"};function gz(e,t){return e?e.startsWith("$t:")?t(e.slice(3)):e:null}function hz(e){const{params:t,t:n}=e,o=Array.isArray(t?.groups)?t.groups:[];return o.length===0?i.jsx("div",{className:"g7le-node-editor g7le-node-editor--array-group","data-testid":"g7le-array-group-misconfigured",style:vz,children:n("layout_editor.array_editor.no_array_prop")}):i.jsx("div",{className:"g7le-node-editor g7le-node-editor--array-group","data-testid":"g7le-array-group-editor",style:yz,children:o.map((r,s)=>{const a=gz(r.title,n),{title:l,...d}=r;return i.jsxs("div",{"data-testid":`g7le-array-group-${r.arrayProp??s}`,style:bz,children:[a&&i.jsx("div",{style:mz,children:a}),i.jsx($h,{...e,params:d})]},r.arrayProp??s)})})}const yz={display:"flex",flexDirection:"column",gap:16,width:"100%",marginBottom:12},bz={display:"flex",flexDirection:"column",gap:4},mz={fontSize:12,fontWeight:700,color:"#1e293b",borderBottom:"1px solid #e2e8f0",paddingBottom:4},vz={fontSize:11,color:"#94a3b8",fontStyle:"italic"},_z=/\{\{.*?\}\}/;function xz(e){return typeof e=="string"&&_z.test(e)}function wz(e,t,n){return e?e.startsWith("$t:")?t(e.slice(3)):e:n}function kz(e){const{node:t,params:n,t:o,onPatchNode:r}=e,s=typeof n?.arrayProp=="string"?n.arrayProp:null,a=typeof n?.idField=="string"?n.idField:"id",l=typeof n?.cellChildrenProp=="string"?n.cellChildrenProp:"cellChildren",d=typeof n?.cellChildComponent=="string"?n.cellChildComponent:"Div",c=wz(typeof n?.itemLabel=="string"?n.itemLabel:void 0,o,o("layout_editor.array_editor.item")),[p,f]=u.useState(null),y=s?(t.props??{})[s]:void 0,g=Array.isArray(y)?y:[],m=u.useCallback(C=>{if(!s)return;const E={...t.props??{}};E[s]=C,r({...t,props:E})},[s,t,r]),h=u.useCallback(()=>{const C=n?.newItem;return C&&typeof C=="object"?JSON.parse(JSON.stringify(C)):{[a]:"",[l]:[]}},[n,a,l]),v=u.useCallback(()=>{m([...g,h()])},[m,g,h]),b=u.useCallback(C=>{m(g.filter((E,S)=>S!==C)),f(null)},[m,g]),x=u.useCallback((C,E)=>{const S=C+E;if(S<0||S>=g.length)return;const T=[...g];[T[C],T[S]]=[T[S],T[C]],m(T)},[m,g]),k=u.useCallback((C,E)=>{const S=g.map((T,$)=>$===C?{...T,[a]:E}:T);m(S)},[g,m,a]),w=u.useCallback(C=>({type:"composite",name:"CardGridCell",children:Array.isArray(C[l])?C[l]:[]}),[l]),_=u.useCallback(C=>E=>{const S=Array.isArray(E.children)?E.children:[],T=g.map(($,A)=>A===C?{...$,[l]:S}:$);m(T)},[g,m,l]);return s?xz(y)||y!==void 0&&!Array.isArray(y)?i.jsx("div",{className:"g7le-node-editor g7le-node-editor--cell-tree","data-testid":"g7le-cell-tree-bound",style:Mz,children:o("layout_editor.array_editor.bound_degraded")}):i.jsxs("div",{className:"g7le-node-editor g7le-node-editor--cell-tree","data-testid":"g7le-cell-tree-editor",style:Sz,children:[i.jsx("div",{style:Cz,children:o("layout_editor.cell_tree_editor.columns_title")}),g.length===0&&i.jsx("div",{"data-testid":"g7le-cell-tree-empty",style:Th,children:o("layout_editor.array_editor.empty")}),g.map((C,E)=>{const S=typeof C[a]=="string"?C[a]:"",T=p===E;return i.jsxs("div",{"data-testid":`g7le-cell-tree-row-${E}`,style:$z,children:[i.jsxs("div",{style:Ez,children:[i.jsxs("span",{style:Iz,children:["#",E+1]}),i.jsx("input",{type:"text","data-testid":`g7le-cell-tree-id-${E}`,value:S,placeholder:o("layout_editor.cell_tree_editor.id_placeholder"),onChange:$=>k(E,$.target.value),style:Az}),i.jsx("button",{type:"button","data-testid":`g7le-cell-tree-up-${E}`,title:o("layout_editor.array_editor.move_up"),disabled:E===0,onClick:()=>x(E,-1),style:Ah,children:"↑"}),i.jsx("button",{type:"button","data-testid":`g7le-cell-tree-down-${E}`,title:o("layout_editor.array_editor.move_down"),disabled:E===g.length-1,onClick:()=>x(E,1),style:Ah,children:"↓"}),i.jsx("button",{type:"button","data-testid":`g7le-cell-tree-remove-${E}`,title:o("layout_editor.array_editor.remove"),onClick:()=>b(E),style:Tz,children:"✕"})]}),i.jsx("button",{type:"button","data-testid":`g7le-cell-tree-toggle-${E}`,onClick:()=>f(T?null:E),style:Dz,children:o(T?"layout_editor.cell_tree_editor.collapse_cells":"layout_editor.cell_tree_editor.expand_cells")}),T&&i.jsx("div",{"data-testid":`g7le-cell-tree-cells-${E}`,style:Nz,children:i.jsx(qg,{...e,node:w(C),params:{childComponent:d},onPatchNode:_(E)})})]},E)}),i.jsx("button",{type:"button","data-testid":"g7le-cell-tree-add",onClick:v,style:zz,children:o("layout_editor.cell_tree_editor.add_column",{item:c})})]}):i.jsx("div",{className:"g7le-node-editor g7le-node-editor--cell-tree","data-testid":"g7le-cell-tree-misconfigured",style:Th,children:o("layout_editor.array_editor.no_array_prop")})}const Sz={display:"flex",flexDirection:"column",gap:8,width:"100%",marginBottom:12},Cz={fontSize:12,fontWeight:700,color:"#0f172a",marginBottom:2},$z={display:"flex",flexDirection:"column",gap:6,padding:8,border:"1px solid #e2e8f0",borderRadius:8,background:"#f8fafc"},Ez={display:"flex",gap:4,alignItems:"center"},Iz={fontSize:11,fontWeight:700,color:"#64748b",flexShrink:0},Az={flex:1,minWidth:0,padding:"4px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6},Ah={padding:"2px 6px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"},Tz={padding:"2px 6px",fontSize:12,border:"1px solid #fecaca",borderRadius:6,background:"#fff",color:"#dc2626",cursor:"pointer"},Dz={padding:"3px 8px",fontSize:11,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#2563eb",cursor:"pointer",alignSelf:"flex-start"},Nz={paddingLeft:8,borderLeft:"2px solid #e2e8f0"},zz={padding:"4px 8px",fontSize:12,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",alignSelf:"flex-start"},Th={fontSize:11,color:"#94a3b8",fontStyle:"italic"},Mz={fontSize:11,color:"#b45309",fontStyle:"italic",padding:"4px 2px"};function Lz(e,t,n){const o=Be(e,t);if(!n||n.length===0)return{measured:[],grid:o};const r=[];for(const s of o.rows)for(const a of s.cells){const d=tl(e,a,t).map(p=>`children.${p}`).join("."),c=n.find(p=>p.path===d||p.path.endsWith("."+d));c&&r.push({ref:a,box:{top:c.top,left:c.left,width:c.width,height:c.height}})}return{measured:r,grid:o}}const pl=26,fl=50,gl=6,Dh=44,Nh=18,zh="g7le-table-inplace-empty-cell-style";function Pz(){if(typeof document>"u"||document.getElementById(zh))return;const e=document.createElement("style");e.id=zh,e.textContent=".g7le-preview-frame td[data-editor-name],.g7le-preview-frame th[data-editor-name]{min-width:56px;height:38px;}.g7le-preview-frame table[data-editor-name]{min-width:120px;}",document.head.appendChild(e)}function Oz({node:e,params:t,nodeBox:n,cellBoxes:o,selectedCellPath:r,colorScheme:s,t:a,onPatchNode:l,onRequestInlineEdit:d}){const c=u.useMemo(()=>t&&typeof t=="object"?t:null,[t]),{measured:p,grid:f}=u.useMemo(()=>Lz(e,c,o),[e,c,o]),[y,g]=u.useState(null),[m,h]=u.useState(null),v=u.useMemo(()=>{if(!r)return null;for(const j of f.rows)for(const oe of j.cells){const ue=tl(e,oe,c).map(J=>`children.${J}`).join(".");if(r===ue||r.startsWith(ue+"."))return{r:oe.gridRow,c:oe.gridCol}}return null},[r,f,e,c]),b=u.useMemo(()=>y&&Ue(f,y.r,y.c)?y:v,[y,v,f]),[x,k]=u.useState(!1),[w,_]=u.useState(s==="dark"?"dark":"light"),[C,E]=u.useState(null),[S,T]=u.useState(null),$=u.useRef(null),A=u.useCallback(()=>{$.current!==null&&(clearTimeout($.current),$.current=null)},[]),z=u.useCallback(()=>{A(),$.current=setTimeout(()=>{E(null),T(null),$.current=null},240)},[A]);u.useEffect(()=>()=>A(),[A]),u.useEffect(()=>{Pz()},[]);const D=u.useCallback(j=>l(j),[l]),O=u.useMemo(()=>b?Ue(f,b.r,b.c):null,[f,b]),M=u.useMemo(()=>O&&typeof O.cell.props?.className=="string"?O.cell.props.className:"",[O]),B=u.useCallback(j=>D(nl(e,c,j)),[e,c,D]),N=u.useCallback(j=>D(Rg(e,c,j)),[e,c,D]),H=u.useCallback((j,oe)=>D(eh(e,c,j,oe)),[e,c,D]),L=u.useCallback(j=>D(nh(e,c,j)),[e,c,D]),I=u.useCallback(j=>D(oh(e,c,j)),[e,c,D]),P=u.useCallback((j,oe)=>D(th(e,c,j,oe)),[e,c,D]),F=u.useCallback(j=>{if(!O)return;const oe=O.gridRow,ue=O.gridCol,J=j==="down"?oe+O.rowSpan:oe+O.rowSpan-1,le=j==="right"?ue+O.colSpan:ue+O.colSpan-1;if(J>=f.rows.length||le>=f.colCount)return;const Ie=ol(e,c,oe,ue,J,le);Ie.ok&&D(Ie.table)},[O,f,e,c,D]),G=!!(O&&O.gridCol+O.colSpan!b||!m||!Ue(f,m.r,m.c)?null:{r0:Math.min(b.r,m.r),c0:Math.min(b.c,m.c),r1:Math.max(b.r,m.r),c1:Math.max(b.c,m.c)},[b,m,f]),Z=u.useMemo(()=>{if(!Y)return[];const j=new Set,oe=[];for(const ue of f.rows)for(const J of ue.cells)if(J.gridRow>=Y.r0&&J.gridRow<=Y.r1&&J.gridCol>=Y.c0&&J.gridCol<=Y.c1){const le=`${J.gridRow}:${J.gridCol}`;j.has(le)||(j.add(le),oe.push({r:J.gridRow,c:J.gridCol}))}return oe},[Y,f]),se=Z.length>1,re=u.useCallback(()=>{if(!Y)return;const j=ol(e,c,Y.r0,Y.c0,Y.r1,Y.c1);j.ok&&(D(j.table),h(null))},[Y,e,c,D]),U=u.useCallback(()=>{b&&D(rh(e,c,b.r,b.c))},[e,c,b,D]),ee=u.useMemo(()=>{const j=c?.cellBorder;return j&&typeof j=="object"?j:null},[c]),fe=u.useMemo(()=>{const j=c?.cellBackground;return j&&typeof j=="object"?j:null},[c]),K=u.useMemo(()=>{const j=c?.cellPadding;return j&&typeof j=="object"?j:null},[c]),ne=u.useMemo(()=>{if(x){const j=new Set,oe=[];for(const ue of f.rows)for(const J of ue.cells){const le=`${J.gridRow}:${J.gridCol}`;j.has(le)||(j.add(le),oe.push({r:J.gridRow,c:J.gridCol}))}return oe}return se?Z:b?[{r:b.r,c:b.c}]:[]},[x,se,Z,b,f]),me=u.useCallback(j=>{if(ne.length===0)return;let oe=e;for(const ue of ne){const J=(ee?.colors??[]).map(Ie=>Ie.token),le=j.split(/\s+/).filter(Ie=>Ie&&!J.includes(Ie)).join(" ");oe=Ci(oe,c,ue.r,ue.c,le)}D(oe)},[e,c,ne,ee,D]),Ce=u.useMemo(()=>{const j=(ee?.sides??[]).find(J=>J.value==="all")??(ee?.sides??[])[0],oe=(ee?.widths??[]).find(J=>J.value!=="none");if(!j||!oe)return[];const ue=oe.suffix??"";return[ue?`${j.prefix}${ue}`:j.prefix]},[ee]),ze=u.useCallback((j,oe,ue)=>{if(Ce.length===0)return j;const J=(ee?.sides??[]).map(Oe=>Oe.prefix),le=Ue(Be(j,c),oe,ue),dt=(typeof le?.cell?.props?.className=="string"?le.cell.props.className:"").split(/\s+/).filter(Boolean);if(dt.some(Oe=>J.some(He=>Oe===He||Oe.startsWith(He+"-")&&/^-?\d+$/.test(Oe.slice(He.length+1)))))return j;const ot=[...dt,...Ce].join(" ").trim();return Ci(j,c,oe,ue,ot)},[Ce,ee,c]),Se=u.useCallback((j,oe)=>{if(j.length===0)return;const ue=new Set(j.map(le=>`${le.r}:${le.c}`));let J=e;for(const le of j){if(J=ze(J,le.r,le.c),J=Jt(J,c,le.r,le.c,"borderColor",oe),le.r>0&&!ue.has(`${le.r-1}:${le.c}`)){const Ie=Ue(Be(J,c),le.r-1,le.c);Ie&&(J=Jt(J,c,Ie.gridRow,Ie.gridCol,"borderBottomColor",oe))}if(le.c>0&&!ue.has(`${le.r}:${le.c-1}`)){const Ie=Ue(Be(J,c),le.r,le.c-1);Ie&&(J=Jt(J,c,Ie.gridRow,Ie.gridCol,"borderRightColor",oe))}}D(J)},[e,c,D,ze]),qe=u.useMemo(()=>(ee?.colors??[]).map(j=>j.token).filter(Boolean),[ee]),De=u.useCallback(j=>{if(ne.length===0||qe.length===0)return;let oe=e;for(const ue of ne)oe=ze(oe,ue.r,ue.c),oe=go(oe,c,ue.r,ue.c,j,qe,w);D(oe)},[ne,e,c,D,ze,qe,w]),Pe=u.useCallback(j=>Se(ne,j),[Se,ne]),Qe=u.useMemo(()=>{if(w==="dark")return"";const j=O?.cell.props?.style;return typeof j?.borderColor=="string"?j.borderColor:""},[O,w]),Me=u.useCallback((j,oe)=>{if(ne.length===0)return;let ue=e;for(const J of ne)ue=Jt(ue,c,J.r,J.c,j,oe);D(ue)},[ne,e,c,D]),Re=u.useMemo(()=>(fe?.colors??[]).map(j=>j.token).filter(j=>!!j),[fe]),ve=u.useCallback(j=>{if(ne.length===0||Re.length===0)return;let oe=e;for(const ue of ne)oe=go(oe,c,ue.r,ue.c,j,Re,w);D(oe)},[ne,e,c,D,Re,w]),te=u.useCallback(j=>Me("backgroundColor",j),[Me]),he=u.useCallback(()=>{if(ne.length===0)return;let j=e;for(const oe of ne)j=go(j,c,oe.r,oe.c,void 0,Re,w),w==="light"&&(j=Jt(j,c,oe.r,oe.c,"backgroundColor",void 0));D(j)},[ne,e,c,D,Re,w]),Q=u.useCallback(j=>Me("padding",j),[Me]),ie=u.useMemo(()=>{if(w==="dark")return"";const j=O?.cell.props?.style;return typeof j?.backgroundColor=="string"?j.backgroundColor:""},[O,w]),_e=u.useMemo(()=>typeof O?.cell.props?.className=="string"?O.cell.props.className:"",[O]),ge=u.useMemo(()=>{const j=O?.cell.props?.style;return typeof j?.padding=="string"?j.padding:""},[O]),Ae=u.useCallback(j=>{const oe=j.currentTarget,ue=oe.style.pointerEvents;oe.style.pointerEvents="none";const J=document.elementFromPoint(j.clientX,j.clientY);oe.style.pointerEvents=ue;const le=J?.closest?.("[data-dnd-handle-path]");le&&le.dispatchEvent(new PointerEvent("pointerdown",{bubbles:!0,cancelable:!0,clientX:j.clientX,clientY:j.clientY,pointerId:j.pointerId,pointerType:j.pointerType,button:j.button,isPrimary:!0}))},[]),Ne=u.useMemo(()=>{const j=new Map;for(const oe of p)j.has(oe.ref.gridCol)||j.set(oe.ref.gridCol,oe.box);return j},[p]),Le=u.useMemo(()=>{const j=new Map;for(const oe of p)j.has(oe.ref.gridRow)||j.set(oe.ref.gridRow,oe.box);return j},[p]);if(p.length===0)return null;const q=!!(O&&(O.colSpan>1||O.rowSpan>1)),ae=S!==null?S:b?.c??null,pe=C!==null?C:b?.r??null,$e=n.top-pl-gl-Dh,be=n.left-fl-gl-Dh;return i.jsxs("div",{className:"g7le-table-inplace","data-testid":"g7le-table-inplace",style:{position:"absolute",inset:0,pointerEvents:"none",zIndex:g7},children:[p.map(j=>{const oe=b&&b.r===j.ref.gridRow&&b.c===j.ref.gridCol,ue=Y&&j.ref.gridRow>=Y.r0&&j.ref.gridRow<=Y.r1&&j.ref.gridCol>=Y.c0&&j.ref.gridCol<=Y.c1;return i.jsx("div",{"data-testid":`g7le-inplace-cell-${j.ref.gridRow}-${j.ref.gridCol}`,role:"button",tabIndex:-1,"aria-label":a("layout_editor.table_inplace.select_cell"),onMouseEnter:()=>{A(),E(j.ref.gridRow),T(j.ref.gridCol)},onMouseLeave:()=>{z()},onPointerDown:J=>Ae(J),onClick:J=>{if(J.stopPropagation(),J.shiftKey&&(y||b))h({r:j.ref.gridRow,c:j.ref.gridCol});else{g({r:j.ref.gridRow,c:j.ref.gridCol}),h(null);const le=tl(e,j.ref,c).map(Ie=>`children.${Ie}`).join(".");d?.(le)}},style:{position:"absolute",top:j.box.top,left:j.box.left,width:j.box.width,height:j.box.height,minWidth:Nh,minHeight:Nh,boxSizing:"border-box",pointerEvents:"auto",cursor:"pointer",outline:oe?"2px solid #2563eb":"none",outlineOffset:-2,background:ue&&!oe?"rgba(37,99,235,0.14)":"transparent"}},`cell-${j.ref.gridRow}-${j.ref.gridCol}`)}),i.jsx("div",{"data-testid":"g7le-inplace-col-rail",onMouseEnter:A,onMouseLeave:z,style:{position:"absolute",top:$e,left:n.left,width:n.width,height:pl,pointerEvents:"none"},children:ae!==null&&Ne.has(ae)&&(()=>{const j=ae,oe=Ne.get(j),ue=wi(f,j,-1),J=wi(f,j,1),le=oe.left-n.left;return i.jsxs("div",{"data-testid":`g7le-inplace-colgutter-${j}`,onMouseEnter:()=>{A(),T(j)},onMouseLeave:z,style:{position:"absolute",top:0,left:le,width:oe.width,minWidth:96,height:pl,display:"flex",gap:3,justifyContent:"center",alignItems:"center",pointerEvents:"auto"},children:[i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.move_col_left"),disabled:!ue.ok,onClick:()=>P(j,-1),"data-testid":`g7le-inplace-col-left-${j}`,style:ue.ok?_n:Ei,children:"←"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.add_col"),onClick:()=>L(j),"data-testid":`g7le-inplace-col-add-${j}`,style:_n,children:"+"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.remove_col"),disabled:f.colCount<=1,onClick:()=>I(j),"data-testid":`g7le-inplace-col-remove-${j}`,style:Mh,children:"✕"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.move_col_right"),disabled:!J.ok,onClick:()=>P(j,1),"data-testid":`g7le-inplace-col-right-${j}`,style:J.ok?_n:Ei,children:"→"})]},`colgut-${j}`)})()}),i.jsx("div",{"data-testid":"g7le-inplace-row-rail",style:{position:"absolute",top:n.top,left:be,width:fl,height:n.height,pointerEvents:"none"},children:pe!==null&&Le.has(pe)&&(()=>{const j=pe,oe=Le.get(j),ue=xi(f,j,-1),J=xi(f,j,1),le=oe.top-n.top;return i.jsxs("div",{"data-testid":`g7le-inplace-rowgutter-${j}`,onMouseEnter:()=>{A(),E(j)},onMouseLeave:z,style:{position:"absolute",top:le,left:0,width:fl,height:oe.height,minHeight:48,display:"grid",gridTemplateColumns:"repeat(2, 22px)",gridAutoRows:"22px",gap:3,justifyContent:"center",alignContent:"center",pointerEvents:"auto"},children:[i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.move_row_up"),disabled:!ue.ok,onClick:()=>H(j,-1),"data-testid":`g7le-inplace-row-up-${j}`,style:ue.ok?_n:Ei,children:"↑"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.add_row"),onClick:()=>B(j),"data-testid":`g7le-inplace-row-add-${j}`,style:_n,children:"+"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.remove_row"),disabled:f.rows.length<=1,onClick:()=>N(j),"data-testid":`g7le-inplace-row-remove-${j}`,style:Mh,children:"✕"}),i.jsx("button",{type:"button",title:a("layout_editor.table_inplace.move_row_down"),disabled:!J.ok,onClick:()=>H(j,1),"data-testid":`g7le-inplace-row-down-${j}`,style:J.ok?_n:Ei,children:"↓"})]},`rowgut-${j}`)})()}),i.jsxs("div",{"data-testid":"g7le-inplace-corner-add",style:{position:"absolute",top:n.top+n.height+gl,left:n.left,display:"flex",flexDirection:"column",gap:6,pointerEvents:"auto",minWidth:200,maxWidth:Math.max(240,n.width),background:"#fff",border:"1px solid #e2e8f0",borderRadius:8,padding:8,boxShadow:"0 2px 8px rgba(0,0,0,0.12)"},children:[i.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap"},children:[i.jsxs("button",{type:"button","data-testid":"g7le-inplace-add-row-bottom",onClick:()=>B(f.rows.length-1),style:Lh,children:["+ ",a("layout_editor.table_inplace.add_row")]}),i.jsxs("button",{type:"button","data-testid":"g7le-inplace-add-col-right",onClick:()=>L(f.colCount-1),style:Lh,children:["+ ",a("layout_editor.table_inplace.add_col")]})]}),!b&&i.jsx("div",{"data-testid":"g7le-inplace-select-hint",style:{fontSize:11,color:"#94a3b8",borderTop:"1px solid #f1f5f9",paddingTop:6},children:a("layout_editor.table_inplace.select_cell_hint")}),b&&i.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:6,borderTop:"1px solid #f1f5f9",paddingTop:6},children:[se&&i.jsx("div",{"data-testid":"g7le-inplace-range-count",style:{fontSize:11,color:"#2563eb"},children:a("layout_editor.table_inplace.range_selected",{count:Z.length})}),i.jsxs("div",{style:{display:"flex",gap:6,flexWrap:"wrap",alignItems:"center"},children:[se?i.jsx("button",{type:"button","data-testid":"g7le-inplace-merge-range",onClick:re,style:rr,children:a("layout_editor.table_inplace.merge_range")}):i.jsxs(i.Fragment,{children:[i.jsx("button",{type:"button","data-testid":"g7le-inplace-merge-right",disabled:!G,onClick:()=>F("right"),style:G?rr:hl,children:a("layout_editor.table_inplace.merge_right")}),i.jsx("button",{type:"button","data-testid":"g7le-inplace-merge-down",disabled:!V,onClick:()=>F("down"),style:V?rr:hl,children:a("layout_editor.table_inplace.merge_down")})]}),i.jsx("button",{type:"button","data-testid":"g7le-inplace-unmerge",disabled:!q,onClick:U,style:q?rr:hl,children:a("layout_editor.table_inplace.unmerge")})]}),i.jsxs("div",{"data-testid":"g7le-inplace-cell-color",style:{borderTop:"1px solid #f1f5f9",paddingTop:6,display:"flex",flexDirection:"column",gap:6},children:[i.jsxs("label",{style:{display:"flex",alignItems:"center",gap:6,fontSize:11,color:"#475569",cursor:"pointer"},children:[i.jsx("input",{type:"checkbox","data-testid":"g7le-inplace-border-all-toggle",checked:x,onChange:j=>k(j.target.checked)}),a("layout_editor.table_inplace.border_apply_all")]}),i.jsx(yh,{colorScheme:w,onChange:_,t:a}),ee&&i.jsx("div",{"data-testid":"g7le-inplace-cell-border",children:i.jsx(dh,{className:x?"":M,catalog:ee,t:a,onChange:me,colorScheme:w,onPresetToken:De,colorStyle:x?"":Qe,onColorStyle:Pe})}),i.jsx("div",{"data-testid":"g7le-inplace-cell-fill",children:i.jsx(fh,{colorStyle:x?"":ie,className:x?"":_e,catalog:fe,t:a,colorScheme:w,onPresetToken:ve,onCustomColor:te,onClear:he})})]}),i.jsx("div",{"data-testid":"g7le-inplace-cell-padding",style:{borderTop:"1px solid #f1f5f9",paddingTop:6},children:i.jsx(gh,{paddingStyle:x?"":ge,catalog:K,t:a,onChange:Q})})]})]})]})}const _n={width:22,height:22,lineHeight:"20px",padding:0,fontSize:13,border:"1px solid #cbd5e1",borderRadius:5,background:"#fff",color:"#475569",cursor:"pointer",boxShadow:"0 1px 3px rgba(0,0,0,0.18)"},Mh={..._n,border:"1px solid #fecaca",color:"#dc2626"},Ei={..._n,cursor:"not-allowed",opacity:.4,color:"#94a3b8",borderColor:"#e2e8f0"},rr={padding:"4px 10px",fontSize:12,border:"1px solid #cbd5e1",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer",boxShadow:"0 1px 2px rgba(0,0,0,0.12)"},hl={...rr,cursor:"not-allowed",opacity:.4},Lh={padding:"3px 8px",fontSize:11,border:"1px dashed #94a3b8",borderRadius:6,background:"#fff",color:"#475569",cursor:"pointer"};let Ph=!1;function Bz(){Ph||(Pn("children",qg),Pn("table",T8),Pn("array",$h),Pn("array-group",hz),Pn("array-cell-tree",kz),Oa("table",Oz),Ph=!0)}function Wz(){if(typeof window>"u")return;const e=window.G7Core;if(!e)return;const t=e.layoutEditor,n=Array.isArray(t?.__queue)?t.__queue:[],o=Array.isArray(t?.__readyCallbacks)?t.__readyCallbacks:[];e.layoutEditor={registerWidget:Xe,registerNodeEditor:Pn,registerCanvasOverlay:Oa,onReady:r=>{typeof r=="function"&&r()}};for(const r of n){const[s,...a]=r;try{s==="widget"?Xe(a[0],a[1]):s==="nodeEditor"?Pn(a[0],a[1]):s==="canvasOverlay"&&Oa(a[0],a[1])}catch{}}for(const r of o)try{r()}catch{}}const jz=1280;qN(),Bz(),Wz();async function Hz(e){if(typeof fetch!="function")return[];try{const t=await fetch(en(`/api/admin/templates/${encodeURIComponent(e)}/editor/permission-candidates`,"json"),{credentials:"same-origin",headers:je()});if(!t.ok)return[];const o=(await t.json().catch(()=>null))?.data?.permissions;if(!Array.isArray(o))return[];const r=[];for(const s of o)if(s&&typeof s=="object"){const a=s.key,l=s.name;typeof a=="string"&&a.length>0&&r.push({value:a,label:typeof l=="string"&&l?l:a})}return r}catch{return[]}}function Fz({templateIdentifier:e}){gD({templateIdentifier:e}),hD(e);const{state:t,dispatch:n}=Je(),{t:o}=tt(),r=yo(),s=Cp(),a=xD(),l=t.selectedRoute?.layoutName??null,d=CD(e,l),c=t.editMode==="extension",p=u.useMemo(()=>c?kD(a):s,[c,a,s]),[f,y]=u.useState(null),[g,m]=u.useState(null),[h,v]=u.useState([]),[b,x]=u.useState("user"),[k,w]=u.useState(null),[_,C]=u.useState(null),[E,S]=u.useState([]);u.useEffect(()=>{let te=!1;return(async()=>{try{const he=await fetch(en(`/api/templates/${encodeURIComponent(e)}/components`,"json"),{credentials:"same-origin",headers:{Accept:"application/json"}});if(!he.ok)return;const Q=await he.json().catch(()=>null);!te&&Q&&typeof Q=="object"&&y(Q)}catch{}})(),()=>{te=!0}},[e]),u.useEffect(()=>{let te=!1;return(async()=>{const{spec:he,sampleGlobalSources:Q}=await eb({templateIdentifier:e,coreSeed:$D()});te||(m(he),v(Q),Vz(e,he,Q))})(),()=>{te=!0}},[e]),u.useEffect(()=>{let te=!1;return(async()=>{if(typeof fetch=="function")try{const he=await fetch(`/api/admin/templates/${encodeURIComponent(e)}`,{credentials:"same-origin",headers:je()});if(!he.ok)return;const ie=(await he.json().catch(()=>null))?.data,_e=ie?.type;te||((_e==="admin"||_e==="user")&&x(_e),typeof ie?.name=="string"&&ie.name&&w(ie.name),typeof ie?.version=="string"&&ie.version&&C(ie.version))}catch{}})(),()=>{te=!0}},[e]),u.useEffect(()=>{let te=!1;return(async()=>{if(typeof fetch=="function")try{const he=await fetch("/api/admin/templates/?per_page=100&page=1",{credentials:"same-origin",headers:je()});if(!he.ok)return;const ie=(await he.json().catch(()=>null))?.data?.data;if(!te&&Array.isArray(ie)){const _e=[];for(const ge of ie){if(!ge||typeof ge!="object")continue;const Ae=ge.identifier;if(typeof Ae!="string"||!Ae||ge.is_pending===!0)continue;const Le=ge.type==="admin"?"admin":"user",q=ge.name,ae=ge.version;_e.push({identifier:Ae,name:typeof q=="string"?q:Ae,version:typeof ae=="string"?ae:"",type:Le})}S(_e)}}catch{}})(),()=>{te=!0}},[e]);const T=g?.nesting??null,$=t.selectedRoute?.path??null,A=t.editMode,z=t.selectedRoute?.layoutName??(c?a.document?.hostLayoutName??null:null),D=t.routeTree,O=u.useMemo(()=>{if(A!=="extension"||!z)return null;const te=bl(D,z);return te||`__base__/${z}`},[A,z,D]),M=c&&t.returnRoute===null&&!!z;u.useEffect(()=>{if(!M||!z)return;const te=bl(D,z);te&&n({type:"SET_RETURN_ROUTE",route:{path:te,layoutName:z}})},[M,z,D,n]),u.useEffect(()=>{const te=G4(A,$,O),he=Y4(g?.states?.groups,te);n({type:"SET_AVAILABLE_STATES",states:he,activeStateId:X4(he)})},[g,A,$,O,n]);const[B,N]=u.useState([]);u.useEffect(()=>{let te=!1;return(async()=>{const he=await Hz(e);te||N(he)})(),()=>{te=!0}},[e]),yD(),bD();const H=u.useCallback(te=>{const he=t.routeTree,Q=te.split("?")[0]?.split("#")[0]??te;return Kz(he,Q)?"route_in_tree":"route_not_in_tree"},[t.routeTree]),L=u.useCallback(te=>{const he=te.split("?")[0]?.split("#")[0]??te,Q=yl(t.routeTree,he);Q&&(p.isDirty&&!(!(typeof window<"u")||window.confirm(o("layout_editor.chrome.dirty_guard.message")))||n({type:"SELECT_ROUTE",route:{path:Q.path,layoutName:Q.layoutName}}))},[t.routeTree,p.isDirty,n]),I=u.useRef([]),P=u.useCallback(te=>{I.current=te},[]),[F,G]=u.useState(null),V=u.useCallback(()=>G(null),[]),Y=u.useRef(null),Z=u.useRef(null);u.useEffect(()=>{const te=Z.current,he=Y.current;if(!te||!he||typeof ResizeObserver>"u")return;const Q=()=>{he.style.setProperty("--g7le-header-h",`${Math.round(te.getBoundingClientRect().height)}px`)};Q();const ie=new ResizeObserver(Q);return ie.observe(te),()=>ie.disconnect()},[]);const se=u.useCallback(()=>{p.reload()},[p]),re=u.useCallback(()=>{p.isDirty&&!(!(typeof window<"u")||window.confirm(o("layout_editor.chrome.dirty_guard.message")))||window.G7Core?.dispatch?.({handler:"openWindow",params:{path:`/admin/templates/${b}`,target:"_self"}})},[p.isDirty,o,b]),U=u.useCallback(te=>{if(!te||te===e||p.isDirty&&!(typeof window<"u"?window.confirm(o("layout_editor.chrome.dirty_guard.message")):!0))return;const he=Zs(te);window.G7Core?.dispatch?.({handler:"openWindow",params:{path:he,target:"_self"}})},[e,p.isDirty,o]),ee=u.useCallback(()=>{const te=ME(e,t.selectedRoute?.path??null);window.G7Core?.dispatch?.({handler:"openWindow",params:{path:te}})},[e,t.selectedRoute]),fe=u.useCallback(()=>{const te=t.selectedRoute?.layoutName??"";if(!te)return;const he=r.open({ariaLabel:o("layout_editor.attachment_manager.title"),width:720,maxHeightRatio:.82,content:u.createElement(Ml,{templateIdentifier:e,layoutName:te,t:o,onClose:()=>r.close(he)})})},[r,e,t.selectedRoute,o]),K=u.useCallback(()=>{const te=t.selectedRoute?.layoutName??"";if(!te)return;const he=Hy(s.document?.raw??{}),Q=r.open({ariaLabel:o("layout_editor.translation_manager.title"),width:720,maxHeightRatio:.82,content:u.createElement(dm,{templateIdentifier:e,layoutName:te,t:o,referencedKeys:he,onClose:()=>r.close(Q)})})},[r,e,t.selectedRoute,o,s.document]),ne=u.useCallback((te,he)=>{const Q=window.G7Core;if(Q&&typeof Q.t=="function"){const ie=Q.t(te,he);if(ie&&ie!==te&&!ie.startsWith("$t:"))return ie}return o(te,he)},[o]),me=u.useCallback(()=>{if(!t.selectedRoute||t.editMode==="extension"||t.editMode==="iteration_item")return;const te=r.open({ariaLabel:o("layout_editor.page_settings.title",{name:t.selectedRoute.path??""}),width:1080,maxHeightRatio:.88,closeOnEscape:!1,content:u.createElement(u$,{templateIdentifier:e,spec:g,t:o,resolveLabel:ne,permissionCandidates:B,onClose:()=>r.close(te)})})},[r,t.selectedRoute,t.editMode,o,ne,e,g,B]),Ce=u.useCallback(async()=>{const te=await d.createPreview(s.document?.raw??null);if(te.kind!=="success"){const he=te.kind==="network_error"?te.message:o("layout_editor.preview_action.no_document");typeof window<"u"&&window.alert(he)}},[d,s.document,o]),ze=u.useCallback(()=>{const te=t.selectedRoute?.layoutName??"",he=t.selectedRoute?.path??"",Q=t.editMode==="extension"&&he.startsWith("__extension__/")?he.slice(14):null,ie=Q?{kind:"extension",extensionId:Q}:te?{kind:"layout",layoutName:te}:null;if(!ie)return;const _e=r.open({ariaLabel:o("layout_editor.version_history.title"),width:640,maxHeightRatio:.82,content:u.createElement(X$,{templateIdentifier:e,target:ie,t:o,onRestored:async ge=>{typeof ge=="number"&&(ie.kind==="extension"?n({type:"SET_EXTENSION_VERSION",extensionId:ie.extensionId,version:ge}):n({type:"SET_LAYOUT_VERSION",layoutName:ie.layoutName,version:ge})),await p.reload()},onClose:()=>r.close(_e)})})},[r,e,t.selectedRoute,t.editMode,o,p,n]),Se=p.dirtyKeys.size>0||p.isDirty;u.useEffect(()=>{if(!Se)return;const te=he=>{he.preventDefault(),he.returnValue=""};return window.addEventListener("beforeunload",te),()=>window.removeEventListener("beforeunload",te)},[Se]);const qe=u.useCallback(()=>{!p.isDirty||!(!(typeof window<"u")||window.confirm(o("layout_editor.chrome.reset_guard.message")))||p.reload()},[p,o]),De=u.useCallback(async()=>{const te=await p.save({sessionAddedPaths:I.current});G(te),te.kind==="success"&&typeof te.newContentVersion=="number"&&(te.savedExtensionId?n({type:"SET_EXTENSION_VERSION",extensionId:te.savedExtensionId,version:te.newContentVersion}):te.savedLayoutName&&n({type:"SET_LAYOUT_VERSION",layoutName:te.savedLayoutName,version:te.newContentVersion}))},[p,n]),Pe=u.useCallback(()=>{const te=r.open({ariaLabel:o("layout_editor.shortcuts.title"),width:560,maxHeightRatio:.85,content:u.createElement(iE,{t:o,onClose:()=>r.close(te)})})},[r,o]),Qe=u.useMemo(()=>({save:()=>{De()},exit:re,editCode:ee,reset:qe,translations:K,addElement:()=>{t.selectedRoute&&n({type:"TOGGLE_PALETTE"})},help:Pe,preview:()=>{t.selectedRoute?.layoutName&&Ce()}}),[De,re,ee,qe,K,t.selectedRoute,n,Pe,Ce]),[Me,Re]=u.useState(!1);u.useEffect(()=>{const te=window.setInterval(()=>{Re(!!window.__g7LayoutEditorHasSelection)},200);return()=>window.clearInterval(te)},[]),np({handlers:Qe,hasSelection:Me});const ve=p;return t.routesError?i.jsx("div",{className:"g7le-chrome g7le-chrome--routes-error","data-testid":"g7le-chrome-routes-error",style:{position:"fixed",inset:0,display:"flex",background:"#f8fafc",color:"#0f172a",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple SD Gothic Neo", "Noto Sans KR", sans-serif',fontSize:13,lineHeight:1.5,zIndex:9e3},children:i.jsx(Fa,{error:t.routesError})}):i.jsx("div",{className:"g7le-chrome","data-testid":"g7le-chrome",ref:Y,style:{position:"static",minHeight:"100vh",minWidth:jz,background:"#f8fafc",color:"#0f172a",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Apple SD Gothic Neo", "Noto Sans KR", sans-serif',fontSize:13,lineHeight:1.5,zIndex:9e3},children:i.jsxs(dy,{value:ve,children:[c&&a.needsHostPicker&&a.document&&i.jsx(SD,{hostLayouts:a.document.hostLayouts,extensionLabel:null,onSelect:a.selectHost}),i.jsxs("div",{className:"g7le-chrome__header","data-testid":"g7le-chrome-header",ref:Z,style:{position:"sticky",top:0,zIndex:20,background:"#f8fafc"},children:[i.jsx(by,{onSave:()=>{De()},isDirty:p.isDirty,onExit:re,onEditCode:ee,onManageImages:fe,onManageTranslations:K,onPageSettings:me,onReset:qe,onShowShortcuts:Pe,onPreview:Ce,onShowVersions:ze,templateName:k,templateVersion:_,templateList:E,onSwitchTemplate:U}),i.jsx(xE,{result:F,onDismiss:V,onLoadLatest:se}),i.jsxs("div",{className:"g7le-chrome__device-toolbar","data-testid":"g7le-chrome-device-toolbar",style:{display:"flex",justifyContent:"center",padding:"6px 12px",background:"#f1f5f9",borderBottom:"1px solid #e2e8f0"},children:[i.jsx(U4,{}),i.jsx(q4,{})]})]}),i.jsxs("div",{className:"g7le-chrome__body",style:{display:"grid",gridTemplateColumns:"auto 1fr",alignItems:"stretch"},children:[i.jsx(HE,{}),i.jsx(j4,{manifest:f,nesting:T,componentPalette:g?.componentPalette??null,spec:g,permissionCandidates:B,sampleGlobalSources:h,resolveRouteMatch:H,onNavigateToDestination:L,onSessionAddedPathsChange:P})]}),i.jsx(py,{})]})})}function yl(e,t){for(const n of e){if(n.kind==="route"&&n.path===t)return n;if(n.children&&n.children.length>0){const o=yl(n.children,t);if(o)return o}}return null}function Kz(e,t){return yl(e,t)!==null}function bl(e,t){for(const n of e){if(n.kind==="route"&&n.layoutName===t&&typeof n.path=="string")return n.path;if(n.children&&n.children.length>0){const o=bl(n.children,t);if(o)return o}}return null}function Vz(e,t,n){const o=[];Va({sources:n,isGuestOnly:!1,warn:s=>{const a=/extension '([^']+)' override of core key '([^']+)'/.exec(s);a&&o.push(`${a[1]}:${a[2]}`)}});const r=t?.sampleData?.byDataSourceId?Object.keys(t.sampleData.byDataSourceId).length:0;Qh({templateIdentifier:e,mergedSources:[...n.map(s=>({kind:s.kind,id:s.id}))],blockCounts:{controls:t?.controls?Object.keys(t.controls).length:0,componentCapabilities:t?.componentCapabilities?Object.keys(t.componentCapabilities).length:0,actionRecipes:t?.actionRecipes?Object.keys(t.actionRecipes).length:0,conditionRecipes:t?.conditionRecipes?Object.keys(t.conditionRecipes).length:0,paletteGroups:t?.componentPalette?.groups?.length??0,stateGroups:t?.states?.groups?.length??0,sampleDataIds:r},sampleGlobalSourceCount:n.length,sampleGlobalConflicts:o,timestamp:Date.now()})}function Oh({templateIdentifier:e,initialLocale:t}){return u.useEffect(()=>()=>{Vh(),qh(),Yh(),Xh(),Jh(),Zh(),Rh(),ey(),ty()},[]),i.jsx(ly,{templateIdentifier:e,initialLocale:t,children:i.jsx(uy,{children:i.jsx(Fz,{templateIdentifier:e})})})}if(typeof window<"u"){const e=window.G7Core||(window.G7Core={});if(e.__LayoutEditorChrome=Oh,typeof e.__onChromeReady=="function")try{e.__onChromeReady()}catch{}}dn.LayoutEditorChrome=Oh,Object.defineProperty(dn,Symbol.toStringTag,{value:"Module"})})(this.G7LayoutEditor=this.G7LayoutEditor||{},ReactJSXRuntime,React,ReactDOM); //# sourceMappingURL=layout-editor.min.js.map diff --git a/public/build/core/template-engine.min.js b/public/build/core/template-engine.min.js index 783d7b14..a9626fc3 100644 --- a/public/build/core/template-engine.min.js +++ b/public/build/core/template-engine.min.js @@ -1,20 +1,20 @@ -var oT=Object.defineProperty;var lT=(Yt,Xr,Jr)=>Xr in Yt?oT(Yt,Xr,{enumerable:!0,configurable:!0,writable:!0,value:Jr}):Yt[Xr]=Jr;var $=(Yt,Xr,Jr)=>lT(Yt,typeof Xr!="symbol"?Xr+"":Xr,Jr);(function(Yt){"use strict";function Xr(o,e){for(var n=0;na[i]})}}}return Object.freeze(Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}))}function Jr(o){return o&&o.__esModule&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o}var Ju={exports:{}},We={};var qg;function BS(){if(qg)return We;qg=1;var o=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),l=Symbol.for("react.consumer"),c=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"),S=Symbol.iterator;function v(H){return H===null||typeof H!="object"?null:(H=S&&H[S]||H["@@iterator"],typeof H=="function"?H:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},A=Object.assign,x={};function L(H,T,ce){this.props=H,this.context=T,this.refs=x,this.updater=ce||_}L.prototype.isReactComponent={},L.prototype.setState=function(H,T){if(typeof H!="object"&&typeof H!="function"&&H!=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,H,T,"setState")},L.prototype.forceUpdate=function(H){this.updater.enqueueForceUpdate(this,H,"forceUpdate")};function M(){}M.prototype=L.prototype;function R(H,T,ce){this.props=H,this.context=T,this.refs=x,this.updater=ce||_}var D=R.prototype=new M;D.constructor=R,A(D,L.prototype),D.isPureReactComponent=!0;var B=Array.isArray;function q(){}var P={H:null,A:null,T:null,S:null},K=Object.prototype.hasOwnProperty;function ge(H,T,ce){var de=ce.ref;return{$$typeof:o,type:H,key:T,ref:de!==void 0?de:null,props:ce}}function Ee(H,T){return ge(H.type,T,H.props)}function Se(H){return typeof H=="object"&&H!==null&&H.$$typeof===o}function Ue(H){var T={"=":"=0",":":"=2"};return"$"+H.replace(/[=:]/g,function(ce){return T[ce]})}var Ve=/\/+/g;function qe(H,T){return typeof H=="object"&&H!==null&&H.key!=null?Ue(""+H.key):T.toString(36)}function St(H){switch(H.status){case"fulfilled":return H.value;case"rejected":throw H.reason;default:switch(typeof H.status=="string"?H.then(q,q):(H.status="pending",H.then(function(T){H.status==="pending"&&(H.status="fulfilled",H.value=T)},function(T){H.status==="pending"&&(H.status="rejected",H.reason=T)})),H.status){case"fulfilled":return H.value;case"rejected":throw H.reason}}throw H}function J(H,T,ce,de,ye){var ie=typeof H;(ie==="undefined"||ie==="boolean")&&(H=null);var xe=!1;if(H===null)xe=!0;else switch(ie){case"bigint":case"string":case"number":xe=!0;break;case"object":switch(H.$$typeof){case o:case e:xe=!0;break;case m:return xe=H._init,J(xe(H._payload),T,ce,de,ye)}}if(xe)return ye=ye(H),xe=de===""?"."+qe(H,0):de,B(ye)?(ce="",xe!=null&&(ce=xe.replace(Ve,"$&/")+"/"),J(ye,T,ce,"",function($e){return $e})):ye!=null&&(Se(ye)&&(ye=Ee(ye,ce+(ye.key==null||H&&H.key===ye.key?"":(""+ye.key).replace(Ve,"$&/")+"/")+xe)),T.push(ye)),1;xe=0;var _e=de===""?".":de+":";if(B(H))for(var Te=0;Te>>1,pe=J[Z];if(0>>1;Zi(ce,Le))dei(ye,ce)?(J[Z]=ye,J[de]=Le,Z=de):(J[Z]=ce,J[T]=Le,Z=T);else if(dei(ye,Le))J[Z]=ye,J[de]=Le,Z=de;else break e}}return fe}function i(J,fe){var Le=J.sortIndex-fe.sortIndex;return Le!==0?Le:J.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 c=Date,d=c.now();o.unstable_now=function(){return c.now()-d}}var f=[],g=[],m=1,b=null,S=3,v=!1,_=!1,A=!1,x=!1,L=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,R=typeof setImmediate<"u"?setImmediate:null;function D(J){for(var fe=n(g);fe!==null;){if(fe.callback===null)a(g);else if(fe.startTime<=J)a(g),fe.sortIndex=fe.expirationTime,e(f,fe);else break;fe=n(g)}}function B(J){if(A=!1,D(J),!_)if(n(f)!==null)_=!0,q||(q=!0,Ue());else{var fe=n(g);fe!==null&&St(B,fe.startTime-J)}}var q=!1,P=-1,K=5,ge=-1;function Ee(){return x?!0:!(o.unstable_now()-geJ&&Ee());){var Z=b.callback;if(typeof Z=="function"){b.callback=null,S=b.priorityLevel;var pe=Z(b.expirationTime<=J);if(J=o.unstable_now(),typeof pe=="function"){b.callback=pe,D(J),fe=!0;break t}b===n(f)&&a(f),D(J)}else a(f);b=n(f)}if(b!==null)fe=!0;else{var H=n(g);H!==null&&St(B,H.startTime-J),fe=!1}}break e}finally{b=null,S=Le,v=!1}fe=void 0}}finally{fe?Ue():q=!1}}}var Ue;if(typeof R=="function")Ue=function(){R(Se)};else if(typeof MessageChannel<"u"){var Ve=new MessageChannel,qe=Ve.port2;Ve.port1.onmessage=Se,Ue=function(){qe.postMessage(null)}}else Ue=function(){L(Se,0)};function St(J,fe){P=L(function(){J(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(J){J.callback=null},o.unstable_forceFrameRate=function(J){0>J||125Z?(J.sortIndex=Le,e(g,J),n(f)===null&&J===n(g)&&(A?(M(P),P=-1):A=!0,St(B,Le-Z))):(J.sortIndex=pe,e(f,J),_||v||(_=!0,q||(q=!0,Ue()))),J},o.unstable_shouldYield=Ee,o.unstable_wrapCallback=function(J){var fe=S;return function(){var Le=S;S=fe;try{return J.apply(this,arguments)}finally{S=Le}}}})(td)),td}var Fg;function qS(){return Fg||(Fg=1,ed.exports=PS()),ed.exports}var nd={exports:{}},wn={};var Kg;function GS(){if(Kg)return wn;Kg=1;var o=Qu();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(),nd.exports=GS(),nd.exports}var Xg;function VS(){if(Xg)return Xs;Xg=1;var o=qS(),e=Qu(),n=Yg();function a(t){var r="https://react.dev/errors/"+t;if(1pe||(t.current=Z[pe],Z[pe]=null,pe--)}function ce(t,r){pe++,Z[pe]=t.current,t.current=r}var de=H(null),ye=H(null),ie=H(null),xe=H(null);function _e(t,r){switch(ce(ie,r),ce(ye,t),ce(de,null),r.nodeType){case 9:case 11:t=(t=r.documentElement)&&(t=t.namespaceURI)?oS(t):0;break;default:if(t=r.tagName,r=r.namespaceURI)r=oS(r),t=lS(r,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}T(de),ce(de,t)}function Te(){T(de),T(ye),T(ie)}function $e(t){t.memoizedState!==null&&ce(xe,t);var r=de.current,s=lS(r,t.type);r!==s&&(ce(ye,t),ce(de,s))}function ht(t){ye.current===t&&(T(de),T(ye)),xe.current===t&&(T(xe),Tl._currentValue=Le)}var wt,kt;function ft(t){if(wt===void 0)try{throw Error()}catch(s){var r=s.stack.trim().match(/\n( *(at )?)/);wt=r&&r[1]||"",kt=-1Xr in Qt?ET(Qt,Xr,{enumerable:!0,configurable:!0,writable:!0,value:Jr}):Qt[Xr]=Jr;var $=(Qt,Xr,Jr)=>_T(Qt,typeof Xr!="symbol"?Xr+"":Xr,Jr);(function(Qt){"use strict";function Xr(o,e){for(var n=0;na[i]})}}}return Object.freeze(Object.defineProperty(o,Symbol.toStringTag,{value:"Module"}))}function Jr(o){return o&&o.__esModule&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o}var td={exports:{}},Ye={};var Fg;function WS(){if(Fg)return Ye;Fg=1;var o=Symbol.for("react.transitional.element"),e=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),i=Symbol.for("react.profiler"),l=Symbol.for("react.consumer"),c=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"),y=Symbol.for("react.activity"),S=Symbol.iterator;function v(N){return N===null||typeof N!="object"?null:(N=S&&N[S]||N["@@iterator"],typeof N=="function"?N:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},A=Object.assign,x={};function O(N,R,de){this.props=N,this.context=R,this.refs=x,this.updater=de||_}O.prototype.isReactComponent={},O.prototype.setState=function(N,R){if(typeof N!="object"&&typeof N!="function"&&N!=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,N,R,"setState")},O.prototype.forceUpdate=function(N){this.updater.enqueueForceUpdate(this,N,"forceUpdate")};function M(){}M.prototype=O.prototype;function T(N,R,de){this.props=N,this.context=R,this.refs=x,this.updater=de||_}var D=T.prototype=new M;D.constructor=T,A(D,O.prototype),D.isPureReactComponent=!0;var z=Array.isArray;function P(){}var q={H:null,A:null,T:null,S:null},W=Object.prototype.hasOwnProperty;function he(N,R,de){var fe=de.ref;return{$$typeof:o,type:N,key:R,ref:fe!==void 0?fe:null,props:de}}function Ee(N,R){return he(N.type,R,N.props)}function be(N){return typeof N=="object"&&N!==null&&N.$$typeof===o}function Ue(N){var R={"=":"=0",":":"=2"};return"$"+N.replace(/[=:]/g,function(de){return R[de]})}var Fe=/\/+/g;function Ge(N,R){return typeof N=="object"&&N!==null&&N.key!=null?Ue(""+N.key):R.toString(36)}function wt(N){switch(N.status){case"fulfilled":return N.value;case"rejected":throw N.reason;default:switch(typeof N.status=="string"?N.then(P,P):(N.status="pending",N.then(function(R){N.status==="pending"&&(N.status="fulfilled",N.value=R)},function(R){N.status==="pending"&&(N.status="rejected",N.reason=R)})),N.status){case"fulfilled":return N.value;case"rejected":throw N.reason}}throw N}function J(N,R,de,fe,xe){var ee=typeof N;(ee==="undefined"||ee==="boolean")&&(N=null);var _e=!1;if(N===null)_e=!0;else switch(ee){case"bigint":case"string":case"number":_e=!0;break;case"object":switch(N.$$typeof){case o:case e:_e=!0;break;case m:return _e=N._init,J(_e(N._payload),R,de,fe,xe)}}if(_e)return xe=xe(N),_e=fe===""?"."+Ge(N,0):fe,z(xe)?(de="",_e!=null&&(de=_e.replace(Fe,"$&/")+"/"),J(xe,R,de,"",function(Ie){return Ie})):xe!=null&&(be(xe)&&(xe=Ee(xe,de+(xe.key==null||N&&N.key===xe.key?"":(""+xe.key).replace(Fe,"$&/")+"/")+_e)),R.push(xe)),1;_e=0;var Be=fe===""?".":fe+":";if(z(N))for(var ke=0;ke>>1,pe=J[te];if(0>>1;tei(de,Me))fei(xe,de)?(J[te]=xe,J[fe]=Me,te=fe):(J[te]=de,J[R]=Me,te=R);else if(fei(xe,Me))J[te]=xe,J[fe]=Me,te=fe;else break e}}return ue}function i(J,ue){var Me=J.sortIndex-ue.sortIndex;return Me!==0?Me:J.id-ue.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 c=Date,d=c.now();o.unstable_now=function(){return c.now()-d}}var f=[],g=[],m=1,y=null,S=3,v=!1,_=!1,A=!1,x=!1,O=typeof setTimeout=="function"?setTimeout:null,M=typeof clearTimeout=="function"?clearTimeout:null,T=typeof setImmediate<"u"?setImmediate:null;function D(J){for(var ue=n(g);ue!==null;){if(ue.callback===null)a(g);else if(ue.startTime<=J)a(g),ue.sortIndex=ue.expirationTime,e(f,ue);else break;ue=n(g)}}function z(J){if(A=!1,D(J),!_)if(n(f)!==null)_=!0,P||(P=!0,Ue());else{var ue=n(g);ue!==null&&wt(z,ue.startTime-J)}}var P=!1,q=-1,W=5,he=-1;function Ee(){return x?!0:!(o.unstable_now()-heJ&&Ee());){var te=y.callback;if(typeof te=="function"){y.callback=null,S=y.priorityLevel;var pe=te(y.expirationTime<=J);if(J=o.unstable_now(),typeof pe=="function"){y.callback=pe,D(J),ue=!0;break t}y===n(f)&&a(f),D(J)}else a(f);y=n(f)}if(y!==null)ue=!0;else{var N=n(g);N!==null&&wt(z,N.startTime-J),ue=!1}}break e}finally{y=null,S=Me,v=!1}ue=void 0}}finally{ue?Ue():P=!1}}}var Ue;if(typeof T=="function")Ue=function(){T(be)};else if(typeof MessageChannel<"u"){var Fe=new MessageChannel,Ge=Fe.port2;Fe.port1.onmessage=be,Ue=function(){Ge.postMessage(null)}}else Ue=function(){O(be,0)};function wt(J,ue){q=O(function(){J(o.unstable_now())},ue)}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(J){J.callback=null},o.unstable_forceFrameRate=function(J){0>J||125te?(J.sortIndex=Me,e(g,J),n(f)===null&&J===n(g)&&(A?(M(q),q=-1):A=!0,wt(z,Me-te))):(J.sortIndex=pe,e(f,J),_||v||(_=!0,P||(P=!0,Ue()))),J},o.unstable_shouldYield=Ee,o.unstable_wrapCallback=function(J){var ue=S;return function(){var Me=S;S=ue;try{return J.apply(this,arguments)}finally{S=Me}}}})(id)),id}var Yg;function XS(){return Yg||(Yg=1,ad.exports=YS()),ad.exports}var sd={exports:{}},_n={};var Xg;function JS(){if(Xg)return _n;Xg=1;var o=nd();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(),sd.exports=JS(),sd.exports}var Zg;function QS(){if(Zg)return Zs;Zg=1;var o=XS(),e=nd(),n=Qg();function a(t){var r="https://react.dev/errors/"+t;if(1pe||(t.current=te[pe],te[pe]=null,pe--)}function de(t,r){pe++,te[pe]=t.current,t.current=r}var fe=N(null),xe=N(null),ee=N(null),_e=N(null);function Be(t,r){switch(de(ee,r),de(xe,t),de(fe,null),r.nodeType){case 9:case 11:t=(t=r.documentElement)&&(t=t.namespaceURI)?pS(t):0;break;default:if(t=r.tagName,r=r.namespaceURI)r=pS(r),t=mS(r,t);else switch(t){case"svg":t=1;break;case"math":t=2;break;default:t=0}}R(fe),de(fe,t)}function ke(){R(fe),R(xe),R(ee)}function Ie(t){t.memoizedState!==null&&de(_e,t);var r=fe.current,s=mS(r,t.type);r!==s&&(de(xe,t),de(fe,s))}function Ct(t){xe.current===t&&(R(fe),R(xe)),_e.current===t&&(R(_e),Ol._currentValue=Me)}var ot,Ot;function vt(t){if(ot===void 0)try{throw Error()}catch(s){var r=s.stack.trim().match(/\n( *(at )?)/);ot=r&&r[1]||"",Ot=-1)":-1h||j[u]!==X[h]){var re=` -`+j[u].replace(" at new "," at ");return t.displayName&&re.includes("")&&(re=re.replace("",t.displayName)),re}while(1<=u&&0<=h);break}}}finally{nn=!1,Error.prepareStackTrace=s}return(s=t?t.displayName||t.name:"")?ft(s):""}function Nt(t,r){switch(t.tag){case 26:case 27:case 5:return ft(t.type);case 16:return ft("Lazy");case 13:return t.child!==r&&r!==null?ft("Suspense Fallback"):ft("Suspense");case 19:return ft("SuspenseList");case 0:case 15:return Ft(t.type,!1);case 11:return Ft(t.type.render,!1);case 1:return Ft(t.type,!0);case 31:return ft("Activity");default:return""}}function Br(t){try{var r="",s=null;do r+=Nt(t,s),s=t,t=t.return;while(t);return r}catch(u){return` +`);for(h=u=0;uh||U[u]!==X[h]){var ae=` +`+U[u].replace(" at new "," at ");return t.displayName&&ae.includes("")&&(ae=ae.replace("",t.displayName)),ae}while(1<=u&&0<=h);break}}}finally{_t=!1,Error.prepareStackTrace=s}return(s=t?t.displayName||t.name:"")?vt(s):""}function nt(t,r){switch(t.tag){case 26:case 27:case 5:return vt(t.type);case 16:return vt("Lazy");case 13:return t.child!==r&&r!==null?vt("Suspense Fallback"):vt("Suspense");case 19:return vt("SuspenseList");case 0:case 15:return Oe(t.type,!1);case 11:return Oe(t.type.render,!1);case 1:return Oe(t.type,!0);case 31:return vt("Activity");default:return""}}function sn(t){try{var r="",s=null;do r+=nt(t,s),s=t,t=t.return;while(t);return r}catch(u){return` Error generating stack: `+u.message+` -`+u.stack}}var fn=Object.prototype.hasOwnProperty,rn=o.unstable_scheduleCallback,hn=o.unstable_cancelCallback,Fn=o.unstable_shouldYield,Pr=o.unstable_requestPaint,Pt=o.unstable_now,wi=o.unstable_getCurrentPriorityLevel,na=o.unstable_ImmediatePriority,gn=o.unstable_UserBlockingPriority,Rn=o.unstable_NormalPriority,tt=o.unstable_LowPriority,$n=o.unstable_IdlePriority,pn=o.log,ra=o.unstable_setDisableYieldValue,ir=null,an=null;function En(t){if(typeof pn=="function"&&ra(t),an&&typeof an.setStrictMode=="function")try{an.setStrictMode(ir,t)}catch{}}var sn=Math.clz32?Math.clz32:ue,V=Math.log,se=Math.LN2;function ue(t){return t>>>=0,t===0?32:31-(V(t)/se|0)|0}var ee=256,ve=262144,he=4194304;function Ce(t){var r=t&42;if(r!==0)return r;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 Ae(t,r,s){var u=t.pendingLanes;if(u===0)return 0;var h=0,p=t.suspendedLanes,w=t.pingedLanes;t=t.warmLanes;var k=u&134217727;return k!==0?(u=k&~p,u!==0?h=Ce(u):(w&=k,w!==0?h=Ce(w):s||(s=k&~t,s!==0&&(h=Ce(s))))):(k=u&~p,k!==0?h=Ce(k):w!==0?h=Ce(w):s||(s=u&~t,s!==0&&(h=Ce(s)))),h===0?0:r!==0&&r!==h&&(r&p)===0&&(p=h&-h,s=r&-r,p>=s||p===32&&(s&4194048)!==0)?r:h}function Fe(t,r){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&r)===0}function Re(t,r){switch(t){case 1:case 2:case 4:case 8:case 64:return r+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 r+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 Ne(){var t=he;return he<<=1,(he&62914560)===0&&(he=4194304),t}function ke(t){for(var r=[],s=0;31>s;s++)r.push(t);return r}function Ze(t,r){t.pendingLanes|=r,r!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function ze(t,r,s,u,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,j=t.expirationTimes,X=t.hiddenUpdates;for(s=w&~s;0"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var kf=/[\n"\\]/g;function In(t){return t.replace(kf,function(r){return"\\"+r.charCodeAt(0).toString(16)+" "})}function ms(t,r,s,u,h,p,w,k){t.name="",w!=null&&typeof w!="function"&&typeof w!="symbol"&&typeof w!="boolean"?t.type=w:t.removeAttribute("type"),r!=null?w==="number"?(r===0&&t.value===""||t.value!=r)&&(t.value=""+An(r)):t.value!==""+An(r)&&(t.value=""+An(r)):w!=="submit"&&w!=="reset"||t.removeAttribute("value"),r!=null?ia(t,w,An(r)):s!=null?ia(t,w,An(s)):u!=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=""+An(k):t.removeAttribute("name")}function _i(t,r,s,u,h,p,w,k){if(p!=null&&typeof p!="function"&&typeof p!="symbol"&&typeof p!="boolean"&&(t.type=p),r!=null||s!=null){if(!(p!=="submit"&&p!=="reset"||r!=null)){Io(t);return}s=s!=null?""+An(s):"",r=r!=null?""+An(r):s,k||r===t.value||(t.value=r),t.defaultValue=r}u=u??h,u=typeof u!="function"&&typeof u!="symbol"&&!!u,t.checked=k?t.checked:!!u,t.defaultChecked=!!u,w!=null&&typeof w!="function"&&typeof w!="symbol"&&typeof w!="boolean"&&(t.name=w),Io(t)}function ia(t,r,s){r==="number"&&za(t.ownerDocument)===t||t.defaultValue===""+s||(t.defaultValue=""+s)}function ja(t,r,s,u){if(t=t.options,r){r={};for(var h=0;h"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Bo=!1;if(Rr)try{var xi={};Object.defineProperty(xi,"passive",{get:function(){Bo=!0}}),window.addEventListener("test",xi,xi),window.removeEventListener("test",xi,xi)}catch{Bo=!1}var Vr=null,Po=null,bs=null;function Hc(){if(bs)return bs;var t,r=Po,s=r.length,u,h="value"in Vr?Vr.value:Vr.textContent,p=h.length;for(t=0;t=ne),Ke=" ",lt=!1;function gt(t,r){switch(t){case"keyup":return O.indexOf(r.keyCode)!==-1;case"keydown":return r.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function zt(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Dr=!1;function Kf(t,r){switch(t){case"compositionend":return zt(r);case"keypress":return r.which!==32?null:(lt=!0,Ke);case"textInput":return t=r.data,t===Ke&<?null:t;default:return null}}function Gc(t,r){if(Dr)return t==="compositionend"||!I&>(t,r)?(t=Hc(),bs=Po=Vr=null,Dr=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(r.ctrlKey||r.altKey||r.metaKey)||r.ctrlKey&&r.altKey){if(r.char&&1=r)return{node:s,offset:r-t};t=u}e:{for(;s;){if(s.nextSibling){s=s.nextSibling;break e}s=s.parentNode}s=void 0}s=Ay(s)}}function Ty(t,r){return t&&r?t===r?!0:t&&t.nodeType===3?!1:r&&r.nodeType===3?Ty(t,r.parentNode):"contains"in t?t.contains(r):t.compareDocumentPosition?!!(t.compareDocumentPosition(r)&16):!1:!1}function Ry(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var r=za(t.document);r instanceof t.HTMLIFrameElement;){try{var s=typeof r.contentWindow.location.href=="string"}catch{s=!1}if(s)t=r.contentWindow;else break;r=za(t.document)}return r}function Qf(t){var r=t&&t.nodeName&&t.nodeName.toLowerCase();return r&&(r==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||r==="textarea"||t.contentEditable==="true")}var UA=Rr&&"documentMode"in document&&11>=document.documentMode,Cs=null,Zf=null,Qo=null,eh=!1;function ky(t,r,s){var u=s.window===s?s.document:s.nodeType===9?s:s.ownerDocument;eh||Cs==null||Cs!==za(u)||(u=Cs,"selectionStart"in u&&Qf(u)?u={start:u.selectionStart,end:u.selectionEnd}:(u=(u.ownerDocument&&u.ownerDocument.defaultView||window).getSelection(),u={anchorNode:u.anchorNode,anchorOffset:u.anchorOffset,focusNode:u.focusNode,focusOffset:u.focusOffset}),Qo&&Jo(Qo,u)||(Qo=u,u=Iu(Zf,"onSelect"),0>=w,h-=w,Fr=1<<32-sn(r)+h|s<Je?(st=Ie,Ie=null):st=Ie.sibling;var mt=Q(F,Ie,Y[Je],oe);if(mt===null){Ie===null&&(Ie=st);break}t&&Ie&&mt.alternate===null&&r(F,Ie),G=p(mt,G,Je),pt===null?Be=mt:pt.sibling=mt,pt=mt,Ie=st}if(Je===Y.length)return s(F,Ie),ct&&ca(F,Je),Be;if(Ie===null){for(;JeJe?(st=Ie,Ie=null):st=Ie.sibling;var di=Q(F,Ie,mt.value,oe);if(di===null){Ie===null&&(Ie=st);break}t&&Ie&&di.alternate===null&&r(F,Ie),G=p(di,G,Je),pt===null?Be=di:pt.sibling=di,pt=di,Ie=st}if(mt.done)return s(F,Ie),ct&&ca(F,Je),Be;if(Ie===null){for(;!mt.done;Je++,mt=Y.next())mt=le(F,mt.value,oe),mt!==null&&(G=p(mt,G,Je),pt===null?Be=mt:pt.sibling=mt,pt=mt);return ct&&ca(F,Je),Be}for(Ie=u(Ie);!mt.done;Je++,mt=Y.next())mt=te(Ie,F,Je,mt.value,oe),mt!==null&&(t&&mt.alternate!==null&&Ie.delete(mt.key===null?Je:mt.key),G=p(mt,G,Je),pt===null?Be=mt:pt.sibling=mt,pt=mt);return t&&Ie.forEach(function(sT){return r(F,sT)}),ct&&ca(F,Je),Be}function Tt(F,G,Y,oe){if(typeof Y=="object"&&Y!==null&&Y.type===A&&Y.key===null&&(Y=Y.props.children),typeof Y=="object"&&Y!==null){switch(Y.$$typeof){case v:e:{for(var Be=Y.key;G!==null;){if(G.key===Be){if(Be=Y.type,Be===A){if(G.tag===7){s(F,G.sibling),oe=h(G,Y.props.children),oe.return=F,F=oe;break e}}else if(G.elementType===Be||typeof Be=="object"&&Be!==null&&Be.$$typeof===K&&Pi(Be)===G.type){s(F,G.sibling),oe=h(G,Y.props),al(oe,Y),oe.return=F,F=oe;break e}s(F,G);break}else r(F,G);G=G.sibling}Y.type===A?(oe=Hi(Y.props.children,F.mode,oe,Y.key),oe.return=F,F=oe):(oe=Zc(Y.type,Y.key,Y.props,null,F.mode,oe),al(oe,Y),oe.return=F,F=oe)}return w(F);case _:e:{for(Be=Y.key;G!==null;){if(G.key===Be)if(G.tag===4&&G.stateNode.containerInfo===Y.containerInfo&&G.stateNode.implementation===Y.implementation){s(F,G.sibling),oe=h(G,Y.children||[]),oe.return=F,F=oe;break e}else{s(F,G);break}else r(F,G);G=G.sibling}oe=oh(Y,F.mode,oe),oe.return=F,F=oe}return w(F);case K:return Y=Pi(Y),Tt(F,G,Y,oe)}if(St(Y))return De(F,G,Y,oe);if(Ue(Y)){if(Be=Ue(Y),typeof Be!="function")throw Error(a(150));return Y=Be.call(Y),Pe(F,G,Y,oe)}if(typeof Y.then=="function")return Tt(F,G,su(Y),oe);if(Y.$$typeof===R)return Tt(F,G,nu(F,Y),oe);ou(F,Y)}return typeof Y=="string"&&Y!==""||typeof Y=="number"||typeof Y=="bigint"?(Y=""+Y,G!==null&&G.tag===6?(s(F,G.sibling),oe=h(G,Y),oe.return=F,F=oe):(s(F,G),oe=sh(Y,F.mode,oe),oe.return=F,F=oe),w(F)):s(F,G)}return function(F,G,Y,oe){try{rl=0;var Be=Tt(F,G,Y,oe);return Ms=null,Be}catch(Ie){if(Ie===Ls||Ie===au)throw Ie;var pt=Wn(29,Ie,null,F.mode);return pt.lanes=oe,pt.return=F,pt}}}var Gi=Qy(!0),Zy=Qy(!1),Wa=!1;function vh(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Sh(t,r){t=t.updateQueue,r.updateQueue===t&&(r.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Ya(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Xa(t,r,s){var u=t.updateQueue;if(u===null)return null;if(u=u.shared,(bt&2)!==0){var h=u.pending;return h===null?r.next=r:(r.next=h.next,h.next=r),u.pending=r,r=Qc(t),Iy(t,null,s),r}return Jc(t,u,r,s),Qc(t)}function il(t,r,s){if(r=r.updateQueue,r!==null&&(r=r.shared,(s&4194048)!==0)){var u=r.lanes;u&=t.pendingLanes,s|=u,r.lanes=s,we(t,s)}}function wh(t,r){var s=t.updateQueue,u=t.alternate;if(u!==null&&(u=u.updateQueue,s===u)){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=r:p=p.next=r}else h=p=r;s={baseState:u.baseState,firstBaseUpdate:h,lastBaseUpdate:p,shared:u.shared,callbacks:u.callbacks},t.updateQueue=s;return}t=s.lastBaseUpdate,t===null?s.firstBaseUpdate=r:t.next=r,s.lastBaseUpdate=r}var Ch=!1;function sl(){if(Ch){var t=Os;if(t!==null)throw t}}function ol(t,r,s,u){Ch=!1;var h=t.updateQueue;Wa=!1;var p=h.firstBaseUpdate,w=h.lastBaseUpdate,k=h.shared.pending;if(k!==null){h.shared.pending=null;var j=k,X=j.next;j.next=null,w===null?p=X:w.next=X,w=j;var re=t.alternate;re!==null&&(re=re.updateQueue,k=re.lastBaseUpdate,k!==w&&(k===null?re.firstBaseUpdate=X:k.next=X,re.lastBaseUpdate=j))}if(p!==null){var le=h.baseState;w=0,re=X=j=null,k=p;do{var Q=k.lane&-536870913,te=Q!==k.lane;if(te?(it&Q)===Q:(u&Q)===Q){Q!==0&&Q===Ds&&(Ch=!0),re!==null&&(re=re.next={lane:0,tag:k.tag,payload:k.payload,callback:null,next:null});e:{var De=t,Pe=k;Q=r;var Tt=s;switch(Pe.tag){case 1:if(De=Pe.payload,typeof De=="function"){le=De.call(Tt,le,Q);break e}le=De;break e;case 3:De.flags=De.flags&-65537|128;case 0:if(De=Pe.payload,Q=typeof De=="function"?De.call(Tt,le,Q):De,Q==null)break e;le=b({},le,Q);break e;case 2:Wa=!0}}Q=k.callback,Q!==null&&(t.flags|=64,te&&(t.flags|=8192),te=h.callbacks,te===null?h.callbacks=[Q]:te.push(Q))}else te={lane:Q,tag:k.tag,payload:k.payload,callback:k.callback,next:null},re===null?(X=re=te,j=le):re=re.next=te,w|=Q;if(k=k.next,k===null){if(k=h.shared.pending,k===null)break;te=k,k=te.next,te.next=null,h.lastBaseUpdate=te,h.shared.pending=null}}while(!0);re===null&&(j=le),h.baseState=j,h.firstBaseUpdate=X,h.lastBaseUpdate=re,p===null&&(h.shared.lanes=0),ti|=w,t.lanes=w,t.memoizedState=le}}function eb(t,r){if(typeof t!="function")throw Error(a(191,t));t.call(r)}function tb(t,r){var s=t.callbacks;if(s!==null)for(t.callbacks=null,t=0;tp?p:8;var w=J.T,k={};J.T=k,Bh(t,!1,r,s);try{var j=h(),X=J.S;if(X!==null&&X(k,j),j!==null&&typeof j=="object"&&typeof j.then=="function"){var re=YA(j,u);ul(t,r,re,Zn(t))}else ul(t,r,u,Zn(t))}catch(le){ul(t,r,{then:function(){},status:"rejected",reason:le},Zn())}finally{fe.p=p,w!==null&&k.types!==null&&(w.types=k.types),J.T=w}}function tx(){}function jh(t,r,s,u){if(t.tag!==5)throw Error(a(476));var h=Mb(t).queue;Lb(t,h,r,Le,s===null?tx:function(){return $b(t),s(u)})}function Mb(t){var r=t.memoizedState;if(r!==null)return r;r={memoizedState:Le,baseState:Le,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ha,lastRenderedState:Le},next:null};var s={};return r.next={memoizedState:s,baseState:s,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ha,lastRenderedState:s},next:null},t.memoizedState=r,t=t.alternate,t!==null&&(t.memoizedState=r),r}function $b(t){var r=Mb(t);r.next===null&&(r=t.alternate.memoizedState),ul(t,r.next.queue,{},Zn())}function Uh(){return bn(Tl)}function Nb(){return Wt().memoizedState}function Ib(){return Wt().memoizedState}function nx(t){for(var r=t.return;r!==null;){switch(r.tag){case 24:case 3:var s=Zn();t=Ya(s);var u=Xa(r,t,s);u!==null&&(Bn(u,r,s),il(u,r,s)),r={cache:ph()},t.payload=r;return}r=r.return}}function rx(t,r,s){var u=Zn();s={lane:u,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null},yu(t)?zb(r,s):(s=ah(t,r,s,u),s!==null&&(Bn(s,t,u),jb(s,r,u)))}function Hb(t,r,s){var u=Zn();ul(t,r,s,u)}function ul(t,r,s,u){var h={lane:u,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null};if(yu(t))zb(r,h);else{var p=t.alternate;if(t.lanes===0&&(p===null||p.lanes===0)&&(p=r.lastRenderedReducer,p!==null))try{var w=r.lastRenderedState,k=p(w,s);if(h.hasEagerState=!0,h.eagerState=k,Kn(k,w))return Jc(t,r,h,0),Rt===null&&Xc(),!1}catch{}if(s=ah(t,r,h,u),s!==null)return Bn(s,t,u),jb(s,r,u),!0}return!1}function Bh(t,r,s,u){if(u={lane:2,revertLane:vg(),gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null},yu(t)){if(r)throw Error(a(479))}else r=ah(t,s,u,2),r!==null&&Bn(r,t,2)}function yu(t){var r=t.alternate;return t===Xe||r!==null&&r===Xe}function zb(t,r){Ns=uu=!0;var s=t.pending;s===null?r.next=r:(r.next=s.next,s.next=r),t.pending=r}function jb(t,r,s){if((s&4194048)!==0){var u=r.lanes;u&=t.pendingLanes,s|=u,r.lanes=s,we(t,s)}}var dl={readContext:bn,use:hu,useCallback:qt,useContext:qt,useEffect:qt,useImperativeHandle:qt,useLayoutEffect:qt,useInsertionEffect:qt,useMemo:qt,useReducer:qt,useRef:qt,useState:qt,useDebugValue:qt,useDeferredValue:qt,useTransition:qt,useSyncExternalStore:qt,useId:qt,useHostTransitionStatus:qt,useFormState:qt,useActionState:qt,useOptimistic:qt,useMemoCache:qt,useCacheRefresh:qt};dl.useEffectEvent=qt;var Ub={readContext:bn,use:hu,useCallback:function(t,r){return Dn().memoizedState=[t,r===void 0?null:r],t},useContext:bn,useEffect:Eb,useImperativeHandle:function(t,r,s){s=s!=null?s.concat([t]):null,pu(4194308,4,Tb.bind(null,r,t),s)},useLayoutEffect:function(t,r){return pu(4194308,4,t,r)},useInsertionEffect:function(t,r){pu(4,2,t,r)},useMemo:function(t,r){var s=Dn();r=r===void 0?null:r;var u=t();if(Vi){En(!0);try{t()}finally{En(!1)}}return s.memoizedState=[u,r],u},useReducer:function(t,r,s){var u=Dn();if(s!==void 0){var h=s(r);if(Vi){En(!0);try{s(r)}finally{En(!1)}}}else h=r;return u.memoizedState=u.baseState=h,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:h},u.queue=t,t=t.dispatch=rx.bind(null,Xe,t),[u.memoizedState,t]},useRef:function(t){var r=Dn();return t={current:t},r.memoizedState=t},useState:function(t){t=$h(t);var r=t.queue,s=Hb.bind(null,Xe,r);return r.dispatch=s,[t.memoizedState,s]},useDebugValue:Hh,useDeferredValue:function(t,r){var s=Dn();return zh(s,t,r)},useTransition:function(){var t=$h(!1);return t=Lb.bind(null,Xe,t.queue,!0,!1),Dn().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,r,s){var u=Xe,h=Dn();if(ct){if(s===void 0)throw Error(a(407));s=s()}else{if(s=r(),Rt===null)throw Error(a(349));(it&127)!==0||ob(u,r,s)}h.memoizedState=s;var p={value:s,getSnapshot:r};return h.queue=p,Eb(cb.bind(null,u,p,t),[t]),u.flags|=2048,Hs(9,{destroy:void 0},lb.bind(null,u,p,s,r),null),s},useId:function(){var t=Dn(),r=Rt.identifierPrefix;if(ct){var s=Kr,u=Fr;s=(u&~(1<<32-sn(u)-1)).toString(32)+s,r="_"+r+"R_"+s,s=du++,0<\/script>",p=p.removeChild(p.firstChild);break;case"select":p=typeof u.is=="string"?w.createElement("select",{is:u.is}):w.createElement("select"),u.multiple?p.multiple=!0:u.size&&(p.size=u.size);break;default:p=typeof u.is=="string"?w.createElement(h,{is:u.is}):w.createElement(h)}}p[Ht]=r,p[_n]=u;e:for(w=r.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===r)break e;for(;w.sibling===null;){if(w.return===null||w.return===r)break e;w=w.return}w.sibling.return=w.return,w=w.sibling}r.stateNode=p;e:switch(Sn(p,h,u),h){case"button":case"input":case"select":case"textarea":u=!!u.autoFocus;break e;case"img":u=!0;break e;default:u=!1}u&&pa(r)}}return Ot(r),tg(r,r.type,t===null?null:t.memoizedProps,r.pendingProps,s),null;case 6:if(t&&r.stateNode!=null)t.memoizedProps!==u&&pa(r);else{if(typeof u!="string"&&r.stateNode===null)throw Error(a(166));if(t=ie.current,Rs(r)){if(t=r.stateNode,s=r.memoizedProps,u=null,h=yn,h!==null)switch(h.tag){case 27:case 5:u=h.memoizedProps}t[Ht]=r,t=!!(t.nodeValue===s||u!==null&&u.suppressHydrationWarning===!0||iS(t.nodeValue,s)),t||Fa(r,!0)}else t=Hu(t).createTextNode(u),t[Ht]=r,r.stateNode=t}return Ot(r),null;case 31:if(s=r.memoizedState,t===null||t.memoizedState!==null){if(u=Rs(r),s!==null){if(t===null){if(!u)throw Error(a(318));if(t=r.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(a(557));t[Ht]=r}else zi(),(r.flags&128)===0&&(r.memoizedState=null),r.flags|=4;Ot(r),t=!1}else s=dh(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=s),t=!0;if(!t)return r.flags&256?(Xn(r),r):(Xn(r),null);if((r.flags&128)!==0)throw Error(a(558))}return Ot(r),null;case 13:if(u=r.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(h=Rs(r),u!==null&&u.dehydrated!==null){if(t===null){if(!h)throw Error(a(318));if(h=r.memoizedState,h=h!==null?h.dehydrated:null,!h)throw Error(a(317));h[Ht]=r}else zi(),(r.flags&128)===0&&(r.memoizedState=null),r.flags|=4;Ot(r),h=!1}else h=dh(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=h),h=!0;if(!h)return r.flags&256?(Xn(r),r):(Xn(r),null)}return Xn(r),(r.flags&128)!==0?(r.lanes=s,r):(s=u!==null,t=t!==null&&t.memoizedState!==null,s&&(u=r.child,h=null,u.alternate!==null&&u.alternate.memoizedState!==null&&u.alternate.memoizedState.cachePool!==null&&(h=u.alternate.memoizedState.cachePool.pool),p=null,u.memoizedState!==null&&u.memoizedState.cachePool!==null&&(p=u.memoizedState.cachePool.pool),p!==h&&(u.flags|=2048)),s!==t&&s&&(r.child.flags|=8192),Cu(r,r.updateQueue),Ot(r),null);case 4:return Te(),t===null&&Eg(r.stateNode.containerInfo),Ot(r),null;case 10:return da(r.type),Ot(r),null;case 19:if(T(Kt),u=r.memoizedState,u===null)return Ot(r),null;if(h=(r.flags&128)!==0,p=u.rendering,p===null)if(h)hl(u,!1);else{if(Gt!==0||t!==null&&(t.flags&128)!==0)for(t=r.child;t!==null;){if(p=cu(t),p!==null){for(r.flags|=128,hl(u,!1),t=p.updateQueue,r.updateQueue=t,Cu(r,t),r.subtreeFlags=0,t=s,s=r.child;s!==null;)Hy(s,t),s=s.sibling;return ce(Kt,Kt.current&1|2),ct&&ca(r,u.treeForkCount),r.child}t=t.sibling}u.tail!==null&&Pt()>Tu&&(r.flags|=128,h=!0,hl(u,!1),r.lanes=4194304)}else{if(!h)if(t=cu(p),t!==null){if(r.flags|=128,h=!0,t=t.updateQueue,r.updateQueue=t,Cu(r,t),hl(u,!0),u.tail===null&&u.tailMode==="hidden"&&!p.alternate&&!ct)return Ot(r),null}else 2*Pt()-u.renderingStartTime>Tu&&s!==536870912&&(r.flags|=128,h=!0,hl(u,!1),r.lanes=4194304);u.isBackwards?(p.sibling=r.child,r.child=p):(t=u.last,t!==null?t.sibling=p:r.child=p,u.last=p)}return u.tail!==null?(t=u.tail,u.rendering=t,u.tail=t.sibling,u.renderingStartTime=Pt(),t.sibling=null,s=Kt.current,ce(Kt,h?s&1|2:s&1),ct&&ca(r,u.treeForkCount),t):(Ot(r),null);case 22:case 23:return Xn(r),_h(),u=r.memoizedState!==null,t!==null?t.memoizedState!==null!==u&&(r.flags|=8192):u&&(r.flags|=8192),u?(s&536870912)!==0&&(r.flags&128)===0&&(Ot(r),r.subtreeFlags&6&&(r.flags|=8192)):Ot(r),s=r.updateQueue,s!==null&&Cu(r,s.retryQueue),s=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(s=t.memoizedState.cachePool.pool),u=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(u=r.memoizedState.cachePool.pool),u!==s&&(r.flags|=2048),t!==null&&T(Bi),null;case 24:return s=null,t!==null&&(s=t.memoizedState.cache),r.memoizedState.cache!==s&&(r.flags|=2048),da(Jt),Ot(r),null;case 25:return null;case 30:return null}throw Error(a(156,r.tag))}function lx(t,r){switch(ch(r),r.tag){case 1:return t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 3:return da(Jt),Te(),t=r.flags,(t&65536)!==0&&(t&128)===0?(r.flags=t&-65537|128,r):null;case 26:case 27:case 5:return ht(r),null;case 31:if(r.memoizedState!==null){if(Xn(r),r.alternate===null)throw Error(a(340));zi()}return t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 13:if(Xn(r),t=r.memoizedState,t!==null&&t.dehydrated!==null){if(r.alternate===null)throw Error(a(340));zi()}return t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 19:return T(Kt),null;case 4:return Te(),null;case 10:return da(r.type),null;case 22:case 23:return Xn(r),_h(),t!==null&&T(Bi),t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 24:return da(Jt),null;case 25:return null;default:return null}}function uv(t,r){switch(ch(r),r.tag){case 3:da(Jt),Te();break;case 26:case 27:case 5:ht(r);break;case 4:Te();break;case 31:r.memoizedState!==null&&Xn(r);break;case 13:Xn(r);break;case 19:T(Kt);break;case 10:da(r.type);break;case 22:case 23:Xn(r),_h(),t!==null&&T(Bi);break;case 24:da(Jt)}}function gl(t,r){try{var s=r.updateQueue,u=s!==null?s.lastEffect:null;if(u!==null){var h=u.next;s=h;do{if((s.tag&t)===t){u=void 0;var p=s.create,w=s.inst;u=p(),w.destroy=u}s=s.next}while(s!==h)}}catch(k){Et(r,r.return,k)}}function Za(t,r,s){try{var u=r.updateQueue,h=u!==null?u.lastEffect:null;if(h!==null){var p=h.next;u=p;do{if((u.tag&t)===t){var w=u.inst,k=w.destroy;if(k!==void 0){w.destroy=void 0,h=r;var j=s,X=k;try{X()}catch(re){Et(h,j,re)}}}u=u.next}while(u!==p)}}catch(re){Et(r,r.return,re)}}function dv(t){var r=t.updateQueue;if(r!==null){var s=t.stateNode;try{tb(r,s)}catch(u){Et(t,t.return,u)}}}function fv(t,r,s){s.props=Fi(t.type,t.memoizedProps),s.state=t.memoizedState;try{s.componentWillUnmount()}catch(u){Et(t,r,u)}}function pl(t,r){try{var s=t.ref;if(s!==null){switch(t.tag){case 26:case 27:case 5:var u=t.stateNode;break;case 30:u=t.stateNode;break;default:u=t.stateNode}typeof s=="function"?t.refCleanup=s(u):s.current=u}}catch(h){Et(t,r,h)}}function Wr(t,r){var s=t.ref,u=t.refCleanup;if(s!==null)if(typeof u=="function")try{u()}catch(h){Et(t,r,h)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof s=="function")try{s(null)}catch(h){Et(t,r,h)}else s.current=null}function hv(t){var r=t.type,s=t.memoizedProps,u=t.stateNode;try{e:switch(r){case"button":case"input":case"select":case"textarea":s.autoFocus&&u.focus();break e;case"img":s.src?u.src=s.src:s.srcSet&&(u.srcset=s.srcSet)}}catch(h){Et(t,t.return,h)}}function ng(t,r,s){try{var u=t.stateNode;Dx(u,t.type,s,r),u[_n]=r}catch(h){Et(t,t.return,h)}}function gv(t){return t.tag===5||t.tag===3||t.tag===26||t.tag===27&&si(t.type)||t.tag===4}function rg(t){e:for(;;){for(;t.sibling===null;){if(t.return===null||gv(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&&si(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 ag(t,r,s){var u=t.tag;if(u===5||u===6)t=t.stateNode,r?(s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s).insertBefore(t,r):(r=s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s,r.appendChild(t),s=s._reactRootContainer,s!=null||r.onclick!==null||(r.onclick=Tr));else if(u!==4&&(u===27&&si(t.type)&&(s=t.stateNode,r=null),t=t.child,t!==null))for(ag(t,r,s),t=t.sibling;t!==null;)ag(t,r,s),t=t.sibling}function Eu(t,r,s){var u=t.tag;if(u===5||u===6)t=t.stateNode,r?s.insertBefore(t,r):s.appendChild(t);else if(u!==4&&(u===27&&si(t.type)&&(s=t.stateNode),t=t.child,t!==null))for(Eu(t,r,s),t=t.sibling;t!==null;)Eu(t,r,s),t=t.sibling}function pv(t){var r=t.stateNode,s=t.memoizedProps;try{for(var u=t.type,h=r.attributes;h.length;)r.removeAttributeNode(h[0]);Sn(r,u,s),r[Ht]=t,r[_n]=s}catch(p){Et(t,t.return,p)}}var ma=!1,en=!1,ig=!1,mv=typeof WeakSet=="function"?WeakSet:Set,dn=null;function cx(t,r){if(t=t.containerInfo,xg=Gu,t=Ry(t),Qf(t)){if("selectionStart"in t)var s={start:t.selectionStart,end:t.selectionEnd};else e:{s=(s=t.ownerDocument)&&s.defaultView||window;var u=s.getSelection&&s.getSelection();if(u&&u.rangeCount!==0){s=u.anchorNode;var h=u.anchorOffset,p=u.focusNode;u=u.focusOffset;try{s.nodeType,p.nodeType}catch{s=null;break e}var w=0,k=-1,j=-1,X=0,re=0,le=t,Q=null;t:for(;;){for(var te;le!==s||h!==0&&le.nodeType!==3||(k=w+h),le!==p||u!==0&&le.nodeType!==3||(j=w+u),le.nodeType===3&&(w+=le.nodeValue.length),(te=le.firstChild)!==null;)Q=le,le=te;for(;;){if(le===t)break t;if(Q===s&&++X===h&&(k=w),Q===p&&++re===u&&(j=w),(te=le.nextSibling)!==null)break;le=Q,Q=le.parentNode}le=te}s=k===-1||j===-1?null:{start:k,end:j}}else s=null}s=s||{start:0,end:0}}else s=null;for(Tg={focusedElem:t,selectionRange:s},Gu=!1,dn=r;dn!==null;)if(r=dn,t=r.child,(r.subtreeFlags&1028)!==0&&t!==null)t.return=r,dn=t;else for(;dn!==null;){switch(r=dn,p=r.alternate,t=r.flags,r.tag){case 0:if((t&4)!==0&&(t=r.updateQueue,t=t!==null?t.events:null,t!==null))for(s=0;s title"))),Sn(p,u,s),p[Ht]=t,Xt(p),u=p;break e;case"link":var w=CS("link","href",h).get(u+(s.href||""));if(w){for(var k=0;kTt&&(w=Tt,Tt=Pe,Pe=w);var F=xy(k,Pe),G=xy(k,Tt);if(F&&G&&(te.rangeCount!==1||te.anchorNode!==F.node||te.anchorOffset!==F.offset||te.focusNode!==G.node||te.focusOffset!==G.offset)){var Y=le.createRange();Y.setStart(F.node,F.offset),te.removeAllRanges(),Pe>Tt?(te.addRange(Y),te.extend(G.node,G.offset)):(Y.setEnd(G.node,G.offset),te.addRange(Y))}}}}for(le=[],te=k;te=te.parentNode;)te.nodeType===1&&le.push({element:te,left:te.scrollLeft,top:te.scrollTop});for(typeof k.focus=="function"&&k.focus(),k=0;ks?32:s,J.T=null,s=fg,fg=null;var p=ri,w=wa;if(ln=0,Ps=ri=null,wa=0,(bt&6)!==0)throw Error(a(331));var k=bt;if(bt|=4,Tv(p.current),_v(p,p.current,w,s),bt=k,wl(0,!1),an&&typeof an.onPostCommitFiberRoot=="function")try{an.onPostCommitFiberRoot(ir,p)}catch{}return!0}finally{fe.p=h,J.T=u,Vv(t,r)}}function Kv(t,r,s){r=lr(s,r),r=Vh(t.stateNode,r,2),t=Xa(t,r,2),t!==null&&(Ze(t,2),Yr(t))}function Et(t,r,s){if(t.tag===3)Kv(t,t,s);else for(;r!==null;){if(r.tag===3){Kv(r,t,s);break}else if(r.tag===1){var u=r.stateNode;if(typeof r.type.getDerivedStateFromError=="function"||typeof u.componentDidCatch=="function"&&(ni===null||!ni.has(u))){t=lr(s,t),s=Wb(2),u=Xa(r,s,2),u!==null&&(Yb(s,u,r,t),Ze(u,2),Yr(u));break}}r=r.return}}function mg(t,r,s){var u=t.pingCache;if(u===null){u=t.pingCache=new fx;var h=new Set;u.set(r,h)}else h=u.get(r),h===void 0&&(h=new Set,u.set(r,h));h.has(s)||(lg=!0,h.add(s),t=yx.bind(null,t,r,s),r.then(t,t))}function yx(t,r,s){var u=t.pingCache;u!==null&&u.delete(r),t.pingedLanes|=t.suspendedLanes&s,t.warmLanes&=~s,Rt===t&&(it&s)===s&&(Gt===4||Gt===3&&(it&62914560)===it&&300>Pt()-xu?(bt&2)===0&&qs(t,0):cg|=s,Bs===it&&(Bs=0)),Yr(t)}function Wv(t,r){r===0&&(r=Ne()),t=Ii(t,r),t!==null&&(Ze(t,r),Yr(t))}function bx(t){var r=t.memoizedState,s=0;r!==null&&(s=r.retryLane),Wv(t,s)}function vx(t,r){var s=0;switch(t.tag){case 31:case 13:var u=t.stateNode,h=t.memoizedState;h!==null&&(s=h.retryLane);break;case 19:u=t.stateNode;break;case 22:u=t.stateNode._retryCache;break;default:throw Error(a(314))}u!==null&&u.delete(r),Wv(t,s)}function Sx(t,r){return rn(t,r)}var Mu=null,Vs=null,yg=!1,$u=!1,bg=!1,ii=0;function Yr(t){t!==Vs&&t.next===null&&(Vs===null?Mu=Vs=t:Vs=Vs.next=t),$u=!0,yg||(yg=!0,Cx())}function wl(t,r){if(!bg&&$u){bg=!0;do for(var s=!1,u=Mu;u!==null;){if(t!==0){var h=u.pendingLanes;if(h===0)var p=0;else{var w=u.suspendedLanes,k=u.pingedLanes;p=(1<<31-sn(42|t)+1)-1,p&=h&~(w&~k),p=p&201326741?p&201326741|1:p?p|2:0}p!==0&&(s=!0,Qv(u,p))}else p=it,p=Ae(u,u===Rt?p:0,u.cancelPendingCommit!==null||u.timeoutHandle!==-1),(p&3)===0||Fe(u,p)||(s=!0,Qv(u,p));u=u.next}while(s);bg=!1}}function wx(){Yv()}function Yv(){$u=yg=!1;var t=0;ii!==0&&Lx()&&(t=ii);for(var r=Pt(),s=null,u=Mu;u!==null;){var h=u.next,p=Xv(u,r);p===0?(u.next=null,s===null?Mu=h:s.next=h,h===null&&(Vs=s)):(s=u,(t!==0||(p&3)!==0)&&($u=!0)),u=h}ln!==0&&ln!==5||wl(t),ii!==0&&(ii=0)}function Xv(t,r){for(var s=t.suspendedLanes,u=t.pingedLanes,h=t.expirationTimes,p=t.pendingLanes&-62914561;0k)break;var re=j.transferSize,le=j.initiatorType;re&&sS(le)&&(j=j.responseEnd,w+=re*(j"u"?null:document;function bS(t,r,s){var u=Fs;if(u&&typeof r=="string"&&r){var h=In(r);h='link[rel="'+t+'"][href="'+h+'"]',typeof s=="string"&&(h+='[crossorigin="'+s+'"]'),yS.has(h)||(yS.add(h),t={rel:t,crossOrigin:s,href:r},u.querySelector(h)===null&&(r=u.createElement("link"),Sn(r,"link",t),Xt(r),u.head.appendChild(r)))}}function Bx(t){Ca.D(t),bS("dns-prefetch",t,null)}function Px(t,r){Ca.C(t,r),bS("preconnect",t,r)}function qx(t,r,s){Ca.L(t,r,s);var u=Fs;if(u&&t&&r){var h='link[rel="preload"][as="'+In(r)+'"]';r==="image"&&s&&s.imageSrcSet?(h+='[imagesrcset="'+In(s.imageSrcSet)+'"]',typeof s.imageSizes=="string"&&(h+='[imagesizes="'+In(s.imageSizes)+'"]')):h+='[href="'+In(t)+'"]';var p=h;switch(r){case"style":p=Ks(t);break;case"script":p=Ws(t)}gr.has(p)||(t=b({rel:"preload",href:r==="image"&&s&&s.imageSrcSet?void 0:t,as:r},s),gr.set(p,t),u.querySelector(h)!==null||r==="style"&&u.querySelector(Al(p))||r==="script"&&u.querySelector(xl(p))||(r=u.createElement("link"),Sn(r,"link",t),Xt(r),u.head.appendChild(r)))}}function Gx(t,r){Ca.m(t,r);var s=Fs;if(s&&t){var u=r&&typeof r.as=="string"?r.as:"script",h='link[rel="modulepreload"][as="'+In(u)+'"][href="'+In(t)+'"]',p=h;switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":p=Ws(t)}if(!gr.has(p)&&(t=b({rel:"modulepreload",href:t},r),gr.set(p,t),s.querySelector(h)===null)){switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(s.querySelector(xl(p)))return}u=s.createElement("link"),Sn(u,"link",t),Xt(u),s.head.appendChild(u)}}}function Vx(t,r,s){Ca.S(t,r,s);var u=Fs;if(u&&t){var h=Ia(u).hoistableStyles,p=Ks(t);r=r||"default";var w=h.get(p);if(!w){var k={loading:0,preload:null};if(w=u.querySelector(Al(p)))k.loading=5;else{t=b({rel:"stylesheet",href:t,"data-precedence":r},s),(s=gr.get(p))&&$g(t,s);var j=w=u.createElement("link");Xt(j),Sn(j,"link",t),j._p=new Promise(function(X,re){j.onload=X,j.onerror=re}),j.addEventListener("load",function(){k.loading|=1}),j.addEventListener("error",function(){k.loading|=2}),k.loading|=4,ju(w,r,u)}w={type:"stylesheet",instance:w,count:1,state:k},h.set(p,w)}}}function Fx(t,r){Ca.X(t,r);var s=Fs;if(s&&t){var u=Ia(s).hoistableScripts,h=Ws(t),p=u.get(h);p||(p=s.querySelector(xl(h)),p||(t=b({src:t,async:!0},r),(r=gr.get(h))&&Ng(t,r),p=s.createElement("script"),Xt(p),Sn(p,"link",t),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},u.set(h,p))}}function Kx(t,r){Ca.M(t,r);var s=Fs;if(s&&t){var u=Ia(s).hoistableScripts,h=Ws(t),p=u.get(h);p||(p=s.querySelector(xl(h)),p||(t=b({src:t,async:!0,type:"module"},r),(r=gr.get(h))&&Ng(t,r),p=s.createElement("script"),Xt(p),Sn(p,"link",t),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},u.set(h,p))}}function vS(t,r,s,u){var h=(h=ie.current)?zu(h):null;if(!h)throw Error(a(446));switch(t){case"meta":case"title":return null;case"style":return typeof s.precedence=="string"&&typeof s.href=="string"?(r=Ks(s.href),s=Ia(h).hoistableStyles,u=s.get(r),u||(u={type:"style",instance:null,count:0,state:null},s.set(r,u)),u):{type:"void",instance:null,count:0,state:null};case"link":if(s.rel==="stylesheet"&&typeof s.href=="string"&&typeof s.precedence=="string"){t=Ks(s.href);var p=Ia(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(Al(t)))&&!p._p&&(w.instance=p,w.state.loading=5),gr.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},gr.set(t,s),p||Wx(h,t,s,w.state))),r&&u===null)throw Error(a(528,""));return w}if(r&&u!==null)throw Error(a(529,""));return null;case"script":return r=s.async,s=s.src,typeof s=="string"&&r&&typeof r!="function"&&typeof r!="symbol"?(r=Ws(s),s=Ia(h).hoistableScripts,u=s.get(r),u||(u={type:"script",instance:null,count:0,state:null},s.set(r,u)),u):{type:"void",instance:null,count:0,state:null};default:throw Error(a(444,t))}}function Ks(t){return'href="'+In(t)+'"'}function Al(t){return'link[rel="stylesheet"]['+t+"]"}function SS(t){return b({},t,{"data-precedence":t.precedence,precedence:null})}function Wx(t,r,s,u){t.querySelector('link[rel="preload"][as="style"]['+r+"]")?u.loading=1:(r=t.createElement("link"),u.preload=r,r.addEventListener("load",function(){return u.loading|=1}),r.addEventListener("error",function(){return u.loading|=2}),Sn(r,"link",s),Xt(r),t.head.appendChild(r))}function Ws(t){return'[src="'+In(t)+'"]'}function xl(t){return"script[async]"+t}function wS(t,r,s){if(r.count++,r.instance===null)switch(r.type){case"style":var u=t.querySelector('style[data-href~="'+In(s.href)+'"]');if(u)return r.instance=u,Xt(u),u;var h=b({},s,{"data-href":s.href,"data-precedence":s.precedence,href:null,precedence:null});return u=(t.ownerDocument||t).createElement("style"),Xt(u),Sn(u,"style",h),ju(u,s.precedence,t),r.instance=u;case"stylesheet":h=Ks(s.href);var p=t.querySelector(Al(h));if(p)return r.state.loading|=4,r.instance=p,Xt(p),p;u=SS(s),(h=gr.get(h))&&$g(u,h),p=(t.ownerDocument||t).createElement("link"),Xt(p);var w=p;return w._p=new Promise(function(k,j){w.onload=k,w.onerror=j}),Sn(p,"link",u),r.state.loading|=4,ju(p,s.precedence,t),r.instance=p;case"script":return p=Ws(s.src),(h=t.querySelector(xl(p)))?(r.instance=h,Xt(h),h):(u=s,(h=gr.get(p))&&(u=b({},s),Ng(u,h)),t=t.ownerDocument||t,h=t.createElement("script"),Xt(h),Sn(h,"link",u),t.head.appendChild(h),r.instance=h);case"void":return null;default:throw Error(a(443,r.type))}else r.type==="stylesheet"&&(r.state.loading&4)===0&&(u=r.instance,r.state.loading|=4,ju(u,s.precedence,t));return r.instance}function ju(t,r,s){for(var u=s.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),h=u.length?u[u.length-1]:null,p=h,w=0;w title"):null)}function Yx(t,r,s){if(s===1||r.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof r.precedence!="string"||typeof r.href!="string"||r.href==="")break;return!0;case"link":if(typeof r.rel!="string"||typeof r.href!="string"||r.href===""||r.onLoad||r.onError)break;return r.rel==="stylesheet"?(t=r.disabled,typeof r.precedence=="string"&&t==null):!0;case"script":if(r.async&&typeof r.async!="function"&&typeof r.async!="symbol"&&!r.onLoad&&!r.onError&&r.src&&typeof r.src=="string")return!0}return!1}function _S(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function Xx(t,r,s,u){if(s.type==="stylesheet"&&(typeof u.media!="string"||matchMedia(u.media).matches!==!1)&&(s.state.loading&4)===0){if(s.instance===null){var h=Ks(u.href),p=r.querySelector(Al(h));if(p){r=p._p,r!==null&&typeof r=="object"&&typeof r.then=="function"&&(t.count++,t=Bu.bind(t),r.then(t,t)),s.state.loading|=4,s.instance=p,Xt(p);return}p=r.ownerDocument||r,u=SS(u),(h=gr.get(h))&&$g(u,h),p=p.createElement("link"),Xt(p);var w=p;w._p=new Promise(function(k,j){w.onload=k,w.onerror=j}),Sn(p,"link",u),s.instance=p}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(s,r),(r=s.state.preload)&&(s.state.loading&3)===0&&(t.count++,s=Bu.bind(t),r.addEventListener("load",s),r.addEventListener("error",s))}}var Ig=0;function Jx(t,r){return t.stylesheets&&t.count===0&&qu(t,t.stylesheets),0Ig?50:800)+r);return t.unsuspend=s,function(){t.unsuspend=null,clearTimeout(u),clearTimeout(h)}}:null}function Bu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)qu(this,this.stylesheets);else if(this.unsuspend){var t=this.unsuspend;this.unsuspend=null,t()}}}var Pu=null;function qu(t,r){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Pu=new Map,r.forEach(Qx,t),Pu=null,Bu.call(t))}function Qx(t,r){if(!(r.state.loading&4)){var s=Pu.get(t);if(s)var u=s.get(null);else{s=new Map,Pu.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(),Zu.exports=VS(),Zu.exports}var rd=FS();const ad=Jr(rd),Js=[],KS=50;let id=!1;function Qg(){try{return window.G7Core?.devTools}catch{return}}function Yi(o,e,n){const a=Qg();if(id&&a?.isEnabled?.()){a.trackLog?.(o,e,n);return}id||(o==="error"||o==="warn")&&Js.length{n.isDebugEnabled()&&console.log(e,...a),Yi("log",o,a)},warn:(...a)=>{n.isDebugEnabled()&&console.warn(e,...a),Yi("warn",o,a)},error:(...a)=>{n.isDebugEnabled()&&console.error(e,...a),Yi("error",o,a)}}}Qs.getInstance();const Xi=ut("networkResilience"),Zg=2,ep=300,tp=2e3,WS=15e3;function od(o){return o?.name==="AbortError"}function np(o){return od(o)?!1:o instanceof TypeError}let Ol=!1,rp=!1;function ld(){return Ol}function YS(){typeof window>"u"||rp||(rp=!0,window.addEventListener("pagehide",()=>{Ol=!0}),window.addEventListener("pageshow",o=>{o.persisted&&(Ol=!1)}),window.addEventListener("beforeunload",()=>{Ol=!0}))}function ap(o,e,n){const a=Math.min(e*Math.pow(2,o),n),i=a*.25*(Math.random()*2-1);return Math.max(0,Math.round(a+i))}function ip(o){return new Promise(e=>setTimeout(e,o))}async function Ll(o,e={}){const{retries:n=Zg,baseDelayMs:a=ep,maxDelayMs:i=tp,timeoutMs:l=WS,label:c=o,init:d}=e,f=n+1;let g;for(let m=0;m0?new AbortController:null;try{const _={...d};if(v){const x=d?.signal;x&&(x.aborted?v.abort():x.addEventListener("abort",()=>v.abort(),{once:!0})),_.signal=v.signal,S=setTimeout(()=>{b=!0,v.abort()},l)}return await fetch(o,_)}catch(_){if(g=_,od(_)&&!b||!(b||np(_)))throw _;if(ld())throw Xi.warn(`Document unloading, aborting retries: ${c}`),_;if(m===f-1)throw Xi.warn(`All ${f} attempts failed: ${c}`,_),_;const L=ap(m,a,i);Xi.warn(`Network failure (attempt ${m+1}/${f}), retrying in ${L}ms: ${c}`),await ip(L)}finally{S!==void 0&&clearTimeout(S)}}throw g}async function sp(o,e={},n={}){const{retries:a=Zg,baseDelayMs:i=ep,maxDelayMs:l=tp,label:c=o}=n,d=a+1;for(let f=0;f{const i=document.createElement("script");i.src=o,i.async=!1;for(const[l,c]of Object.entries(e))l==="id"?i.id=c:i.setAttribute(l,c);i.onload=()=>n(),i.onerror=()=>a(new Error(`Failed to load script: ${o}`)),document.head.appendChild(i)})}const op="extension",Ji="extensionless",JS="file";function QS(){const o=globalThis?.G7Config;if(globalThis?.__g7AssetUrlMode===Ji)return Ji;const n=o?.assetUrlMode;return n===Ji||n===op?n:o?.settings?.general?.asset_url_mode===Ji?Ji:op}function lp(){return QS()===Ji}function $r(o,e,n,a){const i=o.replace(/\/+$/,""),l=e.replace(/^\.+/,""),c=lp()?i:`${i}.${l}`,d=[];return a&&d.push(a.replace(/^[?&]+/,"")),n!=null&&n!==""&&d.push(`v=${n}`),d.length>0?`${c}?${d.join("&")}`:c}function Ea(o){if(!o||!lp())return o;const e=globalThis?.location?.origin,n=e&&o.startsWith(e)?o.slice(e.length):o;if(!n.startsWith("/api/"))return o;const[a,i]=ZS(n),l=a.match(/^\/api\/(modules|plugins)\/bundle\.(js|css)$/);if(l)return cp(`/api/${l[1]}/bundle/${l[2]}`,i);const c=a.match(/^\/api\/(templates|modules|plugins)\/assets\/([^/]+)\/(.+)$/);if(c){const[,f,g,m]=c,b=`${JS}=${encodeURIComponent(decodeURIComponent(m))}`;return`/api/${f}/assets/${g}?${b}${i?`&${i}`:""}`}const d=a.match(/^(\/api\/.+)\.(json|js|css)$/);return d?cp(d[1],i):o}function ZS(o){const e=o.indexOf("?");return e===-1?[o,""]:[o.slice(0,e),o.slice(e+1)]}function cp(o,e){return e?`${o}?${e}`:o}const Nr=ut("ComponentRegistry");class cn extends Error{constructor(n,a,i){super(n);$(this,"code");$(this,"details");this.code=a,this.details=i,this.name="ComponentRegistryError"}}const Vn=class Vn{constructor(){$(this,"registry",{});$(this,"manifest",null);$(this,"loadingState","idle");$(this,"error",null);$(this,"templateId",null);$(this,"templateType",null)}static getInstance(){return Vn.instance||(Vn.instance=new Vn),Vn.instance}static createIsolatedInstance(){return new Vn}static resetInstance(){Vn.instance=null}async loadComponents(e,n){if(this.loadingState==="loading")throw new cn("Components are already being loaded","LOADING_IN_PROGRESS");if(this.loadingState==="loaded"&&this.templateId===e&&this.templateType===n){Nr.log("Components already loaded for template:",e,n);return}this.loadingState="loading",this.templateId=e,this.templateType=n,this.error=null;try{await this.loadManifest(),await this.loadComponentBundle(),this.loadingState="loaded",Nr.log("Successfully loaded components:",Object.keys(this.registry).length)}catch(a){throw this.loadingState="error",this.error=a instanceof Error?a:new Error(String(a)),new cn(`Failed to load components: ${this.error.message}`,"LOAD_FAILED",{originalError:this.error})}}async loadManifest(){try{if(!this.templateId)throw new cn("Template ID not set","TEMPLATE_ID_NOT_SET");const e=`${this.templateId}:${this.templateType}`;if(Vn.manifestCache.has(e)){this.manifest=Vn.manifestCache.get(e),Nr.log("Manifest loaded from cache:",this.manifest.templateId);return}const n=$r(`/api/templates/${this.templateId}/components`,"json"),a=await Ll(n,{label:"components.json"});if(!a.ok)throw new cn(`Failed to fetch manifest: ${a.status} ${a.statusText}`,"MANIFEST_FETCH_FAILED",{status:a.status,statusText:a.statusText});const i=await a.json();this.validateManifest(i),this.manifest=i,Vn.manifestCache.set(e,i),Nr.log("Manifest loaded and cached:",i.templateId)}catch(e){throw e instanceof cn?e:new cn("Failed to load component manifest","MANIFEST_LOAD_FAILED",{originalError:e})}}validateManifest(e){if(!e.version)throw new cn("Manifest missing required field: version","MANIFEST_INVALID",{field:"version"});if(!e.templateId)throw new cn("Manifest missing required field: templateId","MANIFEST_INVALID",{field:"templateId"});if(!e.components||typeof e.components!="object")throw new cn("Manifest missing required field: components","MANIFEST_INVALID",{field:"components"});const n=["basic","composite","layout"];for(const a of n){if(!Array.isArray(e.components[a]))throw new cn(`Manifest field 'components.${a}' must be an array`,"MANIFEST_INVALID",{field:`components.${a}`,value:e.components[a]});e.components[a].forEach((i,l)=>{if(!i.name||typeof i.name!="string")throw new cn(`Invalid component metadata at ${a}[${l}]: missing or invalid 'name'`,"MANIFEST_INVALID",{type:a,index:l,metadata:i});if(!i.type||typeof i.type!="string")throw new cn(`Invalid component metadata at ${a}[${l}]: missing or invalid 'type'`,"MANIFEST_INVALID",{type:a,index:l,metadata:i})})}Nr.log("Manifest validation passed")}async loadComponentBundle(){try{if(!this.templateId)throw new cn("Template ID not set","TEMPLATE_ID_NOT_SET");const e=this.getGlobalVariableName(),n=window[e];if(!n||typeof n!="object")throw new cn(`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(n),Nr.log("Component bundle loaded from global variable:",e)}catch(e){throw e instanceof cn?e:new cn("Failed to load component bundle","BUNDLE_LOAD_FAILED",{originalError:e})}}getGlobalVariableName(){if(!this.templateId)throw new cn("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 cn("Manifest not loaded","MANIFEST_NOT_LOADED");const n=["basic","composite","layout"];for(const a of n){const i=this.manifest.components[a]||[];for(const l of i){const c=l.name,d=e[c];if(!d){Nr.warn(`Component '${c}' not found in bundle`);continue}this.registerComponent(c,d,l)}}}registerComponent(e,n,a){this.registry[e]&&Nr.warn(`Component '${e}' already registered, overwriting`);const i=Ye.memo(n);this.registry[e]={component:i,metadata:a},Nr.log(`[ComponentRegistry] Registered component: ${e} (${a.type})`)}getComponent(e){const n=this.registry[e];return n?n.component:null}getMetadata(e){const n=this.registry[e];return n?n.metadata:null}hasComponent(e){return e in this.registry}getComponentsByType(e){return Object.entries(this.registry).filter(([n,a])=>a.metadata.type===e).map(([n,a])=>n)}getAllComponents(){return Object.keys(this.registry)}getComponentMap(){const e={};for(const[n,a]of Object.entries(this.registry))e[n]=a.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,Nr.log("Registry cleared")}};$(Vn,"instance",null),$(Vn,"manifestCache",new Map);let pr=Vn;const up=ut("TranslationEngine");class cd extends Error{constructor(n,a,i){super(n);$(this,"key");$(this,"locale");this.key=a,this.locale=i,this.name="TranslationError"}}const Mn=class Mn{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 Mn.instance||(Mn.instance=new Mn(e)),Mn.instance}static resetInstance(){Mn.instance=null}setCacheVersion(e){this.cacheVersion!==e&&(up.log("Cache version updated:",this.cacheVersion,"->",e),this.cacheVersion=e,this.cache.clear())}getCacheVersion(){return this.cacheVersion}async loadTranslations(e,n,a="/api",i=!1){const l=`${e}:${n}`;if(!i){const c=this.getFromCache(l);if(c)return this.translations.set(l,c),c}try{const c=[];i&&c.push(`_=${Date.now()}`);const d=$r(`${a}/templates/${e}/lang/${n}`,"json",this.cacheVersion>0?this.cacheVersion:null,c.length>0?c.join("&"):void 0),f=await fetch(d);if(!f.ok)throw new cd(`Failed to load translations: ${f.statusText}`,void 0,n);const m=await f.json();return this.saveToCache(l,m),this.translations.set(l,m),m}catch(c){throw new cd(`Failed to fetch translations for ${n}: ${c instanceof Error?c.message:String(c)}`,void 0,n)}}resolveTranslations(e,n,a){let i=e;const l=5;let c=0;for(;c"="+this.translate(m,n,void 0,a)),i===d)break;c++}return i.replace(Mn.TRANSLATION_PATTERN,(d,f,g)=>{const{cleanedParams:m,trailing:b}=this.separateTrailingText(g);return this.translate(f,n,m,a)+b})}translate(e,n,a,i){const l=this.getTranslation(e,n),c=a&&this.cleanParamsStr(a);if(c){const d=this.parseParams(c,i);return this.replaceParams(l,d)}return l}getTranslation(e,n){const{templateId:a,locale:i}=n,l=`${a}:${i}`,c=this.translations.get(l);if(c){const d=this.getNestedValue(c,e);if(d!==null)return d}if(i!==this.options.fallbackLocale){const d=`${a}:${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,n){const a=n.split(".");let i=e;for(const l of a){if(i==null||typeof i!="object")return null;i=i[l]}return typeof i=="string"?i:null}setTranslationValue(e,n,a,i){const l=`${e}:${n}`,c=this.translations.get(l)??{},d=a.split(".");let f=c;for(let g=0;g(l.push(f),`__PLACEHOLDER_${l.length-1}__`)).matchAll(Mn.PARAM_PATTERN);for(const f of d){const[,g,m]=f,b=m.replace(/__PLACEHOLDER_(\d+)__/g,(S,v)=>l[parseInt(v,10)]);a[g.trim()]=this.resolveParamValue(b.trim(),n)}return a}resolveParamValue(e,n){if(e.startsWith("{{")&&e.endsWith("}}")){const a=e.slice(2,-2).trim();if(/[|&()[\]!?:+\-*/%<>=\s]/.test(a)&&n)try{const l=md.evaluateExpression(a,n);return String(l??"")}catch(l){return up.error("Expression evaluation failed:",a,l),""}else{const l=this.getNestedDataValue(n,a);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 a=e.match(/(\s+[^\p{L}\w=|&\s][^\p{L}\w=]*\s*)$/u);return a?{cleanedParams:e.slice(0,-a[1].length),trailing:a[1]}:{cleanedParams:e,trailing:""}}cleanParamsStr(e){return this.separateTrailingText(e).cleanedParams||""}getNestedDataValue(e,n){if(!e)return;const a=n.split(".");let i=e;for(const l of a){if(i==null)return;i=i[l]}return i}replaceParams(e,n){let a=e;for(const[i,l]of Object.entries(n)){const c=new RegExp(`\\{\\{${i}\\}\\}`,"g");a=a.replace(c,String(l));const d=new RegExp(`\\{${i}\\}`,"g");a=a.replace(d,String(l))}return a}getFromCache(e){const n=this.cache.get(e);return n?Date.now()-n.timestamp>this.options.cacheTTL?(this.cache.delete(e),null):n.data:null}saveToCache(e,n){this.cache.set(e,{data:n,timestamp:Date.now()})}clearCache(){this.cache.clear(),this.translations.clear()}pruneCache(){const e=Date.now(),n=[];for(const[a,i]of this.cache.entries())e-i.timestamp>this.options.cacheTTL&&n.push(a);for(const a of n)this.cache.delete(a)}getCacheStats(){const e=Date.now();let n=0;for(const a of this.cache.values())e-a.timestamp>this.options.cacheTTL&&n++;return{size:this.cache.size,expired:n}}};$(Mn,"instance",null),$(Mn,"TRANSLATION_PATTERN",/\$t:(?:defer:)?([a-zA-Z0-9._-]+)(\|(?:(?!\$t:).)+)?/g),$(Mn,"NESTED_TRANSLATION_PARAM_PATTERN",/=(\$t:([a-zA-Z0-9._-]+))(?=[|&\s]|$)/g),$(Mn,"PARAM_PATTERN",/([^=|&]+)=([^|&]+)/g);let _a=Mn,ud=null;function ew(o){return ud||(ud=new _a(o)),ud}const dp=Object.freeze(Object.defineProperty({__proto__:null,TranslationEngine:_a,TranslationError:cd,getTranslationEngine:ew},Symbol.toStringTag,{value:"Module"})),Qi=ut("PipeRegistry");function fp(o,e){const n=o.getFullYear(),a=String(o.getMonth()+1).padStart(2,"0"),i=String(o.getDate()).padStart(2,"0"),l=String(o.getHours()).padStart(2,"0"),c=String(o.getMinutes()).padStart(2,"0"),d=String(o.getSeconds()).padStart(2,"0");return e.replace("YYYY",String(n)).replace("YY",String(n).slice(-2)).replace("MM",a).replace("M",String(o.getMonth()+1)).replace("DD",i).replace("D",String(o.getDate())).replace("HH",l).replace("H",String(o.getHours())).replace("mm",c).replace("m",String(o.getMinutes())).replace("ss",d).replace("s",String(o.getSeconds()))}function tw(o,e="ko"){const a=new Date().getTime()-o.getTime(),i=Math.floor(a/1e3),l=Math.floor(i/60),c=Math.floor(l/60),d=Math.floor(c/24),f=Math.floor(d/7),g=Math.floor(d/30),m=Math.floor(d/365);return e==="ko"?i<60?"방금 전":l<60?`${l}분 전`:c<24?`${c}시간 전`:d<7?`${d}일 전`:f<4?`${f}주 전`:g<12?`${g}개월 전`:`${m}년 전`:i<60?"just now":l<60?`${l} minute${l===1?"":"s"} ago`:c<24?`${c} hour${c===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 dd(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 Zs={date:{fn:(o,e="YYYY-MM-DD")=>{const n=dd(o);return n?fp(n,e):""},description:"날짜 포맷 (기본: YYYY-MM-DD)"},datetime:{fn:(o,e="YYYY-MM-DD HH:mm")=>{const n=dd(o);return n?fp(n,e):""},description:"날짜+시간 포맷 (기본: YYYY-MM-DD HH:mm)"},relativeTime:{fn:(o,e="ko")=>{const n=dd(o);return n?tw(n,e):""},description:'상대 시간 표시 (예: "3분 전")'},number:{fn:(o,e)=>{const n=Number(o);if(isNaN(n))return String(o??"");const a={};return e!==void 0&&(a.minimumFractionDigits=e,a.maximumFractionDigits=e),n.toLocaleString(void 0,a)},description:"숫자 포맷 (천단위 구분, 선택적 소수점)"},truncate:{fn:(o,e=100,n="...")=>typeof o!="string"?String(o??""):o.length<=e?o:o.slice(0,e)+n,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,n)=>Array.isArray(o)?Array.isArray(e)?o.filter(a=>{const i=n?a?.[n]:a;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:"다국어 객체에서 로케일에 맞는 값 추출"}},Zi=new Map,vi=class vi{static getInstance(){return vi.instance||(vi.instance=new vi),vi.instance}register(e,n,a){if(Zs[e]){Qi.warn(`[PipeRegistry] 내장 파이프를 덮어쓸 수 없습니다: ${e}`);return}Zi.set(e,{fn:n,description:a}),Qi.log(`[PipeRegistry] 커스텀 파이프 등록됨: ${e}`)}unregister(e){if(Zs[e])return Qi.warn(`[PipeRegistry] 내장 파이프는 해제할 수 없습니다: ${e}`),!1;const n=Zi.delete(e);return n&&Qi.log(`[PipeRegistry] 커스텀 파이프 해제됨: ${e}`),n}get(e){const n=Zs[e];return n?n.fn:Zi.get(e)?.fn}has(e){return!!Zs[e]||Zi.has(e)}execute(e,n,a=[]){const i=this.get(e);if(!i)return Qi.warn(`[PipeRegistry] 알 수 없는 파이프: ${e}`),n;try{return i(n,...a)}catch(l){return Qi.error(`[PipeRegistry] 파이프 실행 오류 (${e}):`,l),n}}list(){const e=[];for(const[n,a]of Object.entries(Zs))e.push({name:n,description:a.description,type:"built-in"});for(const[n,a]of Zi.entries())e.push({name:n,description:a.description,type:"custom"});return e.sort((n,a)=>n.name.localeCompare(a.name))}clearCustomPipes(){Zi.clear()}};$(vi,"instance",null);let Ml=vi;Ml.getInstance();function nw(o){const e=o.trim(),n=e.indexOf("(");if(n===-1)return{name:e,args:[]};const a=e.slice(0,n).trim(),i=e.slice(n+1,-1);if(!i.trim())return{name:a,args:[]};const l=[];let c="",d=null,f=0;for(let g=0;g0?i[g-1]:"")==="\\"){c+=m;continue}if((m==='"'||m==="'")&&!d){d=m;continue}if(m===d){d=null;continue}if(d){c+=m;continue}if(m==="("||m==="["||m==="{"){f++,c+=m;continue}if(m===")"||m==="]"||m==="}"){f--,c+=m;continue}if(m===","&&f===0){l.push(hp(c.trim())),c="";continue}c+=m}return c.trim()&&l.push(hp(c.trim())),{name:a,args:l}}function hp(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 rw(o){const e=[];let n="",a=null,i=0;for(let l=0;l0?o[l-1]:"",f=l0?o[a-1]:"",c=a0){a--;continue}return null}}return a===0?e.trim():null}function iw(o){const e=[];if(typeof o!="string")return e;for(let n=0;n0){i--;continue}if(o[c+1]==="}"){l=c;break}break}}l!==-1&&(e.push({start:n,end:l+2,expr:o.slice(n+2,l)}),n=l+1)}return e}function eo(o){return/[?:|&!+\-*/<>=()[\]{}]/.test(o)}function gp(o){const e=typeof o=="string"?o.trim():"";return e===""?"empty":fd.has(e)?"literal":Pn(e)?"pipe":eo(e)?"expression":"path"}function hd(o,e,n,a){const i=typeof o=="string"?o.trim():"",l=gp(i),c=a?.skipCache?{skipCache:!0}:void 0;if(l==="empty"){a?.onEmpty?.(o);return}if(l==="literal")return fd.get(i);try{return l==="pipe"?n.evaluatePipeExpression(i,e,c,a?.trackingInfo):l==="expression"?n.evaluateExpression(i,e,a?.trackingInfo):n.resolve(i,e,c,a?.trackingInfo)}catch(d){if(a?.onError)return a.onError(d,i);throw d}}const er="raw:";function pp(o){return o.startsWith(er)?o.slice(er.length):o}const to="﷐",fi="﷑",xa="﷒";function no(o){return to+o+fi}function $l(o){return o.length>=2&&o.charCodeAt(0)===64976&&o.charCodeAt(o.length-1)===64977}function Nl(o){return o.includes(to)}function gd(o){return o.slice(1,-1)}function es(o){if(typeof o=="string")return no(o);if(Array.isArray(o))return o.map(es);if(o&&typeof o=="object"){const e={};for(const[n,a]of Object.entries(o))e[n]=es(a);return e}return o}function Ta(o){if(typeof o=="string")return $l(o)?gd(o):Nl(o)||o.includes(fi)?o.split(to).join("").split(fi).join(""):o;if(Array.isArray(o)){let e=!1;const n=o.map(a=>{const i=Ta(a);return i!==a&&(e=!0),i});return e?n:o}if(o&&typeof o=="object"){if(o.$$typeof!==void 0)return o;let e=!1;const n={};for(const[a,i]of Object.entries(o)){const l=Ta(i);l!==i&&(e=!0),n[a]=l}return e?n:o}return o}const Ra=ut("DataBindingEngine"),sw=/^[$A-Za-z_][$A-Za-z0-9_]*$/,ow=new Set(["break","case","catch","class","const","continue","debugger","default","delete","do","else","enum","export","extends","false","finally","for","function","if","implements","import","in","instanceof","interface","let","new","null","package","private","protected","public","return","static","super","switch","this","throw","true","try","typeof","var","void","while","with","yield","arguments","eval"]);function ro(){try{return window.G7Core?.devTools}catch{return}}class pd extends Error{constructor(n,a,i){super(n);$(this,"path");$(this,"context");this.path=a,this.context=i,this.name="DataBindingError"}}const ta=class ta{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,n){this.isRenderCycleCacheActive()&&this.renderCycleCache.set(e,n)}resolveBindings(e,n,a,i){const l={...this.defaultOptions,...a},c=ro(),d=n._computed&&!n.$computed?{...n,$computed:n._computed}:n,f=(S,v)=>{const _=v.trim();let A=!1,x=_;if(_.startsWith(er)&&(A=!0,x=_.slice(er.length)),Pn(x))try{const P=this.evaluatePipeExpression(x,d,l,{...i,method:"resolveBindings",displayExpression:`{{${_}}}`}),K=this.formatValue(P);return A?no(K):K}catch(P){return Ra.error("Pipe expression evaluation failed:",x,P),S}if(eo(x)){const P=c?.isEnabled()?performance.now():0;try{let K,ge=!1;if(l.skipCache)K=this.evaluateExpression(x,d);else{const Se=`expr:${x}`,Ue=this.getFromRenderCycleCache(Se);Ue!==void 0?(K=Ue,ge=!0):(K=this.evaluateExpression(x,d),this.saveToRenderCycleCache(Se,K))}if(c?.isEnabled()){const Se=performance.now()-P;c.trackExpressionEval({expression:`{{${_}}}`,result:this.sanitizeResultForTracking(K),resultType:this.getResultType(K),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:ge,duration:Se,method:"resolveBindings",skipCache:l.skipCache})}const Ee=this.formatValue(K);return A?no(Ee):Ee}catch(K){return Ra.error("Expression evaluation failed:",x,K),S}}if(l.skipCache){const P=c?.isEnabled()?performance.now():0,K=this.resolvePath(x,d,l);if(c?.isEnabled()){const Ee=performance.now()-P;c.trackExpressionEval({expression:`{{${_}}}`,result:this.sanitizeResultForTracking(K),resultType:this.getResultType(K),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!1,duration:Ee,method:"resolveBindings",skipCache:!0})}const ge=this.formatValue(K);return A?no(ge):ge}const M=x.startsWith("_global")||x.startsWith("_local")||x.startsWith("_isolated")||x.startsWith("$parent"),R=c?.isEnabled()?performance.now():0;let D,B=!1;if(M){const P=this.getFromRenderCycleCache(x);P!==void 0?(D=P,B=!0):(D=this.resolvePath(x,d,l),this.saveToRenderCycleCache(x,D))}else{const P=this.getFromCache(x);P!==void 0?(D=P,B=!0):(D=this.resolvePath(x,d,l),this.saveToCache(x,D))}if(c?.isEnabled()){const P=performance.now()-R;c.trackExpressionEval({expression:`{{${_}}}`,result:this.sanitizeResultForTracking(D),resultType:this.getResultType(D),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:B,duration:P,method:"resolveBindings",skipCache:l.skipCache})}const q=this.formatValue(D);return A?no(q):q},g=iw(e);if(g.length===0)return e;let m="",b=0;for(const S of g)m+=e.slice(b,S.start),m+=f(e.slice(S.start,S.end),S.expr),b=S.end;return m+e.slice(b)}evaluatePipeExpression(e,n,a,i){const l={...this.defaultOptions,...a},c=ro(),d=c?.isEnabled()?performance.now():0,f=n._computed&&!n.$computed?{...n,$computed:n._computed}:n,[g,m]=rw(e);let b,S=!1;const v=eo(g),_=g.startsWith("_global")||g.startsWith("_local")||g.startsWith("_isolated")||g.startsWith("$parent");if(l.skipCache)v?b=this.evaluateExpression(g,f):b=this.resolvePath(g,f,l);else if(v){const x=this.getFromRenderCycleCache(`expr:${g}`);x!==void 0?(b=x,S=!0):(b=this.evaluateExpression(g,f),this.saveToRenderCycleCache(`expr:${g}`,b))}else if(_){const x=this.getFromRenderCycleCache(g);x!==void 0?(b=x,S=!0):(b=this.resolvePath(g,f,l),this.saveToRenderCycleCache(g,b))}else{const x=this.getFromCache(g);x!==void 0?(b=x,S=!0):(b=this.resolvePath(g,f,l),this.saveToCache(g,b))}const A=aw(b,m);if(c?.isEnabled()){const x=performance.now()-d;c.trackExpressionEval({expression:i?.displayExpression??`{{${e}}}`,result:this.sanitizeResultForTracking(A),resultType:this.getResultType(A),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:S,duration:x,method:i?.method??"evaluatePipeExpression",skipCache:l.skipCache})}return A}resolve(e,n,a,i){const l={...this.defaultOptions,...a},c=ro(),d=c?.isEnabled()?performance.now():0;if(l.skipCache){const b=this.resolvePath(e,n,l);return c?.isEnabled()&&c.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,c?.isEnabled()&&c.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,c?.isEnabled()&&c.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,n,l);return f?this.saveToRenderCycleCache(e,m):this.saveToCache(e,m),c?.isEnabled()&&c.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,n,a,i=0,l=new WeakSet){if(typeof e!="string"||e.trim()===""){Ra.warn("resolvePath: 빈 경로가 전달되었습니다 — undefined 로 해석합니다.");return}if(a.maxDepth&&i>a.maxDepth){if(a.detectCircular)throw new pd(`Maximum depth exceeded (${a.maxDepth}). Possible circular reference.`,e,n);return a.defaultValue}const c=this.parsePath(e);let d=n;for(let f=0;fta.CACHE_EXPIRY){this.cache.delete(e),a?.isEnabled()&&a.recordCacheMiss();return}return a?.isEnabled()&&a.recordCacheHit(),n.value}saveToCache(e,n){this.cache.set(e,{value:n,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}resolveObject(e,n,a){if(this.isSwitchExpression(e)){const d=e;return this.resolveSwitch(d,n,a)}if(this.isActionDefinition(e))return{...e};if("iteration"in e)return{...e};const i={},c=[...["cellChildren","expandChildren","expandContext","render"],...a?.skipBindingKeys||[]];for(const[d,f]of Object.entries(e)){if(c.includes(d)){i[d]=f;continue}try{this.resolveObjectEntry(i,d,f,n,a)}catch(g){Ra.warn(`resolveObject: 값 해석 실패 (key: ${d}):`,g),i[d]=void 0}}return i}resolveObjectEntry(e,n,a,i,l){if(typeof a=="string"){const c=Aa(a);if(c!==null){const d=c.trim();let f=!1,g=d;d.startsWith(er)&&(f=!0,g=d.slice(er.length));let m;switch(gp(g)){case"empty":Ra.warn(`resolveObject: 빈 바인딩 \`{{}}\` (key: ${n}) — undefined 로 해석합니다.`),m=void 0;break;case"literal":m=fd.get(g);break;case"pipe":m=this.evaluatePipeExpression(g,i,l);break;case"expression":m=this.evaluateExpression(g,i,l);break;default:m=this.resolve(g,i,l)}e[n]=f&&m!=null?es(m):m}else e[n]=this.resolveBindings(a,i,l)}else Array.isArray(a)?e[n]=a.map(c=>typeof c=="string"?this.resolveBindings(c,i,l):typeof c=="object"&&c!==null?this.resolveObject(c,i,l):c):a&&typeof a=="object"?e[n]=this.resolveObject(a,i,l):e[n]=a}clearCache(){this.cache.clear(),this.expressionFnCache.clear()}invalidateCacheByKeys(e){for(const n of this.cache.keys())for(const a of e)if(n===a||n.startsWith(`${a}.`)||n.startsWith(`${a}[`)){this.cache.delete(n);break}}pruneCache(){const e=Date.now();for(const[n,a]of this.cache.entries())e-a.timestamp>ta.CACHE_EXPIRY&&this.cache.delete(n)}getCacheStats(){const e=Date.now();let n=0;for(const a of this.cache.values())e-a.timestamp>ta.CACHE_EXPIRY&&n++;return{size:this.cache.size,expired:n}}evaluateExpression(e,n,a){const i=ro(),l=i?.isEnabled()?performance.now():0;i?.isEnabled()&&i.trackBindingEval();try{let c=this.preprocessOptionalChaining(e);c=this.preprocessTranslationTokens(c);const d=this.extractVariablesFromExpression(c),f={...n};for(const D of d)D in f||(f[D]=void 0);n._computed&&!f.$computed&&(f.$computed=n._computed);let g=n.$templateId,m=n.$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,B)=>{if(D==null&&!B)return"";if(typeof D=="string")return D;if(D&&typeof D=="object"&&D[b])return D[b];if(B&&typeof B=="string"){const q=f.$t?f.$t(B):B;if(q&&q!==B)return q}return D&&typeof D=="object"?D.ko||D.en||Object.values(D)[0]||"":D==null?"":String(D)};const S=typeof window<"u"?window.G7Core:void 0;f.$uuid=()=>S?.uuid?S.uuid():typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,D=>{const B=Math.random()*16|0;return(D==="x"?B:B&3|8).toString(16)});const v={templateId:g||"",locale:b};f.$t=D=>{if(!D||typeof D!="string")return"";try{return _a.getInstance().translate(D,v)}catch(B){return Ra.warn("$t() translation failed for key:",D,B),D}},f.$get=(D,B,q=void 0)=>{if(D==null)return q;const P=Array.isArray(B)?B:[B];if(P.length===0)return D;let K=D;for(const ge of P){if(K==null||ge==null)return q;K=K[ge]}return K??q};const _=[],A=[];for(const[D,B]of Object.entries(f))!sw.test(D)||ow.has(D)||(_.push(D),A.push(B));const x=`${c}|${_.join(",")}`;let L=this.expressionFnCache.get(x);const M=!!L;L||(L=new Function(..._,`return (${c});`),this.expressionFnCache.set(x,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:a?.componentId,componentName:a?.componentName,propName:a?.propName,fromCache:M,duration:D,method:"evaluateExpression",skipCache:a?.skipCache})}return R}catch(c){throw new Error(`Failed to evaluate expression "${e}": ${c instanceof Error?c.message:String(c)}`)}}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 n=Object.keys(e);return n.length>20?`{Object(${n.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,(n,a,i,l)=>`$t('${l}')`),e.replace(/(?(n.push(l),`__STRING_LITERAL_${n.length-1}__`));const i=[];return a=a.replace(/\$t:[a-zA-Z_][a-zA-Z0-9_.\-]*(?:\|[^'"\s,)]+)?/g,l=>(i.push(l),`__TRANSLATION_TOKEN_${i.length-1}__`)),a=a.replace(/([a-zA-Z_$][a-zA-Z0-9_$]*)\.(?!\?)/g,"$1?."),a=a.replace(/__TRANSLATION_TOKEN_(\d+)__/g,(l,c)=>i[parseInt(c,10)]),a=a.replace(/__STRING_LITERAL_(\d+)__/g,(l,c)=>n[parseInt(c,10)]),a}extractVariablesFromExpression(e){const n=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"]),a=/(?{n!==null&&clearTimeout(n),n=setTimeout(()=>{o(...a)},e)})}class cw{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=lw(()=>{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(Hl.has(e))return Hl.get(e)??null;let n=null;if(Il[e])n={...Il[e]};else{const a=e.match(/^(-?\d*)-(-?\d*)$/);if(a){const[,i,l]=a,c=i===""?0:parseInt(i,10),d=l===""?1/0:parseInt(l,10);!isNaN(c)&&!isNaN(d)&&c<=d&&(n={min:c,max:d})}}return Hl.set(e,n),n}getMatchingKey(e,n){const a=[];for(const i of Object.keys(e)){const l=this.parseRange(i);l&&n>=l.min&&n<=l.max&&a.push({key:i,range:l,isPreset:!!Il[i]})}return a.length===0?null:(a.sort((i,l)=>{if(i.isPreset!==l.isPreset)return i.isPreset?1:-1;const c=i.range.max-i.range.min,d=l.range.max-l.range.min;return c-d}),a[0].key)}matches(e){const n=this.parseRange(e);return n?this.currentWidth>=n.min&&this.currentWidth<=n.max:!1}clearSubscribers(){this.subscribers.clear()}destroy(){this.debouncedHandler&&typeof window<"u"&&window.removeEventListener("resize",this.debouncedHandler),this.clearSubscribers(),Hl.clear()}_setWidthForTesting(e){this.currentWidth=e,this.notifySubscribers()}}const hi=new cw,ao=ut("ConditionEvaluator");function uw(o,e,n,a){return hd(pp(o),e,n,{skipCache:!0,onEmpty:()=>{ao.warn(`${a}: 빈 바인딩 \`{{}}\` — undefined 로 해석합니다.`)}})}function mp(o,e,n){if(!o)return!0;try{const a=Aa(o);let i;if(a!==null?i=uw(a,e,n,"evaluateStringCondition"):i=n.resolveBindings(o,e,{skipCache:!0}),typeof i=="string"){const l=i.toLowerCase().trim();if(l==="false"||l==="0"||l===""||l==="null"||l==="undefined")return!1}return!!i}catch(a){return ao.warn(`evaluateStringCondition: 조건 평가 실패: ${o}`,a),!1}}function zl(o,e,n){if(typeof o=="string")return mp(o,e,n);if("and"in o){if(!Array.isArray(o.and)||o.and.length===0)return ao.warn("evaluateConditionExpression: AND 그룹이 비어있습니다"),!0;for(const a of o.and)if(!zl(a,e,n))return!1;return!0}if("or"in o){if(!Array.isArray(o.or)||o.or.length===0)return ao.warn("evaluateConditionExpression: OR 그룹이 비어있습니다"),!1;for(const a of o.or)if(zl(a,e,n))return!0;return!1}return ao.warn("evaluateConditionExpression: 알 수 없는 조건 형식",o),!1}function yp(o,e,n){if(!Array.isArray(o)||o.length===0)return{matched:!1,branchIndex:-1};for(let a=0;a{tr.warn(`evaluateIfCondition: 빈 바인딩 \`{{}}\` (컴포넌트: ${a||"unknown"}) — undefined 로 해석합니다.`)}}):l=n.resolveBindings(o,e,{skipCache:!0}),typeof l=="string"){const c=l.toLowerCase().trim();if(c==="false"||c==="0"||c===""||c==="null"||c==="undefined")return!1}return!!l}catch(i){return tr.warn(`evaluateIfCondition: 조건 평가 실패 (컴포넌트: ${a||"unknown"}):`,i),!1}}function ts(o,e,n,a){if(o.if!==void 0)return wp(o.if,e,n,a);if(o.condition!==void 0)return wp(o.condition,e,n,a);if(o.conditions===void 0)return!0;const i=o.conditions;try{return dw(i)?zl(i,e,n):fw(i)?yp(i,e,n).matched:(tr.warn(`evaluateRenderCondition: 알 수 없는 conditions 형식 (컴포넌트: ${a||"unknown"})`),!0)}catch(l){return tr.warn(`evaluateRenderCondition: conditions 평가 실패 (컴포넌트: ${a||"unknown"}):`,l),!1}}function Cp(o){if(!o.responsive)return o;const e=hi.getWidth(),n=hi.getMatchingKey(o.responsive,e);if(!n)return o;const a=o.responsive[n];return{...o,props:{...o.props,...a.props},children:a.children??o.children,text:a.text??o.text,if:a.if??o.if,iteration:a.iteration??o.iteration}}function io(o,e,n,a,i){if(!o||o.length===0)return[];const l=i?.bindingEngine??new xn,c=i?.translationEngine??_a.getInstance(),d=i?.translationContext??{templateId:"",locale:"ko"},f=gw(e,i?.componentContext),g=(v,_)=>{if(typeof v=="string")return $l(v)||Nl(v)||!/\$t:[a-zA-Z0-9._-]+/.test(v)?v:c.resolveTranslations(v,d,_);if(Array.isArray(v))return v.map(A=>g(A,_));if(v&&typeof v=="object"){const A={};for(const[x,L]of Object.entries(v))A[x]=g(L,_);return A}return v},m=(v,_)=>{if(typeof v=="string"){if($l(v))return gd(v);if(Nl(v)){const x=[],L=v.replace(new RegExp(`${to}([^${fi}]*)${fi}`,"g"),(R,D)=>(x.push(D),`${xa}${x.length-1}${xa}`));let M=L;return/\$t:[a-zA-Z0-9._-]+/.test(L)&&(M=c.resolveTranslations(L,d,_)),M.replace(new RegExp(`${xa}(\\d+)${xa}`,"g"),(R,D)=>x[parseInt(D)])}if(v.startsWith("$t:defer:")){const x="$t:"+v.slice(9);return c.resolveTranslations(x,d,_)}if(v.startsWith("$t:"))return c.resolveTranslations(v,d,_);if(/\$t:[a-zA-Z0-9._-]+/.test(v)){const x=v.trim();if(!(x.startsWith("{")&&x.endsWith("}")||x.startsWith("[")&&x.endsWith("]"))&&!v.includes("{{"))return c.resolveTranslations(v,d,_)}const A=Sp(v);if(A!==null){let x=!1,L=A;A.startsWith(er)&&(x=!0,L=A.slice(er.length));let M=!1,R=hd(L,_,l,{skipCache:!0,onError:D=>{tr.warn("renderItemChildren: 표현식 평가 실패:",D),M=!0},onEmpty:()=>{tr.warn("renderItemChildren: 빈 바인딩 `{{}}` 은 해석하지 않습니다.")}});return M?void 0:(x||(R=g(R,_)),x&&R!=null?es(R):R)}if(v.includes("{{")){const x=l.resolveBindings(v,_,{skipCache:!0});return typeof x=="string"&&/\$t:[a-zA-Z0-9._-]+/.test(x)?c.resolveTranslations(x,d,_):x}return v}if(Array.isArray(v))return v.map(A=>m(A,_));if(v&&typeof v=="object"){if(l.isSwitchExpression(v))return l.resolveSwitch(v,_,{skipCache:!0});if(l.isActionDefinition(v))return{...v};const A={};for(const[x,L]of Object.entries(v))A[x]=m(L,_);return A}return v},b=(v,_)=>{if(!v)return{};const A={};for(const[x,L]of Object.entries(v))A[x]=m(L,_);return A},S=(v,_,A)=>{const x=Cp(v),L=x.iteration;if(!L)return[];const M=yd(L.source,A,l);if(!Array.isArray(M))return tr.warn(`renderItemChildren: iteration.source가 배열이 아닙니다: ${L.source}`),[];const R=bp();if(R?.isEnabled()){const B=`${_}-iteration`;R.trackIteration(B,L.source,L.item_var,L.index_var,M.length)}const D=n[x.name];return D?M.flatMap((B,q)=>{const P={...A,[L.item_var]:B,[`${L.item_var}_index`]:q,...L.index_var?{[L.index_var]:q}:{}},K=ts({if:x.if,condition:x.condition,conditions:x.conditions},P,l,x.id);if(x.if&&R?.isEnabled()){const St=`${_}-iter-${q}-if`;R.trackIfCondition(St,x.if,K,x.name)}if(!K)return[];const ge=x.id?String(Ta(m(x.id,P))):void 0,Ee=`${_}-iter-${q}`,Se=i?.getRemountKey?i.getRemountKey(ge,Ee):Ee,Ue=b(x.props,P),Ve=bd(Ue,x.actions,P,{actionDispatcher:i?.actionDispatcher,componentContext:i?.componentContext});let qe=null;return x.text!==void 0?qe=m(x.text,P):x.children&&x.children.length>0&&(qe=io(x.children,P,n,Se,i)),R?.isEnabled()&&R.trackRender(x.name),[Ye.createElement(D,{key:Se,...Ta(Ve)},Ta(qe))]}):(tr.warn(`renderItemChildren: 컴포넌트를 찾을 수 없습니다: ${x.name}`),[])};return o.flatMap((v,_)=>{const A=Cp(v),x=A.id?String(Ta(m(A.id,f))):void 0,L=a?`${a}-${x||_}`:x||`child-${_}`,M=i?.getRemountKey?i.getRemountKey(x,L):L;if(A.iteration)return S(A,M,f);const R=ts({if:A.if,condition:A.condition,conditions:A.conditions},f,l,A.id),D=bp();if(A.if&&D?.isEnabled()){const ge=`${M}-if`;D.trackIfCondition(ge,A.if,R,A.name)}if(!R)return[];const B=n[A.name];if(!B)return tr.warn(`renderItemChildren: 컴포넌트를 찾을 수 없습니다: ${A.name}`),[];const q=b(A.props,f),P=bd(q,A.actions,f,{actionDispatcher:i?.actionDispatcher,componentContext:i?.componentContext});let K=null;return A.text!==void 0?K=m(A.text,f):A.children&&A.children.length>0&&(K=io(A.children,f,n,M,i)),D?.isEnabled()&&D.trackRender(A.name),[Ye.createElement(B,{key:M,...Ta(P)},Ta(K))]})}function ns(o,e,n,a){let i,l;return n instanceof xn?(i=n,l=a):(i=vp,l=n),i.resolveBindings(o,e,l)}function pw(o,e,n,a){const i=n??vp,l={skipCache:!0,...a};let c;try{c=i.resolveBindings(o.key,e,{skipCache:l.skipCache})?.toString()?.trim()??""}catch(g){tr.warn("resolveClassMap: key 평가 실패:",o.key,g),c=""}let d="";c&&o.variants&&c in o.variants?d=o.variants[c]: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 Ep(o,e){return function(){return o.apply(e,arguments)}}const{toString:mw}=Object.prototype,{getPrototypeOf:jl}=Object,{iterator:Ul,toStringTag:_p}=Symbol,Bl=(o=>e=>{const n=mw.call(e);return o[n]||(o[n]=n.slice(8,-1).toLowerCase())})(Object.create(null)),mr=o=>(o=o.toLowerCase(),e=>Bl(e)===o),Pl=o=>e=>typeof e===o,{isArray:rs}=Array,as=Pl("undefined");function so(o){return o!==null&&!as(o)&&o.constructor!==null&&!as(o.constructor)&&On(o.constructor.isBuffer)&&o.constructor.isBuffer(o)}const Ap=mr("ArrayBuffer");function yw(o){let e;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?e=ArrayBuffer.isView(o):e=o&&o.buffer&&Ap(o.buffer),e}const bw=Pl("string"),On=Pl("function"),xp=Pl("number"),oo=o=>o!==null&&typeof o=="object",vw=o=>o===!0||o===!1,ql=o=>{if(Bl(o)!=="object")return!1;const e=jl(o);return(e===null||e===Object.prototype||Object.getPrototypeOf(e)===null)&&!(_p in o)&&!(Ul in o)},Sw=o=>{if(!oo(o)||so(o))return!1;try{return Object.keys(o).length===0&&Object.getPrototypeOf(o)===Object.prototype}catch{return!1}},ww=mr("Date"),Cw=mr("File"),Ew=o=>!!(o&&typeof o.uri<"u"),_w=o=>o&&typeof o.getParts<"u",Aw=mr("Blob"),xw=mr("FileList"),Tw=o=>oo(o)&&On(o.pipe);function Rw(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}}const Tp=Rw(),Rp=typeof Tp.FormData<"u"?Tp.FormData:void 0,kw=o=>{if(!o)return!1;if(Rp&&o instanceof Rp)return!0;const e=jl(o);if(!e||e===Object.prototype||!On(o.append))return!1;const n=Bl(o);return n==="formdata"||n==="object"&&On(o.toString)&&o.toString()==="[object FormData]"},Dw=mr("URLSearchParams"),[Ow,Lw,Mw,$w]=["ReadableStream","Request","Response","Headers"].map(mr),Nw=o=>o.trim?o.trim():o.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function lo(o,e,{allOwnKeys:n=!1}={}){if(o===null||typeof o>"u")return;let a,i;if(typeof o!="object"&&(o=[o]),rs(o))for(a=0,i=o.length;a0;)if(i=n[a],e===i.toLowerCase())return i;return null}const gi=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,Dp=o=>!as(o)&&o!==gi;function vd(...o){const{caseless:e,skipUndefined:n}=Dp(this)&&this||{},a={},i=(l,c)=>{if(c==="__proto__"||c==="constructor"||c==="prototype")return;const d=e&&kp(a,c)||c,f=Sd(a,d)?a[d]:void 0;ql(f)&&ql(l)?a[d]=vd(f,l):ql(l)?a[d]=vd({},l):rs(l)?a[d]=l.slice():(!n||!as(l))&&(a[d]=l)};for(let l=0,c=o.length;l(lo(e,(i,l)=>{n&&On(i)?Object.defineProperty(o,l,{__proto__:null,value:Ep(i,n),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(o,l,{__proto__:null,value:i,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:a}),o),Hw=o=>(o.charCodeAt(0)===65279&&(o=o.slice(1)),o),zw=(o,e,n,a)=>{o.prototype=Object.create(e.prototype,a),Object.defineProperty(o.prototype,"constructor",{__proto__:null,value:o,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(o,"super",{__proto__:null,value:e.prototype}),n&&Object.assign(o.prototype,n)},jw=(o,e,n,a)=>{let i,l,c;const d={};if(e=e||{},o==null)return e;do{for(i=Object.getOwnPropertyNames(o),l=i.length;l-- >0;)c=i[l],(!a||a(c,o,e))&&!d[c]&&(e[c]=o[c],d[c]=!0);o=n!==!1&&jl(o)}while(o&&(!n||n(o,e))&&o!==Object.prototype);return e},Uw=(o,e,n)=>{o=String(o),(n===void 0||n>o.length)&&(n=o.length),n-=e.length;const a=o.indexOf(e,n);return a!==-1&&a===n},Bw=o=>{if(!o)return null;if(rs(o))return o;let e=o.length;if(!xp(e))return null;const n=new Array(e);for(;e-- >0;)n[e]=o[e];return n},Pw=(o=>e=>o&&e instanceof o)(typeof Uint8Array<"u"&&jl(Uint8Array)),qw=(o,e)=>{const a=(o&&o[Ul]).call(o);let i;for(;(i=a.next())&&!i.done;){const l=i.value;e.call(o,l[0],l[1])}},Gw=(o,e)=>{let n;const a=[];for(;(n=o.exec(e))!==null;)a.push(n);return a},Vw=mr("HTMLFormElement"),Fw=o=>o.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(n,a,i){return a.toUpperCase()+i}),Sd=(({hasOwnProperty:o})=>(e,n)=>o.call(e,n))(Object.prototype),Kw=mr("RegExp"),Op=(o,e)=>{const n=Object.getOwnPropertyDescriptors(o),a={};lo(n,(i,l)=>{let c;(c=e(i,l,o))!==!1&&(a[l]=c||i)}),Object.defineProperties(o,a)},Ww=o=>{Op(o,(e,n)=>{if(On(o)&&["arguments","caller","callee"].includes(n))return!1;const a=o[n];if(On(a)){if(e.enumerable=!1,"writable"in e){e.writable=!1;return}e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")})}})},Yw=(o,e)=>{const n={},a=i=>{i.forEach(l=>{n[l]=!0})};return rs(o)?a(o):a(String(o).split(e)),n},Xw=()=>{},Jw=(o,e)=>o!=null&&Number.isFinite(o=+o)?o:e;function Qw(o){return!!(o&&On(o.append)&&o[_p]==="FormData"&&o[Ul])}const Zw=o=>{const e=new WeakSet,n=a=>{if(oo(a)){if(e.has(a))return;if(so(a))return a;if(!("toJSON"in a)){e.add(a);const i=rs(a)?[]:{};return lo(a,(l,c)=>{const d=n(l);!as(d)&&(i[c]=d)}),e.delete(a),i}}return a};return n(o)},e0=mr("AsyncFunction"),t0=o=>o&&(oo(o)||On(o))&&On(o.then)&&On(o.catch),Lp=((o,e)=>o?setImmediate:e?((n,a)=>(gi.addEventListener("message",({source:i,data:l})=>{i===gi&&l===n&&a.length&&a.shift()()},!1),i=>{a.push(i),gi.postMessage(n,"*")}))(`axios@${Math.random()}`,[]):n=>setTimeout(n))(typeof setImmediate=="function",On(gi.postMessage)),n0=typeof queueMicrotask<"u"?queueMicrotask.bind(gi):typeof process<"u"&&process.nextTick||Lp,W={isArray:rs,isArrayBuffer:Ap,isBuffer:so,isFormData:kw,isArrayBufferView:yw,isString:bw,isNumber:xp,isBoolean:vw,isObject:oo,isPlainObject:ql,isEmptyObject:Sw,isReadableStream:Ow,isRequest:Lw,isResponse:Mw,isHeaders:$w,isUndefined:as,isDate:ww,isFile:Cw,isReactNativeBlob:Ew,isReactNative:_w,isBlob:Aw,isRegExp:Kw,isFunction:On,isStream:Tw,isURLSearchParams:Dw,isTypedArray:Pw,isFileList:xw,forEach:lo,merge:vd,extend:Iw,trim:Nw,stripBOM:Hw,inherits:zw,toFlatObject:jw,kindOf:Bl,kindOfTest:mr,endsWith:Uw,toArray:Bw,forEachEntry:qw,matchAll:Gw,isHTMLForm:Vw,hasOwnProperty:Sd,hasOwnProp:Sd,reduceDescriptors:Op,freezeMethods:Ww,toObjectSet:Yw,toCamelCase:Fw,noop:Xw,toFiniteNumber:Jw,findKey:kp,global:gi,isContextDefined:Dp,isSpecCompliantForm:Qw,toJSONObject:Zw,isAsyncFn:e0,isThenable:t0,setImmediate:Lp,asap:n0,isIterable:o=>o!=null&&On(o[Ul])},r0=W.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"]),a0=o=>{const e={};let n,a,i;return o&&o.split(` -`).forEach(function(c){i=c.indexOf(":"),n=c.substring(0,i).trim().toLowerCase(),a=c.substring(i+1).trim(),!(!n||e[n]&&r0[n])&&(n==="set-cookie"?e[n]?e[n].push(a):e[n]=[a]:e[n]=e[n]?e[n]+", "+a:a)}),e};function i0(o){let e=0,n=o.length;for(;ee;){const a=o.charCodeAt(n-1);if(a!==9&&a!==32)break;n-=1}return e===0&&n===o.length?o:o.slice(e,n)}const s0=new RegExp("[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+","g"),o0=new RegExp("[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+","g");function wd(o,e){return W.isArray(o)?o.map(n=>wd(n,e)):i0(String(o).replace(e,""))}const l0=o=>wd(o,s0),c0=o=>wd(o,o0);function Mp(o){const e=Object.create(null);return W.forEach(o.toJSON(),(n,a)=>{e[a]=c0(n)}),e}const $p=Symbol("internals");function co(o){return o&&String(o).trim().toLowerCase()}function Gl(o){return o===!1||o==null?o:W.isArray(o)?o.map(Gl):l0(String(o))}function u0(o){const e=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let a;for(;a=n.exec(o);)e[a[1]]=a[2];return e}const d0=o=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(o.trim());function Cd(o,e,n,a,i){if(W.isFunction(a))return a.call(this,e,n);if(i&&(e=n),!!W.isString(e)){if(W.isString(a))return e.indexOf(a)!==-1;if(W.isRegExp(a))return a.test(e)}}function f0(o){return o.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(e,n,a)=>n.toUpperCase()+a)}function h0(o,e){const n=W.toCamelCase(" "+e);["get","set","has"].forEach(a=>{Object.defineProperty(o,a+n,{__proto__:null,value:function(i,l,c){return this[a].call(this,e,i,l,c)},configurable:!0})})}let Tn=class{constructor(e){e&&this.set(e)}set(e,n,a){const i=this;function l(d,f,g){const m=co(f);if(!m)throw new Error("header name must be a non-empty string");const b=W.findKey(i,m);(!b||i[b]===void 0||g===!0||g===void 0&&i[b]!==!1)&&(i[b||f]=Gl(d))}const c=(d,f)=>W.forEach(d,(g,m)=>l(g,m,f));if(W.isPlainObject(e)||e instanceof this.constructor)c(e,n);else if(W.isString(e)&&(e=e.trim())&&!d0(e))c(a0(e),n);else if(W.isObject(e)&&W.isIterable(e)){let d={},f,g;for(const m of e){if(!W.isArray(m))throw TypeError("Object iterator must return a key-value pair");d[g=m[0]]=(f=d[g])?W.isArray(f)?[...f,m[1]]:[f,m[1]]:m[1]}c(d,n)}else e!=null&&l(n,e,a);return this}get(e,n){if(e=co(e),e){const a=W.findKey(this,e);if(a){const i=this[a];if(!n)return i;if(n===!0)return u0(i);if(W.isFunction(n))return n.call(this,i,a);if(W.isRegExp(n))return n.exec(i);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,n){if(e=co(e),e){const a=W.findKey(this,e);return!!(a&&this[a]!==void 0&&(!n||Cd(this,this[a],a,n)))}return!1}delete(e,n){const a=this;let i=!1;function l(c){if(c=co(c),c){const d=W.findKey(a,c);d&&(!n||Cd(a,a[d],d,n))&&(delete a[d],i=!0)}}return W.isArray(e)?e.forEach(l):l(e),i}clear(e){const n=Object.keys(this);let a=n.length,i=!1;for(;a--;){const l=n[a];(!e||Cd(this,this[l],l,e,!0))&&(delete this[l],i=!0)}return i}normalize(e){const n=this,a={};return W.forEach(this,(i,l)=>{const c=W.findKey(a,l);if(c){n[c]=Gl(i),delete n[l];return}const d=e?f0(l):String(l).trim();d!==l&&delete n[l],n[d]=Gl(i),a[d]=!0}),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const n=Object.create(null);return W.forEach(this,(a,i)=>{a!=null&&a!==!1&&(n[i]=e&&W.isArray(a)?a.join(", "):a)}),n}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([e,n])=>e+": "+n).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,...n){const a=new this(e);return n.forEach(i=>a.set(i)),a}static accessor(e){const a=(this[$p]=this[$p]={accessors:{}}).accessors,i=this.prototype;function l(c){const d=co(c);a[d]||(h0(i,c),a[d]=!0)}return W.isArray(e)?e.forEach(l):l(e),this}};Tn.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),W.reduceDescriptors(Tn.prototype,({value:o},e)=>{let n=e[0].toUpperCase()+e.slice(1);return{get:()=>o,set(a){this[n]=a}}}),W.freezeMethods(Tn);const g0="[REDACTED ****]";function p0(o){if(W.hasOwnProp(o,"toJSON"))return!0;let e=Object.getPrototypeOf(o);for(;e&&e!==Object.prototype;){if(W.hasOwnProp(e,"toJSON"))return!0;e=Object.getPrototypeOf(e)}return!1}function m0(o,e){const n=new Set(e.map(l=>String(l).toLowerCase())),a=[],i=l=>{if(l===null||typeof l!="object"||W.isBuffer(l))return l;if(a.indexOf(l)!==-1)return;l instanceof Tn&&(l=l.toJSON()),a.push(l);let c;if(W.isArray(l))c=[],l.forEach((d,f)=>{const g=i(d);W.isUndefined(g)||(c[f]=g)});else{if(!W.isPlainObject(l)&&p0(l))return a.pop(),l;c=Object.create(null);for(const[d,f]of Object.entries(l)){const g=n.has(d.toLowerCase())?g0:i(f);W.isUndefined(g)||(c[d]=g)}}return a.pop(),c};return i(o)}let Oe=class zS extends Error{static from(e,n,a,i,l,c){const d=new zS(e.message,n||e.code,a,i,l);return d.cause=e,d.name=e.name,e.status!=null&&d.status==null&&(d.status=e.status),c&&Object.assign(d,c),d}constructor(e,n,a,i,l){super(e),Object.defineProperty(this,"message",{__proto__:null,value:e,enumerable:!0,writable:!0,configurable:!0}),this.name="AxiosError",this.isAxiosError=!0,n&&(this.code=n),a&&(this.config=a),i&&(this.request=i),l&&(this.response=l,this.status=l.status)}toJSON(){const e=this.config,n=e&&W.hasOwnProp(e,"redact")?e.redact:void 0,a=W.isArray(n)&&n.length>0?m0(e,n):W.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:a,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 y0=null;function Ed(o){return W.isPlainObject(o)||W.isArray(o)}function Np(o){return W.endsWith(o,"[]")?o.slice(0,-2):o}function _d(o,e,n){return o?o.concat(e).map(function(i,l){return i=Np(i),!n&&l?"["+i+"]":i}).join(n?".":""):e}function b0(o){return W.isArray(o)&&!o.some(Ed)}const v0=W.toFlatObject(W,{},null,function(e){return/^is[A-Z]/.test(e)});function Vl(o,e,n){if(!W.isObject(o))throw new TypeError("target must be an object");e=e||new FormData,n=W.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,function(x,L){return!W.isUndefined(L[x])});const a=n.metaTokens,i=n.visitor||b,l=n.dots,c=n.indexes,d=n.Blob||typeof Blob<"u"&&Blob,f=n.maxDepth===void 0?100:n.maxDepth,g=d&&W.isSpecCompliantForm(e);if(!W.isFunction(i))throw new TypeError("visitor must be a function");function m(A){if(A===null)return"";if(W.isDate(A))return A.toISOString();if(W.isBoolean(A))return A.toString();if(!g&&W.isBlob(A))throw new Oe("Blob is not supported. Use a Buffer instead.");return W.isArrayBuffer(A)||W.isTypedArray(A)?g&&typeof Blob=="function"?new Blob([A]):Buffer.from(A):A}function b(A,x,L){let M=A;if(W.isReactNative(e)&&W.isReactNativeBlob(A))return e.append(_d(L,x,l),m(A)),!1;if(A&&!L&&typeof A=="object"){if(W.endsWith(x,"{}"))x=a?x:x.slice(0,-2),A=JSON.stringify(A);else if(W.isArray(A)&&b0(A)||(W.isFileList(A)||W.endsWith(x,"[]"))&&(M=W.toArray(A)))return x=Np(x),M.forEach(function(D,B){!(W.isUndefined(D)||D===null)&&e.append(c===!0?_d([x],B,l):c===null?x:x+"[]",m(D))}),!1}return Ed(A)?!0:(e.append(_d(L,x,l),m(A)),!1)}const S=[],v=Object.assign(v0,{defaultVisitor:b,convertValue:m,isVisitable:Ed});function _(A,x,L=0){if(!W.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(S.indexOf(A)!==-1)throw Error("Circular reference detected in "+x.join("."));S.push(A),W.forEach(A,function(R,D){(!(W.isUndefined(R)||R===null)&&i.call(e,R,W.isString(D)?D.trim():D,x,v))===!0&&_(R,x?x.concat(D):[D],L+1)}),S.pop()}}if(!W.isObject(o))throw new TypeError("data must be an object");return _(o),e}function Ip(o){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+"};return encodeURIComponent(o).replace(/[!'()~]|%20/g,function(a){return e[a]})}function Ad(o,e){this._pairs=[],o&&Vl(o,this,e)}const Hp=Ad.prototype;Hp.append=function(e,n){this._pairs.push([e,n])},Hp.toString=function(e){const n=e?function(a){return e.call(this,a,Ip)}:Ip;return this._pairs.map(function(i){return n(i[0])+"="+n(i[1])},"").join("&")};function S0(o){return encodeURIComponent(o).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function zp(o,e,n){if(!e)return o;const a=n&&n.encode||S0,i=W.isFunction(n)?{serialize:n}:n,l=i&&i.serialize;let c;if(l?c=l(e,i):c=W.isURLSearchParams(e)?e.toString():new Ad(e,i).toString(a),c){const d=o.indexOf("#");d!==-1&&(o=o.slice(0,d)),o+=(o.indexOf("?")===-1?"?":"&")+c}return o}class jp{constructor(){this.handlers=[]}use(e,n,a){return this.handlers.push({fulfilled:e,rejected:n,synchronous:a?a.synchronous:!1,runWhen:a?a.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){W.forEach(this.handlers,function(a){a!==null&&e(a)})}}const xd={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1,legacyInterceptorReqResOrdering:!0},w0={isBrowser:!0,classes:{URLSearchParams:typeof URLSearchParams<"u"?URLSearchParams:Ad,FormData:typeof FormData<"u"?FormData:null,Blob:typeof Blob<"u"?Blob:null},protocols:["http","https","file","blob","url","data"]},Td=typeof window<"u"&&typeof document<"u",Rd=typeof navigator=="object"&&navigator||void 0,C0=Td&&(!Rd||["ReactNative","NativeScript","NS"].indexOf(Rd.product)<0),E0=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function",_0=Td&&window.location.href||"http://localhost",Cn={...Object.freeze(Object.defineProperty({__proto__:null,hasBrowserEnv:Td,hasStandardBrowserEnv:C0,hasStandardBrowserWebWorkerEnv:E0,navigator:Rd,origin:_0},Symbol.toStringTag,{value:"Module"})),...w0};function A0(o,e){return Vl(o,new Cn.classes.URLSearchParams,{visitor:function(n,a,i,l){return Cn.isNode&&W.isBuffer(n)?(this.append(a,n.toString("base64")),!1):l.defaultVisitor.apply(this,arguments)},...e})}function x0(o){return W.matchAll(/\w+|\[(\w*)]/g,o).map(e=>e[0]==="[]"?"":e[1]||e[0])}function T0(o){const e={},n=Object.keys(o);let a;const i=n.length;let l;for(a=0;a=n.length;return c=!c&&W.isArray(i)?i.length:c,f?(W.hasOwnProp(i,c)?i[c]=W.isArray(i[c])?i[c].concat(a):[i[c],a]:i[c]=a,!d):((!W.hasOwnProp(i,c)||!W.isObject(i[c]))&&(i[c]=[]),e(n,a,i[c],l)&&W.isArray(i[c])&&(i[c]=T0(i[c])),!d)}if(W.isFormData(o)&&W.isFunction(o.entries)){const n={};return W.forEachEntry(o,(a,i)=>{e(x0(a),i,n,0)}),n}return null}const is=(o,e)=>o!=null&&W.hasOwnProp(o,e)?o[e]:void 0;function R0(o,e,n){if(W.isString(o))try{return(e||JSON.parse)(o),W.trim(o)}catch(a){if(a.name!=="SyntaxError")throw a}return(n||JSON.stringify)(o)}const uo={transitional:xd,adapter:["xhr","http","fetch"],transformRequest:[function(e,n){const a=n.getContentType()||"",i=a.indexOf("application/json")>-1,l=W.isObject(e);if(l&&W.isHTMLForm(e)&&(e=new FormData(e)),W.isFormData(e))return i?JSON.stringify(Up(e)):e;if(W.isArrayBuffer(e)||W.isBuffer(e)||W.isStream(e)||W.isFile(e)||W.isBlob(e)||W.isReadableStream(e))return e;if(W.isArrayBufferView(e))return e.buffer;if(W.isURLSearchParams(e))return n.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let d;if(l){const f=is(this,"formSerializer");if(a.indexOf("application/x-www-form-urlencoded")>-1)return A0(e,f).toString();if((d=W.isFileList(e))||a.indexOf("multipart/form-data")>-1){const g=is(this,"env"),m=g&&g.FormData;return Vl(d?{"files[]":e}:e,m&&new m,f)}}return l||i?(n.setContentType("application/json",!1),R0(e)):e}],transformResponse:[function(e){const n=is(this,"transitional")||uo.transitional,a=n&&n.forcedJSONParsing,i=is(this,"responseType"),l=i==="json";if(W.isResponse(e)||W.isReadableStream(e))return e;if(e&&W.isString(e)&&(a&&!i||l)){const d=!(n&&n.silentJSONParsing)&&l;try{return JSON.parse(e,is(this,"parseReviver"))}catch(f){if(d)throw f.name==="SyntaxError"?Oe.from(f,Oe.ERR_BAD_RESPONSE,this,null,is(this,"response")):f}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:Cn.classes.FormData,Blob:Cn.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};W.forEach(["delete","get","head","post","put","patch","query"],o=>{uo.headers[o]={}});function kd(o,e){const n=this||uo,a=e||n,i=Tn.from(a.headers);let l=a.data;return W.forEach(o,function(d){l=d.call(n,l,i.normalize(),e?e.status:void 0)}),i.normalize(),l}function Bp(o){return!!(o&&o.__CANCEL__)}let fo=class extends Oe{constructor(e,n,a){super(e??"canceled",Oe.ERR_CANCELED,n,a),this.name="CanceledError",this.__CANCEL__=!0}};function Pp(o,e,n){const a=n.config.validateStatus;!n.status||!a||a(n.status)?o(n):e(new Oe("Request failed with status code "+n.status,n.status>=400&&n.status<500?Oe.ERR_BAD_REQUEST:Oe.ERR_BAD_RESPONSE,n.config,n.request,n))}function k0(o){const e=/^([-+\w]{1,25}):(?:\/\/)?/.exec(o);return e&&e[1]||""}function D0(o,e){o=o||10;const n=new Array(o),a=new Array(o);let i=0,l=0,c;return e=e!==void 0?e:1e3,function(f){const g=Date.now(),m=a[l];c||(c=g),n[i]=f,a[i]=g;let b=l,S=0;for(;b!==i;)S+=n[b++],b=b%o;if(i=(i+1)%o,i===l&&(l=(l+1)%o),g-c{n=m,i=null,l&&(clearTimeout(l),l=null),o(...g)};return[(...g)=>{const m=Date.now(),b=m-n;b>=a?c(g,m):(i=g,l||(l=setTimeout(()=>{l=null,c(i)},a-b)))},()=>i&&c(i)]}const Fl=(o,e,n=3)=>{let a=0;const i=D0(50,250);return O0(l=>{if(!l||typeof l.loaded!="number")return;const c=l.loaded,d=l.lengthComputable?l.total:void 0,f=d!=null?Math.min(c,d):c,g=Math.max(0,f-a),m=i(g);a=Math.max(a,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)},n)},qp=(o,e)=>{const n=o!=null;return[a=>e[0]({lengthComputable:n,total:o,loaded:a}),e[1]]},Gp=o=>(...e)=>W.asap(()=>o(...e)),L0=Cn.hasStandardBrowserEnv?((o,e)=>n=>(n=new URL(n,Cn.origin),o.protocol===n.protocol&&o.host===n.host&&(e||o.port===n.port)))(new URL(Cn.origin),Cn.navigator&&/(msie|trident)/i.test(Cn.navigator.userAgent)):()=>!0,M0=Cn.hasStandardBrowserEnv?{write(o,e,n,a,i,l,c){if(typeof document>"u")return;const d=[`${o}=${encodeURIComponent(e)}`];W.isNumber(n)&&d.push(`expires=${new Date(n).toUTCString()}`),W.isString(a)&&d.push(`path=${a}`),W.isString(i)&&d.push(`domain=${i}`),l===!0&&d.push("secure"),W.isString(c)&&d.push(`SameSite=${c}`),document.cookie=d.join("; ")},read(o){if(typeof document>"u")return null;const e=document.cookie.split(";");for(let n=0;no instanceof Tn?{...o}:o;function pi(o,e){e=e||{};const n=Object.create(null);Object.defineProperty(n,"hasOwnProperty",{__proto__:null,value:Object.prototype.hasOwnProperty,enumerable:!1,writable:!0,configurable:!0});function a(g,m,b,S){return W.isPlainObject(g)&&W.isPlainObject(m)?W.merge.call({caseless:S},g,m):W.isPlainObject(m)?W.merge({},m):W.isArray(m)?m.slice():m}function i(g,m,b,S){if(W.isUndefined(m)){if(!W.isUndefined(g))return a(void 0,g,b,S)}else return a(g,m,b,S)}function l(g,m){if(!W.isUndefined(m))return a(void 0,m)}function c(g,m){if(W.isUndefined(m)){if(!W.isUndefined(g))return a(void 0,g)}else return a(void 0,m)}function d(g,m,b){if(W.hasOwnProp(e,b))return a(g,m);if(W.hasOwnProp(o,b))return a(void 0,g)}const f={url:l,method:l,data:l,baseURL:c,transformRequest:c,transformResponse:c,paramsSerializer:c,timeout:c,timeoutMessage:c,withCredentials:c,withXSRFToken:c,adapter:c,responseType:c,xsrfCookieName:c,xsrfHeaderName:c,onUploadProgress:c,onDownloadProgress:c,decompress:c,maxContentLength:c,maxBodyLength:c,beforeRedirect:c,transport:c,httpAgent:c,httpsAgent:c,cancelToken:c,socketPath:c,allowedSocketPaths:c,responseEncoding:c,validateStatus:d,headers:(g,m,b)=>i(Fp(g),Fp(m),b,!0)};return W.forEach(Object.keys({...o,...e}),function(m){if(m==="__proto__"||m==="constructor"||m==="prototype")return;const b=W.hasOwnProp(f,m)?f[m]:i,S=W.hasOwnProp(o,m)?o[m]:void 0,v=W.hasOwnProp(e,m)?e[m]:void 0,_=b(S,v,m);W.isUndefined(_)&&b!==d||(n[m]=_)}),n}const I0=["content-type","content-length"];function H0(o,e,n){if(n!=="content-only"){o.set(e);return}Object.entries(e).forEach(([a,i])=>{I0.includes(a.toLowerCase())&&o.set(a,i)})}const z0=o=>encodeURIComponent(o).replace(/%([0-9A-F]{2})/gi,(e,n)=>String.fromCharCode(parseInt(n,16))),Kp=o=>{const e=pi({},o),n=S=>W.hasOwnProp(e,S)?e[S]:void 0,a=n("data");let i=n("withXSRFToken");const l=n("xsrfHeaderName"),c=n("xsrfCookieName");let d=n("headers");const f=n("auth"),g=n("baseURL"),m=n("allowAbsoluteUrls"),b=n("url");if(e.headers=d=Tn.from(d),e.url=zp(Vp(g,b,m),o.params,o.paramsSerializer),f&&d.set("Authorization","Basic "+btoa((f.username||"")+":"+(f.password?z0(f.password):""))),W.isFormData(a)&&(Cn.hasStandardBrowserEnv||Cn.hasStandardBrowserWebWorkerEnv?d.setContentType(void 0):W.isFunction(a.getHeaders)&&H0(d,a.getHeaders(),n("formDataHeaderPolicy"))),Cn.hasStandardBrowserEnv&&(W.isFunction(i)&&(i=i(e)),i===!0||i==null&&L0(e.url))){const v=l&&c&&M0.read(c);v&&d.set(l,v)}return e},j0=typeof XMLHttpRequest<"u"&&function(o){return new Promise(function(n,a){const i=Kp(o);let l=i.data;const c=Tn.from(i.headers).normalize();let{responseType:d,onUploadProgress:f,onDownloadProgress:g}=i,m,b,S,v,_;function A(){v&&v(),_&&_(),i.cancelToken&&i.cancelToken.unsubscribe(m),i.signal&&i.signal.removeEventListener("abort",m)}let x=new XMLHttpRequest;x.open(i.method.toUpperCase(),i.url,!0),x.timeout=i.timeout;function L(){if(!x)return;const R=Tn.from("getAllResponseHeaders"in x&&x.getAllResponseHeaders()),B={data:!d||d==="text"||d==="json"?x.responseText:x.response,status:x.status,statusText:x.statusText,headers:R,config:o,request:x};Pp(function(P){n(P),A()},function(P){a(P),A()},B),x=null}"onloadend"in x?x.onloadend=L:x.onreadystatechange=function(){!x||x.readyState!==4||x.status===0&&!(x.responseURL&&x.responseURL.startsWith("file:"))||setTimeout(L)},x.onabort=function(){x&&(a(new Oe("Request aborted",Oe.ECONNABORTED,o,x)),A(),x=null)},x.onerror=function(D){const B=D&&D.message?D.message:"Network Error",q=new Oe(B,Oe.ERR_NETWORK,o,x);q.event=D||null,a(q),A(),x=null},x.ontimeout=function(){let D=i.timeout?"timeout of "+i.timeout+"ms exceeded":"timeout exceeded";const B=i.transitional||xd;i.timeoutErrorMessage&&(D=i.timeoutErrorMessage),a(new Oe(D,B.clarifyTimeoutError?Oe.ETIMEDOUT:Oe.ECONNABORTED,o,x)),A(),x=null},l===void 0&&c.setContentType(null),"setRequestHeader"in x&&W.forEach(Mp(c),function(D,B){x.setRequestHeader(B,D)}),W.isUndefined(i.withCredentials)||(x.withCredentials=!!i.withCredentials),d&&d!=="json"&&(x.responseType=i.responseType),g&&([S,_]=Fl(g,!0),x.addEventListener("progress",S)),f&&x.upload&&([b,v]=Fl(f),x.upload.addEventListener("progress",b),x.upload.addEventListener("loadend",v)),(i.cancelToken||i.signal)&&(m=R=>{x&&(a(!R||R.type?new fo(null,o,x):R),x.abort(),A(),x=null)},i.cancelToken&&i.cancelToken.subscribe(m),i.signal&&(i.signal.aborted?m():i.signal.addEventListener("abort",m)));const M=k0(i.url);if(M&&!Cn.protocols.includes(M)){a(new Oe("Unsupported protocol "+M+":",Oe.ERR_BAD_REQUEST,o));return}x.send(l||null)})},U0=(o,e)=>{if(o=o?o.filter(Boolean):[],!e&&!o.length)return;const n=new AbortController;let a=!1;const i=function(f){if(!a){a=!0,c();const g=f instanceof Error?f:this.reason;n.abort(g instanceof Oe?g:new fo(g instanceof Error?g.message:g))}};let l=e&&setTimeout(()=>{l=null,i(new Oe(`timeout of ${e}ms exceeded`,Oe.ETIMEDOUT))},e);const c=()=>{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}=n;return d.unsubscribe=()=>W.asap(c),d},B0=function*(o,e){let n=o.byteLength;if(n{const i=P0(o,e);let l=0,c,d=f=>{c||(c=!0,a&&a(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(n){let S=l+=b;n(S)}f.enqueue(new Uint8Array(m))}catch(g){throw d(g),g}},cancel(f){return d(f),i.return()}},{highWaterMark:2})};function G0(o){if(!o||typeof o!="string"||!o.startsWith("data:"))return 0;const e=o.indexOf(",");if(e<0)return 0;const n=o.slice(5,e),a=o.slice(e+1);if(/;base64/i.test(n)){let c=a.length;const d=a.length;for(let v=0;v=48&&_<=57||_>=65&&_<=70||_>=97&&_<=102)&&(A>=48&&A<=57||A>=65&&A<=70||A>=97&&A<=102)&&(c-=2,v+=2)}let f=0,g=d-1;const m=v=>v>=2&&a.charCodeAt(v-2)===37&&a.charCodeAt(v-1)===51&&(a.charCodeAt(v)===68||a.charCodeAt(v)===100);g>=0&&(a.charCodeAt(g)===61?(f++,g--):m(g)&&(f++,g-=3)),f===1&&g>=0&&(a.charCodeAt(g)===61||m(g))&&f++;const S=Math.floor(c/4)*3-(f||0);return S>0?S:0}if(typeof Buffer<"u"&&typeof Buffer.byteLength=="function")return Buffer.byteLength(a,"utf8");let l=0;for(let c=0,d=a.length;c=55296&&f<=56319&&c+1=56320&&g<=57343?(l+=4,c++):l+=3}else l+=3}return l}const Dd="1.16.1",Yp=64*1024,{isFunction:Kl}=W,Xp=(o,...e)=>{try{return!!o(...e)}catch{return!1}},V0=o=>{const e=W.global!==void 0&&W.global!==null?W.global:globalThis,{ReadableStream:n,TextEncoder:a}=e;o=W.merge.call({skipUndefined:!0},{Request:e.Request,Response:e.Response},o);const{fetch:i,Request:l,Response:c}=o,d=i?Kl(i):typeof fetch=="function",f=Kl(l),g=Kl(c);if(!d)return!1;const m=d&&Kl(n),b=d&&(typeof a=="function"?(L=>M=>L.encode(M))(new a):async L=>new Uint8Array(await new l(L).arrayBuffer())),S=f&&m&&Xp(()=>{let L=!1;const M=new l(Cn.origin,{body:new n,method:"POST",get duplex(){return L=!0,"half"}}),R=M.headers.has("Content-Type");return M.body!=null&&M.body.cancel(),L&&!R}),v=g&&m&&Xp(()=>W.isReadableStream(new c("").body)),_={stream:v&&(L=>L.body)};d&&["text","arrayBuffer","blob","formData","stream"].forEach(L=>{!_[L]&&(_[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(W.isBlob(L))return L.size;if(W.isSpecCompliantForm(L))return(await new l(Cn.origin,{method:"POST",body:L}).arrayBuffer()).byteLength;if(W.isArrayBufferView(L)||W.isArrayBuffer(L))return L.byteLength;if(W.isURLSearchParams(L)&&(L=L+""),W.isString(L))return(await b(L)).byteLength},x=async(L,M)=>{const R=W.toFiniteNumber(L.getContentLength());return R??A(M)};return async L=>{let{url:M,method:R,data:D,signal:B,cancelToken:q,timeout:P,onDownloadProgress:K,onUploadProgress:ge,responseType:Ee,headers:Se,withCredentials:Ue="same-origin",fetchOptions:Ve,maxContentLength:qe,maxBodyLength:St}=Kp(L);const J=W.isNumber(qe)&&qe>-1,fe=W.isNumber(St)&&St>-1;let Le=i||fetch;Ee=Ee?(Ee+"").toLowerCase():"text";let Z=U0([B,q&&q.toAbortSignal()],P),pe=null;const H=Z&&Z.unsubscribe&&(()=>{Z.unsubscribe()});let T;try{if(J&&typeof M=="string"&&M.startsWith("data:")&&G0(M)>qe)throw new Oe("maxContentLength size of "+qe+" exceeded",Oe.ERR_BAD_RESPONSE,L,pe);if(fe&&R!=="get"&&R!=="head"){const _e=await x(Se,D);if(typeof _e=="number"&&isFinite(_e)&&_e>St)throw new Oe("Request body larger than maxBodyLength limit",Oe.ERR_BAD_REQUEST,L,pe)}if(ge&&S&&R!=="get"&&R!=="head"&&(T=await x(Se,D))!==0){let _e=new l(M,{method:"POST",body:D,duplex:"half"}),Te;if(W.isFormData(D)&&(Te=_e.headers.get("content-type"))&&Se.setContentType(Te),_e.body){const[$e,ht]=qp(T,Fl(Gp(ge)));D=Wp(_e.body,Yp,$e,ht)}}W.isString(Ue)||(Ue=Ue?"include":"omit");const ce=f&&"credentials"in l.prototype;if(W.isFormData(D)){const _e=Se.getContentType();_e&&/^multipart\/form-data/i.test(_e)&&!/boundary=/i.test(_e)&&Se.delete("content-type")}Se.set("User-Agent","axios/"+Dd,!1);const de={...Ve,signal:Z,method:R.toUpperCase(),headers:Mp(Se.normalize()),body:D,duplex:"half",credentials:ce?Ue:void 0};pe=f&&new l(M,de);let ye=await(f?Le(pe,Ve):Le(M,de));if(J){const _e=W.toFiniteNumber(ye.headers.get("content-length"));if(_e!=null&&_e>qe)throw new Oe("maxContentLength size of "+qe+" exceeded",Oe.ERR_BAD_RESPONSE,L,pe)}const ie=v&&(Ee==="stream"||Ee==="response");if(v&&ye.body&&(K||J||ie&&H)){const _e={};["status","statusText","headers"].forEach(ft=>{_e[ft]=ye[ft]});const Te=W.toFiniteNumber(ye.headers.get("content-length")),[$e,ht]=K&&qp(Te,Fl(Gp(K),!0))||[];let wt=0;const kt=ft=>{if(J&&(wt=ft,wt>qe))throw new Oe("maxContentLength size of "+qe+" exceeded",Oe.ERR_BAD_RESPONSE,L,pe);$e&&$e(ft)};ye=new c(Wp(ye.body,Yp,kt,()=>{ht&&ht(),H&&H()}),_e)}Ee=Ee||"text";let xe=await _[W.findKey(_,Ee)||"text"](ye,L);if(J&&!v&&!ie){let _e;if(xe!=null&&(typeof xe.byteLength=="number"?_e=xe.byteLength:typeof xe.size=="number"?_e=xe.size:typeof xe=="string"&&(_e=typeof a=="function"?new a().encode(xe).byteLength:xe.length)),typeof _e=="number"&&_e>qe)throw new Oe("maxContentLength size of "+qe+" exceeded",Oe.ERR_BAD_RESPONSE,L,pe)}return!ie&&H&&H(),await new Promise((_e,Te)=>{Pp(_e,Te,{data:xe,headers:Tn.from(ye.headers),status:ye.status,statusText:ye.statusText,config:L,request:pe})})}catch(ce){if(H&&H(),Z&&Z.aborted&&Z.reason instanceof Oe){const de=Z.reason;throw de.config=L,pe&&(de.request=pe),ce!==de&&(de.cause=ce),de}throw ce&&ce.name==="TypeError"&&/Load failed|fetch/i.test(ce.message)?Object.assign(new Oe("Network Error",Oe.ERR_NETWORK,L,pe,ce&&ce.response),{cause:ce.cause||ce}):Oe.from(ce,ce&&ce.code,L,pe,ce&&ce.response)}}},F0=new Map,Jp=o=>{let e=o&&o.env||{};const{fetch:n,Request:a,Response:i}=e,l=[a,i,n];let c=l.length,d=c,f,g,m=F0;for(;d--;)f=l[d],g=m.get(f),g===void 0&&m.set(f,g=d?new Map:V0(e)),m=g;return g};Jp();const Od={http:y0,xhr:j0,fetch:{get:Jp}};W.forEach(Od,(o,e)=>{if(o){try{Object.defineProperty(o,"name",{__proto__:null,value:e})}catch{}Object.defineProperty(o,"adapterName",{__proto__:null,value:e})}});const Qp=o=>`- ${o}`,K0=o=>W.isFunction(o)||o===null||o===!1;function W0(o,e){o=W.isArray(o)?o:[o];const{length:n}=o;let a,i;const l={};for(let c=0;c`adapter ${f} `+(g===!1?"is not supported by the environment":"is not available in the build"));let d=n?c.length>1?`since : -`+c.map(Qp).join(` -`):" "+Qp(c[0]):"as no adapter specified";throw new Oe("There is no suitable adapter to dispatch the request "+d,"ERR_NOT_SUPPORT")}return i}const Zp={getAdapter:W0,adapters:Od};function Ld(o){if(o.cancelToken&&o.cancelToken.throwIfRequested(),o.signal&&o.signal.aborted)throw new fo(null,o)}function em(o){return Ld(o),o.headers=Tn.from(o.headers),o.data=kd.call(o,o.transformRequest),["post","put","patch"].indexOf(o.method)!==-1&&o.headers.setContentType("application/x-www-form-urlencoded",!1),Zp.getAdapter(o.adapter||uo.adapter,o)(o).then(function(a){Ld(o),o.response=a;try{a.data=kd.call(o,o.transformResponse,a)}finally{delete o.response}return a.headers=Tn.from(a.headers),a},function(a){if(!Bp(a)&&(Ld(o),a&&a.response)){o.response=a.response;try{a.response.data=kd.call(o,o.transformResponse,a.response)}finally{delete o.response}a.response.headers=Tn.from(a.response.headers)}return Promise.reject(a)})}const Wl={};["object","boolean","number","function","string","symbol"].forEach((o,e)=>{Wl[o]=function(a){return typeof a===o||"a"+(e<1?"n ":" ")+o}});const tm={};Wl.transitional=function(e,n,a){function i(l,c){return"[Axios v"+Dd+"] Transitional option '"+l+"'"+c+(a?". "+a:"")}return(l,c,d)=>{if(e===!1)throw new Oe(i(c," has been removed"+(n?" in "+n:"")),Oe.ERR_DEPRECATED);return n&&!tm[c]&&(tm[c]=!0,console.warn(i(c," has been deprecated since v"+n+" and will be removed in the near future"))),e?e(l,c,d):!0}},Wl.spelling=function(e){return(n,a)=>(console.warn(`${a} is likely a misspelling of ${e}`),!0)};function Y0(o,e,n){if(typeof o!="object")throw new Oe("options must be an object",Oe.ERR_BAD_OPTION_VALUE);const a=Object.keys(o);let i=a.length;for(;i-- >0;){const l=a[i],c=Object.prototype.hasOwnProperty.call(e,l)?e[l]:void 0;if(c){const d=o[l],f=d===void 0||c(d,l,o);if(f!==!0)throw new Oe("option "+l+" must be "+f,Oe.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new Oe("Unknown option "+l,Oe.ERR_BAD_OPTION)}}const Yl={assertOptions:Y0,validators:Wl},nr=Yl.validators;let mi=class{constructor(e){this.defaults=e||{},this.interceptors={request:new jp,response:new jp}}async request(e,n){try{return await this._request(e,n)}catch(a){if(a instanceof Error){let i={};Error.captureStackTrace?Error.captureStackTrace(i):i=new Error;const l=(()=>{if(!i.stack)return"";const c=i.stack.indexOf(` +`+u.stack}}var Mt=Object.prototype.hasOwnProperty,Vt=o.unstable_scheduleCallback,on=o.unstable_cancelCallback,ln=o.unstable_shouldYield,Br=o.unstable_requestPaint,Ft=o.unstable_now,Ci=o.unstable_getCurrentPriorityLevel,na=o.unstable_ImmediatePriority,yn=o.unstable_UserBlockingPriority,On=o.unstable_NormalPriority,rt=o.unstable_LowPriority,Hn=o.unstable_IdlePriority,bn=o.log,ra=o.unstable_setDisableYieldValue,sr=null,cn=null;function Tn(t){if(typeof bn=="function"&&ra(t),cn&&typeof cn.setStrictMode=="function")try{cn.setStrictMode(sr,t)}catch{}}var un=Math.clz32?Math.clz32:ce,V=Math.log,se=Math.LN2;function ce(t){return t>>>=0,t===0?32:31-(V(t)/se|0)|0}var Z=256,ve=262144,ge=4194304;function we(t){var r=t&42;if(r!==0)return r;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 Ae(t,r,s){var u=t.pendingLanes;if(u===0)return 0;var h=0,p=t.suspendedLanes,C=t.pingedLanes;t=t.warmLanes;var k=u&134217727;return k!==0?(u=k&~p,u!==0?h=we(u):(C&=k,C!==0?h=we(C):s||(s=k&~t,s!==0&&(h=we(s))))):(k=u&~p,k!==0?h=we(k):C!==0?h=we(C):s||(s=u&~t,s!==0&&(h=we(s)))),h===0?0:r!==0&&r!==h&&(r&p)===0&&(p=h&-h,s=r&-r,p>=s||p===32&&(s&4194048)!==0)?r:h}function Ke(t,r){return(t.pendingLanes&~(t.suspendedLanes&~t.pingedLanes)&r)===0}function Te(t,r){switch(t){case 1:case 2:case 4:case 8:case 64:return r+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 r+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 $e(){var t=ge;return ge<<=1,(ge&62914560)===0&&(ge=4194304),t}function Re(t){for(var r=[],s=0;31>s;s++)r.push(t);return r}function et(t,r){t.pendingLanes|=r,r!==268435456&&(t.suspendedLanes=0,t.pingedLanes=0,t.warmLanes=0)}function je(t,r,s,u,h,p){var C=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,U=t.expirationTimes,X=t.hiddenUpdates;for(s=C&~s;0"u")return null;try{return t.activeElement||t.body}catch{return t.body}}var Lf=/[\n"\\]/g;function zn(t){return t.replace(Lf,function(r){return"\\"+r.charCodeAt(0).toString(16)+" "})}function vs(t,r,s,u,h,p,C,k){t.name="",C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"?t.type=C:t.removeAttribute("type"),r!=null?C==="number"?(r===0&&t.value===""||t.value!=r)&&(t.value=""+kn(r)):t.value!==""+kn(r)&&(t.value=""+kn(r)):C!=="submit"&&C!=="reset"||t.removeAttribute("value"),r!=null?ia(t,C,kn(r)):s!=null?ia(t,C,kn(s)):u!=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=""+kn(k):t.removeAttribute("name")}function Ai(t,r,s,u,h,p,C,k){if(p!=null&&typeof p!="function"&&typeof p!="symbol"&&typeof p!="boolean"&&(t.type=p),r!=null||s!=null){if(!(p!=="submit"&&p!=="reset"||r!=null)){Uo(t);return}s=s!=null?""+kn(s):"",r=r!=null?""+kn(r):s,k||r===t.value||(t.value=r),t.defaultValue=r}u=u??h,u=typeof u!="function"&&typeof u!="symbol"&&!!u,t.checked=k?t.checked:!!u,t.defaultChecked=!!u,C!=null&&typeof C!="function"&&typeof C!="symbol"&&typeof C!="boolean"&&(t.name=C),Uo(t)}function ia(t,r,s){r==="number"&&ja(t.ownerDocument)===t||t.defaultValue===""+s||(t.defaultValue=""+s)}function za(t,r,s,u){if(t=t.options,r){r={};for(var h=0;h"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Vo=!1;if(kr)try{var Ti={};Object.defineProperty(Ti,"passive",{get:function(){Vo=!0}}),window.addEventListener("test",Ti,Ti),window.removeEventListener("test",Ti,Ti)}catch{Vo=!1}var Vr=null,Fo=null,ws=null;function Pc(){if(ws)return ws;var t,r=Fo,s=r.length,u,h="value"in Vr?Vr.value:Vr.textContent,p=h.length;for(t=0;t=re),We=" ",dt=!1;function pt(t,r){switch(t){case"keyup":return L.indexOf(r.keyCode)!==-1;case"keydown":return r.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Pt(t){return t=t.detail,typeof t=="object"&&"data"in t?t.data:null}var Or=!1;function Xf(t,r){switch(t){case"compositionend":return Pt(r);case"keypress":return r.which!==32?null:(dt=!0,We);case"textInput":return t=r.data,t===We&&dt?null:t;default:return null}}function Wc(t,r){if(Or)return t==="compositionend"||!I&&pt(t,r)?(t=Pc(),ws=Fo=Vr=null,Or=!1,t):null;switch(t){case"paste":return null;case"keypress":if(!(r.ctrlKey||r.altKey||r.metaKey)||r.ctrlKey&&r.altKey){if(r.char&&1=r)return{node:s,offset:r-t};t=u}e:{for(;s;){if(s.nextSibling){s=s.nextSibling;break e}s=s.parentNode}s=void 0}s=My(s)}}function Ny(t,r){return t&&r?t===r?!0:t&&t.nodeType===3?!1:r&&r.nodeType===3?Ny(t,r.parentNode):"contains"in t?t.contains(r):t.compareDocumentPosition?!!(t.compareDocumentPosition(r)&16):!1:!1}function Iy(t){t=t!=null&&t.ownerDocument!=null&&t.ownerDocument.defaultView!=null?t.ownerDocument.defaultView:window;for(var r=ja(t.document);r instanceof t.HTMLIFrameElement;){try{var s=typeof r.contentWindow.location.href=="string"}catch{s=!1}if(s)t=r.contentWindow;else break;r=ja(t.document)}return r}function th(t){var r=t&&t.nodeName&&t.nodeName.toLowerCase();return r&&(r==="input"&&(t.type==="text"||t.type==="search"||t.type==="tel"||t.type==="url"||t.type==="password")||r==="textarea"||t.contentEditable==="true")}var nx=kr&&"documentMode"in document&&11>=document.documentMode,As=null,nh=null,nl=null,rh=!1;function Hy(t,r,s){var u=s.window===s?s.document:s.nodeType===9?s:s.ownerDocument;rh||As==null||As!==ja(u)||(u=As,"selectionStart"in u&&th(u)?u={start:u.selectionStart,end:u.selectionEnd}:(u=(u.ownerDocument&&u.ownerDocument.defaultView||window).getSelection(),u={anchorNode:u.anchorNode,anchorOffset:u.anchorOffset,focusNode:u.focusNode,focusOffset:u.focusOffset}),nl&&tl(nl,u)||(nl=u,u=Uu(nh,"onSelect"),0>=C,h-=C,Fr=1<<32-un(r)+h|s<Qe?(ct=Ne,Ne=null):ct=Ne.sibling;var yt=Q(K,Ne,Y[Qe],oe);if(yt===null){Ne===null&&(Ne=ct);break}t&&Ne&&yt.alternate===null&&r(K,Ne),G=p(yt,G,Qe),mt===null?Pe=yt:mt.sibling=yt,mt=yt,Ne=ct}if(Qe===Y.length)return s(K,Ne),ft&&ca(K,Qe),Pe;if(Ne===null){for(;QeQe?(ct=Ne,Ne=null):ct=Ne.sibling;var di=Q(K,Ne,yt.value,oe);if(di===null){Ne===null&&(Ne=ct);break}t&&Ne&&di.alternate===null&&r(K,Ne),G=p(di,G,Qe),mt===null?Pe=di:mt.sibling=di,mt=di,Ne=ct}if(yt.done)return s(K,Ne),ft&&ca(K,Qe),Pe;if(Ne===null){for(;!yt.done;Qe++,yt=Y.next())yt=le(K,yt.value,oe),yt!==null&&(G=p(yt,G,Qe),mt===null?Pe=yt:mt.sibling=yt,mt=yt);return ft&&ca(K,Qe),Pe}for(Ne=u(Ne);!yt.done;Qe++,yt=Y.next())yt=ne(Ne,K,Qe,yt.value,oe),yt!==null&&(t&&yt.alternate!==null&&Ne.delete(yt.key===null?Qe:yt.key),G=p(yt,G,Qe),mt===null?Pe=yt:mt.sibling=yt,mt=yt);return t&&Ne.forEach(function(CT){return r(K,CT)}),ft&&ca(K,Qe),Pe}function Dt(K,G,Y,oe){if(typeof Y=="object"&&Y!==null&&Y.type===A&&Y.key===null&&(Y=Y.props.children),typeof Y=="object"&&Y!==null){switch(Y.$$typeof){case v:e:{for(var Pe=Y.key;G!==null;){if(G.key===Pe){if(Pe=Y.type,Pe===A){if(G.tag===7){s(K,G.sibling),oe=h(G,Y.props.children),oe.return=K,K=oe;break e}}else if(G.elementType===Pe||typeof Pe=="object"&&Pe!==null&&Pe.$$typeof===W&&qi(Pe)===G.type){s(K,G.sibling),oe=h(G,Y.props),ll(oe,Y),oe.return=K,K=oe;break e}s(K,G);break}else r(K,G);G=G.sibling}Y.type===A?(oe=ji(Y.props.children,K.mode,oe,Y.key),oe.return=K,K=oe):(oe=ru(Y.type,Y.key,Y.props,null,K.mode,oe),ll(oe,Y),oe.return=K,K=oe)}return C(K);case _:e:{for(Pe=Y.key;G!==null;){if(G.key===Pe)if(G.tag===4&&G.stateNode.containerInfo===Y.containerInfo&&G.stateNode.implementation===Y.implementation){s(K,G.sibling),oe=h(G,Y.children||[]),oe.return=K,K=oe;break e}else{s(K,G);break}else r(K,G);G=G.sibling}oe=uh(Y,K.mode,oe),oe.return=K,K=oe}return C(K);case W:return Y=qi(Y),Dt(K,G,Y,oe)}if(wt(Y))return De(K,G,Y,oe);if(Ue(Y)){if(Pe=Ue(Y),typeof Pe!="function")throw Error(a(150));return Y=Pe.call(Y),qe(K,G,Y,oe)}if(typeof Y.then=="function")return Dt(K,G,uu(Y),oe);if(Y.$$typeof===T)return Dt(K,G,su(K,Y),oe);du(K,Y)}return typeof Y=="string"&&Y!==""||typeof Y=="number"||typeof Y=="bigint"?(Y=""+Y,G!==null&&G.tag===6?(s(K,G.sibling),oe=h(G,Y),oe.return=K,K=oe):(s(K,G),oe=ch(Y,K.mode,oe),oe.return=K,K=oe),C(K)):s(K,G)}return function(K,G,Y,oe){try{ol=0;var Pe=Dt(K,G,Y,oe);return Is=null,Pe}catch(Ne){if(Ne===Ns||Ne===lu)throw Ne;var mt=Xn(29,Ne,null,K.mode);return mt.lanes=oe,mt.return=K,mt}}}var Vi=sb(!0),ob=sb(!1),Wa=!1;function Ch(t){t.updateQueue={baseState:t.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Eh(t,r){t=t.updateQueue,r.updateQueue===t&&(r.updateQueue={baseState:t.baseState,firstBaseUpdate:t.firstBaseUpdate,lastBaseUpdate:t.lastBaseUpdate,shared:t.shared,callbacks:null})}function Ya(t){return{lane:t,tag:0,payload:null,callback:null,next:null}}function Xa(t,r,s){var u=t.updateQueue;if(u===null)return null;if(u=u.shared,(St&2)!==0){var h=u.pending;return h===null?r.next=r:(r.next=h.next,h.next=r),u.pending=r,r=nu(t),Gy(t,null,s),r}return tu(t,u,r,s),nu(t)}function cl(t,r,s){if(r=r.updateQueue,r!==null&&(r=r.shared,(s&4194048)!==0)){var u=r.lanes;u&=t.pendingLanes,s|=u,r.lanes=s,Se(t,s)}}function _h(t,r){var s=t.updateQueue,u=t.alternate;if(u!==null&&(u=u.updateQueue,s===u)){var h=null,p=null;if(s=s.firstBaseUpdate,s!==null){do{var C={lane:s.lane,tag:s.tag,payload:s.payload,callback:null,next:null};p===null?h=p=C:p=p.next=C,s=s.next}while(s!==null);p===null?h=p=r:p=p.next=r}else h=p=r;s={baseState:u.baseState,firstBaseUpdate:h,lastBaseUpdate:p,shared:u.shared,callbacks:u.callbacks},t.updateQueue=s;return}t=s.lastBaseUpdate,t===null?s.firstBaseUpdate=r:t.next=r,s.lastBaseUpdate=r}var Ah=!1;function ul(){if(Ah){var t=$s;if(t!==null)throw t}}function dl(t,r,s,u){Ah=!1;var h=t.updateQueue;Wa=!1;var p=h.firstBaseUpdate,C=h.lastBaseUpdate,k=h.shared.pending;if(k!==null){h.shared.pending=null;var U=k,X=U.next;U.next=null,C===null?p=X:C.next=X,C=U;var ae=t.alternate;ae!==null&&(ae=ae.updateQueue,k=ae.lastBaseUpdate,k!==C&&(k===null?ae.firstBaseUpdate=X:k.next=X,ae.lastBaseUpdate=U))}if(p!==null){var le=h.baseState;C=0,ae=X=U=null,k=p;do{var Q=k.lane&-536870913,ne=Q!==k.lane;if(ne?(lt&Q)===Q:(u&Q)===Q){Q!==0&&Q===Ms&&(Ah=!0),ae!==null&&(ae=ae.next={lane:0,tag:k.tag,payload:k.payload,callback:null,next:null});e:{var De=t,qe=k;Q=r;var Dt=s;switch(qe.tag){case 1:if(De=qe.payload,typeof De=="function"){le=De.call(Dt,le,Q);break e}le=De;break e;case 3:De.flags=De.flags&-65537|128;case 0:if(De=qe.payload,Q=typeof De=="function"?De.call(Dt,le,Q):De,Q==null)break e;le=y({},le,Q);break e;case 2:Wa=!0}}Q=k.callback,Q!==null&&(t.flags|=64,ne&&(t.flags|=8192),ne=h.callbacks,ne===null?h.callbacks=[Q]:ne.push(Q))}else ne={lane:Q,tag:k.tag,payload:k.payload,callback:k.callback,next:null},ae===null?(X=ae=ne,U=le):ae=ae.next=ne,C|=Q;if(k=k.next,k===null){if(k=h.shared.pending,k===null)break;ne=k,k=ne.next,ne.next=null,h.lastBaseUpdate=ne,h.shared.pending=null}}while(!0);ae===null&&(U=le),h.baseState=U,h.firstBaseUpdate=X,h.lastBaseUpdate=ae,p===null&&(h.shared.lanes=0),ti|=C,t.lanes=C,t.memoizedState=le}}function lb(t,r){if(typeof t!="function")throw Error(a(191,t));t.call(r)}function cb(t,r){var s=t.callbacks;if(s!==null)for(t.callbacks=null,t=0;tp?p:8;var C=J.T,k={};J.T=k,Gh(t,!1,r,s);try{var U=h(),X=J.S;if(X!==null&&X(k,U),U!==null&&typeof U=="object"&&typeof U.then=="function"){var ae=dx(U,u);gl(t,r,ae,tr(t))}else gl(t,r,u,tr(t))}catch(le){gl(t,r,{then:function(){},status:"rejected",reason:le},tr())}finally{ue.p=p,C!==null&&k.types!==null&&(C.types=k.types),J.T=C}}function yx(){}function Bh(t,r,s,u){if(t.tag!==5)throw Error(a(476));var h=Pb(t).queue;Ub(t,h,r,Me,s===null?yx:function(){return Bb(t),s(u)})}function Pb(t){var r=t.memoizedState;if(r!==null)return r;r={memoizedState:Me,baseState:Me,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ha,lastRenderedState:Me},next:null};var s={};return r.next={memoizedState:s,baseState:s,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ha,lastRenderedState:s},next:null},t.memoizedState=r,t=t.alternate,t!==null&&(t.memoizedState=r),r}function Bb(t){var r=Pb(t);r.next===null&&(r=t.alternate.memoizedState),gl(t,r.next.queue,{},tr())}function qh(){return wn(Ol)}function qb(){return Jt().memoizedState}function Gb(){return Jt().memoizedState}function bx(t){for(var r=t.return;r!==null;){switch(r.tag){case 24:case 3:var s=tr();t=Ya(s);var u=Xa(r,t,s);u!==null&&(Gn(u,r,s),cl(u,r,s)),r={cache:bh()},t.payload=r;return}r=r.return}}function vx(t,r,s){var u=tr();s={lane:u,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null},wu(t)?Fb(r,s):(s=oh(t,r,s,u),s!==null&&(Gn(s,t,u),Kb(s,r,u)))}function Vb(t,r,s){var u=tr();gl(t,r,s,u)}function gl(t,r,s,u){var h={lane:u,revertLane:0,gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null};if(wu(t))Fb(r,h);else{var p=t.alternate;if(t.lanes===0&&(p===null||p.lanes===0)&&(p=r.lastRenderedReducer,p!==null))try{var C=r.lastRenderedState,k=p(C,s);if(h.hasEagerState=!0,h.eagerState=k,Yn(k,C))return tu(t,r,h,0),Lt===null&&eu(),!1}catch{}if(s=oh(t,r,h,u),s!==null)return Gn(s,t,u),Kb(s,r,u),!0}return!1}function Gh(t,r,s,u){if(u={lane:2,revertLane:Cg(),gesture:null,action:u,hasEagerState:!1,eagerState:null,next:null},wu(t)){if(r)throw Error(a(479))}else r=oh(t,s,u,2),r!==null&&Gn(r,t,2)}function wu(t){var r=t.alternate;return t===Je||r!==null&&r===Je}function Fb(t,r){js=gu=!0;var s=t.pending;s===null?r.next=r:(r.next=s.next,s.next=r),t.pending=r}function Kb(t,r,s){if((s&4194048)!==0){var u=r.lanes;u&=t.pendingLanes,s|=u,r.lanes=s,Se(t,s)}}var pl={readContext:wn,use:yu,useCallback:Kt,useContext:Kt,useEffect:Kt,useImperativeHandle:Kt,useLayoutEffect:Kt,useInsertionEffect:Kt,useMemo:Kt,useReducer:Kt,useRef:Kt,useState:Kt,useDebugValue:Kt,useDeferredValue:Kt,useTransition:Kt,useSyncExternalStore:Kt,useId:Kt,useHostTransitionStatus:Kt,useFormState:Kt,useActionState:Kt,useOptimistic:Kt,useMemoCache:Kt,useCacheRefresh:Kt};pl.useEffectEvent=Kt;var Wb={readContext:wn,use:yu,useCallback:function(t,r){return Mn().memoizedState=[t,r===void 0?null:r],t},useContext:wn,useEffect:Ob,useImperativeHandle:function(t,r,s){s=s!=null?s.concat([t]):null,vu(4194308,4,Nb.bind(null,r,t),s)},useLayoutEffect:function(t,r){return vu(4194308,4,t,r)},useInsertionEffect:function(t,r){vu(4,2,t,r)},useMemo:function(t,r){var s=Mn();r=r===void 0?null:r;var u=t();if(Fi){Tn(!0);try{t()}finally{Tn(!1)}}return s.memoizedState=[u,r],u},useReducer:function(t,r,s){var u=Mn();if(s!==void 0){var h=s(r);if(Fi){Tn(!0);try{s(r)}finally{Tn(!1)}}}else h=r;return u.memoizedState=u.baseState=h,t={pending:null,lanes:0,dispatch:null,lastRenderedReducer:t,lastRenderedState:h},u.queue=t,t=t.dispatch=vx.bind(null,Je,t),[u.memoizedState,t]},useRef:function(t){var r=Mn();return t={current:t},r.memoizedState=t},useState:function(t){t=Hh(t);var r=t.queue,s=Vb.bind(null,Je,r);return r.dispatch=s,[t.memoizedState,s]},useDebugValue:Uh,useDeferredValue:function(t,r){var s=Mn();return Ph(s,t,r)},useTransition:function(){var t=Hh(!1);return t=Ub.bind(null,Je,t.queue,!0,!1),Mn().memoizedState=t,[!1,t]},useSyncExternalStore:function(t,r,s){var u=Je,h=Mn();if(ft){if(s===void 0)throw Error(a(407));s=s()}else{if(s=r(),Lt===null)throw Error(a(349));(lt&127)!==0||pb(u,r,s)}h.memoizedState=s;var p={value:s,getSnapshot:r};return h.queue=p,Ob(yb.bind(null,u,p,t),[t]),u.flags|=2048,Us(9,{destroy:void 0},mb.bind(null,u,p,s,r),null),s},useId:function(){var t=Mn(),r=Lt.identifierPrefix;if(ft){var s=Kr,u=Fr;s=(u&~(1<<32-un(u)-1)).toString(32)+s,r="_"+r+"R_"+s,s=pu++,0<\/script>",p=p.removeChild(p.firstChild);break;case"select":p=typeof u.is=="string"?C.createElement("select",{is:u.is}):C.createElement("select"),u.multiple?p.multiple=!0:u.size&&(p.size=u.size);break;default:p=typeof u.is=="string"?C.createElement(h,{is:u.is}):C.createElement(h)}}p[Ut]=r,p[Rn]=u;e:for(C=r.child;C!==null;){if(C.tag===5||C.tag===6)p.appendChild(C.stateNode);else if(C.tag!==4&&C.tag!==27&&C.child!==null){C.child.return=C,C=C.child;continue}if(C===r)break e;for(;C.sibling===null;){if(C.return===null||C.return===r)break e;C=C.return}C.sibling.return=C.return,C=C.sibling}r.stateNode=p;e:switch(En(p,h,u),h){case"button":case"input":case"select":case"textarea":u=!!u.autoFocus;break e;case"img":u=!0;break e;default:u=!1}u&&pa(r)}}return Nt(r),ag(r,r.type,t===null?null:t.memoizedProps,r.pendingProps,s),null;case 6:if(t&&r.stateNode!=null)t.memoizedProps!==u&&pa(r);else{if(typeof u!="string"&&r.stateNode===null)throw Error(a(166));if(t=ee.current,Os(r)){if(t=r.stateNode,s=r.memoizedProps,u=null,h=Sn,h!==null)switch(h.tag){case 27:case 5:u=h.memoizedProps}t[Ut]=r,t=!!(t.nodeValue===s||u!==null&&u.suppressHydrationWarning===!0||hS(t.nodeValue,s)),t||Fa(r,!0)}else t=Pu(t).createTextNode(u),t[Ut]=r,r.stateNode=t}return Nt(r),null;case 31:if(s=r.memoizedState,t===null||t.memoizedState!==null){if(u=Os(r),s!==null){if(t===null){if(!u)throw Error(a(318));if(t=r.memoizedState,t=t!==null?t.dehydrated:null,!t)throw Error(a(557));t[Ut]=r}else zi(),(r.flags&128)===0&&(r.memoizedState=null),r.flags|=4;Nt(r),t=!1}else s=gh(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=s),t=!0;if(!t)return r.flags&256?(Qn(r),r):(Qn(r),null);if((r.flags&128)!==0)throw Error(a(558))}return Nt(r),null;case 13:if(u=r.memoizedState,t===null||t.memoizedState!==null&&t.memoizedState.dehydrated!==null){if(h=Os(r),u!==null&&u.dehydrated!==null){if(t===null){if(!h)throw Error(a(318));if(h=r.memoizedState,h=h!==null?h.dehydrated:null,!h)throw Error(a(317));h[Ut]=r}else zi(),(r.flags&128)===0&&(r.memoizedState=null),r.flags|=4;Nt(r),h=!1}else h=gh(),t!==null&&t.memoizedState!==null&&(t.memoizedState.hydrationErrors=h),h=!0;if(!h)return r.flags&256?(Qn(r),r):(Qn(r),null)}return Qn(r),(r.flags&128)!==0?(r.lanes=s,r):(s=u!==null,t=t!==null&&t.memoizedState!==null,s&&(u=r.child,h=null,u.alternate!==null&&u.alternate.memoizedState!==null&&u.alternate.memoizedState.cachePool!==null&&(h=u.alternate.memoizedState.cachePool.pool),p=null,u.memoizedState!==null&&u.memoizedState.cachePool!==null&&(p=u.memoizedState.cachePool.pool),p!==h&&(u.flags|=2048)),s!==t&&s&&(r.child.flags|=8192),xu(r,r.updateQueue),Nt(r),null);case 4:return ke(),t===null&&xg(r.stateNode.containerInfo),Nt(r),null;case 10:return da(r.type),Nt(r),null;case 19:if(R(Xt),u=r.memoizedState,u===null)return Nt(r),null;if(h=(r.flags&128)!==0,p=u.rendering,p===null)if(h)yl(u,!1);else{if(Wt!==0||t!==null&&(t.flags&128)!==0)for(t=r.child;t!==null;){if(p=hu(t),p!==null){for(r.flags|=128,yl(u,!1),t=p.updateQueue,r.updateQueue=t,xu(r,t),r.subtreeFlags=0,t=s,s=r.child;s!==null;)Vy(s,t),s=s.sibling;return de(Xt,Xt.current&1|2),ft&&ca(r,u.treeForkCount),r.child}t=t.sibling}u.tail!==null&&Ft()>Ou&&(r.flags|=128,h=!0,yl(u,!1),r.lanes=4194304)}else{if(!h)if(t=hu(p),t!==null){if(r.flags|=128,h=!0,t=t.updateQueue,r.updateQueue=t,xu(r,t),yl(u,!0),u.tail===null&&u.tailMode==="hidden"&&!p.alternate&&!ft)return Nt(r),null}else 2*Ft()-u.renderingStartTime>Ou&&s!==536870912&&(r.flags|=128,h=!0,yl(u,!1),r.lanes=4194304);u.isBackwards?(p.sibling=r.child,r.child=p):(t=u.last,t!==null?t.sibling=p:r.child=p,u.last=p)}return u.tail!==null?(t=u.tail,u.rendering=t,u.tail=t.sibling,u.renderingStartTime=Ft(),t.sibling=null,s=Xt.current,de(Xt,h?s&1|2:s&1),ft&&ca(r,u.treeForkCount),t):(Nt(r),null);case 22:case 23:return Qn(r),Th(),u=r.memoizedState!==null,t!==null?t.memoizedState!==null!==u&&(r.flags|=8192):u&&(r.flags|=8192),u?(s&536870912)!==0&&(r.flags&128)===0&&(Nt(r),r.subtreeFlags&6&&(r.flags|=8192)):Nt(r),s=r.updateQueue,s!==null&&xu(r,s.retryQueue),s=null,t!==null&&t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(s=t.memoizedState.cachePool.pool),u=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(u=r.memoizedState.cachePool.pool),u!==s&&(r.flags|=2048),t!==null&&R(Bi),null;case 24:return s=null,t!==null&&(s=t.memoizedState.cache),r.memoizedState.cache!==s&&(r.flags|=2048),da(en),Nt(r),null;case 25:return null;case 30:return null}throw Error(a(156,r.tag))}function _x(t,r){switch(fh(r),r.tag){case 1:return t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 3:return da(en),ke(),t=r.flags,(t&65536)!==0&&(t&128)===0?(r.flags=t&-65537|128,r):null;case 26:case 27:case 5:return Ct(r),null;case 31:if(r.memoizedState!==null){if(Qn(r),r.alternate===null)throw Error(a(340));zi()}return t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 13:if(Qn(r),t=r.memoizedState,t!==null&&t.dehydrated!==null){if(r.alternate===null)throw Error(a(340));zi()}return t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 19:return R(Xt),null;case 4:return ke(),null;case 10:return da(r.type),null;case 22:case 23:return Qn(r),Th(),t!==null&&R(Bi),t=r.flags,t&65536?(r.flags=t&-65537|128,r):null;case 24:return da(en),null;case 25:return null;default:return null}}function bv(t,r){switch(fh(r),r.tag){case 3:da(en),ke();break;case 26:case 27:case 5:Ct(r);break;case 4:ke();break;case 31:r.memoizedState!==null&&Qn(r);break;case 13:Qn(r);break;case 19:R(Xt);break;case 10:da(r.type);break;case 22:case 23:Qn(r),Th(),t!==null&&R(Bi);break;case 24:da(en)}}function bl(t,r){try{var s=r.updateQueue,u=s!==null?s.lastEffect:null;if(u!==null){var h=u.next;s=h;do{if((s.tag&t)===t){u=void 0;var p=s.create,C=s.inst;u=p(),C.destroy=u}s=s.next}while(s!==h)}}catch(k){xt(r,r.return,k)}}function Za(t,r,s){try{var u=r.updateQueue,h=u!==null?u.lastEffect:null;if(h!==null){var p=h.next;u=p;do{if((u.tag&t)===t){var C=u.inst,k=C.destroy;if(k!==void 0){C.destroy=void 0,h=r;var U=s,X=k;try{X()}catch(ae){xt(h,U,ae)}}}u=u.next}while(u!==p)}}catch(ae){xt(r,r.return,ae)}}function vv(t){var r=t.updateQueue;if(r!==null){var s=t.stateNode;try{cb(r,s)}catch(u){xt(t,t.return,u)}}}function Sv(t,r,s){s.props=Ki(t.type,t.memoizedProps),s.state=t.memoizedState;try{s.componentWillUnmount()}catch(u){xt(t,r,u)}}function vl(t,r){try{var s=t.ref;if(s!==null){switch(t.tag){case 26:case 27:case 5:var u=t.stateNode;break;case 30:u=t.stateNode;break;default:u=t.stateNode}typeof s=="function"?t.refCleanup=s(u):s.current=u}}catch(h){xt(t,r,h)}}function Wr(t,r){var s=t.ref,u=t.refCleanup;if(s!==null)if(typeof u=="function")try{u()}catch(h){xt(t,r,h)}finally{t.refCleanup=null,t=t.alternate,t!=null&&(t.refCleanup=null)}else if(typeof s=="function")try{s(null)}catch(h){xt(t,r,h)}else s.current=null}function wv(t){var r=t.type,s=t.memoizedProps,u=t.stateNode;try{e:switch(r){case"button":case"input":case"select":case"textarea":s.autoFocus&&u.focus();break e;case"img":s.src?u.src=s.src:s.srcSet&&(u.srcset=s.srcSet)}}catch(h){xt(t,t.return,h)}}function ig(t,r,s){try{var u=t.stateNode;Fx(u,t.type,s,r),u[Rn]=r}catch(h){xt(t,t.return,h)}}function Cv(t){return t.tag===5||t.tag===3||t.tag===26||t.tag===27&&si(t.type)||t.tag===4}function sg(t){e:for(;;){for(;t.sibling===null;){if(t.return===null||Cv(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&&si(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 og(t,r,s){var u=t.tag;if(u===5||u===6)t=t.stateNode,r?(s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s).insertBefore(t,r):(r=s.nodeType===9?s.body:s.nodeName==="HTML"?s.ownerDocument.body:s,r.appendChild(t),s=s._reactRootContainer,s!=null||r.onclick!==null||(r.onclick=Rr));else if(u!==4&&(u===27&&si(t.type)&&(s=t.stateNode,r=null),t=t.child,t!==null))for(og(t,r,s),t=t.sibling;t!==null;)og(t,r,s),t=t.sibling}function Tu(t,r,s){var u=t.tag;if(u===5||u===6)t=t.stateNode,r?s.insertBefore(t,r):s.appendChild(t);else if(u!==4&&(u===27&&si(t.type)&&(s=t.stateNode),t=t.child,t!==null))for(Tu(t,r,s),t=t.sibling;t!==null;)Tu(t,r,s),t=t.sibling}function Ev(t){var r=t.stateNode,s=t.memoizedProps;try{for(var u=t.type,h=r.attributes;h.length;)r.removeAttributeNode(h[0]);En(r,u,s),r[Ut]=t,r[Rn]=s}catch(p){xt(t,t.return,p)}}var ma=!1,rn=!1,lg=!1,_v=typeof WeakSet=="function"?WeakSet:Set,pn=null;function Ax(t,r){if(t=t.containerInfo,kg=Wu,t=Iy(t),th(t)){if("selectionStart"in t)var s={start:t.selectionStart,end:t.selectionEnd};else e:{s=(s=t.ownerDocument)&&s.defaultView||window;var u=s.getSelection&&s.getSelection();if(u&&u.rangeCount!==0){s=u.anchorNode;var h=u.anchorOffset,p=u.focusNode;u=u.focusOffset;try{s.nodeType,p.nodeType}catch{s=null;break e}var C=0,k=-1,U=-1,X=0,ae=0,le=t,Q=null;t:for(;;){for(var ne;le!==s||h!==0&&le.nodeType!==3||(k=C+h),le!==p||u!==0&&le.nodeType!==3||(U=C+u),le.nodeType===3&&(C+=le.nodeValue.length),(ne=le.firstChild)!==null;)Q=le,le=ne;for(;;){if(le===t)break t;if(Q===s&&++X===h&&(k=C),Q===p&&++ae===u&&(U=C),(ne=le.nextSibling)!==null)break;le=Q,Q=le.parentNode}le=ne}s=k===-1||U===-1?null:{start:k,end:U}}else s=null}s=s||{start:0,end:0}}else s=null;for(Dg={focusedElem:t,selectionRange:s},Wu=!1,pn=r;pn!==null;)if(r=pn,t=r.child,(r.subtreeFlags&1028)!==0&&t!==null)t.return=r,pn=t;else for(;pn!==null;){switch(r=pn,p=r.alternate,t=r.flags,r.tag){case 0:if((t&4)!==0&&(t=r.updateQueue,t=t!==null?t.events:null,t!==null))for(s=0;s title"))),En(p,u,s),p[Ut]=t,Zt(p),u=p;break e;case"link":var C=DS("link","href",h).get(u+(s.href||""));if(C){for(var k=0;kDt&&(C=Dt,Dt=qe,qe=C);var K=$y(k,qe),G=$y(k,Dt);if(K&&G&&(ne.rangeCount!==1||ne.anchorNode!==K.node||ne.anchorOffset!==K.offset||ne.focusNode!==G.node||ne.focusOffset!==G.offset)){var Y=le.createRange();Y.setStart(K.node,K.offset),ne.removeAllRanges(),qe>Dt?(ne.addRange(Y),ne.extend(G.node,G.offset)):(Y.setEnd(G.node,G.offset),ne.addRange(Y))}}}}for(le=[],ne=k;ne=ne.parentNode;)ne.nodeType===1&&le.push({element:ne,left:ne.scrollLeft,top:ne.scrollTop});for(typeof k.focus=="function"&&k.focus(),k=0;ks?32:s,J.T=null,s=pg,pg=null;var p=ri,C=wa;if(fn=0,Vs=ri=null,wa=0,(St&6)!==0)throw Error(a(331));var k=St;if(St|=4,Nv(p.current),Lv(p,p.current,C,s),St=k,Al(0,!1),cn&&typeof cn.onPostCommitFiberRoot=="function")try{cn.onPostCommitFiberRoot(sr,p)}catch{}return!0}finally{ue.p=h,J.T=u,Zv(t,r)}}function tS(t,r,s){r=cr(s,r),r=Wh(t.stateNode,r,2),t=Xa(t,r,2),t!==null&&(et(t,2),Yr(t))}function xt(t,r,s){if(t.tag===3)tS(t,t,s);else for(;r!==null;){if(r.tag===3){tS(r,t,s);break}else if(r.tag===1){var u=r.stateNode;if(typeof r.type.getDerivedStateFromError=="function"||typeof u.componentDidCatch=="function"&&(ni===null||!ni.has(u))){t=cr(s,t),s=nv(2),u=Xa(r,s,2),u!==null&&(rv(s,u,r,t),et(u,2),Yr(u));break}}r=r.return}}function vg(t,r,s){var u=t.pingCache;if(u===null){u=t.pingCache=new Rx;var h=new Set;u.set(r,h)}else h=u.get(r),h===void 0&&(h=new Set,u.set(r,h));h.has(s)||(dg=!0,h.add(s),t=Mx.bind(null,t,r,s),r.then(t,t))}function Mx(t,r,s){var u=t.pingCache;u!==null&&u.delete(r),t.pingedLanes|=t.suspendedLanes&s,t.warmLanes&=~s,Lt===t&&(lt&s)===s&&(Wt===4||Wt===3&&(lt&62914560)===lt&&300>Ft()-Du?(St&2)===0&&Fs(t,0):fg|=s,Gs===lt&&(Gs=0)),Yr(t)}function nS(t,r){r===0&&(r=$e()),t=Hi(t,r),t!==null&&(et(t,r),Yr(t))}function $x(t){var r=t.memoizedState,s=0;r!==null&&(s=r.retryLane),nS(t,s)}function Nx(t,r){var s=0;switch(t.tag){case 31:case 13:var u=t.stateNode,h=t.memoizedState;h!==null&&(s=h.retryLane);break;case 19:u=t.stateNode;break;case 22:u=t.stateNode._retryCache;break;default:throw Error(a(314))}u!==null&&u.delete(r),nS(t,s)}function Ix(t,r){return Vt(t,r)}var Hu=null,Ws=null,Sg=!1,ju=!1,wg=!1,ii=0;function Yr(t){t!==Ws&&t.next===null&&(Ws===null?Hu=Ws=t:Ws=Ws.next=t),ju=!0,Sg||(Sg=!0,jx())}function Al(t,r){if(!wg&&ju){wg=!0;do for(var s=!1,u=Hu;u!==null;){if(t!==0){var h=u.pendingLanes;if(h===0)var p=0;else{var C=u.suspendedLanes,k=u.pingedLanes;p=(1<<31-un(42|t)+1)-1,p&=h&~(C&~k),p=p&201326741?p&201326741|1:p?p|2:0}p!==0&&(s=!0,sS(u,p))}else p=lt,p=Ae(u,u===Lt?p:0,u.cancelPendingCommit!==null||u.timeoutHandle!==-1),(p&3)===0||Ke(u,p)||(s=!0,sS(u,p));u=u.next}while(s);wg=!1}}function Hx(){rS()}function rS(){ju=Sg=!1;var t=0;ii!==0&&Wx()&&(t=ii);for(var r=Ft(),s=null,u=Hu;u!==null;){var h=u.next,p=aS(u,r);p===0?(u.next=null,s===null?Hu=h:s.next=h,h===null&&(Ws=s)):(s=u,(t!==0||(p&3)!==0)&&(ju=!0)),u=h}fn!==0&&fn!==5||Al(t),ii!==0&&(ii=0)}function aS(t,r){for(var s=t.suspendedLanes,u=t.pingedLanes,h=t.expirationTimes,p=t.pendingLanes&-62914561;0k)break;var ae=U.transferSize,le=U.initiatorType;ae&&gS(le)&&(U=U.responseEnd,C+=ae*(U"u"?null:document;function xS(t,r,s){var u=Ys;if(u&&typeof r=="string"&&r){var h=zn(r);h='link[rel="'+t+'"][href="'+h+'"]',typeof s=="string"&&(h+='[crossorigin="'+s+'"]'),AS.has(h)||(AS.add(h),t={rel:t,crossOrigin:s,href:r},u.querySelector(h)===null&&(r=u.createElement("link"),En(r,"link",t),Zt(r),u.head.appendChild(r)))}}function rT(t){Ca.D(t),xS("dns-prefetch",t,null)}function aT(t,r){Ca.C(t,r),xS("preconnect",t,r)}function iT(t,r,s){Ca.L(t,r,s);var u=Ys;if(u&&t&&r){var h='link[rel="preload"][as="'+zn(r)+'"]';r==="image"&&s&&s.imageSrcSet?(h+='[imagesrcset="'+zn(s.imageSrcSet)+'"]',typeof s.imageSizes=="string"&&(h+='[imagesizes="'+zn(s.imageSizes)+'"]')):h+='[href="'+zn(t)+'"]';var p=h;switch(r){case"style":p=Xs(t);break;case"script":p=Js(t)}pr.has(p)||(t=y({rel:"preload",href:r==="image"&&s&&s.imageSrcSet?void 0:t,as:r},s),pr.set(p,t),u.querySelector(h)!==null||r==="style"&&u.querySelector(kl(p))||r==="script"&&u.querySelector(Dl(p))||(r=u.createElement("link"),En(r,"link",t),Zt(r),u.head.appendChild(r)))}}function sT(t,r){Ca.m(t,r);var s=Ys;if(s&&t){var u=r&&typeof r.as=="string"?r.as:"script",h='link[rel="modulepreload"][as="'+zn(u)+'"][href="'+zn(t)+'"]',p=h;switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":p=Js(t)}if(!pr.has(p)&&(t=y({rel:"modulepreload",href:t},r),pr.set(p,t),s.querySelector(h)===null)){switch(u){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(s.querySelector(Dl(p)))return}u=s.createElement("link"),En(u,"link",t),Zt(u),s.head.appendChild(u)}}}function oT(t,r,s){Ca.S(t,r,s);var u=Ys;if(u&&t){var h=Ia(u).hoistableStyles,p=Xs(t);r=r||"default";var C=h.get(p);if(!C){var k={loading:0,preload:null};if(C=u.querySelector(kl(p)))k.loading=5;else{t=y({rel:"stylesheet",href:t,"data-precedence":r},s),(s=pr.get(p))&&Hg(t,s);var U=C=u.createElement("link");Zt(U),En(U,"link",t),U._p=new Promise(function(X,ae){U.onload=X,U.onerror=ae}),U.addEventListener("load",function(){k.loading|=1}),U.addEventListener("error",function(){k.loading|=2}),k.loading|=4,qu(C,r,u)}C={type:"stylesheet",instance:C,count:1,state:k},h.set(p,C)}}}function lT(t,r){Ca.X(t,r);var s=Ys;if(s&&t){var u=Ia(s).hoistableScripts,h=Js(t),p=u.get(h);p||(p=s.querySelector(Dl(h)),p||(t=y({src:t,async:!0},r),(r=pr.get(h))&&jg(t,r),p=s.createElement("script"),Zt(p),En(p,"link",t),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},u.set(h,p))}}function cT(t,r){Ca.M(t,r);var s=Ys;if(s&&t){var u=Ia(s).hoistableScripts,h=Js(t),p=u.get(h);p||(p=s.querySelector(Dl(h)),p||(t=y({src:t,async:!0,type:"module"},r),(r=pr.get(h))&&jg(t,r),p=s.createElement("script"),Zt(p),En(p,"link",t),s.head.appendChild(p)),p={type:"script",instance:p,count:1,state:null},u.set(h,p))}}function TS(t,r,s,u){var h=(h=ee.current)?Bu(h):null;if(!h)throw Error(a(446));switch(t){case"meta":case"title":return null;case"style":return typeof s.precedence=="string"&&typeof s.href=="string"?(r=Xs(s.href),s=Ia(h).hoistableStyles,u=s.get(r),u||(u={type:"style",instance:null,count:0,state:null},s.set(r,u)),u):{type:"void",instance:null,count:0,state:null};case"link":if(s.rel==="stylesheet"&&typeof s.href=="string"&&typeof s.precedence=="string"){t=Xs(s.href);var p=Ia(h).hoistableStyles,C=p.get(t);if(C||(h=h.ownerDocument||h,C={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},p.set(t,C),(p=h.querySelector(kl(t)))&&!p._p&&(C.instance=p,C.state.loading=5),pr.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},pr.set(t,s),p||uT(h,t,s,C.state))),r&&u===null)throw Error(a(528,""));return C}if(r&&u!==null)throw Error(a(529,""));return null;case"script":return r=s.async,s=s.src,typeof s=="string"&&r&&typeof r!="function"&&typeof r!="symbol"?(r=Js(s),s=Ia(h).hoistableScripts,u=s.get(r),u||(u={type:"script",instance:null,count:0,state:null},s.set(r,u)),u):{type:"void",instance:null,count:0,state:null};default:throw Error(a(444,t))}}function Xs(t){return'href="'+zn(t)+'"'}function kl(t){return'link[rel="stylesheet"]['+t+"]"}function RS(t){return y({},t,{"data-precedence":t.precedence,precedence:null})}function uT(t,r,s,u){t.querySelector('link[rel="preload"][as="style"]['+r+"]")?u.loading=1:(r=t.createElement("link"),u.preload=r,r.addEventListener("load",function(){return u.loading|=1}),r.addEventListener("error",function(){return u.loading|=2}),En(r,"link",s),Zt(r),t.head.appendChild(r))}function Js(t){return'[src="'+zn(t)+'"]'}function Dl(t){return"script[async]"+t}function kS(t,r,s){if(r.count++,r.instance===null)switch(r.type){case"style":var u=t.querySelector('style[data-href~="'+zn(s.href)+'"]');if(u)return r.instance=u,Zt(u),u;var h=y({},s,{"data-href":s.href,"data-precedence":s.precedence,href:null,precedence:null});return u=(t.ownerDocument||t).createElement("style"),Zt(u),En(u,"style",h),qu(u,s.precedence,t),r.instance=u;case"stylesheet":h=Xs(s.href);var p=t.querySelector(kl(h));if(p)return r.state.loading|=4,r.instance=p,Zt(p),p;u=RS(s),(h=pr.get(h))&&Hg(u,h),p=(t.ownerDocument||t).createElement("link"),Zt(p);var C=p;return C._p=new Promise(function(k,U){C.onload=k,C.onerror=U}),En(p,"link",u),r.state.loading|=4,qu(p,s.precedence,t),r.instance=p;case"script":return p=Js(s.src),(h=t.querySelector(Dl(p)))?(r.instance=h,Zt(h),h):(u=s,(h=pr.get(p))&&(u=y({},s),jg(u,h)),t=t.ownerDocument||t,h=t.createElement("script"),Zt(h),En(h,"link",u),t.head.appendChild(h),r.instance=h);case"void":return null;default:throw Error(a(443,r.type))}else r.type==="stylesheet"&&(r.state.loading&4)===0&&(u=r.instance,r.state.loading|=4,qu(u,s.precedence,t));return r.instance}function qu(t,r,s){for(var u=s.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),h=u.length?u[u.length-1]:null,p=h,C=0;C title"):null)}function dT(t,r,s){if(s===1||r.itemProp!=null)return!1;switch(t){case"meta":case"title":return!0;case"style":if(typeof r.precedence!="string"||typeof r.href!="string"||r.href==="")break;return!0;case"link":if(typeof r.rel!="string"||typeof r.href!="string"||r.href===""||r.onLoad||r.onError)break;return r.rel==="stylesheet"?(t=r.disabled,typeof r.precedence=="string"&&t==null):!0;case"script":if(r.async&&typeof r.async!="function"&&typeof r.async!="symbol"&&!r.onLoad&&!r.onError&&r.src&&typeof r.src=="string")return!0}return!1}function LS(t){return!(t.type==="stylesheet"&&(t.state.loading&3)===0)}function fT(t,r,s,u){if(s.type==="stylesheet"&&(typeof u.media!="string"||matchMedia(u.media).matches!==!1)&&(s.state.loading&4)===0){if(s.instance===null){var h=Xs(u.href),p=r.querySelector(kl(h));if(p){r=p._p,r!==null&&typeof r=="object"&&typeof r.then=="function"&&(t.count++,t=Vu.bind(t),r.then(t,t)),s.state.loading|=4,s.instance=p,Zt(p);return}p=r.ownerDocument||r,u=RS(u),(h=pr.get(h))&&Hg(u,h),p=p.createElement("link"),Zt(p);var C=p;C._p=new Promise(function(k,U){C.onload=k,C.onerror=U}),En(p,"link",u),s.instance=p}t.stylesheets===null&&(t.stylesheets=new Map),t.stylesheets.set(s,r),(r=s.state.preload)&&(s.state.loading&3)===0&&(t.count++,s=Vu.bind(t),r.addEventListener("load",s),r.addEventListener("error",s))}}var zg=0;function hT(t,r){return t.stylesheets&&t.count===0&&Ku(t,t.stylesheets),0zg?50:800)+r);return t.unsuspend=s,function(){t.unsuspend=null,clearTimeout(u),clearTimeout(h)}}:null}function Vu(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Ku(this,this.stylesheets);else if(this.unsuspend){var t=this.unsuspend;this.unsuspend=null,t()}}}var Fu=null;function Ku(t,r){t.stylesheets=null,t.unsuspend!==null&&(t.count++,Fu=new Map,r.forEach(gT,t),Fu=null,Vu.call(t))}function gT(t,r){if(!(r.state.loading&4)){var s=Fu.get(t);if(s)var u=s.get(null);else{s=new Map,Fu.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(),rd.exports=QS(),rd.exports}var od=ZS();const ld=Jr(od),eo=[],ew=50;let cd=!1;function tp(){try{return window.G7Core?.devTools}catch{return}}function Xi(o,e,n){const a=tp();if(cd&&a?.isEnabled?.()){a.trackLog?.(o,e,n);return}cd||(o==="error"||o==="warn")&&eo.length{n.isDebugEnabled()&&console.log(e,...a),Xi("log",o,a)},warn:(...a)=>{n.isDebugEnabled()&&console.warn(e,...a),Xi("warn",o,a)},error:(...a)=>{n.isDebugEnabled()&&console.error(e,...a),Xi("error",o,a)}}}to.getInstance();const Ji=ht("networkResilience"),np=2,rp=300,ap=2e3,tw=15e3;function dd(o){return o?.name==="AbortError"}function ip(o){return dd(o)?!1:o instanceof TypeError}let Nl=!1,sp=!1;function fd(){return Nl}function nw(){typeof window>"u"||sp||(sp=!0,window.addEventListener("pagehide",()=>{Nl=!0}),window.addEventListener("pageshow",o=>{o.persisted&&(Nl=!1)}),window.addEventListener("beforeunload",()=>{Nl=!0}))}function op(o,e,n){const a=Math.min(e*Math.pow(2,o),n),i=a*.25*(Math.random()*2-1);return Math.max(0,Math.round(a+i))}function lp(o){return new Promise(e=>setTimeout(e,o))}async function Il(o,e={}){const{retries:n=np,baseDelayMs:a=rp,maxDelayMs:i=ap,timeoutMs:l=tw,label:c=o,init:d}=e,f=n+1;let g;for(let m=0;m0?new AbortController:null;try{const _={...d};if(v){const x=d?.signal;x&&(x.aborted?v.abort():x.addEventListener("abort",()=>v.abort(),{once:!0})),_.signal=v.signal,S=setTimeout(()=>{y=!0,v.abort()},l)}return await fetch(o,_)}catch(_){if(g=_,dd(_)&&!y||!(y||ip(_)))throw _;if(fd())throw Ji.warn(`Document unloading, aborting retries: ${c}`),_;if(m===f-1)throw Ji.warn(`All ${f} attempts failed: ${c}`,_),_;const O=op(m,a,i);Ji.warn(`Network failure (attempt ${m+1}/${f}), retrying in ${O}ms: ${c}`),await lp(O)}finally{S!==void 0&&clearTimeout(S)}}throw g}async function cp(o,e={},n={}){const{retries:a=np,baseDelayMs:i=rp,maxDelayMs:l=ap,label:c=o}=n,d=a+1;for(let f=0;f{const i=document.createElement("script");i.src=o,i.async=!1;for(const[l,c]of Object.entries(e))l==="id"?i.id=c:i.setAttribute(l,c);i.onload=()=>n(),i.onerror=()=>a(new Error(`Failed to load script: ${o}`)),document.head.appendChild(i)})}const up="extension",Qi="extensionless",aw="file";function iw(){const o=globalThis?.G7Config;if(globalThis?.__g7AssetUrlMode===Qi)return Qi;const n=o?.assetUrlMode;return n===Qi||n===up?n:o?.settings?.general?.asset_url_mode===Qi?Qi:up}function dp(){return iw()===Qi}function Nr(o,e,n,a){const i=o.replace(/\/+$/,""),l=e.replace(/^\.+/,""),c=dp()?i:`${i}.${l}`,d=[];return a&&d.push(a.replace(/^[?&]+/,"")),n!=null&&n!==""&&d.push(`v=${n}`),d.length>0?`${c}?${d.join("&")}`:c}function Ea(o){if(!o||!dp())return o;const e=globalThis?.location?.origin,n=e&&o.startsWith(e)?o.slice(e.length):o;if(!n.startsWith("/api/"))return o;const[a,i]=sw(n),l=a.match(/^\/api\/(modules|plugins)\/bundle\.(js|css)$/);if(l)return fp(`/api/${l[1]}/bundle/${l[2]}`,i);const c=a.match(/^\/api\/(templates|modules|plugins)\/assets\/([^/]+)\/(.+)$/);if(c){const[,f,g,m]=c,y=`${aw}=${encodeURIComponent(decodeURIComponent(m))}`;return`/api/${f}/assets/${g}?${y}${i?`&${i}`:""}`}const d=a.match(/^(\/api\/.+)\.(json|js|css)$/);return d?fp(d[1],i):o}function sw(o){const e=o.indexOf("?");return e===-1?[o,""]:[o.slice(0,e),o.slice(e+1)]}function fp(o,e){return e?`${o}?${e}`:o}const Ir=ht("ComponentRegistry");class hn extends Error{constructor(n,a,i){super(n);$(this,"code");$(this,"details");this.code=a,this.details=i,this.name="ComponentRegistryError"}}const Wn=class Wn{constructor(){$(this,"registry",{});$(this,"manifest",null);$(this,"loadingState","idle");$(this,"error",null);$(this,"templateId",null);$(this,"templateType",null)}static getInstance(){return Wn.instance||(Wn.instance=new Wn),Wn.instance}static createIsolatedInstance(){return new Wn}static resetInstance(){Wn.instance=null}async loadComponents(e,n){if(this.loadingState==="loading")throw new hn("Components are already being loaded","LOADING_IN_PROGRESS");if(this.loadingState==="loaded"&&this.templateId===e&&this.templateType===n){Ir.log("Components already loaded for template:",e,n);return}this.loadingState="loading",this.templateId=e,this.templateType=n,this.error=null;try{await this.loadManifest(),await this.loadComponentBundle(),this.loadingState="loaded",Ir.log("Successfully loaded components:",Object.keys(this.registry).length)}catch(a){throw this.loadingState="error",this.error=a instanceof Error?a:new Error(String(a)),new hn(`Failed to load components: ${this.error.message}`,"LOAD_FAILED",{originalError:this.error})}}async loadManifest(){try{if(!this.templateId)throw new hn("Template ID not set","TEMPLATE_ID_NOT_SET");const e=`${this.templateId}:${this.templateType}`;if(Wn.manifestCache.has(e)){this.manifest=Wn.manifestCache.get(e),Ir.log("Manifest loaded from cache:",this.manifest.templateId);return}const n=Nr(`/api/templates/${this.templateId}/components`,"json"),a=await Il(n,{label:"components.json"});if(!a.ok)throw new hn(`Failed to fetch manifest: ${a.status} ${a.statusText}`,"MANIFEST_FETCH_FAILED",{status:a.status,statusText:a.statusText});const i=await a.json();this.validateManifest(i),this.manifest=i,Wn.manifestCache.set(e,i),Ir.log("Manifest loaded and cached:",i.templateId)}catch(e){throw e instanceof hn?e:new hn("Failed to load component manifest","MANIFEST_LOAD_FAILED",{originalError:e})}}validateManifest(e){if(!e.version)throw new hn("Manifest missing required field: version","MANIFEST_INVALID",{field:"version"});if(!e.templateId)throw new hn("Manifest missing required field: templateId","MANIFEST_INVALID",{field:"templateId"});if(!e.components||typeof e.components!="object")throw new hn("Manifest missing required field: components","MANIFEST_INVALID",{field:"components"});const n=["basic","composite","layout"];for(const a of n){if(!Array.isArray(e.components[a]))throw new hn(`Manifest field 'components.${a}' must be an array`,"MANIFEST_INVALID",{field:`components.${a}`,value:e.components[a]});e.components[a].forEach((i,l)=>{if(!i.name||typeof i.name!="string")throw new hn(`Invalid component metadata at ${a}[${l}]: missing or invalid 'name'`,"MANIFEST_INVALID",{type:a,index:l,metadata:i});if(!i.type||typeof i.type!="string")throw new hn(`Invalid component metadata at ${a}[${l}]: missing or invalid 'type'`,"MANIFEST_INVALID",{type:a,index:l,metadata:i})})}Ir.log("Manifest validation passed")}async loadComponentBundle(){try{if(!this.templateId)throw new hn("Template ID not set","TEMPLATE_ID_NOT_SET");const e=this.getGlobalVariableName(),n=window[e];if(!n||typeof n!="object")throw new hn(`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(n),Ir.log("Component bundle loaded from global variable:",e)}catch(e){throw e instanceof hn?e:new hn("Failed to load component bundle","BUNDLE_LOAD_FAILED",{originalError:e})}}getGlobalVariableName(){if(!this.templateId)throw new hn("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 hn("Manifest not loaded","MANIFEST_NOT_LOADED");const n=["basic","composite","layout"];for(const a of n){const i=this.manifest.components[a]||[];for(const l of i){const c=l.name,d=e[c];if(!d){Ir.warn(`Component '${c}' not found in bundle`);continue}this.registerComponent(c,d,l)}}}registerComponent(e,n,a){this.registry[e]&&Ir.warn(`Component '${e}' already registered, overwriting`);const i=Xe.memo(n);this.registry[e]={component:i,metadata:a},Ir.log(`[ComponentRegistry] Registered component: ${e} (${a.type})`)}getComponent(e){const n=this.registry[e];return n?n.component:null}getMetadata(e){const n=this.registry[e];return n?n.metadata:null}hasComponent(e){return e in this.registry}getComponentsByType(e){return Object.entries(this.registry).filter(([n,a])=>a.metadata.type===e).map(([n,a])=>n)}getAllComponents(){return Object.keys(this.registry)}getComponentMap(){const e={};for(const[n,a]of Object.entries(this.registry))e[n]=a.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,Ir.log("Registry cleared")}};$(Wn,"instance",null),$(Wn,"manifestCache",new Map);let mr=Wn;const hp=ht("TranslationEngine");class hd extends Error{constructor(n,a,i){super(n);$(this,"key");$(this,"locale");this.key=a,this.locale=i,this.name="TranslationError"}}const In=class In{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 In.instance||(In.instance=new In(e)),In.instance}static resetInstance(){In.instance=null}setCacheVersion(e){this.cacheVersion!==e&&(hp.log("Cache version updated:",this.cacheVersion,"->",e),this.cacheVersion=e,this.cache.clear())}getCacheVersion(){return this.cacheVersion}async loadTranslations(e,n,a="/api",i=!1){const l=`${e}:${n}`;if(!i){const c=this.getFromCache(l);if(c)return this.translations.set(l,c),c}try{const c=[];i&&c.push(`_=${Date.now()}`);const d=Nr(`${a}/templates/${e}/lang/${n}`,"json",this.cacheVersion>0?this.cacheVersion:null,c.length>0?c.join("&"):void 0),f=await fetch(d);if(!f.ok)throw new hd(`Failed to load translations: ${f.statusText}`,void 0,n);const m=await f.json();return this.saveToCache(l,m),this.translations.set(l,m),m}catch(c){throw new hd(`Failed to fetch translations for ${n}: ${c instanceof Error?c.message:String(c)}`,void 0,n)}}resolveTranslations(e,n,a){let i=e;const l=5;let c=0;for(;c"="+this.translate(m,n,void 0,a)),i===d)break;c++}return i.replace(In.TRANSLATION_PATTERN,(d,f,g)=>{const{cleanedParams:m,trailing:y}=this.separateTrailingText(g);return this.translate(f,n,m,a)+y})}translate(e,n,a,i){const l=this.getTranslation(e,n),c=a&&this.cleanParamsStr(a);if(c){const d=this.parseParams(c,i);return this.replaceParams(l,d)}return l}getTranslation(e,n){const{templateId:a,locale:i}=n,l=`${a}:${i}`,c=this.translations.get(l);if(c){const d=this.getNestedValue(c,e);if(d!==null)return d}if(i!==this.options.fallbackLocale){const d=`${a}:${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,n){const a=n.split(".");let i=e;for(const l of a){if(i==null||typeof i!="object")return null;i=i[l]}return typeof i=="string"?i:null}setTranslationValue(e,n,a,i){const l=`${e}:${n}`,c=this.translations.get(l)??{},d=a.split(".");let f=c;for(let g=0;g(l.push(f),`__PLACEHOLDER_${l.length-1}__`)).matchAll(In.PARAM_PATTERN);for(const f of d){const[,g,m]=f,y=m.replace(/__PLACEHOLDER_(\d+)__/g,(S,v)=>l[parseInt(v,10)]);a[g.trim()]=this.resolveParamValue(y.trim(),n)}return a}resolveParamValue(e,n){if(e.startsWith("{{")&&e.endsWith("}}")){const a=e.slice(2,-2).trim();if(/[|&()[\]!?:+\-*/%<>=\s]/.test(a)&&n)try{const l=Sd.evaluateExpression(a,n);return String(l??"")}catch(l){return hp.error("Expression evaluation failed:",a,l),""}else{const l=this.getNestedDataValue(n,a);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 a=e.match(/(\s+[^\p{L}\w=|&\s][^\p{L}\w=]*\s*)$/u);return a?{cleanedParams:e.slice(0,-a[1].length),trailing:a[1]}:{cleanedParams:e,trailing:""}}cleanParamsStr(e){return this.separateTrailingText(e).cleanedParams||""}getNestedDataValue(e,n){if(!e)return;const a=n.split(".");let i=e;for(const l of a){if(i==null)return;i=i[l]}return i}replaceParams(e,n){let a=e;for(const[i,l]of Object.entries(n)){const c=new RegExp(`\\{\\{${i}\\}\\}`,"g");a=a.replace(c,String(l));const d=new RegExp(`\\{${i}\\}`,"g");a=a.replace(d,String(l))}return a}getFromCache(e){const n=this.cache.get(e);return n?Date.now()-n.timestamp>this.options.cacheTTL?(this.cache.delete(e),null):n.data:null}saveToCache(e,n){this.cache.set(e,{data:n,timestamp:Date.now()})}clearCache(){this.cache.clear(),this.translations.clear()}pruneCache(){const e=Date.now(),n=[];for(const[a,i]of this.cache.entries())e-i.timestamp>this.options.cacheTTL&&n.push(a);for(const a of n)this.cache.delete(a)}getCacheStats(){const e=Date.now();let n=0;for(const a of this.cache.values())e-a.timestamp>this.options.cacheTTL&&n++;return{size:this.cache.size,expired:n}}};$(In,"instance",null),$(In,"TRANSLATION_PATTERN",/\$t:(?:defer:)?([a-zA-Z0-9._-]+)(\|(?:(?!\$t:).)+)?/g),$(In,"NESTED_TRANSLATION_PARAM_PATTERN",/=(\$t:([a-zA-Z0-9._-]+))(?=[|&\s]|$)/g),$(In,"PARAM_PATTERN",/([^=|&]+)=([^|&]+)/g);let _a=In,gd=null;function ow(o){return gd||(gd=new _a(o)),gd}const gp=Object.freeze(Object.defineProperty({__proto__:null,TranslationEngine:_a,TranslationError:hd,getTranslationEngine:ow},Symbol.toStringTag,{value:"Module"})),Zi=ht("PipeRegistry");function pp(o,e){const n=o.getFullYear(),a=String(o.getMonth()+1).padStart(2,"0"),i=String(o.getDate()).padStart(2,"0"),l=String(o.getHours()).padStart(2,"0"),c=String(o.getMinutes()).padStart(2,"0"),d=String(o.getSeconds()).padStart(2,"0");return e.replace("YYYY",String(n)).replace("YY",String(n).slice(-2)).replace("MM",a).replace("M",String(o.getMonth()+1)).replace("DD",i).replace("D",String(o.getDate())).replace("HH",l).replace("H",String(o.getHours())).replace("mm",c).replace("m",String(o.getMinutes())).replace("ss",d).replace("s",String(o.getSeconds()))}function lw(o,e="ko"){const a=new Date().getTime()-o.getTime(),i=Math.floor(a/1e3),l=Math.floor(i/60),c=Math.floor(l/60),d=Math.floor(c/24),f=Math.floor(d/7),g=Math.floor(d/30),m=Math.floor(d/365);return e==="ko"?i<60?"방금 전":l<60?`${l}분 전`:c<24?`${c}시간 전`:d<7?`${d}일 전`:f<4?`${f}주 전`:g<12?`${g}개월 전`:`${m}년 전`:i<60?"just now":l<60?`${l} minute${l===1?"":"s"} ago`:c<24?`${c} hour${c===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 pd(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 no={date:{fn:(o,e="YYYY-MM-DD")=>{const n=pd(o);return n?pp(n,e):""},description:"날짜 포맷 (기본: YYYY-MM-DD)"},datetime:{fn:(o,e="YYYY-MM-DD HH:mm")=>{const n=pd(o);return n?pp(n,e):""},description:"날짜+시간 포맷 (기본: YYYY-MM-DD HH:mm)"},relativeTime:{fn:(o,e="ko")=>{const n=pd(o);return n?lw(n,e):""},description:'상대 시간 표시 (예: "3분 전")'},number:{fn:(o,e)=>{const n=Number(o);if(isNaN(n))return String(o??"");const a={};return e!==void 0&&(a.minimumFractionDigits=e,a.maximumFractionDigits=e),n.toLocaleString(void 0,a)},description:"숫자 포맷 (천단위 구분, 선택적 소수점)"},truncate:{fn:(o,e=100,n="...")=>typeof o!="string"?String(o??""):o.length<=e?o:o.slice(0,e)+n,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,n)=>Array.isArray(o)?Array.isArray(e)?o.filter(a=>{const i=n?a?.[n]:a;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:"다국어 객체에서 로케일에 맞는 값 추출"}},es=new Map,Si=class Si{static getInstance(){return Si.instance||(Si.instance=new Si),Si.instance}register(e,n,a){if(no[e]){Zi.warn(`[PipeRegistry] 내장 파이프를 덮어쓸 수 없습니다: ${e}`);return}es.set(e,{fn:n,description:a}),Zi.log(`[PipeRegistry] 커스텀 파이프 등록됨: ${e}`)}unregister(e){if(no[e])return Zi.warn(`[PipeRegistry] 내장 파이프는 해제할 수 없습니다: ${e}`),!1;const n=es.delete(e);return n&&Zi.log(`[PipeRegistry] 커스텀 파이프 해제됨: ${e}`),n}get(e){const n=no[e];return n?n.fn:es.get(e)?.fn}has(e){return!!no[e]||es.has(e)}execute(e,n,a=[]){const i=this.get(e);if(!i)return Zi.warn(`[PipeRegistry] 알 수 없는 파이프: ${e}`),n;try{return i(n,...a)}catch(l){return Zi.error(`[PipeRegistry] 파이프 실행 오류 (${e}):`,l),n}}list(){const e=[];for(const[n,a]of Object.entries(no))e.push({name:n,description:a.description,type:"built-in"});for(const[n,a]of es.entries())e.push({name:n,description:a.description,type:"custom"});return e.sort((n,a)=>n.name.localeCompare(a.name))}clearCustomPipes(){es.clear()}};$(Si,"instance",null);let Hl=Si;Hl.getInstance();function cw(o){const e=o.trim(),n=e.indexOf("(");if(n===-1)return{name:e,args:[]};const a=e.slice(0,n).trim(),i=e.slice(n+1,-1);if(!i.trim())return{name:a,args:[]};const l=[];let c="",d=null,f=0;for(let g=0;g0?i[g-1]:"")==="\\"){c+=m;continue}if((m==='"'||m==="'")&&!d){d=m;continue}if(m===d){d=null;continue}if(d){c+=m;continue}if(m==="("||m==="["||m==="{"){f++,c+=m;continue}if(m===")"||m==="]"||m==="}"){f--,c+=m;continue}if(m===","&&f===0){l.push(mp(c.trim())),c="";continue}c+=m}return c.trim()&&l.push(mp(c.trim())),{name:a,args:l}}function mp(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 uw(o){const e=[];let n="",a=null,i=0;for(let l=0;l0?o[l-1]:"",f=l0?o[a-1]:"",c=a0){a--;continue}return null}}return a===0?e.trim():null}function fw(o){const e=[];if(typeof o!="string")return e;for(let n=0;n0){i--;continue}if(o[c+1]==="}"){l=c;break}break}}l!==-1&&(e.push({start:n,end:l+2,expr:o.slice(n+2,l)}),n=l+1)}return e}function ro(o){return/[?:|&!+\-*/<>=()[\]{}]/.test(o)}function yp(o){const e=typeof o=="string"?o.trim():"";return e===""?"empty":md.has(e)?"literal":Vn(e)?"pipe":ro(e)?"expression":"path"}function yd(o,e,n,a){const i=typeof o=="string"?o.trim():"",l=yp(i),c=a?.skipCache?{skipCache:!0}:void 0;if(l==="empty"){a?.onEmpty?.(o);return}if(l==="literal")return md.get(i);try{return l==="pipe"?n.evaluatePipeExpression(i,e,c,a?.trackingInfo):l==="expression"?n.evaluateExpression(i,e,a?.trackingInfo):n.resolve(i,e,c,a?.trackingInfo)}catch(d){if(a?.onError)return a.onError(d,i);throw d}}const nr="raw:";function bp(o){return o.startsWith(nr)?o.slice(nr.length):o}const ao="﷐",fi="﷑",xa="﷒";function io(o){return ao+o+fi}function jl(o){return o.length>=2&&o.charCodeAt(0)===64976&&o.charCodeAt(o.length-1)===64977}function zl(o){return o.includes(ao)}function bd(o){return o.slice(1,-1)}function ts(o){if(typeof o=="string")return io(o);if(Array.isArray(o))return o.map(ts);if(o&&typeof o=="object"){const e={};for(const[n,a]of Object.entries(o))e[n]=ts(a);return e}return o}function Ta(o){if(typeof o=="string")return jl(o)?bd(o):zl(o)||o.includes(fi)?o.split(ao).join("").split(fi).join(""):o;if(Array.isArray(o)){let e=!1;const n=o.map(a=>{const i=Ta(a);return i!==a&&(e=!0),i});return e?n:o}if(o&&typeof o=="object"){if(o.$$typeof!==void 0)return o;let e=!1;const n={};for(const[a,i]of Object.entries(o)){const l=Ta(i);l!==i&&(e=!0),n[a]=l}return e?n:o}return o}const Ra=ht("DataBindingEngine"),hw=/^[$A-Za-z_][$A-Za-z0-9_]*$/,gw=new Set(["break","case","catch","class","const","continue","debugger","default","delete","do","else","enum","export","extends","false","finally","for","function","if","implements","import","in","instanceof","interface","let","new","null","package","private","protected","public","return","static","super","switch","this","throw","true","try","typeof","var","void","while","with","yield","arguments","eval"]);function so(){try{return window.G7Core?.devTools}catch{return}}class vd extends Error{constructor(n,a,i){super(n);$(this,"path");$(this,"context");this.path=a,this.context=i,this.name="DataBindingError"}}const ta=class ta{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,n){this.isRenderCycleCacheActive()&&this.renderCycleCache.set(e,n)}resolveBindings(e,n,a,i){const l={...this.defaultOptions,...a},c=so(),d=n._computed&&!n.$computed?{...n,$computed:n._computed}:n,f=(S,v)=>{const _=v.trim();let A=!1,x=_;if(_.startsWith(nr)&&(A=!0,x=_.slice(nr.length)),Vn(x))try{const q=this.evaluatePipeExpression(x,d,l,{...i,method:"resolveBindings",displayExpression:`{{${_}}}`}),W=this.formatValue(q);return A?io(W):W}catch(q){return Ra.error("Pipe expression evaluation failed:",x,q),S}if(ro(x)){const q=c?.isEnabled()?performance.now():0;try{let W,he=!1;if(l.skipCache)W=this.evaluateExpression(x,d);else{const be=`expr:${x}`,Ue=this.getFromRenderCycleCache(be);Ue!==void 0?(W=Ue,he=!0):(W=this.evaluateExpression(x,d),this.saveToRenderCycleCache(be,W))}if(c?.isEnabled()){const be=performance.now()-q;c.trackExpressionEval({expression:`{{${_}}}`,result:this.sanitizeResultForTracking(W),resultType:this.getResultType(W),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:he,duration:be,method:"resolveBindings",skipCache:l.skipCache})}const Ee=this.formatValue(W);return A?io(Ee):Ee}catch(W){return Ra.error("Expression evaluation failed:",x,W),S}}if(l.skipCache){const q=c?.isEnabled()?performance.now():0,W=this.resolvePath(x,d,l);if(c?.isEnabled()){const Ee=performance.now()-q;c.trackExpressionEval({expression:`{{${_}}}`,result:this.sanitizeResultForTracking(W),resultType:this.getResultType(W),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!1,duration:Ee,method:"resolveBindings",skipCache:!0})}const he=this.formatValue(W);return A?io(he):he}const M=x.startsWith("_global")||x.startsWith("_local")||x.startsWith("_isolated")||x.startsWith("$parent"),T=c?.isEnabled()?performance.now():0;let D,z=!1;if(M){const q=this.getFromRenderCycleCache(x);q!==void 0?(D=q,z=!0):(D=this.resolvePath(x,d,l),this.saveToRenderCycleCache(x,D))}else{const q=this.getFromCache(x);q!==void 0?(D=q,z=!0):(D=this.resolvePath(x,d,l),this.saveToCache(x,D))}if(c?.isEnabled()){const q=performance.now()-T;c.trackExpressionEval({expression:`{{${_}}}`,result:this.sanitizeResultForTracking(D),resultType:this.getResultType(D),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:z,duration:q,method:"resolveBindings",skipCache:l.skipCache})}const P=this.formatValue(D);return A?io(P):P},g=fw(e);if(g.length===0)return e;let m="",y=0;for(const S of g)m+=e.slice(y,S.start),m+=f(e.slice(S.start,S.end),S.expr),y=S.end;return m+e.slice(y)}evaluatePipeExpression(e,n,a,i){const l={...this.defaultOptions,...a},c=so(),d=c?.isEnabled()?performance.now():0,f=n._computed&&!n.$computed?{...n,$computed:n._computed}:n,[g,m]=uw(e);let y,S=!1;const v=ro(g),_=g.startsWith("_global")||g.startsWith("_local")||g.startsWith("_isolated")||g.startsWith("$parent");if(l.skipCache)v?y=this.evaluateExpression(g,f):y=this.resolvePath(g,f,l);else if(v){const x=this.getFromRenderCycleCache(`expr:${g}`);x!==void 0?(y=x,S=!0):(y=this.evaluateExpression(g,f),this.saveToRenderCycleCache(`expr:${g}`,y))}else if(_){const x=this.getFromRenderCycleCache(g);x!==void 0?(y=x,S=!0):(y=this.resolvePath(g,f,l),this.saveToRenderCycleCache(g,y))}else{const x=this.getFromCache(g);x!==void 0?(y=x,S=!0):(y=this.resolvePath(g,f,l),this.saveToCache(g,y))}const A=dw(y,m);if(c?.isEnabled()){const x=performance.now()-d;c.trackExpressionEval({expression:i?.displayExpression??`{{${e}}}`,result:this.sanitizeResultForTracking(A),resultType:this.getResultType(A),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:S,duration:x,method:i?.method??"evaluatePipeExpression",skipCache:l.skipCache})}return A}resolve(e,n,a,i){const l={...this.defaultOptions,...a},c=so(),d=c?.isEnabled()?performance.now():0;if(l.skipCache){const y=this.resolvePath(e,n,l);return c?.isEnabled()&&c.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(y),resultType:this.getResultType(y),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!1,duration:performance.now()-d,method:"resolve",skipCache:!0}),y}const f=e.startsWith("_global")||e.startsWith("_local")||e.startsWith("_isolated")||e.startsWith("$parent");let g=!1;if(f){const y=this.getFromRenderCycleCache(e);if(y!==void 0)return g=!0,c?.isEnabled()&&c.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(y),resultType:this.getResultType(y),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!0,duration:performance.now()-d,method:"resolve",skipCache:l.skipCache}),y}else{const y=this.getFromCache(e);if(y!==void 0)return g=!0,c?.isEnabled()&&c.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(y),resultType:this.getResultType(y),componentId:i?.componentId,componentName:i?.componentName,propName:i?.propName,fromCache:!0,duration:performance.now()-d,method:"resolve",skipCache:l.skipCache}),y}const m=this.resolvePath(e,n,l);return f?this.saveToRenderCycleCache(e,m):this.saveToCache(e,m),c?.isEnabled()&&c.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,n,a,i=0,l=new WeakSet){if(typeof e!="string"||e.trim()===""){Ra.warn("resolvePath: 빈 경로가 전달되었습니다 — undefined 로 해석합니다.");return}if(a.maxDepth&&i>a.maxDepth){if(a.detectCircular)throw new vd(`Maximum depth exceeded (${a.maxDepth}). Possible circular reference.`,e,n);return a.defaultValue}const c=this.parsePath(e);let d=n;for(let f=0;fta.CACHE_EXPIRY){this.cache.delete(e),a?.isEnabled()&&a.recordCacheMiss();return}return a?.isEnabled()&&a.recordCacheHit(),n.value}saveToCache(e,n){this.cache.set(e,{value:n,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}resolveObject(e,n,a){if(this.isSwitchExpression(e)){const d=e;return this.resolveSwitch(d,n,a)}if(this.isActionDefinition(e))return{...e};if("iteration"in e)return{...e};const i={},c=[...["cellChildren","expandChildren","expandContext","render"],...a?.skipBindingKeys||[]];for(const[d,f]of Object.entries(e)){if(c.includes(d)){i[d]=f;continue}try{this.resolveObjectEntry(i,d,f,n,a)}catch(g){Ra.warn(`resolveObject: 값 해석 실패 (key: ${d}):`,g),i[d]=void 0}}return i}resolveObjectEntry(e,n,a,i,l){if(typeof a=="string"){const c=Aa(a);if(c!==null){const d=c.trim();let f=!1,g=d;d.startsWith(nr)&&(f=!0,g=d.slice(nr.length));let m;switch(yp(g)){case"empty":Ra.warn(`resolveObject: 빈 바인딩 \`{{}}\` (key: ${n}) — undefined 로 해석합니다.`),m=void 0;break;case"literal":m=md.get(g);break;case"pipe":m=this.evaluatePipeExpression(g,i,l);break;case"expression":m=this.evaluateExpression(g,i,l);break;default:m=this.resolve(g,i,l)}e[n]=f&&m!=null?ts(m):m}else e[n]=this.resolveBindings(a,i,l)}else Array.isArray(a)?e[n]=a.map(c=>typeof c=="string"?this.resolveBindings(c,i,l):typeof c=="object"&&c!==null?this.resolveObject(c,i,l):c):a&&typeof a=="object"?e[n]=this.resolveObject(a,i,l):e[n]=a}clearCache(){this.cache.clear(),this.expressionFnCache.clear()}invalidateCacheByKeys(e){for(const n of this.cache.keys())for(const a of e)if(n===a||n.startsWith(`${a}.`)||n.startsWith(`${a}[`)){this.cache.delete(n);break}}pruneCache(){const e=Date.now();for(const[n,a]of this.cache.entries())e-a.timestamp>ta.CACHE_EXPIRY&&this.cache.delete(n)}getCacheStats(){const e=Date.now();let n=0;for(const a of this.cache.values())e-a.timestamp>ta.CACHE_EXPIRY&&n++;return{size:this.cache.size,expired:n}}evaluateExpression(e,n,a){const i=so(),l=i?.isEnabled()?performance.now():0;i?.isEnabled()&&i.trackBindingEval();try{let c=this.preprocessOptionalChaining(e);c=this.preprocessTranslationTokens(c);const d=this.extractVariablesFromExpression(c),f={...n};for(const D of d)D in f||(f[D]=void 0);n._computed&&!f.$computed&&(f.$computed=n._computed);let g=n.$templateId,m=n.$locale;if(typeof window<"u"&&(!g||!m)){const D=window.__templateApp?.getConfig?.();g??(g=D?.templateId),m??(m=D?.locale)}const y=m||"ko";f.$localized=(D,z)=>{if(D==null&&!z)return"";if(typeof D=="string")return D;if(D&&typeof D=="object"&&D[y])return D[y];if(z&&typeof z=="string"){const P=f.$t?f.$t(z):z;if(P&&P!==z)return P}return D&&typeof D=="object"?D.ko||D.en||Object.values(D)[0]||"":D==null?"":String(D)};const S=typeof window<"u"?window.G7Core:void 0;f.$uuid=()=>S?.uuid?S.uuid():typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,D=>{const z=Math.random()*16|0;return(D==="x"?z:z&3|8).toString(16)});const v={templateId:g||"",locale:y};f.$t=D=>{if(!D||typeof D!="string")return"";try{return _a.getInstance().translate(D,v)}catch(z){return Ra.warn("$t() translation failed for key:",D,z),D}},f.$get=(D,z,P=void 0)=>{if(D==null)return P;const q=Array.isArray(z)?z:[z];if(q.length===0)return D;let W=D;for(const he of q){if(W==null||he==null)return P;W=W[he]}return W??P};const _=[],A=[];for(const[D,z]of Object.entries(f))!hw.test(D)||gw.has(D)||(_.push(D),A.push(z));const x=`${c}|${_.join(",")}`;let O=this.expressionFnCache.get(x);const M=!!O;O||(O=new Function(..._,`return (${c});`),this.expressionFnCache.set(x,O));const T=O(...A);if(i?.isEnabled()){const D=performance.now()-l;i.trackExpressionEval({expression:e,result:this.sanitizeResultForTracking(T),resultType:this.getResultType(T),componentId:a?.componentId,componentName:a?.componentName,propName:a?.propName,fromCache:M,duration:D,method:"evaluateExpression",skipCache:a?.skipCache})}return T}catch(c){throw new Error(`Failed to evaluate expression "${e}": ${c instanceof Error?c.message:String(c)}`)}}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 n=Object.keys(e);return n.length>20?`{Object(${n.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,(n,a,i,l)=>`$t('${l}')`),e.replace(/(?(n.push(l),`__STRING_LITERAL_${n.length-1}__`));const i=[];return a=a.replace(/\$t:[a-zA-Z_][a-zA-Z0-9_.\-]*(?:\|[^'"\s,)]+)?/g,l=>(i.push(l),`__TRANSLATION_TOKEN_${i.length-1}__`)),a=a.replace(/([a-zA-Z_$][a-zA-Z0-9_$]*)\.(?!\?)/g,"$1?."),a=a.replace(/__TRANSLATION_TOKEN_(\d+)__/g,(l,c)=>i[parseInt(c,10)]),a=a.replace(/__STRING_LITERAL_(\d+)__/g,(l,c)=>n[parseInt(c,10)]),a}extractVariablesFromExpression(e){const n=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"]),a=/(?{n!==null&&clearTimeout(n),n=setTimeout(()=>{o(...a)},e)})}class mw{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=pw(()=>{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(Pl.has(e))return Pl.get(e)??null;let n=null;if(Ul[e])n={...Ul[e]};else{const a=e.match(/^(-?\d*)-(-?\d*)$/);if(a){const[,i,l]=a,c=i===""?0:parseInt(i,10),d=l===""?1/0:parseInt(l,10);!isNaN(c)&&!isNaN(d)&&c<=d&&(n={min:c,max:d})}}return Pl.set(e,n),n}getMatchingKey(e,n){const a=[];for(const i of Object.keys(e)){const l=this.parseRange(i);l&&n>=l.min&&n<=l.max&&a.push({key:i,range:l,isPreset:!!Ul[i]})}return a.length===0?null:(a.sort((i,l)=>{if(i.isPreset!==l.isPreset)return i.isPreset?1:-1;const c=i.range.max-i.range.min,d=l.range.max-l.range.min;return c-d}),a[0].key)}matches(e){const n=this.parseRange(e);return n?this.currentWidth>=n.min&&this.currentWidth<=n.max:!1}clearSubscribers(){this.subscribers.clear()}destroy(){this.debouncedHandler&&typeof window<"u"&&window.removeEventListener("resize",this.debouncedHandler),this.clearSubscribers(),Pl.clear()}_setWidthForTesting(e){this.currentWidth=e,this.notifySubscribers()}}const hi=new mw,oo=ht("ConditionEvaluator");function yw(o,e,n,a){return yd(bp(o),e,n,{skipCache:!0,onEmpty:()=>{oo.warn(`${a}: 빈 바인딩 \`{{}}\` — undefined 로 해석합니다.`)}})}function vp(o,e,n){if(!o)return!0;try{const a=Aa(o);let i;if(a!==null?i=yw(a,e,n,"evaluateStringCondition"):i=n.resolveBindings(o,e,{skipCache:!0}),typeof i=="string"){const l=i.toLowerCase().trim();if(l==="false"||l==="0"||l===""||l==="null"||l==="undefined")return!1}return!!i}catch(a){return oo.warn(`evaluateStringCondition: 조건 평가 실패: ${o}`,a),!1}}function Bl(o,e,n){if(typeof o=="string")return vp(o,e,n);if("and"in o){if(!Array.isArray(o.and)||o.and.length===0)return oo.warn("evaluateConditionExpression: AND 그룹이 비어있습니다"),!0;for(const a of o.and)if(!Bl(a,e,n))return!1;return!0}if("or"in o){if(!Array.isArray(o.or)||o.or.length===0)return oo.warn("evaluateConditionExpression: OR 그룹이 비어있습니다"),!1;for(const a of o.or)if(Bl(a,e,n))return!0;return!1}return oo.warn("evaluateConditionExpression: 알 수 없는 조건 형식",o),!1}function Sp(o,e,n){if(!Array.isArray(o)||o.length===0)return{matched:!1,branchIndex:-1};for(let a=0;a{rr.warn(`evaluateIfCondition: 빈 바인딩 \`{{}}\` (컴포넌트: ${a||"unknown"}) — undefined 로 해석합니다.`)}}):l=n.resolveBindings(o,e,{skipCache:!0}),typeof l=="string"){const c=l.toLowerCase().trim();if(c==="false"||c==="0"||c===""||c==="null"||c==="undefined")return!1}return!!l}catch(i){return rr.warn(`evaluateIfCondition: 조건 평가 실패 (컴포넌트: ${a||"unknown"}):`,i),!1}}function ns(o,e,n,a){if(o.if!==void 0)return _p(o.if,e,n,a);if(o.condition!==void 0)return _p(o.condition,e,n,a);if(o.conditions===void 0)return!0;const i=o.conditions;try{return bw(i)?Bl(i,e,n):vw(i)?Sp(i,e,n).matched:(rr.warn(`evaluateRenderCondition: 알 수 없는 conditions 형식 (컴포넌트: ${a||"unknown"})`),!0)}catch(l){return rr.warn(`evaluateRenderCondition: conditions 평가 실패 (컴포넌트: ${a||"unknown"}):`,l),!1}}function Ap(o){if(!o.responsive)return o;const e=hi.getWidth(),n=hi.getMatchingKey(o.responsive,e);if(!n)return o;const a=o.responsive[n];return{...o,props:{...o.props,...a.props},children:a.children??o.children,text:a.text??o.text,if:a.if??o.if,iteration:a.iteration??o.iteration}}function lo(o,e,n,a,i){if(!o||o.length===0)return[];const l=i?.bindingEngine??new Dn,c=i?.translationEngine??_a.getInstance(),d=i?.translationContext??{templateId:"",locale:"ko"},f=ww(e,i?.componentContext),g=(v,_)=>{if(typeof v=="string")return jl(v)||zl(v)||!/\$t:[a-zA-Z0-9._-]+/.test(v)?v:c.resolveTranslations(v,d,_);if(Array.isArray(v))return v.map(A=>g(A,_));if(v&&typeof v=="object"){const A={};for(const[x,O]of Object.entries(v))A[x]=g(O,_);return A}return v},m=(v,_)=>{if(typeof v=="string"){if(jl(v))return bd(v);if(zl(v)){const x=[],O=v.replace(new RegExp(`${ao}([^${fi}]*)${fi}`,"g"),(T,D)=>(x.push(D),`${xa}${x.length-1}${xa}`));let M=O;return/\$t:[a-zA-Z0-9._-]+/.test(O)&&(M=c.resolveTranslations(O,d,_)),M.replace(new RegExp(`${xa}(\\d+)${xa}`,"g"),(T,D)=>x[parseInt(D)])}if(v.startsWith("$t:defer:")){const x="$t:"+v.slice(9);return c.resolveTranslations(x,d,_)}if(v.startsWith("$t:"))return c.resolveTranslations(v,d,_);if(/\$t:[a-zA-Z0-9._-]+/.test(v)){const x=v.trim();if(!(x.startsWith("{")&&x.endsWith("}")||x.startsWith("[")&&x.endsWith("]"))&&!v.includes("{{"))return c.resolveTranslations(v,d,_)}const A=Ep(v);if(A!==null){let x=!1,O=A;A.startsWith(nr)&&(x=!0,O=A.slice(nr.length));let M=!1,T=yd(O,_,l,{skipCache:!0,onError:D=>{rr.warn("renderItemChildren: 표현식 평가 실패:",D),M=!0},onEmpty:()=>{rr.warn("renderItemChildren: 빈 바인딩 `{{}}` 은 해석하지 않습니다.")}});return M?void 0:(x||(T=g(T,_)),x&&T!=null?ts(T):T)}if(v.includes("{{")){const x=l.resolveBindings(v,_,{skipCache:!0});return typeof x=="string"&&/\$t:[a-zA-Z0-9._-]+/.test(x)?c.resolveTranslations(x,d,_):x}return v}if(Array.isArray(v))return v.map(A=>m(A,_));if(v&&typeof v=="object"){if(l.isSwitchExpression(v))return l.resolveSwitch(v,_,{skipCache:!0});if(l.isActionDefinition(v))return{...v};const A={};for(const[x,O]of Object.entries(v))A[x]=m(O,_);return A}return v},y=(v,_)=>{if(!v)return{};const A={};for(const[x,O]of Object.entries(v))A[x]=m(O,_);return A},S=(v,_,A)=>{const x=Ap(v),O=x.iteration;if(!O)return[];const M=wd(O.source,A,l);if(!Array.isArray(M))return rr.warn(`renderItemChildren: iteration.source가 배열이 아닙니다: ${O.source}`),[];const T=wp();if(T?.isEnabled()){const z=`${_}-iteration`;T.trackIteration(z,O.source,O.item_var,O.index_var,M.length)}const D=n[x.name];return D?M.flatMap((z,P)=>{const q={...A,[O.item_var]:z,[`${O.item_var}_index`]:P,...O.index_var?{[O.index_var]:P}:{}},W=ns({if:x.if,condition:x.condition,conditions:x.conditions},q,l,x.id);if(x.if&&T?.isEnabled()){const wt=`${_}-iter-${P}-if`;T.trackIfCondition(wt,x.if,W,x.name)}if(!W)return[];const he=x.id?String(Ta(m(x.id,q))):void 0,Ee=`${_}-iter-${P}`,be=i?.getRemountKey?i.getRemountKey(he,Ee):Ee,Ue=y(x.props,q),Fe=Cd(Ue,x.actions,q,{actionDispatcher:i?.actionDispatcher,componentContext:i?.componentContext});let Ge=null;return x.text!==void 0?Ge=m(x.text,q):x.children&&x.children.length>0&&(Ge=lo(x.children,q,n,be,i)),T?.isEnabled()&&T.trackRender(x.name),[Xe.createElement(D,{key:be,...Ta(Fe)},Ta(Ge))]}):(rr.warn(`renderItemChildren: 컴포넌트를 찾을 수 없습니다: ${x.name}`),[])};return o.flatMap((v,_)=>{const A=Ap(v),x=A.id?String(Ta(m(A.id,f))):void 0,O=a?`${a}-${x||_}`:x||`child-${_}`,M=i?.getRemountKey?i.getRemountKey(x,O):O;if(A.iteration)return S(A,M,f);const T=ns({if:A.if,condition:A.condition,conditions:A.conditions},f,l,A.id),D=wp();if(A.if&&D?.isEnabled()){const he=`${M}-if`;D.trackIfCondition(he,A.if,T,A.name)}if(!T)return[];const z=n[A.name];if(!z)return rr.warn(`renderItemChildren: 컴포넌트를 찾을 수 없습니다: ${A.name}`),[];const P=y(A.props,f),q=Cd(P,A.actions,f,{actionDispatcher:i?.actionDispatcher,componentContext:i?.componentContext});let W=null;return A.text!==void 0?W=m(A.text,f):A.children&&A.children.length>0&&(W=lo(A.children,f,n,M,i)),D?.isEnabled()&&D.trackRender(A.name),[Xe.createElement(z,{key:M,...Ta(q)},Ta(W))]})}function rs(o,e,n,a){let i,l;return n instanceof Dn?(i=n,l=a):(i=Cp,l=n),i.resolveBindings(o,e,l)}function Cw(o,e,n,a){const i=n??Cp,l={skipCache:!0,...a};let c;try{c=i.resolveBindings(o.key,e,{skipCache:l.skipCache})?.toString()?.trim()??""}catch(g){rr.warn("resolveClassMap: key 평가 실패:",o.key,g),c=""}let d="";c&&o.variants&&c in o.variants?d=o.variants[c]: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 xp(o,e){return function(){return o.apply(e,arguments)}}const{toString:Ew}=Object.prototype,{getPrototypeOf:as}=Object,{iterator:co,toStringTag:Tp}=Symbol,ql=(({hasOwnProperty:o})=>(e,n)=>o.call(e,n))(Object.prototype),uo=(o,e)=>{let n=o;const a=[];for(;n!=null&&n!==Object.prototype;){if(a.indexOf(n)!==-1)return!1;if(a.push(n),ql(n,e))return!0;n=as(n)}return!1},_w=(o,e)=>o!=null&&uo(o,e)?o[e]:void 0,Ed=(o=>e=>{const n=Ew.call(e);return o[n]||(o[n]=n.slice(8,-1).toLowerCase())})(Object.create(null)),yr=o=>(o=o.toLowerCase(),e=>Ed(e)===o),Gl=o=>e=>typeof e===o,{isArray:gi}=Array,is=Gl("undefined");function ss(o){return o!==null&&!is(o)&&o.constructor!==null&&!is(o.constructor)&&$n(o.constructor.isBuffer)&&o.constructor.isBuffer(o)}const Rp=yr("ArrayBuffer");function Aw(o){let e;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?e=ArrayBuffer.isView(o):e=o&&o.buffer&&Rp(o.buffer),e}const xw=Gl("string"),$n=Gl("function"),kp=Gl("number"),os=o=>o!==null&&typeof o=="object",Tw=o=>o===!0||o===!1,Vl=o=>{if(!os(o))return!1;const e=as(o);return(e===null||e===Object.prototype||as(e)===null)&&!uo(o,Tp)&&!uo(o,co)},Rw=o=>{if(!os(o)||ss(o))return!1;try{return Object.keys(o).length===0&&Object.getPrototypeOf(o)===Object.prototype}catch{return!1}},kw=yr("Date"),Dw=yr("File"),Ow=o=>!!(o&&typeof o.uri<"u"),Lw=o=>o&&typeof o.getParts<"u",Mw=yr("Blob"),$w=yr("FileList"),Nw=o=>os(o)&&$n(o.pipe);function Iw(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{}}const Dp=Iw(),Op=typeof Dp.FormData<"u"?Dp.FormData:void 0,Hw=o=>{if(!o)return!1;if(Op&&o instanceof Op)return!0;const e=as(o);if(!e||e===Object.prototype||!$n(o.append))return!1;const n=Ed(o);return n==="formdata"||n==="object"&&$n(o.toString)&&o.toString()==="[object FormData]"},jw=yr("URLSearchParams"),[zw,Uw,Pw,Bw]=["ReadableStream","Request","Response","Headers"].map(yr),qw=o=>o.trim?o.trim():o.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function fo(o,e,{allOwnKeys:n=!1}={}){if(o===null||typeof o>"u")return;let a,i;if(typeof o!="object"&&(o=[o]),gi(o))for(a=0,i=o.length;a0;)if(i=n[a],e===i.toLowerCase())return i;return null}const pi=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global,Mp=o=>!is(o)&&o!==pi;function _d(...o){const{caseless:e,skipUndefined:n}=Mp(this)&&this||{},a={},i=(l,c)=>{if(c==="__proto__"||c==="constructor"||c==="prototype")return;const d=e&&typeof c=="string"&&Lp(a,c)||c,f=ql(a,d)?a[d]:void 0;Vl(f)&&Vl(l)?a[d]=_d(f,l):Vl(l)?a[d]=_d({},l):gi(l)?a[d]=l.slice():(!n||!is(l))&&(a[d]=l)};for(let l=0,c=o.length;l(fo(e,(i,l)=>{n&&$n(i)?Object.defineProperty(o,l,{__proto__:null,value:xp(i,n),writable:!0,enumerable:!0,configurable:!0}):Object.defineProperty(o,l,{__proto__:null,value:i,writable:!0,enumerable:!0,configurable:!0})},{allOwnKeys:a}),o),Vw=o=>(o.charCodeAt(0)===65279&&(o=o.slice(1)),o),Fw=(o,e,n,a)=>{o.prototype=Object.create(e.prototype,a),Object.defineProperty(o.prototype,"constructor",{__proto__:null,value:o,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(o,"super",{__proto__:null,value:e.prototype}),n&&Object.assign(o.prototype,n)},Kw=(o,e,n,a)=>{let i,l,c;const d={};if(e=e||{},o==null)return e;do{for(i=Object.getOwnPropertyNames(o),l=i.length;l-- >0;)c=i[l],(!a||a(c,o,e))&&!d[c]&&(e[c]=o[c],d[c]=!0);o=n!==!1&&as(o)}while(o&&(!n||n(o,e))&&o!==Object.prototype);return e},Ww=(o,e,n)=>{o=String(o),(n===void 0||n>o.length)&&(n=o.length),n-=e.length;const a=o.indexOf(e,n);return a!==-1&&a===n},Yw=o=>{if(!o)return null;if(gi(o))return o;let e=o.length;if(!kp(e))return null;const n=new Array(e);for(;e-- >0;)n[e]=o[e];return n},Xw=(o=>e=>o&&e instanceof o)(typeof Uint8Array<"u"&&as(Uint8Array)),Jw=(o,e)=>{const a=(o&&o[co]).call(o);let i;for(;(i=a.next())&&!i.done;){const l=i.value;e.call(o,l[0],l[1])}},Qw=(o,e)=>{let n;const a=[];for(;(n=o.exec(e))!==null;)a.push(n);return a},Zw=yr("HTMLFormElement"),e0=o=>o.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(n,a,i){return a.toUpperCase()+i}),{propertyIsEnumerable:t0}=Object.prototype,n0=yr("RegExp"),$p=(o,e)=>{const n=Object.getOwnPropertyDescriptors(o),a={};fo(n,(i,l)=>{let c;(c=e(i,l,o))!==!1&&(a[l]=c||i)}),Object.defineProperties(o,a)},r0=o=>{$p(o,(e,n)=>{if($n(o)&&["arguments","caller","callee"].includes(n))return!1;const a=o[n];if($n(a)){if(e.enumerable=!1,"writable"in e){e.writable=!1;return}e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+n+"'")})}})},a0=(o,e)=>{const n={},a=i=>{i.forEach(l=>{n[l]=!0})};return gi(o)?a(o):a(String(o).split(e)),n},i0=()=>{},s0=(o,e)=>o!=null&&Number.isFinite(o=+o)?o:e;function o0(o){return!!(o&&$n(o.append)&&o[Tp]==="FormData"&&o[co])}const l0=o=>{const e=new WeakSet,n=a=>{if(os(a)){if(e.has(a))return;if(ss(a))return a;if(!("toJSON"in a)){e.add(a);const i=gi(a)?[]:{};return fo(a,(l,c)=>{const d=n(l);!is(d)&&(i[c]=d)}),e.delete(a),i}}return a};return n(o)},c0=yr("AsyncFunction"),u0=o=>o&&(os(o)||$n(o))&&$n(o.then)&&$n(o.catch),Np=((o,e)=>o?setImmediate:e?((n,a)=>(pi.addEventListener("message",({source:i,data:l})=>{i===pi&&l===n&&a.length&&a.shift()()},!1),i=>{a.push(i),pi.postMessage(n,"*")}))(`axios@${Math.random()}`,[]):n=>setTimeout(n))(typeof setImmediate=="function",$n(pi.postMessage)),d0=typeof queueMicrotask<"u"?queueMicrotask.bind(pi):typeof process<"u"&&process.nextTick||Np,Ip=o=>o!=null&&$n(o[co]),F={isArray:gi,isArrayBuffer:Rp,isBuffer:ss,isFormData:Hw,isArrayBufferView:Aw,isString:xw,isNumber:kp,isBoolean:Tw,isObject:os,isPlainObject:Vl,isEmptyObject:Rw,isReadableStream:zw,isRequest:Uw,isResponse:Pw,isHeaders:Bw,isUndefined:is,isDate:kw,isFile:Dw,isReactNativeBlob:Ow,isReactNative:Lw,isBlob:Mw,isRegExp:n0,isFunction:$n,isStream:Nw,isURLSearchParams:jw,isTypedArray:Xw,isFileList:$w,forEach:fo,merge:_d,extend:Gw,trim:qw,stripBOM:Vw,inherits:Fw,toFlatObject:Kw,kindOf:Ed,kindOfTest:yr,endsWith:Ww,toArray:Yw,forEachEntry:Jw,matchAll:Qw,isHTMLForm:Zw,hasOwnProperty:ql,hasOwnProp:ql,hasOwnInPrototypeChain:uo,getSafeProp:_w,reduceDescriptors:$p,freezeMethods:r0,toObjectSet:a0,toCamelCase:e0,noop:i0,toFiniteNumber:s0,findKey:Lp,global:pi,isContextDefined:Mp,isSpecCompliantForm:o0,toJSONObject:l0,isAsyncFn:c0,isThenable:u0,setImmediate:Np,asap:d0,isIterable:Ip,isSafeIterable:o=>o!=null&&uo(o,co)&&Ip(o)},f0=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"]),h0=o=>{const e={};let n,a,i;return o&&o.split(` +`).forEach(function(c){i=c.indexOf(":"),n=c.substring(0,i).trim().toLowerCase(),a=c.substring(i+1).trim(),!(!n||e[n]&&f0[n])&&(n==="set-cookie"?e[n]?e[n].push(a):e[n]=[a]:e[n]=e[n]?e[n]+", "+a:a)}),e};function g0(o){let e=0,n=o.length;for(;ee;){const a=o.charCodeAt(n-1);if(a!==9&&a!==32)break;n-=1}return e===0&&n===o.length?o:o.slice(e,n)}const p0=new RegExp("[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+","g"),m0=new RegExp("[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+","g");function Ad(o,e){return F.isArray(o)?o.map(n=>Ad(n,e)):g0(String(o).replace(e,""))}const y0=o=>Ad(o,p0),b0=o=>Ad(o,m0);function Hp(o){const e=Object.create(null);return F.forEach(o.toJSON(),(n,a)=>{e[a]=b0(n)}),e}const jp=Symbol("internals");function ho(o){return o&&String(o).trim().toLowerCase()}function Fl(o){return o===!1||o==null?o:F.isArray(o)?o.map(Fl):y0(String(o))}function v0(o){const e=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let a;for(;a=n.exec(o);)e[a[1]]=a[2];return e}const S0=o=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(o.trim());function xd(o,e,n,a,i){if(F.isFunction(a))return a.call(this,e,n);if(i&&(e=n),!!F.isString(e)){if(F.isString(a))return e.indexOf(a)!==-1;if(F.isRegExp(a))return a.test(e)}}function w0(o){return o.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(e,n,a)=>n.toUpperCase()+a)}function C0(o,e){const n=F.toCamelCase(" "+e);["get","set","has"].forEach(a=>{Object.defineProperty(o,a+n,{__proto__:null,value:function(i,l,c){return this[a].call(this,e,i,l,c)},configurable:!0})})}let An=class{constructor(e){e&&this.set(e)}set(e,n,a){const i=this;function l(d,f,g){const m=ho(f);if(!m)return;const y=F.findKey(i,m);(!y||i[y]===void 0||g===!0||g===void 0&&i[y]!==!1)&&(i[y||f]=Fl(d))}const c=(d,f)=>F.forEach(d,(g,m)=>l(g,m,f));if(F.isPlainObject(e)||e instanceof this.constructor)c(e,n);else if(F.isString(e)&&(e=e.trim())&&!S0(e))c(h0(e),n);else if(F.isObject(e)&&F.isSafeIterable(e)){let d=Object.create(null),f,g;for(const m of e){if(!F.isArray(m))throw new TypeError("Object iterator must return a key-value pair");g=m[0],F.hasOwnProp(d,g)?(f=d[g],d[g]=F.isArray(f)?[...f,m[1]]:[f,m[1]]):d[g]=m[1]}c(d,n)}else e!=null&&l(n,e,a);return this}get(e,n){if(e=ho(e),e){const a=F.findKey(this,e);if(a){const i=this[a];if(!n)return i;if(n===!0)return v0(i);if(F.isFunction(n))return n.call(this,i,a);if(F.isRegExp(n))return n.exec(i);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,n){if(e=ho(e),e){const a=F.findKey(this,e);return!!(a&&this[a]!==void 0&&(!n||xd(this,this[a],a,n)))}return!1}delete(e,n){const a=this;let i=!1;function l(c){if(c=ho(c),c){const d=F.findKey(a,c);d&&(!n||xd(a,a[d],d,n))&&(delete a[d],i=!0)}}return F.isArray(e)?e.forEach(l):l(e),i}clear(e){const n=Object.keys(this);let a=n.length,i=!1;for(;a--;){const l=n[a];(!e||xd(this,this[l],l,e,!0))&&(delete this[l],i=!0)}return i}normalize(e){const n=this,a={};return F.forEach(this,(i,l)=>{const c=F.findKey(a,l);if(c){n[c]=Fl(i),delete n[l];return}const d=e?w0(l):String(l).trim();d!==l&&delete n[l],n[d]=Fl(i),a[d]=!0}),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const n=Object.create(null);return F.forEach(this,(a,i)=>{a!=null&&a!==!1&&(n[i]=e&&F.isArray(a)?a.join(", "):a)}),n}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([e,n])=>e+": "+n).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,...n){const a=new this(e);return n.forEach(i=>a.set(i)),a}static accessor(e){const a=(this[jp]=this[jp]={accessors:{}}).accessors,i=this.prototype;function l(c){const d=ho(c);a[d]||(C0(i,c),a[d]=!0)}return F.isArray(e)?e.forEach(l):l(e),this}};An.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),F.reduceDescriptors(An.prototype,({value:o},e)=>{let n=e[0].toUpperCase()+e.slice(1);return{get:()=>o,set(a){this[n]=a}}}),F.freezeMethods(An);const E0="[REDACTED ****]";function _0(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 A0(o,e){const n=new Set(e.map(l=>String(l).toLowerCase())),a=[],i=l=>{if(l===null||typeof l!="object"||F.isBuffer(l))return l;if(a.indexOf(l)!==-1)return;l instanceof An&&(l=l.toJSON()),a.push(l);let c;if(F.isArray(l))c=[],l.forEach((d,f)=>{const g=i(d);F.isUndefined(g)||(c[f]=g)});else{if(!F.isPlainObject(l)&&_0(l))return a.pop(),l;c=Object.create(null);for(const[d,f]of Object.entries(l)){const g=n.has(d.toLowerCase())?E0:i(f);F.isUndefined(g)||(c[d]=g)}}return a.pop(),c};return i(o)}let Ce=class FS extends Error{static from(e,n,a,i,l,c){const d=new FS(e.message,n||e.code,a,i,l);return Object.defineProperty(d,"cause",{__proto__:null,value:e,writable:!0,enumerable:!1,configurable:!0}),d.name=e.name,e.status!=null&&d.status==null&&(d.status=e.status),c&&Object.assign(d,c),d}constructor(e,n,a,i,l){super(e),Object.defineProperty(this,"message",{__proto__:null,value:e,enumerable:!0,writable:!0,configurable:!0}),this.name="AxiosError",this.isAxiosError=!0,n&&(this.code=n),a&&(this.config=a),i&&(this.request=i),l&&(this.response=l,this.status=l.status)}toJSON(){const e=this.config,n=e&&F.hasOwnProp(e,"redact")?e.redact:void 0,a=F.isArray(n)&&n.length>0?A0(e,n):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:a,code:this.code,status:this.status}}};Ce.ERR_BAD_OPTION_VALUE="ERR_BAD_OPTION_VALUE",Ce.ERR_BAD_OPTION="ERR_BAD_OPTION",Ce.ECONNABORTED="ECONNABORTED",Ce.ETIMEDOUT="ETIMEDOUT",Ce.ECONNREFUSED="ECONNREFUSED",Ce.ERR_NETWORK="ERR_NETWORK",Ce.ERR_FR_TOO_MANY_REDIRECTS="ERR_FR_TOO_MANY_REDIRECTS",Ce.ERR_DEPRECATED="ERR_DEPRECATED",Ce.ERR_BAD_RESPONSE="ERR_BAD_RESPONSE",Ce.ERR_BAD_REQUEST="ERR_BAD_REQUEST",Ce.ERR_CANCELED="ERR_CANCELED",Ce.ERR_NOT_SUPPORT="ERR_NOT_SUPPORT",Ce.ERR_INVALID_URL="ERR_INVALID_URL",Ce.ERR_FORM_DATA_DEPTH_EXCEEDED="ERR_FORM_DATA_DEPTH_EXCEEDED";const x0=null,zp=100;function Td(o){return F.isPlainObject(o)||F.isArray(o)}function Up(o){return F.endsWith(o,"[]")?o.slice(0,-2):o}function Rd(o,e,n){return o?o.concat(e).map(function(i,l){return i=Up(i),!n&&l?"["+i+"]":i}).join(n?".":""):e}function T0(o){return F.isArray(o)&&!o.some(Td)}const R0=F.toFlatObject(F,{},null,function(e){return/^is[A-Z]/.test(e)});function Kl(o,e,n){if(!F.isObject(o))throw new TypeError("target must be an object");e=e||new FormData,n=F.toFlatObject(n,{metaTokens:!0,dots:!1,indexes:!1},!1,function(M,T){return!F.isUndefined(T[M])});const a=n.metaTokens,i=n.visitor||_,l=n.dots,c=n.indexes,d=n.Blob||typeof Blob<"u"&&Blob,f=n.maxDepth===void 0?zp:n.maxDepth,g=d&&F.isSpecCompliantForm(e),m=[];if(!F.isFunction(i))throw new TypeError("visitor must be a function");function y(O){if(O===null)return"";if(F.isDate(O))return O.toISOString();if(F.isBoolean(O))return O.toString();if(!g&&F.isBlob(O))throw new Ce("Blob is not supported. Use a Buffer instead.");if(F.isArrayBuffer(O)||F.isTypedArray(O)){if(g&&typeof d=="function")return new d([O]);if(typeof Buffer<"u")return Buffer.from(O);throw new Ce("Blob is not supported. Use a Buffer instead.",Ce.ERR_NOT_SUPPORT)}return O}function S(O){if(O>f)throw new Ce("Object is too deeply nested ("+O+" levels). Max depth: "+f,Ce.ERR_FORM_DATA_DEPTH_EXCEEDED)}function v(O,M){if(f===1/0)return JSON.stringify(O);const T=[];return JSON.stringify(O,function(z,P){if(!F.isObject(P))return P;for(;T.length&&T[T.length-1]!==this;)T.pop();return T.push(P),S(M+T.length-1),P})}function _(O,M,T){let D=O;if(F.isReactNative(e)&&F.isReactNativeBlob(O))return e.append(Rd(T,M,l),y(O)),!1;if(O&&!T&&typeof O=="object"){if(F.endsWith(M,"{}"))M=a?M:M.slice(0,-2),O=v(O,1);else if(F.isArray(O)&&T0(O)||(F.isFileList(O)||F.endsWith(M,"[]"))&&(D=F.toArray(O)))return M=Up(M),D.forEach(function(P,q){!(F.isUndefined(P)||P===null)&&e.append(c===!0?Rd([M],q,l):c===null?M:M+"[]",y(P))}),!1}return Td(O)?!0:(e.append(Rd(T,M,l),y(O)),!1)}const A=Object.assign(R0,{defaultVisitor:_,convertValue:y,isVisitable:Td});function x(O,M,T=0){if(!F.isUndefined(O)){if(S(T),m.indexOf(O)!==-1)throw new Error("Circular reference detected in "+M.join("."));m.push(O),F.forEach(O,function(z,P){(!(F.isUndefined(z)||z===null)&&i.call(e,z,F.isString(P)?P.trim():P,M,A))===!0&&x(z,M?M.concat(P):[P],T+1)}),m.pop()}}if(!F.isObject(o))throw new TypeError("data must be an object");return x(o),e}function Pp(o){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+"};return encodeURIComponent(o).replace(/[!'()~]|%20/g,function(a){return e[a]})}function kd(o,e){this._pairs=[],o&&Kl(o,this,e)}const Bp=kd.prototype;Bp.append=function(e,n){this._pairs.push([e,n])},Bp.toString=function(e){const n=e?a=>e.call(this,a,Pp):Pp;return this._pairs.map(function(i){return n(i[0])+"="+n(i[1])},"").join("&")};function k0(o){return encodeURIComponent(o).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+")}function qp(o,e,n){if(!e)return o;o=o||"";const a=F.isFunction(n)?{serialize:n}:n,i=F.getSafeProp(a,"encode")||k0,l=F.getSafeProp(a,"serialize");let c;if(l?c=l(e,a):c=F.isURLSearchParams(e)?e.toString():new kd(e,a).toString(i),c){const d=o.indexOf("#");d!==-1&&(o=o.slice(0,d)),o+=(o.indexOf("?")===-1?"?":"&")+c}return o}class Gp{constructor(){this.handlers=[]}use(e,n,a){return this.handlers.push({fulfilled:e,rejected:n,synchronous:a?a.synchronous:!1,runWhen:a?a.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(a){a!==null&&e(a)})}}const Dd={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1,legacyInterceptorReqResOrdering:!0,advertiseZstdAcceptEncoding:!1,validateStatusUndefinedResolves:!0},D0={isBrowser:!0,classes:{URLSearchParams:typeof URLSearchParams<"u"?URLSearchParams:kd,FormData:typeof FormData<"u"?FormData:null,Blob:typeof Blob<"u"?Blob:null},protocols:["http","https","file","blob","url","data"]},Od=typeof window<"u"&&typeof document<"u",Ld=typeof navigator=="object"&&navigator||void 0,O0=Od&&(!Ld||["ReactNative","NativeScript","NS"].indexOf(Ld.product)<0),L0=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function",M0=Od&&window.location.href||"http://localhost",mn={...Object.freeze(Object.defineProperty({__proto__:null,hasBrowserEnv:Od,hasStandardBrowserEnv:O0,hasStandardBrowserWebWorkerEnv:L0,navigator:Ld,origin:M0},Symbol.toStringTag,{value:"Module"})),...D0};function $0(o,e){return Kl(o,new mn.classes.URLSearchParams,{visitor:function(n,a,i,l){return mn.isNode&&F.isBuffer(n)?(this.append(a,n.toString("base64")),!1):l.defaultVisitor.apply(this,arguments)},...e})}const Vp=zp;function Fp(o){if(o>Vp)throw new Ce("FormData field is too deeply nested ("+o+" levels). Max depth: "+Vp,Ce.ERR_FORM_DATA_DEPTH_EXCEEDED)}function N0(o){const e=[],n=/\w+|\[(\w*)]/g;let a;for(;(a=n.exec(o))!==null;)Fp(e.length),e.push(a[0]==="[]"?"":a[1]||a[0]);return e}function I0(o){const e={},n=Object.keys(o);let a;const i=n.length;let l;for(a=0;a=n.length;return c=!c&&F.isArray(i)?i.length:c,f?(F.hasOwnProp(i,c)?i[c]=F.isArray(i[c])?i[c].concat(a):[i[c],a]:i[c]=a,!d):((!F.hasOwnProp(i,c)||!F.isObject(i[c]))&&(i[c]=[]),e(n,a,i[c],l)&&F.isArray(i[c])&&(i[c]=I0(i[c])),!d)}if(F.isFormData(o)&&F.isFunction(o.entries)){const n={};return F.forEachEntry(o,(a,i)=>{e(N0(a),i,n,0)}),n}return null}const ls=(o,e)=>o!=null&&F.hasOwnProp(o,e)?o[e]:void 0;function H0(o,e,n){if(F.isString(o))try{return(e||JSON.parse)(o),F.trim(o)}catch(a){if(a.name!=="SyntaxError")throw a}return(n||JSON.stringify)(o)}const go={transitional:Dd,adapter:["xhr","http","fetch"],transformRequest:[function(e,n){const a=n.getContentType()||"",i=a.indexOf("application/json")>-1,l=F.isObject(e);if(l&&F.isHTMLForm(e)&&(e=new FormData(e)),F.isFormData(e))return i?JSON.stringify(Kp(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 n.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let d;if(l){const f=ls(this,"formSerializer");if(a.indexOf("application/x-www-form-urlencoded")>-1)return $0(e,f).toString();if((d=F.isFileList(e))||a.indexOf("multipart/form-data")>-1){const g=ls(this,"env"),m=g&&g.FormData;return Kl(d?{"files[]":e}:e,m&&new m,f)}}return l||i?(n.setContentType("application/json",!1),H0(e)):e}],transformResponse:[function(e){const n=ls(this,"transitional")||go.transitional,a=n&&n.forcedJSONParsing,i=ls(this,"responseType"),l=i==="json";if(F.isResponse(e)||F.isReadableStream(e))return e;if(e&&F.isString(e)&&(a&&!i||l)){const d=!(n&&n.silentJSONParsing)&&l;try{return JSON.parse(e,ls(this,"parseReviver"))}catch(f){if(d)throw f.name==="SyntaxError"?Ce.from(f,Ce.ERR_BAD_RESPONSE,this,null,ls(this,"response")):f}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:mn.classes.FormData,Blob:mn.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=>{go.headers[o]={}});function Md(o,e){const n=this||go,a=e||n,i=An.from(a.headers);let l=a.data;return F.forEach(o,function(d){l=d.call(n,l,i.normalize(),e?e.status:void 0)}),i.normalize(),l}function Wp(o){return!!(o&&o.__CANCEL__)}let po=class extends Ce{constructor(e,n,a){super(e??"canceled",Ce.ERR_CANCELED,n,a),this.name="CanceledError",this.__CANCEL__=!0}};function Yp(o,e,n){const a=n.config.validateStatus;!n.status||!a||a(n.status)?o(n):e(new Ce("Request failed with status code "+n.status,n.status>=400&&n.status<500?Ce.ERR_BAD_REQUEST:Ce.ERR_BAD_RESPONSE,n.config,n.request,n))}function j0(o){const e=/^([-+\w]{1,25}):(?:\/\/)?/.exec(o);return e&&e[1]||""}function z0(o,e){o=o||10;const n=new Array(o),a=new Array(o);let i=0,l=0,c;return e=e!==void 0?e:1e3,function(f){const g=Date.now(),m=a[l];c||(c=g),n[i]=f,a[i]=g;let y=l,S=0;for(;y!==i;)S+=n[y++],y=y%o;if(i=(i+1)%o,i===l&&(l=(l+1)%o),g-c{n=m,i=null,l&&(clearTimeout(l),l=null),o(...g)};return[(...g)=>{const m=Date.now(),y=m-n;y>=a?c(g,m):(i=g,l||(l=setTimeout(()=>{l=null,c(i)},a-y)))},()=>i&&c(i)]}const Wl=(o,e,n=3)=>{let a=0;const i=z0(50,250);return U0(l=>{if(!l||typeof l.loaded!="number")return;const c=l.loaded,d=l.lengthComputable?l.total:void 0,f=d!=null?Math.min(c,d):c,g=Math.max(0,f-a),m=i(g);a=Math.max(a,f);const y={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(y)},n)},Xp=(o,e)=>{const n=o!=null;return[a=>e[0]({lengthComputable:n,total:o,loaded:a}),e[1]]},Jp=o=>(...e)=>F.asap(()=>o(...e)),P0=mn.hasStandardBrowserEnv?((o,e)=>n=>(n=new URL(n,mn.origin),o.protocol===n.protocol&&o.host===n.host&&(e||o.port===n.port)))(new URL(mn.origin),mn.navigator&&/(msie|trident)/i.test(mn.navigator.userAgent)):()=>!0,B0=mn.hasStandardBrowserEnv?{write(o,e,n,a,i,l,c){if(typeof document>"u")return;const d=[`${o}=${encodeURIComponent(e)}`];F.isNumber(n)&&d.push(`expires=${new Date(n).toUTCString()}`),F.isString(a)&&d.push(`path=${a}`),F.isString(i)&&d.push(`domain=${i}`),l===!0&&d.push("secure"),F.isString(c)&&d.push(`SameSite=${c}`),document.cookie=d.join("; ")},read(o){if(typeof document>"u")return null;const e=document.cookie.split(";");for(let n=0;no instanceof An?{...o}:o;function mi(o,e){o=o||{},e=e||{};const n=Object.create(null);Object.defineProperty(n,"hasOwnProperty",{__proto__:null,value:Object.prototype.hasOwnProperty,enumerable:!1,writable:!0,configurable:!0});function a(m,y,S,v){return F.isPlainObject(m)&&F.isPlainObject(y)?F.merge.call({caseless:v},m,y):F.isPlainObject(y)?F.merge({},y):F.isArray(y)?y.slice():y}function i(m,y,S,v){if(F.isUndefined(y)){if(!F.isUndefined(m))return a(void 0,m,S,v)}else return a(m,y,S,v)}function l(m,y){if(!F.isUndefined(y))return a(void 0,y)}function c(m,y){if(F.isUndefined(y)){if(!F.isUndefined(m))return a(void 0,m)}else return a(void 0,y)}function d(m){const y=F.hasOwnProp(e,"transitional")?e.transitional:void 0;if(!F.isUndefined(y))if(F.isPlainObject(y)){if(F.hasOwnProp(y,m))return y[m]}else return;const S=F.hasOwnProp(o,"transitional")?o.transitional:void 0;if(F.isPlainObject(S)&&F.hasOwnProp(S,m))return S[m]}function f(m,y,S){if(F.hasOwnProp(e,S))return a(m,y);if(F.hasOwnProp(o,S))return a(void 0,m)}const g={url:l,method:l,data:l,baseURL:c,transformRequest:c,transformResponse:c,paramsSerializer:c,timeout:c,timeoutMessage:c,withCredentials:c,withXSRFToken:c,adapter:c,responseType:c,xsrfCookieName:c,xsrfHeaderName:c,onUploadProgress:c,onDownloadProgress:c,decompress:c,maxContentLength:c,maxBodyLength:c,beforeRedirect:c,transport:c,httpAgent:c,httpsAgent:c,cancelToken:c,socketPath:c,allowedSocketPaths:c,responseEncoding:c,validateStatus:f,headers:(m,y,S)=>i(em(m),em(y),S,!0)};return F.forEach(Object.keys({...o,...e}),function(y){if(y==="__proto__"||y==="constructor"||y==="prototype")return;const S=F.hasOwnProp(g,y)?g[y]:i,v=F.hasOwnProp(o,y)?o[y]:void 0,_=F.hasOwnProp(e,y)?e[y]:void 0,A=S(v,_,y);F.isUndefined(A)&&S!==f||(n[y]=A)}),F.hasOwnProp(e,"validateStatus")&&F.isUndefined(e.validateStatus)&&d("validateStatusUndefinedResolves")===!1&&(F.hasOwnProp(o,"validateStatus")?n.validateStatus=a(void 0,o.validateStatus):delete n.validateStatus),n}const Y0=["content-type","content-length"];function X0(o,e,n){if(n!=="content-only"){o.set(e);return}Object.entries(e||{}).forEach(([a,i])=>{Y0.includes(a.toLowerCase())&&o.set(a,i)})}const J0=o=>encodeURIComponent(o).replace(/%([0-9A-F]{2})/gi,(e,n)=>String.fromCharCode(parseInt(n,16)));function tm(o){const e=mi({},o),n=S=>F.hasOwnProp(e,S)?e[S]:void 0,a=n("data");let i=n("withXSRFToken");const l=n("xsrfHeaderName"),c=n("xsrfCookieName");let d=n("headers");const f=n("auth"),g=n("baseURL"),m=n("allowAbsoluteUrls"),y=n("url");if(e.headers=d=An.from(d),e.url=qp(Zp(g,y,m,e),n("params"),n("paramsSerializer")),f){const S=F.getSafeProp(f,"username")||"",v=F.getSafeProp(f,"password")||"";try{d.set("Authorization","Basic "+btoa(S+":"+(v?J0(v):"")))}catch(_){throw Ce.from(_,Ce.ERR_BAD_OPTION_VALUE,o)}}if(F.isFormData(a)&&(mn.hasStandardBrowserEnv||mn.hasStandardBrowserWebWorkerEnv||F.isReactNative(a)?d.setContentType(void 0):F.isFunction(a.getHeaders)&&X0(d,a.getHeaders(),n("formDataHeaderPolicy"))),mn.hasStandardBrowserEnv&&(F.isFunction(i)&&(i=i(e)),i===!0||i==null&&P0(e.url))){const v=l&&c&&B0.read(c);v&&d.set(l,v)}return e}const Q0=typeof XMLHttpRequest<"u"&&function(o){return new Promise(function(n,a){const i=tm(o);let l=i.data;const c=An.from(i.headers).normalize();let{responseType:d,onUploadProgress:f,onDownloadProgress:g}=i,m,y,S,v,_;function A(){v&&v(),_&&_(),i.cancelToken&&i.cancelToken.unsubscribe(m),i.signal&&i.signal.removeEventListener("abort",m)}let x=new XMLHttpRequest;x.open(i.method.toUpperCase(),i.url,!0),x.timeout=i.timeout;function O(){if(!x)return;const T=An.from("getAllResponseHeaders"in x&&x.getAllResponseHeaders()),z={data:!d||d==="text"||d==="json"?x.responseText:x.response,status:x.status,statusText:x.statusText,headers:T,config:o,request:x};Yp(function(q){n(q),A()},function(q){a(q),A()},z),x=null}"onloadend"in x?x.onloadend=O:x.onreadystatechange=function(){!x||x.readyState!==4||x.status===0&&!(x.responseURL&&x.responseURL.startsWith("file:"))||setTimeout(O)},x.onabort=function(){x&&(a(new Ce("Request aborted",Ce.ECONNABORTED,o,x)),A(),x=null)},x.onerror=function(D){const z=D&&D.message?D.message:"Network Error",P=new Ce(z,Ce.ERR_NETWORK,o,x);P.event=D||null,a(P),A(),x=null},x.ontimeout=function(){let D=i.timeout?"timeout of "+i.timeout+"ms exceeded":"timeout exceeded";const z=i.transitional||Dd;i.timeoutErrorMessage&&(D=i.timeoutErrorMessage),a(new Ce(D,z.clarifyTimeoutError?Ce.ETIMEDOUT:Ce.ECONNABORTED,o,x)),A(),x=null},l===void 0&&c.setContentType(null),"setRequestHeader"in x&&F.forEach(Hp(c),function(D,z){x.setRequestHeader(z,D)}),F.isUndefined(i.withCredentials)||(x.withCredentials=!!i.withCredentials),d&&d!=="json"&&(x.responseType=i.responseType),g&&([S,_]=Wl(g,!0),x.addEventListener("progress",S)),f&&x.upload&&([y,v]=Wl(f),x.upload.addEventListener("progress",y),x.upload.addEventListener("loadend",v)),(i.cancelToken||i.signal)&&(m=T=>{x&&(a(!T||T.type?new po(null,o,x):T),x.abort(),A(),x=null)},i.cancelToken&&i.cancelToken.subscribe(m),i.signal&&(i.signal.aborted?m():i.signal.addEventListener("abort",m)));const M=j0(i.url);if(M&&!mn.protocols.includes(M)){a(new Ce("Unsupported protocol "+M+":",Ce.ERR_BAD_REQUEST,o)),A();return}x.send(l||null)})},Z0=(o,e)=>{if(o=o?o.filter(Boolean):[],!e&&!o.length)return;const n=new AbortController;let a=!1;const i=function(f){if(!a){a=!0,c();const g=f instanceof Error?f:this.reason;n.abort(g instanceof Ce?g:new po(g instanceof Error?g.message:g))}};let l=e&&setTimeout(()=>{l=null,i(new Ce(`timeout of ${e}ms exceeded`,Ce.ETIMEDOUT))},e);const c=()=>{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,{once:!0}));const{signal:d}=n;return d.unsubscribe=()=>F.asap(c),d},eC=function*(o,e){let n=o.byteLength;if(n{const i=tC(o,e);let l=0,c,d=f=>{c||(c=!0,a&&a(f))};return new ReadableStream({async pull(f){try{const{done:g,value:m}=await i.next();if(g){d(),f.close();return}let y=m.byteLength;if(n){let S=l+=y;n(S)}f.enqueue(new Uint8Array(m))}catch(g){throw d(g),g}},cancel(f){return d(f),i.return()}},{highWaterMark:2})},Yl=o=>o>=48&&o<=57||o>=65&&o<=70||o>=97&&o<=102,rC=(o,e,n)=>e+2v>=2&&a.charCodeAt(v-2)===37&&a.charCodeAt(v-1)===51&&(a.charCodeAt(v)===68||a.charCodeAt(v)===100);g>=0&&(a.charCodeAt(g)===61?(f++,g--):m(g)&&(f++,g-=3)),f===1&&g>=0&&(a.charCodeAt(g)===61||m(g))&&f++;const S=Math.floor(c/4)*3-(f||0);return S>0?S:0}let l=0;for(let c=0,d=a.length;c=55296&&f<=56319&&c+1=56320&&g<=57343?(l+=4,c++):l+=3}else l+=3}return l}const $d="1.18.1",rm=64*1024,{isFunction:Xl}=F,iC=o=>encodeURIComponent(o).replace(/%([0-9A-F]{2})/gi,(e,n)=>String.fromCharCode(parseInt(n,16))),am=o=>{if(!F.isString(o))return o;try{return decodeURIComponent(o)}catch{return o}},im=(o,...e)=>{try{return!!o(...e)}catch{return!1}},sC=o=>{const e=o.indexOf("://");let n=o;return e!==-1&&(n=n.slice(e+3)),n.includes("@")||n.includes(":")},oC=o=>{const e=F.global!==void 0&&F.global!==null?F.global:globalThis,{ReadableStream:n,TextEncoder:a}=e;o=F.merge.call({skipUndefined:!0},{Request:e.Request,Response:e.Response},o);const{fetch:i,Request:l,Response:c}=o,d=i?Xl(i):typeof fetch=="function",f=Xl(l),g=Xl(c);if(!d)return!1;const m=d&&Xl(n),y=d&&(typeof a=="function"?(O=>M=>O.encode(M))(new a):async O=>new Uint8Array(await new l(O).arrayBuffer())),S=f&&m&&im(()=>{let O=!1;const M=new l(mn.origin,{body:new n,method:"POST",get duplex(){return O=!0,"half"}}),T=M.headers.has("Content-Type");return M.body!=null&&M.body.cancel(),O&&!T}),v=g&&m&&im(()=>F.isReadableStream(new c("").body)),_={stream:v&&(O=>O.body)};d&&["text","arrayBuffer","blob","formData","stream"].forEach(O=>{!_[O]&&(_[O]=(M,T)=>{let D=M&&M[O];if(D)return D.call(M);throw new Ce(`Response type '${O}' is not supported`,Ce.ERR_NOT_SUPPORT,T)})});const A=async O=>{if(O==null)return 0;if(F.isBlob(O))return O.size;if(F.isSpecCompliantForm(O))return(await new l(mn.origin,{method:"POST",body:O}).arrayBuffer()).byteLength;if(F.isArrayBufferView(O)||F.isArrayBuffer(O))return O.byteLength;if(F.isURLSearchParams(O)&&(O=O+""),F.isString(O))return(await y(O)).byteLength},x=async(O,M)=>{const T=F.toFiniteNumber(O.getContentLength());return T??A(M)};return async O=>{let{url:M,method:T,data:D,signal:z,cancelToken:P,timeout:q,onDownloadProgress:W,onUploadProgress:he,responseType:Ee,headers:be,withCredentials:Ue="same-origin",fetchOptions:Fe,maxContentLength:Ge,maxBodyLength:wt}=tm(O);const J=F.isNumber(Ge)&&Ge>-1,ue=F.isNumber(wt)&&wt>-1,Me=ee=>F.hasOwnProp(O,ee)?O[ee]:void 0;let te=i||fetch;Ee=Ee?(Ee+"").toLowerCase():"text";let pe=Z0([z,P&&P.toAbortSignal()],q),N=null;const R=pe&&pe.unsubscribe&&(()=>{pe.unsubscribe()});let de,fe=null;const xe=()=>new Ce("Request body larger than maxBodyLength limit",Ce.ERR_BAD_REQUEST,O,N);try{let ee;const _e=Me("auth");if(_e){const Oe=F.getSafeProp(_e,"username")||"",nt=F.getSafeProp(_e,"password")||"";ee={username:Oe,password:nt}}if(sC(M)){const Oe=new URL(M,mn.origin);if(!ee&&(Oe.username||Oe.password)){const nt=am(Oe.username),sn=am(Oe.password);ee={username:nt,password:sn}}(Oe.username||Oe.password)&&(Oe.username="",Oe.password="",M=Oe.href)}if(ee&&(be.delete("authorization"),be.set("Authorization","Basic "+btoa(iC((ee.username||"")+":"+(ee.password||""))))),J&&typeof M=="string"&&M.startsWith("data:")&&aC(M)>Ge)throw new Ce("maxContentLength size of "+Ge+" exceeded",Ce.ERR_BAD_RESPONSE,O,N);if(ue&&T!=="get"&&T!=="head"){const Oe=await A(D);if(typeof Oe=="number"&&isFinite(Oe)&&(de=Oe,Oe>wt))throw xe()}const Be=ue&&(F.isReadableStream(D)||F.isStream(D)),ke=(Oe,nt,sn)=>nm(Oe,rm,Mt=>{if(ue&&Mt>wt)throw fe=xe();nt&&nt(Mt)},sn);if(S&&T!=="get"&&T!=="head"&&(he||Be)){if(de=de??await x(be,D),de!==0||Be){let Oe=new l(M,{method:"POST",body:D,duplex:"half"}),nt;if(F.isFormData(D)&&(nt=Oe.headers.get("content-type"))&&be.setContentType(nt),Oe.body){const[sn,Mt]=he&&Xp(de,Wl(Jp(he)))||[];D=ke(Oe.body,sn,Mt)}}}else if(Be&&!f&&m&&T!=="get"&&T!=="head")D=ke(D);else if(Be&&f&&!S&&T!=="get"&&T!=="head")throw new Ce("Stream request bodies are not supported by the current fetch implementation",Ce.ERR_NOT_SUPPORT,O,N);F.isString(Ue)||(Ue=Ue?"include":"omit");const Ie=f&&"credentials"in l.prototype;if(F.isFormData(D)){const Oe=be.getContentType();Oe&&/^multipart\/form-data/i.test(Oe)&&!/boundary=/i.test(Oe)&&be.delete("content-type")}be.set("User-Agent","axios/"+$d,!1);const Ct={...Fe,signal:pe,method:T.toUpperCase(),headers:Hp(be.normalize()),body:D,duplex:"half",credentials:Ie?Ue:void 0};N=f&&new l(M,Ct);let ot=await(f?te(N,Fe):te(M,Ct));const Ot=An.from(ot.headers);if(J){const Oe=F.toFiniteNumber(Ot.getContentLength());if(Oe!=null&&Oe>Ge)throw new Ce("maxContentLength size of "+Ge+" exceeded",Ce.ERR_BAD_RESPONSE,O,N)}const vt=v&&(Ee==="stream"||Ee==="response");if(v&&ot.body&&(W||J||vt&&R)){const Oe={};["status","statusText","headers"].forEach(ln=>{Oe[ln]=ot[ln]});const nt=F.toFiniteNumber(Ot.getContentLength()),[sn,Mt]=W&&Xp(nt,Wl(Jp(W),!0))||[];let Vt=0;const on=ln=>{if(J&&(Vt=ln,Vt>Ge))throw new Ce("maxContentLength size of "+Ge+" exceeded",Ce.ERR_BAD_RESPONSE,O,N);sn&&sn(ln)};ot=new c(nm(ot.body,rm,on,()=>{Mt&&Mt(),R&&R()}),Oe)}Ee=Ee||"text";let _t=await _[F.findKey(_,Ee)||"text"](ot,O);if(J&&!v&&!vt){let Oe;if(_t!=null&&(typeof _t.byteLength=="number"?Oe=_t.byteLength:typeof _t.size=="number"?Oe=_t.size:typeof _t=="string"&&(Oe=typeof a=="function"?new a().encode(_t).byteLength:_t.length)),typeof Oe=="number"&&Oe>Ge)throw new Ce("maxContentLength size of "+Ge+" exceeded",Ce.ERR_BAD_RESPONSE,O,N)}return!vt&&R&&R(),await new Promise((Oe,nt)=>{Yp(Oe,nt,{data:_t,headers:An.from(ot.headers),status:ot.status,statusText:ot.statusText,config:O,request:N})})}catch(ee){if(R&&R(),pe&&pe.aborted&&pe.reason instanceof Ce){const _e=pe.reason;throw _e.config=O,N&&(_e.request=N),ee!==_e&&Object.defineProperty(_e,"cause",{__proto__:null,value:ee,writable:!0,enumerable:!1,configurable:!0}),_e}if(fe)throw N&&!fe.request&&(fe.request=N),fe;if(ee instanceof Ce)throw N&&!ee.request&&(ee.request=N),ee;if(ee&&ee.name==="TypeError"&&/Load failed|fetch/i.test(ee.message)){const _e=new Ce("Network Error",Ce.ERR_NETWORK,O,N,ee&&ee.response);throw Object.defineProperty(_e,"cause",{__proto__:null,value:ee.cause||ee,writable:!0,enumerable:!1,configurable:!0}),_e}throw Ce.from(ee,ee&&ee.code,O,N,ee&&ee.response)}}},lC=new Map,sm=o=>{let e=o&&o.env||{};const{fetch:n,Request:a,Response:i}=e,l=[a,i,n];let c=l.length,d=c,f,g,m=lC;for(;d--;)f=l[d],g=m.get(f),g===void 0&&m.set(f,g=d?new Map:oC(e)),m=g;return g};sm();const Nd={http:x0,xhr:Q0,fetch:{get:sm}};F.forEach(Nd,(o,e)=>{if(o){try{Object.defineProperty(o,"name",{__proto__:null,value:e})}catch{}Object.defineProperty(o,"adapterName",{__proto__:null,value:e})}});const om=o=>`- ${o}`,cC=o=>F.isFunction(o)||o===null||o===!1;function uC(o,e){o=F.isArray(o)?o:[o];const{length:n}=o;let a,i;const l={};for(let c=0;c`adapter ${f} `+(g===!1?"is not supported by the environment":"is not available in the build"));let d=n?c.length>1?`since : +`+c.map(om).join(` +`):" "+om(c[0]):"as no adapter specified";throw new Ce("There is no suitable adapter to dispatch the request "+d,Ce.ERR_NOT_SUPPORT)}return i}const lm={getAdapter:uC,adapters:Nd};function Id(o){if(o.cancelToken&&o.cancelToken.throwIfRequested(),o.signal&&o.signal.aborted)throw new po(null,o)}function cm(o){return Id(o),o.headers=An.from(o.headers),o.data=Md.call(o,o.transformRequest),["post","put","patch"].indexOf(o.method)!==-1&&o.headers.setContentType("application/x-www-form-urlencoded",!1),lm.getAdapter(o.adapter||go.adapter,o)(o).then(function(a){Id(o),o.response=a;try{a.data=Md.call(o,o.transformResponse,a)}finally{delete o.response}return a.headers=An.from(a.headers),a},function(a){if(!Wp(a)&&(Id(o),a&&a.response)){o.response=a.response;try{a.response.data=Md.call(o,o.transformResponse,a.response)}finally{delete o.response}a.response.headers=An.from(a.response.headers)}return Promise.reject(a)})}const Jl={};["object","boolean","number","function","string","symbol"].forEach((o,e)=>{Jl[o]=function(a){return typeof a===o||"a"+(e<1?"n ":" ")+o}});const um={};Jl.transitional=function(e,n,a){function i(l,c){return"[Axios v"+$d+"] Transitional option '"+l+"'"+c+(a?". "+a:"")}return(l,c,d)=>{if(e===!1)throw new Ce(i(c," has been removed"+(n?" in "+n:"")),Ce.ERR_DEPRECATED);return n&&!um[c]&&(um[c]=!0,console.warn(i(c," has been deprecated since v"+n+" and will be removed in the near future"))),e?e(l,c,d):!0}},Jl.spelling=function(e){return(n,a)=>(console.warn(`${a} is likely a misspelling of ${e}`),!0)};function dC(o,e,n){if(typeof o!="object"||o===null)throw new Ce("options must be an object",Ce.ERR_BAD_OPTION_VALUE);const a=Object.keys(o);let i=a.length;for(;i-- >0;){const l=a[i],c=Object.prototype.hasOwnProperty.call(e,l)?e[l]:void 0;if(c){const d=o[l],f=d===void 0||c(d,l,o);if(f!==!0)throw new Ce("option "+l+" must be "+f,Ce.ERR_BAD_OPTION_VALUE);continue}if(n!==!0)throw new Ce("Unknown option "+l,Ce.ERR_BAD_OPTION)}}const Ql={assertOptions:dC,validators:Jl},xn=Ql.validators;let yi=class{constructor(e){this.defaults=e||{},this.interceptors={request:new Gp,response:new Gp}}async request(e,n){try{return await this._request(e,n)}catch(a){if(a instanceof Error){let i={};Error.captureStackTrace?Error.captureStackTrace(i):i=new Error;const l=(()=>{if(!i.stack)return"";const c=i.stack.indexOf(` `);return c===-1?"":i.stack.slice(c+1)})();try{if(!a.stack)a.stack=l;else if(l){const c=l.indexOf(` `),d=c===-1?-1:l.indexOf(` `,c+1),f=d===-1?"":l.slice(d+1);String(a.stack).endsWith(f)||(a.stack+=` -`+l)}}catch{}}throw a}}_request(e,n){typeof e=="string"?(n=n||{},n.url=e):n=e||{},n=pi(this.defaults,n);const{transitional:a,paramsSerializer:i,headers:l}=n;a!==void 0&&Yl.assertOptions(a,{silentJSONParsing:nr.transitional(nr.boolean),forcedJSONParsing:nr.transitional(nr.boolean),clarifyTimeoutError:nr.transitional(nr.boolean),legacyInterceptorReqResOrdering:nr.transitional(nr.boolean)},!1),i!=null&&(W.isFunction(i)?n.paramsSerializer={serialize:i}:Yl.assertOptions(i,{encode:nr.function,serialize:nr.function},!0)),n.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?n.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:n.allowAbsoluteUrls=!0),Yl.assertOptions(n,{baseUrl:nr.spelling("baseURL"),withXsrfToken:nr.spelling("withXSRFToken")},!0),n.method=(n.method||this.defaults.method||"get").toLowerCase();let c=l&&W.merge(l.common,l[n.method]);l&&W.forEach(["delete","get","head","post","put","patch","query","common"],_=>{delete l[_]}),n.headers=Tn.concat(c,l);const d=[];let f=!0;this.interceptors.request.forEach(function(A){if(typeof A.runWhen=="function"&&A.runWhen(n)===!1)return;f=f&&A.synchronous;const x=n.transitional||xd;x&&x.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,S;if(!f){const _=[em.bind(this),void 0];for(_.unshift(...d),_.push(...g),S=_.length,m=Promise.resolve(n);b{if(!a._listeners)return;let l=a._listeners.length;for(;l-- >0;)a._listeners[l](i);a._listeners=null}),this.promise.then=i=>{let l;const c=new Promise(d=>{a.subscribe(d),l=d}).then(i);return c.cancel=function(){a.unsubscribe(l)},c},e(function(l,c,d){a.reason||(a.reason=new fo(l,c,d),n(a.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 n=this._listeners.indexOf(e);n!==-1&&this._listeners.splice(n,1)}toAbortSignal(){const e=new AbortController,n=a=>{e.abort(a)};return this.subscribe(n),e.signal.unsubscribe=()=>this.unsubscribe(n),e.signal}static source(){let e;return{token:new jS(function(i){e=i}),cancel:e}}};function J0(o){return function(n){return o.apply(null,n)}}function Q0(o){return W.isObject(o)&&o.isAxiosError===!0}const Md={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(Md).forEach(([o,e])=>{Md[e]=o});function nm(o){const e=new mi(o),n=Ep(mi.prototype.request,e);return W.extend(n,mi.prototype,e,{allOwnKeys:!0}),W.extend(n,e,null,{allOwnKeys:!0}),n.create=function(i){return nm(pi(o,i))},n}const Vt=nm(uo);Vt.Axios=mi,Vt.CanceledError=fo,Vt.CancelToken=X0,Vt.isCancel=Bp,Vt.VERSION=Dd,Vt.toFormData=Vl,Vt.AxiosError=Oe,Vt.Cancel=Vt.CanceledError,Vt.all=function(e){return Promise.all(e)},Vt.spread=J0,Vt.isAxiosError=Q0,Vt.mergeConfig=pi,Vt.AxiosHeaders=Tn,Vt.formToJSON=o=>Up(W.isHTMLForm(o)?new FormData(o):o),Vt.getAdapter=Zp.getAdapter,Vt.HttpStatusCode=Md,Vt.default=Vt;const{Axios:pT,AxiosError:mT,CanceledError:yT,isCancel:bT,CancelToken:vT,VERSION:ST,all:wT,Cancel:CT,isAxiosError:ET,spread:_T,toFormData:AT,AxiosHeaders:xT,HttpStatusCode:TT,formToJSON:RT,getAdapter:kT,mergeConfig:DT,create:OT}=Vt,$d="g7.identity.redirectStash",Xl=ut("IdentityGuardInterceptor");class vt{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 n=this.deferredResolver;if(!n){Xl.warn("IdentityGuardInterceptor.resolveDeferred 호출됐지만 대기 중인 launcher 가 없습니다. 모달이 launcher 외부에서 열렸는지 확인하세요.");return}this.deferredResolver=null,n(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,n){return e===428&&typeof n=="object"&&n!==null&&n.error_code==="identity_verification_required"}static async handle(e,n,a){this.domainNoticeShown=!1;const i=this.launcher??eC,c=!!(a&&(a.email||a.phone))?{...e.verification,target:a}:e.verification,d=await i(c);if(d.status!=="verified")return null;const f=c.return_request;if(!f)return null;const g=Z0(f.url,d.token);return fetch(g,{method:f.method,headers:n?.headers??{Accept:"application/json","Content-Type":"application/json"},body:n?.body,credentials:n?.credentials??"same-origin"})}static redirectExternally(e){const n=e.redirect_url;if(!n)return Xl.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 a={return_url:window.location.href,payload:e,stashed_at:Date.now()};try{window.sessionStorage?.setItem($d,JSON.stringify(a))}catch(i){Xl.warn("sessionStorage 접근 실패 — stash 없이 redirect 합니다.",i)}window.location.href=n}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}}$(vt,"launcher",null),$(vt,"deferredResolver",null),$(vt,"domainNoticeShown",!1);function Z0(o,e){if(!e)return o;try{const n=typeof window<"u"?window.location.origin:"http://localhost",a=new URL(o,n);return a.searchParams.set("verification_token",e),/^https?:\/\//i.test(o)?a.toString():`${a.pathname}${a.search}${a.hash}`}catch{const n=o.includes("?")?"&":"?";return`${o}${n}verification_token=${encodeURIComponent(e)}`}}const eC=async o=>{if(typeof window>"u")return{status:"cancelled"};if(o.render_hint==="external_redirect"||o.redirect_url)return vt.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 n=window.location.href,a={return_url:n,payload:o,stashed_at:Date.now()};try{window.sessionStorage?.setItem($d,JSON.stringify(a))}catch{}const i=`/identity/challenge?return=${encodeURIComponent(n)}`;try{await e.dispatch({handler:"navigate",params:{path:i}})}catch(l){Xl.warn("navigate 실패 — window.location 으로 폴백",l),window.location.href=i}return new Promise(()=>{})},tC=ut("ApiClient");function Nd(){return typeof window<"u"&&window.__G7_DEVTOOLS__?window.__G7_DEVTOOLS__:null}class nC{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=Vt.create({baseURL:this.config.baseURL,timeout:this.config.timeout,headers:{"Content-Type":"application/json",Accept:"application/json"},paramsSerializer:{serialize:n=>{const a=[];for(const[i,l]of Object.entries(n))if(l!=null)if(Array.isArray(l)){const c=i.endsWith("[]")?i:`${i}[]`;for(const d of l)a.push(`${encodeURIComponent(c)}=${encodeURIComponent(String(d))}`)}else a.push(`${encodeURIComponent(i)}=${encodeURIComponent(String(l))}`);return a.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 n=this.getToken();if(n&&e.headers&&(e.headers.Authorization=`Bearer ${n}`),typeof window<"u"&&e.headers){const i=localStorage.getItem("g7_locale");i&&(e.headers["Accept-Language"]=i)}const a=Nd();if(a?.isEnabled()){const i=this.buildFullUrl(e),l=(e.method||"GET").toUpperCase(),c=a.trackRequest(i,l,{requestBody:e.data});e._devToolsRequestId=c}return e},e=>Promise.reject(e)),this.client.interceptors.response.use(e=>{const n=e.config,a=n._devToolsRequestId;if(a){const i=Nd();i?.isEnabled()&&i.completeRequest(a,e.status,e.data),n._devToolsRequestId=null}return e},async e=>{const n=e.config,a=n?.url||"",l=["/auth/","/layouts/"].some(c=>a.includes(c));if(e.response?.status===401&&!n?._retry&&!l){if(n._retry=!0,await yr.getInstance().refreshToken()){const f=this.getToken();return f&&(n.headers.Authorization=`Bearer ${f}`),n._devToolsRequestId=null,this.client(n)}return this.completeDevToolsRequest(n,e),this.removeToken(),this.config.onUnauthorized&&this.config.onUnauthorized(),Promise.reject(e)}if(e.response?.status===401&&l)return this.completeDevToolsRequest(n,e),Promise.reject(e);if(vt.isIdentityRequired(e.response?.status,e.response?.data)){this.completeDevToolsRequest(n,e);const c={},d=n?.headers??{};for(const[S,v]of Object.entries(d))typeof v=="string"&&(c[S]=v);let f;n?.data!==void 0&&n?.data!==null&&(f=typeof n.data=="string"?n.data:JSON.stringify(n.data),c["Content-Type"]=c["Content-Type"]??"application/json");const g=n?.identity_target,m=await vt.handle(e.response.data,{headers:c,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(n,e),this.callOnError(e),Promise.reject(e)):(this.completeDevToolsRequest(n,e),e.response&&this.callOnError(e),Promise.reject(e))})}async get(e,n){return(await this.client.get(e,n)).data}async post(e,n,a){return(await this.client.post(e,n,a)).data}async put(e,n,a){return(await this.client.put(e,n,a)).data}async patch(e,n,a){return(await this.client.patch(e,n,a)).data}async delete(e,n){return(await this.client.delete(e,n)).data}getInstance(){return this.client}setOnUnauthorized(e){this.config.onUnauthorized=e}setOnError(e){this.config.onError=e}completeDevToolsRequest(e,n){if(!e?._devToolsRequestId)return;const a=Nd();if(!a?.isEnabled())return;const i=e._devToolsRequestId;e._devToolsRequestId=null,n.response?a.completeRequest(i,n.response.status,n.response.data):n.request?a.failRequest(i,n.message||"Network error"):a.failRequest(i,n.message||"Request error")}buildFullUrl(e){let n=e.url||"";if(e.baseURL&&!n.startsWith("http")&&(n=`${e.baseURL}${n.startsWith("/")?"":"/"}${n}`),e.params&&typeof e.params=="object"){const a=e.params,i=[];for(const[l,c]of Object.entries(a))if(c!=null)if(Array.isArray(c)){const d=l.endsWith("[]")?l:`${l}[]`;for(const f of c)i.push(`${encodeURIComponent(d)}=${encodeURIComponent(String(f))}`)}else i.push(`${encodeURIComponent(l)}=${encodeURIComponent(String(c))}`);i.length>0&&(n+=(n.includes("?")?"&":"?")+i.join("&"))}return n}callOnError(e){if(!this.config.onError)return;const n={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(n)}catch(a){tC.error("Error in onError handler:",a)}}}let Id=null;function Ir(){return Id||(Id=new nC),Id}const ho=ut("AuthManager");function ss(o,e,n,a){try{window.G7Core?.devTools?.trackAuthEvent?.(o,e,n,a)}catch{}}const Jl={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"}},_r=class _r{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",Jl.admin),this.config.set("user",Jl.user)}static getInstance(){return _r.instance||(_r.instance=new _r),_r.instance}on(e,n){this.eventHandlers.has(e)||this.eventHandlers.set(e,[]),this.eventHandlers.get(e).push(n)}emit(e,...n){const a=this.eventHandlers.get(e);a&&a.forEach(i=>i(...n))}isAuthenticated(){return this.state.isAuthenticated}getUser(){return this.state.user}getAuthType(){return this.state.type}async checkAuth(e){const n=Ir();if(!n.getToken())return this.clearState(),!1;const i=this.config.get(e);if(!i)return ho.error(`Unknown auth type: ${e}`),!1;try{const l=await n.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(n){return ho.warn(`Preload auth failed for type ${e}:`,n),!1}}async login(e,n,a){const i=Ir();if(!this.config.get(e))throw new Error(`Unknown auth type: ${e}`);const c=e==="admin"?Jl.admin.loginEndpoint:Jl.user.loginEndpoint;try{const d=a?.headers?{headers:a.headers}:void 0,f=await i.post(c,n,d);if(f.success&&f.data){i.setToken(f.data.token);const g=f.data.user.language,m=localStorage.getItem(_r.LOCALE_STORAGE_KEY),b=g&&g!==m;if(g)try{localStorage.setItem(_r.LOCALE_STORAGE_KEY,g)}catch(S){ho.warn("Failed to save user language to localStorage:",S)}return this.state={isAuthenticated:!0,user:f.data.user,type:e},this.emit("login",this.state),this.emit("authStateChange",this.state),ss("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,ss("login",!1,g.message,{type:e,status:d.response?.status}),g}}async logout(){const e=Ir(),n=this.state.type?this.config.get(this.state.type):null;try{n&&await e.post(n.logoutEndpoint)}catch(a){ho.warn("Logout API call failed:",a)}finally{e.removeToken();const a={...this.state};if(this.clearState(),this.emit("logout",a),this.emit("authStateChange",this.state),ss("logout",!0,void 0,{previousType:a.type}),n&&a.type){const i=window.location.pathname+window.location.search;window.location.href=this.getLoginRedirectUrl(a.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 n=this.config.get(e);if(!n)return!1;const a=Ir();try{const i=await a.post(n.refreshEndpoint);return i.success&&i.data?.token?(a.setToken(i.data.token),this.emit("tokenRefreshed"),ss("token-refresh",!0,void 0,{type:e}),!0):(ss("token-refresh",!1,"No token in response",{type:e}),!1)}catch(i){return ho.error("Token refresh failed:",i),ss("token-refresh",!1,i instanceof Error?i.message:"Unknown error",{type:e}),!1}}getLoginRedirectUrl(e,n,a){const i=this.config.get(e);if(!i)return"/login";const l=encodeURIComponent(n);let c=`${i.loginPath}?redirect=${l}`;return a&&(c+=`&reason=${encodeURIComponent(a)}`),c}updateConfig(e,n){if(n.loginPath!==void 0){const i=n.loginPath;if(!i.startsWith("/")||i.startsWith("//"))throw new Error(`AuthManager.updateConfig: loginPath must be a same-origin path starting with '/' (got: ${i})`)}const a=this.config.get(e);a&&this.config.set(e,{...a,...n})}getRedirectUrl(e){const a=this.config.get(e)?.defaultPath||"/",l=new URLSearchParams(window.location.search).get("redirect");if(l)try{const c=decodeURIComponent(l);if(c.startsWith("/"))return c}catch{}return a}getConfig(e){return this.config.get(e)}clearState(){this.state={isAuthenticated:!1,user:null,type:null}}static resetInstance(){_r.instance=null}};$(_r,"instance"),$(_r,"LOCALE_STORAGE_KEY","g7_locale");let yr=_r;const rm={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}}"}}},Qr={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,n){if(o.handler!=="showErrorPage"||o.params?.errorCode!==void 0)return o;const a=typeof e=="string"?parseInt(e,10):e,i=isNaN(a)?n:a;return i===void 0?o:{...o,params:{...o.params,errorCode:i}}}},br=ut("ErrorHandlingResolver"),Ma=class Ma{constructor(){$(this,"templateErrorHandling",null);$(this,"layoutErrorHandling",null);$(this,"executeAction",null)}static getInstance(){return Ma.instance||(Ma.instance=new Ma),Ma.instance}static resetInstance(){Ma.instance=null}setTemplateConfig(e){this.templateErrorHandling=e,br.log("Template config set:",e)}setLayoutConfig(e){this.layoutErrorHandling=e,br.log("Layout config set:",e)}setActionExecutor(e){this.executeAction=e}resolve(e,n={}){const{errorHandling:a,onError:i}=n;br.log("Resolving error:",e,{hasActionErrorHandling:!!a,hasActionOnError:!!i,hasLayoutConfig:!!this.layoutErrorHandling,hasTemplateConfig:!!this.templateErrorHandling});let l=Qr.findHandler(a,e);if(l){const c=this.getMatchedKey(a,e);return{handler:Qr.injectErrorCode(l,c,e),level:"action",matchedKey:c}}if(i){const c=Qr.normalizeOnError(i);if(c.length>0)return{handler:c.length===1?c[0]:{handler:"sequence",actions:c},level:"action",matchedKey:"onError"}}if(l=Qr.findHandler(this.layoutErrorHandling||void 0,e),l){const c=this.getMatchedKey(this.layoutErrorHandling,e);return{handler:Qr.injectErrorCode(l,c,e),level:"layout",matchedKey:c}}if(l=Qr.findHandler(this.templateErrorHandling||void 0,e),l){const c=this.getMatchedKey(this.templateErrorHandling,e);return{handler:Qr.injectErrorCode(l,c,e),level:"template",matchedKey:c}}if(l=Qr.findHandler(rm,e),l){const c=this.getMatchedKey(rm,e);return{handler:Qr.injectErrorCode(l,c,e),level:"system",matchedKey:c}}return{handler:null,level:null,matchedKey:null}}async execute(e,n){if(!this.executeAction){br.error("Action executor is not set");return}br.log("Executing handler:",e.handler,{errorContext:n});try{return await this.executeAction(e,{error:n})}catch(a){throw br.error("Failed to execute handler:",a),a}}async resolveAndExecute(e,n,a={}){const i=this.resolve(e,a);if(br.log("Resolve result:",{errorCode:e,handler:i.handler?.handler,level:i.level,matchedKey:i.matchedKey}),!i.handler)return br.warn("No handler found for error:",e),{handled:!1};try{return{handled:!0,result:await this.execute(i.handler,n)}}catch(l){return br.error("Handler execution failed:",l),{handled:!1}}}getMatchedKey(e,n){return e[n]?n:e[String(n)]?String(n):"default"}clearLayoutConfig(){this.layoutErrorHandling=null,br.log("Layout config cleared")}clearAllConfig(){this.templateErrorHandling=null,this.layoutErrorHandling=null,br.log("All config cleared")}getConfigStatus(){return{hasTemplate:this.templateErrorHandling!==null,hasLayout:this.layoutErrorHandling!==null,hasExecutor:this.executeAction!==null}}};$(Ma,"instance",null);let Hd=Ma;function vr(){return Hd.getInstance()}var zd={exports:{}},go={};var am;function rC(){if(am)return go;am=1;var o=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(a,i,l){var c=null;if(l!==void 0&&(c=""+l),i.key!==void 0&&(c=""+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:a,key:c,ref:i!==void 0?i:null,props:l}}return go.Fragment=e,go.jsx=n,go.jsxs=n,go}var im;function aC(){return im||(im=1,zd.exports=rC()),zd.exports}var dt=aC();const iC=Xr({__proto__:null,default:Jr(dt)},[dt]),jd=ut("ParentContextProvider"),sm=N.createContext(null);let Ql=null;function Ud(){Ql?(jd.log("[triggerModalParentUpdate] 모달 부모 컨텍스트 업데이트 트리거"),Ql()):jd.warn("[triggerModalParentUpdate] Provider가 아직 마운트되지 않음")}const om=({children:o})=>{const[e,n]=N.useState(0),a=N.useRef(!0),i=N.useCallback(()=>{const c=window.__g7LayoutContextStack||[];return c[c.length-1]?.dataContext},[]);N.useEffect(()=>(a.current=!0,Ql=()=>{a.current&&(n(c=>c+1),jd.log("[ParentContextProvider] 버전 업데이트됨"))},()=>{a.current=!1,Ql=null}),[]);const l={version:e,getParentDataContext:i};return dt.jsx(sm.Provider,{value:l,children:o})};function sC(){return N.useContext(sm)}const z=ut("ActionDispatcher");function oC(o,e,n,a){return n||(np(o)||od(o)?"$t:core.errors.network_request_failed":a||`Failed to execute action: ${e}`)}const lm=new Set(["navigate","navigateBack","navigateForward","replaceUrl","refresh","logout"]),lC=new Set(["redirect"]);function qn(){try{return window.G7Core?.devTools}catch{return}}class jt extends Error{constructor(n,a,i){super(n);$(this,"action");$(this,"originalError");$(this,"unknownHandler",!1);this.action=a,this.originalError=i,this.name="ActionError"}}const ps=class ps{constructor(e={},n,a){$(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 xn,this.translationEngine=n,this.translationContext=a,this.defaultContext=e,this.registerDefaultHandlers(),this.setupErrorHandling()}setGlobalHeaders(e){this.globalHeaders=e||[]}setNamedActions(e){this.namedActions=e||{};const n=qn();n?.isEnabled?.()&&n.setNamedActionDefinitions?.(this.namedActions),z.log("[setNamedActions] registered:",Object.keys(this.namedActions))}getNamedActions(){return this.namedActions}setPreviewMode(e){this.previewMode=e,z.log("Preview mode:",e?"enabled":"disabled")}isPreviewMode(){return this.previewMode}static getPreviewSuppressedHandlers(){return lm}static getPreviewSuppressedLayoutFeatures(){return lC}resolveActionRef(e){if(!e.actionRef)return e;const n=this.namedActions[e.actionRef];if(!n)return z.warn(`[resolveActionRef] named action not found: "${e.actionRef}"`),e;const a=qn();a?.isEnabled?.()&&a.trackNamedActionRef?.({actionRefName:e.actionRef,resolvedHandler:n.handler,timestamp:Date.now()});const{actionRef:i,type:l,key:c,event:d,...f}=e,g={...n,...Object.fromEntries(Object.entries(f).filter(([,m])=>m!==void 0)),type:l??n.type};return c!==void 0&&(g.key=c),d!==void 0&&(g.event=d),g}matchesPattern(e,n){if(n==="*")return!0;const a=n.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${a}$`).test(e)}getMatchingGlobalHeaders(e,n){const a={};for(const i of this.globalHeaders)this.matchesPattern(e,i.pattern)&&Object.entries(i.headers).forEach(([l,c])=>{const d=ns(c,n,{skipCache:!0});d!=null&&d!==""&&(a[l]=String(d))});return a}setupErrorHandling(){if(this.errorHandlingSetup)return;vr().setActionExecutor(async(n,a)=>{const i={type:"click",handler:n.handler,target:n.target,params:n.params,actions:n.actions},l={data:{...this.defaultContext.data,error:a.error}};return await this.dispatchAction(i,l)}),this.errorHandlingSetup=!0}registerDefaultHandlers(){this.registerHandler("refetchDataSource",async(n,a)=>{const i=n.params?.dataSourceId,l=n.params?.sync;if(!i){z.warn("refetchDataSource: dataSourceId is required");return}if(typeof window<"u"&&window.G7Core?.dataSource?.refetch){const c=window.G7Core?.state?.get?.()||{},d={...a.state?._global,...c},f=window.G7Core?.state?.getLocal?.()||{},g=a.data?._local||a.state||{},m={...f,...g},b=a.isolatedContext?.state;z.log("[refetchDataSource] localStateOverride:",m),await window.G7Core.dataSource.refetch(i,{...l?{sync:!0}:{},...d?{globalStateOverride:d}:{},...m?{localStateOverride:m}:{},...b?{isolatedStateOverride:b}:{}})}else z.warn("refetchDataSource: G7Core.dataSource.refetch is not available")}),this.registerHandler("appendDataSource",async(n,a)=>{const{dataSourceId:i,dataPath:l,newData:c}=n.params||{};if(!i){z.warn("appendDataSource: dataSourceId is required");return}if(c===void 0){z.warn("appendDataSource: newData is required");return}if(typeof window<"u"&&window.G7Core?.dataSource?.updateData){if(!Array.isArray(c)){z.warn("appendDataSource: newData must be an array, got:",typeof c,c);return}await window.G7Core.dataSource.updateData(i,l||null,c,"append")}else z.warn("appendDataSource: G7Core.dataSource.updateData is not available")}),this.registerHandler("updateDataSource",async(n,a)=>{const{dataSourceId:i,data:l,merge:c=!1}=n.params||{};if(!i){z.warn("updateDataSource: dataSourceId is required");return}if(l===void 0){z.warn("updateDataSource: data is required");return}typeof window<"u"&&window.G7Core?.dataSource?.set?(z.log(`[updateDataSource] Updating dataSource '${i}' with:`,l),window.G7Core.dataSource.set(i,l,{merge:c})):z.warn("updateDataSource: G7Core.dataSource.set is not available")}),this.registerHandler("scrollIntoView",async(n,a)=>{const{selector:i,behavior:l="smooth",block:c="nearest",inline:d="nearest",waitForElement:f=!1,timeout:g=2e3,delay:m=0,retryCount:b=0,retryInterval:S=50,scrollContainer:v}=n.params||{};if(!i){z.warn("scrollIntoView: selector is required");return}if(typeof window>"u"||typeof document>"u"){z.warn("scrollIntoView: window/document is not available");return}let _=null;if(f){if(_=await new Promise(A=>{const x=document.querySelector(i);if(x){A(x);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})}),!_){z.warn(`scrollIntoView: element not found for selector "${i}" after ${g}ms timeout`);return}}else{m>0&&await new Promise(x=>setTimeout(x,m)),_=document.querySelector(i);let A=0;for(;!_&&AsetTimeout(x,S)),_=document.querySelector(i),A++;if(!_){z.warn(`scrollIntoView: element not found for selector "${i}" after ${A+1} attempts`);return}}if(v){const A=document.querySelector(v);if(!A){z.warn(`scrollIntoView: container not found for selector "${v}"`);return}const x=_.getBoundingClientRect(),L=A.getBoundingClientRect(),M=x.top-L.top+A.scrollTop,R=M+x.height;let D;switch(c){case"start":D=M;break;case"center":D=M-A.clientHeight/2+x.height/2;break;case"end":D=R-A.clientHeight;break;default:const B=x.topL.bottom;if(B)D=M;else if(q)D=R-A.clientHeight;else return;break}A.scrollTo({top:Math.max(0,D),behavior:l});return}_.scrollIntoView({behavior:l,block:c,inline:d})}),this.registerHandler("reloadExtensions",async(n,a)=>{if(typeof window>"u"){z.warn("reloadExtensions: window is not available");return}const i=window.__templateApp;if(!i){z.warn("reloadExtensions: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState()}catch(d){throw z.error("reloadExtensions: reloadExtensionState failed",d),d}else z.warn("reloadExtensions: TemplateApp.reloadExtensionState unavailable");const{moduleInfo:l,pluginInfo:c}=n.params||{};if(l)try{await this.executeAction({handler:"reloadModuleHandlers",params:n.params},a)}catch(d){z.error("reloadExtensions: reloadModuleHandlers failed",d)}if(c)try{await this.executeAction({handler:"reloadPluginHandlers",params:n.params},a)}catch(d){z.error("reloadExtensions: reloadPluginHandlers failed",d)}z.log("reloadExtensions: done")}),this.registerHandler("reloadRoutes",async(n,a)=>{if(typeof window>"u"){z.warn("reloadRoutes: window is not available");return}const i=window.__templateApp;if(!i){z.warn("reloadRoutes: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState(),z.log("reloadRoutes: delegated to reloadExtensionState")}catch(l){throw z.error("reloadRoutes: Failed to reload routes",l),l}else{const l=i.getRouter?.();l&&(await l.loadRoutes(),z.log("reloadRoutes: Routes reloaded (legacy fallback)"))}}),this.registerHandler("refresh",async(n,a)=>{if(typeof window>"u"){z.warn("refresh: window is not available");return}const i=Number(n.params?.delayMs??0);i>0&&await new Promise(l=>setTimeout(l,i)),window.location.reload()}),this.registerHandler("remount",async(n,a)=>{const{componentId:i}=n.params||{};if(!i){z.warn("remount: componentId parameter is required");return}if(!this.globalStateUpdater){z.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}}),z.log(`remount: ${i} key incremented to ${f+1}`)}),this.registerHandler("reloadTranslations",async(n,a)=>{if(typeof window>"u"){z.warn("reloadTranslations: window is not available");return}const i=window.__templateApp;if(!i){z.warn("reloadTranslations: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState(),z.log("reloadTranslations: delegated to reloadExtensionState")}catch(l){throw z.error("reloadTranslations: Failed to reload translations",l),l}}),this.registerHandler("reloadModuleHandlers",async(n,a)=>{if(typeof window>"u"){z.warn("reloadModuleHandlers: window is not available");return}const{moduleInfo:i,action:l}=n.params||{};if(!i){z.warn("reloadModuleHandlers: moduleInfo is required");return}const c=i.data||i;if(!c.identifier){z.warn("reloadModuleHandlers: moduleInfo with identifier is required");return}if(!l||l!=="add"&&l!=="remove"){z.warn('reloadModuleHandlers: action must be "add" or "remove"');return}const d=window.G7Config;if(!d){z.warn("reloadModuleHandlers: G7Config not available");return}const f=c.identifier;try{if(l==="add"){if(c.assets&&(d.moduleAssets=d.moduleAssets||{},d.moduleAssets[f]=c.assets,z.log(`reloadModuleHandlers: Added assets for ${f}`),c.assets.js)){const g=c.assets.js,m=`module-${f}`;if(document.getElementById(m)){z.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((S,v)=>{b.onload=()=>{z.log(`reloadModuleHandlers: Script loaded successfully for ${f}`),S()},b.onerror=()=>{z.error(`reloadModuleHandlers: Failed to load script for ${f}`),v(new Error(`Failed to load module script: ${g}`))},document.head.appendChild(b)}),c.assets.css){const S=c.assets.css,v=`module-css-${f}`;if(!document.getElementById(v)){const _=document.createElement("link");_.id=v,_.rel="stylesheet",_.href=S,document.head.appendChild(_),z.log(`reloadModuleHandlers: CSS loaded for ${f}`)}}}}else if(l==="remove"){d.moduleAssets&&d.moduleAssets[f]&&(delete d.moduleAssets[f],z.log(`reloadModuleHandlers: Removed assets for ${f}`));const g=`module-${f}`,m=document.getElementById(g);m&&(m.remove(),z.log(`reloadModuleHandlers: Removed script for ${f}`));const b=`module-css-${f}`,S=document.getElementById(b);S&&(S.remove(),z.log(`reloadModuleHandlers: Removed CSS for ${f}`))}}catch(g){throw z.error(`reloadModuleHandlers: Failed to ${l} module assets`,g),g}}),this.registerHandler("reloadPluginHandlers",async(n,a)=>{if(typeof window>"u"){z.warn("reloadPluginHandlers: window is not available");return}const{pluginInfo:i,action:l}=n.params||{};if(!i){z.warn("reloadPluginHandlers: pluginInfo is required");return}const c=i.data||i;if(!c.identifier){z.warn("reloadPluginHandlers: pluginInfo with identifier is required");return}if(!l||l!=="add"&&l!=="remove"){z.warn('reloadPluginHandlers: action must be "add" or "remove"');return}const d=window.G7Config;if(!d){z.warn("reloadPluginHandlers: G7Config not available");return}const f=c.identifier;try{if(l==="add"){if(c.assets&&(d.pluginAssets=d.pluginAssets||{},d.pluginAssets[f]=c.assets,z.log(`reloadPluginHandlers: Added assets for ${f}`),c.assets.js)){const g=c.assets.js,m=`plugin-${f}`;if(document.getElementById(m)){z.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((S,v)=>{b.onload=()=>{z.log(`reloadPluginHandlers: Script loaded successfully for ${f}`),S()},b.onerror=()=>{z.error(`reloadPluginHandlers: Failed to load script for ${f}`),v(new Error(`Failed to load plugin script: ${g}`))},document.head.appendChild(b)}),c.assets.css){const S=c.assets.css,v=`plugin-css-${f}`;if(!document.getElementById(v)){const _=document.createElement("link");_.id=v,_.rel="stylesheet",_.href=S,document.head.appendChild(_),z.log(`reloadPluginHandlers: CSS loaded for ${f}`)}}}}else if(l==="remove"){d.pluginAssets&&d.pluginAssets[f]&&(delete d.pluginAssets[f],z.log(`reloadPluginHandlers: Removed assets for ${f}`));const g=`plugin-${f}`,m=document.getElementById(g);m&&(m.remove(),z.log(`reloadPluginHandlers: Removed script for ${f}`));const b=`plugin-css-${f}`,S=document.getElementById(b);S&&(S.remove(),z.log(`reloadPluginHandlers: Removed CSS for ${f}`))}}catch(g){throw z.error(`reloadPluginHandlers: Failed to ${l} plugin assets`,g),g}});let e=!1;this.registerHandler("showErrorPage",async(n,a)=>{if(e){z.log("showErrorPage: Already active, skipping duplicate call");return}if(e=!0,typeof window>"u"){e=!1,z.warn("showErrorPage: window is not available");return}const i=window.__templateApp;if(!i){e=!1,z.warn("showErrorPage: TemplateApp not initialized");return}const l=i.getErrorPageHandler?.();if(!l){e=!1,z.warn("showErrorPage: ErrorPageHandler not available");return}const c=n.params?.errorCode||500,d=n.params?.target||"content";let f=n.params?.containerId;f||(f=d==="full"?"app":"main_content"),z.log("showErrorPage:",{errorCode:c,target:d,containerId:f});const g=(m,b=6e4)=>new Promise((S,v)=>{const _=document.getElementById(m);if(_){S(_);return}z.log(`showErrorPage: Waiting for container #${m}...`);let A;const x=new MutationObserver((L,M)=>{const R=document.getElementById(m);R&&(z.log(`showErrorPage: Container #${m} found`),M.disconnect(),clearTimeout(A),S(R))});x.observe(document.body,{childList:!0,subtree:!0}),A=setTimeout(()=>{x.disconnect(),v(new Error(`Container #${m} not found within ${b}ms`))},b)});try{await g(f);const m=vr(),b=m.layoutErrorHandling;m.clearLayoutConfig();try{await l.renderError(c,f)||z.warn(`showErrorPage: Failed to render error page for code ${c}`)}finally{m.setLayoutConfig(b)}}catch(m){throw z.error("showErrorPage: Error rendering error page:",m),m}finally{e=!1}}),this.registerHandler("emitEvent",async(n,a)=>{const i=n.params?.event,l=n.params?.data;if(!i){z.warn("emitEvent: event parameter is required");return}if(typeof window>"u"){z.warn("emitEvent: window is not available");return}const c=window.G7Core;if(!c?.componentEvent?.emit){z.warn("emitEvent: G7Core.componentEvent is not available");return}try{z.log(`emitEvent: Emitting "${i}"`,l);const d={...l,_context:{data:a.data,state:a.state}},f=await c.componentEvent.emit(i,d);if(!f||f.length===0?z.warn(`emitEvent: No listeners found for "${i}"`):z.log(`emitEvent: Event "${i}" completed with ${f.length} listener(s)`,f),this.globalStateUpdater){const g=(c?.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=a.state&&typeof a.state=="object"&&!Array.isArray(a.state)?a.state:g;window.__g7SequenceLocalSync={...b,_eventResult:m}}}catch(d){if(z.error(`emitEvent: Event "${i}" failed`,d),this.globalStateUpdater){const f=c?.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(n,a)=>{const{productId:i,field:l,value:c}=n.params||{};if(!i||!l){z.warn("updateProductField: productId and field are required");return}if(typeof window>"u"){z.warn("updateProductField: window is not available");return}const d=window.G7Core;if(!d?.state?.get||!this.globalStateUpdater){z.warn("updateProductField: G7Core.state or globalStateUpdater is not available");return}try{const f=d.state.get()||{},m=(f.products?.data?.data||[]).map(S=>S.id===i?{...S,[l]:c,_modified:!0}:S),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)}}),z.log(`updateProductField: Updated product ${i}, field: ${l}, value:`,c)}catch(f){throw z.error("updateProductField: Error updating product field",f),f}}),this.registerHandler("updateOptionField",async(n,a)=>{const{productId:i,optionId:l,field:c,value:d}=n.params||{};if(!i||!l||!c){z.warn("updateOptionField: productId, optionId and field are required");return}if(typeof window>"u"){z.warn("updateOptionField: window is not available");return}const f=window.G7Core;if(!f?.state?.get||!this.globalStateUpdater){z.warn("updateOptionField: G7Core.state or globalStateUpdater is not available");return}try{const g=f.state.get()||{},b=(g.products?.data?.data||[]).map(v=>{if(v.id===i&&v.options){const _=v.options.map(A=>A.id===l?{...A,[c]:d,_modified:!0}:A);return{...v,options:_,_modified:!0}}return v}),S=new Set(g._local?.modifiedProductIds||[]);S.add(i),this.globalStateUpdater({products:{...g.products,data:{...g.products?.data,data:b}},_local:{...g._local,modifiedProductIds:Array.from(S)}}),z.log(`updateOptionField: Updated product ${i} option ${l}, field: ${c}, value:`,d)}catch(g){throw z.error("updateOptionField: Error updating option field",g),g}}),this.registerHandler("setLocale",async(n,a)=>{const i=n.target;if(!i||typeof i!="string"){z.warn("setLocale: Invalid locale:",i);return}const l=window.__templateApp;if(l&&typeof l.changeLocale=="function")try{await l.changeLocale(i),z.log("setLocale: Locale changed to",i)}catch(c){z.error("setLocale: Failed to change locale:",c),window.location.reload()}else{z.warn("setLocale: TemplateApp not found, falling back to page reload");try{localStorage.setItem("g7_locale",i)}catch{}window.location.reload()}}),this.registerHandler("suppress",async()=>{z.log("suppress: Error intentionally suppressed")}),this.registerBuiltInHandlerMetadata()}registerBuiltInHandlerMetadata(){const e=qn();if(!e?.isEnabled())return;const n=[{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 a of n)e.trackHandlerRegistration(a.name,"built-in",a.description)}createHandler(e,n,a){z.log("createHandler called for:",e.handler,e.type);const i=window.__g7DevTools,l=Date.now(),c=a?.state?{...a.state}:null,d=`handler_${e.handler}_${l}`;return async f=>{if(z.log("Handler invoked for:",e.handler,"event:",f.type),i?.isEnabled?.()&&c){const m=window.G7Core?.state?.getLocal?.()??a?.state??{},b=Date.now()-l;for(const S of Object.keys(c)){const v=c[S],_=m[S];v!==_&&b>100&&(i.trackStaleClosureWarning?.({type:"event-handler-stale",location:`createHandler(${e.handler})`,capturedPath:`_local.${S}`,capturedValue:v,capturedAt:l,currentValue:_,actionId:d,stackTrace:new Error().stack}),z.warn(`[Stale Closure] _local.${S} changed after handler creation:`,`captured="${v}" → current="${_}" (${b}ms ago)`))}}try{f.type!=="change"&&f.preventDefault();let g={};if(f.type==="submit"&&f.target instanceof HTMLFormElement){const S=f.target;new FormData(S).forEach((_,A)=>{g[A]=_})}const m={...this.defaultContext,data:{...n,form:g,_local:a?.state||{},$event:f},event:f,...a&&{state:a.state,setState:a.setState},isolatedContext:a?.isolatedContext};if(e.confirm){let S=this.resolveValue(e.confirm,m.data);if(this.translationEngine&&this.translationContext&&S.startsWith("$t:")&&(S=this.translationEngine.resolveTranslations(S,this.translationContext,m.data)),!confirm(S))return}const b=window.__g7ActionContext;window.__g7ActionContext={...a,data:m.data};try{await this.executeAction(e,m)}finally{window.__g7ActionContext=b}}catch(g){if(z.error("Action execution failed:",g),e.onError){const m=g instanceof jt&&g.originalError?g.originalError:g,b={...this.defaultContext,data:{...n,error:m,_local:a?.state||{},$event:f},event:f,...a&&{state:a.state,setState:a.setState}},S=Array.isArray(e.onError)?e.onError:[e.onError];for(const v of S)await this.executeAction(v,b)}}}}generateActionId(e,n){const a=e.handler,i=n||"no-target",l=Date.now(),c=Math.random().toString(36).substring(2,9);return`${a}_${i.replace(/[^a-zA-Z0-9]/g,"_")}_${l}_${c}`}async executeAction(e,n){if(e=this.resolveActionRef(e),typeof e.handler=="string"&&e.handler.includes("{{")){const f=this.evaluateExpression(e.handler,n.data);e={...e,handler:f==null?"":String(f)}}const a=qn(),i=a?.isEnabled()?`action_${Date.now()}_${Math.random().toString(36).substring(2,11)}`:void 0,l=performance.now();let c;if(i&&a&&a.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),context:this.sanitizeForDevTools({hasState:!!n.state,hasSetState:!!n.setState,dataKeys:n.data?Object.keys(n.data):[]}),startTime:l,status:"started"}),e.if!==void 0)try{const f=this.resolveValue(e.if,n.data),g=f===!0||f==="true"||f&&f!=="false"&&f!=="0"&&f!==!1;if(z.log("[executeAction] if condition result:",e.handler,g),!g)return i&&a&&a.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 z.error("[executeAction] if condition error:",e.handler,f),i&&a&&a.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,n.data);i&&(c=this.sanitizeForDevTools(f));const g=e.target?this.resolveValue(e.target,n.data):void 0;if(e.handler==="apiCall"&&n.setState){d=this.generateActionId(e,g);const b=n.state?.loadingActions||{};n.setState({loadingActions:{...b,[d]:!0}})}if(this.previewMode&&lm.has(e.handler))return z.warn(`Preview mode: "${e.handler}" suppressed`,g||f),i&&a&&a.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,n);break;case"navigateBack":m=await this.handleNavigateBack();break;case"navigateForward":m=await this.handleNavigateForward();break;case"openWindow":{const _=f.path||g;m=await this.handleOpenWindow(_,f);break}case"replaceUrl":{const _=f.path||g||window.location.pathname;m=await this.handleReplaceUrl(_,f);break}case"apiCall":if(e.onSuccess&&a?.isEnabled()&&i){const _=window.G7Core,A={};if(_?.state?.get){const x=_.state.get();A._global=x}n.state&&(A._local=n.state),a.registerStateCaptureForHandler?.(i,["_global","_local"],A)}const S=e.auth_mode??(e.auth_required?"required":"none"),v=e.identity_target?this.resolveParams(e.identity_target,n.data):void 0;m=await this.handleApiCall(g,f,n,S,v);break;case"login":m=await this.handleLogin(g,f,n);break;case"logout":m=await this.handleLogout(g,n);break;case"setState":z.log("[executeAction] setState resolvedParams:",f),m=await this.handleSetState(e.render!==void 0?{...f,__render:e.render}:f,n);break;case"setError":m=await this.handleSetError(g,f,n);break;case"openModal":m=await this.handleOpenModal(g,n);break;case"closeModal":m=await this.handleCloseModal(n);break;case"showAlert":m=await this.handleShowAlert(g,n);break;case"toast":m=await this.handleToast(f,n);break;case"switch":m=await this.handleSwitch(e,n);break;case"conditions":m=await this.handleConditions(e,n);break;case"sequence":m=await this.handleSequence(e,n);break;case"parallel":m=await this.handleParallel(e,n);break;case"startInterval":m=this.handleStartInterval(f,n);break;case"stopInterval":m=this.handleStopInterval(f);break;case"loadScript":m=await this.handleLoadScript(f,e,n);break;case"callExternal":m=await this.handleCallExternal(f,e,n);break;case"callExternalEmbed":m=await this.handleCallExternalEmbed(f,e,n);break;case"saveToLocalStorage":m=await this.handleSaveToLocalStorage(f,n);break;case"loadFromLocalStorage":m=await this.handleLoadFromLocalStorage(f,n);break;default:m=await this.handleCustomAction({...e,target:g,params:f},n);break}if(e.resultTo&&m!==void 0){const{target:b,key:S,merge:v}=e.resultTo,_=this.resolveValue(S,n.data),A=v==="replace"?"replace":v==="shallow"?"shallow":"deep";if(b==="_local"&&n.setState){const x=this.buildNestedUpdate(_,m),L=A!=="deep"?{...x,__mergeMode:A}:x;n.setState(L),z.log(`[resultTo] Saved to _local.${_} (merge=${A}):`,m)}else if(b==="_local"&&this.globalStateUpdater){const M=(window.G7Core?.state?.get()||{})._local||{},R=this.buildNestedUpdate(_,m);let D;A==="replace"?D=R:A==="shallow"?D={...M,...R}:D=this.deepMergeWithState(R,M),this.globalStateUpdater({_local:D}),z.log(`[resultTo] Saved to _local.${_} via globalStateUpdater (merge=${A}):`,m)}else if(b==="_global"&&this.globalStateUpdater){const x=this.buildNestedUpdate(_,m);this.globalStateUpdater(x),z.log(`[resultTo] Saved to _global.${_}:`,m)}else if(b==="_isolated"&&n.isolatedContext){const x=this.buildNestedUpdate(_,m);n.isolatedContext.mergeState(x,A),z.log(`[resultTo] Saved to _isolated.${_} (merge=${A}):`,m)}else z.warn(`[resultTo] Cannot save result: target=${b}, setState=${!!n.setState}, globalStateUpdater=${!!this.globalStateUpdater}, isolatedContext=${!!n.isolatedContext}`)}if(e.onSuccess){if(a?.isEnabled()&&i&&e.handler==="apiCall"){const v=window.G7Core,_={};v?.state?.get&&(_._global=v.state.get()),n.state&&(_._local=n.state),a.detectStaleClosure?.(i,`${e.handler} → onSuccess`,_,"callback-state-capture",i)}const b={...n,data:{...n.data,result:m,response:m}},S=Array.isArray(e.onSuccess)?e.onSuccess:[e.onSuccess];S.length>1?await this.handleSequence({handler:"sequence",type:"click",actions:S},b):S.length===1&&await this.executeAction(S[0],b)}return i&&a&&a.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),resolvedParams:c,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 jt?f:new jt(`Failed to execute action: ${e.handler}`,e,f instanceof Error?f:void 0),m=g.originalError?.response||{},b=m.data||{},S=g.originalError?.status||m.status||500;let v=oC(g.originalError??f,e.handler,b.message,g.message);this.translationEngine&&this.translationContext&&v.startsWith("$t:")&&(v=this.translationEngine.resolveTranslations(v,this.translationContext));const _={status:S,message:v,errors:b.errors||m.errors,data:b,statusText:g.originalError?.statusText,error_code:b.error_code??m.error_code};if(g.unknownHandler)throw z.warn(`Unknown action handler "${e.handler}" — skipped (extension not loaded?). Not surfaced to the user.`),g;const x=vr().resolve(S,{errorHandling:e.errorHandling,onError:e.onError});if(x.handler){if(a?.isEnabled()&&i&&e.handler==="apiCall"){const M=window.G7Core,R={};M?.state?.get&&(R._global=M.state.get()),n.state&&(R._local=n.state),a.detectStaleClosure?.(i,`${e.handler} → onError`,R,"callback-state-capture",i)}const L={...n,data:{...n.data,error:_}};try{const M={type:"click",handler:x.handler.handler,target:x.handler.target,params:x.handler.params,actions:x.handler.actions};return await this.executeAction(M,L),{success:!1,error:g}}catch(M){return z.error("Error executing error handler:",M),{success:!1,error:g}}}throw i&&a&&a.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),resolvedParams:c,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"&&n.setState&&d){const f=n.state?.loadingActions||{},{[d]:g,...m}=f;n.setState({loadingActions:m})}}}async handleNavigate(e,n,a){let i=e;if(n.query||n.mergeQuery===!0)if(n.mergeQuery===!0)i=this.buildMergedQueryPath(e,n.query??{});else{const c=new URLSearchParams;for(const[f,g]of Object.entries(n.query))if(g!=null&&g!=="")if(Array.isArray(g)){const m=f.endsWith("[]")?f:`${f}[]`;for(const b of g)b!=null&&b!==""&&c.append(m,String(b))}else c.set(f,String(g));const d=c.toString();d&&(i=`${e}?${d}`)}if(z.log("handleNavigate:",{target:e,params:n,finalPath:i,replace:n.replace,windowLocationSearch:window.location.search}),n.replace===!0){const c=window.G7Core;if(c?.updateQueryParams){const d=typeof n.transition_overlay_target=="string"?n.transition_overlay_target:void 0;await c.updateQueryParams(i,d?{transitionOverlayTarget:d}:void 0),z.log("handleNavigate: Used updateQueryParams for replace mode",d?{transitionOverlayTarget:d}:void 0),this.applyScrollOption(n.scroll,n.scrollBehavior,"top");return}z.warn("handleNavigate: G7Core.updateQueryParams not available, falling back to React Router")}const l=this.resolveNavigateFallbackAction(i,n);if(l){z.warn(`handleNavigate: No route matched, falling back to "${l.handler}"`),await this.dispatchAction({type:"click",handler:l.handler,params:l.params},a),this.applyScrollOption(n.scroll,n.scrollBehavior,"top");return}if(!a.navigate)throw new jt("Navigate function is not provided in context");a.navigate(i,{replace:n.replace===!0}),this.applyScrollOption(n.scroll,n.scrollBehavior,"top")}resolveNavigateFallbackAction(e,n){const a=n.fallback;if(a===!1||n.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 c=e.split("?")[0];return l.match(c)?null:this.resolveNavigateFallback(a,e,n)}resolveNavigateFallback(e,n,a){return e==null?{handler:"openWindow",params:{path:n,target:"_self"}}:typeof e=="string"?{handler:e,params:{path:n}}:typeof e=="object"&&typeof e.handler=="string"?{handler:e.handler,params:{path:n,...e.params||{}}}:(z.warn("resolveNavigateFallback: unrecognized fallback option, using openWindow",e),{handler:"openWindow",params:{path:n,target:"_blank"}})}applyScrollOption(e,n,a){const i=e===void 0?a:e;if(i==="preserve")return;const l=n==="smooth"?"smooth":"instant",c=b=>{if(typeof b!="object"||b===null)return!1;const S=b;return"container"in S||"to"in S||"block"in S||"offset"in S},d=(b,S,v=0)=>{b===window?window.scrollTo({top:S,left:v,behavior:l}):b.scrollTo({top:S,left:v,behavior:l})},f=(b,S,v,_)=>{if(S===window){b.scrollIntoView({behavior:l,block:v}),_&&window.scrollBy({top:-_,left:0,behavior:l});return}const A=S,x=b.getBoundingClientRect(),L=A.getBoundingClientRect(),M=A.scrollTop+(x.top-L.top);let R;v==="center"?R=M-(A.clientHeight-b.clientHeight)/2:v==="end"?R=M-(A.clientHeight-b.clientHeight):R=M,R-=_,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(v=>{if(v.scrollTop===0&&v.scrollLeft===0)return;const _=window.getComputedStyle(v),A=_.overflowY,x=_.overflowX;(A==="auto"||A==="scroll"||x==="auto"||x==="scroll")&&v.scrollTo({top:0,left:0,behavior:l})})},m=()=>{try{if(c(i)){const b=i,S=b.block??"start",v=typeof b.offset=="number"?b.offset:0;let _=window;if(typeof b.container=="string"&&b.container.length>0){const x=document.querySelector(b.container);if(!x){z.warn(`applyScrollOption: container not found: ${b.container}`);return}_=x}const A=b.to??"top";if(A==="top"){_===window?g():d(_,0);return}if(typeof A=="number"){d(_,A-v);return}if(typeof A=="object"&&A!==null&&("x"in A||"y"in A)){const{x=0,y:L=0}=A;d(_,L-v,x);return}if(typeof A=="string"&&(A.startsWith("#")||A.startsWith("."))){const x=document.querySelector(A);x?f(x,_,S,v):z.warn(`applyScrollOption: target element not found: ${A}`);return}z.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:S=0}=i;window.scrollTo({top:S,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){z.warn("applyScrollOption: failed to apply scroll",b)}};typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame(m):m()}async handleOpenWindow(e,n){let a=e;if(n.query){const l=new URLSearchParams;for(const[d,f]of Object.entries(n.query))f!=null&&f!==""&&l.set(d,String(f));const c=l.toString();c&&(a=`${e}?${c}`)}const i=n.target==="_self"?"_self":"_blank";z.log("handleOpenWindow:",{target:e,params:n,finalPath:a,windowTarget:i}),i==="_self"?window.location.assign(a):window.open(a,"_blank")}async handleNavigateBack(){z.log("handleNavigateBack"),window.history.back()}async handleNavigateForward(){z.log("handleNavigateForward"),window.history.forward()}async handleReplaceUrl(e,n){let a=e;if(n.query||n.mergeQuery===!0)if(n.mergeQuery===!0)a=this.buildMergedQueryPath(e,n.query??{});else{const i=new URLSearchParams;for(const[c,d]of Object.entries(n.query))if(d!=null&&d!=="")if(Array.isArray(d)){const f=c.endsWith("[]")?c:`${c}[]`;for(const g of d)g!=null&&g!==""&&i.append(f,String(g))}else i.set(c,String(d));const l=i.toString();l&&(a=`${e}?${l}`)}z.log("handleReplaceUrl:",{target:e,params:n,finalPath:a}),window.history.replaceState(null,"",a),this.applyScrollOption(n.scroll,n.scrollBehavior,"preserve")}buildMergedQueryPath(e,n){const a=new URLSearchParams(window.location.search);for(const[c,d]of Object.entries(n))if(d==null||d==="")a.delete(c);else if(Array.isArray(d)){const f=c.endsWith("[]")?c:`${c}[]`;a.delete(c),a.delete(f);for(const g of d)g!=null&&g!==""&&a.append(f,String(g))}else a.set(c,String(d));const i=a.toString(),l=e.split("?")[0];return i?`${l}?${i}`:l}async ensureCsrfToken(){try{await fetch("/sanctum/csrf-cookie",{credentials:"include"})}catch(e){throw new jt("Failed to fetch CSRF token",void 0,e instanceof Error?e:void 0)}}getCsrfTokenFromCookie(){const a=`; ${document.cookie}`.split("; XSRF-TOKEN=");if(a.length===2){const i=a.pop()?.split(";").shift();return i?decodeURIComponent(i):null}return null}buildQueryString(e){const n=new URLSearchParams;for(const[a,i]of Object.entries(e))if(!(i==null||i===""))if(Array.isArray(i))for(const l of i)l!=null&&l!==""&&n.append(`${a}[]`,String(l));else typeof i=="object"?n.append(a,JSON.stringify(i)):n.append(a,String(i));return n.toString()}async handleEnsureIdentityVerified(e){const n=typeof e.purpose=="string"?e.purpose:"sensitive_action",a=e.target&&typeof e.target=="object"?e.target:void 0;return await vt.handle({success:!1,error_code:"identity_verification_required",message:"",verification:{policy_key:e.policy_key??"",purpose:n,provider_id:e.provider_id??null,render_hint:e.render_hint??null,return_request:null}},void 0,a)!==null}handleResolveIdentityChallenge(e){const n=typeof e.result=="string"?e.result:"cancelled";let a;switch(n){case"verified":{const i=typeof e.token=="string"?e.token:"";if(!i){z.warn("resolveIdentityChallenge: result=verified 인데 token 이 비어있습니다. failed 로 강등합니다."),a={status:"failed",failureCode:"MISSING_TOKEN"};break}a={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){z.warn("resolveIdentityChallenge: result=pending 인데 pollUrl/expiresAt 누락 — failed 로 강등합니다."),a={status:"failed",failureCode:"MALFORMED_PENDING"};break}a={status:"pending",pollUrl:i,pollIntervalMs:typeof e.pollIntervalMs=="number"?e.pollIntervalMs:void 0,expiresAt:l};break}case"failed":a={status:"failed",failureCode:typeof e.failureCode=="string"?e.failureCode:"UNKNOWN",reason:typeof e.reason=="string"?e.reason:void 0};break;default:a={status:"cancelled"};break}return vt.resolveDeferred(a),!0}async handleApiCall(e,n,a,i="none",l){const{method:c="GET",body:d,headers:f,contentType:g}=n;c!=="GET"&&c!=="HEAD"&&await this.ensureCsrfToken();const m=this.getCsrfTokenFromCookie();let b={};if(i==="required"||i==="optional"){const K=Ir().getToken();K&&(b={Authorization:`Bearer ${K}`})}let S=e;const v=n.query||(c==="GET"?d:null);if(v&&typeof v=="object"){const P=this.buildQueryString(v);if(P){const K=e.includes("?")?"&":"?";S=`${e}${K}${P}`}}const _=window.G7Core?.state?.getGlobal?.()||a.state?._global||{},A=window.G7Core?.state?.getLocal?.()||a.state?._local||{},x={_global:_,_local:A},L=this.getMatchingGlobalHeaders(e,x),M={};if(typeof window<"u"){const P=localStorage.getItem("g7_locale");P&&(M["Accept-Language"]=P)}const R=g==="multipart/form-data",D={method:c,headers:{...R?{}:{"Content-Type":"application/json"},Accept:"application/json",...M,...m&&{"X-XSRF-TOKEN":m},...b,...L,...f},credentials:"include"};if(d&&c!=="GET")if(R){const P=new FormData;for(const[K,ge]of Object.entries(d))ge instanceof File||ge instanceof Blob?P.append(K,ge):ge!=null&&P.append(K,typeof ge=="object"?JSON.stringify(ge):String(ge));D.body=P}else D.body=JSON.stringify(d);const B=qn();let q=null;B?.isEnabled()&&(q=B.trackRequest(S,c));try{let P=await fetch(S,D),K;try{K=await P.json()}catch{K=null}if(vt.isIdentityRequired(P.status,K)){const ge=await vt.handle(K,{body:D.body,headers:D.headers,credentials:D.credentials},l);if(ge){P=ge;try{K=await P.json()}catch{K=null}}}if(q&&B?.isEnabled()&&(B.completeRequest(q,P.status,K),q=null),!P.ok){const ge=K||{},Ee=new Error(ge.message||`API call failed: ${P.statusText}`);throw Ee.response=ge,Ee.status=P.status,Ee.statusText=P.statusText,new jt(ge.message||`API call failed: ${P.statusText}`,void 0,Ee)}return K}catch(P){throw q&&B?.isEnabled()&&B.failRequest(q,P instanceof Error?P.message:String(P)),P}}async handleLogin(e,n,a){const{body:i}=n;if(!i||!i.email||!i.password)throw new jt("Login requires email and password in body params");const l=e==="user"?"user":"admin",c=l==="admin"?"/api/auth/admin/login":"/api/auth/login",d=window.G7Core?.state?.getGlobal?.()||a.state?._global||{},f=window.G7Core?.state?.getLocal?.()||a.state?._local||{},g={_global:d,_local:f},m=this.getMatchingGlobalHeaders(c,g),b=yr.getInstance();try{const S=Object.keys(m).length>0?{headers:m}:void 0;return{user:await b.login(l,{email:i.email,password:i.password},S)}}catch(S){const v=S.message||"Login failed",_=new Error(v);throw _.response=S.response?.data||{},_.status=S.status||S.response?.status||500,new jt(v,void 0,_)}}async handleLogout(e,n){await yr.getInstance().logout()}async handleSetState(e,n){z.log("[handleSetState] START, params:",e);const{target:a="component",scope:i,merge:l,__render:c,...d}=e,f=qn(),g=window.G7Core;if(typeof a=="string"&&(a.startsWith("$parent.")||a.startsWith("$root.")))return this.handleParentScopeSetState(a,d,l,n);const m=n.state&&Object.keys(n.state).length>0?n.state:g?.state?.get()||{},b=a==="global"?"_global":a.startsWith("_local.")?a:"_local",S=b==="_global"?m._global:b.startsWith("_local.")?this.getNestedProperty(m._local||{},b.slice(7)):m._local,v=f?.isEnabled()?f.startStateChange(b,S,d,{actionId:n.actionId,handlerType:"setState",source:`target=${a}`}):void 0,_=l==="replace"?"replace":l==="shallow"?"shallow":"deep",A=_!=="deep"?{...d,__mergeMode:_,...v?{__setStateId:v}:{}}:{...d,...v?{__setStateId:v}:{}};if(a==="global"){if(!this.globalStateUpdater){z.warn("Global state updater is not set"),v&&f&&f.completeStateChange(v);return}const x=g?.state?.get()||{},{__setStateId:L,__mergeMode:M,...R}=A,D=_==="deep"?this.deepMergeWithState(R,x):R,B={...D,...v?{__setStateId:v}:{},..._!=="deep"?{__mergeMode:_}:{}};return z.log("setState global:",B),this.globalStateUpdater(B,{render:c}),v&&f&&setTimeout(()=>f.completeStateChange(v),0),{__target:"global",..._!=="deep"?{__mergeMode:_}:{},...D}}else if(a==="isolated"){const x=n.isolatedContext;if(x){const{__mergeMode:L,__setStateId:M,...R}=A;return x.mergeState(R,_),z.log("[handleSetState] isolated state updated:",R,"mergeMode:",_),v&&f&&setTimeout(()=>f.completeStateChange(v),0),{__target:"isolated",...R}}else if(z.warn('[handleSetState] isolated target used but no IsolatedStateContext found. Make sure the component has "isolatedState" attribute. Falling back to local state.'),n.setState){const M=window.__g7PendingLocalState||n.state||{},R=_==="deep"?this.deepMergeWithState(A,M):A;return n.setState(R),v&&f&&setTimeout(()=>f.completeStateChange(v),0),R}else throw v&&f&&f.completeStateChange(v),new jt("isolated target used but no IsolatedStateContext found and no setState function in context")}else if(a==="local"||a==="component"||a==="_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,...B}=A,q=_==="deep"?this.deepMergeWithState(B,M.state||{}):B;return z.log(`[handleSetState] scope=${i}: 타겟 컨텍스트에 상태 업데이트`,q),M.setState(q),v&&f&&setTimeout(()=>f.completeStateChange(v),0),q}}z.warn(`[handleSetState] scope=${i}: 레이아웃 컨텍스트 스택이 비어있습니다. current로 폴백합니다.`)}const x=n.setState&&!n._isDispatchFallbackContext;if(z.log("[handleSetState] isRealComponentContext:",x,"context.setState:",!!n.setState,"_isDispatchFallbackContext:",n._isDispatchFallbackContext),x){z.log("[handleSetState] Using COMPONENT setState path"),z.log("[handleSetState] resolvedPayload:",A),z.log("[handleSetState] context.state:",n.state),z.log("[handleSetState] mergeMode:",_);const M=window.__g7PendingLocalState||n.state||{},R=_==="deep"?this.deepMergeWithState(A,{}):A;z.log("[handleSetState] convertedPayload (변경 필드만, dot notation 변환):",R),n.setState(R);const D=_==="deep"?this.deepMergeWithState(A,M):_==="shallow"?{...n.state||{},...A}:A,{__mergeMode:B,__setStateId:q,...P}=D;window.__g7PendingLocalState=P,z.log("[handleSetState] __g7PendingLocalState updated:",P),this.globalStateUpdater&&(this.globalStateUpdater({_local:P},{render:!1}),z.log("[handleSetState] _global._local synced (render:false):",P));const{__mergeMode:K,__setStateId:ge,...Ee}=A;if(_==="replace")window.__g7ForcedLocalFields=Ee;else{const Se=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=this.deepMergeWithState(Ee,Se)}return z.log("[handleSetState] __g7ForcedLocalFields updated:",Ee),v&&f&&setTimeout(()=>f.completeStateChange(v),0),{__target:"local",...D}}else if(this.globalStateUpdater){z.log("[handleSetState] Using GLOBAL STATE UPDATER path for _local");const M=window.__g7PendingLocalState||m._local||{};z.log("[handleSetState] currentLocal (with pending):",M);const R=_==="deep"?this.deepMergeWithState(A,M):A;return z.log("[handleSetState] finalLocal (merged):",R),this.globalStateUpdater({_local:R},{render:c}),window.__g7PendingLocalState=R,z.log("[handleSetState] __g7PendingLocalState updated for globalStateUpdater path"),v&&f&&setTimeout(()=>f.completeStateChange(v),0),{__target:"local",...R}}else throw v&&f&&f.completeStateChange(v),new jt("setState function is not provided in context and globalStateUpdater is not set")}else if(a.startsWith("_local.")){const x=a.slice(7),{__mergeMode:L,__setStateId:M,...R}=A,D=R.value!==void 0?R.value:Object.values(R)[0];if(n.setState){const q=window.__g7PendingLocalState||n.state||{},P=this.createNestedUpdate(x,D,q),K={...q,...P};return n.setState(P),v&&f&&setTimeout(()=>f.completeStateChange(v),0),K}else throw v&&f&&f.completeStateChange(v),new jt("setState function is not provided in context")}else{if(!n.setState)throw v&&f&&f.completeStateChange(v),new jt("setState function is not provided in context");const L=window.__g7PendingLocalState||n.state||{},M=_==="deep"?this.deepMergeWithState(A,L):A;return n.setState(M),v&&f&&setTimeout(()=>f.completeStateChange(v),0),M}}async handleParentScopeSetState(e,n,a,i){const l=qn(),c=window.G7Core,d=a==="replace"?"replace":a==="shallow"?"shallow":"deep",f=e.startsWith("$parent."),g=f?"$parent.":"$root.",m=e.slice(g.length);let b,S;if(m==="_local"||m==="_global")b=m,S=void 0;else if(m.startsWith("_local."))b="_local",S=m.slice(7);else if(m.startsWith("_global."))b="_global",S=m.slice(8);else{z.warn(`[handleParentScopeSetState] 지원하지 않는 타겟 형식: ${e}. _local 또는 _global으로 시작해야 합니다.`);return}const v=window.__g7LayoutContextStack||[];if(v.length===0){z.warn(`[handleParentScopeSetState] 레이아웃 컨텍스트 스택이 비어있습니다. target=${e}`);return}const _=f?v[v.length-1]:v[0];if(!_){z.warn(`[handleParentScopeSetState] 타겟 컨텍스트를 찾을 수 없습니다. target=${e}`);return}const A=b==="_global"?_.state?._global:_.state?._local,x=l?.isEnabled()?l.startStateChange(e,A,n,{actionId:i.actionId,handlerType:"setState",source:`target=${e}`}):void 0,{__mergeMode:L,__setStateId:M,...R}=n;if(b==="_global"){if(!this.globalStateUpdater){z.warn("[handleParentScopeSetState] globalStateUpdater가 설정되지 않았습니다."),x&&l&&l.completeStateChange(x);return}const D=c?.state?.get()||{};if(S){const B=R.value!==void 0?R.value:Object.values(R)[0],q=this.createNestedUpdate(S,B,D),P={...D,...q};z.log(`[handleParentScopeSetState] ${e}: 전역 상태 중첩 경로 업데이트`,P),this.globalStateUpdater(P)}else{const B=d==="deep"?this.deepMergeWithState(R,D):R;z.log(`[handleParentScopeSetState] ${e}: 전역 상태 업데이트 (mergeMode=${d})`,B),this.globalStateUpdater(d!=="deep"?{...B,__mergeMode:d}:B)}return x&&l&&setTimeout(()=>l.completeStateChange(x),0),{__target:e,...R}}else{if(!_.setState){z.warn(`[handleParentScopeSetState] 타겟 컨텍스트에 setState가 없습니다. target=${e}`),x&&l&&l.completeStateChange(x);return}const D=_.state||{};if(S){const B=R.value!==void 0?R.value:Object.values(R)[0],q=this.createNestedUpdate(S,B,D),P={...D,...q};return z.log(`[handleParentScopeSetState] ${e}: 로컬 상태 중첩 경로 업데이트`,q),_.setState(q),_.state=P,_.dataContext&&(_.dataContext._local=P),Ud(),x&&l&&setTimeout(()=>l.completeStateChange(x),0),P}else{const B=d!=="deep"?{...R,__mergeMode:d}:R,q=d==="replace"?R:d==="shallow"?{...D,...R}:this.deepMergeWithState(R,D);return z.log(`[handleParentScopeSetState] ${e}: 로컬 상태 업데이트 (mergeMode=${d})`,q),_.setState(B),_.state=q,_.dataContext&&(_.dataContext._local=q),Ud(),x&&l&&setTimeout(()=>l.completeStateChange(x),0),q}}}deepMergeWithState(e,n){const a=["errors"];let i=e;if("..."in e){const c=e["..."];if(c&&typeof c=="object"&&!Array.isArray(c)){const{"...":d,...f}=e;i={...c,...f}}else{const{"...":d,...f}=e;i=f}}const l={...n};for(const[c,d]of Object.entries(i)){if(a.includes(c)){l[c]=d;continue}if(c.includes(".")&&c!=="..."){const f=this.createNestedUpdate(c,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[c]=d;continue}d!==null&&typeof d=="object"&&!Array.isArray(d)&&n[c]!==null&&typeof n[c]=="object"&&!Array.isArray(n[c])?l[c]=this.deepMergeWithState(d,n[c]):l[c]=d}return l}deepMergeInto(e,n,a){for(const[i,l]of Object.entries(n)){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]===a[i]&&(e[i]={...e[i]}),this.deepMergeInto(e[i],l,a[i]||{})):typeof l=="object"&&!Array.isArray(l)&&e[i]===void 0&&a[i]!==null&&typeof a[i]=="object"&&!Array.isArray(a[i])?e[i]={...a[i],...l}:e[i]=l}}createNestedUpdate(e,n,a){const i=e.split(".");if(i.length===1)return{[i[0]]:n};const l={};let c=l,d=a;for(let f=0;f{this.globalStateUpdater({_local:v})};m.push({state:b,setState:S,dataContext:{_local:b||n.data?._local,_global:l?n.data?._global:n.data?._global||i?.state?.get?.(),_computed:n.data?._computed}}),window.__g7LayoutContextStack=m,z.log(`[handleOpenModal] 레이아웃 컨텍스트 스택에 push, 스택 크기: ${m.length}, state:`,b,l?"(direct)":"(fallback via G7Core)")}else z.warn(`[handleOpenModal] 컨텍스트 스택에 push 실패 - setState: ${!!n.setState}, state: ${n.state!==void 0}, G7Core: ${!!i?.state?.getLocal}`);const f=[...a,e];this.globalStateUpdater({modalStack:f,activeModal:e});const g=qn();if(g?.isEnabled()){const m=a.length>0?a[a.length-1]:void 0;g.trackModalOpen?.({modalId:e,modalName:e,scopeType:"isolated",parentModalId:m,initialState:n.state?{...n.state}:{}})}}async handleCloseModal(e){if(!this.globalStateUpdater){z.warn("Global state updater is not set for closeModal");return}const n=e?.data?._global?.modalStack||[],a=n.length>0?n[n.length-1]:null,i=n.slice(0,-1),l=i.length>0?i[i.length-1]:null,c=window.__g7LayoutContextStack||[];if(c.length>0){const d=c[c.length-1];d&&(d.dataContext=void 0),c.pop(),window.__g7LayoutContextStack=c,z.log(`[handleCloseModal] 레이아웃 컨텍스트 스택에서 pop, 스택 크기: ${c.length}`)}if(a){const d=qn();d?.isEnabled()&&d.trackModalClose?.(a,e?.state)}this.globalStateUpdater({modalStack:i,activeModal:l})}async handleShowAlert(e,n){let a=e;this.translationEngine&&this.translationContext&&e.startsWith("$t:")&&(a=this.translationEngine.resolveTranslations(e,this.translationContext,n.data)),alert(a)}async handleToast(e,n){const{type:a="info",message:i,icon:l,duration:c}=e;if(a==="error"){const f=n.data?.error;if((f?.error_code==="identity_verification_required"||f?.data?.error_code==="identity_verification_required")&&vt.consumeDomainNoticeShown()){z.log("[Toast] IDV 도메인 안내 표출됨 — 중복 가드 토스트 1건 skip");return}}let d=i;if(this.translationEngine&&this.translationContext&&i?.startsWith("$t:")&&(d=this.translationEngine.resolveTranslations(i,this.translationContext,n.data)),this.globalStateUpdater){const g={id:`toast_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,type:a,message:d,...l&&{icon:l},...c&&{duration:c}},v=[...window.G7Core?.state?.get()?.toasts||[],g];this.globalStateUpdater({toasts:v})}else z.log(`[Toast ${a}] ${d}`)}async handleSwitch(e,n){const{cases:a}=e;if(!a){z.warn("switch handler requires cases property");return}const i=this.resolveParams(e.params,n.data);let l;if(i?.value!==void 0?(l=i.value,z.log("switch handler: using params.value as case key:",l)):(l=n.data?.$args?.[0],z.log("switch handler: using $args[0] as case key:",l)),l==null){if(a.default)return z.log("switch handler: case key is undefined, using default case"),await this.executeAction(a.default,n);z.warn("switch handler: case key is not defined and no default case");return}const c=String(l);let d=a[c];if(!d&&a.default&&(z.log(`switch handler: no case found for key "${c}", using default case`),d=a.default),!d){z.warn(`switch handler: no case found for key "${c}" and no default case`);return}return await this.executeAction(d,n)}async handleConditions(e,n){const{conditions:a}=e;if(!a||!Array.isArray(a)){z.warn("conditions handler requires conditions array");return}const i=n.data||{},l=yp(a,i,this.bindingEngine);if(!l.matched){z.log("conditions handler: no matching branch found");return}const c=a[l.branchIndex];if(z.log(`conditions handler: matched branch ${l.branchIndex}`),!c.then){z.warn('conditions handler: matched branch has no "then" action');return}return Array.isArray(c.then)?await this.handleSequence({...e,actions:c.then},n):await this.executeAction(c.then,n)}handleStartInterval(e,n){const a=typeof e.id=="string"?e.id:"",i=Number(e.intervalMs??1e3),l=Array.isArray(e.actions)?e.actions:[];if(a===""||!l.length||i<=0)return z.warn("startInterval requires non-empty id, positive intervalMs, and actions array"),{success:!1};const c=this.intervals.get(a);c&&(clearInterval(c),this.intervals.delete(a));const d=setInterval(()=>{for(const f of l)this.executeAction(f,n).catch(g=>{z.error(`[startInterval:${a}] tick action failed`,g)})},i);return this.intervals.set(a,d),{success:!0,id:a}}handleStopInterval(e){const n=typeof e.id=="string"?e.id:"";if(n==="")return z.warn("stopInterval requires id parameter"),{success:!1};const a=this.intervals.get(n);return a&&(clearInterval(a),this.intervals.delete(n)),{success:!0,id:n}}stopAllIntervals(){for(const e of this.intervals.values())clearInterval(e);this.intervals.clear()}async handleSequence(e,n){const a=e.actions||e.params?.actions;if(!a||!Array.isArray(a)||a.length===0)return z.warn("sequence handler requires non-empty actions array"),[];const i=qn(),l=i?.isEnabled()&&i.startSequenceExecution?.({eventType:e.type})||"";window.__g7SequenceLocalSync=void 0;const c=[];let d,f=n.state?{...n.state}:{},g=n.isolatedContext?.state?{...n.isolatedContext.state}:{},m=n.data?._computed||{};const b=window.G7Core,S=()=>({_global:b?.state?.get()||{},_local:{...f},_isolated:Object.keys(g).length>0?{...g}:void 0});for(let v=0;v0){const R={},D={...n.data,_local:f,_computed:R,$computed:R,_isolated:g};for(const[B,q]of Object.entries(M))if(typeof q=="string"){const P=q.trim();if(P.startsWith("{{")&&P.endsWith("}}"))try{const K=P.slice(2,-2).trim();R[B]=Pn(K)?this.bindingEngine.evaluatePipeExpression(K,D,{skipCache:!0}):this.bindingEngine.evaluateExpression(K,D,{skipCache:!0})}catch{R[B]=m[B]}}m=R,z.log("[handleSequence] _computed recalculated after setState:",m)}}if(_.handler!=="setState"){const M=window.__g7SequenceLocalSync;if(M&&M!==f){f=M,window.__g7SequenceLocalSync=void 0,z.log("[handleSequence] currentState synchronized from __g7SequenceLocalSync after custom handler:",_.handler);const R=n.data?._computedDefinitions;if(R&&Object.keys(R).length>0){const D={},B={...n.data,_local:f,_computed:D,$computed:D,_isolated:g};for(const[q,P]of Object.entries(R))if(typeof P=="string"){const K=P.trim();if(K.startsWith("{{")&&K.endsWith("}}"))try{const ge=K.slice(2,-2).trim();D[q]=Pn(ge)?this.bindingEngine.evaluatePipeExpression(ge,B,{skipCache:!0}):this.bindingEngine.evaluateExpression(ge,B,{skipCache:!0})}catch{D[q]=m[q]}}m=D,z.log("[handleSequence] _computed recalculated after custom handler:",m)}}}l&&i?.isEnabled()&&i.captureSequenceActionAfter?.(l,v,S(),Date.now()-A,L.data)}catch(L){throw l&&i?.isEnabled()&&(i.captureSequenceActionAfter?.(l,v,S(),Date.now()-A,void 0,L),i.endSequenceExecution?.(l,L)),z.error(`sequence handler: action[${v}] failed:`,L),L}}return window.__g7SequenceLocalSync=void 0,l&&i?.isEnabled()&&i.endSequenceExecution?.(l),c}async handleParallel(e,n){const a=e.actions||e.params?.actions;if(!a||!Array.isArray(a)||a.length===0)return z.warn("parallel handler requires non-empty actions array"),[];z.log(`parallel handler: executing ${a.length} actions in parallel`);const i=n.isolatedContext?{...n.isolatedContext,state:{...n.isolatedContext.state}}:null,l=a.map((f,g)=>{const m={...n,isolatedContext:i};return this.executeAction(f,m).catch(b=>{throw z.error(`parallel handler: action[${g}] failed:`,b),b})}),c=await Promise.allSettled(l),d=c.filter(f=>f.status==="rejected").length;return d>0&&z.warn(`parallel handler: ${d}/${a.length} actions failed`),c}async handleLoadScript(e,n,a){const{src:i,id:l,async:c=!0,defer:d=!1}=e;if(!i)throw new jt('loadScript handler requires "src" parameter',n);const f=l||`script_${i.replace(/[^a-zA-Z0-9]/g,"_")}`;return ps.loadedScripts.has(f)?(z.log(`loadScript: script already loaded, skipping: ${f}`),n.onLoad&&await this.executeAction(n.onLoad,a),!0):document.getElementById(f)?(z.log(`loadScript: script element already exists: ${f}`),ps.loadedScripts.add(f),n.onLoad&&await this.executeAction(n.onLoad,a),!0):(z.log(`loadScript: loading script: ${i}`),new Promise((m,b)=>{const S=document.createElement("script");S.id=f,S.src=i,S.async=c,S.defer=d,S.onload=async()=>{if(z.log(`loadScript: script loaded successfully: ${f}`),ps.loadedScripts.add(f),n.onLoad)try{await this.executeAction(n.onLoad,a)}catch(v){z.error("loadScript: onLoad action failed:",v)}m(!0)},S.onerror=v=>{z.error(`loadScript: failed to load script: ${i}`,v),b(new jt(`Failed to load script: ${i}`,n))},document.head.appendChild(S)}))}async handleCallExternal(e,n,a){const i=e.constructor,l=e.args||{},c=e.method,d=e.methodArgs||[],f=e.callbackEvent,g=e.embedTarget,m=e.callbackSetState,b=e.callbackAction;if(!i)throw new jt('callExternal handler requires "constructor" parameter',n);const S=this.getNestedProperty(window,i);if(!S||typeof S!="function")throw new jt(`Constructor not found or not a function: ${i}. Make sure the script is loaded first using loadScript handler.`,n);z.log(`callExternal: calling constructor ${i}`);const v={...l};for(const[A,x]of Object.entries(l))x===!0&&(v[A]=L=>{if(z.log(`callExternal: callback triggered for ${A}`,L),f&&typeof window<"u"&&window.G7Core?.componentEvent&&window.G7Core.componentEvent.emit(f,L),m&&a.setState){const M=B=>{const q={};for(const[P,K]of Object.entries(B))typeof K=="string"?q[P]=this.getNestedProperty(L,K):typeof K=="object"&&K!==null&&(q[P]=M(K));return q},R=M(m);z.log("callExternal: callbackSetState mapping result",R);const D=this.deepMergeWithState(R,a.state||{});z.log("callExternal: merged with existing state",D),a.setState(D)}else f&&a.setState&&a.setState({[`${f.replace(/:/g,"_")}_result`]:L});if(b){const M={...a,data:{...a.data,$event:L}},R=Array.isArray(b)?b:[b];for(const D of R)try{this.executeAction(D,M)}catch(B){z.error("callExternal: callbackAction failed:",B)}}});const _=new S(v);if(c&&typeof _[c]=="function"){if(z.log(`callExternal: calling method ${c}`),c==="embed"&&g){const A=document.querySelector(g);if(A)return _[c](A,...d);throw new jt(`Embed target element not found: ${g}`,n)}return _[c](...d)}return _}async handleCallExternalEmbed(e,n,a){const i=e.constructor,l=e.args||{},c=e.callbackSetState,d=e.callbackEvent,f=e.layerClassName,g=e.callbackAction;if(!i)throw new jt('callExternalEmbed handler requires "constructor" parameter',n);const m=this.getNestedProperty(window,i);if(!m||typeof m!="function")throw new jt(`Constructor not found or not a function: ${i}. Make sure the script is loaded first.`,n);z.log(`callExternalEmbed: creating layer for ${i}`);const{layer:b,closeLayer:S}=this.createEmbedLayer(f),v={...l};for(const[A,x]of Object.entries(l))x===!0&&(v[A]=L=>{if(z.log(`callExternalEmbed: callback triggered for ${A}`,L),S(),d&&typeof window<"u"&&window.G7Core?.componentEvent&&window.G7Core.componentEvent.emit(d,L),c&&a.setState){const M=B=>{const q={};for(const[P,K]of Object.entries(B))typeof K=="string"?q[P]=this.getNestedProperty(L,K):typeof K=="object"&&K!==null&&(q[P]=M(K));return q},R=M(c);z.log("callExternalEmbed: callbackSetState mapping result",R);const D=this.deepMergeWithState(R,a.state||{});z.log("callExternalEmbed: merged with existing state",D),a.setState(D)}if(g){const M={...a,data:{...a.data,$event:L}},R=Array.isArray(g)?g:[g];for(const D of R)try{this.executeAction(D,M)}catch(B){z.error("callExternalEmbed: callbackAction failed:",B)}}});const _=new m(v);if(typeof _.embed=="function")_.embed(b),z.log("callExternalEmbed: embedded in layer");else throw S(),new jt(`Constructor ${i} does not have embed method`,n);return _}isImeComposing(e){return e?.isComposing===!0||e?.keyCode===229}createEmbedLayer(e){const n=document.createElement("div");n.id="g7-embed-overlay",n.style.cssText=` +`+l)}}catch{}}throw a}}_request(e,n){typeof e=="string"?(n=n||{},n.url=e):n=e||{},n=mi(this.defaults,n);const{transitional:a,paramsSerializer:i,headers:l}=n;a!==void 0&&Ql.assertOptions(a,{silentJSONParsing:xn.transitional(xn.boolean),forcedJSONParsing:xn.transitional(xn.boolean),clarifyTimeoutError:xn.transitional(xn.boolean),legacyInterceptorReqResOrdering:xn.transitional(xn.boolean),advertiseZstdAcceptEncoding:xn.transitional(xn.boolean),validateStatusUndefinedResolves:xn.transitional(xn.boolean)},!1),i!=null&&(F.isFunction(i)?n.paramsSerializer={serialize:i}:Ql.assertOptions(i,{encode:xn.function,serialize:xn.function},!0)),n.allowAbsoluteUrls!==void 0||(this.defaults.allowAbsoluteUrls!==void 0?n.allowAbsoluteUrls=this.defaults.allowAbsoluteUrls:n.allowAbsoluteUrls=!0),Ql.assertOptions(n,{baseUrl:xn.spelling("baseURL"),withXsrfToken:xn.spelling("withXSRFToken")},!0),n.method=(n.method||this.defaults.method||"get").toLowerCase();let c=l&&F.merge(l.common,l[n.method]);l&&F.forEach(["delete","get","head","post","put","patch","query","common"],_=>{delete l[_]}),n.headers=An.concat(c,l);const d=[];let f=!0;this.interceptors.request.forEach(function(A){if(typeof A.runWhen=="function"&&A.runWhen(n)===!1)return;f=f&&A.synchronous;const x=n.transitional||Dd;x&&x.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,y=0,S;if(!f){const _=[cm.bind(this),void 0];for(_.unshift(...d),_.push(...g),S=_.length,m=Promise.resolve(n);y{if(!a._listeners)return;let l=a._listeners.length;for(;l-- >0;)a._listeners[l](i);a._listeners=null}),this.promise.then=i=>{let l;const c=new Promise(d=>{a.subscribe(d),l=d}).then(i);return c.cancel=function(){a.unsubscribe(l)},c},e(function(l,c,d){a.reason||(a.reason=new po(l,c,d),n(a.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 n=this._listeners.indexOf(e);n!==-1&&this._listeners.splice(n,1)}toAbortSignal(){const e=new AbortController,n=a=>{e.abort(a)};return this.subscribe(n),e.signal.unsubscribe=()=>this.unsubscribe(n),e.signal}static source(){let e;return{token:new KS(function(i){e=i}),cancel:e}}};function hC(o){return function(n){return o.apply(null,n)}}function gC(o){return F.isObject(o)&&o.isAxiosError===!0}const Hd={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(Hd).forEach(([o,e])=>{Hd[e]=o});function dm(o){const e=new yi(o),n=xp(yi.prototype.request,e);return F.extend(n,yi.prototype,e,{allOwnKeys:!0}),F.extend(n,e,null,{allOwnKeys:!0}),n.create=function(i){return dm(mi(o,i))},n}const Yt=dm(go);Yt.Axios=yi,Yt.CanceledError=po,Yt.CancelToken=fC,Yt.isCancel=Wp,Yt.VERSION=$d,Yt.toFormData=Kl,Yt.AxiosError=Ce,Yt.Cancel=Yt.CanceledError,Yt.all=function(e){return Promise.all(e)},Yt.spread=hC,Yt.isAxiosError=gC,Yt.mergeConfig=mi,Yt.AxiosHeaders=An,Yt.formToJSON=o=>Kp(F.isHTMLForm(o)?new FormData(o):o),Yt.getAdapter=lm.getAdapter,Yt.HttpStatusCode=Hd,Yt.default=Yt;const{Axios:OT,AxiosError:LT,CanceledError:MT,isCancel:$T,CancelToken:NT,VERSION:IT,all:HT,Cancel:jT,isAxiosError:zT,spread:UT,toFormData:PT,AxiosHeaders:BT,HttpStatusCode:qT,formToJSON:GT,getAdapter:VT,mergeConfig:FT,create:KT}=Yt,jd="g7.identity.redirectStash",Zl=ht("IdentityGuardInterceptor");class Et{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 n=this.deferredResolver;if(!n){Zl.warn("IdentityGuardInterceptor.resolveDeferred 호출됐지만 대기 중인 launcher 가 없습니다. 모달이 launcher 외부에서 열렸는지 확인하세요.");return}this.deferredResolver=null,n(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,n){return e===428&&typeof n=="object"&&n!==null&&n.error_code==="identity_verification_required"}static async handle(e,n,a){this.domainNoticeShown=!1;const i=this.launcher??mC,c=!!(a&&(a.email||a.phone))?{...e.verification,target:a}:e.verification,d=await i(c);if(d.status!=="verified")return null;const f=c.return_request;if(!f)return null;const g=pC(f.url,d.token);return fetch(g,{method:f.method,headers:n?.headers??{Accept:"application/json","Content-Type":"application/json"},body:n?.body,credentials:n?.credentials??"same-origin"})}static redirectExternally(e){const n=e.redirect_url;if(!n)return Zl.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 a={return_url:window.location.href,payload:e,stashed_at:Date.now()};try{window.sessionStorage?.setItem(jd,JSON.stringify(a))}catch(i){Zl.warn("sessionStorage 접근 실패 — stash 없이 redirect 합니다.",i)}window.location.href=n}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}}$(Et,"launcher",null),$(Et,"deferredResolver",null),$(Et,"domainNoticeShown",!1);function pC(o,e){if(!e)return o;try{const n=typeof window<"u"?window.location.origin:"http://localhost",a=new URL(o,n);return a.searchParams.set("verification_token",e),/^https?:\/\//i.test(o)?a.toString():`${a.pathname}${a.search}${a.hash}`}catch{const n=o.includes("?")?"&":"?";return`${o}${n}verification_token=${encodeURIComponent(e)}`}}const mC=async o=>{if(typeof window>"u")return{status:"cancelled"};if(o.render_hint==="external_redirect"||o.redirect_url)return Et.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 n=window.location.href,a={return_url:n,payload:o,stashed_at:Date.now()};try{window.sessionStorage?.setItem(jd,JSON.stringify(a))}catch{}const i=`/identity/challenge?return=${encodeURIComponent(n)}`;try{await e.dispatch({handler:"navigate",params:{path:i}})}catch(l){Zl.warn("navigate 실패 — window.location 으로 폴백",l),window.location.href=i}return new Promise(()=>{})},yC=ht("ApiClient");function zd(){return typeof window<"u"&&window.__G7_DEVTOOLS__?window.__G7_DEVTOOLS__:null}class bC{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=Yt.create({baseURL:this.config.baseURL,timeout:this.config.timeout,headers:{"Content-Type":"application/json",Accept:"application/json"},paramsSerializer:{serialize:n=>{const a=[];for(const[i,l]of Object.entries(n))if(l!=null)if(Array.isArray(l)){const c=i.endsWith("[]")?i:`${i}[]`;for(const d of l)a.push(`${encodeURIComponent(c)}=${encodeURIComponent(String(d))}`)}else a.push(`${encodeURIComponent(i)}=${encodeURIComponent(String(l))}`);return a.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 n=this.getToken();if(n&&e.headers&&(e.headers.Authorization=`Bearer ${n}`),typeof window<"u"&&e.headers){const i=localStorage.getItem("g7_locale");i&&(e.headers["Accept-Language"]=i)}const a=zd();if(a?.isEnabled()){const i=this.buildFullUrl(e),l=(e.method||"GET").toUpperCase(),c=a.trackRequest(i,l,{requestBody:e.data});e._devToolsRequestId=c}return e},e=>Promise.reject(e)),this.client.interceptors.response.use(e=>{const n=e.config,a=n._devToolsRequestId;if(a){const i=zd();i?.isEnabled()&&i.completeRequest(a,e.status,e.data),n._devToolsRequestId=null}return e},async e=>{const n=e.config,a=n?.url||"",l=["/auth/","/layouts/"].some(c=>a.includes(c));if(e.response?.status===401&&!n?._retry&&!l){if(n._retry=!0,await br.getInstance().refreshToken()){const f=this.getToken();return f&&(n.headers.Authorization=`Bearer ${f}`),n._devToolsRequestId=null,this.client(n)}return this.completeDevToolsRequest(n,e),this.removeToken(),this.config.onUnauthorized&&this.config.onUnauthorized(),Promise.reject(e)}if(e.response?.status===401&&l)return this.completeDevToolsRequest(n,e),Promise.reject(e);if(Et.isIdentityRequired(e.response?.status,e.response?.data)){this.completeDevToolsRequest(n,e);const c={},d=n?.headers??{};for(const[S,v]of Object.entries(d))typeof v=="string"&&(c[S]=v);let f;n?.data!==void 0&&n?.data!==null&&(f=typeof n.data=="string"?n.data:JSON.stringify(n.data),c["Content-Type"]=c["Content-Type"]??"application/json");const g=n?.identity_target,m=await Et.handle(e.response.data,{headers:c,body:f,credentials:"same-origin"},g);if(!m)return Promise.reject(e);let y=null;try{y=await m.json()}catch{y=null}return m.ok?{...e.response,status:m.status,data:y}:Promise.reject(Object.assign(new Error("replay failed"),{response:{status:m.status,data:y}}))}return e.response?.status===403?(this.completeDevToolsRequest(n,e),this.callOnError(e),Promise.reject(e)):(this.completeDevToolsRequest(n,e),e.response&&this.callOnError(e),Promise.reject(e))})}async get(e,n){return(await this.client.get(e,n)).data}async post(e,n,a){return(await this.client.post(e,n,a)).data}async put(e,n,a){return(await this.client.put(e,n,a)).data}async patch(e,n,a){return(await this.client.patch(e,n,a)).data}async delete(e,n){return(await this.client.delete(e,n)).data}getInstance(){return this.client}setOnUnauthorized(e){this.config.onUnauthorized=e}setOnError(e){this.config.onError=e}completeDevToolsRequest(e,n){if(!e?._devToolsRequestId)return;const a=zd();if(!a?.isEnabled())return;const i=e._devToolsRequestId;e._devToolsRequestId=null,n.response?a.completeRequest(i,n.response.status,n.response.data):n.request?a.failRequest(i,n.message||"Network error"):a.failRequest(i,n.message||"Request error")}buildFullUrl(e){let n=e.url||"";if(e.baseURL&&!n.startsWith("http")&&(n=`${e.baseURL}${n.startsWith("/")?"":"/"}${n}`),e.params&&typeof e.params=="object"){const a=e.params,i=[];for(const[l,c]of Object.entries(a))if(c!=null)if(Array.isArray(c)){const d=l.endsWith("[]")?l:`${l}[]`;for(const f of c)i.push(`${encodeURIComponent(d)}=${encodeURIComponent(String(f))}`)}else i.push(`${encodeURIComponent(l)}=${encodeURIComponent(String(c))}`);i.length>0&&(n+=(n.includes("?")?"&":"?")+i.join("&"))}return n}callOnError(e){if(!this.config.onError)return;const n={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(n)}catch(a){yC.error("Error in onError handler:",a)}}}let Ud=null;function Hr(){return Ud||(Ud=new bC),Ud}const mo=ht("AuthManager");function cs(o,e,n,a){try{window.G7Core?.devTools?.trackAuthEvent?.(o,e,n,a)}catch{}}const ec={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"}},Ar=class Ar{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",ec.admin),this.config.set("user",ec.user)}static getInstance(){return Ar.instance||(Ar.instance=new Ar),Ar.instance}on(e,n){this.eventHandlers.has(e)||this.eventHandlers.set(e,[]),this.eventHandlers.get(e).push(n)}emit(e,...n){const a=this.eventHandlers.get(e);a&&a.forEach(i=>i(...n))}isAuthenticated(){return this.state.isAuthenticated}getUser(){return this.state.user}getAuthType(){return this.state.type}async checkAuth(e){const n=Hr();if(!n.getToken())return this.clearState(),!1;const i=this.config.get(e);if(!i)return mo.error(`Unknown auth type: ${e}`),!1;try{const l=await n.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(n){return mo.warn(`Preload auth failed for type ${e}:`,n),!1}}async login(e,n,a){const i=Hr();if(!this.config.get(e))throw new Error(`Unknown auth type: ${e}`);const c=e==="admin"?ec.admin.loginEndpoint:ec.user.loginEndpoint;try{const d=a?.headers?{headers:a.headers}:void 0,f=await i.post(c,n,d);if(f.success&&f.data){i.setToken(f.data.token);const g=f.data.user.language,m=localStorage.getItem(Ar.LOCALE_STORAGE_KEY),y=g&&g!==m;if(g)try{localStorage.setItem(Ar.LOCALE_STORAGE_KEY,g)}catch(S){mo.warn("Failed to save user language to localStorage:",S)}return this.state={isAuthenticated:!0,user:f.data.user,type:e},this.emit("login",this.state),this.emit("authStateChange",this.state),cs("login",!0,void 0,{userId:f.data.user.uuid,email:f.data.user.email,type:e}),y&&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,cs("login",!1,g.message,{type:e,status:d.response?.status}),g}}async logout(){const e=Hr(),n=this.state.type?this.config.get(this.state.type):null;try{n&&await e.post(n.logoutEndpoint)}catch(a){mo.warn("Logout API call failed:",a)}finally{e.removeToken();const a={...this.state};if(this.clearState(),this.emit("logout",a),this.emit("authStateChange",this.state),cs("logout",!0,void 0,{previousType:a.type}),n&&a.type){const i=window.location.pathname+window.location.search;window.location.href=this.getLoginRedirectUrl(a.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 n=this.config.get(e);if(!n)return!1;const a=Hr();try{const i=await a.post(n.refreshEndpoint);return i.success&&i.data?.token?(a.setToken(i.data.token),this.emit("tokenRefreshed"),cs("token-refresh",!0,void 0,{type:e}),!0):(cs("token-refresh",!1,"No token in response",{type:e}),!1)}catch(i){return mo.error("Token refresh failed:",i),cs("token-refresh",!1,i instanceof Error?i.message:"Unknown error",{type:e}),!1}}getLoginRedirectUrl(e,n,a){const i=this.config.get(e);if(!i)return"/login";const l=encodeURIComponent(n);let c=`${i.loginPath}?redirect=${l}`;return a&&(c+=`&reason=${encodeURIComponent(a)}`),c}updateConfig(e,n){if(n.loginPath!==void 0){const i=n.loginPath;if(!i.startsWith("/")||i.startsWith("//"))throw new Error(`AuthManager.updateConfig: loginPath must be a same-origin path starting with '/' (got: ${i})`)}const a=this.config.get(e);a&&this.config.set(e,{...a,...n})}getRedirectUrl(e){const a=this.config.get(e)?.defaultPath||"/",l=new URLSearchParams(window.location.search).get("redirect");if(l)try{const c=decodeURIComponent(l);if(c.startsWith("/"))return c}catch{}return a}getConfig(e){return this.config.get(e)}clearState(){this.state={isAuthenticated:!1,user:null,type:null}}static resetInstance(){Ar.instance=null}};$(Ar,"instance"),$(Ar,"LOCALE_STORAGE_KEY","g7_locale");let br=Ar;const fm={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}}"}}},Qr={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,n){if(o.handler!=="showErrorPage"||o.params?.errorCode!==void 0)return o;const a=typeof e=="string"?parseInt(e,10):e,i=isNaN(a)?n:a;return i===void 0?o:{...o,params:{...o.params,errorCode:i}}}},vr=ht("ErrorHandlingResolver"),Ma=class Ma{constructor(){$(this,"templateErrorHandling",null);$(this,"layoutErrorHandling",null);$(this,"executeAction",null)}static getInstance(){return Ma.instance||(Ma.instance=new Ma),Ma.instance}static resetInstance(){Ma.instance=null}setTemplateConfig(e){this.templateErrorHandling=e,vr.log("Template config set:",e)}setLayoutConfig(e){this.layoutErrorHandling=e,vr.log("Layout config set:",e)}setActionExecutor(e){this.executeAction=e}resolve(e,n={}){const{errorHandling:a,onError:i}=n;vr.log("Resolving error:",e,{hasActionErrorHandling:!!a,hasActionOnError:!!i,hasLayoutConfig:!!this.layoutErrorHandling,hasTemplateConfig:!!this.templateErrorHandling});let l=Qr.findHandler(a,e);if(l){const c=this.getMatchedKey(a,e);return{handler:Qr.injectErrorCode(l,c,e),level:"action",matchedKey:c}}if(i){const c=Qr.normalizeOnError(i);if(c.length>0)return{handler:c.length===1?c[0]:{handler:"sequence",actions:c},level:"action",matchedKey:"onError"}}if(l=Qr.findHandler(this.layoutErrorHandling||void 0,e),l){const c=this.getMatchedKey(this.layoutErrorHandling,e);return{handler:Qr.injectErrorCode(l,c,e),level:"layout",matchedKey:c}}if(l=Qr.findHandler(this.templateErrorHandling||void 0,e),l){const c=this.getMatchedKey(this.templateErrorHandling,e);return{handler:Qr.injectErrorCode(l,c,e),level:"template",matchedKey:c}}if(l=Qr.findHandler(fm,e),l){const c=this.getMatchedKey(fm,e);return{handler:Qr.injectErrorCode(l,c,e),level:"system",matchedKey:c}}return{handler:null,level:null,matchedKey:null}}async execute(e,n){if(!this.executeAction){vr.error("Action executor is not set");return}vr.log("Executing handler:",e.handler,{errorContext:n});try{return await this.executeAction(e,{error:n})}catch(a){throw vr.error("Failed to execute handler:",a),a}}async resolveAndExecute(e,n,a={}){const i=this.resolve(e,a);if(vr.log("Resolve result:",{errorCode:e,handler:i.handler?.handler,level:i.level,matchedKey:i.matchedKey}),!i.handler)return vr.warn("No handler found for error:",e),{handled:!1};try{return{handled:!0,result:await this.execute(i.handler,n)}}catch(l){return vr.error("Handler execution failed:",l),{handled:!1}}}getMatchedKey(e,n){return e[n]?n:e[String(n)]?String(n):"default"}clearLayoutConfig(){this.layoutErrorHandling=null,vr.log("Layout config cleared")}clearAllConfig(){this.templateErrorHandling=null,this.layoutErrorHandling=null,vr.log("All config cleared")}getConfigStatus(){return{hasTemplate:this.templateErrorHandling!==null,hasLayout:this.layoutErrorHandling!==null,hasExecutor:this.executeAction!==null}}};$(Ma,"instance",null);let Pd=Ma;function Sr(){return Pd.getInstance()}var Bd={exports:{}},yo={};var hm;function vC(){if(hm)return yo;hm=1;var o=Symbol.for("react.transitional.element"),e=Symbol.for("react.fragment");function n(a,i,l){var c=null;if(l!==void 0&&(c=""+l),i.key!==void 0&&(c=""+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:a,key:c,ref:i!==void 0?i:null,props:l}}return yo.Fragment=e,yo.jsx=n,yo.jsxs=n,yo}var gm;function SC(){return gm||(gm=1,Bd.exports=vC()),Bd.exports}var gt=SC();const wC=Xr({__proto__:null,default:Jr(gt)},[gt]),qd=ht("ParentContextProvider"),pm=H.createContext(null);let tc=null;function Gd(){tc?(qd.log("[triggerModalParentUpdate] 모달 부모 컨텍스트 업데이트 트리거"),tc()):qd.warn("[triggerModalParentUpdate] Provider가 아직 마운트되지 않음")}const mm=({children:o})=>{const[e,n]=H.useState(0),a=H.useRef(!0),i=H.useCallback(()=>{const c=window.__g7LayoutContextStack||[];return c[c.length-1]?.dataContext},[]);H.useEffect(()=>(a.current=!0,tc=()=>{a.current&&(n(c=>c+1),qd.log("[ParentContextProvider] 버전 업데이트됨"))},()=>{a.current=!1,tc=null}),[]);const l={version:e,getParentDataContext:i};return gt.jsx(pm.Provider,{value:l,children:o})};function CC(){return H.useContext(pm)}const j=ht("ActionDispatcher");function EC(o,e,n,a){return n||(ip(o)||dd(o)?"$t:core.errors.network_request_failed":a||`Failed to execute action: ${e}`)}const ym=new Set(["navigate","navigateBack","navigateForward","replaceUrl","refresh","logout"]),_C=new Set(["redirect"]);function Fn(){try{return window.G7Core?.devTools}catch{return}}class Bt extends Error{constructor(n,a,i){super(n);$(this,"action");$(this,"originalError");$(this,"unknownHandler",!1);this.action=a,this.originalError=i,this.name="ActionError"}}const bs=class bs{constructor(e={},n,a){$(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 Dn,this.translationEngine=n,this.translationContext=a,this.defaultContext=e,this.registerDefaultHandlers(),this.setupErrorHandling()}setGlobalHeaders(e){this.globalHeaders=e||[]}setNamedActions(e){this.namedActions=e||{};const n=Fn();n?.isEnabled?.()&&n.setNamedActionDefinitions?.(this.namedActions),j.log("[setNamedActions] registered:",Object.keys(this.namedActions))}getNamedActions(){return this.namedActions}setPreviewMode(e){this.previewMode=e,j.log("Preview mode:",e?"enabled":"disabled")}isPreviewMode(){return this.previewMode}static getPreviewSuppressedHandlers(){return ym}static getPreviewSuppressedLayoutFeatures(){return _C}resolveActionRef(e){if(!e.actionRef)return e;const n=this.namedActions[e.actionRef];if(!n)return j.warn(`[resolveActionRef] named action not found: "${e.actionRef}"`),e;const a=Fn();a?.isEnabled?.()&&a.trackNamedActionRef?.({actionRefName:e.actionRef,resolvedHandler:n.handler,timestamp:Date.now()});const{actionRef:i,type:l,key:c,event:d,...f}=e,g={...n,...Object.fromEntries(Object.entries(f).filter(([,m])=>m!==void 0)),type:l??n.type};return c!==void 0&&(g.key=c),d!==void 0&&(g.event=d),g}matchesPattern(e,n){if(n==="*")return!0;const a=n.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${a}$`).test(e)}getMatchingGlobalHeaders(e,n){const a={};for(const i of this.globalHeaders)this.matchesPattern(e,i.pattern)&&Object.entries(i.headers).forEach(([l,c])=>{const d=rs(c,n,{skipCache:!0});d!=null&&d!==""&&(a[l]=String(d))});return a}setupErrorHandling(){if(this.errorHandlingSetup)return;Sr().setActionExecutor(async(n,a)=>{const i={type:"click",handler:n.handler,target:n.target,params:n.params,actions:n.actions},l={data:{...this.defaultContext.data,error:a.error}};return await this.dispatchAction(i,l)}),this.errorHandlingSetup=!0}registerDefaultHandlers(){this.registerHandler("refetchDataSource",async(n,a)=>{const i=n.params?.dataSourceId,l=n.params?.sync;if(!i){j.warn("refetchDataSource: dataSourceId is required");return}if(typeof window<"u"&&window.G7Core?.dataSource?.refetch){const c=window.G7Core?.state?.get?.()||{},d={...a.state?._global,...c},f=window.G7Core?.state?.getLocal?.()||{},g=a.data?._local||a.state||{},m={...f,...g},y=a.isolatedContext?.state;j.log("[refetchDataSource] localStateOverride:",m),await window.G7Core.dataSource.refetch(i,{...l?{sync:!0}:{},...d?{globalStateOverride:d}:{},...m?{localStateOverride:m}:{},...y?{isolatedStateOverride:y}:{}})}else j.warn("refetchDataSource: G7Core.dataSource.refetch is not available")}),this.registerHandler("appendDataSource",async(n,a)=>{const{dataSourceId:i,dataPath:l,newData:c}=n.params||{};if(!i){j.warn("appendDataSource: dataSourceId is required");return}if(c===void 0){j.warn("appendDataSource: newData is required");return}if(typeof window<"u"&&window.G7Core?.dataSource?.updateData){if(!Array.isArray(c)){j.warn("appendDataSource: newData must be an array, got:",typeof c,c);return}await window.G7Core.dataSource.updateData(i,l||null,c,"append")}else j.warn("appendDataSource: G7Core.dataSource.updateData is not available")}),this.registerHandler("updateDataSource",async(n,a)=>{const{dataSourceId:i,data:l,merge:c=!1}=n.params||{};if(!i){j.warn("updateDataSource: dataSourceId is required");return}if(l===void 0){j.warn("updateDataSource: data is required");return}typeof window<"u"&&window.G7Core?.dataSource?.set?(j.log(`[updateDataSource] Updating dataSource '${i}' with:`,l),window.G7Core.dataSource.set(i,l,{merge:c})):j.warn("updateDataSource: G7Core.dataSource.set is not available")}),this.registerHandler("scrollIntoView",async(n,a)=>{const{selector:i,behavior:l="smooth",block:c="nearest",inline:d="nearest",waitForElement:f=!1,timeout:g=2e3,delay:m=0,retryCount:y=0,retryInterval:S=50,scrollContainer:v}=n.params||{};if(!i){j.warn("scrollIntoView: selector is required");return}if(typeof window>"u"||typeof document>"u"){j.warn("scrollIntoView: window/document is not available");return}let _=null;if(f){if(_=await new Promise(A=>{const x=document.querySelector(i);if(x){A(x);return}const O=setTimeout(()=>{M.disconnect(),A(null)},g),M=new MutationObserver(()=>{const T=document.querySelector(i);T&&(clearTimeout(O),M.disconnect(),A(T))});M.observe(document.body,{childList:!0,subtree:!0})}),!_){j.warn(`scrollIntoView: element not found for selector "${i}" after ${g}ms timeout`);return}}else{m>0&&await new Promise(x=>setTimeout(x,m)),_=document.querySelector(i);let A=0;for(;!_&&AsetTimeout(x,S)),_=document.querySelector(i),A++;if(!_){j.warn(`scrollIntoView: element not found for selector "${i}" after ${A+1} attempts`);return}}if(v){const A=document.querySelector(v);if(!A){j.warn(`scrollIntoView: container not found for selector "${v}"`);return}const x=_.getBoundingClientRect(),O=A.getBoundingClientRect(),M=x.top-O.top+A.scrollTop,T=M+x.height;let D;switch(c){case"start":D=M;break;case"center":D=M-A.clientHeight/2+x.height/2;break;case"end":D=T-A.clientHeight;break;default:const z=x.topO.bottom;if(z)D=M;else if(P)D=T-A.clientHeight;else return;break}A.scrollTo({top:Math.max(0,D),behavior:l});return}_.scrollIntoView({behavior:l,block:c,inline:d})}),this.registerHandler("reloadExtensions",async(n,a)=>{if(typeof window>"u"){j.warn("reloadExtensions: window is not available");return}const i=window.__templateApp;if(!i){j.warn("reloadExtensions: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState()}catch(d){throw j.error("reloadExtensions: reloadExtensionState failed",d),d}else j.warn("reloadExtensions: TemplateApp.reloadExtensionState unavailable");const{moduleInfo:l,pluginInfo:c}=n.params||{};if(l)try{await this.executeAction({handler:"reloadModuleHandlers",params:n.params},a)}catch(d){j.error("reloadExtensions: reloadModuleHandlers failed",d)}if(c)try{await this.executeAction({handler:"reloadPluginHandlers",params:n.params},a)}catch(d){j.error("reloadExtensions: reloadPluginHandlers failed",d)}j.log("reloadExtensions: done")}),this.registerHandler("reloadRoutes",async(n,a)=>{if(typeof window>"u"){j.warn("reloadRoutes: window is not available");return}const i=window.__templateApp;if(!i){j.warn("reloadRoutes: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState(),j.log("reloadRoutes: delegated to reloadExtensionState")}catch(l){throw j.error("reloadRoutes: Failed to reload routes",l),l}else{const l=i.getRouter?.();l&&(await l.loadRoutes(),j.log("reloadRoutes: Routes reloaded (legacy fallback)"))}}),this.registerHandler("refresh",async(n,a)=>{if(typeof window>"u"){j.warn("refresh: window is not available");return}const i=Number(n.params?.delayMs??0);i>0&&await new Promise(l=>setTimeout(l,i)),window.location.reload()}),this.registerHandler("remount",async(n,a)=>{const{componentId:i}=n.params||{};if(!i){j.warn("remount: componentId parameter is required");return}if(!this.globalStateUpdater){j.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}}),j.log(`remount: ${i} key incremented to ${f+1}`)}),this.registerHandler("reloadTranslations",async(n,a)=>{if(typeof window>"u"){j.warn("reloadTranslations: window is not available");return}const i=window.__templateApp;if(!i){j.warn("reloadTranslations: TemplateApp not initialized");return}if(typeof i.reloadExtensionState=="function")try{await i.reloadExtensionState(),j.log("reloadTranslations: delegated to reloadExtensionState")}catch(l){throw j.error("reloadTranslations: Failed to reload translations",l),l}}),this.registerHandler("reloadModuleHandlers",async(n,a)=>{if(typeof window>"u"){j.warn("reloadModuleHandlers: window is not available");return}const{moduleInfo:i,action:l}=n.params||{};if(!i){j.warn("reloadModuleHandlers: moduleInfo is required");return}const c=i.data||i;if(!c.identifier){j.warn("reloadModuleHandlers: moduleInfo with identifier is required");return}if(!l||l!=="add"&&l!=="remove"){j.warn('reloadModuleHandlers: action must be "add" or "remove"');return}const d=window.G7Config;if(!d){j.warn("reloadModuleHandlers: G7Config not available");return}const f=c.identifier;try{if(l==="add"){if(c.assets&&(d.moduleAssets=d.moduleAssets||{},d.moduleAssets[f]=c.assets,j.log(`reloadModuleHandlers: Added assets for ${f}`),c.assets.js)){const g=c.assets.js,m=`module-${f}`;if(document.getElementById(m)){j.warn(`reloadModuleHandlers: Script ${m} already loaded`);return}const y=document.createElement("script");if(y.id=m,y.src=g,y.async=!0,await new Promise((S,v)=>{y.onload=()=>{j.log(`reloadModuleHandlers: Script loaded successfully for ${f}`),S()},y.onerror=()=>{j.error(`reloadModuleHandlers: Failed to load script for ${f}`),v(new Error(`Failed to load module script: ${g}`))},document.head.appendChild(y)}),c.assets.css){const S=c.assets.css,v=`module-css-${f}`;if(!document.getElementById(v)){const _=document.createElement("link");_.id=v,_.rel="stylesheet",_.href=S,document.head.appendChild(_),j.log(`reloadModuleHandlers: CSS loaded for ${f}`)}}}}else if(l==="remove"){d.moduleAssets&&d.moduleAssets[f]&&(delete d.moduleAssets[f],j.log(`reloadModuleHandlers: Removed assets for ${f}`));const g=`module-${f}`,m=document.getElementById(g);m&&(m.remove(),j.log(`reloadModuleHandlers: Removed script for ${f}`));const y=`module-css-${f}`,S=document.getElementById(y);S&&(S.remove(),j.log(`reloadModuleHandlers: Removed CSS for ${f}`))}}catch(g){throw j.error(`reloadModuleHandlers: Failed to ${l} module assets`,g),g}}),this.registerHandler("reloadPluginHandlers",async(n,a)=>{if(typeof window>"u"){j.warn("reloadPluginHandlers: window is not available");return}const{pluginInfo:i,action:l}=n.params||{};if(!i){j.warn("reloadPluginHandlers: pluginInfo is required");return}const c=i.data||i;if(!c.identifier){j.warn("reloadPluginHandlers: pluginInfo with identifier is required");return}if(!l||l!=="add"&&l!=="remove"){j.warn('reloadPluginHandlers: action must be "add" or "remove"');return}const d=window.G7Config;if(!d){j.warn("reloadPluginHandlers: G7Config not available");return}const f=c.identifier;try{if(l==="add"){if(c.assets&&(d.pluginAssets=d.pluginAssets||{},d.pluginAssets[f]=c.assets,j.log(`reloadPluginHandlers: Added assets for ${f}`),c.assets.js)){const g=c.assets.js,m=`plugin-${f}`;if(document.getElementById(m)){j.warn(`reloadPluginHandlers: Script ${m} already loaded`);return}const y=document.createElement("script");if(y.id=m,y.src=g,y.async=!0,await new Promise((S,v)=>{y.onload=()=>{j.log(`reloadPluginHandlers: Script loaded successfully for ${f}`),S()},y.onerror=()=>{j.error(`reloadPluginHandlers: Failed to load script for ${f}`),v(new Error(`Failed to load plugin script: ${g}`))},document.head.appendChild(y)}),c.assets.css){const S=c.assets.css,v=`plugin-css-${f}`;if(!document.getElementById(v)){const _=document.createElement("link");_.id=v,_.rel="stylesheet",_.href=S,document.head.appendChild(_),j.log(`reloadPluginHandlers: CSS loaded for ${f}`)}}}}else if(l==="remove"){d.pluginAssets&&d.pluginAssets[f]&&(delete d.pluginAssets[f],j.log(`reloadPluginHandlers: Removed assets for ${f}`));const g=`plugin-${f}`,m=document.getElementById(g);m&&(m.remove(),j.log(`reloadPluginHandlers: Removed script for ${f}`));const y=`plugin-css-${f}`,S=document.getElementById(y);S&&(S.remove(),j.log(`reloadPluginHandlers: Removed CSS for ${f}`))}}catch(g){throw j.error(`reloadPluginHandlers: Failed to ${l} plugin assets`,g),g}});let e=!1;this.registerHandler("showErrorPage",async(n,a)=>{if(e){j.log("showErrorPage: Already active, skipping duplicate call");return}if(e=!0,typeof window>"u"){e=!1,j.warn("showErrorPage: window is not available");return}const i=window.__templateApp;if(!i){e=!1,j.warn("showErrorPage: TemplateApp not initialized");return}const l=i.getErrorPageHandler?.();if(!l){e=!1,j.warn("showErrorPage: ErrorPageHandler not available");return}const c=n.params?.errorCode||500,d=n.params?.target||"content";let f=n.params?.containerId;f||(f=d==="full"?"app":"main_content"),j.log("showErrorPage:",{errorCode:c,target:d,containerId:f});const g=(m,y=6e4)=>new Promise((S,v)=>{const _=document.getElementById(m);if(_){S(_);return}j.log(`showErrorPage: Waiting for container #${m}...`);let A;const x=new MutationObserver((O,M)=>{const T=document.getElementById(m);T&&(j.log(`showErrorPage: Container #${m} found`),M.disconnect(),clearTimeout(A),S(T))});x.observe(document.body,{childList:!0,subtree:!0}),A=setTimeout(()=>{x.disconnect(),v(new Error(`Container #${m} not found within ${y}ms`))},y)});try{await g(f);const m=Sr(),y=m.layoutErrorHandling;m.clearLayoutConfig();try{await l.renderError(c,f)||j.warn(`showErrorPage: Failed to render error page for code ${c}`)}finally{m.setLayoutConfig(y)}}catch(m){throw j.error("showErrorPage: Error rendering error page:",m),m}finally{e=!1}}),this.registerHandler("emitEvent",async(n,a)=>{const i=n.params?.event,l=n.params?.data;if(!i){j.warn("emitEvent: event parameter is required");return}if(typeof window>"u"){j.warn("emitEvent: window is not available");return}const c=window.G7Core;if(!c?.componentEvent?.emit){j.warn("emitEvent: G7Core.componentEvent is not available");return}try{j.log(`emitEvent: Emitting "${i}"`,l);const d={...l,_context:{data:a.data,state:a.state}},f=await c.componentEvent.emit(i,d);if(!f||f.length===0?j.warn(`emitEvent: No listeners found for "${i}"`):j.log(`emitEvent: Event "${i}" completed with ${f.length} listener(s)`,f),this.globalStateUpdater){const g=(c?.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 y=a.state&&typeof a.state=="object"&&!Array.isArray(a.state)?a.state:g;window.__g7SequenceLocalSync={...y,_eventResult:m}}}catch(d){if(j.error(`emitEvent: Event "${i}" failed`,d),this.globalStateUpdater){const f=c?.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(n,a)=>{const{productId:i,field:l,value:c}=n.params||{};if(!i||!l){j.warn("updateProductField: productId and field are required");return}if(typeof window>"u"){j.warn("updateProductField: window is not available");return}const d=window.G7Core;if(!d?.state?.get||!this.globalStateUpdater){j.warn("updateProductField: G7Core.state or globalStateUpdater is not available");return}try{const f=d.state.get()||{},m=(f.products?.data?.data||[]).map(S=>S.id===i?{...S,[l]:c,_modified:!0}:S),y=new Set(f._local?.modifiedProductIds||[]);y.add(i),this.globalStateUpdater({products:{...f.products,data:{...f.products?.data,data:m}},_local:{...f._local,modifiedProductIds:Array.from(y)}}),j.log(`updateProductField: Updated product ${i}, field: ${l}, value:`,c)}catch(f){throw j.error("updateProductField: Error updating product field",f),f}}),this.registerHandler("updateOptionField",async(n,a)=>{const{productId:i,optionId:l,field:c,value:d}=n.params||{};if(!i||!l||!c){j.warn("updateOptionField: productId, optionId and field are required");return}if(typeof window>"u"){j.warn("updateOptionField: window is not available");return}const f=window.G7Core;if(!f?.state?.get||!this.globalStateUpdater){j.warn("updateOptionField: G7Core.state or globalStateUpdater is not available");return}try{const g=f.state.get()||{},y=(g.products?.data?.data||[]).map(v=>{if(v.id===i&&v.options){const _=v.options.map(A=>A.id===l?{...A,[c]:d,_modified:!0}:A);return{...v,options:_,_modified:!0}}return v}),S=new Set(g._local?.modifiedProductIds||[]);S.add(i),this.globalStateUpdater({products:{...g.products,data:{...g.products?.data,data:y}},_local:{...g._local,modifiedProductIds:Array.from(S)}}),j.log(`updateOptionField: Updated product ${i} option ${l}, field: ${c}, value:`,d)}catch(g){throw j.error("updateOptionField: Error updating option field",g),g}}),this.registerHandler("setLocale",async(n,a)=>{const i=n.target;if(!i||typeof i!="string"){j.warn("setLocale: Invalid locale:",i);return}const l=window.__templateApp;if(l&&typeof l.changeLocale=="function")try{await l.changeLocale(i),j.log("setLocale: Locale changed to",i)}catch(c){j.error("setLocale: Failed to change locale:",c),window.location.reload()}else{j.warn("setLocale: TemplateApp not found, falling back to page reload");try{localStorage.setItem("g7_locale",i)}catch{}window.location.reload()}}),this.registerHandler("suppress",async()=>{j.log("suppress: Error intentionally suppressed")}),this.registerBuiltInHandlerMetadata()}registerBuiltInHandlerMetadata(){const e=Fn();if(!e?.isEnabled())return;const n=[{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 a of n)e.trackHandlerRegistration(a.name,"built-in",a.description)}createHandler(e,n,a){j.log("createHandler called for:",e.handler,e.type);const i=window.__g7DevTools,l=Date.now(),c=a?.state?{...a.state}:null,d=`handler_${e.handler}_${l}`;return async f=>{if(j.log("Handler invoked for:",e.handler,"event:",f.type),i?.isEnabled?.()&&c){const m=window.G7Core?.state?.getLocal?.()??a?.state??{},y=Date.now()-l;for(const S of Object.keys(c)){const v=c[S],_=m[S];v!==_&&y>100&&(i.trackStaleClosureWarning?.({type:"event-handler-stale",location:`createHandler(${e.handler})`,capturedPath:`_local.${S}`,capturedValue:v,capturedAt:l,currentValue:_,actionId:d,stackTrace:new Error().stack}),j.warn(`[Stale Closure] _local.${S} changed after handler creation:`,`captured="${v}" → current="${_}" (${y}ms ago)`))}}try{f.type!=="change"&&f.preventDefault();let g={};if(f.type==="submit"&&f.target instanceof HTMLFormElement){const S=f.target;new FormData(S).forEach((_,A)=>{g[A]=_})}const m={...this.defaultContext,data:{...n,form:g,_local:a?.state||{},$event:f},event:f,...a&&{state:a.state,setState:a.setState},isolatedContext:a?.isolatedContext};if(e.confirm){let S=this.resolveValue(e.confirm,m.data);if(this.translationEngine&&this.translationContext&&S.startsWith("$t:")&&(S=this.translationEngine.resolveTranslations(S,this.translationContext,m.data)),!confirm(S))return}const y=window.__g7ActionContext;window.__g7ActionContext={...a,data:m.data};try{await this.executeAction(e,m)}finally{window.__g7ActionContext=y}}catch(g){if(j.error("Action execution failed:",g),e.onError){const m=g instanceof Bt&&g.originalError?g.originalError:g,y={...this.defaultContext,data:{...n,error:m,_local:a?.state||{},$event:f},event:f,...a&&{state:a.state,setState:a.setState}},S=Array.isArray(e.onError)?e.onError:[e.onError];for(const v of S)await this.executeAction(v,y)}}}}generateActionId(e,n){const a=e.handler,i=n||"no-target",l=Date.now(),c=Math.random().toString(36).substring(2,9);return`${a}_${i.replace(/[^a-zA-Z0-9]/g,"_")}_${l}_${c}`}async executeAction(e,n){if(e=this.resolveActionRef(e),typeof e.handler=="string"&&e.handler.includes("{{")){const f=this.evaluateExpression(e.handler,n.data);e={...e,handler:f==null?"":String(f)}}const a=Fn(),i=a?.isEnabled()?`action_${Date.now()}_${Math.random().toString(36).substring(2,11)}`:void 0,l=performance.now();let c;if(i&&a&&a.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),context:this.sanitizeForDevTools({hasState:!!n.state,hasSetState:!!n.setState,dataKeys:n.data?Object.keys(n.data):[]}),startTime:l,status:"started"}),e.if!==void 0)try{const f=this.resolveValue(e.if,n.data),g=f===!0||f==="true"||f&&f!=="false"&&f!=="0"&&f!==!1;if(j.log("[executeAction] if condition result:",e.handler,g),!g)return i&&a&&a.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 j.error("[executeAction] if condition error:",e.handler,f),i&&a&&a.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,n.data);i&&(c=this.sanitizeForDevTools(f));const g=e.target?this.resolveValue(e.target,n.data):void 0;if(e.handler==="apiCall"&&n.setState){d=this.generateActionId(e,g);const y=n.state?.loadingActions||{};n.setState({loadingActions:{...y,[d]:!0}})}if(this.previewMode&&ym.has(e.handler))return j.warn(`Preview mode: "${e.handler}" suppressed`,g||f),i&&a&&a.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 y=f.path||g;m=await this.handleNavigate(y,f,n);break;case"navigateBack":m=await this.handleNavigateBack();break;case"navigateForward":m=await this.handleNavigateForward();break;case"openWindow":{const _=f.path||g;m=await this.handleOpenWindow(_,f);break}case"replaceUrl":{const _=f.path||g||window.location.pathname;m=await this.handleReplaceUrl(_,f);break}case"apiCall":if(e.onSuccess&&a?.isEnabled()&&i){const _=window.G7Core,A={};if(_?.state?.get){const x=_.state.get();A._global=x}n.state&&(A._local=n.state),a.registerStateCaptureForHandler?.(i,["_global","_local"],A)}const S=e.auth_mode??(e.auth_required?"required":"none"),v=e.identity_target?this.resolveParams(e.identity_target,n.data):void 0;m=await this.handleApiCall(g,f,n,S,v);break;case"login":m=await this.handleLogin(g,f,n);break;case"logout":m=await this.handleLogout(g,n);break;case"setState":j.log("[executeAction] setState resolvedParams:",f),m=await this.handleSetState(e.render!==void 0?{...f,__render:e.render}:f,n);break;case"setError":m=await this.handleSetError(g,f,n);break;case"openModal":m=await this.handleOpenModal(g,n);break;case"closeModal":m=await this.handleCloseModal(n);break;case"showAlert":m=await this.handleShowAlert(g,n);break;case"toast":m=await this.handleToast(f,n);break;case"switch":m=await this.handleSwitch(e,n);break;case"conditions":m=await this.handleConditions(e,n);break;case"sequence":m=await this.handleSequence(e,n);break;case"parallel":m=await this.handleParallel(e,n);break;case"startInterval":m=this.handleStartInterval(f,n);break;case"stopInterval":m=this.handleStopInterval(f);break;case"loadScript":m=await this.handleLoadScript(f,e,n);break;case"callExternal":m=await this.handleCallExternal(f,e,n);break;case"callExternalEmbed":m=await this.handleCallExternalEmbed(f,e,n);break;case"saveToLocalStorage":m=await this.handleSaveToLocalStorage(f,n);break;case"loadFromLocalStorage":m=await this.handleLoadFromLocalStorage(f,n);break;default:m=await this.handleCustomAction({...e,target:g,params:f},n);break}if(e.resultTo&&m!==void 0){const{target:y,key:S,merge:v}=e.resultTo,_=this.resolveValue(S,n.data),A=v==="replace"?"replace":v==="shallow"?"shallow":"deep";if(y==="_local"&&n.setState){const x=this.buildNestedUpdate(_,m),O=A!=="deep"?{...x,__mergeMode:A}:x;n.setState(O),j.log(`[resultTo] Saved to _local.${_} (merge=${A}):`,m)}else if(y==="_local"&&this.globalStateUpdater){const M=(window.G7Core?.state?.get()||{})._local||{},T=this.buildNestedUpdate(_,m);let D;A==="replace"?D=T:A==="shallow"?D={...M,...T}:D=this.deepMergeWithState(T,M),this.globalStateUpdater({_local:D}),j.log(`[resultTo] Saved to _local.${_} via globalStateUpdater (merge=${A}):`,m)}else if(y==="_global"&&this.globalStateUpdater){const x=this.buildNestedUpdate(_,m);this.globalStateUpdater(x),j.log(`[resultTo] Saved to _global.${_}:`,m)}else if(y==="_isolated"&&n.isolatedContext){const x=this.buildNestedUpdate(_,m);n.isolatedContext.mergeState(x,A),j.log(`[resultTo] Saved to _isolated.${_} (merge=${A}):`,m)}else j.warn(`[resultTo] Cannot save result: target=${y}, setState=${!!n.setState}, globalStateUpdater=${!!this.globalStateUpdater}, isolatedContext=${!!n.isolatedContext}`)}if(e.onSuccess){if(a?.isEnabled()&&i&&e.handler==="apiCall"){const v=window.G7Core,_={};v?.state?.get&&(_._global=v.state.get()),n.state&&(_._local=n.state),a.detectStaleClosure?.(i,`${e.handler} → onSuccess`,_,"callback-state-capture",i)}const y={...n,data:{...n.data,result:m,response:m}},S=Array.isArray(e.onSuccess)?e.onSuccess:[e.onSuccess];S.length>1?await this.handleSequence({handler:"sequence",type:"click",actions:S},y):S.length===1&&await this.executeAction(S[0],y)}return i&&a&&a.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),resolvedParams:c,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 Bt?f:new Bt(`Failed to execute action: ${e.handler}`,e,f instanceof Error?f:void 0),m=g.originalError?.response||{},y=m.data||{},S=g.originalError?.status||m.status||500;let v=EC(g.originalError??f,e.handler,y.message,g.message);this.translationEngine&&this.translationContext&&v.startsWith("$t:")&&(v=this.translationEngine.resolveTranslations(v,this.translationContext));const _={status:S,message:v,errors:y.errors||m.errors,data:y,statusText:g.originalError?.statusText,error_code:y.error_code??m.error_code};if(g.unknownHandler)throw j.warn(`Unknown action handler "${e.handler}" — skipped (extension not loaded?). Not surfaced to the user.`),g;const x=Sr().resolve(S,{errorHandling:e.errorHandling,onError:e.onError});if(x.handler){if(a?.isEnabled()&&i&&e.handler==="apiCall"){const M=window.G7Core,T={};M?.state?.get&&(T._global=M.state.get()),n.state&&(T._local=n.state),a.detectStaleClosure?.(i,`${e.handler} → onError`,T,"callback-state-capture",i)}const O={...n,data:{...n.data,error:_}};try{const M={type:"click",handler:x.handler.handler,target:x.handler.target,params:x.handler.params,actions:x.handler.actions};return await this.executeAction(M,O),{success:!1,error:g}}catch(M){return j.error("Error executing error handler:",M),{success:!1,error:g}}}throw i&&a&&a.logAction({id:i,type:e.handler,params:this.sanitizeForDevTools(e.params),resolvedParams:c,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"&&n.setState&&d){const f=n.state?.loadingActions||{},{[d]:g,...m}=f;n.setState({loadingActions:m})}}}async handleNavigate(e,n,a){let i=e;if(n.query||n.mergeQuery===!0)if(n.mergeQuery===!0)i=this.buildMergedQueryPath(e,n.query??{});else{const c=new URLSearchParams;for(const[f,g]of Object.entries(n.query))if(g!=null&&g!=="")if(Array.isArray(g)){const m=f.endsWith("[]")?f:`${f}[]`;for(const y of g)y!=null&&y!==""&&c.append(m,String(y))}else c.set(f,String(g));const d=c.toString();d&&(i=`${e}?${d}`)}if(j.log("handleNavigate:",{target:e,params:n,finalPath:i,replace:n.replace,windowLocationSearch:window.location.search}),n.replace===!0){const c=window.G7Core;if(c?.updateQueryParams){const d=typeof n.transition_overlay_target=="string"?n.transition_overlay_target:void 0;await c.updateQueryParams(i,d?{transitionOverlayTarget:d}:void 0),j.log("handleNavigate: Used updateQueryParams for replace mode",d?{transitionOverlayTarget:d}:void 0),this.applyScrollOption(n.scroll,n.scrollBehavior,"top");return}j.warn("handleNavigate: G7Core.updateQueryParams not available, falling back to React Router")}const l=this.resolveNavigateFallbackAction(i,n);if(l){j.warn(`handleNavigate: No route matched, falling back to "${l.handler}"`),await this.dispatchAction({type:"click",handler:l.handler,params:l.params},a),this.applyScrollOption(n.scroll,n.scrollBehavior,"top");return}if(!a.navigate)throw new Bt("Navigate function is not provided in context");a.navigate(i,{replace:n.replace===!0}),this.applyScrollOption(n.scroll,n.scrollBehavior,"top")}resolveNavigateFallbackAction(e,n){const a=n.fallback;if(a===!1||n.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 c=e.split("?")[0];return l.match(c)?null:this.resolveNavigateFallback(a,e,n)}resolveNavigateFallback(e,n,a){return e==null?{handler:"openWindow",params:{path:n,target:"_self"}}:typeof e=="string"?{handler:e,params:{path:n}}:typeof e=="object"&&typeof e.handler=="string"?{handler:e.handler,params:{path:n,...e.params||{}}}:(j.warn("resolveNavigateFallback: unrecognized fallback option, using openWindow",e),{handler:"openWindow",params:{path:n,target:"_blank"}})}applyScrollOption(e,n,a){const i=e===void 0?a:e;if(i==="preserve")return;const l=n==="smooth"?"smooth":"instant",c=y=>{if(typeof y!="object"||y===null)return!1;const S=y;return"container"in S||"to"in S||"block"in S||"offset"in S},d=(y,S,v=0)=>{y===window?window.scrollTo({top:S,left:v,behavior:l}):y.scrollTo({top:S,left:v,behavior:l})},f=(y,S,v,_)=>{if(S===window){y.scrollIntoView({behavior:l,block:v}),_&&window.scrollBy({top:-_,left:0,behavior:l});return}const A=S,x=y.getBoundingClientRect(),O=A.getBoundingClientRect(),M=A.scrollTop+(x.top-O.top);let T;v==="center"?T=M-(A.clientHeight-y.clientHeight)/2:v==="end"?T=M-(A.clientHeight-y.clientHeight):T=M,T-=_,A.scrollTo({top:Math.max(0,T),left:0,behavior:l})},g=()=>{window.scrollTo({top:0,left:0,behavior:l});const y=document.getElementById("app")??document.body;if(!y)return;y.querySelectorAll("*").forEach(v=>{if(v.scrollTop===0&&v.scrollLeft===0)return;const _=window.getComputedStyle(v),A=_.overflowY,x=_.overflowX;(A==="auto"||A==="scroll"||x==="auto"||x==="scroll")&&v.scrollTo({top:0,left:0,behavior:l})})},m=()=>{try{if(c(i)){const y=i,S=y.block??"start",v=typeof y.offset=="number"?y.offset:0;let _=window;if(typeof y.container=="string"&&y.container.length>0){const x=document.querySelector(y.container);if(!x){j.warn(`applyScrollOption: container not found: ${y.container}`);return}_=x}const A=y.to??"top";if(A==="top"){_===window?g():d(_,0);return}if(typeof A=="number"){d(_,A-v);return}if(typeof A=="object"&&A!==null&&("x"in A||"y"in A)){const{x=0,y:O=0}=A;d(_,O-v,x);return}if(typeof A=="string"&&(A.startsWith("#")||A.startsWith("."))){const x=document.querySelector(A);x?f(x,_,S,v):j.warn(`applyScrollOption: target element not found: ${A}`);return}j.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:y=0,y:S=0}=i;window.scrollTo({top:S,left:y,behavior:l});return}if(typeof i=="string"&&(i.startsWith("#")||i.startsWith("."))){const y=document.querySelector(i);y&&y.scrollIntoView({behavior:l,block:"start"});return}}catch(y){j.warn("applyScrollOption: failed to apply scroll",y)}};typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame(m):m()}async handleOpenWindow(e,n){let a=e;if(n.query){const l=new URLSearchParams;for(const[d,f]of Object.entries(n.query))f!=null&&f!==""&&l.set(d,String(f));const c=l.toString();c&&(a=`${e}?${c}`)}const i=n.target==="_self"?"_self":"_blank";j.log("handleOpenWindow:",{target:e,params:n,finalPath:a,windowTarget:i}),i==="_self"?window.location.assign(a):window.open(a,"_blank")}async handleNavigateBack(){j.log("handleNavigateBack"),window.history.back()}async handleNavigateForward(){j.log("handleNavigateForward"),window.history.forward()}async handleReplaceUrl(e,n){let a=e;if(n.query||n.mergeQuery===!0)if(n.mergeQuery===!0)a=this.buildMergedQueryPath(e,n.query??{});else{const i=new URLSearchParams;for(const[c,d]of Object.entries(n.query))if(d!=null&&d!=="")if(Array.isArray(d)){const f=c.endsWith("[]")?c:`${c}[]`;for(const g of d)g!=null&&g!==""&&i.append(f,String(g))}else i.set(c,String(d));const l=i.toString();l&&(a=`${e}?${l}`)}j.log("handleReplaceUrl:",{target:e,params:n,finalPath:a}),window.history.replaceState(null,"",a),this.applyScrollOption(n.scroll,n.scrollBehavior,"preserve")}buildMergedQueryPath(e,n){const a=new URLSearchParams(window.location.search);for(const[c,d]of Object.entries(n))if(d==null||d==="")a.delete(c);else if(Array.isArray(d)){const f=c.endsWith("[]")?c:`${c}[]`;a.delete(c),a.delete(f);for(const g of d)g!=null&&g!==""&&a.append(f,String(g))}else a.set(c,String(d));const i=a.toString(),l=e.split("?")[0];return i?`${l}?${i}`:l}async ensureCsrfToken(){try{await fetch("/sanctum/csrf-cookie",{credentials:"include"})}catch(e){throw new Bt("Failed to fetch CSRF token",void 0,e instanceof Error?e:void 0)}}getCsrfTokenFromCookie(){const a=`; ${document.cookie}`.split("; XSRF-TOKEN=");if(a.length===2){const i=a.pop()?.split(";").shift();return i?decodeURIComponent(i):null}return null}buildQueryString(e){const n=new URLSearchParams;for(const[a,i]of Object.entries(e))if(!(i==null||i===""))if(Array.isArray(i))for(const l of i)l!=null&&l!==""&&n.append(`${a}[]`,String(l));else typeof i=="object"?n.append(a,JSON.stringify(i)):n.append(a,String(i));return n.toString()}async handleEnsureIdentityVerified(e){const n=typeof e.purpose=="string"?e.purpose:"sensitive_action",a=e.target&&typeof e.target=="object"?e.target:void 0;return await Et.handle({success:!1,error_code:"identity_verification_required",message:"",verification:{policy_key:e.policy_key??"",purpose:n,provider_id:e.provider_id??null,render_hint:e.render_hint??null,return_request:null}},void 0,a)!==null}handleResolveIdentityChallenge(e){const n=typeof e.result=="string"?e.result:"cancelled";let a;switch(n){case"verified":{const i=typeof e.token=="string"?e.token:"";if(!i){j.warn("resolveIdentityChallenge: result=verified 인데 token 이 비어있습니다. failed 로 강등합니다."),a={status:"failed",failureCode:"MISSING_TOKEN"};break}a={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){j.warn("resolveIdentityChallenge: result=pending 인데 pollUrl/expiresAt 누락 — failed 로 강등합니다."),a={status:"failed",failureCode:"MALFORMED_PENDING"};break}a={status:"pending",pollUrl:i,pollIntervalMs:typeof e.pollIntervalMs=="number"?e.pollIntervalMs:void 0,expiresAt:l};break}case"failed":a={status:"failed",failureCode:typeof e.failureCode=="string"?e.failureCode:"UNKNOWN",reason:typeof e.reason=="string"?e.reason:void 0};break;default:a={status:"cancelled"};break}return Et.resolveDeferred(a),!0}async handleApiCall(e,n,a,i="none",l){const{method:c="GET",body:d,headers:f,contentType:g}=n;c!=="GET"&&c!=="HEAD"&&await this.ensureCsrfToken();const m=this.getCsrfTokenFromCookie();let y={};if(i==="required"||i==="optional"){const W=Hr().getToken();W&&(y={Authorization:`Bearer ${W}`})}let S=e;const v=n.query||(c==="GET"?d:null);if(v&&typeof v=="object"){const q=this.buildQueryString(v);if(q){const W=e.includes("?")?"&":"?";S=`${e}${W}${q}`}}const _=window.G7Core?.state?.getGlobal?.()||a.state?._global||{},A=window.G7Core?.state?.getLocal?.()||a.state?._local||{},x={_global:_,_local:A},O=this.getMatchingGlobalHeaders(e,x),M={};if(typeof window<"u"){const q=localStorage.getItem("g7_locale");q&&(M["Accept-Language"]=q)}const T=g==="multipart/form-data",D={method:c,headers:{...T?{}:{"Content-Type":"application/json"},Accept:"application/json",...M,...m&&{"X-XSRF-TOKEN":m},...y,...O,...f},credentials:"include"};if(d&&c!=="GET")if(T){const q=new FormData;for(const[W,he]of Object.entries(d))he instanceof File||he instanceof Blob?q.append(W,he):he!=null&&q.append(W,typeof he=="object"?JSON.stringify(he):String(he));D.body=q}else D.body=JSON.stringify(d);const z=Fn();let P=null;z?.isEnabled()&&(P=z.trackRequest(S,c));try{let q=await fetch(S,D),W;try{W=await q.json()}catch{W=null}if(Et.isIdentityRequired(q.status,W)){const he=await Et.handle(W,{body:D.body,headers:D.headers,credentials:D.credentials},l);if(he){q=he;try{W=await q.json()}catch{W=null}}}if(P&&z?.isEnabled()&&(z.completeRequest(P,q.status,W),P=null),!q.ok){const he=W||{},Ee=new Error(he.message||`API call failed: ${q.statusText}`);throw Ee.response=he,Ee.status=q.status,Ee.statusText=q.statusText,new Bt(he.message||`API call failed: ${q.statusText}`,void 0,Ee)}return W}catch(q){throw P&&z?.isEnabled()&&z.failRequest(P,q instanceof Error?q.message:String(q)),q}}async handleLogin(e,n,a){const{body:i}=n;if(!i||!i.email||!i.password)throw new Bt("Login requires email and password in body params");const l=e==="user"?"user":"admin",c=l==="admin"?"/api/auth/admin/login":"/api/auth/login",d=window.G7Core?.state?.getGlobal?.()||a.state?._global||{},f=window.G7Core?.state?.getLocal?.()||a.state?._local||{},g={_global:d,_local:f},m=this.getMatchingGlobalHeaders(c,g),y=br.getInstance();try{const S=Object.keys(m).length>0?{headers:m}:void 0;return{user:await y.login(l,{email:i.email,password:i.password},S)}}catch(S){const v=S.message||"Login failed",_=new Error(v);throw _.response=S.response?.data||{},_.status=S.status||S.response?.status||500,new Bt(v,void 0,_)}}async handleLogout(e,n){await br.getInstance().logout()}async handleSetState(e,n){j.log("[handleSetState] START, params:",e);const{target:a="component",scope:i,merge:l,__render:c,...d}=e,f=Fn(),g=window.G7Core;if(typeof a=="string"&&(a.startsWith("$parent.")||a.startsWith("$root.")))return this.handleParentScopeSetState(a,d,l,n);const m=n.state&&Object.keys(n.state).length>0?n.state:g?.state?.get()||{},y=a==="global"?"_global":a.startsWith("_local.")?a:"_local",S=y==="_global"?m._global:y.startsWith("_local.")?this.getNestedProperty(m._local||{},y.slice(7)):m._local,v=f?.isEnabled()?f.startStateChange(y,S,d,{actionId:n.actionId,handlerType:"setState",source:`target=${a}`}):void 0,_=l==="replace"?"replace":l==="shallow"?"shallow":"deep",A=_!=="deep"?{...d,__mergeMode:_,...v?{__setStateId:v}:{}}:{...d,...v?{__setStateId:v}:{}};if(a==="global"){if(!this.globalStateUpdater){j.warn("Global state updater is not set"),v&&f&&f.completeStateChange(v);return}const x=g?.state?.get()||{},{__setStateId:O,__mergeMode:M,...T}=A,D=_==="deep"?this.deepMergeWithState(T,x):T,z={...D,...v?{__setStateId:v}:{},..._!=="deep"?{__mergeMode:_}:{}};return j.log("setState global:",z),this.globalStateUpdater(z,{render:c}),v&&f&&setTimeout(()=>f.completeStateChange(v),0),{__target:"global",..._!=="deep"?{__mergeMode:_}:{},...D}}else if(a==="isolated"){const x=n.isolatedContext;if(x){const{__mergeMode:O,__setStateId:M,...T}=A;return x.mergeState(T,_),j.log("[handleSetState] isolated state updated:",T,"mergeMode:",_),v&&f&&setTimeout(()=>f.completeStateChange(v),0),{__target:"isolated",...T}}else if(j.warn('[handleSetState] isolated target used but no IsolatedStateContext found. Make sure the component has "isolatedState" attribute. Falling back to local state.'),n.setState){const M=window.__g7PendingLocalState||n.state||{},T=_==="deep"?this.deepMergeWithState(A,M):A;return n.setState(T),v&&f&&setTimeout(()=>f.completeStateChange(v),0),T}else throw v&&f&&f.completeStateChange(v),new Bt("isolated target used but no IsolatedStateContext found and no setState function in context")}else if(a==="local"||a==="component"||a==="_local"){if(i==="parent"||i==="root"){const O=window.__g7LayoutContextStack||[];if(O.length>0){const M=i==="parent"?O[O.length-1]:O[0];if(M?.setState){const{__mergeMode:T,__setStateId:D,...z}=A,P=_==="deep"?this.deepMergeWithState(z,M.state||{}):z;return j.log(`[handleSetState] scope=${i}: 타겟 컨텍스트에 상태 업데이트`,P),M.setState(P),v&&f&&setTimeout(()=>f.completeStateChange(v),0),P}}j.warn(`[handleSetState] scope=${i}: 레이아웃 컨텍스트 스택이 비어있습니다. current로 폴백합니다.`)}const x=n.setState&&!n._isDispatchFallbackContext;if(j.log("[handleSetState] isRealComponentContext:",x,"context.setState:",!!n.setState,"_isDispatchFallbackContext:",n._isDispatchFallbackContext),x){j.log("[handleSetState] Using COMPONENT setState path"),j.log("[handleSetState] resolvedPayload:",A),j.log("[handleSetState] context.state:",n.state),j.log("[handleSetState] mergeMode:",_);const M=window.__g7PendingLocalState||n.state||{},T=_==="deep"?this.deepMergeWithState(A,{}):A;j.log("[handleSetState] convertedPayload (변경 필드만, dot notation 변환):",T),n.setState(T);const D=_==="deep"?this.deepMergeWithState(A,M):_==="shallow"?{...n.state||{},...A}:A,{__mergeMode:z,__setStateId:P,...q}=D;window.__g7PendingLocalState=q,j.log("[handleSetState] __g7PendingLocalState updated:",q),this.globalStateUpdater&&(this.globalStateUpdater({_local:q},{render:!1}),j.log("[handleSetState] _global._local synced (render:false):",q));const{__mergeMode:W,__setStateId:he,...Ee}=A;if(_==="replace")window.__g7ForcedLocalFields=Ee;else{const be=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=this.deepMergeWithState(Ee,be)}return j.log("[handleSetState] __g7ForcedLocalFields updated:",Ee),v&&f&&setTimeout(()=>f.completeStateChange(v),0),{__target:"local",...D}}else if(this.globalStateUpdater){j.log("[handleSetState] Using GLOBAL STATE UPDATER path for _local");const M=window.__g7PendingLocalState||m._local||{};j.log("[handleSetState] currentLocal (with pending):",M);const T=_==="deep"?this.deepMergeWithState(A,M):A;return j.log("[handleSetState] finalLocal (merged):",T),this.globalStateUpdater({_local:T},{render:c}),window.__g7PendingLocalState=T,j.log("[handleSetState] __g7PendingLocalState updated for globalStateUpdater path"),v&&f&&setTimeout(()=>f.completeStateChange(v),0),{__target:"local",...T}}else throw v&&f&&f.completeStateChange(v),new Bt("setState function is not provided in context and globalStateUpdater is not set")}else if(a.startsWith("_local.")){const x=a.slice(7),{__mergeMode:O,__setStateId:M,...T}=A,D=T.value!==void 0?T.value:Object.values(T)[0];if(n.setState){const P=window.__g7PendingLocalState||n.state||{},q=this.createNestedUpdate(x,D,P),W={...P,...q};return n.setState(q),v&&f&&setTimeout(()=>f.completeStateChange(v),0),W}else throw v&&f&&f.completeStateChange(v),new Bt("setState function is not provided in context")}else{if(!n.setState)throw v&&f&&f.completeStateChange(v),new Bt("setState function is not provided in context");const O=window.__g7PendingLocalState||n.state||{},M=_==="deep"?this.deepMergeWithState(A,O):A;return n.setState(M),v&&f&&setTimeout(()=>f.completeStateChange(v),0),M}}async handleParentScopeSetState(e,n,a,i){const l=Fn(),c=window.G7Core,d=a==="replace"?"replace":a==="shallow"?"shallow":"deep",f=e.startsWith("$parent."),g=f?"$parent.":"$root.",m=e.slice(g.length);let y,S;if(m==="_local"||m==="_global")y=m,S=void 0;else if(m.startsWith("_local."))y="_local",S=m.slice(7);else if(m.startsWith("_global."))y="_global",S=m.slice(8);else{j.warn(`[handleParentScopeSetState] 지원하지 않는 타겟 형식: ${e}. _local 또는 _global으로 시작해야 합니다.`);return}const v=window.__g7LayoutContextStack||[];if(v.length===0){j.warn(`[handleParentScopeSetState] 레이아웃 컨텍스트 스택이 비어있습니다. target=${e}`);return}const _=f?v[v.length-1]:v[0];if(!_){j.warn(`[handleParentScopeSetState] 타겟 컨텍스트를 찾을 수 없습니다. target=${e}`);return}const A=y==="_global"?_.state?._global:_.state?._local,x=l?.isEnabled()?l.startStateChange(e,A,n,{actionId:i.actionId,handlerType:"setState",source:`target=${e}`}):void 0,{__mergeMode:O,__setStateId:M,...T}=n;if(y==="_global"){if(!this.globalStateUpdater){j.warn("[handleParentScopeSetState] globalStateUpdater가 설정되지 않았습니다."),x&&l&&l.completeStateChange(x);return}const D=c?.state?.get()||{};if(S){const z=T.value!==void 0?T.value:Object.values(T)[0],P=this.createNestedUpdate(S,z,D),q={...D,...P};j.log(`[handleParentScopeSetState] ${e}: 전역 상태 중첩 경로 업데이트`,q),this.globalStateUpdater(q)}else{const z=d==="deep"?this.deepMergeWithState(T,D):T;j.log(`[handleParentScopeSetState] ${e}: 전역 상태 업데이트 (mergeMode=${d})`,z),this.globalStateUpdater(d!=="deep"?{...z,__mergeMode:d}:z)}return x&&l&&setTimeout(()=>l.completeStateChange(x),0),{__target:e,...T}}else{if(!_.setState){j.warn(`[handleParentScopeSetState] 타겟 컨텍스트에 setState가 없습니다. target=${e}`),x&&l&&l.completeStateChange(x);return}const D=_.state||{};if(S){const z=T.value!==void 0?T.value:Object.values(T)[0],P=this.createNestedUpdate(S,z,D),q={...D,...P};return j.log(`[handleParentScopeSetState] ${e}: 로컬 상태 중첩 경로 업데이트`,P),_.setState(P),_.state=q,_.dataContext&&(_.dataContext._local=q),Gd(),x&&l&&setTimeout(()=>l.completeStateChange(x),0),q}else{const z=d!=="deep"?{...T,__mergeMode:d}:T,P=d==="replace"?T:d==="shallow"?{...D,...T}:this.deepMergeWithState(T,D);return j.log(`[handleParentScopeSetState] ${e}: 로컬 상태 업데이트 (mergeMode=${d})`,P),_.setState(z),_.state=P,_.dataContext&&(_.dataContext._local=P),Gd(),x&&l&&setTimeout(()=>l.completeStateChange(x),0),P}}}deepMergeWithState(e,n){const a=["errors"];let i=e;if("..."in e){const c=e["..."];if(c&&typeof c=="object"&&!Array.isArray(c)){const{"...":d,...f}=e;i={...c,...f}}else{const{"...":d,...f}=e;i=f}}const l={...n};for(const[c,d]of Object.entries(i)){if(a.includes(c)){l[c]=d;continue}if(c.includes(".")&&c!=="..."){const f=this.createNestedUpdate(c,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[c]=d;continue}d!==null&&typeof d=="object"&&!Array.isArray(d)&&n[c]!==null&&typeof n[c]=="object"&&!Array.isArray(n[c])?l[c]=this.deepMergeWithState(d,n[c]):l[c]=d}return l}deepMergeInto(e,n,a){for(const[i,l]of Object.entries(n)){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]===a[i]&&(e[i]={...e[i]}),this.deepMergeInto(e[i],l,a[i]||{})):typeof l=="object"&&!Array.isArray(l)&&e[i]===void 0&&a[i]!==null&&typeof a[i]=="object"&&!Array.isArray(a[i])?e[i]={...a[i],...l}:e[i]=l}}createNestedUpdate(e,n,a){const i=e.split(".");if(i.length===1)return{[i[0]]:n};const l={};let c=l,d=a;for(let f=0;f{this.globalStateUpdater({_local:v})};m.push({state:y,setState:S,dataContext:{_local:y||n.data?._local,_global:l?n.data?._global:n.data?._global||i?.state?.get?.(),_computed:n.data?._computed}}),window.__g7LayoutContextStack=m,j.log(`[handleOpenModal] 레이아웃 컨텍스트 스택에 push, 스택 크기: ${m.length}, state:`,y,l?"(direct)":"(fallback via G7Core)")}else j.warn(`[handleOpenModal] 컨텍스트 스택에 push 실패 - setState: ${!!n.setState}, state: ${n.state!==void 0}, G7Core: ${!!i?.state?.getLocal}`);const f=[...a,e];this.globalStateUpdater({modalStack:f,activeModal:e});const g=Fn();if(g?.isEnabled()){const m=a.length>0?a[a.length-1]:void 0;g.trackModalOpen?.({modalId:e,modalName:e,scopeType:"isolated",parentModalId:m,initialState:n.state?{...n.state}:{}})}}async handleCloseModal(e){if(!this.globalStateUpdater){j.warn("Global state updater is not set for closeModal");return}const n=e?.data?._global?.modalStack||[],a=n.length>0?n[n.length-1]:null,i=n.slice(0,-1),l=i.length>0?i[i.length-1]:null,c=window.__g7LayoutContextStack||[];if(c.length>0){const d=c[c.length-1];d&&(d.dataContext=void 0),c.pop(),window.__g7LayoutContextStack=c,j.log(`[handleCloseModal] 레이아웃 컨텍스트 스택에서 pop, 스택 크기: ${c.length}`)}if(a){const d=Fn();d?.isEnabled()&&d.trackModalClose?.(a,e?.state)}this.globalStateUpdater({modalStack:i,activeModal:l})}async handleShowAlert(e,n){let a=e;this.translationEngine&&this.translationContext&&e.startsWith("$t:")&&(a=this.translationEngine.resolveTranslations(e,this.translationContext,n.data)),alert(a)}async handleToast(e,n){const{type:a="info",message:i,icon:l,duration:c}=e;if(a==="error"){const f=n.data?.error;if((f?.error_code==="identity_verification_required"||f?.data?.error_code==="identity_verification_required")&&Et.consumeDomainNoticeShown()){j.log("[Toast] IDV 도메인 안내 표출됨 — 중복 가드 토스트 1건 skip");return}}let d=i;if(this.translationEngine&&this.translationContext&&i?.startsWith("$t:")&&(d=this.translationEngine.resolveTranslations(i,this.translationContext,n.data)),this.globalStateUpdater){const g={id:`toast_${Date.now()}_${Math.random().toString(36).substring(2,9)}`,type:a,message:d,...l&&{icon:l},...c&&{duration:c}},v=[...window.G7Core?.state?.get()?.toasts||[],g];this.globalStateUpdater({toasts:v})}else j.log(`[Toast ${a}] ${d}`)}async handleSwitch(e,n){const{cases:a}=e;if(!a){j.warn("switch handler requires cases property");return}const i=this.resolveParams(e.params,n.data);let l;if(i?.value!==void 0?(l=i.value,j.log("switch handler: using params.value as case key:",l)):(l=n.data?.$args?.[0],j.log("switch handler: using $args[0] as case key:",l)),l==null){if(a.default)return j.log("switch handler: case key is undefined, using default case"),await this.executeAction(a.default,n);j.warn("switch handler: case key is not defined and no default case");return}const c=String(l);let d=a[c];if(!d&&a.default&&(j.log(`switch handler: no case found for key "${c}", using default case`),d=a.default),!d){j.warn(`switch handler: no case found for key "${c}" and no default case`);return}return await this.executeAction(d,n)}async handleConditions(e,n){const{conditions:a}=e;if(!a||!Array.isArray(a)){j.warn("conditions handler requires conditions array");return}const i=n.data||{},l=Sp(a,i,this.bindingEngine);if(!l.matched){j.log("conditions handler: no matching branch found");return}const c=a[l.branchIndex];if(j.log(`conditions handler: matched branch ${l.branchIndex}`),!c.then){j.warn('conditions handler: matched branch has no "then" action');return}return Array.isArray(c.then)?await this.handleSequence({...e,actions:c.then},n):await this.executeAction(c.then,n)}handleStartInterval(e,n){const a=typeof e.id=="string"?e.id:"",i=Number(e.intervalMs??1e3),l=Array.isArray(e.actions)?e.actions:[];if(a===""||!l.length||i<=0)return j.warn("startInterval requires non-empty id, positive intervalMs, and actions array"),{success:!1};const c=this.intervals.get(a);c&&(clearInterval(c),this.intervals.delete(a));const d=setInterval(()=>{for(const f of l)this.executeAction(f,n).catch(g=>{j.error(`[startInterval:${a}] tick action failed`,g)})},i);return this.intervals.set(a,d),{success:!0,id:a}}handleStopInterval(e){const n=typeof e.id=="string"?e.id:"";if(n==="")return j.warn("stopInterval requires id parameter"),{success:!1};const a=this.intervals.get(n);return a&&(clearInterval(a),this.intervals.delete(n)),{success:!0,id:n}}stopAllIntervals(){for(const e of this.intervals.values())clearInterval(e);this.intervals.clear()}async handleSequence(e,n){const a=e.actions||e.params?.actions;if(!a||!Array.isArray(a)||a.length===0)return j.warn("sequence handler requires non-empty actions array"),[];const i=Fn(),l=i?.isEnabled()&&i.startSequenceExecution?.({eventType:e.type})||"";window.__g7SequenceLocalSync=void 0;const c=[];let d,f=n.state?{...n.state}:{},g=n.isolatedContext?.state?{...n.isolatedContext.state}:{},m=n.data?._computed||{};const y=window.G7Core,S=()=>({_global:y?.state?.get()||{},_local:{...f},_isolated:Object.keys(g).length>0?{...g}:void 0});for(let v=0;v0){const T={},D={...n.data,_local:f,_computed:T,$computed:T,_isolated:g};for(const[z,P]of Object.entries(M))if(typeof P=="string"){const q=P.trim();if(q.startsWith("{{")&&q.endsWith("}}"))try{const W=q.slice(2,-2).trim();T[z]=Vn(W)?this.bindingEngine.evaluatePipeExpression(W,D,{skipCache:!0}):this.bindingEngine.evaluateExpression(W,D,{skipCache:!0})}catch{T[z]=m[z]}}m=T,j.log("[handleSequence] _computed recalculated after setState:",m)}}if(_.handler!=="setState"){const M=window.__g7SequenceLocalSync;if(M&&M!==f){f=M,window.__g7SequenceLocalSync=void 0,j.log("[handleSequence] currentState synchronized from __g7SequenceLocalSync after custom handler:",_.handler);const T=n.data?._computedDefinitions;if(T&&Object.keys(T).length>0){const D={},z={...n.data,_local:f,_computed:D,$computed:D,_isolated:g};for(const[P,q]of Object.entries(T))if(typeof q=="string"){const W=q.trim();if(W.startsWith("{{")&&W.endsWith("}}"))try{const he=W.slice(2,-2).trim();D[P]=Vn(he)?this.bindingEngine.evaluatePipeExpression(he,z,{skipCache:!0}):this.bindingEngine.evaluateExpression(he,z,{skipCache:!0})}catch{D[P]=m[P]}}m=D,j.log("[handleSequence] _computed recalculated after custom handler:",m)}}}l&&i?.isEnabled()&&i.captureSequenceActionAfter?.(l,v,S(),Date.now()-A,O.data)}catch(O){throw l&&i?.isEnabled()&&(i.captureSequenceActionAfter?.(l,v,S(),Date.now()-A,void 0,O),i.endSequenceExecution?.(l,O)),j.error(`sequence handler: action[${v}] failed:`,O),O}}return window.__g7SequenceLocalSync=void 0,l&&i?.isEnabled()&&i.endSequenceExecution?.(l),c}async handleParallel(e,n){const a=e.actions||e.params?.actions;if(!a||!Array.isArray(a)||a.length===0)return j.warn("parallel handler requires non-empty actions array"),[];j.log(`parallel handler: executing ${a.length} actions in parallel`);const i=n.isolatedContext?{...n.isolatedContext,state:{...n.isolatedContext.state}}:null,l=a.map((f,g)=>{const m={...n,isolatedContext:i};return this.executeAction(f,m).catch(y=>{throw j.error(`parallel handler: action[${g}] failed:`,y),y})}),c=await Promise.allSettled(l),d=c.filter(f=>f.status==="rejected").length;return d>0&&j.warn(`parallel handler: ${d}/${a.length} actions failed`),c}async handleLoadScript(e,n,a){const{src:i,id:l,async:c=!0,defer:d=!1}=e;if(!i)throw new Bt('loadScript handler requires "src" parameter',n);const f=l||`script_${i.replace(/[^a-zA-Z0-9]/g,"_")}`;return bs.loadedScripts.has(f)?(j.log(`loadScript: script already loaded, skipping: ${f}`),n.onLoad&&await this.executeAction(n.onLoad,a),!0):document.getElementById(f)?(j.log(`loadScript: script element already exists: ${f}`),bs.loadedScripts.add(f),n.onLoad&&await this.executeAction(n.onLoad,a),!0):(j.log(`loadScript: loading script: ${i}`),new Promise((m,y)=>{const S=document.createElement("script");S.id=f,S.src=i,S.async=c,S.defer=d,S.onload=async()=>{if(j.log(`loadScript: script loaded successfully: ${f}`),bs.loadedScripts.add(f),n.onLoad)try{await this.executeAction(n.onLoad,a)}catch(v){j.error("loadScript: onLoad action failed:",v)}m(!0)},S.onerror=v=>{j.error(`loadScript: failed to load script: ${i}`,v),y(new Bt(`Failed to load script: ${i}`,n))},document.head.appendChild(S)}))}async handleCallExternal(e,n,a){const i=e.constructor,l=e.args||{},c=e.method,d=e.methodArgs||[],f=e.callbackEvent,g=e.embedTarget,m=e.callbackSetState,y=e.callbackAction;if(!i)throw new Bt('callExternal handler requires "constructor" parameter',n);const S=this.getNestedProperty(window,i);if(!S||typeof S!="function")throw new Bt(`Constructor not found or not a function: ${i}. Make sure the script is loaded first using loadScript handler.`,n);j.log(`callExternal: calling constructor ${i}`);const v={...l};for(const[A,x]of Object.entries(l))x===!0&&(v[A]=O=>{if(j.log(`callExternal: callback triggered for ${A}`,O),f&&typeof window<"u"&&window.G7Core?.componentEvent&&window.G7Core.componentEvent.emit(f,O),m&&a.setState){const M=z=>{const P={};for(const[q,W]of Object.entries(z))typeof W=="string"?P[q]=this.getNestedProperty(O,W):typeof W=="object"&&W!==null&&(P[q]=M(W));return P},T=M(m);j.log("callExternal: callbackSetState mapping result",T);const D=this.deepMergeWithState(T,a.state||{});j.log("callExternal: merged with existing state",D),a.setState(D)}else f&&a.setState&&a.setState({[`${f.replace(/:/g,"_")}_result`]:O});if(y){const M={...a,data:{...a.data,$event:O}},T=Array.isArray(y)?y:[y];for(const D of T)try{this.executeAction(D,M)}catch(z){j.error("callExternal: callbackAction failed:",z)}}});const _=new S(v);if(c&&typeof _[c]=="function"){if(j.log(`callExternal: calling method ${c}`),c==="embed"&&g){const A=document.querySelector(g);if(A)return _[c](A,...d);throw new Bt(`Embed target element not found: ${g}`,n)}return _[c](...d)}return _}async handleCallExternalEmbed(e,n,a){const i=e.constructor,l=e.args||{},c=e.callbackSetState,d=e.callbackEvent,f=e.layerClassName,g=e.callbackAction;if(!i)throw new Bt('callExternalEmbed handler requires "constructor" parameter',n);const m=this.getNestedProperty(window,i);if(!m||typeof m!="function")throw new Bt(`Constructor not found or not a function: ${i}. Make sure the script is loaded first.`,n);j.log(`callExternalEmbed: creating layer for ${i}`);const{layer:y,closeLayer:S}=this.createEmbedLayer(f),v={...l};for(const[A,x]of Object.entries(l))x===!0&&(v[A]=O=>{if(j.log(`callExternalEmbed: callback triggered for ${A}`,O),S(),d&&typeof window<"u"&&window.G7Core?.componentEvent&&window.G7Core.componentEvent.emit(d,O),c&&a.setState){const M=z=>{const P={};for(const[q,W]of Object.entries(z))typeof W=="string"?P[q]=this.getNestedProperty(O,W):typeof W=="object"&&W!==null&&(P[q]=M(W));return P},T=M(c);j.log("callExternalEmbed: callbackSetState mapping result",T);const D=this.deepMergeWithState(T,a.state||{});j.log("callExternalEmbed: merged with existing state",D),a.setState(D)}if(g){const M={...a,data:{...a.data,$event:O}},T=Array.isArray(g)?g:[g];for(const D of T)try{this.executeAction(D,M)}catch(z){j.error("callExternalEmbed: callbackAction failed:",z)}}});const _=new m(v);if(typeof _.embed=="function")_.embed(y),j.log("callExternalEmbed: embedded in layer");else throw S(),new Bt(`Constructor ${i} does not have embed method`,n);return _}isImeComposing(e){return e?.isComposing===!0||e?.keyCode===229}createEmbedLayer(e){const n=document.createElement("div");n.id="g7-embed-overlay",n.style.cssText=` position: fixed; inset: 0; background-color: rgba(0, 0, 0, 0.5); @@ -47,11 +47,11 @@ Error generating stack: `+u.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=()=>{n.parentNode&&n.parentNode.removeChild(n)};i.onclick=l;const c=d=>{this.isImeComposing(d)||d.key==="Escape"&&(l(),document.removeEventListener("keydown",c))};return document.addEventListener("keydown",c),n.onclick=d=>{d.target===n&&l()},a.appendChild(i),n.appendChild(a),document.body.appendChild(n),{overlay:n,layer:a,closeLayer:l}}getNestedProperty(e,n){return n.split(".").reduce((a,i)=>a&&a[i]!==void 0?a[i]:void 0,e)}async handleSaveToLocalStorage(e,n){const{key:a,value:i}=e;if(!a)return z.error("saveToLocalStorage: key parameter is required"),!1;try{const l=typeof i=="string"?i:JSON.stringify(i);return localStorage.setItem(a,l),z.log(`saveToLocalStorage: saved ${a}`,i),!0}catch(l){return z.error("saveToLocalStorage: failed to save",{key:a,error:l}),!1}}async handleLoadFromLocalStorage(e,n){const{key:a,target:i,stateKey:l,defaultValue:c}=e;if(!a)return z.error("loadFromLocalStorage: key parameter is required"),c;try{const d=localStorage.getItem(a);if(d===null)return z.log(`loadFromLocalStorage: no value found for ${a}, using default`),l&&n.setState&&n.setState({[l]:c}),c;let f;try{f=JSON.parse(d)}catch{f=d}return z.log(`loadFromLocalStorage: loaded ${a}`,f),l&&n.setState&&n.setState({[l]:f}),f}catch(d){return z.error("loadFromLocalStorage: failed to load",{key:a,error:d}),c}}async handleCustomAction(e,n){const a=this.customHandlers.get(e.handler);if(!a){if(this.previewMode){z.warn(`[Preview] Unknown action handler "${e.handler}" — skipped (preview mode)`);return}const i=new jt(`Unknown action handler: ${e.handler}`,e);throw i.unknownHandler=!0,i}return await a(e,n)}resolveParams(e,n){if(!e)return{};const a={};for(const[i,l]of Object.entries(e))i.includes("{{")&&z.warn(`[resolveParams] setState params의 키에 표현식이 포함되어 있습니다: "${i}". 키는 해석되지 않습니다. 배열 항목 수정은 .map()/.filter() 패턴을 사용하세요.`),typeof l=="string"&&l.includes("{{")?a[i]=this.evaluateExpression(l,n):typeof l=="string"?a[i]=l:Array.isArray(l)?a[i]=l.map(c=>typeof c=="string"&&c.includes("{{")?this.evaluateExpression(c,n):c):typeof l=="object"&&l!==null&&!Array.isArray(l)&&Object.getPrototypeOf(l)!==Object.prototype&&Object.getPrototypeOf(l)!==null?a[i]=l:typeof l=="object"&&l!==null?a[i]=this.resolveParams(l,n):a[i]=l;return a}resolveValue(e,n){return n?this.bindingEngine.resolveBindings(e,n,{skipCache:!0}):e}evaluateExpressions(e,n){let a={};for(const[i,l]of Object.entries(e))if(i==="..."){let c=l;typeof l=="string"&&l.includes("{{")&&(c=this.evaluateExpression(l,n)),c&&typeof c=="object"&&!Array.isArray(c)&&(a={...a,...c})}else typeof l=="string"&&l.includes("{{")?a[i]=this.evaluateExpression(l,n):typeof l=="object"&&l!==null&&!Array.isArray(l)?a[i]=this.evaluateExpressions(l,n):a[i]=l;return a}evaluateExpressionsIfNeeded(e,n){const a={};for(const[i,l]of Object.entries(e))typeof l=="string"&&l.includes("{{")?a[i]=this.evaluateExpression(l,n):a[i]=l;return a}evaluateExpression(e,n){if(!n)return e;const a=Aa(e);if(a===null){let c=n;if(e.includes("_global")){const f=window.G7Core?.state?.get()?._global;f&&(c={...n,_global:f})}if(e.includes("_computed")||e.includes("$computed")){const f=window.__g7ActionContext?.computedRef?.current;f&&Object.keys(f).length>0&&(c={...c,_computed:f,$computed:f})}return this.bindingEngine.resolveBindings(e,c,{skipCache:!0})}let i=a;i=i.replace(/\$args\.(\d+)/g,"$args[$1]");let l=n;if(i.includes("_global")){const d=window.G7Core?.state?.get()?._global;d&&(l={...n,_global:d})}if(i.includes("_computed")||i.includes("$computed")){const d=window.__g7ActionContext?.computedRef?.current;d&&Object.keys(d).length>0&&(l={...l,_computed:d,$computed:d})}i.includes("_global.modules")&&(z.log("[evaluateExpression] expression:",i),z.log("[evaluateExpression] dataContext._global:",l._global),z.log("[evaluateExpression] dataContext._global?.modules:",l._global?.modules));try{const c=Pn(i)?this.bindingEngine.evaluatePipeExpression(i,l,{skipCache:!0}):this.bindingEngine.evaluateExpression(i,l);return i.includes("_global.modules")&&z.log("[evaluateExpression] result:",c),typeof c=="string"&&c.startsWith("$t:")&&this.translationEngine&&this.translationContext?this.translationEngine.resolveTranslations(c,this.translationContext,n):c}catch(c){return z.error("Expression evaluation failed:",e,c),e}}setDefaultContext(e){this.defaultContext={...this.defaultContext,...e}}setGlobalStateUpdater(e){this.globalStateUpdater=e}getGlobalStateUpdater(){return this.globalStateUpdater}async dispatchAction(e,n){const a={...this.defaultContext,...n,data:{...this.defaultContext.data,...n?.data}};if(e.confirm){let i=this.resolveValue(e.confirm,a.data);if(this.translationEngine&&this.translationContext&&i.startsWith("$t:")&&(i=this.translationEngine.resolveTranslations(i,this.translationContext,a.data)),!confirm(i))return{success:!1}}try{return await this.executeAction(e,a)}catch(i){if(z.error("dispatchAction failed:",i),e.onError){const l=i instanceof jt&&i.originalError?{message:i.originalError.message,response:i.originalError.response}:{message:i instanceof Error?i.message:String(i)},c={...a,data:{...a.data,error:l}},d=Array.isArray(e.onError)?e.onError:[e.onError];for(const f of d)await this.executeAction(f,c)}return{success:!1,error:i instanceof Error?i:new Error(String(i))}}}registerHandler(e,n,a){this.customHandlers.set(e,n);const i=qn();i?.isEnabled()&&i.trackHandlerRegistration(e,a?.category??"custom",a?.description,a?.source)}unregisterHandler(e){this.customHandlers.delete(e);const n=qn();n?.isEnabled()&&n.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 n=e.target;if(n&&!("tagName"in n)){const l={type:e.type??"custom",target:{value:n.value,name:n.name??""}};return e._changedKeys&&(l._changedKeys=e._changedKeys),l}const i=n?{value:n.value,name:n.name??"",checked:n.checked??!1,type:n.type??"",tagName:n.tagName}:{};if(e.type==="scroll"&&n){const l=n;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:n?i:null}}executeDebouncedAction(e,n,a,i,l){const c={...a,$event:n,$args:l},d={type:n.type,target:n.target,preventDefault:()=>{},stopPropagation:()=>{}};this.createHandler(e,c,i)(d)}handleDebouncedAction(e,n,a,i,l,c){const d=this.normalizeDebounceConfig(e.debounce),f=l||`default-${e.handler}-${Date.now()}`,g=this.extractEventData(n),m=g._changedKeys;if(m&&Array.isArray(m)&&g?.target?.value&&typeof g.target.value=="object"&&!Array.isArray(g.target.value)){const _=this.debounceAccumulatedValues.get(f);if(_){const A={..._};for(const x of m)A[x]=g.target.value[x];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 S=qn();S?.isEnabled()&&S.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 v=!this.debounceTimers.has(f+"_leading");if(d.leading&&v&&(this.debounceTimers.set(f+"_leading",setTimeout(()=>{},0)),this.executeDebouncedAction(e,g,a,i,c),S?.isEnabled()&&S.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 _=()=>{this.executeDebouncedAction(e,g,a,i,c),S?.isEnabled()&&S.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),_()},d.delay);this.debounceTimers.set(f,A),this.pendingDebounceFlushers.set(f,_)}}clearDebounceTimers(e){if(e)for(const[n,a]of this.debounceTimers)n.startsWith(e+"-")&&(clearTimeout(a),this.debounceTimers.delete(n),this.pendingDebounceFlushers.delete(n),this.debounceAccumulatedValues.delete(n));else{for(const n of this.debounceTimers.values())clearTimeout(n);this.debounceTimers.clear(),this.pendingDebounceFlushers.clear(),this.debounceAccumulatedValues.clear()}}debouncedCall(e,n,a){const i=this.debounceTimers.get(e);i&&(clearTimeout(i),this.debounceTimers.delete(e));const l=setTimeout(()=>{this.debounceTimers.delete(e),this.pendingDebounceFlushers.delete(e),a()},n);this.debounceTimers.set(e,l),this.pendingDebounceFlushers.set(e,a)}flushPendingDebounceTimers(){if(this.pendingDebounceFlushers.size===0)return;const e=new Map(this.pendingDebounceFlushers);for(const[n,a]of e){const i=this.debounceTimers.get(n);i&&(clearTimeout(i),this.debounceTimers.delete(n)),this.debounceTimers.delete(n+"_leading"),this.pendingDebounceFlushers.delete(n),a()}this.globalStateUpdater&&this.globalStateUpdater({})}bindActionsToProps(e,n,a){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),S=b.event||this.getEventHandlerName(b.type);l.has(S)||l.set(S,[]),l.get(S).push(b)}const c=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]=(...S)=>{for(const v of b){const _=S[0],A=_&&typeof _=="object"&&"preventDefault"in _;if(A&&(m==="onDragOver"||m==="onDrop")&&_.preventDefault(),A&&v.key&&"key"in _){if(this.isImeComposing(_)){z.log("Key filter skipped (IME composing):",v.key);continue}if(_.key!==v.key){z.log("Key filter not matched:",v.key,"actual:",_.key);continue}z.log("Key filter matched:",v.key)}if(v.debounce){const x=`${c}-${v.handler}-${m}`,L=_&&typeof _=="object"&&!("preventDefault"in _)&&"target"in _&&_.target!==null;let M;if(A)M=_;else if(L){const D={type:"custom",target:_.target,preventDefault:()=>{},stopPropagation:()=>{}};_._changedKeys&&(D._changedKeys=_._changedKeys),M=D}else M=new Event("custom");const R=v.event?{...n,$args:S}:n;this.handleDebouncedAction(v,M,R,a,x,S)}else if(this.flushPendingDebounceTimers(),v.event){const x={...n,$args:S},L=A?_:new Event("custom");this.createHandler(v,x,a)(L)}else if(A)this.createHandler(v,n,a)(_);else if(_&&typeof _=="object"&&!("preventDefault"in _)&&"target"in _&&_.target!==null){const L={type:"custom",target:_.target,preventDefault:()=>{},stopPropagation:()=>{}};this.createHandler(v,n,a)(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,n=5){const a=new WeakSet,i=(l,c)=>{if(l==null||typeof l=="string"||typeof l=="number"||typeof l=="boolean")return l;if(c>n)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(a.has(l))return"[Circular Array]";a.add(l);const d=l.slice(0,10).map(f=>i(f,c+1));return l.length>10&&d.push(`... ${l.length-10} more items`),d}if(typeof l=="object"){if(a.has(l))return"[Circular Reference]";a.add(l);const d={},f=Object.keys(l),g=f.slice(0,20);for(const m of g)try{d[m]=i(l[m],c+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)}};$(ps,"loadedScripts",new Set);let po=ps,Zl=null;function cm(o){return Zl||(Zl=new po(o)),Zl}function cC(o){Zl=o}const um=ut("TransitionManager");class uC{constructor(){$(this,"isPending",!1);$(this,"subscribers",new Set)}setPending(e){this.isPending!==e&&(um.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(){um.log("notifySubscribers:",{isPending:this.isPending,subscriberCount:this.subscribers.size}),this.subscribers.forEach(e=>{e(this.isPending)})}clearSubscribers(){this.subscribers.clear()}}const Hr=new uC,ec=ut("TransitionContext"),dm=N.createContext({isTransitioning:!1}),Bd=({children:o})=>{const[e,n]=N.useState(()=>{const i=Hr.getIsPending();return ec.log("Initial state:",i),i});N.useEffect(()=>{ec.log("Subscribing to TransitionManager");const i=Hr.subscribe(l=>{ec.log("Received isPending update:",l),n(l)});return()=>{ec.log("Unsubscribing from TransitionManager"),i()}},[]);const a=N.useMemo(()=>({isTransitioning:e}),[e]);return dt.jsx(dm.Provider,{value:a,children:o})},fm=()=>N.useContext(dm),tc="__g7LocalInitTracking";function Pd(){const o=globalThis;return o[tc]||(o[tc]={hash:"",timestamp:void 0,consumed:void 0}),o[tc]}function dC(){const o=globalThis;o[tc]={hash:"",timestamp:void 0,consumed:void 0}}function fC(o){Pd().consumed=o}function hC(o){return Pd().consumed===o}function gC(o){return o.globalTrackedKey!==o.trackingKey?"apply":o.instanceHandledKey===o.trackingKey?"skip":"prune"}function pC(o,e){return typeof o=="number"&&typeof e=="number"?Math.max(o,e):e??o}function mC(o,e){if(e===void 0)return o;if(!(o!==null&&typeof o=="object"&&e!==null&&typeof e=="object"&&!hC(o)))return e;const{_forceLocalInit:a,...i}=o,{_forceLocalInit:l,...c}=e,d={...i,...c},f=pC(a,l);return f!==void 0&&(d._forceLocalInit=f),d}function yC(o){return o<768?"mobile":o<1024?"tablet":"desktop"}function hm(o){const e=yC(o);return{width:o,isMobile:e==="mobile",isTablet:e==="tablet",isDesktop:e==="desktop",matchedPreset:e}}const qd=N.createContext(hm(1024)),nc=({children:o,overrideWidth:e})=>{const[n,a]=N.useState(()=>hi.getWidth());N.useEffect(()=>{const c=hi.subscribe(d=>{a(d)});return()=>{c()}},[]);const i=e??n,l=N.useMemo(()=>hm(i),[i]);return dt.jsx(qd.Provider,{value:l,children:o})},Gd=()=>N.useContext(qd);window.G7Core?.createLogger?.("Core:State");function bC(o,e,n,a){const{syncOnControlledChange:i=!0,isEqual:l}=a??{},c=o!==void 0;N.useRef(c);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&&c&&o!==m.current&&(l?!l(d,o):d!==o)&&f(o),m.current=o},[o,c,i,l,d]);const S=N.useCallback(v=>{const _=typeof v=="function"?v(g):v;(l?l(g,_):g===_)||(b.current=!0,f(_),n?.(_),requestAnimationFrame(()=>{b.current=!1}))},[g,c,n,l]);return[g,S]}function vC(o,e){return o===e?!0:o.length!==e.length?!1:o.every((n,a)=>n===e[a])}function gm(o,e){if(o===e)return!0;const n=Object.keys(o),a=Object.keys(e);return n.length!==a.length?!1:n.every(i=>o[i]===e[i])}const pm=N.createContext({}),SC=({children:o,value:e})=>dt.jsx(pm.Provider,{value:e,children:o}),wC=()=>N.useContext(pm),CC=(o,e)=>{if(!o)return;const n=e.split(".");let a=o;for(const i of n){if(a==null)return;a=a[i]}return a},EC=(o,e,n)=>{const a=e.split(".");if(a.length===1)return{...o,[a[0]]:n};const i={...o};let l=i;for(let c=0;c{os.warn("IsolatedStateContext not available: setState called outside IsolatedStateProvider")},getState:()=>{},mergeState:()=>{os.warn("IsolatedStateContext not available: mergeState called outside IsolatedStateProvider")},stateRef:{current:{}},scopeId:""},mm=N.createContext(_C);let AC=0;function xC(){return`isolated-${++AC}-${Date.now().toString(36)}`}function ym(o,e){if(e==null)return o;if(typeof e!="object"||Array.isArray(e))return e;const n={...o};for(const a of Object.keys(e)){const i=e[a],l=o?.[a];i!==null&&typeof i=="object"&&!Array.isArray(i)&&l!==null&&typeof l=="object"&&!Array.isArray(l)?n[a]=ym(l,i):n[a]=i}return n}function TC(o,e){return e?e.split(".").reduce((n,a)=>n?.[a],o):o}function RC(o,e,n){const a=e.split("."),i={...o};let l=i;for(let c=0;c{const i=N.useRef(e||xC()).current,[l,c]=N.useState(o),d=N.useRef(l);d.current=l;const f=N.useCallback(v=>TC(d.current,v),[]),g=N.useCallback((v,_)=>{c(A=>{const x=RC(A,v,_);return os.log(`[${i}] setState: ${v} =`,_),x})},[i]),m=N.useCallback((v,_="deep")=>{c(A=>{let x;return _==="replace"?x=v:_==="shallow"?x={...A,...v}:x=ym(A,v),os.log(`[${i}] mergeState (${_}):`,v),x})},[i]),b=N.useMemo(()=>({state:l,setState:g,getState:f,mergeState:m,stateRef:d,scopeId:i}),[l,g,f,m,i]),S=N.useMemo(()=>({state:d.current,setState:g,getState:f,mergeState:m}),[g,f,m]);return N.useEffect(()=>{const v=window.G7Core,_=window.__g7IsolatedStates||{};return window.__g7IsolatedStates||(window.__g7IsolatedStates=_),_[i]=S,v&&(v._isolatedStates||(v._isolatedStates={}),v._isolatedStates[i]=l),v?.devTools?.isEnabled?.()&&v.devTools.emit?.("isolated:created",{id:i,state:l}),os.log(`[${i}] IsolatedStateProvider mounted with initial state:`,l),()=>{delete _[i],v?._isolatedStates&&delete v._isolatedStates[i],v?.devTools?.isEnabled?.()&&v.devTools.emit?.("isolated:destroyed",{id:i}),os.log(`[${i}] IsolatedStateProvider unmounted`)}},[i,S]),N.useEffect(()=>{const v=window.G7Core,_=window.__g7IsolatedStates;_?.[i]&&(_[i].state=l),v?._isolatedStates&&(v._isolatedStates[i]=l),v?.devTools?.isEnabled?.()&&v.devTools.emit?.("isolated:updated",{id:i,state:l})},[l,i]),dt.jsx(mm.Provider,{value:b,children:n})},DC=()=>{const o=N.useContext(mm);return o.scopeId?o:null};var ka=Yg();function OC(){for(var o=arguments.length,e=new Array(o),n=0;na=>{e.forEach(i=>i(a))},e)}const rc=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function ls(o){const e=Object.prototype.toString.call(o);return e==="[object Window]"||e==="[object global]"}function Vd(o){return"nodeType"in o}function Ln(o){var e,n;return o?ls(o)?o:Vd(o)&&(e=(n=o.ownerDocument)==null?void 0:n.defaultView)!=null?e:window:window}function Fd(o){const{Document:e}=Ln(o);return o instanceof e}function mo(o){return ls(o)?!1:o instanceof Ln(o).HTMLElement}function bm(o){return o instanceof Ln(o).SVGElement}function cs(o){return o?ls(o)?o.document:Vd(o)?Fd(o)?o:mo(o)||bm(o)?o.ownerDocument:document:document:document}const zr=rc?N.useLayoutEffect:N.useEffect;function Kd(o){const e=N.useRef(o);return zr(()=>{e.current=o}),N.useCallback(function(){for(var n=arguments.length,a=new Array(n),i=0;i{o.current=setInterval(a,i)},[]),n=N.useCallback(()=>{o.current!==null&&(clearInterval(o.current),o.current=null)},[]);return[e,n]}function yo(o,e){e===void 0&&(e=[o]);const n=N.useRef(o);return zr(()=>{n.current!==o&&(n.current=o)},e),n}function bo(o,e){const n=N.useRef();return N.useMemo(()=>{const a=o(n.current);return n.current=a,a},[...e])}function ac(o){const e=Kd(o),n=N.useRef(null),a=N.useCallback(i=>{i!==n.current&&e?.(i,n.current),n.current=i},[]);return[n,a]}function Wd(o){const e=N.useRef();return N.useEffect(()=>{e.current=o},[o]),e.current}let Yd={};function vo(o,e){return N.useMemo(()=>{if(e)return e;const n=Yd[o]==null?0:Yd[o]+1;return Yd[o]=n,o+"-"+n},[o,e])}function vm(o){return function(e){for(var n=arguments.length,a=new Array(n>1?n-1:0),i=1;i{const d=Object.entries(c);for(const[f,g]of d){const m=l[f];m!=null&&(l[f]=m+o*g)}return l},{...e})}}const us=vm(1),So=vm(-1);function MC(o){return"clientX"in o&&"clientY"in o}function Xd(o){if(!o)return!1;const{KeyboardEvent:e}=Ln(o.target);return e&&o instanceof e}function $C(o){if(!o)return!1;const{TouchEvent:e}=Ln(o.target);return e&&o instanceof e}function Jd(o){if($C(o)){if(o.touches&&o.touches.length){const{clientX:e,clientY:n}=o.touches[0];return{x:e,y:n}}else if(o.changedTouches&&o.changedTouches.length){const{clientX:e,clientY:n}=o.changedTouches[0];return{x:e,y:n}}}return MC(o)?{x:o.clientX,y:o.clientY}:null}const wo=Object.freeze({Translate:{toString(o){if(!o)return;const{x:e,y:n}=o;return"translate3d("+(e?Math.round(e):0)+"px, "+(n?Math.round(n):0)+"px, 0)"}},Scale:{toString(o){if(!o)return;const{scaleX:e,scaleY:n}=o;return"scaleX("+e+") scaleY("+n+")"}},Transform:{toString(o){if(o)return[wo.Translate.toString(o),wo.Scale.toString(o)].join(" ")}},Transition:{toString(o){let{property:e,duration:n,easing:a}=o;return e+" "+n+"ms "+a}}}),Sm="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function NC(o){return o.matches(Sm)?o:o.querySelector(Sm)}const IC={display:"none"};function HC(o){let{id:e,value:n}=o;return Ye.createElement("div",{id:e,style:IC},n)}function zC(o){let{id:e,announcement:n,ariaLiveType:a="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":a,"aria-atomic":!0},n)}function jC(){const[o,e]=N.useState("");return{announce:N.useCallback(a=>{a!=null&&e(a)},[]),announcement:o}}const wm=N.createContext(null);function UC(o){const e=N.useContext(wm);N.useEffect(()=>{if(!e)throw new Error("useDndMonitor must be used within a children of ");return e(o)},[o,e])}function BC(){const[o]=N.useState(()=>new Set),e=N.useCallback(a=>(o.add(a),()=>o.delete(a)),[o]);return[N.useCallback(a=>{let{type:i,event:l}=a;o.forEach(c=>{var d;return(d=c[i])==null?void 0:d.call(c,l)})},[o]),e]}const PC={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=()=>{n.parentNode&&n.parentNode.removeChild(n)};i.onclick=l;const c=d=>{this.isImeComposing(d)||d.key==="Escape"&&(l(),document.removeEventListener("keydown",c))};return document.addEventListener("keydown",c),n.onclick=d=>{d.target===n&&l()},a.appendChild(i),n.appendChild(a),document.body.appendChild(n),{overlay:n,layer:a,closeLayer:l}}getNestedProperty(e,n){return n.split(".").reduce((a,i)=>a&&a[i]!==void 0?a[i]:void 0,e)}async handleSaveToLocalStorage(e,n){const{key:a,value:i}=e;if(!a)return j.error("saveToLocalStorage: key parameter is required"),!1;try{const l=typeof i=="string"?i:JSON.stringify(i);return localStorage.setItem(a,l),j.log(`saveToLocalStorage: saved ${a}`,i),!0}catch(l){return j.error("saveToLocalStorage: failed to save",{key:a,error:l}),!1}}async handleLoadFromLocalStorage(e,n){const{key:a,target:i,stateKey:l,defaultValue:c}=e;if(!a)return j.error("loadFromLocalStorage: key parameter is required"),c;try{const d=localStorage.getItem(a);if(d===null)return j.log(`loadFromLocalStorage: no value found for ${a}, using default`),l&&n.setState&&n.setState({[l]:c}),c;let f;try{f=JSON.parse(d)}catch{f=d}return j.log(`loadFromLocalStorage: loaded ${a}`,f),l&&n.setState&&n.setState({[l]:f}),f}catch(d){return j.error("loadFromLocalStorage: failed to load",{key:a,error:d}),c}}async handleCustomAction(e,n){const a=this.customHandlers.get(e.handler);if(!a){if(this.previewMode){j.warn(`[Preview] Unknown action handler "${e.handler}" — skipped (preview mode)`);return}const i=new Bt(`Unknown action handler: ${e.handler}`,e);throw i.unknownHandler=!0,i}return await a(e,n)}resolveParams(e,n){if(!e)return{};const a={};for(const[i,l]of Object.entries(e))i.includes("{{")&&j.warn(`[resolveParams] setState params의 키에 표현식이 포함되어 있습니다: "${i}". 키는 해석되지 않습니다. 배열 항목 수정은 .map()/.filter() 패턴을 사용하세요.`),typeof l=="string"&&l.includes("{{")?a[i]=this.evaluateExpression(l,n):typeof l=="string"?a[i]=l:Array.isArray(l)?a[i]=l.map(c=>typeof c=="string"&&c.includes("{{")?this.evaluateExpression(c,n):c):typeof l=="object"&&l!==null&&!Array.isArray(l)&&Object.getPrototypeOf(l)!==Object.prototype&&Object.getPrototypeOf(l)!==null?a[i]=l:typeof l=="object"&&l!==null?a[i]=this.resolveParams(l,n):a[i]=l;return a}resolveValue(e,n){return n?this.bindingEngine.resolveBindings(e,n,{skipCache:!0}):e}evaluateExpressions(e,n){let a={};for(const[i,l]of Object.entries(e))if(i==="..."){let c=l;typeof l=="string"&&l.includes("{{")&&(c=this.evaluateExpression(l,n)),c&&typeof c=="object"&&!Array.isArray(c)&&(a={...a,...c})}else typeof l=="string"&&l.includes("{{")?a[i]=this.evaluateExpression(l,n):typeof l=="object"&&l!==null&&!Array.isArray(l)?a[i]=this.evaluateExpressions(l,n):a[i]=l;return a}evaluateExpressionsIfNeeded(e,n){const a={};for(const[i,l]of Object.entries(e))typeof l=="string"&&l.includes("{{")?a[i]=this.evaluateExpression(l,n):a[i]=l;return a}evaluateExpression(e,n){if(!n)return e;const a=Aa(e);if(a===null){let c=n;if(e.includes("_global")){const f=window.G7Core?.state?.get()?._global;f&&(c={...n,_global:f})}if(e.includes("_computed")||e.includes("$computed")){const f=window.__g7ActionContext?.computedRef?.current;f&&Object.keys(f).length>0&&(c={...c,_computed:f,$computed:f})}return this.bindingEngine.resolveBindings(e,c,{skipCache:!0})}let i=a;i=i.replace(/\$args\.(\d+)/g,"$args[$1]");let l=n;if(i.includes("_global")){const d=window.G7Core?.state?.get()?._global;d&&(l={...n,_global:d})}if(i.includes("_computed")||i.includes("$computed")){const d=window.__g7ActionContext?.computedRef?.current;d&&Object.keys(d).length>0&&(l={...l,_computed:d,$computed:d})}i.includes("_global.modules")&&(j.log("[evaluateExpression] expression:",i),j.log("[evaluateExpression] dataContext._global:",l._global),j.log("[evaluateExpression] dataContext._global?.modules:",l._global?.modules));try{const c=Vn(i)?this.bindingEngine.evaluatePipeExpression(i,l,{skipCache:!0}):this.bindingEngine.evaluateExpression(i,l);return i.includes("_global.modules")&&j.log("[evaluateExpression] result:",c),typeof c=="string"&&c.startsWith("$t:")&&this.translationEngine&&this.translationContext?this.translationEngine.resolveTranslations(c,this.translationContext,n):c}catch(c){return j.error("Expression evaluation failed:",e,c),e}}setDefaultContext(e){this.defaultContext={...this.defaultContext,...e}}setGlobalStateUpdater(e){this.globalStateUpdater=e}getGlobalStateUpdater(){return this.globalStateUpdater}async dispatchAction(e,n){const a={...this.defaultContext,...n,data:{...this.defaultContext.data,...n?.data}};if(e.confirm){let i=this.resolveValue(e.confirm,a.data);if(this.translationEngine&&this.translationContext&&i.startsWith("$t:")&&(i=this.translationEngine.resolveTranslations(i,this.translationContext,a.data)),!confirm(i))return{success:!1}}try{return await this.executeAction(e,a)}catch(i){if(j.error("dispatchAction failed:",i),e.onError){const l=i instanceof Bt&&i.originalError?{message:i.originalError.message,response:i.originalError.response}:{message:i instanceof Error?i.message:String(i)},c={...a,data:{...a.data,error:l}},d=Array.isArray(e.onError)?e.onError:[e.onError];for(const f of d)await this.executeAction(f,c)}return{success:!1,error:i instanceof Error?i:new Error(String(i))}}}registerHandler(e,n,a){this.customHandlers.set(e,n);const i=Fn();i?.isEnabled()&&i.trackHandlerRegistration(e,a?.category??"custom",a?.description,a?.source)}unregisterHandler(e){this.customHandlers.delete(e);const n=Fn();n?.isEnabled()&&n.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 n=e.target;if(n&&!("tagName"in n)){const l={type:e.type??"custom",target:{value:n.value,name:n.name??""}};return e._changedKeys&&(l._changedKeys=e._changedKeys),l}const i=n?{value:n.value,name:n.name??"",checked:n.checked??!1,type:n.type??"",tagName:n.tagName}:{};if(e.type==="scroll"&&n){const l=n;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:n?i:null}}executeDebouncedAction(e,n,a,i,l){const c={...a,$event:n,$args:l},d={type:n.type,target:n.target,preventDefault:()=>{},stopPropagation:()=>{}};this.createHandler(e,c,i)(d)}handleDebouncedAction(e,n,a,i,l,c){const d=this.normalizeDebounceConfig(e.debounce),f=l||`default-${e.handler}-${Date.now()}`,g=this.extractEventData(n),m=g._changedKeys;if(m&&Array.isArray(m)&&g?.target?.value&&typeof g.target.value=="object"&&!Array.isArray(g.target.value)){const _=this.debounceAccumulatedValues.get(f);if(_){const A={..._};for(const x of m)A[x]=g.target.value[x];g.target.value=A}this.debounceAccumulatedValues.set(f,g.target.value)}const y=this.debounceTimers.get(f);y&&(clearTimeout(y),this.debounceTimers.delete(f));const S=Fn();S?.isEnabled()&&S.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 v=!this.debounceTimers.has(f+"_leading");if(d.leading&&v&&(this.debounceTimers.set(f+"_leading",setTimeout(()=>{},0)),this.executeDebouncedAction(e,g,a,i,c),S?.isEnabled()&&S.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 _=()=>{this.executeDebouncedAction(e,g,a,i,c),S?.isEnabled()&&S.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),_()},d.delay);this.debounceTimers.set(f,A),this.pendingDebounceFlushers.set(f,_)}}clearDebounceTimers(e){if(e)for(const[n,a]of this.debounceTimers)n.startsWith(e+"-")&&(clearTimeout(a),this.debounceTimers.delete(n),this.pendingDebounceFlushers.delete(n),this.debounceAccumulatedValues.delete(n));else{for(const n of this.debounceTimers.values())clearTimeout(n);this.debounceTimers.clear(),this.pendingDebounceFlushers.clear(),this.debounceAccumulatedValues.clear()}}debouncedCall(e,n,a){const i=this.debounceTimers.get(e);i&&(clearTimeout(i),this.debounceTimers.delete(e));const l=setTimeout(()=>{this.debounceTimers.delete(e),this.pendingDebounceFlushers.delete(e),a()},n);this.debounceTimers.set(e,l),this.pendingDebounceFlushers.set(e,a)}flushPendingDebounceTimers(){if(this.pendingDebounceFlushers.size===0)return;const e=new Map(this.pendingDebounceFlushers);for(const[n,a]of e){const i=this.debounceTimers.get(n);i&&(clearTimeout(i),this.debounceTimers.delete(n)),this.debounceTimers.delete(n+"_leading"),this.pendingDebounceFlushers.delete(n),a()}this.globalStateUpdater&&this.globalStateUpdater({})}bindActionsToProps(e,n,a){const i={...e};if(e.actions&&Array.isArray(e.actions)){const l=new Map;for(const m of e.actions){const y=this.resolveActionRef(m),S=y.event||this.getEventHandlerName(y.type);l.has(S)||l.set(S,[]),l.get(S).push(y)}const c=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,y]of l)i[m]=(...S)=>{for(const v of y){const _=S[0],A=_&&typeof _=="object"&&"preventDefault"in _;if(A&&(m==="onDragOver"||m==="onDrop")&&_.preventDefault(),A&&v.key&&"key"in _){if(this.isImeComposing(_)){j.log("Key filter skipped (IME composing):",v.key);continue}if(_.key!==v.key){j.log("Key filter not matched:",v.key,"actual:",_.key);continue}j.log("Key filter matched:",v.key)}if(v.debounce){const x=`${c}-${v.handler}-${m}`,O=_&&typeof _=="object"&&!("preventDefault"in _)&&"target"in _&&_.target!==null;let M;if(A)M=_;else if(O){const D={type:"custom",target:_.target,preventDefault:()=>{},stopPropagation:()=>{}};_._changedKeys&&(D._changedKeys=_._changedKeys),M=D}else M=new Event("custom");const T=v.event?{...n,$args:S}:n;this.handleDebouncedAction(v,M,T,a,x,S)}else if(this.flushPendingDebounceTimers(),v.event){const x={...n,$args:S},O=A?_:new Event("custom");this.createHandler(v,x,a)(O)}else if(A)this.createHandler(v,n,a)(_);else if(_&&typeof _=="object"&&!("preventDefault"in _)&&"target"in _&&_.target!==null){const O={type:"custom",target:_.target,preventDefault:()=>{},stopPropagation:()=>{}};this.createHandler(v,n,a)(O)}}}}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,n=5){const a=new WeakSet,i=(l,c)=>{if(l==null||typeof l=="string"||typeof l=="number"||typeof l=="boolean")return l;if(c>n)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(a.has(l))return"[Circular Array]";a.add(l);const d=l.slice(0,10).map(f=>i(f,c+1));return l.length>10&&d.push(`... ${l.length-10} more items`),d}if(typeof l=="object"){if(a.has(l))return"[Circular Reference]";a.add(l);const d={},f=Object.keys(l),g=f.slice(0,20);for(const m of g)try{d[m]=i(l[m],c+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)}};$(bs,"loadedScripts",new Set);let bo=bs,nc=null;function bm(o){return nc||(nc=new bo(o)),nc}function AC(o){nc=o}const vm=ht("TransitionManager");class xC{constructor(){$(this,"isPending",!1);$(this,"subscribers",new Set)}setPending(e){this.isPending!==e&&(vm.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(){vm.log("notifySubscribers:",{isPending:this.isPending,subscriberCount:this.subscribers.size}),this.subscribers.forEach(e=>{e(this.isPending)})}clearSubscribers(){this.subscribers.clear()}}const jr=new xC,rc=ht("TransitionContext"),Sm=H.createContext({isTransitioning:!1}),Vd=({children:o})=>{const[e,n]=H.useState(()=>{const i=jr.getIsPending();return rc.log("Initial state:",i),i});H.useEffect(()=>{rc.log("Subscribing to TransitionManager");const i=jr.subscribe(l=>{rc.log("Received isPending update:",l),n(l)});return()=>{rc.log("Unsubscribing from TransitionManager"),i()}},[]);const a=H.useMemo(()=>({isTransitioning:e}),[e]);return gt.jsx(Sm.Provider,{value:a,children:o})},wm=()=>H.useContext(Sm),ac="__g7LocalInitTracking";function Fd(){const o=globalThis;return o[ac]||(o[ac]={hash:"",timestamp:void 0,consumed:void 0}),o[ac]}function TC(){const o=globalThis;o[ac]={hash:"",timestamp:void 0,consumed:void 0}}function RC(o){Fd().consumed=o}function kC(o){return Fd().consumed===o}function DC(o){return o.globalTrackedKey!==o.trackingKey?"apply":o.instanceHandledKey===o.trackingKey?"skip":"prune"}function OC(o,e){return typeof o=="number"&&typeof e=="number"?Math.max(o,e):e??o}function LC(o,e){if(e===void 0)return o;if(!(o!==null&&typeof o=="object"&&e!==null&&typeof e=="object"&&!kC(o)))return e;const{_forceLocalInit:a,...i}=o,{_forceLocalInit:l,...c}=e,d={...i,...c},f=OC(a,l);return f!==void 0&&(d._forceLocalInit=f),d}function MC(o){return o<768?"mobile":o<1024?"tablet":"desktop"}function Cm(o){const e=MC(o);return{width:o,isMobile:e==="mobile",isTablet:e==="tablet",isDesktop:e==="desktop",matchedPreset:e}}const Kd=H.createContext(Cm(1024)),ic=({children:o,overrideWidth:e})=>{const[n,a]=H.useState(()=>hi.getWidth());H.useEffect(()=>{const c=hi.subscribe(d=>{a(d)});return()=>{c()}},[]);const i=e??n,l=H.useMemo(()=>Cm(i),[i]);return gt.jsx(Kd.Provider,{value:l,children:o})},Wd=()=>H.useContext(Kd);window.G7Core?.createLogger?.("Core:State");function $C(o,e,n,a){const{syncOnControlledChange:i=!0,isEqual:l}=a??{},c=o!==void 0;H.useRef(c);const[d,f]=H.useState(o!==void 0?o:e),g=d,m=H.useRef(o),y=H.useRef(!1);H.useEffect(()=>{if(y.current){m.current=o;return}i&&c&&o!==m.current&&(l?!l(d,o):d!==o)&&f(o),m.current=o},[o,c,i,l,d]);const S=H.useCallback(v=>{const _=typeof v=="function"?v(g):v;(l?l(g,_):g===_)||(y.current=!0,f(_),n?.(_),requestAnimationFrame(()=>{y.current=!1}))},[g,c,n,l]);return[g,S]}function NC(o,e){return o===e?!0:o.length!==e.length?!1:o.every((n,a)=>n===e[a])}function Em(o,e){if(o===e)return!0;const n=Object.keys(o),a=Object.keys(e);return n.length!==a.length?!1:n.every(i=>o[i]===e[i])}const _m=H.createContext({}),IC=({children:o,value:e})=>gt.jsx(_m.Provider,{value:e,children:o}),HC=()=>H.useContext(_m),jC=(o,e)=>{if(!o)return;const n=e.split(".");let a=o;for(const i of n){if(a==null)return;a=a[i]}return a},zC=(o,e,n)=>{const a=e.split(".");if(a.length===1)return{...o,[a[0]]:n};const i={...o};let l=i;for(let c=0;c{us.warn("IsolatedStateContext not available: setState called outside IsolatedStateProvider")},getState:()=>{},mergeState:()=>{us.warn("IsolatedStateContext not available: mergeState called outside IsolatedStateProvider")},stateRef:{current:{}},scopeId:""},Am=H.createContext(UC);let PC=0;function BC(){return`isolated-${++PC}-${Date.now().toString(36)}`}function xm(o,e){if(e==null)return o;if(typeof e!="object"||Array.isArray(e))return e;const n={...o};for(const a of Object.keys(e)){const i=e[a],l=o?.[a];i!==null&&typeof i=="object"&&!Array.isArray(i)&&l!==null&&typeof l=="object"&&!Array.isArray(l)?n[a]=xm(l,i):n[a]=i}return n}function qC(o,e){return e?e.split(".").reduce((n,a)=>n?.[a],o):o}function GC(o,e,n){const a=e.split("."),i={...o};let l=i;for(let c=0;c{const i=H.useRef(e||BC()).current,[l,c]=H.useState(o),d=H.useRef(l);d.current=l;const f=H.useCallback(v=>qC(d.current,v),[]),g=H.useCallback((v,_)=>{c(A=>{const x=GC(A,v,_);return us.log(`[${i}] setState: ${v} =`,_),x})},[i]),m=H.useCallback((v,_="deep")=>{c(A=>{let x;return _==="replace"?x=v:_==="shallow"?x={...A,...v}:x=xm(A,v),us.log(`[${i}] mergeState (${_}):`,v),x})},[i]),y=H.useMemo(()=>({state:l,setState:g,getState:f,mergeState:m,stateRef:d,scopeId:i}),[l,g,f,m,i]),S=H.useMemo(()=>({state:d.current,setState:g,getState:f,mergeState:m}),[g,f,m]);return H.useEffect(()=>{const v=window.G7Core,_=window.__g7IsolatedStates||{};return window.__g7IsolatedStates||(window.__g7IsolatedStates=_),_[i]=S,v&&(v._isolatedStates||(v._isolatedStates={}),v._isolatedStates[i]=l),v?.devTools?.isEnabled?.()&&v.devTools.emit?.("isolated:created",{id:i,state:l}),us.log(`[${i}] IsolatedStateProvider mounted with initial state:`,l),()=>{delete _[i],v?._isolatedStates&&delete v._isolatedStates[i],v?.devTools?.isEnabled?.()&&v.devTools.emit?.("isolated:destroyed",{id:i}),us.log(`[${i}] IsolatedStateProvider unmounted`)}},[i,S]),H.useEffect(()=>{const v=window.G7Core,_=window.__g7IsolatedStates;_?.[i]&&(_[i].state=l),v?._isolatedStates&&(v._isolatedStates[i]=l),v?.devTools?.isEnabled?.()&&v.devTools.emit?.("isolated:updated",{id:i,state:l})},[l,i]),gt.jsx(Am.Provider,{value:y,children:n})},FC=()=>{const o=H.useContext(Am);return o.scopeId?o:null};var ka=Qg();function KC(){for(var o=arguments.length,e=new Array(o),n=0;na=>{e.forEach(i=>i(a))},e)}const sc=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function ds(o){const e=Object.prototype.toString.call(o);return e==="[object Window]"||e==="[object global]"}function Yd(o){return"nodeType"in o}function Nn(o){var e,n;return o?ds(o)?o:Yd(o)&&(e=(n=o.ownerDocument)==null?void 0:n.defaultView)!=null?e:window:window}function Xd(o){const{Document:e}=Nn(o);return o instanceof e}function vo(o){return ds(o)?!1:o instanceof Nn(o).HTMLElement}function Tm(o){return o instanceof Nn(o).SVGElement}function fs(o){return o?ds(o)?o.document:Yd(o)?Xd(o)?o:vo(o)||Tm(o)?o.ownerDocument:document:document:document}const zr=sc?H.useLayoutEffect:H.useEffect;function Jd(o){const e=H.useRef(o);return zr(()=>{e.current=o}),H.useCallback(function(){for(var n=arguments.length,a=new Array(n),i=0;i{o.current=setInterval(a,i)},[]),n=H.useCallback(()=>{o.current!==null&&(clearInterval(o.current),o.current=null)},[]);return[e,n]}function So(o,e){e===void 0&&(e=[o]);const n=H.useRef(o);return zr(()=>{n.current!==o&&(n.current=o)},e),n}function wo(o,e){const n=H.useRef();return H.useMemo(()=>{const a=o(n.current);return n.current=a,a},[...e])}function oc(o){const e=Jd(o),n=H.useRef(null),a=H.useCallback(i=>{i!==n.current&&e?.(i,n.current),n.current=i},[]);return[n,a]}function Qd(o){const e=H.useRef();return H.useEffect(()=>{e.current=o},[o]),e.current}let Zd={};function Co(o,e){return H.useMemo(()=>{if(e)return e;const n=Zd[o]==null?0:Zd[o]+1;return Zd[o]=n,o+"-"+n},[o,e])}function Rm(o){return function(e){for(var n=arguments.length,a=new Array(n>1?n-1:0),i=1;i{const d=Object.entries(c);for(const[f,g]of d){const m=l[f];m!=null&&(l[f]=m+o*g)}return l},{...e})}}const hs=Rm(1),Eo=Rm(-1);function YC(o){return"clientX"in o&&"clientY"in o}function ef(o){if(!o)return!1;const{KeyboardEvent:e}=Nn(o.target);return e&&o instanceof e}function XC(o){if(!o)return!1;const{TouchEvent:e}=Nn(o.target);return e&&o instanceof e}function tf(o){if(XC(o)){if(o.touches&&o.touches.length){const{clientX:e,clientY:n}=o.touches[0];return{x:e,y:n}}else if(o.changedTouches&&o.changedTouches.length){const{clientX:e,clientY:n}=o.changedTouches[0];return{x:e,y:n}}}return YC(o)?{x:o.clientX,y:o.clientY}:null}const _o=Object.freeze({Translate:{toString(o){if(!o)return;const{x:e,y:n}=o;return"translate3d("+(e?Math.round(e):0)+"px, "+(n?Math.round(n):0)+"px, 0)"}},Scale:{toString(o){if(!o)return;const{scaleX:e,scaleY:n}=o;return"scaleX("+e+") scaleY("+n+")"}},Transform:{toString(o){if(o)return[_o.Translate.toString(o),_o.Scale.toString(o)].join(" ")}},Transition:{toString(o){let{property:e,duration:n,easing:a}=o;return e+" "+n+"ms "+a}}}),km="a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]";function JC(o){return o.matches(km)?o:o.querySelector(km)}const QC={display:"none"};function ZC(o){let{id:e,value:n}=o;return Xe.createElement("div",{id:e,style:QC},n)}function eE(o){let{id:e,announcement:n,ariaLiveType:a="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 Xe.createElement("div",{id:e,style:i,role:"status","aria-live":a,"aria-atomic":!0},n)}function tE(){const[o,e]=H.useState("");return{announce:H.useCallback(a=>{a!=null&&e(a)},[]),announcement:o}}const Dm=H.createContext(null);function nE(o){const e=H.useContext(Dm);H.useEffect(()=>{if(!e)throw new Error("useDndMonitor must be used within a children of ");return e(o)},[o,e])}function rE(){const[o]=H.useState(()=>new Set),e=H.useCallback(a=>(o.add(a),()=>o.delete(a)),[o]);return[H.useCallback(a=>{let{type:i,event:l}=a;o.forEach(c=>{var d;return(d=c[i])==null?void 0:d.call(c,l)})},[o]),e]}const aE={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. - `},qC={onDragStart(o){let{active:e}=o;return"Picked up draggable item "+e.id+"."},onDragOver(o){let{active:e,over:n}=o;return n?"Draggable item "+e.id+" was moved over droppable area "+n.id+".":"Draggable item "+e.id+" is no longer over a droppable area."},onDragEnd(o){let{active:e,over:n}=o;return n?"Draggable item "+e.id+" was dropped over droppable area "+n.id:"Draggable item "+e.id+" was dropped."},onDragCancel(o){let{active:e}=o;return"Dragging was cancelled. Draggable item "+e.id+" was dropped."}};function GC(o){let{announcements:e=qC,container:n,hiddenTextDescribedById:a,screenReaderInstructions:i=PC}=o;const{announce:l,announcement:c}=jC(),d=vo("DndLiveRegion"),[f,g]=N.useState(!1);if(N.useEffect(()=>{g(!0)},[]),UC(N.useMemo(()=>({onDragStart(b){let{active:S}=b;l(e.onDragStart({active:S}))},onDragMove(b){let{active:S,over:v}=b;e.onDragMove&&l(e.onDragMove({active:S,over:v}))},onDragOver(b){let{active:S,over:v}=b;l(e.onDragOver({active:S,over:v}))},onDragEnd(b){let{active:S,over:v}=b;l(e.onDragEnd({active:S,over:v}))},onDragCancel(b){let{active:S,over:v}=b;l(e.onDragCancel({active:S,over:v}))}}),[l,e])),!f)return null;const m=Ye.createElement(Ye.Fragment,null,Ye.createElement(HC,{id:a,value:i.draggable}),Ye.createElement(zC,{id:d,announcement:c}));return n?ka.createPortal(m,n):m}var tn;(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"})(tn||(tn={}));function ic(){}function Cm(o,e){return N.useMemo(()=>({sensor:o,options:e??{}}),[o,e])}function VC(){for(var o=arguments.length,e=new Array(o),n=0;n[...e].filter(a=>a!=null),[...e])}const Sr=Object.freeze({x:0,y:0});function Em(o,e){return Math.sqrt(Math.pow(o.x-e.x,2)+Math.pow(o.y-e.y,2))}function _m(o,e){let{data:{value:n}}=o,{data:{value:a}}=e;return n-a}function FC(o,e){let{data:{value:n}}=o,{data:{value:a}}=e;return a-n}function Am(o){let{left:e,top:n,height:a,width:i}=o;return[{x:e,y:n},{x:e+i,y:n},{x:e,y:n+a},{x:e+i,y:n+a}]}function xm(o,e){if(!o||o.length===0)return null;const[n]=o;return n[e]}function Tm(o,e,n){return e===void 0&&(e=o.left),n===void 0&&(n=o.top),{x:e+o.width*.5,y:n+o.height*.5}}const KC=o=>{let{collisionRect:e,droppableRects:n,droppableContainers:a}=o;const i=Tm(e,e.left,e.top),l=[];for(const c of a){const{id:d}=c,f=n.get(d);if(f){const g=Em(Tm(f),i);l.push({id:d,data:{droppableContainer:c,value:g}})}}return l.sort(_m)},WC=o=>{let{collisionRect:e,droppableRects:n,droppableContainers:a}=o;const i=Am(e),l=[];for(const c of a){const{id:d}=c,f=n.get(d);if(f){const g=Am(f),m=i.reduce((S,v,_)=>S+Em(g[_],v),0),b=Number((m/4).toFixed(4));l.push({id:d,data:{droppableContainer:c,value:b}})}}return l.sort(_m)};function YC(o,e){const n=Math.max(e.top,o.top),a=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),c=i-a,d=l-n;if(a{let{collisionRect:e,droppableRects:n,droppableContainers:a}=o;const i=[];for(const l of a){const{id:c}=l,d=n.get(c);if(d){const f=YC(d,e);f>0&&i.push({id:c,data:{droppableContainer:l,value:f}})}}return i.sort(FC)};function JC(o,e,n){return{...o,scaleX:e&&n?e.width/n.width:1,scaleY:e&&n?e.height/n.height:1}}function Rm(o,e){return o&&e?{x:o.left-e.left,y:o.top-e.top}:Sr}function QC(o){return function(n){for(var a=arguments.length,i=new Array(a>1?a-1:0),l=1;l({...c,top:c.top+o*d.y,bottom:c.bottom+o*d.y,left:c.left+o*d.x,right:c.right+o*d.x}),{...n})}}const ZC=QC(1);function eE(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 tE(o,e,n){const a=eE(e);if(!a)return o;const{scaleX:i,scaleY:l,x:c,y:d}=a,f=o.left-c-(1-i)*parseFloat(n),g=o.top-d-(1-l)*parseFloat(n.slice(n.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 nE={ignoreTransform:!1};function ds(o,e){e===void 0&&(e=nE);let n=o.getBoundingClientRect();if(e.ignoreTransform){const{transform:g,transformOrigin:m}=Ln(o).getComputedStyle(o);g&&(n=tE(n,g,m))}const{top:a,left:i,width:l,height:c,bottom:d,right:f}=n;return{top:a,left:i,width:l,height:c,bottom:d,right:f}}function km(o){return ds(o,{ignoreTransform:!0})}function rE(o){const e=o.innerWidth,n=o.innerHeight;return{top:0,left:0,right:e,bottom:n,width:e,height:n}}function aE(o,e){return e===void 0&&(e=Ln(o).getComputedStyle(o)),e.position==="fixed"}function iE(o,e){e===void 0&&(e=Ln(o).getComputedStyle(o));const n=/(auto|scroll|overlay)/;return["overflow","overflowX","overflowY"].some(i=>{const l=e[i];return typeof l=="string"?n.test(l):!1})}function sc(o,e){const n=[];function a(i){if(e!=null&&n.length>=e||!i)return n;if(Fd(i)&&i.scrollingElement!=null&&!n.includes(i.scrollingElement))return n.push(i.scrollingElement),n;if(!mo(i)||bm(i)||n.includes(i))return n;const l=Ln(o).getComputedStyle(i);return i!==o&&iE(i,l)&&n.push(i),aE(i,l)?n:a(i.parentNode)}return o?a(o):n}function Dm(o){const[e]=sc(o,1);return e??null}function Qd(o){return!rc||!o?null:ls(o)?o:Vd(o)?Fd(o)||o===cs(o).scrollingElement?window:mo(o)?o:null:null}function Om(o){return ls(o)?o.scrollX:o.scrollLeft}function Lm(o){return ls(o)?o.scrollY:o.scrollTop}function Zd(o){return{x:Om(o),y:Lm(o)}}var un;(function(o){o[o.Forward=1]="Forward",o[o.Backward=-1]="Backward"})(un||(un={}));function Mm(o){return!rc||!o?!1:o===document.scrollingElement}function $m(o){const e={x:0,y:0},n=Mm(o)?{height:window.innerHeight,width:window.innerWidth}:{height:o.clientHeight,width:o.clientWidth},a={x:o.scrollWidth-n.width,y:o.scrollHeight-n.height},i=o.scrollTop<=e.y,l=o.scrollLeft<=e.x,c=o.scrollTop>=a.y,d=o.scrollLeft>=a.x;return{isTop:i,isLeft:l,isBottom:c,isRight:d,maxScroll:a,minScroll:e}}const sE={x:.2,y:.2};function oE(o,e,n,a,i){let{top:l,left:c,right:d,bottom:f}=n;a===void 0&&(a=10),i===void 0&&(i=sE);const{isTop:g,isBottom:m,isLeft:b,isRight:S}=$m(o),v={x:0,y:0},_={x:0,y:0},A={height:e.height*i.y,width:e.width*i.x};return!g&&l<=e.top+A.height?(v.y=un.Backward,_.y=a*Math.abs((e.top+A.height-l)/A.height)):!m&&f>=e.bottom-A.height&&(v.y=un.Forward,_.y=a*Math.abs((e.bottom-A.height-f)/A.height)),!S&&d>=e.right-A.width?(v.x=un.Forward,_.x=a*Math.abs((e.right-A.width-d)/A.width)):!b&&c<=e.left+A.width&&(v.x=un.Backward,_.x=a*Math.abs((e.left+A.width-c)/A.width)),{direction:v,speed:_}}function lE(o){if(o===document.scrollingElement){const{innerWidth:l,innerHeight:c}=window;return{top:0,left:0,right:l,bottom:c,width:l,height:c}}const{top:e,left:n,right:a,bottom:i}=o.getBoundingClientRect();return{top:e,left:n,right:a,bottom:i,width:o.clientWidth,height:o.clientHeight}}function Nm(o){return o.reduce((e,n)=>us(e,Zd(n)),Sr)}function cE(o){return o.reduce((e,n)=>e+Om(n),0)}function uE(o){return o.reduce((e,n)=>e+Lm(n),0)}function dE(o,e){if(e===void 0&&(e=ds),!o)return;const{top:n,left:a,bottom:i,right:l}=e(o);Dm(o)&&(i<=0||l<=0||n>=window.innerHeight||a>=window.innerWidth)&&o.scrollIntoView({block:"center",inline:"center"})}const fE=[["x",["left","right"],cE],["y",["top","bottom"],uE]];class ef{constructor(e,n){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 a=sc(n),i=Nm(a);this.rect={...e},this.width=e.width,this.height=e.height;for(const[l,c,d]of fE)for(const f of c)Object.defineProperty(this,f,{get:()=>{const g=d(a),m=i[l]-g;return this.rect[f]+m},enumerable:!0});Object.defineProperty(this,"rect",{enumerable:!1})}}class Co{constructor(e){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(n=>{var a;return(a=this.target)==null?void 0:a.removeEventListener(...n)})},this.target=e}add(e,n,a){var i;(i=this.target)==null||i.addEventListener(e,n,a),this.listeners.push([e,n,a])}}function hE(o){const{EventTarget:e}=Ln(o);return o instanceof e?o:cs(o)}function tf(o,e){const n=Math.abs(o.x),a=Math.abs(o.y);return typeof e=="number"?Math.sqrt(n**2+a**2)>e:"x"in e&&"y"in e?n>e.x&&a>e.y:"x"in e?n>e.x:"y"in e?a>e.y:!1}var rr;(function(o){o.Click="click",o.DragStart="dragstart",o.Keydown="keydown",o.ContextMenu="contextmenu",o.Resize="resize",o.SelectionChange="selectionchange",o.VisibilityChange="visibilitychange"})(rr||(rr={}));function Im(o){o.preventDefault()}function gE(o){o.stopPropagation()}var ot;(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"})(ot||(ot={}));const Hm={start:[ot.Space,ot.Enter],cancel:[ot.Esc],end:[ot.Space,ot.Enter,ot.Tab]},pE=(o,e)=>{let{currentCoordinates:n}=e;switch(o.code){case ot.Right:return{...n,x:n.x+25};case ot.Left:return{...n,x:n.x-25};case ot.Down:return{...n,y:n.y+25};case ot.Up:return{...n,y:n.y-25}}};class nf{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:n}}=e;this.props=e,this.listeners=new Co(cs(n)),this.windowListeners=new Co(Ln(n)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(rr.Resize,this.handleCancel),this.windowListeners.add(rr.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(rr.Keydown,this.handleKeyDown))}handleStart(){const{activeNode:e,onStart:n}=this.props,a=e.node.current;a&&dE(a),n(Sr)}handleKeyDown(e){if(Xd(e)){const{active:n,context:a,options:i}=this.props,{keyboardCodes:l=Hm,coordinateGetter:c=pE,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}=a.current,m=g?{x:g.left,y:g.top}:Sr;this.referenceCoordinates||(this.referenceCoordinates=m);const b=c(e,{active:n,context:a.current,currentCoordinates:m});if(b){const S=So(b,m),v={x:0,y:0},{scrollableAncestors:_}=a.current;for(const A of _){const x=e.code,{isTop:L,isRight:M,isLeft:R,isBottom:D,maxScroll:B,minScroll:q}=$m(A),P=lE(A),K={x:Math.min(x===ot.Right?P.right-P.width/2:P.right,Math.max(x===ot.Right?P.left:P.left+P.width/2,b.x)),y:Math.min(x===ot.Down?P.bottom-P.height/2:P.bottom,Math.max(x===ot.Down?P.top:P.top+P.height/2,b.y))},ge=x===ot.Right&&!M||x===ot.Left&&!R,Ee=x===ot.Down&&!D||x===ot.Up&&!L;if(ge&&K.x!==b.x){const Se=A.scrollLeft+S.x,Ue=x===ot.Right&&Se<=B.x||x===ot.Left&&Se>=q.x;if(Ue&&!S.y){A.scrollTo({left:Se,behavior:d});return}Ue?v.x=A.scrollLeft-Se:v.x=x===ot.Right?A.scrollLeft-B.x:A.scrollLeft-q.x,v.x&&A.scrollBy({left:-v.x,behavior:d});break}else if(Ee&&K.y!==b.y){const Se=A.scrollTop+S.y,Ue=x===ot.Down&&Se<=B.y||x===ot.Up&&Se>=q.y;if(Ue&&!S.x){A.scrollTo({top:Se,behavior:d});return}Ue?v.y=A.scrollTop-Se:v.y=x===ot.Down?A.scrollTop-B.y:A.scrollTop-q.y,v.y&&A.scrollBy({top:-v.y,behavior:d});break}}this.handleMove(e,us(So(b,this.referenceCoordinates),v))}}}handleMove(e,n){const{onMove:a}=this.props;e.preventDefault(),a(n)}handleEnd(e){const{onEnd:n}=this.props;e.preventDefault(),this.detach(),n()}handleCancel(e){const{onCancel:n}=this.props;e.preventDefault(),this.detach(),n()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}}nf.activators=[{eventName:"onKeyDown",handler:(o,e,n)=>{let{keyboardCodes:a=Hm,onActivation:i}=e,{active:l}=n;const{code:c}=o.nativeEvent;if(a.start.includes(c)){const d=l.activatorNode.current;return d&&o.target!==d?!1:(o.preventDefault(),i?.({event:o.nativeEvent}),!0)}return!1}}];function zm(o){return!!(o&&"distance"in o)}function jm(o){return!!(o&&"delay"in o)}class rf{constructor(e,n,a){var i;a===void 0&&(a=hE(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=n;const{event:l}=e,{target:c}=l;this.props=e,this.events=n,this.document=cs(c),this.documentListeners=new Co(this.document),this.listeners=new Co(a),this.windowListeners=new Co(Ln(c)),this.initialCoordinates=(i=Jd(l))!=null?i:Sr,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:n,bypassActivationConstraint:a}}}=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(rr.Resize,this.handleCancel),this.windowListeners.add(rr.DragStart,Im),this.windowListeners.add(rr.VisibilityChange,this.handleCancel),this.windowListeners.add(rr.ContextMenu,Im),this.documentListeners.add(rr.Keydown,this.handleKeydown),n){if(a!=null&&a({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(jm(n)){this.timeoutId=setTimeout(this.handleStart,n.delay),this.handlePending(n);return}if(zm(n)){this.handlePending(n);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,n){const{active:a,onPending:i}=this.props;i(a,e,this.initialCoordinates,n)}handleStart(){const{initialCoordinates:e}=this,{onStart:n}=this.props;e&&(this.activated=!0,this.documentListeners.add(rr.Click,gE,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(rr.SelectionChange,this.removeTextSelection),n(e))}handleMove(e){var n;const{activated:a,initialCoordinates:i,props:l}=this,{onMove:c,options:{activationConstraint:d}}=l;if(!i)return;const f=(n=Jd(e))!=null?n:Sr,g=So(i,f);if(!a&&d){if(zm(d)){if(d.tolerance!=null&&tf(g,d.tolerance))return this.handleCancel();if(tf(g,d.distance))return this.handleStart()}if(jm(d)&&tf(g,d.tolerance))return this.handleCancel();this.handlePending(d,g);return}e.cancelable&&e.preventDefault(),c(f)}handleEnd(){const{onAbort:e,onEnd:n}=this.props;this.detach(),this.activated||e(this.props.active),n()}handleCancel(){const{onAbort:e,onCancel:n}=this.props;this.detach(),this.activated||e(this.props.active),n()}handleKeydown(e){e.code===ot.Esc&&this.handleCancel()}removeTextSelection(){var e;(e=this.document.getSelection())==null||e.removeAllRanges()}}const mE={cancel:{name:"pointercancel"},move:{name:"pointermove"},end:{name:"pointerup"}};class af extends rf{constructor(e){const{event:n}=e,a=cs(n.target);super(e,mE,a)}}af.activators=[{eventName:"onPointerDown",handler:(o,e)=>{let{nativeEvent:n}=o,{onActivation:a}=e;return!n.isPrimary||n.button!==0?!1:(a?.({event:n}),!0)}}];const yE={move:{name:"mousemove"},end:{name:"mouseup"}};var sf;(function(o){o[o.RightClick=2]="RightClick"})(sf||(sf={}));class bE extends rf{constructor(e){super(e,yE,cs(e.event.target))}}bE.activators=[{eventName:"onMouseDown",handler:(o,e)=>{let{nativeEvent:n}=o,{onActivation:a}=e;return n.button===sf.RightClick?!1:(a?.({event:n}),!0)}}];const of={cancel:{name:"touchcancel"},move:{name:"touchmove"},end:{name:"touchend"}};class vE extends rf{constructor(e){super(e,of)}static setup(){return window.addEventListener(of.move.name,e,{capture:!1,passive:!1}),function(){window.removeEventListener(of.move.name,e)};function e(){}}}vE.activators=[{eventName:"onTouchStart",handler:(o,e)=>{let{nativeEvent:n}=o,{onActivation:a}=e;const{touches:i}=n;return i.length>1?!1:(a?.({event:n}),!0)}}];var Eo;(function(o){o[o.Pointer=0]="Pointer",o[o.DraggableRect=1]="DraggableRect"})(Eo||(Eo={}));var oc;(function(o){o[o.TreeOrder=0]="TreeOrder",o[o.ReversedTreeOrder=1]="ReversedTreeOrder"})(oc||(oc={}));function SE(o){let{acceleration:e,activator:n=Eo.Pointer,canScroll:a,draggingRect:i,enabled:l,interval:c=5,order:d=oc.TreeOrder,pointerCoordinates:f,scrollableAncestors:g,scrollableAncestorRects:m,delta:b,threshold:S}=o;const v=CE({delta:b,disabled:!l}),[_,A]=LC(),x=N.useRef({x:0,y:0}),L=N.useRef({x:0,y:0}),M=N.useMemo(()=>{switch(n){case Eo.Pointer:return f?{top:f.y,bottom:f.y,left:f.x,right:f.x}:null;case Eo.DraggableRect:return i}},[n,i,f]),R=N.useRef(null),D=N.useCallback(()=>{const q=R.current;if(!q)return;const P=x.current.x*L.current.x,K=x.current.y*L.current.y;q.scrollBy(P,K)},[]),B=N.useMemo(()=>d===oc.TreeOrder?[...g].reverse():g,[d,g]);N.useEffect(()=>{if(!l||!g.length||!M){A();return}for(const q of B){if(a?.(q)===!1)continue;const P=g.indexOf(q),K=m[P];if(!K)continue;const{direction:ge,speed:Ee}=oE(q,K,M,e,S);for(const Se of["x","y"])v[Se][ge[Se]]||(Ee[Se]=0,ge[Se]=0);if(Ee.x>0||Ee.y>0){A(),R.current=q,_(D,c),x.current=Ee,L.current=ge;return}}x.current={x:0,y:0},L.current={x:0,y:0},A()},[e,D,a,A,l,c,JSON.stringify(M),JSON.stringify(v),_,g,B,m,JSON.stringify(S)])}const wE={x:{[un.Backward]:!1,[un.Forward]:!1},y:{[un.Backward]:!1,[un.Forward]:!1}};function CE(o){let{delta:e,disabled:n}=o;const a=Wd(e);return bo(i=>{if(n||!a||!i)return wE;const l={x:Math.sign(e.x-a.x),y:Math.sign(e.y-a.y)};return{x:{[un.Backward]:i.x[un.Backward]||l.x===-1,[un.Forward]:i.x[un.Forward]||l.x===1},y:{[un.Backward]:i.y[un.Backward]||l.y===-1,[un.Forward]:i.y[un.Forward]||l.y===1}}},[n,e,a])}function EE(o,e){const n=e!=null?o.get(e):void 0,a=n?n.node.current:null;return bo(i=>{var l;return e==null?null:(l=a??i)!=null?l:null},[a,e])}function _E(o,e){return N.useMemo(()=>o.reduce((n,a)=>{const{sensor:i}=a,l=i.activators.map(c=>({eventName:c.eventName,handler:e(c.handler,a)}));return[...n,...l]},[]),[o,e])}var _o;(function(o){o[o.Always=0]="Always",o[o.BeforeDragging=1]="BeforeDragging",o[o.WhileDragging=2]="WhileDragging"})(_o||(_o={}));var lf;(function(o){o.Optimized="optimized"})(lf||(lf={}));const Um=new Map;function AE(o,e){let{dragging:n,dependencies:a,config:i}=e;const[l,c]=N.useState(null),{frequency:d,measure:f,strategy:g}=i,m=N.useRef(o),b=x(),S=yo(b),v=N.useCallback(function(L){L===void 0&&(L=[]),!S.current&&c(M=>M===null?L:M.concat(L.filter(R=>!M.includes(R))))},[S]),_=N.useRef(null),A=bo(L=>{if(b&&!n)return Um;if(!L||L===Um||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,B=D?new ef(f(D),D):null;R.rect.current=B,B&&M.set(R.id,B)}return M}return L},[o,l,n,b,f]);return N.useEffect(()=>{m.current=o},[o]),N.useEffect(()=>{b||v()},[n,b]),N.useEffect(()=>{l&&l.length>0&&c(null)},[JSON.stringify(l)]),N.useEffect(()=>{b||typeof d!="number"||_.current!==null||(_.current=setTimeout(()=>{v(),_.current=null},d))},[d,b,v,...a]),{droppableRects:A,measureDroppableContainers:v,measuringScheduled:l!=null};function x(){switch(g){case _o.Always:return!1;case _o.BeforeDragging:return n;default:return!n}}}function Bm(o,e){return bo(n=>o?n||(typeof e=="function"?e(o):o):null,[e,o])}function xE(o,e){return Bm(o,e)}function TE(o){let{callback:e,disabled:n}=o;const a=Kd(e),i=N.useMemo(()=>{if(n||typeof window>"u"||typeof window.MutationObserver>"u")return;const{MutationObserver:l}=window;return new l(a)},[a,n]);return N.useEffect(()=>()=>i?.disconnect(),[i]),i}function lc(o){let{callback:e,disabled:n}=o;const a=Kd(e),i=N.useMemo(()=>{if(n||typeof window>"u"||typeof window.ResizeObserver>"u")return;const{ResizeObserver:l}=window;return new l(a)},[n]);return N.useEffect(()=>()=>i?.disconnect(),[i]),i}function RE(o){return new ef(ds(o),o)}function Pm(o,e,n){e===void 0&&(e=RE);const[a,i]=N.useState(null);function l(){i(f=>{if(!o)return null;if(o.isConnected===!1){var g;return(g=f??n)!=null?g:null}const m=e(o);return JSON.stringify(f)===JSON.stringify(m)?f:m})}const c=TE({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=lc({callback:l});return zr(()=>{l(),o?(d?.observe(o),c?.observe(document.body,{childList:!0,subtree:!0})):(d?.disconnect(),c?.disconnect())},[o]),a}function kE(o){const e=Bm(o);return Rm(o,e)}const qm=[];function DE(o){const e=N.useRef(o),n=bo(a=>o?a&&a!==qm&&o&&e.current&&o.parentNode===e.current.parentNode?a:sc(o):qm,[o]);return N.useEffect(()=>{e.current=o},[o]),n}function OE(o){const[e,n]=N.useState(null),a=N.useRef(o),i=N.useCallback(l=>{const c=Qd(l.target);c&&n(d=>d?(d.set(c,Zd(c)),new Map(d)):null)},[]);return N.useEffect(()=>{const l=a.current;if(o!==l){c(l);const d=o.map(f=>{const g=Qd(f);return g?(g.addEventListener("scroll",i,{passive:!0}),[g,Zd(g)]):null}).filter(f=>f!=null);n(d.length?new Map(d):null),a.current=o}return()=>{c(o),c(l)};function c(d){d.forEach(f=>{const g=Qd(f);g?.removeEventListener("scroll",i)})}},[i,o]),N.useMemo(()=>o.length?e?Array.from(e.values()).reduce((l,c)=>us(l,c),Sr):Nm(o):Sr,[o,e])}function Gm(o,e){e===void 0&&(e=[]);const n=N.useRef(null);return N.useEffect(()=>{n.current=null},e),N.useEffect(()=>{const a=o!==Sr;a&&!n.current&&(n.current=o),!a&&n.current&&(n.current=null)},[o]),n.current?So(o,n.current):Sr}function LE(o){N.useEffect(()=>{if(!rc)return;const e=o.map(n=>{let{sensor:a}=n;return a.setup==null?void 0:a.setup()});return()=>{for(const n of e)n?.()}},o.map(e=>{let{sensor:n}=e;return n}))}function ME(o,e){return N.useMemo(()=>o.reduce((n,a)=>{let{eventName:i,handler:l}=a;return n[i]=c=>{l(c,e)},n},{}),[o,e])}function Vm(o){return N.useMemo(()=>o?rE(o):null,[o])}const Fm=[];function $E(o,e){e===void 0&&(e=ds);const[n]=o,a=Vm(n?Ln(n):null),[i,l]=N.useState(Fm);function c(){l(()=>o.length?o.map(f=>Mm(f)?a:new ef(e(f),f)):Fm)}const d=lc({callback:c});return zr(()=>{d?.disconnect(),c(),o.forEach(f=>d?.observe(f))},[o]),i}function NE(o){if(!o)return null;if(o.children.length>1)return o;const e=o.children[0];return mo(e)?e:o}function IE(o){let{measure:e}=o;const[n,a]=N.useState(null),i=N.useCallback(g=>{for(const{target:m}of g)if(mo(m)){a(b=>{const S=e(m);return b?{...b,width:S.width,height:S.height}:S});break}},[e]),l=lc({callback:i}),c=N.useCallback(g=>{const m=NE(g);l?.disconnect(),m&&l?.observe(m),a(m?e(m):null)},[e,l]),[d,f]=ac(c);return N.useMemo(()=>({nodeRef:d,rect:n,setRef:f}),[n,d,f])}const HE=[{sensor:af,options:{}},{sensor:nf,options:{}}],zE={current:{}},cc={draggable:{measure:km},droppable:{measure:km,strategy:_o.WhileDragging,frequency:lf.Optimized},dragOverlay:{measure:ds}};class Ao extends Map{get(e){var n;return e!=null&&(n=super.get(e))!=null?n:void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(e=>{let{disabled:n}=e;return!n})}getNodeFor(e){var n,a;return(n=(a=this.get(e))==null?void 0:a.node.current)!=null?n:void 0}}const jE={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new Ao,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:ic},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:cc,measureDroppableContainers:ic,windowRect:null,measuringScheduled:!1},UE={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:""},dispatch:ic,draggableNodes:new Map,over:null,measureDroppableContainers:ic},uc=N.createContext(UE),Km=N.createContext(jE);function BE(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new Ao}}}function PE(o,e){switch(e.type){case tn.DragStart:return{...o,draggable:{...o.draggable,initialCoordinates:e.initialCoordinates,active:e.active}};case tn.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 tn.DragEnd:case tn.DragCancel:return{...o,draggable:{...o.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case tn.RegisterDroppable:{const{element:n}=e,{id:a}=n,i=new Ao(o.droppable.containers);return i.set(a,n),{...o,droppable:{...o.droppable,containers:i}}}case tn.SetDroppableDisabled:{const{id:n,key:a,disabled:i}=e,l=o.droppable.containers.get(n);if(!l||a!==l.key)return o;const c=new Ao(o.droppable.containers);return c.set(n,{...l,disabled:i}),{...o,droppable:{...o.droppable,containers:c}}}case tn.UnregisterDroppable:{const{id:n,key:a}=e,i=o.droppable.containers.get(n);if(!i||a!==i.key)return o;const l=new Ao(o.droppable.containers);return l.delete(n),{...o,droppable:{...o.droppable,containers:l}}}default:return o}}function qE(o){let{disabled:e}=o;const{active:n,activatorEvent:a,draggableNodes:i}=N.useContext(uc),l=Wd(a),c=Wd(n?.id);return N.useEffect(()=>{if(!e&&!a&&l&&c!=null){if(!Xd(l)||document.activeElement===l.target)return;const d=i.get(c);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=NC(m);if(b){b.focus();break}}})}},[a,e,i,c,l]),null}function GE(o,e){let{transform:n,...a}=e;return o!=null&&o.length?o.reduce((i,l)=>l({transform:i,...a}),n):n}function VE(o){return N.useMemo(()=>({draggable:{...cc.draggable,...o?.draggable},droppable:{...cc.droppable,...o?.droppable},dragOverlay:{...cc.dragOverlay,...o?.dragOverlay}}),[o?.draggable,o?.droppable,o?.dragOverlay])}function FE(o){let{activeNode:e,measure:n,initialRect:a,config:i=!0}=o;const l=N.useRef(!1),{x:c,y:d}=typeof i=="boolean"?{x:i,y:i}:i;zr(()=>{if(!c&&!d||!e){l.current=!1;return}if(l.current||!a)return;const g=e?.node.current;if(!g||g.isConnected===!1)return;const m=n(g),b=Rm(m,a);if(c||(b.x=0),d||(b.y=0),l.current=!0,Math.abs(b.x)>0||Math.abs(b.y)>0){const S=Dm(g);S&&S.scrollBy({top:b.y,left:b.x})}},[e,c,d,a,n])}const Wm=N.createContext({...Sr,scaleX:1,scaleY:1});var Da;(function(o){o[o.Uninitialized=0]="Uninitialized",o[o.Initializing=1]="Initializing",o[o.Initialized=2]="Initialized"})(Da||(Da={}));const KE=N.memo(function(e){var n,a,i,l;let{id:c,accessibility:d,autoScroll:f=!0,children:g,sensors:m=HE,collisionDetection:b=XC,measuring:S,modifiers:v,..._}=e;const A=N.useReducer(PE,void 0,BE),[x,L]=A,[M,R]=BC(),[D,B]=N.useState(Da.Uninitialized),q=D===Da.Initialized,{draggable:{active:P,nodes:K,translate:ge},droppable:{containers:Ee}}=x,Se=P!=null?K.get(P):null,Ue=N.useRef({initial:null,translated:null}),Ve=N.useMemo(()=>{var he;return P!=null?{id:P,data:(he=Se?.data)!=null?he:zE,rect:Ue}:null},[P,Se]),qe=N.useRef(null),[St,J]=N.useState(null),[fe,Le]=N.useState(null),Z=yo(_,Object.values(_)),pe=vo("DndDescribedBy",c),H=N.useMemo(()=>Ee.getEnabled(),[Ee]),T=VE(S),{droppableRects:ce,measureDroppableContainers:de,measuringScheduled:ye}=AE(H,{dragging:q,dependencies:[ge.x,ge.y],config:T.droppable}),ie=EE(K,P),xe=N.useMemo(()=>fe?Jd(fe):null,[fe]),_e=ve(),Te=xE(ie,T.draggable.measure);FE({activeNode:P!=null?K.get(P):null,config:_e.layoutShiftCompensation,initialRect:Te,measure:T.draggable.measure});const $e=Pm(ie,T.draggable.measure,Te),ht=Pm(ie?ie.parentElement:null),wt=N.useRef({activatorEvent:null,active:null,activeNode:ie,collisionRect:null,collisions:null,droppableRects:ce,draggableNodes:K,draggingNode:null,draggingNodeRect:null,droppableContainers:Ee,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),kt=Ee.getNodeFor((n=wt.current.over)==null?void 0:n.id),ft=IE({measure:T.dragOverlay.measure}),nn=(a=ft.nodeRef.current)!=null?a:ie,Ft=q?(i=ft.rect)!=null?i:$e:null,Nt=!!(ft.nodeRef.current&&ft.rect),Br=kE(Nt?null:$e),fn=Vm(nn?Ln(nn):null),rn=DE(q?kt??ie:null),hn=$E(rn),Fn=GE(v,{transform:{x:ge.x-Br.x,y:ge.y-Br.y,scaleX:1,scaleY:1},activatorEvent:fe,active:Ve,activeNodeRect:$e,containerNodeRect:ht,draggingNodeRect:Ft,over:wt.current.over,overlayNodeRect:ft.rect,scrollableAncestors:rn,scrollableAncestorRects:hn,windowRect:fn}),Pr=xe?us(xe,ge):null,Pt=OE(rn),wi=Gm(Pt),na=Gm(Pt,[$e]),gn=us(Fn,wi),Rn=Ft?ZC(Ft,Fn):null,tt=Ve&&Rn?b({active:Ve,collisionRect:Rn,droppableRects:ce,droppableContainers:H,pointerCoordinates:Pr}):null,$n=xm(tt,"id"),[pn,ra]=N.useState(null),ir=Nt?Fn:us(Fn,na),an=JC(ir,(l=pn?.rect)!=null?l:null,$e),En=N.useRef(null),sn=N.useCallback((he,Ce)=>{let{sensor:Ae,options:Fe}=Ce;if(qe.current==null)return;const Re=K.get(qe.current);if(!Re)return;const Ne=he.nativeEvent,ke=new Ae({active:qe.current,activeNode:Re,event:Ne,options:Fe,context:wt,onAbort(ze){if(!K.get(ze))return;const{onDragAbort:we}=Z.current,He={id:ze};we?.(He),M({type:"onDragAbort",event:He})},onPending(ze,Ge,we,He){if(!K.get(ze))return;const{onDragPending:_t}=Z.current,Lt={id:ze,constraint:Ge,initialCoordinates:we,offset:He};_t?.(Lt),M({type:"onDragPending",event:Lt})},onStart(ze){const Ge=qe.current;if(Ge==null)return;const we=K.get(Ge);if(!we)return;const{onDragStart:He}=Z.current,et={activatorEvent:Ne,active:{id:Ge,data:we.data,rect:Ue}};ka.unstable_batchedUpdates(()=>{He?.(et),B(Da.Initializing),L({type:tn.DragStart,initialCoordinates:ze,active:Ge}),M({type:"onDragStart",event:et}),J(En.current),Le(Ne)})},onMove(ze){L({type:tn.DragMove,coordinates:ze})},onEnd:Ze(tn.DragEnd),onCancel:Ze(tn.DragCancel)});En.current=ke;function Ze(ze){return async function(){const{active:we,collisions:He,over:et,scrollAdjustedTranslate:_t}=wt.current;let Lt=null;if(we&&_t){const{cancelDrop:kn}=Z.current;Lt={activatorEvent:Ne,active:we,collisions:He,delta:_t,over:et},ze===tn.DragEnd&&typeof kn=="function"&&await Promise.resolve(kn(Lt))&&(ze=tn.DragCancel)}qe.current=null,ka.unstable_batchedUpdates(()=>{L({type:ze}),B(Da.Uninitialized),ra(null),J(null),Le(null),En.current=null;const kn=ze===tn.DragEnd?"onDragEnd":"onDragCancel";if(Lt){const It=Z.current[kn];It?.(Lt),M({type:kn,event:Lt})}})}}},[K]),V=N.useCallback((he,Ce)=>(Ae,Fe)=>{const Re=Ae.nativeEvent,Ne=K.get(Fe);if(qe.current!==null||!Ne||Re.dndKit||Re.defaultPrevented)return;const ke={active:Ne};he(Ae,Ce.options,ke)===!0&&(Re.dndKit={capturedBy:Ce.sensor},qe.current=Fe,sn(Ae,Ce))},[K,sn]),se=_E(m,V);LE(m),zr(()=>{$e&&D===Da.Initializing&&B(Da.Initialized)},[$e,D]),N.useEffect(()=>{const{onDragMove:he}=Z.current,{active:Ce,activatorEvent:Ae,collisions:Fe,over:Re}=wt.current;if(!Ce||!Ae)return;const Ne={active:Ce,activatorEvent:Ae,collisions:Fe,delta:{x:gn.x,y:gn.y},over:Re};ka.unstable_batchedUpdates(()=>{he?.(Ne),M({type:"onDragMove",event:Ne})})},[gn.x,gn.y]),N.useEffect(()=>{const{active:he,activatorEvent:Ce,collisions:Ae,droppableContainers:Fe,scrollAdjustedTranslate:Re}=wt.current;if(!he||qe.current==null||!Ce||!Re)return;const{onDragOver:Ne}=Z.current,ke=Fe.get($n),Ze=ke&&ke.rect.current?{id:ke.id,rect:ke.rect.current,data:ke.data,disabled:ke.disabled}:null,ze={active:he,activatorEvent:Ce,collisions:Ae,delta:{x:Re.x,y:Re.y},over:Ze};ka.unstable_batchedUpdates(()=>{ra(Ze),Ne?.(ze),M({type:"onDragOver",event:ze})})},[$n]),zr(()=>{wt.current={activatorEvent:fe,active:Ve,activeNode:ie,collisionRect:Rn,collisions:tt,droppableRects:ce,draggableNodes:K,draggingNode:nn,draggingNodeRect:Ft,droppableContainers:Ee,over:pn,scrollableAncestors:rn,scrollAdjustedTranslate:gn},Ue.current={initial:Ft,translated:Rn}},[Ve,ie,tt,Rn,K,nn,Ft,ce,Ee,pn,rn,gn]),SE({..._e,delta:ge,draggingRect:Rn,pointerCoordinates:Pr,scrollableAncestors:rn,scrollableAncestorRects:hn});const ue=N.useMemo(()=>({active:Ve,activeNode:ie,activeNodeRect:$e,activatorEvent:fe,collisions:tt,containerNodeRect:ht,dragOverlay:ft,draggableNodes:K,droppableContainers:Ee,droppableRects:ce,over:pn,measureDroppableContainers:de,scrollableAncestors:rn,scrollableAncestorRects:hn,measuringConfiguration:T,measuringScheduled:ye,windowRect:fn}),[Ve,ie,$e,fe,tt,ht,ft,K,Ee,ce,pn,de,rn,hn,T,ye,fn]),ee=N.useMemo(()=>({activatorEvent:fe,activators:se,active:Ve,activeNodeRect:$e,ariaDescribedById:{draggable:pe},dispatch:L,draggableNodes:K,over:pn,measureDroppableContainers:de}),[fe,se,Ve,$e,L,pe,K,pn,de]);return Ye.createElement(wm.Provider,{value:R},Ye.createElement(uc.Provider,{value:ee},Ye.createElement(Km.Provider,{value:ue},Ye.createElement(Wm.Provider,{value:an},g)),Ye.createElement(qE,{disabled:d?.restoreFocus===!1})),Ye.createElement(GC,{...d,hiddenTextDescribedById:pe}));function ve(){const he=St?.autoScrollEnabled===!1,Ce=typeof f=="object"?f.enabled===!1:f===!1,Ae=q&&!he&&!Ce;return typeof f=="object"?{...f,enabled:Ae}:{enabled:Ae}}}),WE=N.createContext(null),Ym="button",YE="Draggable";function XE(o){let{id:e,data:n,disabled:a=!1,attributes:i}=o;const l=vo(YE),{activators:c,activatorEvent:d,active:f,activeNodeRect:g,ariaDescribedById:m,draggableNodes:b,over:S}=N.useContext(uc),{role:v=Ym,roleDescription:_="draggable",tabIndex:A=0}=i??{},x=f?.id===e,L=N.useContext(x?Wm:WE),[M,R]=ac(),[D,B]=ac(),q=ME(c,e),P=yo(n);zr(()=>(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 K=N.useMemo(()=>({role:v,tabIndex:A,"aria-disabled":a,"aria-pressed":x&&v===Ym?!0:void 0,"aria-roledescription":_,"aria-describedby":m.draggable}),[a,v,A,x,_,m.draggable]);return{active:f,activatorEvent:d,activeNodeRect:g,attributes:K,isDragging:x,listeners:a?void 0:q,node:M,over:S,setNodeRef:R,setActivatorNodeRef:B,transform:L}}function JE(){return N.useContext(Km)}const QE="Droppable",ZE={timeout:25};function e_(o){let{data:e,disabled:n=!1,id:a,resizeObserverConfig:i}=o;const l=vo(QE),{active:c,dispatch:d,over:f,measureDroppableContainers:g}=N.useContext(uc),m=N.useRef({disabled:n}),b=N.useRef(!1),S=N.useRef(null),v=N.useRef(null),{disabled:_,updateMeasurementsFor:A,timeout:x}={...ZE,...i},L=yo(A??a),M=N.useCallback(()=>{if(!b.current){b.current=!0;return}v.current!=null&&clearTimeout(v.current),v.current=setTimeout(()=>{g(Array.isArray(L.current)?L.current:[L.current]),v.current=null},x)},[x]),R=lc({callback:M,disabled:_||!c}),D=N.useCallback((K,ge)=>{R&&(ge&&(R.unobserve(ge),b.current=!1),K&&R.observe(K))},[R]),[B,q]=ac(D),P=yo(e);return N.useEffect(()=>{!R||!B.current||(R.disconnect(),b.current=!1,R.observe(B.current))},[B,R]),N.useEffect(()=>(d({type:tn.RegisterDroppable,element:{id:a,key:l,disabled:n,node:B,rect:S,data:P}}),()=>d({type:tn.UnregisterDroppable,key:l,id:a})),[a]),N.useEffect(()=>{n!==m.current.disabled&&(d({type:tn.SetDroppableDisabled,id:a,key:l,disabled:n}),m.current.disabled=n)},[a,l,n,d]),{active:c,rect:S,isOver:f?.id===a,node:B,over:f,setNodeRef:q}}function cf(o,e,n){const a=o.slice();return a.splice(n<0?a.length+n:n,0,a.splice(e,1)[0]),a}function t_(o,e){return o.reduce((n,a,i)=>{const l=e.get(a);return l&&(n[i]=l),n},Array(o.length))}function dc(o){return o!==null&&o>=0}function n_(o,e){if(o===e)return!0;if(o.length!==e.length)return!1;for(let n=0;n{var e;let{rects:n,activeNodeRect:a,activeIndex:i,overIndex:l,index:c}=o;const d=(e=n[i])!=null?e:a;if(!d)return null;const f=i_(n,c,i);if(c===i){const g=n[l];return g?{x:ii&&c<=l?{x:-d.width-f,y:0,...fc}:c=l?{x:d.width+f,y:0,...fc}:{x:0,y:0,...fc}};function i_(o,e,n){const a=o[e],i=o[e-1],l=o[e+1];return!a||!i&&!l?0:n{let{rects:e,activeIndex:n,overIndex:a,index:i}=o;const l=cf(e,a,n),c=e[i],d=l[i];return!d||!c?null:{x:d.left-c.left,y:d.top-c.top,scaleX:d.width/c.width,scaleY:d.height/c.height}},hc={scaleX:1,scaleY:1},s_=o=>{var e;let{activeIndex:n,activeNodeRect:a,index:i,rects:l,overIndex:c}=o;const d=(e=l[n])!=null?e:a;if(!d)return null;if(i===n){const g=l[c];return g?{x:0,y:nn&&i<=c?{x:0,y:-d.height-f,...hc}:i=c?{x:0,y:d.height+f,...hc}:{x:0,y:0,...hc}};function o_(o,e,n){const a=o[e],i=o[e-1],l=o[e+1];return a?na.map(q=>typeof q=="object"&&"id"in q?q.id:q),[a]),_=c!=null,A=c?v.indexOf(c.id):-1,x=g?v.indexOf(g.id):-1,L=N.useRef(v),M=!n_(v,L.current),R=x!==-1&&A===-1||M,D=r_(l);zr(()=>{M&&_&&m(v)},[M,v,_,m]),N.useEffect(()=>{L.current=v},[v]);const B=N.useMemo(()=>({activeIndex:A,containerId:b,disabled:D,disableTransforms:R,items:v,overIndex:x,useDragOverlay:S,sortedRects:t_(v,f),strategy:i}),[A,b,D.draggable,D.droppable,R,v,x,f,S,i]);return Ye.createElement(Jm.Provider,{value:B},e)}const c_=o=>{let{id:e,items:n,activeIndex:a,overIndex:i}=o;return cf(n,a,i).indexOf(e)},u_=o=>{let{containerId:e,isSorting:n,wasDragging:a,index:i,items:l,newIndex:c,previousItems:d,previousContainerId:f,transition:g}=o;return!g||!a||d!==l&&i===c?!1:n?!0:c!==i&&e===f},d_={duration:200,easing:"ease"},Qm="transform",f_=wo.Transition.toString({property:Qm,duration:0,easing:"linear"}),h_={roleDescription:"sortable"};function g_(o){let{disabled:e,index:n,node:a,rect:i}=o;const[l,c]=N.useState(null),d=N.useRef(n);return zr(()=>{if(!e&&n!==d.current&&a.current){const f=i.current;if(f){const g=ds(a.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)&&c(m)}}n!==d.current&&(d.current=n)},[e,n,a,i]),N.useEffect(()=>{l&&c(null)},[l]),l}function p_(o){let{animateLayoutChanges:e=u_,attributes:n,disabled:a,data:i,getNewIndex:l=c_,id:c,strategy:d,resizeObserverConfig:f,transition:g=d_}=o;const{items:m,containerId:b,activeIndex:S,disabled:v,disableTransforms:_,sortedRects:A,overIndex:x,useDragOverlay:L,strategy:M}=N.useContext(Jm),R=m_(a,v),D=m.indexOf(c),B=N.useMemo(()=>({sortable:{containerId:b,index:D,items:m},...i}),[b,i,D,m]),q=N.useMemo(()=>m.slice(m.indexOf(c)),[m,c]),{rect:P,node:K,isOver:ge,setNodeRef:Ee}=e_({id:c,data:B,disabled:R.droppable,resizeObserverConfig:{updateMeasurementsFor:q,...f}}),{active:Se,activatorEvent:Ue,activeNodeRect:Ve,attributes:qe,setNodeRef:St,listeners:J,isDragging:fe,over:Le,setActivatorNodeRef:Z,transform:pe}=XE({id:c,data:B,attributes:{...h_,...n},disabled:R.draggable}),H=OC(Ee,St),T=!!Se,ce=T&&!_&&dc(S)&&dc(x),de=!L&&fe,ye=de&&ce?pe:null,xe=ce?ye??(d??M)({rects:A,activeNodeRect:Ve,activeIndex:S,overIndex:x,index:D}):null,_e=dc(S)&&dc(x)?l({id:c,items:m,activeIndex:S,overIndex:x}):D,Te=Se?.id,$e=N.useRef({activeId:Te,items:m,newIndex:_e,containerId:b}),ht=m!==$e.current.items,wt=e({active:Se,containerId:b,isDragging:fe,isSorting:T,id:c,index:D,items:m,newIndex:$e.current.newIndex,previousItems:$e.current.items,previousContainerId:$e.current.containerId,transition:g,wasDragging:$e.current.activeId!=null}),kt=g_({disabled:!wt,index:D,node:K,rect:P});return N.useEffect(()=>{T&&$e.current.newIndex!==_e&&($e.current.newIndex=_e),b!==$e.current.containerId&&($e.current.containerId=b),m!==$e.current.items&&($e.current.items=m)},[T,_e,b,m]),N.useEffect(()=>{if(Te===$e.current.activeId)return;if(Te!=null&&$e.current.activeId==null){$e.current.activeId=Te;return}const nn=setTimeout(()=>{$e.current.activeId=Te},50);return()=>clearTimeout(nn)},[Te]),{active:Se,activeIndex:S,attributes:qe,data:B,rect:P,index:D,newIndex:_e,items:m,isOver:ge,isSorting:T,isDragging:fe,listeners:J,node:K,overIndex:x,over:Le,setNodeRef:H,setActivatorNodeRef:Z,setDroppableNodeRef:Ee,setDraggableNodeRef:St,transform:kt??xe,transition:ft()};function ft(){if(kt||ht&&$e.current.newIndex===D)return f_;if(!(de&&!Xd(Ue)||!g)&&(T||wt))return wo.Transition.toString({...g,property:Qm})}}function m_(o,e){var n,a;return typeof o=="boolean"?{draggable:o,droppable:!1}:{draggable:(n=o?.draggable)!=null?n:e.draggable,droppable:(a=o?.droppable)!=null?a:e.droppable}}function gc(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 y_=[ot.Down,ot.Right,ot.Up,ot.Left],b_=(o,e)=>{let{context:{active:n,collisionRect:a,droppableRects:i,droppableContainers:l,over:c,scrollableAncestors:d}}=e;if(y_.includes(o.code)){if(o.preventDefault(),!n||!a)return;const f=[];l.getEnabled().forEach(b=>{if(!b||b!=null&&b.disabled)return;const S=i.get(b.id);if(S)switch(o.code){case ot.Down:a.topS.top&&f.push(b);break;case ot.Left:a.left>S.left&&f.push(b);break;case ot.Right:a.left1&&(m=g[1].id),m!=null){const b=l.get(n.id),S=l.get(m),v=S?i.get(S.id):null,_=S?.node.current;if(_&&v&&b&&S){const x=sc(_).some((q,P)=>d[P]!==q),L=Zm(b,S),M=v_(b,S),R=x||!L?{x:0,y:0}:{x:M?a.width-v.width:0,y:M?a.height-v.height:0},D={x:v.left,y:v.top};return R.x&&R.y?D:So(D,R)}}}};function Zm(o,e){return!gc(o)||!gc(e)?!1:o.data.current.sortable.containerId===e.data.current.sortable.containerId}function v_(o,e){return!gc(o)||!gc(e)||!Zm(o,e)?!1:o.data.current.sortable.index{const d=N.useId(),f=N.useRef({inProgress:!1,lastSortTime:0,lastActiveId:null}),g=VC(Cm(af,{activationConstraint:{distance:5}}),Cm(nf,{coordinateGetter:b_})),m=N.useCallback(v=>{f.current={inProgress:!0,lastSortTime:Date.now(),lastActiveId:v.active.id},l?.({activeId:v.active.id})},[l]),b=N.useCallback(v=>{const{active:_,over:A}=v,x=Date.now();if(!A||_.id===A.id){f.current.inProgress=!1;return}const{lastSortTime:L,lastActiveId:M,inProgress:R}=f.current;if(M===_.id&&x-L<500&&!R)return;f.current={inProgress:!1,lastSortTime:x,lastActiveId:_.id};const D=o.findIndex(q=>String(q[e])===String(_.id)),B=o.findIndex(q=>String(q[e])===String(A.id));if(D!==-1&&B!==-1&&D!==B){const q=cf(o,D,B);i?.(q,{oldIndex:D,newIndex:B})}},[o,e,i]),S=o.map(v=>String(v[e]));return dt.jsx(KE,{id:d,sensors:g,collisionDetection:KC,onDragStart:m,onDragEnd:b,children:dt.jsx(l_,{items:S,strategy:S_[n],children:a})},c!==void 0?`${d}-v${c}`:d)},ey=N.createContext(null),C_=({value:o,children:e})=>dt.jsx(ey.Provider,{value:o,children:e}),E_=()=>N.useContext(ey),__=({id:o,handle:e,as:n="div",children:a})=>{const{attributes:i,listeners:l,setNodeRef:c,transform:d,transition:f,isDragging:g}=p_({id:o}),m={transform:wo.Transform.toString(d),transition:f,opacity:g?.5:1,position:"relative"};return dt.jsx(n,{ref:c,style:m,...i,...e?{}:l,"data-sortable-item":!0,"data-sortable-id":String(o),"data-dragging":g,children:dt.jsx(C_,{value:{listeners:l,handle:e,isDragging:g},children:a})})},at=ut("DynamicRenderer");function Zr(){try{return window.G7Core?.devTools}catch{return}}function df(o,e,n,a){if(typeof o=="string"){if(/\$t:[a-zA-Z_][a-zA-Z0-9_.\-]*/.test(o))try{return e.resolveTranslations(o,n,a)}catch{return o}return o}if(Array.isArray(o))return o.map(i=>df(i,e,n,a));if(o&&typeof o=="object"){const i={};for(const[l,c]of Object.entries(o))i[l]=df(c,e,n,a);return i}return o}function A_(o){const e=Object.keys(o);return e.length>0&&e.every(n=>/^\d+$/.test(n))}const wr=(o,e)=>{const n=["errors"],a={...o};for(const i of Object.keys(e)){const l=e[i],c=o[i];if(l===null){a[i]=null;continue}if(n.includes(i)){a[i]=l;continue}if(Array.isArray(l)){a[i]=l;continue}if(Array.isArray(c)&&l!==null&&typeof l=="object"&&!Array.isArray(l)&&A_(l)){const d=Object.keys(l).map(g=>parseInt(g,10));if((d.length>0?Math.max(...d):0)>=c.length+d.length+10)a[i]={...l};else{const g=[...c];for(const[m,b]of Object.entries(l)){const S=parseInt(m,10);S>=0&&S=g.length&&(g[S]=b)}a[i]=g}}else l!==null&&typeof l=="object"&&c!==null&&typeof c=="object"&&!Array.isArray(c)?a[i]=wr(c,l):a[i]=l}return a},pc=(o,e)=>{let n=null;const a=()=>(n===null&&(n={...o}),n);for(const i of Object.keys(e)){if(!(i in o))continue;const l=e[i],c=o[i];if(l!==null&&typeof l=="object"&&!Array.isArray(l)&&c!==null&&typeof c=="object"&&!Array.isArray(c)){const d=pc(c,l);if(d===c)continue;Object.keys(d).length===0?delete a()[i]:a()[i]=d}else delete a()[i]}return n??o},x_=o=>{const e={},n=o.split(";").filter(a=>a.trim());for(const a of n){const i=a.indexOf(":");if(i===-1)continue;const l=a.substring(0,i).trim(),c=a.substring(i+1).trim();if(l&&c){const d=l.replace(/-([a-z])/g,(f,g)=>g.toUpperCase());e[d]=c}}return e};class T_ extends N.Component{constructor(e){super(e),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,n){at.error(`컴포넌트 렌더링 에러 (ID: ${this.props.componentId}, Name: ${this.props.componentName}):`,e,n)}render(){return this.state.hasError?this.props.fallback?this.props.fallback:dt.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:[dt.jsx("div",{className:"font-semibold mb-1",children:"컴포넌트 로드 실패"}),dt.jsxs("div",{className:"text-xs opacity-80",children:[this.props.componentName&&`[${this.props.componentName}] `,"데이터를 표시할 수 없습니다."]}),this.state.error&&dt.jsxs("details",{className:"mt-2",children:[dt.jsx("summary",{className:"cursor-pointer text-xs opacity-70 hover:opacity-100",children:"상세 정보"}),dt.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 jr=N.memo(({componentDef:o,dataContext:e,translationContext:n,registry:a,bindingEngine:i,translationEngine:l,actionDispatcher:c,parentComponentContext:d,parentFormContextProp:f,parentDataContext:g,isRootRenderer:m=!1,isInsideIteration:b=!1,isEditMode:S=!1,onComponentSelect:v,onComponentHover:_,onDragStart:A,onDragEnd:x,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 B=N.useRef(null);N.useLayoutEffect(()=>{if(!d&&e._localInit&&typeof e._localInit=="object"){const{_forceLocalInit:V,_merge:se,...ue}=e._localInit,ee=`${JSON.stringify(ue)}:${V||"no-force"}`;if(B.current!==ee){B.current=ee;const ve=se||"shallow",Ce=window.G7Core?.state?.get?.()?._local||{},Ae=window.__g7PendingLocalState||{},Fe={...Ce,...Ae};ve==="replace"?window.__g7PendingLocalState={loadingActions:Fe.loadingActions||{},...ue,hasChanges:!1}:ve==="deep"?window.__g7PendingLocalState=wr(Fe,{...ue,hasChanges:!1}):window.__g7PendingLocalState={...Fe,...ue,hasChanges:!1};const Re=window.__g7SetLocalOverrideKeys;Re&&typeof Re=="object"&&(ve==="replace"?window.__g7SetLocalOverrideKeys={...ue,hasChanges:!1}:window.__g7SetLocalOverrideKeys=wr(Re,{...ue,hasChanges:!1}))}}}),N.useLayoutEffect(()=>{if(!d){const V=window.__g7SetLocalOverrideKeys;if(V){D(ve=>pc(ve,V));const se=V,ue=window.__g7ForcedLocalFields,ee=window.__g7LastSetLocalSnapshot;queueMicrotask(()=>{window.__g7SetLocalOverrideKeys===se&&(window.__g7SetLocalOverrideKeys=void 0),window.__g7ForcedLocalFields===ue&&(window.__g7ForcedLocalFields=void 0),window.__g7LastSetLocalSnapshot===ee&&(window.__g7LastSetLocalSnapshot=void 0)})}}},[e._local]);const q=N.useRef(M);N.useEffect(()=>{o._fromBase&&M&&q.current!==M&&(q.current=M,D({loadingActions:{}}))},[M,o._fromBase]);const P=N.useRef(""),K=N.useRef(!1),ge=N.useRef(null),Ee=N.useRef(null),Se=N.useRef({}),Ue=N.useRef({}),Ve=N.useRef(g),qe=DC(),St=sC(),J=St?.getParentDataContext()??g;N.useEffect(()=>{if(e._localInit&&typeof e._localInit=="object"){const{_forceLocalInit:V,...se}=e._localInit,ue=JSON.stringify(se),ee=V!==void 0,ve=Pd(),he=`${ue}:${V||"no-force"}`,Ce=gC({globalTrackedKey:ve.hash,instanceHandledKey:Ee.current,trackingKey:he});if(Ce==="apply"){Ee.current=he,ve.hash=he,ve.timestamp=V,P.current=ue,ee&&(K.current=!0);const{_merge:Fe,...Re}=se,Ne=Fe||"shallow";D(ke=>Ne==="replace"?{loadingActions:ke.loadingActions||{},...Re,hasChanges:!1}:Ne==="deep"?wr(ke,{...Re,hasChanges:!1}):{...ke,...Re,hasChanges:!1}),e._globalSetState&&e._globalSetState(ke=>{const Ze=ke?._local||{};let ze;return Ne==="replace"?ze={...Re,hasChanges:!1}:Ne==="deep"?ze=wr(Ze,{...Re,hasChanges:!1}):ze={...Ze,...Re,hasChanges:!1},{...ke,_local:ze}}),i.invalidateCacheByKeys(["_local"]),at.log("_localInit applied (data changed):",Object.keys(se))}else if(Ce==="prune"){Ee.current=he;const{_merge:Fe,...Re}=se;D(ke=>pc(ke,Re)),pc(R,Re)!==R&&(i.invalidateCacheByKeys(["_local"]),at.log("_localInit pruned (applied by another renderer):",Object.keys(Re)))}ge.current=e._localInit,fC(e._localInit)}},[e._localInit,g,i]);const{isTransitioning:fe}=fm(),Le=wC(),Z=f??Le,{width:pe}=Gd(),H=E_(),T=N.useMemo(()=>{let V=o;if(o.type==="iterator"&&o.data){const{data:ee,itemName:ve,indexName:he,...Ce}=o;V={...Ce,iteration:{source:ee,item_var:ve||"item",index_var:he}}}if(!V.responsive)return V;const se=hi.getMatchingKey(V.responsive,pe);if(!se)return V;const ue=V.responsive[se];return{...V,props:{...V.props,...ue.props},children:ue.children??V.children,text:ue.text??V.text,if:ue.if??V.if,iteration:ue.iteration??V.iteration,__responsiveChildrenKey:ue.children!==void 0?se:void 0}},[o,pe]),ce=N.useCallback(V=>{const se=V?.__setStateId;if(D(ue=>{const ee=window.__g7PendingLocalState,he=window.__g7SetLocalOverrideKeys||ee,Ce=he?wr(ue,he):ue;if(typeof V=="function"){const ke=V(Ce);return wr(Ce,ke)}const{__mergeMode:Ae,__setStateId:Fe,...Re}=V;let Ne;if(Ae==="replace"?Ne=Re:Ae==="shallow"?Ne={...Ce,...Re}:Ne=wr(Ce,Re),Ae!==void 0){const ke=window.__g7ForcedLocalFields;ke&&(window.__g7ForcedLocalFields={...ke,...Re})}return Ne}),se){const ue=Zr();if(ue?.isEnabled()){const ee=T.id||"unknown",ve=T.name||"Unknown";setTimeout(()=>{ue.trackComponentRender?.(ee,ve,0,["_local"],[]),ue.completeStateChange?.(se)},0)}}},[T.id,T.name]),de=d?.state??R,ye=d?.setState??ce,ie=N.useMemo(()=>{const V=e._localInit&&e._localInit!==ge.current;let se;V&&e._local?se=e._local:se=e._local?wr(e._local,de):de;const ue=window.__g7ForcedLocalFields;ue&&(se=wr(se,ue));const ee={...e,_local:se},ve=e._computedDefinitions;if(ve&&Object.keys(ve).length>0){const he=new xn,Ce={...ee,...qe?{_isolated:qe.state}:{}},Ae={},Fe=Zr(),Re=Fe?.isEnabled()??!1;for(const[Ne,ke]of Object.entries(ve)){const Ze=Re?Date.now():0,ze=Re?e._computed?.[Ne]:void 0;let Ge;try{if(typeof ke=="string")if(ke.startsWith("{{")&&ke.endsWith("}}")){const we=ke.slice(2,-2).trim(),He=Pn(we)?he.evaluatePipeExpression(we,Ce,{skipCache:!0}):he.evaluateExpression(we,Ce,{skipCache:!0});Ae[Ne]=He}else Ae[Ne]=ke;else if(ke&&typeof ke=="object"&&"$switch"in ke){const we=he.resolveSwitch(ke,Ce,{skipCache:!0});Ae[Ne]=we}}catch(we){at.warn(`Failed to recalculate computed value: ${Ne}`,we),Ae[Ne]=e._computed?.[Ne],Ge=we instanceof Error?we.message:String(we)}if(Re&&(Ge||ze!==Ae[Ne])){const He=Date.now()-Ze;Fe.trackComputedProperty?.(Ne,typeof ke=="string"?ke:JSON.stringify(ke),[{type:"_local",path:"_local",value:ee._local}],Ae[Ne],He,T.id,Ge),ze!==Ae[Ne]&&Fe.trackComputedRecalc?.(Ne,"dependency-change",ze,Ae[Ne],He,{type:"_local",path:"_local"},T.id)}}ee._computed=Ae}if(qe&&(ee._isolated=qe.state),J&&(ee.$parent=J),o.extensionPointProps){const he=i.resolveObject(o.extensionPointProps,ee,b?{skipCache:!0}:void 0);ee.extensionPointProps=S&&l?df(he,l,n,ee):he}return o.extensionPointCallbacks&&(ee.extensionPointCallbacks=o.extensionPointCallbacks),S&&(ee.$templateId===void 0&&n?.templateId&&(ee.$templateId=n.templateId),ee.$locale===void 0&&n?.locale&&(ee.$locale=n.locale)),ee},[e,de,qe?.state,J,St?.version,o.extensionPointProps,o.extensionPointCallbacks]);Se.current=ie._local,Ue.current=ie._computed||{},Ve.current=J,N.useEffect(()=>{const V=Zr();if(!V?.isEnabled())return;const se=ie._local;se&&V.updateLocalState(se);const ue=ie._computed;ue&&V.updateComputedState(ue),J&&V.updateParentContext?.(J);const ee=T.id||`comp-${Date.now()}`,ve=T.name||"Unknown",he={global:Object.keys(e._global||{}),local:Object.keys(se||{}),context:d?Object.keys(d.state||{}):[]},Ce={type:d?"componentContext":"dynamicState",hasComponentContext:!!d,parentId:d?"parent":void 0};V.trackComponentStateSource?.(ee,ve,he,Ce),de&&Object.keys(de).length>0&&V.trackDynamicState?.(ee,de);const Ae=!!(T.expandChildren||T.props?.expandChildren);V.trackContextFlow?.(ee,ve,!!d,Ae,!0)},[ie._local,e,T.id,T.name,d,de,T.expandChildren,T.props?.expandChildren,J]);const xe=N.useMemo(()=>({state:{...ie._local},setState:ye,stateRef:Se,computedRef:Ue,isolatedContext:qe,parentDataContext:ie}),[ie._local,ye,R,qe,ie]),_e=N.useMemo(()=>{const V=ts({if:T.if,condition:T.condition,conditions:T.conditions},ie,i,T.id);if(T.if||T.condition!==void 0||T.conditions){const ue=Zr();ue?.isEnabled()&&T.if&&ue.trackIfCondition(T.id||`if-${Date.now()}`,T.if,V)}return V},[T.if,T.conditions,ie,i,T.id]),Te=N.useMemo(()=>{if(!T.slot)return null;const V=T.slot;if(V.startsWith("{{")&&V.endsWith("}}")){const se=V.slice(2,-2).trim();try{const ue={componentId:T.id,componentName:T.name,propName:"slot"},ee=Pn(se)?i.evaluatePipeExpression(se,ie,void 0,ue):i.evaluateExpression(se,ie,ue);return at.log(`[Slot] 표현식 평가: "${se}" => "${ee}" (컴포넌트: ${T.id})`),typeof ee=="string"?ee:null}catch(ue){return at.warn(`slot 표현식 평가 실패 (컴포넌트: ${T.id}):`,ue),null}}return at.log(`[Slot] 정적 슬롯 ID: "${V}" (컴포넌트: ${T.id})`),V},[T.slot,T.id,ie,i]),$e=N.useMemo(()=>!Te||!T.id?"":`${T.id}-${Te}-${JSON.stringify(T.slotOrder??0)}`,[Te,T.id,T.slotOrder]),ht=N.useRef(null);N.useEffect(()=>{const V=window.__slotContextValue,se=V?.isEnabled??!1;if(T.slot&&at.log(`[Slot Registration] 컴포넌트: ${T.id}, isSlotEnabled: ${se}, shouldRender: ${_e}, resolvedSlotId: ${Te}`),!se||!_e){T.slot&&at.log(`[Slot Registration] 등록 스킵 - isSlotEnabled: ${se}, shouldRender: ${_e}`),ht.current&&T.id&&V&&(V.unregisterFromSlot(ht.current,T.id),ht.current=null);return}if(!Te||!T.id){T.slot&&at.log(`[Slot Registration] 등록 스킵 - resolvedSlotId: ${Te}, id: ${T.id}`),ht.current&&T.id&&V&&(V.unregisterFromSlot(ht.current,T.id),ht.current=null);return}ht.current&&ht.current!==Te&&V.unregisterFromSlot(ht.current,T.id);const ue={...T,slot:void 0,slotOrder:void 0};return V.registerToSlot(Te,T.id,{componentDef:ue,dataContext:e,order:T.slotOrder??0,parentFormContext:f??null,getParentComponentContext:()=>xe,translationContext:n,registrationKey:$e}),ht.current=Te,()=>{const ee=window.__slotContextValue;Te&&T.id&&ee&&ee.unregisterFromSlot(Te,T.id)}},[_e,Te,T,e,f,xe,n,$e]);const wt=N.useCallback(V=>{if(typeof V=="string"){if($l(V))return gd(V);if(Nl(V)){const se=[],ue=V.replace(new RegExp(`${to}([^${fi}]*)${fi}`,"g"),(ve,he)=>(se.push(he),`${xa}${se.length-1}${xa}`));let ee=ue;return/\$t:[a-zA-Z0-9._-]+/.test(ue)&&(ee=l.resolveTranslations(ue,n,ie)),ee.replace(new RegExp(`${xa}(\\d+)${xa}`,"g"),(ve,he)=>se[parseInt(he)])}if(V.startsWith("$t:defer:"))return V;if(/\$t:[a-zA-Z0-9._-]+/.test(V)){const se=V.trim();return se.startsWith("{")&&se.endsWith("}")||se.startsWith("[")&&se.endsWith("]")?V:l.resolveTranslations(V,n,ie)}return V}if(Array.isArray(V))return V.map(se=>wt(se));if(V&&typeof V=="object"){const se={};for(const[ue,ee]of Object.entries(V))se[ue]=wt(ee);return se}return V},[l,n,ie]),kt=N.useCallback(V=>eo(V),[]),ft=N.useCallback(V=>Aa(V),[]),nn=N.useMemo(()=>{let V={...T.props||{}};const se=["cellChildren","expandChildren","expandContext","render"],ee=a.getMetadata(T.name)?.skipBindingKeys||[],ve=[...new Set([...se,...ee])],he=b?{skipCache:!0}:void 0,Ce={...he??{},skipBindingKeys:ve},Ae=we=>{if(he)return he;if(we.startsWith("_computed")||we.startsWith("$computed"))return{skipCache:!0}};for(const[we,He]of Object.entries(V))if(!ve.includes(we))if(typeof He=="string"){const et=ft(He);if(et!==null){let _t=!1,Lt=et;et.startsWith(er)&&(_t=!0,Lt=et.slice(er.length));const kn={componentId:T.id,componentName:T.name,propName:we};let It;if(Pn(Lt))try{It=i.evaluatePipeExpression(Lt,ie,Ae(Lt),kn)}catch(Ht){at.warn(`파이프 표현식 평가 실패 (컴포넌트: ${T.id}, prop: ${we}):`,Ht),It=void 0}else if(kt(Lt))try{It=i.evaluateExpression(Lt,ie,kn)}catch(Ht){at.warn(`표현식 평가 실패 (컴포넌트: ${T.id}, prop: ${we}):`,Ht),It=void 0}else It=i.resolve(Lt,ie,Ae(Lt),kn);V[we]=_t&&It!=null?es(It):It}else{const _t={componentId:T.id,componentName:T.name,propName:we};V[we]=i.resolveBindings(He,ie,he,_t)}}else Array.isArray(He)?V[we]=He.map(et=>typeof et=="string"?i.resolveBindings(et,ie,he):typeof et=="object"&&et!==null?i.resolveObject(et,ie,Ce):et):He&&typeof He=="object"&&(V[we]=i.resolveObject(He,ie,Ce));for(const[we,He]of Object.entries(V))V[we]=wt(He);if(typeof V.style=="string"&&(V.style=x_(V.style)),V=bd(V,S?void 0:T.actions,ie,{componentContext:xe,actionDispatcher:c}),T.classMap){const we=pw(T.classMap,ie,i,{skipCache:!0});if(we){const He=V.className||"";V.className=He?`${He} ${we}`:we}}T.style&&(V.style=T.style),T.actions&&T.actions.length>0&&T.type==="composite"&&Object.assign(V,de),T.component_layout&&(V.__componentLayoutDefs=T.component_layout);const Fe=T.expandChildren||T.props?.expandChildren,Re=T.props?.cellChildren,Ne=T.children&&T.children.length>0,ke=T.component_layout,Ze=T.slot,ze=T.props?.modalId,Ge=T.type==="composite";return(Fe||Re||Ne||ke||Ze||ze||Ge)&&(V.__componentContext=xe),V},[T.props,T.actions,T.style,T.classMap,T.id,ie,n,i,l,xe,de,wt,kt,ft,b]),Ft=N.useRef(null),Nt=N.useMemo(()=>Ft.current&&gm(Ft.current,nn)?Ft.current:(Ft.current=nn,nn),[nn]),Br=N.useMemo(()=>{const V=T.id;if(typeof V!="string"||!V.includes("{{"))return V;const se=i.resolveBindings(V,ie,{skipCache:!0});return typeof se=="string"?se:V},[T.id,ie,i]),fn=N.useMemo(()=>{const V=T.dataKey,se=T.trackChanges,ue=T.debounce;if(V){const ee=V.startsWith("_global."),ve=ee?V.slice(8):V,he=ee?e._global:ie._local;return{dataKey:ve,trackChanges:se??!1,debounce:ue,setState:ee?Ae=>{e._globalSetState?e._globalSetState(Ae):at.warn("_global.formData 사용 시 _globalSetState가 필요합니다.")}:ye,state:he??{},_isGlobal:ee}}if(Z.dataKey)return Z},[T.dataKey,T.trackChanges,T.debounce,T.id,ye,ie._local,e._global,e._globalSetState,Z]),rn=N.useRef(new Set);N.useEffect(()=>{rn.current.clear()},[e._global?._remountKeys]);const hn=N.useCallback((V,se)=>{const ue=e._global?._remountKeys;return V&&ue?.[V]&&!rn.current.has(V)?(rn.current.add(V),`${V}-remount-${ue[V]}`):V||se},[e._global?._remountKeys]),Fn=N.useMemo(()=>{if(T.text!==void 0){if(typeof T.text=="string"){const V=T.text;let se=V;const ue={componentId:T.id,componentName:T.name,propName:"text",skipCache:!0},ee=ft(V);if(ee!==null){let ve=!1,he=ee;if(ee.startsWith(er)&&(ve=!0,he=ee.slice(er.length)),Pn(he))try{se=i.evaluatePipeExpression(he,ie,{skipCache:!0},ue)}catch(Ce){at.warn(`text 파이프 표현식 평가 실패 (컴포넌트: ${T.id}):`,Ce),se=""}else if(kt(he))try{se=i.evaluateExpression(he,ie,ue)}catch(Ce){at.warn(`text 표현식 평가 실패 (컴포넌트: ${T.id}):`,Ce),se=""}else se=i.resolve(he,ie,{skipCache:!0},ue);ve&&se!=null&&(se=es(se))}else V.includes("{{")&&(se=i.resolveBindings(V,ie,{skipCache:!0},ue));return se=wt(se),se??""}return T.text}return!T.children||T.children.length===0?null:T.children.map((V,se)=>{if(typeof V=="string")return V;const ue=T.__responsiveChildrenKey,ee=ue?`responsive.${ue}.children`:"children",ve=L?`${L}.${ee}.${se}`:`${se}`,he=V._fromBase?V.id||`child-${se}`:hn(V.id,`child-${se}`),Ce=!V._fromBase&&M?`${he}_${M}`:he;return dt.jsx(jr,{componentDef:V,dataContext:ie,translationContext:n,registry:a,bindingEngine:i,translationEngine:l,actionDispatcher:c,parentComponentContext:xe,parentFormContextProp:fn,isInsideIteration:b,isEditMode:S,onComponentSelect:v,onComponentHover:_,componentPath:ve,onDragStart:A,onDragEnd:x,layoutKey:M},Ce)})},[T.text,T.children,T.id,e,ie,n,a,i,l,c,xe,fn,ft,kt,wt,hn,b,S,v,_,L,A,x,M]),Pr=N.useMemo(()=>{if(!T.iteration)return null;try{const V=yd(T.iteration.source,ie,i);if(!Array.isArray(V))return at.warn(`iteration source가 배열이 아닙니다 (컴포넌트: ${T.id}):`,V),null;const se=Zr();return se?.isEnabled()&&se.trackIteration(T.id||`iteration-${Date.now()}`,T.iteration.source,T.iteration.item_var,T.iteration.index_var,V.length),V.map((ue,ee)=>{const ve={...ie,[T.iteration.item_var]:ue,[`${T.iteration.item_var}_index`]:ee};T.iteration.index_var&&(ve[T.iteration.index_var]=ee);const he=ee===0||ee===V.length-1;se?.isEnabled()&&he&&se.trackNestedContext?.({componentId:`${T.id||"unknown"}-iter-${ee}`,componentType:"iteration",parentContext:{available:Object.keys(ie),values:{}},ownContext:{added:[T.iteration.item_var,...T.iteration.index_var?[T.iteration.index_var]:[]],values:{[T.iteration.item_var]:ue,...T.iteration.index_var?{[T.iteration.index_var]:ee}:{}}},depth:1});const Ce={...T,iteration:void 0,responsive:void 0},Ae=L?`${L}.iteration.${ee}`:`iteration.${ee}`,Fe=`${hn(T.id,"item")}-${ee}`;return dt.jsx(jr,{componentDef:Ce,dataContext:ve,translationContext:n,registry:a,bindingEngine:i,translationEngine:l,actionDispatcher:c,parentComponentContext:xe,parentFormContextProp:fn,isInsideIteration:!0,isEditMode:S,onComponentSelect:v,onComponentHover:_,componentPath:Ae,onDragStart:A,onDragEnd:x,layoutKey:M},Fe)})}catch(V){return at.error(`iteration 렌더링 실패 (컴포넌트: ${T.id}):`,V),null}},[T.iteration,T.children,T.id,e,ie,n,a,i,l,c,xe,fn,hn,S,v,_,L,A,x,M]),[Pt,wi]=N.useState(0),na=N.useMemo(()=>{if(!T.sortable||!T.itemTemplate)return null;const{sortable:V,itemTemplate:se}=T;try{const ue=yd(V.source,ie,i);if(!Array.isArray(ue))return at.warn(`sortable source가 배열이 아닙니다 (컴포넌트: ${T.id}):`,ue),null;if(ue.length===0)return null;const ee=V.itemKey||"id",ve=V.strategy||"verticalList",he=V.itemVar||"$item",Ce=V.indexVar||"$index",Ae=V.handle,Fe=V.wrapperElement,Re=(Ze,ze)=>{const Ge=T.actions?.filter(we=>we.event==="onSortEnd"||we.type==="onSortEnd");if(wi(we=>we+1),Ge&&Ge.length>0&&c){const we={...ie,$sortedItems:Ze,$sortEvent:ze};Ge.forEach(He=>{try{const et=c.createHandler(He,we,xe),_t=new Event("sortend");et(_t)}catch(et){at.error(`onSortEnd action failed: ${He.handler}`,et)}})}},Ne=Ze=>{const ze=T.actions?.filter(Ge=>Ge.event==="onSortStart"||Ge.type==="onSortStart");if(ze&&ze.length>0&&c){const Ge={...ie,$activeId:Ze.activeId};ze.forEach(we=>{try{const He=c.createHandler(we,Ge,xe),et=new Event("sortstart");He(et)}catch(He){at.error(`onSortStart action failed: ${we.handler}`,He)}})}},ke=ue.map((Ze,ze)=>{const Ge=String(Ze[ee]),we={...ie,[he]:Ze,[Ce]:ze},He=L?`${L}.sortable.${ze}`:`sortable.${ze}`,et=`${hn(T.id,"sortable-item")}-v${Pt}-${Ge}`;return dt.jsx(__,{id:Ge,handle:Ae,...Fe?{as:Fe}:{},children:(Fe&&se.children?se.children:[se]).map((_t,Lt)=>dt.jsx(jr,{componentDef:_t,dataContext:we,translationContext:n,registry:a,bindingEngine:i,translationEngine:l,actionDispatcher:c,parentComponentContext:xe,parentFormContextProp:void 0,isInsideIteration:!0,isEditMode:S,onComponentSelect:v,onComponentHover:_,componentPath:He,onDragStart:A,onDragEnd:x,layoutKey:M},`${et}-child-${Lt}`))},et)});return dt.jsx(w_,{items:ue,itemKey:ee,strategy:ve,onSortEnd:Re,onSortStart:Ne,sortVersion:Pt,children:ke})}catch(ue){return at.error(`sortable 렌더링 실패 (컴포넌트: ${T.id}):`,ue),null}},[T.sortable,T.itemTemplate,T.actions,T.id,e,ie,n,a,i,l,c,xe,hn,S,v,_,L,A,x,Pt,M]),gn=N.useRef(!1);N.useEffect(()=>{if(gn.current)return;gn.current=!0;const V=Zr();if(V?.isEnabled()&&V.trackMount(o.id,{name:o.name,type:o.type||"component",props:Nt}),o.lifecycle?.onMount&&o.lifecycle.onMount.length>0)for(const ue of o.lifecycle.onMount)try{const ee=c.createHandler(ue,ie,xe),ve=new Event("mount");ee(ve),at.log(`Lifecycle onMount executed: ${ue.handler} (Component: ${o.id})`)}catch(ee){at.error(`Lifecycle onMount failed: ${ue.handler} (Component: ${o.id})`,ee)}const se=[];if(o.onComponentEvent&&o.onComponentEvent.length>0){const ue=window.G7Core;if(ue?.componentEvent?.on)for(const ee of o.onComponentEvent){if(!ee.event){at.warn(`onComponentEvent: event name is required (Component: ${o.id})`);continue}const ve=async Ce=>{try{const Ae={...ie,_eventData:Ce},Re=await c.createHandler({handler:ee.handler,params:ee.params,onSuccess:ee.onSuccess,onError:ee.onError},Ae,xe)(new CustomEvent(ee.event,{detail:Ce}));return at.log(`onComponentEvent "${ee.event}" handled: ${ee.handler} (Component: ${o.id})`,{eventData:Ce,result:Re}),Re}catch(Ae){throw at.error(`onComponentEvent "${ee.event}" failed: ${ee.handler} (Component: ${o.id})`,Ae),Ae}},he=ue.componentEvent.on(ee.event,ve);se.push(he),at.log(`onComponentEvent: Subscribed to "${ee.event}" (Component: ${o.id})`)}else at.warn(`onComponentEvent: G7Core.componentEvent is not available (Component: ${o.id})`)}return()=>{const ue=Zr();ue?.isEnabled()&&ue.trackUnmount(o.id);for(const ee of se)try{ee()}catch(ve){at.error(`onComponentEvent: Failed to unsubscribe (Component: ${o.id})`,ve)}if(se.length>0&&at.log(`onComponentEvent: Unsubscribed ${se.length} event(s) (Component: ${o.id})`),o.lifecycle?.onUnmount&&o.lifecycle.onUnmount.length>0)for(const ee of o.lifecycle.onUnmount)try{const ve=c.createHandler(ee,ie,xe),he=new Event("unmount");ve(he),at.log(`Lifecycle onUnmount executed: ${ee.handler} (Component: ${o.id})`)}catch(ve){at.error(`Lifecycle onUnmount failed: ${ee.handler} (Component: ${o.id})`,ve)}}},[]);const Rn=N.useMemo(()=>{const V=Nt.dataKey,se=Nt.trackChanges,ue=Nt.debounce;return V?{dataKey:V,trackChanges:se??!1,debounce:ue,setState:ye,state:de}:null},[Nt.dataKey,Nt.trackChanges,Nt.debounce,ye,de]);N.useEffect(()=>{const V=T.dataKey||Nt.dataKey;if(!V)return;const se=Zr();if(!se?.isEnabled())return;const ue=[],ee=he=>{if(he)for(const Ce of he){const Ae=Ce?.props?.name;if(Ae&&ue.push({name:Ae,type:Ce.name||Ce.type||"unknown"}),Ce?.children&&ee(Ce.children),Ce?.slots)for(const Fe of Object.values(Ce.slots))Array.isArray(Fe)&&ee(Fe)}};if(o.children&&ee(o.children),o.slots)for(const he of Object.values(o.slots))Array.isArray(he)&&ee(he);const ve=o.id||`form-${V}`;return se.trackForm(ve,V,ue),()=>{se.untrackForm(ve)}},[T,Nt.dataKey,o.id,o.children]);const tt=N.useRef(null),$n=N.useRef(void 0);N.useEffect(()=>{const V=Nt?.name;if(!V||!Z.dataKey||!Z.setState||Nt?.autoBinding===!1)return;const se=`${Z.dataKey}.${V}`,ue=window.__g7AutoBindingPaths??new Map;return window.__g7AutoBindingPaths=ue,ue.set(se,(ue.get(se)??0)+1),()=>{const ee=ue.get(se)??0;ee<=1?ue.delete(se):ue.set(se,ee-1)}},[Nt?.name,Nt?.autoBinding,Z.dataKey,Z.setState]);const pn=N.useMemo(()=>{const{dataKey:V,trackChanges:se,debounce:ue,...ee}=Nt,ve=ee.name;if(!ve||!Z.dataKey||!Z.setState)return ee;if(ee.autoBinding===!1){const{autoBinding:Ge,...we}=ee;return we}const he=`${Z.dataKey}.${ve}`,Ce=CC(Z.state,he),Ae=Ce!==void 0?Ce:ee.value,Re=a.getMetadata(o.name)?.bindingType,Ne=typeof Ae=="boolean"&&(Re==="checked"||Re==="checkable"&&["checkbox","radio"].includes(ee?.type)),ke=Z.debounce,Ze=Ge=>{const we=Z.state||{},He=EC(we,he,Ge);if(Z.trackChanges&&(He.hasChanges=!0),window.__g7PendingLocalState=He,Z.setState(He),Z._isGlobal)return;const et=window.G7Core,_t={[he]:Ge};Z.trackChanges&&(_t.hasChanges=!0),et?.state?.setLocal?.(_t,{render:!1})},ze=(Ge,we)=>{ke&&ke>0?(tt.current&&clearTimeout(tt.current),tt.current=setTimeout(()=>{Ze(Ge),tt.current=null,we&&(we(),window.__g7PendingLocalState=null)},ke)):(Ze(Ge),we&&(we(),window.__g7PendingLocalState=null))};if(Ne)return{...ee,checked:Ae,onChange:we=>{const He=we.target.checked;Ze(He),ee.onChange&&ee.onChange(we)}};{const Ge=He=>{const et=He?.target?.value!==void 0?He.target.value:He;ke&&ke>0&&($n.current=et);const _t=He?.target?{target:{value:et,name:He.target.name,type:He.target.type,checked:He.target.checked},currentTarget:He.currentTarget?{value:et,name:He.currentTarget.name}:void 0}:He;ze(et,()=>{ee.onChange&&ee.onChange(_t)})};let we;return $n.current!==void 0?tt.current!==null?we=$n.current:String(Ae??"")===String($n.current)?($n.current=void 0,we=Ae??""):we=$n.current:we=Ae??"",{...ee,value:we,onChange:Ge}}},[Nt,Z,Z.state,Z.debounce]),ra=N.useMemo(()=>{const V=Zr();if(V?.isEnabled()&&V.trackRender(o.name),!_e)return T.iteration?Pr:null;if(T.sortable&&T.itemTemplate)return na;if(T.iteration)return Pr;if(T.type==="extension_point"){const{layout:Re,columns:Ne,gap:ke,className:Ze,...ze}=T.props||{};let Ge=Ze||"";return Re==="grid"&&Ne?Ge=`${Ge} grid grid-cols-${Ne} gap-${ke||4}`.trim():Re==="flex"&&(Ge=`${Ge} flex flex-col gap-${ke||4}`.trim()),dt.jsx("div",{id:Br,className:Ge||void 0,...ze,children:Fn})}const se=a.getComponent(T.name);if(!se)return at.error(`컴포넌트를 찾을 수 없습니다: ${T.name} (ID: ${T.id})`,"componentDef:",JSON.stringify(T,null,2)),null;const ue=e._global?._remountKeys,ee={...pn,id:pn.id??Br,...ue&&Object.keys(ue).length>0&&{__remountTrigger:JSON.stringify(ue)}};if(H?.listeners&&H.handle&&pn["data-drag-handle"]!==void 0&&(Object.assign(ee,H.listeners),ee.style={...ee.style,cursor:H.isDragging?"grabbing":"grab"}),S){const Re=T.id||`auto_${T.name||T.type||"unknown"}_${Math.random().toString(36).substring(2,8)}`,Ne=ze=>{typeof ze.preventDefault=="function"&&ze.preventDefault(),v&&(ze.stopPropagation(),v(Re,ze))},ke={"data-editor-id":Re,"data-editor-name":T.name,"data-editor-type":T.type,onClick:Ne};L&&(ke["data-editor-path"]=L);const Ze=T.__editorSlotName??T.slot;typeof Ze=="string"&&(ke["data-editor-slot"]=Ze),_&&(ke.onMouseMove=ze=>{ze.stopPropagation(),_(Re,ze)},ke.onMouseLeave=ze=>{_(null,ze)}),Object.assign(ee,ke),ee.editorAttrs=ke}const ve=T.type==="basic",he=T.type==="layout",Ae=ve||he?(()=>{const Re={};for(const[Ne,ke]of Object.entries(ee))Ne.startsWith("__")||Ne==="editorAttrs"&&ve||(Re[Ne]=ke);return Re})():ee;let Fe=dt.jsx(se,{...Ae,children:Fn});if(fn&&(Fe=dt.jsx(SC,{value:fn,children:Fe})),T.isolatedState){const Re=typeof T.isolatedState=="object"?T.isolatedState:{},Ne=e?._isolatedInit,ke=Ne?{...Re,...Ne}:Re;Fe=dt.jsx(kC,{initialState:ke,scopeId:T.isolatedScopeId,children:Fe})}return Fe},[_e,T.iteration,T.sortable,T.itemTemplate,T.type,T.name,T.id,T.props,T.isolatedState,T.isolatedScopeId,a,pn,Fn,Pr,na,H,Rn,S,v,_,A,x,L,e._global?._remountKeys]),ir=N.useMemo(()=>{const V=T.blur_until_loaded;if(!V||e?._global?.__isPreview)return!1;if(typeof V=="string"){const ee=ft(V);if(ee!==null)try{const ve={componentId:T.id,componentName:T.name,propName:"blur_until_loaded"};return!!i.evaluateExpression(ee,ie,ve)}catch(ve){return at.warn(`blur_until_loaded 표현식 평가 실패 (컴포넌트: ${T.id}):`,ve),!1}return!1}if(typeof V=="object"&&V!==null){if(!V.enabled)return!1;if(V.data_sources)return(Array.isArray(V.data_sources)?V.data_sources:[V.data_sources]).some(Ce=>e[Ce]===void 0);if(fe)return!0;const ee=["route","query","_global","_local","_dataSourceErrors"];return Object.keys(e).filter(he=>!ee.includes(he)&&!he.startsWith("_")).some(he=>e[he]===void 0)}if(fe)return!0;const se=["route","query","_global","_local","_dataSourceErrors"];return Object.keys(e).filter(ee=>!se.includes(ee)&&!ee.startsWith("_")).some(ee=>e[ee]===void 0)},[T.blur_until_loaded,T.id,fe,e,ie,i,ft]);if(ir){const V=T.blur_until_loaded;if(typeof V=="object"&&V?.data_sources){const ue=(Array.isArray(V.data_sources)?V.data_sources:[V.data_sources]).reduce((ve,he)=>(ve[he]=e[he]===void 0?"UNDEFINED":"LOADED",ve),{}),ee=Object.keys(e).filter(ve=>!ve.startsWith("_"));at.log(`[BLUR APPLIED] Component: ${T.id}, data_sources status:`,ue,"Available keys:",ee)}else at.log(`[BLUR APPLIED] Component: ${T.id}, blur_until_loaded:`,V)}const an=N.useMemo(()=>{if(!T.blur_until_loaded)return{wrapperClasses:"",innerClasses:""};const V=nn?.className||"";if(!V)return{wrapperClasses:"",innerClasses:""};const se=[/^(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-)/],ue=V.split(/\s+/).filter(Boolean),ee=[],ve=[];for(const he of ue)se.some(Ae=>Ae.test(he))?ee.push(he):ve.push(he);return{wrapperClasses:ee.join(" "),innerClasses:ve.join(" ")}},[T.blur_until_loaded,nn?.className]),En=window.__slotContextValue;return Te&&En?.isEnabled?null:dt.jsx(T_,{componentId:o.id,componentName:o.name,children:T.blur_until_loaded?dt.jsx("div",{className:[an.wrapperClasses,ir?"opacity-50 blur-sm transition-all duration-300 pointer-events-none":void 0].filter(Boolean).join(" ")||void 0,children:ra}):ra})});jr.displayName="DynamicRenderer",typeof window<"u"&&(window.__DynamicRenderer=jr);function R_(o){const e={};try{const a=new URL(o,typeof window<"u"?window.location.origin:"http://localhost").searchParams,i=new Set;for(const l of a.keys()){if(i.has(l))continue;i.add(l);const c=a.getAll(l);c.length>1||l.endsWith("[]")?e[l]=c:e[l]=c[0]}}catch{}return e}function k_(o){try{return new URL(o,typeof window<"u"?window.location.origin:"http://localhost").pathname}catch{return o.split("?")[0]}}const Si=class Si{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 Si.instance||(Si.instance=new Si),Si.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 a=window.G7Core?.state?.get?.();return a?.settings?.advanced?.debug_mode===!0||a?._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 n={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(n),this.stateHistory.length>this.config.maxHistorySize&&this.stateHistory.shift(),this.notifyStateWatchers(n)}getState(){try{const e=window.G7Core,n=e?.state?.get?.()||{},a={};if(e?._isolatedStates&&typeof e._isolatedStates=="object")for(const[i,l]of Object.entries(e._isolatedStates))a[i]=this.sanitizeObject(l);return{_global:n._global||n,_local:this.currentLocalState,_computed:this.currentComputedState,_isolated:Object.keys(a).length>0?a: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 n={};try{n=(window.G7Core?.state?.get?.()||{})._local||{}}catch{n={}}const a=this.findMismatchedLeafPaths(e,n);return{hasMismatch:a.length>0,mismatchedPaths:a,storageA:e,storageB:n}}findMismatchedLeafPaths(e,n,a=""){const i=[],l=new Set([...Object.keys(e||{}),...Object.keys(n||{})]);for(const c of l){const d=a?`${a}.${c}`:c,f=e?.[c],g=n?.[c],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 S=f===void 0?"__undefined__":JSON.stringify(f),v=g===void 0?"__undefined__":JSON.stringify(g);S!==v&&i.push(d)}}return i}watchState(e,n){return this.stateWatchers.has(e)||this.stateWatchers.set(e,new Set),this.stateWatchers.get(e).add(n),()=>{this.stateWatchers.get(e)?.delete(n)}}notifyStateWatchers(e){if(this.stateWatchers.get("*")?.forEach(n=>{try{n(e.next,e.prev,"*")}catch(a){console.error("[G7DevTools] State watcher error:",a)}}),e.diff)for(const n of e.diff.changed)this.stateWatchers.get(n.path)?.forEach(a=>{try{a(n.newValue,n.oldValue,n.path)}catch(i){console.error("[G7DevTools] State watcher error:",i)}})}diffSnapshots(e,n){const a=this.stateHistory.find(l=>l.id===e),i=this.stateHistory.find(l=>l.id===n);return!a||!i?null:this.calculateDiff(a.next,i.next)}calculateDiff(e,n,a=""){const i={added:[],removed:[],changed:[]},l=new Set(Object.keys(e)),c=new Set(Object.keys(n));for(const d of c){const f=a?`${a}.${d}`:d;l.has(d)?JSON.stringify(e[d])!==JSON.stringify(n[d])&&i.changed.push({path:f,oldValue:e[d],newValue:n[d]}):i.added.push(f)}for(const d of l){const f=a?`${a}.${d}`:d;c.has(d)||i.removed.push(f)}return i}logAction(e){if(!this.config.enabled)return;const n=this.actionHistory.findIndex(a=>a.id===e.id);n>=0?this.actionHistory[n]={...this.actionHistory[n],...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(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Action watcher error:",a)}})}getActionMetrics(){const e=this.actionHistory.filter(l=>l.status==="success"),n=this.actionHistory.filter(l=>l.status==="error"),a={};for(const l of this.actionHistory)a[l.type]=(a[l.type]||0)+1;const i=e.reduce((l,c)=>l+(c.duration||0),0);return{totalActions:this.actionHistory.length,successCount:e.length,errorCount:n.length,averageDuration:e.length>0?i/e.length:0,actionsByType:a}}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 n={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(n),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 n=0,a=0,i=0,l=0;const c={},d={};for(const g of e)g.decision==="cache_hit"?n++:g.decision==="cache_miss"?a++:g.decision==="skip_cache"?i++:g.decision==="invalidate"&&l++,c[g.reason]=(c[g.reason]||0)+1,g.context.componentId&&(d[g.context.componentId]=(d[g.context.componentId]||0)+1);const f=n+a+i;return{totalDecisions:e.length,cacheHits:n,cacheMisses:a,skipCacheCount:i,invalidateCount:l,byReason:c,byComponent:d,avgHitRate:f>0?n/f:0}}getRecentCacheDecisions(e=20,n){let a=[...this.cacheDecisions];return n&&(a=a.filter(i=>i.decision===n)),a.slice(-e)}clearCacheDecisionData(){this.cacheDecisions=[],this.cacheDecisionIdCounter=0}summarizePropsForLifecycle(e){if(!e||typeof e!="object")return e;const n={},a=["children","ref","key"];for(const[i,l]of Object.entries(e))if(!a.includes(i))if(l==null)n[i]=l;else if(Array.isArray(l))n[i]=`[Array(${l.length})]`;else if(typeof l=="object"){const c=Object.keys(l);c.length<=3?n[i]=`{${c.join(", ")}}`:n[i]=`{${c.slice(0,3).join(", ")}, ... +${c.length-3}}`}else typeof l=="string"&&l.length>50?n[i]=l.substring(0,50)+"...":typeof l=="function"?n[i]="[Function]":n[i]=l;return n}trackMount(e,n){if(!this.config.enabled)return;const a=this.summarizePropsForLifecycle(n.props),i={...n,props:a,id:e,mountTime:Date.now()};this.mountedComponents.set(e,i),this.mountWatchers.forEach(l=>{try{l({componentId:e,componentName:n.name,timestamp:i.mountTime})}catch(c){console.error("[G7DevTools] Mount watcher error:",c)}})}trackUnmount(e){if(!this.config.enabled)return;const n=this.mountedComponents.get(e),a=this.eventListeners.get(e)||[];a.length>0&&console.warn(`[G7DevTools] 컴포넌트 ${e} 언마운트 시 ${a.length}개 리스너 미정리`),n&&this.unmountWatchers.forEach(i=>{try{i({componentId:e,componentName:n.name,timestamp:Date.now(),orphanedListeners:a.length})}catch(l){console.error("[G7DevTools] Unmount watcher error:",l)}}),this.mountedComponents.delete(e)}trackListener(e,n,a){if(!this.config.enabled)return;const i=this.eventListeners.get(e)||[];i.push({type:n,target:a,addedAt:Date.now()}),this.eventListeners.set(e,i)}removeListener(e,n){if(!this.config.enabled)return;const a=this.eventListeners.get(e)||[],i=a.findIndex(l=>l.type===n);i>=0&&a.splice(i,1)}getMountedComponents(){return Array.from(this.mountedComponents.values())}getOrphanedListeners(){const e=[];for(const[n,a]of this.eventListeners)this.mountedComponents.has(n)||e.push(...a.map(i=>({...i,componentId:n})));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 n=this.renderCounts.get(e)||0;this.renderCounts.set(e,n+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 n=this.getOrphanedListeners().length;n>0&&e.push({type:"orphaned-listeners",message:`${n}개의 정리되지 않은 이벤트 리스너`,suggestion:"useEffect cleanup 또는 removeEventListener 확인",severity:n>10?"error":"warning"});const a=Array.from(this.renderCounts.entries()).filter(([,i])=>i>50);return a.length>0&&e.push({type:"excessive-renders",message:`${a.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,n=this.analyzeProfile(e);return console.log("[G7DevTools] 프로파일링 완료",n),n}analyzeProfile(e){const n=this.profilingData.filter(g=>g.type==="render"),a=this.profilingData.filter(g=>g.type==="binding"),i=this.profilingData.filter(g=>g.type==="action"),l={};for(const g of n)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 c=Object.entries(l).map(([g,m])=>({name:g,renderCount:m.count,avgDuration:m.durations.length>0?m.durations.reduce((b,S)=>b+S,0)/m.durations.length:0})).sort((g,m)=>m.renderCount-g.renderCount).slice(0,10),d={};for(const g of a)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:n.length,totalBindings:a.length,totalActions:i.length,slowestComponents:c,hotPaths:f}}}resetPerformanceStats(){this.renderCounts.clear(),this.bindingEvalCount=0,this.profilingData=[]}trackRequest(e,n,a){if(!this.config.enabled)return"";const i=this.generateId(),l=k_(e),c=R_(e);return this.activeRequests.set(i,{id:i,url:l,fullUrl:e,queryParams:c,method:n,startTime:Date.now(),status:"pending",requestBody:a?.requestBody?this.sanitizeObject(a.requestBody):void 0,dataSourceId:a?.dataSourceId}),this.isProfiling&&this.profilingData.push({type:"network",timestamp:performance.now()}),i}completeRequest(e,n,a){if(!this.config.enabled)return;const i=this.activeRequests.get(e);if(!i)return;const l={...i,status:n>=200&&n<300?"success":"error",statusCode:n,duration:Date.now()-i.startTime,endTime:Date.now(),response:this.sanitizeObject(a)};this.requestHistory.push(l),this.activeRequests.delete(e),this.requestHistory.length>this.config.maxHistorySize&&this.requestHistory.shift(),this.notifyRequestWatchers(l)}failRequest(e,n){if(!this.config.enabled)return;const a=this.activeRequests.get(e);if(!a)return;const i={...a,status:"error",error:n,duration:Date.now()-a.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(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Request watcher error:",a)}})}trackWebSocketConnection(e,n,a){this.config.enabled&&this.wsConnections.set(e,{id:e,url:n,state:a,connectedAt:a==="open"?Date.now():void 0})}trackWebSocketMessage(e,n,a,i){if(!this.config.enabled)return;const l={id:this.generateId(),connectionId:e,direction:n,type:a,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(n=>n.state==="open")?"connected":e.some(n=>n.state==="connecting")?"reconnecting":"disconnected"}watchWebSocketMessage(e){return this.wsMessageWatchers.add(e),()=>{this.wsMessageWatchers.delete(e)}}notifyWebSocketWatchers(e){this.wsMessageWatchers.forEach(n=>{try{n(e)}catch(a){console.error("[G7DevTools] WebSocket watcher error:",a)}})}trackIfCondition(e,n,a){if(!this.config.enabled)return;const i=this.ifConditions.get(e),l=i?.evaluatedValue;this.ifConditions.set(e,{id:e,expression:n,evaluatedValue:a,evaluationCount:(i?.evaluationCount||0)+1,lastEvaluated:Date.now()}),i&&l!==a&&this.notifyConditionWatchers({id:e,expression:n,oldValue:l,newValue:a,timestamp:Date.now()})}trackIteration(e,n){this.config.enabled&&this.iterations.set(e,{id:e,...n,lastRendered:Date.now()})}getIfConditions(){return Array.from(this.ifConditions.values())}getIterations(){return Array.from(this.iterations.values())}getScopeChain(e){const n=[],a=this.getState();return n.push({name:"_global",value:a._global,source:"global"}),n.push({name:"_local",value:a._local,source:"local"}),n.push({name:"_computed",value:a._computed,source:"computed"}),n}watchConditionChange(e){return this.conditionWatchers.add(e),()=>{this.conditionWatchers.delete(e)}}notifyConditionWatchers(e){this.conditionWatchers.forEach(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Condition watcher error:",a)}})}trackForm(e,n,a){this.config.enabled&&this.forms.set(e,{id:e,dataKey:n,inputs:a,trackedAt:Date.now()})}trackFormChange(e,n,a){if(!this.config.enabled)return;const i={formId:e,inputName:n,value:a,timestamp:Date.now()};this.notifyFormWatchers(i)}untrackForm(e){this.forms.delete(e)}getForms(){return Array.from(this.forms.values())}getFormState(e){const n=this.getState();return this.getNestedValue(n,e)||{}}getBindingPath(e,n){return`${e}.${n}`}watchFormChange(e){return this.formWatchers.add(e),()=>{this.formWatchers.delete(e)}}notifyFormWatchers(e){this.formWatchers.forEach(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Form watcher error:",a)}})}trackFormBindingIssue(e,n,a){if(!this.config.enabled)return;const i={id:`form-issue-${++this.formBindingIssueIdCounter}`,timestamp:Date.now(),type:e,severity:n,formId:a.formId,formDataKey:a.formDataKey,inputInfo:a.inputInfo,contextInfo:a.contextInfo,description:a.description,suggestion:a.suggestion,docLink:a.docLink};this.formBindingIssues.push(i),this.formBindingIssues.length>this.maxFormBindingIssues&&this.formBindingIssues.shift()}validateFormBinding(e,n,a,i){const l=a.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:n,inputInfo:{name:f.name,type:f.type},description:"Input에 name 속성이 없어 자동 바인딩이 동작하지 않습니다",suggestion:"Input에 name 속성을 추가하세요",docLink:"troubleshooting-components-form.md"})),n||(g.push("Form에 dataKey가 없습니다"),m=!1),{inputName:f.name||"(unnamed)",inputType:f.type,bindingPath:n&&f.name?`${n}.${f.name}`:"-",isValid:m,currentValue:f.value,issues:g}});if(n||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:n,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 c={formId:e,dataKey:n,timestamp:Date.now(),contextPropagation:i,inputBindings:l,isValid:l.every(f=>f.isValid)&&!!n&&!i.isContextBroken,issueCount:l.filter(f=>!f.isValid).length+(n?0:1)+(i.isContextBroken?1:0)},d=this.formBindingValidations.findIndex(f=>f.formId===e);return d>=0?this.formBindingValidations[d]=c:this.formBindingValidations.push(c),c}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},n={info:0,warning:0,error:0};for(const i of this.formBindingIssues)e[i.type]++,n[i.severity]++;const a=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:n,topIssues:a}}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,n,a,i,l,c,d){if(!this.config.enabled)return;const f=`computed-${e}-${c||"global"}`,g={id:f,name:e,expression:n,componentId:c,dependencies:a,currentValue:this.safeClone(i),lastComputedAt:Date.now(),computationTime:l,error:d};this.computedProperties.set(f,g)}trackComputedRecalc(e,n,a,i,l,c,d){if(!this.config.enabled)return;const f=`computed-${e}-${d||"global"}`,g=JSON.stringify(a)!==JSON.stringify(i),m={id:`recalc-${++this.computedRecalcIdCounter}`,computedId:f,computedName:e,timestamp:Date.now(),trigger:n,triggeredBy:c,previousValue:this.safeClone(a),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,n){const a=new Set,i=[];let l=!1,c,d=0;const f=(m,b)=>{if(d=Math.max(d,b),a.has(m))return l=!0,c=[...i,m],{name:m,type:"computed",children:[],depth:b};a.add(m),i.push(m);const S=this.computedProperties.get(`computed-${m}-${n||"global"}`),v=[];if(S)for(const _ of S.dependencies)_.type==="computed"?v.push(f(_.path,b+1)):v.push({name:_.path,type:_.type,children:[],depth:b+1});return i.pop(),a.delete(m),{name:m,type:"computed",children:v,depth:b}},g=f(e,0);return{root:e,tree:g,hasCycle:l,cyclePath:c,maxDepth:d}}getComputedDependencyTrackingInfo(){const e=Array.from(this.computedProperties.values()),n=this.getComputedDependencyStats(),a=[];for(const i of e){const l=this.analyzeComputedDependencyChain(i.name,i.componentId);a.push(l)}return{properties:e,recalcLogs:[...this.computedRecalcLogs],dependencyChains:a,stats:n,timestamp:Date.now()}}getComputedDependencyStats(){const e={"state-change":0,"datasource-update":0,"dependency-change":0,manual:0,initial:0},n={},a={};let i=0,l=0;for(const g of this.computedRecalcLogs)e[g.trigger]++,g.valueChanged||l++,n[g.computedName]=(n[g.computedName]||0)+1,a[g.computedName]||(a[g.computedName]=[]),a[g.computedName].push(g.computationTime),i+=g.computationTime;const c=Object.entries(n).sort((g,m)=>m[1]-g[1]).slice(0,5).map(([g,m])=>({name:g,count:m})),d=Object.entries(a).map(([g,m])=>({name:g,avgTime:m.reduce((b,S)=>b+S,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:c,slowestComputed:d,cycleDetectionCount:f,byTrigger:e}}clearComputedTracking(){this.computedProperties.clear(),this.computedRecalcLogs=[],this.computedRecalcIdCounter=0}trackModalOpen(e){if(!this.config.enabled)return;const n={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,n),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,n){if(!this.config.enabled)return;const a=this.modalStates.get(e);a&&(a.closedAt=Date.now(),n&&(a.currentState={...n}),this.detectStateLeakage(a))}validateModalDefinitionExists(e,n){const a=this.currentLayout;if(!a?.layoutJson)return;const i=a.layoutJson.modals;if(!i){this.recordModalStateIssue({type:"missing-definition",modalId:e,modalName:n,severity:"error",description:`모달 "${e}"이(가) modalStack에 추가되었으나, 현재 레이아웃에 modals 섹션이 없습니다. 레이아웃 경로: ${a.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:n,severity:"error",description:`모달 "${e}"이(가) modalStack에 추가되었으나, 렌더링된 레이아웃의 modals 섹션에 해당 ID의 정의가 없습니다. partial 로딩 실패, 레이아웃 병합 문제, extends 상속 누락 등을 확인하세요. 레이아웃 경로: ${a.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 n=this.modalStates.get(e.modalId);if(!n)return;n.stateChangeCount++,n.currentState[e.stateKey]=e.newValue;const a=this.checkIsolationViolation(n,e.stateKey),i={id:`modal-change-${++this.modalStateChangeLogIdCounter}`,modalId:e.modalId,modalName:n.modalName,timestamp:Date.now(),stateKey:e.stateKey,previousValue:e.previousValue,newValue:e.newValue,changeSource:e.changeSource||"user-action",violatesIsolation:a};this.modalStateChangeLogs.push(i),this.modalStateChangeLogs.length>this.maxModalStateChangeLogs&&this.modalStateChangeLogs.shift(),a&&this.recordModalStateIssue({type:"isolation-violation",modalId:e.modalId,modalName:n.modalName,severity:"warning",description:`모달 '${n.modalName}'에서 격리된 상태 키 '${e.stateKey}'가 변경됨`,affectedStateKeys:[e.stateKey]})}detectStateLeakage(e){if(e.scopeType==="isolated")for(const n of e.isolatedStateKeys){const a=e.initialState[n],i=e.currentState[n];if(a!==i&&e.parentModalId){const l=this.modalStates.get(e.parentModalId);l&&l.currentState.hasOwnProperty(n)&&this.recordModalStateIssue({type:"state-leakage",modalId:e.modalId,modalName:e.modalName,severity:"error",description:`모달 닫힘 후 상태 '${n}'가 부모 모달로 유출될 수 있음`,affectedStateKeys:[n],leakedValue:i,expectedValue:a})}}}checkIsolationViolation(e,n){return e.scopeType==="isolated",!1}recordModalStateIssue(e){const n={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(n),this.modalStateIssues.length>this.maxModalStateIssues&&this.modalStateIssues.shift()}getModalStateScopeTrackingInfo(){const e=Array.from(this.modalStates.values()),n=this.getModalStateScopeStats();return{modals:e,issues:[...this.modalStateIssues],relations:[...this.modalStateRelations],changeLogs:[...this.modalStateChangeLogs],stats:n,timestamp:Date.now()}}getModalStateScopeStats(){const e=Array.from(this.modalStates.values()),n={warning:0,error:0},a={"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)n[l.severity]++,a[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:n,issuesByType:a,byScope:i,leakageDetectionCount:a["state-leakage"],cleanupFailureCount:a["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 n={...e,id:`named_action_ref_${++this.namedActionRefIdCounter}`};this.namedActionRefLogs.push(n),this.namedActionRefLogs.length>this.maxNamedActionRefLogs&&(this.namedActionRefLogs=this.namedActionRefLogs.slice(-this.maxNamedActionRefLogs))}getNamedActionTrackingInfo(){const e={};for(const a of this.namedActionRefLogs)e[a.actionRefName]=(e[a.actionRefName]||0)+1;const n=Object.keys(this.namedActionDefinitions).filter(a=>!e[a]);return{definitions:this.namedActionDefinitions,refLogs:[...this.namedActionRefLogs],stats:{totalDefinitions:Object.keys(this.namedActionDefinitions).length,totalRefs:this.namedActionRefLogs.length,refCountByName:e,unusedDefinitions:n},timestamp:Date.now()}}clearNamedActionTracking(){this.namedActionDefinitions={},this.namedActionRefLogs=[],this.namedActionRefIdCounter=0}trackExpressionEval(e){if(!this.config.enabled)return;const n={...e,id:`expr-${++this.expressionIdCounter}`,timestamp:Date.now(),warning:this.detectExpressionWarning(e)};this.expressionHistory.push(n),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(n)}detectExpressionWarning(e){const{expression:n,result:a,resultType:i,method:l,duration:c}=e;if(i==="undefined"&&!n.includes("??")&&!n.includes("||")&&/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(n.replace(/{{|}}/g,"").trim()))return{type:"undefined-result",message:"표현식 결과가 undefined입니다",suggestion:`데이터가 로드되었는지 확인하거나 fallback 값을 추가하세요: ${n} ?? ''`};if(i==="null")return{type:"null-result",message:"표현식 결과가 null입니다",suggestion:`nullish coalescing 연산자를 사용하세요: ${n} ?? ''`};if(l==="resolveBindings"&&i==="string"){const d=String(a);if(d.includes("[object Object]")||/^\[.*\]$/.test(d))return{type:"array-to-string",message:"배열/객체가 문자열로 변환되었습니다",suggestion:"evaluateExpression()을 사용하여 원본 타입을 유지하세요"}}if(l==="resolveBindings"&&i==="string"&&String(a).includes("[object Object]"))return{type:"object-to-string",message:"객체가 [object Object]로 변환되었습니다",suggestion:"evaluateExpression()을 사용하거나 특정 속성에 접근하세요"};if(i==="undefined"&&n.includes(".")&&!n.includes("?.")){const d=n.replace(/{{|}}/g,"").trim().split(".");if(d.length>=2)return{type:"missing-optional-chain",message:"Optional chaining(?.) 누락 가능성",suggestion:`안전한 접근을 위해 ?. 사용을 고려하세요: ${d.join("?.")}`}}if((n.includes("{{item.")||n.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(c&&c>10)return{type:"slow-evaluation",message:`표현식 평가에 ${c.toFixed(2)}ms 소요됨`,suggestion:"복잡한 표현식을 단순화하거나 computed 값으로 분리하세요"}}getExpressions(){return[...this.expressionHistory]}getExpressionWarnings(){return this.expressionHistory.filter(e=>e.warning!=null)}searchExpressions(e){const n=e.toLowerCase();return this.expressionHistory.filter(a=>a.expression.toLowerCase().includes(n)||a.componentName?.toLowerCase().includes(n)||a.propName?.toLowerCase().includes(n))}getExpressionStats(){const e=this.expressionHistory,n=new Set(e.map(f=>f.expression)),a=e.filter(f=>f.warning!=null),i=e.filter(f=>f.fromCache),l=e.filter(f=>f.duration!=null).map(f=>f.duration),c={};for(const f of e)c[f.resultType]=(c[f.resultType]||0)+1;const d={};for(const f of a)f.warning&&(d[f.warning.type]=(d[f.warning.type]||0)+1);return{totalEvaluations:e.length,uniqueExpressions:n.size,warningCount:a.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:c,byWarning:d}}clearExpressions(){this.expressionHistory=[],this.expressionIdCounter=0}watchExpressions(e){return this.expressionWatchers.add(e),()=>{this.expressionWatchers.delete(e)}}notifyExpressionWatchers(e){this.expressionWatchers.forEach(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Expression watcher error:",a)}})}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,n=new WeakSet){if(e===null||typeof e!="object")return e;if(n.has(e))return"[Circular]";if(n.add(e),Array.isArray(e))return e.map(i=>this.sanitizeObject(i,n));const a={};for(const i of Object.keys(e))try{a[i]=this.sanitizeObject(e[i],n)}catch{a[i]="[Unable to serialize]"}return a}getNestedValue(e,n){if(!n)return e;const a=n.split(".");let i=e;for(const l of a){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 n=[...this.stateHistory].reverse().find(a=>a.timestamp<=e);if(n)return{_global:n.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,n,a){if(!this.config.enabled)return;const i=a.map(c=>{if(typeof c=="string")return c;try{return JSON.stringify(c)}catch{return String(c)}}).join(" "),l={id:`log-${++this.logIdCounter}`,level:e,prefix:n,message:i,args:this.sanitizeObject(a),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 n={id:`debounce-action-${++this.debounceActionIdCounter}`,...e,timestamp:Date.now()};this.debounceActionHistory.push(n),this.debounceActionHistory.length>100&&this.debounceActionHistory.shift()}trackDataSourceUpdate(e){if(!this.config.enabled)return;const n={id:`ds-update-${++this.dataSourceUpdateIdCounter}`,...e};this.dataSourceUpdateHistory.push(n),this.dataSourceUpdateHistory.length>100&&this.dataSourceUpdateHistory.shift()}getDebounceActionHistory(e){let n=[...this.debounceActionHistory];return e?.handler&&(n=n.filter(a=>a.handler.includes(e.handler))),e?.status&&(n=n.filter(a=>a.status===e.status)),e?.limit&&(n=n.slice(-e.limit)),n}getDataSourceUpdateHistory(e){let n=[...this.dataSourceUpdateHistory];return e?.dataSourceId&&(n=n.filter(a=>a.dataSourceId===e.dataSourceId)),e?.updateType&&(n=n.filter(a=>a.updateType===e.updateType)),e?.limit&&(n=n.slice(-e.limit)),n}getLogs(e){let n=[...this.logHistory];if(e?.level){const a=Array.isArray(e.level)?e.level:[e.level];n=n.filter(i=>a.includes(i.level))}if(e?.prefix){const a=e.prefix.toLowerCase();n=n.filter(i=>i.prefix.toLowerCase().includes(a))}if(e?.search){const a=e.search.toLowerCase();n=n.filter(i=>i.message.toLowerCase().includes(a))}return e?.since&&(n=n.filter(a=>a.timestamp>=e.since)),e?.limit&&(n=n.slice(-e.limit)),n}getLogStats(){const n=Date.now()-6e4,a={log:0,warn:0,error:0,debug:0,info:0},i={};let l=0,c=0;for(const d of this.logHistory)a[d.level]++,i[d.prefix]=(i[d.prefix]||0)+1,d.timestamp>=n&&(d.level==="error"&&l++,d.level==="warn"&&c++);return{totalLogs:this.logHistory.length,byLevel:a,byPrefix:i,recentErrors:l,recentWarnings:c}}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 n=this.dataSources.get(e);n&&this.dataSources.set(e,{...n,status:"loading"})}trackDataSourceLoaded(e,n,a){if(!this.config.enabled)return;const i=this.dataSources.get(e);if(!i)return;let l,c,d=a;n&&(Array.isArray(n)?(l=n.length,c=n.length>0&&typeof n[0]=="object"?Object.keys(n[0]):void 0):typeof n=="object"&&(Array.isArray(n.data)?(d=d||"data",l=n.data.length,c=n.data.length>0&&typeof n.data[0]=="object"?Object.keys(n.data[0]):void 0):Array.isArray(n.items)?(d=d||"items",l=n.items.length,c=n.items.length>0&&typeof n.items[0]=="object"?Object.keys(n.items[0]):void 0):c=Object.keys(n))),this.dataSources.set(e,{...i,status:"loaded",dataPath:d,itemCount:l,keys:c,lastLoadedAt:Date.now(),error:void 0})}trackDataSourceError(e,n){if(!this.config.enabled)return;const a=this.dataSources.get(e);a&&this.dataSources.set(e,{...a,status:"error",error:n,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 n=this.dataPathTransforms.find(a=>a.dataSourceId===e.dataSourceId);n||(n={dataSourceId:e.dataSourceId,timestamp:Date.now(),transformSteps:[],warnings:[]},this.dataPathTransforms.push(n),this.dataPathTransforms.length>this.maxDataPathTransforms&&this.dataPathTransforms.shift()),n.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&&n.warnings.push(e.warning)}setDataPathFinalBinding(e,n){if(!this.config.enabled)return;const a=this.dataPathTransforms.find(i=>i.dataSourceId===e);a&&(a.finalBinding={expression:n.expression,resolvedPath:n.resolvedPath,value:this.safeClone(n.value)})}getDataPathTransformTrackingInfo(){const e=this.getDataPathTransformStats();return{transforms:[...this.dataPathTransforms],stats:e,timestamp:Date.now()}}getDataPathTransformStats(){const e=this.dataPathTransforms,n={};let a=0;const i={};for(const c of e){n[c.dataSourceId]=(n[c.dataSourceId]||0)+1,a+=c.warnings.length;for(const d of c.warnings)i[d]=(i[d]||0)+1}const l=Object.entries(i).map(([c,d])=>({warning:c,count:d})).sort((c,d)=>d.count-c.count).slice(0,10);return{totalTransforms:e.length,byDataSource:n,warningsCount:a,commonWarnings:l}}getDataPathTransformForDataSource(e){return this.dataPathTransforms.find(n=>n.dataSourceId===e)}clearDataPathTransforms(){this.dataPathTransforms=[]}trackNestedContext(e){if(!this.config.enabled)return"";const n=`nested-${++this.nestedContextIdCounter}`,a=[...new Set([...e.parentContext.available,...e.ownContext.added])],i={...e.parentContext.values,...e.ownContext.values},l={id:n,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:a,values:this.safeClone(i)},accessAttempts:[],depth:e.depth,parentId:e.parentId};return this.nestedContexts.push(l),this.nestedContexts.length>this.maxNestedContexts&&this.nestedContexts.shift(),n}trackNestedContextAccess(e,n){if(!this.config.enabled)return;const a=this.nestedContexts.find(i=>i.id===e);a&&a.accessAttempts.push({path:n.path,found:n.found,value:n.found?this.safeClone(n.value):void 0,error:n.error})}getNestedContextTrackingInfo(){const e=this.getNestedContextStats();return{contexts:[...this.nestedContexts],stats:e,timestamp:Date.now()}}getNestedContextStats(){const e=this.nestedContexts,n={expandChildren:0,cellChildren:0,iteration:0,modal:0,slot:0};let a=0,i=0;const l={};for(const d of e){n[d.componentType]++,d.depth>a&&(a=d.depth);for(const f of d.accessAttempts)f.found||(i++,l[f.path]=(l[f.path]||0)+1)}const c=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:n,maxDepth:a,failedAccessCount:i,commonFailedPaths:c}}getNestedContextForComponent(e){return this.nestedContexts.find(n=>n.componentId===e)}clearNestedContexts(){this.nestedContexts=[],this.nestedContextIdCounter=0}trackHandlerRegistration(e,n="custom",a,i){this.isEnabled&&this.handlers.set(e,{name:e,category:n,description:a,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(n=>n.category===e)}clearHandlers(){this.handlers.clear()}trackEventSubscribe(e){if(!this.isEnabled)return;const n=this.componentEventSubscriptions.get(e),a=Date.now();n?(n.subscriberCount++,n.lastSubscribedAt=a):this.componentEventSubscriptions.set(e,{eventName:e,subscriberCount:1,firstSubscribedAt:a,lastSubscribedAt:a})}trackEventUnsubscribe(e){if(!this.isEnabled)return;const n=this.componentEventSubscriptions.get(e);n&&(n.subscriberCount--,n.subscriberCount<=0&&this.componentEventSubscriptions.delete(e))}trackEventEmit(e,n,a,i,l){if(!this.isEnabled)return;const c={id:`evt_${++this.componentEventIdCounter}`,eventName:e,data:this.sanitizeForLogging(n),timestamp:Date.now(),listenerCount:a,results:i?this.sanitizeForLogging(i):void 0,hasError:!!l,errorMessage:l?.message};this.componentEventEmitHistory.push(c),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((n,a)=>n+a.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,n,a,i){if(!this.config.enabled)return"";const l=`setState_${++this.stateRenderingIdCounter}`;this.currentStateChangeContext={setStateId:l,startTime:performance.now(),changedPath:e,trigger:i||{},renderedComponents:[]};const c={id:`sr_${this.stateRenderingIdCounter}`,setStateId:l,statePath:e,oldValue:this.sanitizeForLogging(n),newValue:this.sanitizeForLogging(a),timestamp:Date.now(),triggeredBy:i||{},renderedComponents:[],totalRenderDuration:0,affectedBindingsCount:0};return this.stateRenderingLogs.push(c),this.stateRenderingLogs.length>this.maxStateRenderingLogs&&this.stateRenderingLogs.shift(),l}trackComponentRender(e,n,a,i=[],l=[],c){if(!this.config.enabled)return;const d=this.componentRenderCounts.get(n)||0;this.componentRenderCounts.set(n,d+1);for(const f of i)this.stateToComponentMap.has(f)||this.stateToComponentMap.set(f,new Set),this.stateToComponentMap.get(f).add(n);if(this.currentStateChangeContext){const f={componentId:e,componentName:n,renderDuration:a,accessedStatePaths:i,evaluatedBindings:l,renderOrder:this.currentStateChangeContext.renderedComponents.length,parentId:c};this.currentStateChangeContext.renderedComponents.push(f)}this.trackRender(n)}completeStateChange(e){if(!this.config.enabled||!this.currentStateChangeContext||this.currentStateChangeContext.setStateId!==e)return;const n=this.currentStateChangeContext,i=performance.now()-n.startTime,l=this.stateRenderingLogs.findIndex(c=>c.setStateId===e);if(l>=0){const c=this.stateRenderingLogs[l];c.renderedComponents=n.renderedComponents,c.totalRenderDuration=i,c.affectedBindingsCount=n.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,n=Object.fromEntries(this.componentRenderCounts),a={};for(const[i,l]of this.stateToComponentMap)a[i]=Array.from(l);return{logs:e,componentRenderCounts:n,stateToComponentMap:a,stats:this.calculateStateRenderingStats()}}calculateStateRenderingStats(){const e=this.stateRenderingLogs;if(e.length===0)return{totalStateChanges:0,totalRenders:0,avgRenderDuration:0,avgComponentsPerChange:0,topRenderedComponents:[],topInfluentialPaths:[]};const n=e.reduce((d,f)=>d+f.renderedComponents.length,0),a=e.reduce((d,f)=>d+f.totalRenderDuration,0)/e.length,i=n/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})),c=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:n,avgRenderDuration:a,avgComponentsPerChange:i,topRenderedComponents:l,topInfluentialPaths:c}}getComponentsAffectedByState(e){const n=this.stateToComponentMap.get(e);return n?Array.from(n):[]}getComponentRenderHistory(e){return this.stateRenderingLogs.filter(n=>n.renderedComponents.some(a=>a.componentName===e))}clearStateRenderingLogs(){this.stateRenderingLogs=[],this.componentRenderCounts.clear(),this.stateToComponentMap.clear(),this.currentStateChangeContext=null,this.stateRenderingIdCounter=0}trackComponentStateSource(e,n,a,i){this.config.enabled&&this.componentStateSources.set(e,{componentId:e,componentName:n,stateSource:a,stateProvider:i})}trackDynamicState(e,n){this.config.enabled&&this.dynamicStates.set(e,n)}trackContextFlow(e,n,a,i,l,c){if(!this.config.enabled)return;const d={component:n,componentId:e,contextReceived:a,passedToChildren:i,usedInRender:l};if(this.contextFlowNodes.set(e,d),c){const f=this.contextFlowNodes.get(c);f&&(f.children||(f.children=[]),f.children.push(d))}}getStateHierarchyInfo(e=!0){const n=this.buildStateHierarchyLayers(),a=this.detectStateConflicts(n),i=Array.from(this.componentStateSources.values());return{layers:e?n.map(c=>({...c,values:this.summarizeValues(c.values,2)})):n,conflicts:a,componentStateSources:i,timestamp:Date.now()}}summarizeValues(e,n,a=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(a>=n){if(Array.isArray(e))return`[Array(${e.length})]`;const c=Object.keys(e);return`{${c.slice(0,5).join(", ")}${c.length>5?`, ... +${c.length-5}`:""}}`}if(Array.isArray(e))return e.length<=3?e.map(c=>this.summarizeValues(c,n,a+1)):{__type:"array",__length:e.length,__preview:e.slice(0,3).map(c=>this.summarizeValues(c,n,a+1))};const i={},l=Object.keys(e);for(const c of l)i[c]=this.summarizeValues(e[c],n,a+1);return i}buildStateHierarchyLayers(){const e=[];try{const a=window.G7Core?.state?.get?.();if(!a)return e;a._local&&e.push({name:"Global _local",type:"global",path:"_local",values:a._local,priority:1}),a._global&&e.push({name:"Global _global",type:"global",path:"_global",values:a._global,priority:1});for(const[l,c]of this.dynamicStates)c&&Object.keys(c).length>0&&e.push({name:`DynamicState (${l})`,type:"dynamicState",componentId:l,values:c,priority:2});const i=this.computeEffectiveState(a._local||{});e.push({name:"Effective _local (merged)",type:"effective",values:i,priority:3})}catch(n){console.warn("[G7DevTools] 상태 계층 빌드 실패:",n)}return e}computeEffectiveState(e){const n={...e};for(const[,a]of this.dynamicStates)a._local&&Object.assign(n,a._local);return n}detectStateConflicts(e){const n=[],a=e.find(l=>l.type==="global"&&l.path==="_local");if(!a)return n;const i=e.filter(l=>l.type==="dynamicState");for(const l of i){const c=l.values._local||l.values;for(const[d,f]of Object.entries(c)){const g=a.values[d];if(JSON.stringify(g)!==JSON.stringify(f)){const m=[],b=[];for(const S of this.componentStateSources.values())S.stateSource.local.some(_=>_===`_local.${d}`||_===d)&&(S.stateProvider.type==="dynamicState"?m.push(S.componentName):S.stateProvider.type==="globalState"&&b.push(S.componentName));n.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 n}getContextFlowInfo(){const e=[],n=new Set(this.contextFlowNodes.keys());for(const a of this.contextFlowNodes.values())if(a.children)for(const i of a.children)n.delete(i.componentId);for(const a of n){const i=this.contextFlowNodes.get(a);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,n,a,i){if(!this.config.enabled)return;const l=this.analyzeTailwindClasses(a),c={componentId:e,componentName:n,classes:a,computedStyles:i,tailwindAnalysis:l};this.componentStyles.set(e,c),this.detectStyleIssues(c)}analyzeTailwindClasses(e){const n=[],a=[],i=[],l=[],c=["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:")&&n.push(f);for(const g of c)if(f.startsWith(g)){a.push(f);break}for(const g of d)if(g.test(f)){i.push(f);break}}return{usedClasses:l,darkClasses:n,responsiveClasses:a,dynamicClasses:i}}detectStyleIssues(e){const{componentId:n,componentName:a,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:n,componentName:a,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 c=l.usedClasses.filter(f=>f.startsWith("bg-")&&!f.startsWith("dark:")),d=l.darkClasses.filter(f=>f.includes("bg-"));c.length>0&&d.length===0&&this.addStyleIssue({id:this.generateId(),type:"dark-mode-missing",componentId:n,componentName:a,property:"background-color",currentValue:c.join(", "),expectedValue:"dark:bg-* 클래스 필요",severity:"info",description:"다크 모드 배경색 클래스가 누락되었습니다.",suggestion:`${c[0]}에 대응하는 dark: 클래스를 추가하세요.`}),l.dynamicClasses.length>0&&this.addStyleIssue({id:this.generateId(),type:"tailwind-purging",componentId:n,componentName:a,property:"class",currentValue:l.dynamicClasses.join(", "),severity:"info",description:"동적으로 생성된 Tailwind 클래스가 있습니다.",suggestion:"tailwind.config.js의 safelist에 추가하거나 전체 클래스명을 상수로 정의하세요."})}addStyleIssue(e){this.styleIssues.some(a=>a.componentId===e.componentId&&a.type===e.type&&a.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(n=>n.type==="invisible-element").length,tailwindIssueCount:this.styleIssues.filter(n=>n.type==="tailwind-purging").length,darkModeIssueCount:this.styleIssues.filter(n=>n.type==="dark-mode-missing").length},timestamp:Date.now()}}clearStyleValidationData(){this.styleIssues=[],this.componentStyles.clear()}trackAuthEvent(e,n,a,i){if(!this.config.enabled)return;const l={id:`auth_${++this.authEventIdCounter}`,type:e,timestamp:Date.now(),success:n,error:a,details:i};this.authEvents.push(l),this.authEvents.length>this.maxAuthEventHistory&&(this.authEvents=this.authEvents.slice(-this.maxAuthEventHistory))}trackAuthHeader(e,n,a,i,l){if(!this.config.enabled)return;const c={url:e,hasAuthHeader:n,headerType:a,tokenValid:i??!1,responseStatus:l,timestamp:Date.now()};this.authHeaderHistory.push(c),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,n=e?.api;let a=e?.auth;!a&&e?.AuthManager?.getInstance&&(a=e.AuthManager.getInstance());const i=n?.getToken?.()||a?.getAccessToken?.()||localStorage.getItem("auth_token")||localStorage.getItem("access_token"),l=a?.getRefreshToken?.()||localStorage.getItem("refresh_token");let c="unknown",d=a?.getUser?.();if(d&&(c="AuthManager"),!d){const v=e?.state?.get?.();d=v?._global?.user||v?._global?.currentUser||v?.user||v?.currentUser,d&&(c="G7Core.state")}const f=a?.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 S=d?{id:d.id,email:d.email,name:d.name,roles:d.roles?.map(v=>typeof v=="string"?{name:v}:{id:v.id,name:v.name,guard_name:v.guard_name}),permissions:d.permissions?.map(v=>typeof v=="string"?{name:v}:{id:v.id,name:v.name,guard_name:v.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:S,tokens:{hasAccessToken:!!i,hasRefreshToken:!!l,storage:g,accessTokenPreview:b},lastActivity:Date.now(),source:c}}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(n=>n.type==="login").length,successfulLogins:e.filter(n=>n.type==="login"&&n.success).length,failedLogins:e.filter(n=>n.type==="login"&&!n.success).length,tokenRefreshes:e.filter(n=>n.type==="token-refresh").length,unauthorizedResponses:e.filter(n=>n.type==="api-unauthorized").length},timestamp:Date.now()}}clearAuthData(){this.authEvents=[],this.authHeaderHistory=[],this.authEventIdCounter=0}trackLayoutLoad(e,n,a,i="api"){if(!this.config.enabled)return;const l=Date.now();this.currentLayout={layoutPath:e,templateId:n,layoutJson:this.sanitizeObject(a),loadedAt:l,version:a.version,layoutName:a.layout_name,source:i};const c={id:`layout-${++this.layoutIdCounter}`,layoutPath:e,templateId:n,loadedAt:l,source:i,version:a.version};this.layoutHistory.push(c),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 n=`exec_${++this.executionIdCounter}_${Date.now()}`,a={handlerName:e,executionId:n,startTime:Date.now(),stateChanges:[],dataSourceChanges:[],alerts:[]};if(this.executionDetails.set(n,a),this.executionDetails.size>this.maxExecutionDetails){const i=Array.from(this.executionDetails.keys());i.slice(0,i.length-this.maxExecutionDetails).forEach(c=>this.executionDetails.delete(c))}return n}endHandlerExecution(e,n,a,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=n,l.exitLocation=a,l.exitDescription=i;const c=this.changeExpectations.get(e);c&&(l.expectedChanges=c,this.checkExpectations(e,l,c),this.changeExpectations.delete(e)),n==="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"}),(n==="early-return-condition"||n==="early-return-validation")&&this.addChangeAlert(e,{type:"early-return-detected",severity:"info",message:`핸들러 "${l.handlerName}"이(가) early return으로 종료됨`,description:i||`종료 위치: ${a||"알 수 없음"}`,handlerName:l.handlerName,suggestion:n==="early-return-validation"?"검증 실패로 인한 early return입니다. 입력 데이터를 확인하세요.":"조건부 early return입니다. 조건문의 평가 결과를 확인하세요."})}recordExitReason(e,n,a,i){if(!this.config.enabled||!e)return;const l=this.executionDetails.get(e);l&&(l.exitReason=n,l.exitLocation=a,l.exitDescription=i)}recordStateChange(e,n,a,i,l){if(!this.config.enabled)return;const c={id:`sc_${++this.stateChangeIdCounter}`,path:n,changeType:a,oldValue:this.safeClone(i),newValue:this.safeClone(l),timestamp:Date.now(),comparison:this.compareValues(i,l),executionId:e};if(this.stateChangeHistory.push(c),e){const d=this.executionDetails.get(e);d&&d.stateChanges.push(c)}this.stateChangeHistory.length>this.maxStateChangeHistory&&this.stateChangeHistory.splice(0,this.stateChangeHistory.length-this.maxStateChangeHistory),c.comparison.isDeepEqual&&typeof i=="object"&&i!==null&&this.addChangeAlert(e||"",{type:"object-reference-same",severity:"warning",message:`상태 "${n}"가 변경되었으나 값이 동일함`,description:"객체 참조가 동일하거나 깊은 비교 결과 변경이 없습니다. 변경 감지가 실패할 수 있습니다.",handlerName:e&&this.executionDetails.get(e)?.handlerName||"unknown",statePath:n,suggestion:"불변성을 유지하여 새 객체를 생성하세요. 예: { ...oldObject, newField: value }",docLink:"troubleshooting-state.md#object-mutation"})}recordDataSourceChange(e,n,a,i,l){if(!this.config.enabled)return;const c={dataSourceId:n,changeType:a,timestamp:Date.now(),previousStatus:i,newStatus:l,executionId:e};if(this.dataSourceChangeHistory.push(c),e){const d=this.executionDetails.get(e);d&&d.dataSourceChanges.push(c)}this.dataSourceChangeHistory.length>this.maxStateChangeHistory&&this.dataSourceChangeHistory.splice(0,this.dataSourceChangeHistory.length-this.maxStateChangeHistory)}expectChange(e,n,a){if(!this.config.enabled||!e)return;const i=this.executionDetails.get(e);if(!i)return;const l={expectedStatePaths:n,expectedDataSources:a,setAt:Date.now(),source:i.handlerName};this.changeExpectations.set(e,l)}checkExpectations(e,n,a){const i=new Set(n.stateChanges.map(c=>c.path)),l=new Set(n.dataSourceChanges.map(c=>c.dataSourceId));for(const c of a.expectedStatePaths)i.has(c)||this.addChangeAlert(e,{type:"expected-not-fulfilled",severity:"error",message:`기대한 상태 변경 "${c}"가 발생하지 않음`,description:`핸들러 "${n.handlerName}"이(가) "${c}" 변경을 예고했지만 실제로 변경되지 않았습니다.`,handlerName:n.handlerName,statePath:c,suggestion:"핸들러 내부 로직을 확인하세요. early return이나 조건부 분기로 인해 변경이 생략되었을 수 있습니다.",docLink:"troubleshooting-state.md"});for(const c of a.expectedDataSources)l.has(c)||this.addChangeAlert(e,{type:"expected-not-fulfilled",severity:"error",message:`기대한 데이터소스 갱신 "${c}"가 발생하지 않음`,description:`핸들러 "${n.handlerName}"이(가) "${c}" 갱신을 예고했지만 실제로 갱신되지 않았습니다.`,handlerName:n.handlerName,dataSourceId:c,suggestion:"refetchDataSource 호출이 실행되었는지 확인하세요.",docLink:"data-sources.md"})}addChangeAlert(e,n){const a={...n,id:`alert_${++this.alertIdCounter}`,timestamp:Date.now()};if(this.changeAlerts.push(a),e){const i=this.executionDetails.get(e);i&&i.alerts.push(a)}this.changeAlerts.length>this.maxChangeAlerts&&this.changeAlerts.splice(0,this.changeAlerts.length-this.maxChangeAlerts)}compareValues(e,n){const a=this.getValueType(e),i=this.getValueType(n),l=a!==i;let c=!1,d;return!l&&(a==="object"||a==="array")?(c=this.deepEqual(e,n),!c&&a==="object"&&(d=this.getChangedKeys(e,n))):c=e===n,{typeChanged:l,oldType:a,newType:i,isDeepEqual:c,changedKeys:d}}getValueType(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}deepEqual(e,n){if(e===n)return!0;if(typeof e!=typeof n)return!1;if(e===null||n===null||typeof e!="object")return e===n;if(Array.isArray(e)!==Array.isArray(n))return!1;const a=Object.keys(e),i=Object.keys(n);if(a.length!==i.length)return!1;for(const l of a)if(!i.includes(l)||!this.deepEqual(e[l],n[l]))return!1;return!0}getChangedKeys(e,n){const a=[],i=new Set([...Object.keys(e),...Object.keys(n)]);for(const l of i)this.deepEqual(e[l],n[l])||a.push(l);return a}getChangeDetectionInfo(){const e=Array.from(this.executionDetails.values()),n={totalExecutions:e.length,executionsWithStateChange:e.filter(a=>a.stateChanges.length>0).length,executionsWithoutStateChange:e.filter(a=>a.stateChanges.length===0&&a.exitReason==="normal").length,earlyReturnCount:e.filter(a=>a.exitReason==="early-return-condition"||a.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:n,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 n of this.changeAlerts)e[n.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,n){let a=[...this.changeAlerts];return n&&(a=a.filter(i=>i.severity===n)),a.slice(-e)}getHandlerExecutions(e,n=10){return Array.from(this.executionDetails.values()).filter(i=>i.handlerName===e).slice(-n)}findExecutionInStack(e){return this.sequenceExecutionStack.find(n=>n.sequenceId===e)}startSequenceExecution(e){if(!this.config.enabled)return"";const n=`seq_${++this.sequenceIdCounter}_${Date.now()}`,a={sequenceId:n,startTime:Date.now(),totalDuration:0,trigger:e,actions:[],status:"running"};return this.sequenceExecutionStack.push(a),n}captureSequenceActionBefore(e,n,a,i,l){if(!this.config.enabled)return;const c=this.findExecutionInStack(e);if(!c)return;const d={index:n,handler:a,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"};c.actions.push(d)}captureSequenceActionAfter(e,n,a,i,l,c){if(!this.config.enabled)return;const d=this.findExecutionInStack(e);if(!d)return;const f=d.actions.find(m=>m.index===n);if(!f)return;f.stateAfterAction={_global:this.safeClone(a._global),_local:this.safeClone(a._local),_isolated:a._isolated?this.safeClone(a._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)),c&&(f.status="error",f.error={name:c.name,message:c.message,stack:c.stack})}endSequenceExecution(e,n){if(!this.config.enabled)return;const a=this.sequenceExecutionStack.findIndex(l=>l.sequenceId===e);if(a===-1)return;const i=this.sequenceExecutionStack[a];if(i.endTime=Date.now(),i.totalDuration=i.endTime-i.startTime,n){i.status="error",i.error={name:n.name,message:n.message,stack:n.stack};const l=i.actions.find(c=>c.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(a,1)}computeStateDiff(e,n){const a=[],i=[],l=[],c=new Set(Object.keys(e)),d=new Set(Object.keys(n));for(const f of d)c.has(f)||a.push(f);for(const f of c)d.has(f)||i.push(f);for(const f of c)if(d.has(f)){const g=e[f],m=n[f];JSON.stringify(g)!==JSON.stringify(m)&&l.push({path:f,oldValue:g,newValue:m})}return{added:a,removed:i,changed:l}}getSequenceTrackingInfo(){const e=this.getSequenceStats(),n=this.sequenceExecutionStack.length>0?this.sequenceExecutionStack[this.sequenceExecutionStack.length-1]:void 0;return{executions:[...this.sequenceExecutions],currentExecution:n,stats:e}}getSequenceStats(){const e=this.sequenceExecutions,n=e.length,a=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),c=n>0?e.reduce((g,m)=>g+m.totalDuration,0)/n: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:n,successCount:a,errorCount:i,totalActions:l,avgDuration:c,topHandlers:f}}clearSequenceData(){this.sequenceExecutions=[],this.sequenceExecutionStack=[],this.sequenceIdCounter=0}getSequenceExecution(e){const n=this.findExecutionInStack(e);return n||this.sequenceExecutions.find(a=>a.sequenceId===e)}getRecentSequences(e=10){return this.sequenceExecutions.slice(-e)}registerStateCaptureForHandler(e,n,a){if(!this.config.enabled)return;const i=new Map,l=Date.now();for(const c of n)i.set(c,{value:this.safeClone(a[c]),capturedAt:l});this.stateCaptureRegistry.set(e,i)}detectStaleClosure(e,n,a,i,l){if(!this.config.enabled)return[];const c=this.stateCaptureRegistry.get(e);if(!c)return[];const d=Date.now(),f=[];for(const[g,m]of c){const b=this.getValueByPath(a,g),S=d-m.capturedAt;if(!this.isDeepEqual(m.value,b)&&S>0){const v=this.createStaleClosureWarning(i,n,g,m.value,m.capturedAt,b,d,S,l);f.push(v),this.addStaleClosureWarning(v)}}return this.stateCaptureRegistry.delete(e),f}trackStaleClosureWarning(e){if(!this.config.enabled)return;const n=Date.now(),a=this.createStaleClosureWarning(e.type,e.location,e.capturedPath,e.capturedValue,e.capturedAt,e.currentValue,n,n-e.capturedAt,e.actionId,e.stackTrace);this.addStaleClosureWarning(a)}createStaleClosureWarning(e,n,a,i,l,c,d,f,g,m){const b=this.getStaleClosureSeverity(e,f),{description:S,suggestion:v,docLink:_}=this.getStaleClosureMessages(e,a,f);return{id:`stale_${++this.staleClosureIdCounter}_${Date.now()}`,timestamp:Date.now(),type:e,location:n,capturedState:{path:a,capturedValue:this.safeClone(i),capturedAt:l},currentState:{path:a,currentValue:this.safeClone(c),retrievedAt:d},timeDiff:f,severity:b,description:S,suggestion:v,docLink:_,actionId:g,stackTrace:m}}getStaleClosureSeverity(e,n){if(n>5e3)return"error";if(n>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,n,a){const i=a<1e3?`${a}ms`:`${(a/1e3).toFixed(1)}s`;switch(e){case"async-state-capture":return{description:`await 후 ${i} 경과 시점에 '${n}' 상태가 변경됨. 캡처된 상태 대신 최신 상태를 사용해야 함`,suggestion:"await 이후에는 G7Core.state.get()으로 최신 상태를 다시 조회하거나, useRef + getter 패턴을 사용하세요",docLink:"troubleshooting-state-closure.md"};case"callback-state-capture":return{description:`콜백에서 ${i} 전에 캡처된 '${n}' 상태를 사용 중. 최신 상태와 다름`,suggestion:"콜백에서 상태를 참조할 때는 stateRef.current 패턴 또는 G7Core.state.get()를 사용하세요",docLink:"troubleshooting-state-closure.md"};case"timeout-state-capture":return{description:`setTimeout/setInterval 콜백에서 '${n}' 상태가 ${i} 전 값 사용 중`,suggestion:"타이머 콜백 내에서는 G7Core.state.get()으로 최신 상태를 조회하세요",docLink:"troubleshooting-state-closure.md"};case"sequence-state-mismatch":return{description:`sequence 내 '${n}' 상태가 이전 액션 결과와 불일치. context.state 대신 캡처된 값 사용 의심`,suggestion:"sequence 내에서는 context.state 또는 $prev를 사용하여 최신 상태를 참조하세요",docLink:"troubleshooting-state-setstate.md"};case"event-handler-stale":return{description:`이벤트 핸들러에서 ${i} 전에 바인딩된 '${n}' 상태 사용 중`,suggestion:"이벤트 핸들러에서 상태를 참조할 때는 useRef 패턴 또는 G7Core.state.get()를 사용하세요",docLink:"troubleshooting-state-closure.md"};default:return{description:`'${n}' 상태에서 stale closure 감지됨 (${i} 경과)`,suggestion:"상태 참조 시 최신 값을 사용하는지 확인하세요"}}}addStaleClosureWarning(e){this.staleClosureWarnings.push(e),this.staleClosureWarnings.length>this.maxStaleClosureWarnings&&this.staleClosureWarnings.shift()}getValueByPath(e,n){const a=n.split(".");let i=e;for(const l of a){if(i==null)return;i=i[l]}return i}isDeepEqual(e,n){if(e===n)return!0;if(e===null||n===null)return e===n;if(typeof e!=typeof n)return!1;if(typeof e!="object")return e===n;try{return JSON.stringify(e)===JSON.stringify(n)}catch{return!1}}getStaleClosureTrackingInfo(){const e=this.getStaleClosureStats();return{warnings:[...this.staleClosureWarnings],stats:e,timestamp:Date.now()}}getStaleClosureStats(){const e=this.staleClosureWarnings,n={"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)n[f.type]++;const a={info:0,warning:0,error:0};for(const f of e)a[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})),c={};for(const f of e)c[f.capturedState.path]=(c[f.capturedState.path]||0)+1;const d=Object.entries(c).sort(([,f],[,g])=>g-f).slice(0,5).map(([f,g])=>({path:f,count:g}));return{totalWarnings:e.length,warningsByType:n,warningsBySeverity:a,topLocations:l,topAffectedPaths:d}}clearStaleClosureData(){this.staleClosureWarnings=[],this.staleClosureIdCounter=0,this.stateCaptureRegistry.clear()}getRecentStaleClosureWarnings(e=10,n){let a=[...this.staleClosureWarnings];return n&&(a=a.filter(i=>i.severity===n)),a.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(a=>{try{return JSON.parse(JSON.stringify(a))}catch{return"[Unserializable]"}});const n={};for(const a of Object.keys(e))try{n[a]=JSON.parse(JSON.stringify(e[a]))}catch{n[a]="[Unserializable]"}return n}}};$(Si,"instance");let Oa=Si;const Gn=ut("LayoutLoader");class Cr extends Error{constructor(n,a,i){super(n);$(this,"code");$(this,"details");this.code=a,this.details=i,this.name="LayoutLoaderError"}}class ff{constructor(e){$(this,"componentRegistry");$(this,"currentLayout",null);$(this,"layoutCache",new Map);$(this,"cacheVersion",0);this.componentRegistry=e}setCacheVersion(e){this.cacheVersion!==e&&(Gn.log("Cache version updated:",this.cacheVersion,"->",e),this.cacheVersion=e,this.layoutCache.clear())}getCacheVersion(){return this.cacheVersion}async loadLayout(e,n){const a=`${e}:${n}`;if(this.layoutCache.has(a)){Gn.log("Loading layout from cache:",n);const l=await this.layoutCache.get(a),c=JSON.parse(JSON.stringify(l));return this.currentLayout=c,Oa.getInstance().trackLayoutLoad(n,e,c,"cache"),c}const i=this.fetchLayout(e,n);return this.layoutCache.set(a,i),i.catch(()=>{this.layoutCache.get(a)===i&&this.layoutCache.delete(a)}),i}async fetchLayout(e,n,a=!1){try{const i=this.cacheVersion>0?this.cacheVersion:null;let l;if(n.startsWith("__preview__/")){const S=n.replace("__preview__/","");l=$r(`/api/layouts/preview/${S}`,"json",i)}else l=$r(`/api/layouts/${e}/${n}`,"json",i);Gn.log("Fetching layout from API:",l);const c=Ir(),d=a?null:c.getToken(),f={Accept:"application/json"};d&&(f.Authorization=`Bearer ${d}`);const g=await Ll(l,{init:{headers:f},label:`layout: ${n}`});let m;try{m=await g.json()}catch{m=null}if(!g.ok){if(g.status===401&&!a&&d){Gn.log("Token invalid, removing and retrying without token"),c.removeToken();try{return await this.fetchLayout(e,n,!0)}catch(v){throw v instanceof Cr&&v.details?.status===401?new Cr(v.message,v.code,{...v.details,hadToken:!0}):v}}const S=m?.message||m?.error;throw new Cr(`Failed to fetch layout: ${g.status} ${g.statusText}`,"FETCH_FAILED",{status:g.status,statusText:g.statusText,url:l,apiMessage:S})}const b=m.data||m;return this.validateLayoutData(b),this.currentLayout=b,Oa.getInstance().trackLayoutLoad(n,e,b,"api"),Gn.log("Layout fetched and cached successfully:",b.layout_name),b}catch(i){const l=`${e}:${n}`;throw this.layoutCache.delete(l),i instanceof Cr?i:new Cr("Failed to load layout","LOAD_FAILED",{originalError:i})}}prefetchLayout(e,n){return this.loadLayout(e,n)}validateLayoutData(e){if(!e.version)throw new Cr("Layout data missing required field: version","VALIDATION_FAILED",{field:"version"});if(!e.layout_name)throw new Cr("Layout data missing required field: layout_name","VALIDATION_FAILED",{field:"layout_name"});if(!Array.isArray(e.components))throw new Cr('Layout data field "components" must be an array',"VALIDATION_FAILED",{field:"components",value:e.components});Gn.log("Layout data validation passed")}renderLayout(e,n){try{const a=n||this.currentLayout;if(!a)throw new Cr("No layout data to render","NO_LAYOUT_DATA");Gn.log("Rendering layout:",a.layout_name),e.innerHTML="",this.renderComponents(e,a.components),Gn.log("Layout rendered successfully")}catch(a){Gn.error("Render error:",a),this.renderErrorState(e,a)}}renderComponents(e,n){for(const a of n){const i=this.renderComponent(a);i&&e.appendChild(i)}}renderComponent(e){try{if(!this.componentRegistry.getComponent(e.type))return Gn.warn(`Component not found: ${e.type}`),this.createPlaceholderElement(e.type);const a=document.createElement("div");return a.setAttribute("data-component",e.type),e.props&&Object.entries(e.props).forEach(([i,l])=>{a.setAttribute(`data-prop-${i}`,JSON.stringify(l))}),e.children&&e.children.length>0?this.renderComponents(a,e.children):e.text&&(a.textContent=e.text),a}catch(n){return Gn.error(`Error rendering component ${e.type}:`,n),this.createErrorElement(e.type,n)}}createPlaceholderElement(e){const n=document.createElement("div");return n.className="component-placeholder",n.setAttribute("data-component-type",e),n.innerHTML=` + `},iE={onDragStart(o){let{active:e}=o;return"Picked up draggable item "+e.id+"."},onDragOver(o){let{active:e,over:n}=o;return n?"Draggable item "+e.id+" was moved over droppable area "+n.id+".":"Draggable item "+e.id+" is no longer over a droppable area."},onDragEnd(o){let{active:e,over:n}=o;return n?"Draggable item "+e.id+" was dropped over droppable area "+n.id:"Draggable item "+e.id+" was dropped."},onDragCancel(o){let{active:e}=o;return"Dragging was cancelled. Draggable item "+e.id+" was dropped."}};function sE(o){let{announcements:e=iE,container:n,hiddenTextDescribedById:a,screenReaderInstructions:i=aE}=o;const{announce:l,announcement:c}=tE(),d=Co("DndLiveRegion"),[f,g]=H.useState(!1);if(H.useEffect(()=>{g(!0)},[]),nE(H.useMemo(()=>({onDragStart(y){let{active:S}=y;l(e.onDragStart({active:S}))},onDragMove(y){let{active:S,over:v}=y;e.onDragMove&&l(e.onDragMove({active:S,over:v}))},onDragOver(y){let{active:S,over:v}=y;l(e.onDragOver({active:S,over:v}))},onDragEnd(y){let{active:S,over:v}=y;l(e.onDragEnd({active:S,over:v}))},onDragCancel(y){let{active:S,over:v}=y;l(e.onDragCancel({active:S,over:v}))}}),[l,e])),!f)return null;const m=Xe.createElement(Xe.Fragment,null,Xe.createElement(ZC,{id:a,value:i.draggable}),Xe.createElement(eE,{id:d,announcement:c}));return n?ka.createPortal(m,n):m}var an;(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"})(an||(an={}));function lc(){}function Om(o,e){return H.useMemo(()=>({sensor:o,options:e??{}}),[o,e])}function oE(){for(var o=arguments.length,e=new Array(o),n=0;n[...e].filter(a=>a!=null),[...e])}const wr=Object.freeze({x:0,y:0});function Lm(o,e){return Math.sqrt(Math.pow(o.x-e.x,2)+Math.pow(o.y-e.y,2))}function Mm(o,e){let{data:{value:n}}=o,{data:{value:a}}=e;return n-a}function lE(o,e){let{data:{value:n}}=o,{data:{value:a}}=e;return a-n}function $m(o){let{left:e,top:n,height:a,width:i}=o;return[{x:e,y:n},{x:e+i,y:n},{x:e,y:n+a},{x:e+i,y:n+a}]}function Nm(o,e){if(!o||o.length===0)return null;const[n]=o;return n[e]}function Im(o,e,n){return e===void 0&&(e=o.left),n===void 0&&(n=o.top),{x:e+o.width*.5,y:n+o.height*.5}}const cE=o=>{let{collisionRect:e,droppableRects:n,droppableContainers:a}=o;const i=Im(e,e.left,e.top),l=[];for(const c of a){const{id:d}=c,f=n.get(d);if(f){const g=Lm(Im(f),i);l.push({id:d,data:{droppableContainer:c,value:g}})}}return l.sort(Mm)},uE=o=>{let{collisionRect:e,droppableRects:n,droppableContainers:a}=o;const i=$m(e),l=[];for(const c of a){const{id:d}=c,f=n.get(d);if(f){const g=$m(f),m=i.reduce((S,v,_)=>S+Lm(g[_],v),0),y=Number((m/4).toFixed(4));l.push({id:d,data:{droppableContainer:c,value:y}})}}return l.sort(Mm)};function dE(o,e){const n=Math.max(e.top,o.top),a=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),c=i-a,d=l-n;if(a{let{collisionRect:e,droppableRects:n,droppableContainers:a}=o;const i=[];for(const l of a){const{id:c}=l,d=n.get(c);if(d){const f=dE(d,e);f>0&&i.push({id:c,data:{droppableContainer:l,value:f}})}}return i.sort(lE)};function hE(o,e,n){return{...o,scaleX:e&&n?e.width/n.width:1,scaleY:e&&n?e.height/n.height:1}}function Hm(o,e){return o&&e?{x:o.left-e.left,y:o.top-e.top}:wr}function gE(o){return function(n){for(var a=arguments.length,i=new Array(a>1?a-1:0),l=1;l({...c,top:c.top+o*d.y,bottom:c.bottom+o*d.y,left:c.left+o*d.x,right:c.right+o*d.x}),{...n})}}const pE=gE(1);function mE(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 yE(o,e,n){const a=mE(e);if(!a)return o;const{scaleX:i,scaleY:l,x:c,y:d}=a,f=o.left-c-(1-i)*parseFloat(n),g=o.top-d-(1-l)*parseFloat(n.slice(n.indexOf(" ")+1)),m=i?o.width/i:o.width,y=l?o.height/l:o.height;return{width:m,height:y,top:g,right:f+m,bottom:g+y,left:f}}const bE={ignoreTransform:!1};function gs(o,e){e===void 0&&(e=bE);let n=o.getBoundingClientRect();if(e.ignoreTransform){const{transform:g,transformOrigin:m}=Nn(o).getComputedStyle(o);g&&(n=yE(n,g,m))}const{top:a,left:i,width:l,height:c,bottom:d,right:f}=n;return{top:a,left:i,width:l,height:c,bottom:d,right:f}}function jm(o){return gs(o,{ignoreTransform:!0})}function vE(o){const e=o.innerWidth,n=o.innerHeight;return{top:0,left:0,right:e,bottom:n,width:e,height:n}}function SE(o,e){return e===void 0&&(e=Nn(o).getComputedStyle(o)),e.position==="fixed"}function wE(o,e){e===void 0&&(e=Nn(o).getComputedStyle(o));const n=/(auto|scroll|overlay)/;return["overflow","overflowX","overflowY"].some(i=>{const l=e[i];return typeof l=="string"?n.test(l):!1})}function cc(o,e){const n=[];function a(i){if(e!=null&&n.length>=e||!i)return n;if(Xd(i)&&i.scrollingElement!=null&&!n.includes(i.scrollingElement))return n.push(i.scrollingElement),n;if(!vo(i)||Tm(i)||n.includes(i))return n;const l=Nn(o).getComputedStyle(i);return i!==o&&wE(i,l)&&n.push(i),SE(i,l)?n:a(i.parentNode)}return o?a(o):n}function zm(o){const[e]=cc(o,1);return e??null}function nf(o){return!sc||!o?null:ds(o)?o:Yd(o)?Xd(o)||o===fs(o).scrollingElement?window:vo(o)?o:null:null}function Um(o){return ds(o)?o.scrollX:o.scrollLeft}function Pm(o){return ds(o)?o.scrollY:o.scrollTop}function rf(o){return{x:Um(o),y:Pm(o)}}var gn;(function(o){o[o.Forward=1]="Forward",o[o.Backward=-1]="Backward"})(gn||(gn={}));function Bm(o){return!sc||!o?!1:o===document.scrollingElement}function qm(o){const e={x:0,y:0},n=Bm(o)?{height:window.innerHeight,width:window.innerWidth}:{height:o.clientHeight,width:o.clientWidth},a={x:o.scrollWidth-n.width,y:o.scrollHeight-n.height},i=o.scrollTop<=e.y,l=o.scrollLeft<=e.x,c=o.scrollTop>=a.y,d=o.scrollLeft>=a.x;return{isTop:i,isLeft:l,isBottom:c,isRight:d,maxScroll:a,minScroll:e}}const CE={x:.2,y:.2};function EE(o,e,n,a,i){let{top:l,left:c,right:d,bottom:f}=n;a===void 0&&(a=10),i===void 0&&(i=CE);const{isTop:g,isBottom:m,isLeft:y,isRight:S}=qm(o),v={x:0,y:0},_={x:0,y:0},A={height:e.height*i.y,width:e.width*i.x};return!g&&l<=e.top+A.height?(v.y=gn.Backward,_.y=a*Math.abs((e.top+A.height-l)/A.height)):!m&&f>=e.bottom-A.height&&(v.y=gn.Forward,_.y=a*Math.abs((e.bottom-A.height-f)/A.height)),!S&&d>=e.right-A.width?(v.x=gn.Forward,_.x=a*Math.abs((e.right-A.width-d)/A.width)):!y&&c<=e.left+A.width&&(v.x=gn.Backward,_.x=a*Math.abs((e.left+A.width-c)/A.width)),{direction:v,speed:_}}function _E(o){if(o===document.scrollingElement){const{innerWidth:l,innerHeight:c}=window;return{top:0,left:0,right:l,bottom:c,width:l,height:c}}const{top:e,left:n,right:a,bottom:i}=o.getBoundingClientRect();return{top:e,left:n,right:a,bottom:i,width:o.clientWidth,height:o.clientHeight}}function Gm(o){return o.reduce((e,n)=>hs(e,rf(n)),wr)}function AE(o){return o.reduce((e,n)=>e+Um(n),0)}function xE(o){return o.reduce((e,n)=>e+Pm(n),0)}function TE(o,e){if(e===void 0&&(e=gs),!o)return;const{top:n,left:a,bottom:i,right:l}=e(o);zm(o)&&(i<=0||l<=0||n>=window.innerHeight||a>=window.innerWidth)&&o.scrollIntoView({block:"center",inline:"center"})}const RE=[["x",["left","right"],AE],["y",["top","bottom"],xE]];class af{constructor(e,n){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 a=cc(n),i=Gm(a);this.rect={...e},this.width=e.width,this.height=e.height;for(const[l,c,d]of RE)for(const f of c)Object.defineProperty(this,f,{get:()=>{const g=d(a),m=i[l]-g;return this.rect[f]+m},enumerable:!0});Object.defineProperty(this,"rect",{enumerable:!1})}}class Ao{constructor(e){this.target=void 0,this.listeners=[],this.removeAll=()=>{this.listeners.forEach(n=>{var a;return(a=this.target)==null?void 0:a.removeEventListener(...n)})},this.target=e}add(e,n,a){var i;(i=this.target)==null||i.addEventListener(e,n,a),this.listeners.push([e,n,a])}}function kE(o){const{EventTarget:e}=Nn(o);return o instanceof e?o:fs(o)}function sf(o,e){const n=Math.abs(o.x),a=Math.abs(o.y);return typeof e=="number"?Math.sqrt(n**2+a**2)>e:"x"in e&&"y"in e?n>e.x&&a>e.y:"x"in e?n>e.x:"y"in e?a>e.y:!1}var ar;(function(o){o.Click="click",o.DragStart="dragstart",o.Keydown="keydown",o.ContextMenu="contextmenu",o.Resize="resize",o.SelectionChange="selectionchange",o.VisibilityChange="visibilitychange"})(ar||(ar={}));function Vm(o){o.preventDefault()}function DE(o){o.stopPropagation()}var ut;(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"})(ut||(ut={}));const Fm={start:[ut.Space,ut.Enter],cancel:[ut.Esc],end:[ut.Space,ut.Enter,ut.Tab]},OE=(o,e)=>{let{currentCoordinates:n}=e;switch(o.code){case ut.Right:return{...n,x:n.x+25};case ut.Left:return{...n,x:n.x-25};case ut.Down:return{...n,y:n.y+25};case ut.Up:return{...n,y:n.y-25}}};class of{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:n}}=e;this.props=e,this.listeners=new Ao(fs(n)),this.windowListeners=new Ao(Nn(n)),this.handleKeyDown=this.handleKeyDown.bind(this),this.handleCancel=this.handleCancel.bind(this),this.attach()}attach(){this.handleStart(),this.windowListeners.add(ar.Resize,this.handleCancel),this.windowListeners.add(ar.VisibilityChange,this.handleCancel),setTimeout(()=>this.listeners.add(ar.Keydown,this.handleKeyDown))}handleStart(){const{activeNode:e,onStart:n}=this.props,a=e.node.current;a&&TE(a),n(wr)}handleKeyDown(e){if(ef(e)){const{active:n,context:a,options:i}=this.props,{keyboardCodes:l=Fm,coordinateGetter:c=OE,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}=a.current,m=g?{x:g.left,y:g.top}:wr;this.referenceCoordinates||(this.referenceCoordinates=m);const y=c(e,{active:n,context:a.current,currentCoordinates:m});if(y){const S=Eo(y,m),v={x:0,y:0},{scrollableAncestors:_}=a.current;for(const A of _){const x=e.code,{isTop:O,isRight:M,isLeft:T,isBottom:D,maxScroll:z,minScroll:P}=qm(A),q=_E(A),W={x:Math.min(x===ut.Right?q.right-q.width/2:q.right,Math.max(x===ut.Right?q.left:q.left+q.width/2,y.x)),y:Math.min(x===ut.Down?q.bottom-q.height/2:q.bottom,Math.max(x===ut.Down?q.top:q.top+q.height/2,y.y))},he=x===ut.Right&&!M||x===ut.Left&&!T,Ee=x===ut.Down&&!D||x===ut.Up&&!O;if(he&&W.x!==y.x){const be=A.scrollLeft+S.x,Ue=x===ut.Right&&be<=z.x||x===ut.Left&&be>=P.x;if(Ue&&!S.y){A.scrollTo({left:be,behavior:d});return}Ue?v.x=A.scrollLeft-be:v.x=x===ut.Right?A.scrollLeft-z.x:A.scrollLeft-P.x,v.x&&A.scrollBy({left:-v.x,behavior:d});break}else if(Ee&&W.y!==y.y){const be=A.scrollTop+S.y,Ue=x===ut.Down&&be<=z.y||x===ut.Up&&be>=P.y;if(Ue&&!S.x){A.scrollTo({top:be,behavior:d});return}Ue?v.y=A.scrollTop-be:v.y=x===ut.Down?A.scrollTop-z.y:A.scrollTop-P.y,v.y&&A.scrollBy({top:-v.y,behavior:d});break}}this.handleMove(e,hs(Eo(y,this.referenceCoordinates),v))}}}handleMove(e,n){const{onMove:a}=this.props;e.preventDefault(),a(n)}handleEnd(e){const{onEnd:n}=this.props;e.preventDefault(),this.detach(),n()}handleCancel(e){const{onCancel:n}=this.props;e.preventDefault(),this.detach(),n()}detach(){this.listeners.removeAll(),this.windowListeners.removeAll()}}of.activators=[{eventName:"onKeyDown",handler:(o,e,n)=>{let{keyboardCodes:a=Fm,onActivation:i}=e,{active:l}=n;const{code:c}=o.nativeEvent;if(a.start.includes(c)){const d=l.activatorNode.current;return d&&o.target!==d?!1:(o.preventDefault(),i?.({event:o.nativeEvent}),!0)}return!1}}];function Km(o){return!!(o&&"distance"in o)}function Wm(o){return!!(o&&"delay"in o)}class lf{constructor(e,n,a){var i;a===void 0&&(a=kE(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=n;const{event:l}=e,{target:c}=l;this.props=e,this.events=n,this.document=fs(c),this.documentListeners=new Ao(this.document),this.listeners=new Ao(a),this.windowListeners=new Ao(Nn(c)),this.initialCoordinates=(i=tf(l))!=null?i:wr,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:n,bypassActivationConstraint:a}}}=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(ar.Resize,this.handleCancel),this.windowListeners.add(ar.DragStart,Vm),this.windowListeners.add(ar.VisibilityChange,this.handleCancel),this.windowListeners.add(ar.ContextMenu,Vm),this.documentListeners.add(ar.Keydown,this.handleKeydown),n){if(a!=null&&a({event:this.props.event,activeNode:this.props.activeNode,options:this.props.options}))return this.handleStart();if(Wm(n)){this.timeoutId=setTimeout(this.handleStart,n.delay),this.handlePending(n);return}if(Km(n)){this.handlePending(n);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,n){const{active:a,onPending:i}=this.props;i(a,e,this.initialCoordinates,n)}handleStart(){const{initialCoordinates:e}=this,{onStart:n}=this.props;e&&(this.activated=!0,this.documentListeners.add(ar.Click,DE,{capture:!0}),this.removeTextSelection(),this.documentListeners.add(ar.SelectionChange,this.removeTextSelection),n(e))}handleMove(e){var n;const{activated:a,initialCoordinates:i,props:l}=this,{onMove:c,options:{activationConstraint:d}}=l;if(!i)return;const f=(n=tf(e))!=null?n:wr,g=Eo(i,f);if(!a&&d){if(Km(d)){if(d.tolerance!=null&&sf(g,d.tolerance))return this.handleCancel();if(sf(g,d.distance))return this.handleStart()}if(Wm(d)&&sf(g,d.tolerance))return this.handleCancel();this.handlePending(d,g);return}e.cancelable&&e.preventDefault(),c(f)}handleEnd(){const{onAbort:e,onEnd:n}=this.props;this.detach(),this.activated||e(this.props.active),n()}handleCancel(){const{onAbort:e,onCancel:n}=this.props;this.detach(),this.activated||e(this.props.active),n()}handleKeydown(e){e.code===ut.Esc&&this.handleCancel()}removeTextSelection(){var e;(e=this.document.getSelection())==null||e.removeAllRanges()}}const LE={cancel:{name:"pointercancel"},move:{name:"pointermove"},end:{name:"pointerup"}};class cf extends lf{constructor(e){const{event:n}=e,a=fs(n.target);super(e,LE,a)}}cf.activators=[{eventName:"onPointerDown",handler:(o,e)=>{let{nativeEvent:n}=o,{onActivation:a}=e;return!n.isPrimary||n.button!==0?!1:(a?.({event:n}),!0)}}];const ME={move:{name:"mousemove"},end:{name:"mouseup"}};var uf;(function(o){o[o.RightClick=2]="RightClick"})(uf||(uf={}));class $E extends lf{constructor(e){super(e,ME,fs(e.event.target))}}$E.activators=[{eventName:"onMouseDown",handler:(o,e)=>{let{nativeEvent:n}=o,{onActivation:a}=e;return n.button===uf.RightClick?!1:(a?.({event:n}),!0)}}];const df={cancel:{name:"touchcancel"},move:{name:"touchmove"},end:{name:"touchend"}};class NE extends lf{constructor(e){super(e,df)}static setup(){return window.addEventListener(df.move.name,e,{capture:!1,passive:!1}),function(){window.removeEventListener(df.move.name,e)};function e(){}}}NE.activators=[{eventName:"onTouchStart",handler:(o,e)=>{let{nativeEvent:n}=o,{onActivation:a}=e;const{touches:i}=n;return i.length>1?!1:(a?.({event:n}),!0)}}];var xo;(function(o){o[o.Pointer=0]="Pointer",o[o.DraggableRect=1]="DraggableRect"})(xo||(xo={}));var uc;(function(o){o[o.TreeOrder=0]="TreeOrder",o[o.ReversedTreeOrder=1]="ReversedTreeOrder"})(uc||(uc={}));function IE(o){let{acceleration:e,activator:n=xo.Pointer,canScroll:a,draggingRect:i,enabled:l,interval:c=5,order:d=uc.TreeOrder,pointerCoordinates:f,scrollableAncestors:g,scrollableAncestorRects:m,delta:y,threshold:S}=o;const v=jE({delta:y,disabled:!l}),[_,A]=WC(),x=H.useRef({x:0,y:0}),O=H.useRef({x:0,y:0}),M=H.useMemo(()=>{switch(n){case xo.Pointer:return f?{top:f.y,bottom:f.y,left:f.x,right:f.x}:null;case xo.DraggableRect:return i}},[n,i,f]),T=H.useRef(null),D=H.useCallback(()=>{const P=T.current;if(!P)return;const q=x.current.x*O.current.x,W=x.current.y*O.current.y;P.scrollBy(q,W)},[]),z=H.useMemo(()=>d===uc.TreeOrder?[...g].reverse():g,[d,g]);H.useEffect(()=>{if(!l||!g.length||!M){A();return}for(const P of z){if(a?.(P)===!1)continue;const q=g.indexOf(P),W=m[q];if(!W)continue;const{direction:he,speed:Ee}=EE(P,W,M,e,S);for(const be of["x","y"])v[be][he[be]]||(Ee[be]=0,he[be]=0);if(Ee.x>0||Ee.y>0){A(),T.current=P,_(D,c),x.current=Ee,O.current=he;return}}x.current={x:0,y:0},O.current={x:0,y:0},A()},[e,D,a,A,l,c,JSON.stringify(M),JSON.stringify(v),_,g,z,m,JSON.stringify(S)])}const HE={x:{[gn.Backward]:!1,[gn.Forward]:!1},y:{[gn.Backward]:!1,[gn.Forward]:!1}};function jE(o){let{delta:e,disabled:n}=o;const a=Qd(e);return wo(i=>{if(n||!a||!i)return HE;const l={x:Math.sign(e.x-a.x),y:Math.sign(e.y-a.y)};return{x:{[gn.Backward]:i.x[gn.Backward]||l.x===-1,[gn.Forward]:i.x[gn.Forward]||l.x===1},y:{[gn.Backward]:i.y[gn.Backward]||l.y===-1,[gn.Forward]:i.y[gn.Forward]||l.y===1}}},[n,e,a])}function zE(o,e){const n=e!=null?o.get(e):void 0,a=n?n.node.current:null;return wo(i=>{var l;return e==null?null:(l=a??i)!=null?l:null},[a,e])}function UE(o,e){return H.useMemo(()=>o.reduce((n,a)=>{const{sensor:i}=a,l=i.activators.map(c=>({eventName:c.eventName,handler:e(c.handler,a)}));return[...n,...l]},[]),[o,e])}var To;(function(o){o[o.Always=0]="Always",o[o.BeforeDragging=1]="BeforeDragging",o[o.WhileDragging=2]="WhileDragging"})(To||(To={}));var ff;(function(o){o.Optimized="optimized"})(ff||(ff={}));const Ym=new Map;function PE(o,e){let{dragging:n,dependencies:a,config:i}=e;const[l,c]=H.useState(null),{frequency:d,measure:f,strategy:g}=i,m=H.useRef(o),y=x(),S=So(y),v=H.useCallback(function(O){O===void 0&&(O=[]),!S.current&&c(M=>M===null?O:M.concat(O.filter(T=>!M.includes(T))))},[S]),_=H.useRef(null),A=wo(O=>{if(y&&!n)return Ym;if(!O||O===Ym||m.current!==o||l!=null){const M=new Map;for(let T of o){if(!T)continue;if(l&&l.length>0&&!l.includes(T.id)&&T.rect.current){M.set(T.id,T.rect.current);continue}const D=T.node.current,z=D?new af(f(D),D):null;T.rect.current=z,z&&M.set(T.id,z)}return M}return O},[o,l,n,y,f]);return H.useEffect(()=>{m.current=o},[o]),H.useEffect(()=>{y||v()},[n,y]),H.useEffect(()=>{l&&l.length>0&&c(null)},[JSON.stringify(l)]),H.useEffect(()=>{y||typeof d!="number"||_.current!==null||(_.current=setTimeout(()=>{v(),_.current=null},d))},[d,y,v,...a]),{droppableRects:A,measureDroppableContainers:v,measuringScheduled:l!=null};function x(){switch(g){case To.Always:return!1;case To.BeforeDragging:return n;default:return!n}}}function Xm(o,e){return wo(n=>o?n||(typeof e=="function"?e(o):o):null,[e,o])}function BE(o,e){return Xm(o,e)}function qE(o){let{callback:e,disabled:n}=o;const a=Jd(e),i=H.useMemo(()=>{if(n||typeof window>"u"||typeof window.MutationObserver>"u")return;const{MutationObserver:l}=window;return new l(a)},[a,n]);return H.useEffect(()=>()=>i?.disconnect(),[i]),i}function dc(o){let{callback:e,disabled:n}=o;const a=Jd(e),i=H.useMemo(()=>{if(n||typeof window>"u"||typeof window.ResizeObserver>"u")return;const{ResizeObserver:l}=window;return new l(a)},[n]);return H.useEffect(()=>()=>i?.disconnect(),[i]),i}function GE(o){return new af(gs(o),o)}function Jm(o,e,n){e===void 0&&(e=GE);const[a,i]=H.useState(null);function l(){i(f=>{if(!o)return null;if(o.isConnected===!1){var g;return(g=f??n)!=null?g:null}const m=e(o);return JSON.stringify(f)===JSON.stringify(m)?f:m})}const c=qE({callback(f){if(o)for(const g of f){const{type:m,target:y}=g;if(m==="childList"&&y instanceof HTMLElement&&y.contains(o)){l();break}}}}),d=dc({callback:l});return zr(()=>{l(),o?(d?.observe(o),c?.observe(document.body,{childList:!0,subtree:!0})):(d?.disconnect(),c?.disconnect())},[o]),a}function VE(o){const e=Xm(o);return Hm(o,e)}const Qm=[];function FE(o){const e=H.useRef(o),n=wo(a=>o?a&&a!==Qm&&o&&e.current&&o.parentNode===e.current.parentNode?a:cc(o):Qm,[o]);return H.useEffect(()=>{e.current=o},[o]),n}function KE(o){const[e,n]=H.useState(null),a=H.useRef(o),i=H.useCallback(l=>{const c=nf(l.target);c&&n(d=>d?(d.set(c,rf(c)),new Map(d)):null)},[]);return H.useEffect(()=>{const l=a.current;if(o!==l){c(l);const d=o.map(f=>{const g=nf(f);return g?(g.addEventListener("scroll",i,{passive:!0}),[g,rf(g)]):null}).filter(f=>f!=null);n(d.length?new Map(d):null),a.current=o}return()=>{c(o),c(l)};function c(d){d.forEach(f=>{const g=nf(f);g?.removeEventListener("scroll",i)})}},[i,o]),H.useMemo(()=>o.length?e?Array.from(e.values()).reduce((l,c)=>hs(l,c),wr):Gm(o):wr,[o,e])}function Zm(o,e){e===void 0&&(e=[]);const n=H.useRef(null);return H.useEffect(()=>{n.current=null},e),H.useEffect(()=>{const a=o!==wr;a&&!n.current&&(n.current=o),!a&&n.current&&(n.current=null)},[o]),n.current?Eo(o,n.current):wr}function WE(o){H.useEffect(()=>{if(!sc)return;const e=o.map(n=>{let{sensor:a}=n;return a.setup==null?void 0:a.setup()});return()=>{for(const n of e)n?.()}},o.map(e=>{let{sensor:n}=e;return n}))}function YE(o,e){return H.useMemo(()=>o.reduce((n,a)=>{let{eventName:i,handler:l}=a;return n[i]=c=>{l(c,e)},n},{}),[o,e])}function ey(o){return H.useMemo(()=>o?vE(o):null,[o])}const ty=[];function XE(o,e){e===void 0&&(e=gs);const[n]=o,a=ey(n?Nn(n):null),[i,l]=H.useState(ty);function c(){l(()=>o.length?o.map(f=>Bm(f)?a:new af(e(f),f)):ty)}const d=dc({callback:c});return zr(()=>{d?.disconnect(),c(),o.forEach(f=>d?.observe(f))},[o]),i}function JE(o){if(!o)return null;if(o.children.length>1)return o;const e=o.children[0];return vo(e)?e:o}function QE(o){let{measure:e}=o;const[n,a]=H.useState(null),i=H.useCallback(g=>{for(const{target:m}of g)if(vo(m)){a(y=>{const S=e(m);return y?{...y,width:S.width,height:S.height}:S});break}},[e]),l=dc({callback:i}),c=H.useCallback(g=>{const m=JE(g);l?.disconnect(),m&&l?.observe(m),a(m?e(m):null)},[e,l]),[d,f]=oc(c);return H.useMemo(()=>({nodeRef:d,rect:n,setRef:f}),[n,d,f])}const ZE=[{sensor:cf,options:{}},{sensor:of,options:{}}],e_={current:{}},fc={draggable:{measure:jm},droppable:{measure:jm,strategy:To.WhileDragging,frequency:ff.Optimized},dragOverlay:{measure:gs}};class Ro extends Map{get(e){var n;return e!=null&&(n=super.get(e))!=null?n:void 0}toArray(){return Array.from(this.values())}getEnabled(){return this.toArray().filter(e=>{let{disabled:n}=e;return!n})}getNodeFor(e){var n,a;return(n=(a=this.get(e))==null?void 0:a.node.current)!=null?n:void 0}}const t_={activatorEvent:null,active:null,activeNode:null,activeNodeRect:null,collisions:null,containerNodeRect:null,draggableNodes:new Map,droppableRects:new Map,droppableContainers:new Ro,over:null,dragOverlay:{nodeRef:{current:null},rect:null,setRef:lc},scrollableAncestors:[],scrollableAncestorRects:[],measuringConfiguration:fc,measureDroppableContainers:lc,windowRect:null,measuringScheduled:!1},n_={activatorEvent:null,activators:[],active:null,activeNodeRect:null,ariaDescribedById:{draggable:""},dispatch:lc,draggableNodes:new Map,over:null,measureDroppableContainers:lc},hc=H.createContext(n_),ny=H.createContext(t_);function r_(){return{draggable:{active:null,initialCoordinates:{x:0,y:0},nodes:new Map,translate:{x:0,y:0}},droppable:{containers:new Ro}}}function a_(o,e){switch(e.type){case an.DragStart:return{...o,draggable:{...o.draggable,initialCoordinates:e.initialCoordinates,active:e.active}};case an.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 an.DragEnd:case an.DragCancel:return{...o,draggable:{...o.draggable,active:null,initialCoordinates:{x:0,y:0},translate:{x:0,y:0}}};case an.RegisterDroppable:{const{element:n}=e,{id:a}=n,i=new Ro(o.droppable.containers);return i.set(a,n),{...o,droppable:{...o.droppable,containers:i}}}case an.SetDroppableDisabled:{const{id:n,key:a,disabled:i}=e,l=o.droppable.containers.get(n);if(!l||a!==l.key)return o;const c=new Ro(o.droppable.containers);return c.set(n,{...l,disabled:i}),{...o,droppable:{...o.droppable,containers:c}}}case an.UnregisterDroppable:{const{id:n,key:a}=e,i=o.droppable.containers.get(n);if(!i||a!==i.key)return o;const l=new Ro(o.droppable.containers);return l.delete(n),{...o,droppable:{...o.droppable,containers:l}}}default:return o}}function i_(o){let{disabled:e}=o;const{active:n,activatorEvent:a,draggableNodes:i}=H.useContext(hc),l=Qd(a),c=Qd(n?.id);return H.useEffect(()=>{if(!e&&!a&&l&&c!=null){if(!ef(l)||document.activeElement===l.target)return;const d=i.get(c);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 y=JC(m);if(y){y.focus();break}}})}},[a,e,i,c,l]),null}function s_(o,e){let{transform:n,...a}=e;return o!=null&&o.length?o.reduce((i,l)=>l({transform:i,...a}),n):n}function o_(o){return H.useMemo(()=>({draggable:{...fc.draggable,...o?.draggable},droppable:{...fc.droppable,...o?.droppable},dragOverlay:{...fc.dragOverlay,...o?.dragOverlay}}),[o?.draggable,o?.droppable,o?.dragOverlay])}function l_(o){let{activeNode:e,measure:n,initialRect:a,config:i=!0}=o;const l=H.useRef(!1),{x:c,y:d}=typeof i=="boolean"?{x:i,y:i}:i;zr(()=>{if(!c&&!d||!e){l.current=!1;return}if(l.current||!a)return;const g=e?.node.current;if(!g||g.isConnected===!1)return;const m=n(g),y=Hm(m,a);if(c||(y.x=0),d||(y.y=0),l.current=!0,Math.abs(y.x)>0||Math.abs(y.y)>0){const S=zm(g);S&&S.scrollBy({top:y.y,left:y.x})}},[e,c,d,a,n])}const ry=H.createContext({...wr,scaleX:1,scaleY:1});var Da;(function(o){o[o.Uninitialized=0]="Uninitialized",o[o.Initializing=1]="Initializing",o[o.Initialized=2]="Initialized"})(Da||(Da={}));const c_=H.memo(function(e){var n,a,i,l;let{id:c,accessibility:d,autoScroll:f=!0,children:g,sensors:m=ZE,collisionDetection:y=fE,measuring:S,modifiers:v,..._}=e;const A=H.useReducer(a_,void 0,r_),[x,O]=A,[M,T]=rE(),[D,z]=H.useState(Da.Uninitialized),P=D===Da.Initialized,{draggable:{active:q,nodes:W,translate:he},droppable:{containers:Ee}}=x,be=q!=null?W.get(q):null,Ue=H.useRef({initial:null,translated:null}),Fe=H.useMemo(()=>{var ge;return q!=null?{id:q,data:(ge=be?.data)!=null?ge:e_,rect:Ue}:null},[q,be]),Ge=H.useRef(null),[wt,J]=H.useState(null),[ue,Me]=H.useState(null),te=So(_,Object.values(_)),pe=Co("DndDescribedBy",c),N=H.useMemo(()=>Ee.getEnabled(),[Ee]),R=o_(S),{droppableRects:de,measureDroppableContainers:fe,measuringScheduled:xe}=PE(N,{dragging:P,dependencies:[he.x,he.y],config:R.droppable}),ee=zE(W,q),_e=H.useMemo(()=>ue?tf(ue):null,[ue]),Be=ve(),ke=BE(ee,R.draggable.measure);l_({activeNode:q!=null?W.get(q):null,config:Be.layoutShiftCompensation,initialRect:ke,measure:R.draggable.measure});const Ie=Jm(ee,R.draggable.measure,ke),Ct=Jm(ee?ee.parentElement:null),ot=H.useRef({activatorEvent:null,active:null,activeNode:ee,collisionRect:null,collisions:null,droppableRects:de,draggableNodes:W,draggingNode:null,draggingNodeRect:null,droppableContainers:Ee,over:null,scrollableAncestors:[],scrollAdjustedTranslate:null}),Ot=Ee.getNodeFor((n=ot.current.over)==null?void 0:n.id),vt=QE({measure:R.dragOverlay.measure}),_t=(a=vt.nodeRef.current)!=null?a:ee,Oe=P?(i=vt.rect)!=null?i:Ie:null,nt=!!(vt.nodeRef.current&&vt.rect),sn=VE(nt?null:Ie),Mt=ey(_t?Nn(_t):null),Vt=FE(P?Ot??ee:null),on=XE(Vt),ln=s_(v,{transform:{x:he.x-sn.x,y:he.y-sn.y,scaleX:1,scaleY:1},activatorEvent:ue,active:Fe,activeNodeRect:Ie,containerNodeRect:Ct,draggingNodeRect:Oe,over:ot.current.over,overlayNodeRect:vt.rect,scrollableAncestors:Vt,scrollableAncestorRects:on,windowRect:Mt}),Br=_e?hs(_e,he):null,Ft=KE(Vt),Ci=Zm(Ft),na=Zm(Ft,[Ie]),yn=hs(ln,Ci),On=Oe?pE(Oe,ln):null,rt=Fe&&On?y({active:Fe,collisionRect:On,droppableRects:de,droppableContainers:N,pointerCoordinates:Br}):null,Hn=Nm(rt,"id"),[bn,ra]=H.useState(null),sr=nt?ln:hs(ln,na),cn=hE(sr,(l=bn?.rect)!=null?l:null,Ie),Tn=H.useRef(null),un=H.useCallback((ge,we)=>{let{sensor:Ae,options:Ke}=we;if(Ge.current==null)return;const Te=W.get(Ge.current);if(!Te)return;const $e=ge.nativeEvent,Re=new Ae({active:Ge.current,activeNode:Te,event:$e,options:Ke,context:ot,onAbort(je){if(!W.get(je))return;const{onDragAbort:Se}=te.current,He={id:je};Se?.(He),M({type:"onDragAbort",event:He})},onPending(je,Ve,Se,He){if(!W.get(je))return;const{onDragPending:Tt}=te.current,It={id:je,constraint:Ve,initialCoordinates:Se,offset:He};Tt?.(It),M({type:"onDragPending",event:It})},onStart(je){const Ve=Ge.current;if(Ve==null)return;const Se=W.get(Ve);if(!Se)return;const{onDragStart:He}=te.current,tt={activatorEvent:$e,active:{id:Ve,data:Se.data,rect:Ue}};ka.unstable_batchedUpdates(()=>{He?.(tt),z(Da.Initializing),O({type:an.DragStart,initialCoordinates:je,active:Ve}),M({type:"onDragStart",event:tt}),J(Tn.current),Me($e)})},onMove(je){O({type:an.DragMove,coordinates:je})},onEnd:et(an.DragEnd),onCancel:et(an.DragCancel)});Tn.current=Re;function et(je){return async function(){const{active:Se,collisions:He,over:tt,scrollAdjustedTranslate:Tt}=ot.current;let It=null;if(Se&&Tt){const{cancelDrop:Ln}=te.current;It={activatorEvent:$e,active:Se,collisions:He,delta:Tt,over:tt},je===an.DragEnd&&typeof Ln=="function"&&await Promise.resolve(Ln(It))&&(je=an.DragCancel)}Ge.current=null,ka.unstable_batchedUpdates(()=>{O({type:je}),z(Da.Uninitialized),ra(null),J(null),Me(null),Tn.current=null;const Ln=je===an.DragEnd?"onDragEnd":"onDragCancel";if(It){const zt=te.current[Ln];zt?.(It),M({type:Ln,event:It})}})}}},[W]),V=H.useCallback((ge,we)=>(Ae,Ke)=>{const Te=Ae.nativeEvent,$e=W.get(Ke);if(Ge.current!==null||!$e||Te.dndKit||Te.defaultPrevented)return;const Re={active:$e};ge(Ae,we.options,Re)===!0&&(Te.dndKit={capturedBy:we.sensor},Ge.current=Ke,un(Ae,we))},[W,un]),se=UE(m,V);WE(m),zr(()=>{Ie&&D===Da.Initializing&&z(Da.Initialized)},[Ie,D]),H.useEffect(()=>{const{onDragMove:ge}=te.current,{active:we,activatorEvent:Ae,collisions:Ke,over:Te}=ot.current;if(!we||!Ae)return;const $e={active:we,activatorEvent:Ae,collisions:Ke,delta:{x:yn.x,y:yn.y},over:Te};ka.unstable_batchedUpdates(()=>{ge?.($e),M({type:"onDragMove",event:$e})})},[yn.x,yn.y]),H.useEffect(()=>{const{active:ge,activatorEvent:we,collisions:Ae,droppableContainers:Ke,scrollAdjustedTranslate:Te}=ot.current;if(!ge||Ge.current==null||!we||!Te)return;const{onDragOver:$e}=te.current,Re=Ke.get(Hn),et=Re&&Re.rect.current?{id:Re.id,rect:Re.rect.current,data:Re.data,disabled:Re.disabled}:null,je={active:ge,activatorEvent:we,collisions:Ae,delta:{x:Te.x,y:Te.y},over:et};ka.unstable_batchedUpdates(()=>{ra(et),$e?.(je),M({type:"onDragOver",event:je})})},[Hn]),zr(()=>{ot.current={activatorEvent:ue,active:Fe,activeNode:ee,collisionRect:On,collisions:rt,droppableRects:de,draggableNodes:W,draggingNode:_t,draggingNodeRect:Oe,droppableContainers:Ee,over:bn,scrollableAncestors:Vt,scrollAdjustedTranslate:yn},Ue.current={initial:Oe,translated:On}},[Fe,ee,rt,On,W,_t,Oe,de,Ee,bn,Vt,yn]),IE({...Be,delta:he,draggingRect:On,pointerCoordinates:Br,scrollableAncestors:Vt,scrollableAncestorRects:on});const ce=H.useMemo(()=>({active:Fe,activeNode:ee,activeNodeRect:Ie,activatorEvent:ue,collisions:rt,containerNodeRect:Ct,dragOverlay:vt,draggableNodes:W,droppableContainers:Ee,droppableRects:de,over:bn,measureDroppableContainers:fe,scrollableAncestors:Vt,scrollableAncestorRects:on,measuringConfiguration:R,measuringScheduled:xe,windowRect:Mt}),[Fe,ee,Ie,ue,rt,Ct,vt,W,Ee,de,bn,fe,Vt,on,R,xe,Mt]),Z=H.useMemo(()=>({activatorEvent:ue,activators:se,active:Fe,activeNodeRect:Ie,ariaDescribedById:{draggable:pe},dispatch:O,draggableNodes:W,over:bn,measureDroppableContainers:fe}),[ue,se,Fe,Ie,O,pe,W,bn,fe]);return Xe.createElement(Dm.Provider,{value:T},Xe.createElement(hc.Provider,{value:Z},Xe.createElement(ny.Provider,{value:ce},Xe.createElement(ry.Provider,{value:cn},g)),Xe.createElement(i_,{disabled:d?.restoreFocus===!1})),Xe.createElement(sE,{...d,hiddenTextDescribedById:pe}));function ve(){const ge=wt?.autoScrollEnabled===!1,we=typeof f=="object"?f.enabled===!1:f===!1,Ae=P&&!ge&&!we;return typeof f=="object"?{...f,enabled:Ae}:{enabled:Ae}}}),u_=H.createContext(null),ay="button",d_="Draggable";function f_(o){let{id:e,data:n,disabled:a=!1,attributes:i}=o;const l=Co(d_),{activators:c,activatorEvent:d,active:f,activeNodeRect:g,ariaDescribedById:m,draggableNodes:y,over:S}=H.useContext(hc),{role:v=ay,roleDescription:_="draggable",tabIndex:A=0}=i??{},x=f?.id===e,O=H.useContext(x?ry:u_),[M,T]=oc(),[D,z]=oc(),P=YE(c,e),q=So(n);zr(()=>(y.set(e,{id:e,key:l,node:M,activatorNode:D,data:q}),()=>{const he=y.get(e);he&&he.key===l&&y.delete(e)}),[y,e]);const W=H.useMemo(()=>({role:v,tabIndex:A,"aria-disabled":a,"aria-pressed":x&&v===ay?!0:void 0,"aria-roledescription":_,"aria-describedby":m.draggable}),[a,v,A,x,_,m.draggable]);return{active:f,activatorEvent:d,activeNodeRect:g,attributes:W,isDragging:x,listeners:a?void 0:P,node:M,over:S,setNodeRef:T,setActivatorNodeRef:z,transform:O}}function h_(){return H.useContext(ny)}const g_="Droppable",p_={timeout:25};function m_(o){let{data:e,disabled:n=!1,id:a,resizeObserverConfig:i}=o;const l=Co(g_),{active:c,dispatch:d,over:f,measureDroppableContainers:g}=H.useContext(hc),m=H.useRef({disabled:n}),y=H.useRef(!1),S=H.useRef(null),v=H.useRef(null),{disabled:_,updateMeasurementsFor:A,timeout:x}={...p_,...i},O=So(A??a),M=H.useCallback(()=>{if(!y.current){y.current=!0;return}v.current!=null&&clearTimeout(v.current),v.current=setTimeout(()=>{g(Array.isArray(O.current)?O.current:[O.current]),v.current=null},x)},[x]),T=dc({callback:M,disabled:_||!c}),D=H.useCallback((W,he)=>{T&&(he&&(T.unobserve(he),y.current=!1),W&&T.observe(W))},[T]),[z,P]=oc(D),q=So(e);return H.useEffect(()=>{!T||!z.current||(T.disconnect(),y.current=!1,T.observe(z.current))},[z,T]),H.useEffect(()=>(d({type:an.RegisterDroppable,element:{id:a,key:l,disabled:n,node:z,rect:S,data:q}}),()=>d({type:an.UnregisterDroppable,key:l,id:a})),[a]),H.useEffect(()=>{n!==m.current.disabled&&(d({type:an.SetDroppableDisabled,id:a,key:l,disabled:n}),m.current.disabled=n)},[a,l,n,d]),{active:c,rect:S,isOver:f?.id===a,node:z,over:f,setNodeRef:P}}function hf(o,e,n){const a=o.slice();return a.splice(n<0?a.length+n:n,0,a.splice(e,1)[0]),a}function y_(o,e){return o.reduce((n,a,i)=>{const l=e.get(a);return l&&(n[i]=l),n},Array(o.length))}function gc(o){return o!==null&&o>=0}function b_(o,e){if(o===e)return!0;if(o.length!==e.length)return!1;for(let n=0;n{var e;let{rects:n,activeNodeRect:a,activeIndex:i,overIndex:l,index:c}=o;const d=(e=n[i])!=null?e:a;if(!d)return null;const f=w_(n,c,i);if(c===i){const g=n[l];return g?{x:ii&&c<=l?{x:-d.width-f,y:0,...pc}:c=l?{x:d.width+f,y:0,...pc}:{x:0,y:0,...pc}};function w_(o,e,n){const a=o[e],i=o[e-1],l=o[e+1];return!a||!i&&!l?0:n{let{rects:e,activeIndex:n,overIndex:a,index:i}=o;const l=hf(e,a,n),c=e[i],d=l[i];return!d||!c?null:{x:d.left-c.left,y:d.top-c.top,scaleX:d.width/c.width,scaleY:d.height/c.height}},mc={scaleX:1,scaleY:1},C_=o=>{var e;let{activeIndex:n,activeNodeRect:a,index:i,rects:l,overIndex:c}=o;const d=(e=l[n])!=null?e:a;if(!d)return null;if(i===n){const g=l[c];return g?{x:0,y:nn&&i<=c?{x:0,y:-d.height-f,...mc}:i=c?{x:0,y:d.height+f,...mc}:{x:0,y:0,...mc}};function E_(o,e,n){const a=o[e],i=o[e-1],l=o[e+1];return a?na.map(P=>typeof P=="object"&&"id"in P?P.id:P),[a]),_=c!=null,A=c?v.indexOf(c.id):-1,x=g?v.indexOf(g.id):-1,O=H.useRef(v),M=!b_(v,O.current),T=x!==-1&&A===-1||M,D=v_(l);zr(()=>{M&&_&&m(v)},[M,v,_,m]),H.useEffect(()=>{O.current=v},[v]);const z=H.useMemo(()=>({activeIndex:A,containerId:y,disabled:D,disableTransforms:T,items:v,overIndex:x,useDragOverlay:S,sortedRects:y_(v,f),strategy:i}),[A,y,D.draggable,D.droppable,T,v,x,f,S,i]);return Xe.createElement(sy.Provider,{value:z},e)}const A_=o=>{let{id:e,items:n,activeIndex:a,overIndex:i}=o;return hf(n,a,i).indexOf(e)},x_=o=>{let{containerId:e,isSorting:n,wasDragging:a,index:i,items:l,newIndex:c,previousItems:d,previousContainerId:f,transition:g}=o;return!g||!a||d!==l&&i===c?!1:n?!0:c!==i&&e===f},T_={duration:200,easing:"ease"},oy="transform",R_=_o.Transition.toString({property:oy,duration:0,easing:"linear"}),k_={roleDescription:"sortable"};function D_(o){let{disabled:e,index:n,node:a,rect:i}=o;const[l,c]=H.useState(null),d=H.useRef(n);return zr(()=>{if(!e&&n!==d.current&&a.current){const f=i.current;if(f){const g=gs(a.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)&&c(m)}}n!==d.current&&(d.current=n)},[e,n,a,i]),H.useEffect(()=>{l&&c(null)},[l]),l}function O_(o){let{animateLayoutChanges:e=x_,attributes:n,disabled:a,data:i,getNewIndex:l=A_,id:c,strategy:d,resizeObserverConfig:f,transition:g=T_}=o;const{items:m,containerId:y,activeIndex:S,disabled:v,disableTransforms:_,sortedRects:A,overIndex:x,useDragOverlay:O,strategy:M}=H.useContext(sy),T=L_(a,v),D=m.indexOf(c),z=H.useMemo(()=>({sortable:{containerId:y,index:D,items:m},...i}),[y,i,D,m]),P=H.useMemo(()=>m.slice(m.indexOf(c)),[m,c]),{rect:q,node:W,isOver:he,setNodeRef:Ee}=m_({id:c,data:z,disabled:T.droppable,resizeObserverConfig:{updateMeasurementsFor:P,...f}}),{active:be,activatorEvent:Ue,activeNodeRect:Fe,attributes:Ge,setNodeRef:wt,listeners:J,isDragging:ue,over:Me,setActivatorNodeRef:te,transform:pe}=f_({id:c,data:z,attributes:{...k_,...n},disabled:T.draggable}),N=KC(Ee,wt),R=!!be,de=R&&!_&&gc(S)&&gc(x),fe=!O&&ue,xe=fe&&de?pe:null,_e=de?xe??(d??M)({rects:A,activeNodeRect:Fe,activeIndex:S,overIndex:x,index:D}):null,Be=gc(S)&&gc(x)?l({id:c,items:m,activeIndex:S,overIndex:x}):D,ke=be?.id,Ie=H.useRef({activeId:ke,items:m,newIndex:Be,containerId:y}),Ct=m!==Ie.current.items,ot=e({active:be,containerId:y,isDragging:ue,isSorting:R,id:c,index:D,items:m,newIndex:Ie.current.newIndex,previousItems:Ie.current.items,previousContainerId:Ie.current.containerId,transition:g,wasDragging:Ie.current.activeId!=null}),Ot=D_({disabled:!ot,index:D,node:W,rect:q});return H.useEffect(()=>{R&&Ie.current.newIndex!==Be&&(Ie.current.newIndex=Be),y!==Ie.current.containerId&&(Ie.current.containerId=y),m!==Ie.current.items&&(Ie.current.items=m)},[R,Be,y,m]),H.useEffect(()=>{if(ke===Ie.current.activeId)return;if(ke!=null&&Ie.current.activeId==null){Ie.current.activeId=ke;return}const _t=setTimeout(()=>{Ie.current.activeId=ke},50);return()=>clearTimeout(_t)},[ke]),{active:be,activeIndex:S,attributes:Ge,data:z,rect:q,index:D,newIndex:Be,items:m,isOver:he,isSorting:R,isDragging:ue,listeners:J,node:W,overIndex:x,over:Me,setNodeRef:N,setActivatorNodeRef:te,setDroppableNodeRef:Ee,setDraggableNodeRef:wt,transform:Ot??_e,transition:vt()};function vt(){if(Ot||Ct&&Ie.current.newIndex===D)return R_;if(!(fe&&!ef(Ue)||!g)&&(R||ot))return _o.Transition.toString({...g,property:oy})}}function L_(o,e){var n,a;return typeof o=="boolean"?{draggable:o,droppable:!1}:{draggable:(n=o?.draggable)!=null?n:e.draggable,droppable:(a=o?.droppable)!=null?a:e.droppable}}function yc(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 M_=[ut.Down,ut.Right,ut.Up,ut.Left],$_=(o,e)=>{let{context:{active:n,collisionRect:a,droppableRects:i,droppableContainers:l,over:c,scrollableAncestors:d}}=e;if(M_.includes(o.code)){if(o.preventDefault(),!n||!a)return;const f=[];l.getEnabled().forEach(y=>{if(!y||y!=null&&y.disabled)return;const S=i.get(y.id);if(S)switch(o.code){case ut.Down:a.topS.top&&f.push(y);break;case ut.Left:a.left>S.left&&f.push(y);break;case ut.Right:a.left1&&(m=g[1].id),m!=null){const y=l.get(n.id),S=l.get(m),v=S?i.get(S.id):null,_=S?.node.current;if(_&&v&&y&&S){const x=cc(_).some((P,q)=>d[q]!==P),O=ly(y,S),M=N_(y,S),T=x||!O?{x:0,y:0}:{x:M?a.width-v.width:0,y:M?a.height-v.height:0},D={x:v.left,y:v.top};return T.x&&T.y?D:Eo(D,T)}}}};function ly(o,e){return!yc(o)||!yc(e)?!1:o.data.current.sortable.containerId===e.data.current.sortable.containerId}function N_(o,e){return!yc(o)||!yc(e)||!ly(o,e)?!1:o.data.current.sortable.index{const d=H.useId(),f=H.useRef({inProgress:!1,lastSortTime:0,lastActiveId:null}),g=oE(Om(cf,{activationConstraint:{distance:5}}),Om(of,{coordinateGetter:$_})),m=H.useCallback(v=>{f.current={inProgress:!0,lastSortTime:Date.now(),lastActiveId:v.active.id},l?.({activeId:v.active.id})},[l]),y=H.useCallback(v=>{const{active:_,over:A}=v,x=Date.now();if(!A||_.id===A.id){f.current.inProgress=!1;return}const{lastSortTime:O,lastActiveId:M,inProgress:T}=f.current;if(M===_.id&&x-O<500&&!T)return;f.current={inProgress:!1,lastSortTime:x,lastActiveId:_.id};const D=o.findIndex(P=>String(P[e])===String(_.id)),z=o.findIndex(P=>String(P[e])===String(A.id));if(D!==-1&&z!==-1&&D!==z){const P=hf(o,D,z);i?.(P,{oldIndex:D,newIndex:z})}},[o,e,i]),S=o.map(v=>String(v[e]));return gt.jsx(c_,{id:d,sensors:g,collisionDetection:cE,onDragStart:m,onDragEnd:y,children:gt.jsx(__,{items:S,strategy:I_[n],children:a})},c!==void 0?`${d}-v${c}`:d)},cy=H.createContext(null),j_=({value:o,children:e})=>gt.jsx(cy.Provider,{value:o,children:e}),z_=()=>H.useContext(cy),U_=({id:o,handle:e,as:n="div",children:a})=>{const{attributes:i,listeners:l,setNodeRef:c,transform:d,transition:f,isDragging:g}=O_({id:o}),m={transform:_o.Transform.toString(d),transition:f,opacity:g?.5:1,position:"relative"};return gt.jsx(n,{ref:c,style:m,...i,...e?{}:l,"data-sortable-item":!0,"data-sortable-id":String(o),"data-dragging":g,children:gt.jsx(j_,{value:{listeners:l,handle:e,isDragging:g},children:a})})},st=ht("DynamicRenderer");function Zr(){try{return window.G7Core?.devTools}catch{return}}function pf(o,e,n,a){if(typeof o=="string"){if(/\$t:[a-zA-Z_][a-zA-Z0-9_.\-]*/.test(o))try{return e.resolveTranslations(o,n,a)}catch{return o}return o}if(Array.isArray(o))return o.map(i=>pf(i,e,n,a));if(o&&typeof o=="object"){const i={};for(const[l,c]of Object.entries(o))i[l]=pf(c,e,n,a);return i}return o}function P_(o){const e=Object.keys(o);return e.length>0&&e.every(n=>/^\d+$/.test(n))}const Cr=(o,e)=>{const n=["errors"],a={...o};for(const i of Object.keys(e)){const l=e[i],c=o[i];if(l===null){a[i]=null;continue}if(n.includes(i)){a[i]=l;continue}if(Array.isArray(l)){a[i]=l;continue}if(Array.isArray(c)&&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)>=c.length+d.length+10)a[i]={...l};else{const g=[...c];for(const[m,y]of Object.entries(l)){const S=parseInt(m,10);S>=0&&S=g.length&&(g[S]=y)}a[i]=g}}else l!==null&&typeof l=="object"&&c!==null&&typeof c=="object"&&!Array.isArray(c)?a[i]=Cr(c,l):a[i]=l}return a},bc=(o,e)=>{let n=null;const a=()=>(n===null&&(n={...o}),n);for(const i of Object.keys(e)){if(!(i in o))continue;const l=e[i],c=o[i];if(l!==null&&typeof l=="object"&&!Array.isArray(l)&&c!==null&&typeof c=="object"&&!Array.isArray(c)){const d=bc(c,l);if(d===c)continue;Object.keys(d).length===0?delete a()[i]:a()[i]=d}else delete a()[i]}return n??o},B_=o=>{const e={},n=o.split(";").filter(a=>a.trim());for(const a of n){const i=a.indexOf(":");if(i===-1)continue;const l=a.substring(0,i).trim(),c=a.substring(i+1).trim();if(l&&c){const d=l.replace(/-([a-z])/g,(f,g)=>g.toUpperCase());e[d]=c}}return e};class q_ extends H.Component{constructor(e){super(e),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,n){st.error(`컴포넌트 렌더링 에러 (ID: ${this.props.componentId}, Name: ${this.props.componentName}):`,e,n)}render(){return this.state.hasError?this.props.fallback?this.props.fallback:gt.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:[gt.jsx("div",{className:"font-semibold mb-1",children:"컴포넌트 로드 실패"}),gt.jsxs("div",{className:"text-xs opacity-80",children:[this.props.componentName&&`[${this.props.componentName}] `,"데이터를 표시할 수 없습니다."]}),this.state.error&>.jsxs("details",{className:"mt-2",children:[gt.jsx("summary",{className:"cursor-pointer text-xs opacity-70 hover:opacity-100",children:"상세 정보"}),gt.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 Ur=H.memo(({componentDef:o,dataContext:e,translationContext:n,registry:a,bindingEngine:i,translationEngine:l,actionDispatcher:c,parentComponentContext:d,parentFormContextProp:f,parentDataContext:g,isRootRenderer:m=!1,isInsideIteration:y=!1,isEditMode:S=!1,onComponentSelect:v,onComponentHover:_,onDragStart:A,onDragEnd:x,componentPath:O,layoutKey:M})=>{const[T,D]=H.useState({loadingActions:{}});H.useLayoutEffect(()=>{d||(i.startRenderCycle(),window.__g7SetLocalOverrideKeys||(window.__g7ForcedLocalFields=void 0),window.__g7PendingLocalState=null)});const z=H.useRef(null);H.useLayoutEffect(()=>{if(!d&&e._localInit&&typeof e._localInit=="object"){const{_forceLocalInit:V,_merge:se,...ce}=e._localInit,Z=`${JSON.stringify(ce)}:${V||"no-force"}`;if(z.current!==Z){z.current=Z;const ve=se||"shallow",we=window.G7Core?.state?.get?.()?._local||{},Ae=window.__g7PendingLocalState||{},Ke={...we,...Ae};ve==="replace"?window.__g7PendingLocalState={loadingActions:Ke.loadingActions||{},...ce,hasChanges:!1}:ve==="deep"?window.__g7PendingLocalState=Cr(Ke,{...ce,hasChanges:!1}):window.__g7PendingLocalState={...Ke,...ce,hasChanges:!1};const Te=window.__g7SetLocalOverrideKeys;Te&&typeof Te=="object"&&(ve==="replace"?window.__g7SetLocalOverrideKeys={...ce,hasChanges:!1}:window.__g7SetLocalOverrideKeys=Cr(Te,{...ce,hasChanges:!1}))}}}),H.useLayoutEffect(()=>{if(!d){const V=window.__g7SetLocalOverrideKeys;if(V){D(ve=>bc(ve,V));const se=V,ce=window.__g7ForcedLocalFields,Z=window.__g7LastSetLocalSnapshot;queueMicrotask(()=>{window.__g7SetLocalOverrideKeys===se&&(window.__g7SetLocalOverrideKeys=void 0),window.__g7ForcedLocalFields===ce&&(window.__g7ForcedLocalFields=void 0),window.__g7LastSetLocalSnapshot===Z&&(window.__g7LastSetLocalSnapshot=void 0)})}}},[e._local]);const P=H.useRef(M);H.useEffect(()=>{o._fromBase&&M&&P.current!==M&&(P.current=M,D({loadingActions:{}}))},[M,o._fromBase]);const q=H.useRef(""),W=H.useRef(!1),he=H.useRef(null),Ee=H.useRef(null),be=H.useRef({}),Ue=H.useRef({}),Fe=H.useRef(g),Ge=FC(),wt=CC(),J=wt?.getParentDataContext()??g;H.useEffect(()=>{if(e._localInit&&typeof e._localInit=="object"){const{_forceLocalInit:V,...se}=e._localInit,ce=JSON.stringify(se),Z=V!==void 0,ve=Fd(),ge=`${ce}:${V||"no-force"}`,we=DC({globalTrackedKey:ve.hash,instanceHandledKey:Ee.current,trackingKey:ge});if(we==="apply"){Ee.current=ge,ve.hash=ge,ve.timestamp=V,q.current=ce,Z&&(W.current=!0);const{_merge:Ke,...Te}=se,$e=Ke||"shallow";D(Re=>$e==="replace"?{loadingActions:Re.loadingActions||{},...Te,hasChanges:!1}:$e==="deep"?Cr(Re,{...Te,hasChanges:!1}):{...Re,...Te,hasChanges:!1}),e._globalSetState&&e._globalSetState(Re=>{const et=Re?._local||{};let je;return $e==="replace"?je={...Te,hasChanges:!1}:$e==="deep"?je=Cr(et,{...Te,hasChanges:!1}):je={...et,...Te,hasChanges:!1},{...Re,_local:je}}),i.invalidateCacheByKeys(["_local"]),st.log("_localInit applied (data changed):",Object.keys(se))}else if(we==="prune"){Ee.current=ge;const{_merge:Ke,...Te}=se;D(Re=>bc(Re,Te)),bc(T,Te)!==T&&(i.invalidateCacheByKeys(["_local"]),st.log("_localInit pruned (applied by another renderer):",Object.keys(Te)))}he.current=e._localInit,RC(e._localInit)}},[e._localInit,g,i]);const{isTransitioning:ue}=wm(),Me=HC(),te=f??Me,{width:pe}=Wd(),N=z_(),R=H.useMemo(()=>{let V=o;if(o.type==="iterator"&&o.data){const{data:Z,itemName:ve,indexName:ge,...we}=o;V={...we,iteration:{source:Z,item_var:ve||"item",index_var:ge}}}if(!V.responsive)return V;const se=hi.getMatchingKey(V.responsive,pe);if(!se)return V;const ce=V.responsive[se];return{...V,props:{...V.props,...ce.props},children:ce.children??V.children,text:ce.text??V.text,if:ce.if??V.if,iteration:ce.iteration??V.iteration,__responsiveChildrenKey:ce.children!==void 0?se:void 0}},[o,pe]),de=H.useCallback(V=>{const se=V?.__setStateId;if(D(ce=>{const Z=window.__g7PendingLocalState,ge=window.__g7SetLocalOverrideKeys||Z,we=ge?Cr(ce,ge):ce;if(typeof V=="function"){const Re=V(we);return Cr(we,Re)}const{__mergeMode:Ae,__setStateId:Ke,...Te}=V;let $e;if(Ae==="replace"?$e=Te:Ae==="shallow"?$e={...we,...Te}:$e=Cr(we,Te),Ae!==void 0){const Re=window.__g7ForcedLocalFields;Re&&(window.__g7ForcedLocalFields={...Re,...Te})}return $e}),se){const ce=Zr();if(ce?.isEnabled()){const Z=R.id||"unknown",ve=R.name||"Unknown";setTimeout(()=>{ce.trackComponentRender?.(Z,ve,0,["_local"],[]),ce.completeStateChange?.(se)},0)}}},[R.id,R.name]),fe=d?.state??T,xe=d?.setState??de,ee=H.useMemo(()=>{const V=e._localInit&&e._localInit!==he.current;let se;V&&e._local?se=e._local:se=e._local?Cr(e._local,fe):fe;const ce=window.__g7ForcedLocalFields;ce&&(se=Cr(se,ce));const Z={...e,_local:se},ve=e._computedDefinitions;if(ve&&Object.keys(ve).length>0){const ge=new Dn,we={...Z,...Ge?{_isolated:Ge.state}:{}},Ae={},Ke=Zr(),Te=Ke?.isEnabled()??!1;for(const[$e,Re]of Object.entries(ve)){const et=Te?Date.now():0,je=Te?e._computed?.[$e]:void 0;let Ve;try{if(typeof Re=="string")if(Re.startsWith("{{")&&Re.endsWith("}}")){const Se=Re.slice(2,-2).trim(),He=Vn(Se)?ge.evaluatePipeExpression(Se,we,{skipCache:!0}):ge.evaluateExpression(Se,we,{skipCache:!0});Ae[$e]=He}else Ae[$e]=Re;else if(Re&&typeof Re=="object"&&"$switch"in Re){const Se=ge.resolveSwitch(Re,we,{skipCache:!0});Ae[$e]=Se}}catch(Se){st.warn(`Failed to recalculate computed value: ${$e}`,Se),Ae[$e]=e._computed?.[$e],Ve=Se instanceof Error?Se.message:String(Se)}if(Te&&(Ve||je!==Ae[$e])){const He=Date.now()-et;Ke.trackComputedProperty?.($e,typeof Re=="string"?Re:JSON.stringify(Re),[{type:"_local",path:"_local",value:Z._local}],Ae[$e],He,R.id,Ve),je!==Ae[$e]&&Ke.trackComputedRecalc?.($e,"dependency-change",je,Ae[$e],He,{type:"_local",path:"_local"},R.id)}}Z._computed=Ae}if(Ge&&(Z._isolated=Ge.state),J&&(Z.$parent=J),o.extensionPointProps){const ge=i.resolveObject(o.extensionPointProps,Z,y?{skipCache:!0}:void 0);Z.extensionPointProps=S&&l?pf(ge,l,n,Z):ge}return o.extensionPointCallbacks&&(Z.extensionPointCallbacks=o.extensionPointCallbacks),S&&(Z.$templateId===void 0&&n?.templateId&&(Z.$templateId=n.templateId),Z.$locale===void 0&&n?.locale&&(Z.$locale=n.locale)),Z},[e,fe,Ge?.state,J,wt?.version,o.extensionPointProps,o.extensionPointCallbacks]);be.current=ee._local,Ue.current=ee._computed||{},Fe.current=J,H.useEffect(()=>{const V=Zr();if(!V?.isEnabled())return;const se=ee._local;se&&V.updateLocalState(se);const ce=ee._computed;ce&&V.updateComputedState(ce),J&&V.updateParentContext?.(J);const Z=R.id||`comp-${Date.now()}`,ve=R.name||"Unknown",ge={global:Object.keys(e._global||{}),local:Object.keys(se||{}),context:d?Object.keys(d.state||{}):[]},we={type:d?"componentContext":"dynamicState",hasComponentContext:!!d,parentId:d?"parent":void 0};V.trackComponentStateSource?.(Z,ve,ge,we),fe&&Object.keys(fe).length>0&&V.trackDynamicState?.(Z,fe);const Ae=!!(R.expandChildren||R.props?.expandChildren);V.trackContextFlow?.(Z,ve,!!d,Ae,!0)},[ee._local,e,R.id,R.name,d,fe,R.expandChildren,R.props?.expandChildren,J]);const _e=H.useMemo(()=>({state:{...ee._local},setState:xe,stateRef:be,computedRef:Ue,isolatedContext:Ge,parentDataContext:ee}),[ee._local,xe,T,Ge,ee]),Be=H.useMemo(()=>{const V=ns({if:R.if,condition:R.condition,conditions:R.conditions},ee,i,R.id);if(R.if||R.condition!==void 0||R.conditions){const ce=Zr();ce?.isEnabled()&&R.if&&ce.trackIfCondition(R.id||`if-${Date.now()}`,R.if,V)}return V},[R.if,R.conditions,ee,i,R.id]),ke=H.useMemo(()=>{if(!R.slot)return null;const V=R.slot;if(V.startsWith("{{")&&V.endsWith("}}")){const se=V.slice(2,-2).trim();try{const ce={componentId:R.id,componentName:R.name,propName:"slot"},Z=Vn(se)?i.evaluatePipeExpression(se,ee,void 0,ce):i.evaluateExpression(se,ee,ce);return st.log(`[Slot] 표현식 평가: "${se}" => "${Z}" (컴포넌트: ${R.id})`),typeof Z=="string"?Z:null}catch(ce){return st.warn(`slot 표현식 평가 실패 (컴포넌트: ${R.id}):`,ce),null}}return st.log(`[Slot] 정적 슬롯 ID: "${V}" (컴포넌트: ${R.id})`),V},[R.slot,R.id,ee,i]),Ie=H.useMemo(()=>!ke||!R.id?"":`${R.id}-${ke}-${JSON.stringify(R.slotOrder??0)}`,[ke,R.id,R.slotOrder]),Ct=H.useRef(null);H.useEffect(()=>{const V=window.__slotContextValue,se=V?.isEnabled??!1;if(R.slot&&st.log(`[Slot Registration] 컴포넌트: ${R.id}, isSlotEnabled: ${se}, shouldRender: ${Be}, resolvedSlotId: ${ke}`),!se||!Be){R.slot&&st.log(`[Slot Registration] 등록 스킵 - isSlotEnabled: ${se}, shouldRender: ${Be}`),Ct.current&&R.id&&V&&(V.unregisterFromSlot(Ct.current,R.id),Ct.current=null);return}if(!ke||!R.id){R.slot&&st.log(`[Slot Registration] 등록 스킵 - resolvedSlotId: ${ke}, id: ${R.id}`),Ct.current&&R.id&&V&&(V.unregisterFromSlot(Ct.current,R.id),Ct.current=null);return}Ct.current&&Ct.current!==ke&&V.unregisterFromSlot(Ct.current,R.id);const ce={...R,slot:void 0,slotOrder:void 0};return V.registerToSlot(ke,R.id,{componentDef:ce,dataContext:e,order:R.slotOrder??0,parentFormContext:f??null,getParentComponentContext:()=>_e,translationContext:n,registrationKey:Ie}),Ct.current=ke,()=>{const Z=window.__slotContextValue;ke&&R.id&&Z&&Z.unregisterFromSlot(ke,R.id)}},[Be,ke,R,e,f,_e,n,Ie]);const ot=H.useCallback(V=>{if(typeof V=="string"){if(jl(V))return bd(V);if(zl(V)){const se=[],ce=V.replace(new RegExp(`${ao}([^${fi}]*)${fi}`,"g"),(ve,ge)=>(se.push(ge),`${xa}${se.length-1}${xa}`));let Z=ce;return/\$t:[a-zA-Z0-9._-]+/.test(ce)&&(Z=l.resolveTranslations(ce,n,ee)),Z.replace(new RegExp(`${xa}(\\d+)${xa}`,"g"),(ve,ge)=>se[parseInt(ge)])}if(V.startsWith("$t:defer:"))return V;if(/\$t:[a-zA-Z0-9._-]+/.test(V)){const se=V.trim();return se.startsWith("{")&&se.endsWith("}")||se.startsWith("[")&&se.endsWith("]")?V:l.resolveTranslations(V,n,ee)}return V}if(Array.isArray(V))return V.map(se=>ot(se));if(V&&typeof V=="object"){const se={};for(const[ce,Z]of Object.entries(V))se[ce]=ot(Z);return se}return V},[l,n,ee]),Ot=H.useCallback(V=>ro(V),[]),vt=H.useCallback(V=>Aa(V),[]),_t=H.useMemo(()=>{let V={...R.props||{}};const se=["cellChildren","expandChildren","expandContext","render"],Z=a.getMetadata(R.name)?.skipBindingKeys||[],ve=[...new Set([...se,...Z])],ge=y?{skipCache:!0}:void 0,we={...ge??{},skipBindingKeys:ve},Ae=Se=>{if(ge)return ge;if(Se.startsWith("_computed")||Se.startsWith("$computed"))return{skipCache:!0}};for(const[Se,He]of Object.entries(V))if(!ve.includes(Se))if(typeof He=="string"){const tt=vt(He);if(tt!==null){let Tt=!1,It=tt;tt.startsWith(nr)&&(Tt=!0,It=tt.slice(nr.length));const Ln={componentId:R.id,componentName:R.name,propName:Se};let zt;if(Vn(It))try{zt=i.evaluatePipeExpression(It,ee,Ae(It),Ln)}catch(Ut){st.warn(`파이프 표현식 평가 실패 (컴포넌트: ${R.id}, prop: ${Se}):`,Ut),zt=void 0}else if(Ot(It))try{zt=i.evaluateExpression(It,ee,Ln)}catch(Ut){st.warn(`표현식 평가 실패 (컴포넌트: ${R.id}, prop: ${Se}):`,Ut),zt=void 0}else zt=i.resolve(It,ee,Ae(It),Ln);V[Se]=Tt&&zt!=null?ts(zt):zt}else{const Tt={componentId:R.id,componentName:R.name,propName:Se};V[Se]=i.resolveBindings(He,ee,ge,Tt)}}else Array.isArray(He)?V[Se]=He.map(tt=>typeof tt=="string"?i.resolveBindings(tt,ee,ge):typeof tt=="object"&&tt!==null?i.resolveObject(tt,ee,we):tt):He&&typeof He=="object"&&(V[Se]=i.resolveObject(He,ee,we));for(const[Se,He]of Object.entries(V))V[Se]=ot(He);if(typeof V.style=="string"&&(V.style=B_(V.style)),V=Cd(V,S?void 0:R.actions,ee,{componentContext:_e,actionDispatcher:c}),R.classMap){const Se=Cw(R.classMap,ee,i,{skipCache:!0});if(Se){const He=V.className||"";V.className=He?`${He} ${Se}`:Se}}R.style&&(V.style=R.style),R.actions&&R.actions.length>0&&R.type==="composite"&&Object.assign(V,fe),R.component_layout&&(V.__componentLayoutDefs=R.component_layout);const Ke=R.expandChildren||R.props?.expandChildren,Te=R.props?.cellChildren,$e=R.children&&R.children.length>0,Re=R.component_layout,et=R.slot,je=R.props?.modalId,Ve=R.type==="composite";return(Ke||Te||$e||Re||et||je||Ve)&&(V.__componentContext=_e),V},[R.props,R.actions,R.style,R.classMap,R.id,ee,n,i,l,_e,fe,ot,Ot,vt,y]),Oe=H.useRef(null),nt=H.useMemo(()=>Oe.current&&Em(Oe.current,_t)?Oe.current:(Oe.current=_t,_t),[_t]),sn=H.useMemo(()=>{const V=R.id;if(typeof V!="string"||!V.includes("{{"))return V;const se=i.resolveBindings(V,ee,{skipCache:!0});return typeof se=="string"?se:V},[R.id,ee,i]),Mt=H.useMemo(()=>{const V=R.dataKey,se=R.trackChanges,ce=R.debounce;if(V){const Z=V.startsWith("_global."),ve=Z?V.slice(8):V,ge=Z?e._global:ee._local;return{dataKey:ve,trackChanges:se??!1,debounce:ce,setState:Z?Ae=>{e._globalSetState?e._globalSetState(Ae):st.warn("_global.formData 사용 시 _globalSetState가 필요합니다.")}:xe,state:ge??{},_isGlobal:Z}}if(te.dataKey)return te},[R.dataKey,R.trackChanges,R.debounce,R.id,xe,ee._local,e._global,e._globalSetState,te]),Vt=H.useRef(new Set);H.useEffect(()=>{Vt.current.clear()},[e._global?._remountKeys]);const on=H.useCallback((V,se)=>{const ce=e._global?._remountKeys;return V&&ce?.[V]&&!Vt.current.has(V)?(Vt.current.add(V),`${V}-remount-${ce[V]}`):V||se},[e._global?._remountKeys]),ln=H.useMemo(()=>{if(R.text!==void 0){if(typeof R.text=="string"){const V=R.text;let se=V;const ce={componentId:R.id,componentName:R.name,propName:"text",skipCache:!0},Z=vt(V);if(Z!==null){let ve=!1,ge=Z;if(Z.startsWith(nr)&&(ve=!0,ge=Z.slice(nr.length)),Vn(ge))try{se=i.evaluatePipeExpression(ge,ee,{skipCache:!0},ce)}catch(we){st.warn(`text 파이프 표현식 평가 실패 (컴포넌트: ${R.id}):`,we),se=""}else if(Ot(ge))try{se=i.evaluateExpression(ge,ee,ce)}catch(we){st.warn(`text 표현식 평가 실패 (컴포넌트: ${R.id}):`,we),se=""}else se=i.resolve(ge,ee,{skipCache:!0},ce);ve&&se!=null&&(se=ts(se))}else V.includes("{{")&&(se=i.resolveBindings(V,ee,{skipCache:!0},ce));return se=ot(se),se??""}return R.text}return!R.children||R.children.length===0?null:R.children.map((V,se)=>{if(typeof V=="string")return V;const ce=R.__responsiveChildrenKey,Z=ce?`responsive.${ce}.children`:"children",ve=O?`${O}.${Z}.${se}`:`${se}`,ge=V._fromBase?V.id||`child-${se}`:on(V.id,`child-${se}`),we=!V._fromBase&&M?`${ge}_${M}`:ge;return gt.jsx(Ur,{componentDef:V,dataContext:ee,translationContext:n,registry:a,bindingEngine:i,translationEngine:l,actionDispatcher:c,parentComponentContext:_e,parentFormContextProp:Mt,isInsideIteration:y,isEditMode:S,onComponentSelect:v,onComponentHover:_,componentPath:ve,onDragStart:A,onDragEnd:x,layoutKey:M},we)})},[R.text,R.children,R.id,e,ee,n,a,i,l,c,_e,Mt,vt,Ot,ot,on,y,S,v,_,O,A,x,M]),Br=H.useMemo(()=>{if(!R.iteration)return null;try{const V=wd(R.iteration.source,ee,i);if(!Array.isArray(V))return st.warn(`iteration source가 배열이 아닙니다 (컴포넌트: ${R.id}):`,V),null;const se=Zr();return se?.isEnabled()&&se.trackIteration(R.id||`iteration-${Date.now()}`,R.iteration.source,R.iteration.item_var,R.iteration.index_var,V.length),V.map((ce,Z)=>{const ve={...ee,[R.iteration.item_var]:ce,[`${R.iteration.item_var}_index`]:Z};R.iteration.index_var&&(ve[R.iteration.index_var]=Z);const ge=Z===0||Z===V.length-1;se?.isEnabled()&&ge&&se.trackNestedContext?.({componentId:`${R.id||"unknown"}-iter-${Z}`,componentType:"iteration",parentContext:{available:Object.keys(ee),values:{}},ownContext:{added:[R.iteration.item_var,...R.iteration.index_var?[R.iteration.index_var]:[]],values:{[R.iteration.item_var]:ce,...R.iteration.index_var?{[R.iteration.index_var]:Z}:{}}},depth:1});const we={...R,iteration:void 0,responsive:void 0},Ae=O?`${O}.iteration.${Z}`:`iteration.${Z}`,Ke=`${on(R.id,"item")}-${Z}`;return gt.jsx(Ur,{componentDef:we,dataContext:ve,translationContext:n,registry:a,bindingEngine:i,translationEngine:l,actionDispatcher:c,parentComponentContext:_e,parentFormContextProp:Mt,isInsideIteration:!0,isEditMode:S,onComponentSelect:v,onComponentHover:_,componentPath:Ae,onDragStart:A,onDragEnd:x,layoutKey:M},Ke)})}catch(V){return st.error(`iteration 렌더링 실패 (컴포넌트: ${R.id}):`,V),null}},[R.iteration,R.children,R.id,e,ee,n,a,i,l,c,_e,Mt,on,S,v,_,O,A,x,M]),[Ft,Ci]=H.useState(0),na=H.useMemo(()=>{if(!R.sortable||!R.itemTemplate)return null;const{sortable:V,itemTemplate:se}=R;try{const ce=wd(V.source,ee,i);if(!Array.isArray(ce))return st.warn(`sortable source가 배열이 아닙니다 (컴포넌트: ${R.id}):`,ce),null;if(ce.length===0)return null;const Z=V.itemKey||"id",ve=V.strategy||"verticalList",ge=V.itemVar||"$item",we=V.indexVar||"$index",Ae=V.handle,Ke=V.wrapperElement,Te=(et,je)=>{const Ve=R.actions?.filter(Se=>Se.event==="onSortEnd"||Se.type==="onSortEnd");if(Ci(Se=>Se+1),Ve&&Ve.length>0&&c){const Se={...ee,$sortedItems:et,$sortEvent:je};Ve.forEach(He=>{try{const tt=c.createHandler(He,Se,_e),Tt=new Event("sortend");tt(Tt)}catch(tt){st.error(`onSortEnd action failed: ${He.handler}`,tt)}})}},$e=et=>{const je=R.actions?.filter(Ve=>Ve.event==="onSortStart"||Ve.type==="onSortStart");if(je&&je.length>0&&c){const Ve={...ee,$activeId:et.activeId};je.forEach(Se=>{try{const He=c.createHandler(Se,Ve,_e),tt=new Event("sortstart");He(tt)}catch(He){st.error(`onSortStart action failed: ${Se.handler}`,He)}})}},Re=ce.map((et,je)=>{const Ve=String(et[Z]),Se={...ee,[ge]:et,[we]:je},He=O?`${O}.sortable.${je}`:`sortable.${je}`,tt=`${on(R.id,"sortable-item")}-v${Ft}-${Ve}`;return gt.jsx(U_,{id:Ve,handle:Ae,...Ke?{as:Ke}:{},children:(Ke&&se.children?se.children:[se]).map((Tt,It)=>gt.jsx(Ur,{componentDef:Tt,dataContext:Se,translationContext:n,registry:a,bindingEngine:i,translationEngine:l,actionDispatcher:c,parentComponentContext:_e,parentFormContextProp:void 0,isInsideIteration:!0,isEditMode:S,onComponentSelect:v,onComponentHover:_,componentPath:He,onDragStart:A,onDragEnd:x,layoutKey:M},`${tt}-child-${It}`))},tt)});return gt.jsx(H_,{items:ce,itemKey:Z,strategy:ve,onSortEnd:Te,onSortStart:$e,sortVersion:Ft,children:Re})}catch(ce){return st.error(`sortable 렌더링 실패 (컴포넌트: ${R.id}):`,ce),null}},[R.sortable,R.itemTemplate,R.actions,R.id,e,ee,n,a,i,l,c,_e,on,S,v,_,O,A,x,Ft,M]),yn=H.useRef(!1);H.useEffect(()=>{if(yn.current)return;yn.current=!0;const V=Zr();if(V?.isEnabled()&&V.trackMount(o.id,{name:o.name,type:o.type||"component",props:nt}),o.lifecycle?.onMount&&o.lifecycle.onMount.length>0)for(const ce of o.lifecycle.onMount)try{const Z=c.createHandler(ce,ee,_e),ve=new Event("mount");Z(ve),st.log(`Lifecycle onMount executed: ${ce.handler} (Component: ${o.id})`)}catch(Z){st.error(`Lifecycle onMount failed: ${ce.handler} (Component: ${o.id})`,Z)}const se=[];if(o.onComponentEvent&&o.onComponentEvent.length>0){const ce=window.G7Core;if(ce?.componentEvent?.on)for(const Z of o.onComponentEvent){if(!Z.event){st.warn(`onComponentEvent: event name is required (Component: ${o.id})`);continue}const ve=async we=>{try{const Ae={...ee,_eventData:we},Te=await c.createHandler({handler:Z.handler,params:Z.params,onSuccess:Z.onSuccess,onError:Z.onError},Ae,_e)(new CustomEvent(Z.event,{detail:we}));return st.log(`onComponentEvent "${Z.event}" handled: ${Z.handler} (Component: ${o.id})`,{eventData:we,result:Te}),Te}catch(Ae){throw st.error(`onComponentEvent "${Z.event}" failed: ${Z.handler} (Component: ${o.id})`,Ae),Ae}},ge=ce.componentEvent.on(Z.event,ve);se.push(ge),st.log(`onComponentEvent: Subscribed to "${Z.event}" (Component: ${o.id})`)}else st.warn(`onComponentEvent: G7Core.componentEvent is not available (Component: ${o.id})`)}return()=>{const ce=Zr();ce?.isEnabled()&&ce.trackUnmount(o.id);for(const Z of se)try{Z()}catch(ve){st.error(`onComponentEvent: Failed to unsubscribe (Component: ${o.id})`,ve)}if(se.length>0&&st.log(`onComponentEvent: Unsubscribed ${se.length} event(s) (Component: ${o.id})`),o.lifecycle?.onUnmount&&o.lifecycle.onUnmount.length>0)for(const Z of o.lifecycle.onUnmount)try{const ve=c.createHandler(Z,ee,_e),ge=new Event("unmount");ve(ge),st.log(`Lifecycle onUnmount executed: ${Z.handler} (Component: ${o.id})`)}catch(ve){st.error(`Lifecycle onUnmount failed: ${Z.handler} (Component: ${o.id})`,ve)}}},[]);const On=H.useMemo(()=>{const V=nt.dataKey,se=nt.trackChanges,ce=nt.debounce;return V?{dataKey:V,trackChanges:se??!1,debounce:ce,setState:xe,state:fe}:null},[nt.dataKey,nt.trackChanges,nt.debounce,xe,fe]);H.useEffect(()=>{const V=R.dataKey||nt.dataKey;if(!V)return;const se=Zr();if(!se?.isEnabled())return;const ce=[],Z=ge=>{if(ge)for(const we of ge){const Ae=we?.props?.name;if(Ae&&ce.push({name:Ae,type:we.name||we.type||"unknown"}),we?.children&&Z(we.children),we?.slots)for(const Ke of Object.values(we.slots))Array.isArray(Ke)&&Z(Ke)}};if(o.children&&Z(o.children),o.slots)for(const ge of Object.values(o.slots))Array.isArray(ge)&&Z(ge);const ve=o.id||`form-${V}`;return se.trackForm(ve,V,ce),()=>{se.untrackForm(ve)}},[R,nt.dataKey,o.id,o.children]);const rt=H.useRef(null),Hn=H.useRef(void 0);H.useEffect(()=>{const V=nt?.name;if(!V||!te.dataKey||!te.setState||nt?.autoBinding===!1)return;const se=`${te.dataKey}.${V}`,ce=window.__g7AutoBindingPaths??new Map;return window.__g7AutoBindingPaths=ce,ce.set(se,(ce.get(se)??0)+1),()=>{const Z=ce.get(se)??0;Z<=1?ce.delete(se):ce.set(se,Z-1)}},[nt?.name,nt?.autoBinding,te.dataKey,te.setState]);const bn=H.useMemo(()=>{const{dataKey:V,trackChanges:se,debounce:ce,...Z}=nt,ve=Z.name;if(!ve||!te.dataKey||!te.setState)return Z;if(Z.autoBinding===!1){const{autoBinding:Ve,...Se}=Z;return Se}const ge=`${te.dataKey}.${ve}`,we=jC(te.state,ge),Ae=we!==void 0?we:Z.value,Te=a.getMetadata(o.name)?.bindingType,$e=typeof Ae=="boolean"&&(Te==="checked"||Te==="checkable"&&["checkbox","radio"].includes(Z?.type)),Re=te.debounce,et=Ve=>{const Se=te.state||{},He=zC(Se,ge,Ve);if(te.trackChanges&&(He.hasChanges=!0),window.__g7PendingLocalState=He,te.setState(He),te._isGlobal)return;const tt=window.G7Core,Tt={[ge]:Ve};te.trackChanges&&(Tt.hasChanges=!0),tt?.state?.setLocal?.(Tt,{render:!1})},je=(Ve,Se)=>{Re&&Re>0?(rt.current&&clearTimeout(rt.current),rt.current=setTimeout(()=>{et(Ve),rt.current=null,Se&&(Se(),window.__g7PendingLocalState=null)},Re)):(et(Ve),Se&&(Se(),window.__g7PendingLocalState=null))};if($e)return{...Z,checked:Ae,onChange:Se=>{const He=Se.target.checked;et(He),Z.onChange&&Z.onChange(Se)}};{const Ve=He=>{const tt=He?.target?.value!==void 0?He.target.value:He;Re&&Re>0&&(Hn.current=tt);const Tt=He?.target?{target:{value:tt,name:He.target.name,type:He.target.type,checked:He.target.checked},currentTarget:He.currentTarget?{value:tt,name:He.currentTarget.name}:void 0}:He;je(tt,()=>{Z.onChange&&Z.onChange(Tt)})};let Se;return Hn.current!==void 0?rt.current!==null?Se=Hn.current:String(Ae??"")===String(Hn.current)?(Hn.current=void 0,Se=Ae??""):Se=Hn.current:Se=Ae??"",{...Z,value:Se,onChange:Ve}}},[nt,te,te.state,te.debounce]),ra=H.useMemo(()=>{const V=Zr();if(V?.isEnabled()&&V.trackRender(o.name),!Be)return R.iteration?Br:null;if(R.sortable&&R.itemTemplate)return na;if(R.iteration)return Br;if(R.type==="extension_point"){const{layout:Te,columns:$e,gap:Re,className:et,...je}=R.props||{};let Ve=et||"";return Te==="grid"&&$e?Ve=`${Ve} grid grid-cols-${$e} gap-${Re||4}`.trim():Te==="flex"&&(Ve=`${Ve} flex flex-col gap-${Re||4}`.trim()),gt.jsx("div",{id:sn,className:Ve||void 0,...je,children:ln})}const se=a.getComponent(R.name);if(!se)return st.error(`컴포넌트를 찾을 수 없습니다: ${R.name} (ID: ${R.id})`,"componentDef:",JSON.stringify(R,null,2)),null;const ce=e._global?._remountKeys,Z={...bn,id:bn.id??sn,...ce&&Object.keys(ce).length>0&&{__remountTrigger:JSON.stringify(ce)}};if(N?.listeners&&N.handle&&bn["data-drag-handle"]!==void 0&&(Object.assign(Z,N.listeners),Z.style={...Z.style,cursor:N.isDragging?"grabbing":"grab"}),S){const Te=R.id||`auto_${R.name||R.type||"unknown"}_${Math.random().toString(36).substring(2,8)}`,$e=je=>{typeof je.preventDefault=="function"&&je.preventDefault(),v&&(je.stopPropagation(),v(Te,je))},Re={"data-editor-id":Te,"data-editor-name":R.name,"data-editor-type":R.type,onClick:$e};O&&(Re["data-editor-path"]=O);const et=R.__editorSlotName??R.slot;typeof et=="string"&&(Re["data-editor-slot"]=et),_&&(Re.onMouseMove=je=>{je.stopPropagation(),_(Te,je)},Re.onMouseLeave=je=>{_(null,je)}),Object.assign(Z,Re),Z.editorAttrs=Re}const ve=R.type==="basic",ge=R.type==="layout",Ae=ve||ge?(()=>{const Te={};for(const[$e,Re]of Object.entries(Z))$e.startsWith("__")||$e==="editorAttrs"&&ve||(Te[$e]=Re);return Te})():Z;let Ke=gt.jsx(se,{...Ae,children:ln});if(Mt&&(Ke=gt.jsx(IC,{value:Mt,children:Ke})),R.isolatedState){const Te=typeof R.isolatedState=="object"?R.isolatedState:{},$e=e?._isolatedInit,Re=$e?{...Te,...$e}:Te;Ke=gt.jsx(VC,{initialState:Re,scopeId:R.isolatedScopeId,children:Ke})}return Ke},[Be,R.iteration,R.sortable,R.itemTemplate,R.type,R.name,R.id,R.props,R.isolatedState,R.isolatedScopeId,a,bn,ln,Br,na,N,On,S,v,_,A,x,O,e._global?._remountKeys]),sr=H.useMemo(()=>{const V=R.blur_until_loaded;if(!V||e?._global?.__isPreview)return!1;if(typeof V=="string"){const Z=vt(V);if(Z!==null)try{const ve={componentId:R.id,componentName:R.name,propName:"blur_until_loaded"};return!!i.evaluateExpression(Z,ee,ve)}catch(ve){return st.warn(`blur_until_loaded 표현식 평가 실패 (컴포넌트: ${R.id}):`,ve),!1}return!1}if(typeof V=="object"&&V!==null){if(!V.enabled)return!1;if(V.data_sources)return(Array.isArray(V.data_sources)?V.data_sources:[V.data_sources]).some(we=>e[we]===void 0);if(ue)return!0;const Z=["route","query","_global","_local","_dataSourceErrors"];return Object.keys(e).filter(ge=>!Z.includes(ge)&&!ge.startsWith("_")).some(ge=>e[ge]===void 0)}if(ue)return!0;const se=["route","query","_global","_local","_dataSourceErrors"];return Object.keys(e).filter(Z=>!se.includes(Z)&&!Z.startsWith("_")).some(Z=>e[Z]===void 0)},[R.blur_until_loaded,R.id,ue,e,ee,i,vt]);if(sr){const V=R.blur_until_loaded;if(typeof V=="object"&&V?.data_sources){const ce=(Array.isArray(V.data_sources)?V.data_sources:[V.data_sources]).reduce((ve,ge)=>(ve[ge]=e[ge]===void 0?"UNDEFINED":"LOADED",ve),{}),Z=Object.keys(e).filter(ve=>!ve.startsWith("_"));st.log(`[BLUR APPLIED] Component: ${R.id}, data_sources status:`,ce,"Available keys:",Z)}else st.log(`[BLUR APPLIED] Component: ${R.id}, blur_until_loaded:`,V)}const cn=H.useMemo(()=>{if(!R.blur_until_loaded)return{wrapperClasses:"",innerClasses:""};const V=_t?.className||"";if(!V)return{wrapperClasses:"",innerClasses:""};const se=[/^(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-)/],ce=V.split(/\s+/).filter(Boolean),Z=[],ve=[];for(const ge of ce)se.some(Ae=>Ae.test(ge))?Z.push(ge):ve.push(ge);return{wrapperClasses:Z.join(" "),innerClasses:ve.join(" ")}},[R.blur_until_loaded,_t?.className]),Tn=window.__slotContextValue;return ke&&Tn?.isEnabled?null:gt.jsx(q_,{componentId:o.id,componentName:o.name,children:R.blur_until_loaded?gt.jsx("div",{className:[cn.wrapperClasses,sr?"opacity-50 blur-sm transition-all duration-300 pointer-events-none":void 0].filter(Boolean).join(" ")||void 0,children:ra}):ra})});Ur.displayName="DynamicRenderer",typeof window<"u"&&(window.__DynamicRenderer=Ur);function G_(o){const e={};try{const a=new URL(o,typeof window<"u"?window.location.origin:"http://localhost").searchParams,i=new Set;for(const l of a.keys()){if(i.has(l))continue;i.add(l);const c=a.getAll(l);c.length>1||l.endsWith("[]")?e[l]=c:e[l]=c[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 wi=class wi{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 wi.instance||(wi.instance=new wi),wi.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 a=window.G7Core?.state?.get?.();return a?.settings?.advanced?.debug_mode===!0||a?._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 n={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(n),this.stateHistory.length>this.config.maxHistorySize&&this.stateHistory.shift(),this.notifyStateWatchers(n)}getState(){try{const e=window.G7Core,n=e?.state?.get?.()||{},a={};if(e?._isolatedStates&&typeof e._isolatedStates=="object")for(const[i,l]of Object.entries(e._isolatedStates))a[i]=this.sanitizeObject(l);return{_global:n._global||n,_local:this.currentLocalState,_computed:this.currentComputedState,_isolated:Object.keys(a).length>0?a: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 n={};try{n=(window.G7Core?.state?.get?.()||{})._local||{}}catch{n={}}const a=this.findMismatchedLeafPaths(e,n);return{hasMismatch:a.length>0,mismatchedPaths:a,storageA:e,storageB:n}}findMismatchedLeafPaths(e,n,a=""){const i=[],l=new Set([...Object.keys(e||{}),...Object.keys(n||{})]);for(const c of l){const d=a?`${a}.${c}`:c,f=e?.[c],g=n?.[c],m=f&&typeof f=="object"&&!Array.isArray(f),y=g&&typeof g=="object"&&!Array.isArray(g);if(m&&y)i.push(...this.findMismatchedLeafPaths(f,g,d));else{const S=f===void 0?"__undefined__":JSON.stringify(f),v=g===void 0?"__undefined__":JSON.stringify(g);S!==v&&i.push(d)}}return i}watchState(e,n){return this.stateWatchers.has(e)||this.stateWatchers.set(e,new Set),this.stateWatchers.get(e).add(n),()=>{this.stateWatchers.get(e)?.delete(n)}}notifyStateWatchers(e){if(this.stateWatchers.get("*")?.forEach(n=>{try{n(e.next,e.prev,"*")}catch(a){console.error("[G7DevTools] State watcher error:",a)}}),e.diff)for(const n of e.diff.changed)this.stateWatchers.get(n.path)?.forEach(a=>{try{a(n.newValue,n.oldValue,n.path)}catch(i){console.error("[G7DevTools] State watcher error:",i)}})}diffSnapshots(e,n){const a=this.stateHistory.find(l=>l.id===e),i=this.stateHistory.find(l=>l.id===n);return!a||!i?null:this.calculateDiff(a.next,i.next)}calculateDiff(e,n,a=""){const i={added:[],removed:[],changed:[]},l=new Set(Object.keys(e)),c=new Set(Object.keys(n));for(const d of c){const f=a?`${a}.${d}`:d;l.has(d)?JSON.stringify(e[d])!==JSON.stringify(n[d])&&i.changed.push({path:f,oldValue:e[d],newValue:n[d]}):i.added.push(f)}for(const d of l){const f=a?`${a}.${d}`:d;c.has(d)||i.removed.push(f)}return i}logAction(e){if(!this.config.enabled)return;const n=this.actionHistory.findIndex(a=>a.id===e.id);n>=0?this.actionHistory[n]={...this.actionHistory[n],...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(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Action watcher error:",a)}})}getActionMetrics(){const e=this.actionHistory.filter(l=>l.status==="success"),n=this.actionHistory.filter(l=>l.status==="error"),a={};for(const l of this.actionHistory)a[l.type]=(a[l.type]||0)+1;const i=e.reduce((l,c)=>l+(c.duration||0),0);return{totalActions:this.actionHistory.length,successCount:e.length,errorCount:n.length,averageDuration:e.length>0?i/e.length:0,actionsByType:a}}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 n={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(n),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 n=0,a=0,i=0,l=0;const c={},d={};for(const g of e)g.decision==="cache_hit"?n++:g.decision==="cache_miss"?a++:g.decision==="skip_cache"?i++:g.decision==="invalidate"&&l++,c[g.reason]=(c[g.reason]||0)+1,g.context.componentId&&(d[g.context.componentId]=(d[g.context.componentId]||0)+1);const f=n+a+i;return{totalDecisions:e.length,cacheHits:n,cacheMisses:a,skipCacheCount:i,invalidateCount:l,byReason:c,byComponent:d,avgHitRate:f>0?n/f:0}}getRecentCacheDecisions(e=20,n){let a=[...this.cacheDecisions];return n&&(a=a.filter(i=>i.decision===n)),a.slice(-e)}clearCacheDecisionData(){this.cacheDecisions=[],this.cacheDecisionIdCounter=0}summarizePropsForLifecycle(e){if(!e||typeof e!="object")return e;const n={},a=["children","ref","key"];for(const[i,l]of Object.entries(e))if(!a.includes(i))if(l==null)n[i]=l;else if(Array.isArray(l))n[i]=`[Array(${l.length})]`;else if(typeof l=="object"){const c=Object.keys(l);c.length<=3?n[i]=`{${c.join(", ")}}`:n[i]=`{${c.slice(0,3).join(", ")}, ... +${c.length-3}}`}else typeof l=="string"&&l.length>50?n[i]=l.substring(0,50)+"...":typeof l=="function"?n[i]="[Function]":n[i]=l;return n}trackMount(e,n){if(!this.config.enabled)return;const a=this.summarizePropsForLifecycle(n.props),i={...n,props:a,id:e,mountTime:Date.now()};this.mountedComponents.set(e,i),this.mountWatchers.forEach(l=>{try{l({componentId:e,componentName:n.name,timestamp:i.mountTime})}catch(c){console.error("[G7DevTools] Mount watcher error:",c)}})}trackUnmount(e){if(!this.config.enabled)return;const n=this.mountedComponents.get(e),a=this.eventListeners.get(e)||[];a.length>0&&console.warn(`[G7DevTools] 컴포넌트 ${e} 언마운트 시 ${a.length}개 리스너 미정리`),n&&this.unmountWatchers.forEach(i=>{try{i({componentId:e,componentName:n.name,timestamp:Date.now(),orphanedListeners:a.length})}catch(l){console.error("[G7DevTools] Unmount watcher error:",l)}}),this.mountedComponents.delete(e)}trackListener(e,n,a){if(!this.config.enabled)return;const i=this.eventListeners.get(e)||[];i.push({type:n,target:a,addedAt:Date.now()}),this.eventListeners.set(e,i)}removeListener(e,n){if(!this.config.enabled)return;const a=this.eventListeners.get(e)||[],i=a.findIndex(l=>l.type===n);i>=0&&a.splice(i,1)}getMountedComponents(){return Array.from(this.mountedComponents.values())}getOrphanedListeners(){const e=[];for(const[n,a]of this.eventListeners)this.mountedComponents.has(n)||e.push(...a.map(i=>({...i,componentId:n})));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 n=this.renderCounts.get(e)||0;this.renderCounts.set(e,n+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 n=this.getOrphanedListeners().length;n>0&&e.push({type:"orphaned-listeners",message:`${n}개의 정리되지 않은 이벤트 리스너`,suggestion:"useEffect cleanup 또는 removeEventListener 확인",severity:n>10?"error":"warning"});const a=Array.from(this.renderCounts.entries()).filter(([,i])=>i>50);return a.length>0&&e.push({type:"excessive-renders",message:`${a.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,n=this.analyzeProfile(e);return console.log("[G7DevTools] 프로파일링 완료",n),n}analyzeProfile(e){const n=this.profilingData.filter(g=>g.type==="render"),a=this.profilingData.filter(g=>g.type==="binding"),i=this.profilingData.filter(g=>g.type==="action"),l={};for(const g of n)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 c=Object.entries(l).map(([g,m])=>({name:g,renderCount:m.count,avgDuration:m.durations.length>0?m.durations.reduce((y,S)=>y+S,0)/m.durations.length:0})).sort((g,m)=>m.renderCount-g.renderCount).slice(0,10),d={};for(const g of a)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:n.length,totalBindings:a.length,totalActions:i.length,slowestComponents:c,hotPaths:f}}}resetPerformanceStats(){this.renderCounts.clear(),this.bindingEvalCount=0,this.profilingData=[]}trackRequest(e,n,a){if(!this.config.enabled)return"";const i=this.generateId(),l=V_(e),c=G_(e);return this.activeRequests.set(i,{id:i,url:l,fullUrl:e,queryParams:c,method:n,startTime:Date.now(),status:"pending",requestBody:a?.requestBody?this.sanitizeObject(a.requestBody):void 0,dataSourceId:a?.dataSourceId}),this.isProfiling&&this.profilingData.push({type:"network",timestamp:performance.now()}),i}completeRequest(e,n,a){if(!this.config.enabled)return;const i=this.activeRequests.get(e);if(!i)return;const l={...i,status:n>=200&&n<300?"success":"error",statusCode:n,duration:Date.now()-i.startTime,endTime:Date.now(),response:this.sanitizeObject(a)};this.requestHistory.push(l),this.activeRequests.delete(e),this.requestHistory.length>this.config.maxHistorySize&&this.requestHistory.shift(),this.notifyRequestWatchers(l)}failRequest(e,n){if(!this.config.enabled)return;const a=this.activeRequests.get(e);if(!a)return;const i={...a,status:"error",error:n,duration:Date.now()-a.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(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Request watcher error:",a)}})}trackWebSocketConnection(e,n,a){this.config.enabled&&this.wsConnections.set(e,{id:e,url:n,state:a,connectedAt:a==="open"?Date.now():void 0})}trackWebSocketMessage(e,n,a,i){if(!this.config.enabled)return;const l={id:this.generateId(),connectionId:e,direction:n,type:a,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(n=>n.state==="open")?"connected":e.some(n=>n.state==="connecting")?"reconnecting":"disconnected"}watchWebSocketMessage(e){return this.wsMessageWatchers.add(e),()=>{this.wsMessageWatchers.delete(e)}}notifyWebSocketWatchers(e){this.wsMessageWatchers.forEach(n=>{try{n(e)}catch(a){console.error("[G7DevTools] WebSocket watcher error:",a)}})}trackIfCondition(e,n,a){if(!this.config.enabled)return;const i=this.ifConditions.get(e),l=i?.evaluatedValue;this.ifConditions.set(e,{id:e,expression:n,evaluatedValue:a,evaluationCount:(i?.evaluationCount||0)+1,lastEvaluated:Date.now()}),i&&l!==a&&this.notifyConditionWatchers({id:e,expression:n,oldValue:l,newValue:a,timestamp:Date.now()})}trackIteration(e,n){this.config.enabled&&this.iterations.set(e,{id:e,...n,lastRendered:Date.now()})}getIfConditions(){return Array.from(this.ifConditions.values())}getIterations(){return Array.from(this.iterations.values())}getScopeChain(e){const n=[],a=this.getState();return n.push({name:"_global",value:a._global,source:"global"}),n.push({name:"_local",value:a._local,source:"local"}),n.push({name:"_computed",value:a._computed,source:"computed"}),n}watchConditionChange(e){return this.conditionWatchers.add(e),()=>{this.conditionWatchers.delete(e)}}notifyConditionWatchers(e){this.conditionWatchers.forEach(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Condition watcher error:",a)}})}trackForm(e,n,a){this.config.enabled&&this.forms.set(e,{id:e,dataKey:n,inputs:a,trackedAt:Date.now()})}trackFormChange(e,n,a){if(!this.config.enabled)return;const i={formId:e,inputName:n,value:a,timestamp:Date.now()};this.notifyFormWatchers(i)}untrackForm(e){this.forms.delete(e)}getForms(){return Array.from(this.forms.values())}getFormState(e){const n=this.getState();return this.getNestedValue(n,e)||{}}getBindingPath(e,n){return`${e}.${n}`}watchFormChange(e){return this.formWatchers.add(e),()=>{this.formWatchers.delete(e)}}notifyFormWatchers(e){this.formWatchers.forEach(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Form watcher error:",a)}})}trackFormBindingIssue(e,n,a){if(!this.config.enabled)return;const i={id:`form-issue-${++this.formBindingIssueIdCounter}`,timestamp:Date.now(),type:e,severity:n,formId:a.formId,formDataKey:a.formDataKey,inputInfo:a.inputInfo,contextInfo:a.contextInfo,description:a.description,suggestion:a.suggestion,docLink:a.docLink};this.formBindingIssues.push(i),this.formBindingIssues.length>this.maxFormBindingIssues&&this.formBindingIssues.shift()}validateFormBinding(e,n,a,i){const l=a.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:n,inputInfo:{name:f.name,type:f.type},description:"Input에 name 속성이 없어 자동 바인딩이 동작하지 않습니다",suggestion:"Input에 name 속성을 추가하세요",docLink:"troubleshooting-components-form.md"})),n||(g.push("Form에 dataKey가 없습니다"),m=!1),{inputName:f.name||"(unnamed)",inputType:f.type,bindingPath:n&&f.name?`${n}.${f.name}`:"-",isValid:m,currentValue:f.value,issues:g}});if(n||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:n,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 c={formId:e,dataKey:n,timestamp:Date.now(),contextPropagation:i,inputBindings:l,isValid:l.every(f=>f.isValid)&&!!n&&!i.isContextBroken,issueCount:l.filter(f=>!f.isValid).length+(n?0:1)+(i.isContextBroken?1:0)},d=this.formBindingValidations.findIndex(f=>f.formId===e);return d>=0?this.formBindingValidations[d]=c:this.formBindingValidations.push(c),c}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},n={info:0,warning:0,error:0};for(const i of this.formBindingIssues)e[i.type]++,n[i.severity]++;const a=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:n,topIssues:a}}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,n,a,i,l,c,d){if(!this.config.enabled)return;const f=`computed-${e}-${c||"global"}`,g={id:f,name:e,expression:n,componentId:c,dependencies:a,currentValue:this.safeClone(i),lastComputedAt:Date.now(),computationTime:l,error:d};this.computedProperties.set(f,g)}trackComputedRecalc(e,n,a,i,l,c,d){if(!this.config.enabled)return;const f=`computed-${e}-${d||"global"}`,g=JSON.stringify(a)!==JSON.stringify(i),m={id:`recalc-${++this.computedRecalcIdCounter}`,computedId:f,computedName:e,timestamp:Date.now(),trigger:n,triggeredBy:c,previousValue:this.safeClone(a),newValue:this.safeClone(i),valueChanged:g,computationTime:l,cascadeCount:0};this.computedRecalcLogs.push(m),this.computedRecalcLogs.length>this.maxComputedRecalcLogs&&this.computedRecalcLogs.shift();const y=this.computedProperties.get(f);y&&(y.currentValue=this.safeClone(i),y.lastComputedAt=Date.now(),y.computationTime=l)}analyzeComputedDependencyChain(e,n){const a=new Set,i=[];let l=!1,c,d=0;const f=(m,y)=>{if(d=Math.max(d,y),a.has(m))return l=!0,c=[...i,m],{name:m,type:"computed",children:[],depth:y};a.add(m),i.push(m);const S=this.computedProperties.get(`computed-${m}-${n||"global"}`),v=[];if(S)for(const _ of S.dependencies)_.type==="computed"?v.push(f(_.path,y+1)):v.push({name:_.path,type:_.type,children:[],depth:y+1});return i.pop(),a.delete(m),{name:m,type:"computed",children:v,depth:y}},g=f(e,0);return{root:e,tree:g,hasCycle:l,cyclePath:c,maxDepth:d}}getComputedDependencyTrackingInfo(){const e=Array.from(this.computedProperties.values()),n=this.getComputedDependencyStats(),a=[];for(const i of e){const l=this.analyzeComputedDependencyChain(i.name,i.componentId);a.push(l)}return{properties:e,recalcLogs:[...this.computedRecalcLogs],dependencyChains:a,stats:n,timestamp:Date.now()}}getComputedDependencyStats(){const e={"state-change":0,"datasource-update":0,"dependency-change":0,manual:0,initial:0},n={},a={};let i=0,l=0;for(const g of this.computedRecalcLogs)e[g.trigger]++,g.valueChanged||l++,n[g.computedName]=(n[g.computedName]||0)+1,a[g.computedName]||(a[g.computedName]=[]),a[g.computedName].push(g.computationTime),i+=g.computationTime;const c=Object.entries(n).sort((g,m)=>m[1]-g[1]).slice(0,5).map(([g,m])=>({name:g,count:m})),d=Object.entries(a).map(([g,m])=>({name:g,avgTime:m.reduce((y,S)=>y+S,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:c,slowestComputed:d,cycleDetectionCount:f,byTrigger:e}}clearComputedTracking(){this.computedProperties.clear(),this.computedRecalcLogs=[],this.computedRecalcIdCounter=0}trackModalOpen(e){if(!this.config.enabled)return;const n={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,n),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,n){if(!this.config.enabled)return;const a=this.modalStates.get(e);a&&(a.closedAt=Date.now(),n&&(a.currentState={...n}),this.detectStateLeakage(a))}validateModalDefinitionExists(e,n){const a=this.currentLayout;if(!a?.layoutJson)return;const i=a.layoutJson.modals;if(!i){this.recordModalStateIssue({type:"missing-definition",modalId:e,modalName:n,severity:"error",description:`모달 "${e}"이(가) modalStack에 추가되었으나, 현재 레이아웃에 modals 섹션이 없습니다. 레이아웃 경로: ${a.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:n,severity:"error",description:`모달 "${e}"이(가) modalStack에 추가되었으나, 렌더링된 레이아웃의 modals 섹션에 해당 ID의 정의가 없습니다. partial 로딩 실패, 레이아웃 병합 문제, extends 상속 누락 등을 확인하세요. 레이아웃 경로: ${a.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 n=this.modalStates.get(e.modalId);if(!n)return;n.stateChangeCount++,n.currentState[e.stateKey]=e.newValue;const a=this.checkIsolationViolation(n,e.stateKey),i={id:`modal-change-${++this.modalStateChangeLogIdCounter}`,modalId:e.modalId,modalName:n.modalName,timestamp:Date.now(),stateKey:e.stateKey,previousValue:e.previousValue,newValue:e.newValue,changeSource:e.changeSource||"user-action",violatesIsolation:a};this.modalStateChangeLogs.push(i),this.modalStateChangeLogs.length>this.maxModalStateChangeLogs&&this.modalStateChangeLogs.shift(),a&&this.recordModalStateIssue({type:"isolation-violation",modalId:e.modalId,modalName:n.modalName,severity:"warning",description:`모달 '${n.modalName}'에서 격리된 상태 키 '${e.stateKey}'가 변경됨`,affectedStateKeys:[e.stateKey]})}detectStateLeakage(e){if(e.scopeType==="isolated")for(const n of e.isolatedStateKeys){const a=e.initialState[n],i=e.currentState[n];if(a!==i&&e.parentModalId){const l=this.modalStates.get(e.parentModalId);l&&l.currentState.hasOwnProperty(n)&&this.recordModalStateIssue({type:"state-leakage",modalId:e.modalId,modalName:e.modalName,severity:"error",description:`모달 닫힘 후 상태 '${n}'가 부모 모달로 유출될 수 있음`,affectedStateKeys:[n],leakedValue:i,expectedValue:a})}}}checkIsolationViolation(e,n){return e.scopeType==="isolated",!1}recordModalStateIssue(e){const n={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(n),this.modalStateIssues.length>this.maxModalStateIssues&&this.modalStateIssues.shift()}getModalStateScopeTrackingInfo(){const e=Array.from(this.modalStates.values()),n=this.getModalStateScopeStats();return{modals:e,issues:[...this.modalStateIssues],relations:[...this.modalStateRelations],changeLogs:[...this.modalStateChangeLogs],stats:n,timestamp:Date.now()}}getModalStateScopeStats(){const e=Array.from(this.modalStates.values()),n={warning:0,error:0},a={"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)n[l.severity]++,a[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:n,issuesByType:a,byScope:i,leakageDetectionCount:a["state-leakage"],cleanupFailureCount:a["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 n={...e,id:`named_action_ref_${++this.namedActionRefIdCounter}`};this.namedActionRefLogs.push(n),this.namedActionRefLogs.length>this.maxNamedActionRefLogs&&(this.namedActionRefLogs=this.namedActionRefLogs.slice(-this.maxNamedActionRefLogs))}getNamedActionTrackingInfo(){const e={};for(const a of this.namedActionRefLogs)e[a.actionRefName]=(e[a.actionRefName]||0)+1;const n=Object.keys(this.namedActionDefinitions).filter(a=>!e[a]);return{definitions:this.namedActionDefinitions,refLogs:[...this.namedActionRefLogs],stats:{totalDefinitions:Object.keys(this.namedActionDefinitions).length,totalRefs:this.namedActionRefLogs.length,refCountByName:e,unusedDefinitions:n},timestamp:Date.now()}}clearNamedActionTracking(){this.namedActionDefinitions={},this.namedActionRefLogs=[],this.namedActionRefIdCounter=0}trackExpressionEval(e){if(!this.config.enabled)return;const n={...e,id:`expr-${++this.expressionIdCounter}`,timestamp:Date.now(),warning:this.detectExpressionWarning(e)};this.expressionHistory.push(n),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(n)}detectExpressionWarning(e){const{expression:n,result:a,resultType:i,method:l,duration:c}=e;if(i==="undefined"&&!n.includes("??")&&!n.includes("||")&&/^[a-zA-Z_$][a-zA-Z0-9_$.]*$/.test(n.replace(/{{|}}/g,"").trim()))return{type:"undefined-result",message:"표현식 결과가 undefined입니다",suggestion:`데이터가 로드되었는지 확인하거나 fallback 값을 추가하세요: ${n} ?? ''`};if(i==="null")return{type:"null-result",message:"표현식 결과가 null입니다",suggestion:`nullish coalescing 연산자를 사용하세요: ${n} ?? ''`};if(l==="resolveBindings"&&i==="string"){const d=String(a);if(d.includes("[object Object]")||/^\[.*\]$/.test(d))return{type:"array-to-string",message:"배열/객체가 문자열로 변환되었습니다",suggestion:"evaluateExpression()을 사용하여 원본 타입을 유지하세요"}}if(l==="resolveBindings"&&i==="string"&&String(a).includes("[object Object]"))return{type:"object-to-string",message:"객체가 [object Object]로 변환되었습니다",suggestion:"evaluateExpression()을 사용하거나 특정 속성에 접근하세요"};if(i==="undefined"&&n.includes(".")&&!n.includes("?.")){const d=n.replace(/{{|}}/g,"").trim().split(".");if(d.length>=2)return{type:"missing-optional-chain",message:"Optional chaining(?.) 누락 가능성",suggestion:`안전한 접근을 위해 ?. 사용을 고려하세요: ${d.join("?.")}`}}if((n.includes("{{item.")||n.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(c&&c>10)return{type:"slow-evaluation",message:`표현식 평가에 ${c.toFixed(2)}ms 소요됨`,suggestion:"복잡한 표현식을 단순화하거나 computed 값으로 분리하세요"}}getExpressions(){return[...this.expressionHistory]}getExpressionWarnings(){return this.expressionHistory.filter(e=>e.warning!=null)}searchExpressions(e){const n=e.toLowerCase();return this.expressionHistory.filter(a=>a.expression.toLowerCase().includes(n)||a.componentName?.toLowerCase().includes(n)||a.propName?.toLowerCase().includes(n))}getExpressionStats(){const e=this.expressionHistory,n=new Set(e.map(f=>f.expression)),a=e.filter(f=>f.warning!=null),i=e.filter(f=>f.fromCache),l=e.filter(f=>f.duration!=null).map(f=>f.duration),c={};for(const f of e)c[f.resultType]=(c[f.resultType]||0)+1;const d={};for(const f of a)f.warning&&(d[f.warning.type]=(d[f.warning.type]||0)+1);return{totalEvaluations:e.length,uniqueExpressions:n.size,warningCount:a.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:c,byWarning:d}}clearExpressions(){this.expressionHistory=[],this.expressionIdCounter=0}watchExpressions(e){return this.expressionWatchers.add(e),()=>{this.expressionWatchers.delete(e)}}notifyExpressionWatchers(e){this.expressionWatchers.forEach(n=>{try{n(e)}catch(a){console.error("[G7DevTools] Expression watcher error:",a)}})}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,n=new WeakSet){if(e===null||typeof e!="object")return e;if(n.has(e))return"[Circular]";if(n.add(e),Array.isArray(e))return e.map(i=>this.sanitizeObject(i,n));const a={};for(const i of Object.keys(e))try{a[i]=this.sanitizeObject(e[i],n)}catch{a[i]="[Unable to serialize]"}return a}getNestedValue(e,n){if(!n)return e;const a=n.split(".");let i=e;for(const l of a){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 n=[...this.stateHistory].reverse().find(a=>a.timestamp<=e);if(n)return{_global:n.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,n,a){if(!this.config.enabled)return;const i=a.map(c=>{if(typeof c=="string")return c;try{return JSON.stringify(c)}catch{return String(c)}}).join(" "),l={id:`log-${++this.logIdCounter}`,level:e,prefix:n,message:i,args:this.sanitizeObject(a),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 n={id:`debounce-action-${++this.debounceActionIdCounter}`,...e,timestamp:Date.now()};this.debounceActionHistory.push(n),this.debounceActionHistory.length>100&&this.debounceActionHistory.shift()}trackDataSourceUpdate(e){if(!this.config.enabled)return;const n={id:`ds-update-${++this.dataSourceUpdateIdCounter}`,...e};this.dataSourceUpdateHistory.push(n),this.dataSourceUpdateHistory.length>100&&this.dataSourceUpdateHistory.shift()}getDebounceActionHistory(e){let n=[...this.debounceActionHistory];return e?.handler&&(n=n.filter(a=>a.handler.includes(e.handler))),e?.status&&(n=n.filter(a=>a.status===e.status)),e?.limit&&(n=n.slice(-e.limit)),n}getDataSourceUpdateHistory(e){let n=[...this.dataSourceUpdateHistory];return e?.dataSourceId&&(n=n.filter(a=>a.dataSourceId===e.dataSourceId)),e?.updateType&&(n=n.filter(a=>a.updateType===e.updateType)),e?.limit&&(n=n.slice(-e.limit)),n}getLogs(e){let n=[...this.logHistory];if(e?.level){const a=Array.isArray(e.level)?e.level:[e.level];n=n.filter(i=>a.includes(i.level))}if(e?.prefix){const a=e.prefix.toLowerCase();n=n.filter(i=>i.prefix.toLowerCase().includes(a))}if(e?.search){const a=e.search.toLowerCase();n=n.filter(i=>i.message.toLowerCase().includes(a))}return e?.since&&(n=n.filter(a=>a.timestamp>=e.since)),e?.limit&&(n=n.slice(-e.limit)),n}getLogStats(){const n=Date.now()-6e4,a={log:0,warn:0,error:0,debug:0,info:0},i={};let l=0,c=0;for(const d of this.logHistory)a[d.level]++,i[d.prefix]=(i[d.prefix]||0)+1,d.timestamp>=n&&(d.level==="error"&&l++,d.level==="warn"&&c++);return{totalLogs:this.logHistory.length,byLevel:a,byPrefix:i,recentErrors:l,recentWarnings:c}}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 n=this.dataSources.get(e);n&&this.dataSources.set(e,{...n,status:"loading"})}trackDataSourceLoaded(e,n,a){if(!this.config.enabled)return;const i=this.dataSources.get(e);if(!i)return;let l,c,d=a;n&&(Array.isArray(n)?(l=n.length,c=n.length>0&&typeof n[0]=="object"?Object.keys(n[0]):void 0):typeof n=="object"&&(Array.isArray(n.data)?(d=d||"data",l=n.data.length,c=n.data.length>0&&typeof n.data[0]=="object"?Object.keys(n.data[0]):void 0):Array.isArray(n.items)?(d=d||"items",l=n.items.length,c=n.items.length>0&&typeof n.items[0]=="object"?Object.keys(n.items[0]):void 0):c=Object.keys(n))),this.dataSources.set(e,{...i,status:"loaded",dataPath:d,itemCount:l,keys:c,lastLoadedAt:Date.now(),error:void 0})}trackDataSourceError(e,n){if(!this.config.enabled)return;const a=this.dataSources.get(e);a&&this.dataSources.set(e,{...a,status:"error",error:n,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 n=this.dataPathTransforms.find(a=>a.dataSourceId===e.dataSourceId);n||(n={dataSourceId:e.dataSourceId,timestamp:Date.now(),transformSteps:[],warnings:[]},this.dataPathTransforms.push(n),this.dataPathTransforms.length>this.maxDataPathTransforms&&this.dataPathTransforms.shift()),n.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&&n.warnings.push(e.warning)}setDataPathFinalBinding(e,n){if(!this.config.enabled)return;const a=this.dataPathTransforms.find(i=>i.dataSourceId===e);a&&(a.finalBinding={expression:n.expression,resolvedPath:n.resolvedPath,value:this.safeClone(n.value)})}getDataPathTransformTrackingInfo(){const e=this.getDataPathTransformStats();return{transforms:[...this.dataPathTransforms],stats:e,timestamp:Date.now()}}getDataPathTransformStats(){const e=this.dataPathTransforms,n={};let a=0;const i={};for(const c of e){n[c.dataSourceId]=(n[c.dataSourceId]||0)+1,a+=c.warnings.length;for(const d of c.warnings)i[d]=(i[d]||0)+1}const l=Object.entries(i).map(([c,d])=>({warning:c,count:d})).sort((c,d)=>d.count-c.count).slice(0,10);return{totalTransforms:e.length,byDataSource:n,warningsCount:a,commonWarnings:l}}getDataPathTransformForDataSource(e){return this.dataPathTransforms.find(n=>n.dataSourceId===e)}clearDataPathTransforms(){this.dataPathTransforms=[]}trackNestedContext(e){if(!this.config.enabled)return"";const n=`nested-${++this.nestedContextIdCounter}`,a=[...new Set([...e.parentContext.available,...e.ownContext.added])],i={...e.parentContext.values,...e.ownContext.values},l={id:n,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:a,values:this.safeClone(i)},accessAttempts:[],depth:e.depth,parentId:e.parentId};return this.nestedContexts.push(l),this.nestedContexts.length>this.maxNestedContexts&&this.nestedContexts.shift(),n}trackNestedContextAccess(e,n){if(!this.config.enabled)return;const a=this.nestedContexts.find(i=>i.id===e);a&&a.accessAttempts.push({path:n.path,found:n.found,value:n.found?this.safeClone(n.value):void 0,error:n.error})}getNestedContextTrackingInfo(){const e=this.getNestedContextStats();return{contexts:[...this.nestedContexts],stats:e,timestamp:Date.now()}}getNestedContextStats(){const e=this.nestedContexts,n={expandChildren:0,cellChildren:0,iteration:0,modal:0,slot:0};let a=0,i=0;const l={};for(const d of e){n[d.componentType]++,d.depth>a&&(a=d.depth);for(const f of d.accessAttempts)f.found||(i++,l[f.path]=(l[f.path]||0)+1)}const c=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:n,maxDepth:a,failedAccessCount:i,commonFailedPaths:c}}getNestedContextForComponent(e){return this.nestedContexts.find(n=>n.componentId===e)}clearNestedContexts(){this.nestedContexts=[],this.nestedContextIdCounter=0}trackHandlerRegistration(e,n="custom",a,i){this.isEnabled&&this.handlers.set(e,{name:e,category:n,description:a,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(n=>n.category===e)}clearHandlers(){this.handlers.clear()}trackEventSubscribe(e){if(!this.isEnabled)return;const n=this.componentEventSubscriptions.get(e),a=Date.now();n?(n.subscriberCount++,n.lastSubscribedAt=a):this.componentEventSubscriptions.set(e,{eventName:e,subscriberCount:1,firstSubscribedAt:a,lastSubscribedAt:a})}trackEventUnsubscribe(e){if(!this.isEnabled)return;const n=this.componentEventSubscriptions.get(e);n&&(n.subscriberCount--,n.subscriberCount<=0&&this.componentEventSubscriptions.delete(e))}trackEventEmit(e,n,a,i,l){if(!this.isEnabled)return;const c={id:`evt_${++this.componentEventIdCounter}`,eventName:e,data:this.sanitizeForLogging(n),timestamp:Date.now(),listenerCount:a,results:i?this.sanitizeForLogging(i):void 0,hasError:!!l,errorMessage:l?.message};this.componentEventEmitHistory.push(c),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((n,a)=>n+a.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,n,a,i){if(!this.config.enabled)return"";const l=`setState_${++this.stateRenderingIdCounter}`;this.currentStateChangeContext={setStateId:l,startTime:performance.now(),changedPath:e,trigger:i||{},renderedComponents:[]};const c={id:`sr_${this.stateRenderingIdCounter}`,setStateId:l,statePath:e,oldValue:this.sanitizeForLogging(n),newValue:this.sanitizeForLogging(a),timestamp:Date.now(),triggeredBy:i||{},renderedComponents:[],totalRenderDuration:0,affectedBindingsCount:0};return this.stateRenderingLogs.push(c),this.stateRenderingLogs.length>this.maxStateRenderingLogs&&this.stateRenderingLogs.shift(),l}trackComponentRender(e,n,a,i=[],l=[],c){if(!this.config.enabled)return;const d=this.componentRenderCounts.get(n)||0;this.componentRenderCounts.set(n,d+1);for(const f of i)this.stateToComponentMap.has(f)||this.stateToComponentMap.set(f,new Set),this.stateToComponentMap.get(f).add(n);if(this.currentStateChangeContext){const f={componentId:e,componentName:n,renderDuration:a,accessedStatePaths:i,evaluatedBindings:l,renderOrder:this.currentStateChangeContext.renderedComponents.length,parentId:c};this.currentStateChangeContext.renderedComponents.push(f)}this.trackRender(n)}completeStateChange(e){if(!this.config.enabled||!this.currentStateChangeContext||this.currentStateChangeContext.setStateId!==e)return;const n=this.currentStateChangeContext,i=performance.now()-n.startTime,l=this.stateRenderingLogs.findIndex(c=>c.setStateId===e);if(l>=0){const c=this.stateRenderingLogs[l];c.renderedComponents=n.renderedComponents,c.totalRenderDuration=i,c.affectedBindingsCount=n.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,n=Object.fromEntries(this.componentRenderCounts),a={};for(const[i,l]of this.stateToComponentMap)a[i]=Array.from(l);return{logs:e,componentRenderCounts:n,stateToComponentMap:a,stats:this.calculateStateRenderingStats()}}calculateStateRenderingStats(){const e=this.stateRenderingLogs;if(e.length===0)return{totalStateChanges:0,totalRenders:0,avgRenderDuration:0,avgComponentsPerChange:0,topRenderedComponents:[],topInfluentialPaths:[]};const n=e.reduce((d,f)=>d+f.renderedComponents.length,0),a=e.reduce((d,f)=>d+f.totalRenderDuration,0)/e.length,i=n/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})),c=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:n,avgRenderDuration:a,avgComponentsPerChange:i,topRenderedComponents:l,topInfluentialPaths:c}}getComponentsAffectedByState(e){const n=this.stateToComponentMap.get(e);return n?Array.from(n):[]}getComponentRenderHistory(e){return this.stateRenderingLogs.filter(n=>n.renderedComponents.some(a=>a.componentName===e))}clearStateRenderingLogs(){this.stateRenderingLogs=[],this.componentRenderCounts.clear(),this.stateToComponentMap.clear(),this.currentStateChangeContext=null,this.stateRenderingIdCounter=0}trackComponentStateSource(e,n,a,i){this.config.enabled&&this.componentStateSources.set(e,{componentId:e,componentName:n,stateSource:a,stateProvider:i})}trackDynamicState(e,n){this.config.enabled&&this.dynamicStates.set(e,n)}trackContextFlow(e,n,a,i,l,c){if(!this.config.enabled)return;const d={component:n,componentId:e,contextReceived:a,passedToChildren:i,usedInRender:l};if(this.contextFlowNodes.set(e,d),c){const f=this.contextFlowNodes.get(c);f&&(f.children||(f.children=[]),f.children.push(d))}}getStateHierarchyInfo(e=!0){const n=this.buildStateHierarchyLayers(),a=this.detectStateConflicts(n),i=Array.from(this.componentStateSources.values());return{layers:e?n.map(c=>({...c,values:this.summarizeValues(c.values,2)})):n,conflicts:a,componentStateSources:i,timestamp:Date.now()}}summarizeValues(e,n,a=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(a>=n){if(Array.isArray(e))return`[Array(${e.length})]`;const c=Object.keys(e);return`{${c.slice(0,5).join(", ")}${c.length>5?`, ... +${c.length-5}`:""}}`}if(Array.isArray(e))return e.length<=3?e.map(c=>this.summarizeValues(c,n,a+1)):{__type:"array",__length:e.length,__preview:e.slice(0,3).map(c=>this.summarizeValues(c,n,a+1))};const i={},l=Object.keys(e);for(const c of l)i[c]=this.summarizeValues(e[c],n,a+1);return i}buildStateHierarchyLayers(){const e=[];try{const a=window.G7Core?.state?.get?.();if(!a)return e;a._local&&e.push({name:"Global _local",type:"global",path:"_local",values:a._local,priority:1}),a._global&&e.push({name:"Global _global",type:"global",path:"_global",values:a._global,priority:1});for(const[l,c]of this.dynamicStates)c&&Object.keys(c).length>0&&e.push({name:`DynamicState (${l})`,type:"dynamicState",componentId:l,values:c,priority:2});const i=this.computeEffectiveState(a._local||{});e.push({name:"Effective _local (merged)",type:"effective",values:i,priority:3})}catch(n){console.warn("[G7DevTools] 상태 계층 빌드 실패:",n)}return e}computeEffectiveState(e){const n={...e};for(const[,a]of this.dynamicStates)a._local&&Object.assign(n,a._local);return n}detectStateConflicts(e){const n=[],a=e.find(l=>l.type==="global"&&l.path==="_local");if(!a)return n;const i=e.filter(l=>l.type==="dynamicState");for(const l of i){const c=l.values._local||l.values;for(const[d,f]of Object.entries(c)){const g=a.values[d];if(JSON.stringify(g)!==JSON.stringify(f)){const m=[],y=[];for(const S of this.componentStateSources.values())S.stateSource.local.some(_=>_===`_local.${d}`||_===d)&&(S.stateProvider.type==="dynamicState"?m.push(S.componentName):S.stateProvider.type==="globalState"&&y.push(S.componentName));n.push({path:`_local.${d}`,globalValue:g,dynamicStateValue:f,effectiveValue:f,usedBy:m,notUsedBy:y,severity:y.length>0?"warning":"info",description:y.length>0?`${y.join(", ")}은(는) globalState._local을 읽어 dynamicState 값을 사용하지 못함`:"dynamicState 값이 globalState와 다르지만 모든 컴포넌트가 dynamicState를 사용"})}}}return n}getContextFlowInfo(){const e=[],n=new Set(this.contextFlowNodes.keys());for(const a of this.contextFlowNodes.values())if(a.children)for(const i of a.children)n.delete(i.componentId);for(const a of n){const i=this.contextFlowNodes.get(a);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,n,a,i){if(!this.config.enabled)return;const l=this.analyzeTailwindClasses(a),c={componentId:e,componentName:n,classes:a,computedStyles:i,tailwindAnalysis:l};this.componentStyles.set(e,c),this.detectStyleIssues(c)}analyzeTailwindClasses(e){const n=[],a=[],i=[],l=[],c=["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:")&&n.push(f);for(const g of c)if(f.startsWith(g)){a.push(f);break}for(const g of d)if(g.test(f)){i.push(f);break}}return{usedClasses:l,darkClasses:n,responsiveClasses:a,dynamicClasses:i}}detectStyleIssues(e){const{componentId:n,componentName:a,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:n,componentName:a,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 c=l.usedClasses.filter(f=>f.startsWith("bg-")&&!f.startsWith("dark:")),d=l.darkClasses.filter(f=>f.includes("bg-"));c.length>0&&d.length===0&&this.addStyleIssue({id:this.generateId(),type:"dark-mode-missing",componentId:n,componentName:a,property:"background-color",currentValue:c.join(", "),expectedValue:"dark:bg-* 클래스 필요",severity:"info",description:"다크 모드 배경색 클래스가 누락되었습니다.",suggestion:`${c[0]}에 대응하는 dark: 클래스를 추가하세요.`}),l.dynamicClasses.length>0&&this.addStyleIssue({id:this.generateId(),type:"tailwind-purging",componentId:n,componentName:a,property:"class",currentValue:l.dynamicClasses.join(", "),severity:"info",description:"동적으로 생성된 Tailwind 클래스가 있습니다.",suggestion:"tailwind.config.js의 safelist에 추가하거나 전체 클래스명을 상수로 정의하세요."})}addStyleIssue(e){this.styleIssues.some(a=>a.componentId===e.componentId&&a.type===e.type&&a.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(n=>n.type==="invisible-element").length,tailwindIssueCount:this.styleIssues.filter(n=>n.type==="tailwind-purging").length,darkModeIssueCount:this.styleIssues.filter(n=>n.type==="dark-mode-missing").length},timestamp:Date.now()}}clearStyleValidationData(){this.styleIssues=[],this.componentStyles.clear()}trackAuthEvent(e,n,a,i){if(!this.config.enabled)return;const l={id:`auth_${++this.authEventIdCounter}`,type:e,timestamp:Date.now(),success:n,error:a,details:i};this.authEvents.push(l),this.authEvents.length>this.maxAuthEventHistory&&(this.authEvents=this.authEvents.slice(-this.maxAuthEventHistory))}trackAuthHeader(e,n,a,i,l){if(!this.config.enabled)return;const c={url:e,hasAuthHeader:n,headerType:a,tokenValid:i??!1,responseStatus:l,timestamp:Date.now()};this.authHeaderHistory.push(c),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,n=e?.api;let a=e?.auth;!a&&e?.AuthManager?.getInstance&&(a=e.AuthManager.getInstance());const i=n?.getToken?.()||a?.getAccessToken?.()||localStorage.getItem("auth_token")||localStorage.getItem("access_token"),l=a?.getRefreshToken?.()||localStorage.getItem("refresh_token");let c="unknown",d=a?.getUser?.();if(d&&(c="AuthManager"),!d){const v=e?.state?.get?.();d=v?._global?.user||v?._global?.currentUser||v?.user||v?.currentUser,d&&(c="G7Core.state")}const f=a?.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 y;i&&typeof i=="string"&&i.length>20?y=`${i.substring(0,10)}...${i.substring(i.length-6)}`:i&&(y="***");const S=d?{id:d.id,email:d.email,name:d.name,roles:d.roles?.map(v=>typeof v=="string"?{name:v}:{id:v.id,name:v.name,guard_name:v.guard_name}),permissions:d.permissions?.map(v=>typeof v=="string"?{name:v}:{id:v.id,name:v.name,guard_name:v.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:S,tokens:{hasAccessToken:!!i,hasRefreshToken:!!l,storage:g,accessTokenPreview:y},lastActivity:Date.now(),source:c}}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(n=>n.type==="login").length,successfulLogins:e.filter(n=>n.type==="login"&&n.success).length,failedLogins:e.filter(n=>n.type==="login"&&!n.success).length,tokenRefreshes:e.filter(n=>n.type==="token-refresh").length,unauthorizedResponses:e.filter(n=>n.type==="api-unauthorized").length},timestamp:Date.now()}}clearAuthData(){this.authEvents=[],this.authHeaderHistory=[],this.authEventIdCounter=0}trackLayoutLoad(e,n,a,i="api"){if(!this.config.enabled)return;const l=Date.now();this.currentLayout={layoutPath:e,templateId:n,layoutJson:this.sanitizeObject(a),loadedAt:l,version:a.version,layoutName:a.layout_name,source:i};const c={id:`layout-${++this.layoutIdCounter}`,layoutPath:e,templateId:n,loadedAt:l,source:i,version:a.version};this.layoutHistory.push(c),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 n=`exec_${++this.executionIdCounter}_${Date.now()}`,a={handlerName:e,executionId:n,startTime:Date.now(),stateChanges:[],dataSourceChanges:[],alerts:[]};if(this.executionDetails.set(n,a),this.executionDetails.size>this.maxExecutionDetails){const i=Array.from(this.executionDetails.keys());i.slice(0,i.length-this.maxExecutionDetails).forEach(c=>this.executionDetails.delete(c))}return n}endHandlerExecution(e,n,a,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=n,l.exitLocation=a,l.exitDescription=i;const c=this.changeExpectations.get(e);c&&(l.expectedChanges=c,this.checkExpectations(e,l,c),this.changeExpectations.delete(e)),n==="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"}),(n==="early-return-condition"||n==="early-return-validation")&&this.addChangeAlert(e,{type:"early-return-detected",severity:"info",message:`핸들러 "${l.handlerName}"이(가) early return으로 종료됨`,description:i||`종료 위치: ${a||"알 수 없음"}`,handlerName:l.handlerName,suggestion:n==="early-return-validation"?"검증 실패로 인한 early return입니다. 입력 데이터를 확인하세요.":"조건부 early return입니다. 조건문의 평가 결과를 확인하세요."})}recordExitReason(e,n,a,i){if(!this.config.enabled||!e)return;const l=this.executionDetails.get(e);l&&(l.exitReason=n,l.exitLocation=a,l.exitDescription=i)}recordStateChange(e,n,a,i,l){if(!this.config.enabled)return;const c={id:`sc_${++this.stateChangeIdCounter}`,path:n,changeType:a,oldValue:this.safeClone(i),newValue:this.safeClone(l),timestamp:Date.now(),comparison:this.compareValues(i,l),executionId:e};if(this.stateChangeHistory.push(c),e){const d=this.executionDetails.get(e);d&&d.stateChanges.push(c)}this.stateChangeHistory.length>this.maxStateChangeHistory&&this.stateChangeHistory.splice(0,this.stateChangeHistory.length-this.maxStateChangeHistory),c.comparison.isDeepEqual&&typeof i=="object"&&i!==null&&this.addChangeAlert(e||"",{type:"object-reference-same",severity:"warning",message:`상태 "${n}"가 변경되었으나 값이 동일함`,description:"객체 참조가 동일하거나 깊은 비교 결과 변경이 없습니다. 변경 감지가 실패할 수 있습니다.",handlerName:e&&this.executionDetails.get(e)?.handlerName||"unknown",statePath:n,suggestion:"불변성을 유지하여 새 객체를 생성하세요. 예: { ...oldObject, newField: value }",docLink:"troubleshooting-state.md#object-mutation"})}recordDataSourceChange(e,n,a,i,l){if(!this.config.enabled)return;const c={dataSourceId:n,changeType:a,timestamp:Date.now(),previousStatus:i,newStatus:l,executionId:e};if(this.dataSourceChangeHistory.push(c),e){const d=this.executionDetails.get(e);d&&d.dataSourceChanges.push(c)}this.dataSourceChangeHistory.length>this.maxStateChangeHistory&&this.dataSourceChangeHistory.splice(0,this.dataSourceChangeHistory.length-this.maxStateChangeHistory)}expectChange(e,n,a){if(!this.config.enabled||!e)return;const i=this.executionDetails.get(e);if(!i)return;const l={expectedStatePaths:n,expectedDataSources:a,setAt:Date.now(),source:i.handlerName};this.changeExpectations.set(e,l)}checkExpectations(e,n,a){const i=new Set(n.stateChanges.map(c=>c.path)),l=new Set(n.dataSourceChanges.map(c=>c.dataSourceId));for(const c of a.expectedStatePaths)i.has(c)||this.addChangeAlert(e,{type:"expected-not-fulfilled",severity:"error",message:`기대한 상태 변경 "${c}"가 발생하지 않음`,description:`핸들러 "${n.handlerName}"이(가) "${c}" 변경을 예고했지만 실제로 변경되지 않았습니다.`,handlerName:n.handlerName,statePath:c,suggestion:"핸들러 내부 로직을 확인하세요. early return이나 조건부 분기로 인해 변경이 생략되었을 수 있습니다.",docLink:"troubleshooting-state.md"});for(const c of a.expectedDataSources)l.has(c)||this.addChangeAlert(e,{type:"expected-not-fulfilled",severity:"error",message:`기대한 데이터소스 갱신 "${c}"가 발생하지 않음`,description:`핸들러 "${n.handlerName}"이(가) "${c}" 갱신을 예고했지만 실제로 갱신되지 않았습니다.`,handlerName:n.handlerName,dataSourceId:c,suggestion:"refetchDataSource 호출이 실행되었는지 확인하세요.",docLink:"data-sources.md"})}addChangeAlert(e,n){const a={...n,id:`alert_${++this.alertIdCounter}`,timestamp:Date.now()};if(this.changeAlerts.push(a),e){const i=this.executionDetails.get(e);i&&i.alerts.push(a)}this.changeAlerts.length>this.maxChangeAlerts&&this.changeAlerts.splice(0,this.changeAlerts.length-this.maxChangeAlerts)}compareValues(e,n){const a=this.getValueType(e),i=this.getValueType(n),l=a!==i;let c=!1,d;return!l&&(a==="object"||a==="array")?(c=this.deepEqual(e,n),!c&&a==="object"&&(d=this.getChangedKeys(e,n))):c=e===n,{typeChanged:l,oldType:a,newType:i,isDeepEqual:c,changedKeys:d}}getValueType(e){return e===null?"null":e===void 0?"undefined":Array.isArray(e)?"array":typeof e}deepEqual(e,n){if(e===n)return!0;if(typeof e!=typeof n)return!1;if(e===null||n===null||typeof e!="object")return e===n;if(Array.isArray(e)!==Array.isArray(n))return!1;const a=Object.keys(e),i=Object.keys(n);if(a.length!==i.length)return!1;for(const l of a)if(!i.includes(l)||!this.deepEqual(e[l],n[l]))return!1;return!0}getChangedKeys(e,n){const a=[],i=new Set([...Object.keys(e),...Object.keys(n)]);for(const l of i)this.deepEqual(e[l],n[l])||a.push(l);return a}getChangeDetectionInfo(){const e=Array.from(this.executionDetails.values()),n={totalExecutions:e.length,executionsWithStateChange:e.filter(a=>a.stateChanges.length>0).length,executionsWithoutStateChange:e.filter(a=>a.stateChanges.length===0&&a.exitReason==="normal").length,earlyReturnCount:e.filter(a=>a.exitReason==="early-return-condition"||a.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:n,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 n of this.changeAlerts)e[n.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,n){let a=[...this.changeAlerts];return n&&(a=a.filter(i=>i.severity===n)),a.slice(-e)}getHandlerExecutions(e,n=10){return Array.from(this.executionDetails.values()).filter(i=>i.handlerName===e).slice(-n)}findExecutionInStack(e){return this.sequenceExecutionStack.find(n=>n.sequenceId===e)}startSequenceExecution(e){if(!this.config.enabled)return"";const n=`seq_${++this.sequenceIdCounter}_${Date.now()}`,a={sequenceId:n,startTime:Date.now(),totalDuration:0,trigger:e,actions:[],status:"running"};return this.sequenceExecutionStack.push(a),n}captureSequenceActionBefore(e,n,a,i,l){if(!this.config.enabled)return;const c=this.findExecutionInStack(e);if(!c)return;const d={index:n,handler:a,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"};c.actions.push(d)}captureSequenceActionAfter(e,n,a,i,l,c){if(!this.config.enabled)return;const d=this.findExecutionInStack(e);if(!d)return;const f=d.actions.find(m=>m.index===n);if(!f)return;f.stateAfterAction={_global:this.safeClone(a._global),_local:this.safeClone(a._local),_isolated:a._isolated?this.safeClone(a._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)),c&&(f.status="error",f.error={name:c.name,message:c.message,stack:c.stack})}endSequenceExecution(e,n){if(!this.config.enabled)return;const a=this.sequenceExecutionStack.findIndex(l=>l.sequenceId===e);if(a===-1)return;const i=this.sequenceExecutionStack[a];if(i.endTime=Date.now(),i.totalDuration=i.endTime-i.startTime,n){i.status="error",i.error={name:n.name,message:n.message,stack:n.stack};const l=i.actions.find(c=>c.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(a,1)}computeStateDiff(e,n){const a=[],i=[],l=[],c=new Set(Object.keys(e)),d=new Set(Object.keys(n));for(const f of d)c.has(f)||a.push(f);for(const f of c)d.has(f)||i.push(f);for(const f of c)if(d.has(f)){const g=e[f],m=n[f];JSON.stringify(g)!==JSON.stringify(m)&&l.push({path:f,oldValue:g,newValue:m})}return{added:a,removed:i,changed:l}}getSequenceTrackingInfo(){const e=this.getSequenceStats(),n=this.sequenceExecutionStack.length>0?this.sequenceExecutionStack[this.sequenceExecutionStack.length-1]:void 0;return{executions:[...this.sequenceExecutions],currentExecution:n,stats:e}}getSequenceStats(){const e=this.sequenceExecutions,n=e.length,a=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),c=n>0?e.reduce((g,m)=>g+m.totalDuration,0)/n: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:n,successCount:a,errorCount:i,totalActions:l,avgDuration:c,topHandlers:f}}clearSequenceData(){this.sequenceExecutions=[],this.sequenceExecutionStack=[],this.sequenceIdCounter=0}getSequenceExecution(e){const n=this.findExecutionInStack(e);return n||this.sequenceExecutions.find(a=>a.sequenceId===e)}getRecentSequences(e=10){return this.sequenceExecutions.slice(-e)}registerStateCaptureForHandler(e,n,a){if(!this.config.enabled)return;const i=new Map,l=Date.now();for(const c of n)i.set(c,{value:this.safeClone(a[c]),capturedAt:l});this.stateCaptureRegistry.set(e,i)}detectStaleClosure(e,n,a,i,l){if(!this.config.enabled)return[];const c=this.stateCaptureRegistry.get(e);if(!c)return[];const d=Date.now(),f=[];for(const[g,m]of c){const y=this.getValueByPath(a,g),S=d-m.capturedAt;if(!this.isDeepEqual(m.value,y)&&S>0){const v=this.createStaleClosureWarning(i,n,g,m.value,m.capturedAt,y,d,S,l);f.push(v),this.addStaleClosureWarning(v)}}return this.stateCaptureRegistry.delete(e),f}trackStaleClosureWarning(e){if(!this.config.enabled)return;const n=Date.now(),a=this.createStaleClosureWarning(e.type,e.location,e.capturedPath,e.capturedValue,e.capturedAt,e.currentValue,n,n-e.capturedAt,e.actionId,e.stackTrace);this.addStaleClosureWarning(a)}createStaleClosureWarning(e,n,a,i,l,c,d,f,g,m){const y=this.getStaleClosureSeverity(e,f),{description:S,suggestion:v,docLink:_}=this.getStaleClosureMessages(e,a,f);return{id:`stale_${++this.staleClosureIdCounter}_${Date.now()}`,timestamp:Date.now(),type:e,location:n,capturedState:{path:a,capturedValue:this.safeClone(i),capturedAt:l},currentState:{path:a,currentValue:this.safeClone(c),retrievedAt:d},timeDiff:f,severity:y,description:S,suggestion:v,docLink:_,actionId:g,stackTrace:m}}getStaleClosureSeverity(e,n){if(n>5e3)return"error";if(n>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,n,a){const i=a<1e3?`${a}ms`:`${(a/1e3).toFixed(1)}s`;switch(e){case"async-state-capture":return{description:`await 후 ${i} 경과 시점에 '${n}' 상태가 변경됨. 캡처된 상태 대신 최신 상태를 사용해야 함`,suggestion:"await 이후에는 G7Core.state.get()으로 최신 상태를 다시 조회하거나, useRef + getter 패턴을 사용하세요",docLink:"troubleshooting-state-closure.md"};case"callback-state-capture":return{description:`콜백에서 ${i} 전에 캡처된 '${n}' 상태를 사용 중. 최신 상태와 다름`,suggestion:"콜백에서 상태를 참조할 때는 stateRef.current 패턴 또는 G7Core.state.get()를 사용하세요",docLink:"troubleshooting-state-closure.md"};case"timeout-state-capture":return{description:`setTimeout/setInterval 콜백에서 '${n}' 상태가 ${i} 전 값 사용 중`,suggestion:"타이머 콜백 내에서는 G7Core.state.get()으로 최신 상태를 조회하세요",docLink:"troubleshooting-state-closure.md"};case"sequence-state-mismatch":return{description:`sequence 내 '${n}' 상태가 이전 액션 결과와 불일치. context.state 대신 캡처된 값 사용 의심`,suggestion:"sequence 내에서는 context.state 또는 $prev를 사용하여 최신 상태를 참조하세요",docLink:"troubleshooting-state-setstate.md"};case"event-handler-stale":return{description:`이벤트 핸들러에서 ${i} 전에 바인딩된 '${n}' 상태 사용 중`,suggestion:"이벤트 핸들러에서 상태를 참조할 때는 useRef 패턴 또는 G7Core.state.get()를 사용하세요",docLink:"troubleshooting-state-closure.md"};default:return{description:`'${n}' 상태에서 stale closure 감지됨 (${i} 경과)`,suggestion:"상태 참조 시 최신 값을 사용하는지 확인하세요"}}}addStaleClosureWarning(e){this.staleClosureWarnings.push(e),this.staleClosureWarnings.length>this.maxStaleClosureWarnings&&this.staleClosureWarnings.shift()}getValueByPath(e,n){const a=n.split(".");let i=e;for(const l of a){if(i==null)return;i=i[l]}return i}isDeepEqual(e,n){if(e===n)return!0;if(e===null||n===null)return e===n;if(typeof e!=typeof n)return!1;if(typeof e!="object")return e===n;try{return JSON.stringify(e)===JSON.stringify(n)}catch{return!1}}getStaleClosureTrackingInfo(){const e=this.getStaleClosureStats();return{warnings:[...this.staleClosureWarnings],stats:e,timestamp:Date.now()}}getStaleClosureStats(){const e=this.staleClosureWarnings,n={"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)n[f.type]++;const a={info:0,warning:0,error:0};for(const f of e)a[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})),c={};for(const f of e)c[f.capturedState.path]=(c[f.capturedState.path]||0)+1;const d=Object.entries(c).sort(([,f],[,g])=>g-f).slice(0,5).map(([f,g])=>({path:f,count:g}));return{totalWarnings:e.length,warningsByType:n,warningsBySeverity:a,topLocations:l,topAffectedPaths:d}}clearStaleClosureData(){this.staleClosureWarnings=[],this.staleClosureIdCounter=0,this.stateCaptureRegistry.clear()}getRecentStaleClosureWarnings(e=10,n){let a=[...this.staleClosureWarnings];return n&&(a=a.filter(i=>i.severity===n)),a.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(a=>{try{return JSON.parse(JSON.stringify(a))}catch{return"[Unserializable]"}});const n={};for(const a of Object.keys(e))try{n[a]=JSON.parse(JSON.stringify(e[a]))}catch{n[a]="[Unserializable]"}return n}}};$(wi,"instance");let Oa=wi;const Kn=ht("LayoutLoader");class Er extends Error{constructor(n,a,i){super(n);$(this,"code");$(this,"details");this.code=a,this.details=i,this.name="LayoutLoaderError"}}class mf{constructor(e){$(this,"componentRegistry");$(this,"currentLayout",null);$(this,"layoutCache",new Map);$(this,"cacheVersion",0);this.componentRegistry=e}setCacheVersion(e){this.cacheVersion!==e&&(Kn.log("Cache version updated:",this.cacheVersion,"->",e),this.cacheVersion=e,this.layoutCache.clear())}getCacheVersion(){return this.cacheVersion}async loadLayout(e,n){const a=`${e}:${n}`;if(this.layoutCache.has(a)){Kn.log("Loading layout from cache:",n);const l=await this.layoutCache.get(a),c=JSON.parse(JSON.stringify(l));return this.currentLayout=c,Oa.getInstance().trackLayoutLoad(n,e,c,"cache"),c}const i=this.fetchLayout(e,n);return this.layoutCache.set(a,i),i.catch(()=>{this.layoutCache.get(a)===i&&this.layoutCache.delete(a)}),i}async fetchLayout(e,n,a=!1){try{const i=this.cacheVersion>0?this.cacheVersion:null;let l;if(n.startsWith("__preview__/")){const S=n.replace("__preview__/","");l=Nr(`/api/layouts/preview/${S}`,"json",i)}else l=Nr(`/api/layouts/${e}/${n}`,"json",i);Kn.log("Fetching layout from API:",l);const c=Hr(),d=a?null:c.getToken(),f={Accept:"application/json"};d&&(f.Authorization=`Bearer ${d}`);const g=await Il(l,{init:{headers:f},label:`layout: ${n}`});let m;try{m=await g.json()}catch{m=null}if(!g.ok){if(g.status===401&&!a&&d){Kn.log("Token invalid, removing and retrying without token"),c.removeToken();try{return await this.fetchLayout(e,n,!0)}catch(v){throw v instanceof Er&&v.details?.status===401?new Er(v.message,v.code,{...v.details,hadToken:!0}):v}}const S=m?.message||m?.error;throw new Er(`Failed to fetch layout: ${g.status} ${g.statusText}`,"FETCH_FAILED",{status:g.status,statusText:g.statusText,url:l,apiMessage:S})}const y=m.data||m;return this.validateLayoutData(y),this.currentLayout=y,Oa.getInstance().trackLayoutLoad(n,e,y,"api"),Kn.log("Layout fetched and cached successfully:",y.layout_name),y}catch(i){const l=`${e}:${n}`;throw this.layoutCache.delete(l),i instanceof Er?i:new Er("Failed to load layout","LOAD_FAILED",{originalError:i})}}prefetchLayout(e,n){return this.loadLayout(e,n)}validateLayoutData(e){if(!e.version)throw new Er("Layout data missing required field: version","VALIDATION_FAILED",{field:"version"});if(!e.layout_name)throw new Er("Layout data missing required field: layout_name","VALIDATION_FAILED",{field:"layout_name"});if(!Array.isArray(e.components))throw new Er('Layout data field "components" must be an array',"VALIDATION_FAILED",{field:"components",value:e.components});Kn.log("Layout data validation passed")}renderLayout(e,n){try{const a=n||this.currentLayout;if(!a)throw new Er("No layout data to render","NO_LAYOUT_DATA");Kn.log("Rendering layout:",a.layout_name),e.innerHTML="",this.renderComponents(e,a.components),Kn.log("Layout rendered successfully")}catch(a){Kn.error("Render error:",a),this.renderErrorState(e,a)}}renderComponents(e,n){for(const a of n){const i=this.renderComponent(a);i&&e.appendChild(i)}}renderComponent(e){try{if(!this.componentRegistry.getComponent(e.type))return Kn.warn(`Component not found: ${e.type}`),this.createPlaceholderElement(e.type);const a=document.createElement("div");return a.setAttribute("data-component",e.type),e.props&&Object.entries(e.props).forEach(([i,l])=>{a.setAttribute(`data-prop-${i}`,JSON.stringify(l))}),e.children&&e.children.length>0?this.renderComponents(a,e.children):e.text&&(a.textContent=e.text),a}catch(n){return Kn.error(`Error rendering component ${e.type}:`,n),this.createErrorElement(e.type,n)}}createPlaceholderElement(e){const n=document.createElement("div");return n.className="component-placeholder",n.setAttribute("data-component-type",e),n.innerHTML=`

Component not found: ${e}

@@ -60,7 +60,7 @@ Error generating stack: `+u.message+`

Component Error: ${e}

${n?.message||"Unknown error"}

- `,a}renderErrorState(e,n){const a=n instanceof Error?n.message:String(n),i=n instanceof Cr?n.code:"UNKNOWN_ERROR";e.innerHTML=` + `,a}renderErrorState(e,n){const a=n instanceof Error?n.message:String(n),i=n instanceof Er?n.code:"UNKNOWN_ERROR";e.innerHTML=`
페이지 새로고침
- `,Gn.error("Error state rendered:",i,a)}getCurrentLayout(){return this.currentLayout}clear(){this.currentLayout=null,this.layoutCache.clear(),Gn.log("Layout data and cache cleared")}}const D_=ut("TranslationContext"),hf=N.createContext(null),mc=({children:o,translationEngine:e,translationContext:n})=>{const a=N.useMemo(()=>(l,c)=>{if(c){const d="|"+Object.entries(c).map(([f,g])=>`${f}=${g}`).join("|");return e.translate(l,n,d)}return e.translate(l,n)},[e,n]),i=N.useMemo(()=>({translationEngine:e,translationContext:n,t:a}),[e,n,a]);return dt.jsx(hf.Provider,{value:i,children:o})},ty=()=>{const o=N.useContext(hf);return o||(D_.warn("TranslationProvider 외부에서 호출되었습니다. 키를 그대로 반환합니다."),{t:e=>e,translationEngine:null,translationContext:null})},La=ut("SlotContext"),O_={registerToSlot:()=>{La.warn("SlotContext not available: registerToSlot called outside SlotProvider")},unregisterFromSlot:()=>{La.warn("SlotContext not available: unregisterFromSlot called outside SlotProvider")},getSlotComponents:()=>[],subscribeToSlot:()=>()=>{},clearAllSlots:()=>{},isEnabled:!1},L_=N.createContext(O_),gf=({children:o})=>{const e=N.useRef(new Map),n=N.useRef(new Map),a=N.useCallback(m=>{const b=n.current.get(m);b&&b.forEach(S=>{try{S()}catch(v){La.error(`Slot subscriber error (slotId: ${m}):`,v)}})},[]),i=N.useCallback((m,b,S)=>{if(!m||!b){La.warn("registerToSlot: slotId and componentId are required");return}e.current.has(m)||e.current.set(m,new Map);const v=e.current.get(m),_=v.get(b);_&&_.registrationKey===S.registrationKey||(v.set(b,S),La.log(`Component registered to slot: ${b} -> ${m} (order: ${S.order})`),a(m))},[a]),l=N.useCallback((m,b)=>{const S=e.current.get(m);S&&S.has(b)&&(S.delete(b),La.log(`Component unregistered from slot: ${b} <- ${m}`),S.size===0&&e.current.delete(m),a(m))},[a]),c=N.useCallback(m=>{const b=e.current.get(m);return b?Array.from(b.values()).sort((S,v)=>S.order-v.order):[]},[]),d=N.useCallback((m,b)=>{n.current.has(m)||n.current.set(m,new Set);const S=n.current.get(m);return S.add(b),()=>{S.delete(b),S.size===0&&n.current.delete(m)}},[]),f=N.useCallback(()=>{e.current.forEach((m,b)=>{a(b)}),e.current.clear(),n.current.clear(),La.log("All slots cleared")},[a]),g=N.useMemo(()=>({registerToSlot:i,unregisterFromSlot:l,getSlotComponents:c,subscribeToSlot:d,clearAllSlots:f,isEnabled:!0}),[i,l,c,d,f]);return N.useLayoutEffect(()=>{typeof window<"u"&&(window.__slotContextValue=g,La.log("SlotContext exposed to window.__slotContextValue"))},[g]),dt.jsx(L_.Provider,{value:g,children:o})};class pf{constructor(){this.notificationCreatedEvent=".Illuminate\\Notifications\\Events\\BroadcastNotificationCreated"}listenForWhisper(e,n){return this.listen(".client-"+e,n)}notification(e){return this.listen(this.notificationCreatedEvent,e)}stopListeningForNotification(e){return this.stopListening(this.notificationCreatedEvent,e)}stopListeningForWhisper(e,n){return this.stopListening(".client-"+e,n)}}class ny{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 M_(o){try{return Reflect.construct(String,[],o),!0}catch{return!1}}class mf extends pf{constructor(e,n,a){super(),this.name=n,this.pusher=e,this.options=a,this.eventFormatter=new ny(this.options.namespace),this.subscribe()}subscribe(){this.subscription=this.pusher.subscribe(this.name)}unsubscribe(){this.pusher.unsubscribe(this.name)}listen(e,n){return this.on(this.eventFormatter.format(e),n),this}listenToAll(e){return this.subscription.bind_global((n,a)=>{if(n.startsWith("pusher:"))return;let i=String(this.options.namespace??"").replace(/\./g,"\\"),l=n.startsWith(i)?n.substring(i.length+1):"."+n;e(l,a)}),this}stopListening(e,n){return n?this.subscription.unbind(this.eventFormatter.format(e),n):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",n=>{e(n)}),this}on(e,n){return this.subscription.bind(e,n),this}}class ry extends mf{whisper(e,n){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,n),this}}class $_ extends mf{whisper(e,n){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,n),this}}class N_ extends ry{here(e){return this.on("pusher:subscription_succeeded",n=>{e(Object.keys(n.members).map(a=>n.members[a]))}),this}joining(e){return this.on("pusher:member_added",n=>{e(n.info)}),this}whisper(e,n){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,n),this}leaving(e){return this.on("pusher:member_removed",n=>{e(n.info)}),this}}class ay extends pf{constructor(e,n,a){super(),this.events={},this.listeners={},this.name=n,this.socket=e,this.options=a,this.eventFormatter=new ny(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,n){return this.on(this.eventFormatter.format(e),n),this}stopListening(e,n){return this.unbindEvent(this.eventFormatter.format(e),n),this}subscribed(e){return this.on("connect",n=>{e(n)}),this}error(e){return this}on(e,n){return this.listeners[e]=this.listeners[e]||[],this.events[e]||(this.events[e]=(a,i)=>{this.name===a&&this.listeners[e]&&this.listeners[e].forEach(l=>l(i))},this.socket.on(e,this.events[e])),this.listeners[e].push(n),this}unbind(){Object.keys(this.events).forEach(e=>{this.unbindEvent(e)})}unbindEvent(e,n){this.listeners[e]=this.listeners[e]||[],n&&(this.listeners[e]=this.listeners[e].filter(a=>a!==n)),(!n||this.listeners[e].length===0)&&(this.events[e]&&(this.socket.removeListener(e,this.events[e]),delete this.events[e]),delete this.listeners[e])}}class iy extends ay{whisper(e,n){return this.socket.emit("client event",{channel:this.name,event:`client-${e}`,data:n}),this}}class I_ extends iy{here(e){return this.on("presence:subscribed",n=>{e(n.map(a=>a.user_info))}),this}joining(e){return this.on("presence:joining",n=>e(n.user_info)),this}whisper(e,n){return this.socket.emit("client event",{channel:this.name,event:`client-${e}`,data:n}),this}leaving(e){return this.on("presence:leaving",n=>e(n.user_info)),this}}class yc extends pf{subscribe(){}unsubscribe(){}listen(e,n){return this}listenToAll(e){return this}stopListening(e,n){return this}subscribed(e){return this}error(e){return this}on(e,n){return this}}class sy extends yc{whisper(e,n){return this}}class H_ extends yc{whisper(e,n){return this}}class z_ extends sy{here(e){return this}joining(e){return this}whisper(e,n){return this}leaving(e){return this}}const oy=class US{constructor(e){this.setOptions(e),this.connect()}setOptions(e){this.options={...US._defaultOptions,...e,broadcaster:e.broadcaster};let n=this.csrfToken();n&&(this.options.auth.headers["X-CSRF-TOKEN"]=n,this.options.userAuthentication.headers["X-CSRF-TOKEN"]=n),n=this.options.bearerToken,n&&(this.options.auth.headers.Authorization="Bearer "+n,this.options.userAuthentication.headers.Authorization="Bearer "+n)}csrfToken(){var e,n;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"?((n=document.querySelector('meta[name="csrf-token"]'))==null?void 0:n.getAttribute("content"))??null:null}};oy._defaultOptions={auth:{headers:{}},authEndpoint:"/broadcasting/auth",userAuthentication:{endpoint:"/broadcasting/user-auth",headers:{}},csrfToken:null,bearerToken:null,host:null,key:null,namespace:"App.Events"};let yf=oy;class bc extends yf{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,n,a){return this.channel(e).listen(n,a)}channel(e){return this.channels[e]||(this.channels[e]=new mf(this.pusher,e,this.options)),this.channels[e]}privateChannel(e){return this.channels["private-"+e]||(this.channels["private-"+e]=new ry(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 N_(this.pusher,"presence-"+e,this.options)),this.channels["presence-"+e]}leave(e){[e,"private-"+e,"private-encrypted-"+e,"presence-"+e].forEach(n=>{this.leaveChannel(n)})}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 n=()=>{e(this.connectionStatus())},a=["state_change","connected","disconnected"];return a.forEach(i=>{this.pusher.connection.bind(i,n)}),()=>{a.forEach(i=>{this.pusher.connection.unbind(i,n)})}}disconnect(){this.pusher.disconnect()}}class j_ extends yf{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(n=>{n.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,n,a){return this.channel(e).listen(n,a)}channel(e){return this.channels[e]||(this.channels[e]=new ay(this.socket,e,this.options)),this.channels[e]}privateChannel(e){return this.channels["private-"+e]||(this.channels["private-"+e]=new iy(this.socket,"private-"+e,this.options)),this.channels["private-"+e]}presenceChannel(e){return this.channels["presence-"+e]||(this.channels["presence-"+e]=new I_(this.socket,"presence-"+e,this.options)),this.channels["presence-"+e]}leave(e){[e,"private-"+e,"presence-"+e].forEach(n=>{this.leaveChannel(n)})}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 n=()=>{e(this.connectionStatus())},a=["connect","disconnect","connect_error","reconnect_attempt","reconnect","reconnect_error","reconnect_failed"];return a.forEach(i=>{this.socket.on(i,n)}),()=>{a.forEach(i=>{this.socket.off(i,n)})}}disconnect(){this.socket.disconnect()}}class ly extends yf{constructor(){super(...arguments),this.channels={}}connect(){}listen(e,n,a){return new yc}channel(e){return new yc}privateChannel(e){return new sy}encryptedPrivateChannel(e){return new H_}presenceChannel(e){return new z_}leave(e){}leaveChannel(e){}socketId(){return"fake-socket-id"}connectionStatus(){return"connected"}onConnectionChange(e){return()=>{}}disconnect(){}}class U_{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 bc({...this.options,cluster:""});else if(this.options.broadcaster==="pusher")this.connector=new bc(this.options);else if(this.options.broadcaster==="ably")this.connector=new bc({...this.options,cluster:"",broadcaster:"pusher"});else if(this.options.broadcaster==="socket.io")this.connector=new j_(this.options);else if(this.options.broadcaster==="null")this.connector=new ly(this.options);else if(typeof this.options.broadcaster=="function"&&M_(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,n,a){return this.connector.listen(e,n,a)}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 bc||e instanceof ly}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,n)=>{this.socketId()&&e.headers.set("X-Socket-ID",this.socketId()),n()})}registerAxiosRequestInterceptor(){axios.interceptors.request.use(e=>(this.socketId()&&(e.headers["X-Socket-Id"]=this.socketId()),e))}registerjQueryAjaxSetup(){typeof jQuery.ajax<"u"&&jQuery.ajaxPrefilter((e,n,a)=>{this.socketId()&&a.setRequestHeader("X-Socket-Id",this.socketId())})}registerTurboRequestInterceptor(){document.addEventListener("turbo:before-fetch-request",e=>{e.detail.fetchOptions.headers["X-Socket-Id"]=this.socketId()})}}var bf={exports:{}};var cy;function B_(){return cy||(cy=1,(function(o,e){(function(a,i){o.exports=i()})(self,()=>(()=>{var n={594(c,d){var f=this&&this.__extends||(function(){var M=function(R,D){return M=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(B,q){B.__proto__=q}||function(B,q){for(var P in q)q.hasOwnProperty(P)&&(B[P]=q[P])},M(R,D)};return function(R,D){M(R,D);function B(){this.constructor=R}R.prototype=D===null?Object.create(D):(B.prototype=D.prototype,new B)}})();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="",B=0;B>>18&63),D+=this._encodeByte(q>>>12&63),D+=this._encodeByte(q>>>6&63),D+=this._encodeByte(q>>>0&63)}var P=R.length-B;if(P>0){var q=R[B]<<16|(P===2?R[B+1]<<8:0);D+=this._encodeByte(q>>>18&63),D+=this._encodeByte(q>>>12&63),P===2?D+=this._encodeByte(q>>>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),B=R.length-D,q=new Uint8Array(this.maxDecodedLength(B)),P=0,K=0,ge=0,Ee=0,Se=0,Ue=0,Ve=0;K>>4,q[P++]=Se<<4|Ue>>>2,q[P++]=Ue<<6|Ve,ge|=Ee&g,ge|=Se&g,ge|=Ue&g,ge|=Ve&g;if(K>>4,ge|=Ee&g,ge|=Se&g),K>>2,ge|=Ue&g),K>>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 B=R.length-1;B>=0&&R[B]===this._paddingCharacter;B--)D++;if(R.length<4||D>2)throw new Error("Base64Coder: incorrect padding")}return D},M})();d.Coder=m;var b=new m;function S(M){return b.encode(M)}d.encode=S;function v(M){return b.decode(M)}d.decode=v;var _=(function(M){f(R,M);function R(){return M!==null&&M.apply(this,arguments)||this}return R.prototype._encodeByte=function(D){var B=D;return B+=65,B+=25-D>>>8&6,B+=51-D>>>8&-75,B+=61-D>>>8&-13,B+=62-D>>>8&49,String.fromCharCode(B)},R.prototype._decodeChar=function(D){var B=g;return B+=(44-D&D-46)>>>8&-g+D-45+62,B+=(94-D&D-96)>>>8&-g+D-95+63,B+=(47-D&D-58)>>>8&-g+D-48+52,B+=(64-D&D-91)>>>8&-g+D-65+0,B+=(96-D&D-123)>>>8&-g+D-97+26,B},R})(m);d.URLSafeCoder=_;var A=new _;function x(M){return A.encode(M)}d.encodeURLSafe=x;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(c,d){var f="utf8: invalid source encoding";function g(m){for(var b=[],S=0;S=m.length)throw new Error(f);var A=m[++S];if((A&192)!==128)throw new Error(f);v=(v&31)<<6|A&63,_=128}else if(v<240){if(S>=m.length-1)throw new Error(f);var A=m[++S],x=m[++S];if((A&192)!==128||(x&192)!==128)throw new Error(f);v=(v&15)<<12|(A&63)<<6|x&63,_=2048}else if(v<248){if(S>=m.length-2)throw new Error(f);var A=m[++S],x=m[++S],L=m[++S];if((A&192)!==128||(x&192)!==128||(L&192)!==128)throw new Error(f);v=(v&15)<<18|(A&63)<<12|(x&63)<<6|L&63,_=65536}else throw new Error(f);if(v<_||v>=55296&&v<=57343)throw new Error(f);if(v>=65536){if(v>1114111)throw new Error(f);v-=65536,b.push(String.fromCharCode(55296|v>>10)),v=56320|v&1023}}b.push(String.fromCharCode(v))}return b.join("")}d.D4=g},721(c,d,f){c.exports=f(207).default},207(c,d,f){f.d(d,{default:()=>ws});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,me=function(){ne||(y.apply(null,arguments),ne=!0)};return this[C]=me,{number:C,id:O,name:I,callback:me}}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 S=b;class v{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=je.createScriptRequest(I.getPath(y,C)),me=I.receivers.create(function(Me){if(I.receivers.remove(me),I.loading[y]){var Ke=I.loading[y];delete I.loading[y];for(var lt=function(zt){zt||ne.cleanup()},gt=0;gt>>6)+J(128|y&63):J(224|y>>>12&15)+J(128|y>>>6&63)+J(128|y&63)},Z=function(E){return E.replace(/[^\x00-\x7F]/g,Le)},pe=function(E){var y=[0,2,1][E.length%3],C=E.charCodeAt(0)<<16|(E.length>1?E.charCodeAt(1):0)<<8|(E.length>2?E.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("")},H=window.btoa||function(E){return E.replace(/[\s\S]{1,3}/g,pe)};class T{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 ce=T;function de(E){window.clearTimeout(E)}function ye(E){window.clearInterval(E)}class ie extends ce{constructor(y,C){super(setTimeout,de,y,function(O){return C(),null})}}class xe extends ce{constructor(y,C){super(setInterval,ye,y,function(O){return C(),O})}}var _e={now(){return Date.now?Date.now():new Date().valueOf()},defer(E){return new ie(0,E)},method(E,...y){var C=Array.prototype.slice.call(arguments,1);return function(O){return O[E].apply(O,C.concat(arguments))}}};const Te=_e;function $e(E,...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=ht.apply(this,arguments);ws.log?ws.log(O):ws.logToConsole&&y.bind(this)(O)}}const tt=new Rn;var $n=function(E,y,C,O,I){(C.headers!==void 0||C.headersProvider!=null)&&tt.warn(`To send headers with the ${O.toString()} request, you must use AJAX, rather than JSONP.`);var ne=E.nextAuthCallbackID.toString();E.nextAuthCallbackID++;var me=E.getDocument(),Me=me.createElement("script");E.auth_callbacks[ne]=function(gt){I(null,gt)};var Ke="Pusher.auth_callbacks['"+ne+"']";Me.src=C.endpoint+"?callback="+encodeURIComponent(Ke)+"&"+y;var lt=me.getElementsByTagName("head")[0]||me.documentElement;lt.insertBefore(Me,lt.firstChild)};const pn=$n;class ra{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 ir{constructor(y,C){this.url=y,this.data=C}send(y){if(!this.request){var C=wi(this.data),O=this.url+"/"+y.number+"?"+C;this.request=je.createScriptRequest(O),this.request.send(y)}}cleanup(){this.request&&this.request.cleanup()}}var an=function(E,y){return function(C,O){var I="http"+(y?"s":"")+"://",ne=I+(E.host||E.options.host)+E.options.path,me=je.createJSONPRequest(ne,C),Me=je.ScriptReceivers.create(function(Ke,lt){m.remove(Me),me.cleanup(),lt&<.host&&(E.host=lt.host),O&&O(Ke,lt)});me.send(Me)}},En={name:"jsonp",getAgent:an};const sn=En;function V(E,y,C){var O=E+(y.useTLS?"s":""),I=y.useTLS?y.hostTLS:y.hostNonTLS;return O+"://"+I+C}function se(E,y){var C="/app/"+E,O="?protocol="+S.PROTOCOL+"&client=js&version="+S.VERSION+(y?"&"+y:"");return C+O}var ue={getInitial:function(E,y){var C=(y.httpPath||"")+se(E,"flash=false");return V("ws",y,C)}},ee={getInitial:function(E,y){var C=(y.httpPath||"/pusher")+se(E);return V("http",y,C)}},ve={getInitial:function(E,y){return V("http",y,y.httpPath||"/pusher")},getPath:function(E,y){return se(E)}};class he{constructor(){this._callbacks={}}get(y){return this._callbacks[Ce(y)]}add(y,C,O){var I=Ce(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?[Ce(y)]:ft(this._callbacks);C||O?this.removeCallback(I,C,O):this.removeAllCallbacks(I)}removeCallback(y,C,O){Ft(y,function(I){this._callbacks[I]=fn(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){Ft(y,function(C){delete this._callbacks[C]},this)}}function Ce(E){return"_"+E}class Ae{constructor(y){this.callbacks=new he,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=fn(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(),tt.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"?(Te.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 $e({cid:this.id},y)}}class Re{constructor(y){this.hooks=y}isSupported(y){return this.hooks.isSupported(y)}createConnection(y,C,O,I){return new Fe(this.hooks,y,C,O,I)}}var Ne=new Re({urls:ue,handlesActivityChecks:!1,supportsPing:!1,isInitialized:function(){return!!je.getWebSocketAPI()},isSupported:function(){return!!je.getWebSocketAPI()},getSocket:function(E){return je.createWebSocket(E)}}),ke={urls:ee,handlesActivityChecks:!1,supportsPing:!0,isInitialized:function(){return!0}},Ze=$e({getSocket:function(E){return je.HTTPFactory.createStreamingSocket(E)}},ke),ze=$e({getSocket:function(E){return je.HTTPFactory.createPollingSocket(E)}},ke),Ge={isSupported:function(){return je.isXHRSupported()}},we=new Re($e({},Ze,Ge)),He=new Re($e({},ze,Ge)),et={ws:Ne,xhr_streaming:we,xhr_polling:He};const _t=et;var Lt=new Re({file:"sockjs",urls:ve,handlesActivityChecks:!0,supportsPing:!1,isSupported:function(){return!0},isInitialized:function(){return window.SockJS!==void 0},getSocket:function(E,y){return new window.SockJS(E,null,{js_path:A.getPath("sockjs",{useTLS:y.useTLS}),ignore_null_origin:y.ignoreNullOrigin})},beforeOpen:function(E,y){E.send(JSON.stringify({path:y}))}}),kn={isSupported:function(E){var y=je.isXDRSupported(E.useTLS);return y}},It=new Re($e({},Ze,kn)),Ht=new Re($e({},ze,kn));_t.xdr_streaming=It,_t.xdr_polling=Ht,_t.sockjs=Lt;const _n=_t;class $a extends Ae{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 $o=new $a;class Af{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=$e({},I,{activityTimeout:this.pingDelay});var ne=this.transport.createConnection(y,C,O,I),me=null,Me=function(){ne.unbind("open",Me),ne.bind("closed",Ke),me=Te.now()},Ke=lt=>{if(ne.unbind("closed",Ke),lt.code===1002||lt.code===1003)this.manager.reportDeath();else if(!lt.wasClean&&me){var gt=Te.now()-me;gt<2*this.maxPingDelay&&(this.manager.reportDeath(),this.pingDelay=Math.max(gt/2,this.minPingDelay))}};return ne.bind("open",Me),ne}isSupported(y){return this.manager.isAlive()&&this.transport.isSupported(y)}}const Ac={decodeMessage:function(E){try{var y=JSON.parse(E.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:E.data}}},encodeMessage:function(E){return JSON.stringify(E)},processHandshake:function(E){var y=Ac.decodeMessage(E);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(E){return E.code<4e3?E.code>=1002&&E.code<=1004?"backoff":null:E.code===4e3?"tls_only":E.code<4100?"refused":E.code<4200?"backoff":E.code<4300?"retry":"refused"},getCloseError:function(E){return E.code!==1e3&&E.code!==1001?{type:"PusherError",data:{code:E.code,message:E.reason||E.message}}:null}},qr=Ac;class Ci extends Ae{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),tt.debug("Event sent",I),this.send(qr.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=qr.decodeMessage(O)}catch(ne){this.emit("error",{type:"MessageParseError",error:ne,data:O.data})}if(I!==void 0){switch(tt.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=()=>{kt(y,(O,I)=>{this.transport.unbind(I,O)})};kt(y,(O,I)=>{this.transport.bind(I,O)})}handleCloseEvent(y){var C=qr.getCloseAction(y),O=qr.getCloseError(y);O&&this.emit("error",O),C&&this.emit(C,{action:C,error:O})}}class No{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=qr.processHandshake(y)}catch(O){this.finish("error",{error:O}),this.transport.close();return}C.action==="connected"?this.finish("connected",{connection:new Ci(C.id,this.transport),activityTimeout:C.activityTimeout}):(this.finish(C.action,{error:C.error}),this.transport.close())},this.onClosed=y=>{this.unbindListeners();var C=qr.getCloseAction(y)||"backoff",O=qr.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($e({transport:this.transport,action:y},C))}}class Na{constructor(y,C){this.timeline=y,this.options=C||{}}send(y,C){this.timeline.isEmpty()||this.timeline.send(je.TimelineTransport.getAgent(this,y),C)}}class Gr extends Ae{constructor(y,C){super(function(O,I){tt.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");tt.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,tt.error(y.toString()),this.emit("pusher:subscription_error",Object.assign({},{type:"AuthError",error:y.message},y instanceof Ue?{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 aa extends Gr{authorize(y,C){return this.pusher.config.channelAuthorizer({channelName:this.name,socketId:y},C)}}class Ia{constructor(){this.reset()}get(y){return Object.prototype.hasOwnProperty.call(this.members,y)?{id:y,info:this.members[y]}:null}each(y){kt(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 Xt=function(E,y,C,O){function I(ne){return ne instanceof C?ne:new C(function(me){me(ne)})}return new(C||(C=Promise))(function(ne,me){function Me(gt){try{lt(O.next(gt))}catch(zt){me(zt)}}function Ke(gt){try{lt(O.throw(gt))}catch(zt){me(zt)}}function lt(gt){gt.done?ne(gt.value):I(gt.value).then(Me,Ke)}lt((O=O.apply(E,y||[])).next())})};class xc extends aa{constructor(y,C){super(y,C),this.members=new Ia}authorize(y,C){super.authorize(y,(O,I)=>Xt(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 me=M.buildLogSuffix("authorizationEndpoint");tt.error(`Invalid auth response for channel '${this.name}', expected 'channel_data' field. ${me}, 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 Tc=f(978),xr=f(594);class Ha extends aa{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,xr.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){tt.debug("Received encrypted event before key has been retrieved from the authEndpoint");return}if(!C.ciphertext||!C.nonce){tt.error("Unexpected format for encrypted event, expected object with `ciphertext` and `nonce` fields, got: "+C);return}let O=(0,xr.decode)(C.ciphertext);if(O.length{if(me){tt.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){tt.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,Tc.D4)(y);try{return JSON.parse(C)}catch{return C}}}class xf extends Ae{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=je.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 ie(y||0,()=>{this.disconnectInternally(),this.connect()})}clearRetryTimer(){this.retryTimer&&(this.retryTimer.ensureAborted(),this.retryTimer=null)}setUnavailableTimer(){this.unavailableTimer=new ie(this.options.unavailableTimeout,()=>{this.updateState("unavailable")})}clearUnavailableTimer(){this.unavailableTimer&&this.unavailableTimer.ensureAborted()}sendActivityCheck(){this.stopActivityCheck(),this.connection.ping(),this.activityTimer=new ie(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 ie(this.activityTimeout,()=>{this.sendActivityCheck()}))}stopActivityCheck(){this.activityTimer&&this.activityTimer.ensureAborted()}buildConnectionCallbacks(y){return $e({},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 $e({},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),tt.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 Rc{constructor(){this.channels={}}add(y,C){return this.channels[y]||(this.channels[y]=kc(y,C)),this.channels[y]}all(){return nn(this.channels)}find(y){return this.channels[y]}remove(y){var C=this.channels[y];return delete this.channels[y],C}disconnect(){kt(this.channels,function(y){y.disconnect()})}}function kc(E,y){if(E.indexOf("private-encrypted-")===0){if(y.config.nacl)return Nn.createEncryptedChannel(E,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(E.indexOf("private-")===0)return Nn.createPrivateChannel(E,y);if(E.indexOf("presence-")===0)return Nn.createPresenceChannel(E,y);if(E.indexOf("#")===0)throw new B('Cannot create a channel with name "'+E+'".');return Nn.createChannel(E,y)}}var Tf={createChannels(){return new Rc},createConnectionManager(E,y){return new xf(E,y)},createChannel(E,y){return new Gr(E,y)},createPrivateChannel(E,y){return new aa(E,y)},createPresenceChannel(E,y){return new xc(E,y)},createEncryptedChannel(E,y,C){return new Ha(E,y,C)},createTimelineSender(E,y){return new Na(E,y)},createHandshake(E,y){return new No(E,y)},createAssistantToTheTransportManager(E,y,C){return new Af(E,y,C)}};const Nn=Tf;class Ei{constructor(y){this.options=y||{},this.livesLeft=this.options.lives||1/0}getAssistant(y){return Nn.createAssistantToTheTransportManager(this,y,{minPingDelay:this.options.minPingDelay,maxPingDelay:this.options.maxPingDelay})}isAlive(){return this.livesLeft>0}reportDeath(){this.livesLeft-=1}}class mn{constructor(y,C){this.strategies=y,this.loop=!!C.loop,this.failFast=!!C.failFast,this.timeout=C.timeout,this.timeoutLimit=C.timeoutLimit}isSupported(){return Fn(this.strategies,Te.method("isSupported"))}connect(y,C){var O=this.strategies,I=0,ne=this.timeout,me=null,Me=(Ke,lt)=>{lt?C(null,lt):(I=I+1,this.loop&&(I=I%O.length),I0&&(ne=new ie(O.timeout,function(){me.abort(),I(!0)})),me=y.connect(C,function(Me,Ke){Me&&ne&&ne.isRunning()&&!O.failFast||(ne&&ne.ensureAborted(),I(Me,Ke))}),{abort:function(){ne&&ne.ensureAborted(),me.abort()},forceMinPriority:function(Me){me.forceMinPriority(Me)}}}}class An{constructor(y){this.strategies=y}isSupported(){return Fn(this.strategies,Te.method("isSupported"))}connect(y,C){return Dc(this.strategies,y,function(O,I){return function(ne,me){if(I[O].error=ne,ne){Rf(I)&&C(!0);return}Ft(I,function(Me){Me.forceMinPriority(me.transport.priority)}),C(null,me)}})}}function Dc(E,y,C){var O=Nt(E,function(I,ne,me,Me){return I.connect(y,C(ne,Me))});return{abort:function(){Ft(O,Io)},forceMinPriority:function(I){Ft(O,function(ne){ne.forceMinPriority(I)})}}}function Rf(E){return Pr(E,function(y){return!!y.error})}function Io(E){!E.error&&!E.aborted&&(E.abort(),E.aborted=!0)}class Oc{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=kf(O),ne=I&&I.cacheSkipCount?I.cacheSkipCount:0,me=[this.strategy];if(I&&I.timestamp+this.ttl>=Te.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}),me.push(new mn([Me],{timeout:I.latency*2+1e3,failFast:!0}))):ne++)}var Ke=Te.now(),lt=me.pop().connect(y,function gt(zt,Dr){zt?(ms(O),me.length>0?(Ke=Te.now(),lt=me.pop().connect(y,gt)):C(zt)):(In(O,Dr.transport.name,Te.now()-Ke,ne),C(null,Dr))});return{abort:function(){lt.abort()},forceMinPriority:function(gt){y=gt,lt&<.forceMinPriority(gt)}}}}function za(E){return"pusherTransport"+(E?"TLS":"NonTLS")}function kf(E){var y=je.getLocalStorage();if(y)try{var C=y[za(E)];if(C)return JSON.parse(C)}catch{ms(E)}return null}function In(E,y,C,O){var I=je.getLocalStorage();if(I)try{I[za(E)]=gn({timestamp:Te.now(),transport:y,latency:C,cacheSkipCount:O})}catch{}}function ms(E){var y=je.getLocalStorage();if(y)try{delete y[za(E)]}catch{}}class _i{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 ie(this.options.delay,function(){I=O.connect(y,C)});return{abort:function(){ne.ensureAborted(),I&&I.abort()},forceMinPriority:function(me){y=me,I&&I.forceMinPriority(me)}}}}class ia{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 ja{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 Ua(E){return function(){return E.isSupported()}}var Lc=function(E,y,C){var O={};function I(Xo,Fc,Kc,Xf,Jf){var Wc=C(E,Xo,Fc,Kc,Xf,Jf);return O[Xo]=Wc,Wc}var ne=Object.assign({},y,{hostNonTLS:E.wsHost+":"+E.wsPort,hostTLS:E.wsHost+":"+E.wssPort,httpPath:E.wsPath}),me=Object.assign({},ne,{useTLS:!0}),Me=Object.assign({},y,{hostNonTLS:E.httpHost+":"+E.httpPort,hostTLS:E.httpHost+":"+E.httpsPort,httpPath:E.httpPath}),Ke={loop:!0,timeout:15e3,timeoutLimit:6e4},lt=new Ei({minPingDelay:1e4,maxPingDelay:E.activityTimeout}),gt=new Ei({lives:2,minPingDelay:1e4,maxPingDelay:E.activityTimeout}),zt=I("ws","ws",3,ne,lt),Dr=I("wss","ws",3,me,lt),Kf=I("sockjs","sockjs",1,Me),Gc=I("xhr_streaming","xhr_streaming",1,Me,gt),Wf=I("xdr_streaming","xdr_streaming",1,Me,gt),Ko=I("xhr_polling","xhr_polling",1,Me),Vc=I("xdr_polling","xdr_polling",1,Me),qa=new mn([zt],Ke),Di=new mn([Dr],Ke),Yf=new mn([Kf],Ke),Oi=new mn([new ia(Ua(Gc),Gc,Wf)],Ke),Wo=new mn([new ia(Ua(Ko),Ko,Vc)],Ke),Yo=new mn([new ia(Ua(Oi),new An([Oi,new _i(Wo,{delay:4e3})]),Wo)],Ke),Li=new ia(Ua(Yo),Yo,Yf),Mi;return y.useTLS?Mi=new An([qa,new _i(Li,{delay:2e3})]):Mi=new An([qa,new _i(Di,{delay:2e3}),new _i(Li,{delay:5e3})]),new Oc(new ja(new ia(Ua(zt),Mi,Li)),O,{ttl:18e5,timeline:y.timeline,useTLS:y.useTLS})};const Ba=Lc;function Df(){var E=this;E.timeline.info(E.buildTimelineMessage({transport:E.name+(E.options.useTLS?"s":"")})),E.hooks.isInitialized()?E.changeState("initialized"):E.hooks.file?(E.changeState("initializing"),A.load(E.hooks.file,{useTLS:E.options.useTLS},function(y,C){E.hooks.isInitialized()?(E.changeState("initialized"),C(!0)):(y&&E.onError(y),E.onClose(),C(!1))})):E.onClose()}var Mc={getRequest:function(E){var y=new window.XDomainRequest;return y.ontimeout=function(){E.emit("error",new q),E.close()},y.onerror=function(C){E.emit("error",C),E.close()},y.onprogress=function(){y.responseText&&y.responseText.length>0&&E.onChunk(200,y.responseText)},y.onload=function(){y.responseText&&y.responseText.length>0&&E.onChunk(200,y.responseText),E.emit("finished",200),E.close()},y},abortRequest:function(E){E.ontimeout=E.onerror=E.onprogress=E.onload=null,E.abort()}};const $c=Mc,Ho=256*1024;class Of extends Ae{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()},je.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&&(je.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>Ho}}var zo;(function(E){E[E.CONNECTING=0]="CONNECTING",E[E.OPEN=1]="OPEN",E[E.CLOSED=3]="CLOSED"})(zo||(zo={}));const sr=zo;var Tr=1;class jo{constructor(y,C){this.hooks=y,this.session=ys(1e3)+"/"+Ic(8),this.location=Uo(C),this.readyState=sr.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===sr.OPEN)try{return je.createSocketRequest("POST",sa(Pa(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=sr.CLOSED,this.onclose&&this.onclose({code:y,reason:C,wasClean:O})}onChunk(y){if(y.status===200){this.readyState===sr.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){Te.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 Uo(E){var y=/([^\?]*)\/*(\??.*)/.exec(E);return{base:y[1],queryString:y[2]}}function Pa(E,y){return E.base+"/"+y+"/xhr_send"}function sa(E){var y=E.indexOf("?")===-1?"?":"&";return E+y+"t="+ +new Date+"&n="+Tr++}function Nc(E,y){var C=/(https?:\/\/)([^\/:]+)((\/|:)?.*)/.exec(E);return C[1]+y+C[3]}function ys(E){return je.randomInt(E)}function Ic(E){for(var y=[],C=0;C0&&E.onChunk(C.status,C.responseText);break;case 4:C.responseText&&C.responseText.length>0&&E.onChunk(C.status,C.responseText),E.emit("finished",C.status),E.close();break}},C},abortRequest:function(E){E.onreadystatechange=null,E.abort()}};const bs=Po;var Hc={createStreamingSocket(E){return this.createSocket(Bo,E)},createPollingSocket(E){return this.createSocket(Vr,E)},createSocket(E,y){return new Ai(E,y)},createXHR(E,y){return this.createRequest(bs,E,y)},createRequest(E,y,C){return new Of(E,y,C)}};const Ti=Hc;Ti.createXDR=function(E,y){return this.createRequest($c,E,y)};var zc={nextAuthCallbackID:1,auth_callbacks:{},ScriptReceivers:m,DependenciesReceivers:_,getDefaultStrategy:Ba,Transports:_n,transportConnectionInitializer:Df,HTTPFactory:Ti,TimelineTransport:sn,getXHRAPI(){return window.XMLHttpRequest},getWebSocketAPI(){return window.WebSocket||window.MozWebSocket},setup(E){window.Pusher=E;var y=()=>{this.onDocumentBody(E.ready)};window.JSON?y():A.load("json2",{},y)},getDocument(){return document},getProtocol(){return this.getDocument().location.protocol},getAuthorizers(){return{ajax:qe,jsonp:pn}},onDocumentBody(E){document.body?E():setTimeout(()=>{this.onDocumentBody(E)},0)},createJSONPRequest(E,y){return new ir(E,y)},createScriptRequest(E){return new ra(E)},getLocalStorage(){try{return window.localStorage}catch{return}},createXHR(){return this.getXHRAPI()?this.createXMLHttpRequest():this.createMicrosoftXHR()},createXMLHttpRequest(){var E=this.getXHRAPI();return new E},createMicrosoftXHR(){return new ActiveXObject("Microsoft.XMLHTTP")},getNetwork(){return $o},createWebSocket(E){var y=this.getWebSocketAPI();return new y(E)},createSocketRequest(E,y){if(this.isXHRSupported())return this.HTTPFactory.createXHR(E,y);if(this.isXDRSupported(y.indexOf("https:")===0))return this.HTTPFactory.createXDR(E,y);throw"Cross-origin HTTP requests are not supported"},isXHRSupported(){var E=this.getXHRAPI();return!!E&&new E().withCredentials!==void 0},isXDRSupported(E){var y=E?"https:":"http:",C=this.getProtocol();return!!window.XDomainRequest&&C===y},addUnloadListener(E){window.addEventListener!==void 0?window.addEventListener("unload",E,!1):window.attachEvent!==void 0&&window.attachEvent("onunload",E)},removeUnloadListener(E){window.addEventListener!==void 0?window.removeEventListener("unload",E,!1):window.detachEvent!==void 0&&window.detachEvent("onunload",E)},randomInt(E){return Math.floor(function(){return(window.crypto||window.msCrypto).getRandomValues(new Uint32Array(1))[0]/Math.pow(2,32)}()*E)}};const je=zc;var kr;(function(E){E[E.ERROR=3]="ERROR",E[E.INFO=6]="INFO",E[E.DEBUG=7]="DEBUG"})(kr||(kr={}));const oa=kr;class Ri{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($e({},C,{timestamp:Te.now()})),this.options.limit&&this.events.length>this.options.limit&&this.events.shift())}error(y){this.log(oa.ERROR,y)}info(y){this.log(oa.INFO,y)}debug(y){this.log(oa.DEBUG,y)}isEmpty(){return this.events.length===0}send(y,C){var O=$e({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 Lf{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||(gt(),ne?ne.close():I.close())},forceMinPriority:zt=>{O||this.priority{var C="socket_id="+encodeURIComponent(E.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=E=>{if(typeof je.getAuthorizers()[E.transport]>"u")throw`'${E.transport}' is not a recognized auth transport`;return(y,C)=>{const O=Mf(y,E);je.getAuthorizers()[E.transport](je,O,E,R.UserAuthentication,C)}},Vo=(E,y)=>{var C="socket_id="+encodeURIComponent(E.socketId);C+="&channel_name="+encodeURIComponent(E.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},Nf=E=>{if(typeof je.getAuthorizers()[E.transport]>"u")throw`'${E.transport}' is not a recognized auth transport`;return(y,C)=>{const O=Vo(y,E);je.getAuthorizers()[E.transport](je,O,E,R.ChannelAuthorization,C)}},If=(E,y,C)=>{const O={authTransport:y.transport,authEndpoint:y.endpoint,auth:{params:y.params,headers:y.headers}};return(I,ne)=>{const me=E.channel(I.channelName);C(me,O).authorize(I.socketId,ne)}};function Uc(E,y){let C={activityTimeout:E.activityTimeout||S.activityTimeout,cluster:E.cluster,httpPath:E.httpPath||S.httpPath,httpPort:E.httpPort||S.httpPort,httpsPort:E.httpsPort||S.httpsPort,pongTimeout:E.pongTimeout||S.pongTimeout,statsHost:E.statsHost||S.stats_host,unavailableTimeout:E.unavailableTimeout||S.unavailableTimeout,wsPath:E.wsPath||S.wsPath,wsPort:E.wsPort||S.wsPort,wssPort:E.wssPort||S.wssPort,enableStats:Uf(E),httpHost:Hf(E),useTLS:jf(E),wsHost:Bc(E),userAuthenticator:Fo(E),channelAuthorizer:Pf(E,y)};return"disabledTransports"in E&&(C.disabledTransports=E.disabledTransports),"enabledTransports"in E&&(C.enabledTransports=E.enabledTransports),"ignoreNullOrigin"in E&&(C.ignoreNullOrigin=E.ignoreNullOrigin),"timelineParams"in E&&(C.timelineParams=E.timelineParams),"nacl"in E&&(C.nacl=E.nacl),C}function Hf(E){return E.httpHost?E.httpHost:E.cluster?`sockjs-${E.cluster}.pusher.com`:S.httpHost}function Bc(E){return E.wsHost?E.wsHost:zf(E.cluster)}function zf(E){return`ws-${E}.pusher.com`}function jf(E){return je.getProtocol()==="https:"?!0:E.forceTLS!==!1}function Uf(E){return"enableStats"in E?E.enableStats:"disableStats"in E?!E.disableStats:!1}const Pc=E=>"customHandler"in E&&E.customHandler!=null;function Fo(E){const y=Object.assign(Object.assign({},S.userAuthentication),E.userAuthentication);return Pc(y)?y.customHandler:$f(y)}function Bf(E,y){let C;if("channelAuthorization"in E)C=Object.assign(Object.assign({},S.channelAuthorization),E.channelAuthorization);else if(C={transport:E.authTransport||S.authTransport,endpoint:E.authEndpoint||S.authEndpoint},"auth"in E&&("params"in E.auth&&(C.params=E.auth.params),"headers"in E.auth&&(C.headers=E.auth.headers)),"authorizer"in E)return{customHandler:If(y,C,E.authorizer)};return C}function Pf(E,y){const C=Bf(E,y);return Pc(C)?C.customHandler:Nf(C)}class qf extends Ae{constructor(y){super(function(C,O){tt.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 qc(){let E,y;return{promise:new Promise((O,I)=>{E=O,y=I}),resolve:E,reject:y}}const Gf=qc;class Vf extends Ae{constructor(y){super(function(C,O){tt.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){tt.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 qf(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{tt.error(`Failed parsing user data after signin: ${y.user_data}`),this._cleanup();return}if(typeof this.user_data.id!="string"||this.user_data.id===""){tt.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 Gr(`#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}=Gf();y.done=!1;const O=()=>{y.done=!0};y.then(O).catch(O),this.signinDonePromise=y,this._signinDoneResolve=C}}class on{static ready(){on.isReady=!0;for(var y=0,C=on.instances.length;yje.getDefaultStrategy(this.config,I,ki);this.connection=Nn.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,me=ne.indexOf("pusher_internal:")===0;if(I.channel){var Me=this.channel(I.channel);Me&&Me.handleEvent(I)}me||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=>{tt.warn(I)}),on.instances.push(this),this.timeline.info({instances:on.instances.length}),this.user=new Vf(this),on.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=Uc(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 xe(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()}}on.instances=[],on.isReady=!1,on.logToConsole=!1,on.Runtime=je,on.ScriptReceivers=je.ScriptReceivers,on.DependenciesReceivers=je.DependenciesReceivers,on.auth_callbacks=je.auth_callbacks;const ws=on;function Ff(E){if(E==null)throw"You must pass your app key when you instantiate Pusher."}je.setup(on)}},a={};function i(c){var d=a[c];if(d!==void 0)return d.exports;var f=a[c]={exports:{}};return n[c].call(f.exports,f,f.exports,i),f.exports}i.d=(c,d)=>{for(var f in d)i.o(d,f)&&!i.o(c,f)&&Object.defineProperty(c,f,{enumerable:!0,get:d[f]})},i.o=(c,d)=>Object.prototype.hasOwnProperty.call(c,d);var l=i(721);return l})())})(bf)),bf.exports}var P_=B_();const uy=Jr(P_),Ut=ut("WebSocketManager");class q_{constructor(){$(this,"echo",null);$(this,"subscriptions",new Map);$(this,"initialized",!1);$(this,"config",null)}configure(e){if(this.initialized){Ut.warn("[WebSocketManager] 이미 초기화되어 설정을 변경할 수 없습니다.");return}this.config=e,Ut.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){Ut.warn("[WebSocketManager] WebSocket 설정이 없습니다. initTemplateApp에서 websocket 옵션을 전달해주세요.");return}const{appKey:e,host:n="localhost",port:a=80,scheme:i="https",authEndpoint:l="/api/broadcasting/auth"}=this.config,c=Number(a)||80,d=i==="https";Ut.log("[WebSocketManager] 연결 설정:",{host:n,port:c,scheme:i,useTLS:d,authEndpoint:l}),window.Pusher=uy;const f=localStorage.getItem("auth_token"),g={wsHost:n,wsPort:c,wssPort:c,forceTLS:d,disableStats:!0,enabledTransports:["ws","wss"],cluster:"mt1",authEndpoint:l,auth:{headers:{Authorization:f?`Bearer ${f}`:"",Accept:"application/json"}}};Ut.log("[WebSocketManager] Pusher 옵션:",g);const m=new uy(e,g);m.connection.bind("connecting",()=>{Ut.log("[WebSocketManager] 연결 시도 중...")}),m.connection.bind("connected",()=>{Ut.log("[WebSocketManager] 연결 성공! Socket ID:",m.connection.socket_id)}),m.connection.bind("failed",()=>{Ut.error("[WebSocketManager] 연결 실패 - WebSocket을 사용할 수 없습니다.")}),m.connection.bind("error",b=>{Ut.error("[WebSocketManager] 연결 오류:",b)}),m.connection.bind("state_change",b=>{Ut.log(`[WebSocketManager] 상태 변경: ${b.previous} → ${b.current}`)}),m.connection.bind("unavailable",()=>{Ut.error("[WebSocketManager] WebSocket 사용 불가 - 연결할 수 없습니다.")}),m.connection.bind("disconnected",()=>{Ut.warn("[WebSocketManager] 연결이 끊어졌습니다.")}),Ut.log("[WebSocketManager] 초기 연결 상태:",m.connection.state),this.echo=new U_({broadcaster:"reverb",client:m}),Ut.log("[WebSocketManager] 연결 시작 시도..."),m.connect(),window.Echo=this.echo,this.initialized=!0,Ut.log("[WebSocketManager] Echo 초기화 완료")}subscribe(e,n,a,i={}){if(this.initialize(),!this.echo)return Ut.warn("[WebSocketManager] Echo가 초기화되지 않았습니다."),"";const{channelType:l="private"}=i,c=`${e}:${n}`;if(this.subscriptions.has(c))return Ut.log(`[WebSocketManager] 이미 구독 중: ${c}`),c;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(`.${n}`,a),this.subscriptions.set(c,d),Ut.log(`[WebSocketManager] 구독 완료: ${c} (${l})`),c}unsubscribe(e){const n=this.subscriptions.get(e);if(!n)return;const a=e.lastIndexOf(":"),i=a>=0?e.substring(a+1):"";if(i)try{n.stopListening(`.${i}`)}catch(l){Ut.warn(`[WebSocketManager] stopListening 실패: ${e}`,l)}this.subscriptions.delete(e),Ut.log(`[WebSocketManager] 구독 해제: ${e}`)}leaveChannel(e){if(!this.echo)return;this.echo.leave(e);const n=[];this.subscriptions.forEach((a,i)=>{i.startsWith(`${e}:`)&&n.push(i)}),n.forEach(a=>this.subscriptions.delete(a)),Ut.log(`[WebSocketManager] 채널 구독 해제: ${e}`)}disconnect(){this.echo&&(this.echo.disconnect(),this.subscriptions.clear(),this.initialized=!1,Ut.log("[WebSocketManager] 연결 종료"))}getEcho(){return this.echo}isInitialized(){return this.initialized}isConfigured(){return this.config!==null&&!!this.config.appKey}getSubscriptionCount(){return this.subscriptions.size}}const vc=new q_,yt=ut("DataSourceManager"),dy=new xn;function Sc(o,e){const n=Aa(o);if(n!==null)try{return Pn(n)?dy.evaluatePipeExpression(n,e,{skipCache:!0}):dy.evaluateExpression(n,e)}catch(a){return yt.error("Failed to evaluate param expression:",n,a),o}return ns(o,e,{skipCache:!0})}function fy(o){const e={};for(const n of o.keys()){if(n in e)continue;const a=o.getAll(n);a.length>1?e[n]=a:a.length===1&&(n.endsWith("[]")?e[n]=a:e[n]=a[0])}return e}function G_(){try{return window.G7Core?.devTools}catch{return}}const _c=class _c{constructor(e={}){$(this,"options");$(this,"dataCache",new Map);$(this,"bindingEngine");$(this,"globalHeaders",[]);this.options=e,this.bindingEngine=new xn}setGlobalHeaders(e){this.globalHeaders=e||[]}matchesPattern(e,n){if(n==="*")return!0;const a=n.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${a}$`).test(e)}toFormData(e){const n=new FormData;for(const[a,i]of Object.entries(e))i instanceof File||i instanceof Blob?n.append(a,i):i!=null&&n.append(a,typeof i=="object"?JSON.stringify(i):String(i));return n}getMatchingGlobalHeaders(e,n){const a={};for(const i of this.globalHeaders)this.matchesPattern(e,i.pattern)&&Object.entries(i.headers).forEach(([l,c])=>{const d=Sc(c,n);d!=null&&d!==""&&(a[l]=String(d))});return a}filterByCondition(e,n={}){const a=new Set,i=[];for(const l of e){if(a.has(l.id))continue;if(!l.if&&!l.conditions){a.add(l.id),i.push(l);continue}ts({if:l.if,conditions:l.conditions},n,this.bindingEngine,`data_source:${l.id}`)&&(a.add(l.id),i.push(l))}return i}checkErrorCondition(e,n){if(!e.errorCondition?.if||e.errorCondition?.errorCode===void 0)return null;try{const a={response:n};if(ts({if:e.errorCondition.if},a,this.bindingEngine,`errorCondition:${e.id}`))return yt.log(`errorCondition matched for ${e.id}, triggering error ${e.errorCondition.errorCode}`),e.errorCondition.errorCode}catch(a){yt.error(`Failed to evaluate errorCondition for ${e.id}:`,a)}return null}async fetchDataSources(e,n={},a=new URLSearchParams,i,l){const c={},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,n,a,i,l);c[g.id]=m,this.dataCache.set(g.id,{data:m,timestamp:Date.now()});const b=this.checkErrorCondition(g,m);if(b!==null){const S={status:b,message:`Error condition matched for ${g.id}`,data:m},v=vr(),_=v.resolve(b,{errorHandling:g.errorHandling,onError:g.onError});if(_.handler)try{await v.execute(_.handler,S)}catch(A){yt.error(`Error executing errorCondition handler for ${g.id}:`,A)}g.fallback!==void 0&&(c[g.id]=g.fallback,this.dataCache.set(g.id,{data:g.fallback,timestamp:Date.now()}),yt.log(`Using fallback data for ${g.id} (errorCondition)`));return}if(g.onSuccess)try{const S={data:m,sourceId:g.id};await this.executeOnSuccessHandler(g.onSuccess,S)}catch(S){yt.error(`Error executing onSuccess handler for ${g.id}:`,S)}}catch(m){yt.error(`Failed to fetch data source: ${g.id}`,m);const b=m?.response?.status||m?.status||500,S=m?.response?.data,v=S?.message||m.message||"Unknown error",_={status:b,message:v,errors:S?.errors,data:S,statusText:m?.response?.statusText},A=vr(),x=A.resolve(b,{errorHandling:g.errorHandling,onError:g.onError});if(x.handler)try{await A.execute(x.handler,_)}catch(L){yt.error(`Error executing error handler for ${g.id}:`,L)}g.fallback!==void 0&&(c[g.id]=g.fallback,this.dataCache.set(g.id,{data:g.fallback,timestamp:Date.now()}),yt.log(`Using fallback data for ${g.id}`)),this.options.onError&&this.options.onError(m,g)}})),c}async fetchDataSourcesWithResults(e,n={},a=new URLSearchParams,i,l,c){if(e.some(m=>m.type==="websocket")){const m=e.filter(b=>b.type==="websocket").map(b=>b.id).join(", ");yt.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=c?.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,n,a,i,l);this.dataCache.set(m.id,{data:b,timestamp:Date.now()});const S=this.checkErrorCondition(m,b);if(S!==null){const v={status:S,message:`Error condition matched for ${m.id}`,data:b},_=vr(),A=_.resolve(S,{errorHandling:m.errorHandling,onError:m.onError});let x=!1;if(A.handler)if(m.loading_strategy==="blocking")_.execute(A.handler,v).catch(L=>{yt.error(`Error executing errorCondition handler for ${m.id}:`,L)}),x=!0;else try{await _.execute(A.handler,v),x=!0}catch(L){yt.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()}),yt.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: ${S}`),errorCode:S,errorHandled:x}}if(m.onSuccess)try{const v={data:b,sourceId:m.id};await this.executeOnSuccessHandler(m.onSuccess,v)}catch(v){yt.error(`Error executing onSuccess handler for ${m.id}:`,v)}return{id:m.id,state:"success",data:b}}catch(b){yt.error(`Failed to fetch data source: ${m.id}`,b);const S=b?.response?.status||b?.status||500,v=b?.response?.data,_=v?.message||b.message||"Unknown error",A={status:S,message:_,errors:v?.errors,data:v,statusText:b?.response?.statusText},x=vr(),L=x.resolve(S,{errorHandling:m.errorHandling,onError:m.onError});let M=!1;if(L.handler)if(m.loading_strategy==="blocking")x.execute(L.handler,A).catch(R=>{yt.error(`Error executing error handler for ${m.id}:`,R)}),M=!0;else try{await x.execute(L.handler,A),M=!0}catch(R){yt.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()}),yt.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:S,errorHandled:M})}}))}fetchDataSourcesInBackground(e,n={},a=new URLSearchParams,i){e.filter(c=>c.auto_fetch!==!1&&c.loading_strategy==="background"&&c.type!=="websocket").forEach(c=>{this.fetchDataSource(c,n,a).then(async d=>{this.dataCache.set(c.id,{data:d,timestamp:Date.now()});const f=this.checkErrorCondition(c,d);if(f!==null){const g={status:f,message:`Error condition matched for ${c.id}`,data:d},m=vr(),b=m.resolve(f,{errorHandling:c.errorHandling,onError:c.onError});if(b.handler)try{await m.execute(b.handler,g)}catch(S){yt.error(`Error executing errorCondition handler for ${c.id}:`,S)}c.fallback!==void 0&&(this.dataCache.set(c.id,{data:c.fallback,timestamp:Date.now()}),yt.log(`Using fallback data for ${c.id} (errorCondition)`),i&&i(c.id,c.fallback));return}if(c.onSuccess)try{const g={data:d,sourceId:c.id};await this.executeOnSuccessHandler(c.onSuccess,g)}catch(g){yt.error(`Error executing onSuccess handler for ${c.id}:`,g)}i&&i(c.id,d)}).catch(async d=>{yt.error(`Background fetch failed: ${c.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},S=vr(),v=S.resolve(f,{errorHandling:c.errorHandling,onError:c.onError});if(v.handler)try{await S.execute(v.handler,b)}catch(_){yt.error(`Error executing error handler for ${c.id}:`,_)}if(c.fallback!==void 0){this.dataCache.set(c.id,{data:c.fallback,timestamp:Date.now()}),yt.log(`Using fallback data for ${c.id}`),i&&i(c.id,c.fallback);return}this.options.onError&&this.options.onError(d,c)})})}async fetchDataSource(e,n,a,i,l){switch(e.type){case"api":return this.fetchApiDataSource(e,n,a,i,l);case"static":return e.data;case"route_params":return n;case"query_params":return fy(a);default:throw new Error(`Unknown data source type: ${e.type}`)}}async fetchApiDataSource(e,n,a,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 c={route:n,query:fy(a)};i&&(c._global=i),l&&(c._local=l);let d=ns(e.endpoint,c,{skipCache:!0});const f=e.method||"GET",m=(e.contentType?typeof e.contentType=="string"&&e.contentType.includes("{{")?ns(e.contentType,c,{skipCache:!0}):e.contentType:"application/json")==="multipart/form-data";let b=m?{...e.params||{}}:JSON.parse(JSON.stringify(e.params||{}));Object.entries(b).forEach(([_,A])=>{typeof A=="string"&&(b[_]=Sc(A,c))}),Object.keys(b).forEach(_=>{b[_]===""&&delete b[_]});const S=G_();let v=null;if(S?.isEnabled()){S.trackDataSourceDefinition({id:e.id,type:e.type,endpoint:d,method:f,autoFetch:e.auto_fetch,initLocal:e.initLocal,initGlobal:e.initGlobal});let _=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 x=A.toString();_=x?`${d}?${x}`:d}v=S.trackRequest(_,f,{requestBody:f!=="GET"?b:void 0,dataSourceId:e.id}),S.trackDataSourceLoading(e.id)}try{let _;const A=e.auth_mode??(e.auth_required===!0?"required":"none"),x=yr.getInstance().isAuthenticated();if(A==="required"&&!x){yt.log(`[DataSourceManager] Skipping ${e.id}: auth_mode is 'required' but no token available`),S?.isEnabled()&&(S.trackDataSourceError(e.id,"Skipped: auth_mode required but not authenticated"),v&&S.failRequest(v,"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"&&x;if(L){const M=Ir(),R=d.startsWith("/api/")?d.substring(4):d.startsWith("/api")?d.substring(4)||"/":d;this.options.onError&&yt.log(`[DataSourceManager] Normalized endpoint: ${d} -> ${R}`);const D=this.getMatchingGlobalHeaders(d,c),B={};e.headers&&Object.entries(e.headers).forEach(([ge,Ee])=>{const Se=Sc(Ee,c);Se!=null&&Se!==""&&(B[ge]=String(Se))});const q={...D,...B},P=Object.keys(q).length>0,K=m?this.toFormData(b):b;switch(f){case"GET":_=await M.get(R,{params:b,...P&&{headers:q}});break;case"POST":P?_=await M.post(R,K,{headers:q}):_=await M.post(R,K);break;case"PUT":P?_=await M.put(R,K,{headers:q}):_=await M.put(R,K);break;case"PATCH":P?_=await M.patch(R,K,{headers:q}):_=await M.patch(R,K);break;case"DELETE":_=await M.delete(R,{params:b,...P&&{headers:q}});break;default:throw new Error(`Unsupported HTTP method: ${f}`)}}else{let M=d;if(f==="GET"){const K=new URLSearchParams(b).toString();M=K?`${d}?${K}`:d}const R={...m?{}:{"Content-Type":"application/json"},Accept:"application/json"};if(typeof window<"u"){const K=localStorage.getItem("g7_locale");K&&(R["Accept-Language"]=K)}const D=this.getMatchingGlobalHeaders(d,c);Object.assign(R,D),e.headers&&Object.entries(e.headers).forEach(([K,ge])=>{const Ee=Sc(ge,c);Ee!=null&&Ee!==""&&(R[K]=String(Ee))});let B;f!=="GET"&&(m?(B=this.toFormData(b),delete R["Content-Type"]):B=JSON.stringify(b));const q=await fetch(M,{method:f,headers:R,body:B});let P;try{P=await q.json()}catch{P=null}if(v&&S?.isEnabled()&&(S.completeRequest(v,q.status,P),v=null),!q.ok){S?.isEnabled()&&S.trackDataSourceError(e.id,`HTTP ${q.status}: ${q.statusText}`);const K=new Error(`HTTP error! status: ${q.status}`);throw K.response={status:q.status,statusText:q.statusText,data:P},K.status=q.status,K}_=P,S?.isEnabled()&&S.trackDataSourceLoaded(e.id,_)}return L&&v&&S?.isEnabled()&&(S.completeRequest(v,200,_),S.trackDataSourceLoaded(e.id,_)),_}catch(_){if(v&&S?.isEnabled()){const A=_;A?.response?S.completeRequest(v,A.response.status,A.response.data):S.failRequest(v,_ instanceof Error?_.message:String(_)),S.trackDataSourceError(e.id,_ instanceof Error?_.message:String(_))}throw _}}getCachedData(e){const n=this.dataCache.get(e);if(!n)return;if(Date.now()-n.timestamp>_c.DATA_CACHE_TTL){this.dataCache.delete(e);return}return n.data}clearCache(){this.dataCache.clear()}subscribeWebSockets(e,n,a={}){const i=[],l=e.filter(c=>c.type==="websocket");return l.length===0||l.forEach(c=>{if(!c.channel||!c.event){yt.warn(`WebSocket source ${c.id} missing channel or event`);return}let d,f;try{d=ns(c.channel,a,{skipCache:!0}),f=ns(c.event,a,{skipCache:!0})}catch(b){yt.error(`Failed to resolve WebSocket channel/event for source ${c.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)){yt.warn(`WebSocket source ${c.id} has invalid channel/event after expression resolution, skipping. Original channel="${c.channel}", resolved="${d}". Original event="${c.event}", resolved="${f}". Available context keys: [${Object.keys(a).join(", ")}]`);return}const m=vc.subscribe(d,f,b=>{const S=c.target_source||c.id;this.dataCache.set(S,{data:b,timestamp:Date.now()}),n(S,b)},{channelType:c.channel_type||"private"});m&&i.push(m)}),i}unsubscribeWebSockets(e){e.length!==0&&e.forEach(n=>{vc.unsubscribe(n)})}async executeOnSuccessHandler(e,n){const a=this.options.actionDispatcher??cm();if(!a){yt.warn("ActionDispatcher not available, skipping onSuccess handler");return}const i=Array.isArray(e)?e:[e];for(const l of i)try{await a.dispatchAction({type:"click",...l},{data:{response:n}})}catch(c){throw yt.error("Failed to execute onSuccess handler:",c),c}}};$(_c,"DATA_CACHE_TTL",3e5);let Er=_c;const V_=new Er,yi=ut("ModalDataSourceWrapper");function F_(o,e){if(!o||!e)return o;const a=e.replace(/\?\./g,".").split(/\.(?![^\[]*\])/).flatMap(l=>{const c=l.match(/^([^\[]*)((?:\[\d+\])*)$/);if(c){const[,d,f]=c,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 a){if(i==null)return;if(l.startsWith("[")&&l.endsWith("]")){const c=parseInt(l.slice(1,-1),10);i=i[c]}else i=i[l]}return i}const hy=({isOpen:o,modalId:e,dataSources:n,dataContext:a,globalStateUpdater:i,bindingEngine:l,debug:c=!1,children:d})=>{const[f,g]=N.useState(!1),[m,b]=N.useState(!1),S=N.useRef(!1),v=N.useRef(null);v.current||(v.current=new Er);const _=N.useCallback(async()=>{if(!(!n||n.length===0)&&v.current){g(!0);try{const A=a.route||{},x=new URLSearchParams(window.location.search),L=n.map(R=>{let D={...R};if(R.endpoint&&l){const B=l.resolveBindings(R.endpoint,a,{skipCache:!0});D.endpoint=B}if(R.params&&l){const B={};Object.entries(R.params).forEach(([q,P])=>{typeof P=="string"?B[q]=l.resolveBindings(P,a,{skipCache:!0}):B[q]=P}),D.params=B}return D});c&&yi.log(`[ModalDataSourceWrapper] Modal "${e}" fetching data sources:`,L.map(R=>({id:R.id,endpoint:R.endpoint})));const M=await v.current.fetchDataSourcesWithResults(L,A,x);i&&M.forEach(R=>{if(R.state==="success"&&R.data!==void 0){const D=L.find(B=>B.id===R.id);if(D?.initGlobal){const B=R.data?.data??R.data,q=Array.isArray(D.initGlobal)?D.initGlobal:[D.initGlobal];for(const P of q)if(typeof P=="string")i({[P]:B}),c&&yi.log(`[ModalDataSourceWrapper] Modal "${e}" initGlobal: ${R.id}.data -> _global.${P}`);else if(typeof P=="object"&&P.key){const{key:K,path:ge}=P,Ee=ge?F_(B,ge):B;i({[K]:Ee}),c&&yi.log(`Modal "${e}" initGlobal: ${R.id}.data${ge?"."+ge:""} -> _global.${K}`)}}}else R.state==="error"&&yi.error(`Modal "${e}" data source error:`,R.id,R.error)}),c&&yi.log(`Modal "${e}" data sources fetched successfully`)}catch(A){yi.error(`Modal "${e}" data source fetch error:`,A)}finally{g(!1),b(!0)}}},[n,a,i,l,e,c]);return N.useEffect(()=>{if(!n||n.length===0)return;const A=window.__templateApp;return A?.registerModalDataSources&&A.registerModalDataSources(e,n),()=>{A?.unregisterModalDataSources&&A.unregisterModalDataSources(e)}},[e,n]),N.useEffect(()=>{!o&&S.current&&(b(!1),c&&yi.log(`[ModalDataSourceWrapper] Modal "${e}" closed, reset fetch state`)),o&&!S.current&&n&&n.length>0&&!m&&_(),S.current=o},[o,n,m,_,e,c]),dt.jsx(dt.Fragment,{children:d})};class wc extends Error{constructor(n,a,i={}){super(a);$(this,"code");$(this,"userMessageKey");$(this,"showStack");$(this,"icon");$(this,"recoverable");this.name="TemplateEngineError",this.code=n,this.userMessageKey=a,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(n,a){if(!a||!n)return this.userMessageKey;try{return a.translate(this.userMessageKey,n)}catch{return this.userMessageKey}}}class K_ extends wc{constructor(){super("TEMPLATE_NOT_FOUND","$t:core.errors.template_not_found",{showStack:!1,icon:"fa-paint-brush",recoverable:!1}),this.name="TemplateNotFoundError"}}function gy(o){if(o instanceof wc)return o;if(o instanceof Error){const e=new wc("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 wc("TEMPLATE_INIT_ERROR","$t:core.errors.template_init_error",{showStack:!1,icon:"fa-circle-exclamation",recoverable:!0})}const W_=ut("ErrorDisplay");class vf{static render(e,n){const a=document.getElementById(e);if(!a){W_.error(`Container #${e} not found`);return}const i=n.debug&&n.showStack&&n.stackTrace,l=window.matchMedia("(prefers-color-scheme: dark)").matches,c={container:` + `,Kn.error("Error state rendered:",i,a)}getCurrentLayout(){return this.currentLayout}clear(){this.currentLayout=null,this.layoutCache.clear(),Kn.log("Layout data and cache cleared")}}const F_=ht("TranslationContext"),yf=H.createContext(null),vc=({children:o,translationEngine:e,translationContext:n})=>{const a=H.useMemo(()=>(l,c)=>{if(c){const d="|"+Object.entries(c).map(([f,g])=>`${f}=${g}`).join("|");return e.translate(l,n,d)}return e.translate(l,n)},[e,n]),i=H.useMemo(()=>({translationEngine:e,translationContext:n,t:a}),[e,n,a]);return gt.jsx(yf.Provider,{value:i,children:o})},uy=()=>{const o=H.useContext(yf);return o||(F_.warn("TranslationProvider 외부에서 호출되었습니다. 키를 그대로 반환합니다."),{t:e=>e,translationEngine:null,translationContext:null})},La=ht("SlotContext"),K_={registerToSlot:()=>{La.warn("SlotContext not available: registerToSlot called outside SlotProvider")},unregisterFromSlot:()=>{La.warn("SlotContext not available: unregisterFromSlot called outside SlotProvider")},getSlotComponents:()=>[],subscribeToSlot:()=>()=>{},clearAllSlots:()=>{},isEnabled:!1},W_=H.createContext(K_),bf=({children:o})=>{const e=H.useRef(new Map),n=H.useRef(new Map),a=H.useCallback(m=>{const y=n.current.get(m);y&&y.forEach(S=>{try{S()}catch(v){La.error(`Slot subscriber error (slotId: ${m}):`,v)}})},[]),i=H.useCallback((m,y,S)=>{if(!m||!y){La.warn("registerToSlot: slotId and componentId are required");return}e.current.has(m)||e.current.set(m,new Map);const v=e.current.get(m),_=v.get(y);_&&_.registrationKey===S.registrationKey||(v.set(y,S),La.log(`Component registered to slot: ${y} -> ${m} (order: ${S.order})`),a(m))},[a]),l=H.useCallback((m,y)=>{const S=e.current.get(m);S&&S.has(y)&&(S.delete(y),La.log(`Component unregistered from slot: ${y} <- ${m}`),S.size===0&&e.current.delete(m),a(m))},[a]),c=H.useCallback(m=>{const y=e.current.get(m);return y?Array.from(y.values()).sort((S,v)=>S.order-v.order):[]},[]),d=H.useCallback((m,y)=>{n.current.has(m)||n.current.set(m,new Set);const S=n.current.get(m);return S.add(y),()=>{S.delete(y),S.size===0&&n.current.delete(m)}},[]),f=H.useCallback(()=>{e.current.forEach((m,y)=>{a(y)}),e.current.clear(),n.current.clear(),La.log("All slots cleared")},[a]),g=H.useMemo(()=>({registerToSlot:i,unregisterFromSlot:l,getSlotComponents:c,subscribeToSlot:d,clearAllSlots:f,isEnabled:!0}),[i,l,c,d,f]);return H.useLayoutEffect(()=>{typeof window<"u"&&(window.__slotContextValue=g,La.log("SlotContext exposed to window.__slotContextValue"))},[g]),gt.jsx(W_.Provider,{value:g,children:o})};class vf{constructor(){this.notificationCreatedEvent=".Illuminate\\Notifications\\Events\\BroadcastNotificationCreated"}listenForWhisper(e,n){return this.listen(".client-"+e,n)}notification(e){return this.listen(this.notificationCreatedEvent,e)}stopListeningForNotification(e){return this.stopListening(this.notificationCreatedEvent,e)}stopListeningForWhisper(e,n){return this.stopListening(".client-"+e,n)}}class dy{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 Y_(o){try{return Reflect.construct(String,[],o),!0}catch{return!1}}class Sf extends vf{constructor(e,n,a){super(),this.name=n,this.pusher=e,this.options=a,this.eventFormatter=new dy(this.options.namespace),this.subscribe()}subscribe(){this.subscription=this.pusher.subscribe(this.name)}unsubscribe(){this.pusher.unsubscribe(this.name)}listen(e,n){return this.on(this.eventFormatter.format(e),n),this}listenToAll(e){return this.subscription.bind_global((n,a)=>{if(n.startsWith("pusher:"))return;let i=String(this.options.namespace??"").replace(/\./g,"\\"),l=n.startsWith(i)?n.substring(i.length+1):"."+n;e(l,a)}),this}stopListening(e,n){return n?this.subscription.unbind(this.eventFormatter.format(e),n):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",n=>{e(n)}),this}on(e,n){return this.subscription.bind(e,n),this}}class fy extends Sf{whisper(e,n){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,n),this}}class X_ extends Sf{whisper(e,n){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,n),this}}class J_ extends fy{here(e){return this.on("pusher:subscription_succeeded",n=>{e(Object.keys(n.members).map(a=>n.members[a]))}),this}joining(e){return this.on("pusher:member_added",n=>{e(n.info)}),this}whisper(e,n){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,n),this}leaving(e){return this.on("pusher:member_removed",n=>{e(n.info)}),this}}class hy extends vf{constructor(e,n,a){super(),this.events={},this.listeners={},this.name=n,this.socket=e,this.options=a,this.eventFormatter=new dy(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,n){return this.on(this.eventFormatter.format(e),n),this}stopListening(e,n){return this.unbindEvent(this.eventFormatter.format(e),n),this}subscribed(e){return this.on("connect",n=>{e(n)}),this}error(e){return this}on(e,n){return this.listeners[e]=this.listeners[e]||[],this.events[e]||(this.events[e]=(a,i)=>{this.name===a&&this.listeners[e]&&this.listeners[e].forEach(l=>l(i))},this.socket.on(e,this.events[e])),this.listeners[e].push(n),this}unbind(){Object.keys(this.events).forEach(e=>{this.unbindEvent(e)})}unbindEvent(e,n){this.listeners[e]=this.listeners[e]||[],n&&(this.listeners[e]=this.listeners[e].filter(a=>a!==n)),(!n||this.listeners[e].length===0)&&(this.events[e]&&(this.socket.removeListener(e,this.events[e]),delete this.events[e]),delete this.listeners[e])}}class gy extends hy{whisper(e,n){return this.socket.emit("client event",{channel:this.name,event:`client-${e}`,data:n}),this}}class Q_ extends gy{here(e){return this.on("presence:subscribed",n=>{e(n.map(a=>a.user_info))}),this}joining(e){return this.on("presence:joining",n=>e(n.user_info)),this}whisper(e,n){return this.socket.emit("client event",{channel:this.name,event:`client-${e}`,data:n}),this}leaving(e){return this.on("presence:leaving",n=>e(n.user_info)),this}}class Sc extends vf{subscribe(){}unsubscribe(){}listen(e,n){return this}listenToAll(e){return this}stopListening(e,n){return this}subscribed(e){return this}error(e){return this}on(e,n){return this}}class py extends Sc{whisper(e,n){return this}}class Z_ extends Sc{whisper(e,n){return this}}class eA extends py{here(e){return this}joining(e){return this}whisper(e,n){return this}leaving(e){return this}}const Tc=class Tc{constructor(e){this.setOptions(e),this.connect()}setOptions(e){this.options={...Tc._defaultOptions,...e,broadcaster:e.broadcaster};let n=this.csrfToken();n&&(this.options.auth.headers["X-CSRF-TOKEN"]=n,this.options.userAuthentication.headers["X-CSRF-TOKEN"]=n),n=this.options.bearerToken,n&&(this.options.auth.headers.Authorization="Bearer "+n,this.options.userAuthentication.headers.Authorization="Bearer "+n)}csrfToken(){return typeof window<"u"&&window.Laravel?.csrfToken?window.Laravel.csrfToken:this.options.csrfToken?this.options.csrfToken:typeof document<"u"&&typeof document.querySelector=="function"?document.querySelector('meta[name="csrf-token"]')?.getAttribute("content")??null:null}};Tc._defaultOptions={auth:{headers:{}},authEndpoint:"/broadcasting/auth",userAuthentication:{endpoint:"/broadcasting/user-auth",headers:{}},csrfToken:null,bearerToken:null,host:null,key:null,namespace:"App.Events"};let ko=Tc;class wc extends ko{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,n,a){return this.channel(e).listen(n,a)}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 fy(this.pusher,"private-"+e,this.options)),this.channels["private-"+e]}encryptedPrivateChannel(e){return this.channels["private-encrypted-"+e]||(this.channels["private-encrypted-"+e]=new X_(this.pusher,"private-encrypted-"+e,this.options)),this.channels["private-encrypted-"+e]}presenceChannel(e){return this.channels["presence-"+e]||(this.channels["presence-"+e]=new J_(this.pusher,"presence-"+e,this.options)),this.channels["presence-"+e]}leave(e){[e,"private-"+e,"private-encrypted-"+e,"presence-"+e].forEach(n=>{this.leaveChannel(n)})}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 n=()=>{e(this.connectionStatus())},a=["state_change","connected","disconnected"];return a.forEach(i=>{this.pusher.connection.bind(i,n)}),()=>{a.forEach(i=>{this.pusher.connection.unbind(i,n)})}}disconnect(){this.pusher.disconnect()}}class tA extends ko{constructor(){super(...arguments),this.channels={}}connect(){const e=this.getSocketIO();this.socket=e(this.options.host??void 0,this.options),this.socket.io.on("reconnect",()=>{Object.values(this.channels).forEach(n=>{n.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,n,a){return this.channel(e).listen(n,a)}channel(e){return this.channels[e]||(this.channels[e]=new hy(this.socket,e,this.options)),this.channels[e]}privateChannel(e){return this.channels["private-"+e]||(this.channels["private-"+e]=new gy(this.socket,"private-"+e,this.options)),this.channels["private-"+e]}presenceChannel(e){return this.channels["presence-"+e]||(this.channels["presence-"+e]=new Q_(this.socket,"presence-"+e,this.options)),this.channels["presence-"+e]}leave(e){[e,"private-"+e,"presence-"+e].forEach(n=>{this.leaveChannel(n)})}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 n=()=>{e(this.connectionStatus())},a=["connect","disconnect","connect_error","reconnect_attempt","reconnect","reconnect_error","reconnect_failed"];return a.forEach(i=>{this.socket.on(i,n)}),()=>{a.forEach(i=>{this.socket.off(i,n)})}}disconnect(){this.socket.disconnect()}}class my extends ko{constructor(){super(...arguments),this.channels={}}connect(){}listen(e,n,a){return new Sc}channel(e){return new Sc}privateChannel(e){return new py}encryptedPrivateChannel(e){return new Z_}presenceChannel(e){return new eA}leave(e){}leaveChannel(e){}socketId(){return"fake-socket-id"}connectionStatus(){return"connected"}onConnectionChange(e){return()=>{}}disconnect(){}}class nA{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 wc({...this.options,cluster:""});else if(this.options.broadcaster==="pusher")this.connector=new wc(this.options);else if(this.options.broadcaster==="ably")this.connector=new wc({...this.options,cluster:"",broadcaster:"pusher"});else if(this.options.broadcaster==="socket.io")this.connector=new tA(this.options);else if(this.options.broadcaster==="null")this.connector=new my(this.options);else if(typeof this.options.broadcaster=="function"&&Y_(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,n,a){return this.connector.listen(e,n,a)}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 wc||e instanceof my}socketId(){return this.connector.socketId()}connectionStatus(){return this.connector.connectionStatus()}registerInterceptors(){typeof Vue<"u"&&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,n)=>{this.socketId()&&e.headers.set("X-Socket-ID",this.socketId()),n()})}registerAxiosRequestInterceptor(){axios.interceptors.request.use(e=>(this.socketId()&&(e.headers["X-Socket-Id"]=this.socketId()),e))}registerjQueryAjaxSetup(){typeof jQuery.ajax<"u"&&jQuery.ajaxPrefilter((e,n,a)=>{this.socketId()&&a.setRequestHeader("X-Socket-Id",this.socketId())})}registerTurboRequestInterceptor(){document.addEventListener("turbo:before-fetch-request",e=>{e.detail.fetchOptions.headers["X-Socket-Id"]=this.socketId()})}}var wf={exports:{}};var yy;function rA(){return yy||(yy=1,(function(o,e){(function(a,i){o.exports=i()})(self,()=>(()=>{var n={594(c,d){var f=this&&this.__extends||(function(){var M=function(T,D){return M=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(z,P){z.__proto__=P}||function(z,P){for(var q in P)P.hasOwnProperty(q)&&(z[q]=P[q])},M(T,D)};return function(T,D){M(T,D);function z(){this.constructor=T}T.prototype=D===null?Object.create(D):(z.prototype=D.prototype,new z)}})();Object.defineProperty(d,"__esModule",{value:!0});var g=256,m=(function(){function M(T){T===void 0&&(T="="),this._paddingCharacter=T}return M.prototype.encodedLength=function(T){return this._paddingCharacter?(T+2)/3*4|0:(T*8+5)/6|0},M.prototype.encode=function(T){for(var D="",z=0;z>>18&63),D+=this._encodeByte(P>>>12&63),D+=this._encodeByte(P>>>6&63),D+=this._encodeByte(P>>>0&63)}var q=T.length-z;if(q>0){var P=T[z]<<16|(q===2?T[z+1]<<8:0);D+=this._encodeByte(P>>>18&63),D+=this._encodeByte(P>>>12&63),q===2?D+=this._encodeByte(P>>>6&63):D+=this._paddingCharacter||"",D+=this._paddingCharacter||""}return D},M.prototype.maxDecodedLength=function(T){return this._paddingCharacter?T/4*3|0:(T*6+7)/8|0},M.prototype.decodedLength=function(T){return this.maxDecodedLength(T.length-this._getPaddingLength(T))},M.prototype.decode=function(T){if(T.length===0)return new Uint8Array(0);for(var D=this._getPaddingLength(T),z=T.length-D,P=new Uint8Array(this.maxDecodedLength(z)),q=0,W=0,he=0,Ee=0,be=0,Ue=0,Fe=0;W>>4,P[q++]=be<<4|Ue>>>2,P[q++]=Ue<<6|Fe,he|=Ee&g,he|=be&g,he|=Ue&g,he|=Fe&g;if(W>>4,he|=Ee&g,he|=be&g),W>>2,he|=Ue&g),W>>8&6,D+=51-T>>>8&-75,D+=61-T>>>8&-15,D+=62-T>>>8&3,String.fromCharCode(D)},M.prototype._decodeChar=function(T){var D=g;return D+=(42-T&T-44)>>>8&-g+T-43+62,D+=(46-T&T-48)>>>8&-g+T-47+63,D+=(47-T&T-58)>>>8&-g+T-48+52,D+=(64-T&T-91)>>>8&-g+T-65+0,D+=(96-T&T-123)>>>8&-g+T-97+26,D},M.prototype._getPaddingLength=function(T){var D=0;if(this._paddingCharacter){for(var z=T.length-1;z>=0&&T[z]===this._paddingCharacter;z--)D++;if(T.length<4||D>2)throw new Error("Base64Coder: incorrect padding")}return D},M})();d.Coder=m;var y=new m;function S(M){return y.encode(M)}d.encode=S;function v(M){return y.decode(M)}d.decode=v;var _=(function(M){f(T,M);function T(){return M!==null&&M.apply(this,arguments)||this}return T.prototype._encodeByte=function(D){var z=D;return z+=65,z+=25-D>>>8&6,z+=51-D>>>8&-75,z+=61-D>>>8&-13,z+=62-D>>>8&49,String.fromCharCode(z)},T.prototype._decodeChar=function(D){var z=g;return z+=(44-D&D-46)>>>8&-g+D-45+62,z+=(94-D&D-96)>>>8&-g+D-95+63,z+=(47-D&D-58)>>>8&-g+D-48+52,z+=(64-D&D-91)>>>8&-g+D-65+0,z+=(96-D&D-123)>>>8&-g+D-97+26,z},T})(m);d.URLSafeCoder=_;var A=new _;function x(M){return A.encode(M)}d.encodeURLSafe=x;function O(M){return A.decode(M)}d.decodeURLSafe=O,d.encodedLength=function(M){return y.encodedLength(M)},d.maxDecodedLength=function(M){return y.maxDecodedLength(M)},d.decodedLength=function(M){return y.decodedLength(M)}},978(c,d){var f="utf8: invalid source encoding";function g(m){for(var y=[],S=0;S=m.length)throw new Error(f);var A=m[++S];if((A&192)!==128)throw new Error(f);v=(v&31)<<6|A&63,_=128}else if(v<240){if(S>=m.length-1)throw new Error(f);var A=m[++S],x=m[++S];if((A&192)!==128||(x&192)!==128)throw new Error(f);v=(v&15)<<12|(A&63)<<6|x&63,_=2048}else if(v<248){if(S>=m.length-2)throw new Error(f);var A=m[++S],x=m[++S],O=m[++S];if((A&192)!==128||(x&192)!==128||(O&192)!==128)throw new Error(f);v=(v&15)<<18|(A&63)<<12|(x&63)<<6|O&63,_=65536}else throw new Error(f);if(v<_||v>=55296&&v<=57343)throw new Error(f);if(v>=65536){if(v>1114111)throw new Error(f);v-=65536,y.push(String.fromCharCode(55296|v>>10)),v=56320|v&1023}}y.push(String.fromCharCode(v))}return y.join("")}d.D4=g},721(c,d,f){c.exports=f(207).default},207(c,d,f){f.d(d,{default:()=>_s});class g{constructor(b,w){this.lastId=0,this.prefix=b,this.name=w}create(b){this.lastId++;var w=this.lastId,L=this.prefix+w,I=this.name+"["+w+"]",re=!1,me=function(){re||(b.apply(null,arguments),re=!0)};return this[w]=me,{number:w,id:L,name:I,callback:me}}remove(b){delete this[b.number]}}var m=new g("_pusher_script_","Pusher.ScriptReceivers"),y={VERSION:"8.6.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 S=y;class v{constructor(b){this.options=b,this.receivers=b.receivers||m,this.loading={}}load(b,w,L){var I=this;if(I.loading[b]&&I.loading[b].length>0)I.loading[b].push(L);else{I.loading[b]=[L];var re=ze.createScriptRequest(I.getPath(b,w)),me=I.receivers.create(function(Le){if(I.receivers.remove(me),I.loading[b]){var We=I.loading[b];delete I.loading[b];for(var dt=function(Pt){Pt||re.cleanup()},pt=0;pt>>6)+J(128|b&63):J(224|b>>>12&15)+J(128|b>>>6&63)+J(128|b&63)},te=function(E){return E.replace(/[^\x00-\x7F]/g,Me)},pe=function(E){var b=[0,2,1][E.length%3],w=E.charCodeAt(0)<<16|(E.length>1?E.charCodeAt(1):0)<<8|(E.length>2?E.charCodeAt(2):0),L=[ue.charAt(w>>>18),ue.charAt(w>>>12&63),b>=2?"=":ue.charAt(w>>>6&63),b>=1?"=":ue.charAt(w&63)];return L.join("")},N=typeof window<"u"&&window.btoa||function(E){return E.replace(/[\s\S]{1,3}/g,pe)};class R{constructor(b,w,L,I){this.clear=w,this.timer=b(()=>{this.timer&&(this.timer=I(this.timer))},L)}isRunning(){return this.timer!==null}ensureAborted(){this.timer&&(this.clear(this.timer),this.timer=null)}}const de=R;function fe(E){window.clearTimeout(E)}function xe(E){window.clearInterval(E)}class ee extends de{constructor(b,w){super(setTimeout,fe,b,function(L){return w(),null})}}class _e extends de{constructor(b,w){super(setInterval,xe,b,function(L){return w(),L})}}var Be={now(){return Date.now?Date.now():new Date().valueOf()},defer(E){return new ee(0,E)},method(E,...b){var w=Array.prototype.slice.call(arguments,1);return function(L){return L[E].apply(L,w.concat(arguments))}}};const ke=Be;function Ie(E,...b){for(var w=0;w{window.console&&window.console.log&&window.console.log(b)}}debug(...b){this.log(this.globalLog,b)}warn(...b){this.log(this.globalLogWarn,b)}error(...b){this.log(this.globalLogError,b)}globalLogWarn(b){window.console&&window.console.warn?window.console.warn(b):this.globalLog(b)}globalLogError(b){window.console&&window.console.error?window.console.error(b):this.globalLogWarn(b)}log(b,...w){var L=Ct.apply(this,arguments);_s.log?_s.log(L):_s.logToConsole&&b.bind(this)(L)}}const rt=new On;var Hn=function(E,b,w,L,I){(w.headers!==void 0||w.headersProvider!=null)&&rt.warn(`To send headers with the ${L.toString()} request, you must use AJAX, rather than JSONP.`);var re=E.nextAuthCallbackID.toString();E.nextAuthCallbackID++;var me=E.getDocument(),Le=me.createElement("script");E.auth_callbacks[re]=function(pt){I(null,pt)};var We="Pusher.auth_callbacks['"+re+"']";Le.src=w.endpoint+"?callback="+encodeURIComponent(We)+"&"+b;var dt=me.getElementsByTagName("head")[0]||me.documentElement;dt.insertBefore(Le,dt.firstChild)};const bn=Hn;class ra{constructor(b){this.src=b}send(b){var w=this,L="Error loading "+w.src;w.script=document.createElement("script"),w.script.id=b.id,w.script.src=w.src,w.script.type="text/javascript",w.script.charset="UTF-8",w.script.addEventListener?(w.script.onerror=function(){b.callback(L)},w.script.onload=function(){b.callback(null)}):w.script.onreadystatechange=function(){(w.script.readyState==="loaded"||w.script.readyState==="complete")&&b.callback(null)},w.script.async===void 0&&document.attachEvent&&/opera/i.test(navigator.userAgent)?(w.errorScript=document.createElement("script"),w.errorScript.id=b.id+"_error",w.errorScript.text=b.name+"('"+L+"');",w.script.async=w.errorScript.async=!1):w.script.async=!0;var I=document.getElementsByTagName("head")[0];I.insertBefore(w.script,I.firstChild),w.errorScript&&I.insertBefore(w.errorScript,w.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 sr{constructor(b,w){this.url=b,this.data=w}send(b){if(!this.request){var w=Ci(this.data),L=this.url+"/"+b.number+"?"+w;this.request=ze.createScriptRequest(L),this.request.send(b)}}cleanup(){this.request&&this.request.cleanup()}}var cn=function(E,b){return function(w,L){var I="http"+(b?"s":"")+"://",re=I+(E.host||E.options.host)+E.options.path,me=ze.createJSONPRequest(re,w),Le=ze.ScriptReceivers.create(function(We,dt){m.remove(Le),me.cleanup(),dt&&dt.host&&(E.host=dt.host),L&&L(We,dt)});me.send(Le)}},Tn={name:"jsonp",getAgent:cn};const un=Tn;function V(E,b,w){var L=E+(b.useTLS?"s":""),I=b.useTLS?b.hostTLS:b.hostNonTLS;return L+"://"+I+w}function se(E,b){var w="/app/"+E,L="?protocol="+S.PROTOCOL+"&client=js&version="+S.VERSION+(b?"&"+b:"");return w+L}var ce={getInitial:function(E,b){var w=(b.httpPath||"")+se(E,"flash=false");return V("ws",b,w)}},Z={getInitial:function(E,b){var w=(b.httpPath||"/pusher")+se(E);return V("http",b,w)}},ve={getInitial:function(E,b){return V("http",b,b.httpPath||"/pusher")},getPath:function(E,b){return se(E)}};class ge{constructor(){this._callbacks={}}get(b){return this._callbacks[we(b)]}add(b,w,L){var I=we(b);this._callbacks[I]=this._callbacks[I]||[],this._callbacks[I].push({fn:w,context:L})}remove(b,w,L){if(!b&&!w&&!L){this._callbacks={};return}var I=b?[we(b)]:vt(this._callbacks);w||L?this.removeCallback(I,w,L):this.removeAllCallbacks(I)}removeCallback(b,w,L){Oe(b,function(I){this._callbacks[I]=Mt(this._callbacks[I]||[],function(re){return w&&w!==re.fn||L&&L!==re.context}),this._callbacks[I].length===0&&delete this._callbacks[I]},this)}removeAllCallbacks(b){Oe(b,function(w){delete this._callbacks[w]},this)}}function we(E){return"_"+E}class Ae{constructor(b){this.callbacks=new ge,this.global_callbacks=[],this.failThrough=b}bind(b,w,L){return this.callbacks.add(b,w,L),this}bind_global(b){return this.global_callbacks.push(b),this}unbind(b,w,L){return this.callbacks.remove(b,w,L),this}unbind_global(b){return b?(this.global_callbacks=Mt(this.global_callbacks||[],w=>w!==b),this):(this.global_callbacks=[],this)}unbind_all(){return this.unbind(),this.unbind_global(),this}emit(b,w,L){for(var I=0;I0)for(var I=0;I{this.onError(w),this.changeState("closed")}),!1}return this.bindListeners(),rt.debug("Connecting",{transport:this.name,url:b}),this.changeState("connecting"),!0}close(){return this.socket?(this.socket.close(),!0):!1}send(b){return this.state==="open"?(ke.defer(()=>{this.socket&&this.socket.send(b)}),!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(b){this.emit("error",{type:"WebSocketError",error:b}),this.timeline.error(this.buildTimelineMessage({error:b.toString()}))}onClose(b){b?this.changeState("closed",{code:b.code,reason:b.reason,wasClean:b.wasClean}):this.changeState("closed"),this.unbindListeners(),this.socket=void 0}onMessage(b){this.emit("message",b)}onActivity(){this.emit("activity")}bindListeners(){this.socket.onopen=()=>{this.onOpen()},this.socket.onerror=b=>{this.onError(b)},this.socket.onclose=b=>{this.onClose(b)},this.socket.onmessage=b=>{this.onMessage(b)},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(b,w){this.state=b,this.timeline.info(this.buildTimelineMessage({state:b,params:w})),this.emit(b,w)}buildTimelineMessage(b){return Ie({cid:this.id},b)}}class Te{constructor(b){this.hooks=b}isSupported(b){return this.hooks.isSupported(b)}createConnection(b,w,L,I){return new Ke(this.hooks,b,w,L,I)}}var $e=new Te({urls:ce,handlesActivityChecks:!1,supportsPing:!1,isInitialized:function(){return!!ze.getWebSocketAPI()},isSupported:function(){return!!ze.getWebSocketAPI()},getSocket:function(E){return ze.createWebSocket(E)}}),Re={urls:Z,handlesActivityChecks:!1,supportsPing:!0,isInitialized:function(){return!0}},et=Ie({getSocket:function(E){return ze.HTTPFactory.createStreamingSocket(E)}},Re),je=Ie({getSocket:function(E){return ze.HTTPFactory.createPollingSocket(E)}},Re),Ve={isSupported:function(){return ze.isXHRSupported()}},Se=new Te(Ie({},et,Ve)),He=new Te(Ie({},je,Ve)),tt={ws:$e,xhr_streaming:Se,xhr_polling:He};const Tt=tt;var It=new Te({file:"sockjs",urls:ve,handlesActivityChecks:!0,supportsPing:!1,isSupported:function(){return!0},isInitialized:function(){return window.SockJS!==void 0},getSocket:function(E,b){return new window.SockJS(E,null,{js_path:A.getPath("sockjs",{useTLS:b.useTLS}),ignore_null_origin:b.ignoreNullOrigin})},beforeOpen:function(E,b){E.send(JSON.stringify({path:b}))}}),Ln={isSupported:function(E){var b=ze.isXDRSupported(E.useTLS);return b}},zt=new Te(Ie({},et,Ln)),Ut=new Te(Ie({},je,Ln));Tt.xdr_streaming=zt,Tt.xdr_polling=Ut,Tt.sockjs=It;const Rn=Tt;class $a extends Ae{constructor(){super();var b=this;typeof window<"u"&&window.addEventListener!==void 0&&(window.addEventListener("online",function(){b.emit("online")},!1),window.addEventListener("offline",function(){b.emit("offline")},!1))}isOnline(){return window.navigator.onLine===void 0?!0:window.navigator.onLine}}var jo=new $a;class Rf{constructor(b,w,L){this.manager=b,this.transport=w,this.minPingDelay=L.minPingDelay,this.maxPingDelay=L.maxPingDelay,this.pingDelay=void 0}createConnection(b,w,L,I){I=Ie({},I,{activityTimeout:this.pingDelay});var re=this.transport.createConnection(b,w,L,I),me=null,Le=function(){re.unbind("open",Le),re.bind("closed",We),me=ke.now()},We=dt=>{if(re.unbind("closed",We),dt.code===1002||dt.code===1003)this.manager.reportDeath();else if(!dt.wasClean&&me){var pt=ke.now()-me;pt<2*this.maxPingDelay&&(this.manager.reportDeath(),this.pingDelay=Math.max(pt/2,this.minPingDelay))}};return re.bind("open",Le),re}isSupported(b){return this.manager.isAlive()&&this.transport.isSupported(b)}}const kc={decodeMessage:function(E){try{var b=JSON.parse(E.data),w=b.data;if(typeof w=="string")try{w=JSON.parse(b.data)}catch{}var L={event:b.event,channel:b.channel,data:w};return b.user_id&&(L.user_id=b.user_id),L}catch(I){throw{type:"MessageParseError",error:I,data:E.data}}},encodeMessage:function(E){return JSON.stringify(E)},processHandshake:function(E){var b=kc.decodeMessage(E);if(b.event==="pusher:connection_established"){if(!b.data.activity_timeout)throw"No activity timeout specified in handshake";return{action:"connected",id:b.data.socket_id,activityTimeout:b.data.activity_timeout*1e3}}else{if(b.event==="pusher:error")return{action:this.getCloseAction(b.data),error:this.getCloseError(b.data)};throw"Invalid handshake"}},getCloseAction:function(E){return E.code<4e3?E.code>=1002&&E.code<=1004?"backoff":null:E.code===4e3?"tls_only":E.code<4100?"refused":E.code<4200?"backoff":E.code<4300?"retry":"refused"},getCloseError:function(E){return E.code!==1e3&&E.code!==1001?{type:"PusherError",data:{code:E.code,message:E.reason||E.message}}:null}},qr=kc;class Ei extends Ae{constructor(b,w){super(),this.id=b,this.transport=w,this.activityTimeout=w.activityTimeout,this.bindListeners()}handlesActivityChecks(){return this.transport.handlesActivityChecks()}send(b){return this.transport.send(b)}send_event(b,w,L){var I={event:b,data:w};return L&&(I.channel=L),rt.debug("Event sent",I),this.send(qr.encodeMessage(I))}ping(){this.transport.supportsPing()?this.transport.ping():this.send_event("pusher:ping",{})}close(){this.transport.close()}bindListeners(){var b={message:L=>{var I;try{I=qr.decodeMessage(L)}catch(re){this.emit("error",{type:"MessageParseError",error:re,data:L.data})}if(I!==void 0){switch(rt.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:L=>{this.emit("error",L)},closed:L=>{w(),L&&L.code&&this.handleCloseEvent(L),this.transport=null,this.emit("closed")}},w=()=>{Ot(b,(L,I)=>{this.transport.unbind(I,L)})};Ot(b,(L,I)=>{this.transport.bind(I,L)})}handleCloseEvent(b){var w=qr.getCloseAction(b),L=qr.getCloseError(b);L&&this.emit("error",L),w&&this.emit(w,{action:w,error:L})}}class zo{constructor(b,w){this.transport=b,this.callback=w,this.bindListeners()}close(){this.unbindListeners(),this.transport.close()}bindListeners(){this.onMessage=b=>{this.unbindListeners();var w;try{w=qr.processHandshake(b)}catch(L){this.finish("error",{error:L}),this.transport.close();return}w.action==="connected"?this.finish("connected",{connection:new Ei(w.id,this.transport),activityTimeout:w.activityTimeout}):(this.finish(w.action,{error:w.error}),this.transport.close())},this.onClosed=b=>{this.unbindListeners();var w=qr.getCloseAction(b)||"backoff",L=qr.getCloseError(b);this.finish(w,{error:L})},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(b,w){this.callback(Ie({transport:this.transport,action:b},w))}}class Na{constructor(b,w){this.timeline=b,this.options=w||{}}send(b,w){this.timeline.isEmpty()||this.timeline.send(ze.TimelineTransport.getAgent(this,b),w)}}class Gr extends Ae{constructor(b,w){super(function(L,I){rt.debug("No callbacks on "+b+" for "+L)}),this.name=b,this.pusher=w,this.subscribed=!1,this.subscriptionPending=!1,this.subscriptionCancelled=!1}authorize(b,w){return w(null,{auth:""})}trigger(b,w){if(b.indexOf("client-")!==0)throw new D("Event '"+b+"' does not start with 'client-'");if(!this.subscribed){var L=M.buildLogSuffix("triggeringClientEvents");rt.warn(`Client event triggered before channel 'subscription_succeeded' event . ${L}`)}return this.pusher.send_event(b,w,this.name)}disconnect(){this.subscribed=!1,this.subscriptionPending=!1}handleEvent(b){var w=b.event,L=b.data;if(w==="pusher_internal:subscription_succeeded")this.handleSubscriptionSucceededEvent(b);else if(w==="pusher_internal:subscription_count")this.handleSubscriptionCountEvent(b);else if(w.indexOf("pusher_internal:")!==0){var I={};this.emit(w,L,I)}}handleSubscriptionSucceededEvent(b){this.subscriptionPending=!1,this.subscribed=!0,this.subscriptionCancelled?this.pusher.unsubscribe(this.name):this.emit("pusher:subscription_succeeded",b.data)}handleSubscriptionCountEvent(b){b.data.subscription_count&&(this.subscriptionCount=b.data.subscription_count),this.emit("pusher:subscription_count",b.data)}subscribe(){this.subscribed||(this.subscriptionPending=!0,this.subscriptionCancelled=!1,this.authorize(this.pusher.connection.socket_id,(b,w)=>{b?(this.subscriptionPending=!1,rt.error(b.toString()),this.emit("pusher:subscription_error",Object.assign({},{type:"AuthError",error:b.message},b instanceof Ue?{status:b.status}:{}))):this.pusher.send_event("pusher:subscribe",{auth:w.auth,channel_data:w.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 aa extends Gr{authorize(b,w){return this.pusher.config.channelAuthorizer({channelName:this.name,socketId:b},w)}}class Ia{constructor(){this.reset()}get(b){return Object.prototype.hasOwnProperty.call(this.members,b)?{id:b,info:this.members[b]}:null}each(b){Ot(this.members,(w,L)=>{b(this.get(L))})}setMyID(b){this.myID=b}onSubscription(b){this.members=b.presence.hash,this.count=b.presence.count,this.me=this.get(this.myID)}addMember(b){return this.get(b.user_id)===null&&this.count++,this.members[b.user_id]=b.user_info,this.get(b.user_id)}removeMember(b){var w=this.get(b.user_id);return w&&(delete this.members[b.user_id],this.count--),w}reset(){this.members={},this.count=0,this.myID=null,this.me=null}}var Zt=function(E,b,w,L){function I(re){return re instanceof w?re:new w(function(me){me(re)})}return new(w||(w=Promise))(function(re,me){function Le(pt){try{dt(L.next(pt))}catch(Pt){me(Pt)}}function We(pt){try{dt(L.throw(pt))}catch(Pt){me(Pt)}}function dt(pt){pt.done?re(pt.value):I(pt.value).then(Le,We)}dt((L=L.apply(E,b||[])).next())})};class Dc extends aa{constructor(b,w){super(b,w),this.members=new Ia}authorize(b,w){super.authorize(b,(L,I)=>Zt(this,void 0,void 0,function*(){if(!L)if(I=I,I.channel_data!=null){var re=JSON.parse(I.channel_data);this.members.setMyID(re.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 me=M.buildLogSuffix("authorizationEndpoint");rt.error(`Invalid auth response for channel '${this.name}', expected 'channel_data' field. ${me}, or the user should be signed in.`),w("Invalid auth response");return}w(L,I)}))}handleEvent(b){var w=b.event;if(w.indexOf("pusher_internal:")===0)this.handleInternalEvent(b);else{var L=b.data,I={};b.user_id&&(I.user_id=b.user_id),this.emit(w,L,I)}}handleInternalEvent(b){var w=b.event,L=b.data;switch(w){case"pusher_internal:subscription_succeeded":this.handleSubscriptionSucceededEvent(b);break;case"pusher_internal:subscription_count":this.handleSubscriptionCountEvent(b);break;case"pusher_internal:member_added":var I=this.members.addMember(L);this.emit("pusher:member_added",I);break;case"pusher_internal:member_removed":var re=this.members.removeMember(L);re&&this.emit("pusher:member_removed",re);break}}handleSubscriptionSucceededEvent(b){this.subscriptionPending=!1,this.subscribed=!0,this.subscriptionCancelled?this.pusher.unsubscribe(this.name):(this.members.onSubscription(b.data),this.emit("pusher:subscription_succeeded",this.members))}disconnect(){this.members.reset(),super.disconnect()}}var Oc=f(978),Tr=f(594);class Ha extends aa{constructor(b,w,L){super(b,w),this.key=null,this.nacl=L}authorize(b,w){super.authorize(b,(L,I)=>{if(L){w(L,I);return}let re=I.shared_secret;if(!re){w(new Error(`No shared_secret key in auth payload for encrypted channel: ${this.name}`),null);return}this.key=(0,Tr.decode)(re),delete I.shared_secret,w(null,I)})}trigger(b,w){throw new he("Client events are not currently supported for encrypted channels")}handleEvent(b){var w=b.event,L=b.data;if(w.indexOf("pusher_internal:")===0||w.indexOf("pusher:")===0){super.handleEvent(b);return}this.handleEncryptedEvent(w,L)}handleEncryptedEvent(b,w){if(!this.key){rt.debug("Received encrypted event before key has been retrieved from the authEndpoint");return}if(!w.ciphertext||!w.nonce){rt.error("Unexpected format for encrypted event, expected object with `ciphertext` and `nonce` fields, got: "+w);return}let L=(0,Tr.decode)(w.ciphertext);if(L.length{if(me){rt.error(`Failed to make a request to the authEndpoint: ${Le}. Unable to fetch new key, so dropping encrypted event`);return}if(re=this.nacl.secretbox.open(L,I,this.key),re===null){rt.error("Failed to decrypt event with new key. Dropping encrypted event");return}this.emit(b,this.getDataToEmit(re))});return}this.emit(b,this.getDataToEmit(re))}getDataToEmit(b){let w=(0,Oc.D4)(b);try{return JSON.parse(w)}catch{return w}}}class kf extends Ae{constructor(b,w){super(),this.state="initialized",this.connection=null,this.key=b,this.options=w,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 L=ze.getNetwork();L.bind("online",()=>{this.timeline.info({netinfo:"online"}),(this.state==="connecting"||this.state==="unavailable")&&this.retryIn(0)}),L.bind("offline",()=>{this.timeline.info({netinfo:"offline"}),this.connection&&this.sendActivityCheck()}),this.updateStrategy()}switchCluster(b){this.key=b,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(b){return this.connection?this.connection.send(b):!1}send_event(b,w,L){return this.connection?this.connection.send_event(b,w,L):!1}disconnect(){this.disconnectInternally(),this.updateState("disconnected")}isUsingTLS(){return this.usingTLS}startConnecting(){var b=(w,L)=>{w?this.runner=this.strategy.connect(0,b):L.action==="error"?(this.emit("error",{type:"HandshakeError",error:L.error}),this.timeline.error({handshakeError:L.error})):(this.abortConnecting(),this.handshakeCallbacks[L.action](L))};this.runner=this.strategy.connect(0,b)}abortConnecting(){this.runner&&(this.runner.abort(),this.runner=null)}disconnectInternally(){if(this.abortConnecting(),this.clearRetryTimer(),this.clearUnavailableTimer(),this.connection){var b=this.abandonConnection();b.close()}}updateStrategy(){this.strategy=this.options.getStrategy({key:this.key,timeline:this.timeline,useTLS:this.usingTLS})}retryIn(b){this.timeline.info({action:"retry",delay:b}),b>0&&this.emit("connecting_in",Math.round(b/1e3)),this.retryTimer=new ee(b||0,()=>{this.disconnectInternally(),this.connect()})}clearRetryTimer(){this.retryTimer&&(this.retryTimer.ensureAborted(),this.retryTimer=null)}setUnavailableTimer(){this.unavailableTimer=new ee(this.options.unavailableTimeout,()=>{this.updateState("unavailable")})}clearUnavailableTimer(){this.unavailableTimer&&this.unavailableTimer.ensureAborted()}sendActivityCheck(){this.stopActivityCheck(),this.connection.ping(),this.activityTimer=new ee(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 ee(this.activityTimeout,()=>{this.sendActivityCheck()}))}stopActivityCheck(){this.activityTimer&&this.activityTimer.ensureAborted()}buildConnectionCallbacks(b){return Ie({},b,{message:w=>{this.resetActivityCheck(),this.emit("message",w)},ping:()=>{this.send_event("pusher:pong",{})},activity:()=>{this.resetActivityCheck()},error:w=>{this.emit("error",w)},closed:()=>{this.abandonConnection(),this.shouldRetry()&&this.retryIn(1e3)}})}buildHandshakeCallbacks(b){return Ie({},b,{connected:w=>{this.activityTimeout=Math.min(this.options.activityTimeout,w.activityTimeout,w.connection.activityTimeout||1/0),this.clearUnavailableTimer(),this.setConnection(w.connection),this.socket_id=this.connection.id,this.updateState("connected",{socket_id:this.socket_id})}})}buildErrorCallbacks(){let b=w=>L=>{L.error&&this.emit("error",{type:"WebSocketError",error:L.error}),w(L)};return{tls_only:b(()=>{this.usingTLS=!0,this.updateStrategy(),this.retryIn(0)}),refused:b(()=>{this.disconnect()}),backoff:b(()=>{this.retryIn(1e3)}),retry:b(()=>{this.retryIn(0)})}}setConnection(b){this.connection=b;for(var w in this.connectionCallbacks)this.connection.bind(w,this.connectionCallbacks[w]);this.resetActivityCheck()}abandonConnection(){if(this.connection){this.stopActivityCheck();for(var b in this.connectionCallbacks)this.connection.unbind(b,this.connectionCallbacks[b]);var w=this.connection;return this.connection=null,w}}updateState(b,w){var L=this.state;if(this.state=b,L!==b){var I=b;I==="connected"&&(I+=" with new socket ID "+w.socket_id),rt.debug("State changed",L+" -> "+I),this.timeline.info({state:b,params:w}),this.emit("state_change",{previous:L,current:b}),this.emit(b,w)}}shouldRetry(){return this.state==="connecting"||this.state==="connected"}}class Lc{constructor(){this.channels={}}add(b,w){return this.channels[b]||(this.channels[b]=Mc(b,w)),this.channels[b]}all(){return _t(this.channels)}find(b){return this.channels[b]}remove(b){var w=this.channels[b];return delete this.channels[b],w}disconnect(){Ot(this.channels,function(b){b.disconnect()})}}function Mc(E,b){if(E.indexOf("private-encrypted-")===0){if(b.config.nacl)return jn.createEncryptedChannel(E,b,b.config.nacl);let w="Tried to subscribe to a private-encrypted- channel but no nacl implementation available",L=M.buildLogSuffix("encryptedChannelSupport");throw new he(`${w}. ${L}`)}else{if(E.indexOf("private-")===0)return jn.createPrivateChannel(E,b);if(E.indexOf("presence-")===0)return jn.createPresenceChannel(E,b);if(E.indexOf("#")===0)throw new z('Cannot create a channel with name "'+E+'".');return jn.createChannel(E,b)}}var Df={createChannels(){return new Lc},createConnectionManager(E,b){return new kf(E,b)},createChannel(E,b){return new Gr(E,b)},createPrivateChannel(E,b){return new aa(E,b)},createPresenceChannel(E,b){return new Dc(E,b)},createEncryptedChannel(E,b,w){return new Ha(E,b,w)},createTimelineSender(E,b){return new Na(E,b)},createHandshake(E,b){return new zo(E,b)},createAssistantToTheTransportManager(E,b,w){return new Rf(E,b,w)}};const jn=Df;class _i{constructor(b){this.options=b||{},this.livesLeft=this.options.lives||1/0}getAssistant(b){return jn.createAssistantToTheTransportManager(this,b,{minPingDelay:this.options.minPingDelay,maxPingDelay:this.options.maxPingDelay})}isAlive(){return this.livesLeft>0}reportDeath(){this.livesLeft-=1}}class vn{constructor(b,w){this.strategies=b,this.loop=!!w.loop,this.failFast=!!w.failFast,this.timeout=w.timeout,this.timeoutLimit=w.timeoutLimit}isSupported(){return ln(this.strategies,ke.method("isSupported"))}connect(b,w){var L=this.strategies,I=0,re=this.timeout,me=null,Le=(We,dt)=>{dt?w(null,dt):(I=I+1,this.loop&&(I=I%L.length),I0&&(re=new ee(L.timeout,function(){me.abort(),I(!0)})),me=b.connect(w,function(Le,We){Le&&re&&re.isRunning()&&!L.failFast||(re&&re.ensureAborted(),I(Le,We))}),{abort:function(){re&&re.ensureAborted(),me.abort()},forceMinPriority:function(Le){me.forceMinPriority(Le)}}}}class kn{constructor(b){this.strategies=b}isSupported(){return ln(this.strategies,ke.method("isSupported"))}connect(b,w){return $c(this.strategies,b,function(L,I){return function(re,me){if(I[L].error=re,re){Of(I)&&w(!0);return}Oe(I,function(Le){Le.forceMinPriority(me.transport.priority)}),w(null,me)}})}}function $c(E,b,w){var L=nt(E,function(I,re,me,Le){return I.connect(b,w(re,Le))});return{abort:function(){Oe(L,Uo)},forceMinPriority:function(I){Oe(L,function(re){re.forceMinPriority(I)})}}}function Of(E){return Br(E,function(b){return!!b.error})}function Uo(E){!E.error&&!E.aborted&&(E.abort(),E.aborted=!0)}class Nc{constructor(b,w,L){this.strategy=b,this.transports=w,this.ttl=L.ttl||18e5,this.usingTLS=L.useTLS,this.timeline=L.timeline}isSupported(){return this.strategy.isSupported()}connect(b,w){var L=this.usingTLS,I=Lf(L),re=I&&I.cacheSkipCount?I.cacheSkipCount:0,me=[this.strategy];if(I&&I.timestamp+this.ttl>=ke.now()){var Le=this.transports[I.transport];Le&&(["ws","wss"].includes(I.transport)||re>3?(this.timeline.info({cached:!0,transport:I.transport,latency:I.latency}),me.push(new vn([Le],{timeout:I.latency*2+1e3,failFast:!0}))):re++)}var We=ke.now(),dt=me.pop().connect(b,function pt(Pt,Or){Pt?(vs(L),me.length>0?(We=ke.now(),dt=me.pop().connect(b,pt)):w(Pt)):(zn(L,Or.transport.name,ke.now()-We,re),w(null,Or))});return{abort:function(){dt.abort()},forceMinPriority:function(pt){b=pt,dt&&dt.forceMinPriority(pt)}}}}function ja(E){return"pusherTransport"+(E?"TLS":"NonTLS")}function Lf(E){var b=ze.getLocalStorage();if(b)try{var w=b[ja(E)];if(w)return JSON.parse(w)}catch{vs(E)}return null}function zn(E,b,w,L){var I=ze.getLocalStorage();if(I)try{I[ja(E)]=yn({timestamp:ke.now(),transport:b,latency:w,cacheSkipCount:L})}catch{}}function vs(E){var b=ze.getLocalStorage();if(b)try{delete b[ja(E)]}catch{}}class Ai{constructor(b,{delay:w}){this.strategy=b,this.options={delay:w}}isSupported(){return this.strategy.isSupported()}connect(b,w){var L=this.strategy,I,re=new ee(this.options.delay,function(){I=L.connect(b,w)});return{abort:function(){re.ensureAborted(),I&&I.abort()},forceMinPriority:function(me){b=me,I&&I.forceMinPriority(me)}}}}class ia{constructor(b,w,L){this.test=b,this.trueBranch=w,this.falseBranch=L}isSupported(){var b=this.test()?this.trueBranch:this.falseBranch;return b.isSupported()}connect(b,w){var L=this.test()?this.trueBranch:this.falseBranch;return L.connect(b,w)}}class za{constructor(b){this.strategy=b}isSupported(){return this.strategy.isSupported()}connect(b,w){var L=this.strategy.connect(b,function(I,re){re&&L.abort(),w(I,re)});return L}}function Ua(E){return function(){return E.isSupported()}}var Ic=function(E,b,w){var L={};function I(el,Xc,Jc,Zf,eh){var Qc=w(E,el,Xc,Jc,Zf,eh);return L[el]=Qc,Qc}var re=Object.assign({},b,{hostNonTLS:E.wsHost+":"+E.wsPort,hostTLS:E.wsHost+":"+E.wssPort,httpPath:E.wsPath}),me=Object.assign({},re,{useTLS:!0}),Le=Object.assign({},b,{hostNonTLS:E.httpHost+":"+E.httpPort,hostTLS:E.httpHost+":"+E.httpsPort,httpPath:E.httpPath}),We={loop:!0,timeout:15e3,timeoutLimit:6e4},dt=new _i({minPingDelay:1e4,maxPingDelay:E.activityTimeout}),pt=new _i({lives:2,minPingDelay:1e4,maxPingDelay:E.activityTimeout}),Pt=I("ws","ws",3,re,dt),Or=I("wss","ws",3,me,dt),Xf=I("sockjs","sockjs",1,Le),Wc=I("xhr_streaming","xhr_streaming",1,Le,pt),Jf=I("xdr_streaming","xdr_streaming",1,Le,pt),Jo=I("xhr_polling","xhr_polling",1,Le),Yc=I("xdr_polling","xdr_polling",1,Le),qa=new vn([Pt],We),Oi=new vn([Or],We),Qf=new vn([Xf],We),Li=new vn([new ia(Ua(Wc),Wc,Jf)],We),Qo=new vn([new ia(Ua(Jo),Jo,Yc)],We),Zo=new vn([new ia(Ua(Li),new kn([Li,new Ai(Qo,{delay:4e3})]),Qo)],We),Mi=new ia(Ua(Zo),Zo,Qf),$i;return b.useTLS?$i=new kn([qa,new Ai(Mi,{delay:2e3})]):$i=new kn([qa,new Ai(Oi,{delay:2e3}),new Ai(Mi,{delay:5e3})]),new Nc(new za(new ia(Ua(Pt),$i,Mi)),L,{ttl:18e5,timeline:b.timeline,useTLS:b.useTLS})};const Pa=Ic;function Mf(){var E=this;E.timeline.info(E.buildTimelineMessage({transport:E.name+(E.options.useTLS?"s":"")})),E.hooks.isInitialized()?E.changeState("initialized"):E.hooks.file?(E.changeState("initializing"),A.load(E.hooks.file,{useTLS:E.options.useTLS},function(b,w){E.hooks.isInitialized()?(E.changeState("initialized"),w(!0)):(b&&E.onError(b),E.onClose(),w(!1))})):E.onClose()}var Hc={getRequest:function(E){var b=new window.XDomainRequest;return b.ontimeout=function(){E.emit("error",new P),E.close()},b.onerror=function(w){E.emit("error",w),E.close()},b.onprogress=function(){b.responseText&&b.responseText.length>0&&E.onChunk(200,b.responseText)},b.onload=function(){b.responseText&&b.responseText.length>0&&E.onChunk(200,b.responseText),E.emit("finished",200),E.close()},b},abortRequest:function(E){E.ontimeout=E.onerror=E.onprogress=E.onload=null,E.abort()}};const jc=Hc,Po=256*1024;class $f extends Ae{constructor(b,w,L){super(),this.hooks=b,this.method=w,this.url=L}start(b){this.position=0,this.xhr=this.hooks.getRequest(this),this.unloader=()=>{this.close()},ze.addUnloadListener(this.unloader),this.xhr.open(this.method,this.url,!0),this.xhr.setRequestHeader&&this.xhr.setRequestHeader("Content-Type","application/json"),this.xhr.send(b)}close(){this.unloader&&(ze.removeUnloadListener(this.unloader),this.unloader=null),this.xhr&&(this.hooks.abortRequest(this.xhr),this.xhr=null)}onChunk(b,w){for(;;){var L=this.advanceBuffer(w);if(L)this.emit("chunk",{status:b,data:L});else break}this.isBufferTooLong(w)&&this.emit("buffer_too_long")}advanceBuffer(b){var w=b.slice(this.position),L=w.indexOf(` +`);return L!==-1?(this.position+=L+1,w.slice(0,L)):null}isBufferTooLong(b){return this.position===b.length&&b.length>Po}}var Bo;(function(E){E[E.CONNECTING=0]="CONNECTING",E[E.OPEN=1]="OPEN",E[E.CLOSED=3]="CLOSED"})(Bo||(Bo={}));const or=Bo;var Rr=1;class qo{constructor(b,w){this.hooks=b,this.session=Ss(1e3)+"/"+Uc(8),this.location=Go(w),this.readyState=or.CONNECTING,this.openStream()}send(b){return this.sendRaw(JSON.stringify([b]))}ping(){this.hooks.sendHeartbeat(this)}close(b,w){this.onClose(b,w,!0)}sendRaw(b){if(this.readyState===or.OPEN)try{return ze.createSocketRequest("POST",sa(Ba(this.location,this.session))).start(b),!0}catch{return!1}else return!1}reconnect(){this.closeStream(),this.openStream()}onClose(b,w,L){this.closeStream(),this.readyState=or.CLOSED,this.onclose&&this.onclose({code:b,reason:w,wasClean:L})}onChunk(b){if(b.status===200){this.readyState===or.OPEN&&this.onActivity();var w,L=b.data.slice(0,1);switch(L){case"o":w=JSON.parse(b.data.slice(1)||"{}"),this.onOpen(w);break;case"a":w=JSON.parse(b.data.slice(1)||"[]");for(var I=0;I{this.onChunk(b)}),this.stream.bind("finished",b=>{this.hooks.onFinished(this,b)}),this.stream.bind("buffer_too_long",()=>{this.reconnect()});try{this.stream.start()}catch(b){ke.defer(()=>{this.onError(b),this.onClose(1006,"Could not start streaming",!1)})}}closeStream(){this.stream&&(this.stream.unbind_all(),this.stream.close(),this.stream=null)}}function Go(E){var b=/([^\?]*)\/*(\??.*)/.exec(E);return{base:b[1],queryString:b[2]}}function Ba(E,b){return E.base+"/"+b+"/xhr_send"}function sa(E){var b=E.indexOf("?")===-1?"?":"&";return E+b+"t="+ +new Date+"&n="+Rr++}function zc(E,b){var w=/(https?:\/\/)([^\/:]+)((\/|:)?.*)/.exec(E);return w[1]+b+w[3]}function Ss(E){return ze.randomInt(E)}function Uc(E){for(var b=[],w=0;w0&&E.onChunk(w.status,w.responseText);break;case 4:w.responseText&&w.responseText.length>0&&E.onChunk(w.status,w.responseText),E.emit("finished",w.status),E.close();break}},w},abortRequest:function(E){E.onreadystatechange=null,E.abort()}};const ws=Fo;var Pc={createStreamingSocket(E){return this.createSocket(Vo,E)},createPollingSocket(E){return this.createSocket(Vr,E)},createSocket(E,b){return new xi(E,b)},createXHR(E,b){return this.createRequest(ws,E,b)},createRequest(E,b,w){return new $f(E,b,w)}};const Ri=Pc;Ri.createXDR=function(E,b){return this.createRequest(jc,E,b)};var Bc={nextAuthCallbackID:1,auth_callbacks:{},ScriptReceivers:m,DependenciesReceivers:_,getDefaultStrategy:Pa,Transports:Rn,transportConnectionInitializer:Mf,HTTPFactory:Ri,TimelineTransport:un,getXHRAPI(){return window.XMLHttpRequest},getWebSocketAPI(){return window.WebSocket||window.MozWebSocket},setup(E){if(typeof window<"u"){window.Pusher=E;var b=()=>{this.onDocumentBody(E.ready)};window.JSON?b():A.load("json2",{},b)}},getDocument(){return document},getProtocol(){return this.getDocument().location.protocol},getAuthorizers(){return{ajax:Ge,jsonp:bn}},onDocumentBody(E){document.body?E():setTimeout(()=>{this.onDocumentBody(E)},0)},createJSONPRequest(E,b){return new sr(E,b)},createScriptRequest(E){return new ra(E)},getLocalStorage(){try{return window.localStorage}catch{return}},createXHR(){return this.getXHRAPI()?this.createXMLHttpRequest():this.createMicrosoftXHR()},createXMLHttpRequest(){var E=this.getXHRAPI();return new E},createMicrosoftXHR(){return new ActiveXObject("Microsoft.XMLHTTP")},getNetwork(){return jo},createWebSocket(E){var b=this.getWebSocketAPI();return new b(E)},createSocketRequest(E,b){if(this.isXHRSupported())return this.HTTPFactory.createXHR(E,b);if(this.isXDRSupported(b.indexOf("https:")===0))return this.HTTPFactory.createXDR(E,b);throw"Cross-origin HTTP requests are not supported"},isXHRSupported(){var E=this.getXHRAPI();return!!E&&new E().withCredentials!==void 0},isXDRSupported(E){var b=E?"https:":"http:",w=this.getProtocol();return!!window.XDomainRequest&&w===b},addUnloadListener(E){window.addEventListener!==void 0?window.addEventListener("pagehide",E,!1):window.attachEvent!==void 0&&window.attachEvent("onunload",E)},removeUnloadListener(E){window.addEventListener!==void 0?window.removeEventListener("pagehide",E,!1):window.detachEvent!==void 0&&window.detachEvent("onunload",E)},randomInt(E){const b=window.crypto||window.msCrypto,w=Math.floor(Math.pow(2,32)/E)*E;let L;do L=b.getRandomValues(new Uint32Array(1))[0];while(L>=w);return L%E}};const ze=Bc;var Dr;(function(E){E[E.ERROR=3]="ERROR",E[E.INFO=6]="INFO",E[E.DEBUG=7]="DEBUG"})(Dr||(Dr={}));const oa=Dr;class ki{constructor(b,w,L){this.key=b,this.session=w,this.events=[],this.options=L||{},this.sent=0,this.uniqueID=0}log(b,w){b<=this.options.level&&(this.events.push(Ie({},w,{timestamp:ke.now()})),this.options.limit&&this.events.length>this.options.limit&&this.events.shift())}error(b){this.log(oa.ERROR,b)}info(b){this.log(oa.INFO,b)}debug(b){this.log(oa.DEBUG,b)}isEmpty(){return this.events.length===0}send(b,w){var L=Ie({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=[],b(L,(I,re)=>{I||this.sent++,w&&w(I,re)}),!0}generateUniqueID(){return this.uniqueID++,this.uniqueID}}class Nf{constructor(b,w,L,I){this.name=b,this.priority=w,this.transport=L,this.options=I||{}}isSupported(){return this.transport.isSupported({useTLS:this.options.useTLS})}connect(b,w){if(this.isSupported()){if(this.priority{L||(pt(),re?re.close():I.close())},forceMinPriority:Pt=>{L||this.priority{var w="socket_id="+encodeURIComponent(E.socketId);for(var L in b.params)w+="&"+encodeURIComponent(L)+"="+encodeURIComponent(b.params[L]);if(b.paramsProvider!=null){let I=b.paramsProvider();for(var L in I)w+="&"+encodeURIComponent(L)+"="+encodeURIComponent(I[L])}return w},Hf=E=>{if(typeof ze.getAuthorizers()[E.transport]>"u")throw`'${E.transport}' is not a recognized auth transport`;return(b,w)=>{const L=If(b,E);ze.getAuthorizers()[E.transport](ze,L,E,T.UserAuthentication,w)}},Yo=(E,b)=>{var w="socket_id="+encodeURIComponent(E.socketId);w+="&channel_name="+encodeURIComponent(E.channelName);for(var L in b.params)w+="&"+encodeURIComponent(L)+"="+encodeURIComponent(b.params[L]);if(b.paramsProvider!=null){let I=b.paramsProvider();for(var L in I)w+="&"+encodeURIComponent(L)+"="+encodeURIComponent(I[L])}return w},jf=E=>{if(typeof ze.getAuthorizers()[E.transport]>"u")throw`'${E.transport}' is not a recognized auth transport`;return(b,w)=>{const L=Yo(b,E);ze.getAuthorizers()[E.transport](ze,L,E,T.ChannelAuthorization,w)}},zf=(E,b,w)=>{const L={authTransport:b.transport,authEndpoint:b.endpoint,auth:{params:b.params,headers:b.headers}};return(I,re)=>{const me=E.channel(I.channelName);w(me,L).authorize(I.socketId,re)}};function Gc(E,b){let w={activityTimeout:E.activityTimeout||S.activityTimeout,cluster:E.cluster,httpPath:E.httpPath||S.httpPath,httpPort:E.httpPort||S.httpPort,httpsPort:E.httpsPort||S.httpsPort,pongTimeout:E.pongTimeout||S.pongTimeout,statsHost:E.statsHost||S.stats_host,unavailableTimeout:E.unavailableTimeout||S.unavailableTimeout,wsPath:E.wsPath||S.wsPath,wsPort:E.wsPort||S.wsPort,wssPort:E.wssPort||S.wssPort,enableStats:qf(E),httpHost:Uf(E),useTLS:Bf(E),wsHost:Vc(E),userAuthenticator:Xo(E),channelAuthorizer:Vf(E,b)};return"disabledTransports"in E&&(w.disabledTransports=E.disabledTransports),"enabledTransports"in E&&(w.enabledTransports=E.enabledTransports),"ignoreNullOrigin"in E&&(w.ignoreNullOrigin=E.ignoreNullOrigin),"timelineParams"in E&&(w.timelineParams=E.timelineParams),"nacl"in E&&(w.nacl=E.nacl),w}function Uf(E){return E.httpHost?E.httpHost:E.cluster?`sockjs-${E.cluster}.pusher.com`:S.httpHost}function Vc(E){return E.wsHost?E.wsHost:Pf(E.cluster)}function Pf(E){return`ws-${E}.pusher.com`}function Bf(E){return ze.getProtocol()==="https:"?!0:E.forceTLS!==!1}function qf(E){return"enableStats"in E?E.enableStats:"disableStats"in E?!E.disableStats:!1}const Fc=E=>"customHandler"in E&&E.customHandler!=null;function Xo(E){const b=Object.assign(Object.assign({},S.userAuthentication),E.userAuthentication);return Fc(b)?b.customHandler:Hf(b)}function Gf(E,b){let w;return"channelAuthorization"in E?w=Object.assign(Object.assign({},S.channelAuthorization),E.channelAuthorization):(w={transport:E.authTransport||S.authTransport,endpoint:E.authEndpoint||S.authEndpoint},"auth"in E&&("params"in E.auth&&(w.params=E.auth.params),"headers"in E.auth&&(w.headers=E.auth.headers)),"authorizer"in E&&(w.customHandler=zf(b,w,E.authorizer))),w}function Vf(E,b){const w=Gf(E,b);return Fc(w)?w.customHandler:jf(w)}class Ff extends Ae{constructor(b){super(function(w,L){rt.debug(`No callbacks on watchlist events for ${w}`)}),this.pusher=b,this.bindWatchlistInternalEvent()}handleEvent(b){b.data.events.forEach(w=>{this.emit(w.name,w)})}bindWatchlistInternalEvent(){this.pusher.connection.bind("message",b=>{var w=b.event;w==="pusher_internal:watchlist_events"&&this.handleEvent(b)})}}function Kc(){let E,b;return{promise:new Promise((L,I)=>{E=L,b=I}),resolve:E,reject:b}}const Kf=Kc;class Wf extends Ae{constructor(b){super(function(w,L){rt.debug("No callbacks on user for "+w)}),this.signin_requested=!1,this.user_data=null,this.serverToUserChannel=null,this.signinDonePromise=null,this._signinDoneResolve=null,this._onAuthorize=(w,L)=>{if(w){rt.warn(`Error during signin: ${w}`),this.emit("pusher:signin_error",Object.assign({},{type:"AuthError",error:w.message},w instanceof Ue?{status:w.status}:{})),this._cleanup();return}this.pusher.send_event("pusher:signin",{auth:L.auth,user_data:L.user_data})},this.pusher=b,this.pusher.connection.bind("state_change",({previous:w,current:L})=>{w!=="connected"&&L==="connected"&&this._signin(),w==="connected"&&L!=="connected"&&(this._cleanup(),this._newSigninPromiseIfNeeded())}),this.watchlist=new Ff(b),this.pusher.connection.bind("message",w=>{var L=w.event;L==="pusher:signin_success"&&this._onSigninSuccess(w.data),this.serverToUserChannel&&this.serverToUserChannel.name===w.channel&&this.serverToUserChannel.handleEvent(w)})}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(b){try{this.user_data=JSON.parse(b.user_data)}catch{rt.error(`Failed parsing user data after signin: ${b.user_data}`),this._cleanup();return}if(typeof this.user_data.id!="string"||this.user_data.id===""){rt.error(`user_data doesn't contain an id. user_data: ${this.user_data}`),this._cleanup();return}this._signinDoneResolve(),this._subscribeChannels()}_subscribeChannels(){const b=w=>{w.subscriptionPending&&w.subscriptionCancelled?w.reinstateSubscription():!w.subscriptionPending&&this.pusher.connection.state==="connected"&&w.subscribe()};this.serverToUserChannel=new Gr(`#server-to-user-${this.user_data.id}`,this.pusher),this.serverToUserChannel.bind_global((w,L)=>{w.indexOf("pusher_internal:")===0||w.indexOf("pusher:")===0||this.emit(w,L)}),b(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:b,resolve:w}=Kf();b.done=!1;const L=()=>{b.done=!0};b.then(L).catch(L),this.signinDonePromise=b,this._signinDoneResolve=w}}class dn{static ready(){dn.isReady=!0;for(var b=0,w=dn.instances.length;bze.getDefaultStrategy(this.config,I,Di);this.connection=jn.createConnectionManager(this.key,{getStrategy:L,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 re=I.event,me=re.indexOf("pusher_internal:")===0;if(I.channel){var Le=this.channel(I.channel);Le&&Le.handleEvent(I)}me||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=>{rt.warn(I)}),dn.instances.push(this),this.timeline.info({instances:dn.instances.length}),this.user=new Wf(this),dn.isReady&&this.connect()}switchCluster(b){const{appKey:w,cluster:L}=b;this.key=w,this.options=Object.assign(Object.assign({},this.options),{cluster:L}),this.config=Gc(this.options,this),this.connection.switchCluster(this.key)}channel(b){return this.channels.find(b)}allChannels(){return this.channels.all()}connect(){if(this.connection.connect(),this.timelineSender&&!this.timelineSenderTimer){var b=this.connection.isUsingTLS(),w=this.timelineSender;this.timelineSenderTimer=new _e(6e4,function(){w.send(b)})}}disconnect(){this.connection.disconnect(),this.timelineSenderTimer&&(this.timelineSenderTimer.ensureAborted(),this.timelineSenderTimer=null)}bind(b,w,L){return this.global_emitter.bind(b,w,L),this}unbind(b,w,L){return this.global_emitter.unbind(b,w,L),this}bind_global(b){return this.global_emitter.bind_global(b),this}unbind_global(b){return this.global_emitter.unbind_global(b),this}unbind_all(b){return this.global_emitter.unbind_all(),this}subscribeAll(){var b;for(b in this.channels.channels)this.channels.channels.hasOwnProperty(b)&&this.subscribe(b)}subscribe(b){var w=this.channels.add(b,this);return w.subscriptionPending&&w.subscriptionCancelled?w.reinstateSubscription():!w.subscriptionPending&&this.connection.state==="connected"&&w.subscribe(),w}unsubscribe(b){var w=this.channels.find(b);w&&w.subscriptionPending?w.cancelSubscription():(w=this.channels.remove(b),w&&w.subscribed&&w.unsubscribe())}send_event(b,w,L){return this.connection.send_event(b,w,L)}shouldUseTLS(){return this.config.useTLS}signin(){this.user.signin()}}dn.instances=[],dn.isReady=!1,dn.logToConsole=!1,dn.Runtime=ze,dn.ScriptReceivers=ze.ScriptReceivers,dn.DependenciesReceivers=ze.DependenciesReceivers,dn.auth_callbacks=ze.auth_callbacks;const _s=dn;function Yf(E){if(E==null)throw"You must pass your app key when you instantiate Pusher."}ze.setup(dn)}},a={};function i(c){var d=a[c];if(d!==void 0)return d.exports;var f=a[c]={exports:{}};return n[c].call(f.exports,f,f.exports,i),f.exports}i.d=(c,d)=>{for(var f in d)i.o(d,f)&&!i.o(c,f)&&Object.defineProperty(c,f,{enumerable:!0,get:d[f]})},i.o=(c,d)=>Object.prototype.hasOwnProperty.call(c,d);var l=i(721);return l})())})(wf)),wf.exports}var aA=rA();const by=Jr(aA),qt=ht("WebSocketManager");class iA{constructor(){$(this,"echo",null);$(this,"subscriptions",new Map);$(this,"initialized",!1);$(this,"config",null)}configure(e){if(this.initialized){qt.warn("[WebSocketManager] 이미 초기화되어 설정을 변경할 수 없습니다.");return}this.config=e,qt.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){qt.warn("[WebSocketManager] WebSocket 설정이 없습니다. initTemplateApp에서 websocket 옵션을 전달해주세요.");return}const{appKey:e,host:n="localhost",port:a=80,scheme:i="https",authEndpoint:l="/api/broadcasting/auth"}=this.config,c=Number(a)||80,d=i==="https";qt.log("[WebSocketManager] 연결 설정:",{host:n,port:c,scheme:i,useTLS:d,authEndpoint:l}),window.Pusher=by;const f=localStorage.getItem("auth_token"),g={wsHost:n,wsPort:c,wssPort:c,forceTLS:d,disableStats:!0,enabledTransports:["ws","wss"],cluster:"mt1",authEndpoint:l,auth:{headers:{Authorization:f?`Bearer ${f}`:"",Accept:"application/json"}}};qt.log("[WebSocketManager] Pusher 옵션:",g);const m=new by(e,g);m.connection.bind("connecting",()=>{qt.log("[WebSocketManager] 연결 시도 중...")}),m.connection.bind("connected",()=>{qt.log("[WebSocketManager] 연결 성공! Socket ID:",m.connection.socket_id)}),m.connection.bind("failed",()=>{qt.error("[WebSocketManager] 연결 실패 - WebSocket을 사용할 수 없습니다.")}),m.connection.bind("error",y=>{qt.error("[WebSocketManager] 연결 오류:",y)}),m.connection.bind("state_change",y=>{qt.log(`[WebSocketManager] 상태 변경: ${y.previous} → ${y.current}`)}),m.connection.bind("unavailable",()=>{qt.error("[WebSocketManager] WebSocket 사용 불가 - 연결할 수 없습니다.")}),m.connection.bind("disconnected",()=>{qt.warn("[WebSocketManager] 연결이 끊어졌습니다.")}),qt.log("[WebSocketManager] 초기 연결 상태:",m.connection.state),this.echo=new nA({broadcaster:"reverb",client:m}),qt.log("[WebSocketManager] 연결 시작 시도..."),m.connect(),window.Echo=this.echo,this.initialized=!0,qt.log("[WebSocketManager] Echo 초기화 완료")}subscribe(e,n,a,i={}){if(this.initialize(),!this.echo)return qt.warn("[WebSocketManager] Echo가 초기화되지 않았습니다."),"";const{channelType:l="private"}=i,c=`${e}:${n}`;if(this.subscriptions.has(c))return qt.log(`[WebSocketManager] 이미 구독 중: ${c}`),c;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(`.${n}`,a),this.subscriptions.set(c,d),qt.log(`[WebSocketManager] 구독 완료: ${c} (${l})`),c}unsubscribe(e){const n=this.subscriptions.get(e);if(!n)return;const a=e.lastIndexOf(":"),i=a>=0?e.substring(a+1):"";if(i)try{n.stopListening(`.${i}`)}catch(l){qt.warn(`[WebSocketManager] stopListening 실패: ${e}`,l)}this.subscriptions.delete(e),qt.log(`[WebSocketManager] 구독 해제: ${e}`)}leaveChannel(e){if(!this.echo)return;this.echo.leave(e);const n=[];this.subscriptions.forEach((a,i)=>{i.startsWith(`${e}:`)&&n.push(i)}),n.forEach(a=>this.subscriptions.delete(a)),qt.log(`[WebSocketManager] 채널 구독 해제: ${e}`)}disconnect(){this.echo&&(this.echo.disconnect(),this.subscriptions.clear(),this.initialized=!1,qt.log("[WebSocketManager] 연결 종료"))}getEcho(){return this.echo}isInitialized(){return this.initialized}isConfigured(){return this.config!==null&&!!this.config.appKey}getSubscriptionCount(){return this.subscriptions.size}}const Cc=new iA,bt=ht("DataSourceManager"),vy=new Dn;function Ec(o,e){const n=Aa(o);if(n!==null)try{return Vn(n)?vy.evaluatePipeExpression(n,e,{skipCache:!0}):vy.evaluateExpression(n,e)}catch(a){return bt.error("Failed to evaluate param expression:",n,a),o}return rs(o,e,{skipCache:!0})}function Sy(o){const e={};for(const n of o.keys()){if(n in e)continue;const a=o.getAll(n);a.length>1?e[n]=a:a.length===1&&(n.endsWith("[]")?e[n]=a:e[n]=a[0])}return e}function sA(){try{return window.G7Core?.devTools}catch{return}}const Rc=class Rc{constructor(e={}){$(this,"options");$(this,"dataCache",new Map);$(this,"bindingEngine");$(this,"globalHeaders",[]);this.options=e,this.bindingEngine=new Dn}setGlobalHeaders(e){this.globalHeaders=e||[]}matchesPattern(e,n){if(n==="*")return!0;const a=n.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${a}$`).test(e)}toFormData(e){const n=new FormData;for(const[a,i]of Object.entries(e))i instanceof File||i instanceof Blob?n.append(a,i):i!=null&&n.append(a,typeof i=="object"?JSON.stringify(i):String(i));return n}getMatchingGlobalHeaders(e,n){const a={};for(const i of this.globalHeaders)this.matchesPattern(e,i.pattern)&&Object.entries(i.headers).forEach(([l,c])=>{const d=Ec(c,n);d!=null&&d!==""&&(a[l]=String(d))});return a}filterByCondition(e,n={}){const a=new Set,i=[];for(const l of e){if(a.has(l.id))continue;if(!l.if&&!l.conditions){a.add(l.id),i.push(l);continue}ns({if:l.if,conditions:l.conditions},n,this.bindingEngine,`data_source:${l.id}`)&&(a.add(l.id),i.push(l))}return i}checkErrorCondition(e,n){if(!e.errorCondition?.if||e.errorCondition?.errorCode===void 0)return null;try{const a={response:n};if(ns({if:e.errorCondition.if},a,this.bindingEngine,`errorCondition:${e.id}`))return bt.log(`errorCondition matched for ${e.id}, triggering error ${e.errorCondition.errorCode}`),e.errorCondition.errorCode}catch(a){bt.error(`Failed to evaluate errorCondition for ${e.id}:`,a)}return null}async fetchDataSources(e,n={},a=new URLSearchParams,i,l){const c={},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,n,a,i,l);c[g.id]=m,this.dataCache.set(g.id,{data:m,timestamp:Date.now()});const y=this.checkErrorCondition(g,m);if(y!==null){const S={status:y,message:`Error condition matched for ${g.id}`,data:m},v=Sr(),_=v.resolve(y,{errorHandling:g.errorHandling,onError:g.onError});if(_.handler)try{await v.execute(_.handler,S)}catch(A){bt.error(`Error executing errorCondition handler for ${g.id}:`,A)}g.fallback!==void 0&&(c[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 S={data:m,sourceId:g.id};await this.executeOnSuccessHandler(g.onSuccess,S)}catch(S){bt.error(`Error executing onSuccess handler for ${g.id}:`,S)}}catch(m){bt.error(`Failed to fetch data source: ${g.id}`,m);const y=m?.response?.status||m?.status||500,S=m?.response?.data,v=S?.message||m.message||"Unknown error",_={status:y,message:v,errors:S?.errors,data:S,statusText:m?.response?.statusText},A=Sr(),x=A.resolve(y,{errorHandling:g.errorHandling,onError:g.onError});if(x.handler)try{await A.execute(x.handler,_)}catch(O){bt.error(`Error executing error handler for ${g.id}:`,O)}g.fallback!==void 0&&(c[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)}})),c}async fetchDataSourcesWithResults(e,n={},a=new URLSearchParams,i,l,c){if(e.some(m=>m.type==="websocket")){const m=e.filter(y=>y.type==="websocket").map(y=>y.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=c?.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 y=await this.fetchDataSource(m,n,a,i,l);this.dataCache.set(m.id,{data:y,timestamp:Date.now()});const S=this.checkErrorCondition(m,y);if(S!==null){const v={status:S,message:`Error condition matched for ${m.id}`,data:y},_=Sr(),A=_.resolve(S,{errorHandling:m.errorHandling,onError:m.onError});let x=!1;if(A.handler)if(m.loading_strategy==="blocking")_.execute(A.handler,v).catch(O=>{bt.error(`Error executing errorCondition handler for ${m.id}:`,O)}),x=!0;else try{await _.execute(A.handler,v),x=!0}catch(O){bt.error(`Error executing errorCondition handler for ${m.id}:`,O)}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: ${S}`),errorCode:S,errorHandled:x}}if(m.onSuccess)try{const v={data:y,sourceId:m.id};await this.executeOnSuccessHandler(m.onSuccess,v)}catch(v){bt.error(`Error executing onSuccess handler for ${m.id}:`,v)}return{id:m.id,state:"success",data:y}}catch(y){bt.error(`Failed to fetch data source: ${m.id}`,y);const S=y?.response?.status||y?.status||500,v=y?.response?.data,_=v?.message||y.message||"Unknown error",A={status:S,message:_,errors:v?.errors,data:v,statusText:y?.response?.statusText},x=Sr(),O=x.resolve(S,{errorHandling:m.errorHandling,onError:m.onError});let M=!1;if(O.handler)if(m.loading_strategy==="blocking")x.execute(O.handler,A).catch(T=>{bt.error(`Error executing error handler for ${m.id}:`,T)}),M=!0;else try{await x.execute(O.handler,A),M=!0}catch(T){bt.error(`Error executing error handler for ${m.id}:`,T)}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(y,m),{id:m.id,state:"error",error:y,errorCode:S,errorHandled:M})}}))}fetchDataSourcesInBackground(e,n={},a=new URLSearchParams,i){e.filter(c=>c.auto_fetch!==!1&&c.loading_strategy==="background"&&c.type!=="websocket").forEach(c=>{this.fetchDataSource(c,n,a).then(async d=>{this.dataCache.set(c.id,{data:d,timestamp:Date.now()});const f=this.checkErrorCondition(c,d);if(f!==null){const g={status:f,message:`Error condition matched for ${c.id}`,data:d},m=Sr(),y=m.resolve(f,{errorHandling:c.errorHandling,onError:c.onError});if(y.handler)try{await m.execute(y.handler,g)}catch(S){bt.error(`Error executing errorCondition handler for ${c.id}:`,S)}c.fallback!==void 0&&(this.dataCache.set(c.id,{data:c.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${c.id} (errorCondition)`),i&&i(c.id,c.fallback));return}if(c.onSuccess)try{const g={data:d,sourceId:c.id};await this.executeOnSuccessHandler(c.onSuccess,g)}catch(g){bt.error(`Error executing onSuccess handler for ${c.id}:`,g)}i&&i(c.id,d)}).catch(async d=>{bt.error(`Background fetch failed: ${c.id}`,d);const f=d?.response?.status||d?.status||500,g=d?.response?.data,m=g?.message||d.message||"Unknown error",y={status:f,message:m,errors:g?.errors,data:g,statusText:d?.response?.statusText},S=Sr(),v=S.resolve(f,{errorHandling:c.errorHandling,onError:c.onError});if(v.handler)try{await S.execute(v.handler,y)}catch(_){bt.error(`Error executing error handler for ${c.id}:`,_)}if(c.fallback!==void 0){this.dataCache.set(c.id,{data:c.fallback,timestamp:Date.now()}),bt.log(`Using fallback data for ${c.id}`),i&&i(c.id,c.fallback);return}this.options.onError&&this.options.onError(d,c)})})}async fetchDataSource(e,n,a,i,l){switch(e.type){case"api":return this.fetchApiDataSource(e,n,a,i,l);case"static":return e.data;case"route_params":return n;case"query_params":return Sy(a);default:throw new Error(`Unknown data source type: ${e.type}`)}}async fetchApiDataSource(e,n,a,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 c={route:n,query:Sy(a)};i&&(c._global=i),l&&(c._local=l);let d=rs(e.endpoint,c,{skipCache:!0});const f=e.method||"GET",m=(e.contentType?typeof e.contentType=="string"&&e.contentType.includes("{{")?rs(e.contentType,c,{skipCache:!0}):e.contentType:"application/json")==="multipart/form-data";let y=m?{...e.params||{}}:JSON.parse(JSON.stringify(e.params||{}));Object.entries(y).forEach(([_,A])=>{typeof A=="string"&&(y[_]=Ec(A,c))}),Object.keys(y).forEach(_=>{y[_]===""&&delete y[_]});const S=sA();let v=null;if(S?.isEnabled()){S.trackDataSourceDefinition({id:e.id,type:e.type,endpoint:d,method:f,autoFetch:e.auto_fetch,initLocal:e.initLocal,initGlobal:e.initGlobal});let _=d;if(f==="GET"&&Object.keys(y).length>0){const A=new URLSearchParams;Object.entries(y).forEach(([O,M])=>{Array.isArray(M)?M.forEach(T=>A.append(O,String(T))):M!=null&&A.append(O,String(M))});const x=A.toString();_=x?`${d}?${x}`:d}v=S.trackRequest(_,f,{requestBody:f!=="GET"?y:void 0,dataSourceId:e.id}),S.trackDataSourceLoading(e.id)}try{let _;const A=e.auth_mode??(e.auth_required===!0?"required":"none"),x=br.getInstance().isAuthenticated();if(A==="required"&&!x){bt.log(`[DataSourceManager] Skipping ${e.id}: auth_mode is 'required' but no token available`),S?.isEnabled()&&(S.trackDataSourceError(e.id,"Skipped: auth_mode required but not authenticated"),v&&S.failRequest(v,"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 O=A==="required"||A==="optional"&&x;if(O){const M=Hr(),T=d.startsWith("/api/")?d.substring(4):d.startsWith("/api")?d.substring(4)||"/":d;this.options.onError&&bt.log(`[DataSourceManager] Normalized endpoint: ${d} -> ${T}`);const D=this.getMatchingGlobalHeaders(d,c),z={};e.headers&&Object.entries(e.headers).forEach(([he,Ee])=>{const be=Ec(Ee,c);be!=null&&be!==""&&(z[he]=String(be))});const P={...D,...z},q=Object.keys(P).length>0,W=m?this.toFormData(y):y;switch(f){case"GET":_=await M.get(T,{params:y,...q&&{headers:P}});break;case"POST":q?_=await M.post(T,W,{headers:P}):_=await M.post(T,W);break;case"PUT":q?_=await M.put(T,W,{headers:P}):_=await M.put(T,W);break;case"PATCH":q?_=await M.patch(T,W,{headers:P}):_=await M.patch(T,W);break;case"DELETE":_=await M.delete(T,{params:y,...q&&{headers:P}});break;default:throw new Error(`Unsupported HTTP method: ${f}`)}}else{let M=d;if(f==="GET"){const W=new URLSearchParams(y).toString();M=W?`${d}?${W}`:d}const T={...m?{}:{"Content-Type":"application/json"},Accept:"application/json"};if(typeof window<"u"){const W=localStorage.getItem("g7_locale");W&&(T["Accept-Language"]=W)}const D=this.getMatchingGlobalHeaders(d,c);Object.assign(T,D),e.headers&&Object.entries(e.headers).forEach(([W,he])=>{const Ee=Ec(he,c);Ee!=null&&Ee!==""&&(T[W]=String(Ee))});let z;f!=="GET"&&(m?(z=this.toFormData(y),delete T["Content-Type"]):z=JSON.stringify(y));const P=await fetch(M,{method:f,headers:T,body:z});let q;try{q=await P.json()}catch{q=null}if(v&&S?.isEnabled()&&(S.completeRequest(v,P.status,q),v=null),!P.ok){S?.isEnabled()&&S.trackDataSourceError(e.id,`HTTP ${P.status}: ${P.statusText}`);const W=new Error(`HTTP error! status: ${P.status}`);throw W.response={status:P.status,statusText:P.statusText,data:q},W.status=P.status,W}_=q,S?.isEnabled()&&S.trackDataSourceLoaded(e.id,_)}return O&&v&&S?.isEnabled()&&(S.completeRequest(v,200,_),S.trackDataSourceLoaded(e.id,_)),_}catch(_){if(v&&S?.isEnabled()){const A=_;A?.response?S.completeRequest(v,A.response.status,A.response.data):S.failRequest(v,_ instanceof Error?_.message:String(_)),S.trackDataSourceError(e.id,_ instanceof Error?_.message:String(_))}throw _}}getCachedData(e){const n=this.dataCache.get(e);if(!n)return;if(Date.now()-n.timestamp>Rc.DATA_CACHE_TTL){this.dataCache.delete(e);return}return n.data}clearCache(){this.dataCache.clear()}subscribeWebSockets(e,n,a={}){const i=[],l=e.filter(c=>c.type==="websocket");return l.length===0||l.forEach(c=>{if(!c.channel||!c.event){bt.warn(`WebSocket source ${c.id} missing channel or event`);return}let d,f;try{d=rs(c.channel,a,{skipCache:!0}),f=rs(c.event,a,{skipCache:!0})}catch(y){bt.error(`Failed to resolve WebSocket channel/event for source ${c.id}:`,y);return}const g=y=>!!(!y||y.trim()===""||y.includes("{{")||y.endsWith(".")||y.endsWith(":")||y.startsWith(".")||y.startsWith(":")||y.includes("..")||y.includes("::"));if(g(d)||g(f)){bt.warn(`WebSocket source ${c.id} has invalid channel/event after expression resolution, skipping. Original channel="${c.channel}", resolved="${d}". Original event="${c.event}", resolved="${f}". Available context keys: [${Object.keys(a).join(", ")}]`);return}const m=Cc.subscribe(d,f,y=>{const S=c.target_source||c.id;this.dataCache.set(S,{data:y,timestamp:Date.now()}),n(S,y)},{channelType:c.channel_type||"private"});m&&i.push(m)}),i}unsubscribeWebSockets(e){e.length!==0&&e.forEach(n=>{Cc.unsubscribe(n)})}async executeOnSuccessHandler(e,n){const a=this.options.actionDispatcher??bm();if(!a){bt.warn("ActionDispatcher not available, skipping onSuccess handler");return}const i=Array.isArray(e)?e:[e];for(const l of i)try{await a.dispatchAction({type:"click",...l},{data:{response:n}})}catch(c){throw bt.error("Failed to execute onSuccess handler:",c),c}}};$(Rc,"DATA_CACHE_TTL",3e5);let _r=Rc;const oA=new _r,bi=ht("ModalDataSourceWrapper");function lA(o,e){if(!o||!e)return o;const a=e.replace(/\?\./g,".").split(/\.(?![^\[]*\])/).flatMap(l=>{const c=l.match(/^([^\[]*)((?:\[\d+\])*)$/);if(c){const[,d,f]=c,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 a){if(i==null)return;if(l.startsWith("[")&&l.endsWith("]")){const c=parseInt(l.slice(1,-1),10);i=i[c]}else i=i[l]}return i}const wy=({isOpen:o,modalId:e,dataSources:n,dataContext:a,globalStateUpdater:i,bindingEngine:l,debug:c=!1,children:d})=>{const[f,g]=H.useState(!1),[m,y]=H.useState(!1),S=H.useRef(!1),v=H.useRef(null);v.current||(v.current=new _r);const _=H.useCallback(async()=>{if(!(!n||n.length===0)&&v.current){g(!0);try{const A=a.route||{},x=new URLSearchParams(window.location.search),O=n.map(T=>{let D={...T};if(T.endpoint&&l){const z=l.resolveBindings(T.endpoint,a,{skipCache:!0});D.endpoint=z}if(T.params&&l){const z={};Object.entries(T.params).forEach(([P,q])=>{typeof q=="string"?z[P]=l.resolveBindings(q,a,{skipCache:!0}):z[P]=q}),D.params=z}return D});c&&bi.log(`[ModalDataSourceWrapper] Modal "${e}" fetching data sources:`,O.map(T=>({id:T.id,endpoint:T.endpoint})));const M=await v.current.fetchDataSourcesWithResults(O,A,x);i&&M.forEach(T=>{if(T.state==="success"&&T.data!==void 0){const D=O.find(z=>z.id===T.id);if(D?.initGlobal){const z=T.data?.data??T.data,P=Array.isArray(D.initGlobal)?D.initGlobal:[D.initGlobal];for(const q of P)if(typeof q=="string")i({[q]:z}),c&&bi.log(`[ModalDataSourceWrapper] Modal "${e}" initGlobal: ${T.id}.data -> _global.${q}`);else if(typeof q=="object"&&q.key){const{key:W,path:he}=q,Ee=he?lA(z,he):z;i({[W]:Ee}),c&&bi.log(`Modal "${e}" initGlobal: ${T.id}.data${he?"."+he:""} -> _global.${W}`)}}}else T.state==="error"&&bi.error(`Modal "${e}" data source error:`,T.id,T.error)}),c&&bi.log(`Modal "${e}" data sources fetched successfully`)}catch(A){bi.error(`Modal "${e}" data source fetch error:`,A)}finally{g(!1),y(!0)}}},[n,a,i,l,e,c]);return H.useEffect(()=>{if(!n||n.length===0)return;const A=window.__templateApp;return A?.registerModalDataSources&&A.registerModalDataSources(e,n),()=>{A?.unregisterModalDataSources&&A.unregisterModalDataSources(e)}},[e,n]),H.useEffect(()=>{!o&&S.current&&(y(!1),c&&bi.log(`[ModalDataSourceWrapper] Modal "${e}" closed, reset fetch state`)),o&&!S.current&&n&&n.length>0&&!m&&_(),S.current=o},[o,n,m,_,e,c]),gt.jsx(gt.Fragment,{children:d})};class _c extends Error{constructor(n,a,i={}){super(a);$(this,"code");$(this,"userMessageKey");$(this,"showStack");$(this,"icon");$(this,"recoverable");this.name="TemplateEngineError",this.code=n,this.userMessageKey=a,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(n,a){if(!a||!n)return this.userMessageKey;try{return a.translate(this.userMessageKey,n)}catch{return this.userMessageKey}}}class cA extends _c{constructor(){super("TEMPLATE_NOT_FOUND","$t:core.errors.template_not_found",{showStack:!1,icon:"fa-paint-brush",recoverable:!1}),this.name="TemplateNotFoundError"}}function Cy(o){if(o instanceof _c)return o;if(o instanceof Error){const e=new _c("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 _c("TEMPLATE_INIT_ERROR","$t:core.errors.template_init_error",{showStack:!1,icon:"fa-circle-exclamation",recoverable:!0})}const uA=ht("ErrorDisplay");class Cf{static render(e,n){const a=document.getElementById(e);if(!a){uA.error(`Container #${e} not found`);return}const i=n.debug&&n.showStack&&n.stackTrace,l=window.matchMedia("(prefers-color-scheme: dark)").matches,c={container:` display: flex; align-items: center; justify-content: center; @@ -224,7 +224,7 @@ Error generating stack: `+u.message+` `:""} - `}static renderFromError(e,n,a,i=!1,l,c,d){let f,g;if(n.userMessageKey.startsWith("$t:"))if(c&&l)try{f=c.translate(n.userMessageKey,l)}catch{f=n.userMessageKey.replace("$t:","")}else f=n.userMessageKey.replace("$t:","");else f=n.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:a,message:f,detailMessage:g,icon:n.icon,showStack:n.showStack,stackTrace:n.stack,showReloadButton:n.recoverable,debug:i})}static escapeHtml(e){if(!e)return"";const n=document.createElement("div");return n.textContent=e,n.innerHTML}}const fs=ut("Router");class Y_{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,n){this.eventHandlers.has(e)||this.eventHandlers.set(e,[]),this.eventHandlers.get(e).push(n)}async emit(e,...n){const a=this.eventHandlers.get(e);a&&await Promise.all(a.map(i=>i(...n)))}async loadRoutes(e){try{const n=e!==void 0&&e>0?e:null,a=await fetch($r(`/api/templates/${this.templateIdentifier}/routes`,"json",n));if(!a.ok)throw new Error(`Failed to load routes: ${a.statusText}`);const i=await a.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,fs.log(`Loaded ${this.routes.length} routes${e?` (v=${e})`:""}`);else throw new Error("Invalid routes data format")}catch(n){throw fs.error("Error loading routes:",n),n}}setRoutes(e){this.routes=e,fs.log(`Set ${this.routes.length} routes`)}match(e){const n=this.normalizePathname(e);for(const a of this.routes){const i=this.matchPattern(a.path,n);if(i!==null)return{route:a,params:i}}return null}normalizePathname(e){return e.length>1&&e.endsWith("/")?e.replace(/\/+$/,"")||"/":e}matchPattern(e,n){const a=[];let i=e.replace(/:([^/]+)/g,(f,g)=>(a.push(g),"([^/]+)"));i.startsWith("*/")&&(i="(?:/[^/]+)?"+i.slice(1)),i=i.replace(/\//g,"\\/");const l=new RegExp(`^${i}$`),c=n.match(l);if(!c)return null;const d={};return a.forEach((f,g)=>{d[f]=c[g+1]}),d}getRoutes(){return[...this.routes]}getAuthType(e,n){return e.auth_type?e.auth_type:n.startsWith("/admin")?"admin":"user"}async navigateToCurrentPath(){const e=window.location.pathname,n=window.location.search,a=this.match(e);if(!a){fs.warn(`No route matched for path: ${e}`),this.emit("routeNotFound",e);return}if(a.route.redirect){fs.log(`Redirecting from ${e} to ${a.route.redirect}`),this.navigate(a.route.redirect);return}if(a.route.auth_required){const c=this.getAuthType(a.route,e),d=yr.getInstance();let f=d.isAuthenticated()&&d.getAuthType()===c;if(f||(f=await d.checkAuth(c)),!f){const g=d.getLoginRedirectUrl(c,e+n);fs.log(`Not authenticated, redirecting to: ${g}`),window.location.href=g;return}}const i=new URLSearchParams(n),l={};for(const c of i.keys()){if(c in l)continue;const d=i.getAll(c);d.length>1?l[c]=d:d.length===1&&(c.endsWith("[]")?l[c]=d:l[c]=d[0])}await this.emit("routeChange",{path:e,layout:a.route.layout,endpoint:a.route.endpoint,params:{...a.route.params||{},...a.params},query:l,auth_required:a.route.auth_required,auth_type:a.route.auth_type,meta:a.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 n=this.pendingNavigation;this.executeNavigation(n)}}}}const X_=/^\/admin\/layout-editor\/([^/?#]+)\/?$/;function py(o){const e=X_.exec(o);return e?{templateIdentifier:e[1]}:null}const Bt=ut("ErrorPageHandler");class J_{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($r(`/api/templates/${this.templateId}/config`,"json"));if(!e.ok)return this.debug&&Bt.warn("Failed to load template config:",e.statusText),this.configLoaded=!0,null;const n=await e.json();if(!n.success||!n.data)return this.debug&&Bt.warn("Invalid template config response"),this.configLoaded=!0,null;const a=n.data;return!a.error_config||!a.error_config.layouts?(this.debug&&Bt.warn("No error_config found in template.json"),this.configLoaded=!0,null):(this.errorConfig=a.error_config,this.configLoaded=!0,this.debug&&Bt.log("Error config loaded:",this.errorConfig),this.errorConfig)}catch(e){return Bt.error("Failed to load error config:",e),this.configLoaded=!0,null}}async renderError(e,n="app"){try{const a=await this.loadConfig();if(!a)return this.debug&&Bt.warn("No error config available, cannot render error page"),!1;const i=a.layouts[e]||a.layouts[String(e)];if(!i)return this.debug&&Bt.warn(`No layout defined for error code: ${e}`),!1;this.debug&&Bt.log(`Loading error layout: ${i} for code: ${e}`);const l=await this.layoutLoader.loadLayout(this.templateId,i);if(!l)return this.debug&&Bt.error(`Failed to load error layout: ${i}`),!1;this.debug&&Bt.log("Error layout loaded:",l);let c={};const d=l.data_sources||[];if(d.length>0){this.debug&&Bt.log("Fetching data sources:",d.map(v=>v.id));const m=d.filter(v=>v.loading_strategy==="blocking"),b=d.filter(v=>!v.loading_strategy||v.loading_strategy==="progressive"),S=[...m,...b];if(S.length>0)try{c=await this.dataSourceManager.fetchDataSources(S,{},new URLSearchParams),this.debug&&Bt.log("Data sources fetched:",Object.keys(c))}catch(v){Bt.error("Failed to fetch data sources:",v)}}const f={};d.length>0&&(this.processInitOptions(d,c,f),this.debug&&Bt.log("initOptions processed:",{globalKeys:Object.keys(this.globalState),localKeys:Object.keys(f)}));const g={...c,errorCode:e,_global:{...this.globalState},_local:{...f}};return await this.renderFunction({containerId:n,layoutJson:l,dataContext:g,translationContext:{templateId:this.templateId,locale:this.locale}}),this.debug&&Bt.log(`Error page ${e} rendered successfully`),!0}catch(a){return Bt.error(`Failed to render error page ${e}:`,a),!1}}processInitOptions(e,n,a){for(const i of e){const l=n[i.id];if(!l)continue;const c=l?.data??l;if(i.initLocal){if(typeof i.initLocal=="string")a[i.initLocal]=c,Bt.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;a[d]=f?this.getValueByPath(c,f):c,Bt.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]=c,Bt.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(c,m):c,Bt.log(`initGlobal: ${i.id}.data${m?"."+m:""} -> _global.${g}`)}}}}getValueByPath(e,n){return n.split(".").reduce((a,i)=>a?.[i],e)}updateGlobalState(e){this.globalState={...this.globalState,...e}}updateLocale(e){this.locale=e,this.debug&&Bt.log("Locale updated:",e)}isConfigLoaded(){return this.configLoaded}async hasErrorLayout(e){const n=await this.loadConfig();return n?!!(n.layouts[e]||n.layouts[String(e)]):!1}clearConfigCache(){this.errorConfig=null,this.configLoaded=!1,this.debug&&Bt.log("Config cache cleared")}}const $t=ut("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 n=[...e].sort((d,f)=>d.priority-f.priority);$t.log("Loading module assets:",n.map(d=>d.identifier));const a=n.filter(d=>d.css).map(d=>this.loadCSS(d.identifier,d.css)),i=n.filter(d=>d.js).map(d=>this.loadJS(d.identifier,d.js)),l=await Promise.allSettled([...a,...i]),c=l.filter(d=>d.status==="rejected");if(c.length>0){$t.warn(`Some module assets failed to load (${c.length}/${l.length}); continuing with the rest`,this.getFailedJsAssets());return}$t.log("All module assets loaded successfully")}async loadBundle(e,n,a){const i=[];if(a&&i.push(this.loadBundleCss(e,a)),n&&i.push(this.loadBundleJs(e,n)),i.length===0){$t.log(`No bundle assets to load for: ${e}`);return}await Promise.all(i)}async loadBundleCss(e,n){const a=`ext-bundle-css-${e}`;if(document.getElementById(a)){$t.log(`Bundle CSS already loaded: ${e}`);return}return new Promise(i=>{const l=document.createElement("link");l.rel="stylesheet",l.href=n,l.id=a,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} (${n})`),i()},document.head.appendChild(l)})}async loadBundleJs(e,n){const a=`ext-bundle-js-${e}`;if(document.getElementById(a)){$t.log(`Bundle JS already loaded: ${e}`);return}const i=this.loadingPromises.get(a);if(i)return $t.log(`Bundle JS already loading: ${e}`),i;const l=sp(n,{id:a},{label:`bundle JS: ${e}`}).then(()=>{$t.log(`Bundle JS loaded: ${e}`);const c=document.getElementById(a);c&&this.registerLoadedAsset(`bundle-${e}`,{type:"js",element:c}),this.loadingPromises.delete(a)}).catch(c=>{throw $t.warn(`Failed to load bundle JS: ${e} (${n})`,c),this.failedJsAssets.add(e),this.loadingPromises.delete(a),c});return this.loadingPromises.set(a,l),l}async loadCSS(e,n){const a=`module-css-${e}`;if(document.getElementById(a)){$t.log(`CSS already loaded: ${e}`);return}return new Promise((i,l)=>{const c=document.createElement("link");c.rel="stylesheet",c.href=n,c.id=a,c.onload=()=>{$t.log(`CSS loaded: ${e}`),this.registerLoadedAsset(e,{type:"css",element:c}),i()},c.onerror=()=>{$t.warn(`Failed to load CSS: ${e} (${n})`),i()},document.head.appendChild(c)})}async loadJS(e,n){const a=`module-js-${e}`;if(document.getElementById(a)){$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=sp(n,{id:a},{label:`JS: ${e}`}).then(()=>{$t.log(`JS loaded: ${e}`);const c=document.getElementById(a);c&&this.registerLoadedAsset(e,{type:"js",element:c}),this.loadingPromises.delete(e)}).catch(c=>{throw $t.warn(`Failed to load JS: ${e} (${n})`,c),this.failedJsAssets.add(e),this.loadingPromises.delete(e),c});return this.loadingPromises.set(e,l),l}registerLoadedAsset(e,n){const a=this.loadedAssets.get(e)||[];a.push(n),this.loadedAssets.set(e,a)}unloadExtensionAsset(e){const n=this.loadedAssets.get(e);if(!n||n.length===0){$t.log(`No assets to unload for: ${e}`);return}n.forEach(a=>{a.element.parentNode&&(a.element.parentNode.removeChild(a.element),$t.log(`${a.type.toUpperCase()} unloaded: ${e}`))}),this.loadedAssets.delete(e),$t.log(`All assets unloaded for: ${e}`)}unloadAllAssets(){Array.from(this.loadedAssets.keys()).forEach(n=>{this.unloadExtensionAsset(n)}),$t.log("All module assets unloaded")}isLoaded(e){return this.loadedAssets.has(e)}getLoadedModules(){return Array.from(this.loadedAssets.keys())}}let Sf=null;function wf(){return Sf||(Sf=new Q_),Sf}function Z_(){if(typeof window>"u")return[];const o=window.G7Config;if(!o?.moduleAssets)return[];const e=[];for(const[n,a]of Object.entries(o.moduleAssets)){const i=a;e.push({identifier:n,js:i.js?Ea(i.js):i.js,css:i.css?Ea(i.css):i.css,priority:i.priority,external:i.external})}return e}function eA(){if(typeof window>"u")return null;const o=window.G7Config;if(!o?.bundleUrls)return null;const e=o.bundleUrls;return{moduleJs:e.moduleJs?Ea(e.moduleJs):e.moduleJs,moduleCss:e.moduleCss?Ea(e.moduleCss):e.moduleCss,pluginJs:e.pluginJs?Ea(e.pluginJs):e.pluginJs,pluginCss:e.pluginCss?Ea(e.pluginCss):e.pluginCss}}function tA(){if(typeof window>"u")return[];const o=window.G7Config;if(!o?.pluginAssets)return[];const e=[];for(const[n,a]of Object.entries(o.pluginAssets)){const i=a;e.push({identifier:n,js:i.js?Ea(i.js):i.js,css:i.css?Ea(i.css):i.css,priority:i.priority,external:i.external})}return e}const Cf=ut("SystemBannerManager");class Cc{static show(e){this.banners.set(e.id,e),this.render(),Cf.log(`Banner shown: ${e.id}`)}static hide(e){this.banners.delete(e)&&(this.render(),Cf.log(`Banner hidden: ${e}`))}static hideAll(){this.banners.clear(),this.render(),Cf.log("All banners hidden")}static detectLocale(){try{const n=window.G7Core;if(n?.locale?.current)return n.locale.current()}catch{}return(navigator.language||"ko").split("-")[0]}static resolveMessage(e,n){return typeof e=="string"?e:e[n]||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 n=Array.from(this.banners.values()).sort((i,l)=>(i.order??0)-(l.order??0)),a=this.detectLocale();e.innerHTML=n.map(i=>{const l=this.resolveMessage(i.message,a),c=i.background||"#f59e0b",d=i.color||"white";return`
${l}
`}).join(""),requestAnimationFrame(()=>{e&&this.adjustAppPadding(e.offsetHeight)})}static adjustAppPadding(e){const n=document.getElementById("app");n&&(n.style.paddingTop=e>0?`${e}px`:"")}}$(Cc,"banners",new Map),$(Cc,"containerId","g7-system-banners");const U=ut("TemplateApp");function my(o){const e={};for(const n of o.keys()){if(n in e)continue;const a=o.getAll(n);a.length>1?e[n]=a:a.length===1&&(n.endsWith("[]")?e[n]=a:e[n]=a[0])}return e}const Ar=class Ar{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 n=this.loadLocaleFromStorage(),a=n||e.locale||"ko";this.config={...e,locale:a},!n&&e.locale&&this.saveLocaleToStorage(e.locale)}loadG7Config(){if(typeof window<"u"&&window.G7Config){const e=window.G7Config;e.settings&&(this.globalState.settings=e.settings,U.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,U.log("Loaded plugin settings from G7Config:",Object.keys(e.plugins))),e.modules&&(this.globalState.modules=e.modules,U.log("Loaded module settings from G7Config:",Object.keys(e.modules))),e.appConfig&&(this.globalState.appConfig=e.appConfig,U.log("Loaded appConfig from G7Config:",Object.keys(e.appConfig)))}}resolveRouteExpressions(e){const n=new xn,a={_global:this.globalState};return e.map(i=>{const l={...i};if(l.path&&l.path.includes("{{")){const c=l.path;l.path=n.resolveBindings(l.path,a),l.path=l.path.replace(/\/\/+/g,"/")||"/",l.path.includes("{{")&&(U.warn("Route expression resolution failed, using fallback:",c),l.path=c.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/")}if(l.redirect&&l.redirect.includes("{{")){const c=l.redirect;l.redirect=n.resolveBindings(l.redirect,a),l.redirect=l.redirect.replace(/\/\/+/g,"/")||"/",l.redirect.includes("{{")&&(U.warn("Route redirect expression resolution failed:",c),l.redirect=c.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/")}return l})}migrateLocaleStorage(){const e=["locale","g7_template_locale"];for(const n of e)try{const a=localStorage.getItem(n);a&&a!==localStorage.getItem(Ar.LOCALE_STORAGE_KEY)&&(localStorage.setItem(Ar.LOCALE_STORAGE_KEY,a),U.log(`Migrated locale from '${n}' to '${Ar.LOCALE_STORAGE_KEY}'`)),localStorage.removeItem(n)}catch(a){U.warn(`Failed to migrate locale key '${n}':`,a)}}async init(){try{Qs.getInstance().setDebug(this.config.debug),U.log("Initializing with config:",this.config),YS();const e=pr.getInstance(),n=yr.getInstance(),a=this.loadCacheVersionFromStorage()||0,[i,l,c,d,f]=await Promise.all([Oo({templateId:this.config.templateId,templateType:this.config.templateType,locale:this.config.locale,debug:this.config.debug,cacheVersion:a}),e.loadComponents(this.config.templateId,this.config.templateType),Ll($r(`/api/templates/${this.config.templateId}/routes`,"json",a>0?a: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 U.error("Error loading routes:",A),A}),n.preloadAuth(this.config.templateType==="admin"?"admin":"user"),fetch($r(`/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=>(U.warn("Error loading template config:",A),null))]);if(U.log("Template Engine initialized"),U.log("ComponentRegistry loaded"),U.log("Routes data loaded"),U.log("User info preloaded"),U.log("Template config loaded:",f),f?.cache_version!==void 0){const A=this.loadCacheVersionFromStorage();if(this.extensionCacheVersion=f.cache_version,this.saveCacheVersionToStorage(this.extensionCacheVersion),U.log("Extension cache version:",this.extensionCacheVersion),A!==null&&A!==this.extensionCacheVersion){U.log("Cache version changed, reloading routes...");const x=await Ll($r(`/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(x.routes)&&(x.routes=this.resolveRouteExpressions(x.routes),Object.assign(c,x),U.log("Routes reloaded with new cache version"));try{const{TranslationEngine:L}=await Promise.resolve().then(()=>dp),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),U.log("Translations reloaded with new cache version")}catch(L){U.error("Failed to reload translations:",L)}}}f?.errorHandling&&(this.templateErrorHandling=f.errorHandling,vr().setTemplateConfig(this.templateErrorHandling),U.log("Template errorHandling registered:",this.templateErrorHandling)),n.on("logout",()=>{U.log("User logged out")}),n.on("authStateChange",A=>{U.log("Auth state changed:",A)}),U.log("AuthManager event handlers registered");const g=Ir(),m=this.config.templateType==="admin"?"admin":"user",b=n.getConfig(m);g.setOnUnauthorized(()=>{U.log("Unauthorized - redirecting to login page"),g.removeToken();const A=window.location.pathname+window.location.search,x=n.getLoginRedirectUrl(m,A,"session_expired");window.location.href=x}),U.log("ApiClient onUnauthorized callback registered"),this.layoutLoader=new ff(e),this.extensionCacheVersion>0&&this.layoutLoader.setCacheVersion(this.extensionCacheVersion),U.log("LayoutLoader initialized:",this.layoutLoader);const S=new Er({onUnauthorized:()=>{U.warn("Unauthorized request in error page")}});if(this.errorPageHandler=new J_({templateId:this.config.templateId,layoutLoader:this.layoutLoader,locale:this.config.locale,debug:this.config.debug,renderFunction:hs,dataSourceManager:S,globalState:this.globalState}),U.log("ErrorPageHandler initialized with DataSourceManager"),await this.handleServerError()){U.log("Server error handled, skipping normal initialization");return}if(this.router=new Y_(this.config.templateId),Array.isArray(c.routes)){const A=this.resolveRouteExpressions(c.routes);this.router.setRoutes(A)}else throw new Error("Invalid routes data format");U.log("Router initialized:",this.router),U.log("Routes set:",this.router.getRoutes());const{getActionDispatcher:v}=await Promise.resolve().then(()=>Ur),_=v();if(_&&(_.setDefaultContext({navigate:A=>this.router?.navigate(A)}),_.setGlobalStateUpdater((A,x)=>this.setGlobalState(A,x)),U.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"&&py(window.location.pathname)){U.log("Layout editor mode detected — skipping router match"),await hs({containerId:"app",layoutJson:{components:[]},dataContext:{},translationContext:{templateId:this.config.templateId,locale:this.config.locale}}),U.log("Template App initialized in layout editor mode");return}this.router.navigateToCurrentPath(),U.log("Template App initialized successfully")}catch(e){U.error("Initialization failed:",e),this.showInitError(e)}}async loadExtensionAssets(){try{const e=wf(),n=eA();if(!n){await this.loadExtensionAssetsIndividually();return}await e.loadBundle("module",n.moduleJs,n.moduleCss),await e.loadBundle("plugin",n.pluginJs,n.pluginCss),U.log("Extension bundle assets loaded successfully")}catch(e){U.warn("Failed to load extension assets:",e)}}async loadExtensionAssetsIndividually(){const e=wf(),n=Z_();n.length>0&&(U.log("Loading module assets (individual fallback):",n.map(i=>i.identifier)),await e.loadActiveExtensionAssets(n));const a=tA();a.length>0&&(U.log("Loading plugin assets (individual fallback):",a.map(i=>i.identifier)),await e.loadActiveExtensionAssets(a))}async handleRouteChange(e){const n=++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(U.log("Route changed:",e,"requestId:",n),!this.layoutLoader)throw new Error("LayoutLoader is not initialized");if(!e.layout)throw new Error("Route layout is not defined");let a=e.layout;const i=a==="__preview__";i&&e.params?.token&&(a=`__preview__/${e.params.token}`);const l=await this.layoutLoader.loadLayout(this.config.templateId,a);if(n!==this.currentRouteChangeId){U.log("Route change cancelled (newer request exists):",n);return}U.log("Layout loaded:",l);const c=vr();l.errorHandling?(c.setLayoutConfig(l.errorHandling),U.log("Layout errorHandling registered:",l.errorHandling)):c.clearLayoutConfig();const d=l.data_sources||[],f=e.query||{},g=new URLSearchParams;for(const[Z,pe]of Object.entries(f))if(Array.isArray(pe))for(const H of pe)g.append(Z,H);else g.set(Z,pe);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:S}=await Promise.resolve().then(()=>Ur),v=new b;if(i){const Z=S();Z&&Z.setPreviewMode(!0),this.setGlobalState({__isPreview:!0}),Cc.show({id:"preview-mode",message:{ko:"⚠ 미리보기 모드 — 페이지 이동이 비활성화됩니다",en:"⚠ Preview Mode — Navigation is disabled"},background:"linear-gradient(90deg, #f59e0b, #d97706)",color:"white"}),U.log("Preview mode activated")}else{const Z=S();Z?.isPreviewMode()&&(Z.setPreviewMode(!1),Cc.hide("preview-mode"))}if(this.currentGlobalHeaders=l.globalHeaders||[],this.currentGlobalHeaders.length>0){v.setGlobalHeaders(this.currentGlobalHeaders);const Z=S();Z&&Z.setGlobalHeaders(this.currentGlobalHeaders),U.log("globalHeaders set:",this.currentGlobalHeaders.map(pe=>pe.pattern))}if(l.named_actions&&Object.keys(l.named_actions).length>0){const Z=S();Z&&Z.setNamedActions(l.named_actions)}const _=v.filterByCondition(d,m);d.length!==_.length&&U.log("Data sources filtered by condition:",{before:d.map(Z=>Z.id),after:_.map(Z=>Z.id)});const A=_.filter(Z=>Z.loading_strategy==="blocking"),x=_.filter(Z=>(Z.loading_strategy||"progressive")!=="blocking"&&Z.type!=="websocket"),L=Array.isArray(l.transition_overlay?.wait_for)?l.transition_overlay.wait_for:[],M=L.length>0&&_.some(Z=>L.includes(Z.id)&&Z.type!=="websocket"&&(Z.loading_strategy||"progressive")!=="background");if((A.length>0||M)&&l.transition_overlay){const Z=typeof l.transition_overlay=="boolean"?{enabled:l.transition_overlay,style:"opaque"}:l.transition_overlay;Z.enabled&&Z.style==="skeleton"&&Z.skeleton?.component&&Z.target?this.renderSkeletonOverlay(Z.target,Z.skeleton,l,Z.fallback_target):Z.enabled&&Z.style==="spinner"&&Z.target&&this.renderSpinnerOverlay(Z.target,Z.spinner,Z.fallback_target)}let R={},D={},B={},q={};this.currentWebSocketSubscriptions.length>0&&(U.log("Unsubscribing previous WebSocket subscriptions:",this.currentWebSocketSubscriptions),v.unsubscribeWebSockets(this.currentWebSocketSubscriptions),this.currentWebSocketSubscriptions=[]),this.currentDataSources=_,this.currentRawDataSources=d,this.currentRouteParams=e.params||{},this.currentQueryParams=g,U.log(`handleRouteChange #${n} - queryObject:`,f),U.log(`handleRouteChange #${n} - queryParams:`,g.toString()),A.length>0&&(U.log("Fetching blocking data sources:",A.map(pe=>pe.id)),(await v.fetchDataSourcesWithResults(A,e.params||{},g)).forEach(pe=>{if(pe.state==="success"&&pe.data!==void 0)R[pe.id]=pe.data;else if(pe.state==="error"&&pe.error){const H=pe.error,T=H.response?.data?.message;D[pe.id]={message:T||pe.error.message,status:H.response?.status||H.status}}}),this.processInitOptions(A,R,B,q),this.currentFetchedData={...R},U.log("Blocking data loaded:",Object.keys(R)),Object.keys(D).length>0&&U.log("Data source errors:",D),Object.keys(B).length>0&&U.log("Local state init (blocking):",Object.keys(B)),Object.keys(q).length>0&&U.log("Isolated state init (blocking):",Object.keys(q)));const P=x.length>0;if(P&&(Hr.setPending(!0),U.log("Transition started before rendering")),n!==this.currentRouteChangeId){U.log("Route change cancelled after blocking data (newer request exists):",n);return}const{getState:K}=await Promise.resolve().then(()=>Ur),ge=K().currentDataContext||{},Ee=x.map(Z=>Z.id),Se={};if(P){Ee.forEach(pe=>{ge[pe]!==void 0?Se[pe]=ge[pe]:Se[pe]=void 0});const Z=Object.keys(Se).filter(pe=>Se[pe]!==void 0);Z.length>0&&U.log("Preserving previous progressive data:",Z),U.log("Progressive data sources initialized:",Ee)}const Ue=l.defines||{},Ve={...Se,...e.params,...R,route:{...e.params||{},path:e.path},query:f,_global:{...this.globalState},_globalSetState:Z=>this.setGlobalState(Z),_dataSourceErrors:Object.keys(D).length>0?D:void 0,_localInit:Object.keys(B).length>0?B:void 0,_isolatedInit:Object.keys(q).length>0?q:void 0,_defines:Object.keys(Ue).length>0?Ue:void 0};if(l.computed&&Object.keys(l.computed).length>0){const Z=this.calculateComputed(l.computed,Ve);Object.keys(Z).length>0&&(Ve._computed=Z,this.globalState._computed=Z,U.log("Computed values calculated:",Object.keys(Z))),Ve._computedDefinitions=l.computed}const qe=l.layout_name||e.layout;this.currentLayoutName!==""&&this.currentLayoutName!==qe&&(U.log("_local reset due to layout change:",{from:this.currentLayoutName,to:qe}),this.globalState._local={},dC()),this.currentLayoutName=qe;const J=l.initLocal||l.state;if(J&&Object.keys(J).length>0){this.globalState._local||(this.globalState._local={});for(const[Z,pe]of Object.entries(J))this.globalState._local[Z]===void 0&&(this.globalState._local[Z]=JSON.parse(JSON.stringify(pe)));Ve._local={...this.globalState._local},U.log("initLocal applied to _local:",Object.keys(J))}if(l.initGlobal&&Object.keys(l.initGlobal).length>0){for(const[Z,pe]of Object.entries(l.initGlobal))this.globalState[Z]===void 0&&(this.globalState[Z]=JSON.parse(JSON.stringify(pe)));U.log("initGlobal applied to _global:",Object.keys(l.initGlobal))}if(l.initIsolated&&Object.keys(l.initIsolated).length>0){for(const[Z,pe]of Object.entries(l.initIsolated))q[Z]===void 0&&(q[Z]=JSON.parse(JSON.stringify(pe)));U.log("initIsolated applied:",Object.keys(l.initIsolated))}Ve._global={...this.globalState,layoutWarnings:l.warnings||[]};const fe=l.initActions||l.init_actions;if(fe&&fe.length>0){await this.executeInitActions(fe,Ve),U.log("initActions executed before render");const Z=this.globalState;if(Z._local){if(Object.keys(B).length>0){for(const[pe,H]of Object.entries(B))Z._local[pe]!==void 0?Z._local[pe]=this.deepMerge(Z._local[pe],H):Z._local[pe]=H;U.log("localInit merged into _local after initActions:",Object.keys(B))}Ve._local=Z._local,U.log("_local merged into dataContext:",Z._local)}if(Ve._global={...this.globalState,layoutWarnings:l.warnings||[]},U.log("_global merged into dataContext after initActions"),l.computed&&Object.keys(l.computed).length>0){const pe=this.calculateComputed(l.computed,Ve);Object.keys(pe).length>0&&(Ve._computed=pe,this.globalState._computed=pe,U.log("Computed values recalculated after init_actions:",Object.keys(pe)))}if(Object.keys(this.currentFetchedData).length>0){for(const[pe,H]of Object.entries(this.currentFetchedData))Ve[pe]=H;U.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 hs({containerId:"app",layoutJson:l,dataContext:Ve,translationContext:{templateId:this.config.templateId,locale:this.config.locale}}),U.log("Initial render complete with blocking data"),this.reattachSpinnerOverlay(),x.length>0){if(n!==this.currentRouteChangeId){U.log("Route change cancelled before progressive fetch (newer request exists):",n),Hr.setPending(!1),this.hideTransitionOverlay();return}U.log("Fetching progressive/background data sources:",x.map(H=>H.id));const{updateTemplateData:Z,getState:pe}=await Promise.resolve().then(()=>Ur);try{const H=x.map(async T=>{try{const de=(await v.fetchDataSourcesWithResults([T],e.params||{},g,this.globalState))[0];if(!de){U.log(`Data source ${T.id} skipped (no fetch result)`);return}if(n!==this.currentRouteChangeId){U.log(`Data source ${T.id} fetch cancelled (newer request exists)`);return}if(de.state==="success"&&de.data!==void 0){U.log(`Progressive data source loaded: ${T.id}`),this.currentFetchedData[T.id]=de.data;const ye={};this.processInitOptions([T],{[T.id]:de.data},ye);const ie=pe();if(ie.bindingEngine){const _e=[T.id];T.initGlobal&&_e.push("_global"),T.initLocal&&_e.push("_local"),ie.bindingEngine.invalidateCacheByKeys(_e)}const xe={[T.id]:de.data};Object.keys(ye).length>0&&(xe._localInit=ye,Object.assign(B,ye)),T.initGlobal&&(xe._global={...this.globalState}),Z(xe)}else if(de.state==="error"&&de.error){const ye=de.error,ie=ye.response?.data?.message;D[T.id]={message:ie||de.error.message,status:ye.response?.status||ye.status},U.log(`Progressive data source error: ${T.id}`,D[T.id]),Z({[T.id]:null,_dataSourceErrors:{...D}})}}catch(ce){U.error(`Failed to fetch data source: ${T.id}`,ce)}});if(await Promise.all(H),n!==this.currentRouteChangeId){U.log("Route change cancelled after progressive fetch (newer request exists):",n);return}U.log("All progressive data sources loaded")}finally{Hr.setPending(!1),this.hideTransitionOverlay()}}else this.hideTransitionOverlay();const Le=_.filter(Z=>Z.type==="websocket");if(Le.length>0){U.log("Subscribing WebSocket data sources:",Le.map(T=>T.id));const{updateTemplateData:Z,getState:pe}=await Promise.resolve().then(()=>Ur),H={...this.currentFetchedData,...e.params,route:{...e.params||{},path:e.path},query:f,_global:{...this.globalState}};U.log("WebSocket binding context keys:",Object.keys(H)),this.currentWebSocketSubscriptions=v.subscribeWebSockets(_,(T,ce)=>{U.log(`WebSocket data received for: ${T}`,ce),this.currentFetchedData[T]=ce;const de=_.find(_e=>_e.id===T),ye=pe();if(ye.bindingEngine){const _e=[T];de?.initGlobal&&_e.push("_global"),de?.initLocal&&_e.push("_local"),ye.bindingEngine.invalidateCacheByKeys(_e)}Z({[T]:ce});const xe=_.find(_e=>_e.type==="websocket"&&(_e.target_source||_e.id)===T)?.onReceive;Array.isArray(xe)&&xe.length>0&&window.G7Core?.dispatch&&(async()=>{for(const Te of xe)try{const $e=this.getActionDispatcher?.();$e&&await $e.dispatchAction(Te,{navigate:this.getRouter?.()?(ht,wt)=>this.getRouter().navigate(ht,wt):void 0,setState:ht=>this.setGlobalState(ht),state:this.globalState,data:{...this.globalState,$args:[ce],$event:ce},_isDispatchFallbackContext:!0})}catch($e){U.error(`WebSocket onReceive action failed for ${T}:`,$e)}})()},H),U.log("WebSocket subscriptions established:",this.currentWebSocketSubscriptions)}U.log("Layout rendered successfully")}catch(a){U.error("Route change handling failed:",a),this.hideTransitionOverlay(),this.showRouteError(a)}}processInitOptions(e,n,a,i){e.some(c=>c.refetchOnMount===!0&&c.initLocal)&&(a._forceLocalInit=Date.now(),U.log("refetchOnMount detected, forcing local state init")),e.forEach(c=>{const d=n[c.id];if(!d)return;const f=d.data??d;if(c.initLocal){if(typeof c.initLocal=="string"){let g=f;if(c.initLocalDefaults&&typeof c.initLocalDefaults=="object"){const b=this.evaluateDefaults(c.initLocalDefaults,n);g={...b,...f},U.log(`initLocalDefaults applied for ${c.initLocal}:`,Object.keys(b))}const m=this.globalState._local?.[c.initLocal];m!==void 0&&typeof m=="object"&&typeof g=="object"?(a[c.initLocal]=this.deepMerge(m,g),U.log(`initLocal (merged): ${c.id}.data -> _local.${c.initLocal}`)):(a[c.initLocal]=g,U.log(`initLocal: ${c.id}.data -> _local.${c.initLocal}`))}else if(typeof c.initLocal=="object"&&c.initLocal.key){const{key:g,path:m}=c.initLocal;let b=m?this.extractValueByPathOrExpression(f,m,c.id):f;if(c.initLocalDefaults&&typeof c.initLocalDefaults=="object"){const v=this.evaluateDefaults(c.initLocalDefaults,n);b={...v,...b},U.log(`initLocalDefaults applied for ${g}:`,Object.keys(v))}const S=this.globalState._local?.[g];S!==void 0&&typeof S=="object"&&typeof b=="object"?(a[g]=this.deepMerge(S,b),U.log(`initLocal (merged): ${c.id}.data${m?"."+m:""} -> _local.${g}`)):(a[g]=b,U.log(`initLocal: ${c.id}.data${m?"."+m:""} -> _local.${g}`))}else if(typeof c.initLocal=="object"){const g=c.initLocal._merge||"deep",m=this.flattenNestedObjectToMappings(c.initLocal);for(const{targetPath:b,sourcePath:S}of m){const v=this.extractValueByPathOrExpression(f,S,c.id);if(b.includes(".")){const _=b.split(".")[0];a[_]===void 0&&this.globalState._local?.[_]!==void 0&&(a[_]=JSON.parse(JSON.stringify(this.globalState._local[_]))),this.setValueAtPath(a,b,v,g),U.log(`initLocal map (${g}): ${c.id} ${S} -> _local.${b}`)}else{const _=this.globalState._local?.[b];g==="replace"?(a[b]=v,U.log(`initLocal map (replace): ${c.id} ${S} -> _local.${b}`)):g==="shallow"?_!==void 0&&typeof _=="object"&&typeof v=="object"?(a[b]={..._,...v},U.log(`initLocal map (shallow): ${c.id} ${S} -> _local.${b}`)):(a[b]=v,U.log(`initLocal map: ${c.id} ${S} -> _local.${b}`)):_!==void 0&&typeof _=="object"&&typeof v=="object"?(a[b]=this.deepMerge(_,v),U.log(`initLocal map (deep): ${c.id} ${S} -> _local.${b}`)):(a[b]=v,U.log(`initLocal map: ${c.id} ${S} -> _local.${b}`))}}}}if(c.initGlobal)if(typeof c.initGlobal=="object"&&!Array.isArray(c.initGlobal)&&!("key"in c.initGlobal))for(const[m,b]of Object.entries(c.initGlobal)){if(typeof b!="string"){U.warn(`initGlobal map value must be string, got ${typeof b} for key ${m}`);continue}const S=this.extractValueByPathOrExpression(f,b,c.id),v=this.globalState[m];v!==void 0&&typeof v=="object"&&typeof S=="object"?(this.globalState[m]=this.deepMerge(v,S),U.log(`initGlobal map (merged): ${c.id} ${b} -> _global.${m}`)):(this.globalState[m]=S,U.log(`initGlobal map: ${c.id} ${b} -> _global.${m}`))}else{const m=Array.isArray(c.initGlobal)?c.initGlobal:[c.initGlobal];for(const b of m)if(typeof b=="string"){const S=this.globalState[b];S!==void 0&&typeof S=="object"&&typeof f=="object"?(this.globalState[b]=this.deepMerge(S,f),U.log(`initGlobal (merged): ${c.id}.data -> _global.${b}`)):(this.globalState[b]=f,U.log(`initGlobal: ${c.id}.data -> _global.${b}`))}else if(typeof b=="object"&&b.key){const{key:S,path:v}=b,_=v?this.extractValueByPathOrExpression(f,v,c.id):f,A=this.globalState[S];A!==void 0&&typeof A=="object"&&typeof _=="object"?(this.globalState[S]=this.deepMerge(A,_),U.log(`initGlobal (merged): ${c.id}.data${v?"."+v:""} -> _global.${S}`)):(this.globalState[S]=_,U.log(`initGlobal: ${c.id}.data${v?"."+v:""} -> _global.${S}`))}}if(i&&c.initIsolated){if(typeof c.initIsolated=="string"){const g=i[c.initIsolated];g!==void 0&&typeof g=="object"&&typeof f=="object"?(i[c.initIsolated]=this.deepMerge(g,f),U.log(`initIsolated (merged): ${c.id}.data -> _isolated.${c.initIsolated}`)):(i[c.initIsolated]=f,U.log(`initIsolated: ${c.id}.data -> _isolated.${c.initIsolated}`))}else if(typeof c.initIsolated=="object"&&c.initIsolated.key){const{key:g,path:m}=c.initIsolated,b=m?this.extractValueByPathOrExpression(f,m,c.id):f,S=i[g];S!==void 0&&typeof S=="object"&&typeof b=="object"?(i[g]=this.deepMerge(S,b),U.log(`initIsolated (merged): ${c.id}.data${m?"."+m:""} -> _isolated.${g}`)):(i[g]=b,U.log(`initIsolated: ${c.id}.data${m?"."+m:""} -> _isolated.${g}`))}else if(typeof c.initIsolated=="object")for(const[g,m]of Object.entries(c.initIsolated)){if(typeof m!="string"){U.warn(`initIsolated map value must be string, got ${typeof m} for key ${g}`);continue}const b=this.extractValueByPathOrExpression(f,m,c.id),S=i[g];S!==void 0&&typeof S=="object"&&typeof b=="object"?(i[g]=this.deepMerge(S,b),U.log(`initIsolated map (merged): ${c.id} ${m} -> _isolated.${g}`)):(i[g]=b,U.log(`initIsolated map: ${c.id} ${m} -> _isolated.${g}`))}}})}evaluateDefaults(e,n){const a={};for(const[i,l]of Object.entries(e))if(typeof l=="string"&&l.startsWith("{{")&&l.endsWith("}}")){const c=l.slice(2,-2).trim();a[i]=this.evaluateExpression(c,n)}else a[i]=l;return a}evaluateExpression(e,n){try{const a=e.split("??").map(i=>i.trim());for(const i of a){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(n,i);if(l!=null)return l}return}catch(a){U.warn(`Expression evaluation failed: ${e}`,a);return}}getNestedValue(e,n){const a=n.replace(/\?\./g,".");let i=e;const l=a.split(/\.(?![^\[]*\])/).flatMap(c=>{const d=c.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[c]}).filter(c=>c!=="");for(const c of l){if(i==null)return;if(c.startsWith("[")&&c.endsWith("]")){const d=parseInt(c.slice(1,-1),10);i=i[d]}else i=i[c]}return i}extractValueByPathOrExpression(e,n,a){const i=Aa(n);if(i!==null){const l=new xn,c={data:e,_global:this.globalState,_local:this.globalState._local||{}};try{const d=Pn(i)?l.evaluatePipeExpression(i,c,{skipCache:!0}):l.evaluateExpression(i,c);return U.log(`initLocal/initGlobal expression evaluated: ${n} -> `,d),d}catch(d){U.warn(`initLocal/initGlobal expression evaluation failed for ${a}:`,n,d);return}}return this.getNestedValue(e,n)}async loadLayoutScripts(e,n){const a=[];for(const i of e){if((i.if!==void 0||i.conditions!==void 0)&&!ts({if:i.if,conditions:i.conditions},n,this.bindingEngine,`script:${i.id}`)){U.log(`Script skipped (condition not met): ${i.id}`);continue}if(document.getElementById(i.id)){U.log(`Script already loaded: ${i.id}`);continue}const c=new Promise((d,f)=>{const g=document.createElement("script");g.src=i.src,g.id=i.id,g.async=i.async??!0,g.onload=()=>{U.log(`Script loaded successfully: ${i.id}`),d()},g.onerror=()=>{U.warn(`Failed to load script: ${i.id} (${i.src})`),d()},document.head.appendChild(g)});a.push(c)}a.length>0&&(await Promise.all(a),U.log(`All scripts loaded: ${e.filter(i=>!document.getElementById(i.id)||a.length>0).map(i=>i.id).join(", ")}`))}evaluateScriptCondition(e,n){try{if(e.startsWith("{{")&&e.endsWith("}}")){const a=e.slice(2,-2).trim();return new Function("ctx",` + `}static renderFromError(e,n,a,i=!1,l,c,d){let f,g;if(n.userMessageKey.startsWith("$t:"))if(c&&l)try{f=c.translate(n.userMessageKey,l)}catch{f=n.userMessageKey.replace("$t:","")}else f=n.userMessageKey.replace("$t:","");else f=n.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:a,message:f,detailMessage:g,icon:n.icon,showStack:n.showStack,stackTrace:n.stack,showReloadButton:n.recoverable,debug:i})}static escapeHtml(e){if(!e)return"";const n=document.createElement("div");return n.textContent=e,n.innerHTML}}const ps=ht("Router");class dA{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,n){this.eventHandlers.has(e)||this.eventHandlers.set(e,[]),this.eventHandlers.get(e).push(n)}async emit(e,...n){const a=this.eventHandlers.get(e);a&&await Promise.all(a.map(i=>i(...n)))}async loadRoutes(e){try{const n=e!==void 0&&e>0?e:null,a=await fetch(Nr(`/api/templates/${this.templateIdentifier}/routes`,"json",n));if(!a.ok)throw new Error(`Failed to load routes: ${a.statusText}`);const i=await a.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,ps.log(`Loaded ${this.routes.length} routes${e?` (v=${e})`:""}`);else throw new Error("Invalid routes data format")}catch(n){throw ps.error("Error loading routes:",n),n}}setRoutes(e){this.routes=e,ps.log(`Set ${this.routes.length} routes`)}match(e){const n=this.normalizePathname(e);for(const a of this.routes){const i=this.matchPattern(a.path,n);if(i!==null)return{route:a,params:i}}return null}normalizePathname(e){return e.length>1&&e.endsWith("/")?e.replace(/\/+$/,"")||"/":e}matchPattern(e,n){const a=[];let i=e.replace(/:([^/]+)/g,(f,g)=>(a.push(g),"([^/]+)"));i.startsWith("*/")&&(i="(?:/[^/]+)?"+i.slice(1)),i=i.replace(/\//g,"\\/");const l=new RegExp(`^${i}$`),c=n.match(l);if(!c)return null;const d={};return a.forEach((f,g)=>{d[f]=c[g+1]}),d}getRoutes(){return[...this.routes]}getAuthType(e,n){return e.auth_type?e.auth_type:n.startsWith("/admin")?"admin":"user"}async navigateToCurrentPath(){const e=window.location.pathname,n=window.location.search,a=this.match(e);if(!a){ps.warn(`No route matched for path: ${e}`),this.emit("routeNotFound",e);return}if(a.route.redirect){ps.log(`Redirecting from ${e} to ${a.route.redirect}`),this.navigate(a.route.redirect);return}if(a.route.auth_required){const c=this.getAuthType(a.route,e),d=br.getInstance();let f=d.isAuthenticated()&&d.getAuthType()===c;if(f||(f=await d.checkAuth(c)),!f){const g=d.getLoginRedirectUrl(c,e+n);ps.log(`Not authenticated, redirecting to: ${g}`),window.location.href=g;return}}const i=new URLSearchParams(n),l={};for(const c of i.keys()){if(c in l)continue;const d=i.getAll(c);d.length>1?l[c]=d:d.length===1&&(c.endsWith("[]")?l[c]=d:l[c]=d[0])}await this.emit("routeChange",{path:e,layout:a.route.layout,endpoint:a.route.endpoint,params:{...a.route.params||{},...a.params},query:l,auth_required:a.route.auth_required,auth_type:a.route.auth_type,meta:a.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 n=this.pendingNavigation;this.executeNavigation(n)}}}}const fA=/^\/admin\/layout-editor\/([^/?#]+)\/?$/;function Ey(o){const e=fA.exec(o);return e?{templateIdentifier:e[1]}:null}const Gt=ht("ErrorPageHandler");class hA{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(Nr(`/api/templates/${this.templateId}/config`,"json"));if(!e.ok)return this.debug&&Gt.warn("Failed to load template config:",e.statusText),this.configLoaded=!0,null;const n=await e.json();if(!n.success||!n.data)return this.debug&&Gt.warn("Invalid template config response"),this.configLoaded=!0,null;const a=n.data;return!a.error_config||!a.error_config.layouts?(this.debug&&Gt.warn("No error_config found in template.json"),this.configLoaded=!0,null):(this.errorConfig=a.error_config,this.configLoaded=!0,this.debug&&Gt.log("Error config loaded:",this.errorConfig),this.errorConfig)}catch(e){return Gt.error("Failed to load error config:",e),this.configLoaded=!0,null}}async renderError(e,n="app"){try{const a=await this.loadConfig();if(!a)return this.debug&&Gt.warn("No error config available, cannot render error page"),!1;const i=a.layouts[e]||a.layouts[String(e)];if(!i)return this.debug&&Gt.warn(`No layout defined for error code: ${e}`),!1;this.debug&&Gt.log(`Loading error layout: ${i} for code: ${e}`);const l=await this.layoutLoader.loadLayout(this.templateId,i);if(!l)return this.debug&&Gt.error(`Failed to load error layout: ${i}`),!1;this.debug&&Gt.log("Error layout loaded:",l);let c={};const d=l.data_sources||[];if(d.length>0){this.debug&&Gt.log("Fetching data sources:",d.map(v=>v.id));const m=d.filter(v=>v.loading_strategy==="blocking"),y=d.filter(v=>!v.loading_strategy||v.loading_strategy==="progressive"),S=[...m,...y];if(S.length>0)try{c=await this.dataSourceManager.fetchDataSources(S,{},new URLSearchParams),this.debug&&Gt.log("Data sources fetched:",Object.keys(c))}catch(v){Gt.error("Failed to fetch data sources:",v)}}const f={};d.length>0&&(this.processInitOptions(d,c,f),this.debug&&Gt.log("initOptions processed:",{globalKeys:Object.keys(this.globalState),localKeys:Object.keys(f)}));const g={...c,errorCode:e,_global:{...this.globalState},_local:{...f}};return await this.renderFunction({containerId:n,layoutJson:l,dataContext:g,translationContext:{templateId:this.templateId,locale:this.locale}}),this.debug&&Gt.log(`Error page ${e} rendered successfully`),!0}catch(a){return Gt.error(`Failed to render error page ${e}:`,a),!1}}processInitOptions(e,n,a){for(const i of e){const l=n[i.id];if(!l)continue;const c=l?.data??l;if(i.initLocal){if(typeof i.initLocal=="string")a[i.initLocal]=c,Gt.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;a[d]=f?this.getValueByPath(c,f):c,Gt.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]=c,Gt.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(c,m):c,Gt.log(`initGlobal: ${i.id}.data${m?"."+m:""} -> _global.${g}`)}}}}getValueByPath(e,n){return n.split(".").reduce((a,i)=>a?.[i],e)}updateGlobalState(e){this.globalState={...this.globalState,...e}}updateLocale(e){this.locale=e,this.debug&&Gt.log("Locale updated:",e)}isConfigLoaded(){return this.configLoaded}async hasErrorLayout(e){const n=await this.loadConfig();return n?!!(n.layouts[e]||n.layouts[String(e)]):!1}clearConfigCache(){this.errorConfig=null,this.configLoaded=!1,this.debug&&Gt.log("Config cache cleared")}}const jt=ht("ModuleAssetLoader");class gA{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){jt.log("No module assets to load");return}const n=[...e].sort((d,f)=>d.priority-f.priority);jt.log("Loading module assets:",n.map(d=>d.identifier));const a=n.filter(d=>d.css).map(d=>this.loadCSS(d.identifier,d.css)),i=n.filter(d=>d.js).map(d=>this.loadJS(d.identifier,d.js)),l=await Promise.allSettled([...a,...i]),c=l.filter(d=>d.status==="rejected");if(c.length>0){jt.warn(`Some module assets failed to load (${c.length}/${l.length}); continuing with the rest`,this.getFailedJsAssets());return}jt.log("All module assets loaded successfully")}async loadBundle(e,n,a){const i=[];if(a&&i.push(this.loadBundleCss(e,a)),n&&i.push(this.loadBundleJs(e,n)),i.length===0){jt.log(`No bundle assets to load for: ${e}`);return}await Promise.all(i)}async loadBundleCss(e,n){const a=`ext-bundle-css-${e}`;if(document.getElementById(a)){jt.log(`Bundle CSS already loaded: ${e}`);return}return new Promise(i=>{const l=document.createElement("link");l.rel="stylesheet",l.href=n,l.id=a,l.onload=()=>{jt.log(`Bundle CSS loaded: ${e}`),this.registerLoadedAsset(`bundle-${e}`,{type:"css",element:l}),i()},l.onerror=()=>{jt.warn(`Failed to load bundle CSS: ${e} (${n})`),i()},document.head.appendChild(l)})}async loadBundleJs(e,n){const a=`ext-bundle-js-${e}`;if(document.getElementById(a)){jt.log(`Bundle JS already loaded: ${e}`);return}const i=this.loadingPromises.get(a);if(i)return jt.log(`Bundle JS already loading: ${e}`),i;const l=cp(n,{id:a},{label:`bundle JS: ${e}`}).then(()=>{jt.log(`Bundle JS loaded: ${e}`);const c=document.getElementById(a);c&&this.registerLoadedAsset(`bundle-${e}`,{type:"js",element:c}),this.loadingPromises.delete(a)}).catch(c=>{throw jt.warn(`Failed to load bundle JS: ${e} (${n})`,c),this.failedJsAssets.add(e),this.loadingPromises.delete(a),c});return this.loadingPromises.set(a,l),l}async loadCSS(e,n){const a=`module-css-${e}`;if(document.getElementById(a)){jt.log(`CSS already loaded: ${e}`);return}return new Promise((i,l)=>{const c=document.createElement("link");c.rel="stylesheet",c.href=n,c.id=a,c.onload=()=>{jt.log(`CSS loaded: ${e}`),this.registerLoadedAsset(e,{type:"css",element:c}),i()},c.onerror=()=>{jt.warn(`Failed to load CSS: ${e} (${n})`),i()},document.head.appendChild(c)})}async loadJS(e,n){const a=`module-js-${e}`;if(document.getElementById(a)){jt.log(`JS already loaded: ${e}`);return}const i=this.loadingPromises.get(e);if(i)return jt.log(`JS already loading: ${e}`),i;const l=cp(n,{id:a},{label:`JS: ${e}`}).then(()=>{jt.log(`JS loaded: ${e}`);const c=document.getElementById(a);c&&this.registerLoadedAsset(e,{type:"js",element:c}),this.loadingPromises.delete(e)}).catch(c=>{throw jt.warn(`Failed to load JS: ${e} (${n})`,c),this.failedJsAssets.add(e),this.loadingPromises.delete(e),c});return this.loadingPromises.set(e,l),l}registerLoadedAsset(e,n){const a=this.loadedAssets.get(e)||[];a.push(n),this.loadedAssets.set(e,a)}unloadExtensionAsset(e){const n=this.loadedAssets.get(e);if(!n||n.length===0){jt.log(`No assets to unload for: ${e}`);return}n.forEach(a=>{a.element.parentNode&&(a.element.parentNode.removeChild(a.element),jt.log(`${a.type.toUpperCase()} unloaded: ${e}`))}),this.loadedAssets.delete(e),jt.log(`All assets unloaded for: ${e}`)}unloadAllAssets(){Array.from(this.loadedAssets.keys()).forEach(n=>{this.unloadExtensionAsset(n)}),jt.log("All module assets unloaded")}isLoaded(e){return this.loadedAssets.has(e)}getLoadedModules(){return Array.from(this.loadedAssets.keys())}}let Ef=null;function _f(){return Ef||(Ef=new gA),Ef}function pA(){if(typeof window>"u")return[];const o=window.G7Config;if(!o?.moduleAssets)return[];const e=[];for(const[n,a]of Object.entries(o.moduleAssets)){const i=a;e.push({identifier:n,js:i.js?Ea(i.js):i.js,css:i.css?Ea(i.css):i.css,priority:i.priority,external:i.external})}return e}function mA(){if(typeof window>"u")return null;const o=window.G7Config;if(!o?.bundleUrls)return null;const e=o.bundleUrls;return{moduleJs:e.moduleJs?Ea(e.moduleJs):e.moduleJs,moduleCss:e.moduleCss?Ea(e.moduleCss):e.moduleCss,pluginJs:e.pluginJs?Ea(e.pluginJs):e.pluginJs,pluginCss:e.pluginCss?Ea(e.pluginCss):e.pluginCss}}function yA(){if(typeof window>"u")return[];const o=window.G7Config;if(!o?.pluginAssets)return[];const e=[];for(const[n,a]of Object.entries(o.pluginAssets)){const i=a;e.push({identifier:n,js:i.js?Ea(i.js):i.js,css:i.css?Ea(i.css):i.css,priority:i.priority,external:i.external})}return e}const Af=ht("SystemBannerManager");class Ac{static show(e){this.banners.set(e.id,e),this.render(),Af.log(`Banner shown: ${e.id}`)}static hide(e){this.banners.delete(e)&&(this.render(),Af.log(`Banner hidden: ${e}`))}static hideAll(){this.banners.clear(),this.render(),Af.log("All banners hidden")}static detectLocale(){try{const n=window.G7Core;if(n?.locale?.current)return n.locale.current()}catch{}return(navigator.language||"ko").split("-")[0]}static resolveMessage(e,n){return typeof e=="string"?e:e[n]||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 n=Array.from(this.banners.values()).sort((i,l)=>(i.order??0)-(l.order??0)),a=this.detectLocale();e.innerHTML=n.map(i=>{const l=this.resolveMessage(i.message,a),c=i.background||"#f59e0b",d=i.color||"white";return`
${l}
`}).join(""),requestAnimationFrame(()=>{e&&this.adjustAppPadding(e.offsetHeight)})}static adjustAppPadding(e){const n=document.getElementById("app");n&&(n.style.paddingTop=e>0?`${e}px`:"")}}$(Ac,"banners",new Map),$(Ac,"containerId","g7-system-banners");const B=ht("TemplateApp");function _y(o){const e={};for(const n of o.keys()){if(n in e)continue;const a=o.getAll(n);a.length>1?e[n]=a:a.length===1&&(n.endsWith("[]")?e[n]=a:e[n]=a[0])}return e}const xr=class xr{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 n=this.loadLocaleFromStorage(),a=n||e.locale||"ko";this.config={...e,locale:a},!n&&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 n=new Dn,a={_global:this.globalState};return e.map(i=>{const l={...i};if(l.path&&l.path.includes("{{")){const c=l.path;l.path=n.resolveBindings(l.path,a),l.path=l.path.replace(/\/\/+/g,"/")||"/",l.path.includes("{{")&&(B.warn("Route expression resolution failed, using fallback:",c),l.path=c.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/")}if(l.redirect&&l.redirect.includes("{{")){const c=l.redirect;l.redirect=n.resolveBindings(l.redirect,a),l.redirect=l.redirect.replace(/\/\/+/g,"/")||"/",l.redirect.includes("{{")&&(B.warn("Route redirect expression resolution failed:",c),l.redirect=c.replace(/\{\{[^}]+\}\}/g,"").replace(/\/\/+/g,"/")||"/")}return l})}migrateLocaleStorage(){const e=["locale","g7_template_locale"];for(const n of e)try{const a=localStorage.getItem(n);a&&a!==localStorage.getItem(xr.LOCALE_STORAGE_KEY)&&(localStorage.setItem(xr.LOCALE_STORAGE_KEY,a),B.log(`Migrated locale from '${n}' to '${xr.LOCALE_STORAGE_KEY}'`)),localStorage.removeItem(n)}catch(a){B.warn(`Failed to migrate locale key '${n}':`,a)}}async init(){try{to.getInstance().setDebug(this.config.debug),B.log("Initializing with config:",this.config),nw();const e=mr.getInstance(),n=br.getInstance(),a=this.loadCacheVersionFromStorage()||0,[i,l,c,d,f]=await Promise.all([No({templateId:this.config.templateId,templateType:this.config.templateType,locale:this.config.locale,debug:this.config.debug,cacheVersion:a}),e.loadComponents(this.config.templateId,this.config.templateType),Il(Nr(`/api/templates/${this.config.templateId}/routes`,"json",a>0?a: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}),n.preloadAuth(this.config.templateType==="admin"?"admin":"user"),fetch(Nr(`/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 x=await Il(Nr(`/api/templates/${this.config.templateId}/routes`,"json",this.extensionCacheVersion),{label:"routes.json (reload)"}).then(O=>{if(!O.ok)throw new Error(`Failed to reload routes: ${O.statusText}`);return O.json()}).then(O=>{if(!O.success)throw new Error("Failed to reload routes from API");return O.data});Array.isArray(x.routes)&&(x.routes=this.resolveRouteExpressions(x.routes),Object.assign(c,x),B.log("Routes reloaded with new cache version"));try{const{TranslationEngine:O}=await Promise.resolve().then(()=>gp),M=O.getInstance();M.setCacheVersion(this.extensionCacheVersion);const T=this.config.locale||"ko",D="en";await M.loadTranslations(this.config.templateId,T,"/api",!0),T!==D&&await M.loadTranslations(this.config.templateId,D,"/api",!0),B.log("Translations reloaded with new cache version")}catch(O){B.error("Failed to reload translations:",O)}}}f?.errorHandling&&(this.templateErrorHandling=f.errorHandling,Sr().setTemplateConfig(this.templateErrorHandling),B.log("Template errorHandling registered:",this.templateErrorHandling)),n.on("logout",()=>{B.log("User logged out")}),n.on("authStateChange",A=>{B.log("Auth state changed:",A)}),B.log("AuthManager event handlers registered");const g=Hr(),m=this.config.templateType==="admin"?"admin":"user",y=n.getConfig(m);g.setOnUnauthorized(()=>{B.log("Unauthorized - redirecting to login page"),g.removeToken();const A=window.location.pathname+window.location.search,x=n.getLoginRedirectUrl(m,A,"session_expired");window.location.href=x}),B.log("ApiClient onUnauthorized callback registered"),this.layoutLoader=new mf(e),this.extensionCacheVersion>0&&this.layoutLoader.setCacheVersion(this.extensionCacheVersion),B.log("LayoutLoader initialized:",this.layoutLoader);const S=new _r({onUnauthorized:()=>{B.warn("Unauthorized request in error page")}});if(this.errorPageHandler=new hA({templateId:this.config.templateId,layoutLoader:this.layoutLoader,locale:this.config.locale,debug:this.config.debug,renderFunction:ms,dataSourceManager:S,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 dA(this.config.templateId),Array.isArray(c.routes)){const A=this.resolveRouteExpressions(c.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:v}=await Promise.resolve().then(()=>Pr),_=v();if(_&&(_.setDefaultContext({navigate:A=>this.router?.navigate(A)}),_.setGlobalStateUpdater((A,x)=>this.setGlobalState(A,x)),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"&&Ey(window.location.pathname)){B.log("Layout editor mode detected — skipping router match"),await ms({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=_f(),n=mA();if(!n){await this.loadExtensionAssetsIndividually();return}await e.loadBundle("module",n.moduleJs,n.moduleCss),await e.loadBundle("plugin",n.pluginJs,n.pluginCss),B.log("Extension bundle assets loaded successfully")}catch(e){B.warn("Failed to load extension assets:",e)}}async loadExtensionAssetsIndividually(){const e=_f(),n=pA();n.length>0&&(B.log("Loading module assets (individual fallback):",n.map(i=>i.identifier)),await e.loadActiveExtensionAssets(n));const a=yA();a.length>0&&(B.log("Loading plugin assets (individual fallback):",a.map(i=>i.identifier)),await e.loadActiveExtensionAssets(a))}async handleRouteChange(e){const n=++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:",n),!this.layoutLoader)throw new Error("LayoutLoader is not initialized");if(!e.layout)throw new Error("Route layout is not defined");let a=e.layout;const i=a==="__preview__";i&&e.params?.token&&(a=`__preview__/${e.params.token}`);const l=await this.layoutLoader.loadLayout(this.config.templateId,a);if(n!==this.currentRouteChangeId){B.log("Route change cancelled (newer request exists):",n);return}B.log("Layout loaded:",l);const c=Sr();l.errorHandling?(c.setLayoutConfig(l.errorHandling),B.log("Layout errorHandling registered:",l.errorHandling)):c.clearLayoutConfig();const d=l.data_sources||[],f=e.query||{},g=new URLSearchParams;for(const[te,pe]of Object.entries(f))if(Array.isArray(pe))for(const N of pe)g.append(te,N);else g.set(te,pe);const m={route:e.params||{},query:f,_global:this.globalState};l.scripts&&Array.isArray(l.scripts)&&await this.loadLayoutScripts(l.scripts,m);const{DataSourceManager:y,getActionDispatcher:S}=await Promise.resolve().then(()=>Pr),v=new y;if(i){const te=S();te&&te.setPreviewMode(!0),this.setGlobalState({__isPreview:!0}),Ac.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=S();te?.isPreviewMode()&&(te.setPreviewMode(!1),Ac.hide("preview-mode"))}if(this.currentGlobalHeaders=l.globalHeaders||[],this.currentGlobalHeaders.length>0){v.setGlobalHeaders(this.currentGlobalHeaders);const te=S();te&&te.setGlobalHeaders(this.currentGlobalHeaders),B.log("globalHeaders set:",this.currentGlobalHeaders.map(pe=>pe.pattern))}if(l.named_actions&&Object.keys(l.named_actions).length>0){const te=S();te&&te.setNamedActions(l.named_actions)}const _=v.filterByCondition(d,m);d.length!==_.length&&B.log("Data sources filtered by condition:",{before:d.map(te=>te.id),after:_.map(te=>te.id)});const A=_.filter(te=>te.loading_strategy==="blocking"),x=_.filter(te=>(te.loading_strategy||"progressive")!=="blocking"&&te.type!=="websocket"),O=Array.isArray(l.transition_overlay?.wait_for)?l.transition_overlay.wait_for:[],M=O.length>0&&_.some(te=>O.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 T={},D={},z={},P={};this.currentWebSocketSubscriptions.length>0&&(B.log("Unsubscribing previous WebSocket subscriptions:",this.currentWebSocketSubscriptions),v.unsubscribeWebSockets(this.currentWebSocketSubscriptions),this.currentWebSocketSubscriptions=[]),this.currentDataSources=_,this.currentRawDataSources=d,this.currentRouteParams=e.params||{},this.currentQueryParams=g,B.log(`handleRouteChange #${n} - queryObject:`,f),B.log(`handleRouteChange #${n} - queryParams:`,g.toString()),A.length>0&&(B.log("Fetching blocking data sources:",A.map(pe=>pe.id)),(await v.fetchDataSourcesWithResults(A,e.params||{},g)).forEach(pe=>{if(pe.state==="success"&&pe.data!==void 0)T[pe.id]=pe.data;else if(pe.state==="error"&&pe.error){const N=pe.error,R=N.response?.data?.message;D[pe.id]={message:R||pe.error.message,status:N.response?.status||N.status}}}),this.processInitOptions(A,T,z,P),this.currentFetchedData={...T},B.log("Blocking data loaded:",Object.keys(T)),Object.keys(D).length>0&&B.log("Data source errors:",D),Object.keys(z).length>0&&B.log("Local state init (blocking):",Object.keys(z)),Object.keys(P).length>0&&B.log("Isolated state init (blocking):",Object.keys(P)));const q=x.length>0;if(q&&(jr.setPending(!0),B.log("Transition started before rendering")),n!==this.currentRouteChangeId){B.log("Route change cancelled after blocking data (newer request exists):",n);return}const{getState:W}=await Promise.resolve().then(()=>Pr),he=W().currentDataContext||{},Ee=x.map(te=>te.id),be={};if(q){Ee.forEach(pe=>{he[pe]!==void 0?be[pe]=he[pe]:be[pe]=void 0});const te=Object.keys(be).filter(pe=>be[pe]!==void 0);te.length>0&&B.log("Preserving previous progressive data:",te),B.log("Progressive data sources initialized:",Ee)}const Ue=l.defines||{},Fe={...be,...e.params,...T,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(z).length>0?z:void 0,_isolatedInit:Object.keys(P).length>0?P:void 0,_defines:Object.keys(Ue).length>0?Ue:void 0};if(l.computed&&Object.keys(l.computed).length>0){const te=this.calculateComputed(l.computed,Fe);Object.keys(te).length>0&&(Fe._computed=te,this.globalState._computed=te,B.log("Computed values calculated:",Object.keys(te))),Fe._computedDefinitions=l.computed}const Ge=l.layout_name||e.layout;this.currentLayoutName!==""&&this.currentLayoutName!==Ge&&(B.log("_local reset due to layout change:",{from:this.currentLayoutName,to:Ge}),this.globalState._local={},TC()),this.currentLayoutName=Ge;const J=l.initLocal||l.state;if(J&&Object.keys(J).length>0){this.globalState._local||(this.globalState._local={});for(const[te,pe]of Object.entries(J))this.globalState._local[te]===void 0&&(this.globalState._local[te]=JSON.parse(JSON.stringify(pe)));Fe._local={...this.globalState._local},B.log("initLocal applied to _local:",Object.keys(J))}if(l.initGlobal&&Object.keys(l.initGlobal).length>0){for(const[te,pe]of Object.entries(l.initGlobal))this.globalState[te]===void 0&&(this.globalState[te]=JSON.parse(JSON.stringify(pe)));B.log("initGlobal applied to _global:",Object.keys(l.initGlobal))}if(l.initIsolated&&Object.keys(l.initIsolated).length>0){for(const[te,pe]of Object.entries(l.initIsolated))P[te]===void 0&&(P[te]=JSON.parse(JSON.stringify(pe)));B.log("initIsolated applied:",Object.keys(l.initIsolated))}Fe._global={...this.globalState,layoutWarnings:l.warnings||[]};const ue=l.initActions||l.init_actions;if(ue&&ue.length>0){await this.executeInitActions(ue,Fe),B.log("initActions executed before render");const te=this.globalState;if(te._local){if(Object.keys(z).length>0){for(const[pe,N]of Object.entries(z))te._local[pe]!==void 0?te._local[pe]=this.deepMerge(te._local[pe],N):te._local[pe]=N;B.log("localInit merged into _local after initActions:",Object.keys(z))}Fe._local=te._local,B.log("_local merged into dataContext:",te._local)}if(Fe._global={...this.globalState,layoutWarnings:l.warnings||[]},B.log("_global merged into dataContext after initActions"),l.computed&&Object.keys(l.computed).length>0){const pe=this.calculateComputed(l.computed,Fe);Object.keys(pe).length>0&&(Fe._computed=pe,this.globalState._computed=pe,B.log("Computed values recalculated after init_actions:",Object.keys(pe)))}if(Object.keys(this.currentFetchedData).length>0){for(const[pe,N]of Object.entries(this.currentFetchedData))Fe[pe]=N;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 ms({containerId:"app",layoutJson:l,dataContext:Fe,translationContext:{templateId:this.config.templateId,locale:this.config.locale}}),B.log("Initial render complete with blocking data"),this.reattachSpinnerOverlay(),x.length>0){if(n!==this.currentRouteChangeId){B.log("Route change cancelled before progressive fetch (newer request exists):",n),jr.setPending(!1),this.hideTransitionOverlay();return}B.log("Fetching progressive/background data sources:",x.map(N=>N.id));const{updateTemplateData:te,getState:pe}=await Promise.resolve().then(()=>Pr);try{const N=x.map(async R=>{try{const fe=(await v.fetchDataSourcesWithResults([R],e.params||{},g,this.globalState))[0];if(!fe){B.log(`Data source ${R.id} skipped (no fetch result)`);return}if(n!==this.currentRouteChangeId){B.log(`Data source ${R.id} fetch cancelled (newer request exists)`);return}if(fe.state==="success"&&fe.data!==void 0){B.log(`Progressive data source loaded: ${R.id}`),this.currentFetchedData[R.id]=fe.data;const xe={};this.processInitOptions([R],{[R.id]:fe.data},xe);const ee=pe();if(ee.bindingEngine){const Be=[R.id];R.initGlobal&&Be.push("_global"),R.initLocal&&Be.push("_local"),ee.bindingEngine.invalidateCacheByKeys(Be)}const _e={[R.id]:fe.data};Object.keys(xe).length>0&&(_e._localInit=xe,Object.assign(z,xe)),R.initGlobal&&(_e._global={...this.globalState}),te(_e)}else if(fe.state==="error"&&fe.error){const xe=fe.error,ee=xe.response?.data?.message;D[R.id]={message:ee||fe.error.message,status:xe.response?.status||xe.status},B.log(`Progressive data source error: ${R.id}`,D[R.id]),te({[R.id]:null,_dataSourceErrors:{...D}})}}catch(de){B.error(`Failed to fetch data source: ${R.id}`,de)}});if(await Promise.all(N),n!==this.currentRouteChangeId){B.log("Route change cancelled after progressive fetch (newer request exists):",n);return}B.log("All progressive data sources loaded")}finally{jr.setPending(!1),this.hideTransitionOverlay()}}else this.hideTransitionOverlay();const Me=_.filter(te=>te.type==="websocket");if(Me.length>0){B.log("Subscribing WebSocket data sources:",Me.map(R=>R.id));const{updateTemplateData:te,getState:pe}=await Promise.resolve().then(()=>Pr),N={...this.currentFetchedData,...e.params,route:{...e.params||{},path:e.path},query:f,_global:{...this.globalState}};B.log("WebSocket binding context keys:",Object.keys(N)),this.currentWebSocketSubscriptions=v.subscribeWebSockets(_,(R,de)=>{B.log(`WebSocket data received for: ${R}`,de),this.currentFetchedData[R]=de;const fe=_.find(Be=>Be.id===R),xe=pe();if(xe.bindingEngine){const Be=[R];fe?.initGlobal&&Be.push("_global"),fe?.initLocal&&Be.push("_local"),xe.bindingEngine.invalidateCacheByKeys(Be)}te({[R]:de});const _e=_.find(Be=>Be.type==="websocket"&&(Be.target_source||Be.id)===R)?.onReceive;Array.isArray(_e)&&_e.length>0&&window.G7Core?.dispatch&&(async()=>{for(const ke of _e)try{const Ie=this.getActionDispatcher?.();Ie&&await Ie.dispatchAction(ke,{navigate:this.getRouter?.()?(Ct,ot)=>this.getRouter().navigate(Ct,ot):void 0,setState:Ct=>this.setGlobalState(Ct),state:this.globalState,data:{...this.globalState,$args:[de],$event:de},_isDispatchFallbackContext:!0})}catch(Ie){B.error(`WebSocket onReceive action failed for ${R}:`,Ie)}})()},N),B.log("WebSocket subscriptions established:",this.currentWebSocketSubscriptions)}B.log("Layout rendered successfully")}catch(a){B.error("Route change handling failed:",a),this.hideTransitionOverlay(),this.showRouteError(a)}}processInitOptions(e,n,a,i){e.some(c=>c.refetchOnMount===!0&&c.initLocal)&&(a._forceLocalInit=Date.now(),B.log("refetchOnMount detected, forcing local state init")),e.forEach(c=>{const d=n[c.id];if(!d)return;const f=d.data??d;if(c.initLocal){if(typeof c.initLocal=="string"){let g=f;if(c.initLocalDefaults&&typeof c.initLocalDefaults=="object"){const y=this.evaluateDefaults(c.initLocalDefaults,n);g={...y,...f},B.log(`initLocalDefaults applied for ${c.initLocal}:`,Object.keys(y))}const m=this.globalState._local?.[c.initLocal];m!==void 0&&typeof m=="object"&&typeof g=="object"?(a[c.initLocal]=this.deepMerge(m,g),B.log(`initLocal (merged): ${c.id}.data -> _local.${c.initLocal}`)):(a[c.initLocal]=g,B.log(`initLocal: ${c.id}.data -> _local.${c.initLocal}`))}else if(typeof c.initLocal=="object"&&c.initLocal.key){const{key:g,path:m}=c.initLocal;let y=m?this.extractValueByPathOrExpression(f,m,c.id):f;if(c.initLocalDefaults&&typeof c.initLocalDefaults=="object"){const v=this.evaluateDefaults(c.initLocalDefaults,n);y={...v,...y},B.log(`initLocalDefaults applied for ${g}:`,Object.keys(v))}const S=this.globalState._local?.[g];S!==void 0&&typeof S=="object"&&typeof y=="object"?(a[g]=this.deepMerge(S,y),B.log(`initLocal (merged): ${c.id}.data${m?"."+m:""} -> _local.${g}`)):(a[g]=y,B.log(`initLocal: ${c.id}.data${m?"."+m:""} -> _local.${g}`))}else if(typeof c.initLocal=="object"){const g=c.initLocal._merge||"deep",m=this.flattenNestedObjectToMappings(c.initLocal);for(const{targetPath:y,sourcePath:S}of m){const v=this.extractValueByPathOrExpression(f,S,c.id);if(y.includes(".")){const _=y.split(".")[0];a[_]===void 0&&this.globalState._local?.[_]!==void 0&&(a[_]=JSON.parse(JSON.stringify(this.globalState._local[_]))),this.setValueAtPath(a,y,v,g),B.log(`initLocal map (${g}): ${c.id} ${S} -> _local.${y}`)}else{const _=this.globalState._local?.[y];g==="replace"?(a[y]=v,B.log(`initLocal map (replace): ${c.id} ${S} -> _local.${y}`)):g==="shallow"?_!==void 0&&typeof _=="object"&&typeof v=="object"?(a[y]={..._,...v},B.log(`initLocal map (shallow): ${c.id} ${S} -> _local.${y}`)):(a[y]=v,B.log(`initLocal map: ${c.id} ${S} -> _local.${y}`)):_!==void 0&&typeof _=="object"&&typeof v=="object"?(a[y]=this.deepMerge(_,v),B.log(`initLocal map (deep): ${c.id} ${S} -> _local.${y}`)):(a[y]=v,B.log(`initLocal map: ${c.id} ${S} -> _local.${y}`))}}}}if(c.initGlobal)if(typeof c.initGlobal=="object"&&!Array.isArray(c.initGlobal)&&!("key"in c.initGlobal))for(const[m,y]of Object.entries(c.initGlobal)){if(typeof y!="string"){B.warn(`initGlobal map value must be string, got ${typeof y} for key ${m}`);continue}const S=this.extractValueByPathOrExpression(f,y,c.id),v=this.globalState[m];v!==void 0&&typeof v=="object"&&typeof S=="object"?(this.globalState[m]=this.deepMerge(v,S),B.log(`initGlobal map (merged): ${c.id} ${y} -> _global.${m}`)):(this.globalState[m]=S,B.log(`initGlobal map: ${c.id} ${y} -> _global.${m}`))}else{const m=Array.isArray(c.initGlobal)?c.initGlobal:[c.initGlobal];for(const y of m)if(typeof y=="string"){const S=this.globalState[y];S!==void 0&&typeof S=="object"&&typeof f=="object"?(this.globalState[y]=this.deepMerge(S,f),B.log(`initGlobal (merged): ${c.id}.data -> _global.${y}`)):(this.globalState[y]=f,B.log(`initGlobal: ${c.id}.data -> _global.${y}`))}else if(typeof y=="object"&&y.key){const{key:S,path:v}=y,_=v?this.extractValueByPathOrExpression(f,v,c.id):f,A=this.globalState[S];A!==void 0&&typeof A=="object"&&typeof _=="object"?(this.globalState[S]=this.deepMerge(A,_),B.log(`initGlobal (merged): ${c.id}.data${v?"."+v:""} -> _global.${S}`)):(this.globalState[S]=_,B.log(`initGlobal: ${c.id}.data${v?"."+v:""} -> _global.${S}`))}}if(i&&c.initIsolated){if(typeof c.initIsolated=="string"){const g=i[c.initIsolated];g!==void 0&&typeof g=="object"&&typeof f=="object"?(i[c.initIsolated]=this.deepMerge(g,f),B.log(`initIsolated (merged): ${c.id}.data -> _isolated.${c.initIsolated}`)):(i[c.initIsolated]=f,B.log(`initIsolated: ${c.id}.data -> _isolated.${c.initIsolated}`))}else if(typeof c.initIsolated=="object"&&c.initIsolated.key){const{key:g,path:m}=c.initIsolated,y=m?this.extractValueByPathOrExpression(f,m,c.id):f,S=i[g];S!==void 0&&typeof S=="object"&&typeof y=="object"?(i[g]=this.deepMerge(S,y),B.log(`initIsolated (merged): ${c.id}.data${m?"."+m:""} -> _isolated.${g}`)):(i[g]=y,B.log(`initIsolated: ${c.id}.data${m?"."+m:""} -> _isolated.${g}`))}else if(typeof c.initIsolated=="object")for(const[g,m]of Object.entries(c.initIsolated)){if(typeof m!="string"){B.warn(`initIsolated map value must be string, got ${typeof m} for key ${g}`);continue}const y=this.extractValueByPathOrExpression(f,m,c.id),S=i[g];S!==void 0&&typeof S=="object"&&typeof y=="object"?(i[g]=this.deepMerge(S,y),B.log(`initIsolated map (merged): ${c.id} ${m} -> _isolated.${g}`)):(i[g]=y,B.log(`initIsolated map: ${c.id} ${m} -> _isolated.${g}`))}}})}evaluateDefaults(e,n){const a={};for(const[i,l]of Object.entries(e))if(typeof l=="string"&&l.startsWith("{{")&&l.endsWith("}}")){const c=l.slice(2,-2).trim();a[i]=this.evaluateExpression(c,n)}else a[i]=l;return a}evaluateExpression(e,n){try{const a=e.split("??").map(i=>i.trim());for(const i of a){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(n,i);if(l!=null)return l}return}catch(a){B.warn(`Expression evaluation failed: ${e}`,a);return}}getNestedValue(e,n){const a=n.replace(/\?\./g,".");let i=e;const l=a.split(/\.(?![^\[]*\])/).flatMap(c=>{const d=c.match(/^([^\[]*)((?:\[\d+\])*)$/);if(d){const[,f,g]=d,m=[];f&&m.push(f);const y=g.match(/\[\d+\]/g);return y&&m.push(...y),m}return[c]}).filter(c=>c!=="");for(const c of l){if(i==null)return;if(c.startsWith("[")&&c.endsWith("]")){const d=parseInt(c.slice(1,-1),10);i=i[d]}else i=i[c]}return i}extractValueByPathOrExpression(e,n,a){const i=Aa(n);if(i!==null){const l=new Dn,c={data:e,_global:this.globalState,_local:this.globalState._local||{}};try{const d=Vn(i)?l.evaluatePipeExpression(i,c,{skipCache:!0}):l.evaluateExpression(i,c);return B.log(`initLocal/initGlobal expression evaluated: ${n} -> `,d),d}catch(d){B.warn(`initLocal/initGlobal expression evaluation failed for ${a}:`,n,d);return}}return this.getNestedValue(e,n)}async loadLayoutScripts(e,n){const a=[];for(const i of e){if((i.if!==void 0||i.conditions!==void 0)&&!ns({if:i.if,conditions:i.conditions},n,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 c=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)});a.push(c)}a.length>0&&(await Promise.all(a),B.log(`All scripts loaded: ${e.filter(i=>!document.getElementById(i.id)||a.length>0).map(i=>i.id).join(", ")}`))}evaluateScriptCondition(e,n){try{if(e.startsWith("{{")&&e.endsWith("}}")){const a=e.slice(2,-2).trim();return new Function("ctx",` with(ctx) { try { return Boolean(${a}); @@ -232,7 +232,7 @@ Error generating stack: `+u.message+` return false; } } - `)(n)}return!!e}catch(a){return U.warn(`Failed to evaluate script condition: ${e}`,a),!1}}showInitError(e){if(ld()){U.warn("Init failed while document is unloading — skipping error screen",e);return}const n=gy(e);vf.renderFromError("app",n,"초기화 실패",this.config.debug,{templateId:this.config.templateId,locale:this.config.locale},void 0,e)}showTransitionOverlay(e,n){const a=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(!a.enabled)return;if(this.hideTransitionOverlay(),a.style==="skeleton"&&a.skeleton?.component&&a.target&&n){this.renderSkeletonOverlay(a.target,a.skeleton,n,a.fallback_target);return}if(a.style==="spinner"&&a.target){this.renderSpinnerOverlay(a.target,a.spinner,a.fallback_target);return}const i=document.documentElement.classList.contains("dark");let l,c="";switch(a.style){case"blur":l=i?"rgba(17,24,39,0.3)":"rgba(255,255,255,0.3)",c="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(a.target){const d=`#${CSS.escape(a.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};${c}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 c.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,n,a,i){const c=pr.getInstance().getComponent(n.component);if(!c){U.log(`Skeleton component "${n.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){U.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,S=`#${CSS.escape(b)}`,v=document.createElement("style");v.id="g7-skeleton-overlay-style",v.textContent=`${S}{position:relative;z-index:0;}${S}::after{content:'';position:absolute;inset:0;background:${m};z-index:2147483646;pointer-events:none;}`,document.head.appendChild(v),this.transitionOverlayEl=v;const _=document.createElement("div");if(_.id="g7-skeleton-overlay",_.setAttribute("role","status"),_.setAttribute("aria-busy","true"),_.setAttribute("aria-label","Loading..."),f==="fullpage")_.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,B=window.scrollY||document.documentElement.scrollTop;_.style.cssText=["position:absolute",`top:${R.top+B}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(_),this.skeletonOverlayContainer=_;const A=a.components||[];let x;if(f==="fullpage")x=A;else{const R=f==="fallback"?i:e;x=this.findComponentChildrenById(A,R)}const L=rd.createRoot(_);this.skeletonOverlayRoot=L,ka.flushSync(()=>{L.render(Ye.createElement(c,{components:x,options:{animation:n.animation||"pulse",iteration_count:n.iteration_count||5}}))});const M=f==="fullpage"?"fullpage (#app)":f==="fallback"?`fallback (#${i})`:`target (#${e})`;U.log(`Skeleton overlay rendered [${M}] with "${n.component}" (${x.length} components)`)}findComponentChildrenById(e,n){const a=i=>{for(const l of i){if(l.id===n)return l.children||[];if(l.children&&Array.isArray(l.children)){const c=a(l.children);if(c!==null)return c}}return null};return a(e)||e}renderSpinnerOverlay(e,n,a){let i=document.getElementById(e),l="target";if(!i&&a&&(i=document.getElementById(a),l="fallback"),i||(i=document.getElementById("app"),l="fullpage"),!i){U.log(`Spinner overlay: no target found (target="#${e}", fallback="${a||"none"}"), falling back to opaque overlay`),this.showTransitionOverlay({enabled:!0,style:"opaque",target:e});return}this.hideSkeletonOverlay();const c=l==="fullpage"?"app":l==="fallback"?a:e,d=`#${CSS.escape(c)}`,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=n?.text||window.G7Core?.t?.("nav.loading")||"";this._spinnerState={target:e,fallbackTarget:a,spinnerConfig:n,resolvedText:g},this._mountSpinnerInTarget(i);const m=l==="fullpage"?"fullpage (#app)":l==="fallback"?`fallback (#${a})`:`target (#${e})`,b=n?.component||"default spinner";U.log(`Spinner overlay rendered [${m}] with "${b}"`)}_mountSpinnerInTarget(e){if(!this._spinnerState)return;const{spinnerConfig:n,resolvedText:a}=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,n?.component){const c=pr.getInstance().getComponent(n.component);if(c){const d=rd.createRoot(i);this.skeletonOverlayRoot=d,ka.flushSync(()=>{d.render(Ye.createElement(c,{options:{text:a}}))});return}U.log(`Spinner component "${n.component}" not found in registry, using default spinner`)}i.innerHTML='
'}reattachSpinnerOverlay(){if(!this._spinnerState)return;const{target:e,fallbackTarget:n}=this._spinnerState;let a=document.getElementById(e);!a&&n&&(a=document.getElementById(n)),a||(a=document.getElementById("app")),a&&(this._mountSpinnerInTarget(a),U.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 Cr&&e.details?.status===401){const a=this.config.templateId||"",i=window.location.pathname,l=a.includes("admin")||i.startsWith("/admin")?"admin":"user",c=i+window.location.search,d=!!Ir().getToken()||e.details?.hadToken===!0,f=yr.getInstance().getLoginRedirectUrl(l,c,d?"session_expired":void 0);window.location.href=f;return}const n=gy(e);vf.renderFromError("app",n,"페이지 로딩 실패",this.config.debug,{templateId:this.config.templateId,locale:this.config.locale},void 0,e)}async handleServerError(){const e=window.G7Error;if(!e)return!1;U.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"))?(U.log(`${e.code} error page rendered successfully`),!0):(U.log(`Falling back to ErrorDisplay for ${e.code}`),this.showInitError(new Error(`Service unavailable (${e.code})`)),!0)}catch(n){return U.error(`Failed to render ${e.code} page:`,n),this.showInitError(new Error(`Service unavailable (${e.code})`)),!0}}async handleRouteNotFound(e){U.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"))){U.log("404 error page rendered successfully");return}U.log("Falling back to ErrorDisplay for 404"),this.showRouteError(new Error(`Page not found: ${e}`))}catch(n){U.error("Failed to render 404 page:",n),this.showRouteError(new Error(`Page not found: ${e}`))}}getRouter(){return this.router}getConfig(){return this.config}getLayoutLoader(){return this.layoutLoader}async reloadExtensionState(){U.log("reloadExtensionState: start");let e;try{const n=await fetch($r(`/api/templates/${this.config.templateId}/config`,"json",null,`_=${Date.now()}`));if(n.ok){const a=await n.json();a?.success&&a?.data?.cache_version!==void 0&&(e=a.data.cache_version)}}catch(n){U.warn("reloadExtensionState: failed to fetch config.json",n)}e!==void 0&&e!==this.extensionCacheVersion&&(U.log(`reloadExtensionState: cache version ${this.extensionCacheVersion} -> ${e}`),this.extensionCacheVersion=e,this.saveCacheVersionToStorage(e));try{this.router&&(await this.router.loadRoutes(this.extensionCacheVersion),U.log("reloadExtensionState: routes reloaded"))}catch(n){U.error("reloadExtensionState: routes reload failed",n)}try{this.layoutLoader&&(this.extensionCacheVersion>0&&this.layoutLoader.setCacheVersion(this.extensionCacheVersion),this.layoutLoader.clear(),U.log("reloadExtensionState: layout cache cleared"))}catch(n){U.error("reloadExtensionState: layout cache clear failed",n)}try{const{TranslationEngine:n}=await Promise.resolve().then(()=>dp),a=n.getInstance();this.extensionCacheVersion>0&&a.setCacheVersion(this.extensionCacheVersion);const i=this.config.locale||"ko",l="en";await a.loadTranslations(this.config.templateId,i,"/api",!0),i!==l&&await a.loadTranslations(this.config.templateId,l,"/api",!0),U.log("reloadExtensionState: translations reloaded")}catch(n){U.error("reloadExtensionState: translations reload failed",n)}try{const n=await fetch(`/api/locales/active?_=${Date.now()}`);if(n.ok){const i=(await n.json())?.data?.locales;if(Array.isArray(i)&&i.length>0){const l=this.globalState.appConfig??{};this.setGlobalState({appConfig:{...l,supportedLocales:i}}),U.log("reloadExtensionState: supportedLocales refreshed",i)}}}catch(n){U.warn("reloadExtensionState: supportedLocales refresh failed",n)}U.log("reloadExtensionState: done")}getActionDispatcher(){return ea().actionDispatcher}async changeLocale(e){try{if(U.log("Changing locale to:",e),this.config.locale===e){U.log("Locale is already",e);return}this.config.locale=e,this.saveLocaleToStorage(e),await this.saveLocaleToDatabase(e),this.layoutLoader&&(this.layoutLoader.clear(),U.log("Layout cache cleared")),this.errorPageHandler&&(this.errorPageHandler.updateLocale(e),U.log("ErrorPageHandler locale updated")),Ec(),await Oo({templateId:this.config.templateId,templateType:this.config.templateType,locale:e,debug:this.config.debug,cacheVersion:this.extensionCacheVersion}),U.log("Template Engine re-initialized with new locale");const{getActionDispatcher:n}=await Promise.resolve().then(()=>Ur),a=n();a&&(a.setDefaultContext({navigate:i=>this.router?.navigate(i)}),a.setGlobalStateUpdater((i,l)=>this.setGlobalState(i,l)),U.log("Navigate function and setGlobalState re-injected to ActionDispatcher")),this.reinitializeModuleHandlers(),U.log("Module handlers re-initialized"),this.reinitializeTemplateHandlers(),U.log("Template handlers re-initialized"),this.reinitializePluginHandlers(),U.log("Plugin handlers re-initialized"),this.router&&this.router.navigateToCurrentPath(),U.log("Locale changed successfully to",e)}catch(n){throw U.error("Failed to change locale:",n),n}}loadLocaleFromStorage(){try{return localStorage.getItem(Ar.LOCALE_STORAGE_KEY)}catch(e){return U.warn("Failed to load locale from storage:",e),null}}saveLocaleToStorage(e){try{localStorage.setItem(Ar.LOCALE_STORAGE_KEY,e)}catch(n){U.warn("Failed to save locale to storage:",n)}}async saveLocaleToDatabase(e){const n=localStorage.getItem("auth_token");if(!n){U.log("No auth token, skipping DB locale save");return}let a,i;if(this.config.localeApi)a=this.config.localeApi.endpoint,i=this.config.localeApi.method;else{const l=this.config.templateType==="admin";a=l?"/api/admin/users/me/language":"/api/user/profile/update-language",i=l?"PATCH":"POST"}try{const l=this.getXsrfToken(),c=await fetch(a,{method:i,headers:{"Content-Type":"application/json",Accept:"application/json",...l&&{"X-XSRF-TOKEN":l},Authorization:`Bearer ${n}`},credentials:"include",body:JSON.stringify({language:e})});c.ok?U.log("Locale saved to DB:",e):U.warn("Failed to save locale to DB (UI will still change):",c.statusText)}catch(l){U.warn("Failed to call locale API (UI will still change):",l)}}getXsrfToken(){if(typeof document>"u")return null;const n=`; ${document.cookie}`.split("; XSRF-TOKEN=");return n.length===2?decodeURIComponent(n.pop()?.split(";").shift()||""):null}loadCacheVersionFromStorage(){try{const e=localStorage.getItem(Ar.CACHE_VERSION_STORAGE_KEY);return e?parseInt(e,10):null}catch(e){return U.warn("Failed to load cache version from storage:",e),null}}saveCacheVersionToStorage(e){try{localStorage.setItem(Ar.CACHE_VERSION_STORAGE_KEY,String(e))}catch(n){U.warn("Failed to save cache version to storage:",n)}}reinitializeModuleHandlers(){if(typeof window>"u")return;const e="__",n=window;Object.keys(n).forEach(a=>{if(a.startsWith(e)&&typeof n[a]?.initModule=="function")try{n[a].initModule(),U.log(`Module handler re-initialized: ${a}`)}catch(i){U.warn(`Failed to re-initialize module handlers for ${a}:`,i)}})}reinitializeTemplateHandlers(){if(typeof window>"u")return;const e=window.G7TemplateHandlers;if(!e){U.warn("Template handlers not found on window.G7TemplateHandlers");return}const n=this.getActionDispatcher();if(!n){U.warn("ActionDispatcher not available for template handler registration");return}Object.entries(e).forEach(([a,i])=>{n.registerHandler(a,i)}),U.log(`${Object.keys(e).length} template handler(s) re-registered:`,Object.keys(e))}reinitializePluginHandlers(){if(typeof window>"u")return;const e="__",n=window;Object.keys(n).forEach(a=>{if(a.startsWith(e)&&typeof n[a]?.initPlugin=="function")try{n[a].initPlugin(),U.log(`Plugin handler re-initialized: ${a}`)}catch(i){U.warn(`Failed to re-initialize plugin handlers for ${a}:`,i)}})}getLocale(){return this.config.locale}getErrorPageHandler(){return this.errorPageHandler}getGlobalState(){return{...this.globalState}}setGlobalState(e,n){const a={...this.globalState};typeof e=="function"?this.globalState=e(this.globalState):this.globalState={...this.globalState,...e},U.log("Global state updated:",this.globalState),window.G7Core?.devTools?.captureStateSnapshot?.({source:"setGlobalState",prev:a,next:this.globalState}),this.globalStateListeners.forEach(l=>{l(this.globalState)}),n?.render!==!1&&Promise.resolve().then(()=>Ur).then(({updateTemplateData:l,getState:c})=>{const d=c();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,n){let a=this.currentDataSources.find(i=>i.id===e);if(!a)for(const[,i]of this.modalDataSources){const l=i.find(c=>c.id===e);if(l){a=l;break}}if(!a){U.warn(`Data source not found: ${e}`);return}U.log(`Refetching data source: ${e}`,n?.sync?"(sync mode)":"",n?.globalStateOverride?"(with global override)":"",n?.localStateOverride?"(with local override)":""),Hr.setPending(!0);try{const i=new Er;this.currentGlobalHeaders.length>0&&i.setGlobalHeaders(this.currentGlobalHeaders);const l=ea(),c=l.currentDataContext?._global||{},d=n?.globalStateOverride?{...c,...n.globalStateOverride}:c,f=l.currentDataContext?._local||{},g=n?.localStateOverride?{...f,...n.localStateOverride}:f,b=(await i.fetchDataSourcesWithResults([a],this.currentRouteParams,this.currentQueryParams,d,g,{ignoreAutoFetch:!0}))[0];if(b.state==="success"&&b.data!==void 0){this.currentFetchedData[e]=b.data;const S={};this.processInitOptions([a],{[e]:b.data},S);const v=ea();if(v.bindingEngine){const A=[e];a.initGlobal&&A.push("_global"),a.initLocal&&A.push("_local"),v.bindingEngine.invalidateCacheByKeys(A)}const _={[e]:b.data};return Object.keys(S).length>0&&(_._localInit=S),a.initGlobal&&(_._global={...this.globalState}),gs(_,n?.sync?{sync:!0}:void 0),U.log(`Data source refetched successfully: ${e}`),b.data}else if(b.state==="error"){U.error(`Failed to refetch data source: ${e}`,b.error);return}}catch(i){U.error(`Error refetching data source: ${e}`,i);return}finally{Hr.setPending(!1)}}registerModalDataSources(e,n){this.modalDataSources.set(e,n),U.log(`Modal data sources registered: ${e} (${n.length} sources)`)}unregisterModalDataSources(e){this.modalDataSources.delete(e),U.log(`Modal data sources unregistered: ${e}`)}getDataSource(e){return this.currentFetchedData[e]}setDataSource(e,n,a){if(!e){U.warn("setDataSource: dataSourceId is required");return}const{merge:i=!1,sync:l=!1}=a||{};i&&this.currentFetchedData[e]?this.currentFetchedData[e]={...this.currentFetchedData[e],...n}:this.currentFetchedData[e]=n,Promise.resolve().then(()=>Ur).then(({updateTemplateData:c})=>{c({[e]:this.currentFetchedData[e]},l?{sync:!0}:void 0)}),U.log(`setDataSource: Updated ${e}`,i?"(merged)":"(replaced)")}updateDataSourceItem(e,n,a,i,l){const{idField:c="id",merge:d=!0,skipRender:f=!1}=l||{},g=this.currentFetchedData[e];if(!g)return U.warn(`updateDataSourceItem: DataSource '${e}' not found`),!1;const m=this.parseItemPath(n);let b=g;for(const _ of m)if(b=b?.[_],b===void 0)return U.warn(`updateDataSourceItem: Path '${n}' not found in dataSource`),!1;if(!Array.isArray(b))return U.warn(`updateDataSourceItem: Target at '${n}' is not an array`),!1;const S=b.findIndex(_=>String(_[c])===String(a));if(S===-1)return U.warn(`updateDataSourceItem: Item with ${c}='${a}' not found`),!1;d?b[S]=this.deepMerge(b[S],i):b[S]={...b[S],...i};const v=window.G7Core?.devTools;return v?.isEnabled?.()&&v.trackDataSourceUpdate?.({dataSourceId:e,updateType:"partial",itemPath:n,itemId:a,updates:i,timestamp:Date.now()}),f||Promise.resolve().then(()=>Ur).then(({updateTemplateData:_})=>{_({[e]:this.currentFetchedData[e]},{sync:!1})}),U.log(`updateDataSourceItem: Updated ${e}.${n}[${c}=${a}]`),!0}parseItemPath(e){const n=[],a=/([^\.\[\]]+)|\[(\d+)\]/g;let i;for(;(i=a.exec(e))!==null;)i[1]!==void 0?n.push(i[1]):i[2]!==void 0&&n.push(parseInt(i[2],10));return n}deepMerge(e,n){if(n==null)return e;if(typeof n!="object"||Array.isArray(n))return n;const a={...e};for(const i of Object.keys(n))typeof n[i]=="object"&&n[i]!==null&&!Array.isArray(n[i])?a[i]=this.deepMerge(a[i]||{},n[i]):a[i]=n[i];return a}setValueAtPath(e,n,a,i="deep"){const l=n.split(".");let c=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){U.log("No auto_fetch data sources to refetch");return}U.log(`Refetching ${g.length} auto_fetch data sources`),Hr.setPending(!0);const m=ea().currentLayoutJson,b=m?.transition_overlay,S=Array.isArray(b?.wait_for)?b.wait_for:[],v=g.some(A=>(A.loading_strategy||"progressive")==="blocking"),_=S.length>0&&g.some(A=>S.includes(A.id)&&A.type!=="websocket"&&(A.loading_strategy||"progressive")!=="background");if((v||_)&&b&&typeof b=="object"){const A=n?.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 Er;this.currentGlobalHeaders.length>0&&A.setGlobalHeaders(this.currentGlobalHeaders);const x=ea(),L=x.currentDataContext?._global||{},M=await A.fetchDataSourcesWithResults(g,this.currentRouteParams,this.currentQueryParams,L,void 0,{ignoreAutoFetch:!1}),R={},D={},B=new Map(g.map(q=>[q.id,q]));for(const q of M){const P=B.get(q.id);if(!P){U.warn(`Refetch result id not found in autoFetchDataSources: ${q.id}`);continue}const K=q.id;q.state==="success"&&q.data!==void 0?(this.currentFetchedData[K]=q.data,R[K]=q.data,this.processInitOptions([P],{[K]:q.data},D),U.log(`Data source refetched: ${K}`)):q.state==="error"&&U.error(`Failed to refetch data source: ${K}`,q.error)}if(x.bindingEngine){const q=Object.keys(R);q.push("query"),x.bindingEngine.invalidateCacheByKeys(q)}if(Object.keys(D).length>0&&(R._localInit=D),Object.keys(R).length>0){if(R.query=my(this.currentQueryParams),x.currentLayoutJson?.computed&&Object.keys(x.currentLayoutJson.computed).length>0){const q={...x.currentDataContext,...R,query:R.query},P=this.calculateComputed(x.currentLayoutJson.computed,q);Object.keys(P).length>0&&(R._computed=P,this.globalState._computed=P,U.log("Computed values recalculated in updateQueryParams:",Object.keys(P)))}gs(R,{sync:!0}),U.log("Template data updated with new query params")}}catch(A){U.error("Error in updateQueryParams:",A)}finally{Hr.setPending(!1),this.hideTransitionOverlay()}}calculateComputed(e,n){const a={},i=new xn;for(const[l,c]of Object.entries(e))try{let d;if(this.isComputedSwitchDefinition(c))d=i.resolveSwitch(c,n,{skipCache:!0});else if(typeof c=="string")if(c.startsWith("{{")&&c.endsWith("}}")){const f=c.slice(2,-2).trim();d=this.evaluateComputedExpression(f,n)}else d=c;a[l]=d,U.log(`Computed ${l}:`,d)}catch(d){U.warn(`Failed to calculate computed value: ${l}`,d),a[l]=void 0}return a}isComputedSwitchDefinition(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&"$switch"in e&&"$cases"in e}evaluateComputedExpression(e,n){try{return new Function("ctx",` + `)(n)}return!!e}catch(a){return B.warn(`Failed to evaluate script condition: ${e}`,a),!1}}showInitError(e){if(fd()){B.warn("Init failed while document is unloading — skipping error screen",e);return}const n=Cy(e);Cf.renderFromError("app",n,"초기화 실패",this.config.debug,{templateId:this.config.templateId,locale:this.config.locale},void 0,e)}showTransitionOverlay(e,n){const a=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(!a.enabled)return;if(this.hideTransitionOverlay(),a.style==="skeleton"&&a.skeleton?.component&&a.target&&n){this.renderSkeletonOverlay(a.target,a.skeleton,n,a.fallback_target);return}if(a.style==="spinner"&&a.target){this.renderSpinnerOverlay(a.target,a.spinner,a.fallback_target);return}const i=document.documentElement.classList.contains("dark");let l,c="";switch(a.style){case"blur":l=i?"rgba(17,24,39,0.3)":"rgba(255,255,255,0.3)",c="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(a.target){const d=`#${CSS.escape(a.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};${c}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 c.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,n,a,i){const c=mr.getInstance().getComponent(n.component);if(!c){B.log(`Skeleton component "${n.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)",y=f==="fullpage"?"app":f==="fallback"?i:e,S=`#${CSS.escape(y)}`,v=document.createElement("style");v.id="g7-skeleton-overlay-style",v.textContent=`${S}{position:relative;z-index:0;}${S}::after{content:'';position:absolute;inset:0;background:${m};z-index:2147483646;pointer-events:none;}`,document.head.appendChild(v),this.transitionOverlayEl=v;const _=document.createElement("div");if(_.id="g7-skeleton-overlay",_.setAttribute("role","status"),_.setAttribute("aria-busy","true"),_.setAttribute("aria-label","Loading..."),f==="fullpage")_.style.cssText=["position:fixed","inset:0","z-index:20","overflow:hidden","pointer-events:none",`background:${m}`].join(";")+";";else{const T=d.getBoundingClientRect(),D=window.scrollX||document.documentElement.scrollLeft,z=window.scrollY||document.documentElement.scrollTop;_.style.cssText=["position:absolute",`top:${T.top+z}px`,`left:${T.left+D}px`,`width:${T.width}px`,`height:${T.height}px`,"z-index:20","overflow:hidden","pointer-events:none",`background:${m}`].join(";")+";"}document.body.appendChild(_),this.skeletonOverlayContainer=_;const A=a.components||[];let x;if(f==="fullpage")x=A;else{const T=f==="fallback"?i:e;x=this.findComponentChildrenById(A,T)}const O=od.createRoot(_);this.skeletonOverlayRoot=O,ka.flushSync(()=>{O.render(Xe.createElement(c,{components:x,options:{animation:n.animation||"pulse",iteration_count:n.iteration_count||5}}))});const M=f==="fullpage"?"fullpage (#app)":f==="fallback"?`fallback (#${i})`:`target (#${e})`;B.log(`Skeleton overlay rendered [${M}] with "${n.component}" (${x.length} components)`)}findComponentChildrenById(e,n){const a=i=>{for(const l of i){if(l.id===n)return l.children||[];if(l.children&&Array.isArray(l.children)){const c=a(l.children);if(c!==null)return c}}return null};return a(e)||e}renderSpinnerOverlay(e,n,a){let i=document.getElementById(e),l="target";if(!i&&a&&(i=document.getElementById(a),l="fallback"),i||(i=document.getElementById("app"),l="fullpage"),!i){B.log(`Spinner overlay: no target found (target="#${e}", fallback="${a||"none"}"), falling back to opaque overlay`),this.showTransitionOverlay({enabled:!0,style:"opaque",target:e});return}this.hideSkeletonOverlay();const c=l==="fullpage"?"app":l==="fallback"?a:e,d=`#${CSS.escape(c)}`,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=n?.text||window.G7Core?.t?.("nav.loading")||"";this._spinnerState={target:e,fallbackTarget:a,spinnerConfig:n,resolvedText:g},this._mountSpinnerInTarget(i);const m=l==="fullpage"?"fullpage (#app)":l==="fallback"?`fallback (#${a})`:`target (#${e})`,y=n?.component||"default spinner";B.log(`Spinner overlay rendered [${m}] with "${y}"`)}_mountSpinnerInTarget(e){if(!this._spinnerState)return;const{spinnerConfig:n,resolvedText:a}=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,n?.component){const c=mr.getInstance().getComponent(n.component);if(c){const d=od.createRoot(i);this.skeletonOverlayRoot=d,ka.flushSync(()=>{d.render(Xe.createElement(c,{options:{text:a}}))});return}B.log(`Spinner component "${n.component}" not found in registry, using default spinner`)}i.innerHTML='
'}reattachSpinnerOverlay(){if(!this._spinnerState)return;const{target:e,fallbackTarget:n}=this._spinnerState;let a=document.getElementById(e);!a&&n&&(a=document.getElementById(n)),a||(a=document.getElementById("app")),a&&(this._mountSpinnerInTarget(a),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 Er&&e.details?.status===401){const a=this.config.templateId||"",i=window.location.pathname,l=a.includes("admin")||i.startsWith("/admin")?"admin":"user",c=i+window.location.search,d=!!Hr().getToken()||e.details?.hadToken===!0,f=br.getInstance().getLoginRedirectUrl(l,c,d?"session_expired":void 0);window.location.href=f;return}const n=Cy(e);Cf.renderFromError("app",n,"페이지 로딩 실패",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(n){return B.error(`Failed to render ${e.code} page:`,n),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(n){B.error("Failed to render 404 page:",n),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 n=await fetch(Nr(`/api/templates/${this.config.templateId}/config`,"json",null,`_=${Date.now()}`));if(n.ok){const a=await n.json();a?.success&&a?.data?.cache_version!==void 0&&(e=a.data.cache_version)}}catch(n){B.warn("reloadExtensionState: failed to fetch config.json",n)}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(n){B.error("reloadExtensionState: routes reload failed",n)}try{this.layoutLoader&&(this.extensionCacheVersion>0&&this.layoutLoader.setCacheVersion(this.extensionCacheVersion),this.layoutLoader.clear(),B.log("reloadExtensionState: layout cache cleared"))}catch(n){B.error("reloadExtensionState: layout cache clear failed",n)}try{const{TranslationEngine:n}=await Promise.resolve().then(()=>gp),a=n.getInstance();this.extensionCacheVersion>0&&a.setCacheVersion(this.extensionCacheVersion);const i=this.config.locale||"ko",l="en";await a.loadTranslations(this.config.templateId,i,"/api",!0),i!==l&&await a.loadTranslations(this.config.templateId,l,"/api",!0),B.log("reloadExtensionState: translations reloaded")}catch(n){B.error("reloadExtensionState: translations reload failed",n)}try{const n=await fetch(`/api/locales/active?_=${Date.now()}`);if(n.ok){const i=(await n.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(n){B.warn("reloadExtensionState: supportedLocales refresh failed",n)}B.log("reloadExtensionState: done")}getActionDispatcher(){return ea().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")),xc(),await No({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:n}=await Promise.resolve().then(()=>Pr),a=n();a&&(a.setDefaultContext({navigate:i=>this.router?.navigate(i)}),a.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(n){throw B.error("Failed to change locale:",n),n}}loadLocaleFromStorage(){try{return localStorage.getItem(xr.LOCALE_STORAGE_KEY)}catch(e){return B.warn("Failed to load locale from storage:",e),null}}saveLocaleToStorage(e){try{localStorage.setItem(xr.LOCALE_STORAGE_KEY,e)}catch(n){B.warn("Failed to save locale to storage:",n)}}async saveLocaleToDatabase(e){const n=localStorage.getItem("auth_token");if(!n){B.log("No auth token, skipping DB locale save");return}let a,i;if(this.config.localeApi)a=this.config.localeApi.endpoint,i=this.config.localeApi.method;else{const l=this.config.templateType==="admin";a=l?"/api/admin/users/me/language":"/api/user/profile/update-language",i=l?"PATCH":"POST"}try{const l=this.getXsrfToken(),c=await fetch(a,{method:i,headers:{"Content-Type":"application/json",Accept:"application/json",...l&&{"X-XSRF-TOKEN":l},Authorization:`Bearer ${n}`},credentials:"include",body:JSON.stringify({language:e})});c.ok?B.log("Locale saved to DB:",e):B.warn("Failed to save locale to DB (UI will still change):",c.statusText)}catch(l){B.warn("Failed to call locale API (UI will still change):",l)}}getXsrfToken(){if(typeof document>"u")return null;const n=`; ${document.cookie}`.split("; XSRF-TOKEN=");return n.length===2?decodeURIComponent(n.pop()?.split(";").shift()||""):null}loadCacheVersionFromStorage(){try{const e=localStorage.getItem(xr.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(xr.CACHE_VERSION_STORAGE_KEY,String(e))}catch(n){B.warn("Failed to save cache version to storage:",n)}}reinitializeModuleHandlers(){if(typeof window>"u")return;const e="__",n=window;Object.keys(n).forEach(a=>{if(a.startsWith(e)&&typeof n[a]?.initModule=="function")try{n[a].initModule(),B.log(`Module handler re-initialized: ${a}`)}catch(i){B.warn(`Failed to re-initialize module handlers for ${a}:`,i)}})}reinitializeTemplateHandlers(){if(typeof window>"u")return;const e=window.G7TemplateHandlers;if(!e){B.warn("Template handlers not found on window.G7TemplateHandlers");return}const n=this.getActionDispatcher();if(!n){B.warn("ActionDispatcher not available for template handler registration");return}Object.entries(e).forEach(([a,i])=>{n.registerHandler(a,i)}),B.log(`${Object.keys(e).length} template handler(s) re-registered:`,Object.keys(e))}reinitializePluginHandlers(){if(typeof window>"u")return;const e="__",n=window;Object.keys(n).forEach(a=>{if(a.startsWith(e)&&typeof n[a]?.initPlugin=="function")try{n[a].initPlugin(),B.log(`Plugin handler re-initialized: ${a}`)}catch(i){B.warn(`Failed to re-initialize plugin handlers for ${a}:`,i)}})}getLocale(){return this.config.locale}getErrorPageHandler(){return this.errorPageHandler}getGlobalState(){return{...this.globalState}}setGlobalState(e,n){const a={...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:a,next:this.globalState}),this.globalStateListeners.forEach(l=>{l(this.globalState)}),n?.render!==!1&&Promise.resolve().then(()=>Pr).then(({updateTemplateData:l,getState:c})=>{const d=c();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,n){let a=this.currentDataSources.find(i=>i.id===e);if(!a)for(const[,i]of this.modalDataSources){const l=i.find(c=>c.id===e);if(l){a=l;break}}if(!a){B.warn(`Data source not found: ${e}`);return}B.log(`Refetching data source: ${e}`,n?.sync?"(sync mode)":"",n?.globalStateOverride?"(with global override)":"",n?.localStateOverride?"(with local override)":""),jr.setPending(!0);try{const i=new _r;this.currentGlobalHeaders.length>0&&i.setGlobalHeaders(this.currentGlobalHeaders);const l=ea(),c=l.currentDataContext?._global||{},d=n?.globalStateOverride?{...c,...n.globalStateOverride}:c,f=l.currentDataContext?._local||{},g=n?.localStateOverride?{...f,...n.localStateOverride}:f,y=(await i.fetchDataSourcesWithResults([a],this.currentRouteParams,this.currentQueryParams,d,g,{ignoreAutoFetch:!0}))[0];if(y.state==="success"&&y.data!==void 0){this.currentFetchedData[e]=y.data;const S={};this.processInitOptions([a],{[e]:y.data},S);const v=ea();if(v.bindingEngine){const A=[e];a.initGlobal&&A.push("_global"),a.initLocal&&A.push("_local"),v.bindingEngine.invalidateCacheByKeys(A)}const _={[e]:y.data};return Object.keys(S).length>0&&(_._localInit=S),a.initGlobal&&(_._global={...this.globalState}),ys(_,n?.sync?{sync:!0}:void 0),B.log(`Data source refetched successfully: ${e}`),y.data}else if(y.state==="error"){B.error(`Failed to refetch data source: ${e}`,y.error);return}}catch(i){B.error(`Error refetching data source: ${e}`,i);return}finally{jr.setPending(!1)}}registerModalDataSources(e,n){this.modalDataSources.set(e,n),B.log(`Modal data sources registered: ${e} (${n.length} sources)`)}unregisterModalDataSources(e){this.modalDataSources.delete(e),B.log(`Modal data sources unregistered: ${e}`)}getDataSource(e){return this.currentFetchedData[e]}setDataSource(e,n,a){if(!e){B.warn("setDataSource: dataSourceId is required");return}const{merge:i=!1,sync:l=!1}=a||{};i&&this.currentFetchedData[e]?this.currentFetchedData[e]={...this.currentFetchedData[e],...n}:this.currentFetchedData[e]=n,Promise.resolve().then(()=>Pr).then(({updateTemplateData:c})=>{c({[e]:this.currentFetchedData[e]},l?{sync:!0}:void 0)}),B.log(`setDataSource: Updated ${e}`,i?"(merged)":"(replaced)")}updateDataSourceItem(e,n,a,i,l){const{idField:c="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(n);let y=g;for(const _ of m)if(y=y?.[_],y===void 0)return B.warn(`updateDataSourceItem: Path '${n}' not found in dataSource`),!1;if(!Array.isArray(y))return B.warn(`updateDataSourceItem: Target at '${n}' is not an array`),!1;const S=y.findIndex(_=>String(_[c])===String(a));if(S===-1)return B.warn(`updateDataSourceItem: Item with ${c}='${a}' not found`),!1;d?y[S]=this.deepMerge(y[S],i):y[S]={...y[S],...i};const v=window.G7Core?.devTools;return v?.isEnabled?.()&&v.trackDataSourceUpdate?.({dataSourceId:e,updateType:"partial",itemPath:n,itemId:a,updates:i,timestamp:Date.now()}),f||Promise.resolve().then(()=>Pr).then(({updateTemplateData:_})=>{_({[e]:this.currentFetchedData[e]},{sync:!1})}),B.log(`updateDataSourceItem: Updated ${e}.${n}[${c}=${a}]`),!0}parseItemPath(e){const n=[],a=/([^\.\[\]]+)|\[(\d+)\]/g;let i;for(;(i=a.exec(e))!==null;)i[1]!==void 0?n.push(i[1]):i[2]!==void 0&&n.push(parseInt(i[2],10));return n}deepMerge(e,n){if(n==null)return e;if(typeof n!="object"||Array.isArray(n))return n;const a={...e};for(const i of Object.keys(n))typeof n[i]=="object"&&n[i]!==null&&!Array.isArray(n[i])?a[i]=this.deepMerge(a[i]||{},n[i]):a[i]=n[i];return a}setValueAtPath(e,n,a,i="deep"){const l=n.split(".");let c=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`),jr.setPending(!0);const m=ea().currentLayoutJson,y=m?.transition_overlay,S=Array.isArray(y?.wait_for)?y.wait_for:[],v=g.some(A=>(A.loading_strategy||"progressive")==="blocking"),_=S.length>0&&g.some(A=>S.includes(A.id)&&A.type!=="websocket"&&(A.loading_strategy||"progressive")!=="background");if((v||_)&&y&&typeof y=="object"){const A=n?.transitionOverlayTarget||y.target;y.enabled&&y.style==="skeleton"&&y.skeleton?.component&&A?this.renderSkeletonOverlay(A,y.skeleton,m,y.fallback_target):y.enabled&&y.style==="spinner"&&A&&this.renderSpinnerOverlay(A,y.spinner,y.fallback_target)}try{const A=new _r;this.currentGlobalHeaders.length>0&&A.setGlobalHeaders(this.currentGlobalHeaders);const x=ea(),O=x.currentDataContext?._global||{},M=await A.fetchDataSourcesWithResults(g,this.currentRouteParams,this.currentQueryParams,O,void 0,{ignoreAutoFetch:!1}),T={},D={},z=new Map(g.map(P=>[P.id,P]));for(const P of M){const q=z.get(P.id);if(!q){B.warn(`Refetch result id not found in autoFetchDataSources: ${P.id}`);continue}const W=P.id;P.state==="success"&&P.data!==void 0?(this.currentFetchedData[W]=P.data,T[W]=P.data,this.processInitOptions([q],{[W]:P.data},D),B.log(`Data source refetched: ${W}`)):P.state==="error"&&B.error(`Failed to refetch data source: ${W}`,P.error)}if(x.bindingEngine){const P=Object.keys(T);P.push("query"),x.bindingEngine.invalidateCacheByKeys(P)}if(Object.keys(D).length>0&&(T._localInit=D),Object.keys(T).length>0){if(T.query=_y(this.currentQueryParams),x.currentLayoutJson?.computed&&Object.keys(x.currentLayoutJson.computed).length>0){const P={...x.currentDataContext,...T,query:T.query},q=this.calculateComputed(x.currentLayoutJson.computed,P);Object.keys(q).length>0&&(T._computed=q,this.globalState._computed=q,B.log("Computed values recalculated in updateQueryParams:",Object.keys(q)))}ys(T,{sync:!0}),B.log("Template data updated with new query params")}}catch(A){B.error("Error in updateQueryParams:",A)}finally{jr.setPending(!1),this.hideTransitionOverlay()}}calculateComputed(e,n){const a={},i=new Dn;for(const[l,c]of Object.entries(e))try{let d;if(this.isComputedSwitchDefinition(c))d=i.resolveSwitch(c,n,{skipCache:!0});else if(typeof c=="string")if(c.startsWith("{{")&&c.endsWith("}}")){const f=c.slice(2,-2).trim();d=this.evaluateComputedExpression(f,n)}else d=c;a[l]=d,B.log(`Computed ${l}:`,d)}catch(d){B.warn(`Failed to calculate computed value: ${l}`,d),a[l]=void 0}return a}isComputedSwitchDefinition(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&"$switch"in e&&"$cases"in e}evaluateComputedExpression(e,n){try{return new Function("ctx",` with(ctx) { try { return ${e}; @@ -240,5 +240,5 @@ Error generating stack: `+u.message+` return undefined; } } - `)(n)}catch(a){U.warn(`Expression evaluation failed: ${e}`,a);return}}async executeInitActions(e,n={}){const{getActionDispatcher:a}=await Promise.resolve().then(()=>Ur),i=a();if(!i){U.warn("ActionDispatcher not available for init_actions");return}U.log("Executing init_actions:",e.map(d=>d.handler)),U.log("Init actions dataContext:",n),U.log("Init actions dataContext._global:",n._global);const l=e.map(d=>d.handler).filter(d=>d.includes("."));l.length>0&&await this.waitForHandlers(i,l);let c={...n};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,c),m=new Event("init");await g(m),U.log(`Init action executed: ${d.handler}`);const b=this.globalState;c={...c,_global:{...b},_local:b._local||c._local||{}},U.log(`Data context refreshed after ${d.handler}:`,{cartKey:c._global?.cartKey})}catch(f){U.error(`Failed to execute init action: ${d.handler}`,f)}}async waitForHandlers(e,n,a=5e3){const i=Date.now(),l=50,c=()=>n.every(f=>e.customHandlers?.has(f));if(c()){U.log("All module handlers already registered");return}const d=wf().getFailedJsAssets();if(d.length>0){const f=d.some(b=>b==="module"||b==="plugin"),g=n.filter(b=>!e.customHandlers?.has(b)),m=g.length>0&&g.every(b=>d.some(S=>b.startsWith(`${S}.`)));if(f||m){U.warn("Extension asset load failed — not waiting for handlers that will never register:",{pending:g,failedAssets:d});return}}return U.log("Waiting for module handlers:",n),new Promise(f=>{const g=()=>{if(c()){U.log("All module handlers now registered"),f();return}if(Date.now()-i>=a){const m=n.filter(b=>!e.customHandlers?.has(b));U.warn("Timeout waiting for handlers:",m),f();return}setTimeout(g,l)};g()})}};$(Ar,"LOCALE_STORAGE_KEY","g7_locale"),$(Ar,"CACHE_VERSION_STORAGE_KEY","g7_cache_version");let xo=Ar;function Ef(o){const e=new xo(o);return o.websocket&&(vc.configure(o.websocket),U.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=Ef,window.G7Core.dataSource={refetch:async(o,e)=>{const n=window.__templateApp;if(!n){U.warn("TemplateApp not initialized (G7Core.dataSource.refetch)");return}return n.refetchDataSource(o,e)},get:o=>{const e=window.__templateApp;if(!e){U.warn("TemplateApp not initialized (G7Core.dataSource.get)");return}return e.getDataSource(o)}});function nA(o={}){const{checked:e,value:n,name:a,type:i="checkbox"}=o,c=n!==void 0?n:i==="checkbox"||i==="radio"?e??!1:String(e??""),d={checked:e??!1,value:c,name:a??"",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 rA(o={}){const{button:e=0,clientX:n=0,clientY:a=0}=o;return{button:e,clientX:n,clientY:a,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 aA(){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 iA(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 sA={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 yy(o){const e=o.replace(/^(dark:|hover:|focus:|active:|disabled:|group-hover:|sm:|md:|lg:|xl:|2xl:)+/,"");for(const[n,a]of Object.entries(sA))if(a.test(e))return n;return null}function by(o){const e=o.match(/^((dark:|hover:|focus:|active:|disabled:|group-hover:|sm:|md:|lg:|xl:|2xl:)+)/);return e?e[1]:""}function oA(o,e){if(!e||e.trim()==="")return o;if(!o||o.trim()==="")return e;const n=o.split(/\s+/).filter(Boolean),a=e.split(/\s+/).filter(Boolean),i=new Map;for(const c of a){const d=yy(c);if(d){const f=by(c),g=`${d}:${f}`;i.set(g,c)}}return[...n.filter(c=>{const d=yy(c);if(!d)return!0;const f=by(c),g=`${d}:${f}`;return!i.has(g)}),...a].join(" ")}function lA(o){return Object.entries(o).filter(([,e])=>e).map(([e])=>e).join(" ")}function cA(...o){return o.filter(e=>typeof e=="string"&&e.length>0).join(" ")}const be=ut("G7CoreGlobals");function uA(){window.React=Ye,window.ReactDOM={...ad,createPortal:ka.createPortal,unstable_batchedUpdates:o=>o()},window.ReactJSXRuntime=iC,be.log("전역 객체 window.React, window.ReactDOM, window.ReactJSXRuntime에 노출됨")}function dA(o){const e=new Map,n=Oa.getInstance();o.componentEvent={on:(a,i)=>(e.has(a)||e.set(a,new Set),e.get(a).add(i),n.trackEventSubscribe(a),()=>{e.get(a)?.delete(i),n.trackEventUnsubscribe(a)}),emit:async(a,i)=>{const l=e.get(a),c=l?.size??0;if(!l||l.size===0)return n.trackEventEmit(a,i,0),[];let d,f=[];try{f=await Promise.all(Array.from(l).map(async g=>{try{return await g(i)}catch(m){throw be.error(`componentEvent: Error in listener for "${a}":`,m),m}}))}catch(g){d=g instanceof Error?g:new Error(String(g))}if(n.trackEventEmit(a,i,c,f,d),d)throw d;return f},off:a=>{e.delete(a),n.trackEventOff(a)},clear:()=>{e.clear(),n.trackEventClear()}},be.log("전역 객체 window.G7Core.componentEvent에 노출됨")}function fA(o){o.__runtime||(o.__runtime={DynamicRenderer:jr,ComponentRegistry:pr,TranslationEngine:_a,DataSourceManager:Er,dataSourceManager:V_,DataBindingEngine:xn,dataBindingEngine:md,ActionDispatcher:po,TranslationReactContext:hf,TranslationProvider:mc,useTranslation:ty,ResponsiveContext:qd,ResponsiveProvider:nc,useResponsive:Gd,responsiveManager:hi,BREAKPOINT_PRESETS:Il,AuthManager:yr,createLogger:ut,G7DevToolsCore:Oa},be.log("전역 객체 window.G7Core.__runtime(코어 런타임 표면)에 노출됨"))}function hA(o){if(o.layoutEditor&&o.layoutEditor.__isStub!==!0||o.layoutEditor&&o.layoutEditor.__isStub===!0)return;const e=[],n=[];o.layoutEditor={__isStub:!0,__queue:e,__readyCallbacks:n,registerWidget:(a,i)=>e.push(["widget",a,i]),registerNodeEditor:(a,i)=>e.push(["nodeEditor",a,i]),registerCanvasOverlay:(a,i)=>e.push(["canvasOverlay",a,i]),onReady:a=>{typeof a=="function"&&n.push(a)}},be.log("전역 객체 window.G7Core.layoutEditor 예약 접수함(stub) 노출됨")}function gA(o,e){o.useTranslation=ty,o.t=(n,a)=>{const i=e.getState();if(!i.translationEngine||!i.translationContext)return n;if(a){const l="|"+Object.entries(a).map(([c,d])=>`${c}=${d}`).join("|");return i.translationEngine.translate(n,i.translationContext,l)}return i.translationEngine.translate(n,i.translationContext)},be.log("전역 객체 window.G7Core.useTranslation에 노출됨")}function pA(o,e){o.createChangeEvent=nA,o.createClickEvent=rA,o.createSubmitEvent=aA,o.createKeyboardEvent=iA,o.uuid=()=>typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,n=>{const a=Math.random()*16|0;return(n==="x"?a:a&3|8).toString(16)}),o.createLogger=ut,be.log("전역 객체 window.G7Core.createLogger에 노출됨"),o.renderItemChildren=(n,a,i,l,c)=>{const d=e.getState(),m={_global:window.__templateApp?.getGlobalState?.()||{},_local:a._local||{},_computed:a._computed||{},...a},b=new Set,S=(_,A)=>{const x=m._global?._remountKeys;return _&&x?.[_]&&!b.has(_)?(b.add(_),`${_}-remount-${x[_]}`):_||A},v={translationContext:d.translationContext,translationEngine:d.translationEngine,bindingEngine:d.bindingEngine,actionDispatcher:d.actionDispatcher,getRemountKey:S,...c};return io(n,m,i,l,v)},o.evaluateCondition=(n,a)=>{if(!n)return!0;const i=e.getState(),c=window.__templateApp?.getGlobalState?.()||{},d={_global:c,_local:c._local||{},_computed:c._computed||{},...a||{}},f=i.bindingEngine??md;return mp(n,d,f)},o.getComponentMap=()=>pr.getInstance().getComponentMap(),o.renderComponentLayout=(n,a,i)=>{if(!n||!Array.isArray(n)||n.length===0)return null;const l=pr.getInstance().getComponentMap(),c=e.getState(),f=window.__templateApp?.getGlobalState?.()||{},g={_global:f._global||{},_local:f._local||{},_computed:f._computed||{},...a},m=new Set,b=(S,v)=>{const _=g._global?._remountKeys;return S&&_?.[S]&&!m.has(S)?(m.add(S),`${S}-remount-${_[S]}`):S||v};return io(n,g,l,i,{translationContext:c.translationContext,translationEngine:c.translationEngine,bindingEngine:c.bindingEngine,actionDispatcher:c.actionDispatcher,getRemountKey:b})},o.renderExpandContent=n=>{const{children:a,row:i,expandContext:l,componentContext:c,keyPrefix:d}=n;if(!a||!Array.isArray(a)||a.length===0)return null;const f=n.componentMap||pr.getInstance().getComponentMap(),g=e.getState(),m=o.state?.get?.()||{},b=c?.stateRef?.current??c?.state??{},S={...m._local||{},...b},v=c?.computedRef?.current??m._computed??{},_=g.bindingEngine??o.getDataBindingEngine?.(),A={...m,_local:S,_computed:v,row:i,item:i,$item:i};let x={};if(l&&typeof l=="object"&&_)try{for(const[D,B]of Object.entries(l))if(typeof B=="string"){const q=Aa(B);if(q!==null)try{x[D]=Pn(q)?_.evaluatePipeExpression(q,A,{skipCache:!0}):_.evaluateExpression(q,A,{skipCache:!0})}catch{x[D]=void 0}else x[D]=_.resolveBindings(B,A,{skipCache:!0})}else x[D]=B}catch(D){be.warn("renderExpandContent: expandContext 평가 오류:",D)}const L={row:i,item:i,$item:i,_local:S,_global:m._global||{},_computed:m._computed||{},...x},M=new Set,R=(D,B)=>{const q=L._global?._remountKeys;return D&&q?.[D]&&!M.has(D)?(M.add(D),`${D}-remount-${q[D]}`):D||B};return io(a,L,f,d,{translationContext:g.translationContext,translationEngine:g.translationEngine??void 0,bindingEngine:g.bindingEngine??void 0,actionDispatcher:g.actionDispatcher,componentContext:c,getRemountKey:R})},o.$get=function(a,i,l=void 0){if(a==null)return l;const c=Array.isArray(i)?i:[i];if(c.length===0)return a;let d=a;for(const f of c){if(d==null||f==null)return l;d=d[f]}return d??l},be.log("전역 객체 window.G7Core.renderItemChildren에 노출됨"),be.log("전역 객체 window.G7Core.renderComponentLayout에 노출됨"),be.log("전역 객체 window.G7Core.renderExpandContent에 노출됨"),be.log("전역 객체 window.G7Core.$get에 노출됨")}function mA(o){o.dispatch=async(e,n)=>{const a=window.__templateApp;if(!a)return be.warn("G7Core.dispatch: TemplateApp이 초기화되지 않았습니다."),{success:!1,error:new Error("TemplateApp이 초기화되지 않았습니다.")};const i=a.getActionDispatcher?.();if(!i)return be.warn("G7Core.dispatch: ActionDispatcher를 찾을 수 없습니다."),{success:!1,error:new Error("ActionDispatcher를 찾을 수 없습니다.")};const l=a.getRouter?.(),c=a.getGlobalState?.(),d=a.setGlobalState?.bind(a),g=n?.componentContext||window.__g7ActionContext,m=window.__g7PendingLocalState;let b=g?.state??c;m&&g&&(b=m,be.log("[dispatch] Using __g7PendingLocalState for context.state:",m));let S=g?.data??c;m&&g?.data?._local&&(S={...g.data,_local:m},be.log("[dispatch] Updated context.data._local with pendingLocalState"));const v={navigate:l?(_,A)=>l.navigate(_,A):void 0,setState:g?.setState??d,state:b,data:S,_isDispatchFallbackContext:!g?.setState};if(e.debounce){const _=e.debounceKey||`dispatch-${e.handler}`,A=typeof e.debounce=="number"?e.debounce:e.debounce.delay;return i.debouncedCall(_,A,()=>{const{debounce:x,debounceKey:L,...M}=e;i.dispatchAction(M,v)}),{success:!0,debounced:!0}}try{return await i.dispatchAction(e,v)}catch(_){return be.error("G7Core.dispatch: 액션 실행 오류:",_),{success:!1,error:_ instanceof Error?_:new Error(String(_))}}},be.log("전역 객체 window.G7Core.dispatch에 노출됨")}function To(o){const e={};for(const[n,a]of Object.entries(o))if(n.includes(".")){const i=n.split(".");let l=e;for(let c=0;c0&&e.every(n=>/^\d+$/.test(n))}function Sy(o,e){const n={...o};for(const a of Object.keys(e))a in n?n[a]!==null&&typeof n[a]=="object"&&!Array.isArray(n[a])&&e[a]!==null&&typeof e[a]=="object"&&!Array.isArray(e[a])&&(n[a]=Sy(n[a],e[a])):n[a]=e[a];return n}function ar(o,e){if(Array.isArray(o)&&!Array.isArray(e)&&yA(e)){const a=Object.keys(e).map(l=>parseInt(l,10));if(!((a.length>0?Math.max(...a):0)>=o.length+a.length+10)){const l=[...o];for(const[c,d]of Object.entries(e)){const f=parseInt(c,10);f>=0&&f=l.length&&(l[f]=d)}return l}}const n={...o};for(const[a,i]of Object.entries(e))i!==null&&typeof i=="object"&&!Array.isArray(i)?n[a]!==null&&typeof n[a]=="object"?n[a]=ar(n[a],i):n[a]={...i}:n[a]=i;return n}function bA(o){o.state={get:()=>window.__templateApp?.getGlobalState?.()||{},set:(e,n)=>{const a=window.__templateApp;if(a?.setGlobalState&&a?.getGlobalState){const i=n?.merge||"deep",l=To(e);let c;if(i==="replace")c=l;else if(i==="shallow")c={...a.getGlobalState(),...l};else{const d=a.getGlobalState();c=ar(d,l)}a.setGlobalState(c,{render:n?.render})}else be.warn("G7Core.state.set: TemplateApp이 초기화되지 않았습니다.")},setLocal:(e,n)=>{const a=window.__templateApp;if(n?.render===!1&&!n?.selfManaged){const x=window.__g7AutoBindingPaths;x&&x.size>0&&vy(To(e)).some(M=>x.has(M))&&(be.log("[setLocal] render:false + 자동바인딩 경로 겹침 감지 → render:true 자동 승격 (engine-v1.43.0)"),n={...n,render:!0})}if(n?.debounce){const x=a?.getActionDispatcher?.();if(x){const L=n.debounceKey||`setLocal-${Object.keys(e).join(",")}`,{debounce:M,debounceKey:R,...D}=n;x.debouncedCall(L,n.debounce,()=>{o.state.setLocal(e,D)});return}}const i=n?.scope??"current",l=n?.merge||"deep",c=window.__g7ActionContext,d=To(e);if(i==="parent"||i==="root"){const x=window.__g7LayoutContextStack||[];if(x.length>0){const L=i==="parent"?x[x.length-1]:x[0];if(L?.setState){L.setState(M=>l==="replace"?d:l==="shallow"?{...M||{},...d}:ar(M||{},d)),be.log(`[setLocal] scope=${i}: 타겟 컨텍스트에 상태 업데이트 (mergeMode=${l})`,d);return}}be.warn(`[setLocal] scope=${i}: 레이아웃 컨텍스트 스택이 비어있습니다. current로 폴백합니다.`)}const f=window.__g7PendingLocalState,g=a?.getGlobalState?.()?._local||{},S=!((window.__g7LayoutContextStack||[]).length>0)&&c?.state?c.state:void 0,v=S?Sy(g,S):g,_=f||v;let A;if(l==="replace"?A=d:l==="shallow"?A={..._,...d}:A=ar(_,d),a?.setGlobalState&&(a.setGlobalState({_local:A},{render:n?.render}),be.log(`[setLocal] globalLocal updated via setGlobalState (mergeMode=${l}, render=${n?.render??!0}):`,d)),window.__g7PendingLocalState=A,be.log("[setLocal] __g7PendingLocalState updated:",A),window.__g7SequenceLocalSync=A,window.__g7LastSetLocalSnapshot=A,l==="replace")window.__g7ForcedLocalFields=d;else{const x=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=ar(x,d)}if(be.log("[setLocal] __g7ForcedLocalFields updated:",d),l==="replace")window.__g7SetLocalOverrideKeys=d;else{const x=window.__g7SetLocalOverrideKeys||{};window.__g7SetLocalOverrideKeys=ar(x,d)}be.log("[setLocal] __g7SetLocalOverrideKeys updated:",d),c?.setState&&c.setState(x=>l==="replace"?d:l==="shallow"?{...x||{},...d}:ar(x||{},d)),a?.setGlobalState||be.warn("G7Core.state.setLocal: TemplateApp이 없습니다.")},getLocal:()=>{const a=(window.__templateApp?.getGlobalState?.()||{})._local||{},i=window.__g7PendingLocalState;if(i)return ar(a,i);const l=window.__g7LastSetLocalSnapshot;return l&&l!==a?ar(a,l):a},update:e=>{const n=window.__templateApp;if(n?.getGlobalState&&n?.setGlobalState){const a=n.getGlobalState(),i=e(a);n.setGlobalState(i)}else be.warn("G7Core.state.update: TemplateApp이 초기화되지 않았습니다.")},subscribe:e=>{const n=window.__templateApp;return n?.onGlobalStateChange?n.onGlobalStateChange(e):(be.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,n,a)=>{let i,l,c;typeof e=="string"?(i=e,l=n||{},c=a):(l=e,c=n&&typeof n=="object"&&"merge"in n?n:a);const d=c?.merge||"deep",f=To(l);if(i){const b=window.__g7IsolatedStates?.[i];b?.mergeState?b.mergeState(f,d):be.warn(`G7Core.state.setIsolated: scopeId '${i}'를 찾을 수 없습니다.`);return}const g=window.__g7ActionContext;g?.isolatedContext?.mergeState?g.isolatedContext.mergeState(f,d):be.warn("G7Core.state.setIsolated: 액션 컨텍스트에 isolatedContext가 없습니다.")},getParent:()=>{const e=window.__g7LayoutContextStack||[];if(e.length===0)return be.log("[getParent] 레이아웃 컨텍스트 스택이 비어있습니다."),null;const n=e[e.length-1];if(!n)return null;const a=n.dataContext||{};return{_local:n.state||a._local||{},_global:a._global||o.state.get()||{},setState:n.setState}},setParentLocal:(e,n,a)=>{const i=window.__g7LayoutContextStack||[];if(i.length===0){be.warn("[setParentLocal] 레이아웃 컨텍스트 스택이 비어있습니다.");return}const l=i[i.length-1];if(!l?.setState){be.warn("[setParentLocal] 부모 컨텍스트에 setState가 없습니다.");return}let c,d;typeof e=="string"?(c={[e]:n},d=a):(c=e,d=n&&typeof n=="object"&&"merge"in n?n:a);const f=d?.merge||"deep",g=To(c),m=l.state?._local!==void 0,b=m?l.state._local:l.state||{};let S;f==="replace"?S=g:f==="shallow"?S={...b,...g}:S=ar(b,g),window.__g7PendingLocalState=S;const v=window.__templateApp;if(v?.setGlobalState&&v.setGlobalState({_local:S}),l.setState(S),m?l.state._local=S:l.state=S,l.dataContext&&(l.dataContext._local=S),f==="replace")window.__g7ForcedLocalFields=g;else{const _=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=ar(_,g)}Ud()},setParentGlobal:(e,n)=>{let a;typeof e=="string"?a={[e]:n}:a=e,o.state.set(a),be.log("[setParentGlobal] 전역 상태 업데이트:",a)}},window.__g7IsolatedStates||(window.__g7IsolatedStates={}),o.state.getGlobal=o.state.get,o.state.setGlobal=o.state.set,be.log("전역 객체 window.G7Core.state에 노출됨")}function vA(o){o.dataSource={get:e=>window.__templateApp?.getDataSource?.(e),set:(e,n,a)=>{const i=window.__templateApp;i?.setDataSource?i.setDataSource(e,n,a):be.warn("G7Core.dataSource.set: TemplateApp이 초기화되지 않았습니다.")},refetch:async(e,n)=>{const a=window.__templateApp;if(a?.refetchDataSource)return a.refetchDataSource(e,n);be.warn("G7Core.dataSource.refetch: TemplateApp이 초기화되지 않았습니다.")},updateItem:(e,n,a,i,l)=>{const c=window.__templateApp;return c?.updateDataSourceItem?c.updateDataSourceItem(e,n,a,i,l):(be.warn("G7Core.dataSource.updateItem: TemplateApp이 초기화되지 않았습니다."),!1)},updateData:(e,n,a,i="append")=>{const l=window.__templateApp;if(!l?.getDataSource||!l?.setDataSource)return be.warn("G7Core.dataSource.updateData: TemplateApp이 초기화되지 않았습니다."),!1;const c=l.getDataSource(e);if(!c)return be.warn(`G7Core.dataSource.updateData: 데이터 소스 '${e}'를 찾을 수 없습니다.`),!1;let d,f=c,g=null;if(n){const b=n.split(".");g=b.pop();for(const S of b)if(f&&typeof f=="object"&&S in f)f=f[S];else return be.warn(`G7Core.dataSource.updateData: 경로 '${n}'를 찾을 수 없습니다.`),!1;d=f[g]}else d=c;if(!Array.isArray(d))return be.warn("G7Core.dataSource.updateData: 대상 경로의 데이터가 배열이 아닙니다."),!1;if(!Array.isArray(a))return be.warn("G7Core.dataSource.updateData: newData가 배열이 아닙니다."),!1;const m=i==="prepend"?[...a,...d]:[...d,...a];return n&&g?(f[g]=m,l.setDataSource(e,c,{merge:!1})):l.setDataSource(e,m,{merge:!1}),be.log(`G7Core.dataSource.updateData: '${e}'에 ${a.length}개 항목 ${i==="prepend"?"앞에":"뒤에"} 추가됨`),!0}},be.log("전역 객체 window.G7Core.dataSource에 노출됨")}function SA(o,e){o.locale={current:()=>window.__templateApp?.getLocale?.()||"ko",supported:()=>{const a=window.__templateApp?.globalState?.appConfig?.supportedLocales;return Array.isArray(a)&&a.length>0?a:e.getState().templateMetadata?.locales||["ko","en"]},change:async n=>{const a=window.__templateApp;a?.changeLocale?await a.changeLocale(n):be.warn("G7Core.locale.change: TemplateApp이 초기화되지 않았습니다.")}},be.log("전역 객체 window.G7Core.locale에 노출됨")}function wA(o){o.toast={show:(e,n)=>{o.dispatch({handler:"toast",params:{message:e,type:n?.type||"info",...n?.duration&&{duration:n.duration}}})},success:(e,n)=>{o.toast.show(e,{type:"success",duration:n})},error:(e,n)=>{o.toast.show(e,{type:"error",duration:n})},warning:(e,n)=>{o.toast.show(e,{type:"warning",duration:n})},info:(e,n)=>{o.toast.show(e,{type:"info",duration:n})}},be.log("전역 객체 window.G7Core.toast에 노출됨")}function CA(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 n=o.state.get();return n._global?.activeModal===e||n._global?.modalStack?.includes(e)||!1},getStack:()=>o.state.get()._global?.modalStack||[]},be.log("전역 객체 window.G7Core.modal에 노출됨")}function EA(o){o.style={mergeClasses:oA,conditionalClass:lA,joinClasses:cA},be.log("전역 객체 window.G7Core.style에 노출됨")}function _A(o,e){const{webSocketManager:n}=e;o.websocket={manager:n,subscribe:(a,i,l,c)=>n.subscribe(a,i,l,c),unsubscribe:a=>n.unsubscribe(a),leaveChannel:a=>n.leaveChannel(a),disconnect:()=>n.disconnect(),isInitialized:()=>n.isInitialized(),getSubscriptionCount:()=>n.getSubscriptionCount()},be.log("전역 객체 window.G7Core.websocket에 노출됨")}function AA(o,e){const{transitionManager:n}=e;o.navigation={isPending:()=>n?.getIsPending?.()||!1,onComplete:a=>{if(!n)return a(),()=>{};let i=n.getIsPending();const l=n.subscribe(c=>{c?i=!0:i&&(a(),l())});return l}},be.log("전역 객체 window.G7Core.navigation에 노출됨")}function xA(o){o.plugin={getSettings:e=>window.G7Config?.plugins?.[e],get:(e,n,a)=>window.G7Config?.plugins?.[e]?.[n]??a,getAll:()=>window.G7Config?.plugins??{}},be.log("전역 객체 window.G7Core.plugin에 노출됨")}function TA(o){o.module={getSettings:e=>window.G7Config?.modules?.[e],get:(e,n,a)=>window.G7Config?.modules?.[e]?.[n]??a,getAll:()=>window.G7Config?.modules??{}},be.log("전역 객체 window.G7Core.module에 노출됨")}function RA(o,e){const{transitionManager:n,responsiveManager:a}=e;o.AuthManager=yr,o.api=Ir(),o.TransitionManager=n,o.useTransitionState=fm,o.ResponsiveManager=a,o.useResponsive=Gd,o.useControllableState=bC,o.shallowArrayEqual=vC,o.shallowObjectEqual=gm,o.updateQueryParams=async(i,l)=>{const c=window.__templateApp;if(c?.updateQueryParams)return c.updateQueryParams(i,l);be.warn("G7Core.updateQueryParams: TemplateApp이 초기화되지 않았습니다.")},be.log("전역 객체 window.G7Core.AuthManager에 노출됨"),be.log("전역 객체 window.G7Core.api에 노출됨"),be.log("전역 객체 window.G7Core.ResponsiveManager에 노출됨"),be.log("전역 객체 window.G7Core.useResponsive에 노출됨"),be.log("전역 객체 window.G7Core.useControllableState에 노출됨"),be.log("전역 객체 window.G7Core.updateQueryParams에 노출됨")}function kA(o,e){o.getSlotContext=()=>window.__slotContextValue??null,o.getDynamicRenderer=()=>window.__DynamicRenderer??null,o.getComponentRegistry=()=>e.getComponentRegistry?.()??pr.getInstance(),o.getDataBindingEngine=()=>e.getDataBindingEngine?.()??e.getState().bindingEngine,o.getTranslationEngine=()=>e.getTranslationEngine?.()??e.getState().translationEngine,o.getActionDispatcher=()=>e.getActionDispatcher?.()??e.getState().actionDispatcher,be.log("전역 객체 window.G7Core 슬롯 API에 노출됨 (getSlotContext, getDynamicRenderer 등)")}function DA(o){o.identity={setLauncher:vt.setLauncher.bind(vt),handle:vt.handle.bind(vt),isIdentityRequired:vt.isIdentityRequired.bind(vt),hasLauncher:vt.hasLauncher.bind(vt),markDomainNoticeShown:vt.markDomainNoticeShown.bind(vt),redirectExternally:vt.redirectExternally.bind(vt),createDeferred:vt.createDeferred.bind(vt),resolveDeferred:vt.resolveDeferred.bind(vt),reset:vt.reset.bind(vt),redirectStashKey:$d},be.log("전역 객체 window.G7Core 본인인증(IDV) API에 노출됨 (identity)")}function OA(o){if(typeof window>"u")return;uA(),window.G7Core||(window.G7Core={});const e=window.G7Core;fA(e),dA(e),hA(e),RA(e,o),gA(e,o),pA(e,o),mA(e),bA(e),vA(e),SA(e,o),wA(e),CA(e),EA(e),_A(e,o),AA(e,o),xA(e),TA(e),kA(e,o),DA(e),be.log("G7Core 전역 객체 초기화 완료")}function LA(){const o=window.G7Core;if(!o){be.warn("G7Core가 초기화되지 않았습니다.");return}const e=()=>Oa.getInstance(),n={isEnabled:()=>{try{return e().isEnabled()}catch{return!1}},trackRender:a=>{try{e().isEnabled()&&e().trackRender(a)}catch{}},trackIteration:(a,i,l,c,d)=>{try{e().isEnabled()&&e().trackIteration(a,{source:i,itemVar:l,indexVar:c,sourceLength:d})}catch{}},trackIfCondition:(a,i,l,c)=>{try{e().isEnabled()&&e().trackIfCondition(a,i,l)}catch{}},trackMount:(a,i)=>{try{e().isEnabled()&&e().trackMount(a,{...i,id:a})}catch{}},trackUnmount:a=>{try{e().isEnabled()&&e().trackUnmount(a)}catch{}},trackExpressionEval:a=>{try{e().isEnabled()&&e().trackExpressionEval(a)}catch{}},trackBindingEval:a=>{try{e().isEnabled()&&e().trackBindingEval(a)}catch{}},recordCacheHit:()=>{try{e().isEnabled()&&e().recordCacheHit()}catch{}},recordCacheMiss:()=>{try{e().isEnabled()&&e().recordCacheMiss()}catch{}},trackHandlerRegistration:(a,i,l,c)=>{try{e().isEnabled()&&e().trackHandlerRegistration(a,i,l,c)}catch{}},trackHandlerUnregistration:a=>{try{e().isEnabled()&&e().trackHandlerUnregistration(a)}catch{}},logAction:a=>{try{e().isEnabled()&&e().logAction(a)}catch{}},trackRequest:(a,i)=>{try{return e().isEnabled()?e().trackRequest(a,i):""}catch{return""}},completeRequest:(a,i,l)=>{try{e().isEnabled()&&e().completeRequest(a,i,l)}catch{}},failRequest:(a,i)=>{try{e().isEnabled()&&e().failRequest(a,i)}catch{}},trackDataSourceDefinition:a=>{try{e().isEnabled()&&e().trackDataSourceDefinition(a)}catch{}},trackDataSourceLoading:a=>{try{e().isEnabled()&&e().trackDataSourceLoading(a)}catch{}},trackDataSourceLoaded:(a,i,l)=>{try{e().isEnabled()&&e().trackDataSourceLoaded(a,i,l)}catch{}},trackDataSourceError:(a,i)=>{try{e().isEnabled()&&e().trackDataSourceError(a,i)}catch{}},trackForm:(a,i,l)=>{try{e().isEnabled()&&e().trackForm(a,i,l)}catch{}},untrackForm:a=>{try{e().isEnabled()&&e().untrackForm(a)}catch{}},startStateChange:(a,i,l,c)=>{try{return e().isEnabled()?e().startStateChange(a,i,l,c):""}catch{return""}},completeStateChange:a=>{try{e().isEnabled()&&e().completeStateChange(a)}catch{}},trackComponentRender:(a,i,l,c,d,f)=>{try{e().isEnabled()&&e().trackComponentRender(a,i,l,c,d,f)}catch{}},updateLocalState:a=>{try{e().isEnabled()&&e().updateLocalState(a)}catch{}},updateComputedState:a=>{try{e().isEnabled()&&e().updateComputedState(a)}catch{}},updateParentContext:a=>{try{e().isEnabled()&&e().updateParentContext(a)}catch{}},trackComponentStateSource:(a,i,l,c)=>{try{e().isEnabled()&&e().trackComponentStateSource(a,i,l,c)}catch{}},trackDynamicState:(a,i)=>{try{e().isEnabled()&&e().trackDynamicState(a,i)}catch{}},trackContextFlow:(a,i,l,c,d,f)=>{try{e().isEnabled()&&e().trackContextFlow(a,i,l,c,d,f)}catch{}},trackComponentStyle:(a,i,l,c)=>{try{e().isEnabled()&&e().trackComponentStyle(a,i,l,c)}catch{}},trackAuthEvent:(a,i,l,c)=>{try{e().isEnabled()&&e().trackAuthEvent(a,i,l,c)}catch{}},trackAuthHeader:(a,i,l,c,d)=>{try{e().isEnabled()&&e().trackAuthHeader(a,i,l,c,d)}catch{}},trackLog:(a,i,l)=>{try{e().isEnabled()&&e().trackLog(a,i,l)}catch{}},trackAction:a=>{try{e().isEnabled()&&e().trackAction?.(a)}catch{}},trackDataSourceUpdate:a=>{try{e().isEnabled()&&e().trackDataSourceUpdate?.(a)}catch{}},startSequenceExecution:a=>{try{return e().isEnabled()?e().startSequenceExecution(a):""}catch{return""}},captureSequenceActionBefore:(a,i,l,c,d)=>{try{e().isEnabled()&&e().captureSequenceActionBefore(a,i,l,c,d)}catch{}},captureSequenceActionAfter:(a,i,l,c,d,f)=>{try{e().isEnabled()&&e().captureSequenceActionAfter(a,i,l,c,d,f)}catch{}},endSequenceExecution:(a,i)=>{try{e().isEnabled()&&e().endSequenceExecution(a,i)}catch{}},registerStateCaptureForHandler:(a,i,l)=>{try{e().isEnabled()&&e().registerStateCaptureForHandler(a,i,l)}catch{}},detectStaleClosure:(a,i,l,c,d)=>{try{return e().isEnabled()?e().detectStaleClosure(a,i,l,c,d):[]}catch{return[]}},trackStaleClosureWarning:a=>{try{e().isEnabled()&&e().trackStaleClosureWarning(a)}catch{}},trackModalOpen:a=>{try{e().isEnabled()&&e().trackModalOpen(a)}catch{}},trackModalClose:(a,i)=>{try{e().isEnabled()&&e().trackModalClose(a,i)}catch{}},trackModalStateChange:a=>{try{e().isEnabled()&&e().trackModalStateChange(a)}catch{}},trackNestedContext:a=>{try{return e().isEnabled()?e().trackNestedContext(a):""}catch{return""}},trackNestedContextAccess:(a,i)=>{try{e().isEnabled()&&e().trackNestedContextAccess(a,i)}catch{}},trackComputedProperty:(a,i,l,c,d,f,g)=>{try{e().isEnabled()&&e().trackComputedProperty(a,i,l,c,d,f,g)}catch{}},trackComputedRecalc:(a,i,l,c,d,f,g)=>{try{e().isEnabled()&&e().trackComputedRecalc(a,i,l,c,d,f,g)}catch{}},setNamedActionDefinitions:a=>{try{e().isEnabled()&&e().setNamedActionDefinitions(a)}catch{}},trackNamedActionRef:a=>{try{e().isEnabled()&&e().trackNamedActionRef(a)}catch{}}};o.devTools=n,be.log("G7Core.devTools 인터페이스 초기화 완료")}let Ro=null;function MA(){const o=window.G7Core;return o?.__devtools?Promise.resolve(o.__devtools):Ro||(Ro=new Promise((e,n)=>{const a=window.G7Config?.coreDevToolsAsset||"/build/core/devtools.min.js",i="g7-devtools-bundle",l=()=>{const f=window.G7Core?.__devtools;f?e(f):n(new Error("DevTools 번들 로드됨 — 그러나 __devtools 미노출"))};window.G7Core=window.G7Core||{},window.G7Core.__onDevToolsReady=l;const c=document.getElementById(i);if(c){c.addEventListener("load",l,{once:!0}),c.addEventListener("error",()=>n(new Error(`DevTools 번들 로드 실패: ${a}`)),{once:!0});return}const d=document.createElement("script");d.id=i,d.src=a,d.async=!1,d.addEventListener("load",l,{once:!0}),d.addEventListener("error",()=>{Ro=null,n(new Error(`DevTools 번들 로드 실패: ${a}`))},{once:!0}),document.head.appendChild(d)}),Ro)}function $A(){const o=window.G7Core;if(!o){be.warn("G7Core가 초기화되지 않았습니다.");return}const e=Oa.getInstance();if(e.initialize(),!e.isEnabled()){window.G7DevTools={isEnabled:()=>!1,enable:()=>{be.log("환경설정 > 고급 설정 > 디버그 모드를 켜세요")}},sd(),be.log("G7DevTools 비활성화됨 (디버그 모드 꺼짐)");return}NA(o,e)}async function NA(o,e){let n;try{n=await MA()}catch(g){be.warn("DevTools 번들 로드 실패 — 최소 API 로 폴백:",g),window.G7DevTools={isEnabled:()=>!1,enable:()=>{}},sd();return}const{DiagnosticEngine:a,getServerConnector:i,getStyleTracker:l}=n;LA(),sd();try{l().enable(),be.log("StyleTracker 활성화됨")}catch(g){be.warn("StyleTracker 활성화 실패:",g)}const c=new a,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){be.warn("DataBindingEngine이 없습니다.");return}return m.evaluateExpression(g,e.getState())},getCacheStats:()=>e.getCacheStats(),clearStats:()=>{e.resetCacheStats(),be.log("캐시 통계 초기화됨")}},diagnose:{analyze:g=>c.analyze(g),suggestFix:g=>c.suggestFix(g),getCommonIssues:()=>c.getCommonIssues(),getRulesByCategory:g=>c.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,be.log("G7DevTools 전역 객체 초기화 완료 (window.G7DevTools)"),IA(n.DevToolsPanel)}function IA(o){if(document.getElementById("g7-devtools-root")){be.log("DevToolsPanel 이미 렌더링됨");return}const e=document.createElement("div");e.id="g7-devtools-root",document.body.appendChild(e);try{ad.createRoot(e).render(Ye.createElement(o)),be.log("DevToolsPanel UI 렌더링 완료")}catch(n){be.error("DevToolsPanel UI 렌더링 실패:",n)}}const Qe=ut("TemplateEngine"),ae={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 ko=!1;const Do=[];async function HA(o){try{Qe.log("템플릿 메타데이터 로드 중...",o);const e=o.split("-").map(a=>a.split("_").map(i=>i.charAt(0).toUpperCase()+i.slice(1)).join("")).join(""),n=window[e];return n?.templateMetadata?(Qe.log("템플릿 메타데이터 로드 완료 (전역 변수)",n.templateMetadata),n.templateMetadata):(Qe.warn(`템플릿 번들에 메타데이터가 없습니다. 전역 변수: ${e}`),{identifier:o,locales:["ko","en"],name:{ko:o,en:o},description:{ko:"",en:""},version:"1.0.0",type:"admin"})}catch(e){return Qe.error("템플릿 메타데이터 로드 실패",e),{identifier:o,locales:["ko","en"],name:{ko:o,en:o},description:{ko:"",en:""},version:"1.0.0",type:"admin"}}}function wy(){const e=(typeof window<"u"?window.__templateApp:void 0)?.globalState?.appConfig?.supportedLocales,n=ae.templateMetadata?.locales;return{$locale:ae.locale,$locales:Array.isArray(e)&&e.length>0?e:n||["ko","en"],$templateLocales:n||["ko","en"],$templateId:ae.templateId}}async function Oo(o){try{if(Qe.log("템플릿 엔진 초기화 시작",o),ae.isInitialized)throw new Error("템플릿 엔진이 이미 초기화되었습니다. destroyTemplate()을 먼저 호출하세요.");if(!o.templateId)throw new K_;ko=o.debug??!1,typeof window<"u"&&(window.G7Config||(window.G7Config={}),window.G7Config.debug=ko),$A(),ae.templateId=o.templateId,ae.locale=o.locale||"ko",Qe.log("엔진 인스턴스 생성 중..."),ae.registry=pr.getInstance(),ae.bindingEngine=new xn,ae.translationEngine=_a.getInstance(),o.cacheVersion!==void 0&&o.cacheVersion>0&&ae.translationEngine.setCacheVersion(o.cacheVersion),ae.translationContext={templateId:o.templateId,locale:ae.locale},ae.actionDispatcher=new po({},ae.translationEngine,ae.translationContext),cC(ae.actionDispatcher),Qe.log("다국어 파일 로드 중...",o.templateId,ae.locale);const e="en",n=[ae.translationEngine.loadTranslations(o.templateId,ae.locale).then(()=>{Qe.log(`다국어 파일 로드 완료: ${ae.locale}`)}).catch(a=>{Qe.warn(`다국어 파일 로드 실패 (${ae.locale}):`,a instanceof Error?a.message:a)})];ae.locale!==e&&n.push(ae.translationEngine.loadTranslations(o.templateId,e).then(()=>{Qe.log(`폴백 다국어 파일 로드 완료: ${e}`)}).catch(a=>{Qe.warn(`폴백 다국어 파일 로드 실패 (${e}):`,a instanceof Error?a.message:a)})),await Promise.allSettled(n),Qe.log("템플릿 메타데이터 로드 중...",o.templateId),ae.templateMetadata=await HA(o.templateId),ae.isInitialized=!0,Qe.log("템플릿 엔진 초기화 완료 (ComponentRegistry는 별도 로드)")}catch(e){throw Qe.error("템플릿 엔진 초기화 실패",e),ae.isInitialized=!1,ae.registry=null,ae.bindingEngine=null,ae.translationEngine=null,ae.actionDispatcher=null,e}}let Lo=null;function _f(){const o=window.G7Core;return o?.__LayoutEditorChrome?Promise.resolve(o.__LayoutEditorChrome):Lo||(Lo=new Promise((e,n)=>{const a=window.G7Config?.coreEditorAsset||"/build/core/layout-editor.min.js",i="g7-layout-editor-bundle",l=document.getElementById(i),c=()=>{const f=window.G7Core?.__LayoutEditorChrome;f?e(f):n(new Error("편집기 번들 로드됨 — 그러나 __LayoutEditorChrome 미노출"))};if(window.G7Core=window.G7Core||{},window.G7Core.__onChromeReady=c,l){l.addEventListener("load",c,{once:!0}),l.addEventListener("error",()=>n(new Error(`편집기 번들 로드 실패: ${a}`)),{once:!0});return}const d=document.createElement("script");d.id=i,d.src=a,d.async=!1,d.addEventListener("load",c,{once:!0}),d.addEventListener("error",()=>{Lo=null,n(new Error(`편집기 번들 로드 실패: ${a}`))},{once:!0}),document.head.appendChild(d)}),Lo)}async function hs(o){try{if(Qe.log("템플릿 렌더링 시작",o),!ae.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 n=wy();if(ae.containerId=o.containerId,ae.currentLayoutJson=o.layoutJson,ae.currentDataContext={...n,...o.dataContext||{}},ae.translationContext=o.translationContext||{templateId:ae.templateId||"",locale:ae.locale},ae.reactRoot||(Qe.log("React Root 생성"),ae.reactRoot=ad.createRoot(e)),typeof window<"u"){const l=py(window.location.pathname);if(l){Qe.log("레이아웃 편집기 모드 진입",l);let c;try{c=await _f()}catch(f){Qe.error("레이아웃 편집기 번들 로드 실패",f),vf.render(o.containerId,{title:"레이아웃 편집기 로드 실패",message:f instanceof Error?f.message:"편집기 번들을 불러오지 못했습니다.",icon:"fas fa-triangle-exclamation",showStack:!1,showReloadButton:!0,debug:ko});return}const d=Ye.createElement(c,{templateIdentifier:l.templateIdentifier,initialLocale:ae.locale});ae.reactRoot.render(Ye.createElement(mc,{translationEngine:ae.translationEngine,translationContext:ae.translationContext,children:Ye.createElement(Bd,{children:Ye.createElement(nc,{children:Ye.createElement(gf,{children:d})})})}));return}}const a=o.layoutJson.components||[];if(a.length===0){Qe.warn("렌더링할 컴포넌트가 없습니다.");return}const i=o.layoutJson.modals||[];if(Qe.log("modals 배열:",i),Qe.log("modals 개수:",i.length),Qe.log("DynamicRenderer로 렌더링 시작"),ae.reactRoot.render(Ye.createElement(mc,{translationEngine:ae.translationEngine,translationContext:ae.translationContext},Ye.createElement(Bd,null,Ye.createElement(nc,null,Ye.createElement(gf,null,[...a.map((l,c)=>{const d=ae.currentLayoutJson?.layout_name||"";return Ye.createElement(jr,{key:d&&!l._fromBase?`${l.id}_${d}`:l.id,componentDef:l,dataContext:ae.currentDataContext,translationContext:ae.translationContext,registry:ae.registry,bindingEngine:ae.bindingEngine,translationEngine:ae.translationEngine,actionDispatcher:ae.actionDispatcher,isRootRenderer:c===0,layoutKey:d})}),Ye.createElement(om,{key:"__modal_parent_context_provider"},i.map(l=>{const c=ae.currentDataContext._global?.modalStack||[],f=c.includes(l.id)||ae.currentDataContext._global?.activeModal===l.id,g=c.indexOf(l.id),m=g>=0?50+g:50,b=window.__g7LayoutContextStack||[],v=b[b.length-1]?.dataContext,_=Ye.createElement(jr,{key:`modal_${l.id}_renderer`,componentDef:{...l,props:{...l.props,isOpen:f,style:{...l.props?.style,zIndex:m},onClose:ae.actionDispatcher?.createHandler({type:"click",handler:"closeModal"},ae.currentDataContext)}},dataContext:ae.currentDataContext,translationContext:ae.translationContext,registry:ae.registry,bindingEngine:ae.bindingEngine,translationEngine:ae.translationEngine,actionDispatcher:ae.actionDispatcher,parentDataContext:v});return l.data_sources&&l.data_sources.length>0?Ye.createElement(hy,{key:`modal_${l.id}`,isOpen:f,modalId:l.id,dataSources:l.data_sources,dataContext:ae.currentDataContext,globalStateUpdater:ae.actionDispatcher?.getGlobalStateUpdater(),bindingEngine:ae.bindingEngine,debug:ko,children:_}):_}))]))))),Qe.log("템플릿 렌더링 완료"),Do.length>0){Qe.log(`대기 중인 데이터 업데이트 ${Do.length}건 적용`);const l=[...Do];Do.length=0;for(const{data:c,options:d}of l)gs(c,d)}}catch(e){throw Qe.error("템플릿 렌더링 실패",e),e}}function gs(o,e){try{if(Qe.log("템플릿 데이터 업데이트 시작",Object.keys(o)),!ae.isInitialized)throw new Error("템플릿 엔진이 초기화되지 않았습니다.");if(!ae.reactRoot||!ae.currentLayoutJson){Qe.log("React 미준비 - 데이터 업데이트 큐잉:",Object.keys(o)),Do.push({data:o,options:e});return}const n=wy(),a={...ae.currentDataContext._global||{},...o._global||{}},i=mC(ae.currentDataContext._localInit,o._localInit);ae.currentDataContext={...n,...ae.currentDataContext,...o,_global:a,_localInit:i},a._local!==void 0&&(ae.currentDataContext._local=a._local),a._computed!==void 0&&(ae.currentDataContext._computed=a._computed);const l=ae.currentLayoutJson.components||[],c=ae.currentLayoutJson.modals||[];Qe.log("updateTemplateData - modals 배열:",c),Qe.log("updateTemplateData - modals 개수:",c.length),Qe.log("updateTemplateData - activeModal:",ae.currentDataContext._global?.activeModal);const d=()=>{ae.reactRoot.render(Ye.createElement(mc,{translationEngine:ae.translationEngine,translationContext:ae.translationContext},Ye.createElement(Bd,null,Ye.createElement(nc,null,Ye.createElement(gf,null,[...l.map((f,g)=>{const m=ae.currentLayoutJson?.layout_name||"";return Ye.createElement(jr,{key:m&&!f._fromBase?`${f.id}_${m}`:f.id,componentDef:f,dataContext:ae.currentDataContext,translationContext:ae.translationContext,registry:ae.registry,bindingEngine:ae.bindingEngine,translationEngine:ae.translationEngine,actionDispatcher:ae.actionDispatcher,isRootRenderer:g===0,layoutKey:m})}),Ye.createElement(om,{key:"__modal_parent_context_provider_update"},c.map(f=>{const g=ae.currentDataContext._global?.modalStack||[],b=g.includes(f.id)||ae.currentDataContext._global?.activeModal===f.id,S=g.indexOf(f.id),v=S>=0?50+S:50,_=window.__g7LayoutContextStack||[],x=_[_.length-1]?.dataContext,L=Ye.createElement(jr,{key:`modal_${f.id}_renderer`,componentDef:{...f,props:{...f.props,isOpen:b,style:{...f.props?.style,zIndex:v},onClose:ae.actionDispatcher?.createHandler({type:"click",handler:"closeModal"},ae.currentDataContext)}},dataContext:ae.currentDataContext,translationContext:ae.translationContext,registry:ae.registry,bindingEngine:ae.bindingEngine,translationEngine:ae.translationEngine,actionDispatcher:ae.actionDispatcher,parentDataContext:x});return f.data_sources&&f.data_sources.length>0?Ye.createElement(hy,{key:`modal_${f.id}`,isOpen:b,modalId:f.id,dataSources:f.data_sources,dataContext:ae.currentDataContext,globalStateUpdater:ae.actionDispatcher?.getGlobalStateUpdater(),bindingEngine:ae.bindingEngine,debug:ko,children:L}):L}))])))))};e?.sync?(Qe.log("재렌더링 시작 (sync mode - 즉시 렌더링)"),d()):(Qe.log("재렌더링 시작 (with startTransition)"),N.startTransition(()=>{d()})),Qe.log("템플릿 데이터 업데이트 완료")}catch(n){throw Qe.error("템플릿 데이터 업데이트 실패",n),n}}function Ec(){try{Qe.log("템플릿 정리 시작"),ae.reactRoot&&(Qe.log("React Root 언마운트"),ae.reactRoot.unmount(),ae.reactRoot=null),ae.templateId=null,ae.locale="ko",ae.isInitialized=!1,ae.containerId=null,ae.currentLayoutJson=null,ae.currentDataContext={},ae.translationContext={templateId:"",locale:"ko"},ae.registry=null,ae.bindingEngine=null,ae.translationEngine=null,ae.actionDispatcher=null,ae.templateMetadata=null,Qe.log("템플릿 정리 완료")}catch(o){throw Qe.error("템플릿 정리 실패",o),o}}function ea(){return Object.freeze({...ae})}function Cy(){return ae.actionDispatcher}const Mo={initTemplateEngine:Oo,renderTemplate:hs,updateTemplateData:gs,destroyTemplate:Ec,getState:ea};typeof window<"u"&&(window.G7Core||(window.G7Core={}),window.G7Core.TemplateEngine=Mo,OA({getState:()=>({translationEngine:ae.translationEngine,translationContext:ae.translationContext,bindingEngine:ae.bindingEngine,actionDispatcher:ae.actionDispatcher,templateMetadata:ae.templateMetadata}),transitionManager:Hr,responsiveManager:hi,webSocketManager:vc}),Qe.log("전역 객체 window.G7Core.TemplateEngine에 노출됨"));const Ur=Object.freeze(Object.defineProperty({__proto__:null,DataSourceManager:Er,LayoutLoader:ff,TemplateApp:xo,TemplateEngine:Mo,default:Mo,destroyTemplate:Ec,getActionDispatcher:Cy,getState:ea,initTemplateApp:Ef,initTemplateEngine:Oo,loadLayoutEditorBundle:_f,renderTemplate:hs,updateTemplateData:gs},Symbol.toStringTag,{value:"Module"}));Yt.DataSourceManager=Er,Yt.LayoutLoader=ff,Yt.TemplateApp=xo,Yt.TemplateEngine=Mo,Yt.default=Mo,Yt.destroyTemplate=Ec,Yt.getActionDispatcher=Cy,Yt.getState=ea,Yt.initTemplateApp=Ef,Yt.initTemplateEngine=Oo,Yt.loadLayoutEditorBundle=_f,Yt.renderTemplate=hs,Yt.updateTemplateData=gs,Object.defineProperties(Yt,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})})(this.G7Core=this.G7Core||{}); + `)(n)}catch(a){B.warn(`Expression evaluation failed: ${e}`,a);return}}async executeInitActions(e,n={}){const{getActionDispatcher:a}=await Promise.resolve().then(()=>Pr),i=a();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:",n),B.log("Init actions dataContext._global:",n._global);const l=e.map(d=>d.handler).filter(d=>d.includes("."));l.length>0&&await this.waitForHandlers(i,l);let c={...n};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,c),m=new Event("init");await g(m),B.log(`Init action executed: ${d.handler}`);const y=this.globalState;c={...c,_global:{...y},_local:y._local||c._local||{}},B.log(`Data context refreshed after ${d.handler}:`,{cartKey:c._global?.cartKey})}catch(f){B.error(`Failed to execute init action: ${d.handler}`,f)}}async waitForHandlers(e,n,a=5e3){const i=Date.now(),l=50,c=()=>n.every(f=>e.customHandlers?.has(f));if(c()){B.log("All module handlers already registered");return}const d=_f().getFailedJsAssets();if(d.length>0){const f=d.some(y=>y==="module"||y==="plugin"),g=n.filter(y=>!e.customHandlers?.has(y)),m=g.length>0&&g.every(y=>d.some(S=>y.startsWith(`${S}.`)));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:",n),new Promise(f=>{const g=()=>{if(c()){B.log("All module handlers now registered"),f();return}if(Date.now()-i>=a){const m=n.filter(y=>!e.customHandlers?.has(y));B.warn("Timeout waiting for handlers:",m),f();return}setTimeout(g,l)};g()})}};$(xr,"LOCALE_STORAGE_KEY","g7_locale"),$(xr,"CACHE_VERSION_STORAGE_KEY","g7_cache_version");let Do=xr;function xf(o){const e=new Do(o);return o.websocket&&(Cc.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=xf,window.G7Core.dataSource={refetch:async(o,e)=>{const n=window.__templateApp;if(!n){B.warn("TemplateApp not initialized (G7Core.dataSource.refetch)");return}return n.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 bA(o={}){const{checked:e,value:n,name:a,type:i="checkbox"}=o,c=n!==void 0?n:i==="checkbox"||i==="radio"?e??!1:String(e??""),d={checked:e??!1,value:c,name:a??"",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 vA(o={}){const{button:e=0,clientX:n=0,clientY:a=0}=o;return{button:e,clientX:n,clientY:a,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 SA(){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 wA(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 CA={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 Ay(o){const e=o.replace(/^(dark:|hover:|focus:|active:|disabled:|group-hover:|sm:|md:|lg:|xl:|2xl:)+/,"");for(const[n,a]of Object.entries(CA))if(a.test(e))return n;return null}function xy(o){const e=o.match(/^((dark:|hover:|focus:|active:|disabled:|group-hover:|sm:|md:|lg:|xl:|2xl:)+)/);return e?e[1]:""}function EA(o,e){if(!e||e.trim()==="")return o;if(!o||o.trim()==="")return e;const n=o.split(/\s+/).filter(Boolean),a=e.split(/\s+/).filter(Boolean),i=new Map;for(const c of a){const d=Ay(c);if(d){const f=xy(c),g=`${d}:${f}`;i.set(g,c)}}return[...n.filter(c=>{const d=Ay(c);if(!d)return!0;const f=xy(c),g=`${d}:${f}`;return!i.has(g)}),...a].join(" ")}function _A(o){return Object.entries(o).filter(([,e])=>e).map(([e])=>e).join(" ")}function AA(...o){return o.filter(e=>typeof e=="string"&&e.length>0).join(" ")}const ye=ht("G7CoreGlobals");function xA(){window.React=Xe,window.ReactDOM={...ld,createPortal:ka.createPortal,unstable_batchedUpdates:o=>o()},window.ReactJSXRuntime=wC,ye.log("전역 객체 window.React, window.ReactDOM, window.ReactJSXRuntime에 노출됨")}function TA(o){const e=new Map,n=Oa.getInstance();o.componentEvent={on:(a,i)=>(e.has(a)||e.set(a,new Set),e.get(a).add(i),n.trackEventSubscribe(a),()=>{e.get(a)?.delete(i),n.trackEventUnsubscribe(a)}),emit:async(a,i)=>{const l=e.get(a),c=l?.size??0;if(!l||l.size===0)return n.trackEventEmit(a,i,0),[];let d,f=[];try{f=await Promise.all(Array.from(l).map(async g=>{try{return await g(i)}catch(m){throw ye.error(`componentEvent: Error in listener for "${a}":`,m),m}}))}catch(g){d=g instanceof Error?g:new Error(String(g))}if(n.trackEventEmit(a,i,c,f,d),d)throw d;return f},off:a=>{e.delete(a),n.trackEventOff(a)},clear:()=>{e.clear(),n.trackEventClear()}},ye.log("전역 객체 window.G7Core.componentEvent에 노출됨")}function RA(o){o.__runtime||(o.__runtime={DynamicRenderer:Ur,ComponentRegistry:mr,TranslationEngine:_a,DataSourceManager:_r,dataSourceManager:oA,DataBindingEngine:Dn,dataBindingEngine:Sd,ActionDispatcher:bo,TranslationReactContext:yf,TranslationProvider:vc,useTranslation:uy,ResponsiveContext:Kd,ResponsiveProvider:ic,useResponsive:Wd,responsiveManager:hi,BREAKPOINT_PRESETS:Ul,AuthManager:br,createLogger:ht,G7DevToolsCore:Oa},ye.log("전역 객체 window.G7Core.__runtime(코어 런타임 표면)에 노출됨"))}function kA(o){if(o.layoutEditor&&o.layoutEditor.__isStub!==!0||o.layoutEditor&&o.layoutEditor.__isStub===!0)return;const e=[],n=[];o.layoutEditor={__isStub:!0,__queue:e,__readyCallbacks:n,registerWidget:(a,i)=>e.push(["widget",a,i]),registerNodeEditor:(a,i)=>e.push(["nodeEditor",a,i]),registerCanvasOverlay:(a,i)=>e.push(["canvasOverlay",a,i]),onReady:a=>{typeof a=="function"&&n.push(a)}},ye.log("전역 객체 window.G7Core.layoutEditor 예약 접수함(stub) 노출됨")}function DA(o,e){o.useTranslation=uy,o.t=(n,a)=>{const i=e.getState();if(!i.translationEngine||!i.translationContext)return n;if(a){const l="|"+Object.entries(a).map(([c,d])=>`${c}=${d}`).join("|");return i.translationEngine.translate(n,i.translationContext,l)}return i.translationEngine.translate(n,i.translationContext)},ye.log("전역 객체 window.G7Core.useTranslation에 노출됨")}function OA(o,e){o.createChangeEvent=bA,o.createClickEvent=vA,o.createSubmitEvent=SA,o.createKeyboardEvent=wA,o.uuid=()=>typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,n=>{const a=Math.random()*16|0;return(n==="x"?a:a&3|8).toString(16)}),o.createLogger=ht,ye.log("전역 객체 window.G7Core.createLogger에 노출됨"),o.renderItemChildren=(n,a,i,l,c)=>{const d=e.getState(),m={_global:window.__templateApp?.getGlobalState?.()||{},_local:a._local||{},_computed:a._computed||{},...a},y=new Set,S=(_,A)=>{const x=m._global?._remountKeys;return _&&x?.[_]&&!y.has(_)?(y.add(_),`${_}-remount-${x[_]}`):_||A},v={translationContext:d.translationContext,translationEngine:d.translationEngine,bindingEngine:d.bindingEngine,actionDispatcher:d.actionDispatcher,getRemountKey:S,...c};return lo(n,m,i,l,v)},o.evaluateCondition=(n,a)=>{if(!n)return!0;const i=e.getState(),c=window.__templateApp?.getGlobalState?.()||{},d={_global:c,_local:c._local||{},_computed:c._computed||{},...a||{}},f=i.bindingEngine??Sd;return vp(n,d,f)},o.getComponentMap=()=>mr.getInstance().getComponentMap(),o.renderComponentLayout=(n,a,i)=>{if(!n||!Array.isArray(n)||n.length===0)return null;const l=mr.getInstance().getComponentMap(),c=e.getState(),f=window.__templateApp?.getGlobalState?.()||{},g={_global:f._global||{},_local:f._local||{},_computed:f._computed||{},...a},m=new Set,y=(S,v)=>{const _=g._global?._remountKeys;return S&&_?.[S]&&!m.has(S)?(m.add(S),`${S}-remount-${_[S]}`):S||v};return lo(n,g,l,i,{translationContext:c.translationContext,translationEngine:c.translationEngine,bindingEngine:c.bindingEngine,actionDispatcher:c.actionDispatcher,getRemountKey:y})},o.renderExpandContent=n=>{const{children:a,row:i,expandContext:l,componentContext:c,keyPrefix:d}=n;if(!a||!Array.isArray(a)||a.length===0)return null;const f=n.componentMap||mr.getInstance().getComponentMap(),g=e.getState(),m=o.state?.get?.()||{},y=c?.stateRef?.current??c?.state??{},S={...m._local||{},...y},v=c?.computedRef?.current??m._computed??{},_=g.bindingEngine??o.getDataBindingEngine?.(),A={...m,_local:S,_computed:v,row:i,item:i,$item:i};let x={};if(l&&typeof l=="object"&&_)try{for(const[D,z]of Object.entries(l))if(typeof z=="string"){const P=Aa(z);if(P!==null)try{x[D]=Vn(P)?_.evaluatePipeExpression(P,A,{skipCache:!0}):_.evaluateExpression(P,A,{skipCache:!0})}catch{x[D]=void 0}else x[D]=_.resolveBindings(z,A,{skipCache:!0})}else x[D]=z}catch(D){ye.warn("renderExpandContent: expandContext 평가 오류:",D)}const O={row:i,item:i,$item:i,_local:S,_global:m._global||{},_computed:m._computed||{},...x},M=new Set,T=(D,z)=>{const P=O._global?._remountKeys;return D&&P?.[D]&&!M.has(D)?(M.add(D),`${D}-remount-${P[D]}`):D||z};return lo(a,O,f,d,{translationContext:g.translationContext,translationEngine:g.translationEngine??void 0,bindingEngine:g.bindingEngine??void 0,actionDispatcher:g.actionDispatcher,componentContext:c,getRemountKey:T})},o.$get=function(a,i,l=void 0){if(a==null)return l;const c=Array.isArray(i)?i:[i];if(c.length===0)return a;let d=a;for(const f of c){if(d==null||f==null)return l;d=d[f]}return d??l},ye.log("전역 객체 window.G7Core.renderItemChildren에 노출됨"),ye.log("전역 객체 window.G7Core.renderComponentLayout에 노출됨"),ye.log("전역 객체 window.G7Core.renderExpandContent에 노출됨"),ye.log("전역 객체 window.G7Core.$get에 노출됨")}function LA(o){o.dispatch=async(e,n)=>{const a=window.__templateApp;if(!a)return ye.warn("G7Core.dispatch: TemplateApp이 초기화되지 않았습니다."),{success:!1,error:new Error("TemplateApp이 초기화되지 않았습니다.")};const i=a.getActionDispatcher?.();if(!i)return ye.warn("G7Core.dispatch: ActionDispatcher를 찾을 수 없습니다."),{success:!1,error:new Error("ActionDispatcher를 찾을 수 없습니다.")};const l=a.getRouter?.(),c=a.getGlobalState?.(),d=a.setGlobalState?.bind(a),g=n?.componentContext||window.__g7ActionContext,m=window.__g7PendingLocalState;let y=g?.state??c;m&&g&&(y=m,ye.log("[dispatch] Using __g7PendingLocalState for context.state:",m));let S=g?.data??c;m&&g?.data?._local&&(S={...g.data,_local:m},ye.log("[dispatch] Updated context.data._local with pendingLocalState"));const v={navigate:l?(_,A)=>l.navigate(_,A):void 0,setState:g?.setState??d,state:y,data:S,_isDispatchFallbackContext:!g?.setState};if(e.debounce){const _=e.debounceKey||`dispatch-${e.handler}`,A=typeof e.debounce=="number"?e.debounce:e.debounce.delay;return i.debouncedCall(_,A,()=>{const{debounce:x,debounceKey:O,...M}=e;i.dispatchAction(M,v)}),{success:!0,debounced:!0}}try{return await i.dispatchAction(e,v)}catch(_){return ye.error("G7Core.dispatch: 액션 실행 오류:",_),{success:!1,error:_ instanceof Error?_:new Error(String(_))}}},ye.log("전역 객체 window.G7Core.dispatch에 노출됨")}function Oo(o){const e={};for(const[n,a]of Object.entries(o))if(n.includes(".")){const i=n.split(".");let l=e;for(let c=0;c0&&e.every(n=>/^\d+$/.test(n))}function Ry(o,e){const n={...o};for(const a of Object.keys(e))a in n?n[a]!==null&&typeof n[a]=="object"&&!Array.isArray(n[a])&&e[a]!==null&&typeof e[a]=="object"&&!Array.isArray(e[a])&&(n[a]=Ry(n[a],e[a])):n[a]=e[a];return n}function ir(o,e){if(Array.isArray(o)&&!Array.isArray(e)&&MA(e)){const a=Object.keys(e).map(l=>parseInt(l,10));if(!((a.length>0?Math.max(...a):0)>=o.length+a.length+10)){const l=[...o];for(const[c,d]of Object.entries(e)){const f=parseInt(c,10);f>=0&&f=l.length&&(l[f]=d)}return l}}const n={...o};for(const[a,i]of Object.entries(e))i!==null&&typeof i=="object"&&!Array.isArray(i)?n[a]!==null&&typeof n[a]=="object"?n[a]=ir(n[a],i):n[a]={...i}:n[a]=i;return n}function $A(o){o.state={get:()=>window.__templateApp?.getGlobalState?.()||{},set:(e,n)=>{const a=window.__templateApp;if(a?.setGlobalState&&a?.getGlobalState){const i=n?.merge||"deep",l=Oo(e);let c;if(i==="replace")c=l;else if(i==="shallow")c={...a.getGlobalState(),...l};else{const d=a.getGlobalState();c=ir(d,l)}a.setGlobalState(c,{render:n?.render})}else ye.warn("G7Core.state.set: TemplateApp이 초기화되지 않았습니다.")},setLocal:(e,n)=>{const a=window.__templateApp;if(n?.render===!1&&!n?.selfManaged){const x=window.__g7AutoBindingPaths;x&&x.size>0&&Ty(Oo(e)).some(M=>x.has(M))&&(ye.log("[setLocal] render:false + 자동바인딩 경로 겹침 감지 → render:true 자동 승격 (engine-v1.43.0)"),n={...n,render:!0})}if(n?.debounce){const x=a?.getActionDispatcher?.();if(x){const O=n.debounceKey||`setLocal-${Object.keys(e).join(",")}`,{debounce:M,debounceKey:T,...D}=n;x.debouncedCall(O,n.debounce,()=>{o.state.setLocal(e,D)});return}}const i=n?.scope??"current",l=n?.merge||"deep",c=window.__g7ActionContext,d=Oo(e);if(i==="parent"||i==="root"){const x=window.__g7LayoutContextStack||[];if(x.length>0){const O=i==="parent"?x[x.length-1]:x[0];if(O?.setState){O.setState(M=>l==="replace"?d:l==="shallow"?{...M||{},...d}:ir(M||{},d)),ye.log(`[setLocal] scope=${i}: 타겟 컨텍스트에 상태 업데이트 (mergeMode=${l})`,d);return}}ye.warn(`[setLocal] scope=${i}: 레이아웃 컨텍스트 스택이 비어있습니다. current로 폴백합니다.`)}const f=window.__g7PendingLocalState,g=a?.getGlobalState?.()?._local||{},S=!((window.__g7LayoutContextStack||[]).length>0)&&c?.state?c.state:void 0,v=S?Ry(g,S):g,_=f||v;let A;if(l==="replace"?A=d:l==="shallow"?A={..._,...d}:A=ir(_,d),a?.setGlobalState&&(a.setGlobalState({_local:A},{render:n?.render}),ye.log(`[setLocal] globalLocal updated via setGlobalState (mergeMode=${l}, render=${n?.render??!0}):`,d)),window.__g7PendingLocalState=A,ye.log("[setLocal] __g7PendingLocalState updated:",A),window.__g7SequenceLocalSync=A,window.__g7LastSetLocalSnapshot=A,l==="replace")window.__g7ForcedLocalFields=d;else{const x=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=ir(x,d)}if(ye.log("[setLocal] __g7ForcedLocalFields updated:",d),l==="replace")window.__g7SetLocalOverrideKeys=d;else{const x=window.__g7SetLocalOverrideKeys||{};window.__g7SetLocalOverrideKeys=ir(x,d)}ye.log("[setLocal] __g7SetLocalOverrideKeys updated:",d),c?.setState&&c.setState(x=>l==="replace"?d:l==="shallow"?{...x||{},...d}:ir(x||{},d)),a?.setGlobalState||ye.warn("G7Core.state.setLocal: TemplateApp이 없습니다.")},getLocal:()=>{const a=(window.__templateApp?.getGlobalState?.()||{})._local||{},i=window.__g7PendingLocalState;if(i)return ir(a,i);const l=window.__g7LastSetLocalSnapshot;return l&&l!==a?ir(a,l):a},update:e=>{const n=window.__templateApp;if(n?.getGlobalState&&n?.setGlobalState){const a=n.getGlobalState(),i=e(a);n.setGlobalState(i)}else ye.warn("G7Core.state.update: TemplateApp이 초기화되지 않았습니다.")},subscribe:e=>{const n=window.__templateApp;return n?.onGlobalStateChange?n.onGlobalStateChange(e):(ye.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,n,a)=>{let i,l,c;typeof e=="string"?(i=e,l=n||{},c=a):(l=e,c=n&&typeof n=="object"&&"merge"in n?n:a);const d=c?.merge||"deep",f=Oo(l);if(i){const y=window.__g7IsolatedStates?.[i];y?.mergeState?y.mergeState(f,d):ye.warn(`G7Core.state.setIsolated: scopeId '${i}'를 찾을 수 없습니다.`);return}const g=window.__g7ActionContext;g?.isolatedContext?.mergeState?g.isolatedContext.mergeState(f,d):ye.warn("G7Core.state.setIsolated: 액션 컨텍스트에 isolatedContext가 없습니다.")},getParent:()=>{const e=window.__g7LayoutContextStack||[];if(e.length===0)return ye.log("[getParent] 레이아웃 컨텍스트 스택이 비어있습니다."),null;const n=e[e.length-1];if(!n)return null;const a=n.dataContext||{};return{_local:n.state||a._local||{},_global:a._global||o.state.get()||{},setState:n.setState}},setParentLocal:(e,n,a)=>{const i=window.__g7LayoutContextStack||[];if(i.length===0){ye.warn("[setParentLocal] 레이아웃 컨텍스트 스택이 비어있습니다.");return}const l=i[i.length-1];if(!l?.setState){ye.warn("[setParentLocal] 부모 컨텍스트에 setState가 없습니다.");return}let c,d;typeof e=="string"?(c={[e]:n},d=a):(c=e,d=n&&typeof n=="object"&&"merge"in n?n:a);const f=d?.merge||"deep",g=Oo(c),m=l.state?._local!==void 0,y=m?l.state._local:l.state||{};let S;f==="replace"?S=g:f==="shallow"?S={...y,...g}:S=ir(y,g),window.__g7PendingLocalState=S;const v=window.__templateApp;if(v?.setGlobalState&&v.setGlobalState({_local:S}),l.setState(S),m?l.state._local=S:l.state=S,l.dataContext&&(l.dataContext._local=S),f==="replace")window.__g7ForcedLocalFields=g;else{const _=window.__g7ForcedLocalFields||{};window.__g7ForcedLocalFields=ir(_,g)}Gd()},setParentGlobal:(e,n)=>{let a;typeof e=="string"?a={[e]:n}:a=e,o.state.set(a),ye.log("[setParentGlobal] 전역 상태 업데이트:",a)}},window.__g7IsolatedStates||(window.__g7IsolatedStates={}),o.state.getGlobal=o.state.get,o.state.setGlobal=o.state.set,ye.log("전역 객체 window.G7Core.state에 노출됨")}function NA(o){o.dataSource={get:e=>window.__templateApp?.getDataSource?.(e),set:(e,n,a)=>{const i=window.__templateApp;i?.setDataSource?i.setDataSource(e,n,a):ye.warn("G7Core.dataSource.set: TemplateApp이 초기화되지 않았습니다.")},refetch:async(e,n)=>{const a=window.__templateApp;if(a?.refetchDataSource)return a.refetchDataSource(e,n);ye.warn("G7Core.dataSource.refetch: TemplateApp이 초기화되지 않았습니다.")},updateItem:(e,n,a,i,l)=>{const c=window.__templateApp;return c?.updateDataSourceItem?c.updateDataSourceItem(e,n,a,i,l):(ye.warn("G7Core.dataSource.updateItem: TemplateApp이 초기화되지 않았습니다."),!1)},updateData:(e,n,a,i="append")=>{const l=window.__templateApp;if(!l?.getDataSource||!l?.setDataSource)return ye.warn("G7Core.dataSource.updateData: TemplateApp이 초기화되지 않았습니다."),!1;const c=l.getDataSource(e);if(!c)return ye.warn(`G7Core.dataSource.updateData: 데이터 소스 '${e}'를 찾을 수 없습니다.`),!1;let d,f=c,g=null;if(n){const y=n.split(".");g=y.pop();for(const S of y)if(f&&typeof f=="object"&&S in f)f=f[S];else return ye.warn(`G7Core.dataSource.updateData: 경로 '${n}'를 찾을 수 없습니다.`),!1;d=f[g]}else d=c;if(!Array.isArray(d))return ye.warn("G7Core.dataSource.updateData: 대상 경로의 데이터가 배열이 아닙니다."),!1;if(!Array.isArray(a))return ye.warn("G7Core.dataSource.updateData: newData가 배열이 아닙니다."),!1;const m=i==="prepend"?[...a,...d]:[...d,...a];return n&&g?(f[g]=m,l.setDataSource(e,c,{merge:!1})):l.setDataSource(e,m,{merge:!1}),ye.log(`G7Core.dataSource.updateData: '${e}'에 ${a.length}개 항목 ${i==="prepend"?"앞에":"뒤에"} 추가됨`),!0}},ye.log("전역 객체 window.G7Core.dataSource에 노출됨")}function IA(o,e){o.locale={current:()=>window.__templateApp?.getLocale?.()||"ko",supported:()=>{const a=window.__templateApp?.globalState?.appConfig?.supportedLocales;return Array.isArray(a)&&a.length>0?a:e.getState().templateMetadata?.locales||["ko","en"]},change:async n=>{const a=window.__templateApp;a?.changeLocale?await a.changeLocale(n):ye.warn("G7Core.locale.change: TemplateApp이 초기화되지 않았습니다.")}},ye.log("전역 객체 window.G7Core.locale에 노출됨")}function HA(o){o.toast={show:(e,n)=>{o.dispatch({handler:"toast",params:{message:e,type:n?.type||"info",...n?.duration&&{duration:n.duration}}})},success:(e,n)=>{o.toast.show(e,{type:"success",duration:n})},error:(e,n)=>{o.toast.show(e,{type:"error",duration:n})},warning:(e,n)=>{o.toast.show(e,{type:"warning",duration:n})},info:(e,n)=>{o.toast.show(e,{type:"info",duration:n})}},ye.log("전역 객체 window.G7Core.toast에 노출됨")}function jA(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 n=o.state.get();return n._global?.activeModal===e||n._global?.modalStack?.includes(e)||!1},getStack:()=>o.state.get()._global?.modalStack||[]},ye.log("전역 객체 window.G7Core.modal에 노출됨")}function zA(o){o.style={mergeClasses:EA,conditionalClass:_A,joinClasses:AA},ye.log("전역 객체 window.G7Core.style에 노출됨")}function UA(o,e){const{webSocketManager:n}=e;o.websocket={manager:n,subscribe:(a,i,l,c)=>n.subscribe(a,i,l,c),unsubscribe:a=>n.unsubscribe(a),leaveChannel:a=>n.leaveChannel(a),disconnect:()=>n.disconnect(),isInitialized:()=>n.isInitialized(),getSubscriptionCount:()=>n.getSubscriptionCount()},ye.log("전역 객체 window.G7Core.websocket에 노출됨")}function PA(o,e){const{transitionManager:n}=e;o.navigation={isPending:()=>n?.getIsPending?.()||!1,onComplete:a=>{if(!n)return a(),()=>{};let i=n.getIsPending();const l=n.subscribe(c=>{c?i=!0:i&&(a(),l())});return l}},ye.log("전역 객체 window.G7Core.navigation에 노출됨")}function BA(o){o.plugin={getSettings:e=>window.G7Config?.plugins?.[e],get:(e,n,a)=>window.G7Config?.plugins?.[e]?.[n]??a,getAll:()=>window.G7Config?.plugins??{}},ye.log("전역 객체 window.G7Core.plugin에 노출됨")}function qA(o){o.module={getSettings:e=>window.G7Config?.modules?.[e],get:(e,n,a)=>window.G7Config?.modules?.[e]?.[n]??a,getAll:()=>window.G7Config?.modules??{}},ye.log("전역 객체 window.G7Core.module에 노출됨")}function GA(o,e){const{transitionManager:n,responsiveManager:a}=e;o.AuthManager=br,o.api=Hr(),o.TransitionManager=n,o.useTransitionState=wm,o.ResponsiveManager=a,o.useResponsive=Wd,o.useControllableState=$C,o.shallowArrayEqual=NC,o.shallowObjectEqual=Em,o.updateQueryParams=async(i,l)=>{const c=window.__templateApp;if(c?.updateQueryParams)return c.updateQueryParams(i,l);ye.warn("G7Core.updateQueryParams: TemplateApp이 초기화되지 않았습니다.")},ye.log("전역 객체 window.G7Core.AuthManager에 노출됨"),ye.log("전역 객체 window.G7Core.api에 노출됨"),ye.log("전역 객체 window.G7Core.ResponsiveManager에 노출됨"),ye.log("전역 객체 window.G7Core.useResponsive에 노출됨"),ye.log("전역 객체 window.G7Core.useControllableState에 노출됨"),ye.log("전역 객체 window.G7Core.updateQueryParams에 노출됨")}function VA(o,e){o.getSlotContext=()=>window.__slotContextValue??null,o.getDynamicRenderer=()=>window.__DynamicRenderer??null,o.getComponentRegistry=()=>e.getComponentRegistry?.()??mr.getInstance(),o.getDataBindingEngine=()=>e.getDataBindingEngine?.()??e.getState().bindingEngine,o.getTranslationEngine=()=>e.getTranslationEngine?.()??e.getState().translationEngine,o.getActionDispatcher=()=>e.getActionDispatcher?.()??e.getState().actionDispatcher,ye.log("전역 객체 window.G7Core 슬롯 API에 노출됨 (getSlotContext, getDynamicRenderer 등)")}function FA(o){o.identity={setLauncher:Et.setLauncher.bind(Et),handle:Et.handle.bind(Et),isIdentityRequired:Et.isIdentityRequired.bind(Et),hasLauncher:Et.hasLauncher.bind(Et),markDomainNoticeShown:Et.markDomainNoticeShown.bind(Et),redirectExternally:Et.redirectExternally.bind(Et),createDeferred:Et.createDeferred.bind(Et),resolveDeferred:Et.resolveDeferred.bind(Et),reset:Et.reset.bind(Et),redirectStashKey:jd},ye.log("전역 객체 window.G7Core 본인인증(IDV) API에 노출됨 (identity)")}function KA(o){if(typeof window>"u")return;xA(),window.G7Core||(window.G7Core={});const e=window.G7Core;RA(e),TA(e),kA(e),GA(e,o),DA(e,o),OA(e,o),LA(e),$A(e),NA(e),IA(e,o),HA(e),jA(e),zA(e),UA(e,o),PA(e,o),BA(e),qA(e),VA(e,o),FA(e),ye.log("G7Core 전역 객체 초기화 완료")}function WA(){const o=window.G7Core;if(!o){ye.warn("G7Core가 초기화되지 않았습니다.");return}const e=()=>Oa.getInstance(),n={isEnabled:()=>{try{return e().isEnabled()}catch{return!1}},trackRender:a=>{try{e().isEnabled()&&e().trackRender(a)}catch{}},trackIteration:(a,i,l,c,d)=>{try{e().isEnabled()&&e().trackIteration(a,{source:i,itemVar:l,indexVar:c,sourceLength:d})}catch{}},trackIfCondition:(a,i,l,c)=>{try{e().isEnabled()&&e().trackIfCondition(a,i,l)}catch{}},trackMount:(a,i)=>{try{e().isEnabled()&&e().trackMount(a,{...i,id:a})}catch{}},trackUnmount:a=>{try{e().isEnabled()&&e().trackUnmount(a)}catch{}},trackExpressionEval:a=>{try{e().isEnabled()&&e().trackExpressionEval(a)}catch{}},trackBindingEval:a=>{try{e().isEnabled()&&e().trackBindingEval(a)}catch{}},recordCacheHit:()=>{try{e().isEnabled()&&e().recordCacheHit()}catch{}},recordCacheMiss:()=>{try{e().isEnabled()&&e().recordCacheMiss()}catch{}},trackHandlerRegistration:(a,i,l,c)=>{try{e().isEnabled()&&e().trackHandlerRegistration(a,i,l,c)}catch{}},trackHandlerUnregistration:a=>{try{e().isEnabled()&&e().trackHandlerUnregistration(a)}catch{}},logAction:a=>{try{e().isEnabled()&&e().logAction(a)}catch{}},trackRequest:(a,i)=>{try{return e().isEnabled()?e().trackRequest(a,i):""}catch{return""}},completeRequest:(a,i,l)=>{try{e().isEnabled()&&e().completeRequest(a,i,l)}catch{}},failRequest:(a,i)=>{try{e().isEnabled()&&e().failRequest(a,i)}catch{}},trackDataSourceDefinition:a=>{try{e().isEnabled()&&e().trackDataSourceDefinition(a)}catch{}},trackDataSourceLoading:a=>{try{e().isEnabled()&&e().trackDataSourceLoading(a)}catch{}},trackDataSourceLoaded:(a,i,l)=>{try{e().isEnabled()&&e().trackDataSourceLoaded(a,i,l)}catch{}},trackDataSourceError:(a,i)=>{try{e().isEnabled()&&e().trackDataSourceError(a,i)}catch{}},trackForm:(a,i,l)=>{try{e().isEnabled()&&e().trackForm(a,i,l)}catch{}},untrackForm:a=>{try{e().isEnabled()&&e().untrackForm(a)}catch{}},startStateChange:(a,i,l,c)=>{try{return e().isEnabled()?e().startStateChange(a,i,l,c):""}catch{return""}},completeStateChange:a=>{try{e().isEnabled()&&e().completeStateChange(a)}catch{}},trackComponentRender:(a,i,l,c,d,f)=>{try{e().isEnabled()&&e().trackComponentRender(a,i,l,c,d,f)}catch{}},updateLocalState:a=>{try{e().isEnabled()&&e().updateLocalState(a)}catch{}},updateComputedState:a=>{try{e().isEnabled()&&e().updateComputedState(a)}catch{}},updateParentContext:a=>{try{e().isEnabled()&&e().updateParentContext(a)}catch{}},trackComponentStateSource:(a,i,l,c)=>{try{e().isEnabled()&&e().trackComponentStateSource(a,i,l,c)}catch{}},trackDynamicState:(a,i)=>{try{e().isEnabled()&&e().trackDynamicState(a,i)}catch{}},trackContextFlow:(a,i,l,c,d,f)=>{try{e().isEnabled()&&e().trackContextFlow(a,i,l,c,d,f)}catch{}},trackComponentStyle:(a,i,l,c)=>{try{e().isEnabled()&&e().trackComponentStyle(a,i,l,c)}catch{}},trackAuthEvent:(a,i,l,c)=>{try{e().isEnabled()&&e().trackAuthEvent(a,i,l,c)}catch{}},trackAuthHeader:(a,i,l,c,d)=>{try{e().isEnabled()&&e().trackAuthHeader(a,i,l,c,d)}catch{}},trackLog:(a,i,l)=>{try{e().isEnabled()&&e().trackLog(a,i,l)}catch{}},trackAction:a=>{try{e().isEnabled()&&e().trackAction?.(a)}catch{}},trackDataSourceUpdate:a=>{try{e().isEnabled()&&e().trackDataSourceUpdate?.(a)}catch{}},startSequenceExecution:a=>{try{return e().isEnabled()?e().startSequenceExecution(a):""}catch{return""}},captureSequenceActionBefore:(a,i,l,c,d)=>{try{e().isEnabled()&&e().captureSequenceActionBefore(a,i,l,c,d)}catch{}},captureSequenceActionAfter:(a,i,l,c,d,f)=>{try{e().isEnabled()&&e().captureSequenceActionAfter(a,i,l,c,d,f)}catch{}},endSequenceExecution:(a,i)=>{try{e().isEnabled()&&e().endSequenceExecution(a,i)}catch{}},registerStateCaptureForHandler:(a,i,l)=>{try{e().isEnabled()&&e().registerStateCaptureForHandler(a,i,l)}catch{}},detectStaleClosure:(a,i,l,c,d)=>{try{return e().isEnabled()?e().detectStaleClosure(a,i,l,c,d):[]}catch{return[]}},trackStaleClosureWarning:a=>{try{e().isEnabled()&&e().trackStaleClosureWarning(a)}catch{}},trackModalOpen:a=>{try{e().isEnabled()&&e().trackModalOpen(a)}catch{}},trackModalClose:(a,i)=>{try{e().isEnabled()&&e().trackModalClose(a,i)}catch{}},trackModalStateChange:a=>{try{e().isEnabled()&&e().trackModalStateChange(a)}catch{}},trackNestedContext:a=>{try{return e().isEnabled()?e().trackNestedContext(a):""}catch{return""}},trackNestedContextAccess:(a,i)=>{try{e().isEnabled()&&e().trackNestedContextAccess(a,i)}catch{}},trackComputedProperty:(a,i,l,c,d,f,g)=>{try{e().isEnabled()&&e().trackComputedProperty(a,i,l,c,d,f,g)}catch{}},trackComputedRecalc:(a,i,l,c,d,f,g)=>{try{e().isEnabled()&&e().trackComputedRecalc(a,i,l,c,d,f,g)}catch{}},setNamedActionDefinitions:a=>{try{e().isEnabled()&&e().setNamedActionDefinitions(a)}catch{}},trackNamedActionRef:a=>{try{e().isEnabled()&&e().trackNamedActionRef(a)}catch{}}};o.devTools=n,ye.log("G7Core.devTools 인터페이스 초기화 완료")}let Lo=null;function YA(){const o=window.G7Core;return o?.__devtools?Promise.resolve(o.__devtools):Lo||(Lo=new Promise((e,n)=>{const a=window.G7Config?.coreDevToolsAsset||"/build/core/devtools.min.js",i="g7-devtools-bundle",l=()=>{const f=window.G7Core?.__devtools;f?e(f):n(new Error("DevTools 번들 로드됨 — 그러나 __devtools 미노출"))};window.G7Core=window.G7Core||{},window.G7Core.__onDevToolsReady=l;const c=document.getElementById(i);if(c){c.addEventListener("load",l,{once:!0}),c.addEventListener("error",()=>n(new Error(`DevTools 번들 로드 실패: ${a}`)),{once:!0});return}const d=document.createElement("script");d.id=i,d.src=a,d.async=!1,d.addEventListener("load",l,{once:!0}),d.addEventListener("error",()=>{Lo=null,n(new Error(`DevTools 번들 로드 실패: ${a}`))},{once:!0}),document.head.appendChild(d)}),Lo)}function XA(){const o=window.G7Core;if(!o){ye.warn("G7Core가 초기화되지 않았습니다.");return}const e=Oa.getInstance();if(e.initialize(),!e.isEnabled()){window.G7DevTools={isEnabled:()=>!1,enable:()=>{ye.log("환경설정 > 고급 설정 > 디버그 모드를 켜세요")}},ud(),ye.log("G7DevTools 비활성화됨 (디버그 모드 꺼짐)");return}JA(o,e)}async function JA(o,e){let n;try{n=await YA()}catch(g){ye.warn("DevTools 번들 로드 실패 — 최소 API 로 폴백:",g),window.G7DevTools={isEnabled:()=>!1,enable:()=>{}},ud();return}const{DiagnosticEngine:a,getServerConnector:i,getStyleTracker:l}=n;WA(),ud();try{l().enable(),ye.log("StyleTracker 활성화됨")}catch(g){ye.warn("StyleTracker 활성화 실패:",g)}const c=new a,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){ye.warn("DataBindingEngine이 없습니다.");return}return m.evaluateExpression(g,e.getState())},getCacheStats:()=>e.getCacheStats(),clearStats:()=>{e.resetCacheStats(),ye.log("캐시 통계 초기화됨")}},diagnose:{analyze:g=>c.analyze(g),suggestFix:g=>c.suggestFix(g),getCommonIssues:()=>c.getCommonIssues(),getRulesByCategory:g=>c.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,ye.log("G7DevTools 전역 객체 초기화 완료 (window.G7DevTools)"),QA(n.DevToolsPanel)}function QA(o){if(document.getElementById("g7-devtools-root")){ye.log("DevToolsPanel 이미 렌더링됨");return}const e=document.createElement("div");e.id="g7-devtools-root",document.body.appendChild(e);try{ld.createRoot(e).render(Xe.createElement(o)),ye.log("DevToolsPanel UI 렌더링 완료")}catch(n){ye.error("DevToolsPanel UI 렌더링 실패:",n)}}const Ze=ht("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 Mo=!1;const $o=[];async function ZA(o){try{Ze.log("템플릿 메타데이터 로드 중...",o);const e=o.split("-").map(a=>a.split("_").map(i=>i.charAt(0).toUpperCase()+i.slice(1)).join("")).join(""),n=window[e];return n?.templateMetadata?(Ze.log("템플릿 메타데이터 로드 완료 (전역 변수)",n.templateMetadata),n.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 ky(){const e=(typeof window<"u"?window.__templateApp:void 0)?.globalState?.appConfig?.supportedLocales,n=ie.templateMetadata?.locales;return{$locale:ie.locale,$locales:Array.isArray(e)&&e.length>0?e:n||["ko","en"],$templateLocales:n||["ko","en"],$templateId:ie.templateId}}async function No(o){try{if(Ze.log("템플릿 엔진 초기화 시작",o),ie.isInitialized)throw new Error("템플릿 엔진이 이미 초기화되었습니다. destroyTemplate()을 먼저 호출하세요.");if(!o.templateId)throw new cA;Mo=o.debug??!1,typeof window<"u"&&(window.G7Config||(window.G7Config={}),window.G7Config.debug=Mo),XA(),ie.templateId=o.templateId,ie.locale=o.locale||"ko",Ze.log("엔진 인스턴스 생성 중..."),ie.registry=mr.getInstance(),ie.bindingEngine=new Dn,ie.translationEngine=_a.getInstance(),o.cacheVersion!==void 0&&o.cacheVersion>0&&ie.translationEngine.setCacheVersion(o.cacheVersion),ie.translationContext={templateId:o.templateId,locale:ie.locale},ie.actionDispatcher=new bo({},ie.translationEngine,ie.translationContext),AC(ie.actionDispatcher),Ze.log("다국어 파일 로드 중...",o.templateId,ie.locale);const e="en",n=[ie.translationEngine.loadTranslations(o.templateId,ie.locale).then(()=>{Ze.log(`다국어 파일 로드 완료: ${ie.locale}`)}).catch(a=>{Ze.warn(`다국어 파일 로드 실패 (${ie.locale}):`,a instanceof Error?a.message:a)})];ie.locale!==e&&n.push(ie.translationEngine.loadTranslations(o.templateId,e).then(()=>{Ze.log(`폴백 다국어 파일 로드 완료: ${e}`)}).catch(a=>{Ze.warn(`폴백 다국어 파일 로드 실패 (${e}):`,a instanceof Error?a.message:a)})),await Promise.allSettled(n),Ze.log("템플릿 메타데이터 로드 중...",o.templateId),ie.templateMetadata=await ZA(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 Io=null;function Tf(){const o=window.G7Core;return o?.__LayoutEditorChrome?Promise.resolve(o.__LayoutEditorChrome):Io||(Io=new Promise((e,n)=>{const a=window.G7Config?.coreEditorAsset||"/build/core/layout-editor.min.js",i="g7-layout-editor-bundle",l=document.getElementById(i),c=()=>{const f=window.G7Core?.__LayoutEditorChrome;f?e(f):n(new Error("편집기 번들 로드됨 — 그러나 __LayoutEditorChrome 미노출"))};if(window.G7Core=window.G7Core||{},window.G7Core.__onChromeReady=c,l){l.addEventListener("load",c,{once:!0}),l.addEventListener("error",()=>n(new Error(`편집기 번들 로드 실패: ${a}`)),{once:!0});return}const d=document.createElement("script");d.id=i,d.src=a,d.async=!1,d.addEventListener("load",c,{once:!0}),d.addEventListener("error",()=>{Io=null,n(new Error(`편집기 번들 로드 실패: ${a}`))},{once:!0}),document.head.appendChild(d)}),Io)}async function ms(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 n=ky();if(ie.containerId=o.containerId,ie.currentLayoutJson=o.layoutJson,ie.currentDataContext={...n,...o.dataContext||{}},ie.translationContext=o.translationContext||{templateId:ie.templateId||"",locale:ie.locale},ie.reactRoot||(Ze.log("React Root 생성"),ie.reactRoot=ld.createRoot(e)),typeof window<"u"){const l=Ey(window.location.pathname);if(l){Ze.log("레이아웃 편집기 모드 진입",l);let c;try{c=await Tf()}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:Mo});return}const d=Xe.createElement(c,{templateIdentifier:l.templateIdentifier,initialLocale:ie.locale});ie.reactRoot.render(Xe.createElement(vc,{translationEngine:ie.translationEngine,translationContext:ie.translationContext,children:Xe.createElement(Vd,{children:Xe.createElement(ic,{children:Xe.createElement(bf,{children:d})})})}));return}}const a=o.layoutJson.components||[];if(a.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(Xe.createElement(vc,{translationEngine:ie.translationEngine,translationContext:ie.translationContext},Xe.createElement(Vd,null,Xe.createElement(ic,null,Xe.createElement(bf,null,[...a.map((l,c)=>{const d=ie.currentLayoutJson?.layout_name||"";return Xe.createElement(Ur,{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:c===0,layoutKey:d})}),Xe.createElement(mm,{key:"__modal_parent_context_provider"},i.map(l=>{const c=ie.currentDataContext._global?.modalStack||[],f=c.includes(l.id)||ie.currentDataContext._global?.activeModal===l.id,g=c.indexOf(l.id),m=g>=0?50+g:50,y=window.__g7LayoutContextStack||[],v=y[y.length-1]?.dataContext,_=Xe.createElement(Ur,{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:v});return l.data_sources&&l.data_sources.length>0?Xe.createElement(wy,{key:`modal_${l.id}`,isOpen:f,modalId:l.id,dataSources:l.data_sources,dataContext:ie.currentDataContext,globalStateUpdater:ie.actionDispatcher?.getGlobalStateUpdater(),bindingEngine:ie.bindingEngine,debug:Mo,children:_}):_}))]))))),Ze.log("템플릿 렌더링 완료"),$o.length>0){Ze.log(`대기 중인 데이터 업데이트 ${$o.length}건 적용`);const l=[...$o];$o.length=0;for(const{data:c,options:d}of l)ys(c,d)}}catch(e){throw Ze.error("템플릿 렌더링 실패",e),e}}function ys(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)),$o.push({data:o,options:e});return}const n=ky(),a={...ie.currentDataContext._global||{},...o._global||{}},i=LC(ie.currentDataContext._localInit,o._localInit);ie.currentDataContext={...n,...ie.currentDataContext,...o,_global:a,_localInit:i},a._local!==void 0&&(ie.currentDataContext._local=a._local),a._computed!==void 0&&(ie.currentDataContext._computed=a._computed);const l=ie.currentLayoutJson.components||[],c=ie.currentLayoutJson.modals||[];Ze.log("updateTemplateData - modals 배열:",c),Ze.log("updateTemplateData - modals 개수:",c.length),Ze.log("updateTemplateData - activeModal:",ie.currentDataContext._global?.activeModal);const d=()=>{ie.reactRoot.render(Xe.createElement(vc,{translationEngine:ie.translationEngine,translationContext:ie.translationContext},Xe.createElement(Vd,null,Xe.createElement(ic,null,Xe.createElement(bf,null,[...l.map((f,g)=>{const m=ie.currentLayoutJson?.layout_name||"";return Xe.createElement(Ur,{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})}),Xe.createElement(mm,{key:"__modal_parent_context_provider_update"},c.map(f=>{const g=ie.currentDataContext._global?.modalStack||[],y=g.includes(f.id)||ie.currentDataContext._global?.activeModal===f.id,S=g.indexOf(f.id),v=S>=0?50+S:50,_=window.__g7LayoutContextStack||[],x=_[_.length-1]?.dataContext,O=Xe.createElement(Ur,{key:`modal_${f.id}_renderer`,componentDef:{...f,props:{...f.props,isOpen:y,style:{...f.props?.style,zIndex:v},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:x});return f.data_sources&&f.data_sources.length>0?Xe.createElement(wy,{key:`modal_${f.id}`,isOpen:y,modalId:f.id,dataSources:f.data_sources,dataContext:ie.currentDataContext,globalStateUpdater:ie.actionDispatcher?.getGlobalStateUpdater(),bindingEngine:ie.bindingEngine,debug:Mo,children:O}):O}))])))))};e?.sync?(Ze.log("재렌더링 시작 (sync mode - 즉시 렌더링)"),d()):(Ze.log("재렌더링 시작 (with startTransition)"),H.startTransition(()=>{d()})),Ze.log("템플릿 데이터 업데이트 완료")}catch(n){throw Ze.error("템플릿 데이터 업데이트 실패",n),n}}function xc(){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 ea(){return Object.freeze({...ie})}function Dy(){return ie.actionDispatcher}const Ho={initTemplateEngine:No,renderTemplate:ms,updateTemplateData:ys,destroyTemplate:xc,getState:ea};typeof window<"u"&&(window.G7Core||(window.G7Core={}),window.G7Core.TemplateEngine=Ho,KA({getState:()=>({translationEngine:ie.translationEngine,translationContext:ie.translationContext,bindingEngine:ie.bindingEngine,actionDispatcher:ie.actionDispatcher,templateMetadata:ie.templateMetadata}),transitionManager:jr,responsiveManager:hi,webSocketManager:Cc}),Ze.log("전역 객체 window.G7Core.TemplateEngine에 노출됨"));const Pr=Object.freeze(Object.defineProperty({__proto__:null,DataSourceManager:_r,LayoutLoader:mf,TemplateApp:Do,TemplateEngine:Ho,default:Ho,destroyTemplate:xc,getActionDispatcher:Dy,getState:ea,initTemplateApp:xf,initTemplateEngine:No,loadLayoutEditorBundle:Tf,renderTemplate:ms,updateTemplateData:ys},Symbol.toStringTag,{value:"Module"}));Qt.DataSourceManager=_r,Qt.LayoutLoader=mf,Qt.TemplateApp=Do,Qt.TemplateEngine=Ho,Qt.default=Ho,Qt.destroyTemplate=xc,Qt.getActionDispatcher=Dy,Qt.getState=ea,Qt.initTemplateApp=xf,Qt.initTemplateEngine=No,Qt.loadLayoutEditorBundle=Tf,Qt.renderTemplate=ms,Qt.updateTemplateData=ys,Object.defineProperties(Qt,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})})(this.G7Core=this.G7Core||{}); //# sourceMappingURL=template-engine.min.js.map diff --git a/resources/js/core/template-engine/CHANGELOG.md b/resources/js/core/template-engine/CHANGELOG.md index df2fe9c9..bb7a93b8 100644 --- a/resources/js/core/template-engine/CHANGELOG.md +++ b/resources/js/core/template-engine/CHANGELOG.md @@ -5,6 +5,17 @@ > > 형식: [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/) +## [engine-v1.58.0] - 2026-08-07 + +### Added + +#### 편집기 상태 scope — 선택 세그먼트 토큰 `/*?` + +- `matchStateScope.ts::matchRoutePattern` — `scope.match` 에 `/*?`(0개 또는 1개 세그먼트) 토큰을 추가했다. 0개일 때는 앞 슬래시까지 함께 접힌다. +- 배경: 라우트 접두사가 운영자 설정이면 세그먼트가 **있을 수도 없을 수도** 있다. 상점 주소는 `route_path` 로 바꿀 수 있고(`/store/products`) `no_route` 를 켜면 세그먼트가 아예 없다(`/products`). 기존 `*` 는 정확히 한 세그먼트라 후자를 표현할 수 없어, 그런 사이트에서는 상태 그룹이 매칭되지 않고 캔버스 상태 토글이 **예외·경고 없이 사라졌다**. +- 치환 순서 주의: 정규식 이스케이프가 `?` 를 `\?` 로 바꾸므로 선택 세그먼트는 이스케이프 **후** 형태(`/*\?`)를 먼저 치환하고, 그 뒤 남은 `*` 를 한 세그먼트로 바꾼다. 순서를 뒤집으면 `/*?` 의 `*` 가 먼저 소비된다. +- 기존 패턴 호환: 치환은 `/*?` 형태에만 반응하므로 `?` 를 쓰지 않는 패턴의 결과 정규식은 종전과 동일하다(저장소 내 route scope 패턴 중 `?` 사용 0건 — 전수 확인). + ## [engine-v1.57.0] - 2026-08-06 ### Added diff --git a/resources/js/core/template-engine/layout-editor/__tests__/utils/matchStateScope.test.ts b/resources/js/core/template-engine/layout-editor/__tests__/utils/matchStateScope.test.ts index 8396b3ce..eb47bef9 100644 --- a/resources/js/core/template-engine/layout-editor/__tests__/utils/matchStateScope.test.ts +++ b/resources/js/core/template-engine/layout-editor/__tests__/utils/matchStateScope.test.ts @@ -117,6 +117,61 @@ describe('matchStateItems — scope 매칭 items 평탄화', () => { expect(matchStateItems(globGroups, { kind: 'route', match: '/admin/a/b/edit' })).toEqual([]); }); + // 라우트 접두사가 운영자 설정이라 있을 수도 없을 수도 있는 경우(engine-v1.58.0). + // 상점 주소는 `route_path` 로 바꿀 수 있고(`/store/products`) `no_route` 를 켜면 + // 세그먼트가 아예 없다(`/products`). `*` 는 정확히 한 세그먼트라 후자를 표현하지 못해, + // 그 상점에서는 상태 그룹이 매칭되지 않고 상태 토글이 조용히 사라졌다. + describe('route `/*?` 선택 세그먼트 (0개 또는 1개)', () => { + const optionalGroups: EditorStateGroupSpec[] = [ + { scope: { kind: 'route', match: '/*?/products' }, items: [{ id: 'list' }] }, + ]; + const ids = (path: string) => + matchStateItems(optionalGroups, { kind: 'route', match: path }).map((i) => i.id); + + it('세그먼트가 기본값이면 매칭된다', () => { + expect(ids('/shop/products')).toEqual(['list']); + }); + + it('세그먼트를 운영자가 바꿔도 매칭된다', () => { + expect(ids('/store/products')).toEqual(['list']); + }); + + it('세그먼트가 없으면(no_route) 슬래시까지 접혀 매칭된다', () => { + expect(ids('/products')).toEqual(['list']); + }); + + it('세그먼트가 둘 이상이면 매칭되지 않는다', () => { + expect(ids('/a/b/products')).toEqual([]); + }); + + it('다른 경로는 매칭되지 않는다', () => { + expect(ids('/shop/cart')).toEqual([]); + expect(ids('/products/1')).toEqual([]); + }); + }); + + // 회귀: `?` 를 쓰지 않는 기존 패턴은 동작이 바뀌지 않아야 한다 + // (선택 세그먼트 치환은 `/*?` 형태에만 반응한다). + // + // 관리자 라우트는 routes.json 이 path 자체를 `*/admin/...` 로 선언하므로 편집기가 + // 넘기는 selectedRoute.path 도 같은 문자열이다 — 이 경우는 glob 이 아니라 정확 일치로 + // 먼저 걸린다. 그 경로가 그대로인지 함께 고정한다. + it('`?` 없는 기존 패턴은 동작이 바뀌지 않는다', () => { + const legacy: EditorStateGroupSpec[] = [ + { scope: { kind: 'route', match: '*/admin/users' }, items: [{ id: 'users' }] }, + ]; + // 정확 일치 경로 (관리자 라우트 실제 형태) + expect(matchStateItems(legacy, { kind: 'route', match: '*/admin/users' }).map((i) => i.id)).toEqual([ + 'users', + ]); + // `*` 는 한 세그먼트에 대응하므로 접두사 세그먼트가 하나 있으면 glob 으로도 걸린다 + expect(matchStateItems(legacy, { kind: 'route', match: 'x/admin/users' }).map((i) => i.id)).toEqual([ + 'users', + ]); + // 접두사 세그먼트가 없으면 여전히 미매칭 — `*` 는 0개를 허용하지 않는다 + expect(matchStateItems(legacy, { kind: 'route', match: '/admin/users' })).toEqual([]); + }); + it('같은 scope 그룹이 둘이면 items concat (확장 네임스페이스 병합)', () => { const merged: EditorStateGroupSpec[] = [ { scope: { kind: 'route', match: '/x' }, items: [{ id: 'a' }] }, diff --git a/resources/js/core/template-engine/layout-editor/utils/matchStateScope.ts b/resources/js/core/template-engine/layout-editor/utils/matchStateScope.ts index 964e6ecb..cff48b20 100644 --- a/resources/js/core/template-engine/layout-editor/utils/matchStateScope.ts +++ b/resources/js/core/template-engine/layout-editor/utils/matchStateScope.ts @@ -160,22 +160,36 @@ function matchScope( } /** - * 라우트 path 매칭 — 정확 일치 또는 `*` 세그먼트 glob 1단계. + * 라우트 path 매칭 — 정확 일치 또는 세그먼트 glob. * - * `*` 는 한 path 세그먼트(슬래시 미포함)에 대응한다. `:param` path 토큰은 리터럴로 - * 취급한다(스펙 작성자가 토큰을 그대로 적은 경우 정확 일치). + * 두 가지 토큰을 지원한다: + * - `*` — 한 path 세그먼트(슬래시 미포함)에 대응. 예: `/*​/admin/users` + * - `/*?` — **0개 또는 1개** 세그먼트에 대응(앞 슬래시 포함). 0개일 때는 슬래시까지 + * 함께 사라진다. 라우트 접두사가 운영자 설정이라 **있을 수도 없을 수도 있는** 경우를 + * 위한 것이다 — 예를 들어 상점 주소는 `route_path` 로 바꿀 수 있고(`/store/products`) + * `no_route` 를 켜면 세그먼트가 아예 없다(`/products`). `*` 는 정확히 한 세그먼트라 + * 후자를 표현할 수 없어, 그 상점에서는 상태 그룹이 매칭되지 않고 상태 토글이 조용히 + * 사라졌다(engine-v1.58.0 이전). + * + * `:param` path 토큰은 리터럴로 취급한다(스펙 작성자가 토큰을 그대로 적은 경우 정확 일치). * * @param path 현재 라우트 path * @param pattern scope.match 패턴 * @return 일치 여부 + * @since engine-v1.58.0 `/*?` 선택 세그먼트 토큰 추가 */ function matchRoutePattern(path: string, pattern: string): boolean { if (pattern === path) return true; if (!pattern.includes('*')) return false; - // 각 세그먼트의 정규식 특수문자를 이스케이프하되 `*` 만 `[^/]+` 로 치환. + + // 정규식 특수문자를 이스케이프하면 `?` 도 `\?` 가 되므로, 선택 세그먼트 토큰은 + // 이스케이프 **후** 형태(`/*\?`)를 기준으로 먼저 치환한다. 그 뒤 남은 `*` 를 + // 한 세그먼트로 바꾼다 (순서를 바꾸면 `/*?` 의 `*` 가 먼저 소비된다). const escaped = pattern .replace(/[.+?^${}()|[\]\\]/g, '\\$&') + .replace(/\/\*\\\?/g, '(?:/[^/]+)?') .replace(/\*/g, '[^/]+'); + return new RegExp(`^${escaped}$`).test(path); } diff --git a/templates/_bundled/sirsoft-basic/CHANGELOG.md b/templates/_bundled/sirsoft-basic/CHANGELOG.md index 5cca2d8c..0e90fb8b 100644 --- a/templates/_bundled/sirsoft-basic/CHANGELOG.md +++ b/templates/_bundled/sirsoft-basic/CHANGELOG.md @@ -17,12 +17,14 @@ ### Changed - 마이페이지 주문내역이 주문상품 전체를 명시적으로 요청하도록 바꿨습니다. 주문내역 조회의 기본 응답이 대표 상품 1건만 담도록 가벼워졌기 때문이며, 화면에 보이는 주문상품 목록은 종전과 동일합니다. (#76 @jordy-bitree 님께서 제보해주셨습니다.) +- 화면 편집기 상품 상세의 상태 미리보기에서 "품절" 로 똑같이 표시되던 두 상태를 "재고 소진 (판매중)" 과 "품절 처리" 로 구분했습니다. 재고만 떨어진 상품과 판매를 품절로 지정한 상품은 화면 모양이 달라 따로 편집해야 하는데, 목록에서 어느 쪽인지 고를 수 없었습니다. ### Fixed - 주문 상세의 결제 정보 영역에 결제 플러그인이 제공하는 공급가액·부가세·영수증 링크·에스크로 구매확정 버튼이 표시되지 않던 문제를 수정했습니다. - 총 건수를 끝까지 세지 못한 목록에서 페이지 이동 막대가 사라지거나 "1페이지뿐" 으로 잘못 표시되던 문제를 수정했습니다. 마이페이지의 주문·마일리지·위시리스트·알림함, 게시판 목록, 상품 리뷰·문의, 내가 쓴 글 목록이 해당합니다. - 검색 결과의 탭 배지가 끝까지 세지 못한 건수를 정확한 숫자처럼 보여주던 문제를 수정했습니다. 이제 그 경우 숫자 뒤에 "이상" 표시가 붙습니다. +- 게시판 목록 주소에 정렬 조건(`sort_by`·`sort_order`)을 붙여도 목록에 반영되지 않던 문제를 수정했습니다. 예를 들어 조회순으로 정렬한 주소를 공유하거나 즐겨찾기해 두면 열었을 때 기본 정렬로 보였습니다. 주소에 정렬 조건이 없을 때는 종전처럼 게시판 설정의 기본 정렬을 따릅니다. #### 검색·봇 화면 diff --git a/templates/_bundled/sirsoft-basic/__tests__/layouts/board-list-sort-params.test.ts b/templates/_bundled/sirsoft-basic/__tests__/layouts/board-list-sort-params.test.ts new file mode 100644 index 00000000..c82dd292 --- /dev/null +++ b/templates/_bundled/sirsoft-basic/__tests__/layouts/board-list-sort-params.test.ts @@ -0,0 +1,115 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync, readdirSync } from 'node:fs'; +import { resolve, dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +/** + * 사용자 게시판 목록 — 정렬 쿼리 파라미터 전달 (#534 검수 발견) + * + * 서버 계약(`PostService::extractSortParams`)의 정렬 우선순위는 + * **쿼리 파라미터(sort_by/sort_order) > 게시판 설정(order_by/order_direction) > 기본값** 이다. + * 그런데 사용자 목록 레이아웃의 데이터소스가 이 두 파라미터를 아예 싣지 않아, + * `/board/{slug}?sort_by=view_count` 로 들어가도 요청은 `posts?page=1` 로 나갔다. + * 관리자 목록은 정상 동작하는데 사용자 화면만 조용히 무시됐다 — 예외도 경고도 없다. + * + * 폴백을 빈 문자열로 두는 것이 이 테스트의 핵심이다. 관리자 목록처럼 + * `{{query.sort_by || 'created_at'}}` 로 기본값을 박으면, URL 에 정렬이 없을 때 + * `sort_by=created_at` 이 **항상** 실려 나가 게시판 설정(`order_by`)을 덮어쓴다. + * 게시판 관리자가 "조회순" 으로 설정해도 목록이 최신순으로 나오게 된다. + * 빈 값이면 템플릿 엔진이 파라미터를 생략하고, 설령 실려도 Laravel 의 + * ConvertEmptyStringsToNull 이 null 로 바꿔 `??` 사슬이 게시판 설정으로 떨어진다. + */ +describe('사용자 게시판 목록 — 정렬 쿼리 파라미터', () => { + const layoutsDir = resolve(dirname(fileURLToPath(import.meta.url)), '../../layouts'); + + /** + * 레이아웃 디렉토리를 훑어 게시글 목록 엔드포인트를 쓰는 데이터소스를 전부 모읍니다. + * + * 파일명을 열거하지 않는다 — 목록 레이아웃이 늘어날 때 그 레이아웃만 조용히 + * 검사 밖에 남으면, 지금 고치는 결함이 새 화면에서 그대로 재발한다. + */ + const collectPostListSources = (): Array<{ file: string; source: Record }> => { + const found: Array<{ file: string; source: Record }> = []; + + const walk = (dir: string): void => { + for (const entry of readdirSync(dir, { withFileTypes: true })) { + const full = join(dir, entry.name); + + if (entry.isDirectory()) { + walk(full); + continue; + } + if (!entry.name.endsWith('.json')) continue; + + let parsed: { data_sources?: Array> }; + try { + parsed = JSON.parse(readFileSync(full, 'utf8')); + } catch { + continue; + } + + for (const ds of parsed.data_sources ?? []) { + const endpoint = String(ds.endpoint ?? ''); + // 게시판별 게시글 목록만 — 회원 프로필의 작성글 목록(users/{id}/posts)은 별개 화면이다. + if (/\/boards\/[^/]+\/posts$/.test(endpoint)) { + found.push({ file: full.slice(layoutsDir.length + 1).replace(/\\/g, '/'), source: ds }); + } + } + } + }; + + walk(layoutsDir); + + return found; + }; + + const sources = collectPostListSources(); + + it('게시글 목록 데이터소스가 레이아웃에서 도출된다', () => { + // 스캔이 빗나가면 sources 가 비고 아래 단언들이 루프를 돌지 않아 전부 통과한다. + // 모집단을 먼저 고정해 그 조용한 통과를 막는다. + expect(sources.length, '발견된 게시글 목록 데이터소스').toBeGreaterThan(0); + expect(sources.map((s) => s.file)).toContain('board/index.json'); + }); + + it('정렬 파라미터(sort_by/sort_order)를 서버로 전달한다', () => { + for (const { file, source } of sources) { + const params = (source.params ?? {}) as Record; + + expect(Object.keys(params), `${file} 의 params`).toContain('sort_by'); + expect(Object.keys(params), `${file} 의 params`).toContain('sort_order'); + } + }); + + it('정렬 파라미터를 URL 쿼리에서 읽는다', () => { + for (const { file, source } of sources) { + const params = (source.params ?? {}) as Record; + + expect(params.sort_by, `${file} 의 sort_by`).toMatch(/query[.[]'?sort_by/); + expect(params.sort_order, `${file} 의 sort_order`).toMatch(/query[.[]'?sort_order/); + } + }); + + it('정렬 파라미터에 기본 컬럼을 박지 않는다 (게시판 설정이 이겨야 한다)', () => { + for (const { file, source } of sources) { + const params = (source.params ?? {}) as Record; + + // 'created_at' / 'desc' 같은 리터럴 폴백이 있으면 URL 에 정렬이 없을 때도 + // 그 값이 실려 나가 게시판 설정(order_by)을 덮어쓴다. + expect(params.sort_by, `${file} 의 sort_by 폴백`).not.toMatch( + /created_at|view_count|title|author/ + ); + expect(params.sort_order, `${file} 의 sort_order 폴백`).not.toMatch(/asc|desc/); + } + }); + + it('정렬이 없을 때 빈 값으로 떨어진다', () => { + for (const { file, source } of sources) { + const params = (source.params ?? {}) as Record; + + // 같은 데이터소스의 search/category 와 동일한 관례 — 빈 문자열 폴백. + expect(params.sort_by, `${file} 의 sort_by`).toMatch(/\?\?\s*''/); + expect(params.sort_order, `${file} 의 sort_order`).toMatch(/\?\?\s*''/); + } + }); +}); diff --git a/templates/_bundled/sirsoft-basic/__tests__/layouts/orderDomainSampleData.test.ts b/templates/_bundled/sirsoft-basic/__tests__/layouts/orderDomainSampleData.test.ts index 2fa15235..312b563c 100644 --- a/templates/_bundled/sirsoft-basic/__tests__/layouts/orderDomainSampleData.test.ts +++ b/templates/_bundled/sirsoft-basic/__tests__/layouts/orderDomainSampleData.test.ts @@ -216,8 +216,9 @@ describe('주문완료 페이지 상태 override 충실 shape', () => { return ecomSpec.states.groups.find((g: any) => g.scope?.match === match); } - describe('/shop/orders/:id/complete — vbank/dbank override = base 충실 shape', () => { - const g = findGroup('/shop/orders/:id/complete'); + // scope 는 상점 주소 설정과 무관한 선택 세그먼트 토큰을 쓴다 (engine-v1.58.0 `/*?`). + describe('주문 완료 — vbank/dbank override = base 충실 shape', () => { + const g = findGroup('/*?/orders/:id/complete'); for (const variant of ['vbank', 'dbank']) { it(`${variant} override 는 base 와 동일 충실 shape (options 복수 + 무스텁)`, () => { const item = g.items.find((s: any) => s.id === variant); @@ -243,8 +244,8 @@ describe('주문완료 페이지 상태 override 충실 shape', () => { }); }); - describe('/shop/cart — empty_cart override = 실제 shape 빈 상태', () => { - const g = findGroup('/shop/cart'); + describe('장바구니 — empty_cart override = 실제 shape 빈 상태', () => { + const g = findGroup('/*?/cart'); it('empty_cart 은 items 빈 배열 + item_count 0 + 무스텁', () => { const ci = g.items.find((s: any) => s.id === 'empty_cart').sampleDataOverrides.byDataSourceId.cartItems; expect(hasStub(ci)).toBe(false); diff --git a/templates/_bundled/sirsoft-basic/__tests__/layouts/stageEGateStates.test.ts b/templates/_bundled/sirsoft-basic/__tests__/layouts/stageEGateStates.test.ts index ecbe7f57..8ab54d80 100644 --- a/templates/_bundled/sirsoft-basic/__tests__/layouts/stageEGateStates.test.ts +++ b/templates/_bundled/sirsoft-basic/__tests__/layouts/stageEGateStates.test.ts @@ -57,7 +57,9 @@ function item(group: any, id: string): any { } describe('단계 E — 상품상세 리뷰/문의 탭 게이트 상태', () => { - const g = ecomGroup('/shop/products/:id'); + // scope 는 상점 주소 설정과 무관한 선택 세그먼트 토큰 + routes.json 의 실제 파라미터명을 쓴다 + // (engine-v1.58.0 `/*?`, 파라미터는 `:product_code`). + const g = ecomGroup('/*?/products/:product_code'); it('reviews_tab / qna_tab 상태가 등록되어 있다', () => { expect(item(g, 'reviews_tab')).toBeTruthy(); @@ -196,14 +198,14 @@ describe('단계 E — 통합검색 서브탭 게이트 상태 + posts/pages 본 describe('단계 E — 주문서/장바구니 금액 상세 토글 게이트 상태', () => { it('/shop/checkout summary_details_expanded 가 두 토글을 ON 한다 (게이트 경로)', () => { - const it0 = item(ecomGroup('/shop/checkout'), 'summary_details_expanded'); + const it0 = item(ecomGroup('/*?/checkout'), 'summary_details_expanded'); expect(it0).toBeTruthy(); expect(it0.initialState?.local?.showTaxDetails).toBe(true); expect(it0.initialState?.local?.showDiscountDetails).toBe(true); }); it('/shop/cart summary_tax_expanded 가 세금 토글 + 선택상품을 ON 한다 (이중 중첩 게이트)', () => { - const it0 = item(ecomGroup('/shop/cart'), 'summary_tax_expanded'); + const it0 = item(ecomGroup('/*?/cart'), 'summary_tax_expanded'); expect(it0).toBeTruthy(); // 세금 상세는 selectedItems.length>0 게이트 안에 showTaxDetails 토글로 이중 중첩. expect(it0.initialState?.local?.showTaxDetails).toBe(true); diff --git a/templates/_bundled/sirsoft-basic/lang/partial/en/editor.json b/templates/_bundled/sirsoft-basic/lang/partial/en/editor.json index adf30087..83f9edf3 100644 --- a/templates/_bundled/sirsoft-basic/lang/partial/en/editor.json +++ b/templates/_bundled/sirsoft-basic/lang/partial/en/editor.json @@ -951,7 +951,7 @@ "with_data": "Has data", "empty_data": "No data", "in_stock": "In stock", - "out_of_stock": "Out of stock", + "out_of_stock": "Out of stock (on sale)", "cart_with_items": "Has items", "cart_empty": "Empty cart", "read_normal": "Normal post", @@ -989,7 +989,7 @@ "board_edit": "Edit post", "board_reply_with_quote": "Write reply (quote parent)", "shop_access_denied": "Access denied", - "sold_out": "Sold out", + "sold_out": "Marked sold out", "suspended": "Suspended", "coming_soon": "Coming soon", "product_reviews_tab": "Reviews tab", diff --git a/templates/_bundled/sirsoft-basic/lang/partial/ko/editor.json b/templates/_bundled/sirsoft-basic/lang/partial/ko/editor.json index 6e357baa..b56013ed 100644 --- a/templates/_bundled/sirsoft-basic/lang/partial/ko/editor.json +++ b/templates/_bundled/sirsoft-basic/lang/partial/ko/editor.json @@ -951,7 +951,7 @@ "with_data": "데이터 있음", "empty_data": "데이터 없음", "in_stock": "재고 있음", - "out_of_stock": "품절", + "out_of_stock": "재고 소진 (판매중)", "cart_with_items": "상품 담김", "cart_empty": "장바구니 비었음", "read_normal": "일반 게시글", @@ -989,7 +989,7 @@ "board_edit": "글 수정", "board_reply_with_quote": "답글 작성 (부모글 인용)", "shop_access_denied": "접근 제한", - "sold_out": "품절", + "sold_out": "품절 처리", "suspended": "판매 중지", "coming_soon": "판매 예정", "product_reviews_tab": "리뷰 탭", diff --git a/templates/_bundled/sirsoft-basic/layouts/board/index.json b/templates/_bundled/sirsoft-basic/layouts/board/index.json index 78ad522c..94295742 100644 --- a/templates/_bundled/sirsoft-basic/layouts/board/index.json +++ b/templates/_bundled/sirsoft-basic/layouts/board/index.json @@ -39,6 +39,8 @@ "page": "{{query.page ?? 1}}", "search": "{{query.search ?? ''}}", "category": "{{query.category ?? ''}}", + "sort_by": "{{query.sort_by ?? ''}}", + "sort_order": "{{query.sort_order ?? ''}}", "filters[0][field]": "{{query['filters[0][field]'] ?? ''}}", "filters[0][value]": "{{query['filters[0][value]'] ?? ''}}", "filters[0][operator]": "{{query['filters[0][operator]'] ?? ''}}", diff --git a/templates/_bundled/sirsoft-basic/tests/Playwright/specs/board-list-sort-query.spec.ts b/templates/_bundled/sirsoft-basic/tests/Playwright/specs/board-list-sort-query.spec.ts new file mode 100644 index 00000000..717ae2d8 --- /dev/null +++ b/templates/_bundled/sirsoft-basic/tests/Playwright/specs/board-list-sort-query.spec.ts @@ -0,0 +1,103 @@ +/** + * 사용자 게시판 목록 — URL 정렬 파라미터가 서버까지 도달하는지 검증 (#534 검수 발견) + * + * 배경: + * - 서버 계약(`PostService::extractSortParams`)의 정렬 우선순위는 + * 쿼리 파라미터(sort_by/sort_order) > 게시판 설정(order_by) > 기본값 이다. + * - 그런데 사용자 목록 레이아웃의 데이터소스가 sort_by/sort_order 를 싣지 않아 + * `/board/{slug}?sort_by=view_count` 로 들어가도 요청이 `posts?page=1` 로 나갔다. + * 목록은 조용히 기존 정렬 그대로였다 — 예외도 콘솔 경고도 없다. + * - 관리자 목록은 정상 동작했으므로 단위 테스트로는 드러나지 않았고, 실제 요청 URL 을 + * 봐야만 확인된다. 그래서 **네트워크 요청을 가로채 파라미터를 직접 검사한다.** + * + * 회귀 방향이 둘이라 양쪽을 다 본다: + * 1) URL 에 정렬이 있으면 → 요청에 실려야 한다 + * 2) URL 에 정렬이 없으면 → 실리지 **않아야** 한다. + * 기본값을 박아 `sort_by=created_at` 이 항상 나가면 게시판 설정(order_by)이 + * 덮여, 운영자가 "조회순" 으로 설정해도 최신순으로 나온다. + */ +import { test, expect, type Page } from '@playwright/test'; + +/** 게시글 목록 API 경로 (게시판 slug 무관 매칭) */ +const POSTS_ENDPOINT = /\/api\/modules\/sirsoft-board\/boards\/[^/]+\/posts(\?|$)/; + +/** + * 목록 화면 진입 중 발생한 게시글 목록 요청의 쿼리 파라미터를 수집합니다. + * + * @param page Playwright 페이지 + * @param path 진입할 사용자 목록 경로 + * @return 수집된 URLSearchParams 배열 (요청 순서) + */ +async function capturePostsRequests(page: Page, path: string): Promise { + const captured: URLSearchParams[] = []; + + page.on('request', (req) => { + if (POSTS_ENDPOINT.test(req.url())) { + captured.push(new URL(req.url()).searchParams); + } + }); + + await page.goto(path); + await page.waitForResponse( + (res) => POSTS_ENDPOINT.test(res.url()) && res.status() === 200, + { timeout: 15_000 } + ); + + return captured; +} + +/** + * 목록이 있는 공개 게시판 slug 하나를 공개 API 로 찾습니다. + * 시드 데이터에 특정 게시판이 있다고 가정하지 않는다 — 회귀는 레이아웃에 있지 특정 게시판에 있지 않다. + * + * @param page Playwright 페이지 + * @return 게시판 slug 또는 없으면 null + */ +async function findPublicBoardSlug(page: Page): Promise { + const res = await page.request.get('/api/modules/sirsoft-board/boards/board-menu', { + headers: { Accept: 'application/json' }, + }); + + if (!res.ok()) return null; + + const body = await res.json(); + const boards = body?.data?.data ?? body?.data ?? []; + + return Array.isArray(boards) && boards.length > 0 ? (boards[0].slug ?? null) : null; +} + +test.describe('사용자 게시판 목록 — URL 정렬 파라미터', () => { + test('URL 의 sort_by/sort_order 가 목록 요청에 실린다', async ({ page }) => { + const slug = await findPublicBoardSlug(page); + test.skip(!slug, '공개 게시판이 없어 검증할 수 없습니다'); + + const requests = await capturePostsRequests( + page, + `/board/${slug}?sort_by=view_count&sort_order=desc` + ); + + expect(requests.length, '게시글 목록 요청').toBeGreaterThan(0); + + // 마지막 요청이 화면에 실제로 반영된 요청이다. + const params = requests[requests.length - 1]; + + expect(params.get('sort_by'), 'sort_by 파라미터').toBe('view_count'); + expect(params.get('sort_order'), 'sort_order 파라미터').toBe('desc'); + }); + + test('URL 에 정렬이 없으면 정렬 파라미터를 보내지 않는다 (게시판 설정 보존)', async ({ page }) => { + const slug = await findPublicBoardSlug(page); + test.skip(!slug, '공개 게시판이 없어 검증할 수 없습니다'); + + const requests = await capturePostsRequests(page, `/board/${slug}`); + + expect(requests.length, '게시글 목록 요청').toBeGreaterThan(0); + + for (const params of requests) { + // 빈 값으로도 보내면 안 된다 — 서버의 `??` 사슬에서 빈 문자열이 게시판 설정을 + // 가로챌 여지를 남기지 않는다. + expect(params.get('sort_by') || '', 'sort_by 미전송').toBe(''); + expect(params.get('sort_order') || '', 'sort_order 미전송').toBe(''); + } + }); +}); diff --git a/tests/Playwright/specs/layout-editor/state-scope-optional-segment.spec.ts b/tests/Playwright/specs/layout-editor/state-scope-optional-segment.spec.ts new file mode 100644 index 00000000..26288458 --- /dev/null +++ b/tests/Playwright/specs/layout-editor/state-scope-optional-segment.spec.ts @@ -0,0 +1,63 @@ +/** + * Layout Editor — 상점 화면의 상태 미리보기 전환이 상점 주소 설정과 무관하게 표시된다. + * + * 상점 주소는 운영자 설정이다. 편집기는 라우트 path 의 `{{...}}` 표현식을 실제 값으로 + * 평가하므로(useEditorRoutes::resolveEditorRouteExpressions) `selectedRoute.path` 의 첫 + * 세그먼트가 사이트마다 다르다 — 기본 `/shop/products`, `route_path` 를 바꾸면 + * `/store/products`, `no_route` 를 켜면 `/products`. + * + * editor-spec 의 `states.groups[].scope.match` 가 `/shop/...` 리터럴이던 시절에는 기본값이 + * 아닌 상점에서 상태 그룹이 매칭되지 않아 캔버스 상태 토글(PageStateSwitcher)이 조용히 + * 사라졌다. 예외도 경고도 남지 않아 "이 화면은 원래 상태 전환이 없다" 로 오인된다. + * 선택 세그먼트 토큰 `/*?`(engine-v1.58.0)로 세 경우를 모두 매칭한다. + * + * 단위 테스트(matchStateScope.test.ts)는 매칭 함수만 본다. 이 spec 은 편집기를 실제로 + * 열어 상태 토글이 화면에 나타나는지를 확인한다 — 스펙과 라우트 평가가 실제로 만나는 + * 지점은 브라우저에만 있다. + * + * @scenario route_setting × surface + * @effects editor_state_switcher_visible_on_default_shop_route + * + editor_state_switcher_visible_after_route_path_change + * + * 활성화 절차: PLAYWRIGHT_BASE_URL 과 PlaywrightIssueToken 발급이 가능한 환경에서 + * `test.describe.skip` → `test.describe` 로 바꾼다. 상점 주소를 바꾸는 축은 이커머스 + * 모듈 설정(basic_info.route_path)을 변경해야 하므로, 설정 변경 API 가 열려 있는 + * 검수 환경에서만 두 번째 케이스가 의미를 갖는다. + */ +import { test, expect, issueToken, authenticatePage } from '../../fixtures/auth'; + +const PRODUCTS_ROUTE = '/shop/products'; + +test.describe.skip('레이아웃 편집기 — 상점 화면 상태 전환 노출', () => { + test('기본 상점 주소에서 상태 전환 토글이 보인다', async ({ page }) => { + const token = issueToken('core.templates.layouts.edit'); + await authenticatePage(page, token); + + await page.goto( + `/admin/layout-editor/sirsoft-basic?route=${encodeURIComponent(PRODUCTS_ROUTE)}`, + ); + await page.waitForLoadState('domcontentloaded', { timeout: 30_000 }); + await page.waitForSelector('[data-testid="g7le-preview-frame"]', { timeout: 30_000 }); + + // 상태 그룹이 매칭되어야 토글이 마운트된다. 미매칭이면 이 요소 자체가 없다. + const switcher = page.locator('[data-testid="g7le-state-switcher"]'); + await expect(switcher).toBeVisible({ timeout: 20_000 }); + }); + + test('상점 주소를 바꾼 사이트에서도 상태 전환 토글이 보인다', async ({ page }) => { + // 이 케이스는 basic_info.route_path 가 기본값이 아닌 환경에서만 의미가 있다. + // 검수 환경의 실제 설정값을 읽어 라우트를 만든다 — 기본값이면 위 케이스와 같아진다. + const token = issueToken('core.templates.layouts.edit'); + await authenticatePage(page, token); + + const routePath = process.env.G7_E2E_SHOP_ROUTE_PATH ?? 'store'; + await page.goto( + `/admin/layout-editor/sirsoft-basic?route=${encodeURIComponent(`/${routePath}/products`)}`, + ); + await page.waitForLoadState('domcontentloaded', { timeout: 30_000 }); + await page.waitForSelector('[data-testid="g7le-preview-frame"]', { timeout: 30_000 }); + + const switcher = page.locator('[data-testid="g7le-state-switcher"]'); + await expect(switcher).toBeVisible({ timeout: 20_000 }); + }); +});