Skip to content

Instantly share code, notes, and snippets.

@greymechanic
Created October 25, 2017 16:34
Show Gist options
  • Save greymechanic/53387977e37d52cd1cc0102a50142afa to your computer and use it in GitHub Desktop.
Save greymechanic/53387977e37d52cd1cc0102a50142afa to your computer and use it in GitHub Desktop.
const styleLocations = {
v: ["-top", "-bottom"],
h: ["-left", "-right"],
l: ["-left"],
r: ["-right"],
t: ["-top"],
b: ["-bottom"],
a: [""],
};
const styleTypes = {
m: "margin",
p: "padding",
};
const styleSizes = {
n: 0,
xs: 3,
x: 6,
m: 12,
l: 21,
xl: 36,
};
const buildWhiteSpace = () => {
let whitespace = {};
Object.keys(styleSizes).forEach(size => {
Object.keys(styleLocations).forEach(loc => {
Object.keys(styleTypes).forEach(type => {
let whitespaceClass = type + loc + size;
let ruleName = styleLocations[loc].map(r => {
return styleTypes[type] + r;
});
let rule = {};
ruleName.forEach(name => {
rule[name] = styleSizes[size];
});
whitespace[whitespaceClass] = rule;
});
});
});
return whitespace;
};
@zgotsch
Copy link

zgotsch commented Nov 3, 2017

As Flow is a static analysis system that doesn't understand Javascript, it isn't possible to do this sort of inference without augmentation. You could use a function to enforce typed access to the generated object:

const styleLocations = {
  v: ["-top", "-bottom"],
  h: ["-left", "-right"],
  l: ["-left"],
  r: ["-right"],
  t: ["-top"],
  b: ["-bottom"],
  a: ["-top", "-bottom", "-left", "-right"],
};
const styleTypes = {
  m: "margin",
  p: "padding",
};
const styleSizes = {
  n: 0,
  xs: 3,
  x: 6,
  m: 12,
  l: 21,
  xl: 36,
};

const whitespaceDefs = {};
Object.keys(styleSizes).forEach(size => {
  Object.keys(styleLocations).forEach(loc => {
    Object.keys(styleTypes).forEach(type => {
      let whitespaceClass = type + loc + size;
      let ruleName = styleLocations[loc].map(r => {
        return styleTypes[type] + r;
      });
      let rule = {};
      ruleName.forEach(name => {
        rule[name] = styleSizes[size];
      });
      whitespaceDefs[whitespaceClass] = rule;
    });
  });
});
const whitespaceSheet = StyleSheet.create(whitespaceDefs);

type StyleLocation: $Keys<typeof styleLocations>;
type StyleType: $Keys<typeof styleTypes>;
type StyleSize: $Keys<typeof styleSize>;

function ws(type: StyleType, location: StyleLocation, size: StyleSize): SheetDefinition {
  const key = [location, type, size].join("");
  const definition = whitespaceSheet[key];
  invariant(definition !== undefined, "Asked for a missing whitespace definition. This should never typecheck.");
  return definition;
}

Usage:
<MyComponent className={css(ws("m", "t", "s"))} />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment