basalt-ui 1.33.0 → 1.34.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/AGENTS.md +1 -1
- package/CHANGELOG.md +26 -0
- package/MIGRATING.md +108 -15
- package/README.md +3 -0
- package/agent/skills/basalt-app/SKILL.md +5 -3
- package/configs/oxlint-basalt.json +33 -0
- package/configs/oxlint-plugin.js +21 -6
- package/configs/oxlint-plugin.test.ts +98 -10
- package/configs/oxlint.json +2 -30
- package/dist/cli/check-theme.d.ts.map +1 -1
- package/dist/cli/check-theme.js +37 -36
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +3 -5
- package/dist/cli/guard-hook.d.ts.map +1 -1
- package/dist/cli/guard-hook.js +6 -34
- package/dist/cli/index.d.ts +29 -61
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +63 -19
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +7 -16
- package/dist/common/vx-families.d.ts +7 -0
- package/dist/common/vx-families.d.ts.map +1 -0
- package/dist/common/vx-families.js +32 -0
- package/dist/common/vx-family.d.ts +11 -0
- package/dist/common/vx-family.d.ts.map +1 -0
- package/dist/common/vx-family.js +12 -0
- package/dist/guard/index.d.ts +2 -2
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +11 -13
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-mobile-nav.js +2 -1
- package/dist/shell/app-mobile-nav.module.css +12 -0
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +32 -36
- package/dist/shell/app-sidebar.module.css +6 -0
- package/dist/shell/index.d.ts +0 -1
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +0 -2
- package/dist/shell/nav-glyph.d.ts +14 -0
- package/dist/shell/nav-glyph.d.ts.map +1 -0
- package/dist/shell/nav-glyph.js +21 -0
- package/dist/shell/nav-types.d.ts +1 -0
- package/dist/shell/nav-types.d.ts.map +1 -1
- package/dist/shell/sidebar-search.d.ts.map +1 -1
- package/dist/shell/sidebar-search.js +1 -3
- package/dist/surfaces.d.ts +2 -2
- package/dist/surfaces.js +2 -2
- package/dist/tokens/index.d.ts +1 -1
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +17 -1
- package/dist/tokens/size-classes.d.ts +12 -0
- package/dist/tokens/size-classes.d.ts.map +1 -1
- package/dist/tokens/size-classes.js +11 -5
- package/llms.txt +4 -4
- package/package.json +1 -1
- package/src/cli/check-theme.ts +60 -37
- package/src/cli/doctor.ts +3 -5
- package/src/cli/guard-hook.ts +8 -35
- package/src/cli/index.ts +102 -91
- package/src/cli/sync.ts +7 -16
- package/src/common/vx-families.ts +36 -0
- package/src/common/vx-family.ts +22 -0
- package/src/guard/index.ts +22 -25
- package/src/index.ts +0 -2
- package/src/shell/app-mobile-nav.module.css +12 -0
- package/src/shell/app-mobile-nav.tsx +8 -1
- package/src/shell/app-sidebar.module.css +6 -0
- package/src/shell/app-sidebar.tsx +52 -50
- package/src/shell/index.tsx +0 -1
- package/src/shell/nav-glyph.tsx +38 -0
- package/src/shell/nav-types.ts +1 -0
- package/src/shell/sidebar-search.tsx +1 -5
- package/src/surfaces.ts +2 -2
- package/src/tokens/index.ts +28 -1
- package/src/tokens/size-classes.ts +18 -5
- package/dist/shell/use-breakpoint.d.ts +0 -10
- package/dist/shell/use-breakpoint.d.ts.map +0 -1
- package/dist/shell/use-breakpoint.js +0 -11
- package/src/shell/use-breakpoint.ts +0 -37
package/AGENTS.md
CHANGED
|
@@ -8,7 +8,7 @@ Toolchain: Bun runtime, oxlint + oxfmt, conventional commits (empty scope), `mas
|
|
|
8
8
|
|
|
9
9
|
| Subpath | Layer | Purpose |
|
|
10
10
|
| --------------------------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
11
|
-
| `basalt-ui` | mantine-coupled | BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, PageBar, PageAside, useSizeClass
|
|
11
|
+
| `basalt-ui` | mantine-coupled | BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, PageBar, PageAside, useSizeClass, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, WidgetHeader, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, QueryState/LoadingState/ErrorState, SettingsSection/SettingsRow/DangerZone), ConnectivityProvider/useConnectivity/ConnectivityIndicator (auto-mounted, C1: absorbed from the dropped ./connectivity), createBasaltQueryClient/unwrap/BasaltQueryDevtools (C1: absorbed from the dropped ./query), BasaltDevDock (C5: lazy Router/Query devtools + theme lab in one dock) |
|
|
12
12
|
| `basalt-ui/charts` | headless | CartesianChart + visx chart primitives, kinds, sparklines, hooks, and token re-exports (Mantine-free) |
|
|
13
13
|
| `basalt-ui/tokens` | headless | VX token refs, buildPaletteCss, defineSeries, seriesTokens, groupTokens, alpha (Mantine-free) |
|
|
14
14
|
| `basalt-ui/theme-lab` | mantine-coupled | ThemeLabControls, applyOverrides, COLOR_GROUPS — a low-level inspector for the non-derived structural tokens; identity/color tuning lives in DeriveControls |
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
# [1.34.0](https://github.com/jkrumm/basalt-ui/compare/v1.33.0...v1.34.0) (2026-10-01)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* --merge-lint replaces a guards-only extends instead of stacking it ([b2e551b](https://github.com/jkrumm/basalt-ui/commit/b2e551bc1dc431a457f58db2f8727c5f2546a9f2))
|
|
7
|
+
* card-with-border remedy names its card-inset half ([1edfae7](https://github.com/jkrumm/basalt-ui/commit/1edfae79a0366d0f6c4618a7bd07d8c2370a1753))
|
|
8
|
+
* derive basalt's --vx-* families from every emitted name ([07ea183](https://github.com/jkrumm/basalt-ui/commit/07ea1834f4cfc14979bb81e4cd2afc5849f28712))
|
|
9
|
+
* dev-gate the basalt-family ref warning and pin its version ([23396df](https://github.com/jkrumm/basalt-ui/commit/23396df7d4fbb1f7b16f0d2f192c07485b6a4e47))
|
|
10
|
+
* give icon-less nav items a first-letter glyph and a name in the rail ([9095f15](https://github.com/jkrumm/basalt-ui/commit/9095f157d1652316f03e2ff1668faddb406a34ef))
|
|
11
|
+
* name an icon-less row by aria-label only in the collapsed rail ([bc13e09](https://github.com/jkrumm/basalt-ui/commit/bc13e09ff3c12e56be98c5353cf95c5925463ff9))
|
|
12
|
+
* never autofix a removed deprecation row ([0534a28](https://github.com/jkrumm/basalt-ui/commit/0534a287da5252b8699b9bd4eb5ec36c1279b1b9))
|
|
13
|
+
* refuse a release that reaches a deprecation's removeIn while it still ships ([eb55145](https://github.com/jkrumm/basalt-ui/commit/eb5514507011e9b9fdb7f1a23e335bc1c478c3aa))
|
|
14
|
+
* restore check-grace's singular 'grace entry' in the clear line ([6fca61c](https://github.com/jkrumm/basalt-ui/commit/6fca61cb5ec1dae71b1f8b9661817a17919ca9b5))
|
|
15
|
+
* take the rail glyph from a real grapheme via Intl.Segmenter ([ff4e396](https://github.com/jkrumm/basalt-ui/commit/ff4e39637f12cddb8817cd4be9367bb63f0ab5fc))
|
|
16
|
+
* treat a false icon as absent and expose a label-only glyph helper ([323ddbb](https://github.com/jkrumm/basalt-ui/commit/323ddbb0dc28c41b54c1c33271eb7d6a348ab1bd))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* check-theme names an unwired AST lane ([91472ef](https://github.com/jkrumm/basalt-ui/commit/91472efbf87b336716c1871392878e648b355cd0))
|
|
22
|
+
* judge every unemitted name inside a basalt-owned --vx-* family ([4864a9d](https://github.com/jkrumm/basalt-ui/commit/4864a9d78a0a0ef95d1f6caee85043b0d64c75ea))
|
|
23
|
+
* remove useBreakpoint, overdue since 1.33.0 ([d68f538](https://github.com/jkrumm/basalt-ui/commit/d68f538dde34acecda481f567c17ade5a86074d4))
|
|
24
|
+
* ship a guards-only oxlint preset, configs/oxlint-basalt.json ([f96d150](https://github.com/jkrumm/basalt-ui/commit/f96d15097aabf5461b524270eb5ce523928bfab5))
|
|
25
|
+
* ship CONTAINER_KEYS for SimpleGrid type="container" keys ([acb5933](https://github.com/jkrumm/basalt-ui/commit/acb5933cf407cfb203819ad09bb7cf0315f73e79))
|
|
26
|
+
|
|
1
27
|
# [1.33.0](https://github.com/jkrumm/basalt-ui/compare/v1.32.1...v1.33.0) (2026-10-01)
|
|
2
28
|
|
|
3
29
|
|
package/MIGRATING.md
CHANGED
|
@@ -66,18 +66,18 @@ There is one row per SURFACE, not per export, and a surface earns a row once any
|
|
|
66
66
|
shipped lefthook preset both changed in 1.30.0 with no row that owned them — which is how a
|
|
67
67
|
consumer read this index, found nothing, and diffed a KPI row that had silently gone 4-up → 2-up.
|
|
68
68
|
|
|
69
|
-
| Surface | 1.27.0 | 1.28.0 | 1.29.0 | 1.30.0 | 1.30.1 | 1.30.2 | 1.31.0 | 1.32.0 | 1.32.1 | 1.33.0 | Unreleased |
|
|
70
|
-
| ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------- |
|
|
71
|
-
| **tokens** (`./tokens`) | — | `--vx-divider` → `rgba()` on both schemes (§ Shell) | `--vx-space-touch-target` added (§ Additions) | eight spacing numbers (§ Chrome) | — | — | `--vx-hit` replaces the touch vars; `SIZE_CLASSES` (§ 1.31.0) | — | `SIZE_CLASSES`/`CONTAINER_CLASSES` actually exported (§ Fixes) | `CONTAINER_GRID_BREAKPOINTS`; `raw-breakpoint` trusts it (§ 1.33.0) | — |
|
|
72
|
-
| **charts** (`./charts`) | — | phone tier, `curve`, formatters, `state`, log axis (§ preamble) | `ChartState.empty: string`, `AxisBottomNumeric` (§ Additions) | responsive `height`, `legend.maxRows` (§ Charts) | `height` reaches the kinds; `maxRows` beats the `fill` fit (§ Charts) | — | container-class tier + `height` keys (§ 1.31.0) | — | `ResponsiveChartHeight` `sm` → key (§ Container recipes) | — | — |
|
|
73
|
-
| **shell** (`.`) | — | scrollport, region seams, **the brand left the sidebar** (§§ scrollport, brand, Shell) | `PageTitle`, `BasaltDevDock`, `useBreakpoint` (§ Additions) | More popover, aside pill, the responsive gutter, `useBasaltSpacing` (§ Chrome) | — | — | `theme.breakpoints` derived, `useSizeClass`, `data-basalt-host`, `useBreakpoint` on notice (§ 1.31.0) | `useBreakpoint` removal → 1.33.0; `useSizeClass` is shell-only (§ 1.32.0) | shell-less `shell/` gutter, `AppShell` breakpoints, `useSizeClass` for overlays (§§ Shell-less, `useSizeClass`) | — | — |
|
|
74
|
-
| **controls** (`./controls`) | `NumberFilter`, `field.number` (§ Controls) | sheet renders panel rows; `PanelRow`, `SliderControl` (§ `basalt-ui/controls`) | — | — | — | — | — | — | — | `NumberFilter clearable`; `createSearchStore` `resets` (§ State and controls) | — |
|
|
75
|
-
| **forms** (`./forms`) | — | `field` → `inputProps`, **`inputProps` drops `key`**, the layout tier (§ `inputProps`) | `field` DELETED — and the `--fix` recipe no longer works (§ Consolidation) | — | — | — | — | — | `FormGroup` row no longer stretches (§ Fixes) | — | — |
|
|
76
|
-
| **data** (`./data/table`) | — | root is a `<div>`, row selection, `getItemKey` required (§ `basalt-ui/data`) | `./data` + `./query` + `./connectivity` dropped (§ Consolidation) | — | — | — | — | — | `renderCard` documented (§ `renderCard`) | — | — |
|
|
77
|
-
| **dashboard** (`.`) | `StatCard`: `unit`, `breakdown`, delta format (§ `StatCard`) | `StatGroup`, `WidgetGrid`, query-aware `StatCard` — additive | — | **the column law keys on the CONTAINER; `cols={4}` is 2-up at `sm`** (§ Dashboard) | — | — | — | — | — | — | — |
|
|
78
|
-
| **toolchain** (`./configs/*`) | — | — | the shipped lefthook preset's `check-theme` BROKE — the CLI resolver stopped ascending (§ CLI) | the preset's default bin, and the `root:` recipe (§ Toolchain) | — | — | — | — | — | — | — |
|
|
79
|
-
| **CLI** (`basalt-ui`) | — | — | **resolver stops relocating; `doctor` loses 6 of 10 checks** (§ CLI) | — | — | — | — | — | — | — | — |
|
|
80
|
-
| **guards** | five rules → `error` (§ Guards) | six new ids at `warn` (§ preamble) | `query-dual-import` retired in 1.29.1 (§ Guards) | four rules → `error` (§ Guards) | — | — | — | `raw-breakpoint`: the container-grid answer, `error` at 1.33.0 (§ 1.32.0) | `FormRow`/`FormGroup` homes in both lanes; `basalt-main` dropped (§ Fixes) | C1 + breakpoint pairs → `error`; `unknown-vx-token` `warn` (§ Guards) | — |
|
|
69
|
+
| Surface | 1.27.0 | 1.28.0 | 1.29.0 | 1.30.0 | 1.30.1 | 1.30.2 | 1.31.0 | 1.32.0 | 1.32.1 | 1.33.0 | 1.34.0 | Unreleased |
|
|
70
|
+
| ----------------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------- | ---------- |
|
|
71
|
+
| **tokens** (`./tokens`) | — | `--vx-divider` → `rgba()` on both schemes (§ Shell) | `--vx-space-touch-target` added (§ Additions) | eight spacing numbers (§ Chrome) | — | — | `--vx-hit` replaces the touch vars; `SIZE_CLASSES` (§ 1.31.0) | — | `SIZE_CLASSES`/`CONTAINER_CLASSES` actually exported (§ Fixes) | `CONTAINER_GRID_BREAKPOINTS`; `raw-breakpoint` trusts it (§ 1.33.0) | `CONTAINER_KEYS` (§ 1.34.0) | — |
|
|
72
|
+
| **charts** (`./charts`) | — | phone tier, `curve`, formatters, `state`, log axis (§ preamble) | `ChartState.empty: string`, `AxisBottomNumeric` (§ Additions) | responsive `height`, `legend.maxRows` (§ Charts) | `height` reaches the kinds; `maxRows` beats the `fill` fit (§ Charts) | — | container-class tier + `height` keys (§ 1.31.0) | — | `ResponsiveChartHeight` `sm` → key (§ Container recipes) | — | — | — |
|
|
73
|
+
| **shell** (`.`) | — | scrollport, region seams, **the brand left the sidebar** (§§ scrollport, brand, Shell) | `PageTitle`, `BasaltDevDock`, `useBreakpoint` (§ Additions) | More popover, aside pill, the responsive gutter, `useBasaltSpacing` (§ Chrome) | — | — | `theme.breakpoints` derived, `useSizeClass`, `data-basalt-host`, `useBreakpoint` on notice (§ 1.31.0) | `useBreakpoint` removal → 1.33.0; `useSizeClass` is shell-only (§ 1.32.0) | shell-less `shell/` gutter, `AppShell` breakpoints, `useSizeClass` for overlays (§§ Shell-less, `useSizeClass`) | — | `useBreakpoint` removed (§ 1.34.0) | — |
|
|
74
|
+
| **controls** (`./controls`) | `NumberFilter`, `field.number` (§ Controls) | sheet renders panel rows; `PanelRow`, `SliderControl` (§ `basalt-ui/controls`) | — | — | — | — | — | — | — | `NumberFilter clearable`; `createSearchStore` `resets` (§ State and controls) | — | — |
|
|
75
|
+
| **forms** (`./forms`) | — | `field` → `inputProps`, **`inputProps` drops `key`**, the layout tier (§ `inputProps`) | `field` DELETED — and the `--fix` recipe no longer works (§ Consolidation) | — | — | — | — | — | `FormGroup` row no longer stretches (§ Fixes) | — | — | — |
|
|
76
|
+
| **data** (`./data/table`) | — | root is a `<div>`, row selection, `getItemKey` required (§ `basalt-ui/data`) | `./data` + `./query` + `./connectivity` dropped (§ Consolidation) | — | — | — | — | — | `renderCard` documented (§ `renderCard`) | — | — | — |
|
|
77
|
+
| **dashboard** (`.`) | `StatCard`: `unit`, `breakdown`, delta format (§ `StatCard`) | `StatGroup`, `WidgetGrid`, query-aware `StatCard` — additive | — | **the column law keys on the CONTAINER; `cols={4}` is 2-up at `sm`** (§ Dashboard) | — | — | — | — | — | — | — | — |
|
|
78
|
+
| **toolchain** (`./configs/*`) | — | — | the shipped lefthook preset's `check-theme` BROKE — the CLI resolver stopped ascending (§ CLI) | the preset's default bin, and the `root:` recipe (§ Toolchain) | — | — | — | — | — | — | — | — |
|
|
79
|
+
| **CLI** (`basalt-ui`) | — | — | **resolver stops relocating; `doctor` loses 6 of 10 checks** (§ CLI) | — | — | — | — | — | — | — | — | — |
|
|
80
|
+
| **guards** | five rules → `error` (§ Guards) | six new ids at `warn` (§ preamble) | `query-dual-import` retired in 1.29.1 (§ Guards) | four rules → `error` (§ Guards) | — | — | — | `raw-breakpoint`: the container-grid answer, `error` at 1.33.0 (§ 1.32.0) | `FormRow`/`FormGroup` homes in both lanes; `basalt-main` dropped (§ Fixes) | C1 + breakpoint pairs → `error`; `unknown-vx-token` `warn` (§ Guards) | — | — |
|
|
81
81
|
|
|
82
82
|
---
|
|
83
83
|
|
|
@@ -86,6 +86,97 @@ consumer read this index, found nothing, and diffed a KPI row that had silently
|
|
|
86
86
|
_Nothing yet. Author the next section under this heading as `## Unreleased — <title>`; the
|
|
87
87
|
release renames it and opens a new one here._
|
|
88
88
|
|
|
89
|
+
## 1.34.0 — the 1.34.0 minor
|
|
90
|
+
|
|
91
|
+
### `CONTAINER_KEYS` — the `SimpleGrid type="container"` keys ship
|
|
92
|
+
|
|
93
|
+
`basalt-ui/tokens` exports `CONTAINER_CLASSES` as the CSS lengths `SimpleGrid type="container"`
|
|
94
|
+
keys take (`compact` 240px · `regular` 480px · `wide` 800px), so the computed key is one import
|
|
95
|
+
instead of a template literal at every call site (argo: 19 sites behind two local `CQ_*` consts).
|
|
96
|
+
`micro` has no key — `base` is that class. `basalt/raw-breakpoint` judges theme names only, so the
|
|
97
|
+
computed key is green; nothing to waive.
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { CONTAINER_KEYS as CQ } from 'basalt-ui/tokens'
|
|
101
|
+
;<SimpleGrid type="container" cols={{ base: 1, [CQ.regular]: 2, [CQ.wide]: 3 }}>
|
|
102
|
+
…
|
|
103
|
+
</SimpleGrid>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| Delete | Replace with |
|
|
107
|
+
| --------------------------------------------------------------------------------------------- | -------------------------- |
|
|
108
|
+
| ``[`${CONTAINER_CLASSES.regular}px`]`` (or `.wide` / `.compact`) as a key | `[CONTAINER_KEYS.regular]` |
|
|
109
|
+
| a local ``CQ_REGULAR = `${CONTAINER_CLASSES.regular}px` `` const (argo's `container-grid.ts`) | the import above |
|
|
110
|
+
|
|
111
|
+
`Grid type="container"` is unchanged: `breakpoints={CONTAINER_GRID_BREAKPOINTS}` (§ 1.33.0) stays
|
|
112
|
+
its answer, and that map is now built from `CONTAINER_KEYS` — same values.
|
|
113
|
+
|
|
114
|
+
### `useBreakpoint` — removed from `basalt-ui`
|
|
115
|
+
|
|
116
|
+
| Was | Now |
|
|
117
|
+
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
118
|
+
| `useBreakpoint` — removed from `basalt-ui` | shell chrome: `useSizeClass() !== 'compact'` for `'sm'`, `useSizeClass() === 'expanded'` for `'lg'`; a page's own layout swap: a `type="container"` SimpleGrid/Grid or an `@container` rule (§ 1.32.0 `basalt/raw-breakpoint`) |
|
|
119
|
+
| `BreakpointName` — removed from `basalt-ui` | — (no replacement; `SizeClass` is the shell's vocabulary) |
|
|
120
|
+
|
|
121
|
+
On notice since 1.31.0, dated twice (1.31.0 → 1.33.0) and shipped one minor past that date; measured
|
|
122
|
+
fleet usage at removal was zero. The fix was never autofixable (the replacement is a different
|
|
123
|
+
shape), so `basalt/deprecated-export` keeps its row through 1.34.0 only to say the import is gone
|
|
124
|
+
instead of "still resolves".
|
|
125
|
+
|
|
126
|
+
### Guards — `unknown-vx-token` judges basalt's families in full (`warn`, `error` moves to 1.35.0)
|
|
127
|
+
|
|
128
|
+
`var(--vx-surface-2, transparent)` rendered transparent in image-gen since the file was written,
|
|
129
|
+
and 1.33.0 said nothing: it judged only removed names and bare roots, because `groupTokens` could
|
|
130
|
+
emit any name. Now:
|
|
131
|
+
|
|
132
|
+
- **Judged: every unemitted name inside a basalt-owned family** — the leading lowercase run of the
|
|
133
|
+
name: `accent`, `fill`, `ink`, `line`, `radius`, `shadow`, `space`, `status`, `surface`, `text`,
|
|
134
|
+
`tooltip`, … (the full list is in the finding's remedy, generated from what basalt emits). So
|
|
135
|
+
`--vx-surface-2`, `--vx-ink3`, `--vx-space-gutter` and a bare `--vx-space` are all findings.
|
|
136
|
+
- **Not judged: a name in any other family** (argo's `--vx-activity-*`, rb's `--vx-confidence-*`),
|
|
137
|
+
a computed name, and a name the same file declares.
|
|
138
|
+
- **`groupTokens` / `seriesTokens` warn** (once per name) on a ref inside a basalt family —
|
|
139
|
+
`groupTokens('surface', …)`, a series key `ink3` — and **throw from 1.35.0**, when the kind
|
|
140
|
+
promotes. That refusal is what makes the guard's judgement sound. Rename the group
|
|
141
|
+
(`groupTokens('app', …)`), and its `buildPaletteCss` `groups` key with it. Measured: no consumer
|
|
142
|
+
names one. `on` is not judged: the theme emits `--vx-on-<color>` for your own colors too.
|
|
143
|
+
|
|
144
|
+
Widening restarts the grace: `warn` through 1.34.x, `error` at 1.35.0. Measured at ship time:
|
|
145
|
+
argo, rb, image-gen, image-share, email-gateway, linewatch, obsidian, weatherorb all at 0
|
|
146
|
+
(image-gen's one hit was already fixed by hand in r4).
|
|
147
|
+
|
|
148
|
+
### `check-theme` says when the AST lane is not wired
|
|
149
|
+
|
|
150
|
+
When the nearest `.oxlintrc.json` up to the repo root neither extends a shipped preset nor loads
|
|
151
|
+
`configs/oxlint-plugin.js` with `basalt/*` rules on (or the target does not resolve), `check-theme`
|
|
152
|
+
prints one line — `AST lane not enforced — N basalt/* rule ids unguarded (incl. the promoted
|
|
153
|
+
control-outside-home, raw-breakpoint)`. Information only; the exit code is unchanged. `basalt-ui
|
|
154
|
+
doctor` names the fix.
|
|
155
|
+
|
|
156
|
+
### `card-with-border` names its `card-inset` half
|
|
157
|
+
|
|
158
|
+
Dropping `withBorder` and keeping `padding="md"` satisfied `check-theme` and then failed oxlint's
|
|
159
|
+
`basalt/card-inset`. The text-lane remedy now says to fix the inset in the same edit.
|
|
160
|
+
|
|
161
|
+
### `configs/oxlint-basalt.json` — the guard lane without the generic preset
|
|
162
|
+
|
|
163
|
+
Wiring `configs/oxlint.json` into a repo with history turns on the generic jsx-a11y / unicorn /
|
|
164
|
+
import / promise set alongside the `basalt/*` rules, and email-gateway hit unrelated errors before a
|
|
165
|
+
single guard could land. The new guards-only preset is the `basalt/*` plugin rules at their shipped
|
|
166
|
+
levels and nothing else:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{ "extends": ["./node_modules/basalt-ui/configs/oxlint-basalt.json"] }
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Take it first, move to `configs/oxlint.json` when the generic debt is paid. The full preset now
|
|
173
|
+
`extends` the guards-only one, so every `basalt/*` level lives in one file; extending the full one
|
|
174
|
+
behaves exactly as before. `doctor` and `check-theme` accept either.
|
|
175
|
+
|
|
176
|
+
The full preset assumes the shipped `tsconfig.react-app.json` base (`lib: ES2023`): its
|
|
177
|
+
`unicorn/no-array-sort` warning steers to `toSorted()`, which an older `lib` does not type. Extend
|
|
178
|
+
that tsconfig rather than waiving the rule.
|
|
179
|
+
|
|
89
180
|
## 1.33.0 — the 1.33.0 minor
|
|
90
181
|
|
|
91
182
|
### `CONTAINER_GRID_BREAKPOINTS` — the `Grid type="container"` map ships
|
|
@@ -113,7 +204,8 @@ The trust is provenance-gated: the import must name `CONTAINER_GRID_BREAKPOINTS`
|
|
|
113
204
|
`tokens.CONTAINER_GRID_BREAKPOINTS` on `import * as tokens`, and a same-file `const bp = …` of
|
|
114
205
|
either all count; a parameter or inner `const` that shadows the name does not). A map of your own
|
|
115
206
|
that deviates from it — a 1200px `xl`, say — stays a same-file literal. `SimpleGrid type="container"` is unchanged: its keys
|
|
116
|
-
are CSS lengths, so ``[`${CONTAINER_CLASSES.regular}px`]`` stays the form.
|
|
207
|
+
are CSS lengths, so ``[`${CONTAINER_CLASSES.regular}px`]`` stays the form (from 1.34.0:
|
|
208
|
+
`[CONTAINER_KEYS.regular]`, § 1.34.0).
|
|
117
209
|
|
|
118
210
|
### State and controls — `resets: ['page']`, `NumberFilter clearable`
|
|
119
211
|
|
|
@@ -347,8 +439,9 @@ source, which is what the rule's exemption is built on:
|
|
|
347
439
|
<Grid><Grid.Col span={{ base: 12, lg: 4 }}>…</Grid.Col></Grid>
|
|
348
440
|
|
|
349
441
|
// after — the grid's own width
|
|
350
|
-
import {
|
|
351
|
-
|
|
442
|
+
import { CONTAINER_KEYS as CQ, CONTAINER_GRID_BREAKPOINTS } from 'basalt-ui/tokens'
|
|
443
|
+
// CONTAINER_KEYS ships from 1.34.0; before it, [`${CONTAINER_CLASSES.regular}px`]
|
|
444
|
+
<SimpleGrid type="container" cols={{ base: 1, [CQ.regular]: 3 }}>…</SimpleGrid>
|
|
352
445
|
// the shipped map (§ 1.33.0); on 1.32.x, a same-file literal of the same five keys
|
|
353
446
|
<Grid type="container" breakpoints={CONTAINER_GRID_BREAKPOINTS}>
|
|
354
447
|
<Grid.Col span={{ base: 12, md: 4 }}>…</Grid.Col>
|
package/README.md
CHANGED
|
@@ -872,6 +872,9 @@ The `./configs/*` export gives consumer apps raw presets to `extends` or copy vi
|
|
|
872
872
|
{ "extends": ["./node_modules/basalt-ui/configs/oxlint.json"] }
|
|
873
873
|
```
|
|
874
874
|
|
|
875
|
+
`configs/oxlint-basalt.json` is the guard lane alone — the `basalt/*` rules, none of the generic
|
|
876
|
+
jsx-a11y / unicorn / import set — for a repo with history to take first; `oxlint.json` extends it.
|
|
877
|
+
|
|
875
878
|
`tsconfig.json` `extends` resolves the SAME way, through package exports (`bundler`
|
|
876
879
|
`moduleResolution`, CI-verified by `scripts/pack-test.sh`) — three raw presets, `base` (the shared
|
|
877
880
|
strict flags), `react-app` (`base` + DOM/JSX libs) and `node` (`base` + Node types):
|
|
@@ -27,9 +27,11 @@ once and yours forever. Claude Code cannot load rules or skills out of `node_mod
|
|
|
27
27
|
only reason anything is copied at all; everything a MACHINE reads is an `extends` reference into
|
|
28
28
|
`node_modules/basalt-ui/configs/`, so the toolchain auto-updates with the package.
|
|
29
29
|
|
|
30
|
-
**`init` on an existing app is a lint-debt event, not a no-op** —
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
**`init` on an existing app is a lint-debt event, not a no-op** — `.claude/rules/basalt-batteries.md`
|
|
31
|
+
§ "App bootstrapping" says what it turns on. Too much at once? Extend `configs/oxlint-basalt.json`
|
|
32
|
+
(the basalt/\* guards alone, no generic jsx-a11y/unicorn set) first, `configs/oxlint.json` later —
|
|
33
|
+
the full one pairs with the shipped `tsconfig.react-app.json` (ES2023 lib: `unicorn/no-array-sort`
|
|
34
|
+
steers to `toSorted()`).
|
|
33
35
|
|
|
34
36
|
## 2. Wire the runtime (the CLI scaffolds files, not your app's composition)
|
|
35
37
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"jsPlugins": ["./oxlint-plugin.js"],
|
|
3
|
+
"rules": {
|
|
4
|
+
"basalt/no-raw-font-size": "error",
|
|
5
|
+
"basalt/raw-size-literal": "error",
|
|
6
|
+
"basalt/card-inset": "error",
|
|
7
|
+
"basalt/chart-in-raw-surface": "error",
|
|
8
|
+
"basalt/hand-rolled-plot": "error",
|
|
9
|
+
"basalt/chart-legend-literal": "error",
|
|
10
|
+
"basalt/shadow-basalt-export": "warn",
|
|
11
|
+
"basalt/hand-rolled-shell": "error",
|
|
12
|
+
"basalt/raw-scroll-container": "error",
|
|
13
|
+
"basalt/hand-rolled-filter": "error",
|
|
14
|
+
"basalt/control-outside-home": "error",
|
|
15
|
+
"basalt/bound-control-outside-home": "error",
|
|
16
|
+
"basalt/control-size-literal": "error",
|
|
17
|
+
"basalt/page-bar-budget": "error",
|
|
18
|
+
"basalt/in-body-page-title": "error",
|
|
19
|
+
"basalt/responsive-twin": "error",
|
|
20
|
+
"basalt/search-literal-link": "error",
|
|
21
|
+
"basalt/use-search-from-literal": "error",
|
|
22
|
+
"basalt/provider-above-router": "error",
|
|
23
|
+
"basalt/query-fn-unwrap": "error",
|
|
24
|
+
"basalt/deprecated-export": "warn",
|
|
25
|
+
"basalt/forms-field-key": "error",
|
|
26
|
+
"basalt/visx-boundary": "error",
|
|
27
|
+
"basalt/visx-tooltip": "error",
|
|
28
|
+
"basalt/agent-resume-guard": "error",
|
|
29
|
+
"basalt/agent-no-raw-usechat": "error",
|
|
30
|
+
"basalt/ai-sdk-major": "error",
|
|
31
|
+
"basalt/raw-breakpoint": "error"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/configs/oxlint-plugin.js
CHANGED
|
@@ -3623,6 +3623,7 @@ const queryFnUnwrap = {
|
|
|
3623
3623
|
* prop?: string
|
|
3624
3624
|
* replacement: string
|
|
3625
3625
|
* removeIn: string
|
|
3626
|
+
* removed?: true
|
|
3626
3627
|
* fix?: false
|
|
3627
3628
|
* }} DeprecatedExport
|
|
3628
3629
|
*/
|
|
@@ -3646,7 +3647,12 @@ const queryFnUnwrap = {
|
|
|
3646
3647
|
* `removeIn` at least one minor out, add the `MIGRATING.md` row, and this rule starts nudging.
|
|
3647
3648
|
* `oxlint-plugin.test.ts` scans every `src/**\/index.ts(x)` barrel for a JSDoc `@deprecated` and
|
|
3648
3649
|
* fails when one has no row here, so the barrel half cannot be forgotten. Removing the export is a
|
|
3649
|
-
* separate commit that deletes the row in the
|
|
3650
|
+
* separate commit that either deletes the row (the fix is manual from then on — say so in the
|
|
3651
|
+
* removal's MIGRATING row) or keeps it one minor past the removal with `removed: true` and
|
|
3652
|
+
* `removeIn` set to the removing minor, so the message reads "was removed in X" instead of "still
|
|
3653
|
+
* resolves" — and never autofixes, whatever `fix` says. `scripts/check-grace.ts` refuses a release
|
|
3654
|
+
* at or past a `removeIn` whose export still ships — the gap that let `useBreakpoint` outlive its
|
|
3655
|
+
* date twice.
|
|
3650
3656
|
*
|
|
3651
3657
|
* @type {readonly DeprecatedExport[]}
|
|
3652
3658
|
*/
|
|
@@ -3662,8 +3668,8 @@ export const DEPRECATED_EXPORTS = [
|
|
|
3662
3668
|
name: 'useBreakpoint',
|
|
3663
3669
|
replacement:
|
|
3664
3670
|
'useSizeClass() for shell chrome; a page’s own layout swap is a container decision — a type="container" SimpleGrid/Grid or an @container rule',
|
|
3665
|
-
removeIn: '1.
|
|
3666
|
-
|
|
3671
|
+
removeIn: '1.34.0',
|
|
3672
|
+
removed: true,
|
|
3667
3673
|
},
|
|
3668
3674
|
]
|
|
3669
3675
|
|
|
@@ -3672,6 +3678,13 @@ function deprecatedExportMessage(row) {
|
|
|
3672
3678
|
row.prop === undefined
|
|
3673
3679
|
? `\`${row.name}\` from ${row.subpath}`
|
|
3674
3680
|
: `\`${row.prop}\` on <${row.name}>`
|
|
3681
|
+
if (row.removed === true) {
|
|
3682
|
+
return (
|
|
3683
|
+
`Removed basalt export — ${what} was removed in ${row.removeIn} and no longer resolves; use ` +
|
|
3684
|
+
`\`${row.replacement}\` instead (packages/basalt-ui/MIGRATING.md carries the row). ` +
|
|
3685
|
+
'(basalt/deprecated-export)'
|
|
3686
|
+
)
|
|
3687
|
+
}
|
|
3675
3688
|
return (
|
|
3676
3689
|
`Deprecated basalt export — ${what} is superseded by \`${row.replacement}\` and is removed in ` +
|
|
3677
3690
|
`${row.removeIn}. It still resolves today, so nothing is broken yet; migrate before that minor ` +
|
|
@@ -3724,7 +3737,8 @@ const deprecatedExport = {
|
|
|
3724
3737
|
context.report({
|
|
3725
3738
|
node: spec,
|
|
3726
3739
|
message: deprecatedExportMessage(row),
|
|
3727
|
-
|
|
3740
|
+
// A removed row's replacement is prose for a gone import, never a drop-in name.
|
|
3741
|
+
...(row.fix === false || row.removed === true
|
|
3728
3742
|
? {}
|
|
3729
3743
|
: { fix: (fixer) => fixer.replaceText(spec, `${row.replacement} as ${local}`) }),
|
|
3730
3744
|
})
|
|
@@ -4186,12 +4200,13 @@ const RAW_BREAKPOINT_EXEMPT_FILE = /(?:^|[\\/])(?:use-media-query\.ts|ChartToolt
|
|
|
4186
4200
|
* (`CONTAINER_CLASSES`, `basalt-ui/tokens`: compact 240 / regular 480 / wide 800), never on the
|
|
4187
4201
|
* viewport — `useSizeClass()` is the shell's seam, not a page's. Mantine 9's own `type="container"`
|
|
4188
4202
|
* grids are the primitive: both self-wrap in an `inline-size` container, so they need no ancestor.
|
|
4189
|
-
* The px literals are `
|
|
4203
|
+
* The px literals are `CONTAINER_KEYS` written out (the plugin cannot import TS source);
|
|
4190
4204
|
* `oxlint-plugin.test.ts` asserts every one against it, and the MIGRATING recipe too.
|
|
4191
4205
|
*/
|
|
4192
4206
|
export const RAW_BREAKPOINT_RECIPE =
|
|
4193
4207
|
'A page’s own layout keys on its container: <SimpleGrid type="container" cols={{ base: 1, ' +
|
|
4194
|
-
|
|
4208
|
+
'[CONTAINER_KEYS.regular]: 2, [CONTAINER_KEYS.wide]: 3 }}> (basalt-ui/tokens; the keys are ' +
|
|
4209
|
+
"the px lengths '480px'/'800px'), or <Grid " +
|
|
4195
4210
|
'type="container" breakpoints={CONTAINER_GRID_BREAKPOINTS}> (basalt-ui/tokens), with Grid.Col ' +
|
|
4196
4211
|
'span={{ base: 12, sm: 6 }} keyed through that map; a Flex direction swap becomes that SimpleGrid (equal ' +
|
|
4197
4212
|
'columns), a wrapping Group, or a CSS-module @container basalt-grid rule. useSizeClass() is for ' +
|
|
@@ -644,7 +644,7 @@ describe('basalt/ai-sdk-major', () => {
|
|
|
644
644
|
describe('basalt/raw-scroll-container promotion', () => {
|
|
645
645
|
it('ships "error" (not "warn"/"off") in the consumer preset', () => {
|
|
646
646
|
const shipped = JSON.parse(
|
|
647
|
-
readFileSync(resolve(import.meta.dirname, 'oxlint.json'), 'utf8'),
|
|
647
|
+
readFileSync(resolve(import.meta.dirname, 'oxlint-basalt.json'), 'utf8'),
|
|
648
648
|
) as { rules: Record<string, unknown> }
|
|
649
649
|
expect(shipped.rules['basalt/raw-scroll-container']).toBe('error')
|
|
650
650
|
})
|
|
@@ -682,7 +682,7 @@ describe('basalt agent rules promotion', () => {
|
|
|
682
682
|
'%s ships "error" (not "warn"/"off") in the consumer preset',
|
|
683
683
|
(rule) => {
|
|
684
684
|
const shipped = JSON.parse(
|
|
685
|
-
readFileSync(resolve(import.meta.dirname, 'oxlint.json'), 'utf8'),
|
|
685
|
+
readFileSync(resolve(import.meta.dirname, 'oxlint-basalt.json'), 'utf8'),
|
|
686
686
|
) as { rules: Record<string, unknown> }
|
|
687
687
|
expect(shipped.rules[rule]).toBe('error')
|
|
688
688
|
},
|
|
@@ -1402,7 +1402,9 @@ describe('twin lanes share one promotion', () => {
|
|
|
1402
1402
|
})
|
|
1403
1403
|
|
|
1404
1404
|
describe('PLUGIN_RULE_GRACE', () => {
|
|
1405
|
-
const shipped = JSON.parse(
|
|
1405
|
+
const shipped = JSON.parse(
|
|
1406
|
+
readFileSync(resolve(import.meta.dirname, 'oxlint-basalt.json'), 'utf8'),
|
|
1407
|
+
) as {
|
|
1406
1408
|
rules: Record<string, unknown>
|
|
1407
1409
|
}
|
|
1408
1410
|
const pkgVersion = (
|
|
@@ -3357,8 +3359,26 @@ describe('basalt/query-fn-unwrap', () => {
|
|
|
3357
3359
|
|
|
3358
3360
|
// ── deprecated-export (B4) ───────────────────────────────────────────────────
|
|
3359
3361
|
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
+
describe('basalt/deprecated-export', () => {
|
|
3363
|
+
it('reports a removed row as gone, never as "still resolves"', () => {
|
|
3364
|
+
const { code, rules, output } = run(
|
|
3365
|
+
`import { useBreakpoint } from 'basalt-ui'\nexport const x = useBreakpoint\n`,
|
|
3366
|
+
)
|
|
3367
|
+
expect(code).toBe(1)
|
|
3368
|
+
expect(rules).toContain('deprecated-export')
|
|
3369
|
+
expect(output).toContain('was removed in 1.34.0')
|
|
3370
|
+
expect(output).not.toContain('still resolves')
|
|
3371
|
+
})
|
|
3372
|
+
|
|
3373
|
+
// The row no longer says `fix: false`; `removed` alone must suppress the rewrite, because a
|
|
3374
|
+
// removed row's replacement is prose (`useSizeClass() for shell chrome; …`), not a name.
|
|
3375
|
+
it('never autofixes a removed row', () => {
|
|
3376
|
+
const source = `import { useBreakpoint } from 'basalt-ui'\nexport const x = useBreakpoint\n`
|
|
3377
|
+
writeFileSync(resolve(dir, 'removed-fix.tsx'), source)
|
|
3378
|
+
Bun.spawnSync([OXLINT_BIN, '-c', '.oxlintrc.json', '--fix', 'removed-fix.tsx'], { cwd: dir })
|
|
3379
|
+
expect(readFileSync(resolve(dir, 'removed-fix.tsx'), 'utf8')).toBe(source)
|
|
3380
|
+
})
|
|
3381
|
+
})
|
|
3362
3382
|
|
|
3363
3383
|
// ── forms-field-key ──────────────────────────────────────────────────────────
|
|
3364
3384
|
|
|
@@ -3574,6 +3594,23 @@ describe('basalt/raw-breakpoint', () => {
|
|
|
3574
3594
|
).not.toContain('raw-breakpoint')
|
|
3575
3595
|
})
|
|
3576
3596
|
|
|
3597
|
+
it('does NOT flag CONTAINER_KEYS computed keys (named, aliased, namespace)', () => {
|
|
3598
|
+
const keyed = (imp: string, key: string) =>
|
|
3599
|
+
run(
|
|
3600
|
+
`import { SimpleGrid } from '@mantine/core'\n${imp}\n` +
|
|
3601
|
+
`export const C = () => <SimpleGrid type="container" cols={{ base: 1, [${key}.regular]: 2, [${key}.wide]: 3 }} />\n`,
|
|
3602
|
+
).rules
|
|
3603
|
+
expect(
|
|
3604
|
+
keyed(`import { CONTAINER_KEYS } from 'basalt-ui/tokens'`, 'CONTAINER_KEYS'),
|
|
3605
|
+
).not.toContain('raw-breakpoint')
|
|
3606
|
+
expect(keyed(`import { CONTAINER_KEYS as CQ } from 'basalt-ui/tokens'`, 'CQ')).not.toContain(
|
|
3607
|
+
'raw-breakpoint',
|
|
3608
|
+
)
|
|
3609
|
+
expect(
|
|
3610
|
+
keyed(`import * as tokens from 'basalt-ui/tokens'`, 'tokens.CONTAINER_KEYS'),
|
|
3611
|
+
).not.toContain('raw-breakpoint')
|
|
3612
|
+
})
|
|
3613
|
+
|
|
3577
3614
|
it('does NOT flag a lone `base` under type="container"', () => {
|
|
3578
3615
|
expect(grid(`<SimpleGrid type="container" cols={{ base: 2 }} />`).rules).not.toContain(
|
|
3579
3616
|
'raw-breakpoint',
|
|
@@ -3997,16 +4034,39 @@ describe('DEPRECATED_EXPORTS', () => {
|
|
|
3997
4034
|
}
|
|
3998
4035
|
).version
|
|
3999
4036
|
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4037
|
+
const [major, minor] = pkgVersion.split('.').map(Number)
|
|
4038
|
+
const floor = `${major}.${(minor as number) + 1}.0`
|
|
4039
|
+
const surface = JSON.parse(
|
|
4040
|
+
readFileSync(resolve(import.meta.dirname, '..', 'scripts', 'export-surface.json'), 'utf8'),
|
|
4041
|
+
) as Record<string, string[]>
|
|
4042
|
+
const shipped = (row: (typeof DEPRECATED_EXPORTS)[number]) =>
|
|
4043
|
+
surface[row.subpath === 'basalt-ui' ? '.' : row.subpath.replace('basalt-ui', '.')]?.includes(
|
|
4044
|
+
row.name,
|
|
4045
|
+
) === true
|
|
4046
|
+
|
|
4047
|
+
it('carries a replacement and a well-formed removeIn on every row', () => {
|
|
4003
4048
|
for (const row of DEPRECATED_EXPORTS) {
|
|
4004
4049
|
expect([row.name, row.replacement.length > 0]).toEqual([row.name, true])
|
|
4005
4050
|
expect([row.name, /^\d+\.\d+\.\d+$/.test(row.removeIn)]).toEqual([row.name, true])
|
|
4051
|
+
}
|
|
4052
|
+
})
|
|
4053
|
+
|
|
4054
|
+
// A live row still ships, so its removal is still ahead: at least the next minor.
|
|
4055
|
+
it('dates every live row at least one minor out', () => {
|
|
4056
|
+
for (const row of DEPRECATED_EXPORTS.filter((r) => r.removed !== true)) {
|
|
4006
4057
|
expect([row.name, compareSemver(row.removeIn, floor) >= 0]).toEqual([row.name, true])
|
|
4007
4058
|
}
|
|
4008
4059
|
})
|
|
4009
4060
|
|
|
4061
|
+
// A removed row is kept past the removal only for its message: the export must really be gone,
|
|
4062
|
+
// and the removing minor is the next one at the latest — never a date still ahead.
|
|
4063
|
+
it('pins every removed row to an export that no longer ships', () => {
|
|
4064
|
+
for (const row of DEPRECATED_EXPORTS.filter((r) => r.removed === true)) {
|
|
4065
|
+
expect([row.name, compareSemver(row.removeIn, floor) <= 0]).toEqual([row.name, true])
|
|
4066
|
+
if (row.prop === undefined) expect([row.name, shipped(row)]).toEqual([row.name, false])
|
|
4067
|
+
}
|
|
4068
|
+
})
|
|
4069
|
+
|
|
4010
4070
|
it('names a real published subpath on every row', () => {
|
|
4011
4071
|
const exports = Object.keys(
|
|
4012
4072
|
(
|
|
@@ -4064,7 +4124,9 @@ describe('DEPRECATED_EXPORTS', () => {
|
|
|
4064
4124
|
describe('the `Ships:` line above each rule', () => {
|
|
4065
4125
|
const source = readFileSync(resolve(import.meta.dirname, 'oxlint-plugin.js'), 'utf8')
|
|
4066
4126
|
const lines = source.split('\n')
|
|
4067
|
-
const shipped = JSON.parse(
|
|
4127
|
+
const shipped = JSON.parse(
|
|
4128
|
+
readFileSync(resolve(import.meta.dirname, 'oxlint-basalt.json'), 'utf8'),
|
|
4129
|
+
) as {
|
|
4068
4130
|
rules: Record<string, unknown>
|
|
4069
4131
|
}
|
|
4070
4132
|
// The registry block maps rule id → the `const` implementing it.
|
|
@@ -4077,7 +4139,7 @@ describe('the `Ships:` line above each rule', () => {
|
|
|
4077
4139
|
})
|
|
4078
4140
|
|
|
4079
4141
|
for (const { id, binding } of registry) {
|
|
4080
|
-
it(`${id}: the claim matches oxlint.json`, () => {
|
|
4142
|
+
it(`${id}: the claim matches oxlint-basalt.json`, () => {
|
|
4081
4143
|
const at = lines.indexOf(`const ${binding} = {`)
|
|
4082
4144
|
expect([id, at]).not.toEqual([id, -1])
|
|
4083
4145
|
const claim = /^\/\/ Ships: (.+)$/.exec(lines[at - 1] as string)?.[1]
|
|
@@ -4102,3 +4164,29 @@ describe('the `Ships:` line above each rule', () => {
|
|
|
4102
4164
|
})
|
|
4103
4165
|
}
|
|
4104
4166
|
})
|
|
4167
|
+
|
|
4168
|
+
// emailgw r4b: wiring the full preset on a repo with history forced unrelated jsx-a11y/unicorn
|
|
4169
|
+
// errors before a single basalt/* rule could land. The guards-only preset is the guard lane alone,
|
|
4170
|
+
// and the full preset extends it, so every basalt/* level is stated in exactly one file.
|
|
4171
|
+
describe('configs/oxlint-basalt.json — the guards-only preset', () => {
|
|
4172
|
+
const read = (file: string) =>
|
|
4173
|
+
JSON.parse(readFileSync(resolve(import.meta.dirname, file), 'utf8')) as Record<string, unknown>
|
|
4174
|
+
const guards = read('oxlint-basalt.json')
|
|
4175
|
+
const full = read('oxlint.json')
|
|
4176
|
+
|
|
4177
|
+
it('carries the plugin and basalt/* rules, nothing from the generic preset', () => {
|
|
4178
|
+
expect(Object.keys(guards).toSorted()).toEqual(['jsPlugins', 'rules'])
|
|
4179
|
+
expect(guards['jsPlugins']).toEqual(['./oxlint-plugin.js'])
|
|
4180
|
+
const ids = Object.keys(guards['rules'] as object)
|
|
4181
|
+
expect(ids.filter((id) => !id.startsWith('basalt/'))).toEqual([])
|
|
4182
|
+
expect(ids.length).toBeGreaterThan(0)
|
|
4183
|
+
})
|
|
4184
|
+
|
|
4185
|
+
it('is extended by the full preset, which states no basalt/* level of its own', () => {
|
|
4186
|
+
expect(full['extends']).toEqual(['./oxlint-basalt.json'])
|
|
4187
|
+
expect(full['jsPlugins']).toBeUndefined()
|
|
4188
|
+
expect(Object.keys(full['rules'] as object).filter((id) => id.startsWith('basalt/'))).toEqual(
|
|
4189
|
+
[],
|
|
4190
|
+
)
|
|
4191
|
+
})
|
|
4192
|
+
})
|
package/configs/oxlint.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": ["./oxlint-basalt.json"],
|
|
2
3
|
"plugins": ["react", "typescript", "import", "unicorn", "jsx-a11y", "promise", "oxc"],
|
|
3
|
-
"jsPlugins": ["./oxlint-plugin.js"],
|
|
4
4
|
"categories": {
|
|
5
5
|
"correctness": "error",
|
|
6
6
|
"suspicious": "warn"
|
|
@@ -22,35 +22,7 @@
|
|
|
22
22
|
{
|
|
23
23
|
"allow": ["__APP_VERSION__"]
|
|
24
24
|
}
|
|
25
|
-
]
|
|
26
|
-
"basalt/no-raw-font-size": "error",
|
|
27
|
-
"basalt/raw-size-literal": "error",
|
|
28
|
-
"basalt/card-inset": "error",
|
|
29
|
-
"basalt/chart-in-raw-surface": "error",
|
|
30
|
-
"basalt/hand-rolled-plot": "error",
|
|
31
|
-
"basalt/chart-legend-literal": "error",
|
|
32
|
-
"basalt/shadow-basalt-export": "warn",
|
|
33
|
-
"basalt/hand-rolled-shell": "error",
|
|
34
|
-
"basalt/raw-scroll-container": "error",
|
|
35
|
-
"basalt/hand-rolled-filter": "error",
|
|
36
|
-
"basalt/control-outside-home": "error",
|
|
37
|
-
"basalt/bound-control-outside-home": "error",
|
|
38
|
-
"basalt/control-size-literal": "error",
|
|
39
|
-
"basalt/page-bar-budget": "error",
|
|
40
|
-
"basalt/in-body-page-title": "error",
|
|
41
|
-
"basalt/responsive-twin": "error",
|
|
42
|
-
"basalt/search-literal-link": "error",
|
|
43
|
-
"basalt/use-search-from-literal": "error",
|
|
44
|
-
"basalt/provider-above-router": "error",
|
|
45
|
-
"basalt/query-fn-unwrap": "error",
|
|
46
|
-
"basalt/deprecated-export": "warn",
|
|
47
|
-
"basalt/forms-field-key": "error",
|
|
48
|
-
"basalt/visx-boundary": "error",
|
|
49
|
-
"basalt/visx-tooltip": "error",
|
|
50
|
-
"basalt/agent-resume-guard": "error",
|
|
51
|
-
"basalt/agent-no-raw-usechat": "error",
|
|
52
|
-
"basalt/ai-sdk-major": "error",
|
|
53
|
-
"basalt/raw-breakpoint": "error"
|
|
25
|
+
]
|
|
54
26
|
},
|
|
55
27
|
"overrides": [
|
|
56
28
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-theme.d.ts","sourceRoot":"","sources":["../../src/cli/check-theme.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check-theme.d.ts","sourceRoot":"","sources":["../../src/cli/check-theme.ts"],"names":[],"mappings":"AA+EA;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,aAAa,GAAE,MAAsB,EACrC,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,MAAM,CA6IR"}
|