npm package: @lmnl/core
Description: ## Getting Started
Author: estrattonbailey
Latest version: 0.2.2

# lmnl

## Getting Started

Create theme(s):

```tsx
import { createTheme } from "@lmnl/core";

export const light = createTheme({
  tokens: {
    space: {
      s: 8,
      m: 16,
      l: 24,
    },
    color: {
      theme: "#ff4567",
      text: "#333",
    },
    fontSize: {
      s: 18,
      m: 22,
      l: 26,
    },
    lineHeight: {
      s: 18,
      m: 22,
      l: 26,
    },
    fontFamily: {
      sans: "sans-serif",
      mono: "monospace",
    },
    borderRadius: {
      s: 4,
      m: 8,
      l: 16,
    },
  },
  properties: {
    d: ["display"],
    w: ["width"],
    h: ["height"],
    c: ["color"],
    bg: ["backgroundColor"],
    ma: ["marginTop", "marginBottom", "marginLeft", "marginRight"],
    mt: ["marginTop"],
    mb: ["marginBottom"],
    ml: ["marginLeft"],
    mr: ["marginRight"],
    my: ["marginTop", "marginBottom"],
    mx: ["marginLeft", "marginRight"],
    pa: ["paddingTop", "paddingBottom", "paddingLeft", "paddingRight"],
    pt: ["paddingTop"],
    pb: ["paddingBottom"],
    pl: ["paddingLeft"],
    pr: ["paddingRight"],
    py: ["paddingTop", "paddingBottom"],
    px: ["paddingLeft", "paddingRight"],
    z: ["zIndex"],
    fs: ["fontSize"],
    ff: ["fontFamily"],
    fw: ["fontWeight"],
    lh: ["lineHeight"],
    ta: ["textAlign"],
    radius: ["borderRadius"],
  },
  macros: {
    row: (_: boolean) => ({ flexDirection: "row" }),
    column: (_: boolean) => ({ flex: 1 }),
    aic: (_: boolean) => ({ alignItems: "center" }),
    aie: (_: boolean) => ({ alignItems: "flex-end" }),
    jcs: (_: boolean) => ({ justifyContent: "flex-start" }),
    jcc: (_: boolean) => ({ justifyContent: "center" }),
    jce: (_: boolean) => ({ justifyContent: "flex-end" }),
    jcb: (_: boolean) => ({ justifyContent: "space-between" }),
    rel: (_: boolean) => ({ position: "relative" }),
    abs: (_: boolean) => ({ position: "absolute" }),
    cover: (_: boolean) => ({
      top: 0,
      bottom: 0,
      left: 0,
      right: 0,
    }),
    tac: (_: boolean) => ({ textAlign: "center" }),
    tar: (_: boolean) => ({ textAlign: "right" }),
    mxa: (_: boolean) => ({ marginLeft: "auto", marginRight: "auto" }),
    mya: (_: boolean) => ({ marginTop: "auto", marginBottom: "auto" }),
    caps: (_: boolean) => ({ textTransform: "uppercase" }),
    font(value: "black" | "bold" | "regular", tokens) {
      const variant = {
        black: {
          fontFamily: "inter_black",
        },
        bold: {
          fontFamily: "inter_bold",
        },
        regular: {
          fontFamily: "inter_regular",
        },
      }[value];
      return {
        ...variant,
      };
    },
    fontSize(value: "s" | "m" | "l", tokens) {
      return {
        fontSize: tokens.fontSize[value],
        lineHeight: tokens.lineHeight[value],
      };
    },
  },
  breakpoints: {
    gtPhone: 640,
  },
});

export const dark = createTheme({
  ...light.config,
  tokens: {
    ...light.config.tokens,
    color: {
      ...light.config.tokens.color,
      text: "#fff",
    },
  },
});
```

And then create a system. The boilerplate is intentional, it allows for greater
flexibility.

```tsx
// system.ts
import { createSystem } from "@lmnl/core";

import { light, dark } from "./themes";

const {
  ThemeProvider,
  useTheme,
  useBreakpoints,
  usePick,
  useStyle,
  useStyles,
  styled,
} = createSystem({
  light,
  dark,
});

// export for use in your app
export {
  ThemeProvider,
  useTheme,
  useBreakpoints,
  usePick,
  useStyle,
  useStyles,
  styled,
};

// export some base components
export const Box = styled(View, {});
export type BoxProps = React.ComponentProps<typeof Box>;

export const Text = styled(RNText, {
  color: "text",
});
export type TextProps = React.ComponentProps<typeof Text>;
```

Creating more complex components is pretty easy too. Here's an example of a
semantic HTML component (requires `react-native-web`):

```tsx
import { Text as RNText, Platform } from "react-native";

/**
 * @see https://necolas.github.io/react-native-web/docs/accessibility/#semantic-html
 * @see https://docs.expo.dev/develop/user-interface/fonts/
 */
export const H1 = styled(RNText, {
  role: web("heading"),
  color: "text",
  font: "black",
  fontSize: "m",
  gtPhone: {
    fontSize: "l",
  },
  ...Platform.select({
    web: {
      "aria-level": 1,
    },
  }),
});
```

## Usage

```tsx
import { Image, View } from "react-native";
import { web } from "@lmnl/core";
import {
  ThemeProvider,
  Box,
  Text,
  styled,
  useStyle,
  useStyles,
} from "./system";

const Img = styled(Image, {});

export function App() {
  const styles = useStyle({
    c: "theme",
    fs: "m",
    gtPhone: {
      fs: "l",
    },
  });
  const { outerStyles, innerStyles } = useStyles({
    outerStyles: {
      px: "m",
      h: web("100vh"),
      gtPhone: {
        px: "l",
      },
    },
    innerStyles: {
      pt: "m",
    },
  });

  return (
    <ThemeProvider theme="light">
      <View style={outerStyles}>
        <View style={innerStyles}>
          <Box pb="m" gtPhone={{ pb: "l" }}>
            <Text c="text" fs="l">
              Hello world
            </Text>
            <Img mt="s" source={{ uri: "https://picsum.photos/200/300" }} />
          </Box>
        </View>
      </View>
    </ThemeProvider>
  );
}
```