Git Product home page Git Product logo

Comments (14)

andretchen0 avatar andretchen0 commented on September 15, 2024 1

What's the problem using the default slot

If you're responding to me, then please see my earlier comment.

We can also add some logic to render children when camera and renderer there and provide just the camera and renderer without refs.

I don't think it's a bad idea, but it has much bigger implications than this DX issue.

I'd like to let the team have a chance to discuss this in a broader context, so I've opened a new discussion about the core and mentioned you there. #578 I've laid out what I think are the related open issues, including this one.

from tres.

andretchen0 avatar andretchen0 commented on September 15, 2024

Is this a duplicate of #573 ? If so, can we close there?

Edit: Closed #573.

from tres.

userquin avatar userquin commented on September 15, 2024

it is duplicated, #573 has the hack (can be closed)

from tres.

andretchen0 avatar andretchen0 commented on September 15, 2024

@alvarosabu @userquin

Are we talking about simply getting e.g., the renderer? Or also setting?

from tres.

userquin avatar userquin commented on September 15, 2024

it is only about using the context via default slot props, rn the example is not working since state is undefined, cannot use useTresContext since it can be only used via custom TresCanvas sfc children. Check linked issue and the hack in #573

from tres.

andretchen0 avatar andretchen0 commented on September 15, 2024

it is only about using the context

So it's only for getting, right?

from tres.

userquin avatar userquin commented on September 15, 2024

Yes (like inject or exposed context prop)

from tres.

andretchen0 avatar andretchen0 commented on September 15, 2024

Can we use defineExpose instead?

We're using defineExpose for this sort of thing in Cientos and Tres most other places. Is there a reason it won't work here?

I do think it would be a welcome improvement to simplify the current TresCanvas' context defineExpose for v4 so that accessing the useful bits doesn't require a Demeter violation.

Any thoughts/opinions on using and simplifying defineExpose here?


<slot>

Since we're not setting, only getting, I'm not sure about using the slot as suggested.

From the Vue docs:

We have learned that components can accept props, which can be JavaScript values of any type. But how about template content? In some cases, we may want to pass a template fragment to a child component, and let the child component render the fragment within its own template.

But we're not passing info to a child here, so it feels like a mismatch to use a <slot> to me.

from tres.

userquin avatar userquin commented on September 15, 2024

Rn context is exposed via defineExpose, check the hack, maybe we only need to update the code snippet.

from tres.

userquin avatar userquin commented on September 15, 2024

About the default slot: the problem is the custom renderer, it is adding custom stuff in the default slot, I will ask Kevin if we can retarget the slot using custom setup component when using the custom renderer.

from tres.

userquin avatar userquin commented on September 15, 2024

@alvarosabu @andretchen0 using default slot props in ExtendExample:

imagen

imagen

imagen

imagen

from tres.

userquin avatar userquin commented on September 15, 2024

Here the changes, update TresCanvas.vue in root and run build script from root, then start docs dev server once ExtendExample.vue and extending.md files updated:

src/components/TresCanvas.vue
// L84
const slots = defineSlots<{
  default(context: TresContext): any
}>()

const instance = getCurrentInstance()?.appContext.app

const createInternalComponent = (context: TresContext) =>
  defineComponent({
    setup() {
      const ctx = getCurrentInstance()?.appContext
      if (ctx) ctx.app = instance as App
      provide('useTres', context)
      provide('extend', extend)

      if (typeof window !== 'undefined' && ctx?.app) {
        registerTresDevtools(ctx.app, context)
      }
      return () => h(Fragment, null, slots?.default ? slots.default(context) : [])
    },
  })
docs/.vitepress/theme/components/ExtendExample.vue
<script setup lang="ts">
import { TresCanvas, extend } from '@tresjs/core'
import { OrbitControls } from 'three/addons/controls/OrbitControls'
import { TextGeometry } from 'three/addons/geometries/TextGeometry'

// Add the element to the catalogue
extend({ TextGeometry, OrbitControls })
// import { useTresContext } from '@tresjs/core'

const styles = {
  width: '100%',
  height: '550px',
  border: '1px solid #e2e2e2',
  borderRadius: '8px',
  overflow: 'hidden',
}

