basalt-ui 1.8.0 → 1.10.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.
Files changed (99) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +25 -0
  3. package/README.md +64 -34
  4. package/agent/rules/basalt-agent.md +49 -6
  5. package/agent/rules/basalt-charts.md +74 -5
  6. package/configs/oxlint-plugin.js +279 -0
  7. package/configs/oxlint-plugin.test.ts +216 -1
  8. package/configs/oxlint.json +5 -2
  9. package/dist/agent/use-agent-thread-runs.d.ts.map +1 -1
  10. package/dist/agent/use-agent-thread-runs.js +1 -0
  11. package/dist/agent-chat/index.d.ts +4 -3
  12. package/dist/agent-chat/index.d.ts.map +1 -1
  13. package/dist/charts/hooks/useHoverSync.d.ts +18 -2
  14. package/dist/charts/hooks/useHoverSync.d.ts.map +1 -1
  15. package/dist/charts/hooks/useHoverSync.js +12 -7
  16. package/dist/charts/index.d.ts +1 -0
  17. package/dist/charts/index.d.ts.map +1 -1
  18. package/dist/charts/index.js +6 -0
  19. package/dist/charts/kinds/Bars.d.ts +2 -0
  20. package/dist/charts/kinds/Bars.d.ts.map +1 -1
  21. package/dist/charts/kinds/Bars.js +3 -1
  22. package/dist/charts/kinds/Donut.d.ts +2 -0
  23. package/dist/charts/kinds/Donut.d.ts.map +1 -1
  24. package/dist/charts/kinds/Donut.js +8 -4
  25. package/dist/charts/kinds/DualPanel.d.ts +2 -0
  26. package/dist/charts/kinds/DualPanel.d.ts.map +1 -1
  27. package/dist/charts/kinds/DualPanel.js +2 -1
  28. package/dist/charts/kinds/Heatmap.d.ts +8 -0
  29. package/dist/charts/kinds/Heatmap.d.ts.map +1 -1
  30. package/dist/charts/kinds/Heatmap.js +7 -3
  31. package/dist/charts/kinds/MultiLine.d.ts +2 -0
  32. package/dist/charts/kinds/MultiLine.d.ts.map +1 -1
  33. package/dist/charts/kinds/MultiLine.js +2 -1
  34. package/dist/charts/kinds/StackedArea.d.ts +2 -0
  35. package/dist/charts/kinds/StackedArea.d.ts.map +1 -1
  36. package/dist/charts/kinds/StackedArea.js +2 -1
  37. package/dist/charts/kinds/ZonedLine.d.ts +2 -0
  38. package/dist/charts/kinds/ZonedLine.d.ts.map +1 -1
  39. package/dist/charts/kinds/ZonedLine.js +2 -1
  40. package/dist/charts/primitives/Axes.d.ts +6 -1
  41. package/dist/charts/primitives/Axes.d.ts.map +1 -1
  42. package/dist/charts/primitives/Axes.js +3 -2
  43. package/dist/charts/primitives/ChartFrame.d.ts +8 -1
  44. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  45. package/dist/charts/primitives/ChartFrame.js +8 -4
  46. package/dist/charts/primitives/ChartPending.d.ts +34 -0
  47. package/dist/charts/primitives/ChartPending.d.ts.map +1 -0
  48. package/dist/charts/primitives/ChartPending.js +23 -0
  49. package/dist/charts/primitives/ChartTooltip.d.ts +5 -2
  50. package/dist/charts/primitives/ChartTooltip.d.ts.map +1 -1
  51. package/dist/charts/primitives/ChartTooltip.js +6 -1
  52. package/dist/charts/primitives/HoverOverlay.d.ts +5 -4
  53. package/dist/charts/primitives/HoverOverlay.d.ts.map +1 -1
  54. package/dist/charts/primitives/HoverOverlay.js +4 -2
  55. package/dist/cli/index.d.ts +55 -1
  56. package/dist/cli/index.d.ts.map +1 -1
  57. package/dist/cli/index.js +217 -5
  58. package/dist/dashboard/stat-card.d.ts.map +1 -1
  59. package/dist/guard/index.d.ts.map +1 -1
  60. package/dist/guard/index.js +13 -5
  61. package/dist/surfaces.d.ts +10 -0
  62. package/dist/surfaces.d.ts.map +1 -1
  63. package/dist/surfaces.js +21 -0
  64. package/llms.txt +9 -2
  65. package/package.json +8 -5
  66. package/src/agent/ai-sdk-transport.test.ts +269 -0
  67. package/src/agent/parts.test.ts +261 -0
  68. package/src/agent/thread.test.ts +147 -0
  69. package/src/agent/use-agent-stream.test.tsx +231 -0
  70. package/src/agent/use-agent-thread-runs.resume.test.tsx +261 -0
  71. package/src/agent/use-agent-thread-runs.test.tsx +398 -0
  72. package/src/agent/use-agent-thread-runs.ts +7 -1
  73. package/src/agent/use-agent-thread-runs.wedge.test.tsx +299 -0
  74. package/src/agent-chat/index.ts +4 -3
  75. package/src/charts/hooks/useHoverSync.ts +43 -7
  76. package/src/charts/index.ts +6 -0
  77. package/src/charts/kinds/Bars.tsx +4 -0
  78. package/src/charts/kinds/Donut.tsx +10 -4
  79. package/src/charts/kinds/DualPanel.tsx +5 -1
  80. package/src/charts/kinds/Heatmap.tsx +19 -2
  81. package/src/charts/kinds/MultiLine.tsx +4 -1
  82. package/src/charts/kinds/StackedArea.tsx +4 -1
  83. package/src/charts/kinds/ZonedLine.tsx +4 -1
  84. package/src/charts/primitives/Axes.tsx +7 -1
  85. package/src/charts/primitives/ChartFrame.test.tsx +67 -0
  86. package/src/charts/primitives/ChartFrame.tsx +17 -4
  87. package/src/charts/primitives/ChartPending.tsx +59 -0
  88. package/src/charts/primitives/ChartTooltip.tsx +15 -3
  89. package/src/charts/primitives/HoverOverlay.tsx +12 -6
  90. package/src/cli/index.ts +439 -5
  91. package/src/cli/placement-engine.test.ts +104 -0
  92. package/src/dashboard/stat-card.test.tsx +5 -3
  93. package/src/dashboard/stat-card.tsx +12 -0
  94. package/src/guard/check-source.test.ts +20 -0
  95. package/src/guard/index.ts +20 -9
  96. package/src/provider/index.test.tsx +6 -5
  97. package/src/surfaces.ts +22 -0
  98. package/src/theme/use-basalt-spacing.test.tsx +7 -4
  99. package/src/tokens/build-fonts-css.test.ts +3 -2
