nhn / tui.image-editor

🍞🎨 Full-featured photo image editor using canvas. It is really easy, and it comes with great filters.
http://ui.toast.com/tui-image-editor
MIT License
6.98k stars 1.29k forks source link

Vue 3 Support #788

Open yennor opened 2 years ago

yennor commented 2 years ago

Is there vue 3 support on the roadmap? Right now it still depends on vue 2.6.14 which makes it a bit difficult to install because of dependencies problems.

lja1018 commented 2 years ago

@yennor That's a good suggestion. However, there is no separate roadmap. I'll attach the Enhancement tag.

halaharr commented 1 year ago

Does it not support vue3?

lja1018 commented 1 year ago

@halaharr Vue3 is not supported. It is not registered on our road map yet. I'm sorry.

heavywar commented 1 year ago

@halaharr When?

BenSndq commented 1 year ago

Hi @lja1018 thoughts on when you would consider putting it on the roadmap?

intellizen commented 1 year ago

Vue 2 End of Life is 31st December 2023 (https://v2.vuejs.org/lts/)

It would be really helpful if peer dependencies could be updated to Vue 3 before then.

What is the current plan for Vue 3 support?

mnaeemshakir commented 8 months ago

Hey, any plan for Vue3 support?

jgoldfuss commented 5 months ago

Any Vue3 support on the horizon? If Not I need to start looking for a different image editor that is still supported in recent environments.

pascalwengerter commented 3 weeks ago

I've opened a first draft of a PR that addresses the issue.

For anyone looking for an intermediate solution, I'd suggest piping the content of https://github.com/nhn/tui.image-editor/blob/master/apps/vue-image-editor/src/ImageEditor.vue through an AI coding tool of choice and make sure to import the necessary CSS - it's just a shallow wrapper around the plain JS library anyways. Your custom Vue3 ImageEditor.vue could look sth like:

<template>
  <div ref="tuiImageEditor" style="height: 100%; width: 100%"></div>
</template>

<script lang="ts">
import 'tui-color-picker/dist/tui-color-picker.css'
import 'tui-image-editor/dist/tui-image-editor.css'
import ImageEditor from 'tui-image-editor'
import { defineComponent, onBeforeUnmount, onMounted, ref } from 'vue'

const includeUIOptions = {
  includeUI: {
    initMenu: 'filter'
  }
}
const editorDefaultOptions = {
  cssMaxWidth: 700,
  cssMaxHeight: 500,
  usageStatistics: false
}

export default defineComponent({
  props: {
    includeUi: {
      type: Boolean,
      default: true
    },
    options: {
      type: Object,
      default() {
        return editorDefaultOptions
      }
    }
  },
  setup(props, { emit }) {
    const tuiImageEditor = ref(null)
    let editorInstance = null

    const addEventListener = () => {
      Object.keys(emit).forEach((eventName) => {
        editorInstance.on(eventName, (...args) => emit(eventName, ...args))
      })
    }

    const getRootElement = () => {
      return tuiImageEditor.value
    }

    const invoke = (methodName, ...args) => {
      let result = null
      if (editorInstance[methodName]) {
        result = editorInstance[methodName](...args)
      } else if (methodName.indexOf('.') > -1) {
        const func = getMethod(editorInstance, methodName)
        if (typeof func === 'function') {
          result = func(...args)
        }
      }
      return result
    }

    const getMethod = (instance, methodName) => {
      const { first, rest } = parseDotMethodName(methodName)
      const isInstance = instance.constructor.name !== 'Object'
      const type = typeof instance[first]
      let obj

      if (isInstance && type === 'function') {
        obj = instance[first].bind(instance)
      } else {
        obj = instance[first]
      }

      if (rest.length > 0) {
        return getMethod(obj, rest)
      }

      return obj
    }

    const parseDotMethodName = (methodName) => {
      const firstDotIdx = methodName.indexOf('.')
      let firstMethodName = methodName
      let restMethodName = ''

      if (firstDotIdx > -1) {
        firstMethodName = methodName.substring(0, firstDotIdx)
        restMethodName = methodName.substring(firstDotIdx + 1, methodName.length)
      }

      return {
        first: firstMethodName,
        rest: restMethodName
      }
    }

    onMounted(() => {
      let options = props.options
      if (props.includeUi) {
        options = Object.assign(includeUIOptions, props.options)
      }
      editorInstance = new ImageEditor(tuiImageEditor.value, options)
      addEventListener()
    })

    onBeforeUnmount(() => {
      Object.keys(emit).forEach((eventName) => {
        editorInstance.off(eventName)
      })
      editorInstance.destroy()
      editorInstance = null
    })

    return {
      tuiImageEditor,
      invoke,
      getRootElement
    }
  }
})
</script>