@scalepad/ui 0.2.0 → 0.2.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/README.md +40 -2
- package/package.json +1 -1
- package/scripts/verify-consumption.mjs +36 -3
- package/src/components/Anchor/Anchor.css.ts +1 -1
- package/src/components/ColorInput/ColorInput.figma.tsx +32 -0
- package/src/components/ColorInput/ColorInput.tsx +94 -0
- package/src/components/ColorInput/index.ts +6 -0
- package/src/components/Select/Select.css.ts +8 -3
- package/src/components/Select/Select.tsx +11 -1
- package/src/index.ts +6 -0
- package/src/tokens/index.ts +6 -2
- package/src/tokens/text-styles.ts +31 -2
- package/src/vite.js +50 -9
package/README.md
CHANGED
|
@@ -119,10 +119,11 @@ export default defineConfig({
|
|
|
119
119
|
});
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
-
The preset wires up
|
|
122
|
+
The preset wires up three things consumers commonly miss:
|
|
123
123
|
|
|
124
124
|
1. The vanilla-extract Vite plugin (`@vanilla-extract/vite-plugin`), so every `.css.ts` file inside `node_modules/@scalepad/ui` is compiled at build time.
|
|
125
125
|
2. `optimizeDeps.exclude: ['@scalepad/ui']` + `optimizeDeps.include: ['@mantine/dates', '@mantine/schedule', '@tiptap/react', 'dayjs', 'fast-deep-equal', 'prop-types']`, which together let Vite's esbuild pre-bundling step succeed (it can't ingest `.css.ts` files on its own) and ensure the transitive CommonJS deps reached through the excluded package still get pre-bundled.
|
|
126
|
+
3. A narrowly-scoped Rollup `onLog` filter that drops the noisy `"default" is not exported by …/rrule/dist/esm/index.js` warning (also seen as `[IMPORT_IS_UNDEFINED] Import 'default' will always be undefined …` on older Rollup versions) emitted from `@mantine/schedule`'s `rrule` import. The warning is a static-analysis false positive — Mantine's source explicitly handles both module shapes (`"default" in rruleAll ? rruleAll.default.RRule : rruleAll.RRule`), so the dead branch is tree-shaken away at runtime. The filter is scoped to (importer is `@mantine/schedule` + message mentions `rrule`); other missing-export warnings still surface.
|
|
126
127
|
|
|
127
128
|
You can extend the include list or pass options through to the vanilla-extract plugin:
|
|
128
129
|
|
|
@@ -149,7 +150,27 @@ import react from '@vitejs/plugin-react';
|
|
|
149
150
|
import { defineConfig } from 'vite';
|
|
150
151
|
|
|
151
152
|
export default defineConfig({
|
|
152
|
-
plugins: [
|
|
153
|
+
plugins: [
|
|
154
|
+
react(),
|
|
155
|
+
vanillaExtractPlugin(),
|
|
156
|
+
{
|
|
157
|
+
// See README troubleshooting → "IMPORT_IS_UNDEFINED warning from rrule".
|
|
158
|
+
// Mantine's import is defensive; the flagged branch is dead code under
|
|
159
|
+
// rrule's ESM build, so the warning is safe to drop. Match on importer
|
|
160
|
+
// + message (not on `log.code`) because Rollup emits this under both
|
|
161
|
+
// `MISSING_EXPORT` and `IMPORT_IS_UNDEFINED` in different versions.
|
|
162
|
+
name: 'suppress-mantine-schedule-rrule-warning',
|
|
163
|
+
onLog(level, log) {
|
|
164
|
+
if (
|
|
165
|
+
level === 'warn' &&
|
|
166
|
+
(log.id ?? '').includes('@mantine/schedule') &&
|
|
167
|
+
/\brrule\b/.test(log.message ?? '')
|
|
168
|
+
) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
],
|
|
153
174
|
optimizeDeps: {
|
|
154
175
|
exclude: ['@scalepad/ui'],
|
|
155
176
|
include: [
|
|
@@ -272,6 +293,23 @@ The vanilla-extract Vite plugin isn't wired up, or the package is being pre-bund
|
|
|
272
293
|
- Use the preset: `import { scalepadUi } from '@scalepad/ui/vite'`, OR
|
|
273
294
|
- If wiring manually, make sure your `vite.config.ts` has BOTH `vanillaExtractPlugin()` in `plugins` AND `optimizeDeps.exclude: ['@scalepad/ui']`. Missing either one will fail.
|
|
274
295
|
|
|
296
|
+
### `[IMPORT_IS_UNDEFINED] Import 'default' will always be undefined because there is no matching export in 'node_modules/rrule/dist/esm/index.js'`
|
|
297
|
+
|
|
298
|
+
`@mantine/schedule` reads `rruleAll.default.RRule`, but `rrule@2.x` only has a `default` export on its CJS build (`dist/es5/rrule.js`), not its ESM build (`dist/esm/index.js`). Vite resolves `rrule` via its `module` field, so the static-analysis warning fires on every build — even when the scheduler is never imported.
|
|
299
|
+
|
|
300
|
+
The warning is a false positive. Mantine's source is explicitly defensive about both module shapes:
|
|
301
|
+
|
|
302
|
+
```js
|
|
303
|
+
const RRule = "default" in rruleAll ? rruleAll.default.RRule : rruleAll.RRule;
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Under the ESM build, `"default" in rruleAll` is `false`, the `.default.RRule` branch is dead code, Rollup tree-shakes it away, and only `rruleAll.RRule` runs at runtime — which resolves correctly. Nothing breaks; the message is just noise.
|
|
307
|
+
|
|
308
|
+
Either:
|
|
309
|
+
|
|
310
|
+
- Use the preset (it adds a narrowly-scoped Rollup `onLog` filter for exactly this warning), OR
|
|
311
|
+
- If wiring manually, add the same filter — see the small `suppress-mantine-schedule-rrule-warning` plugin in the manual-setup snippet above.
|
|
312
|
+
|
|
275
313
|
### `The requested module '…@mantine/dates' does not provide an export named '…'` (or similar from `@tiptap/react`, `dayjs`, `prop-types`)
|
|
276
314
|
|
|
277
315
|
These are CommonJS-or-mixed-module deps that Vite's dep scanner can't walk through once `@scalepad/ui` is excluded from pre-bundling. Either:
|
package/package.json
CHANGED
|
@@ -52,6 +52,22 @@ function run(cmd, args, opts = {}) {
|
|
|
52
52
|
return result;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
function runCapture(cmd, args, opts = {}) {
|
|
56
|
+
const display = `${cmd} ${args.join(' ')}`;
|
|
57
|
+
log(`$ ${display} (cwd=${opts.cwd ?? process.cwd()})`);
|
|
58
|
+
const result = spawnSync(cmd, args, {
|
|
59
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
60
|
+
encoding: 'utf8',
|
|
61
|
+
...opts,
|
|
62
|
+
});
|
|
63
|
+
process.stdout.write(result.stdout ?? '');
|
|
64
|
+
process.stderr.write(result.stderr ?? '');
|
|
65
|
+
if (result.status !== 0) {
|
|
66
|
+
die(`${display} exited with status ${result.status}`);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
55
71
|
function findTarball(dir, prefix) {
|
|
56
72
|
const matches = readdirSync(dir).filter(
|
|
57
73
|
(f) => f.startsWith(prefix) && f.endsWith('.tgz'),
|
|
@@ -234,9 +250,26 @@ run('npm', ['install', '--no-audit', '--no-fund', '--legacy-peer-deps=false'], {
|
|
|
234
250
|
cwd: projectDir,
|
|
235
251
|
});
|
|
236
252
|
|
|
237
|
-
// 5. Build.
|
|
253
|
+
// 5. Build. Capture output so we can assert no known-problematic Vite warnings
|
|
254
|
+
// snuck back in (they don't fail the build by default, so a plain run won't
|
|
255
|
+
// catch a regression).
|
|
238
256
|
log('building...');
|
|
239
|
-
|
|
257
|
+
const buildResult = runCapture('npx', ['vite', 'build'], { cwd: projectDir });
|
|
258
|
+
const buildOutput = `${buildResult.stdout ?? ''}\n${buildResult.stderr ?? ''}`;
|
|
259
|
+
|
|
260
|
+
// Regression guard for the rrule / @mantine/schedule warning. The
|
|
261
|
+
// `scalepadUi()` preset aliases `rrule` to its CJS UMD entry so this warning
|
|
262
|
+
// shouldn't appear. See README → Troubleshooting → IMPORT_IS_UNDEFINED.
|
|
263
|
+
if (
|
|
264
|
+
buildOutput.includes('IMPORT_IS_UNDEFINED') ||
|
|
265
|
+
/node_modules\/rrule\/dist\/esm\/index\.js/.test(buildOutput)
|
|
266
|
+
) {
|
|
267
|
+
die(
|
|
268
|
+
'detected rrule IMPORT_IS_UNDEFINED warning in build output — the ' +
|
|
269
|
+
'scalepadUi() preset should be aliasing rrule to rrule/dist/es5/rrule.js. ' +
|
|
270
|
+
'See packages/ui/src/vite.js.',
|
|
271
|
+
);
|
|
272
|
+
}
|
|
240
273
|
|
|
241
|
-
log('OK — built successfully.');
|
|
274
|
+
log('OK — built successfully (no known-problematic warnings).');
|
|
242
275
|
log(`(temp project left at ${projectDir} for inspection; delete when done)`);
|
|
@@ -53,7 +53,7 @@ export const root = style({
|
|
|
53
53
|
* drift.
|
|
54
54
|
*/
|
|
55
55
|
export const variant = styleVariants(textStyleVariants, styles => ({
|
|
56
|
-
fontFamily: styles.fontFamily,
|
|
56
|
+
...(styles.fontFamily != null && { fontFamily: styles.fontFamily }),
|
|
57
57
|
fontWeight: styles.fontWeight,
|
|
58
58
|
fontSize: styles.fontSize,
|
|
59
59
|
lineHeight: styles.lineHeight,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
|
|
3
|
+
import { ColorInput } from './ColorInput';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Code Connect mapping for the LM Design System `ColorInput` (node 4265:237).
|
|
7
|
+
*
|
|
8
|
+
* The Figma component_set has `Size` (Small / Regular / Large) and `State`
|
|
9
|
+
* (Empty / Value / Focus / Error / Error Focus / Disabled) axes. We
|
|
10
|
+
* intentionally don't map the size axis: in code the component follows the
|
|
11
|
+
* `TextInput` chrome (single default size, overridable via `size`), and
|
|
12
|
+
* Figma will be re-aligned to match later. Only the boolean-ish state axes
|
|
13
|
+
* map cleanly today (`disabled`, `error`).
|
|
14
|
+
*/
|
|
15
|
+
figma.connect(
|
|
16
|
+
ColorInput,
|
|
17
|
+
'https://www.figma.com/design/VCLfybgU3OaUUPrQdBaVmP/LM-Design-System?node-id=4265%3A237',
|
|
18
|
+
{
|
|
19
|
+
props: {
|
|
20
|
+
disabled: figma.enum('State', {
|
|
21
|
+
Disabled: true,
|
|
22
|
+
}),
|
|
23
|
+
error: figma.enum('State', {
|
|
24
|
+
Error: 'Invalid color',
|
|
25
|
+
'Error Focus': 'Invalid color',
|
|
26
|
+
}),
|
|
27
|
+
},
|
|
28
|
+
example: props => (
|
|
29
|
+
<ColorInput disabled={props.disabled} error={props.error} />
|
|
30
|
+
),
|
|
31
|
+
},
|
|
32
|
+
);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ColorInput component
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper around Mantine's `ColorInput` that mirrors the conventions of
|
|
5
|
+
* our `TextInput` wrapper (`size='sm'`, `radius='lg'`, `format='hex'`) and
|
|
6
|
+
* pre-loads the swatch grid with `AVATAR_PALETTE` — the 50-color list
|
|
7
|
+
* `@scalepad/ui` already uses for identity chips. Reusing the same palette
|
|
8
|
+
* here keeps every "pick a color" surface in the app consistent without
|
|
9
|
+
* making consumers wire `swatches` themselves.
|
|
10
|
+
*
|
|
11
|
+
* Visual chrome (height, padding, radius, focus ring, error state, disabled
|
|
12
|
+
* state) intentionally follows `TextInput` rather than the standalone Figma
|
|
13
|
+
* ColorInput frame. Figma will be aligned later.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <ColorInput
|
|
18
|
+
* label="Brand color"
|
|
19
|
+
* value={color}
|
|
20
|
+
* onChange={setColor}
|
|
21
|
+
* />
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @example Custom swatches
|
|
25
|
+
* ```tsx
|
|
26
|
+
* <ColorInput
|
|
27
|
+
* swatches={['#ff0000', '#00ff00', '#0000ff']}
|
|
28
|
+
* swatchesPerRow={3}
|
|
29
|
+
* />
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { forwardRef, useMemo } from 'react';
|
|
34
|
+
|
|
35
|
+
import {
|
|
36
|
+
ColorInput as MantineColorInput,
|
|
37
|
+
type ColorInputProps as MantineColorInputProps,
|
|
38
|
+
} from '@mantine/core';
|
|
39
|
+
|
|
40
|
+
import { AVATAR_PALETTE } from '../../utils/avatar';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Default swatch grid for `ColorInput`. Mirrors `AVATAR_PALETTE` and is
|
|
44
|
+
* exported so consumers can compose it with extra brand-specific swatches
|
|
45
|
+
* (`swatches={[...DEFAULT_COLOR_INPUT_SWATCHES, '#abc123']}`).
|
|
46
|
+
*/
|
|
47
|
+
export const DEFAULT_COLOR_INPUT_SWATCHES: readonly string[] = AVATAR_PALETTE;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Default number of swatches per row. 10 columns × 5 rows fits the 50-entry
|
|
51
|
+
* `AVATAR_PALETTE` cleanly without forcing the popover wider than the input.
|
|
52
|
+
*/
|
|
53
|
+
export const DEFAULT_COLOR_INPUT_SWATCHES_PER_ROW = 10;
|
|
54
|
+
|
|
55
|
+
export interface ColorInputProps extends MantineColorInputProps {}
|
|
56
|
+
|
|
57
|
+
export const ColorInput = forwardRef<HTMLInputElement, ColorInputProps>(
|
|
58
|
+
(
|
|
59
|
+
{
|
|
60
|
+
className,
|
|
61
|
+
size = 'sm',
|
|
62
|
+
radius = 'lg',
|
|
63
|
+
format = 'hex',
|
|
64
|
+
swatches,
|
|
65
|
+
swatchesPerRow = DEFAULT_COLOR_INPUT_SWATCHES_PER_ROW,
|
|
66
|
+
...props
|
|
67
|
+
},
|
|
68
|
+
ref,
|
|
69
|
+
) => {
|
|
70
|
+
// `swatches` is mutated by Mantine internals in some flows, so feed it a
|
|
71
|
+
// fresh array (not the frozen palette constant) when defaulting.
|
|
72
|
+
const resolvedSwatches = useMemo(
|
|
73
|
+
() => swatches ?? [...DEFAULT_COLOR_INPUT_SWATCHES],
|
|
74
|
+
[swatches],
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<MantineColorInput
|
|
79
|
+
ref={ref}
|
|
80
|
+
size={size}
|
|
81
|
+
radius={radius}
|
|
82
|
+
format={format}
|
|
83
|
+
swatches={resolvedSwatches}
|
|
84
|
+
swatchesPerRow={swatchesPerRow}
|
|
85
|
+
classNames={{
|
|
86
|
+
input: className,
|
|
87
|
+
}}
|
|
88
|
+
{...props}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
ColorInput.displayName = 'ColorInput';
|
|
@@ -36,13 +36,18 @@ export const selectButton = style({
|
|
|
36
36
|
overflow: 'hidden',
|
|
37
37
|
transition: 'border-color 0.15s ease',
|
|
38
38
|
selectors: {
|
|
39
|
-
'&:hover': {
|
|
39
|
+
'&:hover:not(:disabled)': {
|
|
40
40
|
borderColor: tokens.color.stroke.subduedStrong,
|
|
41
41
|
},
|
|
42
|
-
'&:focus': focusRing,
|
|
43
|
-
'&:active': {
|
|
42
|
+
'&:focus:not(:disabled)': focusRing,
|
|
43
|
+
'&:active:not(:disabled)': {
|
|
44
44
|
borderColor: tokens.color.stroke.strong,
|
|
45
45
|
},
|
|
46
|
+
'&:disabled': {
|
|
47
|
+
cursor: 'not-allowed',
|
|
48
|
+
opacity: 0.6,
|
|
49
|
+
backgroundColor: tokens.color.background.disabledDefault,
|
|
50
|
+
},
|
|
46
51
|
[`${mantineVars.darkSelector} &`]: {
|
|
47
52
|
borderColor: tokens.color.stroke.default,
|
|
48
53
|
backgroundColor: tokens.color.background.default,
|
|
@@ -35,6 +35,11 @@ export interface SelectProps {
|
|
|
35
35
|
* Validation error message displayed below the select
|
|
36
36
|
*/
|
|
37
37
|
error?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Disable the select trigger. When disabled, the dropdown cannot be opened
|
|
40
|
+
* and the button is excluded from the focus order.
|
|
41
|
+
*/
|
|
42
|
+
disabled?: boolean;
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
/**
|
|
@@ -55,7 +60,10 @@ export interface SelectProps {
|
|
|
55
60
|
* ```
|
|
56
61
|
*/
|
|
57
62
|
export const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|
58
|
-
(
|
|
63
|
+
(
|
|
64
|
+
{ labelPrefix, data, value, onChange, placeholder, w, error, disabled },
|
|
65
|
+
ref,
|
|
66
|
+
) => {
|
|
59
67
|
const id = useId();
|
|
60
68
|
const errorId = error ? `${id}-error` : undefined;
|
|
61
69
|
const combobox = useCombobox({
|
|
@@ -88,11 +96,13 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|
|
88
96
|
<button
|
|
89
97
|
ref={ref}
|
|
90
98
|
type="button"
|
|
99
|
+
disabled={disabled}
|
|
91
100
|
className={styles.selectButton}
|
|
92
101
|
onClick={() => combobox.toggleDropdown()}
|
|
93
102
|
aria-haspopup="listbox"
|
|
94
103
|
aria-expanded={combobox.dropdownOpened}
|
|
95
104
|
aria-invalid={!!error}
|
|
105
|
+
aria-disabled={disabled || undefined}
|
|
96
106
|
aria-describedby={errorId}
|
|
97
107
|
style={
|
|
98
108
|
w ? { width: typeof w === 'number' ? `${w}px` : w } : undefined
|
package/src/index.ts
CHANGED
|
@@ -287,6 +287,12 @@ export type {
|
|
|
287
287
|
export type { JSONContent } from '@tiptap/react';
|
|
288
288
|
|
|
289
289
|
// Input components with Figma design specifications
|
|
290
|
+
export {
|
|
291
|
+
ColorInput,
|
|
292
|
+
DEFAULT_COLOR_INPUT_SWATCHES,
|
|
293
|
+
DEFAULT_COLOR_INPUT_SWATCHES_PER_ROW,
|
|
294
|
+
} from './components/ColorInput';
|
|
295
|
+
export type { ColorInputProps } from './components/ColorInput';
|
|
290
296
|
export { CommentComposer } from './components/CommentComposer';
|
|
291
297
|
export type { CommentComposerProps } from './components/CommentComposer';
|
|
292
298
|
export { MultiSelect } from './components/MultiSelect';
|
package/src/tokens/index.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Design tokens that mirror the LM Design System Figma file
|
|
3
|
+
* (https://www.figma.com/design/VCLfybgU3OaUUPrQdBaVmP/LM-Design-System).
|
|
4
|
+
*
|
|
5
|
+
* Source of truth lives in Figma; edit these files by hand to mirror Figma
|
|
6
|
+
* changes and use the Figma MCP (`get_design_context`, `search_design_system`)
|
|
7
|
+
* to fetch authoritative values.
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
10
|
export * from './colors';
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Text-style variants synced from the LM Design System Figma file
|
|
3
|
+
* (https://www.figma.com/design/VCLfybgU3OaUUPrQdBaVmP/LM-Design-System).
|
|
4
|
+
*
|
|
5
|
+
* Source of truth lives in Figma; edit this file by hand to mirror Figma
|
|
6
|
+
* changes. The Figma MCP is the canonical way to fetch the latest values —
|
|
7
|
+
* use `get_design_context` on the relevant text-style node before changing
|
|
8
|
+
* sizes / weights / line-heights / letter-spacing.
|
|
4
9
|
*/
|
|
5
10
|
|
|
6
11
|
import { rem } from '@mantine/core';
|
|
@@ -73,6 +78,27 @@ export const textStyleVariants = {
|
|
|
73
78
|
lineHeight: rem('21px'),
|
|
74
79
|
letterSpacing: 0,
|
|
75
80
|
},
|
|
81
|
+
body2: {
|
|
82
|
+
fontFamily: undefined,
|
|
83
|
+
fontWeight: 400,
|
|
84
|
+
fontSize: rem('16px'),
|
|
85
|
+
lineHeight: rem('23px'),
|
|
86
|
+
letterSpacing: 0,
|
|
87
|
+
},
|
|
88
|
+
'body2.strong': {
|
|
89
|
+
fontFamily: undefined,
|
|
90
|
+
fontWeight: 500,
|
|
91
|
+
fontSize: rem('16px'),
|
|
92
|
+
lineHeight: rem('23px'),
|
|
93
|
+
letterSpacing: 0,
|
|
94
|
+
},
|
|
95
|
+
'body2.stronger': {
|
|
96
|
+
fontFamily: undefined,
|
|
97
|
+
fontWeight: 600,
|
|
98
|
+
fontSize: rem('16px'),
|
|
99
|
+
lineHeight: rem('23px'),
|
|
100
|
+
letterSpacing: 0,
|
|
101
|
+
},
|
|
76
102
|
caption1: {
|
|
77
103
|
fontFamily: undefined,
|
|
78
104
|
fontWeight: 400,
|
|
@@ -166,6 +192,9 @@ export type BodyVariant =
|
|
|
166
192
|
| 'body1'
|
|
167
193
|
| 'body1.strong'
|
|
168
194
|
| 'body1.stronger'
|
|
195
|
+
| 'body2'
|
|
196
|
+
| 'body2.strong'
|
|
197
|
+
| 'body2.stronger'
|
|
169
198
|
| 'caption1'
|
|
170
199
|
| 'caption1.strong'
|
|
171
200
|
| 'caption1.stronger'
|
package/src/vite.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vite preset for `@scalepad/ui`.
|
|
3
3
|
*
|
|
4
|
-
* @scalepad/ui ships as TypeScript + vanilla-extract source.
|
|
4
|
+
* @scalepad/ui ships as TypeScript + vanilla-extract source. Three things must
|
|
5
5
|
* be wired into a consumer's Vite config for it to load cleanly:
|
|
6
6
|
*
|
|
7
7
|
* 1. The vanilla-extract Vite plugin, so every `.css.ts` file the package
|
|
@@ -14,8 +14,24 @@
|
|
|
14
14
|
* - `include: [...]` for the CommonJS transitive deps Vite's scanner
|
|
15
15
|
* stops walking through once the package is excluded from
|
|
16
16
|
* pre-bundling.
|
|
17
|
+
* 3. A narrowly-scoped Rollup `onLog` filter that suppresses the
|
|
18
|
+
* `MISSING_EXPORT` / `IMPORT_IS_UNDEFINED` warning emitted from
|
|
19
|
+
* `@mantine/schedule`'s `rrule` import (Rollup uses the former in
|
|
20
|
+
* current versions and the latter in older ones for the same root
|
|
21
|
+
* cause). The warning is a static-analysis false positive: the Mantine
|
|
22
|
+
* source does
|
|
17
23
|
*
|
|
18
|
-
*
|
|
24
|
+
* const RRule = "default" in rruleAll ? rruleAll.default.RRule : rruleAll.RRule;
|
|
25
|
+
*
|
|
26
|
+
* which is explicitly defensive about both module shapes. Under rrule's
|
|
27
|
+
* ESM build the `default` branch is dead code (Rollup tree-shakes it
|
|
28
|
+
* away); only `rruleAll.RRule` runs and it resolves correctly. Rollup
|
|
29
|
+
* still flags the dead branch at scan time, producing a noisy warning on
|
|
30
|
+
* every build. The filter is scoped to (importer is `@mantine/schedule`
|
|
31
|
+
* + message mentions `rrule`) so unrelated missing-export / undefined-
|
|
32
|
+
* import warnings still surface.
|
|
33
|
+
*
|
|
34
|
+
* This preset wraps all three into a single plugin so consumers can do:
|
|
19
35
|
*
|
|
20
36
|
* import { scalepadUi } from '@scalepad/ui/vite';
|
|
21
37
|
*
|
|
@@ -53,14 +69,30 @@ export const SCALEPAD_UI_OPTIMIZE_DEPS_INCLUDE = Object.freeze([
|
|
|
53
69
|
'prop-types',
|
|
54
70
|
]);
|
|
55
71
|
|
|
72
|
+
/**
|
|
73
|
+
* True iff `log` is the known-noisy rrule / @mantine/schedule warning
|
|
74
|
+
* described in the file header. Rollup emits this under more than one code
|
|
75
|
+
* depending on which static-analysis pass catches it first — `MISSING_EXPORT`
|
|
76
|
+
* ("default" is not exported by …) and `IMPORT_IS_UNDEFINED` (Import
|
|
77
|
+
* `default` will always be undefined …) are both seen in the wild for the
|
|
78
|
+
* exact same import. We match by (importer is @mantine/schedule + message
|
|
79
|
+
* mentions rrule), which is tight enough that unrelated missing-export
|
|
80
|
+
* warnings still surface but loose enough to survive Rollup version drift.
|
|
81
|
+
*/
|
|
82
|
+
function isRruleScheduleDeadBranchWarning(log) {
|
|
83
|
+
if (!log) return false;
|
|
84
|
+
const importer = log.id ?? log.loc?.file ?? '';
|
|
85
|
+
const message = log.message ?? '';
|
|
86
|
+
return importer.includes('@mantine/schedule') && /\brrule\b/.test(message);
|
|
87
|
+
}
|
|
88
|
+
|
|
56
89
|
export function scalepadUi(options = {}) {
|
|
57
|
-
const includeFromOptions =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
];
|
|
90
|
+
const includeFromOptions = options.optimizeDepsIncludeOverride ?? [
|
|
91
|
+
...SCALEPAD_UI_OPTIMIZE_DEPS_INCLUDE,
|
|
92
|
+
...(options.optimizeDepsInclude ?? []),
|
|
93
|
+
];
|
|
62
94
|
|
|
63
|
-
const
|
|
95
|
+
const presetPlugin = {
|
|
64
96
|
name: '@scalepad/ui/vite-preset',
|
|
65
97
|
config: () => ({
|
|
66
98
|
optimizeDeps: {
|
|
@@ -68,12 +100,21 @@ export function scalepadUi(options = {}) {
|
|
|
68
100
|
include: includeFromOptions,
|
|
69
101
|
},
|
|
70
102
|
}),
|
|
103
|
+
// Rollup plugin hook (Rollup 4+, used by Vite 5+). Returning `false`
|
|
104
|
+
// suppresses the log without clobbering the consumer's own `onwarn` or
|
|
105
|
+
// any other plugin's `onLog` — Rollup chains every plugin's handler.
|
|
106
|
+
onLog(level, log) {
|
|
107
|
+
if (level === 'warn' && isRruleScheduleDeadBranchWarning(log)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
},
|
|
71
112
|
};
|
|
72
113
|
|
|
73
114
|
const veResult = vanillaExtractPlugin(options.vanillaExtract);
|
|
74
115
|
const vePlugins = Array.isArray(veResult) ? veResult : [veResult];
|
|
75
116
|
|
|
76
|
-
return [...vePlugins,
|
|
117
|
+
return [...vePlugins, presetPlugin];
|
|
77
118
|
}
|
|
78
119
|
|
|
79
120
|
export default scalepadUi;
|