@@ -409,6 +409,16 @@ describe('raw-html-layout', () => {
409
409
  const f = find(`<div style={{ display: 'flex' }} /> // theme-allow`)
410
410
  expect(kinds(f)).not.toContain('raw-html-layout')
411
411
  })
412
+
413
+ it('does NOT flag a raw <div> with inline display:flex in a chart file — the Flex/Grid/Group remedy is @mantine/*, banned in the Mantine-free chart layer', () => {
414
+ const f = find(`<div style={{ display: 'flex', gap: 8 }} />`, CHART_PATH)
415
+ expect(kinds(f)).not.toContain('raw-html-layout')
416
+ })
417
+
418
+ it('still flags the same literal in a non-chart path (the check is not globally weakened)', () => {
419
+ const f = find(`<div style={{ display: 'flex', gap: 8 }} />`, PATH)
420
+ expect(kinds(f)).toContain('raw-html-layout')
421
+ })
412
422
  })
413
423
 
414
424
  // ── 10. inline-spacing ───────────────────────────────────────────────────────
@@ -527,6 +537,16 @@ describe('inline-display', () => {
527
537
  const f = find(`<Box style={{ display: 'flex' }} /> // theme-allow`)
528
538
  expect(kinds(f)).not.toContain('inline-display')
529
539
  })
540
+
541
+ it('does NOT flag display: "flex" in a chart file — the Flex/Grid/Group remedy is @mantine/*, banned in the Mantine-free chart layer', () => {
542
+ const f = find(`<Box style={{ display: 'flex' }} />`, CHART_PATH)
543
+ expect(kinds(f)).not.toContain('inline-display')
544
+ })
545
+
546
+ it('still flags the same literal in a non-chart path (the check is not globally weakened)', () => {
547
+ const f = find(`<Box style={{ display: 'flex' }} />`, PATH)
548
+ expect(kinds(f)).toContain('inline-display')
549
+ })
530
550
  })
531
551
 
532
552
  // ── 12. raw-visx-axis ────────────────────────────────────────────────────────