// const { camera, renderer } = useTresContext()
</script>

<template>
  <ClientOnly>
    <TresCanvas
      v-slot="{ camera, renderer }"
      shadows
      xwindow-size
      clear-color="#fff"
      :style="styles"
    >
      <TresPerspectiveCamera :position="[0, 2, 4]" />
      <TresScene>
        <TresOrbitControls
          v-if="camera.value && renderer.value"
          :args="[camera.value, renderer.value.domElement]"
        />

        <TresDirectionalLight
          :position="[0, 2, 4]"
          :intensity="2"
          cast-shadow
        />
        <TresMesh :rotation="[-Math.PI / 4, -Math.PI / 4, Math.PI / 4]">
          <TresTorusGeometry :args="[1, 0.5, 16, 32]" />
          <TresMeshToonMaterial color="#FBB03B" />
        </TresMesh>
      </TresScene>
    </TresCanvas>
  </ClientOnly>
</template>
docs/advanced/extending.md
# L36
<ClientOnly>
    <div style="aspect-ratio: 16/9; height: auto; margin: 2rem 0; border-radius: 8px; overflow:hidden;">
        <ExtendExample />
    </div>
</ClientOnly>

from tres.

andretchen0 avatar andretchen0 commented on September 15, 2024

Hey @alvarosabu @userquin !

Rn context is exposed via defineExpose, check the hack

Sorry, I wasn't clear earlier.

I know that Tres is currently using defineExpose to make context available. I was wondering if cleaning up context and continuing to use defineExpose would be an acceptable alternative here.

That would be my preference.

Rationale

The example of bad DX from #573 is indeed a bummer:

<script setup>
// [...]
const trescanvas = ref();
const state = ref();

onMounted(() => {
  setTimeout(() => {
    state.value = trescanvas.value?.context;
  }, 0);
});
// [...]
</script>

<template>
  <TresCanvas ref="trescanvas" shadows alpha>
    <TresPerspectiveCamera :position="[5, 5, 5]" />
    <TresOrbitControls
      v-if="state?.renderer"
      :args="[state?.camera, state?.renderer?.domElement]"
    />
    <!-- -->
  </TresCanvas>
</template>

But as far as I can see, it can be rewritten more simply and cover the presented use case. See below.

It seems to me that the code below isn't materially different from the bad DX example. It only needs one extra line in <script setup> – a ref. It works with the current main branch of Tres. (Edit: It doesn't allow destructuring as written though.)

(Fwiw, extend in the latest release is throwing errors for me, so I can't recreate the bad DX example as written, but I've tried to recreate the salient parts without extend below.)

<script setup lang="ts">
import { TresCanvas } from '@tresjs/core'
import { ref } from 'vue'

// NOTE: TS likes to know the "shape" or the editor will complain.
const r = ref({ context: { renderer: { value: null } } }) 
</script>

<template>
  <div style="height:50%">
    <TresCanvas ref="r" clear-color="#82DBC5">
      <TresMesh>
        <TresBoxGeometry :args="[1, 1, 1]" />
        <TresMeshNormalMaterial />
      </TresMesh>
    </TresCanvas>
  </div>
  <div>
    <div v-if="r.context.renderer.value">
      We have a renderer: {{ Object.keys(r.context.renderer.value) }}
    </div>
    <div v-else>
      We don't have a renderer.
    </div>
  </div>
</template>

StackBlitz

Preference: defineExpose

If I've understood the issue here correctly and if it's true that we can reduce the bad DX example to one extra line of code, my preference would be to stick with defineExpose and reserve <slot>s for use cases as defined in the Vue docs, e.g., we have a template fragment to send to a child for rendering.

Maybe we could smooth out what's defineExposed for v4 so that we can e.g., just use r.renderer in the code above.

Moving forward

I don't want to impede forward progress. If I've misunderstood something here, please let me know. Otherwise, @alvarosabu , I'll leave the final call up to you.

from tres.

userquin avatar userquin commented on September 15, 2024

What's the problem using the default slot and exposing props? We can also add some logic to render children when camera and renderer there and provide just the camera and renderer without refs.

from tres.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.