@adea-ai/ui 0.104.3 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -8
- package/dist/components/composites/action-button/action-button.d.ts.map +1 -1
- package/dist/components/composites/action-button/action-button.js +6 -8
- package/dist/components/composites/action-button/action-button.js.map +1 -1
- package/dist/components/composites/appearance-editor/accent-swatch-groups.d.ts +16 -0
- package/dist/components/composites/appearance-editor/accent-swatch-groups.d.ts.map +1 -0
- package/dist/components/composites/appearance-editor/accent-swatch-groups.js +151 -0
- package/dist/components/composites/appearance-editor/accent-swatch-groups.js.map +1 -0
- package/dist/components/composites/appearance-editor/appearance-choices.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-choices.js +24 -84
- package/dist/components/composites/appearance-editor/appearance-choices.js.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-editor.d.ts +2 -2
- package/dist/components/composites/appearance-editor/appearance-editor.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-editor.js +25 -7
- package/dist/components/composites/appearance-editor/appearance-editor.js.map +1 -1
- package/dist/components/composites/appearance-editor/appearance-types.d.ts +9 -0
- package/dist/components/composites/appearance-editor/appearance-types.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/font-settings-group.d.ts +10 -0
- package/dist/components/composites/appearance-editor/font-settings-group.d.ts.map +1 -0
- package/dist/components/composites/appearance-editor/font-settings-group.js +310 -0
- package/dist/components/composites/appearance-editor/font-settings-group.js.map +1 -0
- package/dist/components/composites/appearance-editor/index.d.ts +2 -0
- package/dist/components/composites/appearance-editor/index.d.ts.map +1 -1
- package/dist/components/composites/appearance-editor/index.js +3 -1
- package/dist/components/composites/update-dialog/update-dialog.js +2 -2
- package/dist/components/composites/update-dialog/update-dialog.js.map +1 -1
- package/dist/components/conversation/message-row.d.ts.map +1 -1
- package/dist/components/conversation/message-row.js +3 -3
- package/dist/components/conversation/message-row.js.map +1 -1
- package/dist/components/conversation/paste-token-editor.js +1 -1
- package/dist/components/conversation/paste-token-editor.js.map +1 -1
- package/dist/components/layout/side-rail/side-rail.js +2 -2
- package/dist/components/layout/side-rail/side-rail.js.map +1 -1
- package/dist/components/layout/top-bar/top-bar.js +1 -1
- package/dist/components/layout/top-bar/top-bar.js.map +1 -1
- package/dist/components/theme/appearance-panel.d.ts +1 -1
- package/dist/components/theme/appearance-panel.d.ts.map +1 -1
- package/dist/components/theme/appearance-panel.js +45 -105
- package/dist/components/theme/appearance-panel.js.map +1 -1
- package/dist/components/theme/theme-provider.d.ts +5 -2
- package/dist/components/theme/theme-provider.d.ts.map +1 -1
- package/dist/components/theme/theme-provider.js +38 -19
- package/dist/components/theme/theme-provider.js.map +1 -1
- package/dist/components/ui/code-block/code-block.d.ts +3 -3
- package/dist/components/ui/code-block/code-block.js +6 -6
- package/dist/components/ui/code-block/code-block.js.map +1 -1
- package/dist/components/ui/command/command.js +1 -1
- package/dist/components/ui/command/command.js.map +1 -1
- package/dist/components/ui/context-menu/context-menu.js +1 -1
- package/dist/components/ui/context-menu/context-menu.js.map +1 -1
- package/dist/components/ui/diff-block/diff-block.js +5 -5
- package/dist/components/ui/diff-block/diff-block.js.map +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.js +101 -8
- package/dist/components/ui/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/ui/kbd/index.d.ts +1 -1
- package/dist/components/ui/kbd/index.d.ts.map +1 -1
- package/dist/components/ui/kbd/index.js +2 -2
- package/dist/components/ui/kbd/kbd.d.ts +40 -2
- package/dist/components/ui/kbd/kbd.d.ts.map +1 -1
- package/dist/components/ui/kbd/kbd.js +74 -7
- package/dist/components/ui/kbd/kbd.js.map +1 -1
- package/dist/components/ui/menubar/menubar.js +1 -1
- package/dist/components/ui/menubar/menubar.js.map +1 -1
- package/dist/components/ui/typography/typography.d.ts +3 -5
- package/dist/components/ui/typography/typography.d.ts.map +1 -1
- package/dist/components/ui/typography/typography.js +6 -8
- package/dist/components/ui/typography/typography.js.map +1 -1
- package/dist/index.js +7 -4
- package/dist/lib/appearance-font-settings.d.ts +53 -0
- package/dist/lib/appearance-font-settings.d.ts.map +1 -0
- package/dist/lib/appearance-font-settings.js +160 -0
- package/dist/lib/appearance-font-settings.js.map +1 -0
- package/dist/lib/font-catalog.d.ts +72 -0
- package/dist/lib/font-catalog.d.ts.map +1 -0
- package/dist/lib/font-catalog.js +71 -0
- package/dist/lib/font-catalog.js.map +1 -0
- package/dist/lib/safe-script.d.ts +3 -0
- package/dist/lib/safe-script.d.ts.map +1 -0
- package/dist/lib/safe-script.js +9 -0
- package/dist/lib/safe-script.js.map +1 -0
- package/dist/lib/tokens.d.ts +2 -19
- package/dist/lib/tokens.d.ts.map +1 -1
- package/dist/lib/tokens.js +63 -39
- package/dist/lib/tokens.js.map +1 -1
- package/dist/r/about-dialog.json +1 -1
- package/dist/r/accordion.json +1 -1
- package/dist/r/account-menu.json +1 -1
- package/dist/r/alert.json +1 -1
- package/dist/r/appearance-editor.json +13 -2
- package/dist/r/breadcrumb.json +1 -1
- package/dist/r/calendar.json +1 -1
- package/dist/r/carousel.json +1 -1
- package/dist/r/catalog-browser.json +1 -1
- package/dist/r/checkbox.json +1 -1
- package/dist/r/code-block.json +1 -1
- package/dist/r/combobox.json +1 -1
- package/dist/r/command.json +1 -1
- package/dist/r/context-menu.json +1 -1
- package/dist/r/conversation.json +1 -1
- package/dist/r/detail-panel.json +1 -1
- package/dist/r/dialog.json +1 -1
- package/dist/r/dropdown-menu.json +1 -1
- package/dist/r/empty.json +1 -1
- package/dist/r/floating-preview.json +1 -1
- package/dist/r/help-center.json +1 -1
- package/dist/r/lib.json +16 -1
- package/dist/r/menubar.json +1 -1
- package/dist/r/native-select.json +1 -1
- package/dist/r/navigation-menu.json +1 -1
- package/dist/r/pagination.json +1 -1
- package/dist/r/radio-group.json +1 -1
- package/dist/r/registry.json +75 -42
- package/dist/r/resizable.json +1 -1
- package/dist/r/scene-controls.json +1 -1
- package/dist/r/select.json +1 -1
- package/dist/r/sheet.json +1 -1
- package/dist/r/sidebar-nav.json +1 -1
- package/dist/r/spinner.json +1 -1
- package/dist/r/split-layout.json +1 -1
- package/dist/r/src/components/composites/action-button/action-button.tsx +2 -1
- package/dist/r/src/components/composites/appearance-editor/accent-swatch-groups.tsx +147 -0
- package/dist/r/src/components/composites/appearance-editor/appearance-choices.tsx +17 -74
- package/dist/r/src/components/composites/appearance-editor/appearance-editor.tsx +19 -6
- package/dist/r/src/components/composites/appearance-editor/appearance-types.ts +9 -0
- package/dist/r/src/components/composites/appearance-editor/font-settings-group.tsx +350 -0
- package/dist/r/src/components/composites/appearance-editor/index.ts +19 -0
- package/dist/r/src/components/composites/update-dialog/update-dialog.tsx +2 -2
- package/dist/r/src/components/conversation/message-row.tsx +7 -3
- package/dist/r/src/components/conversation/paste-token-editor.tsx +1 -1
- package/dist/r/src/components/layout/side-rail/side-rail.tsx +3 -3
- package/dist/r/src/components/layout/top-bar/top-bar.tsx +1 -1
- package/dist/r/src/components/theme/appearance-panel.tsx +34 -83
- package/dist/r/src/components/theme/theme-provider.tsx +50 -20
- package/dist/r/src/components/ui/code-block/code-block.tsx +6 -6
- package/dist/r/src/components/ui/command/command.tsx +1 -1
- package/dist/r/src/components/ui/context-menu/context-menu.tsx +1 -1
- package/dist/r/src/components/ui/diff-block/diff-block.tsx +7 -7
- package/dist/r/src/components/ui/dropdown-menu/dropdown-menu.tsx +145 -7
- package/dist/r/src/components/ui/kbd/index.ts +10 -1
- package/dist/r/src/components/ui/kbd/kbd.tsx +77 -14
- package/dist/r/src/components/ui/menubar/menubar.tsx +1 -1
- package/dist/r/src/components/ui/typography/typography.tsx +6 -8
- package/dist/r/src/lib/appearance-font-settings.ts +233 -0
- package/dist/r/src/lib/font-catalog.ts +80 -0
- package/dist/r/src/lib/safe-script.ts +7 -0
- package/dist/r/src/lib/tokens.ts +64 -59
- package/dist/r/src/styles/appearance-font-settings.css +110 -0
- package/dist/r/src/styles/fonts.css +4 -5
- package/dist/r/src/styles/globals.css +4 -1
- package/dist/r/src/styles/theme.css +14 -0
- package/dist/r/stat.json +1 -1
- package/dist/r/theme.json +5 -0
- package/dist/r/theming.json +4 -2
- package/dist/r/toast.json +1 -1
- package/dist/r/top-bar.json +1 -1
- package/dist/r/tree.json +1 -1
- package/dist/r/update-dialog.json +1 -1
- package/package.json +7 -6
- package/registry.json +75 -42
- package/src/components/composites/action-button/action-button.tsx +2 -1
- package/src/components/composites/appearance-editor/accent-swatch-groups.tsx +147 -0
- package/src/components/composites/appearance-editor/appearance-choices.tsx +17 -74
- package/src/components/composites/appearance-editor/appearance-editor.tsx +19 -6
- package/src/components/composites/appearance-editor/appearance-types.ts +9 -0
- package/src/components/composites/appearance-editor/font-settings-group.tsx +350 -0
- package/src/components/composites/appearance-editor/index.ts +19 -0
- package/src/components/composites/update-dialog/update-dialog.tsx +2 -2
- package/src/components/conversation/message-row.tsx +7 -3
- package/src/components/conversation/paste-token-editor.tsx +1 -1
- package/src/components/layout/side-rail/side-rail.tsx +3 -3
- package/src/components/layout/top-bar/top-bar.tsx +1 -1
- package/src/components/theme/appearance-panel.tsx +34 -83
- package/src/components/theme/theme-provider.tsx +50 -20
- package/src/components/ui/code-block/code-block.tsx +6 -6
- package/src/components/ui/command/command.tsx +1 -1
- package/src/components/ui/context-menu/context-menu.tsx +1 -1
- package/src/components/ui/diff-block/diff-block.tsx +7 -7
- package/src/components/ui/dropdown-menu/dropdown-menu.tsx +145 -7
- package/src/components/ui/kbd/index.ts +10 -1
- package/src/components/ui/kbd/kbd.tsx +77 -14
- package/src/components/ui/menubar/menubar.tsx +1 -1
- package/src/components/ui/typography/typography.tsx +6 -8
- package/src/lib/appearance-font-settings.ts +233 -0
- package/src/lib/font-catalog.ts +80 -0
- package/src/lib/safe-script.ts +7 -0
- package/src/lib/tokens.ts +64 -59
- package/src/styles/appearance-font-settings.css +110 -0
- package/src/styles/fonts.css +4 -5
- package/src/styles/globals.css +4 -1
- package/src/styles/theme.css +14 -0
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
import { RadioGroup as Radio } from '@kobalte/core/radio-group'
|
|
27
27
|
import { For, Show } from 'solid-js'
|
|
28
28
|
import { isThemeAccentId } from '#lib/theme-accents'
|
|
29
|
+
import { AccentSwatchGroups } from './accent-swatch-groups'
|
|
29
30
|
import type { AppearanceEditorProps } from './appearance-types'
|
|
30
31
|
import { ThemeMiniature, ThemeMiniatureSplit } from './theme-preview'
|
|
31
32
|
|
|
@@ -39,7 +40,6 @@ const SURFACES = [
|
|
|
39
40
|
{ value: 'frosted', label: 'Frosted' },
|
|
40
41
|
{ value: 'opaque', label: 'Opaque' },
|
|
41
42
|
] as const
|
|
42
|
-
|
|
43
43
|
export function ModeChoices(props: AppearanceEditorProps) {
|
|
44
44
|
return (
|
|
45
45
|
<Radio
|
|
@@ -113,89 +113,32 @@ export function AccentChoices(props: AppearanceEditorProps) {
|
|
|
113
113
|
disabled={props.saving}
|
|
114
114
|
orientation="horizontal"
|
|
115
115
|
aria-label="Accent"
|
|
116
|
-
|
|
117
|
-
// beside a full-width swatch line overflowed the settings sidebar's
|
|
118
|
-
// control column, so the pair stays a narrow chip plus a wrapped grid.
|
|
119
|
-
class="flex items-center gap-3"
|
|
116
|
+
class="flex flex-col items-start gap-3"
|
|
120
117
|
onChange={(accent) =>
|
|
121
118
|
props.onChange({
|
|
122
119
|
accent: accent === 'custom' ? (props.customAccentValue ?? '') : accent,
|
|
123
120
|
})
|
|
124
121
|
}
|
|
125
122
|
>
|
|
126
|
-
<
|
|
127
|
-
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
123
|
+
<AccentSwatchGroups
|
|
124
|
+
accentOptions={props.accentOptions}
|
|
125
|
+
themeAccentOptions={themeAccents()}
|
|
126
|
+
resolvedAppearance={resolvedAppearance()}
|
|
127
|
+
themeDefaultColor={
|
|
128
|
+
resolvedAppearance() === 'light'
|
|
129
|
+
? props.lightTheme.colors.accent
|
|
130
|
+
: props.darkTheme.colors.accent
|
|
131
|
+
}
|
|
132
|
+
/>
|
|
133
|
+
<div class="flex flex-col gap-1">
|
|
134
|
+
<span class="text-xs font-medium text-muted-foreground">Custom</span>
|
|
135
|
+
<Radio.Item value="custom">
|
|
134
136
|
<Radio.ItemInput />
|
|
135
|
-
<Radio.ItemLabel class="
|
|
136
|
-
|
|
137
|
-
class="block size-full rounded-full"
|
|
138
|
-
aria-hidden="true"
|
|
139
|
-
style={{
|
|
140
|
-
'background-color':
|
|
141
|
-
resolvedAppearance() === 'light'
|
|
142
|
-
? props.lightTheme.colors.accent
|
|
143
|
-
: props.darkTheme.colors.accent,
|
|
144
|
-
}}
|
|
145
|
-
/>
|
|
146
|
-
<span class="sr-only">Theme default</span>
|
|
137
|
+
<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">
|
|
138
|
+
Custom
|
|
147
139
|
</Radio.ItemLabel>
|
|
148
140
|
</Radio.Item>
|
|
149
|
-
<For each={props.accentOptions}>
|
|
150
|
-
{(option) => (
|
|
151
|
-
<Radio.Item
|
|
152
|
-
value={option.id}
|
|
153
|
-
class="rounded-full focus-within:ring-3 focus-within:ring-ring/50"
|
|
154
|
-
>
|
|
155
|
-
<Radio.ItemInput />
|
|
156
|
-
<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">
|
|
157
|
-
<span
|
|
158
|
-
class="block size-full rounded-full"
|
|
159
|
-
aria-hidden="true"
|
|
160
|
-
style={{
|
|
161
|
-
'background-color':
|
|
162
|
-
resolvedAppearance() === 'light' ? option.light : option.dark,
|
|
163
|
-
}}
|
|
164
|
-
/>
|
|
165
|
-
<span class="sr-only">{option.label}</span>
|
|
166
|
-
</Radio.ItemLabel>
|
|
167
|
-
</Radio.Item>
|
|
168
|
-
)}
|
|
169
|
-
</For>
|
|
170
|
-
<For each={themeAccents()}>
|
|
171
|
-
{(option) => (
|
|
172
|
-
<Radio.Item
|
|
173
|
-
value={option.id}
|
|
174
|
-
data-theme-accent={option.id}
|
|
175
|
-
class="rounded-full focus-within:ring-3 focus-within:ring-ring/50"
|
|
176
|
-
>
|
|
177
|
-
<Radio.ItemInput />
|
|
178
|
-
<Radio.ItemLabel class="block size-7 cursor-pointer rounded-full border border-dashed p-0.5 data-[checked]:border-solid data-[checked]:border-primary data-[checked]:ring-1 data-[checked]:ring-primary">
|
|
179
|
-
<span
|
|
180
|
-
class="block size-full rounded-full"
|
|
181
|
-
aria-hidden="true"
|
|
182
|
-
style={{
|
|
183
|
-
'background-color':
|
|
184
|
-
resolvedAppearance() === 'light' ? option.light : option.dark,
|
|
185
|
-
}}
|
|
186
|
-
/>
|
|
187
|
-
<span class="sr-only">{`Theme ${option.label.toLowerCase()}`}</span>
|
|
188
|
-
</Radio.ItemLabel>
|
|
189
|
-
</Radio.Item>
|
|
190
|
-
)}
|
|
191
|
-
</For>
|
|
192
141
|
</div>
|
|
193
|
-
<Radio.Item value="custom">
|
|
194
|
-
<Radio.ItemInput />
|
|
195
|
-
<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">
|
|
196
|
-
Custom
|
|
197
|
-
</Radio.ItemLabel>
|
|
198
|
-
</Radio.Item>
|
|
199
142
|
</Radio>
|
|
200
143
|
)
|
|
201
144
|
}
|
|
@@ -32,10 +32,12 @@
|
|
|
32
32
|
* custom accent/reduced-transparency are accepted Adea divergences (#425).
|
|
33
33
|
*/
|
|
34
34
|
import { EyeOff, Palette, PanelsTopLeft, SlidersHorizontal } from 'lucide-solid'
|
|
35
|
-
import { Show, createUniqueId } from 'solid-js'
|
|
35
|
+
import { Show, createSignal, createUniqueId } from 'solid-js'
|
|
36
36
|
import { cn } from '#lib/utils'
|
|
37
37
|
import { Button } from '../../ui/button/button'
|
|
38
38
|
import { Input } from '../../ui/input/input'
|
|
39
|
+
import { AppearanceFontSettingsGroup } from './font-settings-group'
|
|
40
|
+
import { DEFAULT_APPEARANCE_EDITOR_FONT_SETTINGS } from '#lib/appearance-font-settings'
|
|
39
41
|
|
|
40
42
|
import { Switch } from '../../ui/switch/switch'
|
|
41
43
|
import {
|
|
@@ -54,8 +56,8 @@ import { SettingsRow, TerminalRow, ThemeRow } from './appearance-rows'
|
|
|
54
56
|
* No ThemeProvider is required, and no catalogue, renderer engine or storage is
|
|
55
57
|
* imported. Hosts normalize unknown IDs and custom colors, report recovery,
|
|
56
58
|
* snapshot on open, preview on changes, commit on Save, and restore on dismissal.
|
|
57
|
-
* Both theme rows remain mounted when mode changes.
|
|
58
|
-
*
|
|
59
|
+
* Both theme rows remain mounted when mode changes. Density remains outside the
|
|
60
|
+
* accepted appearance surface; typeface settings are shared and host-persisted.
|
|
59
61
|
*/
|
|
60
62
|
export function AppearanceEditor(props: AppearanceEditorProps) {
|
|
61
63
|
const errorId = createUniqueId()
|
|
@@ -140,6 +142,12 @@ export function AppearanceEditor(props: AppearanceEditorProps) {
|
|
|
140
142
|
</Show>
|
|
141
143
|
</div>
|
|
142
144
|
</Show>
|
|
145
|
+
<AppearanceFontSettingsGroup
|
|
146
|
+
settings={props.draft.fonts ?? DEFAULT_APPEARANCE_EDITOR_FONT_SETTINGS}
|
|
147
|
+
menuPortalMount={props.menuPortalMount}
|
|
148
|
+
disabled={props.saving}
|
|
149
|
+
onChange={(fonts) => props.onChange({ fonts })}
|
|
150
|
+
/>
|
|
143
151
|
<SettingsRow title="Glass" icon={<PanelsTopLeft />} description={glassDescription()}>
|
|
144
152
|
<GlassChoices {...props} />
|
|
145
153
|
</SettingsRow>
|
|
@@ -188,7 +196,7 @@ export function AppearanceEditor(props: AppearanceEditorProps) {
|
|
|
188
196
|
{/* Sticky so Save/Cancel stay reachable in a tall scroll container: the
|
|
189
197
|
editor scrolls with its host panel, and actions parked at the bottom
|
|
190
198
|
of a long form were unreachable without scrolling past every row. */}
|
|
191
|
-
<div class="sticky bottom-0 z-10 mt-2 flex flex-wrap items-center gap-2 border-t bg-background px-4 py-3">
|
|
199
|
+
<div class="global-appearance-editor-actions sticky bottom-0 z-10 mt-2 flex flex-wrap items-center gap-2 border-t bg-background px-4 py-3">
|
|
192
200
|
<Button
|
|
193
201
|
type="button"
|
|
194
202
|
size="sm"
|
|
@@ -228,6 +236,8 @@ export function AppearanceEditor(props: AppearanceEditorProps) {
|
|
|
228
236
|
* Its measured available height also bounds scrolling, keeping footer actions
|
|
229
237
|
* reachable when a narrow popup begins below its trigger. */
|
|
230
238
|
export function AppearancePopover(props: AppearancePopoverProps) {
|
|
239
|
+
const [menuPortalMount, setMenuPortalMount] = createSignal<HTMLElement>()
|
|
240
|
+
|
|
231
241
|
return (
|
|
232
242
|
<Popover
|
|
233
243
|
open={props.open}
|
|
@@ -243,12 +253,15 @@ export function AppearancePopover(props: AppearancePopoverProps) {
|
|
|
243
253
|
>
|
|
244
254
|
<Palette />
|
|
245
255
|
</PopoverTrigger>
|
|
246
|
-
<PopoverContent
|
|
256
|
+
<PopoverContent
|
|
257
|
+
ref={setMenuPortalMount}
|
|
258
|
+
class="w-lg max-w-[calc(100vw-2rem)] max-h-(--kb-popper-content-available-height) overflow-y-auto"
|
|
259
|
+
>
|
|
247
260
|
<PopoverTitle>Appearance</PopoverTitle>
|
|
248
261
|
<PopoverDescription>
|
|
249
262
|
Changes preview immediately. Save keeps them; Cancel restores the previous appearance.
|
|
250
263
|
</PopoverDescription>
|
|
251
|
-
<AppearanceEditor {...props} />
|
|
264
|
+
<AppearanceEditor {...props} menuPortalMount={menuPortalMount()} />
|
|
252
265
|
</PopoverContent>
|
|
253
266
|
</Popover>
|
|
254
267
|
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AccentPreset, AdeaTheme, AdeaThemeRecord } from '@adea-ai/themes'
|
|
2
|
+
import type { AppearanceEditorFontSettings } from '#lib/appearance-font-settings'
|
|
2
3
|
|
|
3
4
|
export type AppearanceDraft = Readonly<{
|
|
4
5
|
mode: 'system' | 'light' | 'dark'
|
|
@@ -13,6 +14,12 @@ export type AppearanceDraft = Readonly<{
|
|
|
13
14
|
terminalThemeId?: string
|
|
14
15
|
/** Theme default, a canonical preset id, or the host's custom accent draft. */
|
|
15
16
|
accent: string
|
|
17
|
+
/**
|
|
18
|
+
* The UI, content and code typeface axes. Optional for compatibility with
|
|
19
|
+
* hosts upgrading from the earlier appearance contract; omitted means the
|
|
20
|
+
* shared System defaults.
|
|
21
|
+
*/
|
|
22
|
+
fonts?: AppearanceEditorFontSettings
|
|
16
23
|
surface: 'theme' | 'frosted' | 'opaque'
|
|
17
24
|
reduceTransparency: boolean
|
|
18
25
|
}>
|
|
@@ -45,6 +52,8 @@ export type AppearanceEditorProps = {
|
|
|
45
52
|
surfaceCapability: { frosted: boolean; reason?: string; themeDefaultDescription?: string }
|
|
46
53
|
/** Undefined means theme import is unavailable, never a working-looking action. */
|
|
47
54
|
onManageThemes?: () => void
|
|
55
|
+
/** Mount nested font menus inside the containing overlay when one exists. */
|
|
56
|
+
menuPortalMount?: HTMLElement
|
|
48
57
|
class?: string
|
|
49
58
|
}
|
|
50
59
|
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { BookOpen, ChevronDown, Code2, PanelsTopLeft } from 'lucide-solid'
|
|
2
|
+
import { For, createMemo, createSignal, createUniqueId } from 'solid-js'
|
|
3
|
+
import { fontOptions } from '#lib/font-catalog'
|
|
4
|
+
import { Button } from '../../ui/button/button'
|
|
5
|
+
import {
|
|
6
|
+
DropdownMenu,
|
|
7
|
+
DropdownMenuContent,
|
|
8
|
+
DropdownMenuRadioGroup,
|
|
9
|
+
DropdownMenuRadioItem,
|
|
10
|
+
DropdownMenuSeparator,
|
|
11
|
+
DropdownMenuTrigger,
|
|
12
|
+
} from '../../ui/dropdown-menu/dropdown-menu'
|
|
13
|
+
import { InputControl } from '../../ui/input/input-control'
|
|
14
|
+
import { SettingsRow } from './appearance-rows'
|
|
15
|
+
import {
|
|
16
|
+
APPEARANCE_EDITOR_FONT_SIZE_MAX,
|
|
17
|
+
APPEARANCE_EDITOR_FONT_SIZE_MIN,
|
|
18
|
+
normalizeAppearanceEditorFontSettings,
|
|
19
|
+
normalizeAppearanceEditorFontSize,
|
|
20
|
+
type AppearanceEditorFontAxis,
|
|
21
|
+
type AppearanceEditorFontFamilyId,
|
|
22
|
+
type AppearanceEditorFontSettings,
|
|
23
|
+
} from '#lib/appearance-font-settings'
|
|
24
|
+
|
|
25
|
+
export type AppearanceFontSettingsGroupProps = {
|
|
26
|
+
settings: AppearanceEditorFontSettings
|
|
27
|
+
menuPortalMount?: HTMLElement
|
|
28
|
+
onChange: (settings: AppearanceEditorFontSettings) => void
|
|
29
|
+
disabled?: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const FONT_ROWS = [
|
|
33
|
+
{
|
|
34
|
+
axis: 'ui',
|
|
35
|
+
label: 'UI',
|
|
36
|
+
description: 'Controls and interface labels.',
|
|
37
|
+
icon: PanelsTopLeft,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
axis: 'content',
|
|
41
|
+
label: 'Content',
|
|
42
|
+
description: 'Reading and long-form text.',
|
|
43
|
+
icon: BookOpen,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
axis: 'code',
|
|
47
|
+
label: 'Code',
|
|
48
|
+
description: 'Code, terminals, and file paths.',
|
|
49
|
+
icon: Code2,
|
|
50
|
+
},
|
|
51
|
+
] as const satisfies readonly {
|
|
52
|
+
axis: AppearanceEditorFontAxis
|
|
53
|
+
label: string
|
|
54
|
+
description: string
|
|
55
|
+
icon: typeof PanelsTopLeft
|
|
56
|
+
}[]
|
|
57
|
+
|
|
58
|
+
const catalogFontOptions = fontOptions.filter((option) => option.id !== 'system')
|
|
59
|
+
const MENU_FOCUS_TARGET_SELECTOR =
|
|
60
|
+
'a[href], area[href], button, input, select, textarea, iframe, [tabindex], [contenteditable], details > summary:first-of-type'
|
|
61
|
+
|
|
62
|
+
function isMenuTabStop(element: HTMLElement) {
|
|
63
|
+
return (
|
|
64
|
+
(element.tabIndex >= 0 ||
|
|
65
|
+
(element.matches('details > summary:first-of-type') && !element.hasAttribute('tabindex'))) &&
|
|
66
|
+
!element.matches(':disabled') &&
|
|
67
|
+
element.getAttribute('aria-disabled') !== 'true' &&
|
|
68
|
+
element.closest('[hidden], [inert], [aria-hidden="true"]') === null &&
|
|
69
|
+
element.getClientRects().length > 0
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function FontFamilyMenu(props: {
|
|
74
|
+
label: string
|
|
75
|
+
family: AppearanceEditorFontFamilyId
|
|
76
|
+
menuPortalMount?: HTMLElement
|
|
77
|
+
disabled?: boolean
|
|
78
|
+
onSelect: (family: AppearanceEditorFontFamilyId) => void
|
|
79
|
+
}) {
|
|
80
|
+
const [menuOpen, setMenuOpen] = createSignal(false)
|
|
81
|
+
const [restoreTriggerFocus, setRestoreTriggerFocus] = createSignal(false)
|
|
82
|
+
const [triggerElement, setTriggerElement] = createSignal<HTMLButtonElement>()
|
|
83
|
+
let focusTargetAfterTab: HTMLElement | undefined
|
|
84
|
+
|
|
85
|
+
const moveFocusOnTab = (event: KeyboardEvent) => {
|
|
86
|
+
if (event.key !== 'Tab' || event.isComposing) return
|
|
87
|
+
|
|
88
|
+
const trigger = triggerElement()
|
|
89
|
+
const owner = props.menuPortalMount
|
|
90
|
+
const parentDialog = owner?.closest<HTMLElement>('[role="dialog"]')
|
|
91
|
+
const focusScope = parentDialog ?? owner?.ownerDocument.body
|
|
92
|
+
if (!trigger || !parentDialog || !focusScope) return
|
|
93
|
+
|
|
94
|
+
const focusStops = Array.from(focusScope.querySelectorAll<HTMLElement>('*')).filter(
|
|
95
|
+
(element) =>
|
|
96
|
+
isMenuTabStop(element) &&
|
|
97
|
+
element.closest('[role="menu"], [hidden], [inert], [aria-hidden="true"]') === null
|
|
98
|
+
)
|
|
99
|
+
const orderedFocusStops = [
|
|
100
|
+
...focusStops
|
|
101
|
+
.filter((element) => element.tabIndex > 0)
|
|
102
|
+
.toSorted((a, b) => a.tabIndex - b.tabIndex),
|
|
103
|
+
...focusStops.filter((element) => element.tabIndex <= 0),
|
|
104
|
+
]
|
|
105
|
+
const triggerIndex = orderedFocusStops.indexOf(trigger)
|
|
106
|
+
if (triggerIndex < 0) return
|
|
107
|
+
const direction = event.shiftKey ? -1 : 1
|
|
108
|
+
const adjacent =
|
|
109
|
+
orderedFocusStops[triggerIndex + direction] ??
|
|
110
|
+
(direction > 0 ? orderedFocusStops[0] : orderedFocusStops.at(-1))
|
|
111
|
+
|
|
112
|
+
event.stopPropagation()
|
|
113
|
+
setRestoreTriggerFocus(false)
|
|
114
|
+
if (adjacent) {
|
|
115
|
+
event.preventDefault()
|
|
116
|
+
focusTargetAfterTab = adjacent
|
|
117
|
+
setMenuOpen(false)
|
|
118
|
+
adjacent.focus({ preventScroll: true })
|
|
119
|
+
} else {
|
|
120
|
+
focusTargetAfterTab = undefined
|
|
121
|
+
setMenuOpen(false)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const selectedLabel = () =>
|
|
125
|
+
fontOptions.find((option) => option.id === props.family)?.label ??
|
|
126
|
+
fontOptions.find((option) => option.id === 'system')?.label ??
|
|
127
|
+
'System'
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<DropdownMenu
|
|
131
|
+
modal={false}
|
|
132
|
+
open={menuOpen()}
|
|
133
|
+
onOpenChange={(open) => {
|
|
134
|
+
setMenuOpen(open)
|
|
135
|
+
if (open) setRestoreTriggerFocus(false)
|
|
136
|
+
}}
|
|
137
|
+
>
|
|
138
|
+
<DropdownMenuTrigger
|
|
139
|
+
ref={setTriggerElement}
|
|
140
|
+
as={Button}
|
|
141
|
+
variant="outline"
|
|
142
|
+
size="sm"
|
|
143
|
+
aria-label={`${props.label} font family`}
|
|
144
|
+
disabled={props.disabled}
|
|
145
|
+
class="w-40 max-w-full justify-between"
|
|
146
|
+
>
|
|
147
|
+
<span class="truncate">{selectedLabel()}</span>
|
|
148
|
+
<ChevronDown aria-hidden="true" class="ms-2 size-4 shrink-0 text-muted-foreground" />
|
|
149
|
+
</DropdownMenuTrigger>
|
|
150
|
+
<DropdownMenuContent
|
|
151
|
+
hideArrow
|
|
152
|
+
portalMount={props.menuPortalMount}
|
|
153
|
+
class="min-w-48"
|
|
154
|
+
onFocusOutside={(event) => {
|
|
155
|
+
// WebKit may briefly focus the owning Popover root while the menu's
|
|
156
|
+
// focus scope starts. Keep the menu open for that transient target;
|
|
157
|
+
// genuine focus moves to another control still dismiss it.
|
|
158
|
+
if (
|
|
159
|
+
!event.defaultPrevented &&
|
|
160
|
+
props.menuPortalMount &&
|
|
161
|
+
event.detail.originalEvent.target === props.menuPortalMount
|
|
162
|
+
) {
|
|
163
|
+
setRestoreTriggerFocus(true)
|
|
164
|
+
event.preventDefault()
|
|
165
|
+
} else if (
|
|
166
|
+
event.detail.originalEvent.target instanceof HTMLElement &&
|
|
167
|
+
props.menuPortalMount?.contains(event.detail.originalEvent.target)
|
|
168
|
+
) {
|
|
169
|
+
setRestoreTriggerFocus(false)
|
|
170
|
+
}
|
|
171
|
+
}}
|
|
172
|
+
onInteractOutside={(event) => {
|
|
173
|
+
if (event.detail.originalEvent.type !== 'pointerdown') return
|
|
174
|
+
const owner = props.menuPortalMount
|
|
175
|
+
const target = event.detail.originalEvent.target
|
|
176
|
+
if (!(target instanceof Element) || !owner?.contains(target)) return
|
|
177
|
+
|
|
178
|
+
const focusTarget = target.closest<HTMLElement>(MENU_FOCUS_TARGET_SELECTOR)
|
|
179
|
+
setRestoreTriggerFocus(!focusTarget || !isMenuTabStop(focusTarget))
|
|
180
|
+
}}
|
|
181
|
+
onKeyDown={moveFocusOnTab}
|
|
182
|
+
onEscapeKeyDown={() => setRestoreTriggerFocus(true)}
|
|
183
|
+
onCloseAutoFocus={(event) => {
|
|
184
|
+
if (menuOpen()) {
|
|
185
|
+
event.preventDefault()
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
if (focusTargetAfterTab) {
|
|
189
|
+
const focusTarget = focusTargetAfterTab
|
|
190
|
+
focusTargetAfterTab = undefined
|
|
191
|
+
event.preventDefault()
|
|
192
|
+
queueMicrotask(() => {
|
|
193
|
+
if (!menuOpen() && focusTarget.isConnected) {
|
|
194
|
+
focusTarget.focus({ preventScroll: true })
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
return
|
|
198
|
+
}
|
|
199
|
+
if (!restoreTriggerFocus()) return
|
|
200
|
+
|
|
201
|
+
event.preventDefault()
|
|
202
|
+
setRestoreTriggerFocus(false)
|
|
203
|
+
const trigger = triggerElement()
|
|
204
|
+
if (
|
|
205
|
+
trigger?.isConnected &&
|
|
206
|
+
!trigger.disabled &&
|
|
207
|
+
trigger.closest('[hidden], [inert], [aria-hidden="true"]') === null &&
|
|
208
|
+
trigger.getClientRects().length > 0
|
|
209
|
+
) {
|
|
210
|
+
trigger.focus({ preventScroll: true })
|
|
211
|
+
}
|
|
212
|
+
}}
|
|
213
|
+
>
|
|
214
|
+
<DropdownMenuRadioGroup
|
|
215
|
+
value={props.family}
|
|
216
|
+
aria-label={`${props.label} system font`}
|
|
217
|
+
onChange={(family) => {
|
|
218
|
+
if (family === 'system') props.onSelect('system')
|
|
219
|
+
}}
|
|
220
|
+
>
|
|
221
|
+
<DropdownMenuRadioItem value="system" closeOnSelect>
|
|
222
|
+
System
|
|
223
|
+
</DropdownMenuRadioItem>
|
|
224
|
+
</DropdownMenuRadioGroup>
|
|
225
|
+
<DropdownMenuSeparator />
|
|
226
|
+
<DropdownMenuRadioGroup
|
|
227
|
+
value={props.family}
|
|
228
|
+
aria-label={`${props.label} available fonts`}
|
|
229
|
+
onChange={(family) => {
|
|
230
|
+
const option = fontOptions.find((candidate) => candidate.id === family)
|
|
231
|
+
if (option && option.id !== 'system') props.onSelect(option.id)
|
|
232
|
+
}}
|
|
233
|
+
>
|
|
234
|
+
<For each={catalogFontOptions}>
|
|
235
|
+
{(option) => (
|
|
236
|
+
<DropdownMenuRadioItem value={option.id} closeOnSelect>
|
|
237
|
+
{option.label}
|
|
238
|
+
</DropdownMenuRadioItem>
|
|
239
|
+
)}
|
|
240
|
+
</For>
|
|
241
|
+
</DropdownMenuRadioGroup>
|
|
242
|
+
</DropdownMenuContent>
|
|
243
|
+
</DropdownMenu>
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Controlled font controls shared by AppearanceEditor and host-owned settings. */
|
|
248
|
+
export function AppearanceFontSettingsGroup(props: AppearanceFontSettingsGroupProps) {
|
|
249
|
+
const [sizeDrafts, setSizeDrafts] = createSignal<
|
|
250
|
+
Partial<Record<AppearanceEditorFontAxis, string>>
|
|
251
|
+
>({})
|
|
252
|
+
const sizeHintPrefix = createUniqueId()
|
|
253
|
+
const settings = createMemo(() => normalizeAppearanceEditorFontSettings(props.settings).settings)
|
|
254
|
+
|
|
255
|
+
const updateAxis = (
|
|
256
|
+
axis: AppearanceEditorFontAxis,
|
|
257
|
+
patch: { family?: AppearanceEditorFontFamilyId; size?: number }
|
|
258
|
+
) => {
|
|
259
|
+
const current = settings()
|
|
260
|
+
props.onChange({
|
|
261
|
+
...current,
|
|
262
|
+
[axis]: {
|
|
263
|
+
...current[axis],
|
|
264
|
+
...patch,
|
|
265
|
+
},
|
|
266
|
+
})
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const commitSize = (axis: AppearanceEditorFontAxis) => {
|
|
270
|
+
const input = sizeDrafts()[axis]
|
|
271
|
+
if (input === undefined) return
|
|
272
|
+
const size = normalizeAppearanceEditorFontSize(input, settings()[axis].size)
|
|
273
|
+
setSizeDrafts((current) => {
|
|
274
|
+
const next = { ...current }
|
|
275
|
+
delete next[axis]
|
|
276
|
+
return next
|
|
277
|
+
})
|
|
278
|
+
if (size !== settings()[axis].size) updateAxis(axis, { size })
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return (
|
|
282
|
+
<div class="global-appearance-font-settings">
|
|
283
|
+
<For each={FONT_ROWS}>
|
|
284
|
+
{(row) => {
|
|
285
|
+
const Icon = row.icon
|
|
286
|
+
const value = () => settings()[row.axis]
|
|
287
|
+
const inputValue = () => sizeDrafts()[row.axis] ?? String(value().size)
|
|
288
|
+
const sizeHintId = `${sizeHintPrefix}-${row.axis}-font-size-help`
|
|
289
|
+
const sizeIsInvalid = () => {
|
|
290
|
+
const draft = sizeDrafts()[row.axis]
|
|
291
|
+
if (draft === undefined || draft.trim() === '') return false
|
|
292
|
+
const parsed = Number(draft)
|
|
293
|
+
return (
|
|
294
|
+
!Number.isFinite(parsed) ||
|
|
295
|
+
!Number.isInteger(parsed) ||
|
|
296
|
+
parsed < APPEARANCE_EDITOR_FONT_SIZE_MIN ||
|
|
297
|
+
parsed > APPEARANCE_EDITOR_FONT_SIZE_MAX
|
|
298
|
+
)
|
|
299
|
+
}
|
|
300
|
+
return (
|
|
301
|
+
<SettingsRow title={row.label} icon={<Icon />} description={row.description}>
|
|
302
|
+
<div class="flex min-w-0 max-w-full flex-wrap items-center gap-2">
|
|
303
|
+
<FontFamilyMenu
|
|
304
|
+
label={row.label}
|
|
305
|
+
family={value().family}
|
|
306
|
+
menuPortalMount={props.menuPortalMount}
|
|
307
|
+
disabled={props.disabled}
|
|
308
|
+
onSelect={(family) => updateAxis(row.axis, { family })}
|
|
309
|
+
/>
|
|
310
|
+
<div class="flex shrink-0 items-center gap-1">
|
|
311
|
+
<InputControl
|
|
312
|
+
type="number"
|
|
313
|
+
min={APPEARANCE_EDITOR_FONT_SIZE_MIN}
|
|
314
|
+
max={APPEARANCE_EDITOR_FONT_SIZE_MAX}
|
|
315
|
+
step={1}
|
|
316
|
+
value={inputValue()}
|
|
317
|
+
disabled={props.disabled}
|
|
318
|
+
aria-label={`${row.label} font size in pixels`}
|
|
319
|
+
aria-describedby={sizeHintId}
|
|
320
|
+
aria-invalid={sizeIsInvalid()}
|
|
321
|
+
class="w-16"
|
|
322
|
+
onInput={(event) =>
|
|
323
|
+
setSizeDrafts((current) => ({
|
|
324
|
+
...current,
|
|
325
|
+
[row.axis]: event.currentTarget.value,
|
|
326
|
+
}))
|
|
327
|
+
}
|
|
328
|
+
onBlur={() => commitSize(row.axis)}
|
|
329
|
+
onKeyDown={(event) => {
|
|
330
|
+
if (event.key !== 'Enter') return
|
|
331
|
+
event.preventDefault()
|
|
332
|
+
commitSize(row.axis)
|
|
333
|
+
}}
|
|
334
|
+
/>
|
|
335
|
+
<span aria-hidden="true" class="text-xs text-muted-foreground">
|
|
336
|
+
px
|
|
337
|
+
</span>
|
|
338
|
+
</div>
|
|
339
|
+
<span id={sizeHintId} class="sr-only">
|
|
340
|
+
Enter a whole number from {APPEARANCE_EDITOR_FONT_SIZE_MIN} to{' '}
|
|
341
|
+
{APPEARANCE_EDITOR_FONT_SIZE_MAX} pixels.
|
|
342
|
+
</span>
|
|
343
|
+
</div>
|
|
344
|
+
</SettingsRow>
|
|
345
|
+
)
|
|
346
|
+
}}
|
|
347
|
+
</For>
|
|
348
|
+
</div>
|
|
349
|
+
)
|
|
350
|
+
}
|
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
export { AppearanceEditor, AppearancePopover } from './appearance-editor'
|
|
2
|
+
export {
|
|
3
|
+
AppearanceFontSettingsGroup,
|
|
4
|
+
type AppearanceFontSettingsGroupProps,
|
|
5
|
+
} from './font-settings-group'
|
|
6
|
+
export {
|
|
7
|
+
APPEARANCE_EDITOR_FONT_AXES,
|
|
8
|
+
APPEARANCE_EDITOR_FONT_SIZE_MAX,
|
|
9
|
+
APPEARANCE_EDITOR_FONT_SIZE_MIN,
|
|
10
|
+
DEFAULT_APPEARANCE_EDITOR_FONT_SETTINGS,
|
|
11
|
+
applyAppearanceFontSettings,
|
|
12
|
+
fontSettingsBootstrapScript,
|
|
13
|
+
normalizeAppearanceEditorFontSettings,
|
|
14
|
+
normalizeAppearanceEditorFontSize,
|
|
15
|
+
type AppearanceEditorFontAxis,
|
|
16
|
+
type AppearanceEditorFontFamilyId,
|
|
17
|
+
type AppearanceEditorFontSetting,
|
|
18
|
+
type AppearanceEditorFontSettings,
|
|
19
|
+
type NormalizedAppearanceEditorFontSettings,
|
|
20
|
+
} from '#lib/appearance-font-settings'
|
|
2
21
|
export type {
|
|
3
22
|
AppearanceDraft,
|
|
4
23
|
AppearanceEditorProps,
|
|
@@ -857,7 +857,7 @@ export function UpdateDialog(props: UpdateDialogProps) {
|
|
|
857
857
|
stop, named by the heading above it, or a keyboard user cannot
|
|
858
858
|
scroll it (`scrollable-region-focusable`). */}
|
|
859
859
|
<div
|
|
860
|
-
class="max-h-52 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-
|
|
860
|
+
class="max-h-52 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-code text-code leading-5 whitespace-pre-wrap text-muted-foreground"
|
|
861
861
|
role="region"
|
|
862
862
|
aria-labelledby="update-release-notes"
|
|
863
863
|
tabindex="0"
|
|
@@ -886,7 +886,7 @@ export function UpdateDialog(props: UpdateDialogProps) {
|
|
|
886
886
|
stop, named by the heading above it, or a keyboard user cannot
|
|
887
887
|
scroll it (`scrollable-region-focusable`). */}
|
|
888
888
|
<div
|
|
889
|
-
class="max-h-72 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-
|
|
889
|
+
class="max-h-72 overflow-y-auto rounded-xl border border-border bg-background/45 p-4 font-code text-code leading-5 whitespace-pre-wrap text-muted-foreground"
|
|
890
890
|
role="region"
|
|
891
891
|
aria-labelledby="update-changelog"
|
|
892
892
|
tabindex="0"
|
|
@@ -141,10 +141,14 @@ export function MessageRow(props: MessageRowProps) {
|
|
|
141
141
|
that repeats every speaker's name in every bubble is one nobody reads. */}
|
|
142
142
|
<span class="visually-hidden">{local.senderName}</span>
|
|
143
143
|
|
|
144
|
-
<div data-slot="message-body" class="text-
|
|
144
|
+
<div data-slot="message-body" class="font-content text-content">
|
|
145
145
|
<Show
|
|
146
146
|
when={!local.deleted}
|
|
147
|
-
fallback={
|
|
147
|
+
fallback={
|
|
148
|
+
<p class="font-content text-content text-muted-foreground italic">
|
|
149
|
+
Message deleted
|
|
150
|
+
</p>
|
|
151
|
+
}
|
|
148
152
|
>
|
|
149
153
|
{local.children}
|
|
150
154
|
</Show>
|
|
@@ -376,7 +380,7 @@ function Prose(props: { text: string }) {
|
|
|
376
380
|
const parts = () => props.text.split(/(`[^`\n]+`)/g).filter(Boolean)
|
|
377
381
|
|
|
378
382
|
return (
|
|
379
|
-
<p class="whitespace-pre-wrap">
|
|
383
|
+
<p class="font-content text-content whitespace-pre-wrap">
|
|
380
384
|
<For each={parts()}>
|
|
381
385
|
{(part) => (
|
|
382
386
|
<Show
|
|
@@ -668,7 +668,7 @@ export function PasteTokenEditor(props: PasteTokenEditorProps) {
|
|
|
668
668
|
data-slot="paste-token-preview"
|
|
669
669
|
class="bg-scrim text-scrim-foreground z-(--z-tooltip) w-fit max-w-64 rounded-md px-2 py-1 text-xs origin-(--kb-tooltip-content-transform-origin) text-balance data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-expanded:duration-150 data-closed:duration-100"
|
|
670
670
|
>
|
|
671
|
-
<pre class="m-0 max-h-48 max-w-64 overflow-y-auto whitespace-pre-wrap break-words font-
|
|
671
|
+
<pre class="m-0 max-h-48 max-w-64 overflow-y-auto whitespace-pre-wrap break-words font-code text-code">
|
|
672
672
|
{summary().text}
|
|
673
673
|
</pre>
|
|
674
674
|
<Show when={summary().hiddenLines > 0}>
|