@cueplusplus/ui 0.8.0 → 0.9.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 (60) hide show
  1. package/CHANGELOG.md +262 -0
  2. package/README.md +49 -0
  3. package/dist/chat/message-list.js +2 -1
  4. package/dist/configurator/_export.d.ts +1 -1
  5. package/dist/configurator/_export.js +53 -13
  6. package/dist/configurator/_overrides.d.ts +25 -6
  7. package/dist/configurator/_overrides.js +30 -17
  8. package/dist/configurator/configurator.js +8 -3
  9. package/dist/configurator/panel-sections.js +43 -13
  10. package/dist/elements/command-palette.js +1 -1
  11. package/dist/elements/flow-graph.js +2 -2
  12. package/dist/elements/markdown.js +1 -1
  13. package/dist/elements/surfaces.js +4 -3
  14. package/dist/index.d.ts +5 -2
  15. package/dist/index.js +2 -1
  16. package/dist/midi/piano-keyboard.js +5 -1
  17. package/dist/primitives/chip.d.ts +1 -1
  18. package/dist/styles.css +23 -1
  19. package/dist/system/density.d.ts +17 -8
  20. package/dist/system/density.js +39 -16
  21. package/dist/system/index.d.ts +5 -2
  22. package/dist/system/index.js +2 -1
  23. package/dist/system/overrides.d.ts +43 -0
  24. package/dist/system/overrides.js +238 -0
  25. package/dist/system/portal.d.ts +4 -2
  26. package/dist/system/portal.js +34 -3
  27. package/dist/system/prepaint.d.ts +58 -7
  28. package/dist/system/prepaint.js +72 -20
  29. package/dist/system/theme-provider.d.ts +133 -8
  30. package/dist/system/theme-provider.js +203 -72
  31. package/dist/system/theme-registry.d.ts +53 -0
  32. package/dist/system/theme-registry.js +66 -0
  33. package/dist/system/use-density.d.ts +13 -5
  34. package/dist/system/use-density.js +142 -13
  35. package/dist/system/use-theme.d.ts +5 -3
  36. package/dist/system/use-theme.js +5 -3
  37. package/dist/system/vocabulary.d.ts +15 -0
  38. package/dist/system/vocabulary.js +111 -0
  39. package/dist/theming/contrast.d.ts +2 -122
  40. package/dist/theming/contrast.js +2 -194
  41. package/dist/theming/create-theme.d.ts +37 -11
  42. package/dist/theming/create-theme.js +54 -17
  43. package/dist/theming/index.d.ts +3 -4
  44. package/dist/theming/index.js +3 -4
  45. package/dist/theming/serialize.d.ts +24 -11
  46. package/dist/theming/serialize.js +16 -18
  47. package/manifest/components/colors-section.json +2 -3
  48. package/manifest/components/cue-portal-frame.json +1 -1
  49. package/manifest/components/density.json +1 -1
  50. package/manifest/components/export-dialog.json +0 -3
  51. package/manifest/components/preset-section.json +2 -3
  52. package/manifest/components/shape-section.json +2 -3
  53. package/manifest/components/theme-configurator.json +0 -3
  54. package/manifest/components/theme-provider.json +24 -9
  55. package/manifest/components/token-editor.json +0 -3
  56. package/manifest/manifest.json +145 -24
  57. package/manifest/tokens.json +121 -11
  58. package/package.json +15 -6
  59. package/dist/theming/_presets.d.ts +0 -11
  60. package/dist/theming/_presets.js +0 -678
@@ -1,22 +1,20 @@
1
1
  "use client";
2
2
  import { cn } from "../lib/cn.js";
3
3
  import { Input } from "../forms/input.js";
4
- import { DENSITY_LEVELS } from "../system/density.js";
4
+ import { useDensities, useThemes } from "../system/theme-registry.js";
5
5
  import { SectionHeader } from "../chrome/section-header.js";
6
6
  import { SegmentedControl } from "../chrome/segmented-control.js";
7
7
  import { Field, FieldLabel } from "../forms/field.js";
8
8
  import { Slider } from "../forms/slider.js";
9
9
  import { Kbd } from "../primitives/kbd.js";
10
10
  import { useTheme } from "../system/use-theme.js";
11
- import { THEME_PRESETS } from "../theming/_presets.js";
12
11
  import { tokenProperty } from "../theming/serialize.js";
13
12
  import { COLOR_TOKENS, FONT_TOKENS, isSafeCssValue } from "./_overrides.js";
14
13
  import { TokenEditor } from "./token-editor.js";
15
14
  import * as React from "react";
16
15
  import { jsx, jsxs } from "react/jsx-runtime";
16
+ import { resolve } from "@cueplusplus/theme-base";
17
17
  //#region src/configurator/panel-sections.tsx
18
- /** The presets, in menu order, with the palette each one is announced by. */
19
- const PRESETS = Object.keys(THEME_PRESETS);
20
18
  /** The five colours a preset is recognisable from, in reading order. */
