grailwind 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/README.md +6 -5
- package/charges.js +33 -2
- package/grailwind.css +9 -0
- package/ordinaries.js +204 -16
- package/package.json +5 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format is based
|
|
4
|
+
on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.2.0] - 2026-11-01
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Charges `on` an ordinary: `charges on` places one, two, three or five charges
|
|
12
|
+
along the pale, fess, bend, bend sinister, chevron, cross, saltire or pall.
|
|
13
|
+
- Fimbriation: `fimbriated-<tincture>` edges an ordinary with a narrow border,
|
|
14
|
+
e.g. `cross-azure fimbriated-argent`.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- Charges at `in-dexter-chief`, `in-chief` and `in-sinister-chief` now sit on
|
|
19
|
+
the chief when one is present, and charges are drawn above it.
|
|
20
|
+
|
|
21
|
+
## [0.1.0] - 2026-10-31
|
|
22
|
+
|
|
23
|
+
Initial release: tinctures, divisions, ordinaries, charges, strict mode and
|
|
24
|
+
custom SVG charges.
|
|
25
|
+
|
|
26
|
+
[0.2.0]: https://github.com/pafirmin/grailwind/compare/v0.1.0...v0.2.0
|
|
27
|
+
[0.1.0]: https://github.com/pafirmin/grailwind/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Grailwind CSS
|
|
2
2
|
|
|
3
|
+

