NEARBuilders / near-bos-webcomponent

Embed NEAR BOS content as a web component
https://petersalomonsen.github.io/near-bos-webcomponent/devhub.near/widget/app
The Unlicense
12 stars 6 forks source link

Routing within the webcomponent #2

Open elliotBraem opened 7 months ago

elliotBraem commented 7 months ago

This is an exploration into the potential of react-router-dom within the web component.

Context

Within the App.js, we do a few things considering react-router-dom:

We use it for taking in the widget source and query params for the root Widget to render:

const location = useLocation();

  useEffect(() => {
    const searchParams = new URLSearchParams(location.search);
    setWidgetProps(
      Array.from(searchParams.entries()).reduce((props, [key, value]) => {
        props[key] = value;
        return props;
      }, {})
    );
  }, [location]);

  let src = location.pathname;

We provide <Link /> as a custom element to the VM (so widgets within the web component can navigate):

customElements: {
    Link: (props) => {
      if (!props.to && props.href) {
        props.to = props.href;
        delete props.href;
      }
      if (props.to) {
        props.to = sanitizeUrl(props.to);
      }
      return <Link {...props} />;
    },
  },

And then we use the Router provider and a single Route to wrap the Viewer widget

return (
    <Router>
      <Route>
        <Viewer widgetSrc={props.widgetSrc} code={props.code}></Viewer>
      </Route>
    </Router>
  );

Areas of exploration

Routes Attribute

What if we allowed a "routes" attribute to <near-social-viewer /> web component?

The NearSocial/viewer already defines an object from data/widgets.js in order to handle some resolution, such as what to use for the default homepage widget and the View page source.

Sort of like how the redirectMap works, I think by passing routes attribute, we could dynamically create routes within this, for example:

Passing this

{
   view: "efiz.near/widget/myApp.view"
   edit: "efiz.near/widget/myApp.edit"
   about: "efiz.near/widget/myApp.about"
}

Would it let widgets within the web component navigate to /view, /edit or /about Could we simplify and standardize routing and pages for complex bos apps?

Widget Resolution Map

What if we passed a widget resolution map into the web component?

For example, a web component could be passed:

{
   image: { src: "mob.near/widget/Image", blockHeight: "12355322" } // locking a component at a specific version
}

Then, when a Widget references it like: <Widget src="image" props={{ }} />, it would resolve from this map. I could imagine this possibly being useful for locking Widget dependencies at specific "versions", and possibly improving the experience when working in different environments e.g testnet vs mainnet.

This may be very useful for customizations that come from a user's /settings in the socialdb.

Code Map

If we had a widget resolution map of some sort, is there any advantage to getting all the widget code from socialdb before loading the web-component, then passing this code map?

For example, a web component could be passed:

{
   image: "return <img src=...."
}

Then, maybe a special <Component> tag takes in a "name" prop like:

return <Component name="image" props={{ src: "" }} />

Then Component resolves the code from the map. Or even better, maybe this code map allows you to use <Image src="" /> freely in your code and will handle the resolution for you. Now developers don't need to worry about tag, using a widget source is more akin to providing a dependency and its version.

petersalomonsen commented 7 months ago

Many good suggestions here ! If passing these maps into the web component, would it then only work similar on near.org / near.social, or would we have configurations that would only work with the web component?

elliotBraem commented 7 months ago

Ideally it would work for prod too; maybe that means a Widget "backend" that embeds an iframe with the near-social-viewer "frontend" -- kinda like how near-social-bridge lets you build a React app then embed into a widget via iframe. It's an option for building larger bos apps in a more familiar environment; it sort-of closes the gap of the embedded app needing to reinstall the react dependencies etc; while still keeping the customizable, composable nature of near social widgets.

Or maybe it's just helpful for development, unbreaking for prod gateways like near.social and near.org, but specifically designed for web4, so that pages can act more like complex react apps.