comfyui-frontend-package 1.37.1__py3-none-any.whl → 1.37.2__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-CTGWwQqp.js → AboutPanel-DLChcmDc.js} +2 -2
- comfyui_frontend_package/static/assets/{AboutPanel-CTGWwQqp.js.map → AboutPanel-DLChcmDc.js.map} +1 -1
- comfyui_frontend_package/static/assets/{AudioPreviewPlayer-DDwwIMxr.js → AudioPreviewPlayer-B8RfUAL6.js} +2 -2
- comfyui_frontend_package/static/assets/{AudioPreviewPlayer-DDwwIMxr.js.map → AudioPreviewPlayer-B8RfUAL6.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ComfyQueueButton-BDRXGOWF.js → ComfyQueueButton-DRgA2g3T.js} +2 -2
- comfyui_frontend_package/static/assets/{ComfyQueueButton-BDRXGOWF.js.map → ComfyQueueButton-DRgA2g3T.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ExtensionPanel-Dxe7qElb.js → ExtensionPanel-CpMR9h6B.js} +2 -2
- comfyui_frontend_package/static/assets/{ExtensionPanel-Dxe7qElb.js.map → ExtensionPanel-CpMR9h6B.js.map} +1 -1
- comfyui_frontend_package/static/assets/{GraphView-Cx4wYzNo.js → GraphView-xK7kCVVH.js} +5 -5
- comfyui_frontend_package/static/assets/{GraphView-Cx4wYzNo.js.map → GraphView-xK7kCVVH.js.map} +1 -1
- comfyui_frontend_package/static/assets/{KeybindingPanel-pmyMPZHn.js → KeybindingPanel-CM_PwegN.js} +2 -2
- comfyui_frontend_package/static/assets/{KeybindingPanel-pmyMPZHn.js.map → KeybindingPanel-CM_PwegN.js.map} +1 -1
- comfyui_frontend_package/static/assets/{LazyImage.vue_vue_type_script_setup_true_lang-C3ynRbso.js → LazyImage.vue_vue_type_script_setup_true_lang-Dza6G4hd.js} +2 -2
- comfyui_frontend_package/static/assets/{LazyImage.vue_vue_type_script_setup_true_lang-C3ynRbso.js.map → LazyImage.vue_vue_type_script_setup_true_lang-Dza6G4hd.js.map} +1 -1
- comfyui_frontend_package/static/assets/{LegacyCreditsPanel-DSos04Q3.js → LegacyCreditsPanel-BujZmWgC.js} +2 -2
- comfyui_frontend_package/static/assets/{LegacyCreditsPanel-DSos04Q3.js.map → LegacyCreditsPanel-BujZmWgC.js.map} +1 -1
- comfyui_frontend_package/static/assets/{Load3D-Cu5zG2Cw.js → Load3D-DWafZUud.js} +2 -2
- comfyui_frontend_package/static/assets/Load3D-DWafZUud.js.map +1 -0
- comfyui_frontend_package/static/assets/{Load3D.vue_vue_type_script_setup_true_lang-BJ0IqFdp.js → Load3D.vue_vue_type_script_setup_true_lang-_XswHXHt.js} +2 -2
- comfyui_frontend_package/static/assets/{Load3D.vue_vue_type_script_setup_true_lang-BJ0IqFdp.js.map → Load3D.vue_vue_type_script_setup_true_lang-_XswHXHt.js.map} +1 -1
- comfyui_frontend_package/static/assets/{Media3DBottom-DsMr4v-s.js → Media3DBottom-Z9nkVIUT.js} +2 -2
- comfyui_frontend_package/static/assets/{Media3DBottom-DsMr4v-s.js.map → Media3DBottom-Z9nkVIUT.js.map} +1 -1
- comfyui_frontend_package/static/assets/{Media3DTop-DQ18QW3M.js → Media3DTop-DKaMli8A.js} +2 -2
- comfyui_frontend_package/static/assets/{Media3DTop-DQ18QW3M.js.map → Media3DTop-DKaMli8A.js.map} +1 -1
- comfyui_frontend_package/static/assets/{MediaAudioBottom-99GB7NqQ.js → MediaAudioBottom-B62n8OnR.js} +2 -2
- comfyui_frontend_package/static/assets/{MediaAudioBottom-99GB7NqQ.js.map → MediaAudioBottom-B62n8OnR.js.map} +1 -1
- comfyui_frontend_package/static/assets/{MediaImageBottom-C6Bpu_d9.js → MediaImageBottom-DChcPA0h.js} +2 -2
- comfyui_frontend_package/static/assets/{MediaImageBottom-C6Bpu_d9.js.map → MediaImageBottom-DChcPA0h.js.map} +1 -1
- comfyui_frontend_package/static/assets/{MediaTitle.vue_vue_type_script_setup_true_lang-BFgOqxto.js → MediaTitle.vue_vue_type_script_setup_true_lang-CFkifLSX.js} +2 -2
- comfyui_frontend_package/static/assets/{MediaTitle.vue_vue_type_script_setup_true_lang-BFgOqxto.js.map → MediaTitle.vue_vue_type_script_setup_true_lang-CFkifLSX.js.map} +1 -1
- comfyui_frontend_package/static/assets/{MediaVideoBottom-DgdszioB.js → MediaVideoBottom-fWb8qHcu.js} +2 -2
- comfyui_frontend_package/static/assets/{MediaVideoBottom-DgdszioB.js.map → MediaVideoBottom-fWb8qHcu.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ServerConfigPanel-BlC22rDX.js → ServerConfigPanel-umnHESaV.js} +2 -2
- comfyui_frontend_package/static/assets/{ServerConfigPanel-BlC22rDX.js.map → ServerConfigPanel-umnHESaV.js.map} +1 -1
- comfyui_frontend_package/static/assets/SubscriptionRequiredDialogContent-BdL9OjAj.js +2 -0
- comfyui_frontend_package/static/assets/SubscriptionRequiredDialogContent-BdL9OjAj.js.map +1 -0
- comfyui_frontend_package/static/assets/{UserPanel-Ccmz94Hx.js → UserPanel-CwkZrKjy.js} +2 -2
- comfyui_frontend_package/static/assets/{UserPanel-Ccmz94Hx.js.map → UserPanel-CwkZrKjy.js.map} +1 -1
- comfyui_frontend_package/static/assets/{UserSelectView-DVFY57_D.js → UserSelectView-TeLhcKfi.js} +2 -2
- comfyui_frontend_package/static/assets/{UserSelectView-DVFY57_D.js.map → UserSelectView-TeLhcKfi.js.map} +1 -1
- comfyui_frontend_package/static/assets/{ValueControlPopover-BLxzZY7u.js → ValueControlPopover-CSvGimoz.js} +2 -2
- comfyui_frontend_package/static/assets/{ValueControlPopover-BLxzZY7u.js.map → ValueControlPopover-CSvGimoz.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetAudioUI-BtX1BUnO.js → WidgetAudioUI-CfZQ32fr.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetAudioUI-BtX1BUnO.js.map → WidgetAudioUI-CfZQ32fr.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetButton-CyIVF8iQ.js → WidgetButton-Bo9rWiUg.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetButton-CyIVF8iQ.js.map → WidgetButton-Bo9rWiUg.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetColorPicker-BcGFRyIl.js → WidgetColorPicker-CyNNmSC9.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetColorPicker-BcGFRyIl.js.map → WidgetColorPicker-CyNNmSC9.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetGalleria-CfluZbRG.js → WidgetGalleria-X2v42F2a.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetGalleria-CfluZbRG.js.map → WidgetGalleria-X2v42F2a.js.map} +1 -1
- comfyui_frontend_package/static/assets/WidgetInputNumber-BL6P8as9.js +2 -0
- comfyui_frontend_package/static/assets/WidgetInputNumber-BL6P8as9.js.map +1 -0
- comfyui_frontend_package/static/assets/{WidgetInputNumber.vue_vue_type_script_setup_true_lang-Bmxd6b-H.js → WidgetInputNumber.vue_vue_type_script_setup_true_lang-DPaOKLY2.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetInputNumber.vue_vue_type_script_setup_true_lang-Bmxd6b-H.js.map → WidgetInputNumber.vue_vue_type_script_setup_true_lang-DPaOKLY2.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetInputText-CecuaK0n.js → WidgetInputText-LR89p-m1.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetInputText-CecuaK0n.js.map → WidgetInputText-LR89p-m1.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetLayoutField.vue_vue_type_script_setup_true_lang-CbjST6rI.js → WidgetLayoutField.vue_vue_type_script_setup_true_lang-C5dBI8au.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetLayoutField.vue_vue_type_script_setup_true_lang-CbjST6rI.js.map → WidgetLayoutField.vue_vue_type_script_setup_true_lang-C5dBI8au.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetLegacy-B8P9bOsC.js → WidgetLegacy-CJpsLPyI.js} +2 -2
- comfyui_frontend_package/static/assets/WidgetLegacy-CJpsLPyI.js.map +1 -0
- comfyui_frontend_package/static/assets/{WidgetMarkdown-nXPgrFZi.js → WidgetMarkdown-DrH35WSE.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetMarkdown-nXPgrFZi.js.map → WidgetMarkdown-DrH35WSE.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetRecordAudio-C6urheNU.js → WidgetRecordAudio-DL4kMpXw.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetRecordAudio-C6urheNU.js.map → WidgetRecordAudio-DL4kMpXw.js.map} +1 -1
- comfyui_frontend_package/static/assets/WidgetSelect-Bk32AcQe.js +2 -0
- comfyui_frontend_package/static/assets/WidgetSelect-Bk32AcQe.js.map +1 -0
- comfyui_frontend_package/static/assets/{WidgetSelect.vue_vue_type_script_setup_true_lang-DTcBUlhn.js → WidgetSelect.vue_vue_type_script_setup_true_lang-CHjOuVyH.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetSelect.vue_vue_type_script_setup_true_lang-DTcBUlhn.js.map → WidgetSelect.vue_vue_type_script_setup_true_lang-CHjOuVyH.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetTextarea-DuXhEnsH.js → WidgetTextarea-orpeeVx4.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetTextarea-DuXhEnsH.js.map → WidgetTextarea-orpeeVx4.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetToggleSwitch-BTeDQHuf.js → WidgetToggleSwitch-CSN313_V.js} +2 -2
- comfyui_frontend_package/static/assets/{WidgetToggleSwitch-BTeDQHuf.js.map → WidgetToggleSwitch-CSN313_V.js.map} +1 -1
- comfyui_frontend_package/static/assets/{WidgetWithControl.vue_vue_type_script_setup_true_lang-DFvQ9Mdf.js → WidgetWithControl.vue_vue_type_script_setup_true_lang-CU_cmbAA.js} +3 -3
- comfyui_frontend_package/static/assets/{WidgetWithControl.vue_vue_type_script_setup_true_lang-DFvQ9Mdf.js.map → WidgetWithControl.vue_vue_type_script_setup_true_lang-CU_cmbAA.js.map} +1 -1
- comfyui_frontend_package/static/assets/{audioService-B43wn81n.js → audioService-DvqSt3rU.js} +2 -2
- comfyui_frontend_package/static/assets/{audioService-B43wn81n.js.map → audioService-DvqSt3rU.js.map} +1 -1
- comfyui_frontend_package/static/assets/{audioUtils-iqnmct8N.js → audioUtils-bxVioEE3.js} +2 -2
- comfyui_frontend_package/static/assets/{audioUtils-iqnmct8N.js.map → audioUtils-bxVioEE3.js.map} +1 -1
- comfyui_frontend_package/static/assets/{index-FoJ8Eu4a.js → index-BODInyrK.js} +21 -21
- comfyui_frontend_package/static/assets/{index-FoJ8Eu4a.js.map → index-BODInyrK.js.map} +1 -1
- comfyui_frontend_package/static/assets/{index-BbFKUlCt.js → index-CyS0uSKu.js} +2 -2
- comfyui_frontend_package/static/assets/{index-BbFKUlCt.js.map → index-CyS0uSKu.js.map} +1 -1
- comfyui_frontend_package/static/assets/{index-B2FA5n0E.js → index-fwtcK193.js} +2 -2
- comfyui_frontend_package/static/assets/{index-B2FA5n0E.js.map → index-fwtcK193.js.map} +1 -1
- comfyui_frontend_package/static/assets/{keybindingService-D_lPZZ7u.js → keybindingService-DR_nPGKY.js} +2 -2
- comfyui_frontend_package/static/assets/{keybindingService-D_lPZZ7u.js.map → keybindingService-DR_nPGKY.js.map} +1 -1
- comfyui_frontend_package/static/index.html +1 -1
- {comfyui_frontend_package-1.37.1.dist-info → comfyui_frontend_package-1.37.2.dist-info}/METADATA +1 -1
- {comfyui_frontend_package-1.37.1.dist-info → comfyui_frontend_package-1.37.2.dist-info}/RECORD +91 -91
- comfyui_frontend_package/static/assets/Load3D-Cu5zG2Cw.js.map +0 -1
- comfyui_frontend_package/static/assets/SubscriptionRequiredDialogContent-CY-BY6v5.js +0 -2
- comfyui_frontend_package/static/assets/SubscriptionRequiredDialogContent-CY-BY6v5.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetInputNumber-BTFa3T0H.js +0 -2
- comfyui_frontend_package/static/assets/WidgetInputNumber-BTFa3T0H.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetLegacy-B8P9bOsC.js.map +0 -1
- comfyui_frontend_package/static/assets/WidgetSelect-VznDfSeg.js +0 -2
- comfyui_frontend_package/static/assets/WidgetSelect-VznDfSeg.js.map +0 -1
- {comfyui_frontend_package-1.37.1.dist-info → comfyui_frontend_package-1.37.2.dist-info}/WHEEL +0 -0
- {comfyui_frontend_package-1.37.1.dist-info → comfyui_frontend_package-1.37.2.dist-info}/top_level.txt +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetInputNumber.vue_vue_type_script_setup_true_lang-Bmxd6b-H.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue","../../src/components/ui/slider/Slider.vue","../../src/renderer/extensions/vueNodes/widgets/composables/useNumberStepCalculation.ts","../../src/renderer/extensions/vueNodes/widgets/composables/useNumberWidgetButtonPt.ts","../../src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberSlider.vue","../../src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumber.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport InputNumber from 'primevue/inputnumber'\nimport { computed } from 'vue'\n\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\nimport {\n INPUT_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport { WidgetInputBaseClass } from './layout'\nimport WidgetLayoutField from './layout/WidgetLayoutField.vue'\n\nconst props = defineProps<{\n widget: SimplifiedWidget<number>\n}>()\n\nconst modelValue = defineModel<number>({ default: 0 })\n\nconst filteredProps = computed(() =>\n filterWidgetProps(props.widget.options, INPUT_EXCLUDED_PROPS)\n)\n\n// Get the precision value for proper number formatting\nconst precision = computed(() => {\n const p = props.widget.options?.precision\n // Treat negative or non-numeric precision as undefined\n return typeof p === 'number' && p >= 0 ? p : undefined\n})\n\n// Calculate the step value based on precision or widget options\nconst stepValue = computed(() => {\n // Use step2 (correct input spec value) instead of step (legacy 10x value)\n if (props.widget.options?.step2 !== undefined) {\n return Number(props.widget.options.step2)\n }\n // Otherwise, derive from precision\n if (precision.value !== undefined) {\n if (precision.value === 0) {\n return 1\n }\n // For precision > 0, step = 1 / (10^precision)\n // precision 1 → 0.1, precision 2 → 0.01, etc.\n return Number((1 / Math.pow(10, precision.value)).toFixed(precision.value))\n }\n // Default to 'any' for unrestricted stepping\n return 0\n})\n\n// Disable grouping separators by default unless explicitly enabled by the node author\nconst useGrouping = computed(() => {\n return props.widget.options?.useGrouping === true\n})\n\n// Check if increment/decrement buttons should be disabled due to precision limits\nconst buttonsDisabled = computed(() => {\n const currentValue = modelValue.value ?? 0\n return (\n !Number.isFinite(currentValue) ||\n Math.abs(currentValue) > Number.MAX_SAFE_INTEGER\n )\n})\n\nconst buttonTooltip = computed(() => {\n if (buttonsDisabled.value) {\n return 'Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)'\n }\n return null\n})\n</script>\n\n<template>\n <WidgetLayoutField :widget>\n <InputNumber\n v-model=\"modelValue\"\n v-tooltip=\"buttonTooltip\"\n v-bind=\"filteredProps\"\n fluid\n button-layout=\"horizontal\"\n size=\"small\"\n variant=\"outlined\"\n :step=\"stepValue\"\n :min-fraction-digits=\"precision\"\n :max-fraction-digits=\"precision\"\n :use-grouping=\"useGrouping\"\n :class=\"cn(WidgetInputBaseClass, 'grow text-xs')\"\n :aria-label=\"widget.name\"\n :show-buttons=\"!buttonsDisabled\"\n :pt=\"{\n root: {\n class: cn(\n '[&>input]:bg-transparent [&>input]:border-0',\n '[&>input]:truncate [&>input]:min-w-[4ch]',\n $slots.default && '[&>input]:pr-7'\n )\n },\n decrementButton: {\n class: 'w-8 border-0'\n },\n incrementButton: {\n class: 'w-8 border-0'\n }\n }\"\n >\n <template #incrementicon>\n <span class=\"pi pi-plus text-sm\" />\n </template>\n <template #decrementicon>\n <span class=\"pi pi-minus text-sm\" />\n </template>\n </InputNumber>\n <div class=\"absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex\">\n <slot />\n </div>\n </WidgetLayoutField>\n</template>\n\n<style scoped>\n:deep(.p-inputnumber-input) {\n height: 1.625rem;\n margin: 1px 0;\n box-shadow: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { reactiveOmit } from '@vueuse/core'\nimport type { SliderRootEmits, SliderRootProps } from 'reka-ui'\nimport {\n SliderRange,\n SliderRoot,\n SliderThumb,\n SliderTrack,\n useForwardPropsEmits\n} from 'reka-ui'\nimport { ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\n\nimport { cn } from '@/utils/tailwindUtil'\n\nconst props = defineProps<\n // eslint-disable-next-line vue/no-unused-properties\n SliderRootProps & { class?: HTMLAttributes['class'] }\n>()\n\nconst pressed = ref(false)\nconst setPressed = (val: boolean) => {\n pressed.value = val\n}\n\nconst emits = defineEmits<SliderRootEmits>()\n\nconst delegatedProps = reactiveOmit(props, 'class')\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <SliderRoot\n v-slot=\"{ modelValue }\"\n data-slot=\"slider\"\n :class=\"\n cn(\n 'relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50',\n 'data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col',\n props.class\n )\n \"\n v-bind=\"forwarded\"\n @slide-start=\"() => setPressed(true)\"\n @slide-move=\"() => setPressed(true)\"\n @slide-end=\"() => setPressed(false)\"\n >\n <SliderTrack\n data-slot=\"slider-track\"\n :class=\"\n cn(\n 'bg-node-stroke relative grow overflow-hidden rounded-full',\n 'cursor-pointer overflow-visible',\n `before:absolute before:-inset-2 before:block before:bg-transparent`,\n 'data-[orientation=horizontal]:h-0.5 data-[orientation=horizontal]:w-full',\n 'data-[orientation=vertical]:h-full data-[orientation=vertical]:w-0.5'\n )\n \"\n >\n <SliderRange\n data-slot=\"slider-range\"\n class=\"absolute bg-node-component-surface-highlight data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full\"\n />\n </SliderTrack>\n\n <SliderThumb\n v-for=\"(_, key) in modelValue\"\n :key=\"key\"\n data-slot=\"slider-thumb\"\n :class=\"\n cn(\n 'bg-node-component-surface-highlight ring-node-component-surface-selected block size-3.5 shrink-0 rounded-full shadow-sm transition-[color,box-shadow]',\n 'cursor-grab',\n 'before:absolute before:-inset-1 before:block before:bg-transparent before:rounded-full',\n 'hover:ring-2 focus-visible:ring-2 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50',\n { 'cursor-grabbing': pressed }\n )\n \"\n />\n </SliderRoot>\n</template>\n","import { computed, toValue } from 'vue'\nimport type { MaybeRefOrGetter } from 'vue'\n\ninterface NumberWidgetOptions {\n step2?: number\n precision?: number\n}\n\n/**\n * Shared composable for calculating step values in number input widgets\n * Handles both explicit step2 values and precision-derived steps\n */\nexport function useNumberStepCalculation(\n options: NumberWidgetOptions | undefined,\n precisionArg: MaybeRefOrGetter<number | undefined>,\n returnUndefinedForDefault = false\n) {\n return computed(() => {\n const precision = toValue(precisionArg)\n // Use step2 (correct input spec value) instead of step (legacy 10x value)\n if (options?.step2 !== undefined) {\n return Number(options.step2)\n }\n\n if (precision === undefined) {\n return returnUndefinedForDefault ? undefined : 0\n }\n\n if (precision === 0) return 1\n\n // For precision > 0, step = 1 / (10^precision)\n const step = 1 / Math.pow(10, precision)\n return returnUndefinedForDefault ? step : Number(step.toFixed(precision))\n })\n}\n","import { cn } from '@comfyorg/tailwind-utils'\n\nconst sharedButtonClasses = cn(\n 'inline-flex items-center justify-center border-0 bg-transparent text-inherit transition-colors duration-150 ease-in-out ',\n 'hover:bg-node-component-surface-hovered active:bg-node-component-surface-selected',\n 'disabled:bg-node-component-disabled disabled:text-node-icon-disabled disabled:cursor-not-allowed'\n)\n\nexport function useNumberWidgetButtonPt(options?: {\n roundedLeft?: boolean\n roundedRight?: boolean\n}) {\n const { roundedLeft = false, roundedRight = false } = options ?? {}\n\n const increment = cn(sharedButtonClasses, roundedRight && 'rounded-r-lg')\n const decrement = cn(sharedButtonClasses, roundedLeft && 'rounded-l-lg')\n\n return {\n incrementButton: {\n class: increment\n },\n decrementButton: {\n class: decrement\n }\n }\n}\n","<template>\n <WidgetLayoutField :widget=\"widget\">\n <div :class=\"cn(WidgetInputBaseClass, 'flex items-center gap-2 pl-3 pr-2')\">\n <Slider\n :model-value=\"[modelValue]\"\n v-bind=\"filteredProps\"\n class=\"flex-grow text-xs\"\n :step=\"stepValue\"\n :aria-label=\"widget.name\"\n @update:model-value=\"updateLocalValue\"\n />\n <InputNumber\n :key=\"timesEmptied\"\n :model-value=\"modelValue\"\n v-bind=\"filteredProps\"\n :step=\"stepValue\"\n :min-fraction-digits=\"precision\"\n :max-fraction-digits=\"precision\"\n :aria-label=\"widget.name\"\n size=\"small\"\n pt:pc-input-text:root=\"min-w-[4ch] bg-transparent border-none text-center truncate\"\n class=\"w-16\"\n :pt=\"sliderNumberPt\"\n @update:model-value=\"handleNumberInputUpdate\"\n />\n </div>\n </WidgetLayoutField>\n</template>\n\n<script setup lang=\"ts\">\nimport InputNumber from 'primevue/inputnumber'\nimport { computed, ref } from 'vue'\n\nimport Slider from '@/components/ui/slider/Slider.vue'\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\nimport {\n STANDARD_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport { useNumberStepCalculation } from '../composables/useNumberStepCalculation'\nimport { useNumberWidgetButtonPt } from '../composables/useNumberWidgetButtonPt'\nimport { WidgetInputBaseClass } from './layout'\nimport WidgetLayoutField from './layout/WidgetLayoutField.vue'\n\nconst { widget } = defineProps<{\n widget: SimplifiedWidget<number>\n}>()\n\nconst modelValue = defineModel<number>({ default: 0 })\n\nconst timesEmptied = ref(0)\n\nconst updateLocalValue = (newValue: number[] | undefined): void => {\n if (newValue?.length) modelValue.value = newValue[0]\n}\n\nconst handleNumberInputUpdate = (newValue: number | undefined) => {\n if (newValue !== undefined) {\n updateLocalValue([newValue])\n return\n }\n timesEmptied.value += 1\n}\n\nconst filteredProps = computed(() =>\n filterWidgetProps(widget.options, STANDARD_EXCLUDED_PROPS)\n)\n\nconst p = widget.options?.precision\nconst precision = typeof p === 'number' && p >= 0 ? p : undefined\n\n// Calculate the step value based on precision or widget options\nconst stepValue = useNumberStepCalculation(widget.options, precision, true)\n\nconst sliderNumberPt = useNumberWidgetButtonPt({\n roundedLeft: true,\n roundedRight: true\n})\n</script>\n\n<style scoped>\n:deep(.p-inputnumber-button.p-disabled .pi),\n:deep(.p-inputnumber-button.p-disabled .p-icon) {\n color: var(--color-node-icon-disabled) !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type {\n SimplifiedControlWidget,\n SimplifiedWidget\n} from '@/types/simplifiedWidget'\n\nimport WidgetInputNumberInput from './WidgetInputNumberInput.vue'\nimport WidgetInputNumberSlider from './WidgetInputNumberSlider.vue'\nimport WidgetWithControl from './WidgetWithControl.vue'\n\nconst props = defineProps<{\n widget: SimplifiedWidget<number>\n}>()\n\nconst modelValue = defineModel<number>({ default: 0 })\n\nconst hasControlAfterGenerate = computed(() => {\n return !!props.widget.controlWidget\n})\n</script>\n\n<template>\n <WidgetWithControl\n v-if=\"hasControlAfterGenerate\"\n v-model=\"modelValue\"\n :widget=\"widget as SimplifiedControlWidget<number>\"\n :component=\"\n widget.type === 'slider'\n ? WidgetInputNumberSlider\n : WidgetInputNumberInput\n \"\n />\n <component\n :is=\"\n widget.type === 'slider'\n ? WidgetInputNumberSlider\n : WidgetInputNumberInput\n \"\n v-else\n v-model=\"modelValue\"\n :widget=\"widget\"\n v-bind=\"$attrs\"\n />\n</template>\n"],"names":["props","__props","modelValue","_useModel","filteredProps","computed","filterWidgetProps","INPUT_EXCLUDED_PROPS","precision","p","stepValue","useGrouping","buttonsDisabled","currentValue","buttonTooltip","pressed","ref","setPressed","__name","val","emits","__emit","delegatedProps","reactiveOmit","forwarded","useForwardPropsEmits","useNumberStepCalculation","options","precisionArg","returnUndefinedForDefault","toValue","step","sharedButtonClasses","cn","useNumberWidgetButtonPt","roundedLeft","roundedRight","increment","decrement","timesEmptied","updateLocalValue","newValue","handleNumberInputUpdate","STANDARD_EXCLUDED_PROPS","sliderNumberPt","hasControlAfterGenerate"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WidgetInputNumber.vue_vue_type_script_setup_true_lang-DPaOKLY2.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue","../../src/components/ui/slider/Slider.vue","../../src/renderer/extensions/vueNodes/widgets/composables/useNumberStepCalculation.ts","../../src/renderer/extensions/vueNodes/widgets/composables/useNumberWidgetButtonPt.ts","../../src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberSlider.vue","../../src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumber.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport InputNumber from 'primevue/inputnumber'\nimport { computed } from 'vue'\n\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\nimport {\n INPUT_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport { WidgetInputBaseClass } from './layout'\nimport WidgetLayoutField from './layout/WidgetLayoutField.vue'\n\nconst props = defineProps<{\n widget: SimplifiedWidget<number>\n}>()\n\nconst modelValue = defineModel<number>({ default: 0 })\n\nconst filteredProps = computed(() =>\n filterWidgetProps(props.widget.options, INPUT_EXCLUDED_PROPS)\n)\n\n// Get the precision value for proper number formatting\nconst precision = computed(() => {\n const p = props.widget.options?.precision\n // Treat negative or non-numeric precision as undefined\n return typeof p === 'number' && p >= 0 ? p : undefined\n})\n\n// Calculate the step value based on precision or widget options\nconst stepValue = computed(() => {\n // Use step2 (correct input spec value) instead of step (legacy 10x value)\n if (props.widget.options?.step2 !== undefined) {\n return Number(props.widget.options.step2)\n }\n // Otherwise, derive from precision\n if (precision.value !== undefined) {\n if (precision.value === 0) {\n return 1\n }\n // For precision > 0, step = 1 / (10^precision)\n // precision 1 → 0.1, precision 2 → 0.01, etc.\n return Number((1 / Math.pow(10, precision.value)).toFixed(precision.value))\n }\n // Default to 'any' for unrestricted stepping\n return 0\n})\n\n// Disable grouping separators by default unless explicitly enabled by the node author\nconst useGrouping = computed(() => {\n return props.widget.options?.useGrouping === true\n})\n\n// Check if increment/decrement buttons should be disabled due to precision limits\nconst buttonsDisabled = computed(() => {\n const currentValue = modelValue.value ?? 0\n return (\n !Number.isFinite(currentValue) ||\n Math.abs(currentValue) > Number.MAX_SAFE_INTEGER\n )\n})\n\nconst buttonTooltip = computed(() => {\n if (buttonsDisabled.value) {\n return 'Increment/decrement disabled: value exceeds JavaScript precision limit (±2^53)'\n }\n return null\n})\n</script>\n\n<template>\n <WidgetLayoutField :widget>\n <InputNumber\n v-model=\"modelValue\"\n v-tooltip=\"buttonTooltip\"\n v-bind=\"filteredProps\"\n fluid\n button-layout=\"horizontal\"\n size=\"small\"\n variant=\"outlined\"\n :step=\"stepValue\"\n :min-fraction-digits=\"precision\"\n :max-fraction-digits=\"precision\"\n :use-grouping=\"useGrouping\"\n :class=\"cn(WidgetInputBaseClass, 'grow text-xs')\"\n :aria-label=\"widget.name\"\n :show-buttons=\"!buttonsDisabled\"\n :pt=\"{\n root: {\n class: cn(\n '[&>input]:bg-transparent [&>input]:border-0',\n '[&>input]:truncate [&>input]:min-w-[4ch]',\n $slots.default && '[&>input]:pr-7'\n )\n },\n decrementButton: {\n class: 'w-8 border-0'\n },\n incrementButton: {\n class: 'w-8 border-0'\n }\n }\"\n >\n <template #incrementicon>\n <span class=\"pi pi-plus text-sm\" />\n </template>\n <template #decrementicon>\n <span class=\"pi pi-minus text-sm\" />\n </template>\n </InputNumber>\n <div class=\"absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex\">\n <slot />\n </div>\n </WidgetLayoutField>\n</template>\n\n<style scoped>\n:deep(.p-inputnumber-input) {\n height: 1.625rem;\n margin: 1px 0;\n box-shadow: none;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { reactiveOmit } from '@vueuse/core'\nimport type { SliderRootEmits, SliderRootProps } from 'reka-ui'\nimport {\n SliderRange,\n SliderRoot,\n SliderThumb,\n SliderTrack,\n useForwardPropsEmits\n} from 'reka-ui'\nimport { ref } from 'vue'\nimport type { HTMLAttributes } from 'vue'\n\nimport { cn } from '@/utils/tailwindUtil'\n\nconst props = defineProps<\n // eslint-disable-next-line vue/no-unused-properties\n SliderRootProps & { class?: HTMLAttributes['class'] }\n>()\n\nconst pressed = ref(false)\nconst setPressed = (val: boolean) => {\n pressed.value = val\n}\n\nconst emits = defineEmits<SliderRootEmits>()\n\nconst delegatedProps = reactiveOmit(props, 'class')\n\nconst forwarded = useForwardPropsEmits(delegatedProps, emits)\n</script>\n\n<template>\n <SliderRoot\n v-slot=\"{ modelValue }\"\n data-slot=\"slider\"\n :class=\"\n cn(\n 'relative flex w-full touch-none items-center select-none data-[disabled]:opacity-50',\n 'data-[orientation=vertical]:h-full data-[orientation=vertical]:min-h-44 data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col',\n props.class\n )\n \"\n v-bind=\"forwarded\"\n @slide-start=\"() => setPressed(true)\"\n @slide-move=\"() => setPressed(true)\"\n @slide-end=\"() => setPressed(false)\"\n >\n <SliderTrack\n data-slot=\"slider-track\"\n :class=\"\n cn(\n 'bg-node-stroke relative grow overflow-hidden rounded-full',\n 'cursor-pointer overflow-visible',\n `before:absolute before:-inset-2 before:block before:bg-transparent`,\n 'data-[orientation=horizontal]:h-0.5 data-[orientation=horizontal]:w-full',\n 'data-[orientation=vertical]:h-full data-[orientation=vertical]:w-0.5'\n )\n \"\n >\n <SliderRange\n data-slot=\"slider-range\"\n class=\"absolute bg-node-component-surface-highlight data-[orientation=horizontal]:h-full data-[orientation=vertical]:w-full\"\n />\n </SliderTrack>\n\n <SliderThumb\n v-for=\"(_, key) in modelValue\"\n :key=\"key\"\n data-slot=\"slider-thumb\"\n :class=\"\n cn(\n 'bg-node-component-surface-highlight ring-node-component-surface-selected block size-3.5 shrink-0 rounded-full shadow-sm transition-[color,box-shadow]',\n 'cursor-grab',\n 'before:absolute before:-inset-1 before:block before:bg-transparent before:rounded-full',\n 'hover:ring-2 focus-visible:ring-2 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50',\n { 'cursor-grabbing': pressed }\n )\n \"\n />\n </SliderRoot>\n</template>\n","import { computed, toValue } from 'vue'\nimport type { MaybeRefOrGetter } from 'vue'\n\ninterface NumberWidgetOptions {\n step2?: number\n precision?: number\n}\n\n/**\n * Shared composable for calculating step values in number input widgets\n * Handles both explicit step2 values and precision-derived steps\n */\nexport function useNumberStepCalculation(\n options: NumberWidgetOptions | undefined,\n precisionArg: MaybeRefOrGetter<number | undefined>,\n returnUndefinedForDefault = false\n) {\n return computed(() => {\n const precision = toValue(precisionArg)\n // Use step2 (correct input spec value) instead of step (legacy 10x value)\n if (options?.step2 !== undefined) {\n return Number(options.step2)\n }\n\n if (precision === undefined) {\n return returnUndefinedForDefault ? undefined : 0\n }\n\n if (precision === 0) return 1\n\n // For precision > 0, step = 1 / (10^precision)\n const step = 1 / Math.pow(10, precision)\n return returnUndefinedForDefault ? step : Number(step.toFixed(precision))\n })\n}\n","import { cn } from '@comfyorg/tailwind-utils'\n\nconst sharedButtonClasses = cn(\n 'inline-flex items-center justify-center border-0 bg-transparent text-inherit transition-colors duration-150 ease-in-out ',\n 'hover:bg-node-component-surface-hovered active:bg-node-component-surface-selected',\n 'disabled:bg-node-component-disabled disabled:text-node-icon-disabled disabled:cursor-not-allowed'\n)\n\nexport function useNumberWidgetButtonPt(options?: {\n roundedLeft?: boolean\n roundedRight?: boolean\n}) {\n const { roundedLeft = false, roundedRight = false } = options ?? {}\n\n const increment = cn(sharedButtonClasses, roundedRight && 'rounded-r-lg')\n const decrement = cn(sharedButtonClasses, roundedLeft && 'rounded-l-lg')\n\n return {\n incrementButton: {\n class: increment\n },\n decrementButton: {\n class: decrement\n }\n }\n}\n","<template>\n <WidgetLayoutField :widget=\"widget\">\n <div :class=\"cn(WidgetInputBaseClass, 'flex items-center gap-2 pl-3 pr-2')\">\n <Slider\n :model-value=\"[modelValue]\"\n v-bind=\"filteredProps\"\n class=\"flex-grow text-xs\"\n :step=\"stepValue\"\n :aria-label=\"widget.name\"\n @update:model-value=\"updateLocalValue\"\n />\n <InputNumber\n :key=\"timesEmptied\"\n :model-value=\"modelValue\"\n v-bind=\"filteredProps\"\n :step=\"stepValue\"\n :min-fraction-digits=\"precision\"\n :max-fraction-digits=\"precision\"\n :aria-label=\"widget.name\"\n size=\"small\"\n pt:pc-input-text:root=\"min-w-[4ch] bg-transparent border-none text-center truncate\"\n class=\"w-16\"\n :pt=\"sliderNumberPt\"\n @update:model-value=\"handleNumberInputUpdate\"\n />\n </div>\n </WidgetLayoutField>\n</template>\n\n<script setup lang=\"ts\">\nimport InputNumber from 'primevue/inputnumber'\nimport { computed, ref } from 'vue'\n\nimport Slider from '@/components/ui/slider/Slider.vue'\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\nimport {\n STANDARD_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport { useNumberStepCalculation } from '../composables/useNumberStepCalculation'\nimport { useNumberWidgetButtonPt } from '../composables/useNumberWidgetButtonPt'\nimport { WidgetInputBaseClass } from './layout'\nimport WidgetLayoutField from './layout/WidgetLayoutField.vue'\n\nconst { widget } = defineProps<{\n widget: SimplifiedWidget<number>\n}>()\n\nconst modelValue = defineModel<number>({ default: 0 })\n\nconst timesEmptied = ref(0)\n\nconst updateLocalValue = (newValue: number[] | undefined): void => {\n if (newValue?.length) modelValue.value = newValue[0]\n}\n\nconst handleNumberInputUpdate = (newValue: number | undefined) => {\n if (newValue !== undefined) {\n updateLocalValue([newValue])\n return\n }\n timesEmptied.value += 1\n}\n\nconst filteredProps = computed(() =>\n filterWidgetProps(widget.options, STANDARD_EXCLUDED_PROPS)\n)\n\nconst p = widget.options?.precision\nconst precision = typeof p === 'number' && p >= 0 ? p : undefined\n\n// Calculate the step value based on precision or widget options\nconst stepValue = useNumberStepCalculation(widget.options, precision, true)\n\nconst sliderNumberPt = useNumberWidgetButtonPt({\n roundedLeft: true,\n roundedRight: true\n})\n</script>\n\n<style scoped>\n:deep(.p-inputnumber-button.p-disabled .pi),\n:deep(.p-inputnumber-button.p-disabled .p-icon) {\n color: var(--color-node-icon-disabled) !important;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type {\n SimplifiedControlWidget,\n SimplifiedWidget\n} from '@/types/simplifiedWidget'\n\nimport WidgetInputNumberInput from './WidgetInputNumberInput.vue'\nimport WidgetInputNumberSlider from './WidgetInputNumberSlider.vue'\nimport WidgetWithControl from './WidgetWithControl.vue'\n\nconst props = defineProps<{\n widget: SimplifiedWidget<number>\n}>()\n\nconst modelValue = defineModel<number>({ default: 0 })\n\nconst hasControlAfterGenerate = computed(() => {\n return !!props.widget.controlWidget\n})\n</script>\n\n<template>\n <WidgetWithControl\n v-if=\"hasControlAfterGenerate\"\n v-model=\"modelValue\"\n :widget=\"widget as SimplifiedControlWidget<number>\"\n :component=\"\n widget.type === 'slider'\n ? WidgetInputNumberSlider\n : WidgetInputNumberInput\n \"\n />\n <component\n :is=\"\n widget.type === 'slider'\n ? WidgetInputNumberSlider\n : WidgetInputNumberInput\n \"\n v-else\n v-model=\"modelValue\"\n :widget=\"widget\"\n v-bind=\"$attrs\"\n />\n</template>\n"],"names":["props","__props","modelValue","_useModel","filteredProps","computed","filterWidgetProps","INPUT_EXCLUDED_PROPS","precision","p","stepValue","useGrouping","buttonsDisabled","currentValue","buttonTooltip","pressed","ref","setPressed","__name","val","emits","__emit","delegatedProps","reactiveOmit","forwarded","useForwardPropsEmits","useNumberStepCalculation","options","precisionArg","returnUndefinedForDefault","toValue","step","sharedButtonClasses","cn","useNumberWidgetButtonPt","roundedLeft","roundedRight","increment","decrement","timesEmptied","updateLocalValue","newValue","handleNumberInputUpdate","STANDARD_EXCLUDED_PROPS","sliderNumberPt","hasControlAfterGenerate"],"mappings":"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"}
|
comfyui_frontend_package/static/assets/{WidgetInputText-CecuaK0n.js → WidgetInputText-LR89p-m1.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{e as i}from"./vendor-primevue-rR0TB_Js.js";import{c as d}from"./index-
|
|
2
|
-
//# sourceMappingURL=WidgetInputText-
|
|
1
|
+
import{e as i}from"./vendor-primevue-rR0TB_Js.js";import{c as d}from"./index-BODInyrK.js";import{f as p,I as u}from"./widgetPropFilter-CygYoMQt.js";import{W as n}from"./index-CyS0uSKu.js";import{_ as f}from"./WidgetLayoutField.vue_vue_type_script_setup_true_lang-C5dBI8au.js";import{bq as c,cF as g,cG as w,E as V,j as P,d as _,k as x,z as b,br as e,m as C}from"./vendor-other-BxP-0xn6.js";import"./vendor-vue-BEnTqVKr.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-BsnVSA6y.js";import"./vendor-tiptap-4vvRsqpM.js";const N=c({__name:"WidgetInputText",props:g({widget:{}},{modelValue:{default:""},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const l=t,a=w(t,"modelValue"),r=V(()=>p(l.widget.options,u));return(o,s)=>(_(),P(f,{widget:o.widget},{default:x(()=>[b(e(i),C({modelValue:a.value,"onUpdate:modelValue":s[0]||(s[0]=m=>a.value=m)},r.value,{class:e(d)(e(n),"w-full text-xs py-2 px-4"),"aria-label":o.widget.name,size:"small",pt:{root:"truncate min-w-[4ch]"}}),null,16,["modelValue","class","aria-label"])]),_:1},8,["widget"]))}});export{N as default};
|
|
2
|
+
//# sourceMappingURL=WidgetInputText-LR89p-m1.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetInputText-
|
|
1
|
+
{"version":3,"file":"WidgetInputText-LR89p-m1.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/WidgetInputText.vue"],"sourcesContent":["<template>\n <WidgetLayoutField :widget=\"widget\">\n <InputText\n v-model=\"modelValue\"\n v-bind=\"filteredProps\"\n :class=\"cn(WidgetInputBaseClass, 'w-full text-xs py-2 px-4')\"\n :aria-label=\"widget.name\"\n size=\"small\"\n :pt=\"{ root: 'truncate min-w-[4ch]' }\"\n />\n </WidgetLayoutField>\n</template>\n\n<script setup lang=\"ts\">\nimport InputText from 'primevue/inputtext'\nimport { computed } from 'vue'\n\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\nimport {\n INPUT_EXCLUDED_PROPS,\n filterWidgetProps\n} from '@/utils/widgetPropFilter'\n\nimport { WidgetInputBaseClass } from './layout'\nimport WidgetLayoutField from './layout/WidgetLayoutField.vue'\n\nconst props = defineProps<{\n widget: SimplifiedWidget<string>\n}>()\n\nconst modelValue = defineModel<string>({ default: '' })\n\nconst filteredProps = computed(() =>\n filterWidgetProps(props.widget.options, INPUT_EXCLUDED_PROPS)\n)\n</script>\n"],"names":["props","__props","modelValue","_useModel","filteredProps","computed","filterWidgetProps","INPUT_EXCLUDED_PROPS"],"mappings":"2pBA2BA,MAAMA,EAAQC,EAIRC,EAAaC,EAAmBF,EAAA,YAAgB,EAEhDG,EAAgBC,EAAS,IAC7BC,EAAkBN,EAAM,OAAO,QAASO,CAAoB,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{bq as l,i as u,c as o,d as s,q as i,e as r,br as a,F as m,A as g,u as p,I as n,s as c,p as f}from"./vendor-other-BxP-0xn6.js";import{c as w}from"./index-
|
|
2
|
-
//# sourceMappingURL=WidgetLayoutField.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
import{bq as l,i as u,c as o,d as s,q as i,e as r,br as a,F as m,A as g,u as p,I as n,s as c,p as f}from"./vendor-other-BxP-0xn6.js";import{c as w}from"./index-BODInyrK.js";const y={class:"grid grid-cols-subgrid min-w-0 justify-between gap-1 text-node-component-slot-text"},b={key:0,class:"truncate content-center-safe"},h={class:"relative min-w-0 flex-1"},_=l({__name:"WidgetLayoutField",props:{widget:{}},setup(v){const d=u("hideLayoutField",!1);return(t,e)=>(s(),o("div",y,[a(d)?i("",!0):(s(),o("div",b,[t.widget.name?(s(),o(m,{key:0},[g(p(t.widget.label||t.widget.name),1)],64)):i("",!0)])),r("div",h,[r("div",{class:c(a(w)("cursor-default min-w-0 rounded-lg focus-within:ring focus-within:ring-component-node-widget-background-highlighted transition-all",t.widget.borderStyle)),onPointerdown:e[0]||(e[0]=n(()=>{},["stop"])),onPointermove:e[1]||(e[1]=n(()=>{},["stop"])),onPointerup:e[2]||(e[2]=n(()=>{},["stop"]))},[f(t.$slots,"default")],34)])]))}});export{_};
|
|
2
|
+
//# sourceMappingURL=WidgetLayoutField.vue_vue_type_script_setup_true_lang-C5dBI8au.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetLayoutField.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
{"version":3,"file":"WidgetLayoutField.vue_vue_type_script_setup_true_lang-C5dBI8au.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/layout/WidgetLayoutField.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { inject } from 'vue'\n\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { cn } from '@/utils/tailwindUtil'\n\ndefineProps<{\n widget: Pick<\n SimplifiedWidget<string | number | undefined>,\n 'name' | 'label' | 'borderStyle'\n >\n}>()\n\nconst hideLayoutField = inject<boolean>('hideLayoutField', false)\n</script>\n\n<template>\n <div\n class=\"grid grid-cols-subgrid min-w-0 justify-between gap-1 text-node-component-slot-text\"\n >\n <div v-if=\"!hideLayoutField\" class=\"truncate content-center-safe\">\n <template v-if=\"widget.name\">\n {{ widget.label || widget.name }}\n </template>\n </div>\n <!-- basis-full grow -->\n <div class=\"relative min-w-0 flex-1\">\n <div\n :class=\"\n cn(\n 'cursor-default min-w-0 rounded-lg focus-within:ring focus-within:ring-component-node-widget-background-highlighted transition-all',\n widget.borderStyle\n )\n \"\n @pointerdown.stop\n @pointermove.stop\n @pointerup.stop\n >\n <slot />\n </div>\n </div>\n </div>\n</template>\n"],"names":["hideLayoutField","inject"],"mappings":"gaAaA,MAAMA,EAAkBC,EAAgB,kBAAmB,EAAK"}
|
comfyui_frontend_package/static/assets/{WidgetLegacy-B8P9bOsC.js → WidgetLegacy-CJpsLPyI.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{aQ as o}from"./index-
|
|
2
|
-
//# sourceMappingURL=WidgetLegacy-
|
|
1
|
+
import{aQ as o}from"./index-BODInyrK.js";import"./vendor-primevue-rR0TB_Js.js";import"./vendor-other-BxP-0xn6.js";import"./vendor-vue-BEnTqVKr.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-BsnVSA6y.js";import"./vendor-tiptap-4vvRsqpM.js";export{o as default};
|
|
2
|
+
//# sourceMappingURL=WidgetLegacy-CJpsLPyI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetLegacy-CJpsLPyI.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
comfyui_frontend_package/static/assets/{WidgetMarkdown-nXPgrFZi.js → WidgetMarkdown-DrH35WSE.js}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var p=Object.defineProperty;var s=(t,a)=>p(t,"name",{value:a,configurable:!0});import{bq as c,cF as v,cG as w,r as n,E as g,c as k,d as b,e as V,l as M,s as $,v as y,z as x,I as i,br as B,n as h}from"./vendor-other-BxP-0xn6.js";import{a9 as z}from"./vendor-primevue-rR0TB_Js.js";import{bp as E}from"./index-
|
|
2
|
-
//# sourceMappingURL=WidgetMarkdown-
|
|
1
|
+
var p=Object.defineProperty;var s=(t,a)=>p(t,"name",{value:a,configurable:!0});import{bq as c,cF as v,cG as w,r as n,E as g,c as k,d as b,e as V,l as M,s as $,v as y,z as x,I as i,br as B,n as h}from"./vendor-other-BxP-0xn6.js";import{a9 as z}from"./vendor-primevue-rR0TB_Js.js";import{bp as E}from"./index-BODInyrK.js";import"./vendor-vue-BEnTqVKr.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-BsnVSA6y.js";import"./vendor-tiptap-4vvRsqpM.js";const H=["innerHTML"],G=c({__name:"WidgetMarkdown",props:v({widget:{}},{modelValue:{default:""},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const a=w(t,"modelValue"),l=n(!1),r=n(),d=g(()=>E(a.value||"")),u=s(async()=>{l.value||t.widget.options?.read_only||(l.value=!0,await h(),r.value?.$el?.focus())},"startEditing"),m=s(()=>{l.value=!1},"handleBlur");return(o,e)=>(b(),k("div",{class:"widget-markdown relative w-full",onDblclick:u},[V("div",{class:$(["comfy-markdown-content size-full min-h-[60px] overflow-y-auto rounded-lg text-sm",l.value===!1?"visible":"invisible"]),innerHTML:d.value},null,10,H),M(x(B(z),{ref_key:"textareaRef",ref:r,modelValue:a.value,"onUpdate:modelValue":e[0]||(e[0]=f=>a.value=f),"aria-label":`${o.$t("g.edit")} ${o.widget.name||o.$t("g.markdown")} ${o.$t("g.content")}`,class:"absolute inset-0 min-h-[60px] w-full resize-none",pt:{root:{class:"text-sm w-full h-full",onBlur:m}},"data-capture-wheel":"true",onClick:e[1]||(e[1]=i(()=>{},["stop"])),onKeydown:e[2]||(e[2]=i(()=>{},["stop"]))},null,8,["modelValue","aria-label","pt"]),[[y,l.value]])],32))}});export{G as default};
|
|
2
|
+
//# sourceMappingURL=WidgetMarkdown-DrH35WSE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetMarkdown-
|
|
1
|
+
{"version":3,"file":"WidgetMarkdown-DrH35WSE.js","sources":["../../src/renderer/extensions/vueNodes/widgets/components/WidgetMarkdown.vue"],"sourcesContent":["<template>\n <div class=\"widget-markdown relative w-full\" @dblclick=\"startEditing\">\n <!-- Display mode: Rendered markdown -->\n <div\n class=\"comfy-markdown-content size-full min-h-[60px] overflow-y-auto rounded-lg text-sm\"\n :class=\"isEditing === false ? 'visible' : 'invisible'\"\n v-html=\"renderedHtml\"\n />\n\n <!-- Edit mode: Textarea -->\n <Textarea\n v-show=\"isEditing\"\n ref=\"textareaRef\"\n v-model=\"modelValue\"\n :aria-label=\"`${$t('g.edit')} ${widget.name || $t('g.markdown')} ${$t('g.content')}`\"\n class=\"absolute inset-0 min-h-[60px] w-full resize-none\"\n :pt=\"{\n root: {\n class: 'text-sm w-full h-full',\n onBlur: handleBlur\n }\n }\"\n data-capture-wheel=\"true\"\n @click.stop\n @keydown.stop\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Textarea from 'primevue/textarea'\nimport { computed, nextTick, ref } from 'vue'\n\nimport type { SimplifiedWidget } from '@/types/simplifiedWidget'\nimport { renderMarkdownToHtml } from '@/utils/markdownRendererUtil'\n\nconst { widget } = defineProps<{\n widget: SimplifiedWidget<string>\n}>()\n\nconst modelValue = defineModel<string>({ default: '' })\n\n// State\nconst isEditing = ref(false)\nconst textareaRef = ref<InstanceType<typeof Textarea> | undefined>()\n\n// Computed\nconst renderedHtml = computed(() => {\n return renderMarkdownToHtml(modelValue.value || '')\n})\n\n// Methods\nconst startEditing = async () => {\n if (isEditing.value || widget.options?.read_only) return\n\n isEditing.value = true\n await nextTick()\n\n // Focus the textarea\n // @ts-expect-error - $el is an internal property of the Textarea component\n textareaRef.value?.$el?.focus()\n}\n\nconst handleBlur = () => {\n isEditing.value = false\n}\n</script>\n"],"names":["modelValue","_useModel","__props","isEditing","ref","textareaRef","renderedHtml","computed","renderMarkdownToHtml","startEditing","__name","nextTick","handleBlur"],"mappings":"omBAwCA,MAAMA,EAAaC,EAAmBC,EAAA,YAAgB,EAGhDC,EAAYC,EAAI,EAAK,EACrBC,EAAcD,EAAA,EAGdE,EAAeC,EAAS,IACrBC,EAAqBR,EAAW,OAAS,EAAE,CACnD,EAGKS,EAAeC,EAAA,SAAY,CAC3BP,EAAU,OAASD,EAAA,OAAO,SAAS,YAEvCC,EAAU,MAAQ,GAClB,MAAMQ,EAAA,EAINN,EAAY,OAAO,KAAK,MAAA,EAC1B,EATqB,gBAWfO,EAAaF,EAAA,IAAM,CACvBP,EAAU,MAAQ,EACpB,EAFmB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var $=Object.defineProperty;var a=(i,l)=>$(i,"name",{value:l,configurable:!0});import{bd as G,c as b,d as k,e as h,r as v,n as K,c6 as F,ey as J,bq as Q,cF as X,ez as Y,E as q,cG as Z,o as ee,q as U,z as D,k as ae,A as te,u as V,br as n,F as ne,y as oe,G as le}from"./vendor-other-BxP-0xn6.js";import{q as H,t as R,f as N}from"./index-
|
|
2
|
-
//# sourceMappingURL=WidgetRecordAudio-
|
|
1
|
+
var $=Object.defineProperty;var a=(i,l)=>$(i,"name",{value:l,configurable:!0});import{bd as G,c as b,d as k,e as h,r as v,n as K,c6 as F,ey as J,bq as Q,cF as X,ez as Y,E as q,cG as Z,o as ee,q as U,z as D,k as ae,A as te,u as V,br as n,F as ne,y as oe,G as le}from"./vendor-other-BxP-0xn6.js";import{q as H,t as R,f as N}from"./index-BODInyrK.js";import{u as O}from"./audioService-DvqSt3rU.js";import{f as re}from"./audioUtils-bxVioEE3.js";import{ab as ie}from"./vendor-primevue-rR0TB_Js.js";import"./vendor-vue-BEnTqVKr.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-BsnVSA6y.js";import"./vendor-tiptap-4vvRsqpM.js";const ue={viewBox:"0 0 24 24",width:"1.2em",height:"1.2em"};function se(i,l){return k(),b("svg",ue,[...l[0]||(l[0]=[h("g",{fill:"none",stroke:"currentColor","stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2"},[h("path",{d:"M12 19v3m7-12v2a7 7 0 0 1-14 0v-2"}),h("rect",{width:"6",height:"13",x:"9",y:"2",rx:"3"})],-1)])])}a(se,"render");const ce=G({name:"lucide-mic",render:se});function de(i,l={}){const o=v(!1),f=v(0),u=v(null);async function e(){if(!i.value)return!1;try{return await i.value.play(),o.value=!0,!0}catch(A){return console.warn("Audio playback failed:",A),o.value=!1,!1}}a(e,"play");function t(){i.value&&(i.value.pause(),i.value.currentTime=0),o.value=!1,l.onPlaybackEnded&&l.onPlaybackEnded()}a(t,"stop");function s(){o.value=!1,l.onPlaybackEnded&&l.onPlaybackEnded()}a(s,"onPlaybackEnded");function g(){i.value?.duration&&l.onMetadataLoaded&&l.onMetadataLoaded(i.value.duration)}a(g,"onMetadataLoaded");async function p(){f.value+=1,await K()}a(p,"resetAudioElement");function r(){return i.value?.currentTime||0}a(r,"getCurrentTime");function y(){return i.value?.duration||0}return a(y,"getDuration"),{isPlaying:o,audioElementKey:f,play:e,stop:t,onPlaybackEnded:s,onMetadataLoaded:g,resetAudioElement:p,getCurrentTime:r,getDuration:y,playbackTimerInterval:u}}a(de,"useAudioPlayback");function ve(i={}){const l=v(!1),o=v(null),f=v([]),u=v(null),e=v(null);async function t(){try{e.value?.startsWith("blob:")&&URL.revokeObjectURL(e.value),f.value=[],e.value=null,await O().registerWavEncoder(),u.value=await navigator.mediaDevices.getUserMedia({audio:!0}),o.value=new J(u.value,{mimeType:"audio/wav"}),o.value.ondataavailable=r=>{f.value.push(r.data)},o.value.onstop=async()=>{const r=new Blob(f.value,{type:"audio/wav"});e.value?.startsWith("blob:")&&URL.revokeObjectURL(e.value),e.value=URL.createObjectURL(r),i.onRecordingComplete&&await i.onRecordingComplete(r),g()},o.value.start(100),l.value=!0}catch(r){throw i.onError&&i.onError(r),r}}a(t,"startRecording");function s(){o.value&&o.value.state!=="inactive"?o.value.stop():g()}a(s,"stopRecording");function g(){l.value=!1,u.value&&(u.value.getTracks().forEach(r=>r.stop()),u.value=null)}a(g,"cleanup");function p(){s(),e.value&&(URL.revokeObjectURL(e.value),e.value=null)}return a(p,"dispose"),F(()=>{p()}),{isRecording:l,recordedURL:e,mediaRecorder:o,startRecording:t,stopRecording:s,dispose:p}}a(ve,"useAudioRecorder");function me(i={}){const{barCount:l=18,minHeight:o=4,maxHeight:f=32}=i,u=v(Array.from({length:l},()=>({height:16}))),e=v(null),t=v(null),s=v(null),g=v(null),p=v(null);function r(){u.value=Array.from({length:l},()=>({height:Math.random()*(f-o)+o}))}a(r,"initWaveform");function y(m){m.value&&(t.value&&s.value?A():w(),g.value=requestAnimationFrame(()=>y(m)))}a(y,"updateWaveform");function A(){if(!t.value||!s.value)return;t.value.getByteFrequencyData(s.value);const m=Math.floor(s.value.length/l);u.value=u.value.map((L,I)=>{let S=0;for(let P=0;P<m;P++)S+=s.value[I*m+P]||0;return{height:S/m/255*(f-o)+o}})}a(A,"updateWaveformFromAudio");function w(){u.value=u.value.map(m=>({height:Math.max(o,Math.min(f,m.height+(Math.random()-.5)*4))}))}a(w,"updateWaveformRandom");async function W(){e.value&&e.value.state!=="closed"&&await e.value.close(),e.value=null,p.value=null}a(W,"setupAudioContext");async function M(m){e.value=new window.AudioContext,t.value=e.value.createAnalyser(),e.value.createMediaStreamSource(m).connect(t.value),t.value.fftSize=256,s.value=new Uint8Array(t.value.frequencyBinCount)}a(M,"setupRecordingVisualization");async function C(m){return e.value&&e.value.state!=="closed"&&await e.value.close(),p.value=null,m?(e.value=new window.AudioContext,t.value=e.value.createAnalyser(),p.value=e.value.createMediaElementSource(m),p.value.connect(t.value),t.value.connect(e.value.destination),t.value.fftSize=256,s.value=new Uint8Array(t.value.frequencyBinCount),!0):!1}a(C,"setupPlaybackVisualization");function T(){g.value&&(cancelAnimationFrame(g.value),g.value=null)}a(T,"stopWaveform");function z(){T(),e.value&&e.value.state!=="closed"&&e.value.close(),e.value=null,p.value=null}return a(z,"dispose"),F(()=>{z()}),{waveformBars:u,initWaveform:r,updateWaveform:y,setupAudioContext:W,setupRecordingVisualization:M,setupPlaybackVisualization:C,stopWaveform:T,dispose:z}}a(me,"useAudioWaveform");const fe={class:"relative"},pe={class:"mb-4"},ge={key:0,class:"flex h-14 w-full items-center gap-4 rounded-lg px-4 bg-node-component-surface text-text-secondary"},ye={class:"flex min-w-30 items-center gap-2"},he={class:"min-w-20 text-xs"},be={class:"min-w-10 text-sm"},ke={class:"flex h-8 flex-1 items-center gap-2 overflow-x-clip"},we=["title"],xe=["title"],Re=["title"],_e=["title"],Ae=["src"],Be=Q({__name:"WidgetRecordAudio",props:X({readonly:{type:Boolean},nodeId:{}},{modelValue:{default:""},modelModifiers:{}}),emits:["update:modelValue"],setup(i){const l=i,o=v();let f="";const u=ve({onRecordingComplete:z,onError:a(()=>{N().addAlert(R("g.micPermissionDenied")||"Microphone permission denied")},"onError")}),e=me({barCount:18,minHeight:4,maxHeight:32}),t=de(o,{onPlaybackEnded:B,onMetadataLoaded:a(d=>{!w.value&&!r.value&&(s.value=Math.floor(d))},"onMetadataLoaded")}),s=v(0),{pause:g,resume:p}=Y(()=>{s.value+=1},1e3,{immediate:!1}),{isRecording:r,recordedURL:y}=u,{waveformBars:A}=e,{isPlaying:w,audioElementKey:W}=t,M=q(()=>r.value||w.value),C=Z(i,"modelValue"),T=q(()=>!l.nodeId||!H.canvas.graph?null:H.canvas.graph.getNodeById(l.nodeId));async function z(d){try{const c=await O().convertBlobToFileAndSubmit(d);C.value=c,f=c}catch{N().addAlert("Failed to upload recorded audio")}}a(z,"handleRecordingComplete");async function m(){if(!l.readonly)try{if(await e.setupAudioContext(),await u.startRecording(),u.mediaRecorder.value){const d=u.mediaRecorder.value.stream;d&&await e.setupRecordingVisualization(d)}s.value=0,p(),e.initWaveform(),e.updateWaveform(M)}catch(d){console.error("Failed to start recording:",d)}}a(m,"handleStartRecording");function L(){u.stopRecording(),g(),e.stopWaveform()}a(L,"handleStopRecording");async function I(){if(!y.value||(s.value=0,await t.resetAudioElement(),await new Promise(_=>setTimeout(_,50)),!o.value)||!await e.setupPlaybackVisualization(o.value))return;await t.play(),e.initWaveform(),e.updateWaveform(M);const c=setInterval(()=>{s.value=Math.floor(t.getCurrentTime())},100);t.playbackTimerInterval.value=c}a(I,"handlePlayRecording");function S(){t.stop(),B()}a(S,"handleStopPlayback");function B(){e.stopWaveform(),t.playbackTimerInterval.value!==null&&(clearInterval(t.playbackTimerInterval.value),t.playbackTimerInterval.value=null);const d=t.getDuration();d?s.value=Math.floor(d):s.value=0}a(B,"handlePlaybackEnded");async function j(){return r.value&&u.mediaRecorder.value&&(u.mediaRecorder.value.stop(),await new Promise((d,c)=>{let _=0;const x=50,E=a(()=>{!r.value&&C.value?d(void 0):++_>=x?c(new Error("Recording serialization timeout after 5 seconds")):setTimeout(E,100)},"checkRecording");E()})),C.value||f||""}a(j,"serializeValue");function P(){const d=T.value;if(!d?.widgets)return;const c=d.widgets.find(_=>_.name==="audio");c&&(c.serializeValue=j)}return a(P,"registerWidgetSerialization"),ee(()=>{e.initWaveform(),P()}),F(()=>{t.playbackTimerInterval.value!==null&&(clearInterval(t.playbackTimerInterval.value),t.playbackTimerInterval.value=null)}),(d,c)=>{const _=ce;return k(),b("div",fe,[h("div",pe,[D(n(ie),{class:"text-base-foreground w-full border-0 bg-secondary-background hover:bg-secondary-background-hover",disabled:n(r)||d.readonly,onClick:m},{default:ae(()=>[te(V(n(R)("g.startRecording","Start Recording"))+" ",1),D(_,{class:"ml-1"})]),_:1},8,["disabled"])]),n(r)||n(w)||n(y)?(k(),b("div",ge,[h("div",ye,[h("span",he,V(n(r)?n(R)("g.listening","Listening..."):n(w)?n(R)("g.playing","Playing..."):n(y)?n(R)("g.ready","Ready"):""),1),h("span",be,V(n(re)(s.value)),1)]),h("div",ke,[(k(!0),b(ne,null,oe(n(A),(x,E)=>(k(),b("div",{key:E,class:"max-h-8 min-h-1 w-0.75 rounded-[1.5px] bg-slate-100 transition-all duration-100",style:le({height:x.height+"px"}),title:`Bar ${E+1}: ${x.height}px`},null,12,we))),128))]),n(r)?(k(),b("button",{key:0,title:n(R)("g.stopRecording","Stop Recording"),class:"flex size-8 animate-pulse items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors",onClick:L},c[2]||(c[2]=[h("div",{class:"size-2.5 rounded-sm bg-danger-100"},null,-1)]),8,xe)):!n(r)&&n(y)&&!n(w)?(k(),b("button",{key:1,title:n(R)("g.playRecording")||"Play Recording",class:"flex size-8 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors",onClick:I},c[3]||(c[3]=[h("i",{class:"text-text-secondary icon-[lucide--play] size-4"},null,-1)]),8,Re)):n(w)?(k(),b("button",{key:2,title:n(R)("g.stopPlayback")||"Stop Playback",class:"flex size-8 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors",onClick:S},c[4]||(c[4]=[h("i",{class:"text-text-secondary icon-[lucide--square] size-4"},null,-1)]),8,_e)):U("",!0)])):U("",!0),n(y)?(k(),b("audio",{ref_key:"audioRef",ref:o,key:n(W),src:n(y),class:"hidden",onEnded:c[0]||(c[0]=(...x)=>n(t).onPlaybackEnded&&n(t).onPlaybackEnded(...x)),onLoadedmetadata:c[1]||(c[1]=(...x)=>n(t).onMetadataLoaded&&n(t).onMetadataLoaded(...x))},null,40,Ae)):U("",!0)])}}});export{Be as default};
|
|
2
|
+
//# sourceMappingURL=WidgetRecordAudio-DL4kMpXw.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetRecordAudio-C6urheNU.js","sources":["../../src/renderer/extensions/vueNodes/widgets/composables/audio/useAudioPlayback.ts","../../src/renderer/extensions/vueNodes/widgets/composables/audio/useAudioRecorder.ts","../../src/renderer/extensions/vueNodes/widgets/composables/audio/useAudioWaveform.ts","../../src/renderer/extensions/vueNodes/widgets/components/WidgetRecordAudio.vue"],"sourcesContent":["import { nextTick, ref } from 'vue'\nimport type { Ref } from 'vue'\n\ninterface AudioPlaybackOptions {\n onPlaybackEnded?: () => void\n onMetadataLoaded?: (duration: number) => void\n}\n\nexport function useAudioPlayback(\n audioRef: Ref<HTMLAudioElement | undefined>,\n options: AudioPlaybackOptions = {}\n) {\n const isPlaying = ref(false)\n const audioElementKey = ref(0)\n const playbackTimerInterval = ref<ReturnType<typeof setInterval> | null>(null)\n\n async function play() {\n if (!audioRef.value) return false\n\n try {\n await audioRef.value.play()\n isPlaying.value = true\n return true\n } catch (error) {\n console.warn('Audio playback failed:', error)\n isPlaying.value = false\n return false\n }\n }\n\n function stop() {\n if (audioRef.value) {\n audioRef.value.pause()\n audioRef.value.currentTime = 0\n }\n isPlaying.value = false\n if (options.onPlaybackEnded) {\n options.onPlaybackEnded()\n }\n }\n\n function onPlaybackEnded() {\n isPlaying.value = false\n if (options.onPlaybackEnded) {\n options.onPlaybackEnded()\n }\n }\n\n function onMetadataLoaded() {\n if (audioRef.value?.duration && options.onMetadataLoaded) {\n options.onMetadataLoaded(audioRef.value.duration)\n }\n }\n\n async function resetAudioElement() {\n audioElementKey.value += 1\n await nextTick()\n }\n\n function getCurrentTime() {\n return audioRef.value?.currentTime || 0\n }\n\n function getDuration() {\n return audioRef.value?.duration || 0\n }\n\n return {\n isPlaying,\n audioElementKey,\n play,\n stop,\n onPlaybackEnded,\n onMetadataLoaded,\n resetAudioElement,\n getCurrentTime,\n getDuration,\n playbackTimerInterval\n }\n}\n","import { MediaRecorder as ExtendableMediaRecorder } from 'extendable-media-recorder'\nimport { onUnmounted, ref } from 'vue'\n\nimport { useAudioService } from '@/services/audioService'\n\ninterface AudioRecorderOptions {\n onRecordingComplete?: (audioBlob: Blob) => Promise<void>\n onError?: (error: Error) => void\n}\n\nexport function useAudioRecorder(options: AudioRecorderOptions = {}) {\n const isRecording = ref(false)\n const mediaRecorder = ref<MediaRecorder | null>(null)\n const audioChunks = ref<Blob[]>([])\n const stream = ref<MediaStream | null>(null)\n const recordedURL = ref<string | null>(null)\n\n async function startRecording() {\n try {\n // Clean up previous recording\n if (recordedURL.value?.startsWith('blob:')) {\n URL.revokeObjectURL(recordedURL.value)\n }\n\n // Initialize\n audioChunks.value = []\n recordedURL.value = null\n\n // Register wav encoder and get media stream\n await useAudioService().registerWavEncoder()\n stream.value = await navigator.mediaDevices.getUserMedia({ audio: true })\n\n // Create media recorder\n mediaRecorder.value = new ExtendableMediaRecorder(stream.value, {\n mimeType: 'audio/wav'\n }) as unknown as MediaRecorder\n\n mediaRecorder.value.ondataavailable = (e) => {\n audioChunks.value.push(e.data)\n }\n\n mediaRecorder.value.onstop = async () => {\n const blob = new Blob(audioChunks.value, { type: 'audio/wav' })\n\n // Create blob URL for preview\n if (recordedURL.value?.startsWith('blob:')) {\n URL.revokeObjectURL(recordedURL.value)\n }\n recordedURL.value = URL.createObjectURL(blob)\n\n // Notify completion\n if (options.onRecordingComplete) {\n await options.onRecordingComplete(blob)\n }\n\n cleanup()\n }\n\n // Start recording\n mediaRecorder.value.start(100)\n isRecording.value = true\n } catch (err) {\n if (options.onError) {\n options.onError(err as Error)\n }\n throw err\n }\n }\n\n function stopRecording() {\n if (mediaRecorder.value && mediaRecorder.value.state !== 'inactive') {\n mediaRecorder.value.stop()\n } else {\n cleanup()\n }\n }\n\n function cleanup() {\n isRecording.value = false\n\n if (stream.value) {\n stream.value.getTracks().forEach((track) => track.stop())\n stream.value = null\n }\n }\n\n function dispose() {\n stopRecording()\n if (recordedURL.value) {\n URL.revokeObjectURL(recordedURL.value)\n recordedURL.value = null\n }\n }\n\n onUnmounted(() => {\n dispose()\n })\n\n return {\n isRecording,\n recordedURL,\n mediaRecorder,\n startRecording,\n stopRecording,\n dispose\n }\n}\n","import { onUnmounted, ref } from 'vue'\nimport type { Ref } from 'vue'\n\ninterface WaveformBar {\n height: number\n}\n\ninterface AudioWaveformOptions {\n barCount?: number\n minHeight?: number\n maxHeight?: number\n}\n\nexport function useAudioWaveform(options: AudioWaveformOptions = {}) {\n const { barCount = 18, minHeight = 4, maxHeight = 32 } = options\n\n const waveformBars = ref<WaveformBar[]>(\n Array.from({ length: barCount }, () => ({ height: 16 }))\n )\n const audioContext = ref<AudioContext | null>(null)\n const analyser = ref<AnalyserNode | null>(null)\n const dataArray = ref<Uint8Array | null>(null)\n const animationId = ref<number | null>(null)\n const mediaElementSource = ref<MediaElementAudioSourceNode | null>(null)\n\n function initWaveform() {\n waveformBars.value = Array.from({ length: barCount }, () => ({\n height: Math.random() * (maxHeight - minHeight) + minHeight\n }))\n }\n\n function updateWaveform(isActive: Ref<boolean>) {\n if (!isActive.value) return\n\n if (analyser.value && dataArray.value) {\n updateWaveformFromAudio()\n } else {\n updateWaveformRandom()\n }\n\n animationId.value = requestAnimationFrame(() => updateWaveform(isActive))\n }\n\n function updateWaveformFromAudio() {\n if (!analyser.value || !dataArray.value) return\n\n analyser.value.getByteFrequencyData(\n dataArray.value as Uint8Array<ArrayBuffer>\n )\n const samplesPerBar = Math.floor(dataArray.value.length / barCount)\n\n waveformBars.value = waveformBars.value.map((_, i) => {\n let sum = 0\n for (let j = 0; j < samplesPerBar; j++) {\n sum += dataArray.value![i * samplesPerBar + j] || 0\n }\n const average = sum / samplesPerBar\n const normalizedHeight =\n (average / 255) * (maxHeight - minHeight) + minHeight\n return { height: normalizedHeight }\n })\n }\n\n function updateWaveformRandom() {\n waveformBars.value = waveformBars.value.map((bar) => ({\n height: Math.max(\n minHeight,\n Math.min(maxHeight, bar.height + (Math.random() - 0.5) * 4)\n )\n }))\n }\n\n async function setupAudioContext() {\n if (audioContext.value && audioContext.value.state !== 'closed') {\n await audioContext.value.close()\n }\n audioContext.value = null\n mediaElementSource.value = null\n }\n\n async function setupRecordingVisualization(stream: MediaStream) {\n audioContext.value = new window.AudioContext()\n analyser.value = audioContext.value.createAnalyser()\n const source = audioContext.value.createMediaStreamSource(stream)\n source.connect(analyser.value)\n\n analyser.value.fftSize = 256\n dataArray.value = new Uint8Array(analyser.value.frequencyBinCount)\n }\n\n async function setupPlaybackVisualization(audioElement: HTMLAudioElement) {\n if (audioContext.value && audioContext.value.state !== 'closed') {\n await audioContext.value.close()\n }\n\n mediaElementSource.value = null\n\n if (!audioElement) return false\n\n audioContext.value = new window.AudioContext()\n analyser.value = audioContext.value.createAnalyser()\n\n mediaElementSource.value =\n audioContext.value.createMediaElementSource(audioElement)\n\n mediaElementSource.value.connect(analyser.value)\n analyser.value.connect(audioContext.value.destination)\n\n analyser.value.fftSize = 256\n dataArray.value = new Uint8Array(analyser.value.frequencyBinCount)\n\n return true\n }\n\n function stopWaveform() {\n if (animationId.value) {\n cancelAnimationFrame(animationId.value)\n animationId.value = null\n }\n }\n\n function dispose() {\n stopWaveform()\n if (audioContext.value && audioContext.value.state !== 'closed') {\n void audioContext.value.close()\n }\n audioContext.value = null\n mediaElementSource.value = null\n }\n\n onUnmounted(() => {\n dispose()\n })\n\n return {\n waveformBars,\n initWaveform,\n updateWaveform,\n setupAudioContext,\n setupRecordingVisualization,\n setupPlaybackVisualization,\n stopWaveform,\n dispose\n }\n}\n","<template>\n <div class=\"relative\">\n <div class=\"mb-4\">\n <Button\n class=\"text-base-foreground w-full border-0 bg-secondary-background hover:bg-secondary-background-hover\"\n :disabled=\"isRecording || readonly\"\n @click=\"handleStartRecording\"\n >\n {{ t('g.startRecording', 'Start Recording') }}\n <i-lucide:mic class=\"ml-1\" />\n </Button>\n </div>\n <div\n v-if=\"isRecording || isPlaying || recordedURL\"\n class=\"flex h-14 w-full items-center gap-4 rounded-lg px-4 bg-node-component-surface text-text-secondary\"\n >\n <!-- Recording Status -->\n <div class=\"flex min-w-30 items-center gap-2\">\n <span class=\"min-w-20 text-xs\">\n {{\n isRecording\n ? t('g.listening', 'Listening...')\n : isPlaying\n ? t('g.playing', 'Playing...')\n : recordedURL\n ? t('g.ready', 'Ready')\n : ''\n }}\n </span>\n <span class=\"min-w-10 text-sm\">{{ formatTime(timer) }}</span>\n </div>\n\n <!-- Waveform Visualization -->\n <div class=\"flex h-8 flex-1 items-center gap-2 overflow-x-clip\">\n <div\n v-for=\"(bar, index) in waveformBars\"\n :key=\"index\"\n class=\"max-h-8 min-h-1 w-0.75 rounded-[1.5px] bg-slate-100 transition-all duration-100\"\n :style=\"{ height: bar.height + 'px' }\"\n :title=\"`Bar ${index + 1}: ${bar.height}px`\"\n />\n </div>\n\n <!-- Control Button -->\n <button\n v-if=\"isRecording\"\n :title=\"t('g.stopRecording', 'Stop Recording')\"\n class=\"flex size-8 animate-pulse items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors\"\n @click=\"handleStopRecording\"\n >\n <div class=\"size-2.5 rounded-sm bg-danger-100\" />\n </button>\n\n <button\n v-else-if=\"!isRecording && recordedURL && !isPlaying\"\n :title=\"t('g.playRecording') || 'Play Recording'\"\n class=\"flex size-8 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors\"\n @click=\"handlePlayRecording\"\n >\n <i class=\"text-text-secondary icon-[lucide--play] size-4\" />\n </button>\n\n <button\n v-else-if=\"isPlaying\"\n :title=\"t('g.stopPlayback') || 'Stop Playback'\"\n class=\"flex size-8 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors\"\n @click=\"handleStopPlayback\"\n >\n <i class=\"text-text-secondary icon-[lucide--square] size-4\" />\n </button>\n </div>\n <audio\n v-if=\"recordedURL\"\n ref=\"audioRef\"\n :key=\"audioElementKey\"\n :src=\"recordedURL\"\n class=\"hidden\"\n @ended=\"playback.onPlaybackEnded\"\n @loadedmetadata=\"playback.onMetadataLoaded\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { useIntervalFn } from '@vueuse/core'\nimport { Button } from 'primevue'\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport { t } from '@/i18n'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport { app } from '@/scripts/app'\nimport { useAudioService } from '@/services/audioService'\n\nimport { useAudioPlayback } from '../composables/audio/useAudioPlayback'\nimport { useAudioRecorder } from '../composables/audio/useAudioRecorder'\nimport { useAudioWaveform } from '../composables/audio/useAudioWaveform'\nimport { formatTime } from '../utils/audioUtils'\n\nconst props = defineProps<{\n readonly?: boolean\n nodeId: string\n}>()\n\n// Audio element ref\nconst audioRef = ref<HTMLAudioElement>()\n\n// Keep track of the last uploaded path as a backup\nlet lastUploadedPath = ''\n\n// Composables\nconst recorder = useAudioRecorder({\n onRecordingComplete: handleRecordingComplete,\n onError: () => {\n useToastStore().addAlert(\n t('g.micPermissionDenied') || 'Microphone permission denied'\n )\n }\n})\n\nconst waveform = useAudioWaveform({\n barCount: 18,\n minHeight: 4,\n maxHeight: 32\n})\n\nconst playback = useAudioPlayback(audioRef, {\n onPlaybackEnded: handlePlaybackEnded,\n onMetadataLoaded: (duration) => {\n if (!isPlaying.value && !isRecording.value) {\n timer.value = Math.floor(duration)\n }\n }\n})\n\n// Timer for recording\nconst timer = ref(0)\nconst { pause: pauseTimer, resume: resumeTimer } = useIntervalFn(\n () => {\n timer.value += 1\n },\n 1000,\n { immediate: false }\n)\n\n// Destructure for template access\nconst { isRecording, recordedURL } = recorder\nconst { waveformBars } = waveform\nconst { isPlaying, audioElementKey } = playback\n\n// Computed for waveform animation\nconst isWaveformActive = computed(() => isRecording.value || isPlaying.value)\n\nconst modelValue = defineModel<string>({ default: '' })\n\nconst litegraphNode = computed(() => {\n if (!props.nodeId || !app.canvas.graph) return null\n return app.canvas.graph.getNodeById(props.nodeId) as LGraphNode | null\n})\n\nasync function handleRecordingComplete(blob: Blob) {\n try {\n const path = await useAudioService().convertBlobToFileAndSubmit(blob)\n modelValue.value = path\n lastUploadedPath = path\n } catch (e) {\n useToastStore().addAlert('Failed to upload recorded audio')\n }\n}\n\nasync function handleStartRecording() {\n if (props.readonly) return\n\n try {\n await waveform.setupAudioContext()\n await recorder.startRecording()\n\n // Setup waveform visualization for recording\n if (recorder.mediaRecorder.value) {\n const stream = recorder.mediaRecorder.value.stream\n if (stream) {\n await waveform.setupRecordingVisualization(stream)\n }\n }\n\n // Start timer\n timer.value = 0\n resumeTimer()\n waveform.initWaveform()\n waveform.updateWaveform(isWaveformActive)\n } catch (err) {\n console.error('Failed to start recording:', err)\n }\n}\n\nfunction handleStopRecording() {\n recorder.stopRecording()\n pauseTimer()\n waveform.stopWaveform()\n}\n\nasync function handlePlayRecording() {\n if (!recordedURL.value) return\n\n // Reset timer\n timer.value = 0\n\n // Reset and setup audio element\n await playback.resetAudioElement()\n\n // Wait for audio element to be ready\n await new Promise((resolve) => setTimeout(resolve, 50))\n\n if (!audioRef.value) return\n\n // Setup waveform visualization for playback\n const setupSuccess = await waveform.setupPlaybackVisualization(audioRef.value)\n if (!setupSuccess) return\n\n // Start playback\n await playback.play()\n\n // Update waveform\n waveform.initWaveform()\n waveform.updateWaveform(isWaveformActive)\n\n // Update timer from audio current time\n const timerInterval = setInterval(() => {\n timer.value = Math.floor(playback.getCurrentTime())\n }, 100)\n\n // Store interval for cleanup\n playback.playbackTimerInterval.value = timerInterval\n}\n\nfunction handleStopPlayback() {\n playback.stop()\n handlePlaybackEnded()\n}\n\nfunction handlePlaybackEnded() {\n waveform.stopWaveform()\n\n // Clear playback timer interval\n if (playback.playbackTimerInterval.value !== null) {\n clearInterval(playback.playbackTimerInterval.value)\n playback.playbackTimerInterval.value = null\n }\n\n const duration = playback.getDuration()\n if (duration) {\n timer.value = Math.floor(duration)\n } else {\n timer.value = 0\n }\n}\n\n// Serialization function for workflow execution\nasync function serializeValue() {\n if (isRecording.value && recorder.mediaRecorder.value) {\n recorder.mediaRecorder.value.stop()\n\n await new Promise((resolve, reject) => {\n let attempts = 0\n const maxAttempts = 50 // 5 seconds max (50 * 100ms)\n const checkRecording = () => {\n if (!isRecording.value && modelValue.value) {\n resolve(undefined)\n } else if (++attempts >= maxAttempts) {\n reject(new Error('Recording serialization timeout after 5 seconds'))\n } else {\n setTimeout(checkRecording, 100)\n }\n }\n checkRecording()\n })\n }\n\n return modelValue.value || lastUploadedPath || ''\n}\n\nfunction registerWidgetSerialization() {\n const node = litegraphNode.value\n if (!node?.widgets) return\n const targetWidget = node.widgets.find((w: IBaseWidget) => w.name === 'audio')\n if (targetWidget) {\n targetWidget.serializeValue = serializeValue\n }\n}\n\nonMounted(() => {\n waveform.initWaveform()\n registerWidgetSerialization()\n})\n\nonUnmounted(() => {\n if (playback.playbackTimerInterval.value !== null) {\n clearInterval(playback.playbackTimerInterval.value)\n playback.playbackTimerInterval.value = null\n }\n})\n</script>\n"],"names":["useAudioPlayback","audioRef","options","isPlaying","ref","audioElementKey","playbackTimerInterval","play","error","__name","stop","onPlaybackEnded","onMetadataLoaded","resetAudioElement","nextTick","getCurrentTime","getDuration","useAudioRecorder","isRecording","mediaRecorder","audioChunks","stream","recordedURL","startRecording","useAudioService","ExtendableMediaRecorder","e","blob","cleanup","err","stopRecording","track","dispose","onUnmounted","useAudioWaveform","barCount","minHeight","maxHeight","waveformBars","audioContext","analyser","dataArray","animationId","mediaElementSource","initWaveform","updateWaveform","isActive","updateWaveformFromAudio","updateWaveformRandom","samplesPerBar","_","i","sum","j","bar","setupAudioContext","setupRecordingVisualization","setupPlaybackVisualization","audioElement","stopWaveform","props","__props","lastUploadedPath","recorder","handleRecordingComplete","useToastStore","t","waveform","playback","handlePlaybackEnded","duration","timer","pauseTimer","resumeTimer","useIntervalFn","isWaveformActive","computed","modelValue","_useModel","litegraphNode","app","path","handleStartRecording","handleStopRecording","handlePlayRecording","resolve","timerInterval","handleStopPlayback","serializeValue","reject","attempts","maxAttempts","checkRecording","registerWidgetSerialization","node","targetWidget","w","onMounted"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WidgetRecordAudio-DL4kMpXw.js","sources":["../../src/renderer/extensions/vueNodes/widgets/composables/audio/useAudioPlayback.ts","../../src/renderer/extensions/vueNodes/widgets/composables/audio/useAudioRecorder.ts","../../src/renderer/extensions/vueNodes/widgets/composables/audio/useAudioWaveform.ts","../../src/renderer/extensions/vueNodes/widgets/components/WidgetRecordAudio.vue"],"sourcesContent":["import { nextTick, ref } from 'vue'\nimport type { Ref } from 'vue'\n\ninterface AudioPlaybackOptions {\n onPlaybackEnded?: () => void\n onMetadataLoaded?: (duration: number) => void\n}\n\nexport function useAudioPlayback(\n audioRef: Ref<HTMLAudioElement | undefined>,\n options: AudioPlaybackOptions = {}\n) {\n const isPlaying = ref(false)\n const audioElementKey = ref(0)\n const playbackTimerInterval = ref<ReturnType<typeof setInterval> | null>(null)\n\n async function play() {\n if (!audioRef.value) return false\n\n try {\n await audioRef.value.play()\n isPlaying.value = true\n return true\n } catch (error) {\n console.warn('Audio playback failed:', error)\n isPlaying.value = false\n return false\n }\n }\n\n function stop() {\n if (audioRef.value) {\n audioRef.value.pause()\n audioRef.value.currentTime = 0\n }\n isPlaying.value = false\n if (options.onPlaybackEnded) {\n options.onPlaybackEnded()\n }\n }\n\n function onPlaybackEnded() {\n isPlaying.value = false\n if (options.onPlaybackEnded) {\n options.onPlaybackEnded()\n }\n }\n\n function onMetadataLoaded() {\n if (audioRef.value?.duration && options.onMetadataLoaded) {\n options.onMetadataLoaded(audioRef.value.duration)\n }\n }\n\n async function resetAudioElement() {\n audioElementKey.value += 1\n await nextTick()\n }\n\n function getCurrentTime() {\n return audioRef.value?.currentTime || 0\n }\n\n function getDuration() {\n return audioRef.value?.duration || 0\n }\n\n return {\n isPlaying,\n audioElementKey,\n play,\n stop,\n onPlaybackEnded,\n onMetadataLoaded,\n resetAudioElement,\n getCurrentTime,\n getDuration,\n playbackTimerInterval\n }\n}\n","import { MediaRecorder as ExtendableMediaRecorder } from 'extendable-media-recorder'\nimport { onUnmounted, ref } from 'vue'\n\nimport { useAudioService } from '@/services/audioService'\n\ninterface AudioRecorderOptions {\n onRecordingComplete?: (audioBlob: Blob) => Promise<void>\n onError?: (error: Error) => void\n}\n\nexport function useAudioRecorder(options: AudioRecorderOptions = {}) {\n const isRecording = ref(false)\n const mediaRecorder = ref<MediaRecorder | null>(null)\n const audioChunks = ref<Blob[]>([])\n const stream = ref<MediaStream | null>(null)\n const recordedURL = ref<string | null>(null)\n\n async function startRecording() {\n try {\n // Clean up previous recording\n if (recordedURL.value?.startsWith('blob:')) {\n URL.revokeObjectURL(recordedURL.value)\n }\n\n // Initialize\n audioChunks.value = []\n recordedURL.value = null\n\n // Register wav encoder and get media stream\n await useAudioService().registerWavEncoder()\n stream.value = await navigator.mediaDevices.getUserMedia({ audio: true })\n\n // Create media recorder\n mediaRecorder.value = new ExtendableMediaRecorder(stream.value, {\n mimeType: 'audio/wav'\n }) as unknown as MediaRecorder\n\n mediaRecorder.value.ondataavailable = (e) => {\n audioChunks.value.push(e.data)\n }\n\n mediaRecorder.value.onstop = async () => {\n const blob = new Blob(audioChunks.value, { type: 'audio/wav' })\n\n // Create blob URL for preview\n if (recordedURL.value?.startsWith('blob:')) {\n URL.revokeObjectURL(recordedURL.value)\n }\n recordedURL.value = URL.createObjectURL(blob)\n\n // Notify completion\n if (options.onRecordingComplete) {\n await options.onRecordingComplete(blob)\n }\n\n cleanup()\n }\n\n // Start recording\n mediaRecorder.value.start(100)\n isRecording.value = true\n } catch (err) {\n if (options.onError) {\n options.onError(err as Error)\n }\n throw err\n }\n }\n\n function stopRecording() {\n if (mediaRecorder.value && mediaRecorder.value.state !== 'inactive') {\n mediaRecorder.value.stop()\n } else {\n cleanup()\n }\n }\n\n function cleanup() {\n isRecording.value = false\n\n if (stream.value) {\n stream.value.getTracks().forEach((track) => track.stop())\n stream.value = null\n }\n }\n\n function dispose() {\n stopRecording()\n if (recordedURL.value) {\n URL.revokeObjectURL(recordedURL.value)\n recordedURL.value = null\n }\n }\n\n onUnmounted(() => {\n dispose()\n })\n\n return {\n isRecording,\n recordedURL,\n mediaRecorder,\n startRecording,\n stopRecording,\n dispose\n }\n}\n","import { onUnmounted, ref } from 'vue'\nimport type { Ref } from 'vue'\n\ninterface WaveformBar {\n height: number\n}\n\ninterface AudioWaveformOptions {\n barCount?: number\n minHeight?: number\n maxHeight?: number\n}\n\nexport function useAudioWaveform(options: AudioWaveformOptions = {}) {\n const { barCount = 18, minHeight = 4, maxHeight = 32 } = options\n\n const waveformBars = ref<WaveformBar[]>(\n Array.from({ length: barCount }, () => ({ height: 16 }))\n )\n const audioContext = ref<AudioContext | null>(null)\n const analyser = ref<AnalyserNode | null>(null)\n const dataArray = ref<Uint8Array | null>(null)\n const animationId = ref<number | null>(null)\n const mediaElementSource = ref<MediaElementAudioSourceNode | null>(null)\n\n function initWaveform() {\n waveformBars.value = Array.from({ length: barCount }, () => ({\n height: Math.random() * (maxHeight - minHeight) + minHeight\n }))\n }\n\n function updateWaveform(isActive: Ref<boolean>) {\n if (!isActive.value) return\n\n if (analyser.value && dataArray.value) {\n updateWaveformFromAudio()\n } else {\n updateWaveformRandom()\n }\n\n animationId.value = requestAnimationFrame(() => updateWaveform(isActive))\n }\n\n function updateWaveformFromAudio() {\n if (!analyser.value || !dataArray.value) return\n\n analyser.value.getByteFrequencyData(\n dataArray.value as Uint8Array<ArrayBuffer>\n )\n const samplesPerBar = Math.floor(dataArray.value.length / barCount)\n\n waveformBars.value = waveformBars.value.map((_, i) => {\n let sum = 0\n for (let j = 0; j < samplesPerBar; j++) {\n sum += dataArray.value![i * samplesPerBar + j] || 0\n }\n const average = sum / samplesPerBar\n const normalizedHeight =\n (average / 255) * (maxHeight - minHeight) + minHeight\n return { height: normalizedHeight }\n })\n }\n\n function updateWaveformRandom() {\n waveformBars.value = waveformBars.value.map((bar) => ({\n height: Math.max(\n minHeight,\n Math.min(maxHeight, bar.height + (Math.random() - 0.5) * 4)\n )\n }))\n }\n\n async function setupAudioContext() {\n if (audioContext.value && audioContext.value.state !== 'closed') {\n await audioContext.value.close()\n }\n audioContext.value = null\n mediaElementSource.value = null\n }\n\n async function setupRecordingVisualization(stream: MediaStream) {\n audioContext.value = new window.AudioContext()\n analyser.value = audioContext.value.createAnalyser()\n const source = audioContext.value.createMediaStreamSource(stream)\n source.connect(analyser.value)\n\n analyser.value.fftSize = 256\n dataArray.value = new Uint8Array(analyser.value.frequencyBinCount)\n }\n\n async function setupPlaybackVisualization(audioElement: HTMLAudioElement) {\n if (audioContext.value && audioContext.value.state !== 'closed') {\n await audioContext.value.close()\n }\n\n mediaElementSource.value = null\n\n if (!audioElement) return false\n\n audioContext.value = new window.AudioContext()\n analyser.value = audioContext.value.createAnalyser()\n\n mediaElementSource.value =\n audioContext.value.createMediaElementSource(audioElement)\n\n mediaElementSource.value.connect(analyser.value)\n analyser.value.connect(audioContext.value.destination)\n\n analyser.value.fftSize = 256\n dataArray.value = new Uint8Array(analyser.value.frequencyBinCount)\n\n return true\n }\n\n function stopWaveform() {\n if (animationId.value) {\n cancelAnimationFrame(animationId.value)\n animationId.value = null\n }\n }\n\n function dispose() {\n stopWaveform()\n if (audioContext.value && audioContext.value.state !== 'closed') {\n void audioContext.value.close()\n }\n audioContext.value = null\n mediaElementSource.value = null\n }\n\n onUnmounted(() => {\n dispose()\n })\n\n return {\n waveformBars,\n initWaveform,\n updateWaveform,\n setupAudioContext,\n setupRecordingVisualization,\n setupPlaybackVisualization,\n stopWaveform,\n dispose\n }\n}\n","<template>\n <div class=\"relative\">\n <div class=\"mb-4\">\n <Button\n class=\"text-base-foreground w-full border-0 bg-secondary-background hover:bg-secondary-background-hover\"\n :disabled=\"isRecording || readonly\"\n @click=\"handleStartRecording\"\n >\n {{ t('g.startRecording', 'Start Recording') }}\n <i-lucide:mic class=\"ml-1\" />\n </Button>\n </div>\n <div\n v-if=\"isRecording || isPlaying || recordedURL\"\n class=\"flex h-14 w-full items-center gap-4 rounded-lg px-4 bg-node-component-surface text-text-secondary\"\n >\n <!-- Recording Status -->\n <div class=\"flex min-w-30 items-center gap-2\">\n <span class=\"min-w-20 text-xs\">\n {{\n isRecording\n ? t('g.listening', 'Listening...')\n : isPlaying\n ? t('g.playing', 'Playing...')\n : recordedURL\n ? t('g.ready', 'Ready')\n : ''\n }}\n </span>\n <span class=\"min-w-10 text-sm\">{{ formatTime(timer) }}</span>\n </div>\n\n <!-- Waveform Visualization -->\n <div class=\"flex h-8 flex-1 items-center gap-2 overflow-x-clip\">\n <div\n v-for=\"(bar, index) in waveformBars\"\n :key=\"index\"\n class=\"max-h-8 min-h-1 w-0.75 rounded-[1.5px] bg-slate-100 transition-all duration-100\"\n :style=\"{ height: bar.height + 'px' }\"\n :title=\"`Bar ${index + 1}: ${bar.height}px`\"\n />\n </div>\n\n <!-- Control Button -->\n <button\n v-if=\"isRecording\"\n :title=\"t('g.stopRecording', 'Stop Recording')\"\n class=\"flex size-8 animate-pulse items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors\"\n @click=\"handleStopRecording\"\n >\n <div class=\"size-2.5 rounded-sm bg-danger-100\" />\n </button>\n\n <button\n v-else-if=\"!isRecording && recordedURL && !isPlaying\"\n :title=\"t('g.playRecording') || 'Play Recording'\"\n class=\"flex size-8 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors\"\n @click=\"handlePlayRecording\"\n >\n <i class=\"text-text-secondary icon-[lucide--play] size-4\" />\n </button>\n\n <button\n v-else-if=\"isPlaying\"\n :title=\"t('g.stopPlayback') || 'Stop Playback'\"\n class=\"flex size-8 items-center justify-center rounded-full border-0 bg-smoke-500/33 transition-colors\"\n @click=\"handleStopPlayback\"\n >\n <i class=\"text-text-secondary icon-[lucide--square] size-4\" />\n </button>\n </div>\n <audio\n v-if=\"recordedURL\"\n ref=\"audioRef\"\n :key=\"audioElementKey\"\n :src=\"recordedURL\"\n class=\"hidden\"\n @ended=\"playback.onPlaybackEnded\"\n @loadedmetadata=\"playback.onMetadataLoaded\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { useIntervalFn } from '@vueuse/core'\nimport { Button } from 'primevue'\nimport { computed, onMounted, onUnmounted, ref } from 'vue'\n\nimport { t } from '@/i18n'\nimport type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'\nimport type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'\nimport { useToastStore } from '@/platform/updates/common/toastStore'\nimport { app } from '@/scripts/app'\nimport { useAudioService } from '@/services/audioService'\n\nimport { useAudioPlayback } from '../composables/audio/useAudioPlayback'\nimport { useAudioRecorder } from '../composables/audio/useAudioRecorder'\nimport { useAudioWaveform } from '../composables/audio/useAudioWaveform'\nimport { formatTime } from '../utils/audioUtils'\n\nconst props = defineProps<{\n readonly?: boolean\n nodeId: string\n}>()\n\n// Audio element ref\nconst audioRef = ref<HTMLAudioElement>()\n\n// Keep track of the last uploaded path as a backup\nlet lastUploadedPath = ''\n\n// Composables\nconst recorder = useAudioRecorder({\n onRecordingComplete: handleRecordingComplete,\n onError: () => {\n useToastStore().addAlert(\n t('g.micPermissionDenied') || 'Microphone permission denied'\n )\n }\n})\n\nconst waveform = useAudioWaveform({\n barCount: 18,\n minHeight: 4,\n maxHeight: 32\n})\n\nconst playback = useAudioPlayback(audioRef, {\n onPlaybackEnded: handlePlaybackEnded,\n onMetadataLoaded: (duration) => {\n if (!isPlaying.value && !isRecording.value) {\n timer.value = Math.floor(duration)\n }\n }\n})\n\n// Timer for recording\nconst timer = ref(0)\nconst { pause: pauseTimer, resume: resumeTimer } = useIntervalFn(\n () => {\n timer.value += 1\n },\n 1000,\n { immediate: false }\n)\n\n// Destructure for template access\nconst { isRecording, recordedURL } = recorder\nconst { waveformBars } = waveform\nconst { isPlaying, audioElementKey } = playback\n\n// Computed for waveform animation\nconst isWaveformActive = computed(() => isRecording.value || isPlaying.value)\n\nconst modelValue = defineModel<string>({ default: '' })\n\nconst litegraphNode = computed(() => {\n if (!props.nodeId || !app.canvas.graph) return null\n return app.canvas.graph.getNodeById(props.nodeId) as LGraphNode | null\n})\n\nasync function handleRecordingComplete(blob: Blob) {\n try {\n const path = await useAudioService().convertBlobToFileAndSubmit(blob)\n modelValue.value = path\n lastUploadedPath = path\n } catch (e) {\n useToastStore().addAlert('Failed to upload recorded audio')\n }\n}\n\nasync function handleStartRecording() {\n if (props.readonly) return\n\n try {\n await waveform.setupAudioContext()\n await recorder.startRecording()\n\n // Setup waveform visualization for recording\n if (recorder.mediaRecorder.value) {\n const stream = recorder.mediaRecorder.value.stream\n if (stream) {\n await waveform.setupRecordingVisualization(stream)\n }\n }\n\n // Start timer\n timer.value = 0\n resumeTimer()\n waveform.initWaveform()\n waveform.updateWaveform(isWaveformActive)\n } catch (err) {\n console.error('Failed to start recording:', err)\n }\n}\n\nfunction handleStopRecording() {\n recorder.stopRecording()\n pauseTimer()\n waveform.stopWaveform()\n}\n\nasync function handlePlayRecording() {\n if (!recordedURL.value) return\n\n // Reset timer\n timer.value = 0\n\n // Reset and setup audio element\n await playback.resetAudioElement()\n\n // Wait for audio element to be ready\n await new Promise((resolve) => setTimeout(resolve, 50))\n\n if (!audioRef.value) return\n\n // Setup waveform visualization for playback\n const setupSuccess = await waveform.setupPlaybackVisualization(audioRef.value)\n if (!setupSuccess) return\n\n // Start playback\n await playback.play()\n\n // Update waveform\n waveform.initWaveform()\n waveform.updateWaveform(isWaveformActive)\n\n // Update timer from audio current time\n const timerInterval = setInterval(() => {\n timer.value = Math.floor(playback.getCurrentTime())\n }, 100)\n\n // Store interval for cleanup\n playback.playbackTimerInterval.value = timerInterval\n}\n\nfunction handleStopPlayback() {\n playback.stop()\n handlePlaybackEnded()\n}\n\nfunction handlePlaybackEnded() {\n waveform.stopWaveform()\n\n // Clear playback timer interval\n if (playback.playbackTimerInterval.value !== null) {\n clearInterval(playback.playbackTimerInterval.value)\n playback.playbackTimerInterval.value = null\n }\n\n const duration = playback.getDuration()\n if (duration) {\n timer.value = Math.floor(duration)\n } else {\n timer.value = 0\n }\n}\n\n// Serialization function for workflow execution\nasync function serializeValue() {\n if (isRecording.value && recorder.mediaRecorder.value) {\n recorder.mediaRecorder.value.stop()\n\n await new Promise((resolve, reject) => {\n let attempts = 0\n const maxAttempts = 50 // 5 seconds max (50 * 100ms)\n const checkRecording = () => {\n if (!isRecording.value && modelValue.value) {\n resolve(undefined)\n } else if (++attempts >= maxAttempts) {\n reject(new Error('Recording serialization timeout after 5 seconds'))\n } else {\n setTimeout(checkRecording, 100)\n }\n }\n checkRecording()\n })\n }\n\n return modelValue.value || lastUploadedPath || ''\n}\n\nfunction registerWidgetSerialization() {\n const node = litegraphNode.value\n if (!node?.widgets) return\n const targetWidget = node.widgets.find((w: IBaseWidget) => w.name === 'audio')\n if (targetWidget) {\n targetWidget.serializeValue = serializeValue\n }\n}\n\nonMounted(() => {\n waveform.initWaveform()\n registerWidgetSerialization()\n})\n\nonUnmounted(() => {\n if (playback.playbackTimerInterval.value !== null) {\n clearInterval(playback.playbackTimerInterval.value)\n playback.playbackTimerInterval.value = null\n }\n})\n</script>\n"],"names":["useAudioPlayback","audioRef","options","isPlaying","ref","audioElementKey","playbackTimerInterval","play","error","__name","stop","onPlaybackEnded","onMetadataLoaded","resetAudioElement","nextTick","getCurrentTime","getDuration","useAudioRecorder","isRecording","mediaRecorder","audioChunks","stream","recordedURL","startRecording","useAudioService","ExtendableMediaRecorder","e","blob","cleanup","err","stopRecording","track","dispose","onUnmounted","useAudioWaveform","barCount","minHeight","maxHeight","waveformBars","audioContext","analyser","dataArray","animationId","mediaElementSource","initWaveform","updateWaveform","isActive","updateWaveformFromAudio","updateWaveformRandom","samplesPerBar","_","i","sum","j","bar","setupAudioContext","setupRecordingVisualization","setupPlaybackVisualization","audioElement","stopWaveform","props","__props","lastUploadedPath","recorder","handleRecordingComplete","useToastStore","t","waveform","playback","handlePlaybackEnded","duration","timer","pauseTimer","resumeTimer","useIntervalFn","isWaveformActive","computed","modelValue","_useModel","litegraphNode","app","path","handleStartRecording","handleStopRecording","handlePlayRecording","resolve","timerInterval","handleStopPlayback","serializeValue","reject","attempts","maxAttempts","checkRecording","registerWidgetSerialization","node","targetWidget","w","onMounted"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{_ as o}from"./WidgetSelect.vue_vue_type_script_setup_true_lang-CHjOuVyH.js";import"./index-BODInyrK.js";import"./vendor-primevue-rR0TB_Js.js";import"./vendor-other-BxP-0xn6.js";import"./vendor-vue-BEnTqVKr.js";import"./vendor-xterm-CWYFmgbN.js";import"./vendor-three-BsnVSA6y.js";import"./vendor-tiptap-4vvRsqpM.js";import"./widgetPropFilter-CygYoMQt.js";import"./index-CyS0uSKu.js";import"./WidgetLayoutField.vue_vue_type_script_setup_true_lang-C5dBI8au.js";import"./LazyImage.vue_vue_type_script_setup_true_lang-Dza6G4hd.js";import"./WidgetWithControl.vue_vue_type_script_setup_true_lang-CU_cmbAA.js";export{o as default};
|
|
2
|
+
//# sourceMappingURL=WidgetSelect-Bk32AcQe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetSelect-Bk32AcQe.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var fe=Object.defineProperty;var v=(t,e)=>fe(t,"name",{value:e,configurable:!0});import{c as x,_ as me,f as oe,t as P,L as ge,a as ve,W as ye,cB as be}from"./index-FoJ8Eu4a.js";import{E as c,bq as T,cF as F,cG as z,j as I,d as m,k as q,z as B,e as M,br as b,m as ae,p as we,c as $,s as C,q as L,u as j,dt as J,r as D,l as se,d9 as he,F as _,y as ee,i as Se,h as ke,A as Me,dh as $e,w as Y,bu as xe,ex as Ue,be as Ce}from"./vendor-other-BxP-0xn6.js";import{i as ze,p as ne}from"./vendor-primevue-rR0TB_Js.js";import"./vendor-xterm-CWYFmgbN.js";import{f as ie,P as re}from"./widgetPropFilter-CygYoMQt.js";import{W as de}from"./index-BbFKUlCt.js";import{_ as ue}from"./WidgetLayoutField.vue_vue_type_script_setup_true_lang-CbjST6rI.js";import{a as Ve,c as Oe}from"./LazyImage.vue_vue_type_script_setup_true_lang-C3ynRbso.js";import{_ as Ae}from"./WidgetWithControl.vue_vue_type_script_setup_true_lang-DFvQ9Mdf.js";function ce(t={}){return c(()=>({appendTo:"self",...t}))}v(ce,"useTransformCompatOverlayProps");const De={class:"absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex"},te=T({__name:"WidgetSelectDefault",props:F({widget:{}},{modelValue:{default(t){return t.widget.options?.values?.[0]||""}},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t,i=z(t,"modelValue"),w=ce(),r=c(()=>{const a=e.widget.options;return a?.values&&Array.isArray(a.values)?a.values:[]}),y=c(()=>!!i.value&&!r.value.includes(i.value)),p=c(()=>({...ie(e.widget.options,re),...w.value,...y.value?{placeholder:`${i.value}`}:{}}));return(a,u)=>(m(),I(ue,{widget:a.widget},{default:q(()=>[B(b(ze),ae({modelValue:i.value,"onUpdate:modelValue":u[0]||(u[0]=g=>i.value=g),invalid:y.value,filter:r.value.length>4,"auto-filter-focus":r.value.length>4,options:r.value},p.value,{class:b(x)(b(de),"w-full text-xs"),"aria-label":a.widget.name,size:"small",pt:{option:"text-xs",dropdown:"w-8",label:b(x)("truncate min-w-[4ch]",a.$slots.default&&"mr-5"),overlay:"w-fit min-w-full"},"data-capture-wheel":"true"}),null,16,["modelValue","invalid","filter","auto-filter-focus","options","class","aria-label","pt"]),M("div",De,[we(a.$slots,"default")])]),_:3},8,["widget"]))}}),Ie={class:"min-w-0 flex-1 px-1 py-2 text-left truncate"},Te={key:0},Qe={key:1},Fe=["multiple","disabled","accept"],Le=T({__name:"FormDropdownInput",props:{isOpen:{type:Boolean,default:!1},placeholder:{default:"Select..."},items:{},selected:{},maxSelectable:{},uploadable:{type:Boolean},disabled:{type:Boolean},accept:{}},emits:["select-click","file-change"],setup(t,{emit:e}){const i=t,w=e,r=c(()=>i.items.filter(p=>i.selected.has(p.id))),y=c(()=>x("border-0 bg-component-node-widget-background outline-none text-text-secondary",i.disabled?"cursor-not-allowed":"hover:bg-component-node-widget-background-hovered cursor-pointer",r.value.length>0&&"text-text-primary"));return(p,a)=>(m(),$("div",{class:C(b(x)(b(de),"flex text-base leading-none",{"opacity-50 cursor-not-allowed !outline-zinc-300/10":p.disabled}))},[M("button",{class:C(b(x)(y.value,"flex justify-between items-center flex-1 min-w-0 h-8",{"rounded-l-lg":p.uploadable,"rounded-lg":!p.uploadable})),onClick:a[0]||(a[0]=u=>w("select-click",u))},[M("span",Ie,[r.value.length?(m(),$("span",Qe,j(r.value.map(u=>u.label??u.name).join(", ")),1)):(m(),$("span",Te,j(p.placeholder),1))]),M("i",{class:C(["icon-[lucide--chevron-down]",b(x)("mr-2 size-4 transition-transform duration-200 flex-shrink-0 text-component-node-foreground-secondary",p.isOpen&&"rotate-180")])},null,2)],2),p.uploadable?(m(),$("label",{key:0,class:C(b(x)(y.value,"relative","size-8 flex justify-center items-center border-l rounded-r-lg border-zinc-300/10"))},[a[2]||(a[2]=M("i",{class:"icon-[lucide--folder-search] size-4"},null,-1)),M("input",{type:"file",class:"absolute inset-0 -z-1 opacity-0",multiple:p.maxSelectable>1,disabled:p.disabled,accept:p.accept,onChange:a[1]||(a[1]=u=>w("file-change",u))},null,40,Fe)],2)):L("",!0)],2))}}),Pe={class:"text-secondary flex gap-2 px-4"},Be={key:0,class:"mr-2 icon-[lucide--loader-circle] size-4 animate-spin"},je={key:1,class:"mr-2 icon-[lucide--search] size-4"},Re=["placeholder"],We={key:0,class:"absolute top-[-2px] left-[-2px] size-2 rounded-full bg-component-node-widget-background-highlighted"},Ke=["onClick"],qe={key:0,class:"icon-[lucide--check] size-4"},K="bg-transparent border-0 outline-0 ring-0 text-left",le="size-6 flex justify-center items-center rounded-sm cursor-pointer transition-all duration-150 hover:scale-108 hover:text-base-foreground active:scale-95",Ee=T({__name:"FormDropdownMenuActions",props:F({isQuerying:{type:Boolean},sortOptions:{}},{layoutMode:{},layoutModeModifiers:{},searchQuery:{},searchQueryModifiers:{},sortSelected:{},sortSelectedModifiers:{}}),emits:["update:layoutMode","update:searchQuery","update:sortSelected"],setup(t){const e=z(t,"layoutMode"),i=z(t,"searchQuery"),w=z(t,"sortSelected"),r=x("h-8 bg-zinc-500/20 rounded-lg outline outline-1 outline-offset-[-1px] outline-node-component-border transition-all duration-150"),y=J("sortPopoverRef"),p=J("sortTriggerRef"),a=D(!1);function u(n){!y.value||!p.value||(a.value=!a.value,y.value.toggle(n,p.value))}v(u,"toggleSortPopover");function g(){a.value=!1,y.value?.hide()}v(g,"closeSortPopover");function o(n){w.value=n.id,g()}return v(o,"handleSortSelected"),(n,f)=>(m(),$("div",Pe,[M("label",{class:C(b(x)(b(r),"flex-1 flex px-2 items-center text-base leading-none cursor-text",i.value?.trim()!==""?"text-base-foreground":"","hover:outline-component-node-widget-background-highlighted/80","focus-within:outline-component-node-widget-background-highlighted/80"))},[n.isQuerying?(m(),$("i",Be)):(m(),$("i",je)),se(M("input",{"onUpdate:modelValue":f[0]||(f[0]=h=>i.value=h),type:"text",autofocus:"",class:C(K),placeholder:n.$t("g.search")},null,8,Re),[[he,i.value]])],2),M("button",{ref_key:"sortTriggerRef",ref:p,class:C(b(x)(K,b(r),"relative w-8 flex justify-center items-center cursor-pointer","hover:outline-component-node-widget-background-highlighted","active:!scale-95")),onClick:u},[w.value!=="default"?(m(),$("div",We)):L("",!0),f[4]||(f[4]=M("i",{class:"icon-[lucide--arrow-up-down] size-4"},null,-1))],2),B(b(ne),{ref_key:"sortPopoverRef",ref:y,dismissable:!0,"close-on-escape":!0,unstyled:"",pt:{root:{class:"absolute z-50"},content:{class:["bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg"]}},onHide:f[1]||(f[1]=h=>a.value=!1)},{default:q(()=>[M("div",{class:C(b(x)("flex flex-col gap-2 p-2 min-w-32","bg-component-node-background","rounded-lg outline outline-offset-[-1px] outline-component-node-border"))},[(m(!0),$(_,null,ee(n.sortOptions,h=>(m(),$("button",{key:h.name,class:C(b(x)(K,"flex justify-between items-center h-6 cursor-pointer","hover:!text-blue-500")),onClick:v(V=>o(h),"onClick")},[M("span",null,j(h.name),1),w.value===h.id?(m(),$("i",qe)):L("",!0)],10,Ke))),128))],2)]),_:1},512),M("div",{class:C(b(x)(b(r),"flex justify-center items-center p-1 gap-1 hover:outline-component-node-widget-background-highlighted"))},[M("button",{class:C(b(x)(K,le,e.value==="list"?"bg-neutral-500/50 text-base-foreground":"")),onClick:f[2]||(f[2]=h=>e.value="list")},f[5]||(f[5]=[M("i",{class:"icon-[lucide--list] size-4"},null,-1)]),2),M("button",{class:C(b(x)(K,le,e.value==="grid"?"bg-neutral-500/50 text-base-foreground":"")),onClick:f[3]||(f[3]=h=>e.value="grid")},f[6]||(f[6]=[M("i",{class:"icon-[lucide--layout-grid] size-4"},null,-1)]),2)],2)]))}}),He={class:"text-secondary mb-4 flex gap-1 px-4 justify-start"},Ne=["disabled","onClick"],Ge=T({__name:"FormDropdownMenuFilter",props:F({filterOptions:{}},{filterSelected:{},filterSelectedModifiers:{}}),emits:["update:filterSelected"],setup(t){const e=z(t,"filterSelected"),{isUploadButtonEnabled:i,showUploadDialog:w}=Ve(),r=c(()=>t.filterOptions.length===1);return(y,p)=>(m(),$("div",He,[(m(!0),$(_,null,ee(y.filterOptions,a=>(m(),$("button",{key:a.id,type:"button",disabled:r.value,class:C(b(x)("px-4 py-2 rounded-md inline-flex justify-center items-center select-none appearance-none border-0 text-base-foreground",!r.value&&"transition-all duration-150 hover:text-base-foreground hover:bg-interface-menu-component-surface-hovered cursor-pointer active:scale-95",!r.value&&e.value===a.id?"!bg-interface-menu-component-surface-selected text-base-foreground":"bg-transparent")),onClick:v(u=>e.value=a.id,"onClick")},j(a.name),11,Ne))),128)),b(i)&&r.value?(m(),I(me,{key:0,class:"ml-auto",size:"md",variant:"textonly",onClick:b(w)},{default:q(()=>[p[0]||(p[0]=M("i",{class:"icon-[lucide--folder-input]"},null,-1)),M("span",null,j(y.$t("g.import")),1)]),_:1},8,["onClick"])):L("",!0)]))}}),pe=Symbol("assetKind"),Xe={key:0,class:"absolute top-1 left-1 size-4 rounded-full border-1 border-base-foreground bg-primary-background"},Ze=["src"],Je={key:3,class:"size-full bg-gradient-to-tr from-blue-400 via-teal-500 to-green-400"},Ye={class:"text-secondary block text-xs"},_e=T({__name:"FormDropdownMenuItem",props:{index:{},selected:{type:Boolean},mediaSrc:{},name:{},label:{},metadata:{},layout:{}},emits:["click","mediaLoad"],setup(t,{emit:e}){const i=t,w=e,r=D(null),y=Se(pe),p=c(()=>y?.value==="video");function a(){w("click",i.index)}v(a,"handleClick");function u(o){if(w("mediaLoad",o),!o.target||!(o.target instanceof HTMLImageElement))return;const n=o.target;n.naturalWidth&&n.naturalHeight&&(r.value=`${n.naturalWidth} x ${n.naturalHeight}`)}v(u,"handleImageLoad");function g(o){if(w("mediaLoad",o),!o.target||!(o.target instanceof HTMLVideoElement))return;const n=o.target;n.videoWidth&&n.videoHeight&&(r.value=`${n.videoWidth} x ${n.videoHeight}`)}return v(g,"handleVideoLoad"),(o,n)=>{const f=ke("tooltip");return m(),$("div",{class:C(b(x)("flex gap-1 select-none group/item cursor-pointer bg-component-node-widget-background","transition-all duration-150",{"flex-col text-center":o.layout==="grid","flex-row text-left max-h-16 rounded-lg hover:scale-102 active:scale-98":o.layout==="list","flex-row text-left hover:bg-component-node-widget-background-hovered rounded-lg":o.layout==="list-small","ring-2 ring-component-node-widget-background-highlighted":o.layout==="list"&&o.selected})),onClick:a},[o.layout!=="list-small"?(m(),$("div",{key:0,class:C(b(x)("relative","w-full aspect-square overflow-hidden outline-1 outline-offset-[-1px] outline-interface-stroke","transition-all duration-150",{"min-w-16 max-w-16 rounded-l-lg":o.layout==="list","rounded-sm group-hover/item:scale-108 group-active/item:scale-95":o.layout==="grid","ring-2 ring-component-node-widget-background-highlighted":o.layout==="grid"&&o.selected}))},[o.selected?(m(),$("div",Xe,n[0]||(n[0]=[M("i",{class:"icon-[lucide--check] size-3 translate-y-[-0.5px] text-base-foreground bold"},null,-1)]))):L("",!0),o.mediaSrc&&p.value?(m(),$("video",{key:1,src:o.mediaSrc,class:"size-full object-cover",preload:"metadata",muted:"",onLoadeddata:g},null,40,Ze)):o.mediaSrc?(m(),I(Oe,{key:2,src:o.mediaSrc,alt:o.name,"image-class":"size-full object-cover",onLoad:u},null,8,["src","alt"])):(m(),$("div",Je))],2)):L("",!0),M("div",{class:C(b(x)("flex gap-1",{"flex-col":o.layout==="grid","flex-col px-4 py-1 w-full justify-center min-w-0":o.layout==="list","flex-row p-2 items-center justify-between w-full":o.layout==="list-small"}))},[se((m(),$("span",{class:C(b(x)("block text-xs line-clamp-2 break-words overflow-hidden","transition-colors duration-150",!!o.selected&&"text-base-foreground"))},[Me(j(o.label??o.name),1)],2)),[[f,o.layout==="grid"?o.label??o.name:void 0]]),M("span",Ye,j(o.metadata||r.value),1)],2)],2)}}}),et={class:"flex max-h-[640px] w-103 flex-col rounded-lg bg-component-node-background pt-4 outline outline-offset-[-1px] outline-node-component-border"},tt={class:"relative flex h-full mt-2 overflow-y-scroll"},lt={key:0,class:"h-50 col-span-full flex items-center justify-center"},ot=["title","aria-label"],at=T({__name:"FormDropdownMenu",props:F({items:{},isSelected:{type:Function},isQuerying:{type:Boolean},filterOptions:{},sortOptions:{}},{filterSelected:{},filterSelectedModifiers:{},layoutMode:{},layoutModeModifiers:{},sortSelected:{},sortSelectedModifiers:{},searchQuery:{},searchQueryModifiers:{}}),emits:F(["item-click"],["update:filterSelected","update:layoutMode","update:sortSelected","update:searchQuery"]),setup(t,{emit:e}){const i=e,w=z(t,"filterSelected"),r=z(t,"layoutMode"),y=z(t,"sortSelected"),p=z(t,"searchQuery");return(a,u)=>(m(),$("div",et,[a.filterOptions.length>0?(m(),I(Ge,{key:0,"filter-selected":w.value,"onUpdate:filterSelected":u[0]||(u[0]=g=>w.value=g),"filter-options":a.filterOptions},null,8,["filter-selected","filter-options"])):L("",!0),B(Ee,{"layout-mode":r.value,"onUpdate:layoutMode":u[1]||(u[1]=g=>r.value=g),"sort-selected":y.value,"onUpdate:sortSelected":u[2]||(u[2]=g=>y.value=g),"search-query":p.value,"onUpdate:searchQuery":u[3]||(u[3]=g=>p.value=g),"sort-options":a.sortOptions,"is-querying":a.isQuerying},null,8,["layout-mode","sort-selected","search-query","sort-options","is-querying"]),M("div",tt,[M("div",{class:C(b(x)("h-full max-h-full grid gap-x-2 gap-y-4 overflow-y-auto px-4 pt-4 pb-4 w-full",{"grid-cols-4":r.value==="grid","grid-cols-1 gap-y-2":r.value==="list","grid-cols-1 gap-y-1":r.value==="list-small"}))},[u[4]||(u[4]=M("div",{class:"pointer-events-none absolute inset-x-3 top-0 z-10 h-5"},null,-1)),a.items.length===0?(m(),$("div",lt,[M("i",{title:a.$t("g.noItems"),"aria-label":a.$t("g.noItems"),class:"icon-[lucide--circle-off] size-30 text-zinc-500/20"},null,8,ot)])):L("",!0),(m(!0),$(_,null,ee(a.items,(g,o)=>(m(),I(_e,{key:g.id,index:o,selected:a.isSelected(g,o),"media-src":g.mediaSrc,name:g.name,label:g.label,metadata:g.metadata,layout:r.value,onClick:v(n=>i("item-click",g,o),"onClick")},null,8,["index","selected","media-src","name","label","metadata","layout","onClick"]))),128))],2)])]))}});async function st(t,e){if(t.trim()==="")return e;const i=t.trim().toLowerCase().split(" ");return e.filter(w=>{const r=w.name.toLowerCase();return i.every(y=>r.includes(y))})}v(st,"defaultSearcher");function nt(){return[{name:"Default",id:"default",sorter:v(({items:t})=>t.slice(),"sorter")},{name:"A-Z",id:"a-z",sorter:v(({items:t})=>t.slice().sort((e,i)=>e.name.localeCompare(i.name)),"sorter")}]}v(nt,"getDefaultSortOptions");const it=T({__name:"FormDropdown",props:F({items:{},placeholder:{default:P("widgets.uploadSelect.placeholder")},multiple:{type:[Boolean,Number],default:!1},uploadable:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},accept:{},filterOptions:{default:v(()=>[],"default")},sortOptions:{default:v(()=>nt(),"default")},isSelected:{type:Function,default:v((t,e,i)=>t.has(e.id),"default")},searcher:{type:Function,default:st}},{selected:{default:new Set},selectedModifiers:{},filterSelected:{default:""},filterSelectedModifiers:{},sortSelected:{default:"default"},sortSelectedModifiers:{},layoutMode:{default:"grid"},layoutModeModifiers:{},files:{default:[]},filesModifiers:{},searchQuery:{default:""},searchQueryModifiers:{}}),emits:["update:selected","update:filterSelected","update:sortSelected","update:layoutMode","update:files","update:searchQuery"],setup(t){const e=t,i=z(t,"selected"),w=z(t,"filterSelected"),r=z(t,"sortSelected"),y=z(t,"layoutMode"),p=z(t,"files"),a=z(t,"searchQuery"),u=$e(a,700,{maxWait:700}),g=D(!1),o=oe(),n=D(),f=J("triggerRef"),h=D(!1),V=c(()=>e.multiple===!0?1/0:typeof e.multiple=="number"?e.multiple:1),R=D([]);Y(a,k=>{g.value=k!==u.value}),Y([u,()=>e.items],(k,S,l)=>{let s=!1,d;l(()=>{s=!0,d?.()}),e.searcher(u.value,e.items,U=>d=U).then(U=>{s||(R.value=U)}).finally(()=>{s||(g.value=!1)})},{immediate:!0});const O=c(()=>e.sortOptions.find(S=>S.id==="default")?.sorter||(({items:S})=>S.slice())),Q=c(()=>r.value==="default"?O.value:e.sortOptions.find(S=>S.id===r.value)?.sorter||O.value),E=c(()=>Q.value({items:R.value})||[]);function H(k,S){return e.isSelected?.(i.value,k,S)??!1}v(H,"internalIsSelected");const N=v(k=>{e.disabled||n.value&&f.value&&(n.value.toggle(k,f.value),h.value=!h.value)},"toggleDropdown"),G=v(()=>{n.value&&(n.value.hide(),h.value=!1)},"closeDropdown");function X(k){if(e.disabled)return;const S=k.target;S.files&&(p.value=Array.from(S.files)),S.value=""}v(X,"handleFileChange");function Z(k,S){if(e.disabled)return;const l=i.value;if(H(k,S))l.delete(k.id);else if(l.size<V.value)l.add(k.id);else if(V.value===1)l.clear(),l.add(k.id);else{o.addAlert("Maximum selection limit reached");return}i.value=new Set(l),V.value===1&&G()}return v(Z,"handleSelection"),(k,S)=>(m(),$("div",{ref_key:"triggerRef",ref:f},[B(Le,{files:p.value,"is-open":h.value,placeholder:k.placeholder,items:k.items,"max-selectable":V.value,selected:i.value,uploadable:k.uploadable,disabled:k.disabled,accept:k.accept,onSelectClick:N,onFileChange:X},null,8,["files","is-open","placeholder","items","max-selectable","selected","uploadable","disabled","accept"]),B(b(ne),{ref_key:"popoverRef",ref:n,dismissable:!0,"close-on-escape":!0,unstyled:"",pt:{root:{class:"absolute z-50"},content:{class:["bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg"]}},onHide:S[4]||(S[4]=l=>h.value=!1)},{default:q(()=>[B(at,{"filter-selected":w.value,"onUpdate:filterSelected":S[0]||(S[0]=l=>w.value=l),"layout-mode":y.value,"onUpdate:layoutMode":S[1]||(S[1]=l=>y.value=l),"sort-selected":r.value,"onUpdate:sortSelected":S[2]||(S[2]=l=>r.value=l),"search-query":a.value,"onUpdate:searchQuery":S[3]||(S[3]=l=>a.value=l),"filter-options":k.filterOptions,"sort-options":k.sortOptions,disabled:k.disabled,"is-querying":g.value,items:E.value,"is-selected":H,"max-selectable":V.value,onClose:G,onItemClick:Z},null,8,["filter-selected","layout-mode","sort-selected","search-query","filter-options","sort-options","disabled","is-querying","items","max-selectable"])]),_:1},512)],512))}});function rt(t){return{category:c(()=>{}),assets:c(()=>[]),dropdownItems:c(()=>[]),isLoading:c(()=>!1),error:c(()=>null)}}v(rt,"useAssetWidgetData");const dt=T({__name:"WidgetSelectDropdown",props:F({widget:{},nodeType:{},assetKind:{},allowUpload:{type:Boolean},uploadFolder:{},isAssetMode:{type:Boolean},defaultLayoutMode:{}},{modelValue:{default(t){return t.widget.options?.values?.[0]||""}},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t;xe(pe,c(()=>e.assetKind));const i=z(t,"modelValue"),w=oe(),r=ge(),y=ce(),p=c(()=>({...ie(e.widget.options,re),...y.value})),u=v(()=>e.isAssetMode&&e.nodeType?rt(Ce(()=>e.nodeType)):null,"getAssetData")(),g=D("all"),o=c(()=>{if(e.isAssetMode){const l=u?.category.value??"All";return[{id:"all",name:Ue(l)}]}return[{id:"all",name:"All"},{id:"inputs",name:"Inputs"},{id:"outputs",name:"Outputs"}]}),n=D(new Set);function f(l){const s=e.widget.options?.getOptionLabel;if(!s)return l;try{return s(l)}catch(d){return console.error("Failed to map value:",d),l}}v(f,"getDisplayLabel");const h=c(()=>{const l=e.widget.options?.values||[];return Array.isArray(l)?l.map((s,d)=>({id:`input-${d}`,mediaSrc:S(s,"input"),name:s,label:f(s),metadata:""})):[]}),V=c(()=>{if(!["image","video"].includes(e.assetKind??""))return[];const l=new Set;return r.historyTasks.forEach(s=>{s.flatOutputs.forEach(d=>{const U=e.assetKind==="image"&&d.mediaType==="images"||e.assetKind==="video"&&d.mediaType==="video";if(d.type==="output"&&U){const W=`${d.subfolder?`${d.subfolder}/${d.filename}`:d.filename} [output]`;l.add(W)}})}),Array.from(l).map(s=>({id:`output-${s}`,mediaSrc:S(s.replace(" [output]",""),"output"),name:s,label:f(s),metadata:""}))}),R=c(()=>e.isAssetMode&&u?u.dropdownItems.value:[...h.value,...V.value]),O=c(()=>{if(e.isAssetMode)return R.value;switch(g.value){case"inputs":return h.value;case"outputs":return V.value;case"all":default:return[...h.value,...V.value]}}),Q=c(()=>{const l=e.widget.options;if(l?.placeholder)return l.placeholder;switch(e.assetKind){case"image":return P("widgets.uploadSelect.placeholderImage");case"video":return P("widgets.uploadSelect.placeholderVideo");case"audio":return P("widgets.uploadSelect.placeholderAudio");case"model":return P("widgets.uploadSelect.placeholderModel");case"unknown":return P("widgets.uploadSelect.placeholderUnknown")}return P("widgets.uploadSelect.placeholder")}),E=c(()=>e.isAssetMode?!1:e.allowUpload===!0),H=c(()=>{switch(e.assetKind){case"image":return"image/*";case"video":return"video/*";case"audio":return"audio/*";default:return}}),N=D(e.defaultLayoutMode??"grid");Y([i,O],([l,s])=>{if(l===void 0){n.value.clear();return}const d=O.value.find(U=>U.name===l);d&&(n.value.clear(),n.value.add(d.id))},{immediate:!0});function G(l){let s;if(l.size>0&&(s=l.values().next().value),s==null){i.value=void 0;return}const d=O.value.find(U=>U.id===s)?.name;if(!d){i.value=void 0;return}i.value=d}v(G,"updateSelectedItems");const X=v(async(l,s=!1,d={})=>{const U=new FormData;U.append("image",l),s&&U.append("subfolder","pasted"),d.type&&U.append("type",d.type);const A=await ve.fetchApi("/upload/image",{method:"POST",body:U});if(A.status!==200)return w.addAlert(A.status+" - "+A.statusText),null;const W=await A.json();return(d.type==="input"||!d.type&&!s)&&await ye().updateInputs(),W.subfolder?`${W.subfolder}/${W.name}`:W.name},"uploadFile"),Z=v(async l=>{const s=e.uploadFolder??"input",d=l.map(A=>X(A,!1,{type:s}));return(await Promise.all(d)).filter(A=>A!==null)},"uploadFiles");async function k(l){if(!(!l||l.length===0))try{const s=await Z(l);if(s.length===0){w.addAlert("File upload failed");return}e.widget.options?.values&&s.forEach(d=>{const U=e.widget.options.values;U.includes(d)||U.push(d)}),i.value=s[0],e.widget.callback&&e.widget.callback(s[0])}catch(s){console.error("Upload error:",s),w.addAlert(`Upload failed: ${s}`)}}v(k,"handleFilesUpdate");function S(l,s="input"){return["image","video"].includes(e.assetKind??"")?`/api/view?filename=${encodeURIComponent(l)}&type=${s}`:""}return v(S,"getMediaUrl"),(l,s)=>(m(),I(ue,{widget:l.widget},{default:q(()=>[B(it,ae({selected:n.value,"onUpdate:selected":s[0]||(s[0]=d=>n.value=d),"filter-selected":g.value,"onUpdate:filterSelected":s[1]||(s[1]=d=>g.value=d),"layout-mode":N.value,"onUpdate:layoutMode":s[2]||(s[2]=d=>N.value=d),items:O.value,placeholder:Q.value,multiple:!1,uploadable:E.value,accept:H.value,"filter-options":o.value},p.value,{class:"w-full","onUpdate:selected":G,"onUpdate:files":k}),null,16,["selected","filter-selected","layout-mode","items","placeholder","uploadable","accept","filter-options"])]),_:1},8,["widget"]))}}),St=T({__name:"WidgetSelect",props:F({widget:{},nodeType:{}},{modelValue:{},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t,i=z(t,"modelValue"),w=c(()=>{if(e.widget.spec&&be(e.widget.spec))return e.widget.spec}),r=c(()=>{const n=w.value;if(!n)return{kind:"unknown",allowUpload:!1,folder:void 0};const{image_upload:f,animated_image_upload:h,video_upload:V,image_folder:R,audio_upload:O}=n;let Q="unknown";return V?Q="video":f||h?Q="image":O&&(Q="audio"),{kind:Q,allowUpload:f===!0||h===!0||V===!0||O===!0,folder:R}}),y=c(()=>!1),p=c(()=>r.value.kind),a=c(()=>y.value||p.value!=="unknown"),u=c(()=>r.value.allowUpload),g=c(()=>r.value.folder??"input"),o=c(()=>y.value?"list":"grid");return(n,f)=>a.value?(m(),I(dt,{key:0,modelValue:i.value,"onUpdate:modelValue":f[0]||(f[0]=h=>i.value=h),widget:n.widget,"node-type":n.widget.nodeType??n.nodeType,"asset-kind":p.value,"allow-upload":u.value,"upload-folder":g.value,"is-asset-mode":y.value,"default-layout-mode":o.value},null,8,["modelValue","widget","node-type","asset-kind","allow-upload","upload-folder","is-asset-mode","default-layout-mode"])):n.widget.controlWidget?(m(),I(Ae,{key:1,modelValue:i.value,"onUpdate:modelValue":f[1]||(f[1]=h=>i.value=h),component:te,widget:n.widget},null,8,["modelValue","widget"])):(m(),I(te,{key:2,modelValue:i.value,"onUpdate:modelValue":f[2]||(f[2]=h=>i.value=h),widget:n.widget},null,8,["modelValue","widget"]))}});export{St as _};
|
|
2
|
-
//# sourceMappingURL=WidgetSelect.vue_vue_type_script_setup_true_lang-
|
|
1
|
+
var fe=Object.defineProperty;var v=(t,e)=>fe(t,"name",{value:e,configurable:!0});import{c as x,_ as me,f as oe,t as P,L as ge,a as ve,W as ye,cB as be}from"./index-BODInyrK.js";import{E as c,bq as T,cF as F,cG as z,j as I,d as m,k as q,z as B,e as M,br as b,m as ae,p as we,c as $,s as C,q as L,u as j,dt as J,r as D,l as se,d9 as he,F as _,y as ee,i as Se,h as ke,A as Me,dh as $e,w as Y,bu as xe,ex as Ue,be as Ce}from"./vendor-other-BxP-0xn6.js";import{i as ze,p as ne}from"./vendor-primevue-rR0TB_Js.js";import"./vendor-xterm-CWYFmgbN.js";import{f as ie,P as re}from"./widgetPropFilter-CygYoMQt.js";import{W as de}from"./index-CyS0uSKu.js";import{_ as ue}from"./WidgetLayoutField.vue_vue_type_script_setup_true_lang-C5dBI8au.js";import{a as Ve,c as Oe}from"./LazyImage.vue_vue_type_script_setup_true_lang-Dza6G4hd.js";import{_ as Ae}from"./WidgetWithControl.vue_vue_type_script_setup_true_lang-CU_cmbAA.js";function ce(t={}){return c(()=>({appendTo:"self",...t}))}v(ce,"useTransformCompatOverlayProps");const De={class:"absolute top-5 right-8 h-4 w-7 -translate-y-4/5 flex"},te=T({__name:"WidgetSelectDefault",props:F({widget:{}},{modelValue:{default(t){return t.widget.options?.values?.[0]||""}},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t,i=z(t,"modelValue"),w=ce(),r=c(()=>{const a=e.widget.options;return a?.values&&Array.isArray(a.values)?a.values:[]}),y=c(()=>!!i.value&&!r.value.includes(i.value)),p=c(()=>({...ie(e.widget.options,re),...w.value,...y.value?{placeholder:`${i.value}`}:{}}));return(a,u)=>(m(),I(ue,{widget:a.widget},{default:q(()=>[B(b(ze),ae({modelValue:i.value,"onUpdate:modelValue":u[0]||(u[0]=g=>i.value=g),invalid:y.value,filter:r.value.length>4,"auto-filter-focus":r.value.length>4,options:r.value},p.value,{class:b(x)(b(de),"w-full text-xs"),"aria-label":a.widget.name,size:"small",pt:{option:"text-xs",dropdown:"w-8",label:b(x)("truncate min-w-[4ch]",a.$slots.default&&"mr-5"),overlay:"w-fit min-w-full"},"data-capture-wheel":"true"}),null,16,["modelValue","invalid","filter","auto-filter-focus","options","class","aria-label","pt"]),M("div",De,[we(a.$slots,"default")])]),_:3},8,["widget"]))}}),Ie={class:"min-w-0 flex-1 px-1 py-2 text-left truncate"},Te={key:0},Qe={key:1},Fe=["multiple","disabled","accept"],Le=T({__name:"FormDropdownInput",props:{isOpen:{type:Boolean,default:!1},placeholder:{default:"Select..."},items:{},selected:{},maxSelectable:{},uploadable:{type:Boolean},disabled:{type:Boolean},accept:{}},emits:["select-click","file-change"],setup(t,{emit:e}){const i=t,w=e,r=c(()=>i.items.filter(p=>i.selected.has(p.id))),y=c(()=>x("border-0 bg-component-node-widget-background outline-none text-text-secondary",i.disabled?"cursor-not-allowed":"hover:bg-component-node-widget-background-hovered cursor-pointer",r.value.length>0&&"text-text-primary"));return(p,a)=>(m(),$("div",{class:C(b(x)(b(de),"flex text-base leading-none",{"opacity-50 cursor-not-allowed !outline-zinc-300/10":p.disabled}))},[M("button",{class:C(b(x)(y.value,"flex justify-between items-center flex-1 min-w-0 h-8",{"rounded-l-lg":p.uploadable,"rounded-lg":!p.uploadable})),onClick:a[0]||(a[0]=u=>w("select-click",u))},[M("span",Ie,[r.value.length?(m(),$("span",Qe,j(r.value.map(u=>u.label??u.name).join(", ")),1)):(m(),$("span",Te,j(p.placeholder),1))]),M("i",{class:C(["icon-[lucide--chevron-down]",b(x)("mr-2 size-4 transition-transform duration-200 flex-shrink-0 text-component-node-foreground-secondary",p.isOpen&&"rotate-180")])},null,2)],2),p.uploadable?(m(),$("label",{key:0,class:C(b(x)(y.value,"relative","size-8 flex justify-center items-center border-l rounded-r-lg border-zinc-300/10"))},[a[2]||(a[2]=M("i",{class:"icon-[lucide--folder-search] size-4"},null,-1)),M("input",{type:"file",class:"absolute inset-0 -z-1 opacity-0",multiple:p.maxSelectable>1,disabled:p.disabled,accept:p.accept,onChange:a[1]||(a[1]=u=>w("file-change",u))},null,40,Fe)],2)):L("",!0)],2))}}),Pe={class:"text-secondary flex gap-2 px-4"},Be={key:0,class:"mr-2 icon-[lucide--loader-circle] size-4 animate-spin"},je={key:1,class:"mr-2 icon-[lucide--search] size-4"},Re=["placeholder"],We={key:0,class:"absolute top-[-2px] left-[-2px] size-2 rounded-full bg-component-node-widget-background-highlighted"},Ke=["onClick"],qe={key:0,class:"icon-[lucide--check] size-4"},K="bg-transparent border-0 outline-0 ring-0 text-left",le="size-6 flex justify-center items-center rounded-sm cursor-pointer transition-all duration-150 hover:scale-108 hover:text-base-foreground active:scale-95",Ee=T({__name:"FormDropdownMenuActions",props:F({isQuerying:{type:Boolean},sortOptions:{}},{layoutMode:{},layoutModeModifiers:{},searchQuery:{},searchQueryModifiers:{},sortSelected:{},sortSelectedModifiers:{}}),emits:["update:layoutMode","update:searchQuery","update:sortSelected"],setup(t){const e=z(t,"layoutMode"),i=z(t,"searchQuery"),w=z(t,"sortSelected"),r=x("h-8 bg-zinc-500/20 rounded-lg outline outline-1 outline-offset-[-1px] outline-node-component-border transition-all duration-150"),y=J("sortPopoverRef"),p=J("sortTriggerRef"),a=D(!1);function u(n){!y.value||!p.value||(a.value=!a.value,y.value.toggle(n,p.value))}v(u,"toggleSortPopover");function g(){a.value=!1,y.value?.hide()}v(g,"closeSortPopover");function o(n){w.value=n.id,g()}return v(o,"handleSortSelected"),(n,f)=>(m(),$("div",Pe,[M("label",{class:C(b(x)(b(r),"flex-1 flex px-2 items-center text-base leading-none cursor-text",i.value?.trim()!==""?"text-base-foreground":"","hover:outline-component-node-widget-background-highlighted/80","focus-within:outline-component-node-widget-background-highlighted/80"))},[n.isQuerying?(m(),$("i",Be)):(m(),$("i",je)),se(M("input",{"onUpdate:modelValue":f[0]||(f[0]=h=>i.value=h),type:"text",autofocus:"",class:C(K),placeholder:n.$t("g.search")},null,8,Re),[[he,i.value]])],2),M("button",{ref_key:"sortTriggerRef",ref:p,class:C(b(x)(K,b(r),"relative w-8 flex justify-center items-center cursor-pointer","hover:outline-component-node-widget-background-highlighted","active:!scale-95")),onClick:u},[w.value!=="default"?(m(),$("div",We)):L("",!0),f[4]||(f[4]=M("i",{class:"icon-[lucide--arrow-up-down] size-4"},null,-1))],2),B(b(ne),{ref_key:"sortPopoverRef",ref:y,dismissable:!0,"close-on-escape":!0,unstyled:"",pt:{root:{class:"absolute z-50"},content:{class:["bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg"]}},onHide:f[1]||(f[1]=h=>a.value=!1)},{default:q(()=>[M("div",{class:C(b(x)("flex flex-col gap-2 p-2 min-w-32","bg-component-node-background","rounded-lg outline outline-offset-[-1px] outline-component-node-border"))},[(m(!0),$(_,null,ee(n.sortOptions,h=>(m(),$("button",{key:h.name,class:C(b(x)(K,"flex justify-between items-center h-6 cursor-pointer","hover:!text-blue-500")),onClick:v(V=>o(h),"onClick")},[M("span",null,j(h.name),1),w.value===h.id?(m(),$("i",qe)):L("",!0)],10,Ke))),128))],2)]),_:1},512),M("div",{class:C(b(x)(b(r),"flex justify-center items-center p-1 gap-1 hover:outline-component-node-widget-background-highlighted"))},[M("button",{class:C(b(x)(K,le,e.value==="list"?"bg-neutral-500/50 text-base-foreground":"")),onClick:f[2]||(f[2]=h=>e.value="list")},f[5]||(f[5]=[M("i",{class:"icon-[lucide--list] size-4"},null,-1)]),2),M("button",{class:C(b(x)(K,le,e.value==="grid"?"bg-neutral-500/50 text-base-foreground":"")),onClick:f[3]||(f[3]=h=>e.value="grid")},f[6]||(f[6]=[M("i",{class:"icon-[lucide--layout-grid] size-4"},null,-1)]),2)],2)]))}}),He={class:"text-secondary mb-4 flex gap-1 px-4 justify-start"},Ne=["disabled","onClick"],Ge=T({__name:"FormDropdownMenuFilter",props:F({filterOptions:{}},{filterSelected:{},filterSelectedModifiers:{}}),emits:["update:filterSelected"],setup(t){const e=z(t,"filterSelected"),{isUploadButtonEnabled:i,showUploadDialog:w}=Ve(),r=c(()=>t.filterOptions.length===1);return(y,p)=>(m(),$("div",He,[(m(!0),$(_,null,ee(y.filterOptions,a=>(m(),$("button",{key:a.id,type:"button",disabled:r.value,class:C(b(x)("px-4 py-2 rounded-md inline-flex justify-center items-center select-none appearance-none border-0 text-base-foreground",!r.value&&"transition-all duration-150 hover:text-base-foreground hover:bg-interface-menu-component-surface-hovered cursor-pointer active:scale-95",!r.value&&e.value===a.id?"!bg-interface-menu-component-surface-selected text-base-foreground":"bg-transparent")),onClick:v(u=>e.value=a.id,"onClick")},j(a.name),11,Ne))),128)),b(i)&&r.value?(m(),I(me,{key:0,class:"ml-auto",size:"md",variant:"textonly",onClick:b(w)},{default:q(()=>[p[0]||(p[0]=M("i",{class:"icon-[lucide--folder-input]"},null,-1)),M("span",null,j(y.$t("g.import")),1)]),_:1},8,["onClick"])):L("",!0)]))}}),pe=Symbol("assetKind"),Xe={key:0,class:"absolute top-1 left-1 size-4 rounded-full border-1 border-base-foreground bg-primary-background"},Ze=["src"],Je={key:3,class:"size-full bg-gradient-to-tr from-blue-400 via-teal-500 to-green-400"},Ye={class:"text-secondary block text-xs"},_e=T({__name:"FormDropdownMenuItem",props:{index:{},selected:{type:Boolean},mediaSrc:{},name:{},label:{},metadata:{},layout:{}},emits:["click","mediaLoad"],setup(t,{emit:e}){const i=t,w=e,r=D(null),y=Se(pe),p=c(()=>y?.value==="video");function a(){w("click",i.index)}v(a,"handleClick");function u(o){if(w("mediaLoad",o),!o.target||!(o.target instanceof HTMLImageElement))return;const n=o.target;n.naturalWidth&&n.naturalHeight&&(r.value=`${n.naturalWidth} x ${n.naturalHeight}`)}v(u,"handleImageLoad");function g(o){if(w("mediaLoad",o),!o.target||!(o.target instanceof HTMLVideoElement))return;const n=o.target;n.videoWidth&&n.videoHeight&&(r.value=`${n.videoWidth} x ${n.videoHeight}`)}return v(g,"handleVideoLoad"),(o,n)=>{const f=ke("tooltip");return m(),$("div",{class:C(b(x)("flex gap-1 select-none group/item cursor-pointer bg-component-node-widget-background","transition-all duration-150",{"flex-col text-center":o.layout==="grid","flex-row text-left max-h-16 rounded-lg hover:scale-102 active:scale-98":o.layout==="list","flex-row text-left hover:bg-component-node-widget-background-hovered rounded-lg":o.layout==="list-small","ring-2 ring-component-node-widget-background-highlighted":o.layout==="list"&&o.selected})),onClick:a},[o.layout!=="list-small"?(m(),$("div",{key:0,class:C(b(x)("relative","w-full aspect-square overflow-hidden outline-1 outline-offset-[-1px] outline-interface-stroke","transition-all duration-150",{"min-w-16 max-w-16 rounded-l-lg":o.layout==="list","rounded-sm group-hover/item:scale-108 group-active/item:scale-95":o.layout==="grid","ring-2 ring-component-node-widget-background-highlighted":o.layout==="grid"&&o.selected}))},[o.selected?(m(),$("div",Xe,n[0]||(n[0]=[M("i",{class:"icon-[lucide--check] size-3 translate-y-[-0.5px] text-base-foreground bold"},null,-1)]))):L("",!0),o.mediaSrc&&p.value?(m(),$("video",{key:1,src:o.mediaSrc,class:"size-full object-cover",preload:"metadata",muted:"",onLoadeddata:g},null,40,Ze)):o.mediaSrc?(m(),I(Oe,{key:2,src:o.mediaSrc,alt:o.name,"image-class":"size-full object-cover",onLoad:u},null,8,["src","alt"])):(m(),$("div",Je))],2)):L("",!0),M("div",{class:C(b(x)("flex gap-1",{"flex-col":o.layout==="grid","flex-col px-4 py-1 w-full justify-center min-w-0":o.layout==="list","flex-row p-2 items-center justify-between w-full":o.layout==="list-small"}))},[se((m(),$("span",{class:C(b(x)("block text-xs line-clamp-2 break-words overflow-hidden","transition-colors duration-150",!!o.selected&&"text-base-foreground"))},[Me(j(o.label??o.name),1)],2)),[[f,o.layout==="grid"?o.label??o.name:void 0]]),M("span",Ye,j(o.metadata||r.value),1)],2)],2)}}}),et={class:"flex max-h-[640px] w-103 flex-col rounded-lg bg-component-node-background pt-4 outline outline-offset-[-1px] outline-node-component-border"},tt={class:"relative flex h-full mt-2 overflow-y-scroll"},lt={key:0,class:"h-50 col-span-full flex items-center justify-center"},ot=["title","aria-label"],at=T({__name:"FormDropdownMenu",props:F({items:{},isSelected:{type:Function},isQuerying:{type:Boolean},filterOptions:{},sortOptions:{}},{filterSelected:{},filterSelectedModifiers:{},layoutMode:{},layoutModeModifiers:{},sortSelected:{},sortSelectedModifiers:{},searchQuery:{},searchQueryModifiers:{}}),emits:F(["item-click"],["update:filterSelected","update:layoutMode","update:sortSelected","update:searchQuery"]),setup(t,{emit:e}){const i=e,w=z(t,"filterSelected"),r=z(t,"layoutMode"),y=z(t,"sortSelected"),p=z(t,"searchQuery");return(a,u)=>(m(),$("div",et,[a.filterOptions.length>0?(m(),I(Ge,{key:0,"filter-selected":w.value,"onUpdate:filterSelected":u[0]||(u[0]=g=>w.value=g),"filter-options":a.filterOptions},null,8,["filter-selected","filter-options"])):L("",!0),B(Ee,{"layout-mode":r.value,"onUpdate:layoutMode":u[1]||(u[1]=g=>r.value=g),"sort-selected":y.value,"onUpdate:sortSelected":u[2]||(u[2]=g=>y.value=g),"search-query":p.value,"onUpdate:searchQuery":u[3]||(u[3]=g=>p.value=g),"sort-options":a.sortOptions,"is-querying":a.isQuerying},null,8,["layout-mode","sort-selected","search-query","sort-options","is-querying"]),M("div",tt,[M("div",{class:C(b(x)("h-full max-h-full grid gap-x-2 gap-y-4 overflow-y-auto px-4 pt-4 pb-4 w-full",{"grid-cols-4":r.value==="grid","grid-cols-1 gap-y-2":r.value==="list","grid-cols-1 gap-y-1":r.value==="list-small"}))},[u[4]||(u[4]=M("div",{class:"pointer-events-none absolute inset-x-3 top-0 z-10 h-5"},null,-1)),a.items.length===0?(m(),$("div",lt,[M("i",{title:a.$t("g.noItems"),"aria-label":a.$t("g.noItems"),class:"icon-[lucide--circle-off] size-30 text-zinc-500/20"},null,8,ot)])):L("",!0),(m(!0),$(_,null,ee(a.items,(g,o)=>(m(),I(_e,{key:g.id,index:o,selected:a.isSelected(g,o),"media-src":g.mediaSrc,name:g.name,label:g.label,metadata:g.metadata,layout:r.value,onClick:v(n=>i("item-click",g,o),"onClick")},null,8,["index","selected","media-src","name","label","metadata","layout","onClick"]))),128))],2)])]))}});async function st(t,e){if(t.trim()==="")return e;const i=t.trim().toLowerCase().split(" ");return e.filter(w=>{const r=w.name.toLowerCase();return i.every(y=>r.includes(y))})}v(st,"defaultSearcher");function nt(){return[{name:"Default",id:"default",sorter:v(({items:t})=>t.slice(),"sorter")},{name:"A-Z",id:"a-z",sorter:v(({items:t})=>t.slice().sort((e,i)=>e.name.localeCompare(i.name)),"sorter")}]}v(nt,"getDefaultSortOptions");const it=T({__name:"FormDropdown",props:F({items:{},placeholder:{default:P("widgets.uploadSelect.placeholder")},multiple:{type:[Boolean,Number],default:!1},uploadable:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},accept:{},filterOptions:{default:v(()=>[],"default")},sortOptions:{default:v(()=>nt(),"default")},isSelected:{type:Function,default:v((t,e,i)=>t.has(e.id),"default")},searcher:{type:Function,default:st}},{selected:{default:new Set},selectedModifiers:{},filterSelected:{default:""},filterSelectedModifiers:{},sortSelected:{default:"default"},sortSelectedModifiers:{},layoutMode:{default:"grid"},layoutModeModifiers:{},files:{default:[]},filesModifiers:{},searchQuery:{default:""},searchQueryModifiers:{}}),emits:["update:selected","update:filterSelected","update:sortSelected","update:layoutMode","update:files","update:searchQuery"],setup(t){const e=t,i=z(t,"selected"),w=z(t,"filterSelected"),r=z(t,"sortSelected"),y=z(t,"layoutMode"),p=z(t,"files"),a=z(t,"searchQuery"),u=$e(a,700,{maxWait:700}),g=D(!1),o=oe(),n=D(),f=J("triggerRef"),h=D(!1),V=c(()=>e.multiple===!0?1/0:typeof e.multiple=="number"?e.multiple:1),R=D([]);Y(a,k=>{g.value=k!==u.value}),Y([u,()=>e.items],(k,S,l)=>{let s=!1,d;l(()=>{s=!0,d?.()}),e.searcher(u.value,e.items,U=>d=U).then(U=>{s||(R.value=U)}).finally(()=>{s||(g.value=!1)})},{immediate:!0});const O=c(()=>e.sortOptions.find(S=>S.id==="default")?.sorter||(({items:S})=>S.slice())),Q=c(()=>r.value==="default"?O.value:e.sortOptions.find(S=>S.id===r.value)?.sorter||O.value),E=c(()=>Q.value({items:R.value})||[]);function H(k,S){return e.isSelected?.(i.value,k,S)??!1}v(H,"internalIsSelected");const N=v(k=>{e.disabled||n.value&&f.value&&(n.value.toggle(k,f.value),h.value=!h.value)},"toggleDropdown"),G=v(()=>{n.value&&(n.value.hide(),h.value=!1)},"closeDropdown");function X(k){if(e.disabled)return;const S=k.target;S.files&&(p.value=Array.from(S.files)),S.value=""}v(X,"handleFileChange");function Z(k,S){if(e.disabled)return;const l=i.value;if(H(k,S))l.delete(k.id);else if(l.size<V.value)l.add(k.id);else if(V.value===1)l.clear(),l.add(k.id);else{o.addAlert("Maximum selection limit reached");return}i.value=new Set(l),V.value===1&&G()}return v(Z,"handleSelection"),(k,S)=>(m(),$("div",{ref_key:"triggerRef",ref:f},[B(Le,{files:p.value,"is-open":h.value,placeholder:k.placeholder,items:k.items,"max-selectable":V.value,selected:i.value,uploadable:k.uploadable,disabled:k.disabled,accept:k.accept,onSelectClick:N,onFileChange:X},null,8,["files","is-open","placeholder","items","max-selectable","selected","uploadable","disabled","accept"]),B(b(ne),{ref_key:"popoverRef",ref:n,dismissable:!0,"close-on-escape":!0,unstyled:"",pt:{root:{class:"absolute z-50"},content:{class:["bg-transparent border-none p-0 pt-2 rounded-lg shadow-lg"]}},onHide:S[4]||(S[4]=l=>h.value=!1)},{default:q(()=>[B(at,{"filter-selected":w.value,"onUpdate:filterSelected":S[0]||(S[0]=l=>w.value=l),"layout-mode":y.value,"onUpdate:layoutMode":S[1]||(S[1]=l=>y.value=l),"sort-selected":r.value,"onUpdate:sortSelected":S[2]||(S[2]=l=>r.value=l),"search-query":a.value,"onUpdate:searchQuery":S[3]||(S[3]=l=>a.value=l),"filter-options":k.filterOptions,"sort-options":k.sortOptions,disabled:k.disabled,"is-querying":g.value,items:E.value,"is-selected":H,"max-selectable":V.value,onClose:G,onItemClick:Z},null,8,["filter-selected","layout-mode","sort-selected","search-query","filter-options","sort-options","disabled","is-querying","items","max-selectable"])]),_:1},512)],512))}});function rt(t){return{category:c(()=>{}),assets:c(()=>[]),dropdownItems:c(()=>[]),isLoading:c(()=>!1),error:c(()=>null)}}v(rt,"useAssetWidgetData");const dt=T({__name:"WidgetSelectDropdown",props:F({widget:{},nodeType:{},assetKind:{},allowUpload:{type:Boolean},uploadFolder:{},isAssetMode:{type:Boolean},defaultLayoutMode:{}},{modelValue:{default(t){return t.widget.options?.values?.[0]||""}},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t;xe(pe,c(()=>e.assetKind));const i=z(t,"modelValue"),w=oe(),r=ge(),y=ce(),p=c(()=>({...ie(e.widget.options,re),...y.value})),u=v(()=>e.isAssetMode&&e.nodeType?rt(Ce(()=>e.nodeType)):null,"getAssetData")(),g=D("all"),o=c(()=>{if(e.isAssetMode){const l=u?.category.value??"All";return[{id:"all",name:Ue(l)}]}return[{id:"all",name:"All"},{id:"inputs",name:"Inputs"},{id:"outputs",name:"Outputs"}]}),n=D(new Set);function f(l){const s=e.widget.options?.getOptionLabel;if(!s)return l;try{return s(l)}catch(d){return console.error("Failed to map value:",d),l}}v(f,"getDisplayLabel");const h=c(()=>{const l=e.widget.options?.values||[];return Array.isArray(l)?l.map((s,d)=>({id:`input-${d}`,mediaSrc:S(s,"input"),name:s,label:f(s),metadata:""})):[]}),V=c(()=>{if(!["image","video"].includes(e.assetKind??""))return[];const l=new Set;return r.historyTasks.forEach(s=>{s.flatOutputs.forEach(d=>{const U=e.assetKind==="image"&&d.mediaType==="images"||e.assetKind==="video"&&d.mediaType==="video";if(d.type==="output"&&U){const W=`${d.subfolder?`${d.subfolder}/${d.filename}`:d.filename} [output]`;l.add(W)}})}),Array.from(l).map(s=>({id:`output-${s}`,mediaSrc:S(s.replace(" [output]",""),"output"),name:s,label:f(s),metadata:""}))}),R=c(()=>e.isAssetMode&&u?u.dropdownItems.value:[...h.value,...V.value]),O=c(()=>{if(e.isAssetMode)return R.value;switch(g.value){case"inputs":return h.value;case"outputs":return V.value;case"all":default:return[...h.value,...V.value]}}),Q=c(()=>{const l=e.widget.options;if(l?.placeholder)return l.placeholder;switch(e.assetKind){case"image":return P("widgets.uploadSelect.placeholderImage");case"video":return P("widgets.uploadSelect.placeholderVideo");case"audio":return P("widgets.uploadSelect.placeholderAudio");case"model":return P("widgets.uploadSelect.placeholderModel");case"unknown":return P("widgets.uploadSelect.placeholderUnknown")}return P("widgets.uploadSelect.placeholder")}),E=c(()=>e.isAssetMode?!1:e.allowUpload===!0),H=c(()=>{switch(e.assetKind){case"image":return"image/*";case"video":return"video/*";case"audio":return"audio/*";default:return}}),N=D(e.defaultLayoutMode??"grid");Y([i,O],([l,s])=>{if(l===void 0){n.value.clear();return}const d=O.value.find(U=>U.name===l);d&&(n.value.clear(),n.value.add(d.id))},{immediate:!0});function G(l){let s;if(l.size>0&&(s=l.values().next().value),s==null){i.value=void 0;return}const d=O.value.find(U=>U.id===s)?.name;if(!d){i.value=void 0;return}i.value=d}v(G,"updateSelectedItems");const X=v(async(l,s=!1,d={})=>{const U=new FormData;U.append("image",l),s&&U.append("subfolder","pasted"),d.type&&U.append("type",d.type);const A=await ve.fetchApi("/upload/image",{method:"POST",body:U});if(A.status!==200)return w.addAlert(A.status+" - "+A.statusText),null;const W=await A.json();return(d.type==="input"||!d.type&&!s)&&await ye().updateInputs(),W.subfolder?`${W.subfolder}/${W.name}`:W.name},"uploadFile"),Z=v(async l=>{const s=e.uploadFolder??"input",d=l.map(A=>X(A,!1,{type:s}));return(await Promise.all(d)).filter(A=>A!==null)},"uploadFiles");async function k(l){if(!(!l||l.length===0))try{const s=await Z(l);if(s.length===0){w.addAlert("File upload failed");return}e.widget.options?.values&&s.forEach(d=>{const U=e.widget.options.values;U.includes(d)||U.push(d)}),i.value=s[0],e.widget.callback&&e.widget.callback(s[0])}catch(s){console.error("Upload error:",s),w.addAlert(`Upload failed: ${s}`)}}v(k,"handleFilesUpdate");function S(l,s="input"){return["image","video"].includes(e.assetKind??"")?`/api/view?filename=${encodeURIComponent(l)}&type=${s}`:""}return v(S,"getMediaUrl"),(l,s)=>(m(),I(ue,{widget:l.widget},{default:q(()=>[B(it,ae({selected:n.value,"onUpdate:selected":s[0]||(s[0]=d=>n.value=d),"filter-selected":g.value,"onUpdate:filterSelected":s[1]||(s[1]=d=>g.value=d),"layout-mode":N.value,"onUpdate:layoutMode":s[2]||(s[2]=d=>N.value=d),items:O.value,placeholder:Q.value,multiple:!1,uploadable:E.value,accept:H.value,"filter-options":o.value},p.value,{class:"w-full","onUpdate:selected":G,"onUpdate:files":k}),null,16,["selected","filter-selected","layout-mode","items","placeholder","uploadable","accept","filter-options"])]),_:1},8,["widget"]))}}),St=T({__name:"WidgetSelect",props:F({widget:{},nodeType:{}},{modelValue:{},modelModifiers:{}}),emits:["update:modelValue"],setup(t){const e=t,i=z(t,"modelValue"),w=c(()=>{if(e.widget.spec&&be(e.widget.spec))return e.widget.spec}),r=c(()=>{const n=w.value;if(!n)return{kind:"unknown",allowUpload:!1,folder:void 0};const{image_upload:f,animated_image_upload:h,video_upload:V,image_folder:R,audio_upload:O}=n;let Q="unknown";return V?Q="video":f||h?Q="image":O&&(Q="audio"),{kind:Q,allowUpload:f===!0||h===!0||V===!0||O===!0,folder:R}}),y=c(()=>!1),p=c(()=>r.value.kind),a=c(()=>y.value||p.value!=="unknown"),u=c(()=>r.value.allowUpload),g=c(()=>r.value.folder??"input"),o=c(()=>y.value?"list":"grid");return(n,f)=>a.value?(m(),I(dt,{key:0,modelValue:i.value,"onUpdate:modelValue":f[0]||(f[0]=h=>i.value=h),widget:n.widget,"node-type":n.widget.nodeType??n.nodeType,"asset-kind":p.value,"allow-upload":u.value,"upload-folder":g.value,"is-asset-mode":y.value,"default-layout-mode":o.value},null,8,["modelValue","widget","node-type","asset-kind","allow-upload","upload-folder","is-asset-mode","default-layout-mode"])):n.widget.controlWidget?(m(),I(Ae,{key:1,modelValue:i.value,"onUpdate:modelValue":f[1]||(f[1]=h=>i.value=h),component:te,widget:n.widget},null,8,["modelValue","widget"])):(m(),I(te,{key:2,modelValue:i.value,"onUpdate:modelValue":f[2]||(f[2]=h=>i.value=h),widget:n.widget},null,8,["modelValue","widget"]))}});export{St as _};
|
|
2
|
+
//# sourceMappingURL=WidgetSelect.vue_vue_type_script_setup_true_lang-CHjOuVyH.js.map
|