@softure-ai/theme-kit 0.0.0-stage → 0.1.1
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 +18 -0
- package/LICENSE +21 -0
- package/README.md +129 -2
- package/bin/softure-theme-css.mjs +14 -0
- package/dist/build/build-theme-package.d.ts +13 -0
- package/dist/build/build-theme-package.d.ts.map +1 -0
- package/dist/build/build-theme-package.js +42 -0
- package/dist/build/build-theme-package.js.map +1 -0
- package/dist/build/index.d.ts +4 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +5 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/theme-package-config.d.ts +22 -0
- package/dist/build/theme-package-config.d.ts.map +1 -0
- package/dist/build/theme-package-config.js +34 -0
- package/dist/build/theme-package-config.js.map +1 -0
- package/dist/build/theme-stylesheet.d.ts +24 -0
- package/dist/build/theme-stylesheet.d.ts.map +1 -0
- package/dist/build/theme-stylesheet.js +24 -0
- package/dist/build/theme-stylesheet.js.map +1 -0
- package/dist/build-theme-css.d.ts +12 -0
- package/dist/build-theme-css.d.ts.map +1 -0
- package/dist/build-theme-css.js +102 -0
- package/dist/build-theme-css.js.map +1 -0
- package/dist/check-theme.d.ts +12 -0
- package/dist/check-theme.d.ts.map +1 -0
- package/dist/check-theme.js +46 -0
- package/dist/check-theme.js.map +1 -0
- package/dist/cli/command.d.ts +9 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +19 -0
- package/dist/cli/command.js.map +1 -0
- package/dist/create-cn.d.ts +18 -0
- package/dist/create-cn.d.ts.map +1 -0
- package/dist/create-cn.js +17 -0
- package/dist/create-cn.js.map +1 -0
- package/dist/define-theme.d.ts +8 -0
- package/dist/define-theme.d.ts.map +1 -0
- package/dist/define-theme.js +14 -0
- package/dist/define-theme.js.map +1 -0
- package/dist/extend-theme.d.ts +20 -0
- package/dist/extend-theme.d.ts.map +1 -0
- package/dist/extend-theme.js +20 -0
- package/dist/extend-theme.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/preflight.css +77 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +2 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/use-is-mobile.d.ts +8 -0
- package/dist/react/use-is-mobile.d.ts.map +1 -0
- package/dist/react/use-is-mobile.js +24 -0
- package/dist/react/use-is-mobile.js.map +1 -0
- package/dist/theme-definition.d.ts +49 -0
- package/dist/theme-definition.d.ts.map +1 -0
- package/dist/theme-definition.js +45 -0
- package/dist/theme-definition.js.map +1 -0
- package/package.json +59 -4
- package/src/build/build-theme-package.ts +45 -0
- package/src/build/index.ts +9 -0
- package/src/build/theme-package-config.ts +46 -0
- package/src/build/theme-stylesheet.ts +43 -0
- package/src/build-theme-css.ts +106 -0
- package/src/check-theme.ts +62 -0
- package/src/cli/command.ts +33 -0
- package/src/create-cn.ts +31 -0
- package/src/define-theme.ts +15 -0
- package/src/extend-theme.ts +33 -0
- package/src/index.ts +16 -0
- package/src/preflight.css +77 -0
- package/src/react/index.ts +1 -0
- package/src/react/use-is-mobile.ts +29 -0
- package/src/theme-definition.ts +92 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Newest first. Each version lists what changed for an app or a theme package that uses the kit.
|
|
4
|
+
|
|
5
|
+
## 0.1.1
|
|
6
|
+
|
|
7
|
+
- No change to the package itself: the first version published through the npm trusted publisher (OIDC) with
|
|
8
|
+
provenance, without a token.
|
|
9
|
+
|
|
10
|
+
## 0.1.0
|
|
11
|
+
|
|
12
|
+
- First version: `ThemeDefinition` and `SHADCN_COLOR_ROLES` (the token contract), `buildThemeCss` (tokens on
|
|
13
|
+
`:root`, dark by the system setting and by `.dark` / `[data-theme]`, the Tailwind `@theme inline` block),
|
|
14
|
+
`findMissingColorRoles`, `createCn` and `createThemeCn`, `useIsMobile` (`./react`) and `preflight.css` (#708).
|
|
15
|
+
- The theme package contract (#708): `defineTheme` (checks a theme where it is declared), `checkTheme` (the problems
|
|
16
|
+
as a list), `extendTheme` (a variant of an existing theme), the `softure-theme-css` command that builds every theme
|
|
17
|
+
package's `theme.css` from `softureTheme` in its `package.json`, and `./build` (`parseThemePackageConfig`,
|
|
18
|
+
`buildThemeStylesheet`, `writeThemeStylesheets`, `buildThemePackage`).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SOFTURE
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,130 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @softure-ai/theme-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The standard every SOFTURE theme package is built on. A theme is plain shadcn/ui (Radix, Tailwind CSS v4, lucide
|
|
4
|
+
icons) with its own tokens and component deltas; the kit holds everything that does not change from theme to theme:
|
|
5
|
+
the token contract, the way a theme is declared, the CSS generator, the build command and the shared helpers. A new
|
|
6
|
+
theme is a new `themes/theme-<name>` folder that follows the contract below; nothing in the kit changes.
|
|
7
|
+
|
|
8
|
+
Apps install a theme package (e.g. [`@softure-ai/theme-notion`](../theme-notion/README.md)), which depends on the kit.
|
|
9
|
+
An app imports the kit directly only for `preflight.css`, `useIsMobile`, or to build its own variant of a theme.
|
|
10
|
+
|
|
11
|
+
## Design
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
ThemeDefinition (data) ──defineTheme──▶ theme (checked) ──buildThemeCss──▶ tokens CSS
|
|
15
|
+
▲ │
|
|
16
|
+
extendTheme(base, overrides) └──softure-theme-css + softureTheme──▶ dist/theme.css
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- **One contract.** `ThemeDefinition` says what a theme decides: colours (light and dark, or an alias of another
|
|
20
|
+
colour), shadows, fonts, named text styles, radii, layout sizes, whether Tailwind's default palette is cleared.
|
|
21
|
+
`SHADCN_COLOR_ROLES` are the colour roles shadcn/ui components read; every theme defines them all, so a component
|
|
22
|
+
written for one theme renders in any other. A theme adds its own tokens on top (`green-tag`, `primary-hover`).
|
|
23
|
+
- **Declared and checked in one place.** `defineTheme(definition)` checks the theme where it is written and throws
|
|
24
|
+
with every problem listed: a missing colour role, a name that is not kebab-case, an empty value or one that could
|
|
25
|
+
break out of the CSS, an alias of a colour the theme does not define. `checkTheme` returns the same problems as a
|
|
26
|
+
list. The literal types stay, so `theme.colors.primary` is known to the compiler.
|
|
27
|
+
- **Built the same way.** A theme package has no build script of its own. It declares its stylesheet as data
|
|
28
|
+
(`softureTheme` in `package.json`) and its build runs the kit's `softure-theme-css`, which writes `dist/theme.css`
|
|
29
|
+
from the package's `theme` and copies its extra stylesheets.
|
|
30
|
+
- **Variants, not copies.** `extendTheme(base, overrides)` gives a theme that differs from another in a few tokens:
|
|
31
|
+
each token group of the overrides is laid over the base's (a token is replaced whole), the result is checked.
|
|
32
|
+
- **Checked in the repository.** `tests/repo/themes.test.ts` runs the contract over every `themes/theme-*` package,
|
|
33
|
+
so a new theme is covered by being created.
|
|
34
|
+
|
|
35
|
+
## What it holds
|
|
36
|
+
|
|
37
|
+
| Export | What it does |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `ThemeDefinition`, `SHADCN_COLOR_ROLES`, `findMissingColorRoles` | The token contract |
|
|
40
|
+
| `defineTheme(definition)` | Declares a theme: checks it, returns it with its literal types, throws with every problem |
|
|
41
|
+
| `checkTheme(definition)` | The contract problems as messages; empty when the theme is complete |
|
|
42
|
+
| `extendTheme(base, overrides)` | A checked variant of a theme: a new name, per group only the tokens that change |
|
|
43
|
+
| `buildThemeCss(definition)` | The theme's tokens as CSS for Tailwind CSS v4 (below) |
|
|
44
|
+
| `createCn(options)`, `createThemeCn(definition)` | shadcn/ui's `cn`, with tailwind-merge told the theme's named text styles and shadows (`text-body` and `text-muted-foreground` both stay) |
|
|
45
|
+
| `useIsMobile()`, `MOBILE_BREAKPOINT` (`/react`) | The sidebar's breakpoint (768 px), on `useSyncExternalStore`; the server renders the desktop layout |
|
|
46
|
+
| `preflight.css` | Tailwind's preflight scoped to `[data-slot]` elements, in `@layer base` with zero specificity, plus `prefers-reduced-motion` |
|
|
47
|
+
| `softure-theme-css [packageDir]` | Builds a theme package's stylesheets after `tsc` (the contract below) |
|
|
48
|
+
| `/build`: `parseThemePackageConfig`, `buildThemeStylesheet`, `writeThemeStylesheets`, `buildThemePackage` | The code behind the command, for tests and tools (Node only) |
|
|
49
|
+
|
|
50
|
+
## The theme package contract
|
|
51
|
+
|
|
52
|
+
Every `themes/theme-<name>` package (named `@softure-ai/theme-<name>` by its folder):
|
|
53
|
+
|
|
54
|
+
1. `src/tokens.ts` exports `theme`, declared with `defineTheme`. It may also export a named alias (`NOTION_THEME`).
|
|
55
|
+
2. `src/index.ts` exports `theme`, `cn` (`createThemeCn(theme)`) and the components. The same names in every theme,
|
|
56
|
+
so an app moves to another theme by changing the import path.
|
|
57
|
+
3. `package.json`:
|
|
58
|
+
- depends on `@softure-ai/theme-kit`; takes `react` and `tailwindcss` `^4.0.0` as peers;
|
|
59
|
+
- `"build": "tsc -p tsconfig.build.json && softure-theme-css"`;
|
|
60
|
+
- exports `./theme.css` (`./dist/theme.css`) and each extra stylesheet (`./<name>.css` → `./dist/<name>.css`);
|
|
61
|
+
- declares the stylesheet:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
"softureTheme": {
|
|
65
|
+
"sources": ["./ui", "./notion"],
|
|
66
|
+
"imports": ["tw-animate-css"],
|
|
67
|
+
"stylesheets": ["sft-bridge.css"]
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`sources`: the component folders under `src/` (and `dist/`), written into `theme.css` as `@source`, so the app's
|
|
72
|
+
Tailwind generates their classes inside `node_modules`. `imports`: CSS packages the components need, imported
|
|
73
|
+
first. `stylesheets`: plain CSS files in `src/` copied to `dist/` as they are. Each defaults to none.
|
|
74
|
+
|
|
75
|
+
`theme.css` is then `@import` lines, `@source` lines and the generated tokens, in that order.
|
|
76
|
+
|
|
77
|
+
## The generated CSS
|
|
78
|
+
|
|
79
|
+
`buildThemeCss` writes, in this order:
|
|
80
|
+
|
|
81
|
+
1. `@custom-variant dark`: Tailwind's `dark:` follows the same rule as the tokens below.
|
|
82
|
+
2. `:root, .light, [data-theme="light"]`: the light values.
|
|
83
|
+
3. `@media (prefers-color-scheme: dark)` → `:root:not(.light, [data-theme="light"])`: the dark values by the system
|
|
84
|
+
setting, unless the page asks for light.
|
|
85
|
+
4. `.dark, [data-theme="dark"]`: the dark values by choice. Works with `next-themes` (`attribute="class"`) and with
|
|
86
|
+
`@softure-ai/ui`'s `ThemeScript` / `ThemeSwitch` (`data-theme` on `<html>`); a section can take a fixed scheme.
|
|
87
|
+
5. `@theme inline`: `--color-<name>`, `--font-*`, `--text-<style>` (size, line height, weight, tracking),
|
|
88
|
+
`--radius-*`, `--shadow-*` and the sizes as `--spacing-*`, so `bg-primary`, `text-page-title`, `rounded-xl`,
|
|
89
|
+
`shadow-menu` and `w-sidebar-width` exist. With `clearDefaultPalette`, `--color-*: initial` first.
|
|
90
|
+
|
|
91
|
+
It throws on a name that is not kebab-case, a value holding `;`, `{`, `}`, `<`, `>` or a line break, and an alias of
|
|
92
|
+
a colour the theme does not define.
|
|
93
|
+
|
|
94
|
+
## Overriding in an app
|
|
95
|
+
|
|
96
|
+
- **A few tokens:** redefine the CSS variables after the theme's `theme.css`, for both schemes:
|
|
97
|
+
|
|
98
|
+
```css
|
|
99
|
+
@import "@softure-ai/theme-notion/theme.css";
|
|
100
|
+
:root { --primary: #e16259; }
|
|
101
|
+
.dark, [data-theme="dark"] { --primary: #df5452; }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- **A variant of its own:** build it from the theme and write the CSS in the app's build, then import the app's file
|
|
105
|
+
instead of the theme's tokens:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { writeFileSync } from "node:fs";
|
|
109
|
+
import { buildThemeCss, extendTheme } from "@softure-ai/theme-kit";
|
|
110
|
+
import { theme } from "@softure-ai/theme-notion";
|
|
111
|
+
|
|
112
|
+
const brand = extendTheme(theme, { name: "Brand", colors: { primary: { light: "#e16259", dark: "#df5452" } } });
|
|
113
|
+
writeFileSync("app/brand-theme.css", buildThemeCss(brand));
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`cn` stays the theme's while the variant adds no text styles or shadows; otherwise use `createThemeCn(brand)`.
|
|
117
|
+
|
|
118
|
+
## Adding a theme
|
|
119
|
+
|
|
120
|
+
1. Create `themes/theme-<name>/` with the workspace package shape (`templates/package/` for `package.json`, the
|
|
121
|
+
`tsconfig` files and `CHANGELOG.md`) and the contract above.
|
|
122
|
+
2. `src/tokens.ts`: `export const theme = defineTheme({ name: "<Name>", colors: { … }, … })`. Every shadcn colour
|
|
123
|
+
role is required; `defineTheme` names the missing ones. A theme close to an existing one can be
|
|
124
|
+
`extendTheme(otherTheme, { … })`. Keep a snapshot of the design system's tokens in `tests/fixtures/` and a test
|
|
125
|
+
that the definition equals it.
|
|
126
|
+
3. `src/lib/utils.ts`: `export const cn = createThemeCn(theme)`.
|
|
127
|
+
4. `src/ui/`: the shadcn/ui components with the theme's deltas (sizes, radii, shadows, variants), listed in the
|
|
128
|
+
README; keep shadcn's file names and formatting, so a later `npx shadcn@latest add` diff stays readable. Add
|
|
129
|
+
compositions in a folder of their own and name every folder in `softureTheme.sources`.
|
|
130
|
+
5. Run `npm test`: `tests/repo/themes.test.ts` checks the package against the contract.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// @ts-check
|
|
3
|
+
// The `softure-theme-css` executable. A checked-in file rather than a file in dist/, so npm links it at install
|
|
4
|
+
// time, before the kit is built; it runs after the kit's build (theme packages depend on the kit, which builds
|
|
5
|
+
// first). The command is loaded by URL, so the type check does not need dist/ either. All logic lives in
|
|
6
|
+
// src/cli/command.ts, which the tests call directly.
|
|
7
|
+
|
|
8
|
+
/** @typedef {{ runThemeCssCommand: (input: { argv: string[]; cwd: string }) => Promise<number> }} CommandModule */
|
|
9
|
+
|
|
10
|
+
/** @type {unknown} */
|
|
11
|
+
const loaded = await import(new URL("../dist/cli/command.js", import.meta.url).href);
|
|
12
|
+
const commandModule = /** @type {CommandModule} */ (loaded);
|
|
13
|
+
|
|
14
|
+
process.exitCode = await commandModule.runThemeCssCommand({ argv: process.argv.slice(2), cwd: process.cwd() });
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type BuildResult = {
|
|
2
|
+
ok: true;
|
|
3
|
+
files: string[];
|
|
4
|
+
} | {
|
|
5
|
+
ok: false;
|
|
6
|
+
error: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Builds a theme package's stylesheets after `tsc`: reads `softureTheme` from its `package.json` and the `theme`
|
|
10
|
+
* export of the built `dist/tokens.js`, checks the theme, writes `dist/theme.css` and copies the stylesheets.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildThemePackage(packageDir: string): Promise<BuildResult>;
|
|
13
|
+
//# sourceMappingURL=build-theme-package.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-theme-package.d.ts","sourceRoot":"","sources":["../../src/build/build-theme-package.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAevF;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgBhF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { pathToFileURL } from "node:url";
|
|
4
|
+
import { checkTheme } from "../check-theme.js";
|
|
5
|
+
import { parseThemePackageConfig } from "./theme-package-config.js";
|
|
6
|
+
import { writeThemeStylesheets } from "./theme-stylesheet.js";
|
|
7
|
+
const DEFINITION_GROUPS = ["colors", "shadows", "fonts", "textStyles", "radii", "sizes"];
|
|
8
|
+
/** A first, structural narrowing of the `theme` export; `checkTheme` then checks the values. */
|
|
9
|
+
function isThemeDefinition(value) {
|
|
10
|
+
if (typeof value !== "object" || value === null)
|
|
11
|
+
return false;
|
|
12
|
+
const record = value;
|
|
13
|
+
return (typeof record.name === "string" &&
|
|
14
|
+
typeof record.clearDefaultPalette === "boolean" &&
|
|
15
|
+
DEFINITION_GROUPS.every((group) => typeof record[group] === "object" && record[group] !== null));
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Builds a theme package's stylesheets after `tsc`: reads `softureTheme` from its `package.json` and the `theme`
|
|
19
|
+
* export of the built `dist/tokens.js`, checks the theme, writes `dist/theme.css` and copies the stylesheets.
|
|
20
|
+
*/
|
|
21
|
+
export async function buildThemePackage(packageDir) {
|
|
22
|
+
const manifest = JSON.parse(readFileSync(join(packageDir, "package.json"), "utf8"));
|
|
23
|
+
const parsed = parseThemePackageConfig(manifest.softureTheme);
|
|
24
|
+
if (!parsed.ok)
|
|
25
|
+
return parsed;
|
|
26
|
+
const tokensPath = join(packageDir, "dist", "tokens.js");
|
|
27
|
+
let tokens;
|
|
28
|
+
try {
|
|
29
|
+
tokens = (await import(pathToFileURL(tokensPath).href));
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
return { ok: false, error: `cannot load ${tokensPath} (run tsc first): ${error instanceof Error ? error.message : String(error)}` };
|
|
33
|
+
}
|
|
34
|
+
const theme = tokens.theme;
|
|
35
|
+
if (!isThemeDefinition(theme))
|
|
36
|
+
return { ok: false, error: `${tokensPath} does not export \`theme\` as a theme definition` };
|
|
37
|
+
const problems = checkTheme(theme);
|
|
38
|
+
if (problems.length > 0)
|
|
39
|
+
return { ok: false, error: `theme "${theme.name}" breaks the theme contract: ${problems.join("; ")}` };
|
|
40
|
+
return { ok: true, files: writeThemeStylesheets({ packageDir, theme, config: parsed.config }) };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=build-theme-package.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-theme-package.js","sourceRoot":"","sources":["../../src/build/build-theme-package.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,MAAM,iBAAiB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,CAAU,CAAC;AAElG,gGAAgG;AAChG,SAAS,iBAAiB,CAAC,KAAc;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,OAAO,CACL,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ;QAC/B,OAAO,MAAM,CAAC,mBAAmB,KAAK,SAAS;QAC/C,iBAAiB,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAChG,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAA4B,CAAC;IAC/G,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,MAAM,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;IACzD,IAAI,MAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAA4B,CAAC;IACrF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,UAAU,qBAAqB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IACtI,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,UAAU,kDAAkD,EAAE,CAAC;IAC5H,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,KAAK,CAAC,IAAI,gCAAgC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IAChI,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,qBAAqB,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;AAClG,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { buildThemePackage, type BuildResult } from "./build-theme-package.js";
|
|
2
|
+
export { parseThemePackageConfig, type ConfigResult, type ThemePackageConfig } from "./theme-package-config.js";
|
|
3
|
+
export { buildThemeStylesheet, writeThemeStylesheets, type ThemeStylesheetInput, type WriteThemeStylesheetsOptions, } from "./theme-stylesheet.js";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/build/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAChH,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,4BAA4B,GAClC,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// Node-only: the code that builds a theme package's stylesheets (`softure-theme-css`). Not for the browser bundle.
|
|
2
|
+
export { buildThemePackage } from "./build-theme-package.js";
|
|
3
|
+
export { parseThemePackageConfig } from "./theme-package-config.js";
|
|
4
|
+
export { buildThemeStylesheet, writeThemeStylesheets, } from "./theme-stylesheet.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/build/index.ts"],"names":[],"mappings":"AAAA,mHAAmH;AACnH,OAAO,EAAE,iBAAiB,EAAoB,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,uBAAuB,EAA8C,MAAM,2BAA2B,CAAC;AAChH,OAAO,EACL,oBAAoB,EACpB,qBAAqB,GAGtB,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a theme package ships its stylesheet, declared under `softureTheme` in its `package.json`. Data, not a script:
|
|
3
|
+
* every theme builds with the same `softure-theme-css` command, and the repository test reads the same declaration.
|
|
4
|
+
*/
|
|
5
|
+
export interface ThemePackageConfig {
|
|
6
|
+
/** Folders of components, relative to `theme.css` (`./ui`), that the app's Tailwind scans through `@source`. */
|
|
7
|
+
sources: string[];
|
|
8
|
+
/** CSS packages the components need, imported at the top of `theme.css` (`tw-animate-css`). */
|
|
9
|
+
imports: string[];
|
|
10
|
+
/** Further plain stylesheets in `src/`, copied to `dist/` as they are (`sft-bridge.css`). */
|
|
11
|
+
stylesheets: string[];
|
|
12
|
+
}
|
|
13
|
+
export type ConfigResult = {
|
|
14
|
+
ok: true;
|
|
15
|
+
config: ThemePackageConfig;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
error: string;
|
|
19
|
+
};
|
|
20
|
+
/** Narrows the `softureTheme` value of a `package.json` to a config, or says what is wrong with it. */
|
|
21
|
+
export declare function parseThemePackageConfig(value: unknown): ConfigResult;
|
|
22
|
+
//# sourceMappingURL=theme-package-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-package-config.d.ts","sourceRoot":"","sources":["../../src/build/theme-package-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IACjC,gHAAgH;IAChH,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+FAA+F;IAC/F,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,6FAA6F;IAC7F,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAiBnG,uGAAuG;AACvG,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAcpE"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const SOURCE_PATH = /^\.\/[a-z0-9-]+(?:\/[a-z0-9-]+)*$/;
|
|
2
|
+
const STYLESHEET_NAME = /^[a-z0-9-]+\.css$/;
|
|
3
|
+
const IMPORT_NAME = /^[@a-z0-9][@a-z0-9._/-]*$/;
|
|
4
|
+
function readList(record, key, pattern, hint) {
|
|
5
|
+
const value = record[key] ?? [];
|
|
6
|
+
if (!Array.isArray(value))
|
|
7
|
+
return `"${key}" is not a list`;
|
|
8
|
+
const items = [];
|
|
9
|
+
for (const item of value) {
|
|
10
|
+
if (typeof item !== "string" || !pattern.test(item))
|
|
11
|
+
return `"${key}" holds ${JSON.stringify(item)}, which is not ${hint}`;
|
|
12
|
+
items.push(item);
|
|
13
|
+
}
|
|
14
|
+
return items;
|
|
15
|
+
}
|
|
16
|
+
/** Narrows the `softureTheme` value of a `package.json` to a config, or says what is wrong with it. */
|
|
17
|
+
export function parseThemePackageConfig(value) {
|
|
18
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
19
|
+
return { ok: false, error: "softureTheme: missing, or not an object" };
|
|
20
|
+
}
|
|
21
|
+
const record = value;
|
|
22
|
+
const unknownKeys = Object.keys(record).filter((key) => !["sources", "imports", "stylesheets"].includes(key));
|
|
23
|
+
if (unknownKeys.length > 0)
|
|
24
|
+
return { ok: false, error: `softureTheme: unknown keys ${unknownKeys.join(", ")}` };
|
|
25
|
+
const sources = readList(record, "sources", SOURCE_PATH, "a relative folder like ./ui");
|
|
26
|
+
const imports = readList(record, "imports", IMPORT_NAME, "a package name");
|
|
27
|
+
const stylesheets = readList(record, "stylesheets", STYLESHEET_NAME, "a .css file name in src/");
|
|
28
|
+
for (const result of [sources, imports, stylesheets]) {
|
|
29
|
+
if (typeof result === "string")
|
|
30
|
+
return { ok: false, error: `softureTheme: ${result}` };
|
|
31
|
+
}
|
|
32
|
+
return { ok: true, config: { sources: sources, imports: imports, stylesheets: stylesheets } };
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=theme-package-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-package-config.js","sourceRoot":"","sources":["../../src/build/theme-package-config.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,GAAG,mCAAmC,CAAC;AACxD,MAAM,eAAe,GAAG,mBAAmB,CAAC;AAC5C,MAAM,WAAW,GAAG,2BAA2B,CAAC;AAEhD,SAAS,QAAQ,CAAC,MAA+B,EAAE,GAA6B,EAAE,OAAe,EAAE,IAAY;IAC7G,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,GAAG,iBAAiB,CAAC;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,KAAkB,EAAE,CAAC;QACtC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,GAAG,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,kBAAkB,IAAI,EAAE,CAAC;QAC3H,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,uBAAuB,CAAC,KAAc;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAC;IACzE,CAAC;IACD,MAAM,MAAM,GAAG,KAAgC,CAAC;IAChD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9G,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,8BAA8B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;IAChH,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,6BAA6B,CAAC,CAAC;IACxF,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAC3E,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,eAAe,EAAE,0BAA0B,CAAC,CAAC;IACjG,KAAK,MAAM,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;QACrD,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,MAAM,EAAE,EAAE,CAAC;IACzF,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,OAAmB,EAAE,OAAO,EAAE,OAAmB,EAAE,WAAW,EAAE,WAAuB,EAAE,EAAE,CAAC;AACpI,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ThemeDefinition } from "../theme-definition.js";
|
|
2
|
+
import type { ThemePackageConfig } from "./theme-package-config.js";
|
|
3
|
+
export interface ThemeStylesheetInput {
|
|
4
|
+
theme: ThemeDefinition;
|
|
5
|
+
/** `@source` paths: relative to the written file, or absolute (a test compiling the sources in place). */
|
|
6
|
+
sources: readonly string[];
|
|
7
|
+
imports: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The text of a theme package's `theme.css`: the CSS imports, the component folders as `@source` (Tailwind resolves
|
|
11
|
+
* them relative to the file, so the app's Tailwind finds them inside `node_modules`), then the generated tokens.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildThemeStylesheet({ theme, sources, imports }: ThemeStylesheetInput): string;
|
|
14
|
+
export interface WriteThemeStylesheetsOptions {
|
|
15
|
+
/** The theme package's folder; its `src/` holds the stylesheets to copy. */
|
|
16
|
+
packageDir: string;
|
|
17
|
+
/** Where the files go; the package's `dist/` by default. */
|
|
18
|
+
distDir?: string;
|
|
19
|
+
theme: ThemeDefinition;
|
|
20
|
+
config: ThemePackageConfig;
|
|
21
|
+
}
|
|
22
|
+
/** Writes `theme.css` and copies the declared stylesheets; returns the written file names. */
|
|
23
|
+
export declare function writeThemeStylesheets({ packageDir, distDir, theme, config }: WriteThemeStylesheetsOptions): string[];
|
|
24
|
+
//# sourceMappingURL=theme-stylesheet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-stylesheet.d.ts","sourceRoot":"","sources":["../../src/build/theme-stylesheet.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,eAAe,CAAC;IACvB,0GAA0G;IAC1G,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,oBAAoB,GAAG,MAAM,CAO9F;AAED,MAAM,WAAW,4BAA4B;IAC3C,4EAA4E;IAC5E,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,8FAA8F;AAC9F,wBAAgB,qBAAqB,CAAC,EAAE,UAAU,EAAE,OAAkC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,4BAA4B,GAAG,MAAM,EAAE,CAK/I"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { copyFileSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { buildThemeCss } from "../build-theme-css.js";
|
|
4
|
+
/**
|
|
5
|
+
* The text of a theme package's `theme.css`: the CSS imports, the component folders as `@source` (Tailwind resolves
|
|
6
|
+
* them relative to the file, so the app's Tailwind finds them inside `node_modules`), then the generated tokens.
|
|
7
|
+
*/
|
|
8
|
+
export function buildThemeStylesheet({ theme, sources, imports }) {
|
|
9
|
+
return [
|
|
10
|
+
...imports.map((name) => `@import ${JSON.stringify(name)};`),
|
|
11
|
+
...sources.map((source) => `@source ${JSON.stringify(source)};`),
|
|
12
|
+
"",
|
|
13
|
+
buildThemeCss(theme),
|
|
14
|
+
].join("\n");
|
|
15
|
+
}
|
|
16
|
+
/** Writes `theme.css` and copies the declared stylesheets; returns the written file names. */
|
|
17
|
+
export function writeThemeStylesheets({ packageDir, distDir = join(packageDir, "dist"), theme, config }) {
|
|
18
|
+
mkdirSync(distDir, { recursive: true });
|
|
19
|
+
writeFileSync(join(distDir, "theme.css"), buildThemeStylesheet({ theme, sources: config.sources, imports: config.imports }));
|
|
20
|
+
for (const name of config.stylesheets)
|
|
21
|
+
copyFileSync(join(packageDir, "src", name), join(distDir, name));
|
|
22
|
+
return ["theme.css", ...config.stylesheets];
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=theme-stylesheet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme-stylesheet.js","sourceRoot":"","sources":["../../src/build/theme-stylesheet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACjE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAWtD;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAwB;IACpF,OAAO;QACL,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAC5D,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC;QAChE,EAAE;QACF,aAAa,CAAC,KAAK,CAAC;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAWD,8FAA8F;AAC9F,MAAM,UAAU,qBAAqB,CAAC,EAAE,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,EAAgC;IACnI,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,oBAAoB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC7H,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,WAAW;QAAE,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IACxG,OAAO,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ThemeDefinition } from "./theme-definition.js";
|
|
2
|
+
/**
|
|
3
|
+
* The theme's CSS for Tailwind CSS v4: the tokens per scheme and the `@theme inline` block that turns them into
|
|
4
|
+
* utilities (`bg-background`, `text-page-title`, `rounded-xl`, `shadow-menu`, `w-sidebar-width`).
|
|
5
|
+
*
|
|
6
|
+
* Schemes: light on `:root` (and on `.light`, `[data-theme="light"]`); dark by the system setting unless the page asks
|
|
7
|
+
* for light, and on `.dark`, `[data-theme="dark"]`, so `next-themes` and `@softure-ai/ui`'s theme switch both work,
|
|
8
|
+
* and a section can take a fixed scheme; Tailwind's `dark:` variant follows the same rule. Throws on a name that is not kebab-case, an unsafe value, or an alias of an
|
|
9
|
+
* undefined colour.
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildThemeCss(definition: ThemeDefinition): string;
|
|
12
|
+
//# sourceMappingURL=build-theme-css.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-theme-css.d.ts","sourceRoot":"","sources":["../src/build-theme-css.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAmF3E;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,eAAe,GAAG,MAAM,CAYjE"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { TOKEN_NAME, UNSAFE_VALUE } from "./check-theme.js";
|
|
2
|
+
import { isColorAlias } from "./theme-definition.js";
|
|
3
|
+
/** Light by default, and for an element or a page that asks for it. */
|
|
4
|
+
const LIGHT_SELECTOR = ':root, .light, [data-theme="light"]';
|
|
5
|
+
/** Dark by the system setting, unless the page asks for light. */
|
|
6
|
+
const SYSTEM_DARK_SELECTOR = ':root:not(.light, [data-theme="light"])';
|
|
7
|
+
/** Dark by choice: `next-themes` (`class="dark"`) or `@softure-ai/ui`'s theme switch (`data-theme="dark"`). */
|
|
8
|
+
const DARK_SELECTOR = '.dark, [data-theme="dark"]';
|
|
9
|
+
/**
|
|
10
|
+
* Tailwind's `dark:` variant on the same rule as the tokens: the system setting unless the page asks for light, or an
|
|
11
|
+
* explicit dark scope. Without it, `dark:` would follow only the system setting.
|
|
12
|
+
*/
|
|
13
|
+
const DARK_VARIANT = `@custom-variant dark {
|
|
14
|
+
@media (prefers-color-scheme: dark) {
|
|
15
|
+
&:where(${SYSTEM_DARK_SELECTOR}, ${SYSTEM_DARK_SELECTOR} *) {
|
|
16
|
+
@slot;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
&:where(.dark, .dark *, [data-theme="dark"], [data-theme="dark"] *) {
|
|
20
|
+
@slot;
|
|
21
|
+
}
|
|
22
|
+
}`;
|
|
23
|
+
function checkName(kind, name) {
|
|
24
|
+
if (!TOKEN_NAME.test(name))
|
|
25
|
+
throw new Error(`buildThemeCss: ${kind} name "${name}" is not a lowercase kebab-case name`);
|
|
26
|
+
return name;
|
|
27
|
+
}
|
|
28
|
+
function checkValue(name, value) {
|
|
29
|
+
if (value.trim() === "" || UNSAFE_VALUE.test(value)) {
|
|
30
|
+
throw new Error(`buildThemeCss: value of "${name}" is empty or holds one of ; { } < > or a line break`);
|
|
31
|
+
}
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
function writeBlock(selector, lines, indent = "") {
|
|
35
|
+
return [`${indent}${selector} {`, ...lines.map((line) => `${indent} ${line}`), `${indent}}`].join("\n");
|
|
36
|
+
}
|
|
37
|
+
function writeSchemeLines(definition, scheme) {
|
|
38
|
+
const colors = Object.entries(definition.colors).flatMap(([name, value]) => {
|
|
39
|
+
checkName("colour", name);
|
|
40
|
+
if (isColorAlias(value)) {
|
|
41
|
+
if (!(value.alias in definition.colors)) {
|
|
42
|
+
throw new Error(`buildThemeCss: colour "${name}" follows "${value.alias}", which the theme does not define`);
|
|
43
|
+
}
|
|
44
|
+
// An alias is a reference, so it follows its target's scheme without a dark line of its own.
|
|
45
|
+
return scheme === "light" ? [`--${name}: var(--${checkName("colour", value.alias)});`] : [];
|
|
46
|
+
}
|
|
47
|
+
return [`--${name}: ${checkValue(name, value[scheme])};`];
|
|
48
|
+
});
|
|
49
|
+
const shadows = Object.entries(definition.shadows).map(([name, value]) => `--shadow-${checkName("shadow", name)}: ${checkValue(`shadow-${name}`, value[scheme])};`);
|
|
50
|
+
return [...colors, ...shadows];
|
|
51
|
+
}
|
|
52
|
+
function writeThemeLines(definition) {
|
|
53
|
+
const lines = [];
|
|
54
|
+
if (definition.clearDefaultPalette)
|
|
55
|
+
lines.push("--color-*: initial;");
|
|
56
|
+
for (const name of Object.keys(definition.colors))
|
|
57
|
+
lines.push(`--color-${name}: var(--${name});`);
|
|
58
|
+
for (const [family, stack] of Object.entries(definition.fonts)) {
|
|
59
|
+
lines.push(`--font-${checkName("font", family)}: ${checkValue(`font-${family}`, stack)};`);
|
|
60
|
+
}
|
|
61
|
+
for (const [name, style] of Object.entries(definition.textStyles)) {
|
|
62
|
+
const prefix = `--text-${checkName("text style", name)}`;
|
|
63
|
+
lines.push(`${prefix}: ${checkValue(prefix, style.fontSize)};`);
|
|
64
|
+
lines.push(`${prefix}--line-height: ${checkValue(prefix, style.lineHeight)};`);
|
|
65
|
+
lines.push(`${prefix}--font-weight: ${String(style.fontWeight)};`);
|
|
66
|
+
if (style.letterSpacing !== undefined)
|
|
67
|
+
lines.push(`${prefix}--letter-spacing: ${checkValue(prefix, style.letterSpacing)};`);
|
|
68
|
+
}
|
|
69
|
+
for (const [step, value] of Object.entries(definition.radii)) {
|
|
70
|
+
lines.push(`--radius-${checkName("radius", step)}: ${checkValue(`radius-${step}`, value)};`);
|
|
71
|
+
}
|
|
72
|
+
// A themed shadow: the utility reads the scheme blocks' value, which the dark blocks switch.
|
|
73
|
+
for (const name of Object.keys(definition.shadows))
|
|
74
|
+
lines.push(`--shadow-${name}: var(--shadow-${name});`);
|
|
75
|
+
for (const [name, value] of Object.entries(definition.sizes)) {
|
|
76
|
+
lines.push(`--spacing-${checkName("size", name)}: ${checkValue(`spacing-${name}`, value)};`);
|
|
77
|
+
}
|
|
78
|
+
return lines;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The theme's CSS for Tailwind CSS v4: the tokens per scheme and the `@theme inline` block that turns them into
|
|
82
|
+
* utilities (`bg-background`, `text-page-title`, `rounded-xl`, `shadow-menu`, `w-sidebar-width`).
|
|
83
|
+
*
|
|
84
|
+
* Schemes: light on `:root` (and on `.light`, `[data-theme="light"]`); dark by the system setting unless the page asks
|
|
85
|
+
* for light, and on `.dark`, `[data-theme="dark"]`, so `next-themes` and `@softure-ai/ui`'s theme switch both work,
|
|
86
|
+
* and a section can take a fixed scheme; Tailwind's `dark:` variant follows the same rule. Throws on a name that is not kebab-case, an unsafe value, or an alias of an
|
|
87
|
+
* undefined colour.
|
|
88
|
+
*/
|
|
89
|
+
export function buildThemeCss(definition) {
|
|
90
|
+
const light = writeSchemeLines(definition, "light");
|
|
91
|
+
const dark = writeSchemeLines(definition, "dark");
|
|
92
|
+
return [
|
|
93
|
+
`/* Theme "${definition.name.replace(/\*\//g, "")}", generated by @softure-ai/theme-kit (buildThemeCss). */`,
|
|
94
|
+
DARK_VARIANT,
|
|
95
|
+
writeBlock(LIGHT_SELECTOR, light),
|
|
96
|
+
`@media (prefers-color-scheme: dark) {\n${writeBlock(SYSTEM_DARK_SELECTOR, dark, " ")}\n}`,
|
|
97
|
+
writeBlock(DARK_SELECTOR, dark),
|
|
98
|
+
writeBlock("@theme inline", writeThemeLines(definition)),
|
|
99
|
+
"",
|
|
100
|
+
].join("\n\n");
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=build-theme-css.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-theme-css.js","sourceRoot":"","sources":["../src/build-theme-css.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ThemeDefinition } from "./theme-definition.js";
|
|
2
|
+
/** A token name: lowercase kebab-case (`primary-hover`, `chart-1`). */
|
|
3
|
+
export declare const TOKEN_NAME: RegExp;
|
|
4
|
+
/** Characters that would end a CSS declaration or block, or open markup. */
|
|
5
|
+
export declare const UNSAFE_VALUE: RegExp;
|
|
6
|
+
/**
|
|
7
|
+
* Every way a definition breaks the theme contract, as readable messages; empty when the theme is complete. Checks the
|
|
8
|
+
* shadcn colour roles, that every token name is kebab-case, that no value is empty or could break out of the CSS, and
|
|
9
|
+
* that every alias points at a colour of the same theme.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkTheme(definition: ThemeDefinition): string[];
|
|
12
|
+
//# sourceMappingURL=check-theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-theme.d.ts","sourceRoot":"","sources":["../src/check-theme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElG,uEAAuE;AACvE,eAAO,MAAM,UAAU,QAA+B,CAAC;AACvD,4EAA4E;AAC5E,eAAO,MAAM,YAAY,QAAgB,CAAC;AA+B1C;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,eAAe,GAAG,MAAM,EAAE,CAoBhE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { findMissingColorRoles, isColorAlias } from "./theme-definition.js";
|
|
2
|
+
/** A token name: lowercase kebab-case (`primary-hover`, `chart-1`). */
|
|
3
|
+
export const TOKEN_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
4
|
+
/** Characters that would end a CSS declaration or block, or open markup. */
|
|
5
|
+
export const UNSAFE_VALUE = /[;{}<>\r\n]/;
|
|
6
|
+
function findNameProblems(kind, names) {
|
|
7
|
+
return names.filter((name) => !TOKEN_NAME.test(name)).map((name) => `${kind} name "${name}" is not a lowercase kebab-case name`);
|
|
8
|
+
}
|
|
9
|
+
function findValueProblems(entries) {
|
|
10
|
+
return entries
|
|
11
|
+
.filter(([, value]) => value.trim() === "" || UNSAFE_VALUE.test(value))
|
|
12
|
+
.map(([name]) => `value of "${name}" is empty or holds one of ; { } < > or a line break`);
|
|
13
|
+
}
|
|
14
|
+
function listValues(definition) {
|
|
15
|
+
const colors = Object.entries(definition.colors).flatMap(([name, value]) => isColorAlias(value) ? [] : [[name, value.light], [name, value.dark]]);
|
|
16
|
+
const shadows = Object.entries(definition.shadows).flatMap(([name, value]) => [
|
|
17
|
+
[`shadow-${name}`, value.light],
|
|
18
|
+
[`shadow-${name}`, value.dark],
|
|
19
|
+
]);
|
|
20
|
+
const fonts = Object.entries(definition.fonts).map(([family, stack]) => [`font-${family}`, stack]);
|
|
21
|
+
const textStyles = Object.entries(definition.textStyles).flatMap(([name, style]) => [style.fontSize, style.lineHeight, ...(style.letterSpacing === undefined ? [] : [style.letterSpacing])].map((value) => [`text-${name}`, value]));
|
|
22
|
+
const radii = Object.entries(definition.radii).map(([step, value]) => [`radius-${step}`, value]);
|
|
23
|
+
const sizes = Object.entries(definition.sizes).map(([name, value]) => [`spacing-${name}`, value]);
|
|
24
|
+
return [...colors, ...shadows, ...fonts, ...textStyles, ...radii, ...sizes];
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Every way a definition breaks the theme contract, as readable messages; empty when the theme is complete. Checks the
|
|
28
|
+
* shadcn colour roles, that every token name is kebab-case, that no value is empty or could break out of the CSS, and
|
|
29
|
+
* that every alias points at a colour of the same theme.
|
|
30
|
+
*/
|
|
31
|
+
export function checkTheme(definition) {
|
|
32
|
+
const problems = [];
|
|
33
|
+
if (definition.name.trim() === "")
|
|
34
|
+
problems.push("the theme has no name");
|
|
35
|
+
const missing = findMissingColorRoles(definition);
|
|
36
|
+
if (missing.length > 0)
|
|
37
|
+
problems.push(`missing shadcn colour roles: ${missing.join(", ")}`);
|
|
38
|
+
problems.push(...findNameProblems("colour", Object.keys(definition.colors)), ...findNameProblems("shadow", Object.keys(definition.shadows)), ...findNameProblems("font", Object.keys(definition.fonts)), ...findNameProblems("text style", Object.keys(definition.textStyles)), ...findNameProblems("radius", Object.keys(definition.radii)), ...findNameProblems("size", Object.keys(definition.sizes)), ...findValueProblems(listValues(definition)));
|
|
39
|
+
for (const [name, value] of Object.entries(definition.colors)) {
|
|
40
|
+
if (isColorAlias(value) && !(value.alias in definition.colors)) {
|
|
41
|
+
problems.push(`colour "${name}" follows "${value.alias}", which the theme does not define`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return problems;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=check-theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-theme.js","sourceRoot":"","sources":["../src/check-theme.ts"],"names":[],"mappings":"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"}
|