@adea-ai/ui 0.99.0 → 0.99.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.
@@ -1 +1 @@
1
- {"version":3,"file":"appearance-choices.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/appearance-editor/appearance-choices.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAc/D,wBAAgB,WAAW,CAAC,KAAK,EAAE,qBAAqB,kCAyCvD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,qBAAqB,kCAgEzD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,qBAAqB,kCA6BxD"}
1
+ {"version":3,"file":"appearance-choices.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/appearance-editor/appearance-choices.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAc/D,wBAAgB,WAAW,CAAC,KAAK,EAAE,qBAAqB,kCAyCvD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,qBAAqB,kCA+EzD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,qBAAqB,kCA6BxD"}
@@ -5,9 +5,9 @@ import { RadioGroup } from "@kobalte/core/radio-group";
5
5
  //#region src/components/composites/appearance-editor/appearance-choices.tsx
6
6
  var _tmpl$ = /*#__PURE__*/ template(`<span class="block h-20 w-full">`);
7
7
  var _tmpl$2 = /*#__PURE__*/ template(`<span>`);
8
- var _tmpl$3 = /*#__PURE__*/ template(`<div class="flex flex-col gap-2">`);
9
- var _tmpl$4 = /*#__PURE__*/ template(`<div class="grid grid-cols-3 gap-2">`);
10
- var _tmpl$5 = /*#__PURE__*/ template(`<span class="block size-full rounded-full"aria-hidden=true>`);
8
+ var _tmpl$3 = /*#__PURE__*/ template(`<span class="block size-full rounded-full"aria-hidden=true>`);
9
+ var _tmpl$4 = /*#__PURE__*/ template(`<span class=sr-only>Theme default`);
10
+ var _tmpl$5 = /*#__PURE__*/ template(`<div class="grid grid-cols-4 gap-2">`);
11
11
  var _tmpl$6 = /*#__PURE__*/ template(`<span class=sr-only>`);
12
12
  var MODES = [
13
13
  {
@@ -104,6 +104,7 @@ function ModeChoices(props) {
104
104
  });
105
105
  }
106
106
  function AccentChoices(props) {
107
+ const resolvedAppearance = () => props.draft.mode === "system" ? props.resolvedAppearance : props.draft.mode;
107
108
  const custom = () => props.draft.accent !== "theme" && !props.accentOptions.some((option) => option.id === props.draft.accent);
108
109
  const accentSelection = () => custom() ? "custom" : props.draft.accent;
109
110
  return createComponent(RadioGroup, {
@@ -119,29 +120,24 @@ function AccentChoices(props) {
119
120
  onChange: (accent) => props.onChange({ accent: accent === "custom" ? props.customAccentValue ?? "" : accent }),
120
121
  get children() {
121
122
  return [(() => {
122
- var _el$3 = _tmpl$3();
123
+ var _el$3 = _tmpl$5();
123
124
  insert(_el$3, createComponent(RadioGroup.Item, {
124
125
  value: "theme",
126
+ "class": "rounded-full focus-within:ring-3 focus-within:ring-ring/50",
125
127
  get children() {
126
128
  return [createComponent(RadioGroup.ItemInput, {}), createComponent(RadioGroup.ItemLabel, {
127
- "class": "flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary",
128
- children: "Theme default"
129
- })];
130
- }
131
- }), null);
132
- insert(_el$3, createComponent(RadioGroup.Item, {
133
- value: "custom",
134
- get children() {
135
- return [createComponent(RadioGroup.ItemInput, {}), createComponent(RadioGroup.ItemLabel, {
136
- "class": "flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary",
137
- children: "Custom"
129
+ "class": "block size-7 cursor-pointer rounded-full border p-0.5 data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary",
130
+ get children() {
131
+ return [(() => {
132
+ var _el$4 = _tmpl$3();
133
+ effect((_$p) => setStyleProperty(_el$4, "background-color", resolvedAppearance() === "light" ? props.lightTheme.colors.accent : props.darkTheme.colors.accent));
134
+ return _el$4;
135
+ })(), _tmpl$4()];
136
+ }
138
137
  })];
139
138
  }
140
139
  }), null);
141
- return _el$3;
142
- })(), (() => {
143
- var _el$4 = _tmpl$4();
144
- insert(_el$4, createComponent(For, {
140
+ insert(_el$3, createComponent(For, {
145
141
  get each() {
146
142
  return props.accentOptions;
147
143
  },
@@ -155,21 +151,29 @@ function AccentChoices(props) {
155
151
  "class": "block size-7 cursor-pointer rounded-full border p-0.5 data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary",
156
152
  get children() {
157
153
  return [(() => {
158
- var _el$5 = _tmpl$5();
159
- effect((_$p) => setStyleProperty(_el$5, "background-color", (props.draft.mode === "system" ? props.resolvedAppearance : props.draft.mode) === "light" ? option.light : option.dark));
160
- return _el$5;
161
- })(), (() => {
162
- var _el$6 = _tmpl$6();
163
- insert(_el$6, () => option.label);
154
+ var _el$6 = _tmpl$3();
155
+ effect((_$p) => setStyleProperty(_el$6, "background-color", resolvedAppearance() === "light" ? option.light : option.dark));
164
156
  return _el$6;
157
+ })(), (() => {
158
+ var _el$7 = _tmpl$6();
159
+ insert(_el$7, () => option.label);
160
+ return _el$7;
165
161
  })()];
166
162
  }
167
163
  })];
168
164
  }
169
165
  })
170
- }));
171
- return _el$4;
172
- })()];
166
+ }), null);
167
+ return _el$3;
168
+ })(), createComponent(RadioGroup.Item, {
169
+ value: "custom",
170
+ get children() {
171
+ return [createComponent(RadioGroup.ItemInput, {}), createComponent(RadioGroup.ItemLabel, {
172
+ "class": "flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary",
173
+ children: "Custom"
174
+ })];
175
+ }
176
+ })];
173
177
  }
174
178
  });
175
179
  }
