@dxos/ui-theme 0.13.0 → 0.14.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/dist/plugin/ThemePlugin.cjs +34 -5
- package/dist/plugin/ThemePlugin.cjs.map +1 -1
- package/dist/plugin/ThemePlugin.mjs +36 -7
- package/dist/plugin/ThemePlugin.mjs.map +1 -1
- package/dist/types/src/plugins/ThemePlugin.d.ts +2 -0
- package/dist/types/src/plugins/ThemePlugin.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/main.css +4 -41
- package/src/plugins/ThemePlugin.ts +62 -11
- package/src/workspace.css +45 -0
- package/dist/plugin/main.css +0 -4125
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/ui-theme",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "A set of design system tokens to use with DXOS UI.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@fontsource-variable/inter": "5.2.8",
|
|
39
39
|
"@fontsource-variable/jetbrains-mono": "5.0.21",
|
|
40
40
|
"@fontsource-variable/nunito": "5.2.7",
|
|
41
|
-
"@fontsource/poiret-one": "^5.
|
|
41
|
+
"@fontsource/poiret-one": "^5.2.8",
|
|
42
42
|
"@tailwindcss/forms": "^0.5.9",
|
|
43
43
|
"@tailwindcss/postcss": "^4.3.3",
|
|
44
44
|
"@tailwindcss/vite": "^4.3.3",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"tailwind-scrollbar": "^4.0.0",
|
|
51
51
|
"tailwind-variants": "^3.2.2",
|
|
52
52
|
"tailwindcss": "^4.3.0",
|
|
53
|
-
"@dxos/node-std": "0.
|
|
54
|
-
"@dxos/ui-types": "0.
|
|
53
|
+
"@dxos/node-std": "0.14.0",
|
|
54
|
+
"@dxos/ui-types": "0.14.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@storybook/react-vite": "^10.6.0",
|
package/src/main.css
CHANGED
|
@@ -18,8 +18,10 @@
|
|
|
18
18
|
* Tailwind CSS regeneration, which invalidates `main.css` through its
|
|
19
19
|
* import graph and produces a 3–5-ping HMR storm per icon-sprite write
|
|
20
20
|
* during cold-start (icons land in tight bursts as plugin chunks stream
|
|
21
|
-
* in).
|
|
22
|
-
*
|
|
21
|
+
* in). The entry that imports this file declares the scan paths instead:
|
|
22
|
+
* `workspace.css` in this repo, or the stylesheet `ThemePlugin` generates for
|
|
23
|
+
* an installed copy, since paths relative to this file would reach the
|
|
24
|
+
* consumer's whole `node_modules`.
|
|
23
25
|
*/
|
|
24
26
|
@import 'tailwindcss' source(none);
|
|
25
27
|
|
|
@@ -49,45 +51,6 @@
|
|
|
49
51
|
/* Third-party integrations */
|
|
50
52
|
@import './css/integrations/codemirror.css';
|
|
51
53
|
|
|
52
|
-
/**
|
|
53
|
-
* With `source(none)` on the Tailwind import above, these are the *only*
|
|
54
|
-
* paths Tailwind scans for utility classes. Cover every workspace source
|
|
55
|
-
* directory so lazy-loaded plugin / UI / SDK chunks don't surface new
|
|
56
|
-
* utilities mid-session, and root-level HTML entrypoints (index.html,
|
|
57
|
-
* internal.html, …) are visible too.
|
|
58
|
-
*
|
|
59
|
-
* Paths are relative to this file (`packages/ui/ui-theme/src/main.css`):
|
|
60
|
-
* ../../../ → `packages/`
|
|
61
|
-
* ../../../../tools/ → `tools/`
|
|
62
|
-
*
|
|
63
|
-
* Tailwind ignores `node_modules` and common build/output dirs by default,
|
|
64
|
-
* so a broad workspace glob is safe *for scanning*.
|
|
65
|
-
*
|
|
66
|
-
* NOTE: Tailwind's scanner respects `.gitignore` (so `dist/` is never
|
|
67
|
-
* scanned), but it hands Vite a coarse `dir-dependency` glob and Vite
|
|
68
|
-
* re-expands that itself, ignoring only `node_modules`. That re-expansion
|
|
69
|
-
* sweeps `dist/**` `.d.ts` files into the watch set and causes a `main.css`
|
|
70
|
-
* HMR storm on every package rebuild. Build outputs are excluded from the
|
|
71
|
-
* dev watcher in `plugins/ThemePlugin.ts` (`server.watch.ignored`) rather
|
|
72
|
-
* than here, because `@source not` does NOT propagate to the glob Vite
|
|
73
|
-
* re-expands.
|
|
74
|
-
*/
|
|
75
|
-
@source '../../../**/*.{ts,tsx,html}';
|
|
76
|
-
@source '../../../../tools/**/*.{ts,tsx,html}';
|
|
77
|
-
|
|
78
|
-
/* Plain stylesheets outside this build (Next's theme, plugin overrides): scanning them keeps the theme variables they read (`var(--color-*)`) from being tree-shaken once no utility class names them. */
|
|
79
|
-
@source '../../../**/src/**/*.css';
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Exclude generated/static data files that have no Tailwind classes but are
|
|
83
|
-
* large enough to dominate scan time. The oxide scanner tokenizes every byte;
|
|
84
|
-
* a single 5MB geo-data file can pin Vite at 100% CPU for tens of seconds on
|
|
85
|
-
* a cold start.
|
|
86
|
-
*/
|
|
87
|
-
@source not '../../../ui/react-ui-geo/data/**';
|
|
88
|
-
@source not '../../../ui/solid-ui-geo/data/**';
|
|
89
|
-
@source not '../../../apps/composer-app/src/plugins/welcome/components/Welcome/hero-image.ts';
|
|
90
|
-
|
|
91
54
|
/**
|
|
92
55
|
* Force-emit CSS variables for the full color palette for all:
|
|
93
56
|
* --color-{hue}-{shade}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
import tailwindcssPostcss from '@tailwindcss/postcss';
|
|
8
8
|
import tailwindcssVite from '@tailwindcss/vite';
|
|
9
9
|
import autoprefixer from 'autoprefixer';
|
|
10
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
11
|
-
import { resolve } from 'node:path';
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from 'node:fs';
|
|
11
|
+
import { dirname, join, resolve, sep } from 'node:path';
|
|
12
12
|
import postcssImport from 'postcss-import';
|
|
13
13
|
import postcssNesting from 'postcss-nesting';
|
|
14
14
|
import { type HtmlTagDescriptor, type Plugin, type UserConfig } from 'vite';
|
|
@@ -82,19 +82,61 @@ const skipHotUpdateInBundledDev = (plugin: Plugin): Plugin => {
|
|
|
82
82
|
|
|
83
83
|
export type ThemePluginOptions = {
|
|
84
84
|
srcCssPath?: string;
|
|
85
|
+
/** Extra Tailwind scan globs (absolute, or relative to the Vite root) for a consumer of the published package. */
|
|
86
|
+
content?: string[];
|
|
85
87
|
virtualFileId?: string;
|
|
86
88
|
verbose?: boolean;
|
|
87
89
|
};
|
|
88
90
|
|
|
91
|
+
const toCssString = (path: string): string => JSON.stringify(path.split(sep).join('/'));
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Writes the theme entry for a consumer of the published package and returns its path.
|
|
95
|
+
* `workspace.css` cannot serve them: its scan paths are relative to this package, which from inside
|
|
96
|
+
* `node_modules` reaches every installed package, and Tailwind walks all of it before answering.
|
|
97
|
+
*/
|
|
98
|
+
const writeConsumerTheme = ({
|
|
99
|
+
packageRoot,
|
|
100
|
+
root,
|
|
101
|
+
outPath,
|
|
102
|
+
content,
|
|
103
|
+
}: {
|
|
104
|
+
packageRoot: string;
|
|
105
|
+
root: string;
|
|
106
|
+
outPath: string;
|
|
107
|
+
content: string[];
|
|
108
|
+
}): string => {
|
|
109
|
+
// The scope this package was installed into, and the consumer's own, which differ under pnpm's isolated layout.
|
|
110
|
+
const scopeDirs = new Set([dirname(packageRoot), resolve(root, 'node_modules/@dxos')]);
|
|
111
|
+
const sources = [
|
|
112
|
+
// Tailwind skips `node_modules` below an explicit base, so this covers only the consumer's own files.
|
|
113
|
+
join(root, '**/*.{ts,tsx,js,jsx,html}'),
|
|
114
|
+
...[...scopeDirs].map((scopeDir) => join(scopeDir, '*/dist/lib/**/*.mjs')),
|
|
115
|
+
...content.map((glob) => resolve(root, glob)),
|
|
116
|
+
];
|
|
117
|
+
const css = [
|
|
118
|
+
`@import ${toCssString(join(packageRoot, 'src/main.css'))};`,
|
|
119
|
+
...sources.map((source) => `@source ${toCssString(source)};`),
|
|
120
|
+
'',
|
|
121
|
+
].join('\n');
|
|
122
|
+
|
|
123
|
+
// Rewriting identical content would bump the mtime, which Tailwind reads as a reason to rebuild.
|
|
124
|
+
if (!existsSync(outPath) || readFileSync(outPath, 'utf-8') !== css) {
|
|
125
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
126
|
+
writeFileSync(outPath, css);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return outPath;
|
|
130
|
+
};
|
|
131
|
+
|
|
89
132
|
/**
|
|
90
133
|
* Vite plugin to configure theme.
|
|
91
134
|
* Returns the official Tailwind Vite plugin (persistent incremental scanner) alongside the theme plugin.
|
|
92
135
|
*/
|
|
93
136
|
export const ThemePlugin = (options: ThemePluginOptions): Plugin[] => {
|
|
94
|
-
//
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
const isMonorepo = existsSync(srcThemePath);
|
|
137
|
+
// `src` is published too, so only the location tells a workspace checkout from an installed copy.
|
|
138
|
+
const packageRoot = realpathSync(resolve(import.meta.dirname, ROOT));
|
|
139
|
+
const isMonorepo = !packageRoot.split(sep).includes('node_modules');
|
|
98
140
|
|
|
99
141
|
// Static assets shipped via "files": ["src"] in package.json.
|
|
100
142
|
// Both monorepo and installed package resolve to the same src/plugins/ directory.
|
|
@@ -103,15 +145,12 @@ export const ThemePlugin = (options: ThemePluginOptions): Plugin[] => {
|
|
|
103
145
|
const mainCssPath = resolve(pluginsDir, 'main.css');
|
|
104
146
|
|
|
105
147
|
const config = {
|
|
106
|
-
|
|
148
|
+
// Installed copies get theirs from `configResolved`, which knows the consumer's root.
|
|
149
|
+
srcCssPath: options.srcCssPath ?? (isMonorepo ? resolve(packageRoot, 'src/workspace.css') : ''),
|
|
107
150
|
virtualFileId: options.virtualFileId ?? '@dxos-theme',
|
|
108
151
|
verbose: options.verbose,
|
|
109
152
|
};
|
|
110
153
|
|
|
111
|
-
if (process.env.DEBUG || options.verbose) {
|
|
112
|
-
console.log('ThemePlugin:\n', JSON.stringify(config, null, 2));
|
|
113
|
-
}
|
|
114
|
-
|
|
115
154
|
// Set under `vite dev --experimentalBundle`; see the guard in `hotUpdate`.
|
|
116
155
|
let bundledDev = false;
|
|
117
156
|
|
|
@@ -130,6 +169,18 @@ export const ThemePlugin = (options: ThemePluginOptions): Plugin[] => {
|
|
|
130
169
|
name: 'vite-plugin-dxos-ui-theme',
|
|
131
170
|
configResolved: (resolved) => {
|
|
132
171
|
bundledDev = resolved.experimental.bundledDev === true;
|
|
172
|
+
if (!config.srcCssPath) {
|
|
173
|
+
config.srcCssPath = writeConsumerTheme({
|
|
174
|
+
packageRoot,
|
|
175
|
+
root: resolved.root,
|
|
176
|
+
outPath: resolve(resolved.cacheDir, '..', '.dxos-ui-theme.css'),
|
|
177
|
+
content: options.content ?? [],
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (process.env.DEBUG || options.verbose) {
|
|
182
|
+
console.log('ThemePlugin:\n', JSON.stringify(config, null, 2));
|
|
183
|
+
}
|
|
133
184
|
},
|
|
134
185
|
config: (): UserConfig => {
|
|
135
186
|
return {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-repo theme entry: the theme plus the workspace scan paths.
|
|
3
|
+
* Installed copies of this package never load it; `ThemePlugin` generates their entry instead.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
@import './main.css';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* With `source(none)` on the Tailwind import in `main.css`, these are the *only*
|
|
10
|
+
* paths Tailwind scans for utility classes. Cover every workspace source
|
|
11
|
+
* directory so lazy-loaded plugin / UI / SDK chunks don't surface new
|
|
12
|
+
* utilities mid-session, and root-level HTML entrypoints (index.html,
|
|
13
|
+
* internal.html, …) are visible too.
|
|
14
|
+
*
|
|
15
|
+
* Paths are relative to this file (`packages/ui/ui-theme/src/workspace.css`):
|
|
16
|
+
* ../../../ → `packages/`
|
|
17
|
+
* ../../../../tools/ → `tools/`
|
|
18
|
+
*
|
|
19
|
+
* Tailwind ignores `node_modules` and common build/output dirs by default,
|
|
20
|
+
* so a broad workspace glob is safe *for scanning*.
|
|
21
|
+
*
|
|
22
|
+
* NOTE: Tailwind's scanner respects `.gitignore` (so `dist/` is never
|
|
23
|
+
* scanned), but it hands Vite a coarse `dir-dependency` glob and Vite
|
|
24
|
+
* re-expands that itself, ignoring only `node_modules`. That re-expansion
|
|
25
|
+
* sweeps `dist/**` `.d.ts` files into the watch set and causes a theme
|
|
26
|
+
* HMR storm on every package rebuild. Build outputs are excluded from the
|
|
27
|
+
* dev watcher in `plugins/ThemePlugin.ts` (`server.watch.ignored`) rather
|
|
28
|
+
* than here, because `@source not` does NOT propagate to the glob Vite
|
|
29
|
+
* re-expands.
|
|
30
|
+
*/
|
|
31
|
+
@source '../../../**/*.{ts,tsx,html}';
|
|
32
|
+
@source '../../../../tools/**/*.{ts,tsx,html}';
|
|
33
|
+
|
|
34
|
+
/* Plain stylesheets outside this build (Next's theme, plugin overrides): scanning them keeps the theme variables they read (`var(--color-*)`) from being tree-shaken once no utility class names them. */
|
|
35
|
+
@source '../../../**/src/**/*.css';
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Exclude generated/static data files that have no Tailwind classes but are
|
|
39
|
+
* large enough to dominate scan time. The oxide scanner tokenizes every byte;
|
|
40
|
+
* a single 5MB geo-data file can pin Vite at 100% CPU for tens of seconds on
|
|
41
|
+
* a cold start.
|
|
42
|
+
*/
|
|
43
|
+
@source not '../../../ui/react-ui-geo/data/**';
|
|
44
|
+
@source not '../../../ui/solid-ui-geo/data/**';
|
|
45
|
+
@source not '../../../apps/composer-app/src/plugins/welcome/components/Welcome/hero-image.ts';
|