|
|
4
|
+
|
|
3
5
|
Heraldic blazon for [Tailwind CSS](https://tailwindcss.com). Draw coats of
|
|
4
6
|
arms, or style anything else, in the language heralds have used for 800 years:
|
|
5
7
|
|
|
@@ -51,9 +53,9 @@ tinctures replace Tailwind's colours entirely.
|
|
|
51
53
|
`gyronny-or-sable` and more, or `per-pale`, `per-fess` and `quarterly` for
|
|
52
54
|
layout.
|
|
53
55
|
- **Ordinaries:** `fess-or`, `chevron-gules`, `cross-argent`, `chief-azure`
|
|
54
|
-
and more.
|
|
56
|
+
and more, with `fimbriated-*` for a narrow border.
|
|
55
57
|
- **Charges:** `mullet`, `fleur-de-lis`, `bezant` and more, arranged by
|
|
56
|
-
number, `in-pale`, `in-fess`, `in-bend` or `between` the ordinary, or
|
|
58
|
+
number, `in-pale`, `in-fess`, `in-bend`, `on` or `between` the ordinary, or
|
|
57
59
|
placed at a named point such as `in-dexter-chief`, and sized with
|
|
58
60
|
`charge-size-*`.
|
|
59
61
|
- **Your own charges:** any SVG, via `charge-[url(…)]`.
|
|
@@ -62,9 +64,8 @@ tinctures replace Tailwind's colours entirely.
|
|
|
62
64
|
|
|
63
65
|
```sh
|
|
64
66
|
npm install
|
|
65
|
-
npm test
|
|
66
|
-
npm run
|
|
67
|
-
python3 -m http.server -d docs
|
|
67
|
+
npm test # checks both the default and strict builds
|
|
68
|
+
npm run dev:watch # rebuilds the docs site on change and serves it at http://localhost:8000
|
|
68
69
|
```
|
|
69
70
|
|
|
70
71
|
## Licence
|
package/charges.js
CHANGED
|
@@ -63,6 +63,9 @@ const POINTS = {
|
|
|
63
63
|
};
|
|
64
64
|
const POINT_SIZE = 22;
|
|
65
65
|
|
|
66
|
+
// With a chief on the shield, these points sit on it (see ordinaries.js).
|
|
67
|
+
const CHIEF_POINTS = new Set(["dexter-chief", "chief", "sinister-chief"]);
|
|
68
|
+
|
|
66
69
|
const ARRANGEMENTS = {
|
|
67
70
|
"in-pale": {
|
|
68
71
|
2: { size: 30, points: [[50, 24], [50, 66]] },
|
|
@@ -119,6 +122,8 @@ export default plugin(({ addUtilities, matchUtilities }) => {
|
|
|
119
122
|
const charges = {
|
|
120
123
|
position: "absolute",
|
|
121
124
|
inset: "var(--field-top, 0%) 0 0",
|
|
125
|
+
// Above the chief, which is painted last, so charges can sit on it.
|
|
126
|
+
"z-index": "1",
|
|
122
127
|
"& > *": {
|
|
123
128
|
position: "absolute",
|
|
124
129
|
"aspect-ratio": "1",
|
|
@@ -155,8 +160,34 @@ export default plugin(({ addUtilities, matchUtilities }) => {
|
|
|
155
160
|
}
|
|
156
161
|
utilities[".between"] = between;
|
|
157
162
|
|
|
158
|
-
|
|
159
|
-
|
|
163
|
+
// Falls back to the plain-field default when the ordinary has no points for this count.
|
|
164
|
+
// An undefined var() would otherwise unset `left`/`top` instead of deferring to the :where() default.
|
|
165
|
+
const on = {};
|
|
166
|
+
for (const count of [1, 2, 3, 5]) {
|
|
167
|
+
const fallback = DEFAULTS[count];
|
|
168
|
+
for (let i = 1; i <= count; i++) {
|
|
169
|
+
const [left, top] = fallback?.points[i - 1] ?? [];
|
|
170
|
+
const at = (axis, value) =>
|
|
171
|
+
value === undefined ? `var(--on-${count}-${i}-${axis})` : `var(--on-${count}-${i}-${axis}, ${value}%)`;
|
|
172
|
+
on[`&${hasCount(count)} > :nth-child(${i})`] = {
|
|
173
|
+
left: at("x", left),
|
|
174
|
+
top: at("y", top),
|
|
175
|
+
width: `var(--charge-size, var(--on-size, ${fallback?.size ?? 16}%))`,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
utilities[".on"] = on;
|
|
180
|
+
|
|
181
|
+
for (const [name, [left, top]] of Object.entries(POINTS)) {
|
|
182
|
+
utilities[`.in-${name}`] = {
|
|
183
|
+
".charges > &": CHIEF_POINTS.has(name)
|
|
184
|
+
? {
|
|
185
|
+
left: `${left}%`,
|
|
186
|
+
top: `var(--chief-points-y, ${top}%)`,
|
|
187
|
+
width: `var(--charge-size, var(--chief-points-size, ${POINT_SIZE}%))`,
|
|
188
|
+
}
|
|
189
|
+
: place([left, top], POINT_SIZE),
|
|
190
|
+
};
|
|
160
191
|
}
|
|
161
192
|
|
|
162
193
|
addUtilities(utilities);
|
package/grailwind.css
CHANGED
|
@@ -13,6 +13,15 @@
|
|
|
13
13
|
@plugin "./ordinaries.js";
|
|
14
14
|
@plugin "./charges.js";
|
|
15
15
|
|
|
16
|
+
@property --fimbriated {
|
|
17
|
+
syntax: "*";
|
|
18
|
+
inherits: false;
|
|
19
|
+
}
|
|
20
|
+
@property --fimbriation {
|
|
21
|
+
syntax: "*";
|
|
22
|
+
inherits: false;
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
/* ---------------------------------------------------------------------------
|
|
17
26
|
* Tinctures
|
|
18
27
|
* ------------------------------------------------------------------------- */
|
package/ordinaries.js
CHANGED
|
@@ -6,22 +6,164 @@ import plugin from "tailwindcss/plugin";
|
|
|
6
6
|
const TINCTURES = ["or", "argent", "gules", "azure", "vert", "purpure", "sable"];
|
|
7
7
|
|
|
8
8
|
const ORDINARIES = {
|
|
9
|
-
pale:
|
|
10
|
-
fess:
|
|
11
|
-
bend:
|
|
12
|
-
"bend-sinister":
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
pale: [[35, 0], [65, 0], [65, 100], [35, 100]],
|
|
10
|
+
fess: [[0, 30], [100, 30], [100, 60], [0, 60]],
|
|
11
|
+
bend: [[0, 0], [20, 0], [100, 80], [100, 100], [80, 100], [0, 20]],
|
|
12
|
+
"bend-sinister": [[100, 0], [80, 0], [0, 80], [0, 100], [20, 100], [100, 20]],
|
|
13
|
+
chevron: [[50, 25], [100, 75], [100, 95], [50, 45], [0, 95], [0, 75]],
|
|
14
|
+
cross: [
|
|
15
|
+
[40, 0], [60, 0], [60, 35], [100, 35], [100, 55], [60, 55],
|
|
16
|
+
[60, 100], [40, 100], [40, 55], [0, 55], [0, 35], [40, 35],
|
|
17
|
+
],
|
|
18
|
+
saltire: [
|
|
19
|
+
[0, 0], [15, 0], [50, 35], [85, 0], [100, 0], [100, 15], [65, 50], [100, 85],
|
|
20
|
+
[100, 100], [85, 100], [50, 65], [15, 100], [0, 100], [0, 85], [35, 50], [0, 15],
|
|
21
|
+
],
|
|
22
|
+
pall: [
|
|
23
|
+
[0, 0], [15, 0], [50, 35], [85, 0], [100, 0], [100, 15],
|
|
24
|
+
[60, 55], [60, 100], [40, 100], [40, 55], [0, 15],
|
|
25
|
+
],
|
|
26
|
+
chief: [[0, 0], [100, 0], [100, 30], [0, 30]],
|
|
21
27
|
};
|
|
22
28
|
|
|
29
|
+
const num = (v) => +v.toFixed(3);
|
|
30
|
+
const pct = (v) => (num(v) === 0 ? "0" : `${num(v)}%`);
|
|
31
|
+
const point = ([x, y]) => `${pct(x)} ${pct(y)}`;
|
|
32
|
+
const polygon = (vertices) => `polygon(${vertices.map(point).join(", ")})`;
|
|
33
|
+
|
|
23
34
|
const PSEUDO = { chief: "&::after" };
|
|
24
35
|
|
|
36
|
+
// Fimbriation: the ordinary's clip is widened and filled with the fimbriation
|
|
37
|
+
// tincture, and the ordinary's own tincture is painted over it as gradient
|
|
38
|
+
// bands.
|
|
39
|
+
const W = 100;
|
|
40
|
+
const H = 120;
|
|
41
|
+
const FIMBRIATION = 3;
|
|
42
|
+
|
|
43
|
+
const real = ([x, y]) => [(x * W) / 100, (y * H) / 100];
|
|
44
|
+
const onShieldEdge = (a, b) =>
|
|
45
|
+
(a[0] === b[0] && (a[0] === 0 || a[0] === 100)) ||
|
|
46
|
+
(a[1] === b[1] && (a[1] === 0 || a[1] === 100));
|
|
47
|
+
const signedArea = (vertices) =>
|
|
48
|
+
vertices.reduce((sum, [x1, y1], i) => {
|
|
49
|
+
const [x2, y2] = vertices[(i + 1) % vertices.length];
|
|
50
|
+
return sum + x1 * y2 - x2 * y1;
|
|
51
|
+
}, 0) / 2;
|
|
52
|
+
|
|
53
|
+
// The edge a→b as a line n·p = c, moved outward by `distance` real units.
|
|
54
|
+
const offsetLine = (a, b, outward, distance) => {
|
|
55
|
+
const [ax, ay] = real(a);
|
|
56
|
+
const [bx, by] = real(b);
|
|
57
|
+
const length = Math.hypot(bx - ax, by - ay);
|
|
58
|
+
const n = [(outward * (by - ay)) / length, (outward * (ax - bx)) / length];
|
|
59
|
+
return { n, c: n[0] * ax + n[1] * ay + distance };
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// How far each vertex moves, in %, when fimbriated. Sides on the shield's edge
|
|
63
|
+
// don't move, so their vertices slide along it.
|
|
64
|
+
const widen = (vertices) => {
|
|
65
|
+
const outward = Math.sign(signedArea(vertices));
|
|
66
|
+
const count = vertices.length;
|
|
67
|
+
const line = (i) => {
|
|
68
|
+
const a = vertices[i];
|
|
69
|
+
const b = vertices[(i + 1) % count];
|
|
70
|
+
return offsetLine(a, b, outward, onShieldEdge(a, b) ? 0 : FIMBRIATION);
|
|
71
|
+
};
|
|
72
|
+
return vertices.map((v, i) => {
|
|
73
|
+
const p = line((i - 1 + count) % count);
|
|
74
|
+
const q = line(i);
|
|
75
|
+
const det = p.n[0] * q.n[1] - p.n[1] * q.n[0];
|
|
76
|
+
const [x, y] = [(p.c * q.n[1] - q.c * p.n[1]) / det, (p.n[0] * q.c - q.n[0] * p.c) / det];
|
|
77
|
+
const [rx, ry] = real(v);
|
|
78
|
+
return [((x - rx) * 100) / W, ((y - ry) * 100) / H];
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const shift = (v, d) =>
|
|
83
|
+
num(d) === 0
|
|
84
|
+
? pct(v)
|
|
85
|
+
: `calc(${num(v)}% ${d < 0 ? "-" : "+"} ${num(Math.abs(d))}% * var(--fimbriated, 0))`;
|
|
86
|
+
const widenedPolygon = (vertices) => {
|
|
87
|
+
const offsets = widen(vertices);
|
|
88
|
+
const points = vertices.map(
|
|
89
|
+
([x, y], i) => `${shift(x, offsets[i][0])} ${shift(y, offsets[i][1])}`,
|
|
90
|
+
);
|
|
91
|
+
return `polygon(${points.join(", ")})`;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// The ordinary's tincture, top layer first. `x`/`y` bands run between two x or y
|
|
95
|
+
// values in %; `u-v`/`u+v` are diagonal, between values of x − y or x + y.
|
|
96
|
+
// A `tile` [x0, y0, x1, y1] confines a layer to part of the box (square, if
|
|
97
|
+
// diagonal). Stripes repaint the fimbriation where one arm's band runs on into
|
|
98
|
+
// another's.
|
|
99
|
+
const S = 12;
|
|
100
|
+
const band = (kind, from, to, tile) => ({ kind, from, to, tile });
|
|
101
|
+
const stripe = (kind, from, to, tile) => ({ kind, from, to, tile, stripe: true });
|
|
102
|
+
const BANDS = {
|
|
103
|
+
pale: [band("x", 35, 65)],
|
|
104
|
+
fess: [band("y", 30, 60)],
|
|
105
|
+
bend: [band("u-v", -20, 20)],
|
|
106
|
+
"bend-sinister": [band("u+v", 80, 120)],
|
|
107
|
+
chevron: [
|
|
108
|
+
stripe("u+v", 75 - S, 75),
|
|
109
|
+
stripe("u-v", 25, 25 + S),
|
|
110
|
+
band("u+v", 75, 95),
|
|
111
|
+
band("u-v", 5, 25),
|
|
112
|
+
],
|
|
113
|
+
cross: [band("x", 40, 60), band("y", 35, 55)],
|
|
114
|
+
saltire: [band("u-v", -15, 15), band("u+v", 85, 115)],
|
|
115
|
+
pall: [
|
|
116
|
+
stripe("x", 60, 60 + S, [0, 55, 100, 100]),
|
|
117
|
+
stripe("x", 40 - S, 40, [0, 55, 100, 100]),
|
|
118
|
+
stripe("u+v", 115, 115 + S, [60, 30, 100, 70]),
|
|
119
|
+
stripe("u-v", -15 - S, -15, [0, 30, 40, 70]),
|
|
120
|
+
band("u-v", -15, 15),
|
|
121
|
+
band("u+v", 85, 115),
|
|
122
|
+
band("x", 40, 60, [0, 55, 100, 100]),
|
|
123
|
+
],
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const DIRECTION = { x: "to right", y: "to bottom", "u-v": "to top right", "u+v": "to bottom right" };
|
|
127
|
+
|
|
128
|
+
// A band's edges as % along its gradient, within its tile.
|
|
129
|
+
const stop = ({ kind, tile: [x0, y0, x1, y1] = [0, 0, 100, 100] }, value) => {
|
|
130
|
+
const w = x1 - x0;
|
|
131
|
+
const h = y1 - y0;
|
|
132
|
+
if (kind.length > 1 && w !== h) throw new Error("diagonal bands need a square tile");
|
|
133
|
+
switch (kind) {
|
|
134
|
+
case "x": return ((value - x0) * 100) / w;
|
|
135
|
+
case "y": return ((value - y0) * 100) / h;
|
|
136
|
+
case "u-v": return ((value - (x0 - y0)) * 100) / w / 2 + 50;
|
|
137
|
+
case "u+v": return ((value - x0 - y0) * 100) / w / 2;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// Soften each edge by a pixel, as hard gradient stops aren't antialiased.
|
|
142
|
+
const gradient = (layer, colour) => {
|
|
143
|
+
const a = num(stop(layer, layer.from));
|
|
144
|
+
const b = num(stop(layer, layer.to));
|
|
145
|
+
return (
|
|
146
|
+
`linear-gradient(${DIRECTION[layer.kind]}, transparent calc(${a}% - 0.5px), ` +
|
|
147
|
+
`${colour} calc(${a}% + 0.5px) calc(${b}% - 0.5px), transparent calc(${b}% + 0.5px))`
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const tilePosition = (start, size) => (size === 100 ? "0" : pct((start * 100) / (100 - size)));
|
|
152
|
+
|
|
153
|
+
const bands = (layers, tincture) => ({
|
|
154
|
+
"background-image": layers
|
|
155
|
+
.map((l) => gradient(l, l.stripe ? "var(--fimbriation, transparent)" : `var(--color-${tincture})`))
|
|
156
|
+
.join(", "),
|
|
157
|
+
"background-size": layers
|
|
158
|
+
.map(({ tile: [x0, y0, x1, y1] = [0, 0, 100, 100] }) => `${pct(x1 - x0)} ${pct(y1 - y0)}`)
|
|
159
|
+
.join(", "),
|
|
160
|
+
"background-position": layers
|
|
161
|
+
.map(({ tile: [x0, y0, x1, y1] = [0, 0, 100, 100] }) =>
|
|
162
|
+
`${tilePosition(x0, x1 - x0)} ${tilePosition(y0, y1 - y0)}`)
|
|
163
|
+
.join(", "),
|
|
164
|
+
"background-repeat": "no-repeat",
|
|
165
|
+
});
|
|
166
|
+
|
|
25
167
|
// Where charges go for "between", as [left%, top%], plus their size as % of width.
|
|
26
168
|
const BETWEEN = {
|
|
27
169
|
pale: { size: 18, points: [[18, 42], [82, 42]] },
|
|
@@ -34,6 +176,18 @@ const BETWEEN = {
|
|
|
34
176
|
pall: { size: 18, points: [[50, 11], [18, 56], [82, 56]] },
|
|
35
177
|
};
|
|
36
178
|
|
|
179
|
+
// Where charges go for "on", along the ordinary's centre line, by number of charges.
|
|
180
|
+
const ON = {
|
|
181
|
+
pale: { size: 20, counts: { 1: [[50, 45]], 2: [[50, 28], [50, 62]], 3: [[50, 18], [50, 45], [50, 72]] } },
|
|
182
|
+
fess: { size: 22, counts: { 1: [[50, 45]], 2: [[30, 45], [70, 45]], 3: [[20, 45], [50, 45], [80, 45]] } },
|
|
183
|
+
bend: { size: 18, counts: { 1: [[50, 50]], 2: [[33, 33], [67, 67]], 3: [[24, 24], [50, 50], [76, 76]] } },
|
|
184
|
+
"bend-sinister": { size: 18, counts: { 1: [[50, 50]], 2: [[67, 33], [33, 67]], 3: [[76, 24], [50, 50], [24, 76]] } },
|
|
185
|
+
chevron: { size: 12, counts: { 1: [[50, 36]], 3: [[20, 65], [50, 36], [80, 65]] } },
|
|
186
|
+
cross: { size: 15, counts: { 1: [[50, 45]], 5: [[50, 15], [18, 45], [50, 45], [82, 45], [50, 80]] } },
|
|
187
|
+
saltire: { size: 14, counts: { 1: [[50, 50]], 5: [[22, 22], [78, 22], [50, 50], [22, 78], [78, 78]] } },
|
|
188
|
+
pall: { size: 14, counts: { 1: [[50, 50]], 3: [[22, 22], [78, 22], [50, 75]] } },
|
|
189
|
+
};
|
|
190
|
+
|
|
37
191
|
const betweenVars = ({ size, points }) => {
|
|
38
192
|
const vars = { "--between-size": `${size}%` };
|
|
39
193
|
points.forEach(([left, top], i) => {
|
|
@@ -43,22 +197,56 @@ const betweenVars = ({ size, points }) => {
|
|
|
43
197
|
return vars;
|
|
44
198
|
};
|
|
45
199
|
|
|
200
|
+
const onVars = ({ size, counts }) => {
|
|
201
|
+
const vars = { "--on-size": `${size}%` };
|
|
202
|
+
for (const [count, points] of Object.entries(counts)) {
|
|
203
|
+
points.forEach(([left, top], i) => {
|
|
204
|
+
vars[`--on-${count}-${i + 1}-x`] = `${left}%`;
|
|
205
|
+
vars[`--on-${count}-${i + 1}-y`] = `${top}%`;
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return vars;
|
|
209
|
+
};
|
|
210
|
+
|
|
46
211
|
export default plugin(({ addUtilities }) => {
|
|
47
212
|
const utilities = {};
|
|
48
213
|
|
|
49
|
-
for (const
|
|
214
|
+
for (const tincture of TINCTURES) {
|
|
215
|
+
utilities[`.fimbriated-${tincture}`] = {
|
|
216
|
+
"--fimbriated": "1",
|
|
217
|
+
"--fimbriation": `var(--color-${tincture})`,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
for (const [ordinary, vertices] of Object.entries(ORDINARIES)) {
|
|
50
222
|
for (const tincture of TINCTURES) {
|
|
51
223
|
utilities[`.${ordinary}-${tincture}`] = {
|
|
52
224
|
position: "relative",
|
|
53
225
|
...(BETWEEN[ordinary] && betweenVars(BETWEEN[ordinary])),
|
|
226
|
+
...(ON[ordinary] && onVars(ON[ordinary])),
|
|
54
227
|
// With a chief, everything else is drawn in the field below it.
|
|
55
|
-
...(ordinary === "chief" && {
|
|
228
|
+
...(ordinary === "chief" && {
|
|
229
|
+
"--field-top": "30%",
|
|
230
|
+
// The chief's centre line, relative to the charges container below it.
|
|
231
|
+
"--chief-points-y": "calc(-15% / 0.7)",
|
|
232
|
+
"--chief-points-size": "18%",
|
|
233
|
+
}),
|
|
56
234
|
[PSEUDO[ordinary] ?? "&::before"]: {
|
|
57
235
|
content: '""',
|
|
58
236
|
position: "absolute",
|
|
59
237
|
inset: ordinary === "chief" ? "0" : "var(--field-top, 0%) 0 0",
|
|
60
|
-
|
|
61
|
-
|
|
238
|
+
...(BANDS[ordinary]
|
|
239
|
+
? {
|
|
240
|
+
"--fimbriated": "inherit",
|
|
241
|
+
"--fimbriation": "inherit",
|
|
242
|
+
"background-color": `var(--fimbriation, var(--color-${tincture}))`,
|
|
243
|
+
...bands(BANDS[ordinary], tincture),
|
|
244
|
+
"clip-path": widenedPolygon(vertices),
|
|
245
|
+
}
|
|
246
|
+
: {
|
|
247
|
+
"background-color": `var(--color-${tincture})`,
|
|
248
|
+
"clip-path": polygon(vertices),
|
|
249
|
+
}),
|
|
62
250
|
},
|
|
63
251
|
};
|
|
64
252
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grailwind",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build": "tailwindcss -i docs/app.css -o docs/site.css",
|
|
6
6
|
"dev": "tailwindcss -i docs/app.css -o docs/site.css --watch",
|
|
7
|
-
"test": "node test/modes.mjs"
|
|
7
|
+
"test": "node test/modes.mjs",
|
|
8
|
+
"dev:watch": "tailwindcss -i docs/app.css -o docs/site.css --watch=always & python3 -m http.server ${PORT:-8000} -d docs"
|
|
8
9
|
},
|
|
9
10
|
"keywords": [
|
|
10
11
|
"tailwindcss",
|
|
@@ -38,7 +39,8 @@
|
|
|
38
39
|
"ordinaries.js",
|
|
39
40
|
"charges.js",
|
|
40
41
|
"strict.css",
|
|
41
|
-
"palette-reset.css"
|
|
42
|
+
"palette-reset.css",
|
|
43
|
+
"CHANGELOG.md"
|
|
42
44
|
],
|
|
43
45
|
"peerDependencies": {
|
|
44
46
|
"tailwindcss": "^4.0.0"
|