basalt-ui 1.6.0 → 1.7.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 +12 -0
- package/agent/rules/basalt-mantine.md +80 -40
- package/agent/rules/basalt-tokens.md +3 -1
- package/agent/skills/basalt-design/SKILL.md +21 -7
- package/agent/templates/CLAUDE-block.md.tpl +3 -2
- package/agent/templates/DESIGN.md.tpl +2 -1
- package/configs/oxlint-plugin.js +75 -1
- package/configs/oxlint.json +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/dashboard/index.d.ts +1 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/stat-card.d.ts +6 -1
- package/dist/dashboard/stat-card.d.ts.map +1 -1
- package/dist/dashboard/stat-card.js +37 -4
- package/dist/guard/index.d.ts +7 -1
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +16 -1
- package/dist/guard/types.d.ts +18 -3
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/surfaces.d.ts +2 -2
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +8 -2
- package/dist/theme/controls.module.css +5 -3
- package/dist/vite.d.ts +6 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +21 -1
- package/llms.txt +3 -3
- package/package.json +1 -1
- package/src/cli/index.ts +11 -0
- package/src/dashboard/index.ts +1 -1
- package/src/dashboard/stat-card.tsx +61 -2
- package/src/guard/check-source.test.ts +63 -1
- package/src/guard/index.ts +39 -3
- package/src/guard/types.ts +18 -2
- package/src/index.ts +1 -0
- package/src/surfaces.ts +8 -2
- package/src/theme/controls.module.css +5 -3
- package/src/vite.ts +62 -1
package/src/index.ts
CHANGED
package/src/surfaces.ts
CHANGED
|
@@ -186,9 +186,15 @@ export const SURFACES = {
|
|
|
186
186
|
layer: 'mantine-coupled',
|
|
187
187
|
rule: 'mantine',
|
|
188
188
|
skill: ['basalt-app', 'basalt-design'],
|
|
189
|
-
guardKinds: [
|
|
189
|
+
guardKinds: [
|
|
190
|
+
'raw-motion-value',
|
|
191
|
+
'card-with-border',
|
|
192
|
+
'raw-form-control',
|
|
193
|
+
'sub-16-input-font',
|
|
194
|
+
'mantine-shade-index',
|
|
195
|
+
],
|
|
190
196
|
description:
|
|
191
|
-
'BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard, EmptyState, SettingsSection/SettingsRow/DangerZone)',
|
|
197
|
+
'BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)',
|
|
192
198
|
optionalPeers: ['react-markdown', 'remark-gfm', 'shiki', 'beautiful-mermaid'],
|
|
193
199
|
forbiddenImports: [], // the no-charts/tokens-reexport invariant is comment-only today; Phase-4 plugin
|
|
194
200
|
},
|
|
@@ -214,8 +214,10 @@ html[data-mantine-color-scheme] .inputWrapper[data-variant='default']:not([data-
|
|
|
214
214
|
}
|
|
215
215
|
|
|
216
216
|
/*
|
|
217
|
-
* CheckboxCard / RadioCard (`withBorder`, the default): panel bg +
|
|
218
|
-
*
|
|
217
|
+
* CheckboxCard / RadioCard (`withBorder`, the default): panel bg + depth, no border — the same
|
|
218
|
+
* triad as Card/Paper, but on `shadow-raised`, since a selection card is something you click (the
|
|
219
|
+
* control-vs-panel line, see the header above). Mantine's own border-color rule wraps
|
|
220
|
+
* `[data-with-border]` in
|
|
219
221
|
* `:where()` (0 specificity), so a plain class + real attribute selector ((0,2,0)) already wins;
|
|
220
222
|
* no `html[…]` prefix fight needed, same reasoning as Button/ActionIcon above.
|
|
221
223
|
*/
|
|
@@ -240,7 +242,7 @@ html[data-mantine-color-scheme] .inputWrapper[data-variant='default']:not([data-
|
|
|
240
242
|
|
|
241
243
|
/*
|
|
242
244
|
* Focus = accent border (via --input-bd-focus above) + a subtle accent ring layered over the
|
|
243
|
-
* resting `--field-depth`, so the field keeps its shadow-
|
|
245
|
+
* resting `--field-depth`, so the field keeps its `shadow-raised` depth while focused.
|
|
244
246
|
*/
|
|
245
247
|
.input:focus,
|
|
246
248
|
.input:focus-within {
|
package/src/vite.ts
CHANGED
|
@@ -13,8 +13,13 @@
|
|
|
13
13
|
*
|
|
14
14
|
* NEVER reference `import.meta.env` here — this file is invoked inside the consumer's vite config
|
|
15
15
|
* at config-evaluation time (plain Node), where only `process.env` exists.
|
|
16
|
+
*
|
|
17
|
+
* It also carries the enforcement notice (`warnIfUnenforced`): this is the one basalt seam that runs
|
|
18
|
+
* on every dev start and every build of a consumer app, so it is the only place that can tell an app
|
|
19
|
+
* it installed the components and skipped `basalt-ui init`.
|
|
16
20
|
*/
|
|
17
|
-
import {
|
|
21
|
+
import { existsSync } from 'node:fs'
|
|
22
|
+
import { dirname, resolve } from 'node:path'
|
|
18
23
|
import { searchForWorkspaceRoot } from 'vite'
|
|
19
24
|
import type { HtmlTagDescriptor, Plugin, PluginOption, UserConfig } from 'vite'
|
|
20
25
|
import { SURFACE } from './tokens/palette'
|
|
@@ -46,6 +51,55 @@ export type BasaltViteOptions = {
|
|
|
46
51
|
basaltSrc?: string
|
|
47
52
|
/** App version surfaced via the `__APP_VERSION__` define. Defaults to `0.0.0`. */
|
|
48
53
|
version?: string
|
|
54
|
+
/**
|
|
55
|
+
* Print a one-time notice when `basalt-ui init` has never been run in this project (no
|
|
56
|
+
* `.basalt/manifest.json` found at or above the cwd) — see `warnIfUnenforced`. Default `true`.
|
|
57
|
+
* Set `false` to adopt the components without the toolchain and stop being told about it.
|
|
58
|
+
*/
|
|
59
|
+
enforcementNotice?: boolean
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** How many directories up from `cwd` to look for `.basalt/manifest.json`. Three covers the common
|
|
63
|
+
* shapes: config at the app root, an app in `web/` or `apps/<name>/` under a repo root. */
|
|
64
|
+
const UNENFORCED_SEARCH_DEPTH = 3
|
|
65
|
+
|
|
66
|
+
/** Set once the notice has been printed, so a watch-mode restart doesn't reprint it every reload. */
|
|
67
|
+
let unenforcedNoticePrinted = false
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Print one notice when basalt-ui is installed as a component library and nothing else.
|
|
71
|
+
*
|
|
72
|
+
* `basalt-ui init` is what places the oxlint preset, the theme-guard wiring, the lefthook stub and
|
|
73
|
+
* the agent rules. Skipping it leaves a consumer with the components and NONE of the enforcement —
|
|
74
|
+
* and, critically, no signal that this is the case. The failure is silent and cumulative: every
|
|
75
|
+
* hand-rolled `<Card withBorder radius="md" padding="lg">` renders perfectly, so the app drifts a
|
|
76
|
+
* card idiom at a time until someone looks at a screenshot and asks why the design system did
|
|
77
|
+
* nothing. The first real consumer reached seven such cards across six files that way.
|
|
78
|
+
*
|
|
79
|
+
* This is the only seam basalt owns that runs on every dev start and every build, which makes it
|
|
80
|
+
* the only place that can say so at the time it is still cheap to fix. It stays a notice, never an
|
|
81
|
+
* error: declining to adopt the toolchain is a legitimate choice, and a build that fails because a
|
|
82
|
+
* lint preset is absent would be a worse bug than the one this prevents.
|
|
83
|
+
*/
|
|
84
|
+
function warnIfUnenforced(cwd: string): void {
|
|
85
|
+
if (unenforcedNoticePrinted) return
|
|
86
|
+
|
|
87
|
+
let dir = cwd
|
|
88
|
+
for (let i = 0; i <= UNENFORCED_SEARCH_DEPTH; i++) {
|
|
89
|
+
if (existsSync(resolve(dir, '.basalt/manifest.json'))) return
|
|
90
|
+
const parent = dirname(dir)
|
|
91
|
+
if (parent === dir) break
|
|
92
|
+
dir = parent
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
unenforcedNoticePrinted = true
|
|
96
|
+
// oxlint-disable-next-line no-console -- a build-time notice has no other channel
|
|
97
|
+
console.warn(
|
|
98
|
+
'\n[basalt-ui] Installed, but `basalt-ui init` has never run here — no oxlint preset, no theme\n' +
|
|
99
|
+
' guard, no agent rules. You have the components and none of the enforcement.\n' +
|
|
100
|
+
' Fix: `bunx basalt-ui init`, then add `oxlint . && basalt-ui check-theme` as your\n' +
|
|
101
|
+
' lint script. Silence: pass `enforcementNotice: false` to basaltViteConfig().\n',
|
|
102
|
+
)
|
|
49
103
|
}
|
|
50
104
|
|
|
51
105
|
export function basaltViteConfig(opts: BasaltViteOptions): UserConfig {
|
|
@@ -55,6 +109,13 @@ export function basaltViteConfig(opts: BasaltViteOptions): UserConfig {
|
|
|
55
109
|
// on without editing its vite config. process.env (not import.meta.env) — this runs in Node.
|
|
56
110
|
const basaltSrc = opts.basaltSrc ?? process.env['BASALT_LOCAL']
|
|
57
111
|
|
|
112
|
+
// Skipped under basaltSrc/BASALT_LOCAL: that path means basalt-ui itself is being developed from
|
|
113
|
+
// a sibling checkout (the playground, or a consumer debugging against local source), where the
|
|
114
|
+
// enforcement config lives in basalt's own repo and a manifest is not expected.
|
|
115
|
+
if (opts.enforcementNotice !== false && basaltSrc === undefined) {
|
|
116
|
+
warnIfUnenforced(process.cwd())
|
|
117
|
+
}
|
|
118
|
+
|
|
58
119
|
const config: UserConfig = {
|
|
59
120
|
define: {
|
|
60
121
|
__APP_VERSION__: JSON.stringify(process.env['BUILD_VERSION'] ?? version),
|