blakeembrey/free-style

User supplied identifier

broncha opened this issue · 6 comments

Hi!
Would you be open to the idea where user gets to pass in id to registerStyle ?
My use case here is, for a ui builder I am building, I am thinking of persisting the styles rules into an object like CSS Object. Then generate the css text from that using freestyle. Now with freestyle generating its own hash, I will need to keep track of the hashes. This might have been a small overhead, but what happens when the rules change? The old hash (class) also changes right?
An easy solution here seems like, if the user is allowed to pass in the identified, then the user manages the uniqueness and persists through changes in the rules

@broncha Did you find an answer to what you were trying to do?

I kind of went with styleSheet.registerCss(myCssObj)

But I just found another issue. This is a bit off-topic, but please help me understand this test I wrote. Am I expecting the right thing? styleSheet.registerCss did the thing I was looking for. But everytime I update the style from UI, I am getting duplicates. So basically if there were 6 rules before editing, I end up with 12 after a change, and it keeps on growing

it("removes style from cache", () => {
    const Style = create();

    Style.registerCss({
      body: {
        color: "red",
        "@print": {
          color: "blue"
        }
      },
      h1: {
        color: "red",
        "@print": {
          color: "#000",
          a: {
            color: "blue"
          }
        }
      }
    });

    for (const item of Style.values()) {
      Style.remove(item);
    }
    expect(Style.getStyles()).toEqual("");
  });

This test fails with

Expected: ""
    Received: "{color:red}@print{{color:blue}}"

@broncha Due to current semantics, yes. Basically, it expects you to remove the same things you added but the data structure stored in values is not the same structure you originally added. E.g. color:red and color:blue was de-duped due to being the same. The way this is used in my projects is I'll create separate Style instances, and use merge and unmerge instead (since it'll merge and unmerge the structures expected).

Here's a supported version of your test:

  it("removes style from cache", () => {
    const GlobalStyle = create();
    const Style = create();

    Style.registerCss({
      body: {
        color: "red",
        "@print": {
          color: "blue"
        }
      },
      h1: {
        color: "red",
        "@print": {
          color: "#000",
          a: {
            color: "blue"
          }
        }
      }
    });

    GlobalStyle.merge(Style);
    expect(GlobalStyle.getStyles()).toEqual(Style.getStyles());

    GlobalStyle.unmerge(Style);
    expect(GlobalStyle.getStyles()).toEqual("");
  });

Im using react-free-style for StyleSheetRendering. This did what I was looking for.

    const styleSheet = ContextStyle.freeStyle.clone()
    styleSheet.registerCss(memoizedCssObj)
    ContextStyle.freeStyle.merge(styleSheet)

Thanks for the pointer!

@broncha Depending on what you're doing, and if you're using react-free-style, you could just useCss. It does this sort of thing for you under the hood:

useCss(Style => Style.registerCss(cssObj))

Reference line: https://github.com/blakeembrey/react-free-style/blob/77c25b7ec7f1e606daba389d7edb8f61568adfa6/src/index.ts#L126