@@ -1 +1 @@
1
- {"version":3,"file":"appearance-choices.js","names":["RadioGroup","Radio","For","Show","AppearanceEditorProps","ThemeMiniature","ThemeMiniatureSplit","MODES","value","label","const","SURFACES","ModeChoices","props","_$createComponent","draft","mode","disabled","saving","orientation","onChange","option","find","candidate","children","each","Item","data-mode","ItemInput","ItemLabel","_el$","_tmpl$","_$insert","when","fallback","theme","_$memo","lightTheme","darkTheme","light","dark","_el$2","_tmpl$2","AccentChoices","custom","accent","accentOptions","some","id","accentSelection","customAccentValue","_el$3","_tmpl$3","_el$4","_tmpl$4","_el$5","_tmpl$5","_$effect","_$p","_$setStyleProperty","resolvedAppearance","_el$6","_tmpl$6","GlassChoices","surface","surfaceCapability","frosted","_$createComponent","Radio","_$memo","_$setStyleProperty"],"sources":["../../../../src/components/composites/appearance-editor/appearance-choices.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n// Pinned mode-card, accent-swatch, and glass-chip composition. Kobalte replaces\n// the app port's manual roving focus; it does not replace the donor hierarchy.\nimport { RadioGroup as Radio } from '@kobalte/core/radio-group'\nimport { For, Show } from 'solid-js'\nimport type { AppearanceEditorProps } from './appearance-types'\nimport { ThemeMiniature, ThemeMiniatureSplit } from './theme-preview'\n\nconst MODES = [\n { value: 'system', label: 'System' },\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n] as const\nconst SURFACES = [\n { value: 'theme', label: 'Theme default' },\n { value: 'frosted', label: 'Frosted' },\n { value: 'opaque', label: 'Opaque' },\n] as const\n\nexport function ModeChoices(props: AppearanceEditorProps) {\n return (\n <Radio\n value={props.draft.mode}\n disabled={props.saving}\n orientation=\"horizontal\"\n aria-label=\"Appearance mode\"\n onChange={(mode) => {\n const option = MODES.find((candidate) => candidate.value === mode)\n if (option) props.onChange({ mode: option.value })\n }}\n class=\"grid grid-cols-1 gap-3 px-4 py-4 sm:grid-cols-3\"\n >\n <For each={MODES}>\n {(option) => (\n <Radio.Item\n value={option.value}\n data-mode={option.value}\n class=\"min-w-0 rounded-lg focus-within:ring-3 focus-within:ring-ring/50\"\n >\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"flex cursor-pointer flex-col gap-2 rounded-lg border p-2 text-center text-xs data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\">\n <span class=\"block h-20 w-full\">\n <Show\n when={option.value === 'system'}\n fallback={\n <ThemeMiniature\n theme={option.value === 'light' ? props.lightTheme : props.darkTheme}\n />\n }\n >\n <ThemeMiniatureSplit light={props.lightTheme} dark={props.darkTheme} />\n </Show>\n </span>\n <span>{option.label}</span>\n </Radio.ItemLabel>\n </Radio.Item>\n )}\n </For>\n </Radio>\n )\n}\n\nexport function AccentChoices(props: AppearanceEditorProps) {\n const custom = () =>\n props.draft.accent !== 'theme' &&\n !props.accentOptions.some((option) => option.id === props.draft.accent)\n const accentSelection = () => (custom() ? 'custom' : props.draft.accent)\n return (\n <Radio\n value={accentSelection()}\n disabled={props.saving}\n orientation=\"horizontal\"\n aria-label=\"Accent\"\n // Two chips in a column beside a 3x2 swatch grid: one line of six\n // swatches plus chips overflows the settings sidebar's control column,\n // and the column keeps both rows of the pair balanced (2 x 28px + gap).\n class=\"flex items-center gap-3\"\n onChange={(accent) =>\n props.onChange({\n accent: accent === 'custom' ? (props.customAccentValue ?? '') : accent,\n })\n }\n >\n <div class=\"flex flex-col gap-2\">\n <Radio.Item value=\"theme\">\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary\">\n Theme default\n </Radio.ItemLabel>\n </Radio.Item>\n <Radio.Item value=\"custom\">\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary\">\n Custom\n </Radio.ItemLabel>\n </Radio.Item>\n </div>\n <div class=\"grid grid-cols-3 gap-2\">\n <For each={props.accentOptions}>\n {(option) => (\n <Radio.Item\n value={option.id}\n class=\"rounded-full focus-within:ring-3 focus-within:ring-ring/50\"\n >\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"block size-7 cursor-pointer rounded-full border p-0.5 data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary\">\n <span\n class=\"block size-full rounded-full\"\n aria-hidden=\"true\"\n style={{\n 'background-color':\n (props.draft.mode === 'system'\n ? props.resolvedAppearance\n : props.draft.mode) === 'light'\n ? option.light\n : option.dark,\n }}\n />\n <span class=\"sr-only\">{option.label}</span>\n </Radio.ItemLabel>\n </Radio.Item>\n )}\n </For>\n </div>\n </Radio>\n )\n}\n\nexport function GlassChoices(props: AppearanceEditorProps) {\n return (\n <Radio\n value={props.draft.surface}\n disabled={props.saving}\n orientation=\"horizontal\"\n aria-label=\"Glass\"\n class=\"flex flex-wrap gap-1\"\n onChange={(surface) => {\n const option = SURFACES.find((candidate) => candidate.value === surface)\n if (option) props.onChange({ surface: option.value })\n }}\n >\n <For each={SURFACES}>\n {(option) => (\n <Radio.Item\n value={option.value}\n disabled={option.value === 'frosted' && !props.surfaceCapability.frosted}\n class=\"rounded-md focus-within:ring-3 focus-within:ring-ring/50\"\n >\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\">\n {option.label}\n </Radio.ItemLabel>\n </Radio.Item>\n )}\n </For>\n </Radio>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"appearance-choices.js","names":["RadioGroup","Radio","For","Show","AppearanceEditorProps","ThemeMiniature","ThemeMiniatureSplit","MODES","value","label","const","SURFACES","ModeChoices","props","_$createComponent","draft","mode","disabled","saving","orientation","onChange","option","find","candidate","children","each","Item","data-mode","ItemInput","ItemLabel","_el$","_tmpl$","_$insert","when","fallback","theme","_$memo","lightTheme","darkTheme","light","dark","_el$2","_tmpl$2","AccentChoices","resolvedAppearance","custom","accent","accentOptions","some","id","accentSelection","customAccentValue","_el$3","_tmpl$5","_el$4","_tmpl$3","_$effect","_$p","_$setStyleProperty","colors","_tmpl$4","_el$6","_el$7","_tmpl$6","GlassChoices","surface","surfaceCapability","frosted","_$createComponent","Radio","_$memo","_$setStyleProperty"],"sources":["../../../../src/components/composites/appearance-editor/appearance-choices.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n// Pinned mode-card, accent-swatch, and glass-chip composition. Kobalte replaces\n// the app port's manual roving focus; it does not replace the donor hierarchy.\nimport { RadioGroup as Radio } from '@kobalte/core/radio-group'\nimport { For, Show } from 'solid-js'\nimport type { AppearanceEditorProps } from './appearance-types'\nimport { ThemeMiniature, ThemeMiniatureSplit } from './theme-preview'\n\nconst MODES = [\n { value: 'system', label: 'System' },\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n] as const\nconst SURFACES = [\n { value: 'theme', label: 'Theme default' },\n { value: 'frosted', label: 'Frosted' },\n { value: 'opaque', label: 'Opaque' },\n] as const\n\nexport function ModeChoices(props: AppearanceEditorProps) {\n return (\n <Radio\n value={props.draft.mode}\n disabled={props.saving}\n orientation=\"horizontal\"\n aria-label=\"Appearance mode\"\n onChange={(mode) => {\n const option = MODES.find((candidate) => candidate.value === mode)\n if (option) props.onChange({ mode: option.value })\n }}\n class=\"grid grid-cols-1 gap-3 px-4 py-4 sm:grid-cols-3\"\n >\n <For each={MODES}>\n {(option) => (\n <Radio.Item\n value={option.value}\n data-mode={option.value}\n class=\"min-w-0 rounded-lg focus-within:ring-3 focus-within:ring-ring/50\"\n >\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"flex cursor-pointer flex-col gap-2 rounded-lg border p-2 text-center text-xs data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\">\n <span class=\"block h-20 w-full\">\n <Show\n when={option.value === 'system'}\n fallback={\n <ThemeMiniature\n theme={option.value === 'light' ? props.lightTheme : props.darkTheme}\n />\n }\n >\n <ThemeMiniatureSplit light={props.lightTheme} dark={props.darkTheme} />\n </Show>\n </span>\n <span>{option.label}</span>\n </Radio.ItemLabel>\n </Radio.Item>\n )}\n </For>\n </Radio>\n )\n}\n\nexport function AccentChoices(props: AppearanceEditorProps) {\n // The resolved appearance decides which side of a preset pair — and which\n // theme accent — the swatches paint, so the row previews each choice as the\n // user will see it.\n const resolvedAppearance = () =>\n props.draft.mode === 'system' ? props.resolvedAppearance : props.draft.mode\n const custom = () =>\n props.draft.accent !== 'theme' &&\n !props.accentOptions.some((option) => option.id === props.draft.accent)\n const accentSelection = () => (custom() ? 'custom' : props.draft.accent)\n return (\n <Radio\n value={accentSelection()}\n disabled={props.saving}\n orientation=\"horizontal\"\n aria-label=\"Accent\"\n // One chip (custom) beside a capped swatch grid: a chip-per-state column\n // beside a full-width swatch line overflowed the settings sidebar's\n // control column, so the pair stays a narrow chip plus a wrapped grid.\n class=\"flex items-center gap-3\"\n onChange={(accent) =>\n props.onChange({\n accent: accent === 'custom' ? (props.customAccentValue ?? '') : accent,\n })\n }\n >\n <div class=\"grid grid-cols-4 gap-2\">\n {/* The theme's own accent is the first swatch. Picking it is the same\n act the old dedicated \"Theme default\" chip performed, without a\n second control for the state the row starts in. */}\n <Radio.Item\n value=\"theme\"\n class=\"rounded-full focus-within:ring-3 focus-within:ring-ring/50\"\n >\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"block size-7 cursor-pointer rounded-full border p-0.5 data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary\">\n <span\n class=\"block size-full rounded-full\"\n aria-hidden=\"true\"\n style={{\n 'background-color':\n resolvedAppearance() === 'light'\n ? props.lightTheme.colors.accent\n : props.darkTheme.colors.accent,\n }}\n />\n <span class=\"sr-only\">Theme default</span>\n </Radio.ItemLabel>\n </Radio.Item>\n <For each={props.accentOptions}>\n {(option) => (\n <Radio.Item\n value={option.id}\n class=\"rounded-full focus-within:ring-3 focus-within:ring-ring/50\"\n >\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"block size-7 cursor-pointer rounded-full border p-0.5 data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary\">\n <span\n class=\"block size-full rounded-full\"\n aria-hidden=\"true\"\n style={{\n 'background-color':\n resolvedAppearance() === 'light' ? option.light : option.dark,\n }}\n />\n <span class=\"sr-only\">{option.label}</span>\n </Radio.ItemLabel>\n </Radio.Item>\n )}\n </For>\n </div>\n <Radio.Item value=\"custom\">\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary\">\n Custom\n </Radio.ItemLabel>\n </Radio.Item>\n </Radio>\n )\n}\n\nexport function GlassChoices(props: AppearanceEditorProps) {\n return (\n <Radio\n value={props.draft.surface}\n disabled={props.saving}\n orientation=\"horizontal\"\n aria-label=\"Glass\"\n class=\"flex flex-wrap gap-1\"\n onChange={(surface) => {\n const option = SURFACES.find((candidate) => candidate.value === surface)\n if (option) props.onChange({ surface: option.value })\n }}\n >\n <For each={SURFACES}>\n {(option) => (\n <Radio.Item\n value={option.value}\n disabled={option.value === 'frosted' && !props.surfaceCapability.frosted}\n class=\"rounded-md focus-within:ring-3 focus-within:ring-ring/50\"\n >\n <Radio.ItemInput />\n <Radio.ItemLabel class=\"flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50\">\n {option.label}\n </Radio.ItemLabel>\n </Radio.Item>\n )}\n </For>\n </Radio>\n )\n}\n"],"mappings":";;;;;;;;;;;AA8BA,IAAMO,QAAQ;CACZ;EAAEC,OAAO;EAAUC,OAAO;CAAS;CACnC;EAAED,OAAO;EAASC,OAAO;CAAQ;CACjC;EAAED,OAAO;EAAQC,OAAO;CAAO;AAAC;AAElC,IAAME,WAAW;CACf;EAAEH,OAAO;EAASC,OAAO;CAAgB;CACzC;EAAED,OAAO;EAAWC,OAAO;CAAU;CACrC;EAAED,OAAO;EAAUC,OAAO;CAAS;AAAC;AAGtC,SAAgBG,YAAYC,OAA8B;CACxD,OAAAC,gBACGb,YAAK;EAAA,IACJO,QAAK;GAAA,OAAEK,MAAME,MAAMC;EAAI;EAAA,IACvBC,WAAQ;GAAA,OAAEJ,MAAMK;EAAM;EACtBC,aAAW;EAAA,cAAA;EAEXC,WAAWJ,SAAS;GAClB,MAAMK,SAASd,MAAMe,MAAMC,cAAcA,UAAUf,UAAUQ,IAAI;GACjE,IAAIK,QAAQR,MAAMO,SAAS,EAAEJ,MAAMK,OAAOb,MAAM,CAAC;EACnD;EAAC,SAAA;EAAA,IAAAgB,WAAA;GAAA,OAAAV,gBAGAZ,KAAG;IAACuB,MAAMlB;IAAKiB,WACZH,WAAMP,gBACLb,WAAMyB,MAAI;KAAA,IACTlB,QAAK;MAAA,OAAEa,OAAOb;KAAK;KAAA,KAAA,eAAA;MAAA,OACRa,OAAOb;KAAK;KAAA,SAAA;KAAA,IAAAgB,WAAA;MAAA,OAAA,CAAAV,gBAGtBb,WAAM2B,WAAS,CAAA,CAAA,GAAAd,gBACfb,WAAM4B,WAAS;OAAA,SAAA;OAAA,IAAAL,WAAA;QAAA,OAAA,QAAA;SAAA,IAAAM,OAAAC,OAAA;SAAAC,OAAAF,MAAAhB,gBAEXX,MAAI;UAAA,IACH8B,OAAI;WAAA,OAAEZ,OAAOb,UAAU;UAAQ;UAAA,IAC/B0B,WAAQ;WAAA,OAAApB,gBACLT,gBAAc,EAAA,IACb8B,QAAK;YAAA,OAAEC,WAAAf,OAAOb,UAAU,OAAO,CAAA,CAAA,IAAGK,MAAMwB,aAAaxB,MAAMyB;WAAS,EAAA,CAAA;UAAA;UAAA,IAAAd,WAAA;WAAA,OAAAV,gBAIvER,qBAAmB;YAAA,IAACiC,QAAK;aAAA,OAAE1B,MAAMwB;YAAU;YAAA,IAAEG,OAAI;aAAA,OAAE3B,MAAMyB;YAAS;WAAA,CAAA;UAAA;SAAA,CAAA,CAAA;SAAA,OAAAR;QAAA,EAAA,CAAA,UAAA;SAAA,IAAAW,QAAAC,QAAA;SAAAV,OAAAS,aAGhEpB,OAAOZ,KAAK;SAAA,OAAAgC;QAAA,EAAA,CAAA,CAAA;OAAA;MAAA,CAAA,CAAA;KAAA;IAAA,CAAA;GAGxB,CAAA;EAAA;CAAA,CAAA;AAIT;AAEA,SAAgBE,cAAc9B,OAA8B;CAI1D,MAAM+B,2BACJ/B,MAAME,MAAMC,SAAS,WAAWH,MAAM+B,qBAAqB/B,MAAME,MAAMC;CACzE,MAAM6B,eACJhC,MAAME,MAAM+B,WAAW,WACvB,CAACjC,MAAMkC,cAAcC,MAAM3B,WAAWA,OAAO4B,OAAOpC,MAAME,MAAM+B,MAAM;CACxE,MAAMI,wBAAyBL,OAAO,IAAI,WAAWhC,MAAME,MAAM+B;CACjE,OAAAhC,gBACGb,YAAK;EAAA,IACJO,QAAK;GAAA,OAAE0C,gBAAgB;EAAC;EAAA,IACxBjC,WAAQ;GAAA,OAAEJ,MAAMK;EAAM;EACtBC,aAAW;EAAA,cAAA;EAAA,SAAA;EAMXC,WAAW0B,WACTjC,MAAMO,SAAS,EACb0B,QAAQA,WAAW,WAAYjC,MAAMsC,qBAAqB,KAAML,OAClE,CAAC;EAAC,IAAAtB,WAAA;GAAA,OAAA,QAAA;IAAA,IAAA4B,QAAAC,QAAA;IAAArB,OAAAoB,OAAAtC,gBAODb,WAAMyB,MAAI;KACTlB,OAAK;KAAA,SAAA;KAAA,IAAAgB,WAAA;MAAA,OAAA,CAAAV,gBAGJb,WAAM2B,WAAS,CAAA,CAAA,GAAAd,gBACfb,WAAM4B,WAAS;OAAA,SAAA;OAAA,IAAAL,WAAA;QAAA,OAAA,QAAA;SAAA,IAAA8B,QAAAC,QAAA;SAAAC,QAAAC,QAAAC,iBAAAJ,OAAA,oBAMRV,mBAAmB,MAAM,UACrB/B,MAAMwB,WAAWsB,OAAOb,SACxBjC,MAAMyB,UAAUqB,OAAOb,MAAM,CAAA;SAAA,OAAAQ;QAAA,EAAA,CAAA,GAAAM,QAAA,CAAA;OAAA;MAAA,CAAA,CAAA;KAAA;IAAA,CAAA,GAAA,IAAA;IAAA5B,OAAAoB,OAAAtC,gBAM1CZ,KAAG;KAAA,IAACuB,OAAI;MAAA,OAAEZ,MAAMkC;KAAa;KAAAvB,WAC1BH,WAAMP,gBACLb,WAAMyB,MAAI;MAAA,IACTlB,QAAK;OAAA,OAAEa,OAAO4B;MAAE;MAAA,SAAA;MAAA,IAAAzB,WAAA;OAAA,OAAA,CAAAV,gBAGfb,WAAM2B,WAAS,CAAA,CAAA,GAAAd,gBACfb,WAAM4B,WAAS;QAAA,SAAA;QAAA,IAAAL,WAAA;SAAA,OAAA,QAAA;UAAA,IAAAqC,QAAAN,QAAA;UAAAC,QAAAC,QAAAC,iBAAAG,OAAA,oBAMRjB,mBAAmB,MAAM,UAAUvB,OAAOkB,QAAQlB,OAAOmB,IAAI,CAAA;UAAA,OAAAqB;SAAA,EAAA,CAAA,UAAA;UAAA,IAAAC,QAAAC,QAAA;UAAA/B,OAAA8B,aAG5CzC,OAAOZ,KAAK;UAAA,OAAAqD;SAAA,EAAA,CAAA,CAAA;QAAA;OAAA,CAAA,CAAA;MAAA;KAAA,CAAA;IAGxC,CAAA,GAAA,IAAA;IAAA,OAAAV;GAAA,EAAA,CAAA,GAAAtC,gBAGJb,WAAMyB,MAAI;IAAClB,OAAK;IAAA,IAAAgB,WAAA;KAAA,OAAA,CAAAV,gBACdb,WAAM2B,WAAS,CAAA,CAAA,GAAAd,gBACfb,WAAM4B,WAAS;MAAA,SAAA;MAAAL,UAAA;KAAA,CAAA,CAAA;IAAA;GAAA,CAAA,CAAA;EAAA;CAAA,CAAA;AAMxB;AAEA,SAAgBwC,aAAanD,OAA8B;CACzD,OAAAC,gBACGb,YAAK;EAAA,IACJO,QAAK;GAAA,OAAEK,MAAME,MAAMkD;EAAO;EAAA,IAC1BhD,WAAQ;GAAA,OAAEJ,MAAMK;EAAM;EACtBC,aAAW;EAAA,cAAA;EAAA,SAAA;EAGXC,WAAW6C,YAAY;GACrB,MAAM5C,SAASV,SAASW,MAAMC,cAAcA,UAAUf,UAAUyD,OAAO;GACvE,IAAI5C,QAAQR,MAAMO,SAAS,EAAE6C,SAAS5C,OAAOb,MAAM,CAAC;EACtD;EAAC,IAAAgB,WAAA;GAAA,OAAAV,gBAEAZ,KAAG;IAACuB,MAAMd;IAAQa,WACfH,WAAMP,gBACLb,WAAMyB,MAAI;KAAA,IACTlB,QAAK;MAAA,OAAEa,OAAOb;KAAK;KAAA,IACnBS,WAAQ;MAAA,OAAEmB,WAAAf,OAAOb,UAAU,SAAS,CAAA,CAAA,KAAI,CAACK,MAAMqD,kBAAkBC;KAAO;KAAA,SAAA;KAAA,IAAA3C,WAAA;MAAA,OAAA,CAAAV,gBAGvEb,WAAM2B,WAAS,CAAA,CAAA,GAAAd,gBACfb,WAAM4B,WAAS;OAAA,SAAA;OAAA,IAAAL,WAAA;QAAA,OACbH,OAAOZ;OAAK;MAAA,CAAA,CAAA;KAAA;IAAA,CAAA;GAGlB,CAAA;EAAA;CAAA,CAAA;AAIT"}
@@ -1 +1 @@
1
- {"version":3,"file":"appearance-rows.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/appearance-editor/appearance-rows.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAkD,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AA2BnF,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,GAAG,CAAC,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACzB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;CACtB,eA4BA;AAED,8CAA8C;AAC9C,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,SAAS,CAAA;CACnB,CAAA;AA+PD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAC9B,UAAU,EAAE,OAAO,GAAG,MAAM,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,SAAS,CAAA;IAClB,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B,eAwBA;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,+EAA+E;IAC/E,OAAO,EAAE,SAAS,CAAA;IAClB,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B,eAgCA"}
1
+ {"version":3,"file":"appearance-rows.d.ts","sourceRoot":"","sources":["../../../../src/components/composites/appearance-editor/appearance-rows.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAkD,KAAK,GAAG,EAAE,MAAM,UAAU,CAAA;AA2BnF,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,GAAG,CAAC,OAAO,CAAA;IACjB,WAAW,CAAC,EAAE,GAAG,CAAC,OAAO,CAAA;IACzB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAA;CACtB,eA4BA;AAED,8CAA8C;AAC9C,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,SAAS,CAAA;CACnB,CAAA;AAmQD;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAC9B,UAAU,EAAE,OAAO,GAAG,MAAM,CAAA;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,SAAS,CAAA;IAClB,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B,eAwBA;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,+EAA+E;IAC/E,OAAO,EAAE,SAAS,CAAA;IAClB,MAAM,EAAE,SAAS,eAAe,EAAE,CAAA;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAC/B,eAgCA"}
@@ -145,7 +145,7 @@ function ThemeSelectMenu(props) {
145
145
  get portalMount() {
146
146
  return portalMount();
147
147
  },
148
- "class": "max-h-(--kb-popper-content-available-height) w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto",
148
+ "class": "max-h-80 w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto",
149
149
  onInteractOutside: (event) => {
150
150
  if (event.detail.originalEvent.type !== "pointerdown") return;
151
151
  const focusScope = portalMount()?.closest("[role=\"dialog\"]") ?? portalMount()?.ownerDocument.body;
@@ -1 +1 @@
1
- {"version":3,"file":"appearance-rows.js","names":["AdeaTheme","AdeaThemeRecord","For","Show","createMemo","createSignal","onCleanup","JSX","ChevronDown","Palette","SquareTerminal","cn","Button","DropdownMenu","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","DropdownMenuTrigger","PalettePreview","ThemeMenuPreview","POINTER_FOCUS_TARGET_SELECTOR","isTabStop","element","HTMLElement","tabIndex","matches","hasAttribute","getAttribute","closest","getClientRects","length","SettingsRow","props","title","icon","Element","description","stacked","children","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$7","_$insert","_$createComponent","when","_el$6","_tmpl$","_$effect","_p$","_v$","_v$2","e","_$className","t","undefined","ThemeOption","id","name","preview","ThemeSelectMenu","label","selectedId","triggerPreview","options","disabled","onSelect","portalMount","setPortalMount","HTMLDivElement","triggerElement","setTriggerElement","HTMLButtonElement","menuOpen","setMenuOpen","focusOutsideTarget","setFocusOutsideTarget","restoreTriggerFocus","setRestoreTriggerFocus","focusTargetAfterTab","focusLifecycleVersion","selected","find","option","closeMenu","moveFocusOnTab","event","KeyboardEvent","key","isComposing","trigger","parentDialog","focusScope","ownerDocument","body","focusStops","Array","from","querySelectorAll","filter","orderedFocusStops","toSorted","a","b","triggerIndex","indexOf","direction","shiftKey","adjacent","at","stopPropagation","preventDefault","focus","preventScroll","_el$8","_tmpl$4","_$use","modal","open","onOpenChange","ref","as","variant","size","aria-label","_el$9","_tmpl$3","_el$0","theme","onInteractOutside","detail","originalEvent","type","target","contains","focusTarget","onFocusOutside","onEscapeKeyDown","onCloseAutoFocus","lifecycleVersion","shouldRestore","isConnected","queueMicrotask","activeElement","document","isMenuFocus","isTriggerFocus","value","onChange","each","textValue","closeOnSelect","_el$1","_tmpl$6","_el$10","_el$11","_tmpl$5","ThemeRow","appearance","themes","map","TerminalRow","selectedOption","_$createComponent","_$className"],"sources":["../../../../src/components/composites/appearance-editor/appearance-rows.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n// Retains the compact divided row and palette-preview selector from the pinned\n// Zeron/Adea composition; Kobalte owns option navigation and nested dismissal.\n// One shared menu serves the light, dark, and terminal rows: each option is a\n// compact theme preview with its name and one-line description beside it, and\n// the menu sizes to that content instead of clipping it at the trigger width.\nimport type { AdeaTheme, AdeaThemeRecord } from '@adea-ai/themes'\nimport { For, Show, createMemo, createSignal, onCleanup, type JSX } from 'solid-js'\nimport { ChevronDown, Palette, SquareTerminal } from 'lucide-solid'\nimport { cn } from '#lib/utils'\nimport { Button } from '../../ui/button/button'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n} from '../../ui/dropdown-menu/dropdown-menu'\nimport { PalettePreview, ThemeMenuPreview } from './theme-preview'\n\nconst POINTER_FOCUS_TARGET_SELECTOR =\n 'a[href], area[href], button, input, select, textarea, iframe, [tabindex], [contenteditable], details > summary:first-of-type'\n\nfunction isTabStop(element: HTMLElement) {\n return (\n (element.tabIndex >= 0 ||\n (element.matches('details > summary:first-of-type') && !element.hasAttribute('tabindex'))) &&\n !element.matches(':disabled') &&\n element.getAttribute('aria-disabled') !== 'true' &&\n element.closest('[hidden], [inert], [aria-hidden=\"true\"]') === null &&\n element.getClientRects().length > 0\n )\n}\n\nexport function SettingsRow(props: {\n title: string\n icon: JSX.Element\n description?: JSX.Element\n stacked?: boolean\n children: JSX.Element\n}) {\n return (\n <section\n class={cn('flex gap-3 px-4 py-4', {\n 'flex-col': props.stacked,\n 'flex-wrap items-center': !props.stacked,\n })}\n >\n {/* Reserve readable copy before choosing a side-by-side control row.\n Wrapping follows the actual host width and enlarged text, rather\n than a viewport breakpoint that also matches a narrow popover. */}\n <div class={cn('flex min-w-0 flex-1 items-center gap-3', { 'basis-48': !props.stacked })}>\n <span\n class=\"flex size-9 shrink-0 items-center justify-center rounded-lg border bg-foreground/5 text-muted-foreground [&_svg]:size-4\"\n aria-hidden=\"true\"\n >\n {props.icon}\n </span>\n <div class=\"min-w-0\">\n <h3 class=\"text-sm font-medium\">{props.title}</h3>\n <Show when={props.description}>\n <div class=\"mt-0.5 text-xs text-muted-foreground\">{props.description}</div>\n </Show>\n </div>\n </div>\n <div class=\"min-w-0 max-w-full shrink-0\">{props.children}</div>\n </section>\n )\n}\n\n/** One selectable palette in a theme menu. */\nexport type ThemeOption = {\n id: string\n name: string\n description?: string\n preview: AdeaTheme\n}\n\n/**\n * The shared theme picker. Kobalte handles menu navigation and dismissal;\n * this component moves Tab to the adjacent browser-reported stop because\n * menus consume Tab by default. Enumerating elements and checking their native\n * tabIndex keeps details summaries in the order while preserving explicit\n * tabindex overrides. The menu width follows its content (bounded by the\n * popper's available width) so a long theme name and its description render\n * fully instead of truncating at the trigger's width.\n */\nfunction ThemeSelectMenu(props: {\n /** Row title; also the trigger's accessible name and the group's label. */\n label: string\n selectedId: string\n /** Palette shown on the trigger; hosts pass the accent-applied preview. */\n triggerPreview: AdeaTheme\n options: readonly ThemeOption[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const [portalMount, setPortalMount] = createSignal<HTMLDivElement>()\n const [triggerElement, setTriggerElement] = createSignal<HTMLButtonElement>()\n const [menuOpen, setMenuOpen] = createSignal(false)\n const [focusOutsideTarget, setFocusOutsideTarget] = createSignal<HTMLElement>()\n const [restoreTriggerFocus, setRestoreTriggerFocus] = createSignal(false)\n let focusTargetAfterTab: HTMLElement | undefined\n let focusLifecycleVersion = 0\n onCleanup(() => {\n focusLifecycleVersion += 1\n })\n const selected = createMemo(\n () =>\n props.options.find((option) => option.id === props.selectedId) ??\n props.options.find((option) => option.id === props.triggerPreview.id)\n )\n const closeMenu = () => {\n if (menuOpen()) focusLifecycleVersion += 1\n setMenuOpen(false)\n }\n const moveFocusOnTab = (event: KeyboardEvent) => {\n if (event.key !== 'Tab' || event.isComposing) return\n\n const trigger = triggerElement()\n if (!trigger) return\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n if (!focusScope) return\n\n const focusStops = Array.from(focusScope.querySelectorAll<HTMLElement>('*')).filter(\n (element) =>\n isTabStop(element) &&\n element.closest('[role=\"menu\"], [hidden], [inert], [aria-hidden=\"true\"]') === null\n )\n const orderedFocusStops = [\n ...focusStops\n .filter((element) => element.tabIndex > 0)\n .toSorted((a, b) => a.tabIndex - b.tabIndex),\n ...focusStops.filter((element) => element.tabIndex <= 0),\n ]\n const triggerIndex = orderedFocusStops.indexOf(trigger)\n const direction = event.shiftKey ? -1 : 1\n const adjacent =\n orderedFocusStops[triggerIndex + direction] ??\n (parentDialog ? (direction > 0 ? orderedFocusStops[0] : orderedFocusStops.at(-1)) : undefined)\n\n event.stopPropagation()\n setRestoreTriggerFocus(false)\n if (adjacent) {\n event.preventDefault()\n focusTargetAfterTab = adjacent\n setFocusOutsideTarget(adjacent)\n closeMenu()\n adjacent.focus({ preventScroll: true })\n } else {\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n closeMenu()\n }\n }\n return (\n <div ref={setPortalMount}>\n <DropdownMenu\n modal={false}\n open={menuOpen()}\n onOpenChange={(open) => {\n if (open !== menuOpen()) focusLifecycleVersion += 1\n setMenuOpen(open)\n if (open) {\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n setRestoreTriggerFocus(false)\n }\n }}\n >\n <DropdownMenuTrigger\n ref={setTriggerElement}\n as={Button}\n variant=\"outline\"\n size=\"sm\"\n aria-label={props.label}\n disabled={props.disabled || props.options.length === 0}\n class=\"w-full justify-between sm:w-52\"\n >\n <span class=\"flex min-w-0 flex-1 items-center gap-2\">\n <PalettePreview theme={props.triggerPreview} />\n <span class=\"min-w-0 flex-1 truncate\">\n {selected()?.name ?? props.triggerPreview.name}\n </span>\n </span>\n <ChevronDown aria-hidden=\"true\" class=\"shrink-0 text-muted-foreground\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n portalMount={portalMount()}\n // Sized to content (at least the trigger width, never wider than the\n // popper allows) so long theme names render in full with padding for\n // the selection indicator instead of truncating at the anchor width.\n class=\"max-h-(--kb-popper-content-available-height) w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto\"\n onInteractOutside={(event) => {\n if (event.detail.originalEvent.type !== 'pointerdown') return\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n const target = event.detail.originalEvent.target\n if (!(target instanceof Element) || !focusScope?.contains(target)) return\n\n const focusTarget = target.closest<HTMLElement>(POINTER_FOCUS_TARGET_SELECTOR)\n if (focusTarget && isTabStop(focusTarget)) {\n setRestoreTriggerFocus(false)\n setFocusOutsideTarget(focusTarget)\n } else {\n setRestoreTriggerFocus(true)\n }\n }}\n onFocusOutside={(event) => {\n // The containing dialog or document body can briefly reclaim\n // focus when the menu opens. Keep that handoff from dismissing\n // it; focus moving to another descendant still closes the menu.\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n const target = event.detail.originalEvent.target\n if (target === focusScope) {\n event.preventDefault()\n } else if (target instanceof HTMLElement && focusScope?.contains(target)) {\n setRestoreTriggerFocus(false)\n setFocusOutsideTarget(target)\n }\n }}\n onEscapeKeyDown={() => setRestoreTriggerFocus(true)}\n onCloseAutoFocus={(event) => {\n // A prior menu instance can finish its focus cleanup after this\n // row has already reopened. Do not let that cleanup steal focus.\n if (menuOpen()) {\n event.preventDefault()\n return\n }\n\n const lifecycleVersion = focusLifecycleVersion\n const shouldRestore = restoreTriggerFocus()\n const focusTarget = focusTargetAfterTab ?? focusOutsideTarget()\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n setRestoreTriggerFocus(false)\n if (shouldRestore) {\n // The saved focus may be the containing dialog rather than\n // the trigger when WebKit opens this menu from a pointer click.\n event.preventDefault()\n triggerElement()?.focus({ preventScroll: true })\n return\n }\n\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n if (focusTarget?.isConnected && focusScope?.contains(focusTarget)) {\n // Preserve the intended in-scope destination across\n // Kobalte's deferred stale-focus restore.\n event.preventDefault()\n queueMicrotask(() => {\n if (lifecycleVersion !== focusLifecycleVersion || menuOpen()) return\n\n const activeElement = document.activeElement\n const isMenuFocus =\n activeElement instanceof HTMLElement &&\n activeElement.closest('[role=\"menu\"]') !== null\n const isTriggerFocus = activeElement === triggerElement()\n if (\n activeElement !== focusTarget &&\n (activeElement === document.body ||\n activeElement === focusScope ||\n isMenuFocus ||\n isTriggerFocus)\n ) {\n focusTarget.focus({ preventScroll: true })\n }\n })\n return\n }\n\n const activeElement = document.activeElement\n if (\n focusScope &&\n activeElement instanceof HTMLElement &&\n activeElement !== focusScope &&\n focusScope.contains(activeElement) &&\n activeElement.closest('[role=\"menu\"]') === null\n ) {\n // Preserve a real focus target in this scope instead of\n // restoring the stale element captured when the menu mounted. A\n // focused menu item is about to unmount, so Kobalte must restore\n // focus to the trigger instead.\n event.preventDefault()\n }\n }}\n >\n <DropdownMenuRadioGroup\n value={selected()?.id ?? ''}\n aria-label={`${props.label} options`}\n on:keydown={moveFocusOnTab}\n onChange={(id) => {\n if (!props.disabled && typeof id === 'string') props.onSelect(id)\n }}\n >\n <For each={props.options}>\n {(option) => (\n <DropdownMenuRadioItem\n value={option.id}\n textValue={option.name}\n closeOnSelect={true}\n disabled={props.disabled}\n onSelect={() => setRestoreTriggerFocus(true)}\n >\n <ThemeMenuPreview theme={option.preview} />\n <span class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span class=\"truncate\">{option.name}</span>\n {/* Visual affordance only: the accessible name stays the\n theme name, which is what keyboard and test callers\n match on. */}\n <Show when={option.description}>\n <span\n aria-hidden=\"true\"\n class=\"line-clamp-2 max-w-44 text-2xs text-muted-foreground\"\n >\n {option.description}\n </span>\n </Show>\n </span>\n </DropdownMenuRadioItem>\n )}\n </For>\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n )\n}\n\n/**\n * A compact persistent theme choice for one appearance.\n */\nexport function ThemeRow(props: {\n appearance: 'light' | 'dark'\n selectedId: string\n preview: AdeaTheme\n themes: readonly AdeaThemeRecord[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const label = () => (props.appearance === 'light' ? 'Light theme' : 'Dark theme')\n const options = createMemo<ThemeOption[]>(() =>\n props.themes\n .filter((theme) => theme.appearance === props.appearance)\n .map((theme) => ({\n id: theme.id,\n name: theme.name,\n description: theme.description,\n preview: theme,\n }))\n )\n return (\n <SettingsRow title={label()} icon={<Palette />}>\n <ThemeSelectMenu\n label={label()}\n selectedId={props.selectedId}\n triggerPreview={props.preview}\n options={options()}\n disabled={props.disabled}\n onSelect={props.onSelect}\n />\n </SettingsRow>\n )\n}\n\n/**\n * A terminal palette choice independent of the light/dark rows. The first\n * option (`'theme'`) follows the interface theme, painted with the resolved\n * preview; every catalogue record follows, both appearances, because the\n * terminal paints one fixed ANSI palette rather than an appearance axis.\n */\nexport function TerminalRow(props: {\n selectedId: string\n /** Resolved interface theme: the `theme` option's palette and the fallback. */\n preview: AdeaTheme\n themes: readonly AdeaThemeRecord[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const options = createMemo<ThemeOption[]>(() => [\n {\n id: 'theme',\n name: 'UI theme',\n description: 'Uses the interface theme.',\n preview: props.preview,\n },\n ...props.themes.map((theme) => ({\n id: theme.id,\n name: theme.name,\n description: theme.description,\n preview: theme,\n })),\n ])\n const selectedOption = () => options().find((option) => option.id === props.selectedId)\n const description = () =>\n selectedOption() && selectedOption()?.id !== 'theme'\n ? `The terminal follows ${selectedOption()?.name}.`\n : 'The terminal follows the interface theme.'\n return (\n <SettingsRow title=\"Terminal\" icon={<SquareTerminal />} description={description()}>\n <ThemeSelectMenu\n label=\"Terminal\"\n selectedId={props.selectedId}\n triggerPreview={selectedOption()?.preview ?? props.preview}\n options={options()}\n disabled={props.disabled}\n onSelect={props.onSelect}\n />\n </SettingsRow>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"appearance-rows.js","names":["AdeaTheme","AdeaThemeRecord","For","Show","createMemo","createSignal","onCleanup","JSX","ChevronDown","Palette","SquareTerminal","cn","Button","DropdownMenu","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","DropdownMenuTrigger","PalettePreview","ThemeMenuPreview","POINTER_FOCUS_TARGET_SELECTOR","isTabStop","element","HTMLElement","tabIndex","matches","hasAttribute","getAttribute","closest","getClientRects","length","SettingsRow","props","title","icon","Element","description","stacked","children","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","nextSibling","_el$5","_el$7","_$insert","_$createComponent","when","_el$6","_tmpl$","_$effect","_p$","_v$","_v$2","e","_$className","t","undefined","ThemeOption","id","name","preview","ThemeSelectMenu","label","selectedId","triggerPreview","options","disabled","onSelect","portalMount","setPortalMount","HTMLDivElement","triggerElement","setTriggerElement","HTMLButtonElement","menuOpen","setMenuOpen","focusOutsideTarget","setFocusOutsideTarget","restoreTriggerFocus","setRestoreTriggerFocus","focusTargetAfterTab","focusLifecycleVersion","selected","find","option","closeMenu","moveFocusOnTab","event","KeyboardEvent","key","isComposing","trigger","parentDialog","focusScope","ownerDocument","body","focusStops","Array","from","querySelectorAll","filter","orderedFocusStops","toSorted","a","b","triggerIndex","indexOf","direction","shiftKey","adjacent","at","stopPropagation","preventDefault","focus","preventScroll","_el$8","_tmpl$4","_$use","modal","open","onOpenChange","ref","as","variant","size","aria-label","_el$9","_tmpl$3","_el$0","theme","onInteractOutside","detail","originalEvent","type","target","contains","focusTarget","onFocusOutside","onEscapeKeyDown","onCloseAutoFocus","lifecycleVersion","shouldRestore","isConnected","queueMicrotask","activeElement","document","isMenuFocus","isTriggerFocus","value","onChange","each","textValue","closeOnSelect","_el$1","_tmpl$6","_el$10","_el$11","_tmpl$5","ThemeRow","appearance","themes","map","TerminalRow","selectedOption","_$createComponent","_$className"],"sources":["../../../../src/components/composites/appearance-editor/appearance-rows.tsx"],"sourcesContent":["/*\n * MIT License\n *\n * Copyright (c) 2026 Wing\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n// Retains the compact divided row and palette-preview selector from the pinned\n// Zeron/Adea composition; Kobalte owns option navigation and nested dismissal.\n// One shared menu serves the light, dark, and terminal rows: each option is a\n// compact theme preview with its name and one-line description beside it, and\n// the menu sizes to that content instead of clipping it at the trigger width.\nimport type { AdeaTheme, AdeaThemeRecord } from '@adea-ai/themes'\nimport { For, Show, createMemo, createSignal, onCleanup, type JSX } from 'solid-js'\nimport { ChevronDown, Palette, SquareTerminal } from 'lucide-solid'\nimport { cn } from '#lib/utils'\nimport { Button } from '../../ui/button/button'\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n} from '../../ui/dropdown-menu/dropdown-menu'\nimport { PalettePreview, ThemeMenuPreview } from './theme-preview'\n\nconst POINTER_FOCUS_TARGET_SELECTOR =\n 'a[href], area[href], button, input, select, textarea, iframe, [tabindex], [contenteditable], details > summary:first-of-type'\n\nfunction isTabStop(element: HTMLElement) {\n return (\n (element.tabIndex >= 0 ||\n (element.matches('details > summary:first-of-type') && !element.hasAttribute('tabindex'))) &&\n !element.matches(':disabled') &&\n element.getAttribute('aria-disabled') !== 'true' &&\n element.closest('[hidden], [inert], [aria-hidden=\"true\"]') === null &&\n element.getClientRects().length > 0\n )\n}\n\nexport function SettingsRow(props: {\n title: string\n icon: JSX.Element\n description?: JSX.Element\n stacked?: boolean\n children: JSX.Element\n}) {\n return (\n <section\n class={cn('flex gap-3 px-4 py-4', {\n 'flex-col': props.stacked,\n 'flex-wrap items-center': !props.stacked,\n })}\n >\n {/* Reserve readable copy before choosing a side-by-side control row.\n Wrapping follows the actual host width and enlarged text, rather\n than a viewport breakpoint that also matches a narrow popover. */}\n <div class={cn('flex min-w-0 flex-1 items-center gap-3', { 'basis-48': !props.stacked })}>\n <span\n class=\"flex size-9 shrink-0 items-center justify-center rounded-lg border bg-foreground/5 text-muted-foreground [&_svg]:size-4\"\n aria-hidden=\"true\"\n >\n {props.icon}\n </span>\n <div class=\"min-w-0\">\n <h3 class=\"text-sm font-medium\">{props.title}</h3>\n <Show when={props.description}>\n <div class=\"mt-0.5 text-xs text-muted-foreground\">{props.description}</div>\n </Show>\n </div>\n </div>\n <div class=\"min-w-0 max-w-full shrink-0\">{props.children}</div>\n </section>\n )\n}\n\n/** One selectable palette in a theme menu. */\nexport type ThemeOption = {\n id: string\n name: string\n description?: string\n preview: AdeaTheme\n}\n\n/**\n * The shared theme picker. Kobalte handles menu navigation and dismissal;\n * this component moves Tab to the adjacent browser-reported stop because\n * menus consume Tab by default. Enumerating elements and checking their native\n * tabIndex keeps details summaries in the order while preserving explicit\n * tabindex overrides. The menu width follows its content (bounded by the\n * popper's available width) so a long theme name and its description render\n * fully instead of truncating at the trigger's width.\n */\nfunction ThemeSelectMenu(props: {\n /** Row title; also the trigger's accessible name and the group's label. */\n label: string\n selectedId: string\n /** Palette shown on the trigger; hosts pass the accent-applied preview. */\n triggerPreview: AdeaTheme\n options: readonly ThemeOption[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const [portalMount, setPortalMount] = createSignal<HTMLDivElement>()\n const [triggerElement, setTriggerElement] = createSignal<HTMLButtonElement>()\n const [menuOpen, setMenuOpen] = createSignal(false)\n const [focusOutsideTarget, setFocusOutsideTarget] = createSignal<HTMLElement>()\n const [restoreTriggerFocus, setRestoreTriggerFocus] = createSignal(false)\n let focusTargetAfterTab: HTMLElement | undefined\n let focusLifecycleVersion = 0\n onCleanup(() => {\n focusLifecycleVersion += 1\n })\n const selected = createMemo(\n () =>\n props.options.find((option) => option.id === props.selectedId) ??\n props.options.find((option) => option.id === props.triggerPreview.id)\n )\n const closeMenu = () => {\n if (menuOpen()) focusLifecycleVersion += 1\n setMenuOpen(false)\n }\n const moveFocusOnTab = (event: KeyboardEvent) => {\n if (event.key !== 'Tab' || event.isComposing) return\n\n const trigger = triggerElement()\n if (!trigger) return\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n if (!focusScope) return\n\n const focusStops = Array.from(focusScope.querySelectorAll<HTMLElement>('*')).filter(\n (element) =>\n isTabStop(element) &&\n element.closest('[role=\"menu\"], [hidden], [inert], [aria-hidden=\"true\"]') === null\n )\n const orderedFocusStops = [\n ...focusStops\n .filter((element) => element.tabIndex > 0)\n .toSorted((a, b) => a.tabIndex - b.tabIndex),\n ...focusStops.filter((element) => element.tabIndex <= 0),\n ]\n const triggerIndex = orderedFocusStops.indexOf(trigger)\n const direction = event.shiftKey ? -1 : 1\n const adjacent =\n orderedFocusStops[triggerIndex + direction] ??\n (parentDialog ? (direction > 0 ? orderedFocusStops[0] : orderedFocusStops.at(-1)) : undefined)\n\n event.stopPropagation()\n setRestoreTriggerFocus(false)\n if (adjacent) {\n event.preventDefault()\n focusTargetAfterTab = adjacent\n setFocusOutsideTarget(adjacent)\n closeMenu()\n adjacent.focus({ preventScroll: true })\n } else {\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n closeMenu()\n }\n }\n return (\n <div ref={setPortalMount}>\n <DropdownMenu\n modal={false}\n open={menuOpen()}\n onOpenChange={(open) => {\n if (open !== menuOpen()) focusLifecycleVersion += 1\n setMenuOpen(open)\n if (open) {\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n setRestoreTriggerFocus(false)\n }\n }}\n >\n <DropdownMenuTrigger\n ref={setTriggerElement}\n as={Button}\n variant=\"outline\"\n size=\"sm\"\n aria-label={props.label}\n disabled={props.disabled || props.options.length === 0}\n class=\"w-full justify-between sm:w-52\"\n >\n <span class=\"flex min-w-0 flex-1 items-center gap-2\">\n <PalettePreview theme={props.triggerPreview} />\n <span class=\"min-w-0 flex-1 truncate\">\n {selected()?.name ?? props.triggerPreview.name}\n </span>\n </span>\n <ChevronDown aria-hidden=\"true\" class=\"shrink-0 text-muted-foreground\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent\n portalMount={portalMount()}\n // A fixed height with its own scroll: an adaptive cap measured the\n // host panel instead, and opening a long theme list scrolled the\n // sidebar to reveal the menu. The content scrolls internally at the\n // cap, so the panel around the trigger never moves. Width still\n // follows content (at least the trigger width, never wider than the\n // popper allows) so long theme names render in full with padding for\n // the selection indicator instead of truncating at the anchor width.\n class=\"max-h-80 w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto\"\n onInteractOutside={(event) => {\n if (event.detail.originalEvent.type !== 'pointerdown') return\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n const target = event.detail.originalEvent.target\n if (!(target instanceof Element) || !focusScope?.contains(target)) return\n\n const focusTarget = target.closest<HTMLElement>(POINTER_FOCUS_TARGET_SELECTOR)\n if (focusTarget && isTabStop(focusTarget)) {\n setRestoreTriggerFocus(false)\n setFocusOutsideTarget(focusTarget)\n } else {\n setRestoreTriggerFocus(true)\n }\n }}\n onFocusOutside={(event) => {\n // The containing dialog or document body can briefly reclaim\n // focus when the menu opens. Keep that handoff from dismissing\n // it; focus moving to another descendant still closes the menu.\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n const target = event.detail.originalEvent.target\n if (target === focusScope) {\n event.preventDefault()\n } else if (target instanceof HTMLElement && focusScope?.contains(target)) {\n setRestoreTriggerFocus(false)\n setFocusOutsideTarget(target)\n }\n }}\n onEscapeKeyDown={() => setRestoreTriggerFocus(true)}\n onCloseAutoFocus={(event) => {\n // A prior menu instance can finish its focus cleanup after this\n // row has already reopened. Do not let that cleanup steal focus.\n if (menuOpen()) {\n event.preventDefault()\n return\n }\n\n const lifecycleVersion = focusLifecycleVersion\n const shouldRestore = restoreTriggerFocus()\n const focusTarget = focusTargetAfterTab ?? focusOutsideTarget()\n focusTargetAfterTab = undefined\n setFocusOutsideTarget(undefined)\n setRestoreTriggerFocus(false)\n if (shouldRestore) {\n // The saved focus may be the containing dialog rather than\n // the trigger when WebKit opens this menu from a pointer click.\n event.preventDefault()\n triggerElement()?.focus({ preventScroll: true })\n return\n }\n\n const parentDialog = portalMount()?.closest<HTMLElement>('[role=\"dialog\"]')\n const focusScope = parentDialog ?? portalMount()?.ownerDocument.body\n if (focusTarget?.isConnected && focusScope?.contains(focusTarget)) {\n // Preserve the intended in-scope destination across\n // Kobalte's deferred stale-focus restore.\n event.preventDefault()\n queueMicrotask(() => {\n if (lifecycleVersion !== focusLifecycleVersion || menuOpen()) return\n\n const activeElement = document.activeElement\n const isMenuFocus =\n activeElement instanceof HTMLElement &&\n activeElement.closest('[role=\"menu\"]') !== null\n const isTriggerFocus = activeElement === triggerElement()\n if (\n activeElement !== focusTarget &&\n (activeElement === document.body ||\n activeElement === focusScope ||\n isMenuFocus ||\n isTriggerFocus)\n ) {\n focusTarget.focus({ preventScroll: true })\n }\n })\n return\n }\n\n const activeElement = document.activeElement\n if (\n focusScope &&\n activeElement instanceof HTMLElement &&\n activeElement !== focusScope &&\n focusScope.contains(activeElement) &&\n activeElement.closest('[role=\"menu\"]') === null\n ) {\n // Preserve a real focus target in this scope instead of\n // restoring the stale element captured when the menu mounted. A\n // focused menu item is about to unmount, so Kobalte must restore\n // focus to the trigger instead.\n event.preventDefault()\n }\n }}\n >\n <DropdownMenuRadioGroup\n value={selected()?.id ?? ''}\n aria-label={`${props.label} options`}\n on:keydown={moveFocusOnTab}\n onChange={(id) => {\n if (!props.disabled && typeof id === 'string') props.onSelect(id)\n }}\n >\n <For each={props.options}>\n {(option) => (\n <DropdownMenuRadioItem\n value={option.id}\n textValue={option.name}\n closeOnSelect={true}\n disabled={props.disabled}\n onSelect={() => setRestoreTriggerFocus(true)}\n >\n <ThemeMenuPreview theme={option.preview} />\n <span class=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n <span class=\"truncate\">{option.name}</span>\n {/* Visual affordance only: the accessible name stays the\n theme name, which is what keyboard and test callers\n match on. */}\n <Show when={option.description}>\n <span\n aria-hidden=\"true\"\n class=\"line-clamp-2 max-w-44 text-2xs text-muted-foreground\"\n >\n {option.description}\n </span>\n </Show>\n </span>\n </DropdownMenuRadioItem>\n )}\n </For>\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n )\n}\n\n/**\n * A compact persistent theme choice for one appearance.\n */\nexport function ThemeRow(props: {\n appearance: 'light' | 'dark'\n selectedId: string\n preview: AdeaTheme\n themes: readonly AdeaThemeRecord[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const label = () => (props.appearance === 'light' ? 'Light theme' : 'Dark theme')\n const options = createMemo<ThemeOption[]>(() =>\n props.themes\n .filter((theme) => theme.appearance === props.appearance)\n .map((theme) => ({\n id: theme.id,\n name: theme.name,\n description: theme.description,\n preview: theme,\n }))\n )\n return (\n <SettingsRow title={label()} icon={<Palette />}>\n <ThemeSelectMenu\n label={label()}\n selectedId={props.selectedId}\n triggerPreview={props.preview}\n options={options()}\n disabled={props.disabled}\n onSelect={props.onSelect}\n />\n </SettingsRow>\n )\n}\n\n/**\n * A terminal palette choice independent of the light/dark rows. The first\n * option (`'theme'`) follows the interface theme, painted with the resolved\n * preview; every catalogue record follows, both appearances, because the\n * terminal paints one fixed ANSI palette rather than an appearance axis.\n */\nexport function TerminalRow(props: {\n selectedId: string\n /** Resolved interface theme: the `theme` option's palette and the fallback. */\n preview: AdeaTheme\n themes: readonly AdeaThemeRecord[]\n disabled?: boolean\n onSelect: (id: string) => void\n}) {\n const options = createMemo<ThemeOption[]>(() => [\n {\n id: 'theme',\n name: 'UI theme',\n description: 'Uses the interface theme.',\n preview: props.preview,\n },\n ...props.themes.map((theme) => ({\n id: theme.id,\n name: theme.name,\n description: theme.description,\n preview: theme,\n })),\n ])\n const selectedOption = () => options().find((option) => option.id === props.selectedId)\n const description = () =>\n selectedOption() && selectedOption()?.id !== 'theme'\n ? `The terminal follows ${selectedOption()?.name}.`\n : 'The terminal follows the interface theme.'\n return (\n <SettingsRow title=\"Terminal\" icon={<SquareTerminal />} description={description()}>\n <ThemeSelectMenu\n label=\"Terminal\"\n selectedId={props.selectedId}\n triggerPreview={selectedOption()?.preview ?? props.preview}\n options={options()}\n disabled={props.disabled}\n onSelect={props.onSelect}\n />\n </SettingsRow>\n )\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAc9C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,kCAG7E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,kCAE5F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,MAAM,CAAC,kCAE1F;AAED,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,GAAG;IAC1F,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,kCAoBlE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG;IACvD,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,kCAiCF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,kCAUjE;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,YAAY,CAAC,kCAY/D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7D;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAWhG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,kCAExF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAGhG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,GAAG,CAAC,kCAEpF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAU7D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAkB7D"}
1
+ {"version":3,"file":"dropdown-menu.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,6BAA6B,CAAA;AAEjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAc9C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,kCAG7E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,kCAE5F;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,MAAM,CAAC,kCAE1F;AAED,MAAM,MAAM,wBAAwB,GAAG,cAAc,CAAC,OAAO,mBAAmB,CAAC,OAAO,CAAC,GAAG;IAC1F,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAA;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,kCAoBlE;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG;IACvD,qEAAqE;IACrE,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,kCAiCF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,CAAC,MAAM,CAAC,kCAUjE;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,YAAY,CAAC,kCAe/D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7D;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAgBhG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAG7F;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,kCAExF;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,SAAS,CAAC,kCAGhG;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,GAAG,CAAC,kCAEpF;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAU7D;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,cAAc,CAAC,OAAO,mBAAmB,CAAC,UAAU,CAAC,kCAkB7D"}
@@ -111,7 +111,8 @@ function DropdownMenuCheckboxItem(props) {
111
111
  return cn(menuItem, "pe-8", local.class);
112
112
  } }, rest, { get children() {
113
113
  return [memo(() => local.children), createComponent(DropdownMenu.ItemIndicator, {
114
- "class": "absolute end-2 flex size-4 items-center justify-center",
114
+ "data-slot": "dropdown-menu-indicator",
115
+ "class": "absolute end-2 flex size-4 items-center justify-center text-primary",
115
116
  get children() {
116
117
  return createComponent(Check, { "class": "size-4" });
117
118
  }
@@ -127,7 +128,8 @@ function DropdownMenuRadioItem(props) {
127
128
  return cn(menuItem, "pe-8", local.class);
128
129
  } }, rest, { get children() {
129
130
  return [memo(() => local.children), createComponent(DropdownMenu.ItemIndicator, {
130
- "class": "absolute end-2 flex size-4 items-center justify-center",
131
+ "data-slot": "dropdown-menu-indicator",
132
+ "class": "absolute end-2 flex size-4 items-center justify-center text-primary",
131
133
  get children() {
132
134
  return createComponent(Circle, { "class": "size-2 fill-current" });
133
135
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown-menu.js","names":["DropdownMenu","KobalteDropdownMenu","Check","ChevronRight","Circle","ComponentProps","splitProps","menuContentPadding","destructiveMenuItem","menuItem","menuLabel","menuSeparator","overlayMotion","overlaySurface","popoverArrow","cn","props","local","rest","_$createComponent","_$mergeProps","modal","DropdownMenuTrigger","Trigger","DropdownMenuPortal","Portal","DropdownMenuContentProps","Content","hideArrow","portalMount","HTMLElement","DropdownMenuContent","mount","children","class","_$memo","Arrow","DropdownMenuItem","Item","variant","shortcut","keyshortcuts","aria-keyshortcuts","_el$","_tmpl$","_$insert","DropdownMenuShortcut","_el$2","_tmpl$2","_$spread","DropdownMenuCheckboxItem","CheckboxItem","ItemIndicator","DropdownMenuRadioGroup","RadioGroup","DropdownMenuRadioItem","RadioItem","DropdownMenuLabel","GroupLabel","DropdownMenuGroup","Group","DropdownMenuSeparator","Separator","DropdownMenuSub","Sub","DropdownMenuSubTrigger","SubTrigger","DropdownMenuSubContent","SubContent","DropdownMenu","_$createComponent","KobalteDropdownMenu","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["import { DropdownMenu as KobalteDropdownMenu } from '@kobalte/core/dropdown-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport {\n menuContentPadding,\n destructiveMenuItem,\n menuItem,\n menuLabel,\n menuSeparator,\n overlayMotion,\n overlaySurface,\n popoverArrow,\n} from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n/**\n * DropdownMenu.\n *\n * A list of actions on a trigger, with radio groups for persistent choices\n * that fit naturally in a compact menu. Use Select for form inputs whose\n * selected value needs the field-style control, and Popover for arbitrary\n * content.\n *\n * Kobalte supplies the full menu contract — arrow keys, typeahead, the roving\n * highlight, Escape to close and return focus — which is exactly what a\n * hand-rolled `div` with click handlers gets wrong.\n * Menus are nonmodal by default so their generated focus guards do not become\n * invalid direct children of the ARIA menu. Set `modal` explicitly when the\n * surrounding interaction needs modal containment.\n *\n * The `destructive` variant marks the row with a status-coloured edge and\n * highlighted tint while keeping its label on the body foreground. Pairing it\n * with an AlertDialog is the caller's job.\n */\nexport function DropdownMenu(props: ComponentProps<typeof KobalteDropdownMenu>) {\n const [local, rest] = splitProps(props, ['modal'])\n return <KobalteDropdownMenu modal={local.modal ?? false} {...rest} />\n}\n\nexport function DropdownMenuTrigger(props: ComponentProps<typeof KobalteDropdownMenu.Trigger>) {\n return <KobalteDropdownMenu.Trigger {...props} />\n}\n\nexport function DropdownMenuPortal(props: ComponentProps<typeof KobalteDropdownMenu.Portal>) {\n return <KobalteDropdownMenu.Portal {...props} />\n}\n\nexport type DropdownMenuContentProps = ComponentProps<typeof KobalteDropdownMenu.Content> & {\n hideArrow?: boolean\n /** Mount under an owner element such as a modal, keeping the menu in its accessible subtree. */\n portalMount?: HTMLElement\n}\n\nexport function DropdownMenuContent(props: DropdownMenuContentProps) {\n const [local, rest] = splitProps(props, ['class', 'hideArrow', 'children', 'portalMount'])\n\n return (\n <KobalteDropdownMenu.Portal mount={local.portalMount}>\n <KobalteDropdownMenu.Content\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[10rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n >\n {!local.hideArrow && <KobalteDropdownMenu.Arrow aria-hidden=\"true\" class={popoverArrow} />}\n {local.children}\n </KobalteDropdownMenu.Content>\n </KobalteDropdownMenu.Portal>\n )\n}\n\nexport function DropdownMenuItem(\n props: ComponentProps<typeof KobalteDropdownMenu.Item> & {\n /** Colour the row as a destructive action. Confirm it separately. */\n variant?: 'default' | 'destructive'\n /** Draw a shortcut hint at the trailing edge of the row. */\n shortcut?: string\n /**\n * The parseable chord behind `shortcut`, e.g. `Meta+E`. The drawn glyph is\n * `aria-hidden` — reading it out would pollute the item's accessible name —\n * so this is what assistive technology announces instead. Supply it\n * whenever `shortcut` is drawn.\n */\n keyshortcuts?: string\n }\n) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'variant',\n 'shortcut',\n 'keyshortcuts',\n 'children',\n ])\n\n return (\n <KobalteDropdownMenu.Item\n class={cn(\n menuItem,\n {\n [destructiveMenuItem]: local.variant === 'destructive',\n },\n local.class\n )}\n aria-keyshortcuts={local.keyshortcuts}\n {...rest}\n >\n {local.children}\n {local.shortcut ? (\n <span\n aria-hidden=\"true\"\n class=\"text-muted-foreground ms-auto font-mono text-2xs tracking-widest\"\n >\n {local.shortcut}\n </span>\n ) : null}\n </KobalteDropdownMenu.Item>\n )\n}\n\n/**\n * The chord drawn at a row's trailing edge.\n *\n * A component as well as the `shortcut` prop on an item, because a caller composing\n * a row by hand needs the same treatment — and because the alternative is every\n * caller inventing the same mono-and-dimmed span.\n *\n * The glyphs are decorative: the span is `aria-hidden` and the parseable chord\n * belongs in the row's `aria-keyshortcuts`, so the item's accessible name stays\n * exactly its label.\n */\nexport function DropdownMenuShortcut(props: ComponentProps<'span'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n aria-hidden=\"true\"\n class={cn('text-muted-foreground ms-auto font-mono text-2xs tracking-widest', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DropdownMenuCheckboxItem(\n props: ComponentProps<typeof KobalteDropdownMenu.CheckboxItem>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteDropdownMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Check class=\"size-4\" />\n </KobalteDropdownMenu.ItemIndicator>\n </KobalteDropdownMenu.CheckboxItem>\n )\n}\n\nexport function DropdownMenuRadioGroup(\n props: ComponentProps<typeof KobalteDropdownMenu.RadioGroup>\n) {\n return <KobalteDropdownMenu.RadioGroup {...props} />\n}\n\nexport function DropdownMenuRadioItem(props: ComponentProps<typeof KobalteDropdownMenu.RadioItem>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteDropdownMenu.ItemIndicator class=\"absolute end-2 flex size-4 items-center justify-center\">\n <Circle class=\"size-2 fill-current\" />\n </KobalteDropdownMenu.ItemIndicator>\n </KobalteDropdownMenu.RadioItem>\n )\n}\n\nexport function DropdownMenuLabel(props: ComponentProps<typeof KobalteDropdownMenu.GroupLabel>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDropdownMenu.GroupLabel class={cn(menuLabel, local.class)} {...rest} />\n}\n\nexport function DropdownMenuGroup(props: ComponentProps<typeof KobalteDropdownMenu.Group>) {\n return <KobalteDropdownMenu.Group {...props} />\n}\n\nexport function DropdownMenuSeparator(props: ComponentProps<typeof KobalteDropdownMenu.Separator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDropdownMenu.Separator class={cn(menuSeparator, local.class)} {...rest} />\n}\n\nexport function DropdownMenuSub(props: ComponentProps<typeof KobalteDropdownMenu.Sub>) {\n return <KobalteDropdownMenu.Sub {...props} />\n}\n\nexport function DropdownMenuSubTrigger(\n props: ComponentProps<typeof KobalteDropdownMenu.SubTrigger>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.SubTrigger class={cn(menuItem, local.class)} {...rest}>\n {local.children}\n <ChevronRight class=\"ms-auto size-4\" />\n </KobalteDropdownMenu.SubTrigger>\n )\n}\n\nexport function DropdownMenuSubContent(\n props: ComponentProps<typeof KobalteDropdownMenu.SubContent>\n) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteDropdownMenu.Portal>\n <KobalteDropdownMenu.SubContent\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[8rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n />\n </KobalteDropdownMenu.Portal>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dropdown-menu.js","names":["DropdownMenu","KobalteDropdownMenu","Check","ChevronRight","Circle","ComponentProps","splitProps","menuContentPadding","destructiveMenuItem","menuItem","menuLabel","menuSeparator","overlayMotion","overlaySurface","popoverArrow","cn","props","local","rest","_$createComponent","_$mergeProps","modal","DropdownMenuTrigger","Trigger","DropdownMenuPortal","Portal","DropdownMenuContentProps","Content","hideArrow","portalMount","HTMLElement","DropdownMenuContent","mount","children","class","_$memo","Arrow","DropdownMenuItem","Item","variant","shortcut","keyshortcuts","aria-keyshortcuts","_el$","_tmpl$","_$insert","DropdownMenuShortcut","_el$2","_tmpl$2","_$spread","DropdownMenuCheckboxItem","CheckboxItem","ItemIndicator","DropdownMenuRadioGroup","RadioGroup","DropdownMenuRadioItem","RadioItem","DropdownMenuLabel","GroupLabel","DropdownMenuGroup","Group","DropdownMenuSeparator","Separator","DropdownMenuSub","Sub","DropdownMenuSubTrigger","SubTrigger","DropdownMenuSubContent","SubContent","DropdownMenu","_$createComponent","KobalteDropdownMenu","_$mergeProps","_$memo"],"sources":["../../../../src/components/ui/dropdown-menu/dropdown-menu.tsx"],"sourcesContent":["import { DropdownMenu as KobalteDropdownMenu } from '@kobalte/core/dropdown-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-solid'\nimport type { ComponentProps } from 'solid-js'\nimport { splitProps } from 'solid-js'\nimport {\n menuContentPadding,\n destructiveMenuItem,\n menuItem,\n menuLabel,\n menuSeparator,\n overlayMotion,\n overlaySurface,\n popoverArrow,\n} from '#lib/overlay'\nimport { cn } from '#lib/utils'\n\n/**\n * DropdownMenu.\n *\n * A list of actions on a trigger, with radio groups for persistent choices\n * that fit naturally in a compact menu. Use Select for form inputs whose\n * selected value needs the field-style control, and Popover for arbitrary\n * content.\n *\n * Kobalte supplies the full menu contract — arrow keys, typeahead, the roving\n * highlight, Escape to close and return focus — which is exactly what a\n * hand-rolled `div` with click handlers gets wrong.\n * Menus are nonmodal by default so their generated focus guards do not become\n * invalid direct children of the ARIA menu. Set `modal` explicitly when the\n * surrounding interaction needs modal containment.\n *\n * The `destructive` variant marks the row with a status-coloured edge and\n * highlighted tint while keeping its label on the body foreground. Pairing it\n * with an AlertDialog is the caller's job.\n */\nexport function DropdownMenu(props: ComponentProps<typeof KobalteDropdownMenu>) {\n const [local, rest] = splitProps(props, ['modal'])\n return <KobalteDropdownMenu modal={local.modal ?? false} {...rest} />\n}\n\nexport function DropdownMenuTrigger(props: ComponentProps<typeof KobalteDropdownMenu.Trigger>) {\n return <KobalteDropdownMenu.Trigger {...props} />\n}\n\nexport function DropdownMenuPortal(props: ComponentProps<typeof KobalteDropdownMenu.Portal>) {\n return <KobalteDropdownMenu.Portal {...props} />\n}\n\nexport type DropdownMenuContentProps = ComponentProps<typeof KobalteDropdownMenu.Content> & {\n hideArrow?: boolean\n /** Mount under an owner element such as a modal, keeping the menu in its accessible subtree. */\n portalMount?: HTMLElement\n}\n\nexport function DropdownMenuContent(props: DropdownMenuContentProps) {\n const [local, rest] = splitProps(props, ['class', 'hideArrow', 'children', 'portalMount'])\n\n return (\n <KobalteDropdownMenu.Portal mount={local.portalMount}>\n <KobalteDropdownMenu.Content\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[10rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n >\n {!local.hideArrow && <KobalteDropdownMenu.Arrow aria-hidden=\"true\" class={popoverArrow} />}\n {local.children}\n </KobalteDropdownMenu.Content>\n </KobalteDropdownMenu.Portal>\n )\n}\n\nexport function DropdownMenuItem(\n props: ComponentProps<typeof KobalteDropdownMenu.Item> & {\n /** Colour the row as a destructive action. Confirm it separately. */\n variant?: 'default' | 'destructive'\n /** Draw a shortcut hint at the trailing edge of the row. */\n shortcut?: string\n /**\n * The parseable chord behind `shortcut`, e.g. `Meta+E`. The drawn glyph is\n * `aria-hidden` — reading it out would pollute the item's accessible name —\n * so this is what assistive technology announces instead. Supply it\n * whenever `shortcut` is drawn.\n */\n keyshortcuts?: string\n }\n) {\n const [local, rest] = splitProps(props, [\n 'class',\n 'variant',\n 'shortcut',\n 'keyshortcuts',\n 'children',\n ])\n\n return (\n <KobalteDropdownMenu.Item\n class={cn(\n menuItem,\n {\n [destructiveMenuItem]: local.variant === 'destructive',\n },\n local.class\n )}\n aria-keyshortcuts={local.keyshortcuts}\n {...rest}\n >\n {local.children}\n {local.shortcut ? (\n <span\n aria-hidden=\"true\"\n class=\"text-muted-foreground ms-auto font-mono text-2xs tracking-widest\"\n >\n {local.shortcut}\n </span>\n ) : null}\n </KobalteDropdownMenu.Item>\n )\n}\n\n/**\n * The chord drawn at a row's trailing edge.\n *\n * A component as well as the `shortcut` prop on an item, because a caller composing\n * a row by hand needs the same treatment — and because the alternative is every\n * caller inventing the same mono-and-dimmed span.\n *\n * The glyphs are decorative: the span is `aria-hidden` and the parseable chord\n * belongs in the row's `aria-keyshortcuts`, so the item's accessible name stays\n * exactly its label.\n */\nexport function DropdownMenuShortcut(props: ComponentProps<'span'>) {\n const [local, rest] = splitProps(props, ['class'])\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n aria-hidden=\"true\"\n class={cn('text-muted-foreground ms-auto font-mono text-2xs tracking-widest', local.class)}\n {...rest}\n />\n )\n}\n\nexport function DropdownMenuCheckboxItem(\n props: ComponentProps<typeof KobalteDropdownMenu.CheckboxItem>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n <KobalteDropdownMenu.ItemIndicator\n data-slot=\"dropdown-menu-indicator\"\n class=\"absolute end-2 flex size-4 items-center justify-center text-primary\"\n >\n <Check class=\"size-4\" />\n </KobalteDropdownMenu.ItemIndicator>\n </KobalteDropdownMenu.CheckboxItem>\n )\n}\n\nexport function DropdownMenuRadioGroup(\n props: ComponentProps<typeof KobalteDropdownMenu.RadioGroup>\n) {\n return <KobalteDropdownMenu.RadioGroup {...props} />\n}\n\nexport function DropdownMenuRadioItem(props: ComponentProps<typeof KobalteDropdownMenu.RadioItem>) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>\n {local.children}\n {/* The indicator reads in the accent, like every other selected state in\n the system — a canvas-colored dot on a checked row reads as decoration. */}\n <KobalteDropdownMenu.ItemIndicator\n data-slot=\"dropdown-menu-indicator\"\n class=\"absolute end-2 flex size-4 items-center justify-center text-primary\"\n >\n <Circle class=\"size-2 fill-current\" />\n </KobalteDropdownMenu.ItemIndicator>\n </KobalteDropdownMenu.RadioItem>\n )\n}\n\nexport function DropdownMenuLabel(props: ComponentProps<typeof KobalteDropdownMenu.GroupLabel>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDropdownMenu.GroupLabel class={cn(menuLabel, local.class)} {...rest} />\n}\n\nexport function DropdownMenuGroup(props: ComponentProps<typeof KobalteDropdownMenu.Group>) {\n return <KobalteDropdownMenu.Group {...props} />\n}\n\nexport function DropdownMenuSeparator(props: ComponentProps<typeof KobalteDropdownMenu.Separator>) {\n const [local, rest] = splitProps(props, ['class'])\n return <KobalteDropdownMenu.Separator class={cn(menuSeparator, local.class)} {...rest} />\n}\n\nexport function DropdownMenuSub(props: ComponentProps<typeof KobalteDropdownMenu.Sub>) {\n return <KobalteDropdownMenu.Sub {...props} />\n}\n\nexport function DropdownMenuSubTrigger(\n props: ComponentProps<typeof KobalteDropdownMenu.SubTrigger>\n) {\n const [local, rest] = splitProps(props, ['class', 'children'])\n\n return (\n <KobalteDropdownMenu.SubTrigger class={cn(menuItem, local.class)} {...rest}>\n {local.children}\n <ChevronRight class=\"ms-auto size-4\" />\n </KobalteDropdownMenu.SubTrigger>\n )\n}\n\nexport function DropdownMenuSubContent(\n props: ComponentProps<typeof KobalteDropdownMenu.SubContent>\n) {\n const [local, rest] = splitProps(props, ['class'])\n\n return (\n <KobalteDropdownMenu.Portal>\n <KobalteDropdownMenu.SubContent\n class={cn(\n overlaySurface,\n overlayMotion,\n 'z-(--z-menu) min-w-[8rem] origin-(--kb-menu-content-transform-origin) overflow-hidden',\n menuContentPadding,\n local.class\n )}\n {...rest}\n />\n </KobalteDropdownMenu.Portal>\n )\n}\n"],"mappings":"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"}
@@ -83,6 +83,11 @@ export function ModeChoices(props: AppearanceEditorProps) {
83
83
  }
84
84
 
85
85
  export function AccentChoices(props: AppearanceEditorProps) {
86
+ // The resolved appearance decides which side of a preset pair — and which
87
+ // theme accent — the swatches paint, so the row previews each choice as the
88
+ // user will see it.
89
+ const resolvedAppearance = () =>
90
+ props.draft.mode === 'system' ? props.resolvedAppearance : props.draft.mode
86
91
  const custom = () =>
87
92
  props.draft.accent !== 'theme' &&
88
93
  !props.accentOptions.some((option) => option.id === props.draft.accent)
@@ -93,9 +98,9 @@ export function AccentChoices(props: AppearanceEditorProps) {
93
98
  disabled={props.saving}
94
99
  orientation="horizontal"
95
100
  aria-label="Accent"
96
- // Two chips in a column beside a 3x2 swatch grid: one line of six
97
- // swatches plus chips overflows the settings sidebar's control column,
98
- // and the column keeps both rows of the pair balanced (2 x 28px + gap).
101
+ // One chip (custom) beside a capped swatch grid: a chip-per-state column
102
+ // beside a full-width swatch line overflowed the settings sidebar's
103
+ // control column, so the pair stays a narrow chip plus a wrapped grid.
99
104
  class="flex items-center gap-3"
100
105
  onChange={(accent) =>
101
106
  props.onChange({
@@ -103,21 +108,29 @@ export function AccentChoices(props: AppearanceEditorProps) {
103
108
  })
104
109
  }
105
110
  >
106
- <div class="flex flex-col gap-2">
107
- <Radio.Item value="theme">
111
+ <div class="grid grid-cols-4 gap-2">
112
+ {/* The theme's own accent is the first swatch. Picking it is the same
113
+ act the old dedicated "Theme default" chip performed, without a
114
+ second control for the state the row starts in. */}
115
+ <Radio.Item
116
+ value="theme"
117
+ class="rounded-full focus-within:ring-3 focus-within:ring-ring/50"
118
+ >
108
119
  <Radio.ItemInput />
109
- <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
110
- Theme default
120
+ <Radio.ItemLabel class="block size-7 cursor-pointer rounded-full border p-0.5 data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
121
+ <span
122
+ class="block size-full rounded-full"
123
+ aria-hidden="true"
124
+ style={{
125
+ 'background-color':
126
+ resolvedAppearance() === 'light'
127
+ ? props.lightTheme.colors.accent
128
+ : props.darkTheme.colors.accent,
129
+ }}
130
+ />
131
+ <span class="sr-only">Theme default</span>
111
132
  </Radio.ItemLabel>
112
133
  </Radio.Item>
113
- <Radio.Item value="custom">
114
- <Radio.ItemInput />
115
- <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
116
- Custom
117
- </Radio.ItemLabel>
118
- </Radio.Item>
119
- </div>
120
- <div class="grid grid-cols-3 gap-2">
121
134
  <For each={props.accentOptions}>
122
135
  {(option) => (
123
136
  <Radio.Item
@@ -131,11 +144,7 @@ export function AccentChoices(props: AppearanceEditorProps) {
131
144
  aria-hidden="true"
132
145
  style={{
133
146
  'background-color':
134
- (props.draft.mode === 'system'
135
- ? props.resolvedAppearance
136
- : props.draft.mode) === 'light'
137
- ? option.light
138
- : option.dark,
147
+ resolvedAppearance() === 'light' ? option.light : option.dark,
139
148
  }}
140
149
  />
141
150
  <span class="sr-only">{option.label}</span>
@@ -144,6 +153,12 @@ export function AccentChoices(props: AppearanceEditorProps) {
144
153
  )}
145
154
  </For>
146
155
  </div>
156
+ <Radio.Item value="custom">
157
+ <Radio.ItemInput />
158
+ <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
159
+ Custom
160
+ </Radio.ItemLabel>
161
+ </Radio.Item>
147
162
  </Radio>
148
163
  )
149
164
  }
@@ -210,10 +210,14 @@ function ThemeSelectMenu(props: {
210
210
  </DropdownMenuTrigger>
211
211
  <DropdownMenuContent
212
212
  portalMount={portalMount()}
213
- // Sized to content (at least the trigger width, never wider than the
213
+ // A fixed height with its own scroll: an adaptive cap measured the
214
+ // host panel instead, and opening a long theme list scrolled the
215
+ // sidebar to reveal the menu. The content scrolls internally at the
216
+ // cap, so the panel around the trigger never moves. Width still
217
+ // follows content (at least the trigger width, never wider than the
214
218
  // popper allows) so long theme names render in full with padding for
215
219
  // the selection indicator instead of truncating at the anchor width.
216
- class="max-h-(--kb-popper-content-available-height) w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto"
220
+ class="max-h-80 w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto"
217
221
  onInteractOutside={(event) => {
218
222
  if (event.detail.originalEvent.type !== 'pointerdown') return
219
223
  const parentDialog = portalMount()?.closest<HTMLElement>('[role="dialog"]')
@@ -153,7 +153,10 @@ export function DropdownMenuCheckboxItem(
153
153
  return (
154
154
  <KobalteDropdownMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>
155
155
  {local.children}
156
- <KobalteDropdownMenu.ItemIndicator class="absolute end-2 flex size-4 items-center justify-center">
156
+ <KobalteDropdownMenu.ItemIndicator
157
+ data-slot="dropdown-menu-indicator"
158
+ class="absolute end-2 flex size-4 items-center justify-center text-primary"
159
+ >
157
160
  <Check class="size-4" />
158
161
  </KobalteDropdownMenu.ItemIndicator>
159
162
  </KobalteDropdownMenu.CheckboxItem>
@@ -172,7 +175,12 @@ export function DropdownMenuRadioItem(props: ComponentProps<typeof KobalteDropdo
172
175
  return (
173
176
  <KobalteDropdownMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>
174
177
  {local.children}
175
- <KobalteDropdownMenu.ItemIndicator class="absolute end-2 flex size-4 items-center justify-center">
178
+ {/* The indicator reads in the accent, like every other selected state in
179
+ the system — a canvas-colored dot on a checked row reads as decoration. */}
180
+ <KobalteDropdownMenu.ItemIndicator
181
+ data-slot="dropdown-menu-indicator"
182
+ class="absolute end-2 flex size-4 items-center justify-center text-primary"
183
+ >
176
184
  <Circle class="size-2 fill-current" />
177
185
  </KobalteDropdownMenu.ItemIndicator>
178
186
  </KobalteDropdownMenu.RadioItem>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/ui",
3
- "version": "0.99.0",
3
+ "version": "0.99.1",
4
4
  "description": "The Adea design system: Kobalte-backed Solid components, semantic OKLCH tokens, and the app-shell layout primitives shared by Adea and Cortana.",
5
5
  "keywords": [
6
6
  "adea",
@@ -83,6 +83,11 @@ export function ModeChoices(props: AppearanceEditorProps) {
83
83
  }
84
84
 
85
85
  export function AccentChoices(props: AppearanceEditorProps) {
86
+ // The resolved appearance decides which side of a preset pair — and which
87
+ // theme accent — the swatches paint, so the row previews each choice as the
88
+ // user will see it.
89
+ const resolvedAppearance = () =>
90
+ props.draft.mode === 'system' ? props.resolvedAppearance : props.draft.mode
86
91
  const custom = () =>
87
92
  props.draft.accent !== 'theme' &&
88
93
  !props.accentOptions.some((option) => option.id === props.draft.accent)
@@ -93,9 +98,9 @@ export function AccentChoices(props: AppearanceEditorProps) {
93
98
  disabled={props.saving}
94
99
  orientation="horizontal"
95
100
  aria-label="Accent"
96
- // Two chips in a column beside a 3x2 swatch grid: one line of six
97
- // swatches plus chips overflows the settings sidebar's control column,
98
- // and the column keeps both rows of the pair balanced (2 x 28px + gap).
101
+ // One chip (custom) beside a capped swatch grid: a chip-per-state column
102
+ // beside a full-width swatch line overflowed the settings sidebar's
103
+ // control column, so the pair stays a narrow chip plus a wrapped grid.
99
104
  class="flex items-center gap-3"
100
105
  onChange={(accent) =>
101
106
  props.onChange({
@@ -103,21 +108,29 @@ export function AccentChoices(props: AppearanceEditorProps) {
103
108
  })
104
109
  }
105
110
  >
106
- <div class="flex flex-col gap-2">
107
- <Radio.Item value="theme">
111
+ <div class="grid grid-cols-4 gap-2">
112
+ {/* The theme's own accent is the first swatch. Picking it is the same
113
+ act the old dedicated "Theme default" chip performed, without a
114
+ second control for the state the row starts in. */}
115
+ <Radio.Item
116
+ value="theme"
117
+ class="rounded-full focus-within:ring-3 focus-within:ring-ring/50"
118
+ >
108
119
  <Radio.ItemInput />
109
- <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
110
- Theme default
120
+ <Radio.ItemLabel class="block size-7 cursor-pointer rounded-full border p-0.5 data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
121
+ <span
122
+ class="block size-full rounded-full"
123
+ aria-hidden="true"
124
+ style={{
125
+ 'background-color':
126
+ resolvedAppearance() === 'light'
127
+ ? props.lightTheme.colors.accent
128
+ : props.darkTheme.colors.accent,
129
+ }}
130
+ />
131
+ <span class="sr-only">Theme default</span>
111
132
  </Radio.ItemLabel>
112
133
  </Radio.Item>
113
- <Radio.Item value="custom">
114
- <Radio.ItemInput />
115
- <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
116
- Custom
117
- </Radio.ItemLabel>
118
- </Radio.Item>
119
- </div>
120
- <div class="grid grid-cols-3 gap-2">
121
134
  <For each={props.accentOptions}>
122
135
  {(option) => (
123
136
  <Radio.Item
@@ -131,11 +144,7 @@ export function AccentChoices(props: AppearanceEditorProps) {
131
144
  aria-hidden="true"
132
145
  style={{
133
146
  'background-color':
134
- (props.draft.mode === 'system'
135
- ? props.resolvedAppearance
136
- : props.draft.mode) === 'light'
137
- ? option.light
138
- : option.dark,
147
+ resolvedAppearance() === 'light' ? option.light : option.dark,
139
148
  }}
140
149
  />
141
150
  <span class="sr-only">{option.label}</span>
@@ -144,6 +153,12 @@ export function AccentChoices(props: AppearanceEditorProps) {
144
153
  )}
145
154
  </For>
146
155
  </div>
156
+ <Radio.Item value="custom">
157
+ <Radio.ItemInput />
158
+ <Radio.ItemLabel class="flex h-7 cursor-pointer items-center rounded-md border px-2 text-xs whitespace-nowrap data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
159
+ Custom
160
+ </Radio.ItemLabel>
161
+ </Radio.Item>
147
162
  </Radio>
148
163
  )
149
164
  }
@@ -210,10 +210,14 @@ function ThemeSelectMenu(props: {
210
210
  </DropdownMenuTrigger>
211
211
  <DropdownMenuContent
212
212
  portalMount={portalMount()}
213
- // Sized to content (at least the trigger width, never wider than the
213
+ // A fixed height with its own scroll: an adaptive cap measured the
214
+ // host panel instead, and opening a long theme list scrolled the
215
+ // sidebar to reveal the menu. The content scrolls internally at the
216
+ // cap, so the panel around the trigger never moves. Width still
217
+ // follows content (at least the trigger width, never wider than the
214
218
  // popper allows) so long theme names render in full with padding for
215
219
  // the selection indicator instead of truncating at the anchor width.
216
- class="max-h-(--kb-popper-content-available-height) w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto"
220
+ class="max-h-80 w-max min-w-(--kb-popper-anchor-width) max-w-(--kb-popper-content-available-width) overflow-x-hidden overflow-y-auto"
217
221
  onInteractOutside={(event) => {
218
222
  if (event.detail.originalEvent.type !== 'pointerdown') return
219
223
  const parentDialog = portalMount()?.closest<HTMLElement>('[role="dialog"]')
@@ -153,7 +153,10 @@ export function DropdownMenuCheckboxItem(
153
153
  return (
154
154
  <KobalteDropdownMenu.CheckboxItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>
155
155
  {local.children}
156
- <KobalteDropdownMenu.ItemIndicator class="absolute end-2 flex size-4 items-center justify-center">
156
+ <KobalteDropdownMenu.ItemIndicator
157
+ data-slot="dropdown-menu-indicator"
158
+ class="absolute end-2 flex size-4 items-center justify-center text-primary"
159
+ >
157
160
  <Check class="size-4" />
158
161
  </KobalteDropdownMenu.ItemIndicator>
159
162
  </KobalteDropdownMenu.CheckboxItem>
@@ -172,7 +175,12 @@ export function DropdownMenuRadioItem(props: ComponentProps<typeof KobalteDropdo
172
175
  return (
173
176
  <KobalteDropdownMenu.RadioItem class={cn(menuItem, 'pe-8', local.class)} {...rest}>
174
177
  {local.children}
175
- <KobalteDropdownMenu.ItemIndicator class="absolute end-2 flex size-4 items-center justify-center">
178
+ {/* The indicator reads in the accent, like every other selected state in
179
+ the system — a canvas-colored dot on a checked row reads as decoration. */}
180
+ <KobalteDropdownMenu.ItemIndicator
181
+ data-slot="dropdown-menu-indicator"
182
+ class="absolute end-2 flex size-4 items-center justify-center text-primary"
183
+ >
176
184
  <Circle class="size-2 fill-current" />
177
185
  </KobalteDropdownMenu.ItemIndicator>
178
186
  </KobalteDropdownMenu.RadioItem>