1.0.51 • Published 1 year ago

@wix/react-velo v1.0.51

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

React Velo

Add the ability to use native React APIs (components and hooks) to Velo, by creating a React structure which corresponds to dynamic elements in the editor. React Velo supports React native APIs (ref supports only ref callback syntax and has a slightly different API),

Installation

This module is aimed to be used in Wix Velo environment. 1. Open a Wix Site 2. Enable Dev Mode 3. Add @wix/react-velo npm module 4. Add react npm module

velo-sources-panel.png

Usage Example

Given a site with the following elements (and their Velo IDs), simple-example.png

A Velo User can control these elements the behavior, style and content using the following React Velo code

import React, { useState } from 'react';
import { render, W } from '@wix/react-velo';

function App() {
  const [background, setBackground] = useState('green');
  return (
    <W.myContainer style={{backgroundColor: background}}>
      <W.title text={'Click to change background'} />
      <W.okButton onClick={() => setBackground('red')} />
    </W.myContainer>
  );
}

$w.onReady(() => render(App, $w, React));

API

Module Exports

MemberTypeDescription
renderMethodThe method which initiates the link between the editor elements and the react component which represents their behavior. It should be invoked in $w.onReady method
WObjectAn object representing the Wix Editor/ Editor X elements such that W.<id> is a React representation of the Editor element in this page. The returned component's props are identical to the Velo representation of the Element returned by using $w(<id>). For exact props and usages, see Wix Editor Elements ($w) API

Render method

render(Component, $w, React, callback?)

MemberTypeDescription
ComponentMethodThe React component root
$w$wThe Wix query element provided in a page API
ReactReact InstanceThe React instance used in this page, in order to assure that react-velo is using the same React version as the hosting page
callback() => void(Optional) A callback to be passed to the react-velo react-reconsiler implementation, see React Reconsiler documentation for more details

Repeaters

A Repeater is a special Wix Editor Element which is responsible to generate a list of elements from either a data-set (dynamic) or an array set by Velo code). In order to provide a React component API, React Velo creates a specialized react component which allows controlling the rendering of each item using a renderItem prop, as seen in the following example:

Given A following page with a repeater repeater-example.png

Its React implementation can be controlled using the following code

import React, { useState } from 'react';
import { render, W } from '@wix/react-velo';

function App() {
  const [todos, setTodos] = useState([{
    _id: '1',
    description: 'Item 1',
    status: 'In Progress',
  }, {
    _id: '2',
    description: 'Item 2',
    status: 'Done',
  }]);
  // Actions to control the list can be added
  return <W.TodoList data={todos} renderItem={({ description, status }) => 
    (
      <>
        <W.Description text={description}/>
        <W.Status text={status}/>
      </>
    )
  }/>;
}

$w.onReady(() => render(App, $w, React));
Repeater Component API
propTypeDescription
dataArrayThe data to be used by the repeater, similar to $w('#TodoList').data
renderItem(itemData) => voidThe representation of each item, similarly to $w('#TodoList').onItemReady
Native Elements access

A velo user can access "native" velo components (i.e. the object you get from $w('#someid')) using react's ref mechanism. For example, if you want to use some Text's scrollTo() method, we can do something like that:

let textRef;
const setTextRef = (element) => {
    textRef = element;
};
// ...
<W.MyButton onClick={() => {
    if (textRef) {
        console.log('Scrolling...'); 
        textRef.scrollTo();
    }
}} />
<W.text3 text={`Selected: ${selectedColorName}`} ref={setTextRef} />
Animation

Animation can be achivied using wix-animation as usual, simply by getting the element's native reference and creating a proper animation timeline.

import React from 'react'; // import react for JSX transpilation
import { W, render } from '@wix/react-velo'; // import this library
import wixAnimations from 'wix-animations'; // animations library

