Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: introduce jsx-macros #794

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 184 commits into
base: main
Choose a base branch
from
Open

feat: introduce jsx-macros #794

wants to merge 184 commits into from

Conversation

zhiyuanzmj
Copy link
Member

@zhiyuanzmj zhiyuanzmj commented Sep 6, 2024

Description

This PR provides five macros for functional component.

  1. defineComponent

    • Auto collects usage props to the props option.

      defineComponent((props: { 
        foo: string,
        bar: string        
      // ^ Unused prop as a fallthrough attribute will be automatically added to the root element's attributes. 
      }) => {
        return () => (
          <div>
            <span>{props.foo}</span>
          </div>
        )
      })

      Will be covert to

      defineComponent((props) => {
        return () => (
          <div>
            <span>{props.foo}</span>
          </div>
        )
      }, { props: { foo: null } })
    • The destructuring-props will be auto restructure and collects to the props option.

    • The rest prop will be convert to attrs, And the inheritAttrs option will defaults to false.
      By the way you can define the attrs type.

      defineComponent(({
        foo,
        ...attrs
      }: { foo: string, bar: string }) => {
        return () => (
          <div>
            <span {...attrs}>{foo}</span>
          </div>
        )
      })

      Will be covert to

      defineComponent((_props) => {
        const attrs = useAttrs()
        return () => (
          <div>
            <span {...attrs}>{_props.foo}</span>
          </div>
        )
      }, { inheritAttrs: false, props: { foo: null } })
    • Support await expression and getCurrentInstance() co-usage.

    • Support return JSX.

    • If the prop's default-value ends with !, The prop will be inferred as required.

    Usage

    defineComponent(<T,>({
      foo = undefined as T,
      barRequired = ''! 
      //              ^ specified the prop as required for Volar plugin.
    }) => {
      const modelValue = defineModel({ 
        validator: (value) => value === 'model',
        required: true 
      })
      return (
        <div class={props.class}>
          {[foo, modelValue.value]}
        </div>
      )
    })

    Will be convert to:

    defineComponent(<T,>(_props) => {
      const _default_props = createPropsDefaultProxy(_props, { 'barRequired': '' });
      const modelValue = useModel(_props, 'modelValue')
      return () => (
        <div>
          {[_props.foo, modelValue.value]}
        </div>
      )
    }, { 
      props: {
        foo: null, 
        barRequired: {
          required: true
        },
        modelValue: {
          validator: (value) => value === 'model',
          required: true
        }, 
        'onUpdate:modelValue': null, 
      }
    })
  2. defineModel

    Usage

    function Comp(){
      const modelValue = defineModel<string>()!
      return <div />
    }
    // will be convert to 
    function Comp(props: { modelValue: string, 'onUpdate:modelValue': (e: string) => any  }){
      const modelValue = useModel<string>(props, 'modelValue', { required: true })
      return <div />
    }
  3. defineExpose just like in vue-setup.

    • Also support react & preact

    Setup

    // vue-macros.config.ts
    import { defineConfig } from 'unplugin-vue-macros'
    export default defineConfig({
      jsxMacros: {
         lib: 'react' // Or 'preact'
      },
      scriptSFC: true,
    })

    Usage

    const Comp = () => {
     const [foo] = useState()
     defineExpose({
       foo
     })
     return <div>{foo}</div>
    }
    // will be convert to:
    const Comp = forwardRef((props, _ref)=>{
     const [foo] = useState()
     useImperativeHandle(_ref, () => ({
       foo
     }),['foo'])
     return <div>{foo}</div>
    }
  4. defineSlots

    • If you use generic to define slots, all slots will be optional.
    const slots = defineSlots<{
      default: () => any
    }>()
    slots.default?.()
    //           ^ optional
    • Support default slots (Recommended).
    function Comp(){
      const slots = defineSlots({
        default: (props: {foo: number}) => <div>default slot: {props.foo}</div>
        title: (props: {foo: number}) => <div>title slot: {props.foo}</div>
      })
    
      return (
        <>
          <slots.default foo={1} />
          <slots.title foo={1} />
        </>
      )
    }
  5. defineStyle

    • Support defining multiple style macros in a file.

    • Supported css pre-processors: css | scss|sass|less|stylus|postcss.

      // default pre-processor is `css`.
      defineStyle(`
        .foo {
          color: red;
        }
      `)
      
      // use `scss` pre-processor.
      defineStyle.scss(``)
    • Support css modules, If the macro is an assignment expression.

      const { foo, bar } = defineStyle.scss(`
        .foo {
          color: blue;
          .bar {
            background: red;
          }
        }
      `)
    • Support scoped mode.

      • If defined at the top level of the file, The scoped option is false.
      • If defined within a function, The scoped option defaults to true.

      Usage

      defineStyle(`
        .foo {
           color: red;
         }
      `)  // The scoped option is false.
      
      function Comp(){
        defineStyle(`` {
          scoped: false // default is true, you can manually set to false.
        })
      }
    • Support CSS-variable and JS-variable binding.

      const Comp = () => {
        const color = ref('red')
        defineStyle.scss(`
          .foo {
            color: ${color.value};
          }
        `)
         return <div class="foo" />
      }

Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

Copy link

vercel bot commented Sep 6, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
vue-macros ✅ Ready (Inspect) Visit Preview Mar 14, 2025 2:11am

Copy link

changeset-bot bot commented Sep 6, 2024

🦋 Changeset detected

Latest commit: 22e745c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 34 packages
Name Type
@vue-macros/jsx-macros Minor
unplugin-vue-macros Minor
@vue-macros/volar Minor
@vue-macros/config Patch
@vue-macros/common Patch
@vue-macros/astro Patch
@vue-macros/nuxt Patch
@vue-macros/api Patch
@vue-macros/better-define Patch
@vue-macros/boolean-prop Patch
@vue-macros/chain-call Patch
@vue-macros/define-emit Patch
@vue-macros/define-models Patch
unplugin-vue-define-options Patch
@vue-macros/define-prop Patch
@vue-macros/define-props-refs Patch
@vue-macros/define-props Patch
@vue-macros/define-render Patch
@vue-macros/define-slots Patch
@vue-macros/define-stylex Patch
@vue-macros/export-expose Patch
@vue-macros/export-props Patch
@vue-macros/export-render Patch
@vue-macros/hoist-static Patch
@vue-macros/jsx-directive Patch
@vue-macros/named-template Patch
@vue-macros/reactivity-transform Patch
@vue-macros/script-lang Patch
@vue-macros/setup-block Patch
@vue-macros/setup-component Patch
@vue-macros/setup-sfc Patch
@vue-macros/short-bind Patch
@vue-macros/short-emits Patch
@vue-macros/short-vmodel Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Sep 6, 2024
@zhiyuanzmj zhiyuanzmj changed the title Jsx macros feat: introduce jsx-macros Sep 6, 2024
@dosubot dosubot bot added the volar label Sep 6, 2024
Copy link

pkg-pr-new bot commented Sep 6, 2024

Open in Stackblitz

@vue-macros/api

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/api@794

@vue-macros/astro

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/astro@794

@vue-macros/better-define

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/better-define@794

@vue-macros/boolean-prop

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/boolean-prop@794

@vue-macros/chain-call

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/chain-call@794

@vue-macros/config

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/config@794

@vue-macros/common

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/common@794

@vue-macros/define-emit

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/define-emit@794

@vue-macros/define-models

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/define-models@794

unplugin-vue-define-options

npm i https://pkg.pr.new/vue-macros/vue-macros/unplugin-vue-define-options@794

@vue-macros/define-prop

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/define-prop@794

@vue-macros/define-props

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/define-props@794

@vue-macros/define-props-refs

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/define-props-refs@794

@vue-macros/define-render

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/define-render@794

@vue-macros/define-slots

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/define-slots@794

@vue-macros/define-stylex

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/define-stylex@794

@vue-macros/devtools

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/devtools@794

@vue-macros/eslint-config

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/eslint-config@794

@vue-macros/export-expose

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/export-expose@794

@vue-macros/export-props

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/export-props@794

@vue-macros/export-render

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/export-render@794

@vue-macros/hoist-static

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/hoist-static@794

@vue-macros/jsx-directive

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/jsx-directive@794

@vue-macros/jsx-macros

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/jsx-macros@794

vue-macros

npm i https://pkg.pr.new/vue-macros/vue-macros@794

@vue-macros/named-template

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/named-template@794

@vue-macros/nuxt

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/nuxt@794

@vue-macros/reactivity-transform

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/reactivity-transform@794

@vue-macros/script-lang

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/script-lang@794

@vue-macros/setup-block

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/setup-block@794

@vue-macros/setup-component

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/setup-component@794

@vue-macros/setup-sfc

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/setup-sfc@794

@vue-macros/short-bind

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/short-bind@794

@vue-macros/short-emits

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/short-emits@794

@vue-macros/short-vmodel

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/short-vmodel@794

@vue-macros/test-utils

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/test-utils@794

@vue-macros/volar

npm i https://pkg.pr.new/vue-macros/vue-macros/@vue-macros/volar@794

commit: 0bbb422

@sxzz sxzz force-pushed the main branch 2 times, most recently from 0ec37a2 to b55fa5a Compare September 6, 2024 22:41
@zhiyuanzmj zhiyuanzmj marked this pull request as draft September 7, 2024 04:41
@zhiyuanzmj zhiyuanzmj marked this pull request as ready for review September 8, 2024 12:07
@dosubot dosubot bot added the enhancement New feature or request label Sep 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request size:XXL This PR changes 1000+ lines, ignoring generated files. volar
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant