Skip to content

Commit

Permalink
feat: add rules for border and rounded (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
nwikstrand committed Feb 4, 2023
1 parent 67a2ebc commit 48ec500
Show file tree
Hide file tree
Showing 5 changed files with 297 additions and 0 deletions.
56 changes: 56 additions & 0 deletions plugin/src/_rules/border.js
@@ -0,0 +1,56 @@
import { handler as h, directionMap, cornerMap } from "#utils";

const borderStyles = [
"solid",
"dashed",
"dotted",
"double",
"hidden",
"none",
"groove",
"ridge",
"inset",
"outset",
];

export const borders = [
[/^border$/, handlerBorder],
[/^border()-(\d+)$/, handlerBorder, { autocomplete: "(border)-<directions>" }],
[/^border-([xy])-(\d+)$/, handlerBorder],
[/^border-([rltb])$/, handlerBorder],
[/^border-([rltb])-(\d+)$/, handlerBorder],
[/^border()-(.+)$/, handlerBorderStyle, { autocomplete: "(border)-style" }],
[/^border-([xy])-(.+)$/, handlerBorderStyle],
[/^border-([rltb])-(.+)$/, handlerBorderStyle],
];

function handlerBorder(m, ctx) {
const borderSizes = handlerBorderSize(m, ctx);

if (borderSizes ) return [...borderSizes];
}

function handlerBorderSize([, a = "", b], { theme }) {
const v = theme.lineWidth?.[b ?? 1];
if (a in directionMap && v != null)
return directionMap[a].map((i) => [`border${i}-width`, v]);
}

function handlerBorderStyle([, a = "", s]) {
if (borderStyles.includes(s) && a in directionMap)
return directionMap[a].map((i) => [`border${i}-style`, s]);
}

export const rounded = [
[/^rounded()(?:-(.+))?$/, handlerRounded, { autocomplete: ['(rounded)', '(rounded)-<num>'] }],
[/^rounded-([rltb]+)(?:-(.+))?$/, handlerRounded],
[/^rounded([rltb]{2})(?:-(.+))?$/, handlerRounded],
[/^rounded-([bi][se])(?:-(.+))?$/, handlerRounded],
[/^rounded-([bi][se]-[bi][se])(?:-(.+))?$/, handlerRounded],
]

function handlerRounded([, a = '', s], { theme }) {
const v = theme.borderRadius?.[s ?? 4];
if (a in cornerMap && v != null)
return cornerMap[a].map(i => [`border${i}-radius`, v]);
}
3 changes: 3 additions & 0 deletions plugin/src/_rules/index.js
@@ -1,4 +1,5 @@
import * as align from "./align.js";
import * as border from "./border.js";
import * as color from "./color.js";
import * as display from "./display.js";
import * as flex from "./flex.js";
Expand All @@ -13,6 +14,7 @@ import * as spacing from "./spacing.js";

const ruleGroups = {
...align,
...border,
...color,
...display,
...flex,
Expand All @@ -31,6 +33,7 @@ export const rules = [
].flat(1);

export * from "./align.js";
export * from "./border.js";
export * from "./color.js";
export * from "./display.js";
export * from "./flex.js";
Expand Down
21 changes: 21 additions & 0 deletions plugin/src/theme.js
Expand Up @@ -24,16 +24,37 @@ const zIndex = {
50: "50",
}

const lineWidth = {
0: "0",
1: "1px",
2: "2px",
4: "4px",
8: "8px",
}

const borderRadius = {
0: "0",
2: "2px",
4: "4px",
6: "6px",
8: "8px",
16: "16px",
"full": "9999px",
}

export const useTheme = (opts = {}) => {
const baseSpacing = opts.usePixels ? spacingInPx : spacingInRem
const width = { ...baseSpacing, screen: '100vw' }
const height = { ...baseSpacing, screen: '100vh' }

return {
usingPixels: !!opts.pxSpacing,
breakpoints,
borderRadius,
verticalBreakpoints: breakpoints,
spacing: baseSpacing,
zIndex,
lineWidth,
width,
height,
maxWidth: { none: 'none', ...width },
Expand Down
123 changes: 123 additions & 0 deletions plugin/test/__snapshots__/border.js.snap
@@ -0,0 +1,123 @@
// Vitest Snapshot v1

exports[`border > right, left, top bottom 1`] = `
"/* layer: default */
.border-b{border-bottom-width:1px;}
.border-l{border-left-width:1px;}
.border-r{border-right-width:1px;}
.border-t{border-top-width:1px;}
.border-b-0{border-bottom-width:0;}
.border-b-2{border-bottom-width:2px;}
.border-b-4{border-bottom-width:4px;}
.border-b-8{border-bottom-width:8px;}
.border-l-0{border-left-width:0;}
.border-l-2{border-left-width:2px;}
.border-l-4{border-left-width:4px;}
.border-l-8{border-left-width:8px;}
.border-r-0{border-right-width:0;}
.border-r-2{border-right-width:2px;}
.border-r-4{border-right-width:4px;}
.border-r-8{border-right-width:8px;}
.border-t-0{border-top-width:0;}
.border-t-2{border-top-width:2px;}
.border-t-4{border-top-width:4px;}
.border-t-8{border-top-width:8px;}"
`;

exports[`border > supports setting border style 1`] = `
"/* layer: default */
.border-dashed{border-style:dashed;}
.border-dotted{border-style:dotted;}
.border-double{border-style:double;}
.border-groove{border-style:groove;}
.border-hidden{border-style:hidden;}
.border-inset{border-style:inset;}
.border-none{border-style:none;}
.border-outset{border-style:outset;}
.border-ridge{border-style:ridge;}
.border-solid{border-style:solid;}"
`;

exports[`border > supports setting border width 1`] = `
"/* layer: default */
.border{border-width:1px;}
.border-0{border-width:0;}
.border-2{border-width:2px;}
.border-4{border-width:4px;}
.border-8{border-width:8px;}"
`;

exports[`border > supports x|y with value 1`] = `
"/* layer: default */
.border-x-0{border-left-width:0;border-right-width:0;}
.border-x-2{border-left-width:2px;border-right-width:2px;}
.border-x-4{border-left-width:4px;border-right-width:4px;}
.border-x-8{border-left-width:8px;border-right-width:8px;}
.border-y-0{border-top-width:0;border-bottom-width:0;}
.border-y-2{border-top-width:2px;border-bottom-width:2px;}
.border-y-4{border-top-width:4px;border-bottom-width:4px;}
.border-y-8{border-top-width:8px;border-bottom-width:8px;}"
`;

exports[`rounded > supports x|y with value 1`] = `
"/* layer: default */
.rounded,
.rounded-4{border-radius:4px;}
.rounded-0{border-radius:0;}
.rounded-16{border-radius:16px;}
.rounded-2{border-radius:2px;}
.rounded-8{border-radius:8px;}
.rounded-full{border-radius:9999px;}
.rounded-b,
.rounded-b-4{border-bottom-left-radius:4px;border-bottom-right-radius:4px;}
.rounded-b-0{border-bottom-left-radius:0;border-bottom-right-radius:0;}
.rounded-b-16{border-bottom-left-radius:16px;border-bottom-right-radius:16px;}
.rounded-b-2{border-bottom-left-radius:2px;border-bottom-right-radius:2px;}
.rounded-b-8{border-bottom-left-radius:8px;border-bottom-right-radius:8px;}
.rounded-b-full{border-bottom-left-radius:9999px;border-bottom-right-radius:9999px;}
.rounded-bl-0{border-bottom-left-radius:0;}
.rounded-bl-16{border-bottom-left-radius:16px;}
.rounded-bl-2{border-bottom-left-radius:2px;}
.rounded-bl-4{border-bottom-left-radius:4px;}
.rounded-bl-8{border-bottom-left-radius:8px;}
.rounded-bl-full{border-bottom-left-radius:9999px;}
.rounded-br-0{border-bottom-right-radius:0;}
.rounded-br-16{border-bottom-right-radius:16px;}
.rounded-br-2{border-bottom-right-radius:2px;}
.rounded-br-4{border-bottom-right-radius:4px;}
.rounded-br-8{border-bottom-right-radius:8px;}
.rounded-br-full{border-bottom-right-radius:9999px;}
.rounded-l,
.rounded-l-4{border-top-left-radius:4px;border-bottom-left-radius:4px;}
.rounded-l-0{border-top-left-radius:0;border-bottom-left-radius:0;}
.rounded-l-16{border-top-left-radius:16px;border-bottom-left-radius:16px;}
.rounded-l-2{border-top-left-radius:2px;border-bottom-left-radius:2px;}
.rounded-l-8{border-top-left-radius:8px;border-bottom-left-radius:8px;}
.rounded-l-full{border-top-left-radius:9999px;border-bottom-left-radius:9999px;}
.rounded-r,
.rounded-r-4{border-top-right-radius:4px;border-bottom-right-radius:4px;}
.rounded-r-0{border-top-right-radius:0;border-bottom-right-radius:0;}
.rounded-r-16{border-top-right-radius:16px;border-bottom-right-radius:16px;}
.rounded-r-2{border-top-right-radius:2px;border-bottom-right-radius:2px;}
.rounded-r-8{border-top-right-radius:8px;border-bottom-right-radius:8px;}
.rounded-r-full{border-top-right-radius:9999px;border-bottom-right-radius:9999px;}
.rounded-t,
.rounded-t-4{border-top-left-radius:4px;border-top-right-radius:4px;}
.rounded-t-0{border-top-left-radius:0;border-top-right-radius:0;}
.rounded-t-16{border-top-left-radius:16px;border-top-right-radius:16px;}
.rounded-t-2{border-top-left-radius:2px;border-top-right-radius:2px;}
.rounded-t-8{border-top-left-radius:8px;border-top-right-radius:8px;}
.rounded-t-full{border-top-left-radius:9999px;border-top-right-radius:9999px;}
.rounded-tl-0{border-top-left-radius:0;}
.rounded-tl-16{border-top-left-radius:16px;}
.rounded-tl-2{border-top-left-radius:2px;}
.rounded-tl-4{border-top-left-radius:4px;}
.rounded-tl-8{border-top-left-radius:8px;}
.rounded-tl-full{border-top-left-radius:9999px;}
.rounded-tr-0{border-top-right-radius:0;}
.rounded-tr-16{border-top-right-radius:16px;}
.rounded-tr-2{border-top-right-radius:2px;}
.rounded-tr-4{border-top-right-radius:4px;}
.rounded-tr-8{border-top-right-radius:8px;}
.rounded-tr-full{border-top-right-radius:9999px;}"
`;
94 changes: 94 additions & 0 deletions plugin/test/border.js
@@ -0,0 +1,94 @@
import { setup } from "./_helpers.js";
import { describe, expect, test } from "vitest";

setup();

describe("border", () => {
test("supports x|y with value", async (t) => {
const x = ["border-x-0", "border-x-2", "border-x-4", "border-x-8"];
const y = ["border-y-0", "border-y-2", "border-y-4", "border-y-8"];

const classes = [...x, ...y];

const { css } = await t.uno.generate(classes);

expect(css).toMatchSnapshot();
});

test("supports setting border width", async (t) => {
const classes = ["border", "border-0", "border-2", "border-4", "border-8"];

const { css } = await t.uno.generate(classes);

expect(css).toMatchSnapshot();
});

test("supports setting border style", async (t) => {
const classes = [
"border-solid",
"border-dashed",
"border-dotted",
"border-double",
"border-hidden",
"border-none",
"border-groove",
"border-ridge",
"border-inset",
"border-outset",
];

const { css } = await t.uno.generate(classes);

expect(css).toMatchSnapshot();
});

test("right, left, top bottom", async (t) => {
const right = [
"border-r",
"border-r-0",
"border-r-2",
"border-r-4",
"border-r-8",
];

const left = [
"border-l",
"border-l-0",
"border-l-2",
"border-l-4",
"border-l-8",
];

const top = [
"border-t",
"border-t-0",
"border-t-2",
"border-t-4",
"border-t-8",
];

const bottom = [
"border-b",
"border-b-0",
"border-b-2",
"border-b-4",
"border-b-8",
];

const classes = [...right, ...left, ...top, ...bottom];

const { css } = await t.uno.generate(classes);

expect(css).toMatchSnapshot();
});
});

describe("rounded", () => {
test("supports x|y with value", async (t) => {
const classes = ["rounded", "rounded-0", "rounded-2", "rounded-4", "rounded-8", "rounded-16", "rounded-full", "rounded-t", "rounded-t-0", "rounded-t-2", "rounded-t-4", "rounded-t-8", "rounded-t-16", "rounded-t-full", "rounded-r", "rounded-r-0", "rounded-r-2", "rounded-r-4", "rounded-r-8", "rounded-r-16", "rounded-r-full", "rounded-b", "rounded-b-0", "rounded-b-2", "rounded-b-4", "rounded-b-8", "rounded-b-16", "rounded-b-full", "rounded-l", "rounded-l-0", "rounded-l-2", "rounded-l-4", "rounded-l-8", "rounded-l-16", "rounded-l-full", "rounded-tl-0", "rounded-tl-2", "rounded-tl-4", "rounded-tl-8", "rounded-tl-16", "rounded-tl-full", "rounded-tr-0", "rounded-tr-2", "rounded-tr-4", "rounded-tr-8", "rounded-tr-16", "rounded-tr-full", "rounded-br-0", "rounded-br-2", "rounded-br-4", "rounded-br-8", "rounded-br-16", "rounded-br-full", "rounded-bl-0", "rounded-bl-2", "rounded-bl-4", "rounded-bl-8", "rounded-bl-16", "rounded-bl-full"];

const { css } = await t.uno.generate(classes);

expect(css).toMatchSnapshot();
});
});

0 comments on commit 48ec500

Please sign in to comment.