nonzzz / stylex-extend

An unofficial stylexjs extension
https://nonzzz.github.io/stylex-extend/
MIT License
12 stars 0 forks source link

How to pass props using inline? #11

Open zaydek opened 2 months ago

zaydek commented 2 months ago

I'm trying to do something like the following:

function Foo({ foo }: { foo: any }) {
  return (
    <div {...stylex.props(foo)}>
      helloasdasdasd
    </div>
  );
}

export function App() {
  return (
    <>
      <Foo foo={inline({ backgroundColor: "red" })} />
      <div {...stylex.props(inline({ color: "blue" }))}>
        hello
      </div>
    </>
  );
}

Is it possible to create your own prop for accepting inline on a component?

But I get this error:

react-dom_client.js?v=857fe929:19441 Uncaught Error: 'inline' calls should be compiled away.
    at inline (@stylex-extend_core.js?t=1716341981246&v=857fe929:8:9)
    at App (app.tsx:37:1)
    at renderWithHooks (react-dom_client.js?v=857fe929:11568:26)
    at mountIndeterminateComponent (react-dom_client.js?v=857fe929:14946:21)
    at beginWork (react-dom_client.js?v=857fe929:15934:22)
    at beginWork$1 (react-dom_client.js?v=857fe929:19781:22)
    at performUnitOfWork (react-dom_client.js?v=857fe929:19226:20)
    at workLoopSync (react-dom_client.js?v=857fe929:19165:13)
    at renderRootSync (react-dom_client.js?v=857fe929:19144:15)
    at recoverFromConcurrentError (react-dom_client.js?v=857fe929:18764:28)

Let me know if you need a repro.

zaydek commented 2 months ago
import { inline } from "@stylex-extend/core";
import * as stylex from "@stylexjs/stylex";

const red = inline({ backgroundColor: "red" });

function Foo({ extend }: { extend?: any }) {
  return (
    <div {...stylex.props(extend)}>
      hello
    </div>
  );
}

export function App() {
  return (
    <>
      <Foo extend={red} />
    </>
  );
}
@stylex-extend_core.js?t=1716342266224&v=857fe929:8 Uncaught Error: 'inline' calls should be compiled away.
    at inline (@stylex-extend_core.js?t=1716342266224&v=857fe929:8:9)
    at app.tsx:5:3

I can't quite tell if extend's type is supposed to be stylex.StyleXStyles or something else.

nonzzz commented 2 months ago

Oh, Currently i made a restriction on inline api. It only can called with as a argument with function call. Like this code block can be process

import { inline } from "@stylex-extend/core";

const fn = <T>(...args: T[]) => {
  return args;
};

// correct
const result = fn(inline({ color: "red" }));

// incorrect

const result2 = inline({ color: "pink" });

Follow the correct case it will be translate as

import { create as _create, props as _props } from "@stylexjs/stylex";
const _styles = _create({
  "#0": {
    color: "red",
  },
});
import { inline } from "@stylex-extend/core";
const fn = (...args) => {
  return args;
};
const result = fn(_styles["#0"]);

So i think you can try define a wrapper function to implment the extend feature.

zaydek commented 2 months ago

Yes that worked — thank you! I'll use the fn trick for now. Feel free to ping me if you have an update on this.

nonzzz commented 2 months ago

Restricting inline calls is intended to prevent the abuse of this behavior.

zaydek commented 2 months ago

But wouldn't it be ideal to say

<Foo extend={atom({ backgroundColor: "red" })} />

Instead of

<Foo extend={fn(atom({ backgroundColor: "red" }))} />

?

nonzzz commented 2 months ago

Right. using a function wrapper it.

nonzzz commented 2 months ago

About this limit i think i should find a balance to design it. As you can see is too hard to use when implementing extend.

zaydek commented 2 months ago

Take your time. I'm going to experiment with https://github.com/facebook/stylex/issues/534#issuecomment-2121745213 in the meantime.

predaytor commented 2 weeks ago

really cool! but using this wrapper unfortunately doesn't work:

import { inline } from '@stylex-extend/core';
import type { CSSObject } from '@stylex-extend/shared';

const fn = <T>(...args: T[]) => args;

export const atom = (args: CSSObject) => fn(inline(args));

only direct definition works:

export const atom = (args: CSSObject) => fn(inline({ opacity: '50%' }));
nonzzz commented 2 weeks ago

@predaytor It's a limit.