@pharos-ds/build 0.1.9
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/LICENSE +24 -0
- package/README.md +258 -0
- package/dist/vite.d.ts +91 -0
- package/dist/vite.mjs +287 -0
- package/package.json +63 -0
- package/src/babel.js +106 -0
- package/src/babel.test.mjs +73 -0
- package/src/config.js +92 -0
- package/src/index.js +251 -0
- package/src/next.js +72 -0
- package/src/vite.test.ts +48 -0
- package/src/vite.ts +429 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Caio Silvestre
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2026 Meta Platforms, Inc.
|
|
6
|
+
(portions derived from Astryx — https://github.com/facebook/astryx)
|
|
7
|
+
|
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
9
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
10
|
+
in the Software without restriction, including without limitation the rights
|
|
11
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
12
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
13
|
+
furnished to do so, subject to the following conditions:
|
|
14
|
+
|
|
15
|
+
The above copyright notice and this permission notice shall be included in all
|
|
16
|
+
copies or substantial portions of the Software.
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# @pharos-ds/build
|
|
2
|
+
|
|
3
|
+
Build plugins for XDS source builds. Provides babel, PostCSS, and Vite integrations that compile XDS library and product code with separate class name prefixes, which enables independent CSS layers:
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
reset < pharos-base (library, pharos prefix) < pharos-theme < product (app, x prefix)
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Why?
|
|
10
|
+
|
|
11
|
+
StyleX generates atomic CSS: same declaration = same class name. Without separate prefixes, library and product classes collide and can't be placed in independent CSS layers, which breaks theme overrides.
|
|
12
|
+
|
|
13
|
+
`@pharos-ds/build` solves this by:
|
|
14
|
+
|
|
15
|
+
1. Compiling XDS library code with `pharos` prefix (`.pharos78zum5`)
|
|
16
|
+
2. Compiling product code with default `x` prefix (`.x78zum5`)
|
|
17
|
+
3. Placing each group in its own CSS `@layer`
|
|
18
|
+
|
|
19
|
+
## Packages
|
|
20
|
+
|
|
21
|
+
| Export | Purpose | Platform |
|
|
22
|
+
| -------------------------- | -------------------------------------------- | --------------------------- |
|
|
23
|
+
| `@pharos-ds/build/babel` | Babel plugin: splits class prefixes per file | Next.js, any babel pipeline |
|
|
24
|
+
| `@pharos-ds/build/postcss` | PostCSS plugin: compiles + splits CSS layers | Next.js |
|
|
25
|
+
| `@pharos-ds/build/vite` | Vite plugin: wraps unplugin + splits layers | Vite, Storybook |
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install -D @pharos-ds/build @stylexjs/babel-plugin @babel/core
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
For Vite, also install:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -D @stylexjs/unplugin
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Next.js Setup
|
|
42
|
+
|
|
43
|
+
### 1. babel.config.js
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
const path = require('path');
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
presets: ['next/babel'],
|
|
50
|
+
plugins: [
|
|
51
|
+
[
|
|
52
|
+
'@pharos-ds/build/babel',
|
|
53
|
+
{
|
|
54
|
+
dev: process.env.NODE_ENV !== 'production',
|
|
55
|
+
runtimeInjection: false,
|
|
56
|
+
treeshakeCompensation: true,
|
|
57
|
+
enableInlinedConditionalMerge: true,
|
|
58
|
+
aliases: {
|
|
59
|
+
'@pharos-ds/core/*': [
|
|
60
|
+
path.join(__dirname, 'node_modules/@pharos-ds/core/*'),
|
|
61
|
+
],
|
|
62
|
+
'@pharos-ds/core': [
|
|
63
|
+
path.join(__dirname, 'node_modules/@pharos-ds/core'),
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
unstable_moduleResolution: {type: 'commonJS'},
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. postcss.config.js
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
const path = require('path');
|
|
77
|
+
|
|
78
|
+
module.exports = {
|
|
79
|
+
plugins: {
|
|
80
|
+
'@pharos-ds/build/postcss': {
|
|
81
|
+
appDir: 'src',
|
|
82
|
+
babelPlugins: [
|
|
83
|
+
[
|
|
84
|
+
'@stylexjs/babel-plugin',
|
|
85
|
+
{
|
|
86
|
+
dev: process.env.NODE_ENV !== 'production',
|
|
87
|
+
runtimeInjection: false,
|
|
88
|
+
treeshakeCompensation: true,
|
|
89
|
+
enableInlinedConditionalMerge: true,
|
|
90
|
+
aliases: {
|
|
91
|
+
'@pharos-ds/core/*': [
|
|
92
|
+
path.join(__dirname, 'node_modules/@pharos-ds/core/*'),
|
|
93
|
+
],
|
|
94
|
+
'@pharos-ds/core': [
|
|
95
|
+
path.join(__dirname, 'node_modules/@pharos-ds/core'),
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
unstable_moduleResolution: {type: 'commonJS'},
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 3. next.config.mjs
|
|
108
|
+
|
|
109
|
+
```js
|
|
110
|
+
const nextConfig = {
|
|
111
|
+
transpilePackages: ['@pharos-ds/core', '@pharos-ds/theme-pharos'],
|
|
112
|
+
webpack: config => {
|
|
113
|
+
// Resolve to source TypeScript instead of dist
|
|
114
|
+
config.resolve.conditionNames = ['source', 'import', 'require', 'default'];
|
|
115
|
+
return config;
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export default nextConfig;
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 4. CSS files
|
|
123
|
+
|
|
124
|
+
`src/app/layers.css`:
|
|
125
|
+
|
|
126
|
+
```css
|
|
127
|
+
@layer reset, pharos-base, pharos-theme, product;
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`src/app/globals.css`:
|
|
131
|
+
|
|
132
|
+
```css
|
|
133
|
+
@import './layers.css';
|
|
134
|
+
@import '@pharos-ds/core/reset.css';
|
|
135
|
+
@import '@pharos-ds/theme-pharos/theme.css';
|
|
136
|
+
|
|
137
|
+
@stylex;
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
> `layers.css` must be a separate file because webpack hoists `@import` content above inline CSS.
|
|
141
|
+
|
|
142
|
+
### 5. Browserslist
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"browserslist": ["last 1 Chrome version"]
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Vite Setup
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
import {pharosStylex} from '@pharos-ds/build/vite';
|
|
156
|
+
import react from '@vitejs/plugin-react';
|
|
157
|
+
|
|
158
|
+
export default defineConfig({
|
|
159
|
+
plugins: [
|
|
160
|
+
...pharosStylex({
|
|
161
|
+
stylexOptions: {
|
|
162
|
+
dev: process.env.NODE_ENV === 'development',
|
|
163
|
+
runtimeInjection: false,
|
|
164
|
+
treeshakeCompensation: true,
|
|
165
|
+
unstable_moduleResolution: {
|
|
166
|
+
type: 'commonJS',
|
|
167
|
+
rootDir: __dirname,
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
}),
|
|
171
|
+
react(),
|
|
172
|
+
],
|
|
173
|
+
resolve: {
|
|
174
|
+
alias: {
|
|
175
|
+
'@pharos-ds/core': path.resolve(
|
|
176
|
+
__dirname,
|
|
177
|
+
'node_modules/@pharos-ds/core/src',
|
|
178
|
+
),
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
optimizeDeps: {
|
|
182
|
+
exclude: ['@pharos-ds/core', '@pharos-ds/theme-pharos'],
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## How it works
|
|
190
|
+
|
|
191
|
+
### Babel plugin (`@pharos-ds/build/babel`)
|
|
192
|
+
|
|
193
|
+
Wraps `@stylexjs/babel-plugin` with two internal instances: one with `classNamePrefix: 'pharos'` for library files, one with default `'x'` for product files. Routes each file to the correct instance based on its path.
|
|
194
|
+
|
|
195
|
+
Library patterns (configurable):
|
|
196
|
+
|
|
197
|
+
- `packages/core/`
|
|
198
|
+
- `packages/themes/`
|
|
199
|
+
- `node_modules/@pharos-ds/`
|
|
200
|
+
|
|
201
|
+
### PostCSS plugin (`@pharos-ds/build/postcss`)
|
|
202
|
+
|
|
203
|
+
Compiles StyleX from both library and product source files in two separate passes with different prefixes. Wraps the results in named `@layer` blocks:
|
|
204
|
+
|
|
205
|
+
- Library rules → `@layer pharos-base`
|
|
206
|
+
- Product rules → `@layer product`
|
|
207
|
+
|
|
208
|
+
### Vite plugin (`@pharos-ds/build/vite`)
|
|
209
|
+
|
|
210
|
+
Wraps `@stylexjs/unplugin` and intercepts the dev CSS endpoint (`/virtual:stylex.css`). Partitions the collected rules by file path and serves split-layer CSS.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Advanced Options
|
|
215
|
+
|
|
216
|
+
### Babel plugin
|
|
217
|
+
|
|
218
|
+
```js
|
|
219
|
+
[
|
|
220
|
+
'@pharos-ds/build/babel',
|
|
221
|
+
{
|
|
222
|
+
// Patterns to identify library files (default shown)
|
|
223
|
+
libraryPatterns: [
|
|
224
|
+
'packages/core/',
|
|
225
|
+
'packages/themes/',
|
|
226
|
+
'node_modules/@pharos-ds/',
|
|
227
|
+
],
|
|
228
|
+
|
|
229
|
+
// Class name prefix for library styles (default: 'pharos')
|
|
230
|
+
libraryPrefix: 'pharos',
|
|
231
|
+
|
|
232
|
+
// Class name prefix for product styles (default: 'x')
|
|
233
|
+
classNamePrefix: 'x',
|
|
234
|
+
|
|
235
|
+
// ... all @stylexjs/babel-plugin options
|
|
236
|
+
},
|
|
237
|
+
];
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### PostCSS plugin
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
'@pharos-ds/build/postcss': {
|
|
244
|
+
appDir: 'src', // Your app source directory
|
|
245
|
+
babelPlugins: [...], // StyleX babel plugin config
|
|
246
|
+
libraryPrefix: 'pharos', // Prefix for library CSS (default: 'pharos')
|
|
247
|
+
extraInclude: [...], // Additional glob patterns
|
|
248
|
+
layers: { // Layer names (defaults shown)
|
|
249
|
+
library: 'pharos-base',
|
|
250
|
+
product: 'product',
|
|
251
|
+
},
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Related
|
|
256
|
+
|
|
257
|
+
- [example-nextjs-source](../../apps/example-nextjs-source/): full Next.js source build example
|
|
258
|
+
- [`@stylexjs/babel-plugin`](https://github.com/facebook/stylex): the underlying StyleX compiler
|
package/dist/vite.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import stylex from '@stylexjs/unplugin';
|
|
3
|
+
/**
|
|
4
|
+
* Browser targets for lightningcss (opt-in).
|
|
5
|
+
* Only needed if your StyleX version lowers light-dark() without them.
|
|
6
|
+
* Exported for consumers who want to opt in explicitly.
|
|
7
|
+
*/
|
|
8
|
+
export declare const LIGHTNINGCSS_TARGETS: {
|
|
9
|
+
chrome: number;
|
|
10
|
+
firefox: number;
|
|
11
|
+
safari: number;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Legacy options shape — kept for backward compatibility.
|
|
15
|
+
* Prefer the zero-config form: pharosStylex()
|
|
16
|
+
*/
|
|
17
|
+
export interface PharosVitePluginLegacyOptions {
|
|
18
|
+
stylexOptions: Parameters<typeof stylex.vite>[0];
|
|
19
|
+
libraryPattern?: string;
|
|
20
|
+
/** StyleX atomic class-name prefix for Pharos library styles. @default 'pharos' */
|
|
21
|
+
stylexPrefix?: string;
|
|
22
|
+
layers?: {
|
|
23
|
+
library?: string;
|
|
24
|
+
product?: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export interface PharosVitePluginOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Whether to enable dev mode for StyleX.
|
|
30
|
+
* @default process.env.NODE_ENV !== 'production'
|
|
31
|
+
*/
|
|
32
|
+
dev?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Root directory for module resolution.
|
|
35
|
+
* @default process.cwd()
|
|
36
|
+
*/
|
|
37
|
+
rootDir?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Pattern to identify Pharos library files vs product files.
|
|
40
|
+
* @default 'node_modules/@pharos-ds/'
|
|
41
|
+
*/
|
|
42
|
+
libraryPattern?: string;
|
|
43
|
+
/**
|
|
44
|
+
* CSS layer names for the split output.
|
|
45
|
+
*/
|
|
46
|
+
layers?: {
|
|
47
|
+
/** Layer name for Pharos library styles @default 'pharos-base' */
|
|
48
|
+
library?: string;
|
|
49
|
+
/** Layer name for product styles @default 'product' */
|
|
50
|
+
product?: string;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* LightningCSS browser targets. Only needed if your StyleX version
|
|
54
|
+
* lowers light-dark() without them. Most recent versions preserve
|
|
55
|
+
* light-dark() by default.
|
|
56
|
+
* @default undefined (no targets set)
|
|
57
|
+
*/
|
|
58
|
+
lightningcssTargets?: Record<string, number>;
|
|
59
|
+
/**
|
|
60
|
+
* StyleX atomic class-name prefix for Pharos *library* styles. The product
|
|
61
|
+
* build uses a distinct prefix so library and product atoms never collide
|
|
62
|
+
* across layers.
|
|
63
|
+
*
|
|
64
|
+
* Configurable if a consumer needs a custom library atom prefix.
|
|
65
|
+
* Defaults to `pharos`.
|
|
66
|
+
*
|
|
67
|
+
* @default 'pharos'
|
|
68
|
+
*/
|
|
69
|
+
stylexPrefix?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Extra StyleX options to merge.
|
|
72
|
+
*/
|
|
73
|
+
stylexOverrides?: Record<string, unknown>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Pharos Vite plugin for source builds.
|
|
77
|
+
*
|
|
78
|
+
* Provides sensible defaults for StyleX compilation with Pharos.
|
|
79
|
+
* Just spread into your plugins array:
|
|
80
|
+
*
|
|
81
|
+
* plugins: [...pharosStylex(), react()]
|
|
82
|
+
*
|
|
83
|
+
* Handles:
|
|
84
|
+
* - StyleX compilation with correct settings
|
|
85
|
+
* - CSS layer ordering (reset < pharos-base < pharos-theme < product)
|
|
86
|
+
* - resolve.alias for @pharos-ds/core source
|
|
87
|
+
* - optimizeDeps.exclude to prevent Vite pre-bundling Pharos
|
|
88
|
+
*
|
|
89
|
+
* @param options — optional overrides
|
|
90
|
+
*/
|
|
91
|
+
export declare function pharosStylex(options?: PharosVitePluginOptions | PharosVitePluginLegacyOptions): Plugin[];
|
package/dist/vite.mjs
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
// Built from src/vite.ts — do not edit directly
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// src/vite.ts
|
|
10
|
+
import stylexBabelPlugin from "@stylexjs/babel-plugin";
|
|
11
|
+
import stylex from "@stylexjs/unplugin";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
var LIBRARY_PATTERN = "node_modules/@pharos-ds/";
|
|
16
|
+
var STYLEX_CSS_PATH = "/virtual:stylex.css";
|
|
17
|
+
var LIGHTNINGCSS_TARGETS = {
|
|
18
|
+
chrome: 123 << 16,
|
|
19
|
+
firefox: 120 << 16,
|
|
20
|
+
safari: 17 << 16 | 5 << 8
|
|
21
|
+
};
|
|
22
|
+
function pharosStylex(options = {}) {
|
|
23
|
+
if ("stylexOptions" in options && options.stylexOptions) {
|
|
24
|
+
return pharosStylexLegacy(options);
|
|
25
|
+
}
|
|
26
|
+
const opts = options;
|
|
27
|
+
const {
|
|
28
|
+
dev = process.env.NODE_ENV !== "production",
|
|
29
|
+
rootDir = process.cwd(),
|
|
30
|
+
libraryPattern = LIBRARY_PATTERN,
|
|
31
|
+
layers = {},
|
|
32
|
+
lightningcssTargets,
|
|
33
|
+
stylexPrefix = "pharos",
|
|
34
|
+
stylexOverrides = {}
|
|
35
|
+
} = opts;
|
|
36
|
+
const libraryLayer = layers.library ?? "pharos-base";
|
|
37
|
+
const productLayer = layers.product ?? "product";
|
|
38
|
+
const stylexOptions = {
|
|
39
|
+
dev,
|
|
40
|
+
runtimeInjection: false,
|
|
41
|
+
treeshakeCompensation: true,
|
|
42
|
+
unstable_moduleResolution: {
|
|
43
|
+
type: "commonJS",
|
|
44
|
+
rootDir
|
|
45
|
+
},
|
|
46
|
+
...lightningcssTargets && {
|
|
47
|
+
lightningcssOptions: { targets: lightningcssTargets }
|
|
48
|
+
},
|
|
49
|
+
...stylexOverrides
|
|
50
|
+
};
|
|
51
|
+
const pharosBabelPlugin = path.resolve(__dirname, "../src/babel.js");
|
|
52
|
+
const basePlugin = stylex.vite({
|
|
53
|
+
...stylexOptions,
|
|
54
|
+
useCSSLayers: true,
|
|
55
|
+
babelConfig: {
|
|
56
|
+
plugins: [
|
|
57
|
+
[
|
|
58
|
+
pharosBabelPlugin,
|
|
59
|
+
{
|
|
60
|
+
...stylexOptions,
|
|
61
|
+
libraryPrefix: stylexPrefix,
|
|
62
|
+
babelConfig: void 0
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const layerOrderPlugin = {
|
|
69
|
+
name: "pharos-css-layer-order",
|
|
70
|
+
transformIndexHtml() {
|
|
71
|
+
return [
|
|
72
|
+
{
|
|
73
|
+
tag: "style",
|
|
74
|
+
children: `@layer reset, ${libraryLayer}, pharos-theme, ${productLayer};`,
|
|
75
|
+
injectTo: "head-prepend"
|
|
76
|
+
}
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const configPlugin = {
|
|
81
|
+
name: "pharos-config",
|
|
82
|
+
config() {
|
|
83
|
+
let xdsPackages = ["@pharos-ds/core"];
|
|
84
|
+
try {
|
|
85
|
+
const fs = __require("node:fs");
|
|
86
|
+
const xdsDir = path.resolve(rootDir, "node_modules/@pharos-ds");
|
|
87
|
+
if (fs.existsSync(xdsDir)) {
|
|
88
|
+
xdsPackages = fs.readdirSync(xdsDir).filter((name) => !name.startsWith(".")).map((name) => `@pharos-ds/${name}`);
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
resolve: {
|
|
94
|
+
alias: {
|
|
95
|
+
"@pharos-ds/core/theme/tokens.stylex": path.resolve(
|
|
96
|
+
rootDir,
|
|
97
|
+
"node_modules/@pharos-ds/core/src/theme/tokens.stylex.ts"
|
|
98
|
+
),
|
|
99
|
+
"@pharos-ds/core": path.resolve(
|
|
100
|
+
rootDir,
|
|
101
|
+
"node_modules/@pharos-ds/core/src"
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
optimizeDeps: {
|
|
106
|
+
exclude: xdsPackages
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const splitLayerPlugin = {
|
|
112
|
+
name: "pharos-split-layers",
|
|
113
|
+
configureServer(server) {
|
|
114
|
+
let stylexPlugin = null;
|
|
115
|
+
return () => {
|
|
116
|
+
for (const p of server.config.plugins.flat()) {
|
|
117
|
+
if (p?.__stylexGetSharedStore) {
|
|
118
|
+
stylexPlugin = p;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
server.middlewares.stack.unshift({
|
|
123
|
+
route: "",
|
|
124
|
+
handle: (req, res, next) => {
|
|
125
|
+
if (!req.url?.startsWith(STYLEX_CSS_PATH)) {
|
|
126
|
+
return next();
|
|
127
|
+
}
|
|
128
|
+
if (!stylexPlugin) {
|
|
129
|
+
res.statusCode = 200;
|
|
130
|
+
res.setHeader("Content-Type", "text/css");
|
|
131
|
+
res.end("");
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const shared = stylexPlugin.__stylexGetSharedStore?.();
|
|
135
|
+
const rulesById = shared?.rulesById;
|
|
136
|
+
if (!rulesById || rulesById.size === 0) {
|
|
137
|
+
res.statusCode = 200;
|
|
138
|
+
res.setHeader("Content-Type", "text/css");
|
|
139
|
+
res.end("");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const libraryRules = [];
|
|
143
|
+
const productRules = [];
|
|
144
|
+
for (const [filePath, rules] of rulesById.entries()) {
|
|
145
|
+
if (filePath.includes(libraryPattern)) {
|
|
146
|
+
libraryRules.push(...rules);
|
|
147
|
+
} else {
|
|
148
|
+
productRules.push(...rules);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const libraryCss = libraryRules.length ? stylexBabelPlugin.processStylexRules(libraryRules, {
|
|
152
|
+
useLayers: true
|
|
153
|
+
}) : "";
|
|
154
|
+
const productCss = productRules.length ? stylexBabelPlugin.processStylexRules(productRules, {
|
|
155
|
+
useLayers: true
|
|
156
|
+
}) : "";
|
|
157
|
+
const parts = [];
|
|
158
|
+
if (libraryCss)
|
|
159
|
+
parts.push(`@layer ${libraryLayer} {
|
|
160
|
+
${libraryCss}
|
|
161
|
+
}`);
|
|
162
|
+
if (productCss)
|
|
163
|
+
parts.push(`@layer ${productLayer} {
|
|
164
|
+
${productCss}
|
|
165
|
+
}`);
|
|
166
|
+
res.statusCode = 200;
|
|
167
|
+
res.setHeader("Content-Type", "text/css");
|
|
168
|
+
res.setHeader("Cache-Control", "no-store");
|
|
169
|
+
res.end(parts.join("\n\n"));
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
return [configPlugin, layerOrderPlugin, basePlugin, splitLayerPlugin];
|
|
176
|
+
}
|
|
177
|
+
function pharosStylexLegacy(options) {
|
|
178
|
+
const {
|
|
179
|
+
stylexOptions,
|
|
180
|
+
libraryPattern = LIBRARY_PATTERN,
|
|
181
|
+
stylexPrefix = "pharos",
|
|
182
|
+
layers = {}
|
|
183
|
+
} = options;
|
|
184
|
+
const libraryLayer = layers.library ?? "pharos-base";
|
|
185
|
+
const productLayer = layers.product ?? "product";
|
|
186
|
+
const pharosBabelPlugin = path.resolve(__dirname, "../src/babel.js");
|
|
187
|
+
const existingPlugins = stylexOptions.babelConfig?.plugins ?? [];
|
|
188
|
+
const basePlugin = stylex.vite({
|
|
189
|
+
...stylexOptions,
|
|
190
|
+
useCSSLayers: true,
|
|
191
|
+
babelConfig: {
|
|
192
|
+
...stylexOptions.babelConfig,
|
|
193
|
+
plugins: [
|
|
194
|
+
[
|
|
195
|
+
pharosBabelPlugin,
|
|
196
|
+
{
|
|
197
|
+
...stylexOptions,
|
|
198
|
+
libraryPrefix: stylexPrefix,
|
|
199
|
+
babelConfig: void 0
|
|
200
|
+
}
|
|
201
|
+
],
|
|
202
|
+
...existingPlugins
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
const layerOrderPlugin = {
|
|
207
|
+
name: "pharos-css-layer-order",
|
|
208
|
+
transformIndexHtml() {
|
|
209
|
+
return [
|
|
210
|
+
{
|
|
211
|
+
tag: "style",
|
|
212
|
+
children: `@layer reset, ${libraryLayer}, pharos-theme, ${productLayer};`,
|
|
213
|
+
injectTo: "head-prepend"
|
|
214
|
+
}
|
|
215
|
+
];
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const splitLayerPlugin = {
|
|
219
|
+
name: "pharos-split-layers",
|
|
220
|
+
configureServer(server) {
|
|
221
|
+
let stylexPlugin = null;
|
|
222
|
+
return () => {
|
|
223
|
+
for (const p of server.config.plugins.flat()) {
|
|
224
|
+
if (p?.__stylexGetSharedStore) {
|
|
225
|
+
stylexPlugin = p;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
server.middlewares.stack.unshift({
|
|
230
|
+
route: "",
|
|
231
|
+
handle: (req, res, next) => {
|
|
232
|
+
if (!req.url?.startsWith(STYLEX_CSS_PATH)) {
|
|
233
|
+
return next();
|
|
234
|
+
}
|
|
235
|
+
if (!stylexPlugin) {
|
|
236
|
+
res.statusCode = 200;
|
|
237
|
+
res.setHeader("Content-Type", "text/css");
|
|
238
|
+
res.end("");
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
const shared = stylexPlugin.__stylexGetSharedStore?.();
|
|
242
|
+
const rulesById = shared?.rulesById;
|
|
243
|
+
if (!rulesById || rulesById.size === 0) {
|
|
244
|
+
res.statusCode = 200;
|
|
245
|
+
res.setHeader("Content-Type", "text/css");
|
|
246
|
+
res.end("");
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const libraryRules = [];
|
|
250
|
+
const productRules = [];
|
|
251
|
+
for (const [filePath, rules] of rulesById.entries()) {
|
|
252
|
+
if (filePath.includes(libraryPattern)) {
|
|
253
|
+
libraryRules.push(...rules);
|
|
254
|
+
} else {
|
|
255
|
+
productRules.push(...rules);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const libraryCss = libraryRules.length ? stylexBabelPlugin.processStylexRules(libraryRules, {
|
|
259
|
+
useLayers: true
|
|
260
|
+
}) : "";
|
|
261
|
+
const productCss = productRules.length ? stylexBabelPlugin.processStylexRules(productRules, {
|
|
262
|
+
useLayers: true
|
|
263
|
+
}) : "";
|
|
264
|
+
const parts = [];
|
|
265
|
+
if (libraryCss)
|
|
266
|
+
parts.push(`@layer ${libraryLayer} {
|
|
267
|
+
${libraryCss}
|
|
268
|
+
}`);
|
|
269
|
+
if (productCss)
|
|
270
|
+
parts.push(`@layer ${productLayer} {
|
|
271
|
+
${productCss}
|
|
272
|
+
}`);
|
|
273
|
+
res.statusCode = 200;
|
|
274
|
+
res.setHeader("Content-Type", "text/css");
|
|
275
|
+
res.setHeader("Cache-Control", "no-store");
|
|
276
|
+
res.end(parts.join("\n\n"));
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
};
|
|
282
|
+
return [layerOrderPlugin, basePlugin, splitLayerPlugin];
|
|
283
|
+
}
|
|
284
|
+
export {
|
|
285
|
+
LIGHTNINGCSS_TARGETS,
|
|
286
|
+
pharosStylex
|
|
287
|
+
};
|