dowel-ui 0.2.0 → 0.3.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/README.md CHANGED
@@ -8,7 +8,7 @@ The lacodda line design system: theme tokens and React primitives, distributed a
8
8
 
9
9
  A dowel is the hidden peg that joins two boards so the seam does not show. That is what this does for the products of the line: they look made by one hand, and nobody sees the joint.
10
10
 
11
- **Status:** v0.2.0 - the theme and the scales. Primitives and the registry follow; see the [roadmap](#roadmap).
11
+ **Status:** v0.3.0 - the theme, the scales and an accent per product. Primitives follow; see the [roadmap](#roadmap).
12
12
 
13
13
  ## The theme
14
14
 
@@ -58,7 +58,20 @@ The stock palette is dropped deliberately, so a stray `bg-zinc-800` does not com
58
58
 
59
59
  The same vocabulary also ships as [DTCG](https://www.designtokens.org/tr/2025.10/format/) JSON at `dowel-ui/tokens.json`, generated from the stylesheet so the two cannot drift.
60
60
 
61
- Full vocabulary, shown rather than tabulated: **[colours](https://lacodda.github.io/dowel/reference/tokens/)** in both themes, and **[the scales](https://lacodda.github.io/dowel/reference/scales/)** - radius, type, motion, elevation and stacking order.
61
+ A product of the line states one thing about its appearance - which product it is:
62
+
63
+ ```css
64
+ @import 'dowel-ui/theme.css';
65
+ @import 'dowel-ui/accents/kilna.css';
66
+ ```
67
+
68
+ Or copy the files in instead of depending on the package:
69
+
70
+ ```bash
71
+ npx shadcn@latest add https://lacodda.github.io/dowel/r/theme.json
72
+ ```
73
+
74
+ Full vocabulary, shown rather than tabulated: **[colours](https://lacodda.github.io/dowel/reference/tokens/)** in both themes, **[the scales](https://lacodda.github.io/dowel/reference/scales/)** - radius, type, motion, elevation and stacking order - and **[the accents](https://lacodda.github.io/dowel/reference/accents/)**, where the same screen is drawn in every colour of the line.
62
75
 
63
76
  ## Roadmap
64
77
 
@@ -0,0 +1,10 @@
1
+ /*
2
+ * atlas - nebula #8A7DF5, the colour of its mark (at).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #8A7DF5;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * austeris - orchid #C25BD9, the colour of its mark (au).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #C25BD9;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * dowel - signal amber #E8862D, the colour of its mark (dw).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #E8862D;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * efema - cobalt #5470E8, the colour of its mark (ef).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #5470E8;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * kasl-server - gold #D9A82E, the colour of its mark (ks).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #D9A82E;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * kasl - lime #A9C23F, the colour of its mark (ka).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #A9C23F;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * kilna - magenta #D9569E, the colour of its mark (ki).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #D9569E;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * lyrid - azure #4A8FE8, the colour of its mark (ly).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #4A8FE8;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * lyrn - indigo #6D7BF2, the colour of its mark (ln).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #6D7BF2;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * midda - violet #A46BE8, the colour of its mark (mi).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #A46BE8;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * nitid - cyan #3FA9D9, the colour of its mark (nd).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #3FA9D9;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * nooma - emerald #3FA873, the colour of its mark (nm).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #3FA873;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * sefy - teal #35A8A0, the colour of its mark (se).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #35A8A0;
10
+ }
@@ -0,0 +1,10 @@
1
+ /*
2
+ * turnout - rose #E85B72, the colour of its mark (tn).
3
+ *
4
+ * Import after the theme. Everything else - the hover shade, the soft fill,
5
+ * the focus ring, the colour of text on an accent fill, and the trace of the
6
+ * hue the greys carry - is derived from this one value.
7
+ */
8
+ :root {
9
+ --accent-base: #E85B72;
10
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export { lineProducts, lineProduct, type LineProduct } from './line';
2
+ export { defaultStorageKey, initTheme, nextTheme, resolvedTheme, useTheme, useThemeSwitch, type Theme, } from './theme';
1
3
  /** Tokens that carry a colour. Ordered as they read on a screen: grounds,
2
4
  * then hairlines, then ink, then the accent, then status. */
3
5
  export declare const colorTokens: readonly ["bg", "raise", "soft", "softer", "line", "line-2", "text", "dim", "faint", "accent", "accent-2", "accent-soft", "on-accent", "good", "good-soft", "warn", "warn-soft", "bad", "bad-soft", "info", "info-soft"];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA;6DAC6D;AAC7D,eAAO,MAAM,WAAW,0NAsBd,CAAA;AAEV;oEACoE;AACpE,eAAO,MAAM,eAAe,kGAOlB,CAAA;AAEV;yDACyD;AACzD,eAAO,MAAM,eAAe,0DAA2D,CAAA;AAEvF;8DAC8D;AAC9D,eAAO,MAAM,YAAY,0GAQf,CAAA;AAEV;iCACiC;AACjC,eAAO,MAAM,UAAU,gOAeb,CAAA;AAEV;;0CAE0C;AAC1C,eAAO,MAAM,YAAY,0FAMf,CAAA;AAEV;;qEAEqE;AACrE,eAAO,MAAM,WAAW,0GASd,CAAA;AAEV;;;yDAGyD;AACzD,eAAO,MAAM,SAAS,k0BAQZ,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AACrD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAC7D,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAC7D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AACvD,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AACnD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AACvD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AACrD,MAAM,MAAM,KAAK,GACb,UAAU,GACV,cAAc,GACd,cAAc,GACd,WAAW,GACX,SAAS,GACT,WAAW,GACX,UAAU,CAAA;AAEd;;uCAEuC;AACvC,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAEzC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAA;AACpE,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,aAAa,EACb,QAAQ,EACR,cAAc,EACd,KAAK,KAAK,GACX,MAAM,SAAS,CAAA;AAEhB;6DAC6D;AAC7D,eAAO,MAAM,WAAW,0NAsBd,CAAA;AAEV;oEACoE;AACpE,eAAO,MAAM,eAAe,kGAOlB,CAAA;AAEV;yDACyD;AACzD,eAAO,MAAM,eAAe,0DAA2D,CAAA;AAEvF;8DAC8D;AAC9D,eAAO,MAAM,YAAY,0GAQf,CAAA;AAEV;iCACiC;AACjC,eAAO,MAAM,UAAU,gOAeb,CAAA;AAEV;;0CAE0C;AAC1C,eAAO,MAAM,YAAY,0FAMf,CAAA;AAEV;;qEAEqE;AACrE,eAAO,MAAM,WAAW,0GASd,CAAA;AAEV;;;yDAGyD;AACzD,eAAO,MAAM,SAAS,k0BAQZ,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AACrD,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAC7D,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAA;AAC7D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AACvD,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,CAAC,CAAA;AACnD,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAA;AACvD,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AACrD,MAAM,MAAM,KAAK,GACb,UAAU,GACV,cAAc,GACd,cAAc,GACd,WAAW,GACX,SAAS,GACT,WAAW,GACX,UAAU,CAAA;AAEd;;uCAEuC;AACvC,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAEzC"}
package/dist/index.js CHANGED
@@ -14,6 +14,8 @@
14
14
  * Primitives are distributed through the registry, not from here: a component
15
15
  * is copied into the product and becomes the product's own code.
16
16
  */
17
+ export { lineProducts, lineProduct } from './line';
18
+ export { defaultStorageKey, initTheme, nextTheme, resolvedTheme, useTheme, useThemeSwitch, } from './theme';
17
19
  /** Tokens that carry a colour. Ordered as they read on a screen: grounds,
18
20
  * then hairlines, then ink, then the accent, then status. */
19
21
  export const colorTokens = [
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;6DAC6D;AAC7D,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI;IACJ,OAAO;IACP,MAAM;IACN,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,MAAM;IACN,KAAK;IACL,OAAO;IACP,QAAQ;IACR,UAAU;IACV,aAAa;IACb,WAAW;IACX,MAAM;IACN,WAAW;IACX,MAAM;IACN,WAAW;IACX,KAAK;IACL,UAAU;IACV,MAAM;IACN,WAAW;CACH,CAAA;AAEV;oEACoE;AACpE,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa;IACb,cAAc;IACd,cAAc;IACd,qBAAqB;IACrB,QAAQ;IACR,KAAK;CACG,CAAA;AAEV;yDACyD;AACzD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,aAAa,EAAE,cAAc,EAAE,cAAc,CAAU,CAAA;AAEvF;8DAC8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,YAAY;IACZ,cAAc;CACN,CAAA;AAEV;iCACiC;AACjC,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,WAAW;IACX,WAAW;IACX,UAAU;IACV,SAAS;IACT,SAAS;IACT,WAAW;IACX,SAAS;IACT,SAAS;IACT,UAAU;IACV,oBAAoB;IACpB,oBAAoB;IACpB,sBAAsB;IACtB,kBAAkB;IAClB,gBAAgB;CACR,CAAA;AAEV;;0CAE0C;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,gBAAgB;IAChB,eAAe;IACf,eAAe;IACf,UAAU;IACV,aAAa;CACL,CAAA;AAEV;;qEAEqE;AACrE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,SAAS;IACT,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,WAAW;IACX,SAAS;IACT,WAAW;IACX,SAAS;CACD,CAAA;AAEV;;;yDAGyD;AACzD,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,GAAG,WAAW;IACd,GAAG,eAAe;IAClB,GAAG,eAAe;IAClB,GAAG,YAAY;IACf,GAAG,UAAU;IACb,GAAG,YAAY;IACf,GAAG,WAAW;CACN,CAAA;AAkBV;;uCAEuC;AACvC,MAAM,UAAU,KAAK,CAAC,IAAW;IAC/B,OAAO,KAAK,IAAI,EAAE,CAAA;AACpB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAoB,MAAM,QAAQ,CAAA;AACpE,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,SAAS,EACT,aAAa,EACb,QAAQ,EACR,cAAc,GAEf,MAAM,SAAS,CAAA;AAEhB;6DAC6D;AAC7D,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,IAAI;IACJ,OAAO;IACP,MAAM;IACN,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,MAAM;IACN,KAAK;IACL,OAAO;IACP,QAAQ;IACR,UAAU;IACV,aAAa;IACb,WAAW;IACX,MAAM;IACN,WAAW;IACX,MAAM;IACN,WAAW;IACX,KAAK;IACL,UAAU;IACV,MAAM;IACN,WAAW;CACH,CAAA;AAEV;oEACoE;AACpE,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,aAAa;IACb,cAAc;IACd,cAAc;IACd,qBAAqB;IACrB,QAAQ;IACR,KAAK;CACG,CAAA;AAEV;yDACyD;AACzD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,aAAa,EAAE,cAAc,EAAE,cAAc,CAAU,CAAA;AAEvF;8DAC8D;AAC9D,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,YAAY;IACZ,cAAc;CACN,CAAA;AAEV;iCACiC;AACjC,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,WAAW;IACX,WAAW;IACX,UAAU;IACV,SAAS;IACT,SAAS;IACT,WAAW;IACX,SAAS;IACT,SAAS;IACT,UAAU;IACV,oBAAoB;IACpB,oBAAoB;IACpB,sBAAsB;IACtB,kBAAkB;IAClB,gBAAgB;CACR,CAAA;AAEV;;0CAE0C;AAC1C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,gBAAgB;IAChB,eAAe;IACf,eAAe;IACf,UAAU;IACV,aAAa;CACL,CAAA;AAEV;;qEAEqE;AACrE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,SAAS;IACT,UAAU;IACV,QAAQ;IACR,YAAY;IACZ,WAAW;IACX,SAAS;IACT,WAAW;IACX,SAAS;CACD,CAAA;AAEV;;;yDAGyD;AACzD,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,GAAG,WAAW;IACd,GAAG,eAAe;IAClB,GAAG,eAAe;IAClB,GAAG,YAAY;IACf,GAAG,UAAU;IACb,GAAG,YAAY;IACf,GAAG,WAAW;CACN,CAAA;AAkBV;;uCAEuC;AACvC,MAAM,UAAU,KAAK,CAAC,IAAW;IAC/B,OAAO,KAAK,IAAI,EAAE,CAAA;AACpB,CAAC"}
package/dist/line.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ export interface LineProduct {
2
+ /** Package-and-directory name, and the name of the accent file. */
3
+ readonly name: string;
4
+ /** The two-letter code on the product's mark. */
5
+ readonly code: string;
6
+ /** The accent, as the registry states it. */
7
+ readonly accent: string;
8
+ /** The colour's name in the line's palette. */
9
+ readonly colorName: string;
10
+ }
11
+ export declare const lineProducts: readonly LineProduct[];
12
+ /** The product with this name, or `undefined`. */
13
+ export declare function lineProduct(name: string): LineProduct | undefined;
14
+ //# sourceMappingURL=line.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line.d.ts","sourceRoot":"","sources":["../src/line.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,WAAW;IAC1B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,eAAO,MAAM,YAAY,EAAE,SAAS,WAAW,EAe9C,CAAA;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAEjE"}
package/dist/line.js ADDED
@@ -0,0 +1,35 @@
1
+ /*
2
+ * The products of the lacodda line, and the colour each one is known by.
3
+ *
4
+ * These are the accents from the line's registry of marks: one hue per
5
+ * product, fixed for the life of that product. A product's theme is its mark's
6
+ * colour - the tile on its README, the icon in the taskbar and the primary
7
+ * button on its screens are the same colour, because they are the same fact.
8
+ *
9
+ * The registry itself lives with the mark generator, outside this repository.
10
+ * It is copied here rather than read, because a build must not reach into a
11
+ * private toolchain to know what colour a button is; the release gate checks
12
+ * that every product listed has an accent file, and the contrast tests run
13
+ * over this list, so a wrong value cannot travel far.
14
+ */
15
+ export const lineProducts = [
16
+ { name: 'kasl', code: 'ka', accent: '#A9C23F', colorName: 'lime' },
17
+ { name: 'kasl-server', code: 'ks', accent: '#D9A82E', colorName: 'gold' },
18
+ { name: 'turnout', code: 'tn', accent: '#E85B72', colorName: 'rose' },
19
+ { name: 'sefy', code: 'se', accent: '#35A8A0', colorName: 'teal' },
20
+ { name: 'atlas', code: 'at', accent: '#8A7DF5', colorName: 'nebula' },
21
+ { name: 'nitid', code: 'nd', accent: '#3FA9D9', colorName: 'cyan' },
22
+ { name: 'midda', code: 'mi', accent: '#A46BE8', colorName: 'violet' },
23
+ { name: 'nooma', code: 'nm', accent: '#3FA873', colorName: 'emerald' },
24
+ { name: 'kilna', code: 'ki', accent: '#D9569E', colorName: 'magenta' },
25
+ { name: 'lyrid', code: 'ly', accent: '#4A8FE8', colorName: 'azure' },
26
+ { name: 'efema', code: 'ef', accent: '#5470E8', colorName: 'cobalt' },
27
+ { name: 'dowel', code: 'dw', accent: '#E8862D', colorName: 'signal amber' },
28
+ { name: 'lyrn', code: 'ln', accent: '#6D7BF2', colorName: 'indigo' },
29
+ { name: 'austeris', code: 'au', accent: '#C25BD9', colorName: 'orchid' },
30
+ ];
31
+ /** The product with this name, or `undefined`. */
32
+ export function lineProduct(name) {
33
+ return lineProducts.find((product) => product.name === name);
34
+ }
35
+ //# sourceMappingURL=line.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line.js","sourceRoot":"","sources":["../src/line.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAaH,MAAM,CAAC,MAAM,YAAY,GAA2B;IAClD,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE;IAClE,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE;IACzE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE;IACrE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE;IAClE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE;IACrE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE;IACnE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE;IACrE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE;IACtE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE;IACtE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE;IACpE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE;IACrE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE;IAC3E,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE;IACpE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE;CACzE,CAAA;AAED,kDAAkD;AAClD,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;AAC9D,CAAC"}
@@ -0,0 +1,67 @@
1
+ /** `system` follows the operating system; the other two pin a class. */
2
+ export type Theme = 'system' | 'light' | 'dark';
3
+ /** Where the choice is remembered. A product may use its own key; the default
4
+ * is shared, so two products of the line on the same origin agree. */
5
+ export declare const defaultStorageKey = "dowel.theme";
6
+ /**
7
+ * Apply the remembered theme immediately, before React renders.
8
+ *
9
+ * Call this from the entry module, above the first render. Without it the page
10
+ * paints in the default theme and then corrects itself, which a reader who
11
+ * chose light sees as a flash of dark.
12
+ */
13
+ export declare function initTheme(storageKey?: string): void;
14
+ /**
15
+ * The current theme and a way to change it.
16
+ *
17
+ * While the theme is `system` this follows the operating system as it changes,
18
+ * so a reader who switches their machine to dark at sunset does not have to
19
+ * reload the page.
20
+ */
21
+ export declare function useTheme(storageKey?: string): {
22
+ theme: Theme;
23
+ /** Which theme is showing: `system` resolved against the operating system. */
24
+ resolved: 'light' | 'dark';
25
+ setTheme: (theme: Theme) => void;
26
+ };
27
+ /** The next theme in a fixed cycle, for a control that is one button rather
28
+ * than three. */
29
+ export declare function nextTheme(current: Theme): Theme;
30
+ /**
31
+ * A theme switch, as behaviour without markup.
32
+ *
33
+ * The control itself is the product's: kilna's is a row in its sidebar with an
34
+ * icon and a translated label, and a design system that shipped that would be
35
+ * shipping kilna's sidebar. What is worth sharing is the part every product
36
+ * would otherwise get subtly wrong - the cycle order, the accessible state,
37
+ * and telling assistive technology that a button changes the page's own
38
+ * appearance.
39
+ *
40
+ * const { theme, buttonProps } = useThemeSwitch()
41
+ * <button {...buttonProps} aria-label={t(`theme.${theme}`)}>
42
+ * <Icon /> {t(`theme.${theme}`)}
43
+ * </button>
44
+ *
45
+ * The label stays with the product: a primitive with a string of its own is a
46
+ * primitive that cannot be translated.
47
+ */
48
+ export declare function useThemeSwitch(storageKey?: string): {
49
+ theme: Theme;
50
+ resolved: 'light' | 'dark';
51
+ setTheme: (theme: Theme) => void;
52
+ /** Spread onto the button that cycles the theme. */
53
+ buttonProps: {
54
+ type: 'button';
55
+ onClick: () => void;
56
+ 'aria-live': 'polite';
57
+ };
58
+ };
59
+ /**
60
+ * Which theme is showing, right now, outside React.
61
+ *
62
+ * `useTheme` returns the same thing as `resolved` and keeps it current; this
63
+ * is for the places a hook cannot reach - a canvas that has to pick a colour,
64
+ * a chart library told what palette to draw in.
65
+ */
66
+ export declare function resolvedTheme(theme: Theme): 'light' | 'dark';
67
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAiBA,wEAAwE;AACxE,MAAM,MAAM,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAA;AAI/C;sEACsE;AACtE,eAAO,MAAM,iBAAiB,gBAAgB,CAAA;AAiC9C;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,UAAU,GAAE,MAA0B,GAAG,IAAI,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,UAAU,GAAE,MAA0B,GAAG;IAChE,KAAK,EAAE,KAAK,CAAA;IACZ,8EAA8E;IAC9E,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAA;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC,CA8BA;AAED;iBACiB;AACjB,wBAAgB,SAAS,CAAC,OAAO,EAAE,KAAK,GAAG,KAAK,CAG/C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,UAAU,GAAE,MAA0B,GAAG;IACtE,KAAK,EAAE,KAAK,CAAA;IACZ,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAA;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAChC,oDAAoD;IACpD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAA;QACd,OAAO,EAAE,MAAM,IAAI,CAAA;QACnB,WAAW,EAAE,QAAQ,CAAA;KACtB,CAAA;CACF,CAiBA;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,GAAG,MAAM,CAG5D"}
package/dist/theme.js ADDED
@@ -0,0 +1,127 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ const THEMES = ['system', 'light', 'dark'];
3
+ /** Where the choice is remembered. A product may use its own key; the default
4
+ * is shared, so two products of the line on the same origin agree. */
5
+ export const defaultStorageKey = 'dowel.theme';
6
+ /** Storage is a convenience, never a requirement: private windows, embedded
7
+ * views and blocked site data all make it throw, and a theme switch that
8
+ * cannot remember should still switch. */
9
+ function readStored(key) {
10
+ try {
11
+ const raw = localStorage.getItem(key);
12
+ return THEMES.includes(raw) ? raw : null;
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ function writeStored(key, theme) {
19
+ try {
20
+ localStorage.setItem(key, theme);
21
+ }
22
+ catch {
23
+ // Nothing to do: the choice applies to this page, it just will not survive.
24
+ }
25
+ }
26
+ function applyTheme(theme) {
27
+ const root = document.documentElement;
28
+ root.classList.toggle('light', theme === 'light');
29
+ root.classList.toggle('dark', theme === 'dark');
30
+ }
31
+ /** Whether the operating system is asking for a dark theme right now. */
32
+ function prefersDark() {
33
+ return typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches;
34
+ }
35
+ /**
36
+ * Apply the remembered theme immediately, before React renders.
37
+ *
38
+ * Call this from the entry module, above the first render. Without it the page
39
+ * paints in the default theme and then corrects itself, which a reader who
40
+ * chose light sees as a flash of dark.
41
+ */
42
+ export function initTheme(storageKey = defaultStorageKey) {
43
+ applyTheme(readStored(storageKey) ?? 'system');
44
+ }
45
+ /**
46
+ * The current theme and a way to change it.
47
+ *
48
+ * While the theme is `system` this follows the operating system as it changes,
49
+ * so a reader who switches their machine to dark at sunset does not have to
50
+ * reload the page.
51
+ */
52
+ export function useTheme(storageKey = defaultStorageKey) {
53
+ const [theme, setThemeState] = useState(() => readStored(storageKey) ?? 'system');
54
+ const [systemIsDark, setSystemIsDark] = useState(prefersDark);
55
+ useEffect(() => {
56
+ applyTheme(theme);
57
+ }, [theme]);
58
+ useEffect(() => {
59
+ // The stylesheet follows the operating system on its own - that is what
60
+ // the `prefers-color-scheme` block is for, and the classes are already
61
+ // right. What has to be tracked in React is `resolved`, because a control
62
+ // that draws a sun or a moon needs to know which one is showing.
63
+ const query = window.matchMedia('(prefers-color-scheme: dark)');
64
+ const onChange = (event) => setSystemIsDark(event.matches);
65
+ query.addEventListener('change', onChange);
66
+ return () => query.removeEventListener('change', onChange);
67
+ }, []);
68
+ const setTheme = useCallback((next) => {
69
+ writeStored(storageKey, next);
70
+ setThemeState(next);
71
+ }, [storageKey]);
72
+ const resolved = theme === 'system' ? (systemIsDark ? 'dark' : 'light') : theme;
73
+ return { theme, resolved, setTheme };
74
+ }
75
+ /** The next theme in a fixed cycle, for a control that is one button rather
76
+ * than three. */
77
+ export function nextTheme(current) {
78
+ const index = THEMES.indexOf(current);
79
+ return THEMES[(index + 1) % THEMES.length] ?? 'system';
80
+ }
81
+ /**
82
+ * A theme switch, as behaviour without markup.
83
+ *
84
+ * The control itself is the product's: kilna's is a row in its sidebar with an
85
+ * icon and a translated label, and a design system that shipped that would be
86
+ * shipping kilna's sidebar. What is worth sharing is the part every product
87
+ * would otherwise get subtly wrong - the cycle order, the accessible state,
88
+ * and telling assistive technology that a button changes the page's own
89
+ * appearance.
90
+ *
91
+ * const { theme, buttonProps } = useThemeSwitch()
92
+ * <button {...buttonProps} aria-label={t(`theme.${theme}`)}>
93
+ * <Icon /> {t(`theme.${theme}`)}
94
+ * </button>
95
+ *
96
+ * The label stays with the product: a primitive with a string of its own is a
97
+ * primitive that cannot be translated.
98
+ */
99
+ export function useThemeSwitch(storageKey = defaultStorageKey) {
100
+ const { theme, resolved, setTheme } = useTheme(storageKey);
101
+ const onClick = useCallback(() => setTheme(nextTheme(theme)), [theme, setTheme]);
102
+ return {
103
+ theme,
104
+ resolved,
105
+ setTheme,
106
+ buttonProps: {
107
+ type: 'button',
108
+ onClick,
109
+ // The button's own label changes when it is pressed - it names the
110
+ // theme now in force - and a screen reader should hear that.
111
+ 'aria-live': 'polite',
112
+ },
113
+ };
114
+ }
115
+ /**
116
+ * Which theme is showing, right now, outside React.
117
+ *
118
+ * `useTheme` returns the same thing as `resolved` and keeps it current; this
119
+ * is for the places a hook cannot reach - a canvas that has to pick a colour,
120
+ * a chart library told what palette to draw in.
121
+ */
122
+ export function resolvedTheme(theme) {
123
+ if (theme !== 'system')
124
+ return theme;
125
+ return prefersDark() ? 'dark' : 'light';
126
+ }
127
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dowel-ui",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "The lacodda line design system: theme tokens and React primitives, distributed as a shadcn-compatible registry.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -34,10 +34,11 @@
34
34
  "import": "./dist/index.js"
35
35
  },
36
36
  "./theme.css": "./dist/theme.css",
37
- "./tokens.json": "./dist/tokens.json"
37
+ "./tokens.json": "./dist/tokens.json",
38
+ "./accents/*.css": "./dist/accents/*.css"
38
39
  },
39
40
  "scripts": {
40
- "build": "tsc && node ../../tools/copy-theme.mjs && node ../../tools/build-tokens-json.mjs",
41
+ "build": "tsc && node ../../tools/copy-theme.mjs && node ../../tools/build-tokens-json.mjs && node ../../tools/build-accents.mjs && node ../../tools/build-registry.mjs",
41
42
  "typecheck": "tsc --noEmit",
42
43
  "prepack": "node ../../tools/copy-readme.mjs"
43
44
  },