comfyui-frontend-package 1.38.2__py3-none-any.whl → 1.38.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- comfyui_frontend_package/static/assets/{AboutPanel-C7253TdA.js → AboutPanel-CYH8kZrG.js} +2 -2
- comfyui_frontend_package/static/assets/{AboutPanel-C7253TdA.js.map → AboutPanel-CYH8kZrG.js.map} +1 -1
- comfyui_frontend_package/static/assets/{AudioPreviewPlayer-DgSsFFU7.js → AudioPreviewPlayer-BwJepJEw.js} +2 -2
- comfyui_frontend_package/static/assets/{AudioPreviewPlayer-DgSsFFU7.js.map → AudioPreviewPlayer-BwJepJEw.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ComfyQueueButton-DriR7JtM.js → ComfyQueueButton-BM8zaTn_.js} +2 -2
- comfyui_frontend_package/static/assets/{ComfyQueueButton-DriR7JtM.js.map → ComfyQueueButton-BM8zaTn_.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ExtensionPanel-yJP3r-dq.js → ExtensionPanel-CkIkopXr.js} +2 -2
- comfyui_frontend_package/static/assets/{ExtensionPanel-yJP3r-dq.js.map → ExtensionPanel-CkIkopXr.js.map} +1 -1
- comfyui_frontend_package/static/assets/{GraphView-D-tZ3xO5.css → GraphView-CoiT3fdb.css} +1 -1
- comfyui_frontend_package/static/assets/GraphView-Djp0ICHX.js +15 -0
- comfyui_frontend_package/static/assets/GraphView-Djp0ICHX.js.map +1 -0
- comfyui_frontend_package/static/assets/{KeybindingPanel-f7VKBCyl.js → KeybindingPanel-5iNg_eid.js} +2 -2
- comfyui_frontend_package/static/assets/{KeybindingPanel-f7VKBCyl.js.map → KeybindingPanel-5iNg_eid.js.map} +1 -1
- comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-Bwob1r0X.js +2 -0
- comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-Bwob1r0X.js.map +1 -0
- comfyui_frontend_package/static/assets/{LegacyCreditsPanel-e57J4OZv.js → LegacyCreditsPanel-D28HHk-A.js} +2 -2
- comfyui_frontend_package/static/assets/{LegacyCreditsPanel-e57J4OZv.js.map → LegacyCreditsPanel-D28HHk-A.js.map} +1 -1
- comfyui_frontend_package/static/assets/{Load3D-DYW1gw8I.js → Load3D-CPNYDT4-.js} +2 -2
- comfyui_frontend_package/static/assets/Load3D-CPNYDT4-.js.map +1 -0
- comfyui_frontend_package/static/assets/{Load3D.vue_vue_type_script_setup_true_lang-BLcsvL5E.js → Load3D.vue_vue_type_script_setup_true_lang-KEzORqB0.js} +2 -2
- comfyui_frontend_package/static/assets/{Load3D.vue_vue_type_script_setup_true_lang-BLcsvL5E.js.map → Load3D.vue_vue_type_script_setup_true_lang-KEzORqB0.js.map} +1 -1
- comfyui_frontend_package/static/assets/{Media3DTop-D77j8ukJ.js → Media3DTop-CQp4nFvB.js} +2 -2
- comfyui_frontend_package/static/assets/{Media3DTop-D77j8ukJ.js.map → Media3DTop-CQp4nFvB.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ServerConfigPanel-CQPgIsZk.js → ServerConfigPanel-B3WCmowi.js} +2 -2
- comfyui_frontend_package/static/assets/{ServerConfigPanel-CQPgIsZk.js.map → ServerConfigPanel-B3WCmowi.js.map} +1 -1
- comfyui_frontend_package/static/assets/{SubscriptionRequiredDialogContent-DtxMOWxy.js → SubscriptionRequiredDialogContent-JgqOjXs3.js} +2 -2
- comfyui_frontend_package/static/assets/{SubscriptionRequiredDialogContent-DtxMOWxy.js.map → SubscriptionRequiredDialogContent-JgqOjXs3.js.map} +1 -1
- comfyui_frontend_package/static/assets/{UserPanel-BPwKKP_j.js → UserPanel-B5k84B9y.js} +2 -2
- comfyui_frontend_package/static/assets/{UserPanel-BPwKKP_j.js.map → UserPanel-B5k84B9y.js.map} +1 -1
- comfyui_frontend_package/static/assets/{UserSelectView-DNaXeKx4.js → UserSelectView-R_nCWiDS.js} +2 -2
- comfyui_frontend_package/static/assets/{UserSelectView-DNaXeKx4.js.map → UserSelectView-R_nCWiDS.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ValueControlPopover-kd7h8GFO.js → ValueControlPopover-BqA-EaFY.js} +2 -2
- comfyui_frontend_package/static/assets/{ValueControlPopover-kd7h8GFO.js.map → ValueControlPopover-BqA-EaFY.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetAudioUI-B-Ra7X5I.js → WidgetAudioUI-Bu3u9PBZ.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetAudioUI-B-Ra7X5I.js.map → WidgetAudioUI-Bu3u9PBZ.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetButton-BQWWeE_x.js → WidgetButton-CS0lZIN_.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetButton-BQWWeE_x.js.map → WidgetButton-CS0lZIN_.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetColorPicker-4E2rnL8u.js → WidgetColorPicker-CQ_vqexP.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetColorPicker-4E2rnL8u.js.map → WidgetColorPicker-CQ_vqexP.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetGalleria-DaEjYhLq.js → WidgetGalleria-CE2__qNK.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetGalleria-DaEjYhLq.js.map → WidgetGalleria-CE2__qNK.js.map} +1 -1
- comfyui_frontend_package/static/assets/WidgetInputNumber-CR_vNT3l.js +2 -0
- comfyui_frontend_package/static/assets/WidgetInputNumber-CR_vNT3l.js.map +1 -0
- comfyui_frontend_package/static/assets/{WidgetInputNumber.vue_vue_type_script_setup_true_lang-CdvBpGed.js → WidgetInputNumber.vue_vue_type_script_setup_true_lang-rPX1TIkC.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetInputNumber.vue_vue_type_script_setup_true_lang-CdvBpGed.js.map → WidgetInputNumber.vue_vue_type_script_setup_true_lang-rPX1TIkC.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetInputText-B2YoBI4Y.js → WidgetInputText-NnOJku4t.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetInputText-B2YoBI4Y.js.map → WidgetInputText-NnOJku4t.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetLayoutField.vue_vue_type_script_setup_true_lang-CYDaxuge.js → WidgetLayoutField.vue_vue_type_script_setup_true_lang-BrNsu13j.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetLayoutField.vue_vue_type_script_setup_true_lang-CYDaxuge.js.map → WidgetLayoutField.vue_vue_type_script_setup_true_lang-BrNsu13j.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetLegacy-DgBI3-l2.js → WidgetLegacy-3d5GSSgo.js} +2 -2
- comfyui_frontend_package/static/assets/WidgetLegacy-3d5GSSgo.js.map +1 -0
- comfyui_frontend_package/static/assets/{WidgetMarkdown-Bqcf7Vpy.js → WidgetMarkdown-BTfwNVeV.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetMarkdown-Bqcf7Vpy.js.map → WidgetMarkdown-BTfwNVeV.js.map} +1 -1
- comfyui_frontend_package/static/assets/WidgetRecordAudio-X2n565MP.js +2 -0
- comfyui_frontend_package/static/assets/WidgetRecordAudio-X2n565MP.js.map +1 -0
- comfyui_frontend_package/static/assets/WidgetSelect-DsU3dEFm.js +2 -0
- comfyui_frontend_package/static/assets/WidgetSelect-DsU3dEFm.js.map +1 -0
- comfyui_frontend_package/static/assets/{WidgetSelect.vue_vue_type_script_setup_true_lang-Ua67RWUI.js → WidgetSelect.vue_vue_type_script_setup_true_lang-DLMXofNs.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetSelect.vue_vue_type_script_setup_true_lang-Ua67RWUI.js.map → WidgetSelect.vue_vue_type_script_setup_true_lang-DLMXofNs.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetTextarea-syfN9Olh.js → WidgetTextarea-BguNaUH3.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetTextarea-syfN9Olh.js.map → WidgetTextarea-BguNaUH3.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetToggleSwitch-C2c4CfAT.js → WidgetToggleSwitch-Cnenb1g4.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetToggleSwitch-C2c4CfAT.js.map → WidgetToggleSwitch-Cnenb1g4.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetWithControl.vue_vue_type_script_setup_true_lang-B5RYQ41H.js → WidgetWithControl.vue_vue_type_script_setup_true_lang-CWBg5k0x.js} +3 -3
- comfyui_frontend_package/static/assets/{WidgetWithControl.vue_vue_type_script_setup_true_lang-B5RYQ41H.js.map → WidgetWithControl.vue_vue_type_script_setup_true_lang-CWBg5k0x.js.map} +1 -1
- comfyui_frontend_package/static/assets/{audioService-CnSU5S1Z.js → audioService-C_4pv8R5.js} +2 -2
- comfyui_frontend_package/static/assets/{audioService-CnSU5S1Z.js.map → audioService-C_4pv8R5.js.map} +1 -1
- comfyui_frontend_package/static/assets/{audioUtils-BZ8b3tiu.js → audioUtils-CYVbzDGB.js} +2 -2
- comfyui_frontend_package/static/assets/{audioUtils-BZ8b3tiu.js.map → audioUtils-CYVbzDGB.js.map} +1 -1
- comfyui_frontend_package/static/assets/{index-BBvP0bLh.js → index-BST1SetX.js} +2 -2
- comfyui_frontend_package/static/assets/{index-BBvP0bLh.js.map → index-BST1SetX.js.map} +1 -1
- comfyui_frontend_package/static/assets/index-DOAA7WkP.css +1 -0
- comfyui_frontend_package/static/assets/{index-C5dKoXkW.js → index-DwjwpNvK.js} +2 -2
- comfyui_frontend_package/static/assets/index-DwjwpNvK.js.map +1 -0
- comfyui_frontend_package/static/assets/{index-Bc79VbnU.js → index-U7jagKl8.js} +22 -22
- comfyui_frontend_package/static/assets/index-U7jagKl8.js.map +1 -0
- comfyui_frontend_package/static/assets/{keybindingService-DOwK-S5D.js → keybindingService-6A6hKCpd.js} +2 -2
- comfyui_frontend_package/static/assets/{keybindingService-DOwK-S5D.js.map → keybindingService-6A6hKCpd.js.map} +1 -1
- comfyui_frontend_package/static/assets/{main-9V_ekXTj.js → main-7u-fkFqV.js} +4 -4
- comfyui_frontend_package/static/assets/main-7u-fkFqV.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-Mk83jtey.js → main-BrRR7na1.js} +4 -4
- comfyui_frontend_package/static/assets/main-BrRR7na1.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-QxfzWHY3.js → main-Btwx4xDf.js} +5 -5
- comfyui_frontend_package/static/assets/main-Btwx4xDf.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-D8WRsxlG.js → main-CU-38qC-.js} +3 -3
- comfyui_frontend_package/static/assets/main-CU-38qC-.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-DdPAQm8u.js → main-CZbK9-kR.js} +4 -4
- comfyui_frontend_package/static/assets/main-CZbK9-kR.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-IIi2nOrM.js → main-Cv05dk1q.js} +4 -4
- comfyui_frontend_package/static/assets/main-Cv05dk1q.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-Be2ivsXL.js → main-DVNhdlF2.js} +4 -6
- comfyui_frontend_package/static/assets/main-DVNhdlF2.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-DnlhxsrE.js → main-DckcRPaY.js} +3 -3
- comfyui_frontend_package/static/assets/main-DckcRPaY.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-B992pnxN.js → main-DeynLPZA.js} +4 -4
- comfyui_frontend_package/static/assets/main-DeynLPZA.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-AFY0Q5Cd.js → main-DtCc3tTY.js} +4 -4
- comfyui_frontend_package/static/assets/main-DtCc3tTY.js.map +1 -0
- comfyui_frontend_package/static/assets/{main-QbQAnNpJ.js → main-apejL0E_.js} +4 -4
- comfyui_frontend_package/static/assets/main-apejL0E_.js.map +1 -0
- comfyui_frontend_package/static/index.html +1 -1
- {comfyui_frontend_package-1.38.2.dist-info → comfyui_frontend_package-1.38.3.dist-info}/METADATA +1 -1
- {comfyui_frontend_package-1.38.2.dist-info → comfyui_frontend_package-1.38.3.dist-info}/RECORD +105 -105
- comfyui_frontend_package/static/assets/GraphView-Dwrm8D3J.js +0 -15
- comfyui_frontend_package/static/assets/GraphView-Dwrm8D3J.js.map +0 -1
- comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-CX9YtPlM.js +0 -2
- comfyui_frontend_package/static/assets/LazyImage.vue_vue_type_script_setup_true_lang-CX9YtPlM.js.map +0 -1
- comfyui_frontend_package/static/assets/Load3D-DYW1gw8I.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetInputNumber-u4JzBngV.js +0 -2
- comfyui_frontend_package/static/assets/WidgetInputNumber-u4JzBngV.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetLegacy-DgBI3-l2.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetRecordAudio-hHbaGdj1.js +0 -2
- comfyui_frontend_package/static/assets/WidgetRecordAudio-hHbaGdj1.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetSelect-Cv4W8ECC.js +0 -2
- comfyui_frontend_package/static/assets/WidgetSelect-Cv4W8ECC.js.map +0 -1
- comfyui_frontend_package/static/assets/index-Bc79VbnU.js.map +0 -1
- comfyui_frontend_package/static/assets/index-C5dKoXkW.js.map +0 -1
- comfyui_frontend_package/static/assets/index-gxCJ3H4T.css +0 -1
- comfyui_frontend_package/static/assets/main-9V_ekXTj.js.map +0 -1
- comfyui_frontend_package/static/assets/main-AFY0Q5Cd.js.map +0 -1
- comfyui_frontend_package/static/assets/main-B992pnxN.js.map +0 -1
- comfyui_frontend_package/static/assets/main-Be2ivsXL.js.map +0 -1
- comfyui_frontend_package/static/assets/main-D8WRsxlG.js.map +0 -1
- comfyui_frontend_package/static/assets/main-DdPAQm8u.js.map +0 -1
- comfyui_frontend_package/static/assets/main-DnlhxsrE.js.map +0 -1
- comfyui_frontend_package/static/assets/main-IIi2nOrM.js.map +0 -1
- comfyui_frontend_package/static/assets/main-Mk83jtey.js.map +0 -1
- comfyui_frontend_package/static/assets/main-QbQAnNpJ.js.map +0 -1
- comfyui_frontend_package/static/assets/main-QxfzWHY3.js.map +0 -1
- {comfyui_frontend_package-1.38.2.dist-info → comfyui_frontend_package-1.38.3.dist-info}/WHEEL +0 -0
- {comfyui_frontend_package-1.38.2.dist-info → comfyui_frontend_package-1.38.3.dist-info}/top_level.txt +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LegacyCreditsPanel-e57J4OZv.js","sources":["../../src/components/common/UserCredit.vue","../../src/services/customerEventsService.ts","../../src/components/dialog/content/setting/UsageLogsTable.vue","../../src/components/dialog/content/setting/LegacyCreditsPanel.vue"],"sourcesContent":["<template>\n <div v-if=\"balanceLoading\" class=\"flex items-center gap-1\">\n <div class=\"flex items-center gap-2\">\n <Skeleton shape=\"circle\" width=\"1.5rem\" height=\"1.5rem\" />\n </div>\n <div class=\"flex-1\"></div>\n <Skeleton width=\"8rem\" height=\"2rem\" />\n </div>\n <div v-else class=\"flex items-center gap-1\">\n <Tag\n v-if=\"!showCreditsOnly\"\n severity=\"secondary\"\n rounded\n class=\"p-1 text-amber-400\"\n >\n <template #icon>\n <i class=\"icon-[lucide--component]\" />\n </template>\n </Tag>\n <div :class=\"textClass\">\n {{ showCreditsOnly ? formattedCreditsOnly : formattedBalance }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Skeleton from 'primevue/skeleton'\nimport Tag from 'primevue/tag'\nimport { computed } from 'vue'\nimport { useI18n } from 'vue-i18n'\n\nimport { formatCreditsFromCents } from '@/base/credits/comfyCredits'\nimport { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'\n\nconst { textClass, showCreditsOnly } = defineProps<{\n textClass?: string\n showCreditsOnly?: boolean\n}>()\n\nconst authStore = useFirebaseAuthStore()\nconst balanceLoading = computed(() => authStore.isFetchingBalance)\nconst { t, locale } = useI18n()\n\nconst formattedBalance = computed(() => {\n const cents =\n authStore.balance?.effective_balance_micros ??\n authStore.balance?.amount_micros ??\n 0\n const amount = formatCreditsFromCents({\n cents,\n locale: locale.value\n })\n return `${amount} ${t('credits.credits')}`\n})\n\nconst formattedCreditsOnly = computed(() => {\n const cents =\n authStore.balance?.effective_balance_micros ??\n authStore.balance?.amount_micros ??\n 0\n const amount = formatCreditsFromCents({\n cents,\n locale: locale.value,\n numberOptions: { minimumFractionDigits: 0, maximumFractionDigits: 0 }\n })\n return amount\n})\n</script>\n","import type { AxiosError, AxiosResponse } from 'axios'\nimport axios from 'axios'\nimport { ref, watch } from 'vue'\nimport { useI18n } from 'vue-i18n'\n\nimport { getComfyApiBaseUrl } from '@/config/comfyApi'\nimport { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'\nimport type { components, operations } from '@/types/comfyRegistryTypes'\nimport { isAbortError } from '@/utils/typeGuardUtil'\n\nexport enum EventType {\n CREDIT_ADDED = 'credit_added',\n ACCOUNT_CREATED = 'account_created',\n API_USAGE_STARTED = 'api_usage_started',\n API_USAGE_COMPLETED = 'api_usage_completed'\n}\n\ntype CustomerEventsResponse =\n operations['GetCustomerEvents']['responses']['200']['content']['application/json']\n\ntype CustomerEventsResponseQuery =\n operations['GetCustomerEvents']['parameters']['query']\n\nexport type AuditLog = components['schemas']['AuditLog']\n\nconst customerApiClient = axios.create({\n baseURL: getComfyApiBaseUrl(),\n headers: {\n 'Content-Type': 'application/json'\n }\n})\n\nexport const useCustomerEventsService = () => {\n const isLoading = ref(false)\n const error = ref<string | null>(null)\n const { d } = useI18n()\n\n watch(\n () => getComfyApiBaseUrl(),\n (url) => {\n customerApiClient.defaults.baseURL = url\n }\n )\n\n const handleRequestError = (\n err: unknown,\n context: string,\n routeSpecificErrors?: Record<number, string>\n ) => {\n // Don't treat cancellation as an error\n if (isAbortError(err)) return\n\n let message: string\n if (!axios.isAxiosError(err)) {\n message = `${context} failed: ${err instanceof Error ? err.message : String(err)}`\n } else {\n const axiosError = err as AxiosError<{ message: string }>\n const status = axiosError.response?.status\n if (status && routeSpecificErrors?.[status]) {\n message = routeSpecificErrors[status]\n } else {\n message =\n axiosError.response?.data?.message ??\n `${context} failed with status ${status}`\n }\n }\n\n error.value = message\n }\n\n const executeRequest = async <T>(\n requestCall: () => Promise<AxiosResponse<T>>,\n options: {\n errorContext: string\n routeSpecificErrors?: Record<number, string>\n }\n ): Promise<T | null> => {\n const { errorContext, routeSpecificErrors } = options\n\n isLoading.value = true\n error.value = null\n\n try {\n const response = await requestCall()\n return response.data\n } catch (err) {\n handleRequestError(err, errorContext, routeSpecificErrors)\n return null\n } finally {\n isLoading.value = false\n }\n }\n\n function formatEventType(eventType: string) {\n switch (eventType) {\n case 'credit_added':\n return 'Credits Added'\n case 'account_created':\n return 'Account Created'\n case 'api_usage_completed':\n return 'API Usage'\n default:\n return eventType\n }\n }\n\n function formatDate(dateString: string): string {\n const date = new Date(dateString)\n\n return d(date, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n })\n }\n\n function formatJsonKey(key: string) {\n return key\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ')\n }\n\n function formatJsonValue(value: any) {\n if (typeof value === 'number') {\n // Format numbers with commas and decimals if needed\n return value.toLocaleString()\n }\n if (typeof value === 'string' && value.match(/^\\d{4}-\\d{2}-\\d{2}/)) {\n // Format dates nicely\n return new Date(value).toLocaleString()\n }\n return value\n }\n\n function getEventSeverity(eventType: string) {\n switch (eventType) {\n case 'credit_added':\n return 'success'\n case 'account_created':\n return 'info'\n case 'api_usage_completed':\n return 'warning'\n default:\n return 'info'\n }\n }\n\n function hasAdditionalInfo(event: AuditLog) {\n const { amount, api_name, model, ...otherParams } = event.params || {}\n return Object.keys(otherParams).length > 0\n }\n\n function getTooltipContent(event: AuditLog) {\n const { ...params } = event.params || {}\n\n return Object.entries(params)\n .map(([key, value]) => {\n const formattedKey = formatJsonKey(key)\n const formattedValue = formatJsonValue(value)\n return `<strong>${formattedKey}:</strong> ${formattedValue}`\n })\n .join('<br>')\n }\n\n function formatAmount(amountMicros?: number) {\n if (!amountMicros) return '0.00'\n return (amountMicros / 100).toFixed(2)\n }\n\n async function getMyEvents({\n page = 1,\n limit = 10\n }: CustomerEventsResponseQuery = {}): Promise<CustomerEventsResponse | null> {\n const errorContext = 'Fetching customer events'\n const routeSpecificErrors = {\n 400: 'Invalid input, object invalid',\n 404: 'Not found'\n }\n\n // Get auth headers\n const authHeaders = await useFirebaseAuthStore().getAuthHeader()\n if (!authHeaders) {\n error.value = 'Authentication header is missing'\n return null\n }\n\n const result = await executeRequest<CustomerEventsResponse>(\n () =>\n customerApiClient.get('/customers/events', {\n params: { page, limit },\n headers: authHeaders\n }),\n { errorContext, routeSpecificErrors }\n )\n\n return result\n }\n\n return {\n // State\n isLoading,\n error,\n\n // Methods\n getMyEvents,\n formatEventType,\n getEventSeverity,\n formatAmount,\n hasAdditionalInfo,\n formatDate,\n formatJsonKey,\n formatJsonValue,\n getTooltipContent\n }\n}\n","<template>\n <div>\n <div v-if=\"loading\" class=\"flex items-center justify-center p-8\">\n <ProgressSpinner />\n </div>\n <div v-else-if=\"error\" class=\"p-4\">\n <Message severity=\"error\" :closable=\"false\">{{ error }}</Message>\n </div>\n <DataTable\n v-else\n :value=\"events\"\n :paginator=\"true\"\n :rows=\"pagination.limit\"\n :total-records=\"pagination.total\"\n :first=\"dataTableFirst\"\n :lazy=\"true\"\n class=\"p-datatable-sm custom-datatable\"\n @page=\"onPageChange\"\n >\n <Column field=\"event_type\" :header=\"$t('credits.eventType')\">\n <template #body=\"{ data }\">\n <Badge\n :value=\"customerEventService.formatEventType(data.event_type)\"\n :severity=\"customerEventService.getEventSeverity(data.event_type)\"\n />\n </template>\n </Column>\n <Column field=\"details\" :header=\"$t('credits.details')\">\n <template #body=\"{ data }\">\n <div class=\"event-details\">\n <!-- Credits Added -->\n <template v-if=\"data.event_type === EventType.CREDIT_ADDED\">\n <div class=\"font-semibold text-green-500\">\n {{ $t('credits.added') }} ${{\n customerEventService.formatAmount(data.params?.amount)\n }}\n </div>\n </template>\n\n <!-- Account Created -->\n <template v-else-if=\"data.event_type === EventType.ACCOUNT_CREATED\">\n <div>{{ $t('credits.accountInitialized') }}</div>\n </template>\n\n <!-- API Usage -->\n <template\n v-else-if=\"data.event_type === EventType.API_USAGE_COMPLETED\"\n >\n <div class=\"flex flex-col gap-1\">\n <div class=\"font-semibold\">\n {{ data.params?.api_name || 'API' }}\n </div>\n <div class=\"text-sm text-smoke-400\">\n {{ $t('credits.model') }}: {{ data.params?.model || '-' }}\n </div>\n </div>\n </template>\n </div>\n </template>\n </Column>\n <Column field=\"createdAt\" :header=\"$t('credits.time')\">\n <template #body=\"{ data }\">\n {{ customerEventService.formatDate(data.createdAt) }}\n </template>\n </Column>\n <Column field=\"params\" :header=\"$t('credits.additionalInfo')\">\n <template #body=\"{ data }\">\n <Button\n v-if=\"customerEventService.hasAdditionalInfo(data)\"\n v-tooltip.top=\"{\n escape: false,\n value: tooltipContentMap.get(data.event_id) || '',\n pt: {\n text: {\n style: {\n width: 'max-content !important'\n }\n }\n }\n }\"\n variant=\"textonly\"\n size=\"icon-sm\"\n :aria-label=\"$t('credits.additionalInfo')\"\n >\n <i class=\"pi pi-info-circle\" />\n </Button>\n </template>\n </Column>\n </DataTable>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Badge from 'primevue/badge'\nimport Column from 'primevue/column'\nimport DataTable from 'primevue/datatable'\nimport Message from 'primevue/message'\nimport ProgressSpinner from 'primevue/progressspinner'\nimport { computed, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport { useTelemetry } from '@/platform/telemetry'\nimport type { AuditLog } from '@/services/customerEventsService'\nimport {\n EventType,\n useCustomerEventsService\n} from '@/services/customerEventsService'\n\nconst events = ref<AuditLog[]>([])\nconst loading = ref(true)\nconst error = ref<string | null>(null)\n\nconst customerEventService = useCustomerEventsService()\n\nconst pagination = ref({\n page: 1,\n limit: 7,\n total: 0,\n totalPages: 0\n})\n\nconst dataTableFirst = computed(\n () => (pagination.value.page - 1) * pagination.value.limit\n)\n\nconst tooltipContentMap = computed(() => {\n const map = new Map<string, string>()\n events.value.forEach((event) => {\n if (customerEventService.hasAdditionalInfo(event) && event.event_id) {\n map.set(event.event_id, customerEventService.getTooltipContent(event))\n }\n })\n return map\n})\n\nconst loadEvents = async () => {\n loading.value = true\n error.value = null\n\n try {\n const response = await customerEventService.getMyEvents({\n page: pagination.value.page,\n limit: pagination.value.limit\n })\n\n if (response) {\n if (response.events) {\n events.value = response.events\n }\n\n if (response.page) {\n pagination.value.page = response.page\n }\n\n if (response.limit) {\n pagination.value.limit = response.limit\n }\n\n if (response.total) {\n pagination.value.total = response.total\n }\n\n if (response.totalPages) {\n pagination.value.totalPages = response.totalPages\n }\n\n // Check if a pending top-up has completed\n useTelemetry()?.checkForCompletedTopup(response.events)\n } else {\n error.value = customerEventService.error.value || 'Failed to load events'\n }\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'Unknown error'\n console.error('Error loading events:', err)\n } finally {\n loading.value = false\n }\n}\n\nconst onPageChange = (event: { page: number }) => {\n pagination.value.page = event.page + 1\n loadEvents().catch((error) => {\n console.error('Error loading events:', error)\n })\n}\n\nconst refresh = async () => {\n pagination.value.page = 1\n await loadEvents()\n}\n\ndefineExpose({\n refresh\n})\n</script>\n","<template>\n <TabPanel value=\"Credits\" class=\"credits-container h-full\">\n <!-- Legacy Design -->\n <div class=\"flex h-full flex-col\">\n <h2 class=\"mb-2 text-2xl font-bold\">\n {{ $t('credits.credits') }}\n </h2>\n\n <Divider />\n\n <div class=\"flex flex-col gap-2\">\n <h3 class=\"text-sm font-medium text-muted\">\n {{ $t('credits.yourCreditBalance') }}\n </h3>\n <div class=\"flex items-center justify-between\">\n <UserCredit text-class=\"text-3xl font-bold\" />\n <Skeleton v-if=\"loading\" width=\"2rem\" height=\"2rem\" />\n <Button\n v-else-if=\"isActiveSubscription\"\n :loading=\"loading\"\n @click=\"handlePurchaseCreditsClick\"\n >\n {{ $t('credits.purchaseCredits') }}\n </Button>\n </div>\n <div class=\"flex flex-row items-center\">\n <Skeleton\n v-if=\"balanceLoading\"\n width=\"12rem\"\n height=\"1rem\"\n class=\"text-xs\"\n />\n <div v-else-if=\"formattedLastUpdateTime\" class=\"text-xs text-muted\">\n {{ $t('credits.lastUpdated') }}: {{ formattedLastUpdateTime }}\n </div>\n <Button\n variant=\"muted-textonly\"\n size=\"icon-sm\"\n :aria-label=\"$t('g.refresh')\"\n @click=\"() => authActions.fetchBalance()\"\n >\n <i class=\"pi pi-refresh\" />\n </Button>\n </div>\n </div>\n\n <div class=\"flex items-center justify-between\">\n <h3>{{ $t('credits.activity') }}</h3>\n <Button\n variant=\"muted-textonly\"\n :loading=\"loading\"\n @click=\"handleCreditsHistoryClick\"\n >\n <i class=\"pi pi-arrow-up-right\" />\n {{ $t('credits.invoiceHistory') }}\n </Button>\n </div>\n\n <template v-if=\"creditHistory.length > 0\">\n <div class=\"grow\">\n <DataTable :value=\"creditHistory\" :show-headers=\"false\">\n <Column field=\"title\" :header=\"$t('g.name')\">\n <template #body=\"{ data }\">\n <div class=\"text-sm font-medium\">{{ data.title }}</div>\n <div class=\"text-xs text-muted\">{{ data.timestamp }}</div>\n </template>\n </Column>\n <Column field=\"amount\" :header=\"$t('g.amount')\">\n <template #body=\"{ data }\">\n <div\n :class=\"[\n 'text-center text-base font-medium',\n data.isPositive ? 'text-sky-500' : 'text-red-400'\n ]\"\n >\n {{ data.isPositive ? '+' : '-' }}${{\n formatMetronomeCurrency(data.amount, 'usd')\n }}\n </div>\n </template>\n </Column>\n </DataTable>\n </div>\n </template>\n\n <Divider />\n\n <UsageLogsTable ref=\"usageLogsTableRef\" />\n\n <div class=\"flex flex-row gap-2\">\n <Button variant=\"muted-textonly\" @click=\"handleFaqClick\">\n <i class=\"pi pi-question-circle\" />\n {{ $t('credits.faqs') }}\n </Button>\n <Button variant=\"muted-textonly\" @click=\"handleOpenPartnerNodesInfo\">\n <i class=\"pi pi-question-circle\" />\n {{ $t('subscription.partnerNodesCredits') }}\n </Button>\n <Button variant=\"muted-textonly\" @click=\"handleMessageSupport\">\n <i class=\"pi pi-comments\" />\n {{ $t('credits.messageSupport') }}\n </Button>\n </div>\n </div>\n </TabPanel>\n</template>\n\n<script setup lang=\"ts\">\nimport Column from 'primevue/column'\nimport DataTable from 'primevue/datatable'\nimport Divider from 'primevue/divider'\nimport Skeleton from 'primevue/skeleton'\nimport TabPanel from 'primevue/tabpanel'\nimport { computed, ref, watch } from 'vue'\n\nimport UserCredit from '@/components/common/UserCredit.vue'\nimport UsageLogsTable from '@/components/dialog/content/setting/UsageLogsTable.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'\nimport { useExternalLink } from '@/composables/useExternalLink'\nimport { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'\nimport { useTelemetry } from '@/platform/telemetry'\nimport { useDialogService } from '@/services/dialogService'\nimport { useCommandStore } from '@/stores/commandStore'\nimport { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'\nimport { formatMetronomeCurrency } from '@/utils/formatUtil'\n\ninterface CreditHistoryItemData {\n title: string\n timestamp: string\n amount: number\n isPositive: boolean\n}\n\nconst { buildDocsUrl, docsPaths } = useExternalLink()\nconst dialogService = useDialogService()\nconst authStore = useFirebaseAuthStore()\nconst authActions = useFirebaseAuthActions()\nconst commandStore = useCommandStore()\nconst telemetry = useTelemetry()\nconst { isActiveSubscription } = useSubscription()\nconst loading = computed(() => authStore.loading)\nconst balanceLoading = computed(() => authStore.isFetchingBalance)\n\nconst usageLogsTableRef = ref<InstanceType<typeof UsageLogsTable> | null>(null)\n\nconst formattedLastUpdateTime = computed(() =>\n authStore.lastBalanceUpdateTime\n ? authStore.lastBalanceUpdateTime.toLocaleString()\n : ''\n)\n\nwatch(\n () => authStore.lastBalanceUpdateTime,\n (newTime, oldTime) => {\n if (newTime && newTime !== oldTime && usageLogsTableRef.value) {\n usageLogsTableRef.value.refresh()\n }\n }\n)\n\nconst handlePurchaseCreditsClick = () => {\n // Track purchase credits entry from Settings > Credits panel\n useTelemetry()?.trackAddApiCreditButtonClicked()\n dialogService.showTopUpCreditsDialog()\n}\n\nconst handleCreditsHistoryClick = async () => {\n await authActions.accessBillingPortal()\n}\n\nconst handleMessageSupport = async () => {\n telemetry?.trackHelpResourceClicked({\n resource_type: 'help_feedback',\n is_external: true,\n source: 'credits_panel'\n })\n await commandStore.execute('Comfy.ContactSupport')\n}\n\nconst handleFaqClick = () => {\n window.open(\n buildDocsUrl('/tutorials/api-nodes/faq', { includeLocale: true }),\n '_blank'\n )\n}\n\nconst handleOpenPartnerNodesInfo = () => {\n window.open(\n buildDocsUrl(docsPaths.partnerNodesPricing, { includeLocale: true }),\n '_blank'\n )\n}\n\nconst creditHistory = ref<CreditHistoryItemData[]>([])\n</script>\n"],"names":["authStore","useFirebaseAuthStore","balanceLoading","computed","t","locale","useI18n","formattedBalance","cents","formatCreditsFromCents","formattedCreditsOnly","EventType","customerApiClient","axios","getComfyApiBaseUrl","useCustomerEventsService","__name","isLoading","ref","error","d","watch","url","handleRequestError","err","context","routeSpecificErrors","isAbortError","message","axiosError","status","executeRequest","requestCall","options","errorContext","formatEventType","eventType","formatDate","dateString","date","formatJsonKey","key","word","formatJsonValue","value","getEventSeverity","hasAdditionalInfo","event","amount","api_name","model","otherParams","getTooltipContent","params","formattedKey","formattedValue","formatAmount","amountMicros","getMyEvents","page","limit","authHeaders","events","loading","customerEventService","pagination","dataTableFirst","tooltipContentMap","map","loadEvents","response","useTelemetry","onPageChange","__expose","buildDocsUrl","docsPaths","useExternalLink","dialogService","useDialogService","authActions","useFirebaseAuthActions","commandStore","useCommandStore","isActiveSubscription","useSubscription","usageLogsTableRef","formattedLastUpdateTime","newTime","oldTime","handlePurchaseCreditsClick","handleCreditsHistoryClick","handleMessageSupport","handleFaqClick","handleOpenPartnerNodesInfo","creditHistory"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LegacyCreditsPanel-D28HHk-A.js","sources":["../../src/components/common/UserCredit.vue","../../src/services/customerEventsService.ts","../../src/components/dialog/content/setting/UsageLogsTable.vue","../../src/components/dialog/content/setting/LegacyCreditsPanel.vue"],"sourcesContent":["<template>\n <div v-if=\"balanceLoading\" class=\"flex items-center gap-1\">\n <div class=\"flex items-center gap-2\">\n <Skeleton shape=\"circle\" width=\"1.5rem\" height=\"1.5rem\" />\n </div>\n <div class=\"flex-1\"></div>\n <Skeleton width=\"8rem\" height=\"2rem\" />\n </div>\n <div v-else class=\"flex items-center gap-1\">\n <Tag\n v-if=\"!showCreditsOnly\"\n severity=\"secondary\"\n rounded\n class=\"p-1 text-amber-400\"\n >\n <template #icon>\n <i class=\"icon-[lucide--component]\" />\n </template>\n </Tag>\n <div :class=\"textClass\">\n {{ showCreditsOnly ? formattedCreditsOnly : formattedBalance }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Skeleton from 'primevue/skeleton'\nimport Tag from 'primevue/tag'\nimport { computed } from 'vue'\nimport { useI18n } from 'vue-i18n'\n\nimport { formatCreditsFromCents } from '@/base/credits/comfyCredits'\nimport { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'\n\nconst { textClass, showCreditsOnly } = defineProps<{\n textClass?: string\n showCreditsOnly?: boolean\n}>()\n\nconst authStore = useFirebaseAuthStore()\nconst balanceLoading = computed(() => authStore.isFetchingBalance)\nconst { t, locale } = useI18n()\n\nconst formattedBalance = computed(() => {\n const cents =\n authStore.balance?.effective_balance_micros ??\n authStore.balance?.amount_micros ??\n 0\n const amount = formatCreditsFromCents({\n cents,\n locale: locale.value\n })\n return `${amount} ${t('credits.credits')}`\n})\n\nconst formattedCreditsOnly = computed(() => {\n const cents =\n authStore.balance?.effective_balance_micros ??\n authStore.balance?.amount_micros ??\n 0\n const amount = formatCreditsFromCents({\n cents,\n locale: locale.value,\n numberOptions: { minimumFractionDigits: 0, maximumFractionDigits: 0 }\n })\n return amount\n})\n</script>\n","import type { AxiosError, AxiosResponse } from 'axios'\nimport axios from 'axios'\nimport { ref, watch } from 'vue'\nimport { useI18n } from 'vue-i18n'\n\nimport { getComfyApiBaseUrl } from '@/config/comfyApi'\nimport { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'\nimport type { components, operations } from '@/types/comfyRegistryTypes'\nimport { isAbortError } from '@/utils/typeGuardUtil'\n\nexport enum EventType {\n CREDIT_ADDED = 'credit_added',\n ACCOUNT_CREATED = 'account_created',\n API_USAGE_STARTED = 'api_usage_started',\n API_USAGE_COMPLETED = 'api_usage_completed'\n}\n\ntype CustomerEventsResponse =\n operations['GetCustomerEvents']['responses']['200']['content']['application/json']\n\ntype CustomerEventsResponseQuery =\n operations['GetCustomerEvents']['parameters']['query']\n\nexport type AuditLog = components['schemas']['AuditLog']\n\nconst customerApiClient = axios.create({\n baseURL: getComfyApiBaseUrl(),\n headers: {\n 'Content-Type': 'application/json'\n }\n})\n\nexport const useCustomerEventsService = () => {\n const isLoading = ref(false)\n const error = ref<string | null>(null)\n const { d } = useI18n()\n\n watch(\n () => getComfyApiBaseUrl(),\n (url) => {\n customerApiClient.defaults.baseURL = url\n }\n )\n\n const handleRequestError = (\n err: unknown,\n context: string,\n routeSpecificErrors?: Record<number, string>\n ) => {\n // Don't treat cancellation as an error\n if (isAbortError(err)) return\n\n let message: string\n if (!axios.isAxiosError(err)) {\n message = `${context} failed: ${err instanceof Error ? err.message : String(err)}`\n } else {\n const axiosError = err as AxiosError<{ message: string }>\n const status = axiosError.response?.status\n if (status && routeSpecificErrors?.[status]) {\n message = routeSpecificErrors[status]\n } else {\n message =\n axiosError.response?.data?.message ??\n `${context} failed with status ${status}`\n }\n }\n\n error.value = message\n }\n\n const executeRequest = async <T>(\n requestCall: () => Promise<AxiosResponse<T>>,\n options: {\n errorContext: string\n routeSpecificErrors?: Record<number, string>\n }\n ): Promise<T | null> => {\n const { errorContext, routeSpecificErrors } = options\n\n isLoading.value = true\n error.value = null\n\n try {\n const response = await requestCall()\n return response.data\n } catch (err) {\n handleRequestError(err, errorContext, routeSpecificErrors)\n return null\n } finally {\n isLoading.value = false\n }\n }\n\n function formatEventType(eventType: string) {\n switch (eventType) {\n case 'credit_added':\n return 'Credits Added'\n case 'account_created':\n return 'Account Created'\n case 'api_usage_completed':\n return 'API Usage'\n default:\n return eventType\n }\n }\n\n function formatDate(dateString: string): string {\n const date = new Date(dateString)\n\n return d(date, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n })\n }\n\n function formatJsonKey(key: string) {\n return key\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ')\n }\n\n function formatJsonValue(value: any) {\n if (typeof value === 'number') {\n // Format numbers with commas and decimals if needed\n return value.toLocaleString()\n }\n if (typeof value === 'string' && value.match(/^\\d{4}-\\d{2}-\\d{2}/)) {\n // Format dates nicely\n return new Date(value).toLocaleString()\n }\n return value\n }\n\n function getEventSeverity(eventType: string) {\n switch (eventType) {\n case 'credit_added':\n return 'success'\n case 'account_created':\n return 'info'\n case 'api_usage_completed':\n return 'warning'\n default:\n return 'info'\n }\n }\n\n function hasAdditionalInfo(event: AuditLog) {\n const { amount, api_name, model, ...otherParams } = event.params || {}\n return Object.keys(otherParams).length > 0\n }\n\n function getTooltipContent(event: AuditLog) {\n const { ...params } = event.params || {}\n\n return Object.entries(params)\n .map(([key, value]) => {\n const formattedKey = formatJsonKey(key)\n const formattedValue = formatJsonValue(value)\n return `<strong>${formattedKey}:</strong> ${formattedValue}`\n })\n .join('<br>')\n }\n\n function formatAmount(amountMicros?: number) {\n if (!amountMicros) return '0.00'\n return (amountMicros / 100).toFixed(2)\n }\n\n async function getMyEvents({\n page = 1,\n limit = 10\n }: CustomerEventsResponseQuery = {}): Promise<CustomerEventsResponse | null> {\n const errorContext = 'Fetching customer events'\n const routeSpecificErrors = {\n 400: 'Invalid input, object invalid',\n 404: 'Not found'\n }\n\n // Get auth headers\n const authHeaders = await useFirebaseAuthStore().getAuthHeader()\n if (!authHeaders) {\n error.value = 'Authentication header is missing'\n return null\n }\n\n const result = await executeRequest<CustomerEventsResponse>(\n () =>\n customerApiClient.get('/customers/events', {\n params: { page, limit },\n headers: authHeaders\n }),\n { errorContext, routeSpecificErrors }\n )\n\n return result\n }\n\n return {\n // State\n isLoading,\n error,\n\n // Methods\n getMyEvents,\n formatEventType,\n getEventSeverity,\n formatAmount,\n hasAdditionalInfo,\n formatDate,\n formatJsonKey,\n formatJsonValue,\n getTooltipContent\n }\n}\n","<template>\n <div>\n <div v-if=\"loading\" class=\"flex items-center justify-center p-8\">\n <ProgressSpinner />\n </div>\n <div v-else-if=\"error\" class=\"p-4\">\n <Message severity=\"error\" :closable=\"false\">{{ error }}</Message>\n </div>\n <DataTable\n v-else\n :value=\"events\"\n :paginator=\"true\"\n :rows=\"pagination.limit\"\n :total-records=\"pagination.total\"\n :first=\"dataTableFirst\"\n :lazy=\"true\"\n class=\"p-datatable-sm custom-datatable\"\n @page=\"onPageChange\"\n >\n <Column field=\"event_type\" :header=\"$t('credits.eventType')\">\n <template #body=\"{ data }\">\n <Badge\n :value=\"customerEventService.formatEventType(data.event_type)\"\n :severity=\"customerEventService.getEventSeverity(data.event_type)\"\n />\n </template>\n </Column>\n <Column field=\"details\" :header=\"$t('credits.details')\">\n <template #body=\"{ data }\">\n <div class=\"event-details\">\n <!-- Credits Added -->\n <template v-if=\"data.event_type === EventType.CREDIT_ADDED\">\n <div class=\"font-semibold text-green-500\">\n {{ $t('credits.added') }} ${{\n customerEventService.formatAmount(data.params?.amount)\n }}\n </div>\n </template>\n\n <!-- Account Created -->\n <template v-else-if=\"data.event_type === EventType.ACCOUNT_CREATED\">\n <div>{{ $t('credits.accountInitialized') }}</div>\n </template>\n\n <!-- API Usage -->\n <template\n v-else-if=\"data.event_type === EventType.API_USAGE_COMPLETED\"\n >\n <div class=\"flex flex-col gap-1\">\n <div class=\"font-semibold\">\n {{ data.params?.api_name || 'API' }}\n </div>\n <div class=\"text-sm text-smoke-400\">\n {{ $t('credits.model') }}: {{ data.params?.model || '-' }}\n </div>\n </div>\n </template>\n </div>\n </template>\n </Column>\n <Column field=\"createdAt\" :header=\"$t('credits.time')\">\n <template #body=\"{ data }\">\n {{ customerEventService.formatDate(data.createdAt) }}\n </template>\n </Column>\n <Column field=\"params\" :header=\"$t('credits.additionalInfo')\">\n <template #body=\"{ data }\">\n <Button\n v-if=\"customerEventService.hasAdditionalInfo(data)\"\n v-tooltip.top=\"{\n escape: false,\n value: tooltipContentMap.get(data.event_id) || '',\n pt: {\n text: {\n style: {\n width: 'max-content !important'\n }\n }\n }\n }\"\n variant=\"textonly\"\n size=\"icon-sm\"\n :aria-label=\"$t('credits.additionalInfo')\"\n >\n <i class=\"pi pi-info-circle\" />\n </Button>\n </template>\n </Column>\n </DataTable>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Badge from 'primevue/badge'\nimport Column from 'primevue/column'\nimport DataTable from 'primevue/datatable'\nimport Message from 'primevue/message'\nimport ProgressSpinner from 'primevue/progressspinner'\nimport { computed, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport { useTelemetry } from '@/platform/telemetry'\nimport type { AuditLog } from '@/services/customerEventsService'\nimport {\n EventType,\n useCustomerEventsService\n} from '@/services/customerEventsService'\n\nconst events = ref<AuditLog[]>([])\nconst loading = ref(true)\nconst error = ref<string | null>(null)\n\nconst customerEventService = useCustomerEventsService()\n\nconst pagination = ref({\n page: 1,\n limit: 7,\n total: 0,\n totalPages: 0\n})\n\nconst dataTableFirst = computed(\n () => (pagination.value.page - 1) * pagination.value.limit\n)\n\nconst tooltipContentMap = computed(() => {\n const map = new Map<string, string>()\n events.value.forEach((event) => {\n if (customerEventService.hasAdditionalInfo(event) && event.event_id) {\n map.set(event.event_id, customerEventService.getTooltipContent(event))\n }\n })\n return map\n})\n\nconst loadEvents = async () => {\n loading.value = true\n error.value = null\n\n try {\n const response = await customerEventService.getMyEvents({\n page: pagination.value.page,\n limit: pagination.value.limit\n })\n\n if (response) {\n if (response.events) {\n events.value = response.events\n }\n\n if (response.page) {\n pagination.value.page = response.page\n }\n\n if (response.limit) {\n pagination.value.limit = response.limit\n }\n\n if (response.total) {\n pagination.value.total = response.total\n }\n\n if (response.totalPages) {\n pagination.value.totalPages = response.totalPages\n }\n\n // Check if a pending top-up has completed\n useTelemetry()?.checkForCompletedTopup(response.events)\n } else {\n error.value = customerEventService.error.value || 'Failed to load events'\n }\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'Unknown error'\n console.error('Error loading events:', err)\n } finally {\n loading.value = false\n }\n}\n\nconst onPageChange = (event: { page: number }) => {\n pagination.value.page = event.page + 1\n loadEvents().catch((error) => {\n console.error('Error loading events:', error)\n })\n}\n\nconst refresh = async () => {\n pagination.value.page = 1\n await loadEvents()\n}\n\ndefineExpose({\n refresh\n})\n</script>\n","<template>\n <TabPanel value=\"Credits\" class=\"credits-container h-full\">\n <!-- Legacy Design -->\n <div class=\"flex h-full flex-col\">\n <h2 class=\"mb-2 text-2xl font-bold\">\n {{ $t('credits.credits') }}\n </h2>\n\n <Divider />\n\n <div class=\"flex flex-col gap-2\">\n <h3 class=\"text-sm font-medium text-muted\">\n {{ $t('credits.yourCreditBalance') }}\n </h3>\n <div class=\"flex items-center justify-between\">\n <UserCredit text-class=\"text-3xl font-bold\" />\n <Skeleton v-if=\"loading\" width=\"2rem\" height=\"2rem\" />\n <Button\n v-else-if=\"isActiveSubscription\"\n :loading=\"loading\"\n @click=\"handlePurchaseCreditsClick\"\n >\n {{ $t('credits.purchaseCredits') }}\n </Button>\n </div>\n <div class=\"flex flex-row items-center\">\n <Skeleton\n v-if=\"balanceLoading\"\n width=\"12rem\"\n height=\"1rem\"\n class=\"text-xs\"\n />\n <div v-else-if=\"formattedLastUpdateTime\" class=\"text-xs text-muted\">\n {{ $t('credits.lastUpdated') }}: {{ formattedLastUpdateTime }}\n </div>\n <Button\n variant=\"muted-textonly\"\n size=\"icon-sm\"\n :aria-label=\"$t('g.refresh')\"\n @click=\"() => authActions.fetchBalance()\"\n >\n <i class=\"pi pi-refresh\" />\n </Button>\n </div>\n </div>\n\n <div class=\"flex items-center justify-between\">\n <h3>{{ $t('credits.activity') }}</h3>\n <Button\n variant=\"muted-textonly\"\n :loading=\"loading\"\n @click=\"handleCreditsHistoryClick\"\n >\n <i class=\"pi pi-arrow-up-right\" />\n {{ $t('credits.invoiceHistory') }}\n </Button>\n </div>\n\n <template v-if=\"creditHistory.length > 0\">\n <div class=\"grow\">\n <DataTable :value=\"creditHistory\" :show-headers=\"false\">\n <Column field=\"title\" :header=\"$t('g.name')\">\n <template #body=\"{ data }\">\n <div class=\"text-sm font-medium\">{{ data.title }}</div>\n <div class=\"text-xs text-muted\">{{ data.timestamp }}</div>\n </template>\n </Column>\n <Column field=\"amount\" :header=\"$t('g.amount')\">\n <template #body=\"{ data }\">\n <div\n :class=\"[\n 'text-center text-base font-medium',\n data.isPositive ? 'text-sky-500' : 'text-red-400'\n ]\"\n >\n {{ data.isPositive ? '+' : '-' }}${{\n formatMetronomeCurrency(data.amount, 'usd')\n }}\n </div>\n </template>\n </Column>\n </DataTable>\n </div>\n </template>\n\n <Divider />\n\n <UsageLogsTable ref=\"usageLogsTableRef\" />\n\n <div class=\"flex flex-row gap-2\">\n <Button variant=\"muted-textonly\" @click=\"handleFaqClick\">\n <i class=\"pi pi-question-circle\" />\n {{ $t('credits.faqs') }}\n </Button>\n <Button variant=\"muted-textonly\" @click=\"handleOpenPartnerNodesInfo\">\n <i class=\"pi pi-question-circle\" />\n {{ $t('subscription.partnerNodesCredits') }}\n </Button>\n <Button variant=\"muted-textonly\" @click=\"handleMessageSupport\">\n <i class=\"pi pi-comments\" />\n {{ $t('credits.messageSupport') }}\n </Button>\n </div>\n </div>\n </TabPanel>\n</template>\n\n<script setup lang=\"ts\">\nimport Column from 'primevue/column'\nimport DataTable from 'primevue/datatable'\nimport Divider from 'primevue/divider'\nimport Skeleton from 'primevue/skeleton'\nimport TabPanel from 'primevue/tabpanel'\nimport { computed, ref, watch } from 'vue'\n\nimport UserCredit from '@/components/common/UserCredit.vue'\nimport UsageLogsTable from '@/components/dialog/content/setting/UsageLogsTable.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'\nimport { useExternalLink } from '@/composables/useExternalLink'\nimport { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'\nimport { useTelemetry } from '@/platform/telemetry'\nimport { useDialogService } from '@/services/dialogService'\nimport { useCommandStore } from '@/stores/commandStore'\nimport { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'\nimport { formatMetronomeCurrency } from '@/utils/formatUtil'\n\ninterface CreditHistoryItemData {\n title: string\n timestamp: string\n amount: number\n isPositive: boolean\n}\n\nconst { buildDocsUrl, docsPaths } = useExternalLink()\nconst dialogService = useDialogService()\nconst authStore = useFirebaseAuthStore()\nconst authActions = useFirebaseAuthActions()\nconst commandStore = useCommandStore()\nconst telemetry = useTelemetry()\nconst { isActiveSubscription } = useSubscription()\nconst loading = computed(() => authStore.loading)\nconst balanceLoading = computed(() => authStore.isFetchingBalance)\n\nconst usageLogsTableRef = ref<InstanceType<typeof UsageLogsTable> | null>(null)\n\nconst formattedLastUpdateTime = computed(() =>\n authStore.lastBalanceUpdateTime\n ? authStore.lastBalanceUpdateTime.toLocaleString()\n : ''\n)\n\nwatch(\n () => authStore.lastBalanceUpdateTime,\n (newTime, oldTime) => {\n if (newTime && newTime !== oldTime && usageLogsTableRef.value) {\n usageLogsTableRef.value.refresh()\n }\n }\n)\n\nconst handlePurchaseCreditsClick = () => {\n // Track purchase credits entry from Settings > Credits panel\n useTelemetry()?.trackAddApiCreditButtonClicked()\n dialogService.showTopUpCreditsDialog()\n}\n\nconst handleCreditsHistoryClick = async () => {\n await authActions.accessBillingPortal()\n}\n\nconst handleMessageSupport = async () => {\n telemetry?.trackHelpResourceClicked({\n resource_type: 'help_feedback',\n is_external: true,\n source: 'credits_panel'\n })\n await commandStore.execute('Comfy.ContactSupport')\n}\n\nconst handleFaqClick = () => {\n window.open(\n buildDocsUrl('/tutorials/api-nodes/faq', { includeLocale: true }),\n '_blank'\n )\n}\n\nconst handleOpenPartnerNodesInfo = () => {\n window.open(\n buildDocsUrl(docsPaths.partnerNodesPricing, { includeLocale: true }),\n '_blank'\n )\n}\n\nconst creditHistory = ref<CreditHistoryItemData[]>([])\n</script>\n"],"names":["authStore","useFirebaseAuthStore","balanceLoading","computed","t","locale","useI18n","formattedBalance","cents","formatCreditsFromCents","formattedCreditsOnly","EventType","customerApiClient","axios","getComfyApiBaseUrl","useCustomerEventsService","__name","isLoading","ref","error","d","watch","url","handleRequestError","err","context","routeSpecificErrors","isAbortError","message","axiosError","status","executeRequest","requestCall","options","errorContext","formatEventType","eventType","formatDate","dateString","date","formatJsonKey","key","word","formatJsonValue","value","getEventSeverity","hasAdditionalInfo","event","amount","api_name","model","otherParams","getTooltipContent","params","formattedKey","formattedValue","formatAmount","amountMicros","getMyEvents","page","limit","authHeaders","events","loading","customerEventService","pagination","dataTableFirst","tooltipContentMap","map","loadEvents","response","useTelemetry","onPageChange","__expose","buildDocsUrl","docsPaths","useExternalLink","dialogService","useDialogService","authActions","useFirebaseAuthActions","commandStore","useCommandStore","isActiveSubscription","useSubscription","usageLogsTableRef","formattedLastUpdateTime","newTime","oldTime","handlePurchaseCreditsClick","handleCreditsHistoryClick","handleMessageSupport","handleFaqClick","handleOpenPartnerNodesInfo","creditHistory"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_ as o}from"./Load3D.vue_vue_type_script_setup_true_lang-
|
|
2
|
-
//# sourceMappingURL=Load3D-
|
|
1
|
+
import{_ as o}from"./Load3D.vue_vue_type_script_setup_true_lang-KEzORqB0.js";import"./vendor-other-Dsj-QuOx.js";import"./vendor-primevue-Cif--Rbw.js";import"./index-U7jagKl8.js";import"./vendor-vue-DNQSPQQ2.js";import"./vendor-reka-ui-WjwjFuZo.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-ByuY8CdW.js";import"./vendor-tiptap-YMjM2h-Z.js";export{o as default};
|
|
2
|
+
//# sourceMappingURL=Load3D-CPNYDT4-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Load3D-CPNYDT4-.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var be=Object.defineProperty;var r=(d,u)=>be(d,"name",{value:u,configurable:!0});import{a2 as F,dk as H,dl as L,r as O,o as Z,_ as K,h as q,c as x,d as o,l as C,j as y,k as D,e as n,s as G,z as N,a8 as e,v as X,E as T,q as $,F as ee,y as oe,A as ne,u as Y,I as z,T as ye,bV as E}from"./vendor-other-Dsj-QuOx.js";import{j as ie}from"./vendor-primevue-Cif--Rbw.js";import{_ as S,e as Q,t as A,c as J,d as se,cX as xe,u as we,cY as he,cZ as Me,r as Ce,c_ as $e,cD as De}from"./index-Bc79VbnU.js";const Re={class:"relative show-slider"},Ie={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface p-4 shadow-lg w-[150px]"},re=F({__name:"PopupSlider",props:H({icon:{default:"pi-expand"},tooltipText:{},min:{default:10},max:{default:150},step:{default:1}},{modelValue:{},modelModifiers:{}}),emits:["update:modelValue"],setup(d){const u=L(d,"modelValue"),l=O(!1),t=r(()=>{l.value=!l.value},"toggleSlider"),i=r(a=>{a.target.closest(".show-slider")||(l.value=!1)},"closeSlider");return Z(()=>{document.addEventListener("click",i)}),K(()=>{document.removeEventListener("click",i)}),(a,p)=>{const k=q("tooltip");return o(),x("div",Re,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":a.tooltipText,onClick:t},{default:D(()=>[n("i",{class:G(["pi",a.icon,"text-lg text-base-foreground"])},null,2)]),_:1},8,["aria-label"])),[[k,{value:a.tooltipText,showDelay:300},void 0,{right:!0}]]),C(n("div",Ie,[N(e(ie),{modelValue:u.value,"onUpdate:modelValue":p[0]||(p[0]=v=>u.value=v),class:"w-full",min:a.min,max:a.max,step:a.step},null,8,["modelValue","min","max","step"])],512),[[X,l.value]])])}}}),Se={class:"flex flex-col"},Le=F({__name:"CameraControls",props:{cameraType:{},cameraTypeModifiers:{},fov:{},fovModifiers:{}},emits:["update:cameraType","update:fov"],setup(d){const u=L(d,"cameraType"),l=L(d,"fov"),t=T(()=>u.value==="perspective"),i=r(()=>{u.value=u.value==="perspective"?"orthographic":"perspective"},"switchCamera");return(a,p)=>{const k=q("tooltip");return o(),x("div",Se,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":a.$t("load3d.switchCamera"),onClick:i},{default:D(()=>p[1]||(p[1]=[n("i",{class:G(["pi","pi-camera","text-lg text-base-foreground"])},null,-1)])),_:1},8,["aria-label"])),[[k,{value:a.$t("load3d.switchCamera"),showDelay:300},void 0,{right:!0}]]),t.value?(o(),y(re,{key:0,modelValue:l.value,"onUpdate:modelValue":p[0]||(p[0]=v=>l.value=v),"tooltip-text":a.$t("load3d.fov")},null,8,["modelValue","tooltip-text"])):$("",!0)])}}}),Be={class:"flex flex-col"},Ue={class:"show-export-formats relative"},ze={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"},Ve={class:"flex flex-col"},Ee=F({__name:"ExportControls",emits:["exportModel"],setup(d,{emit:u}){const l=u,t=O(!1),i=[{label:"GLB",value:"glb"},{label:"OBJ",value:"obj"},{label:"STL",value:"stl"}];function a(){t.value=!t.value}r(a,"toggleExportFormats");function p(v){l("exportModel",v),t.value=!1}r(p,"exportModel");function k(v){v.target.closest(".show-export-formats")||(t.value=!1)}return r(k,"closeExportFormatsList"),Z(()=>{document.addEventListener("click",k)}),K(()=>{document.removeEventListener("click",k)}),(v,s)=>{const f=q("tooltip");return o(),x("div",Be,[n("div",Ue,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":v.$t("load3d.exportModel"),onClick:a},{default:D(()=>s[0]||(s[0]=[n("i",{class:"pi pi-download text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[f,{value:v.$t("load3d.exportModel"),showDelay:300},void 0,{right:!0}]]),C(n("div",ze,[n("div",Ve,[(o(),x(ee,null,oe(i,w=>N(S,{key:w.value,variant:"textonly",class:"text-base-foreground",onClick:r(V=>p(w.value),"onClick")},{default:D(()=>[ne(Y(w.label),1)]),_:2},1032,["onClick"])),64))])],512),[[X,t.value]])])])}}}),Pe={class:"flex flex-col"},Te={key:0,class:"show-light-intensity relative"},Ge={class:"absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg",style:{width:"150px"}},Fe=F({__name:"LightControls",props:{lightIntensity:{},lightIntensityModifiers:{},materialMode:{},materialModeModifiers:{}},emits:["update:lightIntensity","update:materialMode"],setup(d){const u=L(d,"lightIntensity"),l=L(d,"materialMode"),t=T(()=>l.value==="original"),i=O(!1),a=Q().get("Comfy.Load3D.LightIntensityMaximum"),p=Q().get("Comfy.Load3D.LightIntensityMinimum"),k=Q().get("Comfy.Load3D.LightAdjustmentIncrement");function v(){i.value=!i.value}r(v,"toggleLightIntensity");function s(f){f.target.closest(".show-light-intensity")||(i.value=!1)}return r(s,"closeLightSlider"),Z(()=>{document.addEventListener("click",s)}),K(()=>{document.removeEventListener("click",s)}),(f,w)=>{const V=q("tooltip");return o(),x("div",Pe,[t.value?(o(),x("div",Te,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":f.$t("load3d.lightIntensity"),onClick:v},{default:D(()=>w[1]||(w[1]=[n("i",{class:"pi pi-sun text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[V,{value:f.$t("load3d.lightIntensity"),showDelay:300},void 0,{right:!0}]]),C(n("div",Ge,[N(e(ie),{modelValue:u.value,"onUpdate:modelValue":w[0]||(w[0]=P=>u.value=P),class:"w-full",min:e(p),max:e(a),step:e(k)},null,8,["modelValue","min","max","step"])],512),[[X,i.value]])])):$("",!0)])}}}),je={class:"flex flex-col"},_e={class:"show-up-direction relative"},Oe={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"},Ae={class:"flex flex-col"},Ne={key:0,class:"show-material-mode relative"},We={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"},qe={class:"flex flex-col"},Je={key:1},Xe=F({__name:"ModelControls",props:H({hideMaterialMode:{type:Boolean,default:!1},isPlyModel:{type:Boolean,default:!1},hasSkeleton:{type:Boolean,default:!1}},{materialMode:{},materialModeModifiers:{},upDirection:{},upDirectionModifiers:{},showSkeleton:{type:Boolean},showSkeletonModifiers:{}}),emits:["update:materialMode","update:upDirection","update:showSkeleton"],setup(d){const u=L(d,"materialMode"),l=L(d,"upDirection"),t=L(d,"showSkeleton"),i=O(!1),a=O(!1),p=["original","-x","+x","-y","+y","-z","+z"],k=T(()=>{const R=["original","normal","wireframe"];return d.isPlyModel&&R.splice(1,0,"pointCloud"),R});function v(){i.value=!i.value,a.value=!1}r(v,"toggleUpDirection");function s(R){l.value=R,i.value=!1}r(s,"selectUpDirection");function f(){a.value=!a.value,i.value=!1}r(f,"toggleMaterialMode");function w(R){u.value=R,a.value=!1}r(w,"selectMaterialMode");function V(R){return A(`load3d.materialModes.${R}`)}r(V,"formatMaterialMode");function P(R){const I=R.target;I.closest(".show-up-direction")||(i.value=!1),I.closest(".show-material-mode")||(a.value=!1)}return r(P,"closeSceneSlider"),Z(()=>{document.addEventListener("click",P)}),K(()=>{document.removeEventListener("click",P)}),(R,I)=>{const j=q("tooltip");return o(),x("div",je,[n("div",_e,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":e(A)("load3d.upDirection"),onClick:v},{default:D(()=>I[1]||(I[1]=[n("i",{class:"pi pi-arrow-up text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[j,{value:e(A)("load3d.upDirection"),showDelay:300},void 0,{right:!0}]]),C(n("div",Oe,[n("div",Ae,[(o(),x(ee,null,oe(p,B=>N(S,{key:B,variant:"textonly",class:G(e(J)("text-base-foreground",l.value===B&&"bg-blue-500")),onClick:r(h=>s(B),"onClick")},{default:D(()=>[ne(Y(B.toUpperCase()),1)]),_:2},1032,["class","onClick"])),64))])],512),[[X,i.value]])]),R.hideMaterialMode?$("",!0):(o(),x("div",Ne,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":e(A)("load3d.materialMode"),onClick:f},{default:D(()=>I[2]||(I[2]=[n("i",{class:"pi pi-box text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[j,{value:e(A)("load3d.materialMode"),showDelay:300},void 0,{right:!0}]]),C(n("div",We,[n("div",qe,[(o(!0),x(ee,null,oe(k.value,B=>(o(),y(S,{key:B,variant:"textonly",class:G(e(J)("whitespace-nowrap text-base-foreground",u.value===B&&"bg-blue-500")),onClick:r(h=>w(B),"onClick")},{default:D(()=>[ne(Y(V(B)),1)]),_:2},1032,["class","onClick"]))),128))])],512),[[X,a.value]])])),R.hasSkeleton?(o(),x("div",Je,[C((o(),y(S,{size:"icon",variant:"textonly",class:G(e(J)("rounded-full",t.value&&"bg-blue-500")),"aria-label":e(A)("load3d.showSkeleton"),onClick:I[0]||(I[0]=B=>t.value=!t.value)},{default:D(()=>I[3]||(I[3]=[n("i",{class:"pi pi-sitemap text-lg text-base-foreground"},null,-1)])),_:1},8,["class","aria-label"])),[[j,{value:e(A)("load3d.showSkeleton"),showDelay:300},void 0,{right:!0}]])])):$("",!0)])}}}),Ye={class:"flex flex-col"},Ze={key:0},He=["value"],Ke={key:1},Qe={key:2},eo={key:4},oo=F({__name:"SceneControls",props:{showGrid:{type:Boolean},showGridModifiers:{},backgroundColor:{},backgroundColorModifiers:{},backgroundImage:{},backgroundImageModifiers:{},backgroundRenderMode:{default:"tiled"},backgroundRenderModeModifiers:{},fov:{},fovModifiers:{}},emits:H(["updateBackgroundImage"],["update:showGrid","update:backgroundColor","update:backgroundImage","update:backgroundRenderMode","update:fov"]),setup(d,{emit:u}){const l=u,t=L(d,"showGrid"),i=L(d,"backgroundColor"),a=L(d,"backgroundImage"),p=L(d,"backgroundRenderMode"),k=L(d,"fov"),v=T(()=>a.value&&a.value!==""),s=O(null),f=O(null),w=r(()=>{t.value=!t.value},"toggleGrid"),V=r(h=>{i.value=h},"updateBackgroundColor"),P=r(()=>{s.value?.click()},"openColorPicker"),R=r(()=>{f.value?.click()},"openImagePicker"),I=r(h=>{const M=h.target;M.files&&M.files[0]&&l("updateBackgroundImage",M.files[0])},"uploadBackgroundImage"),j=r(()=>{l("updateBackgroundImage",null)},"removeBackgroundImage"),B=r(()=>{p.value=p.value==="panorama"?"tiled":"panorama"},"toggleBackgroundRenderMode");return(h,M)=>{const _=q("tooltip");return o(),x("div",Ye,[C((o(),y(S,{variant:"textonly",size:"icon",class:G(e(J)("rounded-full",t.value&&"ring-2 ring-white/50")),"aria-label":h.$t("load3d.showGrid"),onClick:w},{default:D(()=>M[2]||(M[2]=[n("i",{class:"pi pi-table text-lg text-base-foreground"},null,-1)])),_:1},8,["class","aria-label"])),[[_,{value:h.$t("load3d.showGrid"),showDelay:300},void 0,{right:!0}]]),v.value?$("",!0):(o(),x("div",Ze,[C((o(),y(S,{variant:"textonly",size:"icon",class:"rounded-full","aria-label":h.$t("load3d.backgroundColor"),onClick:P},{default:D(()=>[M[3]||(M[3]=n("i",{class:"pi pi-palette text-lg text-base-foreground"},null,-1)),n("input",{ref_key:"colorPickerRef",ref:s,type:"color",value:i.value,class:"pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0",onInput:M[0]||(M[0]=W=>V(W.target.value))},null,40,He)]),_:1},8,["aria-label"])),[[_,{value:h.$t("load3d.backgroundColor"),showDelay:300},void 0,{right:!0}]])])),v.value?$("",!0):(o(),x("div",Ke,[C((o(),y(S,{variant:"textonly",size:"icon",class:"rounded-full","aria-label":h.$t("load3d.uploadBackgroundImage"),onClick:R},{default:D(()=>[M[4]||(M[4]=n("i",{class:"pi pi-image text-lg text-base-foreground"},null,-1)),n("input",{ref_key:"imagePickerRef",ref:f,type:"file",accept:"image/*",class:"pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0",onChange:I},null,544)]),_:1},8,["aria-label"])),[[_,{value:h.$t("load3d.uploadBackgroundImage"),showDelay:300},void 0,{right:!0}]])])),v.value?(o(),x("div",Qe,[C((o(),y(S,{variant:"textonly",size:"icon",class:G(e(J)("rounded-full",p.value==="panorama"&&"ring-2 ring-white/50")),"aria-label":h.$t("load3d.panoramaMode"),onClick:B},{default:D(()=>M[5]||(M[5]=[n("i",{class:"pi pi-globe text-lg text-base-foreground"},null,-1)])),_:1},8,["class","aria-label"])),[[_,{value:h.$t("load3d.panoramaMode"),showDelay:300},void 0,{right:!0}]])])):$("",!0),v.value&&p.value==="panorama"?(o(),y(re,{key:3,modelValue:k.value,"onUpdate:modelValue":M[1]||(M[1]=W=>k.value=W),"tooltip-text":h.$t("load3d.fov")},null,8,["modelValue","tooltip-text"])):$("",!0),v.value?(o(),x("div",eo,[C((o(),y(S,{variant:"textonly",size:"icon",class:"rounded-full","aria-label":h.$t("load3d.removeBackgroundImage"),onClick:j},{default:D(()=>M[6]||(M[6]=[n("i",{class:"pi pi-times text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[_,{value:h.$t("load3d.removeBackgroundImage"),showDelay:300},void 0,{right:!0}]])])):$("",!0)])}}}),to={class:"show-menu relative"},lo={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"},ao={class:"flex flex-col"},no={class:"whitespace-nowrap text-base-foreground"},io={class:"rounded-lg bg-smoke-700/30"},so=F({__name:"Load3DControls",props:H({isSplatModel:{type:Boolean,default:!1},isPlyModel:{type:Boolean,default:!1},hasSkeleton:{type:Boolean,default:!1}},{sceneConfig:{},sceneConfigModifiers:{},modelConfig:{},modelConfigModifiers:{},cameraConfig:{},cameraConfigModifiers:{},lightConfig:{},lightConfigModifiers:{}}),emits:H(["updateBackgroundImage","exportModel"],["update:sceneConfig","update:modelConfig","update:cameraConfig","update:lightConfig"]),setup(d,{emit:u}){const l=L(d,"sceneConfig"),t=L(d,"modelConfig"),i=L(d,"cameraConfig"),a=L(d,"lightConfig"),p=O(!1),k=O("scene"),v={scene:"load3d.scene",model:"load3d.model",camera:"load3d.camera",light:"load3d.light",export:"load3d.export"},s=T(()=>d.isSplatModel?["scene","model","camera"]:["scene","model","camera","light","export"]),f=T(()=>k.value==="scene"&&!!l.value),w=T(()=>k.value==="model"&&!!t.value),V=T(()=>k.value==="camera"&&!!i.value),P=T(()=>k.value==="light"&&!!a.value&&!!t.value),R=T(()=>k.value==="export"),I=r(()=>{p.value=!p.value},"toggleMenu"),j=r(U=>{k.value=U,p.value=!1},"selectCategory"),B=r(U=>`${{scene:"pi pi-image",model:"pi pi-box",camera:"pi pi-camera",light:"pi pi-sun",export:"pi pi-download"}[U]} text-base-foreground text-lg`,"getCategoryIcon"),h=u,M=r(U=>{h("updateBackgroundImage",U)},"handleBackgroundImageUpdate"),_=r(U=>{h("exportModel",U)},"handleExportModel"),W=r(U=>{U.target.closest(".show-menu")||(p.value=!1)},"closeSlider");return Z(()=>{document.addEventListener("click",W)}),K(()=>{document.removeEventListener("click",W)}),(U,g)=>(o(),x("div",{class:"pointer-events-auto absolute top-12 left-2 z-20 flex flex-col rounded-lg bg-backdrop/30",onPointerdown:g[12]||(g[12]=z(()=>{},["stop"])),onPointermove:g[13]||(g[13]=z(()=>{},["stop"])),onPointerup:g[14]||(g[14]=z(()=>{},["stop"])),onWheel:g[15]||(g[15]=z(()=>{},["stop"]))},[n("div",to,[N(S,{variant:"textonly",size:"icon","aria-label":U.$t("menu.showMenu"),class:"rounded-full",onClick:I},{default:D(()=>g[16]||(g[16]=[n("i",{class:"pi pi-bars text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"]),C(n("div",lo,[n("div",ao,[(o(!0),x(ee,null,oe(s.value,m=>(o(),y(S,{key:m,variant:"textonly",class:G(e(J)("flex w-full items-center justify-start",k.value===m&&"bg-button-active-surface")),onClick:r(te=>j(m),"onClick")},{default:D(()=>[n("i",{class:G(B(m))},null,2),n("span",no,Y(U.$t(v[m])),1)]),_:2},1032,["class","onClick"]))),128))])],512),[[X,p.value]])]),C(n("div",io,[f.value?(o(),y(oo,{key:0,"show-grid":l.value.showGrid,"onUpdate:showGrid":g[0]||(g[0]=m=>l.value.showGrid=m),"background-color":l.value.backgroundColor,"onUpdate:backgroundColor":g[1]||(g[1]=m=>l.value.backgroundColor=m),"background-image":l.value.backgroundImage,"onUpdate:backgroundImage":g[2]||(g[2]=m=>l.value.backgroundImage=m),"background-render-mode":l.value.backgroundRenderMode,"onUpdate:backgroundRenderMode":g[3]||(g[3]=m=>l.value.backgroundRenderMode=m),fov:i.value.fov,"onUpdate:fov":g[4]||(g[4]=m=>i.value.fov=m),onUpdateBackgroundImage:M},null,8,["show-grid","background-color","background-image","background-render-mode","fov"])):$("",!0),w.value?(o(),y(Xe,{key:1,"material-mode":t.value.materialMode,"onUpdate:materialMode":g[5]||(g[5]=m=>t.value.materialMode=m),"up-direction":t.value.upDirection,"onUpdate:upDirection":g[6]||(g[6]=m=>t.value.upDirection=m),"show-skeleton":t.value.showSkeleton,"onUpdate:showSkeleton":g[7]||(g[7]=m=>t.value.showSkeleton=m),"hide-material-mode":U.isSplatModel,"is-ply-model":U.isPlyModel,"has-skeleton":U.hasSkeleton},null,8,["material-mode","up-direction","show-skeleton","hide-material-mode","is-ply-model","has-skeleton"])):$("",!0),V.value?(o(),y(Le,{key:2,"camera-type":i.value.cameraType,"onUpdate:cameraType":g[8]||(g[8]=m=>i.value.cameraType=m),fov:i.value.fov,"onUpdate:fov":g[9]||(g[9]=m=>i.value.fov=m)},null,8,["camera-type","fov"])):$("",!0),P.value?(o(),y(Fe,{key:3,"light-intensity":a.value.intensity,"onUpdate:lightIntensity":g[10]||(g[10]=m=>a.value.intensity=m),"material-mode":t.value.materialMode,"onUpdate:materialMode":g[11]||(g[11]=m=>t.value.materialMode=m)},null,8,["light-intensity","material-mode"])):$("",!0),R.value?(o(),y(Ee,{key:4,onExportModel:_})):$("",!0)],512),[[X,k.value]])],32))}}),ro={key:0,class:"absolute inset-0 z-50 flex items-center justify-center bg-backdrop/50"},uo={class:"flex flex-col items-center"},go={class:"mt-4 text-lg text-base-foreground"},co=F({__name:"LoadingOverlay",props:{loading:{type:Boolean},loadingMessage:{}},setup(d){return(u,l)=>(o(),y(ye,{name:"fade"},{default:D(()=>[u.loading?(o(),x("div",ro,[n("div",uo,[l[0]||(l[0]=n("div",{class:"spinner"},null,-1)),n("div",go,Y(u.loadingMessage),1)])])):$("",!0)]),_:1}))}}),po=se(co,[["__scopeId","data-v-c31c7285"]]),vo={key:0,class:"pointer-events-none absolute inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"},fo={class:"rounded-lg border-2 border-dashed border-blue-400 bg-blue-500/20 px-6 py-4 text-lg font-medium text-blue-100"},mo=F({__name:"Load3DScene",props:{initializeLoad3d:{type:Function},cleanup:{type:Function},loading:{type:Boolean},loadingMessage:{},onModelDrop:{type:Function},isPreview:{type:Boolean}},setup(d){const u=d,l=O(null),{isDragging:t,dragMessage:i,handleDragOver:a,handleDragLeave:p,handleDrop:k}=xe({onModelDrop:r(async v=>{u.onModelDrop&&await u.onModelDrop(v)},"onModelDrop"),disabled:T(()=>u.isPreview)});return Z(()=>{l.value&&u.initializeLoad3d(l.value)}),K(()=>{u.cleanup()}),(v,s)=>(o(),x("div",{ref_key:"container",ref:l,class:"relative h-full w-full min-h-[200px]","data-capture-wheel":"true",onPointerdown:s[0]||(s[0]=z(()=>{},["stop"])),onPointermove:s[1]||(s[1]=z(()=>{},["stop"])),onPointerup:s[2]||(s[2]=z(()=>{},["stop"])),onMousedown:s[3]||(s[3]=z(()=>{},["stop"])),onMousemove:s[4]||(s[4]=z(()=>{},["stop"])),onMouseup:s[5]||(s[5]=z(()=>{},["stop"])),onContextmenu:s[6]||(s[6]=z(()=>{},["stop","prevent"])),onDragover:s[7]||(s[7]=z((...f)=>e(a)&&e(a)(...f),["prevent","stop"])),onDragleave:s[8]||(s[8]=z((...f)=>e(p)&&e(p)(...f),["stop"])),onDrop:s[9]||(s[9]=z((...f)=>e(k)&&e(k)(...f),["prevent","stop"]))},[N(po,{loading:v.loading,"loading-message":v.loadingMessage},null,8,["loading","loading-message"]),!v.isPreview&&e(t)?(o(),x("div",vo,[n("div",fo,Y(e(i)),1)])):$("",!0)],544))}}),ko={class:"relative rounded-lg bg-backdrop/30"},bo={class:"flex flex-col gap-2"},yo={key:2,class:"mt-1 text-center text-xs text-base-foreground"},xo=F({__name:"RecordingControls",props:{hasRecording:{type:Boolean},hasRecordingModifiers:{},isRecording:{type:Boolean},isRecordingModifiers:{},recordingDuration:{},recordingDurationModifiers:{}},emits:H(["startRecording","stopRecording","exportRecording","clearRecording"],["update:hasRecording","update:isRecording","update:recordingDuration"]),setup(d,{emit:u}){const l=L(d,"hasRecording"),t=L(d,"isRecording"),i=L(d,"recordingDuration"),a=u;function p(){t.value?a("stopRecording"):a("startRecording")}r(p,"toggleRecording");function k(){a("exportRecording")}r(k,"handleExportRecording");function v(){a("clearRecording")}r(v,"handleClearRecording");function s(f){const w=Math.floor(f/60),V=Math.floor(f%60);return`${w.toString().padStart(2,"0")}:${V.toString().padStart(2,"0")}`}return r(s,"formatDuration"),(f,w)=>{const V=q("tooltip");return o(),x("div",ko,[n("div",bo,[C((o(),y(S,{size:"icon",variant:"textonly",class:G(e(J)("rounded-full",t.value&&"text-red-500 recording-button-blink")),"aria-label":t.value?f.$t("load3d.stopRecording"):f.$t("load3d.startRecording"),onClick:p},{default:D(()=>[n("i",{class:G(["pi",t.value?"pi-circle-fill":"pi-video","text-lg text-base-foreground"])},null,2)]),_:1},8,["class","aria-label"])),[[V,{value:t.value?f.$t("load3d.stopRecording"):f.$t("load3d.startRecording"),showDelay:300},void 0,{right:!0}]]),l.value&&!t.value?C((o(),y(S,{key:0,size:"icon",variant:"textonly",class:"rounded-full","aria-label":f.$t("load3d.exportRecording"),onClick:k},{default:D(()=>w[0]||(w[0]=[n("i",{class:"pi pi-download text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[V,{value:f.$t("load3d.exportRecording"),showDelay:300},void 0,{right:!0}]]):$("",!0),l.value&&!t.value?C((o(),y(S,{key:1,size:"icon",variant:"textonly",class:"rounded-full","aria-label":f.$t("load3d.clearRecording"),onClick:v},{default:D(()=>w[1]||(w[1]=[n("i",{class:"pi pi-trash text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[V,{value:f.$t("load3d.clearRecording"),showDelay:300},void 0,{right:!0}]]):$("",!0),i.value&&i.value>0&&!t.value?(o(),x("div",yo,Y(s(i.value)),1)):$("",!0)])])}}}),wo=se(xo,[["__scopeId","data-v-24c77a32"]]),ho={class:"relative rounded-lg bg-backdrop/30"},Mo={class:"flex flex-col gap-2"},Co=F({__name:"ViewerControls",props:{node:{}},setup(d){const u=r(()=>{const l={node:d.node};we().showDialog({key:"global-load3d-viewer",title:A("load3d.viewer.title"),component:he,props:l,dialogComponentProps:{style:"width: 80vw; height: 80vh;",maximizable:!0,onClose:r(async()=>{await Me().handleViewerClose(l.node)},"onClose")}})},"openIn3DViewer");return(l,t)=>{const i=q("tooltip");return o(),x("div",ho,[n("div",Mo,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":e(A)("load3d.openIn3DViewer"),onClick:u},{default:D(()=>t[0]||(t[0]=[n("i",{class:"pi pi-expand text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[i,{value:e(A)("load3d.openIn3DViewer"),showDelay:300},void 0,{right:!0}]])])])}}}),$o={class:"pointer-events-none absolute top-0 left-0 size-full"},Do={key:1,class:"pointer-events-auto absolute top-12 right-2 z-20"},Bo=F({__name:"Load3D",props:{widget:{},nodeId:{}},setup(d){const u=d;function l(ae){return"node"in ae&&ae.node!==void 0}r(l,"isComponentWidget");const t=O(null);l(u.widget)?t.value=u.widget.node:u.nodeId&&Z(()=>{t.value=Ce.rootGraph?.getNodeById(u.nodeId)||null});const{sceneConfig:i,modelConfig:a,cameraConfig:p,lightConfig:k,isRecording:v,isPreview:s,isSplatModel:f,isPlyModel:w,hasSkeleton:V,hasRecording:P,recordingDuration:R,animations:I,playing:j,selectedSpeed:B,selectedAnimation:h,animationProgress:M,animationDuration:_,loading:W,loadingMessage:U,initializeLoad3d:g,handleMouseEnter:m,handleMouseLeave:te,handleStartRecording:de,handleStopRecording:ue,handleExportRecording:ge,handleClearRecording:ce,handleSeek:pe,handleBackgroundImageUpdate:ve,handleExportModel:fe,handleModelDrop:me,cleanup:ke}=$e(t),le=T(()=>Q().get("Comfy.Load3D.3DViewerEnable"));return(ae,c)=>(o(),x("div",{class:"relative size-full",onMouseenter:c[13]||(c[13]=(...b)=>e(m)&&e(m)(...b)),onMouseleave:c[14]||(c[14]=(...b)=>e(te)&&e(te)(...b)),onPointerdown:c[15]||(c[15]=z(()=>{},["stop"])),onPointermove:c[16]||(c[16]=z(()=>{},["stop"])),onPointerup:c[17]||(c[17]=z(()=>{},["stop"]))},[t.value?(o(),y(mo,{key:0,"initialize-load3d":e(g),cleanup:e(ke),loading:e(W),"loading-message":e(U),"on-model-drop":e(s)?void 0:e(me),"is-preview":e(s)},null,8,["initialize-load3d","cleanup","loading","loading-message","on-model-drop","is-preview"])):$("",!0),n("div",$o,[N(so,{"scene-config":e(i),"onUpdate:sceneConfig":c[0]||(c[0]=b=>E(i)?i.value=b:null),"model-config":e(a),"onUpdate:modelConfig":c[1]||(c[1]=b=>E(a)?a.value=b:null),"camera-config":e(p),"onUpdate:cameraConfig":c[2]||(c[2]=b=>E(p)?p.value=b:null),"light-config":e(k),"onUpdate:lightConfig":c[3]||(c[3]=b=>E(k)?k.value=b:null),"is-splat-model":e(f),"is-ply-model":e(w),"has-skeleton":e(V),onUpdateBackgroundImage:e(ve),onExportModel:e(fe)},null,8,["scene-config","model-config","camera-config","light-config","is-splat-model","is-ply-model","has-skeleton","onUpdateBackgroundImage","onExportModel"]),e(I)&&e(I).length>0?(o(),y(De,{key:0,animations:e(I),"onUpdate:animations":c[4]||(c[4]=b=>E(I)?I.value=b:null),playing:e(j),"onUpdate:playing":c[5]||(c[5]=b=>E(j)?j.value=b:null),"selected-speed":e(B),"onUpdate:selectedSpeed":c[6]||(c[6]=b=>E(B)?B.value=b:null),"selected-animation":e(h),"onUpdate:selectedAnimation":c[7]||(c[7]=b=>E(h)?h.value=b:null),"animation-progress":e(M),"onUpdate:animationProgress":c[8]||(c[8]=b=>E(M)?M.value=b:null),"animation-duration":e(_),"onUpdate:animationDuration":c[9]||(c[9]=b=>E(_)?_.value=b:null),onSeek:e(pe)},null,8,["animations","playing","selected-speed","selected-animation","animation-progress","animation-duration","onSeek"])):$("",!0)]),le.value&&t.value?(o(),x("div",Do,[N(Co,{node:t.value},null,8,["node"])])):$("",!0),e(s)?$("",!0):(o(),x("div",{key:2,class:G(["pointer-events-auto absolute right-2 z-20",{"top-12":!le.value,"top-24":le.value}])},[N(wo,{"is-recording":e(v),"onUpdate:isRecording":c[10]||(c[10]=b=>E(v)?v.value=b:null),"has-recording":e(P),"onUpdate:hasRecording":c[11]||(c[11]=b=>E(P)?P.value=b:null),"recording-duration":e(R),"onUpdate:recordingDuration":c[12]||(c[12]=b=>E(R)?R.value=b:null),onStartRecording:e(de),onStopRecording:e(ue),onExportRecording:e(ge),onClearRecording:e(ce)},null,8,["is-recording","has-recording","recording-duration","onStartRecording","onStopRecording","onExportRecording","onClearRecording"])],2))],32))}});export{Bo as _};
|
|
2
|
-
//# sourceMappingURL=Load3D.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
var be=Object.defineProperty;var r=(d,u)=>be(d,"name",{value:u,configurable:!0});import{a2 as F,dk as H,dl as L,r as O,o as Z,_ as K,h as q,c as x,d as o,l as C,j as y,k as D,e as n,s as G,z as N,a8 as e,v as X,E as T,q as $,F as ee,y as oe,A as ne,u as Y,I as z,T as ye,bV as E}from"./vendor-other-Dsj-QuOx.js";import{j as ie}from"./vendor-primevue-Cif--Rbw.js";import{_ as S,e as Q,t as A,c as J,d as se,cX as xe,u as we,cY as he,cZ as Me,r as Ce,c_ as $e,cD as De}from"./index-U7jagKl8.js";const Re={class:"relative show-slider"},Ie={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface p-4 shadow-lg w-[150px]"},re=F({__name:"PopupSlider",props:H({icon:{default:"pi-expand"},tooltipText:{},min:{default:10},max:{default:150},step:{default:1}},{modelValue:{},modelModifiers:{}}),emits:["update:modelValue"],setup(d){const u=L(d,"modelValue"),l=O(!1),t=r(()=>{l.value=!l.value},"toggleSlider"),i=r(a=>{a.target.closest(".show-slider")||(l.value=!1)},"closeSlider");return Z(()=>{document.addEventListener("click",i)}),K(()=>{document.removeEventListener("click",i)}),(a,p)=>{const k=q("tooltip");return o(),x("div",Re,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":a.tooltipText,onClick:t},{default:D(()=>[n("i",{class:G(["pi",a.icon,"text-lg text-base-foreground"])},null,2)]),_:1},8,["aria-label"])),[[k,{value:a.tooltipText,showDelay:300},void 0,{right:!0}]]),C(n("div",Ie,[N(e(ie),{modelValue:u.value,"onUpdate:modelValue":p[0]||(p[0]=v=>u.value=v),class:"w-full",min:a.min,max:a.max,step:a.step},null,8,["modelValue","min","max","step"])],512),[[X,l.value]])])}}}),Se={class:"flex flex-col"},Le=F({__name:"CameraControls",props:{cameraType:{},cameraTypeModifiers:{},fov:{},fovModifiers:{}},emits:["update:cameraType","update:fov"],setup(d){const u=L(d,"cameraType"),l=L(d,"fov"),t=T(()=>u.value==="perspective"),i=r(()=>{u.value=u.value==="perspective"?"orthographic":"perspective"},"switchCamera");return(a,p)=>{const k=q("tooltip");return o(),x("div",Se,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":a.$t("load3d.switchCamera"),onClick:i},{default:D(()=>p[1]||(p[1]=[n("i",{class:G(["pi","pi-camera","text-lg text-base-foreground"])},null,-1)])),_:1},8,["aria-label"])),[[k,{value:a.$t("load3d.switchCamera"),showDelay:300},void 0,{right:!0}]]),t.value?(o(),y(re,{key:0,modelValue:l.value,"onUpdate:modelValue":p[0]||(p[0]=v=>l.value=v),"tooltip-text":a.$t("load3d.fov")},null,8,["modelValue","tooltip-text"])):$("",!0)])}}}),Be={class:"flex flex-col"},Ue={class:"show-export-formats relative"},ze={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"},Ve={class:"flex flex-col"},Ee=F({__name:"ExportControls",emits:["exportModel"],setup(d,{emit:u}){const l=u,t=O(!1),i=[{label:"GLB",value:"glb"},{label:"OBJ",value:"obj"},{label:"STL",value:"stl"}];function a(){t.value=!t.value}r(a,"toggleExportFormats");function p(v){l("exportModel",v),t.value=!1}r(p,"exportModel");function k(v){v.target.closest(".show-export-formats")||(t.value=!1)}return r(k,"closeExportFormatsList"),Z(()=>{document.addEventListener("click",k)}),K(()=>{document.removeEventListener("click",k)}),(v,s)=>{const f=q("tooltip");return o(),x("div",Be,[n("div",Ue,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":v.$t("load3d.exportModel"),onClick:a},{default:D(()=>s[0]||(s[0]=[n("i",{class:"pi pi-download text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[f,{value:v.$t("load3d.exportModel"),showDelay:300},void 0,{right:!0}]]),C(n("div",ze,[n("div",Ve,[(o(),x(ee,null,oe(i,w=>N(S,{key:w.value,variant:"textonly",class:"text-base-foreground",onClick:r(V=>p(w.value),"onClick")},{default:D(()=>[ne(Y(w.label),1)]),_:2},1032,["onClick"])),64))])],512),[[X,t.value]])])])}}}),Pe={class:"flex flex-col"},Te={key:0,class:"show-light-intensity relative"},Ge={class:"absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg",style:{width:"150px"}},Fe=F({__name:"LightControls",props:{lightIntensity:{},lightIntensityModifiers:{},materialMode:{},materialModeModifiers:{}},emits:["update:lightIntensity","update:materialMode"],setup(d){const u=L(d,"lightIntensity"),l=L(d,"materialMode"),t=T(()=>l.value==="original"),i=O(!1),a=Q().get("Comfy.Load3D.LightIntensityMaximum"),p=Q().get("Comfy.Load3D.LightIntensityMinimum"),k=Q().get("Comfy.Load3D.LightAdjustmentIncrement");function v(){i.value=!i.value}r(v,"toggleLightIntensity");function s(f){f.target.closest(".show-light-intensity")||(i.value=!1)}return r(s,"closeLightSlider"),Z(()=>{document.addEventListener("click",s)}),K(()=>{document.removeEventListener("click",s)}),(f,w)=>{const V=q("tooltip");return o(),x("div",Pe,[t.value?(o(),x("div",Te,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":f.$t("load3d.lightIntensity"),onClick:v},{default:D(()=>w[1]||(w[1]=[n("i",{class:"pi pi-sun text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[V,{value:f.$t("load3d.lightIntensity"),showDelay:300},void 0,{right:!0}]]),C(n("div",Ge,[N(e(ie),{modelValue:u.value,"onUpdate:modelValue":w[0]||(w[0]=P=>u.value=P),class:"w-full",min:e(p),max:e(a),step:e(k)},null,8,["modelValue","min","max","step"])],512),[[X,i.value]])])):$("",!0)])}}}),je={class:"flex flex-col"},_e={class:"show-up-direction relative"},Oe={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"},Ae={class:"flex flex-col"},Ne={key:0,class:"show-material-mode relative"},We={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"},qe={class:"flex flex-col"},Je={key:1},Xe=F({__name:"ModelControls",props:H({hideMaterialMode:{type:Boolean,default:!1},isPlyModel:{type:Boolean,default:!1},hasSkeleton:{type:Boolean,default:!1}},{materialMode:{},materialModeModifiers:{},upDirection:{},upDirectionModifiers:{},showSkeleton:{type:Boolean},showSkeletonModifiers:{}}),emits:["update:materialMode","update:upDirection","update:showSkeleton"],setup(d){const u=L(d,"materialMode"),l=L(d,"upDirection"),t=L(d,"showSkeleton"),i=O(!1),a=O(!1),p=["original","-x","+x","-y","+y","-z","+z"],k=T(()=>{const R=["original","normal","wireframe"];return d.isPlyModel&&R.splice(1,0,"pointCloud"),R});function v(){i.value=!i.value,a.value=!1}r(v,"toggleUpDirection");function s(R){l.value=R,i.value=!1}r(s,"selectUpDirection");function f(){a.value=!a.value,i.value=!1}r(f,"toggleMaterialMode");function w(R){u.value=R,a.value=!1}r(w,"selectMaterialMode");function V(R){return A(`load3d.materialModes.${R}`)}r(V,"formatMaterialMode");function P(R){const I=R.target;I.closest(".show-up-direction")||(i.value=!1),I.closest(".show-material-mode")||(a.value=!1)}return r(P,"closeSceneSlider"),Z(()=>{document.addEventListener("click",P)}),K(()=>{document.removeEventListener("click",P)}),(R,I)=>{const j=q("tooltip");return o(),x("div",je,[n("div",_e,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":e(A)("load3d.upDirection"),onClick:v},{default:D(()=>I[1]||(I[1]=[n("i",{class:"pi pi-arrow-up text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[j,{value:e(A)("load3d.upDirection"),showDelay:300},void 0,{right:!0}]]),C(n("div",Oe,[n("div",Ae,[(o(),x(ee,null,oe(p,B=>N(S,{key:B,variant:"textonly",class:G(e(J)("text-base-foreground",l.value===B&&"bg-blue-500")),onClick:r(h=>s(B),"onClick")},{default:D(()=>[ne(Y(B.toUpperCase()),1)]),_:2},1032,["class","onClick"])),64))])],512),[[X,i.value]])]),R.hideMaterialMode?$("",!0):(o(),x("div",Ne,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":e(A)("load3d.materialMode"),onClick:f},{default:D(()=>I[2]||(I[2]=[n("i",{class:"pi pi-box text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[j,{value:e(A)("load3d.materialMode"),showDelay:300},void 0,{right:!0}]]),C(n("div",We,[n("div",qe,[(o(!0),x(ee,null,oe(k.value,B=>(o(),y(S,{key:B,variant:"textonly",class:G(e(J)("whitespace-nowrap text-base-foreground",u.value===B&&"bg-blue-500")),onClick:r(h=>w(B),"onClick")},{default:D(()=>[ne(Y(V(B)),1)]),_:2},1032,["class","onClick"]))),128))])],512),[[X,a.value]])])),R.hasSkeleton?(o(),x("div",Je,[C((o(),y(S,{size:"icon",variant:"textonly",class:G(e(J)("rounded-full",t.value&&"bg-blue-500")),"aria-label":e(A)("load3d.showSkeleton"),onClick:I[0]||(I[0]=B=>t.value=!t.value)},{default:D(()=>I[3]||(I[3]=[n("i",{class:"pi pi-sitemap text-lg text-base-foreground"},null,-1)])),_:1},8,["class","aria-label"])),[[j,{value:e(A)("load3d.showSkeleton"),showDelay:300},void 0,{right:!0}]])])):$("",!0)])}}}),Ye={class:"flex flex-col"},Ze={key:0},He=["value"],Ke={key:1},Qe={key:2},eo={key:4},oo=F({__name:"SceneControls",props:{showGrid:{type:Boolean},showGridModifiers:{},backgroundColor:{},backgroundColorModifiers:{},backgroundImage:{},backgroundImageModifiers:{},backgroundRenderMode:{default:"tiled"},backgroundRenderModeModifiers:{},fov:{},fovModifiers:{}},emits:H(["updateBackgroundImage"],["update:showGrid","update:backgroundColor","update:backgroundImage","update:backgroundRenderMode","update:fov"]),setup(d,{emit:u}){const l=u,t=L(d,"showGrid"),i=L(d,"backgroundColor"),a=L(d,"backgroundImage"),p=L(d,"backgroundRenderMode"),k=L(d,"fov"),v=T(()=>a.value&&a.value!==""),s=O(null),f=O(null),w=r(()=>{t.value=!t.value},"toggleGrid"),V=r(h=>{i.value=h},"updateBackgroundColor"),P=r(()=>{s.value?.click()},"openColorPicker"),R=r(()=>{f.value?.click()},"openImagePicker"),I=r(h=>{const M=h.target;M.files&&M.files[0]&&l("updateBackgroundImage",M.files[0])},"uploadBackgroundImage"),j=r(()=>{l("updateBackgroundImage",null)},"removeBackgroundImage"),B=r(()=>{p.value=p.value==="panorama"?"tiled":"panorama"},"toggleBackgroundRenderMode");return(h,M)=>{const _=q("tooltip");return o(),x("div",Ye,[C((o(),y(S,{variant:"textonly",size:"icon",class:G(e(J)("rounded-full",t.value&&"ring-2 ring-white/50")),"aria-label":h.$t("load3d.showGrid"),onClick:w},{default:D(()=>M[2]||(M[2]=[n("i",{class:"pi pi-table text-lg text-base-foreground"},null,-1)])),_:1},8,["class","aria-label"])),[[_,{value:h.$t("load3d.showGrid"),showDelay:300},void 0,{right:!0}]]),v.value?$("",!0):(o(),x("div",Ze,[C((o(),y(S,{variant:"textonly",size:"icon",class:"rounded-full","aria-label":h.$t("load3d.backgroundColor"),onClick:P},{default:D(()=>[M[3]||(M[3]=n("i",{class:"pi pi-palette text-lg text-base-foreground"},null,-1)),n("input",{ref_key:"colorPickerRef",ref:s,type:"color",value:i.value,class:"pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0",onInput:M[0]||(M[0]=W=>V(W.target.value))},null,40,He)]),_:1},8,["aria-label"])),[[_,{value:h.$t("load3d.backgroundColor"),showDelay:300},void 0,{right:!0}]])])),v.value?$("",!0):(o(),x("div",Ke,[C((o(),y(S,{variant:"textonly",size:"icon",class:"rounded-full","aria-label":h.$t("load3d.uploadBackgroundImage"),onClick:R},{default:D(()=>[M[4]||(M[4]=n("i",{class:"pi pi-image text-lg text-base-foreground"},null,-1)),n("input",{ref_key:"imagePickerRef",ref:f,type:"file",accept:"image/*",class:"pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0",onChange:I},null,544)]),_:1},8,["aria-label"])),[[_,{value:h.$t("load3d.uploadBackgroundImage"),showDelay:300},void 0,{right:!0}]])])),v.value?(o(),x("div",Qe,[C((o(),y(S,{variant:"textonly",size:"icon",class:G(e(J)("rounded-full",p.value==="panorama"&&"ring-2 ring-white/50")),"aria-label":h.$t("load3d.panoramaMode"),onClick:B},{default:D(()=>M[5]||(M[5]=[n("i",{class:"pi pi-globe text-lg text-base-foreground"},null,-1)])),_:1},8,["class","aria-label"])),[[_,{value:h.$t("load3d.panoramaMode"),showDelay:300},void 0,{right:!0}]])])):$("",!0),v.value&&p.value==="panorama"?(o(),y(re,{key:3,modelValue:k.value,"onUpdate:modelValue":M[1]||(M[1]=W=>k.value=W),"tooltip-text":h.$t("load3d.fov")},null,8,["modelValue","tooltip-text"])):$("",!0),v.value?(o(),x("div",eo,[C((o(),y(S,{variant:"textonly",size:"icon",class:"rounded-full","aria-label":h.$t("load3d.removeBackgroundImage"),onClick:j},{default:D(()=>M[6]||(M[6]=[n("i",{class:"pi pi-times text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[_,{value:h.$t("load3d.removeBackgroundImage"),showDelay:300},void 0,{right:!0}]])])):$("",!0)])}}}),to={class:"show-menu relative"},lo={class:"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg"},ao={class:"flex flex-col"},no={class:"whitespace-nowrap text-base-foreground"},io={class:"rounded-lg bg-smoke-700/30"},so=F({__name:"Load3DControls",props:H({isSplatModel:{type:Boolean,default:!1},isPlyModel:{type:Boolean,default:!1},hasSkeleton:{type:Boolean,default:!1}},{sceneConfig:{},sceneConfigModifiers:{},modelConfig:{},modelConfigModifiers:{},cameraConfig:{},cameraConfigModifiers:{},lightConfig:{},lightConfigModifiers:{}}),emits:H(["updateBackgroundImage","exportModel"],["update:sceneConfig","update:modelConfig","update:cameraConfig","update:lightConfig"]),setup(d,{emit:u}){const l=L(d,"sceneConfig"),t=L(d,"modelConfig"),i=L(d,"cameraConfig"),a=L(d,"lightConfig"),p=O(!1),k=O("scene"),v={scene:"load3d.scene",model:"load3d.model",camera:"load3d.camera",light:"load3d.light",export:"load3d.export"},s=T(()=>d.isSplatModel?["scene","model","camera"]:["scene","model","camera","light","export"]),f=T(()=>k.value==="scene"&&!!l.value),w=T(()=>k.value==="model"&&!!t.value),V=T(()=>k.value==="camera"&&!!i.value),P=T(()=>k.value==="light"&&!!a.value&&!!t.value),R=T(()=>k.value==="export"),I=r(()=>{p.value=!p.value},"toggleMenu"),j=r(U=>{k.value=U,p.value=!1},"selectCategory"),B=r(U=>`${{scene:"pi pi-image",model:"pi pi-box",camera:"pi pi-camera",light:"pi pi-sun",export:"pi pi-download"}[U]} text-base-foreground text-lg`,"getCategoryIcon"),h=u,M=r(U=>{h("updateBackgroundImage",U)},"handleBackgroundImageUpdate"),_=r(U=>{h("exportModel",U)},"handleExportModel"),W=r(U=>{U.target.closest(".show-menu")||(p.value=!1)},"closeSlider");return Z(()=>{document.addEventListener("click",W)}),K(()=>{document.removeEventListener("click",W)}),(U,g)=>(o(),x("div",{class:"pointer-events-auto absolute top-12 left-2 z-20 flex flex-col rounded-lg bg-backdrop/30",onPointerdown:g[12]||(g[12]=z(()=>{},["stop"])),onPointermove:g[13]||(g[13]=z(()=>{},["stop"])),onPointerup:g[14]||(g[14]=z(()=>{},["stop"])),onWheel:g[15]||(g[15]=z(()=>{},["stop"]))},[n("div",to,[N(S,{variant:"textonly",size:"icon","aria-label":U.$t("menu.showMenu"),class:"rounded-full",onClick:I},{default:D(()=>g[16]||(g[16]=[n("i",{class:"pi pi-bars text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"]),C(n("div",lo,[n("div",ao,[(o(!0),x(ee,null,oe(s.value,m=>(o(),y(S,{key:m,variant:"textonly",class:G(e(J)("flex w-full items-center justify-start",k.value===m&&"bg-button-active-surface")),onClick:r(te=>j(m),"onClick")},{default:D(()=>[n("i",{class:G(B(m))},null,2),n("span",no,Y(U.$t(v[m])),1)]),_:2},1032,["class","onClick"]))),128))])],512),[[X,p.value]])]),C(n("div",io,[f.value?(o(),y(oo,{key:0,"show-grid":l.value.showGrid,"onUpdate:showGrid":g[0]||(g[0]=m=>l.value.showGrid=m),"background-color":l.value.backgroundColor,"onUpdate:backgroundColor":g[1]||(g[1]=m=>l.value.backgroundColor=m),"background-image":l.value.backgroundImage,"onUpdate:backgroundImage":g[2]||(g[2]=m=>l.value.backgroundImage=m),"background-render-mode":l.value.backgroundRenderMode,"onUpdate:backgroundRenderMode":g[3]||(g[3]=m=>l.value.backgroundRenderMode=m),fov:i.value.fov,"onUpdate:fov":g[4]||(g[4]=m=>i.value.fov=m),onUpdateBackgroundImage:M},null,8,["show-grid","background-color","background-image","background-render-mode","fov"])):$("",!0),w.value?(o(),y(Xe,{key:1,"material-mode":t.value.materialMode,"onUpdate:materialMode":g[5]||(g[5]=m=>t.value.materialMode=m),"up-direction":t.value.upDirection,"onUpdate:upDirection":g[6]||(g[6]=m=>t.value.upDirection=m),"show-skeleton":t.value.showSkeleton,"onUpdate:showSkeleton":g[7]||(g[7]=m=>t.value.showSkeleton=m),"hide-material-mode":U.isSplatModel,"is-ply-model":U.isPlyModel,"has-skeleton":U.hasSkeleton},null,8,["material-mode","up-direction","show-skeleton","hide-material-mode","is-ply-model","has-skeleton"])):$("",!0),V.value?(o(),y(Le,{key:2,"camera-type":i.value.cameraType,"onUpdate:cameraType":g[8]||(g[8]=m=>i.value.cameraType=m),fov:i.value.fov,"onUpdate:fov":g[9]||(g[9]=m=>i.value.fov=m)},null,8,["camera-type","fov"])):$("",!0),P.value?(o(),y(Fe,{key:3,"light-intensity":a.value.intensity,"onUpdate:lightIntensity":g[10]||(g[10]=m=>a.value.intensity=m),"material-mode":t.value.materialMode,"onUpdate:materialMode":g[11]||(g[11]=m=>t.value.materialMode=m)},null,8,["light-intensity","material-mode"])):$("",!0),R.value?(o(),y(Ee,{key:4,onExportModel:_})):$("",!0)],512),[[X,k.value]])],32))}}),ro={key:0,class:"absolute inset-0 z-50 flex items-center justify-center bg-backdrop/50"},uo={class:"flex flex-col items-center"},go={class:"mt-4 text-lg text-base-foreground"},co=F({__name:"LoadingOverlay",props:{loading:{type:Boolean},loadingMessage:{}},setup(d){return(u,l)=>(o(),y(ye,{name:"fade"},{default:D(()=>[u.loading?(o(),x("div",ro,[n("div",uo,[l[0]||(l[0]=n("div",{class:"spinner"},null,-1)),n("div",go,Y(u.loadingMessage),1)])])):$("",!0)]),_:1}))}}),po=se(co,[["__scopeId","data-v-c31c7285"]]),vo={key:0,class:"pointer-events-none absolute inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm"},fo={class:"rounded-lg border-2 border-dashed border-blue-400 bg-blue-500/20 px-6 py-4 text-lg font-medium text-blue-100"},mo=F({__name:"Load3DScene",props:{initializeLoad3d:{type:Function},cleanup:{type:Function},loading:{type:Boolean},loadingMessage:{},onModelDrop:{type:Function},isPreview:{type:Boolean}},setup(d){const u=d,l=O(null),{isDragging:t,dragMessage:i,handleDragOver:a,handleDragLeave:p,handleDrop:k}=xe({onModelDrop:r(async v=>{u.onModelDrop&&await u.onModelDrop(v)},"onModelDrop"),disabled:T(()=>u.isPreview)});return Z(()=>{l.value&&u.initializeLoad3d(l.value)}),K(()=>{u.cleanup()}),(v,s)=>(o(),x("div",{ref_key:"container",ref:l,class:"relative h-full w-full min-h-[200px]","data-capture-wheel":"true",onPointerdown:s[0]||(s[0]=z(()=>{},["stop"])),onPointermove:s[1]||(s[1]=z(()=>{},["stop"])),onPointerup:s[2]||(s[2]=z(()=>{},["stop"])),onMousedown:s[3]||(s[3]=z(()=>{},["stop"])),onMousemove:s[4]||(s[4]=z(()=>{},["stop"])),onMouseup:s[5]||(s[5]=z(()=>{},["stop"])),onContextmenu:s[6]||(s[6]=z(()=>{},["stop","prevent"])),onDragover:s[7]||(s[7]=z((...f)=>e(a)&&e(a)(...f),["prevent","stop"])),onDragleave:s[8]||(s[8]=z((...f)=>e(p)&&e(p)(...f),["stop"])),onDrop:s[9]||(s[9]=z((...f)=>e(k)&&e(k)(...f),["prevent","stop"]))},[N(po,{loading:v.loading,"loading-message":v.loadingMessage},null,8,["loading","loading-message"]),!v.isPreview&&e(t)?(o(),x("div",vo,[n("div",fo,Y(e(i)),1)])):$("",!0)],544))}}),ko={class:"relative rounded-lg bg-backdrop/30"},bo={class:"flex flex-col gap-2"},yo={key:2,class:"mt-1 text-center text-xs text-base-foreground"},xo=F({__name:"RecordingControls",props:{hasRecording:{type:Boolean},hasRecordingModifiers:{},isRecording:{type:Boolean},isRecordingModifiers:{},recordingDuration:{},recordingDurationModifiers:{}},emits:H(["startRecording","stopRecording","exportRecording","clearRecording"],["update:hasRecording","update:isRecording","update:recordingDuration"]),setup(d,{emit:u}){const l=L(d,"hasRecording"),t=L(d,"isRecording"),i=L(d,"recordingDuration"),a=u;function p(){t.value?a("stopRecording"):a("startRecording")}r(p,"toggleRecording");function k(){a("exportRecording")}r(k,"handleExportRecording");function v(){a("clearRecording")}r(v,"handleClearRecording");function s(f){const w=Math.floor(f/60),V=Math.floor(f%60);return`${w.toString().padStart(2,"0")}:${V.toString().padStart(2,"0")}`}return r(s,"formatDuration"),(f,w)=>{const V=q("tooltip");return o(),x("div",ko,[n("div",bo,[C((o(),y(S,{size:"icon",variant:"textonly",class:G(e(J)("rounded-full",t.value&&"text-red-500 recording-button-blink")),"aria-label":t.value?f.$t("load3d.stopRecording"):f.$t("load3d.startRecording"),onClick:p},{default:D(()=>[n("i",{class:G(["pi",t.value?"pi-circle-fill":"pi-video","text-lg text-base-foreground"])},null,2)]),_:1},8,["class","aria-label"])),[[V,{value:t.value?f.$t("load3d.stopRecording"):f.$t("load3d.startRecording"),showDelay:300},void 0,{right:!0}]]),l.value&&!t.value?C((o(),y(S,{key:0,size:"icon",variant:"textonly",class:"rounded-full","aria-label":f.$t("load3d.exportRecording"),onClick:k},{default:D(()=>w[0]||(w[0]=[n("i",{class:"pi pi-download text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[V,{value:f.$t("load3d.exportRecording"),showDelay:300},void 0,{right:!0}]]):$("",!0),l.value&&!t.value?C((o(),y(S,{key:1,size:"icon",variant:"textonly",class:"rounded-full","aria-label":f.$t("load3d.clearRecording"),onClick:v},{default:D(()=>w[1]||(w[1]=[n("i",{class:"pi pi-trash text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[V,{value:f.$t("load3d.clearRecording"),showDelay:300},void 0,{right:!0}]]):$("",!0),i.value&&i.value>0&&!t.value?(o(),x("div",yo,Y(s(i.value)),1)):$("",!0)])])}}}),wo=se(xo,[["__scopeId","data-v-24c77a32"]]),ho={class:"relative rounded-lg bg-backdrop/30"},Mo={class:"flex flex-col gap-2"},Co=F({__name:"ViewerControls",props:{node:{}},setup(d){const u=r(()=>{const l={node:d.node};we().showDialog({key:"global-load3d-viewer",title:A("load3d.viewer.title"),component:he,props:l,dialogComponentProps:{style:"width: 80vw; height: 80vh;",maximizable:!0,onClose:r(async()=>{await Me().handleViewerClose(l.node)},"onClose")}})},"openIn3DViewer");return(l,t)=>{const i=q("tooltip");return o(),x("div",ho,[n("div",Mo,[C((o(),y(S,{size:"icon",variant:"textonly",class:"rounded-full","aria-label":e(A)("load3d.openIn3DViewer"),onClick:u},{default:D(()=>t[0]||(t[0]=[n("i",{class:"pi pi-expand text-lg text-base-foreground"},null,-1)])),_:1},8,["aria-label"])),[[i,{value:e(A)("load3d.openIn3DViewer"),showDelay:300},void 0,{right:!0}]])])])}}}),$o={class:"pointer-events-none absolute top-0 left-0 size-full"},Do={key:1,class:"pointer-events-auto absolute top-12 right-2 z-20"},Bo=F({__name:"Load3D",props:{widget:{},nodeId:{}},setup(d){const u=d;function l(ae){return"node"in ae&&ae.node!==void 0}r(l,"isComponentWidget");const t=O(null);l(u.widget)?t.value=u.widget.node:u.nodeId&&Z(()=>{t.value=Ce.rootGraph?.getNodeById(u.nodeId)||null});const{sceneConfig:i,modelConfig:a,cameraConfig:p,lightConfig:k,isRecording:v,isPreview:s,isSplatModel:f,isPlyModel:w,hasSkeleton:V,hasRecording:P,recordingDuration:R,animations:I,playing:j,selectedSpeed:B,selectedAnimation:h,animationProgress:M,animationDuration:_,loading:W,loadingMessage:U,initializeLoad3d:g,handleMouseEnter:m,handleMouseLeave:te,handleStartRecording:de,handleStopRecording:ue,handleExportRecording:ge,handleClearRecording:ce,handleSeek:pe,handleBackgroundImageUpdate:ve,handleExportModel:fe,handleModelDrop:me,cleanup:ke}=$e(t),le=T(()=>Q().get("Comfy.Load3D.3DViewerEnable"));return(ae,c)=>(o(),x("div",{class:"relative size-full",onMouseenter:c[13]||(c[13]=(...b)=>e(m)&&e(m)(...b)),onMouseleave:c[14]||(c[14]=(...b)=>e(te)&&e(te)(...b)),onPointerdown:c[15]||(c[15]=z(()=>{},["stop"])),onPointermove:c[16]||(c[16]=z(()=>{},["stop"])),onPointerup:c[17]||(c[17]=z(()=>{},["stop"]))},[t.value?(o(),y(mo,{key:0,"initialize-load3d":e(g),cleanup:e(ke),loading:e(W),"loading-message":e(U),"on-model-drop":e(s)?void 0:e(me),"is-preview":e(s)},null,8,["initialize-load3d","cleanup","loading","loading-message","on-model-drop","is-preview"])):$("",!0),n("div",$o,[N(so,{"scene-config":e(i),"onUpdate:sceneConfig":c[0]||(c[0]=b=>E(i)?i.value=b:null),"model-config":e(a),"onUpdate:modelConfig":c[1]||(c[1]=b=>E(a)?a.value=b:null),"camera-config":e(p),"onUpdate:cameraConfig":c[2]||(c[2]=b=>E(p)?p.value=b:null),"light-config":e(k),"onUpdate:lightConfig":c[3]||(c[3]=b=>E(k)?k.value=b:null),"is-splat-model":e(f),"is-ply-model":e(w),"has-skeleton":e(V),onUpdateBackgroundImage:e(ve),onExportModel:e(fe)},null,8,["scene-config","model-config","camera-config","light-config","is-splat-model","is-ply-model","has-skeleton","onUpdateBackgroundImage","onExportModel"]),e(I)&&e(I).length>0?(o(),y(De,{key:0,animations:e(I),"onUpdate:animations":c[4]||(c[4]=b=>E(I)?I.value=b:null),playing:e(j),"onUpdate:playing":c[5]||(c[5]=b=>E(j)?j.value=b:null),"selected-speed":e(B),"onUpdate:selectedSpeed":c[6]||(c[6]=b=>E(B)?B.value=b:null),"selected-animation":e(h),"onUpdate:selectedAnimation":c[7]||(c[7]=b=>E(h)?h.value=b:null),"animation-progress":e(M),"onUpdate:animationProgress":c[8]||(c[8]=b=>E(M)?M.value=b:null),"animation-duration":e(_),"onUpdate:animationDuration":c[9]||(c[9]=b=>E(_)?_.value=b:null),onSeek:e(pe)},null,8,["animations","playing","selected-speed","selected-animation","animation-progress","animation-duration","onSeek"])):$("",!0)]),le.value&&t.value?(o(),x("div",Do,[N(Co,{node:t.value},null,8,["node"])])):$("",!0),e(s)?$("",!0):(o(),x("div",{key:2,class:G(["pointer-events-auto absolute right-2 z-20",{"top-12":!le.value,"top-24":le.value}])},[N(wo,{"is-recording":e(v),"onUpdate:isRecording":c[10]||(c[10]=b=>E(v)?v.value=b:null),"has-recording":e(P),"onUpdate:hasRecording":c[11]||(c[11]=b=>E(P)?P.value=b:null),"recording-duration":e(R),"onUpdate:recordingDuration":c[12]||(c[12]=b=>E(R)?R.value=b:null),onStartRecording:e(de),onStopRecording:e(ue),onExportRecording:e(ge),onClearRecording:e(ce)},null,8,["is-recording","has-recording","recording-duration","onStartRecording","onStopRecording","onExportRecording","onClearRecording"])],2))],32))}});export{Bo as _};
|
|
2
|
+
//# sourceMappingURL=Load3D.vue_vue_type_script_setup_true_lang-KEzORqB0.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Load3D.vue_vue_type_script_setup_true_lang-BLcsvL5E.js","sources":["../../src/components/load3d/controls/PopupSlider.vue","../../src/components/load3d/controls/CameraControls.vue","../../src/components/load3d/controls/ExportControls.vue","../../src/components/load3d/controls/LightControls.vue","../../src/components/load3d/controls/ModelControls.vue","../../src/components/load3d/controls/SceneControls.vue","../../src/components/load3d/Load3DControls.vue","../../src/components/load3d/Load3DScene.vue","../../src/components/load3d/controls/RecordingControls.vue","../../src/components/load3d/controls/ViewerControls.vue","../../src/components/load3d/Load3D.vue"],"sourcesContent":["<template>\n <div class=\"relative show-slider\">\n <Button\n v-tooltip.right=\"{ value: tooltipText, showDelay: 300 }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"tooltipText\"\n @click=\"toggleSlider\"\n >\n <i :class=\"['pi', icon, 'text-lg text-base-foreground']\" />\n </Button>\n <div\n v-show=\"showSlider\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface p-4 shadow-lg w-[150px]\"\n >\n <Slider\n v-model=\"value\"\n class=\"w-full\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Slider from 'primevue/slider'\nimport { onMounted, onUnmounted, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\n\nconst {\n icon = 'pi-expand',\n min = 10,\n max = 150,\n step = 1\n} = defineProps<{\n icon?: string\n tooltipText: string\n min?: number\n max?: number\n step?: number\n}>()\n\nconst value = defineModel<number>()\nconst showSlider = ref(false)\n\nconst toggleSlider = () => {\n showSlider.value = !showSlider.value\n}\n\nconst closeSlider = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-slider')) {\n showSlider.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeSlider)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeSlider)\n})\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.switchCamera'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.switchCamera')\"\n @click=\"switchCamera\"\n >\n <i :class=\"['pi', 'pi-camera', 'text-lg text-base-foreground']\" />\n </Button>\n <PopupSlider\n v-if=\"showFOVButton\"\n v-model=\"fov\"\n :tooltip-text=\"$t('load3d.fov')\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport PopupSlider from '@/components/load3d/controls/PopupSlider.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport type { CameraType } from '@/extensions/core/load3d/interfaces'\n\nconst cameraType = defineModel<CameraType>('cameraType')\nconst fov = defineModel<number>('fov')\nconst showFOVButton = computed(() => cameraType.value === 'perspective')\n\nconst switchCamera = () => {\n cameraType.value =\n cameraType.value === 'perspective' ? 'orthographic' : 'perspective'\n}\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <div class=\"show-export-formats relative\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.exportModel'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.exportModel')\"\n @click=\"toggleExportFormats\"\n >\n <i class=\"pi pi-download text-lg text-base-foreground\" />\n </Button>\n <div\n v-show=\"showExportFormats\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg\"\n >\n <div class=\"flex flex-col\">\n <Button\n v-for=\"format in exportFormats\"\n :key=\"format.value\"\n variant=\"textonly\"\n class=\"text-base-foreground\"\n @click=\"exportModel(format.value)\"\n >\n {{ format.label }}\n </Button>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, onUnmounted, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\n\nconst emit = defineEmits<{\n (e: 'exportModel', format: string): void\n}>()\n\nconst showExportFormats = ref(false)\n\nconst exportFormats = [\n { label: 'GLB', value: 'glb' },\n { label: 'OBJ', value: 'obj' },\n { label: 'STL', value: 'stl' }\n]\n\nfunction toggleExportFormats() {\n showExportFormats.value = !showExportFormats.value\n}\n\nfunction exportModel(format: string) {\n emit('exportModel', format)\n\n showExportFormats.value = false\n}\n\nfunction closeExportFormatsList(e: MouseEvent) {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-export-formats')) {\n showExportFormats.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeExportFormatsList)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeExportFormatsList)\n})\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <div v-if=\"showLightIntensityButton\" class=\"show-light-intensity relative\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.lightIntensity'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.lightIntensity')\"\n @click=\"toggleLightIntensity\"\n >\n <i class=\"pi pi-sun text-lg text-base-foreground\" />\n </Button>\n <div\n v-show=\"showLightIntensity\"\n class=\"absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg\"\n style=\"width: 150px\"\n >\n <Slider\n v-model=\"lightIntensity\"\n class=\"w-full\"\n :min=\"lightIntensityMinimum\"\n :max=\"lightIntensityMaximum\"\n :step=\"lightAdjustmentIncrement\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Slider from 'primevue/slider'\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport type { MaterialMode } from '@/extensions/core/load3d/interfaces'\nimport { useSettingStore } from '@/platform/settings/settingStore'\n\nconst lightIntensity = defineModel<number>('lightIntensity')\nconst materialMode = defineModel<MaterialMode>('materialMode')\n\nconst showLightIntensityButton = computed(\n () => materialMode.value === 'original'\n)\nconst showLightIntensity = ref(false)\n\nconst lightIntensityMaximum = useSettingStore().get(\n 'Comfy.Load3D.LightIntensityMaximum'\n)\nconst lightIntensityMinimum = useSettingStore().get(\n 'Comfy.Load3D.LightIntensityMinimum'\n)\nconst lightAdjustmentIncrement = useSettingStore().get(\n 'Comfy.Load3D.LightAdjustmentIncrement'\n)\n\nfunction toggleLightIntensity() {\n showLightIntensity.value = !showLightIntensity.value\n}\n\nfunction closeLightSlider(e: MouseEvent) {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-light-intensity')) {\n showLightIntensity.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeLightSlider)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeLightSlider)\n})\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <div class=\"show-up-direction relative\">\n <Button\n v-tooltip.right=\"{\n value: t('load3d.upDirection'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"t('load3d.upDirection')\"\n @click=\"toggleUpDirection\"\n >\n <i class=\"pi pi-arrow-up text-lg text-base-foreground\" />\n </Button>\n <div\n v-show=\"showUpDirection\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg\"\n >\n <div class=\"flex flex-col\">\n <Button\n v-for=\"direction in upDirections\"\n :key=\"direction\"\n variant=\"textonly\"\n :class=\"\n cn(\n 'text-base-foreground',\n upDirection === direction && 'bg-blue-500'\n )\n \"\n @click=\"selectUpDirection(direction)\"\n >\n {{ direction.toUpperCase() }}\n </Button>\n </div>\n </div>\n </div>\n\n <div v-if=\"!hideMaterialMode\" class=\"show-material-mode relative\">\n <Button\n v-tooltip.right=\"{\n value: t('load3d.materialMode'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"t('load3d.materialMode')\"\n @click=\"toggleMaterialMode\"\n >\n <i class=\"pi pi-box text-lg text-base-foreground\" />\n </Button>\n <div\n v-show=\"showMaterialMode\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg\"\n >\n <div class=\"flex flex-col\">\n <Button\n v-for=\"mode in materialModes\"\n :key=\"mode\"\n variant=\"textonly\"\n :class=\"\n cn(\n 'whitespace-nowrap text-base-foreground',\n materialMode === mode && 'bg-blue-500'\n )\n \"\n @click=\"selectMaterialMode(mode)\"\n >\n {{ formatMaterialMode(mode) }}\n </Button>\n </div>\n </div>\n </div>\n\n <div v-if=\"hasSkeleton\">\n <Button\n v-tooltip.right=\"{\n value: t('load3d.showSkeleton'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n :class=\"cn('rounded-full', showSkeleton && 'bg-blue-500')\"\n :aria-label=\"t('load3d.showSkeleton')\"\n @click=\"showSkeleton = !showSkeleton\"\n >\n <i class=\"pi pi-sitemap text-lg text-base-foreground\" />\n </Button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport type {\n MaterialMode,\n UpDirection\n} from '@/extensions/core/load3d/interfaces'\nimport { t } from '@/i18n'\nimport { cn } from '@/utils/tailwindUtil'\n\nconst {\n hideMaterialMode = false,\n isPlyModel = false,\n hasSkeleton = false\n} = defineProps<{\n hideMaterialMode?: boolean\n isPlyModel?: boolean\n hasSkeleton?: boolean\n}>()\n\nconst materialMode = defineModel<MaterialMode>('materialMode')\nconst upDirection = defineModel<UpDirection>('upDirection')\nconst showSkeleton = defineModel<boolean>('showSkeleton')\n\nconst showUpDirection = ref(false)\nconst showMaterialMode = ref(false)\n\nconst upDirections: UpDirection[] = [\n 'original',\n '-x',\n '+x',\n '-y',\n '+y',\n '-z',\n '+z'\n]\n\nconst materialModes = computed(() => {\n const modes: MaterialMode[] = [\n 'original',\n 'normal',\n 'wireframe'\n //'depth' disable for now\n ]\n\n // Only show pointCloud mode for PLY files (point cloud rendering)\n if (isPlyModel) {\n modes.splice(1, 0, 'pointCloud')\n }\n\n return modes\n})\n\nfunction toggleUpDirection() {\n showUpDirection.value = !showUpDirection.value\n showMaterialMode.value = false\n}\n\nfunction selectUpDirection(direction: UpDirection) {\n upDirection.value = direction\n showUpDirection.value = false\n}\n\nfunction toggleMaterialMode() {\n showMaterialMode.value = !showMaterialMode.value\n showUpDirection.value = false\n}\n\nfunction selectMaterialMode(mode: MaterialMode) {\n materialMode.value = mode\n showMaterialMode.value = false\n}\n\nfunction formatMaterialMode(mode: MaterialMode) {\n return t(`load3d.materialModes.${mode}`)\n}\n\nfunction closeSceneSlider(e: MouseEvent) {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-up-direction')) {\n showUpDirection.value = false\n }\n\n if (!target.closest('.show-material-mode')) {\n showMaterialMode.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeSceneSlider)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeSceneSlider)\n})\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <Button\n v-tooltip.right=\"{ value: $t('load3d.showGrid'), showDelay: 300 }\"\n variant=\"textonly\"\n size=\"icon\"\n :class=\"cn('rounded-full', showGrid && 'ring-2 ring-white/50')\"\n :aria-label=\"$t('load3d.showGrid')\"\n @click=\"toggleGrid\"\n >\n <i class=\"pi pi-table text-lg text-base-foreground\" />\n </Button>\n\n <div v-if=\"!hasBackgroundImage\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.backgroundColor'),\n showDelay: 300\n }\"\n variant=\"textonly\"\n size=\"icon\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.backgroundColor')\"\n @click=\"openColorPicker\"\n >\n <i class=\"pi pi-palette text-lg text-base-foreground\" />\n <input\n ref=\"colorPickerRef\"\n type=\"color\"\n :value=\"backgroundColor\"\n class=\"pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0\"\n @input=\"\n updateBackgroundColor(($event.target as HTMLInputElement).value)\n \"\n />\n </Button>\n </div>\n\n <div v-if=\"!hasBackgroundImage\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.uploadBackgroundImage'),\n showDelay: 300\n }\"\n variant=\"textonly\"\n size=\"icon\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.uploadBackgroundImage')\"\n @click=\"openImagePicker\"\n >\n <i class=\"pi pi-image text-lg text-base-foreground\" />\n <input\n ref=\"imagePickerRef\"\n type=\"file\"\n accept=\"image/*\"\n class=\"pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0\"\n @change=\"uploadBackgroundImage\"\n />\n </Button>\n </div>\n\n <div v-if=\"hasBackgroundImage\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.panoramaMode'),\n showDelay: 300\n }\"\n variant=\"textonly\"\n size=\"icon\"\n :class=\"\n cn(\n 'rounded-full',\n backgroundRenderMode === 'panorama' && 'ring-2 ring-white/50'\n )\n \"\n :aria-label=\"$t('load3d.panoramaMode')\"\n @click=\"toggleBackgroundRenderMode\"\n >\n <i class=\"pi pi-globe text-lg text-base-foreground\" />\n </Button>\n </div>\n\n <PopupSlider\n v-if=\"hasBackgroundImage && backgroundRenderMode === 'panorama'\"\n v-model=\"fov\"\n :tooltip-text=\"$t('load3d.fov')\"\n />\n\n <div v-if=\"hasBackgroundImage\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.removeBackgroundImage'),\n showDelay: 300\n }\"\n variant=\"textonly\"\n size=\"icon\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.removeBackgroundImage')\"\n @click=\"removeBackgroundImage\"\n >\n <i class=\"pi pi-times text-lg text-base-foreground\" />\n </Button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\n\nimport PopupSlider from '@/components/load3d/controls/PopupSlider.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport type { BackgroundRenderModeType } from '@/extensions/core/load3d/interfaces'\nimport { cn } from '@/utils/tailwindUtil'\n\nconst emit = defineEmits<{\n (e: 'updateBackgroundImage', file: File | null): void\n}>()\n\nconst showGrid = defineModel<boolean>('showGrid')\nconst backgroundColor = defineModel<string>('backgroundColor')\nconst backgroundImage = defineModel<string>('backgroundImage')\nconst backgroundRenderMode = defineModel<BackgroundRenderModeType>(\n 'backgroundRenderMode',\n { default: 'tiled' }\n)\nconst fov = defineModel<number>('fov')\nconst hasBackgroundImage = computed(\n () => backgroundImage.value && backgroundImage.value !== ''\n)\n\nconst colorPickerRef = ref<HTMLInputElement | null>(null)\nconst imagePickerRef = ref<HTMLInputElement | null>(null)\n\nconst toggleGrid = () => {\n showGrid.value = !showGrid.value\n}\n\nconst updateBackgroundColor = (color: string) => {\n backgroundColor.value = color\n}\n\nconst openColorPicker = () => {\n colorPickerRef.value?.click()\n}\n\nconst openImagePicker = () => {\n imagePickerRef.value?.click()\n}\n\nconst uploadBackgroundImage = (event: Event) => {\n const input = event.target as HTMLInputElement\n\n if (input.files && input.files[0]) {\n emit('updateBackgroundImage', input.files[0])\n }\n}\n\nconst removeBackgroundImage = () => {\n emit('updateBackgroundImage', null)\n}\n\nconst toggleBackgroundRenderMode = () => {\n backgroundRenderMode.value =\n backgroundRenderMode.value === 'panorama' ? 'tiled' : 'panorama'\n}\n</script>\n","<template>\n <div\n class=\"pointer-events-auto absolute top-12 left-2 z-20 flex flex-col rounded-lg bg-backdrop/30\"\n @pointerdown.stop\n @pointermove.stop\n @pointerup.stop\n @wheel.stop\n >\n <div class=\"show-menu relative\">\n <Button\n variant=\"textonly\"\n size=\"icon\"\n :aria-label=\"$t('menu.showMenu')\"\n class=\"rounded-full\"\n @click=\"toggleMenu\"\n >\n <i class=\"pi pi-bars text-lg text-base-foreground\" />\n </Button>\n\n <div\n v-show=\"isMenuOpen\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg\"\n >\n <div class=\"flex flex-col\">\n <Button\n v-for=\"category in availableCategories\"\n :key=\"category\"\n variant=\"textonly\"\n :class=\"\n cn(\n 'flex w-full items-center justify-start',\n activeCategory === category && 'bg-button-active-surface'\n )\n \"\n @click=\"selectCategory(category)\"\n >\n <i :class=\"getCategoryIcon(category)\" />\n <span class=\"whitespace-nowrap text-base-foreground\">{{\n $t(categoryLabels[category])\n }}</span>\n </Button>\n </div>\n </div>\n </div>\n\n <div v-show=\"activeCategory\" class=\"rounded-lg bg-smoke-700/30\">\n <SceneControls\n v-if=\"showSceneControls\"\n v-model:show-grid=\"sceneConfig!.showGrid\"\n v-model:background-color=\"sceneConfig!.backgroundColor\"\n v-model:background-image=\"sceneConfig!.backgroundImage\"\n v-model:background-render-mode=\"sceneConfig!.backgroundRenderMode\"\n v-model:fov=\"cameraConfig!.fov\"\n @update-background-image=\"handleBackgroundImageUpdate\"\n />\n\n <ModelControls\n v-if=\"showModelControls\"\n v-model:material-mode=\"modelConfig!.materialMode\"\n v-model:up-direction=\"modelConfig!.upDirection\"\n v-model:show-skeleton=\"modelConfig!.showSkeleton\"\n :hide-material-mode=\"isSplatModel\"\n :is-ply-model=\"isPlyModel\"\n :has-skeleton=\"hasSkeleton\"\n />\n\n <CameraControls\n v-if=\"showCameraControls\"\n v-model:camera-type=\"cameraConfig!.cameraType\"\n v-model:fov=\"cameraConfig!.fov\"\n />\n\n <LightControls\n v-if=\"showLightControls\"\n v-model:light-intensity=\"lightConfig!.intensity\"\n v-model:material-mode=\"modelConfig!.materialMode\"\n />\n\n <ExportControls\n v-if=\"showExportControls\"\n @export-model=\"handleExportModel\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport CameraControls from '@/components/load3d/controls/CameraControls.vue'\nimport ExportControls from '@/components/load3d/controls/ExportControls.vue'\nimport LightControls from '@/components/load3d/controls/LightControls.vue'\nimport ModelControls from '@/components/load3d/controls/ModelControls.vue'\nimport SceneControls from '@/components/load3d/controls/SceneControls.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport type {\n CameraConfig,\n LightConfig,\n ModelConfig,\n SceneConfig\n} from '@/extensions/core/load3d/interfaces'\nimport { cn } from '@/utils/tailwindUtil'\n\nconst {\n isSplatModel = false,\n isPlyModel = false,\n hasSkeleton = false\n} = defineProps<{\n isSplatModel?: boolean\n isPlyModel?: boolean\n hasSkeleton?: boolean\n}>()\n\nconst sceneConfig = defineModel<SceneConfig>('sceneConfig')\nconst modelConfig = defineModel<ModelConfig>('modelConfig')\nconst cameraConfig = defineModel<CameraConfig>('cameraConfig')\nconst lightConfig = defineModel<LightConfig>('lightConfig')\n\nconst isMenuOpen = ref(false)\nconst activeCategory = ref<string>('scene')\nconst categoryLabels: Record<string, string> = {\n scene: 'load3d.scene',\n model: 'load3d.model',\n camera: 'load3d.camera',\n light: 'load3d.light',\n export: 'load3d.export'\n}\n\nconst availableCategories = computed(() => {\n if (isSplatModel) {\n return ['scene', 'model', 'camera']\n }\n\n return ['scene', 'model', 'camera', 'light', 'export']\n})\n\nconst showSceneControls = computed(\n () => activeCategory.value === 'scene' && !!sceneConfig.value\n)\nconst showModelControls = computed(\n () => activeCategory.value === 'model' && !!modelConfig.value\n)\nconst showCameraControls = computed(\n () => activeCategory.value === 'camera' && !!cameraConfig.value\n)\nconst showLightControls = computed(\n () =>\n activeCategory.value === 'light' &&\n !!lightConfig.value &&\n !!modelConfig.value\n)\nconst showExportControls = computed(() => activeCategory.value === 'export')\n\nconst toggleMenu = () => {\n isMenuOpen.value = !isMenuOpen.value\n}\n\nconst selectCategory = (category: string) => {\n activeCategory.value = category\n isMenuOpen.value = false\n}\n\nconst getCategoryIcon = (category: string) => {\n const icons = {\n scene: 'pi pi-image',\n model: 'pi pi-box',\n camera: 'pi pi-camera',\n light: 'pi pi-sun',\n export: 'pi pi-download'\n }\n // @ts-expect-error fixme ts strict error\n return `${icons[category]} text-base-foreground text-lg`\n}\n\nconst emit = defineEmits<{\n (e: 'updateBackgroundImage', file: File | null): void\n (e: 'exportModel', format: string): void\n}>()\n\nconst handleBackgroundImageUpdate = (file: File | null) => {\n emit('updateBackgroundImage', file)\n}\n\nconst handleExportModel = (format: string) => {\n emit('exportModel', format)\n}\n\nconst closeSlider = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-menu')) {\n isMenuOpen.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeSlider)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeSlider)\n})\n</script>\n","<template>\n <div\n ref=\"container\"\n class=\"relative h-full w-full min-h-[200px]\"\n data-capture-wheel=\"true\"\n @pointerdown.stop\n @pointermove.stop\n @pointerup.stop\n @mousedown.stop\n @mousemove.stop\n @mouseup.stop\n @contextmenu.stop.prevent\n @dragover.prevent.stop=\"handleDragOver\"\n @dragleave.stop=\"handleDragLeave\"\n @drop.prevent.stop=\"handleDrop\"\n >\n <LoadingOverlay :loading=\"loading\" :loading-message=\"loadingMessage\" />\n <div\n v-if=\"!isPreview && isDragging\"\n class=\"pointer-events-none absolute inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm\"\n >\n <div\n class=\"rounded-lg border-2 border-dashed border-blue-400 bg-blue-500/20 px-6 py-4 text-lg font-medium text-blue-100\"\n >\n {{ dragMessage }}\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport LoadingOverlay from '@/components/load3d/LoadingOverlay.vue'\nimport { useLoad3dDrag } from '@/composables/useLoad3dDrag'\n\nconst props = defineProps<{\n initializeLoad3d: (containerRef: HTMLElement) => Promise<void>\n cleanup: () => void\n loading: boolean\n loadingMessage: string\n onModelDrop?: (file: File) => void | Promise<void>\n isPreview: boolean\n}>()\n\nconst container = ref<HTMLElement | null>(null)\n\nconst { isDragging, dragMessage, handleDragOver, handleDragLeave, handleDrop } =\n useLoad3dDrag({\n onModelDrop: async (file) => {\n if (props.onModelDrop) {\n await props.onModelDrop(file)\n }\n },\n disabled: computed(() => props.isPreview)\n })\n\nonMounted(() => {\n if (container.value) {\n void props.initializeLoad3d(container.value)\n }\n})\n\nonUnmounted(() => {\n props.cleanup()\n})\n</script>\n","<template>\n <div class=\"relative rounded-lg bg-backdrop/30\">\n <div class=\"flex flex-col gap-2\">\n <Button\n v-tooltip.right=\"{\n value: isRecording\n ? $t('load3d.stopRecording')\n : $t('load3d.startRecording'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n :class=\"\n cn(\n 'rounded-full',\n isRecording && 'text-red-500 recording-button-blink'\n )\n \"\n :aria-label=\"\n isRecording ? $t('load3d.stopRecording') : $t('load3d.startRecording')\n \"\n @click=\"toggleRecording\"\n >\n <i\n :class=\"[\n 'pi',\n isRecording ? 'pi-circle-fill' : 'pi-video',\n 'text-lg text-base-foreground'\n ]\"\n />\n </Button>\n\n <Button\n v-if=\"hasRecording && !isRecording\"\n v-tooltip.right=\"{\n value: $t('load3d.exportRecording'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.exportRecording')\"\n @click=\"handleExportRecording\"\n >\n <i class=\"pi pi-download text-lg text-base-foreground\" />\n </Button>\n\n <Button\n v-if=\"hasRecording && !isRecording\"\n v-tooltip.right=\"{\n value: $t('load3d.clearRecording'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.clearRecording')\"\n @click=\"handleClearRecording\"\n >\n <i class=\"pi pi-trash text-lg text-base-foreground\" />\n </Button>\n\n <div\n v-if=\"recordingDuration && recordingDuration > 0 && !isRecording\"\n class=\"mt-1 text-center text-xs text-base-foreground\"\n >\n {{ formatDuration(recordingDuration) }}\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Button from '@/components/ui/button/Button.vue'\nimport { cn } from '@/utils/tailwindUtil'\n\nconst hasRecording = defineModel<boolean>('hasRecording')\nconst isRecording = defineModel<boolean>('isRecording')\nconst recordingDuration = defineModel<number>('recordingDuration')\n\nconst emit = defineEmits<{\n (e: 'startRecording'): void\n (e: 'stopRecording'): void\n (e: 'exportRecording'): void\n (e: 'clearRecording'): void\n}>()\n\nfunction toggleRecording() {\n if (isRecording.value) {\n emit('stopRecording')\n } else {\n emit('startRecording')\n }\n}\n\nfunction handleExportRecording() {\n emit('exportRecording')\n}\n\nfunction handleClearRecording() {\n emit('clearRecording')\n}\n\nfunction formatDuration(seconds: number): string {\n const minutes = Math.floor(seconds / 60)\n const remainingSeconds = Math.floor(seconds % 60)\n return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`\n}\n</script>\n\n<style scoped>\n.recording-button-blink {\n animation: blink 1s infinite;\n}\n\n@keyframes blink {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n</style>\n","<template>\n <div class=\"relative rounded-lg bg-backdrop/30\">\n <div class=\"flex flex-col gap-2\">\n <Button\n v-tooltip.right=\"{\n value: t('load3d.openIn3DViewer'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"t('load3d.openIn3DViewer')\"\n @click=\"openIn3DViewer\"\n >\n <i class=\"pi pi-expand text-lg text-base-foreground\" />\n </Button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport { t } from '@/i18n'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport { useLoad3dService } from '@/services/load3dService'\nimport { useDialogStore } from '@/stores/dialogStore'\n\nconst { node } = defineProps<{\n node: LGraphNode\n}>()\n\nconst openIn3DViewer = () => {\n const props = { node: node }\n\n useDialogStore().showDialog({\n key: 'global-load3d-viewer',\n title: t('load3d.viewer.title'),\n component: Load3DViewerContent,\n props: props,\n dialogComponentProps: {\n style: 'width: 80vw; height: 80vh;',\n maximizable: true,\n onClose: async () => {\n await useLoad3dService().handleViewerClose(props.node)\n }\n }\n })\n}\n</script>\n\n<style scoped></style>\n","<template>\n <div\n class=\"relative size-full\"\n @mouseenter=\"handleMouseEnter\"\n @mouseleave=\"handleMouseLeave\"\n @pointerdown.stop\n @pointermove.stop\n @pointerup.stop\n >\n <Load3DScene\n v-if=\"node\"\n :initialize-load3d=\"initializeLoad3d\"\n :cleanup=\"cleanup\"\n :loading=\"loading\"\n :loading-message=\"loadingMessage\"\n :on-model-drop=\"isPreview ? undefined : handleModelDrop\"\n :is-preview=\"isPreview\"\n />\n <div class=\"pointer-events-none absolute top-0 left-0 size-full\">\n <Load3DControls\n v-model:scene-config=\"sceneConfig\"\n v-model:model-config=\"modelConfig\"\n v-model:camera-config=\"cameraConfig\"\n v-model:light-config=\"lightConfig\"\n :is-splat-model=\"isSplatModel\"\n :is-ply-model=\"isPlyModel\"\n :has-skeleton=\"hasSkeleton\"\n @update-background-image=\"handleBackgroundImageUpdate\"\n @export-model=\"handleExportModel\"\n />\n <AnimationControls\n v-if=\"animations && animations.length > 0\"\n v-model:animations=\"animations\"\n v-model:playing=\"playing\"\n v-model:selected-speed=\"selectedSpeed\"\n v-model:selected-animation=\"selectedAnimation\"\n v-model:animation-progress=\"animationProgress\"\n v-model:animation-duration=\"animationDuration\"\n @seek=\"handleSeek\"\n />\n </div>\n <div\n v-if=\"enable3DViewer && node\"\n class=\"pointer-events-auto absolute top-12 right-2 z-20\"\n >\n <ViewerControls :node=\"node as LGraphNode\" />\n </div>\n\n <div\n v-if=\"!isPreview\"\n class=\"pointer-events-auto absolute right-2 z-20\"\n :class=\"{\n 'top-12': !enable3DViewer,\n 'top-24': enable3DViewer\n }\"\n >\n <RecordingControls\n v-model:is-recording=\"isRecording\"\n v-model:has-recording=\"hasRecording\"\n v-model:recording-duration=\"recordingDuration\"\n @start-recording=\"handleStartRecording\"\n @stop-recording=\"handleStopRecording\"\n @export-recording=\"handleExportRecording\"\n @clear-recording=\"handleClearRecording\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport type { Ref } from 'vue'\n\nimport Load3DControls from '@/components/load3d/Load3DControls.vue'\nimport Load3DScene from '@/components/load3d/Load3DScene.vue'\nimport AnimationControls from '@/components/load3d/controls/AnimationControls.vue'\nimport RecordingControls from '@/components/load3d/controls/RecordingControls.vue'\nimport ViewerControls from '@/components/load3d/controls/ViewerControls.vue'\nimport { useLoad3d } from '@/composables/useLoad3d'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport { useSettingStore } from '@/platform/settings/settingStore'\nimport type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema'\nimport { app } from '@/scripts/app'\nimport type { ComponentWidget } from '@/scripts/domWidget'\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\n\nconst props = defineProps<{\n widget: ComponentWidget<string[]> | SimplifiedWidget\n nodeId?: NodeId\n}>()\n\nfunction isComponentWidget(\n widget: ComponentWidget<string[]> | SimplifiedWidget\n): widget is ComponentWidget<string[]> {\n return 'node' in widget && widget.node !== undefined\n}\n\nconst node = ref<LGraphNode | null>(null)\n\nif (isComponentWidget(props.widget)) {\n node.value = props.widget.node\n} else if (props.nodeId) {\n onMounted(() => {\n node.value = app.rootGraph?.getNodeById(props.nodeId!) || null\n })\n}\n\nconst {\n // configs\n sceneConfig,\n modelConfig,\n cameraConfig,\n lightConfig,\n\n // other state\n isRecording,\n isPreview,\n isSplatModel,\n isPlyModel,\n hasSkeleton,\n hasRecording,\n recordingDuration,\n animations,\n playing,\n selectedSpeed,\n selectedAnimation,\n animationProgress,\n animationDuration,\n loading,\n loadingMessage,\n\n // Methods\n initializeLoad3d,\n handleMouseEnter,\n handleMouseLeave,\n handleStartRecording,\n handleStopRecording,\n handleExportRecording,\n handleClearRecording,\n handleSeek,\n handleBackgroundImageUpdate,\n handleExportModel,\n handleModelDrop,\n cleanup\n} = useLoad3d(node as Ref<LGraphNode | null>)\n\nconst enable3DViewer = computed(() =>\n useSettingStore().get('Comfy.Load3D.3DViewerEnable')\n)\n</script>\n"],"names":["value","_useModel","__props","showSlider","ref","toggleSlider","__name","closeSlider","e","onMounted","onUnmounted","cameraType","fov","showFOVButton","computed","switchCamera","emit","__emit","showExportFormats","exportFormats","toggleExportFormats","exportModel","format","closeExportFormatsList","lightIntensity","materialMode","showLightIntensityButton","showLightIntensity","lightIntensityMaximum","useSettingStore","lightIntensityMinimum","lightAdjustmentIncrement","toggleLightIntensity","closeLightSlider","upDirection","showSkeleton","showUpDirection","showMaterialMode","upDirections","materialModes","modes","toggleUpDirection","selectUpDirection","direction","toggleMaterialMode","selectMaterialMode","mode","formatMaterialMode","t","closeSceneSlider","target","showGrid","backgroundColor","backgroundImage","backgroundRenderMode","hasBackgroundImage","colorPickerRef","imagePickerRef","toggleGrid","updateBackgroundColor","color","openColorPicker","openImagePicker","uploadBackgroundImage","event","input","removeBackgroundImage","toggleBackgroundRenderMode","sceneConfig","modelConfig","cameraConfig","lightConfig","isMenuOpen","activeCategory","categoryLabels","availableCategories","showSceneControls","showModelControls","showCameraControls","showLightControls","showExportControls","toggleMenu","selectCategory","category","getCategoryIcon","handleBackgroundImageUpdate","file","handleExportModel","props","container","isDragging","dragMessage","handleDragOver","handleDragLeave","handleDrop","useLoad3dDrag","hasRecording","isRecording","recordingDuration","toggleRecording","handleExportRecording","handleClearRecording","formatDuration","seconds","minutes","remainingSeconds","openIn3DViewer","useDialogStore","Load3DViewerContent","useLoad3dService","isComponentWidget","widget","node","app","isPreview","isSplatModel","isPlyModel","hasSkeleton","animations","playing","selectedSpeed","selectedAnimation","animationProgress","animationDuration","loading","loadingMessage","initializeLoad3d","handleMouseEnter","handleMouseLeave","handleStartRecording","handleStopRecording","handleSeek","handleModelDrop","cleanup","useLoad3d","enable3DViewer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Load3D.vue_vue_type_script_setup_true_lang-KEzORqB0.js","sources":["../../src/components/load3d/controls/PopupSlider.vue","../../src/components/load3d/controls/CameraControls.vue","../../src/components/load3d/controls/ExportControls.vue","../../src/components/load3d/controls/LightControls.vue","../../src/components/load3d/controls/ModelControls.vue","../../src/components/load3d/controls/SceneControls.vue","../../src/components/load3d/Load3DControls.vue","../../src/components/load3d/Load3DScene.vue","../../src/components/load3d/controls/RecordingControls.vue","../../src/components/load3d/controls/ViewerControls.vue","../../src/components/load3d/Load3D.vue"],"sourcesContent":["<template>\n <div class=\"relative show-slider\">\n <Button\n v-tooltip.right=\"{ value: tooltipText, showDelay: 300 }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"tooltipText\"\n @click=\"toggleSlider\"\n >\n <i :class=\"['pi', icon, 'text-lg text-base-foreground']\" />\n </Button>\n <div\n v-show=\"showSlider\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface p-4 shadow-lg w-[150px]\"\n >\n <Slider\n v-model=\"value\"\n class=\"w-full\"\n :min=\"min\"\n :max=\"max\"\n :step=\"step\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Slider from 'primevue/slider'\nimport { onMounted, onUnmounted, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\n\nconst {\n icon = 'pi-expand',\n min = 10,\n max = 150,\n step = 1\n} = defineProps<{\n icon?: string\n tooltipText: string\n min?: number\n max?: number\n step?: number\n}>()\n\nconst value = defineModel<number>()\nconst showSlider = ref(false)\n\nconst toggleSlider = () => {\n showSlider.value = !showSlider.value\n}\n\nconst closeSlider = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-slider')) {\n showSlider.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeSlider)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeSlider)\n})\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.switchCamera'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.switchCamera')\"\n @click=\"switchCamera\"\n >\n <i :class=\"['pi', 'pi-camera', 'text-lg text-base-foreground']\" />\n </Button>\n <PopupSlider\n v-if=\"showFOVButton\"\n v-model=\"fov\"\n :tooltip-text=\"$t('load3d.fov')\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport PopupSlider from '@/components/load3d/controls/PopupSlider.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport type { CameraType } from '@/extensions/core/load3d/interfaces'\n\nconst cameraType = defineModel<CameraType>('cameraType')\nconst fov = defineModel<number>('fov')\nconst showFOVButton = computed(() => cameraType.value === 'perspective')\n\nconst switchCamera = () => {\n cameraType.value =\n cameraType.value === 'perspective' ? 'orthographic' : 'perspective'\n}\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <div class=\"show-export-formats relative\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.exportModel'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.exportModel')\"\n @click=\"toggleExportFormats\"\n >\n <i class=\"pi pi-download text-lg text-base-foreground\" />\n </Button>\n <div\n v-show=\"showExportFormats\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg\"\n >\n <div class=\"flex flex-col\">\n <Button\n v-for=\"format in exportFormats\"\n :key=\"format.value\"\n variant=\"textonly\"\n class=\"text-base-foreground\"\n @click=\"exportModel(format.value)\"\n >\n {{ format.label }}\n </Button>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, onUnmounted, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\n\nconst emit = defineEmits<{\n (e: 'exportModel', format: string): void\n}>()\n\nconst showExportFormats = ref(false)\n\nconst exportFormats = [\n { label: 'GLB', value: 'glb' },\n { label: 'OBJ', value: 'obj' },\n { label: 'STL', value: 'stl' }\n]\n\nfunction toggleExportFormats() {\n showExportFormats.value = !showExportFormats.value\n}\n\nfunction exportModel(format: string) {\n emit('exportModel', format)\n\n showExportFormats.value = false\n}\n\nfunction closeExportFormatsList(e: MouseEvent) {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-export-formats')) {\n showExportFormats.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeExportFormatsList)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeExportFormatsList)\n})\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <div v-if=\"showLightIntensityButton\" class=\"show-light-intensity relative\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.lightIntensity'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.lightIntensity')\"\n @click=\"toggleLightIntensity\"\n >\n <i class=\"pi pi-sun text-lg text-base-foreground\" />\n </Button>\n <div\n v-show=\"showLightIntensity\"\n class=\"absolute top-0 left-12 rounded-lg bg-black/50 p-4 shadow-lg\"\n style=\"width: 150px\"\n >\n <Slider\n v-model=\"lightIntensity\"\n class=\"w-full\"\n :min=\"lightIntensityMinimum\"\n :max=\"lightIntensityMaximum\"\n :step=\"lightAdjustmentIncrement\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Slider from 'primevue/slider'\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport type { MaterialMode } from '@/extensions/core/load3d/interfaces'\nimport { useSettingStore } from '@/platform/settings/settingStore'\n\nconst lightIntensity = defineModel<number>('lightIntensity')\nconst materialMode = defineModel<MaterialMode>('materialMode')\n\nconst showLightIntensityButton = computed(\n () => materialMode.value === 'original'\n)\nconst showLightIntensity = ref(false)\n\nconst lightIntensityMaximum = useSettingStore().get(\n 'Comfy.Load3D.LightIntensityMaximum'\n)\nconst lightIntensityMinimum = useSettingStore().get(\n 'Comfy.Load3D.LightIntensityMinimum'\n)\nconst lightAdjustmentIncrement = useSettingStore().get(\n 'Comfy.Load3D.LightAdjustmentIncrement'\n)\n\nfunction toggleLightIntensity() {\n showLightIntensity.value = !showLightIntensity.value\n}\n\nfunction closeLightSlider(e: MouseEvent) {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-light-intensity')) {\n showLightIntensity.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeLightSlider)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeLightSlider)\n})\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <div class=\"show-up-direction relative\">\n <Button\n v-tooltip.right=\"{\n value: t('load3d.upDirection'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"t('load3d.upDirection')\"\n @click=\"toggleUpDirection\"\n >\n <i class=\"pi pi-arrow-up text-lg text-base-foreground\" />\n </Button>\n <div\n v-show=\"showUpDirection\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg\"\n >\n <div class=\"flex flex-col\">\n <Button\n v-for=\"direction in upDirections\"\n :key=\"direction\"\n variant=\"textonly\"\n :class=\"\n cn(\n 'text-base-foreground',\n upDirection === direction && 'bg-blue-500'\n )\n \"\n @click=\"selectUpDirection(direction)\"\n >\n {{ direction.toUpperCase() }}\n </Button>\n </div>\n </div>\n </div>\n\n <div v-if=\"!hideMaterialMode\" class=\"show-material-mode relative\">\n <Button\n v-tooltip.right=\"{\n value: t('load3d.materialMode'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"t('load3d.materialMode')\"\n @click=\"toggleMaterialMode\"\n >\n <i class=\"pi pi-box text-lg text-base-foreground\" />\n </Button>\n <div\n v-show=\"showMaterialMode\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg\"\n >\n <div class=\"flex flex-col\">\n <Button\n v-for=\"mode in materialModes\"\n :key=\"mode\"\n variant=\"textonly\"\n :class=\"\n cn(\n 'whitespace-nowrap text-base-foreground',\n materialMode === mode && 'bg-blue-500'\n )\n \"\n @click=\"selectMaterialMode(mode)\"\n >\n {{ formatMaterialMode(mode) }}\n </Button>\n </div>\n </div>\n </div>\n\n <div v-if=\"hasSkeleton\">\n <Button\n v-tooltip.right=\"{\n value: t('load3d.showSkeleton'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n :class=\"cn('rounded-full', showSkeleton && 'bg-blue-500')\"\n :aria-label=\"t('load3d.showSkeleton')\"\n @click=\"showSkeleton = !showSkeleton\"\n >\n <i class=\"pi pi-sitemap text-lg text-base-foreground\" />\n </Button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport Button from '@/components/ui/button/Button.vue'\nimport type {\n MaterialMode,\n UpDirection\n} from '@/extensions/core/load3d/interfaces'\nimport { t } from '@/i18n'\nimport { cn } from '@/utils/tailwindUtil'\n\nconst {\n hideMaterialMode = false,\n isPlyModel = false,\n hasSkeleton = false\n} = defineProps<{\n hideMaterialMode?: boolean\n isPlyModel?: boolean\n hasSkeleton?: boolean\n}>()\n\nconst materialMode = defineModel<MaterialMode>('materialMode')\nconst upDirection = defineModel<UpDirection>('upDirection')\nconst showSkeleton = defineModel<boolean>('showSkeleton')\n\nconst showUpDirection = ref(false)\nconst showMaterialMode = ref(false)\n\nconst upDirections: UpDirection[] = [\n 'original',\n '-x',\n '+x',\n '-y',\n '+y',\n '-z',\n '+z'\n]\n\nconst materialModes = computed(() => {\n const modes: MaterialMode[] = [\n 'original',\n 'normal',\n 'wireframe'\n //'depth' disable for now\n ]\n\n // Only show pointCloud mode for PLY files (point cloud rendering)\n if (isPlyModel) {\n modes.splice(1, 0, 'pointCloud')\n }\n\n return modes\n})\n\nfunction toggleUpDirection() {\n showUpDirection.value = !showUpDirection.value\n showMaterialMode.value = false\n}\n\nfunction selectUpDirection(direction: UpDirection) {\n upDirection.value = direction\n showUpDirection.value = false\n}\n\nfunction toggleMaterialMode() {\n showMaterialMode.value = !showMaterialMode.value\n showUpDirection.value = false\n}\n\nfunction selectMaterialMode(mode: MaterialMode) {\n materialMode.value = mode\n showMaterialMode.value = false\n}\n\nfunction formatMaterialMode(mode: MaterialMode) {\n return t(`load3d.materialModes.${mode}`)\n}\n\nfunction closeSceneSlider(e: MouseEvent) {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-up-direction')) {\n showUpDirection.value = false\n }\n\n if (!target.closest('.show-material-mode')) {\n showMaterialMode.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeSceneSlider)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeSceneSlider)\n})\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <Button\n v-tooltip.right=\"{ value: $t('load3d.showGrid'), showDelay: 300 }\"\n variant=\"textonly\"\n size=\"icon\"\n :class=\"cn('rounded-full', showGrid && 'ring-2 ring-white/50')\"\n :aria-label=\"$t('load3d.showGrid')\"\n @click=\"toggleGrid\"\n >\n <i class=\"pi pi-table text-lg text-base-foreground\" />\n </Button>\n\n <div v-if=\"!hasBackgroundImage\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.backgroundColor'),\n showDelay: 300\n }\"\n variant=\"textonly\"\n size=\"icon\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.backgroundColor')\"\n @click=\"openColorPicker\"\n >\n <i class=\"pi pi-palette text-lg text-base-foreground\" />\n <input\n ref=\"colorPickerRef\"\n type=\"color\"\n :value=\"backgroundColor\"\n class=\"pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0\"\n @input=\"\n updateBackgroundColor(($event.target as HTMLInputElement).value)\n \"\n />\n </Button>\n </div>\n\n <div v-if=\"!hasBackgroundImage\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.uploadBackgroundImage'),\n showDelay: 300\n }\"\n variant=\"textonly\"\n size=\"icon\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.uploadBackgroundImage')\"\n @click=\"openImagePicker\"\n >\n <i class=\"pi pi-image text-lg text-base-foreground\" />\n <input\n ref=\"imagePickerRef\"\n type=\"file\"\n accept=\"image/*\"\n class=\"pointer-events-none absolute m-0 h-0 w-0 p-0 opacity-0\"\n @change=\"uploadBackgroundImage\"\n />\n </Button>\n </div>\n\n <div v-if=\"hasBackgroundImage\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.panoramaMode'),\n showDelay: 300\n }\"\n variant=\"textonly\"\n size=\"icon\"\n :class=\"\n cn(\n 'rounded-full',\n backgroundRenderMode === 'panorama' && 'ring-2 ring-white/50'\n )\n \"\n :aria-label=\"$t('load3d.panoramaMode')\"\n @click=\"toggleBackgroundRenderMode\"\n >\n <i class=\"pi pi-globe text-lg text-base-foreground\" />\n </Button>\n </div>\n\n <PopupSlider\n v-if=\"hasBackgroundImage && backgroundRenderMode === 'panorama'\"\n v-model=\"fov\"\n :tooltip-text=\"$t('load3d.fov')\"\n />\n\n <div v-if=\"hasBackgroundImage\">\n <Button\n v-tooltip.right=\"{\n value: $t('load3d.removeBackgroundImage'),\n showDelay: 300\n }\"\n variant=\"textonly\"\n size=\"icon\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.removeBackgroundImage')\"\n @click=\"removeBackgroundImage\"\n >\n <i class=\"pi pi-times text-lg text-base-foreground\" />\n </Button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\n\nimport PopupSlider from '@/components/load3d/controls/PopupSlider.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport type { BackgroundRenderModeType } from '@/extensions/core/load3d/interfaces'\nimport { cn } from '@/utils/tailwindUtil'\n\nconst emit = defineEmits<{\n (e: 'updateBackgroundImage', file: File | null): void\n}>()\n\nconst showGrid = defineModel<boolean>('showGrid')\nconst backgroundColor = defineModel<string>('backgroundColor')\nconst backgroundImage = defineModel<string>('backgroundImage')\nconst backgroundRenderMode = defineModel<BackgroundRenderModeType>(\n 'backgroundRenderMode',\n { default: 'tiled' }\n)\nconst fov = defineModel<number>('fov')\nconst hasBackgroundImage = computed(\n () => backgroundImage.value && backgroundImage.value !== ''\n)\n\nconst colorPickerRef = ref<HTMLInputElement | null>(null)\nconst imagePickerRef = ref<HTMLInputElement | null>(null)\n\nconst toggleGrid = () => {\n showGrid.value = !showGrid.value\n}\n\nconst updateBackgroundColor = (color: string) => {\n backgroundColor.value = color\n}\n\nconst openColorPicker = () => {\n colorPickerRef.value?.click()\n}\n\nconst openImagePicker = () => {\n imagePickerRef.value?.click()\n}\n\nconst uploadBackgroundImage = (event: Event) => {\n const input = event.target as HTMLInputElement\n\n if (input.files && input.files[0]) {\n emit('updateBackgroundImage', input.files[0])\n }\n}\n\nconst removeBackgroundImage = () => {\n emit('updateBackgroundImage', null)\n}\n\nconst toggleBackgroundRenderMode = () => {\n backgroundRenderMode.value =\n backgroundRenderMode.value === 'panorama' ? 'tiled' : 'panorama'\n}\n</script>\n","<template>\n <div\n class=\"pointer-events-auto absolute top-12 left-2 z-20 flex flex-col rounded-lg bg-backdrop/30\"\n @pointerdown.stop\n @pointermove.stop\n @pointerup.stop\n @wheel.stop\n >\n <div class=\"show-menu relative\">\n <Button\n variant=\"textonly\"\n size=\"icon\"\n :aria-label=\"$t('menu.showMenu')\"\n class=\"rounded-full\"\n @click=\"toggleMenu\"\n >\n <i class=\"pi pi-bars text-lg text-base-foreground\" />\n </Button>\n\n <div\n v-show=\"isMenuOpen\"\n class=\"absolute top-0 left-12 rounded-lg bg-interface-menu-surface shadow-lg\"\n >\n <div class=\"flex flex-col\">\n <Button\n v-for=\"category in availableCategories\"\n :key=\"category\"\n variant=\"textonly\"\n :class=\"\n cn(\n 'flex w-full items-center justify-start',\n activeCategory === category && 'bg-button-active-surface'\n )\n \"\n @click=\"selectCategory(category)\"\n >\n <i :class=\"getCategoryIcon(category)\" />\n <span class=\"whitespace-nowrap text-base-foreground\">{{\n $t(categoryLabels[category])\n }}</span>\n </Button>\n </div>\n </div>\n </div>\n\n <div v-show=\"activeCategory\" class=\"rounded-lg bg-smoke-700/30\">\n <SceneControls\n v-if=\"showSceneControls\"\n v-model:show-grid=\"sceneConfig!.showGrid\"\n v-model:background-color=\"sceneConfig!.backgroundColor\"\n v-model:background-image=\"sceneConfig!.backgroundImage\"\n v-model:background-render-mode=\"sceneConfig!.backgroundRenderMode\"\n v-model:fov=\"cameraConfig!.fov\"\n @update-background-image=\"handleBackgroundImageUpdate\"\n />\n\n <ModelControls\n v-if=\"showModelControls\"\n v-model:material-mode=\"modelConfig!.materialMode\"\n v-model:up-direction=\"modelConfig!.upDirection\"\n v-model:show-skeleton=\"modelConfig!.showSkeleton\"\n :hide-material-mode=\"isSplatModel\"\n :is-ply-model=\"isPlyModel\"\n :has-skeleton=\"hasSkeleton\"\n />\n\n <CameraControls\n v-if=\"showCameraControls\"\n v-model:camera-type=\"cameraConfig!.cameraType\"\n v-model:fov=\"cameraConfig!.fov\"\n />\n\n <LightControls\n v-if=\"showLightControls\"\n v-model:light-intensity=\"lightConfig!.intensity\"\n v-model:material-mode=\"modelConfig!.materialMode\"\n />\n\n <ExportControls\n v-if=\"showExportControls\"\n @export-model=\"handleExportModel\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport CameraControls from '@/components/load3d/controls/CameraControls.vue'\nimport ExportControls from '@/components/load3d/controls/ExportControls.vue'\nimport LightControls from '@/components/load3d/controls/LightControls.vue'\nimport ModelControls from '@/components/load3d/controls/ModelControls.vue'\nimport SceneControls from '@/components/load3d/controls/SceneControls.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport type {\n CameraConfig,\n LightConfig,\n ModelConfig,\n SceneConfig\n} from '@/extensions/core/load3d/interfaces'\nimport { cn } from '@/utils/tailwindUtil'\n\nconst {\n isSplatModel = false,\n isPlyModel = false,\n hasSkeleton = false\n} = defineProps<{\n isSplatModel?: boolean\n isPlyModel?: boolean\n hasSkeleton?: boolean\n}>()\n\nconst sceneConfig = defineModel<SceneConfig>('sceneConfig')\nconst modelConfig = defineModel<ModelConfig>('modelConfig')\nconst cameraConfig = defineModel<CameraConfig>('cameraConfig')\nconst lightConfig = defineModel<LightConfig>('lightConfig')\n\nconst isMenuOpen = ref(false)\nconst activeCategory = ref<string>('scene')\nconst categoryLabels: Record<string, string> = {\n scene: 'load3d.scene',\n model: 'load3d.model',\n camera: 'load3d.camera',\n light: 'load3d.light',\n export: 'load3d.export'\n}\n\nconst availableCategories = computed(() => {\n if (isSplatModel) {\n return ['scene', 'model', 'camera']\n }\n\n return ['scene', 'model', 'camera', 'light', 'export']\n})\n\nconst showSceneControls = computed(\n () => activeCategory.value === 'scene' && !!sceneConfig.value\n)\nconst showModelControls = computed(\n () => activeCategory.value === 'model' && !!modelConfig.value\n)\nconst showCameraControls = computed(\n () => activeCategory.value === 'camera' && !!cameraConfig.value\n)\nconst showLightControls = computed(\n () =>\n activeCategory.value === 'light' &&\n !!lightConfig.value &&\n !!modelConfig.value\n)\nconst showExportControls = computed(() => activeCategory.value === 'export')\n\nconst toggleMenu = () => {\n isMenuOpen.value = !isMenuOpen.value\n}\n\nconst selectCategory = (category: string) => {\n activeCategory.value = category\n isMenuOpen.value = false\n}\n\nconst getCategoryIcon = (category: string) => {\n const icons = {\n scene: 'pi pi-image',\n model: 'pi pi-box',\n camera: 'pi pi-camera',\n light: 'pi pi-sun',\n export: 'pi pi-download'\n }\n // @ts-expect-error fixme ts strict error\n return `${icons[category]} text-base-foreground text-lg`\n}\n\nconst emit = defineEmits<{\n (e: 'updateBackgroundImage', file: File | null): void\n (e: 'exportModel', format: string): void\n}>()\n\nconst handleBackgroundImageUpdate = (file: File | null) => {\n emit('updateBackgroundImage', file)\n}\n\nconst handleExportModel = (format: string) => {\n emit('exportModel', format)\n}\n\nconst closeSlider = (e: MouseEvent) => {\n const target = e.target as HTMLElement\n\n if (!target.closest('.show-menu')) {\n isMenuOpen.value = false\n }\n}\n\nonMounted(() => {\n document.addEventListener('click', closeSlider)\n})\n\nonUnmounted(() => {\n document.removeEventListener('click', closeSlider)\n})\n</script>\n","<template>\n <div\n ref=\"container\"\n class=\"relative h-full w-full min-h-[200px]\"\n data-capture-wheel=\"true\"\n @pointerdown.stop\n @pointermove.stop\n @pointerup.stop\n @mousedown.stop\n @mousemove.stop\n @mouseup.stop\n @contextmenu.stop.prevent\n @dragover.prevent.stop=\"handleDragOver\"\n @dragleave.stop=\"handleDragLeave\"\n @drop.prevent.stop=\"handleDrop\"\n >\n <LoadingOverlay :loading=\"loading\" :loading-message=\"loadingMessage\" />\n <div\n v-if=\"!isPreview && isDragging\"\n class=\"pointer-events-none absolute inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm\"\n >\n <div\n class=\"rounded-lg border-2 border-dashed border-blue-400 bg-blue-500/20 px-6 py-4 text-lg font-medium text-blue-100\"\n >\n {{ dragMessage }}\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport LoadingOverlay from '@/components/load3d/LoadingOverlay.vue'\nimport { useLoad3dDrag } from '@/composables/useLoad3dDrag'\n\nconst props = defineProps<{\n initializeLoad3d: (containerRef: HTMLElement) => Promise<void>\n cleanup: () => void\n loading: boolean\n loadingMessage: string\n onModelDrop?: (file: File) => void | Promise<void>\n isPreview: boolean\n}>()\n\nconst container = ref<HTMLElement | null>(null)\n\nconst { isDragging, dragMessage, handleDragOver, handleDragLeave, handleDrop } =\n useLoad3dDrag({\n onModelDrop: async (file) => {\n if (props.onModelDrop) {\n await props.onModelDrop(file)\n }\n },\n disabled: computed(() => props.isPreview)\n })\n\nonMounted(() => {\n if (container.value) {\n void props.initializeLoad3d(container.value)\n }\n})\n\nonUnmounted(() => {\n props.cleanup()\n})\n</script>\n","<template>\n <div class=\"relative rounded-lg bg-backdrop/30\">\n <div class=\"flex flex-col gap-2\">\n <Button\n v-tooltip.right=\"{\n value: isRecording\n ? $t('load3d.stopRecording')\n : $t('load3d.startRecording'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n :class=\"\n cn(\n 'rounded-full',\n isRecording && 'text-red-500 recording-button-blink'\n )\n \"\n :aria-label=\"\n isRecording ? $t('load3d.stopRecording') : $t('load3d.startRecording')\n \"\n @click=\"toggleRecording\"\n >\n <i\n :class=\"[\n 'pi',\n isRecording ? 'pi-circle-fill' : 'pi-video',\n 'text-lg text-base-foreground'\n ]\"\n />\n </Button>\n\n <Button\n v-if=\"hasRecording && !isRecording\"\n v-tooltip.right=\"{\n value: $t('load3d.exportRecording'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.exportRecording')\"\n @click=\"handleExportRecording\"\n >\n <i class=\"pi pi-download text-lg text-base-foreground\" />\n </Button>\n\n <Button\n v-if=\"hasRecording && !isRecording\"\n v-tooltip.right=\"{\n value: $t('load3d.clearRecording'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"$t('load3d.clearRecording')\"\n @click=\"handleClearRecording\"\n >\n <i class=\"pi pi-trash text-lg text-base-foreground\" />\n </Button>\n\n <div\n v-if=\"recordingDuration && recordingDuration > 0 && !isRecording\"\n class=\"mt-1 text-center text-xs text-base-foreground\"\n >\n {{ formatDuration(recordingDuration) }}\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Button from '@/components/ui/button/Button.vue'\nimport { cn } from '@/utils/tailwindUtil'\n\nconst hasRecording = defineModel<boolean>('hasRecording')\nconst isRecording = defineModel<boolean>('isRecording')\nconst recordingDuration = defineModel<number>('recordingDuration')\n\nconst emit = defineEmits<{\n (e: 'startRecording'): void\n (e: 'stopRecording'): void\n (e: 'exportRecording'): void\n (e: 'clearRecording'): void\n}>()\n\nfunction toggleRecording() {\n if (isRecording.value) {\n emit('stopRecording')\n } else {\n emit('startRecording')\n }\n}\n\nfunction handleExportRecording() {\n emit('exportRecording')\n}\n\nfunction handleClearRecording() {\n emit('clearRecording')\n}\n\nfunction formatDuration(seconds: number): string {\n const minutes = Math.floor(seconds / 60)\n const remainingSeconds = Math.floor(seconds % 60)\n return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`\n}\n</script>\n\n<style scoped>\n.recording-button-blink {\n animation: blink 1s infinite;\n}\n\n@keyframes blink {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n</style>\n","<template>\n <div class=\"relative rounded-lg bg-backdrop/30\">\n <div class=\"flex flex-col gap-2\">\n <Button\n v-tooltip.right=\"{\n value: t('load3d.openIn3DViewer'),\n showDelay: 300\n }\"\n size=\"icon\"\n variant=\"textonly\"\n class=\"rounded-full\"\n :aria-label=\"t('load3d.openIn3DViewer')\"\n @click=\"openIn3DViewer\"\n >\n <i class=\"pi pi-expand text-lg text-base-foreground\" />\n </Button>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Load3DViewerContent from '@/components/load3d/Load3dViewerContent.vue'\nimport Button from '@/components/ui/button/Button.vue'\nimport { t } from '@/i18n'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport { useLoad3dService } from '@/services/load3dService'\nimport { useDialogStore } from '@/stores/dialogStore'\n\nconst { node } = defineProps<{\n node: LGraphNode\n}>()\n\nconst openIn3DViewer = () => {\n const props = { node: node }\n\n useDialogStore().showDialog({\n key: 'global-load3d-viewer',\n title: t('load3d.viewer.title'),\n component: Load3DViewerContent,\n props: props,\n dialogComponentProps: {\n style: 'width: 80vw; height: 80vh;',\n maximizable: true,\n onClose: async () => {\n await useLoad3dService().handleViewerClose(props.node)\n }\n }\n })\n}\n</script>\n\n<style scoped></style>\n","<template>\n <div\n class=\"relative size-full\"\n @mouseenter=\"handleMouseEnter\"\n @mouseleave=\"handleMouseLeave\"\n @pointerdown.stop\n @pointermove.stop\n @pointerup.stop\n >\n <Load3DScene\n v-if=\"node\"\n :initialize-load3d=\"initializeLoad3d\"\n :cleanup=\"cleanup\"\n :loading=\"loading\"\n :loading-message=\"loadingMessage\"\n :on-model-drop=\"isPreview ? undefined : handleModelDrop\"\n :is-preview=\"isPreview\"\n />\n <div class=\"pointer-events-none absolute top-0 left-0 size-full\">\n <Load3DControls\n v-model:scene-config=\"sceneConfig\"\n v-model:model-config=\"modelConfig\"\n v-model:camera-config=\"cameraConfig\"\n v-model:light-config=\"lightConfig\"\n :is-splat-model=\"isSplatModel\"\n :is-ply-model=\"isPlyModel\"\n :has-skeleton=\"hasSkeleton\"\n @update-background-image=\"handleBackgroundImageUpdate\"\n @export-model=\"handleExportModel\"\n />\n <AnimationControls\n v-if=\"animations && animations.length > 0\"\n v-model:animations=\"animations\"\n v-model:playing=\"playing\"\n v-model:selected-speed=\"selectedSpeed\"\n v-model:selected-animation=\"selectedAnimation\"\n v-model:animation-progress=\"animationProgress\"\n v-model:animation-duration=\"animationDuration\"\n @seek=\"handleSeek\"\n />\n </div>\n <div\n v-if=\"enable3DViewer && node\"\n class=\"pointer-events-auto absolute top-12 right-2 z-20\"\n >\n <ViewerControls :node=\"node as LGraphNode\" />\n </div>\n\n <div\n v-if=\"!isPreview\"\n class=\"pointer-events-auto absolute right-2 z-20\"\n :class=\"{\n 'top-12': !enable3DViewer,\n 'top-24': enable3DViewer\n }\"\n >\n <RecordingControls\n v-model:is-recording=\"isRecording\"\n v-model:has-recording=\"hasRecording\"\n v-model:recording-duration=\"recordingDuration\"\n @start-recording=\"handleStartRecording\"\n @stop-recording=\"handleStopRecording\"\n @export-recording=\"handleExportRecording\"\n @clear-recording=\"handleClearRecording\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport type { Ref } from 'vue'\n\nimport Load3DControls from '@/components/load3d/Load3DControls.vue'\nimport Load3DScene from '@/components/load3d/Load3DScene.vue'\nimport AnimationControls from '@/components/load3d/controls/AnimationControls.vue'\nimport RecordingControls from '@/components/load3d/controls/RecordingControls.vue'\nimport ViewerControls from '@/components/load3d/controls/ViewerControls.vue'\nimport { useLoad3d } from '@/composables/useLoad3d'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport { useSettingStore } from '@/platform/settings/settingStore'\nimport type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema'\nimport { app } from '@/scripts/app'\nimport type { ComponentWidget } from '@/scripts/domWidget'\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\n\nconst props = defineProps<{\n widget: ComponentWidget<string[]> | SimplifiedWidget\n nodeId?: NodeId\n}>()\n\nfunction isComponentWidget(\n widget: ComponentWidget<string[]> | SimplifiedWidget\n): widget is ComponentWidget<string[]> {\n return 'node' in widget && widget.node !== undefined\n}\n\nconst node = ref<LGraphNode | null>(null)\n\nif (isComponentWidget(props.widget)) {\n node.value = props.widget.node\n} else if (props.nodeId) {\n onMounted(() => {\n node.value = app.rootGraph?.getNodeById(props.nodeId!) || null\n })\n}\n\nconst {\n // configs\n sceneConfig,\n modelConfig,\n cameraConfig,\n lightConfig,\n\n // other state\n isRecording,\n isPreview,\n isSplatModel,\n isPlyModel,\n hasSkeleton,\n hasRecording,\n recordingDuration,\n animations,\n playing,\n selectedSpeed,\n selectedAnimation,\n animationProgress,\n animationDuration,\n loading,\n loadingMessage,\n\n // Methods\n initializeLoad3d,\n handleMouseEnter,\n handleMouseLeave,\n handleStartRecording,\n handleStopRecording,\n handleExportRecording,\n handleClearRecording,\n handleSeek,\n handleBackgroundImageUpdate,\n handleExportModel,\n handleModelDrop,\n cleanup\n} = useLoad3d(node as Ref<LGraphNode | null>)\n\nconst enable3DViewer = computed(() =>\n useSettingStore().get('Comfy.Load3D.3DViewerEnable')\n)\n</script>\n"],"names":["value","_useModel","__props","showSlider","ref","toggleSlider","__name","closeSlider","e","onMounted","onUnmounted","cameraType","fov","showFOVButton","computed","switchCamera","emit","__emit","showExportFormats","exportFormats","toggleExportFormats","exportModel","format","closeExportFormatsList","lightIntensity","materialMode","showLightIntensityButton","showLightIntensity","lightIntensityMaximum","useSettingStore","lightIntensityMinimum","lightAdjustmentIncrement","toggleLightIntensity","closeLightSlider","upDirection","showSkeleton","showUpDirection","showMaterialMode","upDirections","materialModes","modes","toggleUpDirection","selectUpDirection","direction","toggleMaterialMode","selectMaterialMode","mode","formatMaterialMode","t","closeSceneSlider","target","showGrid","backgroundColor","backgroundImage","backgroundRenderMode","hasBackgroundImage","colorPickerRef","imagePickerRef","toggleGrid","updateBackgroundColor","color","openColorPicker","openImagePicker","uploadBackgroundImage","event","input","removeBackgroundImage","toggleBackgroundRenderMode","sceneConfig","modelConfig","cameraConfig","lightConfig","isMenuOpen","activeCategory","categoryLabels","availableCategories","showSceneControls","showModelControls","showCameraControls","showLightControls","showExportControls","toggleMenu","selectCategory","category","getCategoryIcon","handleBackgroundImageUpdate","file","handleExportModel","props","container","isDragging","dragMessage","handleDragOver","handleDragLeave","handleDrop","useLoad3dDrag","hasRecording","isRecording","recordingDuration","toggleRecording","handleExportRecording","handleClearRecording","formatDuration","seconds","minutes","remainingSeconds","openIn3DViewer","useDialogStore","Load3DViewerContent","useLoad3dService","isComponentWidget","widget","node","app","isPreview","isSplatModel","isPlyModel","hasSkeleton","animations","playing","selectedSpeed","selectedAnimation","animationProgress","animationDuration","loading","loadingMessage","initializeLoad3d","handleMouseEnter","handleMouseLeave","handleStartRecording","handleStopRecording","handleSeek","handleModelDrop","cleanup","useLoad3d","enable3DViewer"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var s=Object.defineProperty;var r=(t,e)=>s(t,"name",{value:e,configurable:!0});import{d as a}from"./index-
|
|
2
|
-
//# sourceMappingURL=Media3DTop-
|
|
1
|
+
var s=Object.defineProperty;var r=(t,e)=>s(t,"name",{value:e,configurable:!0});import{d as a}from"./index-U7jagKl8.js";import{c as i,d as l,e as o,u as d}from"./vendor-other-Dsj-QuOx.js";import"./vendor-primevue-Cif--Rbw.js";import"./vendor-vue-DNQSPQQ2.js";import"./vendor-reka-ui-WjwjFuZo.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-ByuY8CdW.js";import"./vendor-tiptap-YMjM2h-Z.js";const c={},n={class:"relative size-full overflow-hidden rounded"},m={class:"flex size-full flex-col items-center justify-center gap-2 bg-modal-card-placeholder-background transition-transform duration-300 group-hover:scale-105 group-data-[selected=true]:scale-105"},p={class:"text-sm text-base-foreground"};function u(t,e){return l(),i("div",n,[o("div",m,[e[0]||(e[0]=o("i",{class:"icon-[lucide--box] text-3xl text-muted-foreground"},null,-1)),o("span",p,d(t.$t("assetBrowser.media.threeDModelPlaceholder")),1)])])}r(u,"_sfc_render");const D=a(c,[["render",u]]);export{D as default};
|
|
2
|
+
//# sourceMappingURL=Media3DTop-CQp4nFvB.js.map
|