21
19
  const SWATCH_TOKENS = [
22
20
  "bg",
@@ -44,13 +42,25 @@ const MODE_ITEMS = [
44
42
  * and `Ultra-large` alone are 25 characters — so the segmented control wears
45
43
  * the garment sizes and the value it sets is still the ladder's own name.
46
44
  */
47
- const DENSITY_LABELS = {
45
+ const BASE_DENSITY_LABELS = {
48
46
  "ultra-compact": "XS",
49
47
  "compact": "S",
50
48
  "normal": "M",
51
49
  "large": "L",
52
50
  "ultra-large": "XL"
53
51
  };
52
+ /**
53
+ * What a rung is called in the panel.
54
+ *
55
+ * A lookup rather than a table, because the ladder is open now: a theme may add
56
+ * a rung, and this package has no garment size to give it. Its own name is the
57
+ * only label that is certainly true — longer than a letter, and honest about
58
+ * being the theme's rather than the ladder's. The base five keep their sizes,
59
+ * so nothing a user has learned moves.
60
+ */
61
+ function densityLabel(rung) {
62
+ return BASE_DENSITY_LABELS[rung] ?? rung;
63
+ }
54
64
  /** Bounds of the text-scale knob, from spec §6's `fontScale`. */
55
65
  const FONT_SCALE = {
56
66
  min: .8,
@@ -77,7 +87,16 @@ const FONT_LABELS = {
77
87
  };
78
88
  /** Base UI hands a range slider an array; every slider here has one thumb. */
79
89
  const single = (value) => Array.isArray(value) ? value[0] ?? 0 : value;
80
- /** A number knob wired to one token, live on drag and persisted on release. */
90
+ /**
91
+ * A number knob wired to one token, live on drag and persisted on release.
92
+ *
93
+ * The three it is used for are `--cue-radius-scale` and `--cue-density`, both
94
+ * crossed with the density ladder when they are written, and `--cue-font-scale`,
95
+ * which the provider publishes inline. Naming them here is not decoration: the
96
+ * package manifest's token list is scraped for literal `--cue-*` spellings, and
97
+ * a token whose only spelling in this file is the bare `token="radius-scale"`
98
+ * prop is a token the docs page for this section does not list.
99
+ */
81
100
  function ScaleSlider({ label, token, edits, bounds }) {
82
101
  const value = Number(edits.value(token));
83
102
  return /* @__PURE__ */ jsx(Slider, {
@@ -147,16 +166,27 @@ function TextTokenField({ label, token, edits, placeholder }) {
147
166
  */
148
167
  function PresetSection({ edits, zoom, className }) {
149
168
  const { theme, density, mode, resolvedMode, setTheme, setDensity, setMode } = useTheme();
169
+ const themes = useThemes();
170
+ const densities = useDensities();
150
171
  return /* @__PURE__ */ jsxs(SectionHeader, {
151
172
  label: "Preset",
152
173
  collapsible: true,
153
174
  className,
154
175
  children: [
155
- /* @__PURE__ */ jsx("div", {
176
+ themes.length === 0 ? /* @__PURE__ */ jsxs("p", {
177
+ className: "text-fg-muted text-ui",
178
+ children: [
179
+ "No themes registered — pass ",
180
+ /* @__PURE__ */ jsx("code", { children: "themes" }),
181
+ " to ",
182
+ /* @__PURE__ */ jsx("code", { children: "ThemeProvider" }),
183
+ "."
184
+ ]
185
+ }) : /* @__PURE__ */ jsx("div", {
156
186
  className: "grid grid-cols-2 gap-(--cue-space-2)",
157
- children: PRESETS.map((name) => {
158
- const preset = THEME_PRESETS[name];
159
- const palette = (resolvedMode === "light" ? preset.light : preset.dark) ?? preset.dark;
187
+ children: themes.map((manifest) => {
188
+ const name = manifest.name;
189
+ const palette = resolve(manifest, { mode: resolvedMode }).colors;
160
190
  const active = name === theme;
161
191
  return /* @__PURE__ */ jsxs("button", {
162
192
  type: "button",
@@ -197,9 +227,9 @@ function PresetSection({ edits, zoom, className }) {
197
227
  itemClassName: "flex-1",
198
228
  value: density,
199
229
  onValueChange: (next) => setDensity(next),
200
- items: DENSITY_LEVELS.map((level) => ({
201
- value: level,
202
- label: DENSITY_LABELS[level]
230
+ items: densities.map((rung) => ({
231
+ value: rung.name,
232
+ label: densityLabel(rung.name)
203
233
  }))
204
234
  }),
205
235
  /* @__PURE__ */ jsx(ScaleSlider, {
@@ -32,7 +32,7 @@ function ElementsCommandPalette({ commands, query, activeId, onQueryChange, onAc
32
32
  if (next) onActiveChange?.(next.id);
33
33
  };
34
34
  useEffect(() => {
35
- document.getElementById(optionId(activeId))?.scrollIntoView({ block: "nearest" });
35
+ document.getElementById(`${listId}-${activeId}`)?.scrollIntoView({ block: "nearest" });
36
36
  }, [activeId, listId]);
37
37
  const onKeyDown = (event) => {
38
38
  if (event.nativeEvent.isComposing) return;
@@ -47,7 +47,7 @@ function FlowGraph({ nodes, edges, visibleCount, className, ...props }) {
47
47
  const from = nodes.find((node) => node.id === edge.from);
48
48
  const to = nodes.find((node) => node.id === edge.to);
49
49
  if (!from || !to) return null;
50
- shownIds.has(edge.from) && shownIds.has(edge.to);
50
+ const live = shownIds.has(edge.from) && shownIds.has(edge.to);
51
51
  const a = center(from);
52
52
  const b = center(to);
53
53
  const midX = (a.x + b.x) / 2;
@@ -55,7 +55,7 @@ function FlowGraph({ nodes, edges, visibleCount, className, ...props }) {
55
55
  d: `M ${a.x + NODE_W / 2} ${a.y} C ${midX} ${a.y}, ${midX} ${b.y}, ${b.x - NODE_W / 2} ${b.y}`,
56
56
  fill: "none",
57
57
  strokeWidth: "1.5",
58
- className: cn("transition-opacity duration-500 motion-reduce:transition-none", "stroke-fg-subtle")
58
+ className: cn("transition-opacity duration-500 motion-reduce:transition-none", "stroke-fg-subtle", live ? "opacity-100" : "opacity-30")
59
59
  }, `${edge.from}-${edge.to}`);
60
60
  })
61
61
  }), shown.map((node) => /* @__PURE__ */ jsx("div", {
@@ -130,7 +130,7 @@ function safeUrl(value) {
130
130
  const FENCE = /^ {0,3}(`{3,}|~{3,})/;
131
131
  /** Whether a character can sit next to a delimiter run without closing a word. */
132
132
  function isBoundary(char) {
133
- return char === "" || /[\s!-\/:-@[-`{-~]/.test(char);
133
+ return char === "" || /[\s!-/:-@[-`{-~]/.test(char);
134
134
  }
135
135
  /**
136
136
  * Where the last block of `source` begins: after the final blank line that is
@@ -80,10 +80,11 @@ function ShimmerLabel({ active = true, className, ...props }) {
80
80
  * announced nor copied into a selection.
81
81
  */
82
82
  function SwapLabel({ active, children, className }) {
83
- const layers = [useRef(null), useRef(null)];
83
+ const restingRef = useRef(null);
84
+ const activeRef = useRef(null);
84
85
  const [width, setWidth] = useState(null);
85
86
  useLayoutEffect(() => {
86
- const target = layers[active]?.current;
87
+ const target = (active === 0 ? restingRef : activeRef).current;
87
88
  if (!target) return void 0;
88
89
  const measure = () => setWidth(Math.ceil(target.getBoundingClientRect().width));
89
90
  measure();
@@ -96,7 +97,7 @@ function SwapLabel({ active, children, className }) {
96
97
  style: width === null ? void 0 : { width },
97
98
  className: cn("grid overflow-x-clip transition-[width] duration-300 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none", className),
98
99
  children: children.map((layer, index) => /* @__PURE__ */ jsx("span", {
99
- ref: layers[index],
100
+ ref: index === 0 ? restingRef : activeRef,
100
101
  "aria-hidden": active !== index,
101
102
  className: cn(labelSwap, active === index ? labelSwapIn : labelSwapOut),
102
103
  children: layer
package/dist/index.d.ts CHANGED
@@ -33,6 +33,7 @@ import { Tree, TreeProps, TreeVisibility, TreeVisibilityToggle, TreeVisibilityTo
33
33
  import { Toolbar, ToolbarButtonProps, ToolbarGroupProps, ToolbarRootProps, ToolbarSeparatorProps } from "./chrome/toolbar.js";
34
34
  import "./chrome/index.js";
35
35
  import { ControlVariantProps, FormControlSize, bareControlClasses, controlClasses, controlGroupFocusClasses, controlSurface, controlVariants } from "./forms/_chassis.js";
36
+ import { TokenOverrides } from "./system/overrides.js";
36
37
  import { FontFamilies, ResolvedMode, ThemeContextValue, ThemeProvider, ThemeProviderProps } from "./system/theme-provider.js";
37
38
  import { Autocomplete, AutocompleteProps } from "./forms/autocomplete.js";
38
39
  import { ButtonGroup, ButtonGroupOrientation, ButtonGroupProps } from "./forms/button-group.js";
@@ -122,7 +123,9 @@ import "./primitives/index.js";
122
123
  import { Density, DensityProps } from "./system/density.js";
123
124
  import { CuePortalFrame, CuePortalFrameProps, useCuePortalProps } from "./system/portal.js";
124
125
  import { DEFAULT_STORAGE_KEY, PersistedPreferences, PrepaintDefaults, PrepaintOptions, prepaintScript } from "./system/prepaint.js";
126
+ import { ThemeRegistry } from "./system/vocabulary.js";
127
+ import { useDensities, useFonts, useThemes } from "./system/theme-registry.js";
125
128
  import { ControlSize, useControlHeight, useDensity } from "./system/use-density.js";
126
129
  import { useTheme } from "./system/use-theme.js";
127
- import { DensityLevel, FontName, Mode, ThemeName } from "./system/index.js";
128
- export { AGENT_COLOR_PROPERTY, AGENT_HUES, AGENT_ROOT_COLOR, Accordion, type AccordionHeaderProps, type AccordionItemProps, type AccordionPanelProps, type AccordionRootProps, type AccordionTriggerProps, type AgentColorOptions, AgentPile, type AgentPileEntry, type AgentPileProps, type AgentPileSize, AlertDialog, type AlertDialogActionProps, type AlertDialogCancelProps, type AlertDialogContentProps, type AlertDialogDescriptionProps, type AlertDialogFooterProps, type AlertDialogRootProps, type AlertDialogTitleProps, type AlertDialogTriggerProps, AppBar, type AppBarActionsProps, type AppBarBrandProps, type AppBarLinkProps, type AppBarNavProps, type AppBarRegister, type AppBarRootProps, type AppBarSeparatorProps, AppShell, type AppShellAsideProps, type AppShellBarProps, type AppShellBodyProps, type AppShellContentProps, type AppShellNavTriggerProps, type AppShellRootProps, type AppShellScrollerProps, type AppShellSidebarProps, AppWindowFrame, type AppWindowFrameProps, type AskAnswer, AskBox, type AskBoxProps, type AskDanger, type AskKind, type AskOption, AudienceIcon, Autocomplete, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarSize, type BarOverflow, type BrandAssetProps, type BrandSize, type BrandTone, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, ButtonGroup, type ButtonGroupOrientation, type ButtonGroupProps, type ButtonProps, Card, type CardContentProps, type CardDescriptionProps, type CardFooterProps, type CardHeaderProps, type CardRootProps, type CardTitleProps, CatalogueIcon, ChannelBetaIcon, ChannelReleasedIcon, Checkbox, CheckboxGroup, type CheckboxGroupProps, type CheckboxProps, Chip, type ChipProps, CliToolIcon, Collapsible, type CollapsiblePanelProps, type CollapsibleRootProps, type CollapsibleTriggerProps, Combobox, type ComboboxOption, type ComboboxProps, CommandPalette, type CommandPaletteItem, type CommandPaletteProps, Composer, type ComposerProps, type ComposerSubmitKey, Container, type ContainerProps, type ContainerWidth, ContextMenu, type ContextMenuContentProps, type ContextMenuRootProps, type ContextMenuTriggerProps, type ControlSize, type ControlVariantProps, CopyButton, type CopyButtonProps, CueLogotype, type CueLogotypeProps, CueMark, type CueMarkProps, CuePortalFrame, type CuePortalFrameProps, DEFAULT_STORAGE_KEY, DataRow, type DataRowDisclosure, type DataRowRootProps, type DataRowSlotProps, DataTree, type DataTreeItem, type DataTreeProps, type DataTreeRowState, DelegationCard, type DelegationCardProps, type DelegationDirection, type DelegationStatus, Density, type DensityLevel, type DensityProps, DescriptionList, type DescriptionListDetailProps, type DescriptionListLayout, type DescriptionListRootProps, type DescriptionListTermProps, Dialog, type DialogCloseProps, type DialogContentProps, type DialogDescriptionProps, type DialogFooterProps, type DialogRootProps, type DialogTitleProps, type DialogTriggerProps, Disclosure, type DisclosureProps, Drawer, type DrawerCloseProps, type DrawerContentProps, type DrawerDescriptionProps, type DrawerFooterProps, type DrawerRootProps, type DrawerSwipeDirection, type DrawerTitleProps, type DrawerTriggerProps, DropdownMenu, type DropdownMenuCheckboxItemProps, type DropdownMenuContentProps, type DropdownMenuGroupProps, type DropdownMenuItemProps, type DropdownMenuLabelProps, type DropdownMenuRootProps, type DropdownMenuSeparatorProps, type DropdownMenuTriggerProps, EmptyState, type EmptyStateProps, EnvVarInput, type EnvVarInputProps, Eyebrow, type EyebrowProps, Field, FieldDescription, type FieldDescriptionProps, FieldError, type FieldErrorProps, type FieldIssue, FieldLabel, type FieldLabelProps, type FieldProps, type FilePartition, type FilePartitionOptions, type FileRejectReason, type FileRejection, FileUpload, type FileUploadProps, FolderIcon, type FontFamilies, type FontName, Footer, type FooterProps, type FormControlSize, Grid, type GridColumns, type GridProps, GroupBar, type GroupBarItem, type GroupBarProps, type GroupBarTone, HoverCard, type HoverCardContentProps, type HoverCardRootProps, type HoverCardTriggerProps, IconButton, type IconButtonProps, InfoTip, type InfoTipProps, Input, InputGroup, type InputGroupProps, type InputProps, Item, type ItemProps, Kbd, type KbdProps, Ledger, type LedgerEmptyProps, type LedgerGroupProps, type LedgerRootProps, type LedgerTierProps, Link, type LinkProps, McpServerIcon, Menubar, type MenubarContentProps, type MenubarMenuProps, type MenubarRootProps, type MenubarTriggerProps, Message, MessageList, type MessageListProps, type MessageProps, type MessageRole, Meter, type MeterProps, type MeterProvenance, type MeterTone, type Mode, MultiSelect, type MultiSelectProps, NavigationMenu, type NavigationMenuContentProps, type NavigationMenuItemProps, type NavigationMenuLinkProps, type NavigationMenuListProps, type NavigationMenuRootProps, type NavigationMenuTriggerProps, type NavigationMenuViewportProps, NumberField, type NumberFieldProps, OTPField, type OTPFieldProps, OVERLAY_SIDE_OFFSET, PageShell, type PageShellProps, type PageWidth, Pagination, type PaginationEntry, type PaginationProps, Panel, PanelHeader, type PanelHeaderProps, type PanelProps, PasswordInput, type PasswordInputProps, type PersistedPreferences, Plussie, type PlussieExpression, type PlussieProps, Popover, type PopoverCloseProps, type PopoverContentProps, type PopoverDescriptionProps, type PopoverRootProps, type PopoverTitleProps, type PopoverTriggerProps, type PrepaintDefaults, type PrepaintOptions, Progress, type ProgressProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, Rating, type RatingProps, type RatingSize, type ResolvedMode, Row, type RowProps, ScrollArea, type ScrollAreaOrientation, type ScrollAreaProps, type ScrollEdges, ScrollableTabsList, type ScrollableTabsListProps, ScrubInput, type ScrubInputProps, SeamCell, type SeamCellProps, SeamGrid, type SeamGridProps, type SeamGround, SeamList, type SeamListProps, SearchInput, type SearchInputProps, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlItem, type SegmentedControlProps, type SegmentedControlSize, Select, type SelectOption, type SelectProps, Separator, type SeparatorProps, Sheet, type SheetCloseProps, type SheetContentProps, type SheetDescriptionProps, type SheetFooterProps, type SheetRootProps, type SheetTitleProps, type SheetTriggerProps, Sidebar, type SidebarItemProps, type SidebarRailProps, type SidebarRootProps, type SidebarSectionProps, Skeleton, type SkeletonProps, SkillIcon, Slider, type SliderProps, type SpaceStep, Sparkline, type SparklineProps, Spinner, type SpinnerProps, Stack, type StackAlign, StackIcon, type StackJustify, type StackProps, StacksMatrixIcon, Stat, type StatProps, type StatTone, StatusBar, type StatusBarGroupProps, type StatusBarItemProps, type StatusBarProminence, type StatusBarProps, type StatusBarTone, StatusDot, type StatusDotProps, type StatusTone, Stepper, type StepperProps, type StepperState, type StepperStep, Switch, type SwitchProps, TAB_FADE_PX, TREE_GUIDE_GLYPHS, Table, type TableCaptionProps, type TableCellProps, type TableGroupRowProps, type TableHeadProps, type TableRootProps, type TableRowProps, TableScrollRegion, type TableScrollRegionProps, type TableSectionProps, Tabs, type TabsListProps, type TabsPanelProps, type TabsRootProps, type TabsTabProps, TagsInput, type TagsInputProps, TerminalFrame, type TerminalFrameLine, type TerminalFrameProps, type TerminalLine, type TerminalLineTone, type TerminalScript, type TerminalStep, Textarea, type TextareaProps, type ThemeContextValue, type ThemeName, ThemeProvider, type ThemeProviderProps, Timeline, type TimelineContentProps, type TimelineItemProps, type TimelineMarkerProps, type TimelineRootProps, TitleBar, type TitleBarProps, Toast, type ToastManager, type ToastOptions, type ToastProviderProps, type ToastTone, type ToastViewportProps, Toggle, ToggleGroup, type ToggleGroupProps, type ToggleProps, Toolbar, type ToolbarButtonProps, type ToolbarGroupProps, type ToolbarRootProps, type ToolbarSeparatorProps, Tooltip, type TooltipContentProps, type TooltipProviderProps, type TooltipRootProps, type TooltipTriggerProps, Tree, type TreeGuide, type TreeItem, type TreeProps, type TreeRow, type TreeVisibility, TreeVisibilityToggle, type TreeVisibilityToggleProps, TwoStepButton, type TwoStepButtonProps, type TwoStepTone, type UploadFile, type UploadStatus, UsageChart, type UsageChartPoint, type UsageChartProps, type UsageChartTone, activateRowFromClick, activateRowFromKeyDown, agentColor, agentColorStyle, bareControlClasses, buttonVariants, chipVariants, computeScrollEdges, controlClasses, controlGroupFocusClasses, controlSurface, controlVariants, edgeFadeMask, envReference, flattenTree, itemVariants, linkVariants, menuItemClasses, menuLabelClasses, menuPopupClasses, menuSeparatorClasses, overlayDescriptionClasses, overlayFooterClasses, overlayModalTransitionClasses, overlayPopupTransitionClasses, overlayPositionerClasses, overlaySurfaceClasses, overlayTextClasses, overlayTitleClasses, paginationRange, parseEnvReference, partitionFiles, prepaintScript, rowVariants, scrimClasses, useControlHeight, useCuePortalProps, useDensity, useSidebar, useTheme, useToast };
130
+ import { DensityEntry, DensityLevel, FontEntry, FontName, Mode, ThemeManifest, ThemeName } from "./system/index.js";
131
+ export { AGENT_COLOR_PROPERTY, AGENT_HUES, AGENT_ROOT_COLOR, Accordion, type AccordionHeaderProps, type AccordionItemProps, type AccordionPanelProps, type AccordionRootProps, type AccordionTriggerProps, type AgentColorOptions, AgentPile, type AgentPileEntry, type AgentPileProps, type AgentPileSize, AlertDialog, type AlertDialogActionProps, type AlertDialogCancelProps, type AlertDialogContentProps, type AlertDialogDescriptionProps, type AlertDialogFooterProps, type AlertDialogRootProps, type AlertDialogTitleProps, type AlertDialogTriggerProps, AppBar, type AppBarActionsProps, type AppBarBrandProps, type AppBarLinkProps, type AppBarNavProps, type AppBarRegister, type AppBarRootProps, type AppBarSeparatorProps, AppShell, type AppShellAsideProps, type AppShellBarProps, type AppShellBodyProps, type AppShellContentProps, type AppShellNavTriggerProps, type AppShellRootProps, type AppShellScrollerProps, type AppShellSidebarProps, AppWindowFrame, type AppWindowFrameProps, type AskAnswer, AskBox, type AskBoxProps, type AskDanger, type AskKind, type AskOption, AudienceIcon, Autocomplete, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, type AvatarSize, type BarOverflow, type BrandAssetProps, type BrandSize, type BrandTone, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, ButtonGroup, type ButtonGroupOrientation, type ButtonGroupProps, type ButtonProps, Card, type CardContentProps, type CardDescriptionProps, type CardFooterProps, type CardHeaderProps, type CardRootProps, type CardTitleProps, CatalogueIcon, ChannelBetaIcon, ChannelReleasedIcon, Checkbox, CheckboxGroup, type CheckboxGroupProps, type CheckboxProps, Chip, type ChipProps, CliToolIcon, Collapsible, type CollapsiblePanelProps, type CollapsibleRootProps, type CollapsibleTriggerProps, Combobox, type ComboboxOption, type ComboboxProps, CommandPalette, type CommandPaletteItem, type CommandPaletteProps, Composer, type ComposerProps, type ComposerSubmitKey, Container, type ContainerProps, type ContainerWidth, ContextMenu, type ContextMenuContentProps, type ContextMenuRootProps, type ContextMenuTriggerProps, type ControlSize, type ControlVariantProps, CopyButton, type CopyButtonProps, CueLogotype, type CueLogotypeProps, CueMark, type CueMarkProps, CuePortalFrame, type CuePortalFrameProps, DEFAULT_STORAGE_KEY, DataRow, type DataRowDisclosure, type DataRowRootProps, type DataRowSlotProps, DataTree, type DataTreeItem, type DataTreeProps, type DataTreeRowState, DelegationCard, type DelegationCardProps, type DelegationDirection, type DelegationStatus, Density, type DensityEntry, type DensityLevel, type DensityProps, DescriptionList, type DescriptionListDetailProps, type DescriptionListLayout, type DescriptionListRootProps, type DescriptionListTermProps, Dialog, type DialogCloseProps, type DialogContentProps, type DialogDescriptionProps, type DialogFooterProps, type DialogRootProps, type DialogTitleProps, type DialogTriggerProps, Disclosure, type DisclosureProps, Drawer, type DrawerCloseProps, type DrawerContentProps, type DrawerDescriptionProps, type DrawerFooterProps, type DrawerRootProps, type DrawerSwipeDirection, type DrawerTitleProps, type DrawerTriggerProps, DropdownMenu, type DropdownMenuCheckboxItemProps, type DropdownMenuContentProps, type DropdownMenuGroupProps, type DropdownMenuItemProps, type DropdownMenuLabelProps, type DropdownMenuRootProps, type DropdownMenuSeparatorProps, type DropdownMenuTriggerProps, EmptyState, type EmptyStateProps, EnvVarInput, type EnvVarInputProps, Eyebrow, type EyebrowProps, Field, FieldDescription, type FieldDescriptionProps, FieldError, type FieldErrorProps, type FieldIssue, FieldLabel, type FieldLabelProps, type FieldProps, type FilePartition, type FilePartitionOptions, type FileRejectReason, type FileRejection, FileUpload, type FileUploadProps, FolderIcon, type FontEntry, type FontFamilies, type FontName, Footer, type FooterProps, type FormControlSize, Grid, type GridColumns, type GridProps, GroupBar, type GroupBarItem, type GroupBarProps, type GroupBarTone, HoverCard, type HoverCardContentProps, type HoverCardRootProps, type HoverCardTriggerProps, IconButton, type IconButtonProps, InfoTip, type InfoTipProps, Input, InputGroup, type InputGroupProps, type InputProps, Item, type ItemProps, Kbd, type KbdProps, Ledger, type LedgerEmptyProps, type LedgerGroupProps, type LedgerRootProps, type LedgerTierProps, Link, type LinkProps, McpServerIcon, Menubar, type MenubarContentProps, type MenubarMenuProps, type MenubarRootProps, type MenubarTriggerProps, Message, MessageList, type MessageListProps, type MessageProps, type MessageRole, Meter, type MeterProps, type MeterProvenance, type MeterTone, type Mode, MultiSelect, type MultiSelectProps, NavigationMenu, type NavigationMenuContentProps, type NavigationMenuItemProps, type NavigationMenuLinkProps, type NavigationMenuListProps, type NavigationMenuRootProps, type NavigationMenuTriggerProps, type NavigationMenuViewportProps, NumberField, type NumberFieldProps, OTPField, type OTPFieldProps, OVERLAY_SIDE_OFFSET, PageShell, type PageShellProps, type PageWidth, Pagination, type PaginationEntry, type PaginationProps, Panel, PanelHeader, type PanelHeaderProps, type PanelProps, PasswordInput, type PasswordInputProps, type PersistedPreferences, Plussie, type PlussieExpression, type PlussieProps, Popover, type PopoverCloseProps, type PopoverContentProps, type PopoverDescriptionProps, type PopoverRootProps, type PopoverTitleProps, type PopoverTriggerProps, type PrepaintDefaults, type PrepaintOptions, Progress, type ProgressProps, Radio, RadioGroup, type RadioGroupProps, type RadioProps, Rating, type RatingProps, type RatingSize, type ResolvedMode, Row, type RowProps, ScrollArea, type ScrollAreaOrientation, type ScrollAreaProps, type ScrollEdges, ScrollableTabsList, type ScrollableTabsListProps, ScrubInput, type ScrubInputProps, SeamCell, type SeamCellProps, SeamGrid, type SeamGridProps, type SeamGround, SeamList, type SeamListProps, SearchInput, type SearchInputProps, SectionHeader, type SectionHeaderProps, SegmentedControl, type SegmentedControlItem, type SegmentedControlProps, type SegmentedControlSize, Select, type SelectOption, type SelectProps, Separator, type SeparatorProps, Sheet, type SheetCloseProps, type SheetContentProps, type SheetDescriptionProps, type SheetFooterProps, type SheetRootProps, type SheetTitleProps, type SheetTriggerProps, Sidebar, type SidebarItemProps, type SidebarRailProps, type SidebarRootProps, type SidebarSectionProps, Skeleton, type SkeletonProps, SkillIcon, Slider, type SliderProps, type SpaceStep, Sparkline, type SparklineProps, Spinner, type SpinnerProps, Stack, type StackAlign, StackIcon, type StackJustify, type StackProps, StacksMatrixIcon, Stat, type StatProps, type StatTone, StatusBar, type StatusBarGroupProps, type StatusBarItemProps, type StatusBarProminence, type StatusBarProps, type StatusBarTone, StatusDot, type StatusDotProps, type StatusTone, Stepper, type StepperProps, type StepperState, type StepperStep, Switch, type SwitchProps, TAB_FADE_PX, TREE_GUIDE_GLYPHS, Table, type TableCaptionProps, type TableCellProps, type TableGroupRowProps, type TableHeadProps, type TableRootProps, type TableRowProps, TableScrollRegion, type TableScrollRegionProps, type TableSectionProps, Tabs, type TabsListProps, type TabsPanelProps, type TabsRootProps, type TabsTabProps, TagsInput, type TagsInputProps, TerminalFrame, type TerminalFrameLine, type TerminalFrameProps, type TerminalLine, type TerminalLineTone, type TerminalScript, type TerminalStep, Textarea, type TextareaProps, type ThemeContextValue, type ThemeManifest, type ThemeName, ThemeProvider, type ThemeProviderProps, type ThemeRegistry, Timeline, type TimelineContentProps, type TimelineItemProps, type TimelineMarkerProps, type TimelineRootProps, TitleBar, type TitleBarProps, Toast, type ToastManager, type ToastOptions, type ToastProviderProps, type ToastTone, type ToastViewportProps, Toggle, ToggleGroup, type ToggleGroupProps, type ToggleProps, type TokenOverrides, Toolbar, type ToolbarButtonProps, type ToolbarGroupProps, type ToolbarRootProps, type ToolbarSeparatorProps, Tooltip, type TooltipContentProps, type TooltipProviderProps, type TooltipRootProps, type TooltipTriggerProps, Tree, type TreeGuide, type TreeItem, type TreeProps, type TreeRow, type TreeVisibility, TreeVisibilityToggle, type TreeVisibilityToggleProps, TwoStepButton, type TwoStepButtonProps, type TwoStepTone, type UploadFile, type UploadStatus, UsageChart, type UsageChartPoint, type UsageChartProps, type UsageChartTone, activateRowFromClick, activateRowFromKeyDown, agentColor, agentColorStyle, bareControlClasses, buttonVariants, chipVariants, computeScrollEdges, controlClasses, controlGroupFocusClasses, controlSurface, controlVariants, edgeFadeMask, envReference, flattenTree, itemVariants, linkVariants, menuItemClasses, menuLabelClasses, menuPopupClasses, menuSeparatorClasses, overlayDescriptionClasses, overlayFooterClasses, overlayModalTransitionClasses, overlayPopupTransitionClasses, overlayPositionerClasses, overlaySurfaceClasses, overlayTextClasses, overlayTitleClasses, paginationRange, parseEnvReference, partitionFiles, prepaintScript, rowVariants, scrimClasses, useControlHeight, useCuePortalProps, useDensities, useDensity, useFonts, useSidebar, useTheme, useThemes, useToast };
package/dist/index.js CHANGED
@@ -25,6 +25,7 @@ import { AppBar } from "./chrome/app-bar.js";
25
25
  import { Sidebar, useSidebar } from "./layout/sidebar.js";
26
26
  import { Density } from "./system/density.js";
27
27
  import { DEFAULT_STORAGE_KEY, prepaintScript } from "./system/prepaint.js";
28
+ import { useDensities, useFonts, useThemes } from "./system/theme-registry.js";
28
29
  import { ThemeProvider } from "./system/theme-provider.js";
29
30
  import { CuePortalFrame, useCuePortalProps } from "./system/portal.js";
30
31
  import { OVERLAY_SIDE_OFFSET, menuItemClasses, menuLabelClasses, menuPopupClasses, menuSeparatorClasses, overlayDescriptionClasses, overlayFooterClasses, overlayModalTransitionClasses, overlayPopupTransitionClasses, overlayPositionerClasses, overlaySurfaceClasses, overlayTextClasses, overlayTitleClasses, scrimClasses } from "./overlays/_surface.js";
@@ -112,4 +113,4 @@ import { Kbd } from "./primitives/kbd.js";
112
113
  import { Skeleton } from "./primitives/skeleton.js";
113
114
  import { useControlHeight, useDensity } from "./system/use-density.js";
114
115
  import { useTheme } from "./system/use-theme.js";
115
- export { AGENT_COLOR_PROPERTY, AGENT_HUES, AGENT_ROOT_COLOR, Accordion, AgentPile, AlertDialog, AppBar, AppShell, AppWindowFrame, AskBox, AudienceIcon, Autocomplete, Avatar, AvatarGroup, Breadcrumb, Button, ButtonGroup, Card, CatalogueIcon, ChannelBetaIcon, ChannelReleasedIcon, Checkbox, CheckboxGroup, Chip, CliToolIcon, Collapsible, Combobox, CommandPalette, Composer, Container, ContextMenu, CopyButton, CueLogotype, CueMark, CuePortalFrame, DEFAULT_STORAGE_KEY, DataRow, DataTree, DelegationCard, Density, DescriptionList, Dialog, Disclosure, Drawer, DropdownMenu, EmptyState, EnvVarInput, Eyebrow, Field, FieldDescription, FieldError, FieldLabel, FileUpload, FolderIcon, Footer, Grid, GroupBar, HoverCard, IconButton, InfoTip, Input, InputGroup, Item, Kbd, Ledger, Link, McpServerIcon, Menubar, Message, MessageList, Meter, MultiSelect, NavigationMenu, NumberField, OTPField, OVERLAY_SIDE_OFFSET, PageShell, Pagination, Panel, PanelHeader, PasswordInput, Plussie, Popover, Progress, Radio, RadioGroup, Rating, Row, ScrollArea, ScrollableTabsList, ScrubInput, SeamCell, SeamGrid, SeamList, SearchInput, SectionHeader, SegmentedControl, Select, Separator, Sheet, Sidebar, Skeleton, SkillIcon, Slider, Sparkline, Spinner, Stack, StackIcon, StacksMatrixIcon, Stat, StatusBar, StatusDot, Stepper, Switch, TAB_FADE_PX, TREE_GUIDE_GLYPHS, Table, TableScrollRegion, Tabs, TagsInput, TerminalFrame, Textarea, ThemeProvider, Timeline, TitleBar, Toast, Toggle, ToggleGroup, Toolbar, Tooltip, Tree, TreeVisibilityToggle, TwoStepButton, UsageChart, activateRowFromClick, activateRowFromKeyDown, agentColor, agentColorStyle, bareControlClasses, buttonVariants, chipVariants, computeScrollEdges, controlClasses, controlGroupFocusClasses, controlSurface, controlVariants, edgeFadeMask, envReference, flattenTree, itemVariants, linkVariants, menuItemClasses, menuLabelClasses, menuPopupClasses, menuSeparatorClasses, overlayDescriptionClasses, overlayFooterClasses, overlayModalTransitionClasses, overlayPopupTransitionClasses, overlayPositionerClasses, overlaySurfaceClasses, overlayTextClasses, overlayTitleClasses, paginationRange, parseEnvReference, partitionFiles, prepaintScript, rowVariants, scrimClasses, useControlHeight, useCuePortalProps, useDensity, useSidebar, useTheme, useToast };
116
+ export { AGENT_COLOR_PROPERTY, AGENT_HUES, AGENT_ROOT_COLOR, Accordion, AgentPile, AlertDialog, AppBar, AppShell, AppWindowFrame, AskBox, AudienceIcon, Autocomplete, Avatar, AvatarGroup, Breadcrumb, Button, ButtonGroup, Card, CatalogueIcon, ChannelBetaIcon, ChannelReleasedIcon, Checkbox, CheckboxGroup, Chip, CliToolIcon, Collapsible, Combobox, CommandPalette, Composer, Container, ContextMenu, CopyButton, CueLogotype, CueMark, CuePortalFrame, DEFAULT_STORAGE_KEY, DataRow, DataTree, DelegationCard, Density, DescriptionList, Dialog, Disclosure, Drawer, DropdownMenu, EmptyState, EnvVarInput, Eyebrow, Field, FieldDescription, FieldError, FieldLabel, FileUpload, FolderIcon, Footer, Grid, GroupBar, HoverCard, IconButton, InfoTip, Input, InputGroup, Item, Kbd, Ledger, Link, McpServerIcon, Menubar, Message, MessageList, Meter, MultiSelect, NavigationMenu, NumberField, OTPField, OVERLAY_SIDE_OFFSET, PageShell, Pagination, Panel, PanelHeader, PasswordInput, Plussie, Popover, Progress, Radio, RadioGroup, Rating, Row, ScrollArea, ScrollableTabsList, ScrubInput, SeamCell, SeamGrid, SeamList, SearchInput, SectionHeader, SegmentedControl, Select, Separator, Sheet, Sidebar, Skeleton, SkillIcon, Slider, Sparkline, Spinner, Stack, StackIcon, StacksMatrixIcon, Stat, StatusBar, StatusDot, Stepper, Switch, TAB_FADE_PX, TREE_GUIDE_GLYPHS, Table, TableScrollRegion, Tabs, TagsInput, TerminalFrame, Textarea, ThemeProvider, Timeline, TitleBar, Toast, Toggle, ToggleGroup, Toolbar, Tooltip, Tree, TreeVisibilityToggle, TwoStepButton, UsageChart, activateRowFromClick, activateRowFromKeyDown, agentColor, agentColorStyle, bareControlClasses, buttonVariants, chipVariants, computeScrollEdges, controlClasses, controlGroupFocusClasses, controlSurface, controlVariants, edgeFadeMask, envReference, flattenTree, itemVariants, linkVariants, menuItemClasses, menuLabelClasses, menuPopupClasses, menuSeparatorClasses, overlayDescriptionClasses, overlayFooterClasses, overlayModalTransitionClasses, overlayPopupTransitionClasses, overlayPositionerClasses, overlaySurfaceClasses, overlayTextClasses, overlayTitleClasses, paginationRange, parseEnvReference, partitionFiles, prepaintScript, rowVariants, scrimClasses, useControlHeight, useCuePortalProps, useDensities, useDensity, useFonts, useSidebar, useTheme, useThemes, useToast };
@@ -49,7 +49,11 @@ const PianoKeyboard = React.forwardRef(function PianoKeyboard({ className, range
49
49
  const [drag, setDrag] = React.useState(null);
50
50
  const settled = React.useMemo(() => keyboardWindow(range, octaves), [range, octaves]);
51
51
  const view = drag?.window ?? settled;
52
- const layout = React.useMemo(() => keyboardLayout(view), [view.start, view.end]);
52
+ const { start: viewStart, end: viewEnd } = view;
53
+ const layout = React.useMemo(() => keyboardLayout({
54
+ start: viewStart,
55
+ end: viewEnd
56
+ }), [viewStart, viewEnd]);
53
57
  const lit = React.useMemo(() => new Set(highlight ?? []), [highlight]);
54
58
  const setEdge = (edge, note) => {
55
59
  const next = edge === "start" ? {
@@ -30,7 +30,7 @@ import * as React from "react";
30
30
  * <span className={chipVariants({ variant: "tag" })}>mcp</span>
31
31
  */
32
32
  declare const chipVariants: (props?: ({
33
- tone?: "danger" | "info" | "warn" | "accent" | "ok" | "busy" | "neutral" | null | undefined;
33
+ tone?: "info" | "warn" | "danger" | "accent" | "ok" | "busy" | "neutral" | null | undefined;
34
34
  variant?: "outline" | "tinted" | "tag" | null | undefined;
35
35
  interactive?: boolean | null | undefined;
36
36
  } & ClassProp) | undefined) => string;
package/dist/styles.css CHANGED
@@ -3,13 +3,35 @@
3
3
  * Consumer app CSS:
4
4
  * @import "tailwindcss";
5
5
  * @import "@cueplusplus/ui/styles.css";
6
+ * @import "@cueplusplus/theme-cue/theme.css"; (or any theme package)
6
7
  *
7
8
  * Tailwind v4 does not scan node_modules, so the library registers its own
8
9
  * sources: `@source "./"` resolves relative to THIS file, i.e. the shipped
9
10
  * dist/, which is where the class strings live after the build.
10
11
  */
11
12
 
12
- @import "@cueplusplus/tokens/theme.css";
13
+ /* Two lines, and the first one is the release's whole behaviour change.
14
+ *
15
+ * It used to be `@cueplusplus/tokens/theme.css`, which carried ten palettes and
16
+ * painted `cue` on a bare `:root`. A palette is a package now, so what this
17
+ * library ships is the *blank* base: `theme-base/base.css` declares every colour
18
+ * token at a neutral default and imports `@cueplusplus/tokens/axes.css` for the
19
+ * geometry and type axes. That is why there is no third line — `base.css`
20
+ * carries the axes with it, and `tailwind.css` maps utilities onto token names
21
+ * and pulls nothing.
22
+ *
23
+ * An app that imports this and registers no theme therefore paints greys and one
24
+ * desaturated accent, rather than somebody's brand. To get a palette back:
25
+ * install a theme package, import its stylesheet after this one, and pass its
26
+ * manifest to the provider —
27
+ *
28
+ * @import "@cueplusplus/ui/styles.css";
29
+ * @import "@cueplusplus/theme-cue/theme.css";
30
+ *
31
+ * with `<ThemeProvider themes={[cue]} theme="cue">`. Order matters and is not an
32
+ * accident: `[data-theme]` and `:root` tie at (0,1,0), so a theme's block wins
33
+ * by being declared later. */
34
+ @import "@cueplusplus/theme-base/base.css";
13
35
  @import "@cueplusplus/tokens/tailwind.css";
14
36
 
15
37
  @source "./";
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- import { Density } from "@cueplusplus/tokens";
2
+ import { Density } from "@cueplusplus/theme-base";
3
3
  //#region src/system/density.d.ts
4
4
  interface DensityProps {
5
5
  /**
@@ -17,14 +17,23 @@ interface DensityProps {
17
17
  /**
18
18
  * Re-scope any subtree to a different density level.
19
19
  *
20
- * Renders a plain `<div data-density="…">`: the geometry custom properties are
21
- * re-declared by the attribute selector and inherit down, so nesting is free and
22
- * needs no JS. The matching React context is published alongside for the rare
23
- * JS reads (`useDensity()`, `useControlHeight()`, portal stamping) — the DOM
24
- * attribute, not the context, is what actually restyles the tree.
20
+ * Renders a plain `<div data-density="…" data-cue-theme="…">`: the geometry
21
+ * custom properties are re-declared by the attribute selector and inherit
22
+ * down, so nesting is free and needs no JS. The matching React context is
23
+ * published alongside for the rare JS reads (`useDensity()`,
24
+ * `useControlHeight()`, portal stamping) — the DOM attributes, not the
25
+ * context, are what actually restyle the tree.
25
26
  *
26
- * Theme and mode are deliberately *not* re-scoped here: density is the only axis
27
- * an island may override (spec §6).
27
+ * `data-cue-theme` carries the nearest `<ThemeProvider>`'s name, or is
28
+ * omitted where there is none. It is read by nothing this island does —
29
+ * theme and mode are deliberately *not* re-scoped here, density is the only
30
+ * axis an island may override (spec §6) — it exists so a theme's own
31
+ * generated CSS can address exactly this island regardless of how many
32
+ * *other* themed providers sit between it and the one it belongs to. A CSS
33
+ * ancestor selector can only ask "does some ancestor carry theme `x`", never
34
+ * "is `x` the *nearest* one"; this stamp answers that question the way
35
+ * `useContext` already does, at render time, and hands the answer to CSS as
36
+ * an attribute rather than leaving it unanswerable there.
28
37
  *
29
38
  * @example
30
39
  * <Density density="ultra-compact">
@@ -10,14 +10,6 @@ import { jsx } from "react/jsx-runtime";
10
10
  * but the level a screen gets when nobody chose is the dense one.
11
11
  */
12
12
  const DEFAULT_DENSITY = "compact";
13
- /** The five levels, as a runtime array for validating persisted input. */
14
- const DENSITY_LEVELS = [
15
- "ultra-compact",
16
- "compact",
17
- "normal",
18
- "large",
19
- "ultra-large"
20
- ];
21
13
  /**
22
14
  * Nearest ambient density. `null` means "nothing has stamped a level yet", which
23
15
  * `useDensity()` reports as {@link DEFAULT_DENSITY}.
@@ -26,16 +18,45 @@ const DENSITY_LEVELS = [
26
18
  */
27
19
  const DensityContext = React.createContext(null);
28
20
  /**
21
+ * Nearest ambient theme's name, published for exactly one reader: `Density`
22
+ * below, which stamps it onto its island as `data-cue-theme` so a theme's
23
+ * CSS can tell *nearest* theme from *any* theme in the ancestor chain (see
24
+ * `densityRules`/`themeSelector`'s comment). `use-density.ts`'s measuring
25
+ * probe stamps the same attribute from the identical value, read through
26
+ * `ThemeContext` there instead, because it already imports that module with
27
+ * no cycle.
28
+ *
29
+ * Defined here, not in `theme-provider.tsx`, and re-exported from nowhere
30
+ * else. `theme-provider.tsx` already imports `DensityContext` from this
31
+ * module; a context this small living over there and imported back here
32
+ * would cycle the two modules. `null` outside a provider, the same as
33
+ * `ThemeContext`'s own theme field would be if it existed with no provider
34
+ * to require — `Density` used bare, with nothing above it, stamps nothing.
35
+ *
36
+ * Internal: `Density` is the only reader. Not `useTheme()` — that throws
37
+ * outside a provider, and this island has no reason to.
38
+ */
39
+ const AmbientThemeContext = React.createContext(null);
40
+ /**
29
41
  * Re-scope any subtree to a different density level.
30
42
  *
31
- * Renders a plain `<div data-density="…">`: the geometry custom properties are
32
- * re-declared by the attribute selector and inherit down, so nesting is free and
33
- * needs no JS. The matching React context is published alongside for the rare
34
- * JS reads (`useDensity()`, `useControlHeight()`, portal stamping) — the DOM
35
- * attribute, not the context, is what actually restyles the tree.
43
+ * Renders a plain `<div data-density="…" data-cue-theme="…">`: the geometry
44
+ * custom properties are re-declared by the attribute selector and inherit
45
+ * down, so nesting is free and needs no JS. The matching React context is
46
+ * published alongside for the rare JS reads (`useDensity()`,
47
+ * `useControlHeight()`, portal stamping) — the DOM attributes, not the
48
+ * context, are what actually restyle the tree.
36
49
  *
37
- * Theme and mode are deliberately *not* re-scoped here: density is the only axis
38
- * an island may override (spec §6).
50
+ * `data-cue-theme` carries the nearest `<ThemeProvider>`'s name, or is
51
+ * omitted where there is none. It is read by nothing this island does —
52
+ * theme and mode are deliberately *not* re-scoped here, density is the only
53
+ * axis an island may override (spec §6) — it exists so a theme's own
54
+ * generated CSS can address exactly this island regardless of how many
55
+ * *other* themed providers sit between it and the one it belongs to. A CSS
56
+ * ancestor selector can only ask "does some ancestor carry theme `x`", never
57
+ * "is `x` the *nearest* one"; this stamp answers that question the way
58
+ * `useContext` already does, at render time, and hands the answer to CSS as
59
+ * an attribute rather than leaving it unanswerable there.
39
60
  *
40
61
  * @example
41
62
  * <Density density="ultra-compact">
@@ -43,10 +64,12 @@ const DensityContext = React.createContext(null);
43
64
  * </Density>
44
65
  */
45
66
  function Density({ density, children, className, style }) {
67
+ const theme = React.useContext(AmbientThemeContext);
46
68
  return /* @__PURE__ */ jsx(DensityContext.Provider, {
47
69
  value: density,
48
70
  children: /* @__PURE__ */ jsx("div", {
49
71
  "data-density": density,
72
+ "data-cue-theme": theme ?? void 0,
50
73
  className,
51
74
  style,
52
75
  children
@@ -54,4 +77,4 @@ function Density({ density, children, className, style }) {
54
77
  });
55
78
  }
56
79
  //#endregion
57
- export { DEFAULT_DENSITY, DENSITY_LEVELS, Density, DensityContext };
80
+ export { AmbientThemeContext, DEFAULT_DENSITY, Density, DensityContext };
@@ -1,8 +1,11 @@
1
+ import { TokenOverrides } from "./overrides.js";
1
2
  import { FontFamilies, ResolvedMode, ThemeContextValue, ThemeProvider, ThemeProviderProps } from "./theme-provider.js";
2
3
  import { Density, DensityProps } from "./density.js";
3
4
  import { CuePortalFrame, CuePortalFrameProps, useCuePortalProps } from "./portal.js";
4
5
  import { DEFAULT_STORAGE_KEY, PersistedPreferences, PrepaintDefaults, PrepaintOptions, prepaintScript } from "./prepaint.js";
6
+ import { ThemeRegistry } from "./vocabulary.js";
7
+ import { useDensities, useFonts, useThemes } from "./theme-registry.js";
5
8
  import { ControlSize, useControlHeight, useDensity } from "./use-density.js";
6
9
  import { useTheme } from "./use-theme.js";
7
- import { Density as DensityLevel, FontName, Mode, ThemeName } from "@cueplusplus/tokens";
8
- export { type ControlSize, CuePortalFrame, type CuePortalFrameProps, DEFAULT_STORAGE_KEY, Density, type DensityLevel, type DensityProps, type FontFamilies, type FontName, type Mode, type PersistedPreferences, type PrepaintDefaults, type PrepaintOptions, type ResolvedMode, type ThemeContextValue, type ThemeName, ThemeProvider, type ThemeProviderProps, prepaintScript, useControlHeight, useCuePortalProps, useDensity, useTheme };
10
+ import { Density as DensityLevel, DensityEntry, FontEntry, FontName, Mode, ThemeManifest, ThemeName } from "@cueplusplus/theme-base";
11
+ export { type ControlSize, CuePortalFrame, type CuePortalFrameProps, DEFAULT_STORAGE_KEY, Density, type DensityEntry, type DensityLevel, type DensityProps, type FontEntry, type FontFamilies, type FontName, type Mode, type PersistedPreferences, type PrepaintDefaults, type PrepaintOptions, type ResolvedMode, type ThemeContextValue, type ThemeManifest, type ThemeName, ThemeProvider, type ThemeProviderProps, type ThemeRegistry, type TokenOverrides, prepaintScript, useControlHeight, useCuePortalProps, useDensities, useDensity, useFonts, useTheme, useThemes };
@@ -1,7 +1,8 @@
1
1
  import { Density } from "./density.js";
2
2
  import { DEFAULT_STORAGE_KEY, prepaintScript } from "./prepaint.js";
3
+ import { useDensities, useFonts, useThemes } from "./theme-registry.js";
3
4
  import { ThemeProvider } from "./theme-provider.js";
4
5
  import { CuePortalFrame, useCuePortalProps } from "./portal.js";
5
6
  import { useControlHeight, useDensity } from "./use-density.js";
6
7
  import { useTheme } from "./use-theme.js";
7
- export { CuePortalFrame, DEFAULT_STORAGE_KEY, Density, ThemeProvider, prepaintScript, useControlHeight, useCuePortalProps, useDensity, useTheme };
8
+ export { CuePortalFrame, DEFAULT_STORAGE_KEY, Density, ThemeProvider, prepaintScript, useControlHeight, useCuePortalProps, useDensities, useDensity, useFonts, useTheme, useThemes };
@@ -0,0 +1,43 @@
1
+ import "react";
2
+ import { ColorToken, GeometryToken, ThemeManifest } from "@cueplusplus/theme-base";
3
+ //#region src/system/overrides.d.ts
4
+ /**
5
+ * A typed edit over the active theme.
6
+ *
7
+ * Not `ThemeOverrides`: `@cueplusplus/ui/configurator` already exports a type
8
+ * by that name — the serialised edit snapshot its panel writes — and the root
9
+ * barrel re-exports `./system` wholesale, so two public types under one name in
10
+ * one package would be an alias every consumer of both subpaths has to write.
11
+ * This one overrides *tokens*, which is what it is named for.
12
+ *
13
+ * Every key is checked against the token contracts, so a typo is a compile
14
+ * error rather than a custom property nothing reads.
15
+ */
16
+ interface TokenOverrides {
17
+ /**
18
+ * Colour tokens, per block. Only the block the resolved mode is in is
19
+ * emitted, so a provider under `mode="light"` never publishes the dark edit —
20
+ * which is what makes the two independent rather than a merge.
21
+ */
22
+ colors?: {
23
+ dark?: Partial<Record<ColorToken, string>>;
24
+ light?: Partial<Record<ColorToken, string>>;
25
+ };
26
+ /**
27
+ * Geometry, per rung. The key is a rung name — one of the base five, or one a
28
+ * registered theme adds — and the value only the tokens that move.
29
+ */
30
+ densities?: Partial<Record<string, Partial<Record<GeometryToken, string>>>>;
31
+ /**
32
+ * Font stacks. These write `--cue-font-sans` / `--cue-font-mono` /
33
+ * `--cue-font-display` directly, and so shadow the pairing on `data-font` for
34
+ * the subtree — see `ThemeProviderProps.overrides`.
35
+ */
36
+ fonts?: Partial<{
37
+ sans: string;
38
+ mono: string;
39
+ display: string;
40
+ }>;
41
+ }
42
+ //#endregion
43
+ export { TokenOverrides };