const timeline = wixAnimations.timeline();
function App() {
  const effect = {scale: 2, duration: 200, "rotate": 360};
  let refSet = false;
  const setRef = (element) => {
    if (!refSet && element) {
      refSet = true;
      timeline.add(element, effect);
    }
  };

  return (
    <W.MyButton
      ref={setRef} 
      onMouseIn={() => timeline.play()}
      onMouseOut={() => timeline.reverse()}
    />
  );
}

$w.onReady(() => render(App, $w, React));

Sometimes a velo user would like to compose multiple elements to a single timeline animation, Here is an example of how it can be achieved:

// A helper function to collect the native element refs
function createAnimation(animationOptionsArray) {
  const timeline = wixAnimations.timeline();
  let refsSetCounter = 0;
  const refsArray = animationOptionsArray.map(() => null);

  const applyAnimationSettings = () => {
    if (refsSetCounter < animationOptionsArray.length) {
      return;
    }

    animationOptionsArray.forEach((animationOptions, idx) => {
      timeline.add(refsArray[idx], animationOptions);
    });
  };
  
  return {
    timeline,
    setRefs: animationOptionsArray.map((_, idx) => (el) => {
      if (!refsArray[idx] && el) {
        refsSetCounter++;
        refsArray[idx] = el;
        applyAnimationSettings();
      }
    })
  };
}
// ...
// Usage:
const animation = createAnimation([
  {scale: 0.8, duration: 200},
  {opacity: 1, duration: 100},
  {opacity: 0, duration: 10},
]);
const onMouseIn = () => animation.timeline.play();
const onMouseOut = () => animation.timeline.reverse();
/// ...
return (
  <W.container1 onClick={onClick}>
    <W.mainColor
      ref={animation.setRefs[0]} 
      style={{backgroundColor: props.color}} 
      onMouseIn={onMouseIn} 
      onMouseOut={onMouseOut}>
    </W.mainColor>
    <W.blackBorder ref={animation.setRefs[1]} />
    <W.emptyBorder ref={animation.setRefs[2]} />
  </W.container1>
);
Widget interaction (Blocks)

You can use $widget.props and $widget.onPropsChanged(...) to get props for your widget, like so:

// Your component
function App() {
  const [items, setItems] = useState($widget.props.items);
  useEffect(() => {
    $widget.onPropsChanged((_, newProps) => {
      setItems(newProps.items);
     });
  }, []); // we want to subscribe to props changed only once
}

or create a HoC that will abstract that away, for example like that:

import React from 'react';
import { render } from '@wix/react-velo';

const withWidgetProps = (ReactInstance, Component) => {
 const [props, setProps] = ReactInstance.useState($widget.props);
 ReactInstance.useEffect(
  () => $widget.onPropsChanged((_, newProps) => setProps({ ...newProps })),
  []
 );

 return <Component {...props} />;
};

// ... and later:
$w.onReady(() => render(withWidgetProps(React, App), $w, React));
1.0.49

1 year ago

1.0.51

1 year ago

1.0.50

1 year ago

1.0.19

2 years ago

1.0.18

2 years ago

1.0.17

2 years ago

1.0.22

2 years ago

1.0.21

2 years ago

1.0.20

2 years ago

1.0.26

2 years ago

1.0.25

2 years ago

1.0.24

2 years ago

1.0.23

2 years ago

1.0.29

2 years ago

1.0.28

2 years ago

1.0.27

2 years ago

1.0.33

2 years ago

1.0.32

2 years ago

1.0.31

2 years ago

1.0.30

2 years ago

1.0.37

2 years ago

1.0.36

2 years ago

1.0.35

2 years ago

1.0.34

2 years ago

1.0.39

2 years ago

1.0.38

2 years ago

1.0.40

2 years ago

1.0.44

2 years ago

1.0.43

2 years ago

1.0.42

2 years ago

1.0.41

2 years ago

1.0.48

2 years ago

1.0.47

2 years ago

1.0.46

2 years ago

1.0.45

2 years ago

1.0.16

2 years ago

1.0.15

2 years ago

1.0.14

2 years ago

1.0.13

2 years ago

1.0.12

2 years ago

1.0.11

2 years ago

1.0.10

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago