@povio/ui 5.0.0-rc.1 → 5.0.0-rc.2
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/.rulesync/rules/ui-buttons-and-content.md +54 -0
- package/.rulesync/rules/ui-inputs-and-forms.md +62 -0
- package/.rulesync/rules/ui-overlays-navigation-and-styling.md +49 -0
- package/.rulesync/rules/ui-overview.md +33 -0
- package/README.md +4 -10
- package/package.json +8 -2
- package/rulesync.jsonc +11 -0
- package/scripts/generate-rules.mjs +34 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
targets: ["*"]
|
|
3
|
+
description: "@povio/ui buttons, labels, status feedback, and text-content APIs"
|
|
4
|
+
globs:
|
|
5
|
+
- "packages/ui/src/components/buttons/**/*"
|
|
6
|
+
- "packages/ui/src/components/text/**/*"
|
|
7
|
+
- "packages/ui/src/components/status/**/*"
|
|
8
|
+
- "packages/ui/src/components/shared/pagination/**/*"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Buttons, text, and status components
|
|
12
|
+
|
|
13
|
+
## Button
|
|
14
|
+
|
|
15
|
+
Use `Button` for an action. Its content is `children`; use `link` only when it navigates through the configured `LinkContext`.
|
|
16
|
+
|
|
17
|
+
- Visual variants: `contained`, `solid`, `outlined`, `outline`, `subtle`, `text`, `ghost`. The default CVA styles `solid` like `contained` and `outline` like `outlined`, but passes every value through unchanged so UI overrides can redefine either value.
|
|
18
|
+
- Colors: `primary`, `secondary`, `error` (destructive theme tokens), and Atlas-specific `dual`. Text buttons with `dual` use primary text and secondary icons. Only primary text buttons support `inverted`, using the primary foreground token.
|
|
19
|
+
- Sizes: `sm` (alias `s`), `default`, and `none` (zero padding); omit the size prop for `default`. Legacy sizes (`xs`, `small`, `m`, `md`, `l`, `lg`) are not supported.
|
|
20
|
+
- Use `fullWidth`; `width="fill"` and `width="hug"` remain valid.
|
|
21
|
+
- Use `loading` or `isLoading`; loading disables the button by default. `disableWhileLoading={false}` opts out; `noDisableWhenLoading` is the legacy inverse.
|
|
22
|
+
- Use `startIcon` and `endIcon`. `icon` plus `iconPosition="left" | "right"` remains supported.
|
|
23
|
+
- Use `IconButton` for icon-only actions and supply `ariaLabel` or `label`. `InlineIconButton` is the text-style icon-only variant.
|
|
24
|
+
- Use `ToggleButton` for one independently toggled state (`isSelected`, `defaultSelected`, `onChange`). It defaults to outlined primary but honors supplied `variant` and `color`.
|
|
25
|
+
- Use `SplitButton` only for a primary action with menu alternatives; use `ButtonGroup` for peer actions.
|
|
26
|
+
- `variant`, `size`, and other CVA props belong to the active override. Never normalize their values inside a component; define default compatibility aliases as CVA entries instead.
|
|
27
|
+
- `PillButton` has its own CVA but follows the same variant contract: `solid` and `outline` are default aliases and are passed unchanged to `pillButton.cva` overrides.
|
|
28
|
+
|
|
29
|
+
## Tags, links, typography
|
|
30
|
+
|
|
31
|
+
Typography sizes are `headline-l`, `h1`–`h4`, `lead`, `body`, `large`, and `small`; There is no typography `variant`; use `className="font-bold"` or `className="italic"` for emphasis. `large` and `small` do not add font weight; use explicit emphasis when needed. Use the same size on mobile and desktop unless explicitly overridden.
|
|
32
|
+
|
|
33
|
+
- `Badge` and `Tag` are display components, not generic buttons. Use `dismissible` and `onRemove` for removal; `dismissable` and `onDismiss` are legacy forms.
|
|
34
|
+
- Pass remove-button behavior through `dismissButtonProps`; arbitrary button props do not belong on the display container.
|
|
35
|
+
- Use `Link` for navigation and `Button` for actions.
|
|
36
|
+
- Use `Typography` with semantic `as` elements (`h1`, `h2`, `p`, `span`) and library typography variants/sizes. Token changes belong in UI overrides, not consumers.
|
|
37
|
+
|
|
38
|
+
## Feedback
|
|
39
|
+
|
|
40
|
+
- Use `Alert` for persistent inline status, `Toast`/`useToast` for transient notifications, `Spinner` for indeterminate progress, and `Progress` for numeric progress.
|
|
41
|
+
- For alerts and toasts, keep `variant` (`contained`/`outlined`) separate from semantic `color` (`neutral`, `success`, `warning`, `error`).
|
|
42
|
+
- Toast actions are `{ text, onPress }`; keep them short and non-destructive.
|
|
43
|
+
|
|
44
|
+
## Reference
|
|
45
|
+
|
|
46
|
+
- `packages/ui/src/components/buttons/Button/Button.tsx` — Button behavior and compatibility.
|
|
47
|
+
- `packages/ui/src/components/text/Tag/Tag.tsx` — dismissible tag contract.
|
|
48
|
+
- `packages/ui/src/components/status/Toast/Toast.tsx` — toast content and actions.
|
|
49
|
+
|
|
50
|
+
## When refactoring
|
|
51
|
+
|
|
52
|
+
- `Button` uses `icon` only for a conventional start/end icon → use `startIcon` or `endIcon`.
|
|
53
|
+
- An icon-only action has no accessible name → use `IconButton` with `ariaLabel` or `label`.
|
|
54
|
+
- A tag/pill receives `onPress` to represent selection → use `ToggleButton` or `ToggleGroup`.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
targets: ["*"]
|
|
3
|
+
description: "@povio/ui form fields, selection controls, pickers, uploads, and React Hook Form integration"
|
|
4
|
+
globs:
|
|
5
|
+
- "packages/ui/src/components/inputs/**/*"
|
|
6
|
+
- "packages/ui/src/hooks/useForm*.ts"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Inputs and forms
|
|
10
|
+
|
|
11
|
+
## Shared field contract
|
|
12
|
+
|
|
13
|
+
- Sizes: `small` and `default` only. Omit `size` for the default; `extra-small` and `large` are not supported. This shared input API has no `sm` or `s` aliases.
|
|
14
|
+
- Use `label`, `helperText`, `error`, `isRequired`, and `isDisabled` as the base field contract.
|
|
15
|
+
- `Input`, `TextArea`, and `NumberField` also accept `errorMessage`, `required`, and `disabled`. Their visual layout is `layout="default" | "floating" | "filter" | "inline"`; `as` remains the legacy layout prop and is not polymorphic element selection.
|
|
16
|
+
- Use `variant="outlined" | "filled"` for text-like inputs. Keep layout separate from variant.
|
|
17
|
+
- Use `isClearable`, `leadingIcon`, `trailingIcon`, `action`, `unit`, `placeholder`, and `inputClassName` only where exposed; do not recreate input chrome in consumers.
|
|
18
|
+
- Controlled fields use `value` and `onChange`; uncontrolled fields use `defaultValue`. Preserve callback value types: strings for text, `number | null` for number fields, and component-specific date values for pickers.
|
|
19
|
+
|
|
20
|
+
## Selection controls
|
|
21
|
+
|
|
22
|
+
- `Checkbox` uses `isSelected`, `defaultSelected`, and `onChange(boolean)`; `children` may be any `ReactNode`.
|
|
23
|
+
- `Switch` uses the same boolean selection contract.
|
|
24
|
+
- `RadioGroup` takes `options: { label, value }[]` and scalar `value`/`defaultValue`/`onChange`.
|
|
25
|
+
- `CheckboxGroup` takes the same options shape and array values. `allValue` is an Atlas extension for all-selected representation.
|
|
26
|
+
- `ToggleGroup`, `Select`, and `Autocomplete` use `selectionMode="single" | "multiple"`. Single values are `Key | null`; multiple values are `Key[]`.
|
|
27
|
+
- `Select` is a closed selection field. `Autocomplete` is the searchable/combobox form of the same item API. Both take `items: { id, label, content?, isDisabled? }[]`.
|
|
28
|
+
- Preserve Select capabilities: `isSearchable`, `isClearable`, `showSelectAllOption`, `showSelectionBar`, `showNewItemOption`, `onNewItemOption`, async `isLoading`/`hasLoadMore`/`onLoadMore`, and `virtualizerOptions`.
|
|
29
|
+
- Use `QuerySelect` and `QueryAutocomplete` only with the package TanStack Query adapter; they are not generic async-select replacements.
|
|
30
|
+
|
|
31
|
+
## Dates, ranges, files, rich text
|
|
32
|
+
|
|
33
|
+
- Use `DatePicker`, `DateRangePicker`, `TimePicker`, and `DateTimePicker` for React Aria date values. Preserve `minValue`, `maxValue`, `granularity`, `isClearable`, and date-input options rather than replacing them with native inputs.
|
|
34
|
+
- Use `Slider` with numeric `value`/`defaultValue`; set `isRange` for two-thumb values.
|
|
35
|
+
- Use `FileInput` for controlled form file values and `FileUpload` for upload lifecycle, progress, cancellation, and uploaded-file display. Both accept `multiple` or `allowsMultiple`.
|
|
36
|
+
- Import `RichTextEditor` from `@povio/ui/rich-text-editor`, not the main package entry point.
|
|
37
|
+
|
|
38
|
+
## Forms
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
// TanStack Form (native binding, e.g. import from "@povio/ui/tanstack/input")
|
|
42
|
+
<Input label="Name" field={{ form, name: "name" }} />
|
|
43
|
+
|
|
44
|
+
// React Hook Form (adapter, e.g. import from "@povio/ui/rhf/input")
|
|
45
|
+
<Input label="Name" formControl={{ control: form.control, name: "name" }} />
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- `field` (TanStack) and `formControl` (React Hook Form) each own `value`, `onChange`, and `onBlur`; do not supply competing controlled props alongside either.
|
|
49
|
+
- `Form` and `Inputs` are Zod schema helpers, available in both the TanStack-native and React Hook Form flavors. Use a regular HTML `<form>` with individual fields when schema-generated rendering is not needed.
|
|
50
|
+
|
|
51
|
+
## Reference
|
|
52
|
+
|
|
53
|
+
- `packages/ui/src/components/inputs/Input/Input.tsx` — core text-field API.
|
|
54
|
+
- `packages/ui/src/components/inputs/Selection/shared/SelectBase.tsx` — selection and async capabilities.
|
|
55
|
+
- `packages/ui/src/components/inputs/shared/form.types.ts` — typed `field` (TanStack) contract.
|
|
56
|
+
- `packages/ui/src/rhf/form.types.ts` — typed `formControl` (React Hook Form) contract.
|
|
57
|
+
|
|
58
|
+
## When refactoring
|
|
59
|
+
|
|
60
|
+
- A consumer uses `as` to select a DOM element → use `layout`; `as` controls legacy input presentation.
|
|
61
|
+
- App code checks `allowsMultiple` → prefer `multiple` in new code.
|
|
62
|
+
- A select hand-rolls filtering or virtualized results → use the exposed Select/Autocomplete props before adding consumer-side overlay logic.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
targets: ["*"]
|
|
3
|
+
description: "@povio/ui overlays, navigation, tables, accessibility, and styling conventions"
|
|
4
|
+
globs:
|
|
5
|
+
- "packages/ui/src/components/overlays/**/*"
|
|
6
|
+
- "packages/ui/src/components/navigation/**/*"
|
|
7
|
+
- "packages/ui/src/components/DropdownMenu/**/*"
|
|
8
|
+
- "packages/ui/src/components/Breadcrumbs/**/*"
|
|
9
|
+
- "packages/ui/src/components/table/**/*"
|
|
10
|
+
- "packages/ui/src/components/**/*.cva.ts"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Overlays, navigation, tables, and styling
|
|
14
|
+
|
|
15
|
+
## Overlays and navigation
|
|
16
|
+
|
|
17
|
+
- Use `Dialog` with controlled `isOpen`; handle transitions with `onOpenChange`. `onClose` remains available for close-only behavior.
|
|
18
|
+
- Use `AlertDialog` for confirmations with a primary action and optional secondary action.
|
|
19
|
+
- Use `Drawer` for a side panel and `BottomSheet` for a mobile bottom sheet. Both own focus trapping and dismissal; do not mount parallel ad-hoc overlays.
|
|
20
|
+
- `Popover` renders a desktop popover and mobile bottom sheet. It requires a trigger, controlled state, and accessible `sheetLabel`.
|
|
21
|
+
- Use `Tooltip` for supplemental text only; it must not be the sole accessible label for an icon action.
|
|
22
|
+
- Use `DropdownMenu` with `trigger`, `items`, and `onAction`. Menu items are `{ id, label, content?, link?, children? }`; nested `children` create submenus.
|
|
23
|
+
- Use `Accordion` for expandable content, `Stepper` for step progress, `Breadcrumbs` for hierarchy, and `Pagination`/`PaginationList` for page navigation.
|
|
24
|
+
|
|
25
|
+
## Tables
|
|
26
|
+
|
|
27
|
+
- `Table` is the base TanStack wrapper. Use `PaginatedTable` or `InfiniteTable` only when their data-loading contracts match the view.
|
|
28
|
+
- Keep table columns in the consumer domain. Use `CellText` and `HeaderText` for consistent text treatment; use `ColumnConfigModal` for persisted visibility/configuration behavior.
|
|
29
|
+
|
|
30
|
+
## Styling and accessibility
|
|
31
|
+
|
|
32
|
+
- Components use class-variance-authority, `UIOverrides`, and tokenized Tailwind classes. Add visual variants through the relevant `*.cva.ts` definition and expose a typed variant prop; do not add hard-coded color values in consumers.
|
|
33
|
+
- Use `UIConfig` for package-wide defaults and `UIOverrides` for recipe overrides. Do not duplicate component markup to bypass them.
|
|
34
|
+
- Preserve React Aria state props/data attributes (`isDisabled`, `isSelected`, `isInvalid`, `data-selected`) when wrapping controls.
|
|
35
|
+
- Root styling uses `className`. Prefer existing slot props (`inputClassName`, `dialogClassName`, `overlayClassName`, `containerClassName`) over selectors reaching into library internals.
|
|
36
|
+
- Keep button-like controls keyboard accessible. Icon-only actions need an accessible name; labels remain associated with fields.
|
|
37
|
+
- Avoid nested runtime ternaries in rendering or prop normalization. Use a named helper, map, or explicit branch.
|
|
38
|
+
|
|
39
|
+
## Reference
|
|
40
|
+
|
|
41
|
+
- `packages/ui/src/components/overlays/Dialog/Dialog.tsx` — controlled dialog behavior.
|
|
42
|
+
- `packages/ui/src/components/DropdownMenu/DropdownMenu.tsx` — responsive menu boundary.
|
|
43
|
+
- `packages/ui/src/config/uiOverrides.context.tsx` — recipe override system.
|
|
44
|
+
|
|
45
|
+
## When refactoring
|
|
46
|
+
|
|
47
|
+
- A component hard-codes a visual token already represented by a CVA recipe → add or reuse a typed recipe variant.
|
|
48
|
+
- An icon-only trigger relies only on a tooltip → add an `aria-label`/`ariaLabel` or visible label.
|
|
49
|
+
- Overlay state is duplicated in an app wrapper and a UI component → make controlled `isOpen`/`onOpenChange` the source of truth.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
root: true
|
|
3
|
+
targets: ["*"]
|
|
4
|
+
description: "@povio/ui public API and component-selection guidance"
|
|
5
|
+
globs: ["packages/ui/**/*"]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# @povio/ui component-library overview
|
|
9
|
+
|
|
10
|
+
`@povio/ui` is a React 19, TypeScript, Tailwind 4 component library built on React Aria Components. Import components and hooks from component-scoped subpaths (e.g. `@povio/ui/dialog`, `@povio/ui/rich-text-editor`), or from the broader `@povio/ui/rhf` (React Hook Form) or `@povio/ui/tanstack` (TanStack Form) entries; internal `src/components/**` paths are not consumer APIs.
|
|
11
|
+
|
|
12
|
+
## Public API and naming
|
|
13
|
+
|
|
14
|
+
- `src/rhf.ts` and `src/tanstack.ts` are the authoritative barrels for the two form-integration flavors; `src/entries/*.ts` (plus `src/entries/rhf/*.ts` and `src/entries/tanstack/*.ts` for form-capable components) back the individual `package.json#exports` subpaths. Add or change a public component in all three places together with its prop type.
|
|
15
|
+
- Component names are canonical and final: `Input`, `NumberField`, `FileInput`, `Switch`, `ToggleGroup`, `DropdownMenu`, `Dialog`, `AlertDialog`, `Popover`, `Spinner`, `Progress`, `Badge`, `RichTextEditor` (exported from `@povio/ui/rich-text-editor`).
|
|
16
|
+
- Use `ButtonGroup` for grouped independent actions. Use `ToggleGroup` only when the group represents selected value(s).
|
|
17
|
+
|
|
18
|
+
## Common conventions
|
|
19
|
+
|
|
20
|
+
- Components use React Aria event names (`onPress`, `onChange`, `isDisabled`, `isSelected`) as their base API.
|
|
21
|
+
- Form-capable components speak a native `field: { form, name }` TanStack Form binding. Consumers on `@povio/ui/rhf/*` get the same components wrapped with a `formControl: { control, name }` React Hook Form adapter instead. Do not pass `value`, `onChange`, or `onBlur` together with `field`/`formControl`.
|
|
22
|
+
- Keep public props semantic and domain-independent. Use `className` for root styling and component-specific `*ClassName` props only for independently styled internal slots.
|
|
23
|
+
- Prefer `ReactNode` for display content and preserve `aria-*` props through to the interactive element.
|
|
24
|
+
|
|
25
|
+
## Reference
|
|
26
|
+
|
|
27
|
+
- `packages/ui/src/rhf.ts` / `packages/ui/src/tanstack.ts` — public exports per form-integration flavor.
|
|
28
|
+
- `packages/ui/src/config/uiConfig.context.tsx` — runtime component defaults.
|
|
29
|
+
|
|
30
|
+
## When refactoring
|
|
31
|
+
|
|
32
|
+
- A consumer imports from `src/components/...` → switch it to a package subpath export.
|
|
33
|
+
- A stateful segmented control is used as an action toolbar → use `ButtonGroup` and `Button`s instead.
|
package/README.md
CHANGED
|
@@ -62,21 +62,15 @@ Replace `size="extra-small"` with `size="small"`, and remove `size="large"` or `
|
|
|
62
62
|
|
|
63
63
|
The package ships RuleSync source rules in `.rulesync/` and `rulesync.jsonc`. They document the public component API, standard aliases, form contracts, accessibility expectations, and styling conventions for AI coding tools. Generated tool files are deliberately excluded from the published npm package.
|
|
64
64
|
|
|
65
|
-
To generate the UI rules into a consuming project's repository root, run the executable bundled with `@povio/ui`:
|
|
65
|
+
To generate the UI rules into a consuming project's repository root, install [`rulesync`](https://github.com/dyoshikawa/rulesync) (`^8.15.0`) in that project, then run the executable bundled with `@povio/ui`:
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
|
-
|
|
68
|
+
bunx --package @povio/ui povio-ui-rules
|
|
69
69
|
```
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
This generates the relevant Cursor, Claude Code, and Codex CLI files in the consuming repository. Add generated files to that repository's `.gitignore` unless they are intentionally versioned. Re-run the command after upgrading `@povio/ui`; verify without writing files by adding `--check` (for example, `bunx --package @povio/ui povio-ui-rules --check`).
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
npx povio-ui-rules
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
This generates the relevant Cursor, Claude Code, and Codex CLI files in the consuming repository. Add generated files to that repository's `.gitignore` unless they are intentionally versioned. Re-run the command after upgrading `@povio/ui`; verify without writing files by adding `--check` (for example, `pnpm exec povio-ui-rules --check`).
|
|
78
|
-
|
|
79
|
-
Within this monorepo, the equivalent package-local commands are `pnpm --filter @povio/ui rules:gen` and `pnpm --filter @povio/ui rules:check`.
|
|
73
|
+
Within this monorepo, the equivalent package-local commands are `bun run --filter @povio/ui rules:gen` and `bun run --filter @povio/ui rules:check`.
|
|
80
74
|
|
|
81
75
|
## Publishing
|
|
82
76
|
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@povio/ui",
|
|
3
|
-
"version": "5.0.0-rc.
|
|
3
|
+
"version": "5.0.0-rc.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"povio-ui-rules": "./scripts/generate-rules.mjs"
|
|
9
|
+
},
|
|
7
10
|
"sideEffects": [
|
|
8
11
|
"**/*.css"
|
|
9
12
|
],
|
|
@@ -1313,7 +1316,10 @@
|
|
|
1313
1316
|
"./package.json": "./package.json"
|
|
1314
1317
|
},
|
|
1315
1318
|
"files": [
|
|
1316
|
-
"dist"
|
|
1319
|
+
"dist",
|
|
1320
|
+
"scripts/generate-rules.mjs",
|
|
1321
|
+
".rulesync",
|
|
1322
|
+
"rulesync.jsonc"
|
|
1317
1323
|
],
|
|
1318
1324
|
"homepage": "https://povio.com",
|
|
1319
1325
|
"license": "UNLICENSED",
|
package/rulesync.jsonc
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://github.com/dyoshikawa/rulesync/releases/latest/download/config-schema.json",
|
|
3
|
+
"targets": ["cursor", "claudecode", "codexcli"],
|
|
4
|
+
"features": ["rules"],
|
|
5
|
+
"outputRoots": ["."],
|
|
6
|
+
"delete": true,
|
|
7
|
+
"verbose": false,
|
|
8
|
+
"silent": false,
|
|
9
|
+
"global": false,
|
|
10
|
+
"gitignoreTargetsOnly": true,
|
|
11
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
7
|
+
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const rulesyncEntry = require.resolve("rulesync");
|
|
10
|
+
const rulesyncCli = join(dirname(rulesyncEntry), "cli", "index.js");
|
|
11
|
+
const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
12
|
+
const configPath = join(packageRoot, "rulesync.jsonc");
|
|
13
|
+
|
|
14
|
+
const result = spawnSync(
|
|
15
|
+
process.execPath,
|
|
16
|
+
[
|
|
17
|
+
rulesyncCli,
|
|
18
|
+
"generate",
|
|
19
|
+
"--input-root",
|
|
20
|
+
packageRoot,
|
|
21
|
+
"--config",
|
|
22
|
+
configPath,
|
|
23
|
+
"--output-roots",
|
|
24
|
+
process.cwd(),
|
|
25
|
+
...process.argv.slice(2),
|
|
26
|
+
],
|
|
27
|
+
{ stdio: "inherit" },
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
if (result.error) {
|
|
31
|
+
throw result.error;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
process.exitCode = result.status ?? 1;
|