basalt-ui 1.34.1 → 1.36.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 (93) hide show
  1. package/AGENTS.md +21 -21
  2. package/CHANGELOG.md +24 -0
  3. package/MIGRATING.md +89 -12
  4. package/agent/rules/basalt-controls.md +1 -1
  5. package/agent/rules/basalt-mantine.md +1 -1
  6. package/configs/oxlint-plugin.js +51 -4
  7. package/configs/oxlint-plugin.test.ts +58 -15
  8. package/dist/charts/primitives/ChartFrame.d.ts.map +1 -1
  9. package/dist/charts/primitives/ChartFrame.js +2 -1
  10. package/dist/charts/primitives/ChartLegend.d.ts.map +1 -1
  11. package/dist/charts/primitives/ChartLegend.js +2 -1
  12. package/dist/charts/primitives/chart-tier.d.ts +0 -2
  13. package/dist/charts/primitives/chart-tier.d.ts.map +1 -1
  14. package/dist/charts/primitives/chart-tier.js +0 -5
  15. package/dist/common/index.d.ts +1 -0
  16. package/dist/common/index.d.ts.map +1 -1
  17. package/dist/common/index.js +2 -0
  18. package/dist/common/use-media-query.d.ts +7 -0
  19. package/dist/common/use-media-query.d.ts.map +1 -1
  20. package/dist/common/use-media-query.js +4 -0
  21. package/dist/common/vx-families.d.ts +1 -1
  22. package/dist/{forms → controls}/form-layout.d.ts +1 -1
  23. package/dist/controls/form-layout.d.ts.map +1 -0
  24. package/dist/{forms → controls}/form-layout.js +2 -2
  25. package/dist/controls/index.d.ts +1 -0
  26. package/dist/controls/index.d.ts.map +1 -1
  27. package/dist/controls/index.js +10 -0
  28. package/dist/forms/index.d.ts +37 -7
  29. package/dist/forms/index.d.ts.map +1 -1
  30. package/dist/forms/index.js +10 -2
  31. package/dist/guard/index.d.ts +3 -1
  32. package/dist/guard/index.d.ts.map +1 -1
  33. package/dist/guard/index.js +16 -12
  34. package/dist/index.d.ts +1 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +3 -1
  37. package/dist/provider/index.d.ts +5 -4
  38. package/dist/provider/index.d.ts.map +1 -1
  39. package/dist/shell/app-mobile-nav.d.ts.map +1 -1
  40. package/dist/shell/app-mobile-nav.js +19 -10
  41. package/dist/shell/app-sidebar-account.d.ts.map +1 -1
  42. package/dist/shell/app-sidebar-account.js +1 -0
  43. package/dist/shell/app-sidebar.d.ts.map +1 -1
  44. package/dist/shell/app-sidebar.js +11 -6
  45. package/dist/shell/app-sidebar.module.css +39 -0
  46. package/dist/shell/app-sidebar.module.css.d.ts +3 -0
  47. package/dist/shell/index.d.ts +12 -5
  48. package/dist/shell/index.d.ts.map +1 -1
  49. package/dist/shell/nav-types.d.ts +19 -3
  50. package/dist/shell/nav-types.d.ts.map +1 -1
  51. package/dist/shell/sidebar-block-model.d.ts +3 -3
  52. package/dist/shell/sidebar-block-model.d.ts.map +1 -1
  53. package/dist/shell/sidebar-block-model.js +6 -2
  54. package/dist/shell/sidebar-blocks.d.ts +2 -1
  55. package/dist/shell/sidebar-blocks.d.ts.map +1 -1
  56. package/dist/shell/sidebar-blocks.js +13 -5
  57. package/dist/shell/use-size-class.d.ts.map +1 -1
  58. package/dist/surfaces.d.ts +4 -4
  59. package/dist/surfaces.d.ts.map +1 -1
  60. package/dist/surfaces.js +13 -5
  61. package/dist/tokens/index.d.ts.map +1 -1
  62. package/dist/tokens/index.js +5 -7
  63. package/llms.txt +5 -5
  64. package/package.json +1 -1
  65. package/src/charts/primitives/ChartFrame.tsx +2 -1
  66. package/src/charts/primitives/ChartLegend.tsx +2 -1
  67. package/src/charts/primitives/chart-tier.tsx +0 -6
  68. package/src/common/index.ts +1 -0
  69. package/src/common/use-media-query.ts +10 -0
  70. package/src/common/vx-families.ts +1 -1
  71. package/src/{forms → controls}/form-layout.tsx +7 -5
  72. package/src/controls/index.ts +16 -0
  73. package/src/forms/index.ts +36 -9
  74. package/src/guard/index.ts +35 -29
  75. package/src/index.ts +1 -0
  76. package/src/provider/index.tsx +5 -4
  77. package/src/shell/app-mobile-nav.tsx +34 -15
  78. package/src/shell/app-sidebar-account.tsx +3 -0
  79. package/src/shell/app-sidebar.module.css +39 -0
  80. package/src/shell/app-sidebar.module.css.d.ts +3 -0
  81. package/src/shell/app-sidebar.tsx +13 -6
  82. package/src/shell/index.tsx +12 -5
  83. package/src/shell/nav-types.ts +19 -3
  84. package/src/shell/sidebar-block-model.ts +13 -5
  85. package/src/shell/sidebar-blocks.tsx +30 -5
  86. package/src/shell/use-size-class.ts +6 -4
  87. package/src/surfaces.ts +13 -5
  88. package/src/tokens/index.ts +12 -15
  89. package/dist/forms/form-layout.d.ts.map +0 -1
  90. /package/dist/{forms → controls}/form-layout.module.css +0 -0
  91. /package/dist/{forms → controls}/form-layout.module.css.d.ts +0 -0
  92. /package/src/{forms → controls}/form-layout.module.css +0 -0
  93. /package/src/{forms → controls}/form-layout.module.css.d.ts +0 -0
