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/dist/guard/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const SURFACE_SHADOW = /\bboxShadow\s*:\s*(?!['"`]?[^'"`]*(?:var\(|\$\{))['"`][^
|
|
|
13
13
|
const CARD_SURFACE_TAG = /<(?:Card|Paper)(?![\w.])(?:=>|[^>])*?>/g;
|
|
14
14
|
const WITH_BORDER_PROP = /\bwithBorder\b(?!\s*=\s*\{\s*false\s*\})/;
|
|
15
15
|
const OFF_SYSTEM_SURFACE_VAR = /var\(--mantine-color-(gray|dark)-\d/g;
|
|
16
|
+
const MANTINE_SHADE_INDEX = /\b(?:color|c|bg|backgroundColor|borderColor)\s*=\s*\{?\s*['"][a-z]+\.\d\b|var\(--mantine-color-(?!gray-|dark-)[a-z]+-\d/g;
|
|
16
17
|
const RAW_HTML_TAG = /<(?:div|span|section|header|nav|footer|aside|main|article|ul|ol)\b/;
|
|
17
18
|
const INLINE_STYLE = /style=\{\{/;
|
|
18
19
|
const LAYOUT_SURFACE_PROP = /\b(?:display|padding|margin|gap|flex|grid|border|background|width|height)\b/;
|
|
@@ -59,6 +60,7 @@ const DEFAULT_GUARD_CONFIG = {
|
|
|
59
60
|
spacingSteps: DEFAULT_SPACING_STEPS,
|
|
60
61
|
rawRadius: true,
|
|
61
62
|
forbiddenAccents: DEFAULT_FORBIDDEN_ACCENTS,
|
|
63
|
+
mantineShadeIndex: true,
|
|
62
64
|
rawSurface: true,
|
|
63
65
|
cardWithBorder: true,
|
|
64
66
|
offSystemSurfaceVar: true,
|
|
@@ -75,7 +77,9 @@ const DEFAULT_GUARD_CONFIG = {
|
|
|
75
77
|
exemptRules: {},
|
|
76
78
|
severity: {}
|
|
77
79
|
};
|
|
78
|
-
const GRACE_PERIOD_KINDS = {
|
|
80
|
+
const GRACE_PERIOD_KINDS = {
|
|
81
|
+
"mantine-shade-index": "introduced 1.7.0 \u2014 promote to error in 1.8.0"
|
|
82
|
+
};
|
|
79
83
|
function severityOf(kind, cfg) {
|
|
80
84
|
return cfg.severity?.[kind] ?? (kind in GRACE_PERIOD_KINDS ? "warn" : "error");
|
|
81
85
|
}
|
|
@@ -283,6 +287,12 @@ const GUARD_RULES = {
|
|
|
283
287
|
appliesTo: (relPath) => !relPath.endsWith(".css"),
|
|
284
288
|
message: "For an off-identity accent use blue/gray or a status hue (red/green/orange/yellow)."
|
|
285
289
|
},
|
|
290
|
+
"mantine-shade-index": {
|
|
291
|
+
kind: "mantine-shade-index",
|
|
292
|
+
pattern: MANTINE_SHADE_INDEX,
|
|
293
|
+
enabled: (cfg) => cfg.mantineShadeIndex,
|
|
294
|
+
message: 'Shade-pinned Mantine color \u2014 one fixed swatch in BOTH color schemes, so it cannot stay legible in either. Use VX.status.* / --vx-status-* for a verdict color, or the bare hue name (c="red") to let the theme resolve the shade per scheme.'
|
|
295
|
+
},
|
|
286
296
|
"raw-spacing": {
|
|
287
297
|
kind: "raw-spacing",
|
|
288
298
|
pattern: (cfg) => new RegExp(
|
|
@@ -469,6 +479,11 @@ function checkSource(text, relPath, cfg) {
|
|
|
469
479
|
findings.push({ relPath, line: i + 1, token: m[0], kind: "off-system-surface-var" });
|
|
470
480
|
}
|
|
471
481
|
}
|
|
482
|
+
if (GUARD_RULES["mantine-shade-index"].enabled(cfg)) {
|
|
483
|
+
for (const m of line.matchAll(GUARD_RULES["mantine-shade-index"].pattern)) {
|
|
484
|
+
findings.push({ relPath, line: i + 1, token: m[0], kind: "mantine-shade-index" });
|
|
485
|
+
}
|
|
486
|
+
}
|
|
472
487
|
if (GUARD_RULES["raw-html-layout"].enabled(cfg) && ruleApplies("raw-html-layout", relPath) && RAW_HTML_TAG.test(line) && INLINE_STYLE.test(line) && LAYOUT_SURFACE_PROP.test(line)) {
|
|
473
488
|
findings.push({ relPath, line: i + 1, token: "<raw-html style>", kind: "raw-html-layout" });
|
|
474
489
|
}
|
package/dist/guard/types.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Guard types — Mantine-free, dependency-free (zero imports beyond TS types).
|
|
3
3
|
*
|
|
4
|
-
* GuardKind is the closed set of
|
|
4
|
+
* GuardKind is the closed set of 20 violation kinds the theme guard can emit.
|
|
5
5
|
* Finding is the structured result per violation, replacing the old `Violation` shape.
|
|
6
6
|
* GuardConfig is the per-run configuration that drives checkSource.
|
|
7
7
|
*/
|
|
8
|
-
/** The
|
|
9
|
-
export type GuardKind = 'raw-hex' | 'raw-color-fn' | 'localstorage-theme' | 'off-identity-accent' | 'raw-spacing' | 'raw-radius' | 'raw-surface' | 'card-with-border' | 'off-system-surface-var' | 'raw-html-layout' | 'inline-spacing' | 'inline-display' | 'raw-visx-axis' | 'raw-motion-value' | 'unframed-chart' | 'chart-missing-aria-label' | 'raw-form-control' | 'sub-16-input-font' | 'raw-font-family';
|
|
8
|
+
/** The 20 theme-guard violation kinds. */
|
|
9
|
+
export type GuardKind = 'raw-hex' | 'raw-color-fn' | 'localstorage-theme' | 'off-identity-accent' | 'mantine-shade-index' | 'raw-spacing' | 'raw-radius' | 'raw-surface' | 'card-with-border' | 'off-system-surface-var' | 'raw-html-layout' | 'inline-spacing' | 'inline-display' | 'raw-visx-axis' | 'raw-motion-value' | 'unframed-chart' | 'chart-missing-aria-label' | 'raw-form-control' | 'sub-16-input-font' | 'raw-font-family';
|
|
10
10
|
/**
|
|
11
11
|
* How hard a finding lands. `error` fails the build; `warn` reports and passes.
|
|
12
12
|
*
|
|
@@ -59,6 +59,21 @@ export type GuardConfig = {
|
|
|
59
59
|
readonly rawRadius: boolean;
|
|
60
60
|
/** Off-identity Mantine accent families forbidden as chrome accents. */
|
|
61
61
|
readonly forbiddenAccents: readonly string[];
|
|
62
|
+
/**
|
|
63
|
+
* Flag a SHADE-PINNED Mantine color — `c="yellow.7"`, `bg="blue.4"`, `var(--mantine-color-red-6)`.
|
|
64
|
+
*
|
|
65
|
+
* This is the sibling of `off-identity-accent`, and the two are deliberately disjoint. That kind
|
|
66
|
+
* polices WHICH hue you reach for and permits the bare status names (`c="red"`, `color="green"`)
|
|
67
|
+
* on purpose: they resolve through the theme, so they flip correctly across color schemes. This
|
|
68
|
+
* kind polices the SHADE INDEX, which does not — a pinned step is one fixed swatch in both
|
|
69
|
+
* schemes, so a `yellow.7` legible on the dark page is the one that fails contrast on the light
|
|
70
|
+
* one. Status color belongs on `VX.status.*` (`--vx-status-warn|bad|good|…`), which is emitted per
|
|
71
|
+
* scheme.
|
|
72
|
+
*
|
|
73
|
+
* `gray-*`/`dark-*` in `var()` form are excluded here because `off-system-surface-var` already
|
|
74
|
+
* owns them (surface color, its own message). Default true.
|
|
75
|
+
*/
|
|
76
|
+
readonly mantineShadeIndex: boolean;
|
|
62
77
|
/** Flag ad-hoc inline surface styling (border/borderRadius/boxShadow literals). Default true. */
|
|
63
78
|
readonly rawSurface: boolean;
|
|
64
79
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/guard/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,cAAc,GACd,oBAAoB,GACpB,qBAAqB,GACrB,aAAa,GACb,YAAY,GACZ,aAAa,GACb,kBAAkB,GAClB,wBAAwB,GACxB,iBAAiB,GACjB,gBAAgB,GAChB,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,GAChB,0BAA0B,GAC1B,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB,CAAA;AAErB;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,CAAA;AAE5C;;;;;;;GAOG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAA;CACjC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,wGAAwG;IACxG,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5C,iGAAiG;IACjG,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC,2GAA2G;IAC3G,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAA;IACrC,sGAAsG;IACtG,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,4FAA4F;IAC5F,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,yFAAyF;IACzF,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,kGAAkG;IAClG,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAA;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC1D;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAA;CAC7D,CAAA"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/guard/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,cAAc,GACd,oBAAoB,GACpB,qBAAqB,GACrB,qBAAqB,GACrB,aAAa,GACb,YAAY,GACZ,aAAa,GACb,kBAAkB,GAClB,wBAAwB,GACxB,iBAAiB,GACjB,gBAAgB,GAChB,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,GAChB,0BAA0B,GAC1B,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB,CAAA;AAErB;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,OAAO,CAAA;AAE5C;;;;;;;GAOG;AACH,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAA;CACjC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,wGAAwG;IACxG,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,uEAAuE;IACvE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAA;IAC5C;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAA;IACnC,iGAAiG;IACjG,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAA;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC,2GAA2G;IAC3G,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAA;IACrC,sGAAsG;IACtG,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,8EAA8E;IAC9E,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,4FAA4F;IAC5F,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B,yFAAyF;IACzF,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAA;IAC7B,kGAAkG;IAClG,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,qBAAqB,EAAE,OAAO,CAAA;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAA;IAChC;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC1D;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAA;CAC7D,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export { MOTION_DURATION, MOTION_SPRING, MOTION_EASE_STANDARD } from './motion/i
|
|
|
13
13
|
export { BasaltShell, NavCountBadge, AppSidebar, SidebarSearch, type SidebarSearchConfig, SidebarAccount, MobileNav, AppBreadcrumbs, type BreadcrumbLinkRenderer, PageHeaderProvider, PageActions, PageActionsOutlet, type SidebarSection, type SidebarItem, type BasaltShellProps, type BrandConfig, type SettingsMenuItem, type AppSidebarProps, type MobileNavItem, type MobileNavSection, type NavLinkRenderer, type MobileNavLinkRenderer, type AccountBadgeTone, type BasaltIdentity, type BasaltRole, type BasaltPlan, type AccountMenuItem, type BasaltAccountState, type BasaltAccountActions, type BasaltAccountProps, } from './shell/index.js';
|
|
14
14
|
export { type BasaltRegister, type Slot, type Series, type SeriesKey, type AsyncState, assertNever, type StandardSchemaV1, } from './register.js';
|
|
15
15
|
export { createPersistedState, type PersistedStateOptions, useOnlineStatus, readPersistedValue, } from './state.js';
|
|
16
|
-
export { DeltaBadge, type DeltaBadgeProps, StatCard, type StatCardProps, EmptyState, type EmptyStateProps, SettingsSection, type SettingsSectionProps, SettingsRow, type SettingsRowProps, DangerZone, type DangerZoneProps, } from './dashboard/index.js';
|
|
16
|
+
export { DeltaBadge, type DeltaBadgeProps, StatCard, type StatCardProps, type StatCardTone, EmptyState, type EmptyStateProps, SettingsSection, type SettingsSectionProps, SettingsRow, type SettingsRowProps, DangerZone, type DangerZoneProps, } from './dashboard/index.js';
|
|
17
17
|
export { ConnectivityProvider, ConnectivityIndicator, useConnectivity } from './connectivity/index.js';
|
|
18
18
|
export type { ConnectivityStatus, ConnectivitySnapshot, ConnectivityProviderProps, ConnectivityOverride, } from './connectivity/index.js';
|
|
19
19
|
export type { SurfaceSpec, RuleName, SkillName } from './surfaces.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,EACxB,mBAAmB,EACnB,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAC5E,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACnE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/E,OAAO,EACL,WAAW,EACX,aAAa,EACb,UAAU,EACV,aAAa,EACb,KAAK,mBAAmB,EACxB,cAAc,EACd,SAAS,EACT,cAAc,EACd,KAAK,sBAAsB,EAC3B,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,GACxB,MAAM,SAAS,CAAA;AAKhB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,IAAI,EACT,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,UAAU,EACf,WAAW,EACX,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,eAAe,EACf,kBAAkB,GACnB,MAAM,SAAS,CAAA;AAGhB,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,QAAQ,EACR,KAAK,aAAa,EAClB,UAAU,EACV,KAAK,eAAe,EACpB,eAAe,EACf,KAAK,oBAAoB,EACzB,WAAW,EACX,KAAK,gBAAgB,EACrB,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC7F,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,gBAAgB,CAAA;AAKvB,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAClE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAU9C,OAAO,EACL,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,aAAa,EACb,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAClF,YAAY,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,cAAc,EACd,KAAK,mBAAmB,EACxB,mBAAmB,EACnB,KAAK,kBAAkB,GACxB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAC5E,YAAY,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAA;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACnE,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAC/E,OAAO,EACL,WAAW,EACX,aAAa,EACb,UAAU,EACV,aAAa,EACb,KAAK,mBAAmB,EACxB,cAAc,EACd,SAAS,EACT,cAAc,EACd,KAAK,sBAAsB,EAC3B,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,GACxB,MAAM,SAAS,CAAA;AAKhB,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,IAAI,EACT,KAAK,MAAM,EACX,KAAK,SAAS,EACd,KAAK,UAAU,EACf,WAAW,EACX,KAAK,gBAAgB,GACtB,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,oBAAoB,EACpB,KAAK,qBAAqB,EAC1B,eAAe,EACf,kBAAkB,GACnB,MAAM,SAAS,CAAA;AAGhB,OAAO,EACL,UAAU,EACV,KAAK,eAAe,EACpB,QAAQ,EACR,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,UAAU,EACV,KAAK,eAAe,EACpB,eAAe,EACf,KAAK,oBAAoB,EACzB,WAAW,EACX,KAAK,gBAAgB,EACrB,UAAU,EACV,KAAK,eAAe,GACrB,MAAM,aAAa,CAAA;AAGpB,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAC7F,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,gBAAgB,CAAA;AAKvB,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAClE,YAAY,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAU9C,OAAO,EACL,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,QAAQ,EACR,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,cAAc,CAAA;AACrB,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,sBAAsB,EACtB,aAAa,EACb,qBAAqB,GACtB,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAClF,YAAY,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,WAAW,EACX,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAA"}
|
package/dist/surfaces.d.ts
CHANGED
|
@@ -130,8 +130,8 @@ export declare const SURFACES: {
|
|
|
130
130
|
readonly layer: "mantine-coupled";
|
|
131
131
|
readonly rule: "mantine";
|
|
132
132
|
readonly skill: readonly ["basalt-app", "basalt-design"];
|
|
133
|
-
readonly guardKinds: readonly ["raw-motion-value", "card-with-border", "raw-form-control", "sub-16-input-font"];
|
|
134
|
-
readonly description: "BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard, EmptyState, SettingsSection/SettingsRow/DangerZone)";
|
|
133
|
+
readonly guardKinds: readonly ["raw-motion-value", "card-with-border", "raw-form-control", "sub-16-input-font", "mantine-shade-index"];
|
|
134
|
+
readonly description: "BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)";
|
|
135
135
|
readonly optionalPeers: readonly ["react-markdown", "remark-gfm", "shiki", "beautiful-mermaid"];
|
|
136
136
|
readonly forbiddenImports: readonly [];
|
|
137
137
|
};
|
package/dist/surfaces.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surfaces.d.ts","sourceRoot":"","sources":["../src/surfaces.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAI9C;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAChB,QAAQ,GACR,QAAQ,GACR,SAAS,GACT,QAAQ,GACR,OAAO,GACP,OAAO,GACP,OAAO,GACP,eAAe,GACf,UAAU,GACV,MAAM,GACN,OAAO,GACP,SAAS,GACT,KAAK,CAAA;AAET;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,eAAe,GAAG,eAAe,CAAA;AAExE;;;;GAIG;AACH,MAAM,MAAM,KAAK,GAAG,iBAAiB,GAAG,UAAU,GAAG,YAAY,GAAG,cAAc,CAAA;AAElF;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,wFAAwF;IACxF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAChC,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,oFAAoF;IACpF,QAAQ,CAAC,WAAW,CAAC,EAAE,IAAI,CAAA;IAC3B,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAA;CACzB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,CAAA;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;CACrC,CAAA;AAID,KAAK,WAAW,GAAG;IACjB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,gBAAgB,EAAE,SAAS,eAAe,EAAE,CAAA;IACrD,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IAChD;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE;QACf,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;QACnC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;KACjC,CAAA;IACD;;;;;;OAMG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC3C,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG;IACvC,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;IACzB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,iGAAiG;IACjG,QAAQ,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,CAAA;IACpC,2FAA2F;IAC3F,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAA;CAC1C,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAA;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAA;CAC5B,CAAA;AAED,kEAAkE;AAClE,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,WAAW,CAAA;AA8BpD;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"surfaces.d.ts","sourceRoot":"","sources":["../src/surfaces.ts"],"names":[],"mappings":"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"}
|
package/dist/surfaces.js
CHANGED
|
@@ -22,8 +22,14 @@ const SURFACES = {
|
|
|
22
22
|
layer: "mantine-coupled",
|
|
23
23
|
rule: "mantine",
|
|
24
24
|
skill: ["basalt-app", "basalt-design"],
|
|
25
|
-
guardKinds: [
|
|
26
|
-
|
|
25
|
+
guardKinds: [
|
|
26
|
+
"raw-motion-value",
|
|
27
|
+
"card-with-border",
|
|
28
|
+
"raw-form-control",
|
|
29
|
+
"sub-16-input-font",
|
|
30
|
+
"mantine-shade-index"
|
|
31
|
+
],
|
|
32
|
+
description: "BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)",
|
|
27
33
|
optionalPeers: ["react-markdown", "remark-gfm", "shiki", "beautiful-mermaid"],
|
|
28
34
|
forbiddenImports: []
|
|
29
35
|
// the no-charts/tokens-reexport invariant is comment-only today; Phase-4 plugin
|
|
@@ -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/dist/vite.d.ts
CHANGED
|
@@ -25,6 +25,12 @@ export type BasaltViteOptions = {
|
|
|
25
25
|
basaltSrc?: string;
|
|
26
26
|
/** App version surfaced via the `__APP_VERSION__` define. Defaults to `0.0.0`. */
|
|
27
27
|
version?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Print a one-time notice when `basalt-ui init` has never been run in this project (no
|
|
30
|
+
* `.basalt/manifest.json` found at or above the cwd) — see `warnIfUnenforced`. Default `true`.
|
|
31
|
+
* Set `false` to adopt the components without the toolchain and stop being told about it.
|
|
32
|
+
*/
|
|
33
|
+
enforcementNotice?: boolean;
|
|
28
34
|
};
|
|
29
35
|
export declare function basaltViteConfig(opts: BasaltViteOptions): UserConfig;
|
|
30
36
|
export type BasaltAppOptions = {
|
package/dist/vite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAA6B,YAAY,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAI/E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B,CAAA;AA6CD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,iBAAiB,GAAG,UAAU,CAgFpE;AAgBD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gGAAgG;IAChG,IAAI,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gGAAgG;IAChG,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IACrD,mGAAmG;IACnG,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,wDAAwD;IACxD,OAAO,CAAC,EAAE,YAAY,GAAG,YAAY,GAAG,YAAY,GAAG,SAAS,CAAA;IAChE;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mGAAmG;IACnG,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,wFAAwF;IACxF,KAAK,CAAC,EAAE,KAAK,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChC,8FAA8F;IAC9F,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;IAC3B,oFAAoF;IACpF,GAAG,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,SAAS,GAAG,qBAAqB,CAAA;KAAE,CAAA;IACvF,8FAA8F;IAC9F,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClD,CAAA;AAuZD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,YAAY,EAAE,CAMzE"}
|
package/dist/vite.js
CHANGED
|
@@ -1,10 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
2
3
|
import { searchForWorkspaceRoot } from "vite";
|
|
3
4
|
import { SURFACE } from "./tokens/palette.js";
|
|
4
5
|
import { resolveColorMix } from "./vite-color-mix.js";
|
|
6
|
+
const UNENFORCED_SEARCH_DEPTH = 3;
|
|
7
|
+
let unenforcedNoticePrinted = false;
|
|
8
|
+
function warnIfUnenforced(cwd) {
|
|
9
|
+
if (unenforcedNoticePrinted) return;
|
|
10
|
+
let dir = cwd;
|
|
11
|
+
for (let i = 0; i <= UNENFORCED_SEARCH_DEPTH; i++) {
|
|
12
|
+
if (existsSync(resolve(dir, ".basalt/manifest.json"))) return;
|
|
13
|
+
const parent = dirname(dir);
|
|
14
|
+
if (parent === dir) break;
|
|
15
|
+
dir = parent;
|
|
16
|
+
}
|
|
17
|
+
unenforcedNoticePrinted = true;
|
|
18
|
+
console.warn(
|
|
19
|
+
"\n[basalt-ui] Installed, but `basalt-ui init` has never run here \u2014 no oxlint preset, no theme\n guard, no agent rules. You have the components and none of the enforcement.\n Fix: `bunx basalt-ui init`, then add `oxlint . && basalt-ui check-theme` as your\n lint script. Silence: pass `enforcementNotice: false` to basaltViteConfig().\n"
|
|
20
|
+
);
|
|
21
|
+
}
|
|
5
22
|
function basaltViteConfig(opts) {
|
|
6
23
|
const { port, host, allowedHosts, apiTarget, version = "0.0.0" } = opts;
|
|
7
24
|
const basaltSrc = opts.basaltSrc ?? process.env["BASALT_LOCAL"];
|
|
25
|
+
if (opts.enforcementNotice !== false && basaltSrc === void 0) {
|
|
26
|
+
warnIfUnenforced(process.cwd());
|
|
27
|
+
}
|
|
8
28
|
const config = {
|
|
9
29
|
define: {
|
|
10
30
|
__APP_VERSION__: JSON.stringify(process.env["BUILD_VERSION"] ?? version),
|
package/llms.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# basalt-ui v1.
|
|
1
|
+
# basalt-ui v1.7.0
|
|
2
2
|
# Opinionated framework for Mantine-based React apps — theme, app shell, visx charts, toolchain presets
|
|
3
3
|
#
|
|
4
4
|
# basalt-ui is an opinionated framework for Mantine-based React apps.
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
# ./tokens.css subpath. Guide: docs/FRAMEWORK-FREE.md in the repo.
|
|
20
20
|
|
|
21
21
|
Package: basalt-ui
|
|
22
|
-
Version: 1.
|
|
22
|
+
Version: 1.7.0
|
|
23
23
|
|
|
24
24
|
## basalt-ui
|
|
25
25
|
Import: import { ... } from 'basalt-ui'
|
|
26
|
-
Description: BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard, EmptyState, SettingsSection/SettingsRow/DangerZone)
|
|
26
|
+
Description: BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, NavCountBadge, ThemeToggle, ThreadWorkspace + thread-chat components, dashboard composites (DeltaBadge, StatCard with threshold tone, EmptyState, SettingsSection/SettingsRow/DangerZone)
|
|
27
27
|
Layer: mantine-coupled
|
|
28
28
|
Rule: basalt-mantine
|
|
29
29
|
OptionalPeers: react-markdown@^10.1.0, remark-gfm@^4.0.1, shiki@^4.3.0, beautiful-mermaid@^1.1.0
|
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -80,6 +80,15 @@ export type BasaltConfig = {
|
|
|
80
80
|
* surface tokens. Default: `true` (ON). Set `false` to disable the `off-system-surface-var` check.
|
|
81
81
|
*/
|
|
82
82
|
offSystemSurfaceVar?: boolean
|
|
83
|
+
/**
|
|
84
|
+
* Flag a SHADE-PINNED Mantine color — `c="yellow.7"`, `bg="blue.4"`,
|
|
85
|
+
* `var(--mantine-color-red-6)`. A pinned step is one fixed swatch in BOTH color schemes, so it
|
|
86
|
+
* cannot stay legible in either; route a verdict color through `VX.status.*` / `--vx-status-*`,
|
|
87
|
+
* or drop the index (`c="red"`) and let the theme resolve the shade per scheme. `gray-*`/`dark-*`
|
|
88
|
+
* in `var()` form belong to `off-system-surface-var` instead. Default: `true` (ON). Set `false`
|
|
89
|
+
* to disable the `mantine-shade-index` check.
|
|
90
|
+
*/
|
|
91
|
+
mantineShadeIndex?: boolean
|
|
83
92
|
/**
|
|
84
93
|
* Flag raw lowercase JSX layout/surface elements (`div`/`span`/`section`/…) carrying an inline
|
|
85
94
|
* `style={{}}` with a layout/surface property — steer to a Mantine layout primitive
|
|
@@ -348,6 +357,7 @@ export function checkTheme(cwd: string = process.cwd()): number {
|
|
|
348
357
|
spacingSteps: cfg.spacingSteps ?? DEFAULT_GUARD_CONFIG.spacingSteps,
|
|
349
358
|
rawRadius: cfg.rawRadius ?? DEFAULT_GUARD_CONFIG.rawRadius,
|
|
350
359
|
forbiddenAccents: cfg.forbiddenAccents ?? DEFAULT_GUARD_CONFIG.forbiddenAccents,
|
|
360
|
+
mantineShadeIndex: cfg.mantineShadeIndex ?? DEFAULT_GUARD_CONFIG.mantineShadeIndex,
|
|
351
361
|
rawSurface: cfg.rawSurface ?? DEFAULT_GUARD_CONFIG.rawSurface,
|
|
352
362
|
cardWithBorder: cfg.cardWithBorder ?? DEFAULT_GUARD_CONFIG.cardWithBorder,
|
|
353
363
|
offSystemSurfaceVar: cfg.offSystemSurfaceVar ?? DEFAULT_GUARD_CONFIG.offSystemSurfaceVar,
|
|
@@ -1827,6 +1837,7 @@ export async function guardHook(cwd: string = process.cwd()): Promise<number> {
|
|
|
1827
1837
|
spacingSteps: cfg.spacingSteps ?? DEFAULT_GUARD_CONFIG.spacingSteps,
|
|
1828
1838
|
rawRadius: cfg.rawRadius ?? DEFAULT_GUARD_CONFIG.rawRadius,
|
|
1829
1839
|
forbiddenAccents: cfg.forbiddenAccents ?? DEFAULT_GUARD_CONFIG.forbiddenAccents,
|
|
1840
|
+
mantineShadeIndex: cfg.mantineShadeIndex ?? DEFAULT_GUARD_CONFIG.mantineShadeIndex,
|
|
1830
1841
|
rawSurface: cfg.rawSurface ?? DEFAULT_GUARD_CONFIG.rawSurface,
|
|
1831
1842
|
cardWithBorder: cfg.cardWithBorder ?? DEFAULT_GUARD_CONFIG.cardWithBorder,
|
|
1832
1843
|
offSystemSurfaceVar: cfg.offSystemSurfaceVar ?? DEFAULT_GUARD_CONFIG.offSystemSurfaceVar,
|
package/src/dashboard/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { DeltaBadge, type DeltaBadgeProps } from './delta-badge'
|
|
2
|
-
export { StatCard, type StatCardProps } from './stat-card'
|
|
2
|
+
export { StatCard, type StatCardProps, type StatCardTone } from './stat-card'
|
|
3
3
|
export { EmptyState, type EmptyStateProps } from './empty-state'
|
|
4
4
|
export {
|
|
5
5
|
SettingsSection,
|
|
@@ -8,6 +8,15 @@
|
|
|
8
8
|
* `src/dashboard` stays @visx-free — `sparkline` is a plain `ReactNode` slot, never a chart import
|
|
9
9
|
* here. Pass a `LineSparkline`/`BarSparkline` from `basalt-ui/charts` at the call site.
|
|
10
10
|
*
|
|
11
|
+
* `tone` marks the card as past a threshold with an accent rail down its leading edge. It exists
|
|
12
|
+
* because `value` is typed `string`: without it, a card whose number has crossed a threshold reads
|
|
13
|
+
* exactly as calm as one that hasn't, and the only way out from the consumer side is to wrap the
|
|
14
|
+
* card in a hand-rolled positioned `<Box>` — which is a second card idiom in the app, drawn by code
|
|
15
|
+
* the guard has no way to recognize as one. The rail is the largest signal available without
|
|
16
|
+
* touching the value's own type: full card height, overlaying the card's edge rather than adding to
|
|
17
|
+
* it, so layout is unchanged. `undefined` renders nothing at all — absence of a reading is neither a
|
|
18
|
+
* good one nor a bad one, and must never be tinted.
|
|
19
|
+
*
|
|
11
20
|
* @example
|
|
12
21
|
* import { StatCard } from 'basalt-ui'
|
|
13
22
|
* import { LineSparkline } from 'basalt-ui/charts'
|
|
@@ -18,12 +27,28 @@
|
|
|
18
27
|
* delta={4.2}
|
|
19
28
|
* sparkline={<LineSparkline data={history} width={160} height={32} />}
|
|
20
29
|
* />
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // Past a threshold — an accent rail down the leading edge, value untouched.
|
|
33
|
+
* <StatCard label="Downtime" value="29 min" tone="bad" />
|
|
21
34
|
*/
|
|
22
|
-
import { Card, Group } from '@mantine/core'
|
|
35
|
+
import { Box, Card, Group, VisuallyHidden } from '@mantine/core'
|
|
23
36
|
import type { ReactNode } from 'react'
|
|
24
37
|
import { DeltaBadge } from './delta-badge'
|
|
25
38
|
import { VX } from '../tokens'
|
|
26
39
|
|
|
40
|
+
/** A threshold verdict on the card's value. `undefined` is never tinted — see the module docblock. */
|
|
41
|
+
export type StatCardTone = 'warn' | 'bad'
|
|
42
|
+
|
|
43
|
+
/** The rail's width, in px. Wide enough to read as a deliberate mark at a glance, narrow enough
|
|
44
|
+
* that it cannot be mistaken for the card's own edge. */
|
|
45
|
+
const TONE_RAIL_WIDTH = 3
|
|
46
|
+
|
|
47
|
+
const TONE_LABEL: Record<StatCardTone, string> = {
|
|
48
|
+
warn: 'Past the warning threshold',
|
|
49
|
+
bad: 'Past the severe threshold',
|
|
50
|
+
}
|
|
51
|
+
|
|
27
52
|
export type StatCardProps = {
|
|
28
53
|
/** Mono uppercase micro-label (docs/DESIGN-SPEC.md §3: 12.5px, tracking 0.06em, faint). */
|
|
29
54
|
label: string
|
|
@@ -38,9 +63,20 @@ export type StatCardProps = {
|
|
|
38
63
|
sparkline?: ReactNode
|
|
39
64
|
/** Optional header-right slot (e.g. a ghost "..." menu trigger) — consumer-owned. */
|
|
40
65
|
menu?: ReactNode
|
|
66
|
+
/** Threshold verdict — draws an accent rail down the card's leading edge and announces itself to
|
|
67
|
+
* assistive tech. Omit it for a reading that is fine, and for one that is absent. */
|
|
68
|
+
tone?: StatCardTone
|
|
41
69
|
}
|
|
42
70
|
|
|
43
|
-
export function StatCard({
|
|
71
|
+
export function StatCard({
|
|
72
|
+
label,
|
|
73
|
+
value,
|
|
74
|
+
delta,
|
|
75
|
+
deltaPeriod,
|
|
76
|
+
sparkline,
|
|
77
|
+
menu,
|
|
78
|
+
tone,
|
|
79
|
+
}: StatCardProps) {
|
|
44
80
|
return (
|
|
45
81
|
<Card
|
|
46
82
|
style={{
|
|
@@ -56,8 +92,31 @@ export function StatCard({ label, value, delta, deltaPeriod, sparkline, menu }:
|
|
|
56
92
|
flexDirection: 'column',
|
|
57
93
|
gap: 'var(--vx-space-stat-card-gap)',
|
|
58
94
|
overflow: 'hidden',
|
|
95
|
+
// Anchors the tone rail. Set unconditionally so a card's stacking context does not change
|
|
96
|
+
// depending on whether it happens to have crossed a threshold this render.
|
|
97
|
+
position: 'relative',
|
|
59
98
|
}}
|
|
99
|
+
data-tone={tone}
|
|
60
100
|
>
|
|
101
|
+
{tone !== undefined && (
|
|
102
|
+
<>
|
|
103
|
+
{/* The rail is decoration; the verdict it encodes is real information, so it is also
|
|
104
|
+
stated in text for anyone who cannot see a 3px colour bar. Colour alone is never the
|
|
105
|
+
only carrier of a threshold. */}
|
|
106
|
+
<VisuallyHidden>{TONE_LABEL[tone]}</VisuallyHidden>
|
|
107
|
+
<Box
|
|
108
|
+
aria-hidden="true"
|
|
109
|
+
style={{
|
|
110
|
+
position: 'absolute',
|
|
111
|
+
insetBlock: 0,
|
|
112
|
+
insetInlineStart: 0,
|
|
113
|
+
width: TONE_RAIL_WIDTH,
|
|
114
|
+
background: tone === 'bad' ? VX.status.bad : VX.status.warn,
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
</>
|
|
118
|
+
)}
|
|
119
|
+
|
|
61
120
|
<Group justify="space-between" align="flex-start" wrap="nowrap" gap="xs">
|
|
62
121
|
<span
|
|
63
122
|
style={{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Unit tests for checkSource — the pure (text, relPath, cfg) → Finding[] core.
|
|
3
3
|
*
|
|
4
|
-
* Covers all
|
|
4
|
+
* Covers all 20 guard kinds. Co-located with the guard, excluded from tsc
|
|
5
5
|
* (tsconfig exclude: src/**\/*.test.ts), run via `bun test`.
|
|
6
6
|
*
|
|
7
7
|
* The walker/reporter half is covered by the integration test in
|
|
@@ -154,6 +154,68 @@ describe('off-identity-accent', () => {
|
|
|
154
154
|
})
|
|
155
155
|
})
|
|
156
156
|
|
|
157
|
+
// ── 4b. mantine-shade-index ──────────────────────────────────────────────────
|
|
158
|
+
|
|
159
|
+
describe('mantine-shade-index', () => {
|
|
160
|
+
it('flags a shade-pinned text color (c="yellow.7")', () => {
|
|
161
|
+
const f = find(`<Text c="yellow.7">stale</Text>`)
|
|
162
|
+
expect(kinds(f)).toContain('mantine-shade-index')
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
it('flags bg="blue.4" and color="red.6"', () => {
|
|
166
|
+
expect(kinds(find(`<Box bg="blue.4" />`))).toContain('mantine-shade-index')
|
|
167
|
+
expect(kinds(find(`<ThemeIcon color="red.6" />`))).toContain('mantine-shade-index')
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('flags the var() form for a non-surface hue', () => {
|
|
171
|
+
const f = find(`const a = { color: 'var(--mantine-color-yellow-7)' }`)
|
|
172
|
+
expect(kinds(f)).toContain('mantine-shade-index')
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
it('flags the var() form in a .css file too — unlike the prop-only kinds', () => {
|
|
176
|
+
const f = find(`.a { color: var(--mantine-color-red-6); }`, 'src/app.css')
|
|
177
|
+
expect(kinds(f)).toContain('mantine-shade-index')
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
// The two kinds partition the space: gray/dark var() steps are surface color and belong to
|
|
181
|
+
// off-system-surface-var, so a single violation must never report under both.
|
|
182
|
+
it('leaves gray/dark var() steps to off-system-surface-var', () => {
|
|
183
|
+
const f = find(`const a = { background: 'var(--mantine-color-gray-3)' }`)
|
|
184
|
+
expect(kinds(f)).toContain('off-system-surface-var')
|
|
185
|
+
expect(kinds(f)).not.toContain('mantine-shade-index')
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
it('does NOT flag a bare status hue — it resolves per scheme, which is the point', () => {
|
|
189
|
+
expect(kinds(find(`<Text c="red">down</Text>`))).not.toContain('mantine-shade-index')
|
|
190
|
+
expect(kinds(find(`<ThemeIcon color="green" />`))).not.toContain('mantine-shade-index')
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('does NOT flag c="dimmed" or a token ref', () => {
|
|
194
|
+
expect(kinds(find(`<Text c="dimmed">age</Text>`))).not.toContain('mantine-shade-index')
|
|
195
|
+
expect(kinds(find(`<Text c={VX.status.warn}>age</Text>`))).not.toContain('mantine-shade-index')
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
it('does NOT flag a theme-allow line', () => {
|
|
199
|
+
const f = find(`<Text c="yellow.7" /> // theme-allow: design exception`)
|
|
200
|
+
expect(kinds(f)).not.toContain('mantine-shade-index')
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
it('is disabled by the mantineShadeIndex knob', () => {
|
|
204
|
+
const f = checkSource(`<Text c="yellow.7" />`, PATH, {
|
|
205
|
+
...DEFAULT_GUARD_CONFIG,
|
|
206
|
+
mantineShadeIndex: false,
|
|
207
|
+
})
|
|
208
|
+
expect(kinds(f)).not.toContain('mantine-shade-index')
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
// The grace-minor doctrine (package CLAUDE.md): a kind that rejects previously-passing code
|
|
212
|
+
// lands as `warn` for one minor. Deleting its GRACE_PERIOD_KINDS entry in 1.7.0 flips this.
|
|
213
|
+
it('lands as a warning, not an error, for its grace minor', () => {
|
|
214
|
+
const f = find(`<Text c="yellow.7" />`)
|
|
215
|
+
expect(f.find((x) => x.kind === 'mantine-shade-index')?.severity).toBe('warn')
|
|
216
|
+
})
|
|
217
|
+
})
|
|
218
|
+
|
|
157
219
|
// ── 5. raw-spacing ───────────────────────────────────────────────────────────
|
|
158
220
|
|
|
159
221
|
describe('raw-spacing', () => {
|
package/src/guard/index.ts
CHANGED
|
@@ -58,6 +58,20 @@ const WITH_BORDER_PROP = /\bwithBorder\b(?!\s*=\s*\{\s*false\s*\})/
|
|
|
58
58
|
// Raw Mantine ramp step used for surface color — gray/dark + a step digit.
|
|
59
59
|
const OFF_SYSTEM_SURFACE_VAR = /var\(--mantine-color-(gray|dark)-\d/g
|
|
60
60
|
|
|
61
|
+
// A SHADE-PINNED Mantine color: the dotted JSX form (`c="yellow.7"`) or the var() form
|
|
62
|
+
// (`var(--mantine-color-red-6)`). Both name one fixed swatch that does NOT flip across color
|
|
63
|
+
// schemes — see the `mantineShadeIndex` doc in guard/types.ts for why the bare hue name is fine and
|
|
64
|
+
// the pinned step is not.
|
|
65
|
+
//
|
|
66
|
+
// The var() half deliberately excludes gray-/dark-, which `off-system-surface-var` already owns, so
|
|
67
|
+
// a surface violation reports once under one kind rather than twice under two.
|
|
68
|
+
//
|
|
69
|
+
// The JSX half is prop-shaped (`c="yellow.7"` needs the `=`), which CSS text has no syntax for, so
|
|
70
|
+
// it cannot fire in a `.css` file; the var() half is a real violation in CSS and is meant to fire
|
|
71
|
+
// there. That split is why this kind, unlike its prop-only neighbours, carries no `appliesTo` gate.
|
|
72
|
+
const MANTINE_SHADE_INDEX =
|
|
73
|
+
/\b(?:color|c|bg|backgroundColor|borderColor)\s*=\s*\{?\s*['"][a-z]+\.\d\b|var\(--mantine-color-(?!gray-|dark-)[a-z]+-\d/g
|
|
74
|
+
|
|
61
75
|
// Raw lowercase JSX layout/surface element with inline style and layout/surface prop — line-scoped.
|
|
62
76
|
const RAW_HTML_TAG = /<(?:div|span|section|header|nav|footer|aside|main|article|ul|ol)\b/
|
|
63
77
|
const INLINE_STYLE = /style=\{\{/
|
|
@@ -241,6 +255,7 @@ export const DEFAULT_GUARD_CONFIG: GuardConfig = {
|
|
|
241
255
|
spacingSteps: DEFAULT_SPACING_STEPS,
|
|
242
256
|
rawRadius: true,
|
|
243
257
|
forbiddenAccents: DEFAULT_FORBIDDEN_ACCENTS,
|
|
258
|
+
mantineShadeIndex: true,
|
|
244
259
|
rawSurface: true,
|
|
245
260
|
cardWithBorder: true,
|
|
246
261
|
offSystemSurfaceVar: true,
|
|
@@ -266,14 +281,18 @@ export const DEFAULT_GUARD_CONFIG: GuardConfig = {
|
|
|
266
281
|
* someone remembering. Adding a kind here is part of shipping it; removing the entry IS the
|
|
267
282
|
* promotion, and belongs in its own commit so the changelog says enforcement got stricter.
|
|
268
283
|
*
|
|
269
|
-
*
|
|
284
|
+
* `mantine-shade-index` landed in 1.7.0 and is the sole entry — it rejects `c="yellow.7"`, which
|
|
285
|
+
* previously passed, and the one real consumer has several. Promote it in 1.8.0 by deleting the
|
|
286
|
+
* entry.
|
|
270
287
|
*
|
|
271
288
|
* @example
|
|
272
289
|
* const GRACE: Partial<Record<GuardKind, string>> = {
|
|
273
290
|
* 'raw-font-family': 'introduced 1.4.0 — promote to error in 1.5.0',
|
|
274
291
|
* }
|
|
275
292
|
*/
|
|
276
|
-
const GRACE_PERIOD_KINDS: Partial<Record<GuardKind, string>> = {
|
|
293
|
+
const GRACE_PERIOD_KINDS: Partial<Record<GuardKind, string>> = {
|
|
294
|
+
'mantine-shade-index': 'introduced 1.7.0 — promote to error in 1.8.0',
|
|
295
|
+
}
|
|
277
296
|
|
|
278
297
|
/** A kind's effective severity: consumer override first, then the grace table, then `error`. */
|
|
279
298
|
function severityOf(kind: GuardKind, cfg: GuardConfig): GuardSeverity {
|
|
@@ -561,7 +580,7 @@ type GuardRule = {
|
|
|
561
580
|
}
|
|
562
581
|
|
|
563
582
|
/**
|
|
564
|
-
* The closed registry of all
|
|
583
|
+
* The closed registry of all 20 guard kinds. The triad test asserts
|
|
565
584
|
* `surface.guardKinds ⊆ keyof GUARD_RULES` at runtime.
|
|
566
585
|
*
|
|
567
586
|
* raw-surface, raw-html-layout, and sub-16-input-font are handled inline in checkSource
|
|
@@ -612,6 +631,13 @@ export const GUARD_RULES = {
|
|
|
612
631
|
appliesTo: (relPath) => !relPath.endsWith('.css'),
|
|
613
632
|
message: 'For an off-identity accent use blue/gray or a status hue (red/green/orange/yellow).',
|
|
614
633
|
},
|
|
634
|
+
'mantine-shade-index': {
|
|
635
|
+
kind: 'mantine-shade-index',
|
|
636
|
+
pattern: MANTINE_SHADE_INDEX,
|
|
637
|
+
enabled: (cfg: GuardConfig) => cfg.mantineShadeIndex,
|
|
638
|
+
message:
|
|
639
|
+
'Shade-pinned Mantine color — one fixed swatch in BOTH color schemes, so it cannot stay legible in either. Use VX.status.* / --vx-status-* for a verdict color, or the bare hue name (c="red") to let the theme resolve the shade per scheme.',
|
|
640
|
+
},
|
|
615
641
|
'raw-spacing': {
|
|
616
642
|
kind: 'raw-spacing',
|
|
617
643
|
pattern: (cfg: GuardConfig) =>
|
|
@@ -842,6 +868,16 @@ export function checkSource(text: string, relPath: string, cfg: GuardConfig): Fi
|
|
|
842
868
|
}
|
|
843
869
|
}
|
|
844
870
|
|
|
871
|
+
// mantine-shade-index — the sibling of off-system-surface-var above, partitioned by hue: that
|
|
872
|
+
// kind owns gray/dark (surface color), this one owns every other shade-pinned step (verdict and
|
|
873
|
+
// accent color). Both halves of the pattern (JSX prop + var()) run in every file type; see the
|
|
874
|
+
// pattern's own comment for why this kind carries no appliesTo gate.
|
|
875
|
+
if (GUARD_RULES['mantine-shade-index'].enabled!(cfg)) {
|
|
876
|
+
for (const m of line.matchAll(GUARD_RULES['mantine-shade-index'].pattern as RegExp)) {
|
|
877
|
+
findings.push({ relPath, line: i + 1, token: m[0], kind: 'mantine-shade-index' })
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
845
881
|
// raw-html-layout: 3-condition conjunction on the same line — gated via GUARD_RULES entry.
|
|
846
882
|
if (
|
|
847
883
|
GUARD_RULES['raw-html-layout'].enabled!(cfg) &&
|
package/src/guard/types.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Guard types — Mantine-free, dependency-free (zero imports beyond TS types).
|
|
3
3
|
*
|
|
4
|
-
* GuardKind is the closed set of
|
|
4
|
+
* GuardKind is the closed set of 20 violation kinds the theme guard can emit.
|
|
5
5
|
* Finding is the structured result per violation, replacing the old `Violation` shape.
|
|
6
6
|
* GuardConfig is the per-run configuration that drives checkSource.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
/** The
|
|
9
|
+
/** The 20 theme-guard violation kinds. */
|
|
10
10
|
export type GuardKind =
|
|
11
11
|
| 'raw-hex'
|
|
12
12
|
| 'raw-color-fn'
|
|
13
13
|
| 'localstorage-theme'
|
|
14
14
|
| 'off-identity-accent'
|
|
15
|
+
| 'mantine-shade-index'
|
|
15
16
|
| 'raw-spacing'
|
|
16
17
|
| 'raw-radius'
|
|
17
18
|
| 'raw-surface'
|
|
@@ -82,6 +83,21 @@ export type GuardConfig = {
|
|
|
82
83
|
readonly rawRadius: boolean
|
|
83
84
|
/** Off-identity Mantine accent families forbidden as chrome accents. */
|
|
84
85
|
readonly forbiddenAccents: readonly string[]
|
|
86
|
+
/**
|
|
87
|
+
* Flag a SHADE-PINNED Mantine color — `c="yellow.7"`, `bg="blue.4"`, `var(--mantine-color-red-6)`.
|
|
88
|
+
*
|
|
89
|
+
* This is the sibling of `off-identity-accent`, and the two are deliberately disjoint. That kind
|
|
90
|
+
* polices WHICH hue you reach for and permits the bare status names (`c="red"`, `color="green"`)
|
|
91
|
+
* on purpose: they resolve through the theme, so they flip correctly across color schemes. This
|
|
92
|
+
* kind polices the SHADE INDEX, which does not — a pinned step is one fixed swatch in both
|
|
93
|
+
* schemes, so a `yellow.7` legible on the dark page is the one that fails contrast on the light
|
|
94
|
+
* one. Status color belongs on `VX.status.*` (`--vx-status-warn|bad|good|…`), which is emitted per
|
|
95
|
+
* scheme.
|
|
96
|
+
*
|
|
97
|
+
* `gray-*`/`dark-*` in `var()` form are excluded here because `off-system-surface-var` already
|
|
98
|
+
* owns them (surface color, its own message). Default true.
|
|
99
|
+
*/
|
|
100
|
+
readonly mantineShadeIndex: boolean
|
|
85
101
|
/** Flag ad-hoc inline surface styling (border/borderRadius/boxShadow literals). Default true. */
|
|
86
102
|
readonly rawSurface: boolean
|
|
87
103
|
/**
|