@adea-ai/ui 0.118.3 → 0.119.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/components/composites/settings/index.d.ts +1 -1
- package/dist/components/composites/settings/index.d.ts.map +1 -1
- package/dist/components/composites/settings/settings-layout.d.ts +18 -2
- package/dist/components/composites/settings/settings-layout.d.ts.map +1 -1
- package/dist/components/composites/settings/settings-layout.js +40 -5
- package/dist/components/composites/settings/settings-layout.js.map +1 -1
- package/dist/components/composites/settings/settings-navigation.d.ts.map +1 -1
- package/dist/components/composites/settings/settings-navigation.js +36 -14
- package/dist/components/composites/settings/settings-navigation.js.map +1 -1
- package/dist/components/ui/code-block/code-block.d.ts +13 -0
- package/dist/components/ui/code-block/code-block.d.ts.map +1 -1
- package/dist/components/ui/code-block/code-block.js +22 -3
- package/dist/components/ui/code-block/code-block.js.map +1 -1
- package/dist/components/ui/item/index.d.ts +1 -1
- package/dist/components/ui/item/index.d.ts.map +1 -1
- package/dist/components/ui/item/item.d.ts +17 -1
- package/dist/components/ui/item/item.d.ts.map +1 -1
- package/dist/components/ui/item/item.js +17 -10
- package/dist/components/ui/item/item.js.map +1 -1
- package/dist/lib/themes.d.ts +6 -0
- package/dist/lib/themes.d.ts.map +1 -1
- package/dist/lib/themes.js +11 -3
- package/dist/lib/themes.js.map +1 -1
- package/dist/r/appearance-editor.json +1 -1
- package/dist/r/lib.json +1 -1
- package/dist/r/registry.json +6 -4
- package/dist/r/settings.json +3 -1
- package/dist/r/src/components/composites/settings/index.ts +5 -1
- package/dist/r/src/components/composites/settings/settings-layout.tsx +48 -5
- package/dist/r/src/components/composites/settings/settings-navigation.tsx +44 -16
- package/dist/r/src/components/ui/code-block/code-block.tsx +27 -2
- package/dist/r/src/components/ui/item/index.ts +1 -0
- package/dist/r/src/components/ui/item/item.tsx +41 -5
- package/dist/r/src/lib/themes.ts +23 -5
- package/dist/r/src/styles/theme.css +17 -13
- package/dist/r/theming.json +1 -1
- package/package.json +2 -2
- package/registry.json +6 -4
- package/src/components/composites/settings/index.ts +5 -1
- package/src/components/composites/settings/settings-layout.tsx +48 -5
- package/src/components/composites/settings/settings-navigation.tsx +44 -16
- package/src/components/ui/code-block/code-block.tsx +27 -2
- package/src/components/ui/item/index.ts +1 -0
- package/src/components/ui/item/item.tsx +41 -5
- package/src/lib/themes.ts +23 -5
- package/src/styles/theme.css +17 -13
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { cn } from "../../../lib/utils.js";
|
|
2
2
|
import { cva } from "../../../lib/variants.js";
|
|
3
|
-
import { createComponent, effect, insert, mergeProps, setAttribute, spread, template } from "solid-js/web";
|
|
3
|
+
import { className, createComponent, effect, insert, mergeProps, setAttribute, spread, template } from "solid-js/web";
|
|
4
4
|
import { Show, splitProps } from "solid-js";
|
|
5
5
|
//#region src/components/ui/item/item.tsx
|
|
6
6
|
var _tmpl$ = /*#__PURE__*/ template(`<span data-slot=item-media class="flex size-8 shrink-0 items-center justify-center [&_svg]:size-4">`);
|
|
7
|
-
var _tmpl$2 = /*#__PURE__*/ template(`<span data-slot=item-trailing
|
|
7
|
+
var _tmpl$2 = /*#__PURE__*/ template(`<span data-slot=item-trailing>`);
|
|
8
8
|
var _tmpl$3 = /*#__PURE__*/ template(`<div data-slot=item><div data-slot=item-body class="flex min-w-0 flex-1 flex-col gap-0.5">`);
|
|
9
9
|
var _tmpl$4 = /*#__PURE__*/ template(`<div data-slot=item-title>`);
|
|
10
10
|
var _tmpl$5 = /*#__PURE__*/ template(`<div data-slot=item-description>`);
|
|
@@ -56,16 +56,22 @@ function Item(props) {
|
|
|
56
56
|
"size",
|
|
57
57
|
"media",
|
|
58
58
|
"trailing",
|
|
59
|
+
"stackTrailing",
|
|
59
60
|
"children"
|
|
60
61
|
]);
|
|
61
62
|
return (() => {
|
|
62
63
|
var _el$ = _tmpl$3(), _el$3 = _el$.firstChild;
|
|
63
|
-
spread(_el$, mergeProps({
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
spread(_el$, mergeProps({
|
|
65
|
+
get ["data-stack-trailing"]() {
|
|
66
|
+
return local.stackTrailing ? "" : void 0;
|
|
67
|
+
},
|
|
68
|
+
get ["class"]() {
|
|
69
|
+
return cn(itemVariants({
|
|
70
|
+
variant: local.variant,
|
|
71
|
+
size: local.size
|
|
72
|
+
}), { "@container/item flex-wrap": local.stackTrailing }, local.class);
|
|
73
|
+
}
|
|
74
|
+
}, rest), false, true);
|
|
69
75
|
insert(_el$, createComponent(Show, {
|
|
70
76
|
get when() {
|
|
71
77
|
return local.media;
|
|
@@ -84,6 +90,7 @@ function Item(props) {
|
|
|
84
90
|
get children() {
|
|
85
91
|
var _el$4 = _tmpl$2();
|
|
86
92
|
insert(_el$4, () => local.trailing);
|
|
93
|
+
effect(() => className(_el$4, cn("flex shrink-0 items-center gap-2", { "@max-md/item:w-full @max-md/item:flex-wrap @max-md/item:justify-end": local.stackTrailing })));
|
|
87
94
|
return _el$4;
|
|
88
95
|
}
|
|
89
96
|
}), null);
|
|
@@ -101,11 +108,11 @@ function ItemTitle(props) {
|
|
|
101
108
|
})();
|
|
102
109
|
}
|
|
103
110
|
function ItemDescription(props) {
|
|
104
|
-
const [local, rest] = splitProps(props, ["class"]);
|
|
111
|
+
const [local, rest] = splitProps(props, ["class", "clamp"]);
|
|
105
112
|
return (() => {
|
|
106
113
|
var _el$6 = _tmpl$5();
|
|
107
114
|
spread(_el$6, mergeProps({ get ["class"]() {
|
|
108
|
-
return cn("text-muted-foreground
|
|
115
|
+
return cn("text-muted-foreground text-xs text-pretty", { "line-clamp-2": local.clamp !== false }, local.class);
|
|
109
116
|
} }, rest), false, false);
|
|
110
117
|
return _el$6;
|
|
111
118
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"item.js","names":["ComponentProps","JSX","Show","splitProps","cva","VariantProps","cn","itemVariants","variants","variant","default","outline","muted","size","sm","md","lg","defaultVariants","ItemVariantProps","ItemProps","media","Element","trailing","Item","props","local","rest","_el$","_tmpl$3","_el$3","firstChild","_$spread","_$mergeProps","class","_$insert","_$createComponent","when","children","_el$2","_tmpl$","_el$4","_tmpl$2","ItemTitle","_el$5","_tmpl$4","ItemDescription","_el$6","_tmpl$5","ItemGroup","label","listLabel","_el$7","_tmpl$7","_el$9","_el$8","_tmpl$6","_$
|
|
1
|
+
{"version":3,"file":"item.js","names":["ComponentProps","JSX","Show","splitProps","cva","VariantProps","cn","itemVariants","variants","variant","default","outline","muted","size","sm","md","lg","defaultVariants","ItemVariantProps","ItemProps","media","Element","trailing","stackTrailing","Item","props","local","rest","_el$","_tmpl$3","_el$3","firstChild","_$spread","_$mergeProps","data-stack-trailing","undefined","class","_$insert","_$createComponent","when","children","_el$2","_tmpl$","_el$4","_tmpl$2","_$effect","_$className","ItemTitle","_el$5","_tmpl$4","ItemDescriptionProps","clamp","ItemDescription","_el$6","_tmpl$5","ItemGroup","label","listLabel","_el$7","_tmpl$7","_el$9","_el$8","_tmpl$6","_$setAttribute","ItemGroupEntry","role","ItemEmpty","_el$0","_tmpl$8","_$mergeProps","_$createComponent","_$className","_$setAttribute"],"sources":["../../../../src/components/ui/item/item.tsx"],"sourcesContent":["import type { ComponentProps, JSX } from 'solid-js'\nimport { Show, splitProps } from 'solid-js'\nimport { cva, type VariantProps } from '#lib/variants'\nimport { cn } from '#lib/utils'\n\n/**\n * Item.\n *\n * The general row: a leading slot, a body, and a trailing slot. It is the shape\n * almost every list in an application takes — a file, a member, a setting, a\n * search result — and it exists as a component because a row is where inconsistency\n * is most visible: twenty of them make any drift in height, padding or alignment\n * obvious at a glance.\n *\n * The difference from `ListRow` is what it is *for*. `ListRow` is one row in a list\n * of like things, sized by the row ladder and meant to be scanned down a column.\n * `Item` is a self-contained block — it has a border, its own surface, an optional\n * title and description — and is meant to stand alone or sit in a grid. A list uses\n * `ListRow`; a search result or a settings card uses `Item`.\n *\n * `variant=\"outline\"` and `\"muted\"` exist because the two questions a caller\n * actually has are \"does this need an edge\" and \"is it on the canvas or inset\".\n */\nexport const itemVariants = cva('flex w-full items-center gap-3 rounded-lg text-sm', {\n variants: {\n variant: {\n default: 'bg-transparent',\n /** On the canvas, with an edge — the search-result shape. */\n outline: 'border border-border bg-card',\n /** Inset: a code well, a disabled row, a quoted message. */\n muted: 'bg-muted',\n },\n size: {\n sm: 'min-h-row-sm px-3 py-1.5',\n md: 'min-h-row-md px-3 py-2',\n lg: 'min-h-row-lg px-4 py-2.5',\n },\n },\n defaultVariants: { variant: 'default', size: 'md' },\n})\n\ntype ItemVariantProps = VariantProps<typeof itemVariants>\n\nexport type ItemProps = ComponentProps<'div'> &\n ItemVariantProps & {\n /** A media slot: an icon, an avatar, a thumbnail. */\n media?: JSX.Element\n /** A trailing slot: a badge, a timestamp, a menu trigger. */\n trailing?: JSX.Element\n /**\n * Move the trailing slot onto its own line, end-aligned under the body, once\n * the item is narrower than 28rem — the width `ListRow` stacks its trailing\n * controls at. Off by default: a row of badges and an icon button fits beside\n * the body, but a pair of labelled buttons squeezes a phone-width body to a\n * few characters.\n */\n stackTrailing?: boolean\n }\n\nexport function Item(props: ItemProps) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'variant',\n 'size',\n 'media',\n 'trailing',\n 'stackTrailing',\n 'children',\n ])\n\n return (\n <div\n data-slot=\"item\"\n data-stack-trailing={local.stackTrailing ? '' : undefined}\n class={cn(\n itemVariants({ variant: local.variant, size: local.size }),\n // The item is its own query container: the trailing slot answers to the\n // width the item was given, not the viewport, so an item in a narrow\n // column of a wide window stacks too.\n { '@container/item flex-wrap': local.stackTrailing },\n local.class\n )}\n {...rest}\n >\n <Show when={local.media}>\n <span\n data-slot=\"item-media\"\n class=\"flex size-8 shrink-0 items-center justify-center [&_svg]:size-4\"\n >\n {local.media}\n </span>\n </Show>\n <div data-slot=\"item-body\" class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n {local.children}\n </div>\n <Show when={local.trailing}>\n <span\n data-slot=\"item-trailing\"\n class={cn('flex shrink-0 items-center gap-2', {\n '@max-md/item:w-full @max-md/item:flex-wrap @max-md/item:justify-end':\n local.stackTrailing,\n })}\n >\n {local.trailing}\n </span>\n </Show>\n </div>\n )\n}\n\nexport function ItemTitle(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return <div data-slot=\"item-title\" class={cn('truncate font-medium', local.class)} {...rest} />\n}\n\nexport type ItemDescriptionProps = ComponentProps<'div'> & {\n /**\n * Clamp to two lines. On by default, so a grid of items keeps one height; pass\n * `false` where the description is the content — a setting's explanation, an\n * error the reader has to read in full.\n */\n clamp?: boolean\n}\n\nexport function ItemDescription(props: ItemDescriptionProps) {\n const [local, rest] = splitProps(props, ['class', 'clamp'])\n return (\n <div\n data-slot=\"item-description\"\n class={cn(\n 'text-muted-foreground text-xs text-pretty',\n { 'line-clamp-2': local.clamp !== false },\n local.class\n )}\n {...rest}\n />\n )\n}\n\n/**\n * A group of items with an optional heading. It is a real `role=\"list\"` with\n * `role=\"listitem\"` children, so a screen reader reports the count — which is how a\n * user knows how many results there are without counting them.\n */\nexport function ItemGroup(\n props: ComponentProps<'div'> & {\n label?: string\n /** The list's accessible name. */ listLabel?: string\n }\n) {\n const [local, rest] = splitProps(props, ['class', 'label', 'listLabel', 'children'])\n\n return (\n <div data-slot=\"item-group\" class={cn('flex flex-col gap-2', local.class)} {...rest}>\n <Show when={local.label}>\n <div class=\"text-muted-foreground text-2xs font-medium tracking-wide uppercase\">\n {local.label}\n </div>\n </Show>\n <div role=\"list\" aria-label={local.listLabel ?? local.label} class=\"flex flex-col gap-2\">\n {local.children}\n </div>\n </div>\n )\n}\n\n/** An item inside an `ItemGroup`, which is what makes it a list item. */\nexport function ItemGroupEntry(props: ItemProps) {\n return <Item role=\"listitem\" {...props} />\n}\n\n/** A centred message for a group with nothing in it. */\nexport function ItemEmpty(props: ComponentProps<'div'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <div\n data-slot=\"item-empty\"\n class={cn('text-muted-foreground py-6 text-center text-sm', local.class)}\n {...rest}\n />\n )\n}\n"],"mappings":"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"}
|
package/dist/lib/themes.d.ts
CHANGED
|
@@ -147,6 +147,12 @@ export type ThemeVariant = {
|
|
|
147
147
|
chart: readonly string[];
|
|
148
148
|
provenance: ThemeProvenance;
|
|
149
149
|
};
|
|
150
|
+
/**
|
|
151
|
+
* A variant's `--primary-subtle`: the tint over `var(--primary)` at the strength its
|
|
152
|
+
* catalogue record measures (`primarySubtleAlpha`). A variant that is not in the
|
|
153
|
+
* catalogue has nothing to measure, and gets its appearance's ceiling.
|
|
154
|
+
*/
|
|
155
|
+
export declare function primarySubtleFor(theme: Pick<ThemeVariant, 'id' | 'appearance'>): string;
|
|
150
156
|
/** The catalogue, in catalogue order. */
|
|
151
157
|
export declare const builtinThemes: readonly ThemeVariant[];
|
|
152
158
|
export declare function themeById(id: string): ThemeVariant | undefined;
|
package/dist/lib/themes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../../src/lib/themes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../../src/lib/themes.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/themes.js
CHANGED
|
@@ -127,6 +127,15 @@ function toVariant(theme) {
|
|
|
127
127
|
}
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* A variant's `--primary-subtle`: the tint over `var(--primary)` at the strength its
|
|
132
|
+
* catalogue record measures (`primarySubtleAlpha`). A variant that is not in the
|
|
133
|
+
* catalogue has nothing to measure, and gets its appearance's ceiling.
|
|
134
|
+
*/
|
|
135
|
+
function primarySubtleFor(theme) {
|
|
136
|
+
const record = getTheme(theme.id);
|
|
137
|
+
return record ? primarySubtleCss(record) : primarySubtleCss(theme.appearance);
|
|
138
|
+
}
|
|
130
139
|
/** The catalogue, in catalogue order. */
|
|
131
140
|
var builtinThemes = Object.freeze(themes.map(toVariant));
|
|
132
141
|
function themeById(id) {
|
|
@@ -276,7 +285,6 @@ function accentVariables(accentId, appearance, pair = {
|
|
|
276
285
|
"--primary": roles.primary,
|
|
277
286
|
"--primary-foreground": roles.primaryForeground,
|
|
278
287
|
"--primary-hover": roles.primaryHover,
|
|
279
|
-
"--primary-subtle": roles.primarySubtle,
|
|
280
288
|
"--ring": roles.ring
|
|
281
289
|
};
|
|
282
290
|
}
|
|
@@ -302,7 +310,7 @@ function themeCssVariables(theme) {
|
|
|
302
310
|
"--primary": c.primary,
|
|
303
311
|
"--primary-foreground": c.primaryForeground,
|
|
304
312
|
"--primary-hover": primaryHover(c.primary, theme.appearance),
|
|
305
|
-
"--primary-subtle":
|
|
313
|
+
"--primary-subtle": primarySubtleFor(theme),
|
|
306
314
|
"--secondary": c.secondary,
|
|
307
315
|
"--secondary-foreground": c.secondaryForeground,
|
|
308
316
|
"--muted": c.muted,
|
|
@@ -411,6 +419,6 @@ function validateThemeRegistry(themes$1 = builtinThemes) {
|
|
|
411
419
|
var defaultLightThemeId = "adea-light";
|
|
412
420
|
var defaultDarkThemeId = "adea-dark";
|
|
413
421
|
//#endregion
|
|
414
|
-
export { accentVariables, appearancePreviewThemes, builtinThemes, contrastRatio, defaultDarkThemeId, defaultLightThemeId, isThemeAccentId, resolveAccentPreset, themeAccentsFor, themeById, themeCssVariables, themeFamilies, themeRecordById, themeRecords, themesForAppearance, validateTheme, validateThemeRegistry, withAccent };
|
|
422
|
+
export { accentVariables, appearancePreviewThemes, builtinThemes, contrastRatio, defaultDarkThemeId, defaultLightThemeId, isThemeAccentId, primarySubtleFor, resolveAccentPreset, themeAccentsFor, themeById, themeCssVariables, themeFamilies, themeRecordById, themeRecords, themesForAppearance, validateTheme, validateThemeRegistry, withAccent };
|
|
415
423
|
|
|
416
424
|
//# sourceMappingURL=themes.js.map
|
package/dist/lib/themes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themes.js","names":["catalogue","themes"],"sources":["../../src/lib/themes.ts"],"sourcesContent":["/**\n * The theme registry, now a bridge.\n *\n * The catalogue itself lives in `@adea-ai/themes`. This module is what is left in\n * the design system: the translation between the catalogue's **canonical** role\n * names and the **shadcn** vocabulary every component here is written against, plus\n * the handful of custom properties this system declares that are presentations of\n * data the catalogue already holds — the `--terminal-*` ramp, the `--editor-*` ramp,\n * and `--chrome`.\n *\n * ## Why it is a bridge and not a copy\n *\n * This file used to hold thirteen themes as hand-written hex literal tables, with its\n * own contrast validator, its own terminal and editor palettes, and its own\n * provenance records. That is a lot of surface to maintain for one consumer of a\n * palette, and it meant every product that wanted the same themes — Adea, Cortana —\n * either imported this package or wrote its own. The catalogue moved out so that\n * there is one answer to \"what is Catppuccin Mocha\", and this file is the part that\n * genuinely belongs to the design system.\n *\n * It is deliberately thin. If you are looking for a colour, it is not here: see\n * `@adea-ai/themes`, whose README explains how the values are produced and whose\n * `NOTICE` records where every palette came from.\n *\n * ## The mapping, and the entry that is not a rename\n *\n * {@link ROLE_FOR} maps canonical roles onto this system's variable vocabulary. One\n * entry will trip a reader: the catalogue's `accent` becomes this system's\n * `primary`, because in the shadcn vocabulary `--primary` is the action colour — the\n * fill of a primary button, the thing a focus ring is drawn in — while `--accent` is\n * a low-contrast hover wash. The catalogue's `accent` is the former, so it goes to\n * `--primary`, and `--accent` is filled from `surfaceHover`, which is what shadcn\n * components actually use it for.\n */\n\nimport {\n ACCENTS,\n accentForeground,\n accentRoles,\n chartSeries,\n getAccent,\n getTheme,\n hasTheme,\n shadcnDestructiveProjection,\n statusForeground,\n tint,\n primaryHover,\n primarySubtleCss,\n syntaxRoles,\n themes as catalogue,\n themesByAppearance,\n themeAccentPresets,\n validateCatalogue,\n type AccentPreset,\n type AdeaTheme,\n type AdeaThemeRecord,\n type ContrastFinding,\n} from '@adea-ai/themes'\nimport { isThemeAccentId } from './theme-accents'\n\nexport { isThemeAccentId } from './theme-accents'\n\nexport type ThemeAppearance = 'light' | 'dark'\n\n/**\n * The surface and text roles, in shadcn's vocabulary.\n *\n * Named to match the components below, which is why they differ from the\n * catalogue's: these are this system's variable names, and renaming them would mean\n * touching every component in the library for no gain.\n */\nexport type ThemeColors = {\n background: string\n foreground: string\n card: string\n cardForeground: string\n popover: string\n popoverForeground: string\n primary: string\n primaryForeground: string\n secondary: string\n secondaryForeground: string\n muted: string\n mutedForeground: string\n accent: string\n accentForeground: string\n destructive: string\n destructiveForeground: string\n destructiveSubtle: string\n /** Contrast-safe solid-action presentation, derived from the canonical error role. */\n destructiveAction: string\n destructiveActionForeground: string\n success: string\n successForeground: string\n successSubtle: string\n warning: string\n warningForeground: string\n warningSubtle: string\n info: string\n infoForeground: string\n infoSubtle: string\n border: string\n input: string\n ring: string\n sidebar: string\n sidebarForeground: string\n sidebarAccent: string\n sidebarBorder: string\n}\n\n/** The sixteen ANSI colours a terminal needs, plus its cursor and selection. */\nexport type ThemeTerminalPalette = {\n background: string\n foreground: string\n cursor: string\n selection: string\n black: string\n red: string\n green: string\n yellow: string\n blue: string\n magenta: string\n cyan: string\n white: string\n brightBlack: string\n brightRed: string\n brightGreen: string\n brightYellow: string\n brightBlue: string\n brightMagenta: string\n brightCyan: string\n brightWhite: string\n}\n\n/** The syntax roles a code view needs. */\nexport type ThemeEditorPalette = {\n keyword: string\n string: string\n number: string\n comment: string\n function: string\n variable: string\n type: string\n tag: string\n attribute: string\n operator: string\n heading: string\n link: string\n diffAdd: string\n diffDelete: string\n diffHunk: string\n searchMatch: string\n}\n\n/** Where a palette came from, and the terms it is used under. */\nexport type ThemeProvenance = {\n /** The project or person the palette belongs to. */\n source: string\n url: string\n /** An SPDX identifier. Every palette in this catalogue is permissive. */\n license: string\n}\n\nexport type ThemeVariant = {\n /** The `data-theme` value and the id a preference stores. */\n id: string\n /** Groups the variants that came from one project. */\n family: string\n familyLabel: string\n label: string\n appearance: ThemeAppearance\n /** One line, shown in a picker. */\n description: string\n colors: ThemeColors\n terminal: ThemeTerminalPalette\n editor: ThemeEditorPalette\n /** The categorical series, in order. */\n chart: readonly string[]\n provenance: ThemeProvenance\n}\n\n/**\n * Canonical role → this system's `ThemeColors` key.\n *\n * Read by {@link toVariant}. The two derived destructive-action presentation values\n * are intentionally excluded; the shared Themes adapter owns their color math.\n */\ntype ThemeRole = Exclude<keyof ThemeColors, 'destructiveAction' | 'destructiveActionForeground'>\n\nconst ROLE_FOR: Readonly<Record<ThemeRole, keyof AdeaThemeRecord['colors']>> = {\n background: 'background',\n foreground: 'text',\n card: 'surface',\n cardForeground: 'text',\n popover: 'surfaceElevated',\n popoverForeground: 'text',\n // Not a rename — see this module's header.\n primary: 'accent',\n primaryForeground: 'accentForeground',\n // shadcn's `secondary` and `muted` are both the first surface rung used as a fill.\n secondary: 'surface',\n secondaryForeground: 'text',\n muted: 'surface',\n mutedForeground: 'textMuted',\n // shadcn's `accent` is a hover wash, which is exactly `surfaceHover`.\n accent: 'surfaceHover',\n accentForeground: 'text',\n destructive: 'error',\n // Overwritten below from the measured pairing; nominal here so the table is total.\n destructiveForeground: 'error',\n destructiveSubtle: 'error',\n success: 'success',\n successForeground: 'success',\n successSubtle: 'success',\n warning: 'warning',\n warningForeground: 'warning',\n warningSubtle: 'warning',\n info: 'info',\n infoForeground: 'info',\n infoSubtle: 'info',\n border: 'border',\n input: 'border',\n ring: 'accent',\n sidebar: 'surface',\n sidebarForeground: 'text',\n sidebarAccent: 'surfaceHover',\n sidebarBorder: 'border',\n}\n\n/** Builds the design system's view of one catalogue entry. */\nfunction toVariant(theme: AdeaThemeRecord): ThemeVariant {\n const colors = {} as ThemeColors\n for (const key of Object.keys(ROLE_FOR) as ThemeRole[]) {\n colors[key] = theme.colors[ROLE_FOR[key]]\n }\n // Keep the semantic foreground paired with the canonical error role. Filled\n // destructive actions use the distinct projection below so their /90 hover state\n // remains readable without changing icons, borders, or tinted status surfaces.\n colors.destructiveForeground = statusForeground(theme, 'error')\n colors.destructiveSubtle = tint(theme.colors.error, theme.colors.background)\n const destructiveAction = shadcnDestructiveProjection(theme)\n colors.destructiveAction = destructiveAction.fill\n colors.destructiveActionForeground = destructiveAction.foreground\n colors.successForeground = statusForeground(theme, 'success')\n colors.successSubtle = tint(theme.colors.success, theme.colors.background)\n colors.warningForeground = statusForeground(theme, 'warning')\n colors.warningSubtle = tint(theme.colors.warning, theme.colors.background)\n colors.infoForeground = statusForeground(theme, 'info')\n colors.infoSubtle = tint(theme.colors.info, theme.colors.background)\n\n const syntax = syntaxRoles(theme)\n\n return {\n id: theme.id,\n family: theme.family,\n familyLabel: theme.familyLabel,\n label: theme.label,\n appearance: theme.appearance,\n description: theme.description,\n colors,\n terminal: {\n // The embedded terminal uses the theme's own canvas rather than a palette of its\n // own. The ANSI colours came from the palette that produced the canvas, so they\n // were chosen against it; a terminal on a different background would be the one\n // surface in the application not lit by the active theme.\n background: theme.colors.background,\n foreground: theme.colors.foreground,\n cursor: theme.cursor,\n selection: theme.selection,\n ...theme.ansi,\n },\n editor: {\n keyword: syntax.keyword,\n string: syntax.string,\n number: syntax.number,\n comment: syntax.comment,\n function: syntax.function,\n variable: syntax.variable,\n type: syntax.type,\n tag: syntax.tag,\n attribute: syntax.attribute,\n operator: syntax.operator,\n heading: syntax.heading,\n link: syntax.link,\n diffAdd: syntax.diffAdd,\n diffDelete: syntax.diffDelete,\n diffHunk: syntax.diffHunk,\n searchMatch: syntax.searchMatch,\n },\n chart: chartSeries(theme),\n provenance: {\n source: theme.provenance.project,\n url: theme.provenance.url,\n license: theme.provenance.license,\n },\n }\n}\n\n/** The catalogue, in catalogue order. */\nexport const builtinThemes: readonly ThemeVariant[] = Object.freeze(catalogue.map(toVariant))\n\nexport function themeById(id: string): ThemeVariant | undefined {\n if (!hasTheme(id)) return undefined\n return builtinThemes.find((theme) => theme.id === id)\n}\n\n/** The variants of one appearance, which is what a picker for that mode shows. */\nexport function themesForAppearance(appearance: ThemeAppearance): readonly ThemeVariant[] {\n const ids = new Set(themesByAppearance(appearance).map((theme) => theme.id))\n return builtinThemes.filter((theme) => ids.has(theme.id))\n}\n\n/** The families in the catalogue, in catalogue order. */\nexport function themeFamilies(): { family: string; label: string; themes: ThemeVariant[] }[] {\n const families = new Map<string, { family: string; label: string; themes: ThemeVariant[] }>()\n for (const theme of builtinThemes) {\n const entry = families.get(theme.family) ?? {\n family: theme.family,\n label: theme.familyLabel,\n themes: [],\n }\n entry.themes.push(theme)\n families.set(theme.family, entry)\n }\n return [...families.values()]\n}\n\n/** The accent presets, in the order a picker should show them. */\nexport const accents = ACCENTS\n\n/**\n * The canonical catalogue records, in catalogue order.\n *\n * {@link builtinThemes} is this system's projection of the catalogue onto the\n * shadcn vocabulary, which is what a document is painted with. A *preview* of a\n * theme — the miniatures `AppearanceEditor` and `ThemeMiniature` draw — reads the\n * catalogue's own roles instead (`surfaceActive`, `borderMuted`, `textSubtle`…),\n * several of which the projection folds together. These are those records, so a\n * consumer hands the editor exactly what it takes rather than reconstructing it\n * from the projection.\n */\nexport const themeRecords: readonly AdeaThemeRecord[] = catalogue\n\nexport function themeRecordById(id: string): AdeaThemeRecord | undefined {\n return getTheme(id)\n}\n\n/** A light/dark theme pair by id, with the defaults standing in for an unknown id. */\nfunction recordPair(lightThemeId: string, darkThemeId: string) {\n const light = getTheme(lightThemeId) ?? getTheme(defaultLightThemeId)!\n const dark = getTheme(darkThemeId) ?? getTheme(defaultDarkThemeId)!\n return { light, dark }\n}\n\n/**\n * The accents the selected light/dark pair carries — offered beside the presets.\n *\n * Computed per pair rather than per theme because a theme accent is a *pair* of\n * values, like a preset: a slot is offered only when both themes can offer it.\n */\nexport function themeAccentsFor(\n lightThemeId: string,\n darkThemeId: string\n): readonly AccentPreset[] {\n const { light, dark } = recordPair(lightThemeId, darkThemeId)\n return themeAccentPresets(light, dark)\n}\n\n/**\n * An accent id resolved against a theme pair: a preset, a theme accent the pair\n * offers, or `undefined` for `theme`, an unknown id, or a slot this pair cannot\n * offer — each of which means \"use the theme's own primary\".\n *\n * Theme accent ids are role-shaped (`ansi-blue`), so a stored one survives a theme\n * switch and resolves to the new theme's blue; when the new pair cannot offer the\n * slot it resolves to nothing, the same fallback a stale preset id gets.\n */\nexport function resolveAccentPreset(\n accentId: string,\n light: AdeaTheme,\n dark: AdeaTheme\n): AccentPreset | undefined {\n if (accentId === 'theme') return undefined\n const preset = getAccent(accentId)\n if (preset) return preset\n if (!isThemeAccentId(accentId)) return undefined\n return themeAccentPresets(light, dark).find((option) => option.id === accentId)\n}\n\n/**\n * A theme with an accent laid over it, in the catalogue's own shape.\n *\n * The accent replaces `accent` and its measured label, which is all an accent\n * changes about a theme; `undefined` returns the theme untouched. This is the\n * overlay a host needs for `AppearanceEditor`'s `lightTheme`/`darkTheme`.\n */\nexport function withAccent<T extends AdeaTheme>(theme: T, accent: AccentPreset | undefined): T {\n if (!accent) return theme\n const value = theme.appearance === 'dark' ? accent.dark : accent.light\n return {\n ...theme,\n colors: { ...theme.colors, accent: value, accentForeground: accentForeground(value) },\n }\n}\n\n/**\n * The two preview themes an appearance selection resolves to, accent applied.\n *\n * The adapter between a stored selection and `AppearanceEditor`: it takes ids —\n * what a preference holds — and returns the canonical records the editor's\n * `lightTheme` and `darkTheme` props take, so a host does not map roles by hand.\n * Unknown ids fall back to the defaults and an accent the pair cannot offer falls\n * back to the theme's own, exactly as `ThemeProvider` resolves them.\n */\nexport function appearancePreviewThemes(selection: {\n lightThemeId: string\n darkThemeId: string\n accent: string\n}): { lightTheme: AdeaThemeRecord; darkTheme: AdeaThemeRecord } {\n const { light, dark } = recordPair(selection.lightThemeId, selection.darkThemeId)\n const accent = resolveAccentPreset(selection.accent, light, dark)\n return { lightTheme: withAccent(light, accent), darkTheme: withAccent(dark, accent) }\n}\n\n/**\n * The properties an accent selection overrides, as CSS custom properties.\n *\n * ## Why this exists rather than relying on the `[data-accent]` blocks\n *\n * `theme.css` carries a `[data-accent='…']` block per preset, and those blocks are\n * correct — but they are unreachable at runtime. `ThemeProvider` writes a theme's\n * whole role set onto `<html>` as *inline* custom properties, and an inline\n * declaration outranks any stylesheet selector regardless of specificity. The\n * attribute was set, the rules existed, the values were right, and every one of the\n * seven accents rendered as the same blue.\n *\n * The blocks are kept, because they are what styles the window between the document\n * arriving and the provider mounting — which is the whole reason `themeScript`\n * exists. But the authoritative value has to be applied by the same code that\n * applies the theme, from the same source, or the two can drift again. So both the\n * provider and the CSS generator call `accentRoles` out of `@adea-ai/themes`, and\n * `tests/appearance-axes.test.ts` asserts the two agree value for value.\n *\n * A theme accent (`ansi-blue`) has no block: its value depends on the theme pair,\n * so it is resolved against `pair` — the selection's light and dark theme ids —\n * and only ever applied here. Without a pair it resolves against the defaults.\n *\n * Returns `undefined` for `theme` — the variant's own primary — for an id the\n * catalogue does not have, and for a theme accent the pair does not offer, so a\n * stale stored preference falls back to the theme rather than blanking the primary.\n */\nexport function accentVariables(\n accentId: string,\n appearance: ThemeAppearance,\n pair: { lightThemeId: string; darkThemeId: string } = {\n lightThemeId: defaultLightThemeId,\n darkThemeId: defaultDarkThemeId,\n }\n): Record<string, string> | undefined {\n if (accentId === 'theme') return undefined\n const { light, dark } = recordPair(pair.lightThemeId, pair.darkThemeId)\n const preset = resolveAccentPreset(accentId, light, dark)\n if (!preset) return undefined\n\n const roles = accentRoles(preset, appearance)\n return {\n '--primary': roles.primary,\n '--primary-foreground': roles.primaryForeground,\n '--primary-hover': roles.primaryHover,\n '--primary-subtle': roles.primarySubtle,\n '--ring': roles.ring,\n }\n}\n\n/**\n * The roles a variant sets, as CSS custom properties.\n *\n * The one place that knows the mapping from a theme's roles to this system's variable\n * names. A provider applies this; nothing else repeats it. The `--terminal-*` and\n * `--editor-*` ramps are presentations of the catalogue's ANSI and syntax data rather\n * than separate roles, which is why they are built here and not in the catalogue.\n */\nexport function themeCssVariables(theme: ThemeVariant): Record<string, string> {\n const c = theme.colors\n const t = theme.terminal\n const e = theme.editor\n return {\n '--background': c.background,\n '--foreground': c.foreground,\n '--card': c.card,\n '--card-foreground': c.cardForeground,\n '--popover': c.popover,\n '--popover-foreground': c.popoverForeground,\n '--primary': c.primary,\n '--primary-foreground': c.primaryForeground,\n /*\n * The two tokens derived from the primary, and they are here rather than left to\n * `theme.css` because they must follow `--primary` — which this function writes\n * for *any* theme in the catalogue, not just the two defaults `theme.css` carries.\n *\n * `--primary-hover` is a resolved colour, not a `color-mix()`: a uniform hover\n * step cannot be expressed as a mix (see `primaryHover`). Left out, a theme switch\n * would keep the previous theme's hover on the new theme's primary.\n *\n * `--primary-subtle` is a mix over `--primary`, so it would follow on its own —\n * it is written anyway so the pair is applied together and neither is left to\n * depend on which stylesheet happened to load.\n */\n '--primary-hover': primaryHover(c.primary, theme.appearance),\n '--primary-subtle': primarySubtleCss(theme.appearance),\n '--secondary': c.secondary,\n '--secondary-foreground': c.secondaryForeground,\n '--muted': c.muted,\n '--muted-foreground': c.mutedForeground,\n '--accent': c.accent,\n '--accent-foreground': c.accentForeground,\n '--destructive': c.destructive,\n '--destructive-foreground': c.destructiveForeground,\n '--destructive-subtle': c.destructiveSubtle,\n '--destructive-action': c.destructiveAction,\n '--destructive-action-foreground': c.destructiveActionForeground,\n '--success': c.success,\n '--success-foreground': c.successForeground,\n '--success-subtle': c.successSubtle,\n '--warning': c.warning,\n '--warning-foreground': c.warningForeground,\n '--warning-subtle': c.warningSubtle,\n '--info': c.info,\n '--info-foreground': c.infoForeground,\n '--info-subtle': c.infoSubtle,\n '--border': c.border,\n '--input': c.input,\n '--ring': c.ring,\n '--sidebar': c.sidebar,\n '--sidebar-foreground': c.sidebarForeground,\n '--sidebar-accent': c.sidebarAccent,\n '--sidebar-border': c.sidebarBorder,\n '--sidebar-primary': c.primary,\n '--sidebar-primary-foreground': c.primaryForeground,\n '--sidebar-ring': c.ring,\n '--sidebar-muted-foreground': c.mutedForeground,\n '--surface-sunken': c.muted,\n '--surface-hover': c.accent,\n '--surface-active': c.border,\n '--chrome': c.background,\n '--terminal-background': t.background,\n '--terminal-foreground': t.foreground,\n '--terminal-cursor': t.cursor,\n '--terminal-selection': t.selection,\n '--terminal-ansi-black': t.black,\n '--terminal-ansi-red': t.red,\n '--terminal-ansi-green': t.green,\n '--terminal-ansi-yellow': t.yellow,\n '--terminal-ansi-blue': t.blue,\n '--terminal-ansi-magenta': t.magenta,\n '--terminal-ansi-cyan': t.cyan,\n '--terminal-ansi-white': t.white,\n '--terminal-ansi-bright-black': t.brightBlack,\n '--terminal-ansi-bright-red': t.brightRed,\n '--terminal-ansi-bright-green': t.brightGreen,\n '--terminal-ansi-bright-yellow': t.brightYellow,\n '--terminal-ansi-bright-blue': t.brightBlue,\n '--terminal-ansi-bright-magenta': t.brightMagenta,\n '--terminal-ansi-bright-cyan': t.brightCyan,\n '--terminal-ansi-bright-white': t.brightWhite,\n '--editor-keyword': e.keyword,\n '--editor-string': e.string,\n '--editor-number': e.number,\n '--editor-comment': e.comment,\n '--editor-function': e.function,\n '--editor-variable': e.variable,\n '--editor-type': e.type,\n '--editor-tag': e.tag,\n '--editor-attribute': e.attribute,\n '--editor-operator': e.operator,\n '--editor-heading': e.heading,\n '--editor-link': e.link,\n '--editor-diff-add': e.diffAdd,\n '--editor-diff-delete': e.diffDelete,\n '--editor-diff-hunk': e.diffHunk,\n '--editor-search-match': e.searchMatch,\n '--chart-1': theme.chart[0] ?? c.primary,\n '--chart-2': theme.chart[1] ?? c.info,\n '--chart-3': theme.chart[2] ?? c.success,\n '--chart-4': theme.chart[3] ?? c.warning,\n '--chart-5': theme.chart[4] ?? c.destructive,\n '--chart-6': theme.chart[5] ?? c.mutedForeground,\n }\n}\n\n/* ---------------------------------------------------------------------------\n * Validation\n *\n * Delegated. The floors are the catalogue's, because they are what makes the\n * catalogue able to hold other people's palettes at all, and a second set of floors\n * here would be a second answer to the same question — and the one that drifts.\n * ------------------------------------------------------------------------- */\n\nexport type ThemeFinding = {\n themeId: string\n role: string\n message: string\n}\n\nfunction toFinding(finding: ContrastFinding): ThemeFinding {\n return { themeId: finding.themeId, role: finding.role, message: finding.message }\n}\n\n/** Validates one variant. The floors, and the reasoning behind them, live in the catalogue. */\nexport function validateTheme(theme: ThemeVariant): ThemeFinding[] {\n const record = catalogue.find((entry) => entry.id === theme.id)\n if (!record) {\n return [{ themeId: theme.id, role: 'id', message: `${theme.id} is not in the catalogue` }]\n }\n return validateCatalogue([record]).map(toFinding)\n}\n\n/** Validates the whole registry, including the catalogue-level invariants. */\nexport function validateThemeRegistry(\n themes: readonly ThemeVariant[] = builtinThemes\n): ThemeFinding[] {\n const records = themes\n .map((theme) => catalogue.find((entry) => entry.id === theme.id))\n .filter((record): record is AdeaThemeRecord => !!record)\n\n const orphaned = themes\n .filter((theme) => !hasTheme(theme.id))\n .map((theme) => ({\n themeId: theme.id,\n role: 'id',\n message: `${theme.id} is in the registry but not in the catalogue`,\n }))\n\n return [...orphaned, ...validateCatalogue(records).map(toFinding)]\n}\n\nexport const defaultLightThemeId = 'adea-light'\nexport const defaultDarkThemeId = 'adea-dark'\n\n/** Re-exported so a consumer measuring a colour does not need a second import. */\nexport { contrastRatio } from '@adea-ai/themes'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"themes.js","names":["catalogue","themes"],"sources":["../../src/lib/themes.ts"],"sourcesContent":["/**\n * The theme registry, now a bridge.\n *\n * The catalogue itself lives in `@adea-ai/themes`. This module is what is left in\n * the design system: the translation between the catalogue's **canonical** role\n * names and the **shadcn** vocabulary every component here is written against, plus\n * the handful of custom properties this system declares that are presentations of\n * data the catalogue already holds — the `--terminal-*` ramp, the `--editor-*` ramp,\n * and `--chrome`.\n *\n * ## Why it is a bridge and not a copy\n *\n * This file used to hold thirteen themes as hand-written hex literal tables, with its\n * own contrast validator, its own terminal and editor palettes, and its own\n * provenance records. That is a lot of surface to maintain for one consumer of a\n * palette, and it meant every product that wanted the same themes — Adea, Cortana —\n * either imported this package or wrote its own. The catalogue moved out so that\n * there is one answer to \"what is Catppuccin Mocha\", and this file is the part that\n * genuinely belongs to the design system.\n *\n * It is deliberately thin. If you are looking for a colour, it is not here: see\n * `@adea-ai/themes`, whose README explains how the values are produced and whose\n * `NOTICE` records where every palette came from.\n *\n * ## The mapping, and the entry that is not a rename\n *\n * {@link ROLE_FOR} maps canonical roles onto this system's variable vocabulary. One\n * entry will trip a reader: the catalogue's `accent` becomes this system's\n * `primary`, because in the shadcn vocabulary `--primary` is the action colour — the\n * fill of a primary button, the thing a focus ring is drawn in — while `--accent` is\n * a low-contrast hover wash. The catalogue's `accent` is the former, so it goes to\n * `--primary`, and `--accent` is filled from `surfaceHover`, which is what shadcn\n * components actually use it for.\n */\n\nimport {\n ACCENTS,\n accentForeground,\n accentRoles,\n chartSeries,\n getAccent,\n getTheme,\n hasTheme,\n shadcnDestructiveProjection,\n statusForeground,\n tint,\n primaryHover,\n primarySubtleCss,\n syntaxRoles,\n themes as catalogue,\n themesByAppearance,\n themeAccentPresets,\n validateCatalogue,\n type AccentPreset,\n type AdeaTheme,\n type AdeaThemeRecord,\n type ContrastFinding,\n} from '@adea-ai/themes'\nimport { isThemeAccentId } from './theme-accents'\n\nexport { isThemeAccentId } from './theme-accents'\n\nexport type ThemeAppearance = 'light' | 'dark'\n\n/**\n * The surface and text roles, in shadcn's vocabulary.\n *\n * Named to match the components below, which is why they differ from the\n * catalogue's: these are this system's variable names, and renaming them would mean\n * touching every component in the library for no gain.\n */\nexport type ThemeColors = {\n background: string\n foreground: string\n card: string\n cardForeground: string\n popover: string\n popoverForeground: string\n primary: string\n primaryForeground: string\n secondary: string\n secondaryForeground: string\n muted: string\n mutedForeground: string\n accent: string\n accentForeground: string\n destructive: string\n destructiveForeground: string\n destructiveSubtle: string\n /** Contrast-safe solid-action presentation, derived from the canonical error role. */\n destructiveAction: string\n destructiveActionForeground: string\n success: string\n successForeground: string\n successSubtle: string\n warning: string\n warningForeground: string\n warningSubtle: string\n info: string\n infoForeground: string\n infoSubtle: string\n border: string\n input: string\n ring: string\n sidebar: string\n sidebarForeground: string\n sidebarAccent: string\n sidebarBorder: string\n}\n\n/** The sixteen ANSI colours a terminal needs, plus its cursor and selection. */\nexport type ThemeTerminalPalette = {\n background: string\n foreground: string\n cursor: string\n selection: string\n black: string\n red: string\n green: string\n yellow: string\n blue: string\n magenta: string\n cyan: string\n white: string\n brightBlack: string\n brightRed: string\n brightGreen: string\n brightYellow: string\n brightBlue: string\n brightMagenta: string\n brightCyan: string\n brightWhite: string\n}\n\n/** The syntax roles a code view needs. */\nexport type ThemeEditorPalette = {\n keyword: string\n string: string\n number: string\n comment: string\n function: string\n variable: string\n type: string\n tag: string\n attribute: string\n operator: string\n heading: string\n link: string\n diffAdd: string\n diffDelete: string\n diffHunk: string\n searchMatch: string\n}\n\n/** Where a palette came from, and the terms it is used under. */\nexport type ThemeProvenance = {\n /** The project or person the palette belongs to. */\n source: string\n url: string\n /** An SPDX identifier. Every palette in this catalogue is permissive. */\n license: string\n}\n\nexport type ThemeVariant = {\n /** The `data-theme` value and the id a preference stores. */\n id: string\n /** Groups the variants that came from one project. */\n family: string\n familyLabel: string\n label: string\n appearance: ThemeAppearance\n /** One line, shown in a picker. */\n description: string\n colors: ThemeColors\n terminal: ThemeTerminalPalette\n editor: ThemeEditorPalette\n /** The categorical series, in order. */\n chart: readonly string[]\n provenance: ThemeProvenance\n}\n\n/**\n * Canonical role → this system's `ThemeColors` key.\n *\n * Read by {@link toVariant}. The two derived destructive-action presentation values\n * are intentionally excluded; the shared Themes adapter owns their color math.\n */\ntype ThemeRole = Exclude<keyof ThemeColors, 'destructiveAction' | 'destructiveActionForeground'>\n\nconst ROLE_FOR: Readonly<Record<ThemeRole, keyof AdeaThemeRecord['colors']>> = {\n background: 'background',\n foreground: 'text',\n card: 'surface',\n cardForeground: 'text',\n popover: 'surfaceElevated',\n popoverForeground: 'text',\n // Not a rename — see this module's header.\n primary: 'accent',\n primaryForeground: 'accentForeground',\n // shadcn's `secondary` and `muted` are both the first surface rung used as a fill.\n secondary: 'surface',\n secondaryForeground: 'text',\n muted: 'surface',\n mutedForeground: 'textMuted',\n // shadcn's `accent` is a hover wash, which is exactly `surfaceHover`.\n accent: 'surfaceHover',\n accentForeground: 'text',\n destructive: 'error',\n // Overwritten below from the measured pairing; nominal here so the table is total.\n destructiveForeground: 'error',\n destructiveSubtle: 'error',\n success: 'success',\n successForeground: 'success',\n successSubtle: 'success',\n warning: 'warning',\n warningForeground: 'warning',\n warningSubtle: 'warning',\n info: 'info',\n infoForeground: 'info',\n infoSubtle: 'info',\n border: 'border',\n input: 'border',\n ring: 'accent',\n sidebar: 'surface',\n sidebarForeground: 'text',\n sidebarAccent: 'surfaceHover',\n sidebarBorder: 'border',\n}\n\n/** Builds the design system's view of one catalogue entry. */\nfunction toVariant(theme: AdeaThemeRecord): ThemeVariant {\n const colors = {} as ThemeColors\n for (const key of Object.keys(ROLE_FOR) as ThemeRole[]) {\n colors[key] = theme.colors[ROLE_FOR[key]]\n }\n // Keep the semantic foreground paired with the canonical error role. Filled\n // destructive actions use the distinct projection below so their /90 hover state\n // remains readable without changing icons, borders, or tinted status surfaces.\n colors.destructiveForeground = statusForeground(theme, 'error')\n colors.destructiveSubtle = tint(theme.colors.error, theme.colors.background)\n const destructiveAction = shadcnDestructiveProjection(theme)\n colors.destructiveAction = destructiveAction.fill\n colors.destructiveActionForeground = destructiveAction.foreground\n colors.successForeground = statusForeground(theme, 'success')\n colors.successSubtle = tint(theme.colors.success, theme.colors.background)\n colors.warningForeground = statusForeground(theme, 'warning')\n colors.warningSubtle = tint(theme.colors.warning, theme.colors.background)\n colors.infoForeground = statusForeground(theme, 'info')\n colors.infoSubtle = tint(theme.colors.info, theme.colors.background)\n\n const syntax = syntaxRoles(theme)\n\n return {\n id: theme.id,\n family: theme.family,\n familyLabel: theme.familyLabel,\n label: theme.label,\n appearance: theme.appearance,\n description: theme.description,\n colors,\n terminal: {\n // The embedded terminal uses the theme's own canvas rather than a palette of its\n // own. The ANSI colours came from the palette that produced the canvas, so they\n // were chosen against it; a terminal on a different background would be the one\n // surface in the application not lit by the active theme.\n background: theme.colors.background,\n foreground: theme.colors.foreground,\n cursor: theme.cursor,\n selection: theme.selection,\n ...theme.ansi,\n },\n editor: {\n keyword: syntax.keyword,\n string: syntax.string,\n number: syntax.number,\n comment: syntax.comment,\n function: syntax.function,\n variable: syntax.variable,\n type: syntax.type,\n tag: syntax.tag,\n attribute: syntax.attribute,\n operator: syntax.operator,\n heading: syntax.heading,\n link: syntax.link,\n diffAdd: syntax.diffAdd,\n diffDelete: syntax.diffDelete,\n diffHunk: syntax.diffHunk,\n searchMatch: syntax.searchMatch,\n },\n chart: chartSeries(theme),\n provenance: {\n source: theme.provenance.project,\n url: theme.provenance.url,\n license: theme.provenance.license,\n },\n }\n}\n\n/**\n * A variant's `--primary-subtle`: the tint over `var(--primary)` at the strength its\n * catalogue record measures (`primarySubtleAlpha`). A variant that is not in the\n * catalogue has nothing to measure, and gets its appearance's ceiling.\n */\nexport function primarySubtleFor(theme: Pick<ThemeVariant, 'id' | 'appearance'>): string {\n const record = getTheme(theme.id)\n return record ? primarySubtleCss(record) : primarySubtleCss(theme.appearance)\n}\n\n/** The catalogue, in catalogue order. */\nexport const builtinThemes: readonly ThemeVariant[] = Object.freeze(catalogue.map(toVariant))\n\nexport function themeById(id: string): ThemeVariant | undefined {\n if (!hasTheme(id)) return undefined\n return builtinThemes.find((theme) => theme.id === id)\n}\n\n/** The variants of one appearance, which is what a picker for that mode shows. */\nexport function themesForAppearance(appearance: ThemeAppearance): readonly ThemeVariant[] {\n const ids = new Set(themesByAppearance(appearance).map((theme) => theme.id))\n return builtinThemes.filter((theme) => ids.has(theme.id))\n}\n\n/** The families in the catalogue, in catalogue order. */\nexport function themeFamilies(): { family: string; label: string; themes: ThemeVariant[] }[] {\n const families = new Map<string, { family: string; label: string; themes: ThemeVariant[] }>()\n for (const theme of builtinThemes) {\n const entry = families.get(theme.family) ?? {\n family: theme.family,\n label: theme.familyLabel,\n themes: [],\n }\n entry.themes.push(theme)\n families.set(theme.family, entry)\n }\n return [...families.values()]\n}\n\n/** The accent presets, in the order a picker should show them. */\nexport const accents = ACCENTS\n\n/**\n * The canonical catalogue records, in catalogue order.\n *\n * {@link builtinThemes} is this system's projection of the catalogue onto the\n * shadcn vocabulary, which is what a document is painted with. A *preview* of a\n * theme — the miniatures `AppearanceEditor` and `ThemeMiniature` draw — reads the\n * catalogue's own roles instead (`surfaceActive`, `borderMuted`, `textSubtle`…),\n * several of which the projection folds together. These are those records, so a\n * consumer hands the editor exactly what it takes rather than reconstructing it\n * from the projection.\n */\nexport const themeRecords: readonly AdeaThemeRecord[] = catalogue\n\nexport function themeRecordById(id: string): AdeaThemeRecord | undefined {\n return getTheme(id)\n}\n\n/** A light/dark theme pair by id, with the defaults standing in for an unknown id. */\nfunction recordPair(lightThemeId: string, darkThemeId: string) {\n const light = getTheme(lightThemeId) ?? getTheme(defaultLightThemeId)!\n const dark = getTheme(darkThemeId) ?? getTheme(defaultDarkThemeId)!\n return { light, dark }\n}\n\n/**\n * The accents the selected light/dark pair carries — offered beside the presets.\n *\n * Computed per pair rather than per theme because a theme accent is a *pair* of\n * values, like a preset: a slot is offered only when both themes can offer it.\n */\nexport function themeAccentsFor(\n lightThemeId: string,\n darkThemeId: string\n): readonly AccentPreset[] {\n const { light, dark } = recordPair(lightThemeId, darkThemeId)\n return themeAccentPresets(light, dark)\n}\n\n/**\n * An accent id resolved against a theme pair: a preset, a theme accent the pair\n * offers, or `undefined` for `theme`, an unknown id, or a slot this pair cannot\n * offer — each of which means \"use the theme's own primary\".\n *\n * Theme accent ids are role-shaped (`ansi-blue`), so a stored one survives a theme\n * switch and resolves to the new theme's blue; when the new pair cannot offer the\n * slot it resolves to nothing, the same fallback a stale preset id gets.\n */\nexport function resolveAccentPreset(\n accentId: string,\n light: AdeaTheme,\n dark: AdeaTheme\n): AccentPreset | undefined {\n if (accentId === 'theme') return undefined\n const preset = getAccent(accentId)\n if (preset) return preset\n if (!isThemeAccentId(accentId)) return undefined\n return themeAccentPresets(light, dark).find((option) => option.id === accentId)\n}\n\n/**\n * A theme with an accent laid over it, in the catalogue's own shape.\n *\n * The accent replaces `accent` and its measured label, which is all an accent\n * changes about a theme; `undefined` returns the theme untouched. This is the\n * overlay a host needs for `AppearanceEditor`'s `lightTheme`/`darkTheme`.\n */\nexport function withAccent<T extends AdeaTheme>(theme: T, accent: AccentPreset | undefined): T {\n if (!accent) return theme\n const value = theme.appearance === 'dark' ? accent.dark : accent.light\n return {\n ...theme,\n colors: { ...theme.colors, accent: value, accentForeground: accentForeground(value) },\n }\n}\n\n/**\n * The two preview themes an appearance selection resolves to, accent applied.\n *\n * The adapter between a stored selection and `AppearanceEditor`: it takes ids —\n * what a preference holds — and returns the canonical records the editor's\n * `lightTheme` and `darkTheme` props take, so a host does not map roles by hand.\n * Unknown ids fall back to the defaults and an accent the pair cannot offer falls\n * back to the theme's own, exactly as `ThemeProvider` resolves them.\n */\nexport function appearancePreviewThemes(selection: {\n lightThemeId: string\n darkThemeId: string\n accent: string\n}): { lightTheme: AdeaThemeRecord; darkTheme: AdeaThemeRecord } {\n const { light, dark } = recordPair(selection.lightThemeId, selection.darkThemeId)\n const accent = resolveAccentPreset(selection.accent, light, dark)\n return { lightTheme: withAccent(light, accent), darkTheme: withAccent(dark, accent) }\n}\n\n/**\n * The properties an accent selection overrides, as CSS custom properties.\n *\n * ## Why this exists rather than relying on the `[data-accent]` blocks\n *\n * `theme.css` carries a `[data-accent='…']` block per preset, and those blocks are\n * correct — but they are unreachable at runtime. `ThemeProvider` writes a theme's\n * whole role set onto `<html>` as *inline* custom properties, and an inline\n * declaration outranks any stylesheet selector regardless of specificity. The\n * attribute was set, the rules existed, the values were right, and every one of the\n * seven accents rendered as the same blue.\n *\n * The blocks are kept, because they are what styles the window between the document\n * arriving and the provider mounting — which is the whole reason `themeScript`\n * exists. But the authoritative value has to be applied by the same code that\n * applies the theme, from the same source, or the two can drift again. So both the\n * provider and the CSS generator call `accentRoles` out of `@adea-ai/themes`, and\n * `tests/appearance-axes.test.ts` asserts the two agree value for value.\n *\n * A theme accent (`ansi-blue`) has no block: its value depends on the theme pair,\n * so it is resolved against `pair` — the selection's light and dark theme ids —\n * and only ever applied here. Without a pair it resolves against the defaults.\n *\n * Returns `undefined` for `theme` — the variant's own primary — for an id the\n * catalogue does not have, and for a theme accent the pair does not offer, so a\n * stale stored preference falls back to the theme rather than blanking the primary.\n */\nexport function accentVariables(\n accentId: string,\n appearance: ThemeAppearance,\n pair: { lightThemeId: string; darkThemeId: string } = {\n lightThemeId: defaultLightThemeId,\n darkThemeId: defaultDarkThemeId,\n }\n): Record<string, string> | undefined {\n if (accentId === 'theme') return undefined\n const { light, dark } = recordPair(pair.lightThemeId, pair.darkThemeId)\n const preset = resolveAccentPreset(accentId, light, dark)\n if (!preset) return undefined\n\n // `--primary-subtle` is deliberately not here. It is a `color-mix()` over\n // `var(--primary)`, so the theme's own declaration (`themeCssVariables`, or the\n // default block in `theme.css`) already follows the accent; and its strength is the\n // *theme's*, measured by `primarySubtleAlpha` to hold body text at 4.5:1 for every\n // accent the theme offers. Writing one here would replace that measured strength\n // with whatever this function was given, which is how an accent used to undo it.\n const roles = accentRoles(preset, appearance)\n return {\n '--primary': roles.primary,\n '--primary-foreground': roles.primaryForeground,\n '--primary-hover': roles.primaryHover,\n '--ring': roles.ring,\n }\n}\n\n/**\n * The roles a variant sets, as CSS custom properties.\n *\n * The one place that knows the mapping from a theme's roles to this system's variable\n * names. A provider applies this; nothing else repeats it. The `--terminal-*` and\n * `--editor-*` ramps are presentations of the catalogue's ANSI and syntax data rather\n * than separate roles, which is why they are built here and not in the catalogue.\n */\nexport function themeCssVariables(theme: ThemeVariant): Record<string, string> {\n const c = theme.colors\n const t = theme.terminal\n const e = theme.editor\n return {\n '--background': c.background,\n '--foreground': c.foreground,\n '--card': c.card,\n '--card-foreground': c.cardForeground,\n '--popover': c.popover,\n '--popover-foreground': c.popoverForeground,\n '--primary': c.primary,\n '--primary-foreground': c.primaryForeground,\n /*\n * The two tokens derived from the primary, and they are here rather than left to\n * `theme.css` because they must follow `--primary` — which this function writes\n * for *any* theme in the catalogue, not just the two defaults `theme.css` carries.\n *\n * `--primary-hover` is a resolved colour, not a `color-mix()`: a uniform hover\n * step cannot be expressed as a mix (see `primaryHover`). Left out, a theme switch\n * would keep the previous theme's hover on the new theme's primary.\n *\n * `--primary-subtle` is a mix over `--primary`, so it follows an accent on its\n * own, but its *strength* is per theme: `primarySubtleCss(record)` lowers the\n * appearance ceiling only as far as this theme needs for body text to clear 4.5:1\n * on the tint, over every surface, for every accent it offers. It has to be\n * written per theme for that reason — the appearance-wide value is not legible on\n * every palette.\n */\n '--primary-hover': primaryHover(c.primary, theme.appearance),\n '--primary-subtle': primarySubtleFor(theme),\n '--secondary': c.secondary,\n '--secondary-foreground': c.secondaryForeground,\n '--muted': c.muted,\n '--muted-foreground': c.mutedForeground,\n '--accent': c.accent,\n '--accent-foreground': c.accentForeground,\n '--destructive': c.destructive,\n '--destructive-foreground': c.destructiveForeground,\n '--destructive-subtle': c.destructiveSubtle,\n '--destructive-action': c.destructiveAction,\n '--destructive-action-foreground': c.destructiveActionForeground,\n '--success': c.success,\n '--success-foreground': c.successForeground,\n '--success-subtle': c.successSubtle,\n '--warning': c.warning,\n '--warning-foreground': c.warningForeground,\n '--warning-subtle': c.warningSubtle,\n '--info': c.info,\n '--info-foreground': c.infoForeground,\n '--info-subtle': c.infoSubtle,\n '--border': c.border,\n '--input': c.input,\n '--ring': c.ring,\n '--sidebar': c.sidebar,\n '--sidebar-foreground': c.sidebarForeground,\n '--sidebar-accent': c.sidebarAccent,\n '--sidebar-border': c.sidebarBorder,\n '--sidebar-primary': c.primary,\n '--sidebar-primary-foreground': c.primaryForeground,\n '--sidebar-ring': c.ring,\n '--sidebar-muted-foreground': c.mutedForeground,\n '--surface-sunken': c.muted,\n '--surface-hover': c.accent,\n '--surface-active': c.border,\n '--chrome': c.background,\n '--terminal-background': t.background,\n '--terminal-foreground': t.foreground,\n '--terminal-cursor': t.cursor,\n '--terminal-selection': t.selection,\n '--terminal-ansi-black': t.black,\n '--terminal-ansi-red': t.red,\n '--terminal-ansi-green': t.green,\n '--terminal-ansi-yellow': t.yellow,\n '--terminal-ansi-blue': t.blue,\n '--terminal-ansi-magenta': t.magenta,\n '--terminal-ansi-cyan': t.cyan,\n '--terminal-ansi-white': t.white,\n '--terminal-ansi-bright-black': t.brightBlack,\n '--terminal-ansi-bright-red': t.brightRed,\n '--terminal-ansi-bright-green': t.brightGreen,\n '--terminal-ansi-bright-yellow': t.brightYellow,\n '--terminal-ansi-bright-blue': t.brightBlue,\n '--terminal-ansi-bright-magenta': t.brightMagenta,\n '--terminal-ansi-bright-cyan': t.brightCyan,\n '--terminal-ansi-bright-white': t.brightWhite,\n '--editor-keyword': e.keyword,\n '--editor-string': e.string,\n '--editor-number': e.number,\n '--editor-comment': e.comment,\n '--editor-function': e.function,\n '--editor-variable': e.variable,\n '--editor-type': e.type,\n '--editor-tag': e.tag,\n '--editor-attribute': e.attribute,\n '--editor-operator': e.operator,\n '--editor-heading': e.heading,\n '--editor-link': e.link,\n '--editor-diff-add': e.diffAdd,\n '--editor-diff-delete': e.diffDelete,\n '--editor-diff-hunk': e.diffHunk,\n '--editor-search-match': e.searchMatch,\n '--chart-1': theme.chart[0] ?? c.primary,\n '--chart-2': theme.chart[1] ?? c.info,\n '--chart-3': theme.chart[2] ?? c.success,\n '--chart-4': theme.chart[3] ?? c.warning,\n '--chart-5': theme.chart[4] ?? c.destructive,\n '--chart-6': theme.chart[5] ?? c.mutedForeground,\n }\n}\n\n/* ---------------------------------------------------------------------------\n * Validation\n *\n * Delegated. The floors are the catalogue's, because they are what makes the\n * catalogue able to hold other people's palettes at all, and a second set of floors\n * here would be a second answer to the same question — and the one that drifts.\n * ------------------------------------------------------------------------- */\n\nexport type ThemeFinding = {\n themeId: string\n role: string\n message: string\n}\n\nfunction toFinding(finding: ContrastFinding): ThemeFinding {\n return { themeId: finding.themeId, role: finding.role, message: finding.message }\n}\n\n/** Validates one variant. The floors, and the reasoning behind them, live in the catalogue. */\nexport function validateTheme(theme: ThemeVariant): ThemeFinding[] {\n const record = catalogue.find((entry) => entry.id === theme.id)\n if (!record) {\n return [{ themeId: theme.id, role: 'id', message: `${theme.id} is not in the catalogue` }]\n }\n return validateCatalogue([record]).map(toFinding)\n}\n\n/** Validates the whole registry, including the catalogue-level invariants. */\nexport function validateThemeRegistry(\n themes: readonly ThemeVariant[] = builtinThemes\n): ThemeFinding[] {\n const records = themes\n .map((theme) => catalogue.find((entry) => entry.id === theme.id))\n .filter((record): record is AdeaThemeRecord => !!record)\n\n const orphaned = themes\n .filter((theme) => !hasTheme(theme.id))\n .map((theme) => ({\n themeId: theme.id,\n role: 'id',\n message: `${theme.id} is in the registry but not in the catalogue`,\n }))\n\n return [...orphaned, ...validateCatalogue(records).map(toFinding)]\n}\n\nexport const defaultLightThemeId = 'adea-light'\nexport const defaultDarkThemeId = 'adea-dark'\n\n/** Re-exported so a consumer measuring a colour does not need a second import. */\nexport { contrastRatio } from '@adea-ai/themes'\n"],"mappings":"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"}
|
package/dist/r/lib.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"title": "Class-name and token helpers",
|
|
5
5
|
"description": "The private helpers the components import: the class-name merge, the variant recipes, the token manifest and the theme bridge. Installed automatically as a peer of any component that needs it.",
|
|
6
6
|
"dependencies": [
|
|
7
|
-
"@adea-ai/themes@^0.9.
|
|
7
|
+
"@adea-ai/themes@^0.9.10",
|
|
8
8
|
"class-variance-authority@^0.7.1",
|
|
9
9
|
"cn@^0.4.0"
|
|
10
10
|
],
|
package/dist/r/registry.json
CHANGED
|
@@ -1993,7 +1993,7 @@
|
|
|
1993
1993
|
"title": "Appearance Editor",
|
|
1994
1994
|
"description": "",
|
|
1995
1995
|
"dependencies": [
|
|
1996
|
-
"@adea-ai/themes@^0.9.
|
|
1996
|
+
"@adea-ai/themes@^0.9.10",
|
|
1997
1997
|
"@kobalte/core@^0.13.14",
|
|
1998
1998
|
"lucide-solid@^1.51.0"
|
|
1999
1999
|
],
|
|
@@ -2186,7 +2186,9 @@
|
|
|
2186
2186
|
"type": "registry:ui",
|
|
2187
2187
|
"title": "Settings",
|
|
2188
2188
|
"description": "",
|
|
2189
|
-
"dependencies": [
|
|
2189
|
+
"dependencies": [
|
|
2190
|
+
"@kobalte/core@^0.13.14"
|
|
2191
|
+
],
|
|
2190
2192
|
"registryDependencies": [
|
|
2191
2193
|
"@adea-ai/ui/sidebar-nav",
|
|
2192
2194
|
"@adea-ai/ui/tabs",
|
|
@@ -2460,7 +2462,7 @@
|
|
|
2460
2462
|
"title": "Theming",
|
|
2461
2463
|
"description": "",
|
|
2462
2464
|
"dependencies": [
|
|
2463
|
-
"@adea-ai/themes@^0.9.
|
|
2465
|
+
"@adea-ai/themes@^0.9.10",
|
|
2464
2466
|
"@kobalte/core@^0.13.14",
|
|
2465
2467
|
"lucide-solid@^1.51.0"
|
|
2466
2468
|
],
|
|
@@ -2575,7 +2577,7 @@
|
|
|
2575
2577
|
"title": "Class-name and token helpers",
|
|
2576
2578
|
"description": "The private helpers the components import: the class-name merge, the variant recipes, the token manifest and the theme bridge. Installed automatically as a peer of any component that needs it.",
|
|
2577
2579
|
"dependencies": [
|
|
2578
|
-
"@adea-ai/themes@^0.9.
|
|
2580
|
+
"@adea-ai/themes@^0.9.10",
|
|
2579
2581
|
"class-variance-authority@^0.7.1",
|
|
2580
2582
|
"cn@^0.4.0"
|
|
2581
2583
|
],
|
package/dist/r/settings.json
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export { SettingsField, SettingsPage, SettingsRow, SettingsSection } from './settings'
|
|
2
|
-
export {
|
|
2
|
+
export {
|
|
3
|
+
SettingsLayout,
|
|
4
|
+
type SettingsLayoutProps,
|
|
5
|
+
type SettingsNavigationLayout,
|
|
6
|
+
} from './settings-layout'
|
|
3
7
|
export {
|
|
4
8
|
SettingsNavigation,
|
|
5
9
|
type SettingsNavigationGroup,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ComponentProps, JSX } from 'solid-js'
|
|
2
|
-
import { splitProps } from 'solid-js'
|
|
2
|
+
import { createSignal, onCleanup, onMount, splitProps } from 'solid-js'
|
|
3
3
|
import { cn } from '../../../lib/utils'
|
|
4
4
|
import { Tabs } from '../../ui/tabs'
|
|
5
5
|
import { SettingsNavigation, type SettingsNavigationGroup } from './settings-navigation'
|
|
@@ -10,7 +10,7 @@ export type SettingsLayoutProps = Omit<
|
|
|
10
10
|
> & {
|
|
11
11
|
/** Grouped navigation entries; the host owns their values and panel content. */
|
|
12
12
|
groups: readonly SettingsNavigationGroup[]
|
|
13
|
-
/** Accessible name for the
|
|
13
|
+
/** Accessible name for the tab list. */
|
|
14
14
|
'aria-label': string
|
|
15
15
|
/** The host-controlled selected destination. */
|
|
16
16
|
value: string
|
|
@@ -20,16 +20,42 @@ export type SettingsLayoutProps = Omit<
|
|
|
20
20
|
onReselect?: (value: string) => void
|
|
21
21
|
/** Reveal the selected row on value changes and window resizes. Defaults to nearest scroll. */
|
|
22
22
|
revealSelected?: boolean | ((trigger: HTMLButtonElement | undefined) => void)
|
|
23
|
+
/**
|
|
24
|
+
* How the section navigation sits beside the panels. `auto` (the default) is
|
|
25
|
+
* the vertical rail from 48rem of viewport width up and a horizontal,
|
|
26
|
+
* scrollable strip of tabs above the panels below it. `rail` and `strip` pin
|
|
27
|
+
* one shape at every width.
|
|
28
|
+
*/
|
|
29
|
+
navigationLayout?: SettingsNavigationLayout
|
|
23
30
|
/** Panels must be rendered as `TabsContent` descendants. */
|
|
24
31
|
children?: JSX.Element
|
|
25
32
|
}
|
|
26
33
|
|
|
34
|
+
export type SettingsNavigationLayout = 'auto' | 'rail' | 'strip'
|
|
35
|
+
|
|
36
|
+
/** The `md` breakpoint the rail has always widened at; below it the rail becomes a strip. */
|
|
37
|
+
const RAIL_MEDIA_QUERY = '(min-width: 48rem)'
|
|
38
|
+
|
|
39
|
+
function railQuery(): MediaQueryList | undefined {
|
|
40
|
+
return typeof window === 'undefined' || typeof window.matchMedia !== 'function'
|
|
41
|
+
? undefined
|
|
42
|
+
: window.matchMedia(RAIL_MEDIA_QUERY)
|
|
43
|
+
}
|
|
44
|
+
|
|
27
45
|
/**
|
|
28
46
|
* SettingsLayout.
|
|
29
47
|
*
|
|
30
48
|
* A controlled, vertical settings rail beside its scrollable panel viewport.
|
|
31
49
|
* The host keeps ownership of selection, URL/hash state and panel content.
|
|
32
|
-
*
|
|
50
|
+
*
|
|
51
|
+
* Below 48rem the rail becomes a horizontal strip of tabs above the panels.
|
|
52
|
+
* A 6rem rail at phone width clips every label, so this is the default rather
|
|
53
|
+
* than an opt-in. It changes the tab root's orientation, not just its
|
|
54
|
+
* styling: the list's `aria-orientation` and Kobalte's arrow keys (Up/Down on
|
|
55
|
+
* the rail, Left/Right on the strip) follow the axis the reader sees. The
|
|
56
|
+
* breakpoint is the viewport's, like CatalogBrowser's and ContextualSidebar's,
|
|
57
|
+
* and is read before the first render so a phone never paints the rail. A
|
|
58
|
+
* server render, which has no viewport, renders the rail.
|
|
33
59
|
*/
|
|
34
60
|
export function SettingsLayout(props: SettingsLayoutProps) {
|
|
35
61
|
const [local, rest] = splitProps(props, [
|
|
@@ -40,12 +66,29 @@ export function SettingsLayout(props: SettingsLayoutProps) {
|
|
|
40
66
|
'value',
|
|
41
67
|
'onReselect',
|
|
42
68
|
'revealSelected',
|
|
69
|
+
'navigationLayout',
|
|
43
70
|
])
|
|
44
71
|
|
|
72
|
+
const [wide, setWide] = createSignal(railQuery()?.matches ?? true)
|
|
73
|
+
onMount(() => {
|
|
74
|
+
const query = railQuery()
|
|
75
|
+
if (!query) return
|
|
76
|
+
const update = () => setWide(query.matches)
|
|
77
|
+
update()
|
|
78
|
+
query.addEventListener('change', update)
|
|
79
|
+
onCleanup(() => query.removeEventListener('change', update))
|
|
80
|
+
})
|
|
81
|
+
const layout = (): 'rail' | 'strip' => {
|
|
82
|
+
const requested = local.navigationLayout ?? 'auto'
|
|
83
|
+
if (requested !== 'auto') return requested
|
|
84
|
+
return wide() ? 'rail' : 'strip'
|
|
85
|
+
}
|
|
86
|
+
|
|
45
87
|
return (
|
|
46
88
|
<Tabs
|
|
47
89
|
{...rest}
|
|
48
|
-
orientation=
|
|
90
|
+
orientation={layout() === 'rail' ? 'vertical' : 'horizontal'}
|
|
91
|
+
data-navigation-layout={layout()}
|
|
49
92
|
value={local.value}
|
|
50
93
|
class={cn('min-h-0 min-w-0 flex-1 gap-0', local.class)}
|
|
51
94
|
>
|
|
@@ -55,7 +98,7 @@ export function SettingsLayout(props: SettingsLayoutProps) {
|
|
|
55
98
|
value={local.value}
|
|
56
99
|
onReselect={local.onReselect}
|
|
57
100
|
revealSelected={local.revealSelected}
|
|
58
|
-
class=
|
|
101
|
+
class={layout() === 'rail' ? 'w-24 md:w-sidebar' : undefined}
|
|
59
102
|
/>
|
|
60
103
|
<div data-slot="settings-layout-panels" class="min-h-0 min-w-0 flex-1 overflow-y-auto p-4">
|
|
61
104
|
{local.children}
|