@@ -139,9 +139,10 @@ export type SidebarProgressBlock = {
139
139
  }
140
140
 
141
141
  /**
142
- * DESKTOP ONLY — arbitrary consumer content (a tree, a filter panel) that no set of rows can
143
- * express. Replaced `BasaltShellProps.sidebarNavExtra`; hidden on the collapsed rail and absent
144
- * from mobile for the same reason that prop was.
142
+ * Arbitrary consumer content (a tree, a filter panel) that no set of rows can express. Replaced
143
+ * `BasaltShellProps.sidebarNavExtra`. By default desktop-only and hidden on the collapsed rail,
144
+ * exactly as that prop was; `icon` + `label` opt it into the rail (as an icon opening the node in a
145
+ * popover) and `mobile: 'more'` into the More sheet.
145
146
  */
146
147
  export type SidebarCustomBlock = {
147
148
  kind: 'custom'
@@ -149,6 +150,21 @@ export type SidebarCustomBlock = {
149
150
  node: ReactNode
150
151
  /** @default 'nav' */
151
152
  placement?: 'nav' | 'bottom'
153
+ /** The rail icon. Needs `label` too: an icon-only trigger must be nameable. */
154
+ icon?: ReactNode
155
+ /** The rail icon's accessible name, the popover heading and the More row / sheet title. */
156
+ label?: string
157
+ /**
158
+ * Collapsed-rail projection: `'icon'` swaps the node for `icon`, which opens it in a popover.
159
+ * @default 'icon' when both `icon` and `label` are set, `'hidden'` otherwise
160
+ */
161
+ rail?: 'icon' | 'hidden'
162
+ /**
163
+ * Below `sm` there is no sidebar: `'more'` makes one More row, labelled `label`, that opens the
164
+ * node in a sheet. Needs `label`.
165
+ * @default 'hidden'
166
+ */
167
+ mobile?: 'more' | 'hidden'
152
168
  }
153
169
 
154
170
  /**
@@ -26,11 +26,17 @@ export function sidebarBlockPlacement(block: SidebarBlock): 'nav' | 'bottom' {
26
26
  /**
27
27
  * The collapsed-rail projection. A list block earns a dot only when it carries a `count` — a rail
28
28
  * icon with no number behind it is a dot that means nothing — and a progress block a ring on the
29
- * settings row. A `custom` block has no rail representation at all (arbitrary content in ~48px of
30
- * icon column), which is exactly what `sidebarNavExtra` did before it.
29
+ * settings row. A `custom` block has a rail form only when it opts in (see below), which is
30
+ * `sidebarNavExtra`'s old hidden-in-the-rail behaviour otherwise.
31
31
  */
32
- export function sidebarBlockRail(block: SidebarBlock): 'dot' | 'ring' | 'hidden' {
33
- if (block.kind === 'custom') return 'hidden'
32
+ export function sidebarBlockRail(block: SidebarBlock): 'dot' | 'ring' | 'icon' | 'hidden' {
33
+ // A `custom` block is arbitrary content with no icon-column form of its own, so it is hidden
34
+ // unless the consumer supplied the icon AND the name that make a rail trigger. Like a list's dot,
35
+ // that overrides an explicit `rail: 'icon'` without them.
36
+ if (block.kind === 'custom') {
37
+ if (block.icon === undefined || block.label === undefined) return 'hidden'
38
+ return block.rail ?? 'icon'
39
+ }
34
40
  if (block.kind === 'progress') return block.rail ?? 'ring'
35
41
  // A dot has to sit ON something. With no `icon` there is no rail node to badge, and with no
36
42
  // `count` there is no number behind the dot — either way the block leaves the rail rather than
@@ -47,7 +53,9 @@ export function sidebarBlockRail(block: SidebarBlock): 'dot' | 'ring' | 'hidden'
47
53
  * threshold is measured against.
48
54
  */
49
55
  export function sidebarBlockMobile(block: SidebarBlock): 'more' | 'hidden' {
50
- if (block.kind === 'custom') return 'hidden'
56
+ // A custom block's More row is named by `label`; without one there is nothing to name it.
57
+ if (block.kind === 'custom')
58
+ return block.mobile === 'more' && block.label !== undefined ? 'more' : 'hidden'
51
59
  if (block.kind === 'progress') return block.mobile ?? 'hidden'
52
60
  return block.mobile ?? 'more'
53
61
  }
@@ -12,7 +12,7 @@
12
12
  * module's class. A second CSS module would hash `.block*` into a different name than the rail
13
13
  * rules could ever select.
14
14
  */
15
- import { Collapse, NavLink, Progress, Text, UnstyledButton } from '@mantine/core'
15
+ import { Collapse, NavLink, Popover, Progress, Text, UnstyledButton } from '@mantine/core'
16
16
  import { useState } from 'react'
17
17
  import type { ReactNode } from 'react'
18
18
  import type {
@@ -280,10 +280,33 @@ function ProgressBlock({ block }: { block: SidebarProgressBlock }) {
280
280
  )
281
281
  }
282
282
 
283
- /** A `kind: 'custom'` block — consumer content, hidden on the rail exactly as `navExtra` was. */
284
- function CustomBlock({ block }: { block: SidebarCustomBlock }) {
283
+ /**
284
+ * A `kind: 'custom'` block — consumer content. Without `icon` + `label` it is hidden on the rail
285
+ * exactly as `navExtra` was (CSS only, the node stays mounted). With them the rail swaps the node
286
+ * for its icon, which opens the node in a popover: that swap is JS-gated on `collapsed`, because
287
+ * the trigger is a different element and nothing in the node's own subtree could express it. The
288
+ * popover mounts only while open, so the inline node is never duplicated.
289
+ */
290
+ function CustomBlock({ block, collapsed }: { block: SidebarCustomBlock; collapsed: boolean }) {
291
+ const rail = sidebarBlockRail(block)
292
+ if (collapsed && rail === 'icon') {
293
+ return (
294
+ <div className={classes.block} data-rail="icon">
295
+ <Popover position="right-start" withArrow={false} offset={4} withinPortal zIndex={400}>
296
+ <Popover.Target>
297
+ <UnstyledButton className={classes.blockRailTrigger} aria-label={block.label}>
298
+ <IconSlot>{block.icon}</IconSlot>
299
+ </UnstyledButton>
300
+ </Popover.Target>
301
+ <Popover.Dropdown p="xs" className={classes.blockRailPopover}>
302
+ {block.node}
303
+ </Popover.Dropdown>
304
+ </Popover>
305
+ </div>
306
+ )
307
+ }
285
308
  return (
286
- <div className={classes.block} data-rail="hidden">
309
+ <div className={classes.block} data-rail={rail}>
287
310
  {block.node}
288
311
  </div>
289
312
  )
@@ -292,10 +315,12 @@ function CustomBlock({ block }: { block: SidebarCustomBlock }) {
292
315
  /** One block, whichever kind it is. `AppSidebar` places it; this decides nothing but the paint. */
293
316
  export function SidebarBlockView({
294
317
  block,
318
+ collapsed = false,
295
319
  }: {
296
320
  block: SidebarListBlock | SidebarProgressBlock | SidebarCustomBlock
321
+ collapsed?: boolean
297
322
  }) {
298
323
  if (block.kind === 'list') return <ListBlock block={block} />
299
324
  if (block.kind === 'progress') return <ProgressBlock block={block} />
300
- return <CustomBlock block={block} />
325
+ return <CustomBlock block={block} collapsed={collapsed} />
301
326
  }
@@ -4,10 +4,12 @@
4
4
  * `'compact' | 'medium' | 'expanded'`, for the JS reads CSS cannot express (portal targets,
5
5
  * mount-one-of-two branches). Shell-only — components size by container, not by this.
6
6
  *
7
- * Built on `useMediaQuery` (`common/use-media-query`), one call per class boundary. The server
8
- * snapshot is `<BasaltProvider sizeClassHint>` (default `'compact'`), so SSR, the hydration pass
9
- * and the first client paint agree, and the real class lands one commit later — no first-frame
10
- * flash from a `matchMedia` read inside a `useState` initializer.
7
+ * Built on `useMediaQuery` (`common/use-media-query`), one call per class boundary. A
8
+ * client-rendered app (`createRoot`) reads `matchMedia` on its FIRST render — no hint, no flash, so
9
+ * a mount-one-of-two branch on this hook is flash-free in a CSR SPA (`use-size-class.test.tsx`
10
+ * pins it). Only SSR and the `hydrateRoot` pass read the server snapshot,
11
+ * `<BasaltProvider sizeClassHint>` (default `'compact'`), so server HTML and hydration agree and the
12
+ * real class lands one commit later.
11
13
  */
12
14
  import { createContext, useContext } from 'react'
13
15
  import { useMediaQuery } from '../common/use-media-query'
package/src/surfaces.ts CHANGED
@@ -299,7 +299,7 @@ export const SURFACES = {
299
299
  "no second cssVariablesResolver — don't hand-build createTheme or re-add the resolver basalt already installs",
300
300
  ],
301
301
  description:
302
- '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)',
302
+ 'BasaltProvider, createBasaltTheme, BasaltShell + sidebar/mobile-nav/breadcrumbs, PageBar, PageAside, useSizeClass, useCoarsePointer, 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)',
303
303
  optionalPeers: [
304
304
  'react-markdown',
305
305
  'remark-gfm',
@@ -443,7 +443,7 @@ export const SURFACES = {
443
443
  // consumer ships today (`PLUGIN_RULE_GRACE`).
444
444
  pluginRules: ['forms-field-key'],
445
445
  description:
446
- 'Mantine form layer: useBasaltForm + inputProps/fieldKey (two calls — a spread `key` is a React 19 warning; the deprecated `field` alias for `inputProps` was removed in 1.29.0, C1 consolidation), the FormSection/FormRow/FormGroup/FormActions layout (FormRow is law C1’s form row), useFormSubmit (submit state, decoded errors, server fieldErrors, focus-first-error, validateAsync), FormStateProvider disable propagation, useFieldArray, FormErrorSummary, useFormDraft with autosave (Standard Schema)',
446
+ 'Mantine form layer: useBasaltForm + inputProps/fieldKey (two calls — a spread `key` is a React 19 warning; the deprecated `field` alias for `inputProps` was removed in 1.29.0, C1 consolidation), useFormSubmit (submit state, decoded errors, server fieldErrors, focus-first-error, validateAsync), FormStateProvider disable propagation, useFieldArray, FormErrorSummary, useFormDraft with autosave (Standard Schema). The FormSection/FormRow/FormGroup/FormActions layout moved to ./controls in 1.36.0 and the useForm/schemaResolver re-exports are deprecated (import from @mantine/form); all six stay here until 1.37.0',
447
447
  optionalPeers: ['@mantine/form'],
448
448
  forbiddenImports: [],
449
449
  },
@@ -564,8 +564,8 @@ export const SURFACES = {
564
564
  layer: 'mantine-coupled',
565
565
  rule: 'controls',
566
566
  skill: ['basalt-design'],
567
- // The text lane of law C1 — the plugin's `control-outside-home` seen through a 12-line host-tag
568
- // window, since a regex scan has no ancestry. Same law, same wave, same promotion.
567
+ // The text lane of law C1 — the plugin's `control-outside-home` seen through a host-tag nesting
568
+ // count, since a regex scan has no AST. Same law, same wave, same promotion.
569
569
  guardKinds: ['raw-selection-control'],
570
570
  // The control tier itself (laws C1/C3/C5/C9). `hand-rolled-filter`, `control-size-literal` and
571
571
  // `responsive-twin` all ship `error`; the two C1 placement rules are the grace entries in
@@ -589,7 +589,7 @@ export const SURFACES = {
589
589
  'C12 — one shape for refresh/sync (SyncButton); only the alias table sees a renamed copy',
590
590
  ],
591
591
  description:
592
- 'The control tier (docs/CONTROLS-SPEC.md §3): FilterSet (nowrap row + measured +N fold + the mobile Filters (n) sheet), RangeFilter/CompareFilter/SelectFilter/MultiSelectFilter/NumberFilter/SearchFilter/ToggleFilter (each bound to a FieldHandle — no value/onChange/size, law C2/C5; NumberFilter is the field.number lane, a radio list over `options` or a stepper without), ViewTabs, and the action/sync family (ActionGroup, OverflowMenu, SyncButton, BarAction/GlobalAction). THREE surfaces, picked by the home and never by a prop (useFilterSurface): pill in a PageBar row, sheet in the mobile Filters (n) drawer, panel in a PageAside body — where every control renders an inspector/facet ROW instead of a chip (docs/ASIDE-SPEC.md §3). PanelRow is that row primitive (label above, hint, mono readout, an `end` control on the label line) and SliderControl is the one bound control with no pill form at all; the counts/max props on MultiSelectFilter render the Foundry facet list there. Every control owns its own desktop/mobile swap in CSS (C9) and renders size="ctl" internally. Resolves and renders with NO @mantine/dates installed — the custom date picker is injected through RangeFilter.customPicker from ./controls-dates.',
592
+ 'The control tier (docs/CONTROLS-SPEC.md §3): FilterSet (nowrap row + measured +N fold + the mobile Filters (n) sheet), RangeFilter/CompareFilter/SelectFilter/MultiSelectFilter/NumberFilter/SearchFilter/ToggleFilter (each bound to a FieldHandle — no value/onChange/size, law C2/C5; NumberFilter is the field.number lane, a radio list over `options` or a stepper without), ViewTabs, the action/sync family (ActionGroup, OverflowMenu, SyncButton, BarAction/GlobalAction), and the form layout FormSection/FormRow/FormGroup/FormActions (moved here from ./forms in 1.36.0 — FormRow is law C1’s form row and needs no @mantine/form). THREE surfaces, picked by the home and never by a prop (useFilterSurface): pill in a PageBar row, sheet in the mobile Filters (n) drawer, panel in a PageAside body — where every control renders an inspector/facet ROW instead of a chip (docs/ASIDE-SPEC.md §3). PanelRow is that row primitive (label above, hint, mono readout, an `end` control on the label line) and SliderControl is the one bound control with no pill form at all; the counts/max props on MultiSelectFilter render the Foundry facet list there. Every control owns its own desktop/mobile swap in CSS (C9) and renders size="ctl" internally. Resolves and renders with NO @mantine/dates installed — the custom date picker is injected through RangeFilter.customPicker from ./controls-dates.',
593
593
  optionalPeers: [],
594
594
  // `@mantine/dates` is an optional peer basaltViteConfig pre-bundles the whole @mantine scope
595
595
  // for — a consumer without the peer (linewatch) must never resolve it through this surface.
@@ -608,6 +608,14 @@ export const SURFACES = {
608
608
  '@mantine/dates/*',
609
609
  '@mantine/dates is an OPTIONAL peer (docs/CONTROLS-SPEC.md §3) — ./controls must resolve with no @mantine/dates installed. The one reach lives in src/controls-dates/, injected into range-filter.tsx’s customPicker seam.',
610
610
  ),
611
+ v(
612
+ '@mantine/form',
613
+ '@mantine/form is an OPTIONAL peer — ./controls (which owns the form layout since 1.36.0) must resolve with no @mantine/form installed. Only ./forms needs it.',
614
+ ),
615
+ vg(
616
+ '@mantine/form/*',
617
+ '@mantine/form is an OPTIONAL peer — ./controls (which owns the form layout since 1.36.0) must resolve with no @mantine/form installed. Only ./forms needs it.',
618
+ ),
611
619
  ],
612
620
  },
613
621
  './controls-dates': {
@@ -808,23 +808,20 @@ function frameworkDerived(data: PaletteData, only: 'core' | 'all', legacyAliases
808
808
  return legacyAliases ? `${canonical}\n${frameworkDerivedAliases(data)}` : canonical
809
809
  }
810
810
 
811
- const warnedVxNames = new Set<string>()
812
-
813
811
  /**
814
- * Warn, once per name, on a consumer series/group name inside a basalt-owned `--vx-*` family
815
- * (`surface`, `space`, `ink`, …): `check-theme`'s `unknown-vx-token` judges every name there against
816
- * what basalt emits, which is sound only while no consumer REF points there. A WARNING for the
817
- * minor that kind is graced in (1.34.x), dev builds only; `grace.test.ts` pins the message's
818
- * version to the ledger's `promote` and requires a throw once the kind promotes.
819
- * The families are the guard's own generated `BASALT_VX_FAMILIES`. Checked on the refs, not in
820
- * `buildPaletteCss`, which runs on every first paint.
812
+ * Throw on a consumer series/group name inside a basalt-owned `--vx-*` family (`surface`, `space`,
813
+ * `ink`, …): `check-theme`'s `unknown-vx-token` judges every name there against what basalt emits,
814
+ * which is sound only while no consumer REF points there. Dev builds only (the call sits behind a
815
+ * literal NODE_ENV read); `unknown-vx-token` left the grace ledger at 1.36.0, which is when this
816
+ * went from a once-per-name warning to a throw. The families are the guard's own generated
817
+ * `BASALT_VX_FAMILIES`. Checked on the refs, not in `buildPaletteCss`, which runs on every first
818
+ * paint.
821
819
  */
822
- function warnConsumerVxName(name: string): void {
820
+ function assertConsumerVxName(name: string): void {
823
821
  const family = vxFamilyOf(name)
824
- if (!BASALT_VX_FAMILIES.includes(family) || warnedVxNames.has(name)) return
825
- warnedVxNames.add(name)
826
- console.warn(
827
- `[basalt] ${name} is inside basalt's own --vx-${family} family — name your series group something basalt does not own (groupTokens('app', …)). Throws from 1.35.0.`,
822
+ if (!BASALT_VX_FAMILIES.includes(family)) return
823
+ throw new Error(
824
+ `[basalt] ${name} is inside basalt's own --vx-${family} family — name your series group something basalt does not own (groupTokens('app', …)).`,
828
825
  )
829
826
  }
830
827
 
@@ -842,7 +839,7 @@ export function seriesTokens<const T extends SeriesMap>(
842
839
  const out = {} as { [K in keyof T]: string }
843
840
  for (const key of Object.keys(map) as (keyof T)[]) {
844
841
  // Literal read at the branch, so a production bundle drops the check (common/dev-gate.test.ts).
845
- if (process.env.NODE_ENV !== 'production') warnConsumerVxName(`--vx-${prefix}${String(key)}`)
842
+ if (process.env.NODE_ENV !== 'production') assertConsumerVxName(`--vx-${prefix}${String(key)}`)
846
843
  out[key] = `var(--vx-${prefix}${String(key)})`
847
844
  }
848
845
  return out
@@ -1 +0,0 @@
1
- {"version":3,"file":"form-layout.d.ts","sourceRoot":"","sources":["../../src/forms/form-layout.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAyC1D,gEAAgE;AAChE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAA;AAExD;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,WAAW,GACxC,eAAe,CAAC,eAAe,CAAC,GAChC,sBAAsB,GAAG;IACvB,0DAA0D;IAC1D,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BAoBlD;AAID,4DAA4D;AAC5D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;AAEtD,MAAM,MAAM,YAAY,GAAG,WAAW,GACpC,eAAe,CAAC,WAAW,CAAC,GAAG;IAC7B,4FAA4F;IAC5F,KAAK,EAAE,MAAM,CAAA;IACb,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,oGAAoG;IACpG,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,4FAA4F;IAC5F,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAEH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,+BA0B1C;AAID,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG;IACzC,qGAAqG;IACrG,KAAK,EAAE,MAAM,CAAA;IACb,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAA;IAC5B,+CAA+C;IAC/C,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BAsB9C;AAID,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG;IAC3C;;;;;;;;OAQG;IACH,OAAO,EAAE,WAAW,CAAA;CACrB,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BAgBlD"}
File without changes
File without changes