BuilderIO / BuilderIO/mitosis

core: add new fields to MitosisComponent type: custom directives

Open
#784 1 comment 3 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
14.4k
Forks
671
PR merge metrics
No merged PRs in 30d

Description

## What
Add a `directives` field to the component JSON output, that accepts custom directives.

## Why?

I realize that not all frameworks support directives, but some of them do. You could argue that the better solution would be to implement shared functionality somewhere else, (which may be true, depending on your use case), but sometimes the features you are looking for are already implemented in a package that provides a custom directive:

Example - Drag & Drop directive:

[Vue](https://github.com/hilongjw/vue-dragging)
[Angular](https://material.angular.io/cdk/drag-drop/overview)
[Svelte](https://github.com/isaacHagoel/svelte-dnd-action)

# How?

Since custom directives are usually registered at the application level, defining and registering directives can be handled outside of Mitosis. All Mitosis needs to do is have a special syntax to mark Node attributes as a directive. i.e.

Input (Mitosis Component)
```jsx
export default function MyComponent(props) {
return (


Some Content

);
}
```

Output (Vue)
```vue


Some content

```

Output (Svelte)
```svelte


Some content

```

Output (JSON)

```json
{
"@type": "@builder.io/mitosis/component",
"imports": [],
"exports": {},
"inputs": [],
"meta": {},
"refs": {},
"state": {},
"children": [
{
"@type": "@builder.io/mitosis/node",
"name": "div",
"meta": {},
"scope": {},
"properties": {
"class": "example"
},
"bindings": {},
"directives": {
"draggable": {}
},
"children": [
{
"@type": "@builder.io/mitosis/node",
"name": "div",
"meta": {},
"scope": {},
"properties": {
"_text": "\n Some Content\n "
},
"bindings": {},
"children": []
}
]
}
],
"hooks": {},
"context": {
"get": {},
"set": {}
},
"name": "MyComponent",
"subComponents": []
}
```

## Challenges

I realize that React doesn't allow directives, which by proxy means that AFAIK there isn't a standard for using custom directives in JSX. However, I know the BuilderIO team is smart, and I'm certain you could find a clever way to figure out how to make it happen.

Framework Examples

Vue 3 (Composition API)

```vue

// enables v-focus in templates
const vFocus = {
mounted: (el) => el.focus()
}

```

Vue 3 (Options API)
```vue

export default {
setup() {
/*...*/
},
directives: {
// enables v-focus in template
focus: {
/* ... */
}
}
}

```

Svelte
```svelte

export let bar;

function foo(node, bar) {
// the node has been mounted in the DOM

return {
update(bar) {
// the value of `bar` has changed
},

destroy() {
// the node has been removed from the DOM
}
};
}


```

Alpine.js (Not currently supported by Mitosis)
```html

Alpine.directive('uppercase', el => {
el.textContent = el.textContent.toUpperCase()
})


Hello World!

```

Contributor guide

Open the contributing guide

Research direction

Locate the MitosisComponent type and the component JSON output path, then compare the proposed directives field with the shown properties and bindings structure. Trace how JSX node attributes reach Vue, Svelte, and Angular outputs; done means the syntax, JSON representation, and supported framework output behavior are defined consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
angular, react, typescript
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.