@@ -282,10 +282,13 @@ export const DEFAULT_GUARD_CONFIG: GuardConfig = {
282
282
  * promotion, and belongs in its own commit so the changelog says enforcement got stricter.
283
283
  *
284
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. Its promotion is **deferred to 1.9.0**:
286
- * 1.8.0 shipped the same day as 1.7.0, so promoting on the next minor number would have given the
287
- * consumer roughly no runway at all — which is the exact failure the grace minor exists to prevent,
288
- * and the runway is measured in consumer upgrades, not in version numbers. Promote it by deleting
285
+ * previously passed, and the one real consumer has several. Its promotion is **deferred to 1.10.0**,
286
+ * for the second time and for the same reason both times: the runway is measured in consumer
287
+ * upgrades, not in version numbers. 1.8.0 shipped the same day as 1.7.0, so promoting there would
288
+ * have given no runway at all. 1.9.0 then carried the chart-layer batch the same consumer asked
289
+ * for — bundling a build-breaking promotion into the minor they upgrade for the fixes turns a
290
+ * routine bump into an unplanned refactor, which is precisely what the grace minor exists to
291
+ * prevent. 1.10.0 is the first minor they can take the promotion on its own. Promote it by deleting
289
292
  * the entry (its own commit).
290
293
  *
291
294
  * @example
@@ -294,7 +297,7 @@ export const DEFAULT_GUARD_CONFIG: GuardConfig = {
294
297
  * }
295
298
  */
296
299
  const GRACE_PERIOD_KINDS: Partial<Record<GuardKind, string>> = {
297
- 'mantine-shade-index': 'introduced 1.7.0 — promote to error in 1.9.0',
300
+ 'mantine-shade-index': 'introduced 1.7.0 — promote to error in 1.10.0',
298
301
  }
299
302
 
300
303
  /** A kind's effective severity: consumer override first, then the grace table, then `error`. */
@@ -688,8 +691,12 @@ export const GUARD_RULES = {
688
691
  kind: 'raw-html-layout',
689
692
  pattern: RAW_HTML_TAG, // handled inline (3-condition conjunction); entry keeps registry complete
690
693
  enabled: (cfg: GuardConfig) => cfg.rawHtmlLayout,
691
- // JSX-tag-shaped (`<div style={{...}}>`) — never appears in CSS text.
692
- appliesTo: (relPath) => !relPath.endsWith('.css'),
694
+ // JSX-tag-shaped (`<div style={{...}}>`) — never appears in CSS text. Also excluded from
695
+ // chart files: the remedy (Box/Flex/Grid/Stack/Group) is `@mantine/*`, and src/charts/** is a
696
+ // lint-enforced Mantine-free layer (basalt/token-layer-boundary) — so inside a chart file the
697
+ // finding is unactionable, not merely inconvenient, and the only "fix" would be a theme-allow
698
+ // comment written inside the very directory this rule protects.
699
+ appliesTo: (relPath) => !isChartFile(relPath) && !relPath.endsWith('.css'),
693
700
  message:
694
701
  'Raw HTML element with inline layout/surface styling — use a Mantine layout primitive (Box/Flex/Grid/Stack/Group).',
695
702
  },
@@ -704,8 +711,12 @@ export const GUARD_RULES = {
704
711
  pattern: INLINE_DISPLAY,
705
712
  enabled: (cfg: GuardConfig) => cfg.inlineDisplay,
706
713
  // JSX-object-shaped (`display: 'flex'`, quoted value) — CSS never quotes a keyword value
707
- // (`display: flex;` is bare), so the pattern's quote anchor can never match real CSS.
708
- appliesTo: (relPath) => !relPath.endsWith('.css'),
714
+ // (`display: flex;` is bare), so the pattern's quote anchor can never match real CSS. Also
715
+ // excluded from chart files: the remedy (Flex/Grid/Group) is `@mantine/*`, and src/charts/**
716
+ // is a lint-enforced Mantine-free layer (basalt/token-layer-boundary) — so inside a chart file
717
+ // the finding is unactionable, not merely inconvenient, and the only "fix" would be a
718
+ // theme-allow comment written inside the very directory this rule protects.
719
+ appliesTo: (relPath) => !isChartFile(relPath) && !relPath.endsWith('.css'),
709
720
  message: 'Use <Flex>/<Grid>/<Group> instead of an inline display:flex/grid.',
710
721
  },
711
722
  'raw-visx-axis': {
@@ -10,11 +10,12 @@
10
10
  * The `BasaltBridge density wiring` block below covers the layer `composeInjectedCss` alone can't:
11
11
  * that `BasaltBridge` (not just the pure `composeInjectedCss` helper) actually reads
12
12
  * `theme.other.basaltDensity` off the RUNNING theme and feeds it through `buildDensityCss` into the
13
- * injected `<style>`, end to end from `createBasaltTheme(undefined, { density })`. No
14
- * `@testing-library/react`/jsdom is configured in this repo (see `tokens/build-fonts-css.test.ts`'s
15
- * doc for that same limitation elsewhere) — `react-dom/server`'s `renderToStaticMarkup` renders the
16
- * real `BasaltProvider` tree without a DOM, which is enough since the injected `<style>` is plain
17
- * text content, not something that needs a live DOM to assert on.
13
+ * injected `<style>`, end to end from `createBasaltTheme(undefined, { density })`. A DOM harness now
14
+ * exists (`tests/setup/dom.ts`, preloaded via the root `bunfig.toml`) — this suite still uses
15
+ * `react-dom/server`'s `renderToStaticMarkup` deliberately, since the injected `<style>` is plain
16
+ * text content on server-rendered markup, not something that needs a live DOM to assert on.
17
+ * Converting this to mount through the DOM harness would only be worth it if a future assertion here
18
+ * needed live DOM behavior (event handling, layout, effects) rather than the static markup string.
18
19
  */
19
20
  import { describe, expect, test } from 'bun:test'
20
21
  import { renderToStaticMarkup } from 'react-dom/server'
package/src/surfaces.ts CHANGED
@@ -371,6 +371,28 @@ export const SURFACES = {
371
371
  // @visx/* ban dropped — `basalt/visx-boundary` now bans it universally outside charts.
372
372
  forbiddenImports: [...MANTINE_BANS],
373
373
  },
374
+ './agent-chat': {
375
+ kind: 'doctrine',
376
+ layer: 'mantine-coupled',
377
+ rule: 'agent',
378
+ skill: ['basalt-app'],
379
+ guardKinds: [],
380
+ description:
381
+ 'Mantine-styled thread-chat components over basalt-ui/agent: ThreadWorkspace, ThreadFeed, ThreadOutcomeCard, ThreadDetailPanel, Composer, ThreadTranscript, threadPartRenderers (Mantine-coupled). remend and motion are required, not optional — ThreadTranscript imports content/markdown.tsx (remend eagerly), and ThreadFeed/ThreadDetailPanel import motion/react eagerly, so this subpath fails to resolve without both installed even though peerDependenciesMeta marks them optional (npm has no per-subpath optionality).',
382
+ optionalPeers: [
383
+ 'ai',
384
+ 'motion',
385
+ 'remend',
386
+ 'use-stick-to-bottom',
387
+ 'react-markdown',
388
+ 'remark-gfm',
389
+ 'shiki',
390
+ '@shikijs/langs',
391
+ '@shikijs/themes',
392
+ 'beautiful-mermaid',
393
+ ],
394
+ forbiddenImports: [],
395
+ },
374
396
  './content': {
375
397
  kind: 'doctrine',
376
398
  layer: 'mantine-coupled',
@@ -6,10 +6,13 @@
6
6
  * with every other density test still green, since those all exercise `deriveSpacing`/
7
7
  * `createBasaltTheme` directly, never this hook.
8
8
  *
9
- * No `@testing-library/react`/jsdom is configured in this repo (see `tokens/build-fonts-css.test.ts`'s
10
- * doc for that same limitation elsewhere) — `react-dom/server`'s `renderToStaticMarkup` is enough to
11
- * invoke a hook inside a REAL `MantineProvider` tree without a DOM, so these assertions exercise the
12
- * actual `useMantineTheme()` read, not a re-implementation of it.
9
+ * A DOM harness now exists (`tests/setup/dom.ts`, preloaded via the root `bunfig.toml`; see
10
+ * `tokens/build-fonts-css.test.ts`'s doc for that same note elsewhere) — this suite still uses
11
+ * `react-dom/server`'s `renderToStaticMarkup` deliberately: it's enough to invoke a hook inside a
12
+ * REAL `MantineProvider` tree without a DOM, so these assertions exercise the actual
13
+ * `useMantineTheme()` read, not a re-implementation of it. Converting to the DOM harness would only
14
+ * be worth it if a future assertion here needed the hook to react to a live DOM event (e.g. a
15
+ * `ResizeObserver`-driven remeasure) rather than a single render-time read.
13
16
  */
14
17
  import { MantineProvider } from '@mantine/core'
15
18
  import type { MantineProviderProps } from '@mantine/core'
@@ -2,8 +2,9 @@
2
2
  * `buildFontsCss` — the pure CSS-building half of the `{ fonts }` option (see
3
3
  * `../theme/fonts-option.test.ts` for the `theme.other.basaltFonts` round-trip this consumes).
4
4
  * `BasaltBridge` calls this directly to append `--basalt-font-*` declarations to the same injected
5
- * `<style>` as the palette CSS; no DOM/render harness is configured in this package, so the pure
6
- * function is the testable seam.
5
+ * `<style>` as the palette CSS. A DOM harness now exists (`tests/setup/dom.ts`, preloaded via the
6
+ * root `bunfig.toml`), but this pure function needs no render at all — it's the testable seam on
7
+ * its own, so this suite calls it directly rather than mounting anything.
7
8
  */
8
9
  import { describe, expect, test } from 'bun:test'
9
10
  import { buildFontsCss } from './index'