waybetter 0.6.0 → 0.7.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 +1 -2
- package/bin/waybetter.mjs +2 -5
- package/cli/buildenv.mjs +1 -1
- package/cli/release.mjs +11 -18
- package/cli/releasecheck.mjs +15 -0
- package/cli/remote.mjs +4 -4
- package/cli/store.mjs +80 -28
- package/cli/strings.mjs +2 -0
- package/dist/runtime/stringPackHook.js +2 -2
- package/dist/runtime/stringPackHook.js.map +1 -1
- package/dist/runtime/stringPackTranslate.d.ts +3 -1
- package/dist/runtime/stringPackTranslate.js +6 -3
- package/dist/runtime/stringPackTranslate.js.map +1 -1
- package/dist/runtime/stringPacks.d.ts +53 -5
- package/dist/runtime/stringPacks.js +161 -25
- package/dist/runtime/stringPacks.js.map +1 -1
- package/dist/runtime/themeBar.d.ts +28 -0
- package/dist/runtime/themeBar.js +82 -0
- package/dist/runtime/themeBar.js.map +1 -0
- package/dist/runtime/themeComponents.js +16 -3
- package/dist/runtime/themeComponents.js.map +1 -1
- package/dist/runtime/themeDecor.js +3 -1
- package/dist/runtime/themeDecor.js.map +1 -1
- package/dist/runtime/themeDerive.d.ts +69 -0
- package/dist/runtime/themeDerive.js +117 -0
- package/dist/runtime/themeDerive.js.map +1 -0
- package/dist/runtime/themeDoctor.d.ts +44 -3
- package/dist/runtime/themeDoctor.js +86 -25
- package/dist/runtime/themeDoctor.js.map +1 -1
- package/dist/runtime/themeGuards.d.ts +60 -0
- package/dist/runtime/themeGuards.js +235 -0
- package/dist/runtime/themeGuards.js.map +1 -0
- package/dist/runtime/themeIcons.d.ts +1 -1
- package/dist/runtime/themeIcons.js +13 -5
- package/dist/runtime/themeIcons.js.map +1 -1
- package/dist/runtime/themeInk.d.ts +37 -0
- package/dist/runtime/themeInk.js +111 -0
- package/dist/runtime/themeInk.js.map +1 -0
- package/dist/runtime/themeInvariants.d.ts +39 -0
- package/dist/runtime/themeInvariants.js +273 -0
- package/dist/runtime/themeInvariants.js.map +1 -0
- package/dist/runtime/themeRuntime.d.ts +15 -1
- package/dist/runtime/themeRuntime.js +78 -5
- package/dist/runtime/themeRuntime.js.map +1 -1
- package/dist/runtime/themeSpec.d.ts +5 -1
- package/dist/runtime/themeSpec.js +9 -13
- package/dist/runtime/themeSpec.js.map +1 -1
- package/dist/shell/InstallDialog.js +14 -8
- package/dist/shell/InstallDialog.js.map +1 -1
- package/dist/shell/StoreView.d.ts +12 -0
- package/dist/shell/StoreView.js +9 -4
- package/dist/shell/StoreView.js.map +1 -1
- package/dist/shell/frame/AppMenu.d.ts +26 -3
- package/dist/shell/frame/AppMenu.js +106 -27
- package/dist/shell/frame/AppMenu.js.map +1 -1
- package/dist/shell/frame/FindBar.js +1 -1
- package/dist/shell/frame/FindBar.js.map +1 -1
- package/dist/shell/frame/Shell.d.ts +1 -0
- package/dist/shell/frame/Shell.js +10 -2
- package/dist/shell/frame/Shell.js.map +1 -1
- package/dist/shell/frame/Titlebar.d.ts +2 -1
- package/dist/shell/frame/Titlebar.js +5 -3
- package/dist/shell/frame/Titlebar.js.map +1 -1
- package/dist/shell/frame/WebPanel.js +4 -1
- package/dist/shell/frame/WebPanel.js.map +1 -1
- package/dist/shell/frame/accountSwitcher.css +10 -10
- package/dist/shell/frame/appMenu.css +19 -13
- package/dist/shell/frame/boot.js +2 -0
- package/dist/shell/frame/boot.js.map +1 -1
- package/dist/shell/frame/chromeTheme.d.ts +19 -1
- package/dist/shell/frame/chromeTheme.js +51 -14
- package/dist/shell/frame/chromeTheme.js.map +1 -1
- package/dist/shell/frame/deck.css +30 -30
- package/dist/shell/frame/edges.css +159 -0
- package/dist/shell/frame/index.d.ts +2 -2
- package/dist/shell/frame/index.js +1 -1
- package/dist/shell/frame/index.js.map +1 -1
- package/dist/shell/frame/mediaModel.d.ts +13 -0
- package/dist/shell/frame/mediaModel.js +14 -0
- package/dist/shell/frame/mediaModel.js.map +1 -1
- package/dist/shell/frame/menuMessages.en.json +43 -1
- package/dist/shell/frame/menuModel.d.ts +42 -0
- package/dist/shell/frame/menuModel.js +8 -0
- package/dist/shell/frame/menuModel.js.map +1 -1
- package/dist/shell/frame/nativeMenu.d.ts +5 -0
- package/dist/shell/frame/nativeMenu.js +178 -0
- package/dist/shell/frame/nativeMenu.js.map +1 -0
- package/dist/shell/frame/nativeMenuModel.d.ts +102 -0
- package/dist/shell/frame/nativeMenuModel.js +186 -0
- package/dist/shell/frame/nativeMenuModel.js.map +1 -0
- package/dist/shell/frame/paletteModel.js +3 -1
- package/dist/shell/frame/paletteModel.js.map +1 -1
- package/dist/shell/frame/paneTheme.css +1 -1
- package/dist/shell/frame/reportModel.d.ts +1 -1
- package/dist/shell/frame/reportModel.js +1 -1
- package/dist/shell/frame/reportModel.js.map +1 -1
- package/dist/shell/frame/shell.css +56 -51
- package/dist/shell/frame/state.d.ts +2 -0
- package/dist/shell/frame/state.js +3 -1
- package/dist/shell/frame/state.js.map +1 -1
- package/dist/shell/frame/themeStore.js +21 -6
- package/dist/shell/frame/themeStore.js.map +1 -1
- package/dist/shell/frame/workspaces.css +12 -12
- package/dist/shell/installController.d.ts +16 -1
- package/dist/shell/installController.js +31 -5
- package/dist/shell/installController.js.map +1 -1
- package/dist/shell/panel/Appearance.js +12 -3
- package/dist/shell/panel/Appearance.js.map +1 -1
- package/dist/shell/panel/Settings.d.ts +1 -1
- package/dist/shell/panel/Settings.js +4 -3
- package/dist/shell/panel/Settings.js.map +1 -1
- package/dist/shell/panel/StoreSection.d.ts +2 -1
- package/dist/shell/panel/StoreSection.js +31 -1
- package/dist/shell/panel/StoreSection.js.map +1 -1
- package/dist/shell/panel/StringPacks.d.ts +12 -3
- package/dist/shell/panel/StringPacks.js +33 -8
- package/dist/shell/panel/StringPacks.js.map +1 -1
- package/dist/shell/panel/backup.css +1 -1
- package/dist/shell/panel/builder.css +48 -40
- package/dist/shell/panel/make.css +8 -7
- package/dist/shell/panel/panel.css +401 -401
- package/dist/shell/panel/panelMessages.d.ts +41 -1
- package/dist/shell/panel/panelMessages.js +13 -1
- package/dist/shell/panel/panelMessages.js.map +1 -1
- package/dist/shell/panel/plugins.css +5 -5
- package/dist/shell/panel/strings.css +1 -1
- package/dist/shell/store.css +34 -14
- package/dist/shell/storeMessages.d.ts +24 -0
- package/dist/shell/storeMessages.js +24 -0
- package/dist/shell/storeMessages.js.map +1 -1
- package/dist/shell/storeModel.d.ts +31 -7
- package/dist/shell/storeModel.js +15 -2
- package/dist/shell/storeModel.js.map +1 -1
- package/dist/shell/stringPacksModel.js +7 -2
- package/dist/shell/stringPacksModel.js.map +1 -1
- package/icons.schema.json +9 -0
- package/locales/ar.json +109 -2
- package/locales/bg.json +109 -2
- package/locales/bn.json +109 -2
- package/locales/ca.json +109 -2
- package/locales/cs.json +109 -2
- package/locales/da.json +109 -2
- package/locales/de.json +109 -2
- package/locales/el.json +109 -2
- package/locales/en.json +108 -2
- package/locales/es.json +109 -2
- package/locales/eu.json +109 -2
- package/locales/fa.json +109 -2
- package/locales/fi.json +109 -2
- package/locales/fil.json +109 -2
- package/locales/fr.json +109 -2
- package/locales/ga.json +109 -2
- package/locales/gl.json +109 -2
- package/locales/gu.json +109 -2
- package/locales/ha.json +109 -2
- package/locales/he.json +109 -2
- package/locales/hi.json +109 -2
- package/locales/hr.json +109 -2
- package/locales/hu.json +110 -2
- package/locales/id.json +109 -2
- package/locales/ig.json +109 -2
- package/locales/it.json +109 -2
- package/locales/ja.json +109 -2
- package/locales/kn.json +109 -2
- package/locales/ko.json +109 -2
- package/locales/mr.json +109 -2
- package/locales/ms.json +109 -2
- package/locales/nb.json +109 -2
- package/locales/nl.json +109 -2
- package/locales/pl.json +109 -2
- package/locales/pt.json +109 -2
- package/locales/ro.json +109 -2
- package/locales/ru.json +109 -2
- package/locales/sk.json +109 -2
- package/locales/sr.json +109 -2
- package/locales/sv.json +109 -2
- package/locales/ta.json +109 -2
- package/locales/th.json +109 -2
- package/locales/tr.json +109 -2
- package/locales/uk.json +109 -2
- package/locales/ur.json +109 -2
- package/locales/vi.json +109 -2
- package/locales/yo.json +109 -2
- package/locales/zh-Hans.json +109 -2
- package/locales/zh-Hant.json +109 -2
- package/package.json +2 -3
- package/store-catalog.schema.json +18 -5
- package/theme.schema.json +9 -0
- package/windows/installer.nsi +22 -2
- package/cli/privacy.mjs +0 -768
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chromeTheme.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/chromeTheme.ts"],"names":[],"mappings":"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","sourcesContent":["// The app's own window in the active theme: the theme's palette and its chrome/mono fonts become\n// the shell's `--wb-c-*` (tabs, address bar, titlebar, menus) and the panel's `--wb-p-*` tokens,\n// which shell.css (and the app's panel CSS) read with Night Ink as the fallback. Pure (tests,\n// shell, panel). The app turns its theme documents into a `ChromeTheme` (site.themes.chrome).\n\n/** The shell's own interface font (what an inheriting chrome role falls back to outside the page). */\nexport const SHELL_UI_FONT = \"'Geist Variable', system-ui, sans-serif\";\nexport const SHELL_MONO_FONT = \"'Geist Mono Variable', ui-monospace, monospace\";\n\n/** A theme as the chrome needs it: seven colors (none: the site's own colors) and two font stacks. */\nexport type ChromeTheme = {\n colors?: { bg: string; surface: string; elevated: string; border: string; text: string; muted: string; accent: string } | null;\n /** The chrome's font stack when the theme sets one other than SHELL_UI_FONT. */\n chromeFont?: string | null;\n /** The mono font stack when the theme sets one. */\n monoFont?: string | null;\n};\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const n = parseInt(hex.slice(1), 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\nconst toHex = (rgb: number[]) => `#${rgb.map(v => Math.round(Math.min(255, Math.max(0, v))).toString(16).padStart(2, '0')).join('')}`;\nexport function luminance(hex: string): number {\n const [r, g, b] = hexToRgb(hex).map(v => { const c = v / 255; return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4; }) as [number, number, number];\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\nexport function contrast(a: string, b: string): number {\n const [x, y] = [luminance(a), luminance(b)].sort((m, n) => n - m) as [number, number];\n return (x + 0.05) / (y + 0.05);\n}\nexport function mix(a: string, b: string, t: number): string {\n const [x, y] = [hexToRgb(a), hexToRgb(b)];\n return toHex(x.map((v, i) => v + (y[i]! - v) * t));\n}\n\nconst channels = (hex: string) => hexToRgb(hex).join(' ');\n\n/** Moves `color` toward `pole` until it reads at `ratio` on `surface`. */\nfunction legible(color: string, surface: string, ratio: number): string {\n if (contrast(color, surface) >= ratio) return color;\n const pole = luminance(surface) > 0.18 ? '#000000' : '#ffffff';\n for (let t = 0.1; t <= 1; t += 0.1) { const next = mix(color, pole, t); if (contrast(next, surface) >= ratio) return next; }\n return pole;\n}\n\n/**\n * CSS custom properties for the chrome in `theme`. A theme that keeps the site's colors changes\n * only the fonts; `own` keeps wayBetter's own style entirely (empty result).\n */\nexport function chromeVars(theme: ChromeTheme, own = false): Record<string, string> {\n if (own) return {};\n const vars: Record<string, string> = {};\n // The chrome inherits the theme's interface font (a web font of the site is not available here: then Geist).\n if (theme.chromeFont) vars['--wb-f-chrome'] = theme.chromeFont;\n if (theme.monoFont) vars['--wb-f-mono'] = theme.monoFont;\n const colors = theme.colors;\n if (!colors) return vars;\n const { bg, surface, elevated, border, text, muted, accent } = colors;\n const dark = luminance(bg) < luminance(text);\n const ink = legible(mix(accent, text, 0.55), elevated, 4.5);\n Object.assign(vars, {\n // Shell chrome: the ground under the tabs is the theme's column background.\n '--wb-c-ground': bg, '--wb-c-chrome': surface, '--wb-c-field': mix(surface, elevated, 0.45),\n '--wb-c-raised': elevated, '--wb-c-raised-2': mix(elevated, border, 0.45),\n '--wb-c-line': border, '--wb-c-line-soft': mix(border, bg, 0.45), '--wb-c-line-strong': mix(border, text, 0.14),\n '--wb-c-text': text, '--wb-c-text-2': mix(text, muted, 0.4), '--wb-c-muted': muted, '--wb-c-faint': mix(muted, bg, 0.38),\n '--wb-c-text-rgb': channels(text), '--wb-c-accent': accent, '--wb-c-accent-rgb': channels(accent), '--wb-c-accent-ink': ink,\n '--wb-c-scheme': dark ? 'dark' : 'light',\n ...(dark ? {} : { '--wb-c-shadow-pop': `0 18px 44px -14px rgba(${hexToRgb(mix(text, bg, 0.2)).join(', ')}, .28), 0 3px 10px rgba(0, 0, 0, .08)` }),\n // Panel.\n '--wb-p-ground': bg, '--wb-p-chrome': mix(bg, surface, 0.5), '--wb-p-card': surface, '--wb-p-field': mix(surface, elevated, 0.5), '--wb-p-raise': elevated,\n '--wb-p-line': border, '--wb-p-line-soft': mix(border, bg, 0.4), '--wb-p-line-strong': mix(border, text, 0.16),\n '--wb-p-text': text, '--wb-p-text-2': mix(text, muted, 0.3), '--wb-p-muted': muted, '--wb-p-faint': mix(muted, bg, 0.35),\n '--wb-p-accent': accent, '--wb-p-accent-rgb': channels(accent), '--wb-p-accent-ink': contrast(accent, '#ffffff') >= contrast(accent, bg) ? '#ffffff' : bg,\n '--wb-p-text-rgb': channels(text), '--wb-p-popover': elevated, '--wb-p-thumb': `linear-gradient(180deg, ${mix(elevated, text, 0.08)}, ${elevated})`,\n '--wb-p-track': mix(elevated, border, 0.5), '--wb-p-knob': mix(muted, text, 0.3),\n });\n return vars;\n}\n\n/** Every variable chromeVars may set (to clear them when a pane returns to the global theme). */\nexport const CHROME_VAR_NAMES = Object.keys(chromeVars({\n colors: { bg: '#000000', surface: '#111111', elevated: '#222222', border: '#333333', text: '#ffffff', muted: '#999999', accent: '#1d9bf0' },\n chromeFont: 'A', monoFont: 'B',\n})).concat('--wb-c-shadow-pop');\n"]}
|
|
1
|
+
{"version":3,"file":"chromeTheme.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/chromeTheme.ts"],"names":[],"mappings":"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","sourcesContent":["// The app's own window in the active theme: the theme's palette and its chrome/mono fonts become\n// the shell's `--wb-c-*` (tabs, address bar, titlebar, menus) and the panel's `--wb-p-*` tokens,\n// which shell.css (and the app's panel CSS) read with Night Ink as the fallback. Pure (tests,\n// shell, panel). The app turns its theme documents into a `ChromeTheme` (site.themes.chrome).\n// Inks come from the engine's contrast solver and surfaces (theme engine v3, steps 4-5).\n\nimport { deriveSurfaces, surfacesInputFromV2, type SurfaceSet } from '../../../runtime/src/themeDerive.ts';\nimport { inkOn } from '../../../runtime/src/themeInk.ts';\n\n/** The shell's own interface font (what an inheriting chrome role falls back to outside the page). */\nexport const SHELL_UI_FONT = \"'Geist Variable', system-ui, sans-serif\";\nexport const SHELL_MONO_FONT = \"'Geist Mono Variable', ui-monospace, monospace\";\n\n/** A theme as the chrome needs it: seven colors (none: the site's own colors) and two font stacks. */\nexport type ChromeTheme = {\n /** `page`, `inverse` and `onInverse` are optional: a bevelled chrome builds its face and title bar from them. */\n colors?: { bg: string; surface: string; elevated: string; border: string; text: string; muted: string; accent: string; page?: string; inverse?: string; onInverse?: string } | null;\n /** The theme's corner radius in px: every chrome radius scales by radius / 12 (0 to 1.5, `--wb-c-rs`). Absent: wayBetter's own. */\n radius?: number | null;\n /**\n * How the chrome's edges are drawn. `bevel`: raised and sunken edges after 98.css (MIT, Jordan\n * Scales), square corners, a face color under tabs, menus and dialogs, a title-bar gradient\n * (frame/edges.css, keyed on `html[data-wb-edges]`). Absent: wayBetter's own soft edges.\n */\n edges?: 'bevel' | null;\n /** The chrome's font stack when the theme sets one other than SHELL_UI_FONT. */\n chromeFont?: string | null;\n /** The mono font stack when the theme sets one. */\n monoFont?: string | null;\n};\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const n = parseInt(hex.slice(1), 16);\n return [(n >> 16) & 255, (n >> 8) & 255, n & 255];\n}\nconst toHex = (rgb: number[]) => `#${rgb.map(v => Math.round(Math.min(255, Math.max(0, v))).toString(16).padStart(2, '0')).join('')}`;\nexport function luminance(hex: string): number {\n const [r, g, b] = hexToRgb(hex).map(v => { const c = v / 255; return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4; }) as [number, number, number];\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\nexport function contrast(a: string, b: string): number {\n const [x, y] = [luminance(a), luminance(b)].sort((m, n) => n - m) as [number, number];\n return (x + 0.05) / (y + 0.05);\n}\nexport function mix(a: string, b: string, t: number): string {\n const [x, y] = [hexToRgb(a), hexToRgb(b)];\n return toHex(x.map((v, i) => v + (y[i]! - v) * t));\n}\n\nconst channels = (hex: string) => hexToRgb(hex).join(' ');\n\n/** The theme's surfaces (theme engine v3, themeDerive.ts): the chrome takes its title bar, face and selection from them. */\nexport function chromeSurfaces(theme: ChromeTheme): SurfaceSet | null {\n return theme.colors ? deriveSurfaces(surfacesInputFromV2(theme.colors, { bevel: theme.edges === 'bevel' })) : null;\n}\n\n/** The colour closest to `color` that reads at `ratio` on `surface` (the engine's solver, themeInk.ts). */\nconst legible = (color: string, surface: string, ratio: number) => inkOn(surface, color, ratio).ink;\n\n/**\n * CSS custom properties for the chrome in `theme`. A theme that keeps the site's colors changes\n * only the fonts (and keeps wayBetter's own corners and edges); `own` keeps wayBetter's own style\n * entirely (empty result).\n */\nexport function chromeVars(theme: ChromeTheme, own = false): Record<string, string> {\n if (own) return {};\n const vars: Record<string, string> = {};\n // The chrome inherits the theme's interface font (a web font of the site is not available here: then Geist).\n if (theme.chromeFont) vars['--wb-f-chrome'] = theme.chromeFont;\n if (theme.monoFont) vars['--wb-f-mono'] = theme.monoFont;\n const colors = theme.colors;\n if (!colors) return vars;\n // Radii follow the theme's own corners: square themes get a square chrome, round ones a rounder one.\n if (typeof theme.radius === 'number' && Number.isFinite(theme.radius)) {\n vars['--wb-c-rs'] = String(Math.round(Math.min(1.5, Math.max(0, theme.radius / 12)) * 100) / 100);\n }\n const { bg, surface, elevated, border, text, muted, accent } = colors;\n const dark = luminance(bg) < luminance(text);\n const ink = legible(mix(accent, text, 0.55), elevated, 4.5);\n Object.assign(vars, {\n // Shell chrome: the ground under the tabs is the theme's column background.\n '--wb-c-ground': bg, '--wb-c-chrome': surface, '--wb-c-field': mix(surface, elevated, 0.45),\n '--wb-c-raised': elevated, '--wb-c-raised-2': mix(elevated, border, 0.45),\n '--wb-c-line': border, '--wb-c-line-soft': mix(border, bg, 0.45), '--wb-c-line-strong': mix(border, text, 0.14),\n '--wb-c-text': text, '--wb-c-text-2': mix(text, muted, 0.4), '--wb-c-muted': legible(muted, elevated, 4.5),\n // Shortcut hints and section labels sit on the menus' raised surface: they keep 4.5:1 there (a 38% fade toward the ground read 2.1 to 3.6:1).\n '--wb-c-faint': legible(mix(muted, bg, 0.38), elevated, 4.5),\n '--wb-c-text-rgb': channels(text), '--wb-c-accent': accent, '--wb-c-accent-rgb': channels(accent), '--wb-c-accent-ink': ink,\n '--wb-c-scheme': dark ? 'dark' : 'light',\n // Status inks (a signed-out account, an error) readable on the menus' raised surface, whatever its shade.\n '--wb-c-warn': legible(dark ? '#f0b14a' : '#9a5b00', elevated, 4.5), '--wb-c-danger-ink': legible(dark ? '#ff8a80' : '#b3261e', elevated, 4.5),\n // The chrome's marks (active tab, palette edge) in the theme's accent instead of wayBetter's brush.\n '--wb-c-brush': `linear-gradient(90deg, ${accent}, ${accent})`,\n ...(dark ? {} : { '--wb-c-shadow-pop': `0 18px 44px -14px rgba(${hexToRgb(mix(text, bg, 0.2)).join(', ')}, .28), 0 3px 10px rgba(0, 0, 0, .08)` }),\n // Panel.\n '--wb-p-ground': bg, '--wb-p-chrome': mix(bg, surface, 0.5), '--wb-p-card': surface, '--wb-p-field': mix(surface, elevated, 0.5), '--wb-p-raise': elevated,\n '--wb-p-line': border, '--wb-p-line-soft': mix(border, bg, 0.4), '--wb-p-line-strong': mix(border, text, 0.16),\n '--wb-p-text': text, '--wb-p-text-2': mix(text, muted, 0.3), '--wb-p-muted': muted, '--wb-p-faint': mix(muted, bg, 0.35),\n '--wb-p-accent': accent, '--wb-p-accent-rgb': channels(accent), '--wb-p-accent-ink': contrast(accent, '#ffffff') >= contrast(accent, bg) ? '#ffffff' : bg,\n '--wb-p-text-rgb': channels(text), '--wb-p-popover': elevated, '--wb-p-thumb': `linear-gradient(180deg, ${mix(elevated, text, 0.08)}, ${elevated})`,\n '--wb-p-track': mix(elevated, border, 0.5), '--wb-p-knob': mix(muted, text, 0.3),\n });\n if (theme.edges === 'bevel') Object.assign(vars, bevelVars(colors));\n return vars;\n}\n\n/**\n * A bevelled chrome: the face every raised part is made of (the theme's `page`, else its raised\n * surface), the four edge lines of 98.css derived from that face (white highlight, light, shadow,\n * near-black), the field under text (the theme's background) and the active title bar (inverse to\n * accent, its label readable on both ends).\n */\nfunction bevelVars(colors: NonNullable<ChromeTheme['colors']>): Record<string, string> {\n const set = deriveSurfaces(surfacesInputFromV2(colors, { bevel: true }));\n const face = set.chrome.fill;\n const strong = set.strong;\n return {\n '--wb-c-edges': 'bevel', '--wb-c-face': face, '--wb-c-face-text': legible(colors.text, face, 7),\n '--wb-c-bevel-hi': mix(face, '#ffffff', 1), '--wb-c-bevel-lt': mix(face, '#ffffff', 0.49),\n '--wb-c-bevel-sh': mix(face, '#000000', 0.335), '--wb-c-bevel-dk': mix(face, '#000000', 0.95),\n // The active title bar is the strong surface: inverse to its gradient end, one ink readable on both.\n '--wb-c-title-from': strong.fill, '--wb-c-title-to': strong.fill2 ?? strong.fill, '--wb-c-title-text': strong.ink,\n // Selected rows (menus, lists): the title bar's own color, as in a 98 menu.\n '--wb-c-select': strong.fill, '--wb-c-select-text': strong.ink,\n // Menus are the face: status inks are measured on it.\n '--wb-c-muted': set.chrome.inkSoft, '--wb-c-faint': set.chrome.inkSoft,\n '--wb-c-warn': legible('#806000', face, 4.5), '--wb-c-danger-ink': legible('#a00000', face, 4.5),\n };\n}\n\n/** Every variable chromeVars may set (to clear them when a pane returns to the global theme). */\nexport const CHROME_VAR_NAMES = Object.keys(chromeVars({\n colors: { bg: '#000000', surface: '#111111', elevated: '#222222', border: '#333333', text: '#ffffff', muted: '#999999', accent: '#1d9bf0' },\n chromeFont: 'A', monoFont: 'B', radius: 12, edges: 'bevel',\n})).concat('--wb-c-shadow-pop');\n\n/** The edge style a set of chrome variables asks for (`html[data-wb-edges]`), or null. */\nexport function chromeEdges(vars: Record<string, string>): string | null {\n return vars['--wb-c-edges'] === 'bevel' ? 'bevel' : null;\n}\n"]}
|
|
@@ -6,25 +6,25 @@
|
|
|
6
6
|
.bt-deck { position: relative; height: 100%; display: flex; flex-direction: column; background: var(--bt-ground); color: var(--bt-text); overflow: hidden; }
|
|
7
7
|
|
|
8
8
|
/* The deck's dockview tab: unread total. */
|
|
9
|
-
.bt-tab-unread { flex: none; min-width: 16px; height: 16px; padding: 0 5px; box-sizing: border-box; border-radius: 999px; background: var(--bt-accent); color: #fff; font: 700 10px/16px var(--bt-mono); text-align: center; }
|
|
9
|
+
.bt-tab-unread { flex: none; min-width: 16px; height: 16px; padding: 0 5px; box-sizing: border-box; border-radius: calc(999px * var(--bt-rs, 1)); background: var(--bt-accent); color: #fff; font: 700 10px/16px var(--bt-mono); text-align: center; }
|
|
10
10
|
|
|
11
11
|
/* Deck bar ---------------------------------------------------------------------------------- */
|
|
12
12
|
.bt-deck-bar { flex: none; display: flex; align-items: center; gap: 10px; height: 40px; padding-block: 0; padding-inline: 14px 10px; }
|
|
13
|
-
.bt-deck-mark { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 7px; background: linear-gradient(135deg, rgba(79, 107, 255, .28), rgba(34, 211, 238, .18)); box-shadow: inset 0 0 0 1px rgba(159, 211, 255, .18); color: #bfe0ff; }
|
|
13
|
+
.bt-deck-mark { display: grid; place-items: center; width: 22px; height: 22px; border-radius: calc(7px * var(--bt-rs, 1)); background: linear-gradient(135deg, rgba(79, 107, 255, .28), rgba(34, 211, 238, .18)); box-shadow: inset 0 0 0 1px rgba(159, 211, 255, .18); color: #bfe0ff; }
|
|
14
14
|
.bt-deck-mark .bt-glyph { width: 13px; height: 13px; }
|
|
15
15
|
.bt-deck-name { font: 650 13.5px/1 var(--bt-ui); letter-spacing: -.01em; }
|
|
16
16
|
.bt-deck-count { color: var(--bt-faint); font: 500 11.5px/1 var(--bt-ui); }
|
|
17
|
-
.bt-deck-total { padding: 4px 8px; border-radius: 999px; background: var(--bt-accent-soft); color: var(--bt-accent-ink); font: 600 11px/1 var(--bt-mono); box-shadow: inset 0 0 0 1px rgba(29, 155, 240, .28); }
|
|
17
|
+
.bt-deck-total { padding: 4px 8px; border-radius: calc(999px * var(--bt-rs, 1)); background: var(--bt-accent-soft); color: var(--bt-accent-ink); font: 600 11px/1 var(--bt-mono); box-shadow: inset 0 0 0 1px rgba(29, 155, 240, .28); }
|
|
18
18
|
.bt-deck-fill { flex: 1; }
|
|
19
|
-
.bt-deck-pager { display: flex; align-items: center; gap: 2px; padding: 2px; border-radius: 999px; background: var(--bt-field); box-shadow: inset 0 0 0 1px var(--bt-line-soft); }
|
|
20
|
-
.bt-deck-pager .bt-icon { width: 24px; height: 24px; border-radius: 999px; }
|
|
19
|
+
.bt-deck-pager { display: flex; align-items: center; gap: 2px; padding: 2px; border-radius: calc(999px * var(--bt-rs, 1)); background: var(--bt-field); box-shadow: inset 0 0 0 1px var(--bt-line-soft); }
|
|
20
|
+
.bt-deck-pager .bt-icon { width: 24px; height: 24px; border-radius: calc(999px * var(--bt-rs, 1)); }
|
|
21
21
|
.bt-deck-pager .bt-glyph { width: 13px; height: 13px; }
|
|
22
22
|
.bt-deck-dot { width: 18px; height: 24px; padding: 0; border: 0; background: transparent; cursor: pointer; position: relative; }
|
|
23
|
-
.bt-deck-dot::after { content: ""; position: absolute; left: 50%; top: 50%; width: 6px; height: 6px; margin: -3px 0 0 -3px; border-radius: 999px; background: var(--bt-line-strong); transition: width var(--bt-t2) var(--bt-ease-out), margin var(--bt-t2) var(--bt-ease-out), background-color var(--bt-t1) var(--bt-ease); }
|
|
23
|
+
.bt-deck-dot::after { content: ""; position: absolute; left: 50%; top: 50%; width: 6px; height: 6px; margin: -3px 0 0 -3px; border-radius: calc(999px * var(--bt-rs, 1)); background: var(--bt-line-strong); transition: width var(--bt-t2) var(--bt-ease-out), margin var(--bt-t2) var(--bt-ease-out), background-color var(--bt-t1) var(--bt-ease); }
|
|
24
24
|
.bt-deck-dot:hover::after { background: var(--bt-muted); }
|
|
25
25
|
.bt-deck-dot.is-on::after { width: 14px; margin-left: -7px; background: var(--bt-accent); } /* rtl-ok: centred with left: 50% */
|
|
26
|
-
.bt-deck-memory { color: var(--bt-muted); font: 500 11px/1 var(--bt-mono); padding: 5px 8px; border-radius: 7px; background: rgba(238, 240, 247, .04); }
|
|
27
|
-
.bt-deck-action { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding-block: 0; padding-inline: 9px 11px; border: 0; border-radius: 8px; background: rgba(238, 240, 247, .05); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .06); color: var(--bt-text-2); font: 550 12.5px/1 var(--bt-ui); cursor: pointer; transition: background-color var(--bt-t1) var(--bt-ease), color var(--bt-t1) var(--bt-ease); }
|
|
26
|
+
.bt-deck-memory { color: var(--bt-muted); font: 500 11px/1 var(--bt-mono); padding: 5px 8px; border-radius: calc(7px * var(--bt-rs, 1)); background: rgba(238, 240, 247, .04); }
|
|
27
|
+
.bt-deck-action { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding-block: 0; padding-inline: 9px 11px; border: 0; border-radius: calc(8px * var(--bt-rs, 1)); background: rgba(238, 240, 247, .05); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .06); color: var(--bt-text-2); font: 550 12.5px/1 var(--bt-ui); cursor: pointer; transition: background-color var(--bt-t1) var(--bt-ease), color var(--bt-t1) var(--bt-ease); }
|
|
28
28
|
.bt-deck-action .bt-glyph { width: 14px; height: 14px; }
|
|
29
29
|
.bt-deck-action:hover { background: rgba(238, 240, 247, .09); color: var(--bt-text); }
|
|
30
30
|
.bt-deck-action.is-on { background: var(--bt-accent-soft); box-shadow: inset 0 0 0 1px rgba(29, 155, 240, .38); color: var(--bt-accent-ink); }
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
.bt-deck-row { position: relative; flex: 1; min-height: 0; margin: 0 8px; }
|
|
36
36
|
.bt-col, .bt-compose {
|
|
37
37
|
position: absolute; top: 0; bottom: 0; display: flex; flex-direction: column; box-sizing: border-box;
|
|
38
|
-
border-radius: 12px 12px 0 0; background: var(--bt-chrome); box-shadow: inset 0 0 0 1px var(--bt-line-soft);
|
|
38
|
+
border-radius: calc(12px * var(--bt-rs, 1)) calc(12px * var(--bt-rs, 1)) 0 0; background: var(--bt-chrome); box-shadow: inset 0 0 0 1px var(--bt-line-soft);
|
|
39
39
|
--bt-col-account: var(--bt-accent);
|
|
40
40
|
}
|
|
41
41
|
/* Motion never transforms a column's body: the webview is placed on the body's rectangle, so only
|
|
@@ -50,12 +50,12 @@
|
|
|
50
50
|
|
|
51
51
|
.bt-col-head, .bt-compose-head {
|
|
52
52
|
position: relative; flex: none; display: flex; align-items: center; gap: 8px; height: 46px; padding-block: 0; padding-inline: 8px 6px;
|
|
53
|
-
border-radius: 12px 12px 0 0; border-bottom: 1px solid var(--bt-line-soft);
|
|
53
|
+
border-radius: calc(12px * var(--bt-rs, 1)) calc(12px * var(--bt-rs, 1)) 0 0; border-bottom: 1px solid var(--bt-line-soft);
|
|
54
54
|
background: linear-gradient(180deg, rgba(238, 240, 247, .025), transparent);
|
|
55
55
|
}
|
|
56
56
|
/* The focused column: an accent line on top and a lifted header. */
|
|
57
57
|
.bt-col-head::before, .bt-compose-head::before {
|
|
58
|
-
content: ""; position: absolute; left: 12px; right: 12px; top: 0; height: 2px; border-radius: 0 0 2px 2px;
|
|
58
|
+
content: ""; position: absolute; left: 12px; right: 12px; top: 0; height: 2px; border-radius: 0 0 calc(2px * var(--bt-rs, 1)) calc(2px * var(--bt-rs, 1));
|
|
59
59
|
background: var(--bt-brush); opacity: 0; transform: scaleX(.6); transition: opacity var(--bt-t2) var(--bt-ease), transform var(--bt-t3) var(--bt-ease-out);
|
|
60
60
|
}
|
|
61
61
|
.bt-col.is-focused .bt-col-head::before, .bt-compose-head::before { opacity: 1; transform: none; }
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
.bt-col.is-focused .bt-col-head { background: linear-gradient(180deg, rgba(29, 155, 240, .08), rgba(29, 155, 240, 0)); }
|
|
64
64
|
|
|
65
65
|
.bt-col-glyph {
|
|
66
|
-
display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: 8px; padding: 0; border: 0;
|
|
66
|
+
display: grid; place-items: center; flex: none; width: 28px; height: 28px; border-radius: calc(8px * var(--bt-rs, 1)); padding: 0; border: 0;
|
|
67
67
|
background: color-mix(in srgb, var(--bt-col-account) 16%, transparent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--bt-col-account) 30%, transparent);
|
|
68
68
|
color: color-mix(in srgb, var(--bt-col-account) 55%, #ffffff);
|
|
69
69
|
}
|
|
@@ -75,15 +75,15 @@
|
|
|
75
75
|
.bt-col-titles span { color: var(--bt-muted); font: 450 11.5px/1.1 var(--bt-ui); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
76
76
|
.bt-col-fill { flex: 1; min-width: 4px; }
|
|
77
77
|
.bt-col-unread {
|
|
78
|
-
flex: none; min-width: 22px; height: 20px; padding: 0 7px; box-sizing: border-box; border: 0; border-radius: 999px; cursor: pointer;
|
|
78
|
+
flex: none; min-width: 22px; height: 20px; padding: 0 7px; box-sizing: border-box; border: 0; border-radius: calc(999px * var(--bt-rs, 1)); cursor: pointer;
|
|
79
79
|
background: var(--bt-accent); color: #fff; font: 700 11px/20px var(--bt-mono); letter-spacing: -.02em;
|
|
80
80
|
box-shadow: 0 0 0 3px rgba(29, 155, 240, .16), 0 4px 12px -4px rgba(29, 155, 240, .8);
|
|
81
81
|
animation: bt-unread-in var(--bt-t3) var(--bt-ease-out);
|
|
82
82
|
}
|
|
83
83
|
.bt-col-unread:hover { filter: brightness(1.12); }
|
|
84
84
|
@keyframes bt-unread-in { from { transform: scale(.6); opacity: 0; } }
|
|
85
|
-
.bt-col-account { display: grid; place-items: center; flex: none; padding: 2px; border-radius: 999px; box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--bt-col-account) 70%, transparent); }
|
|
86
|
-
.bt-col-btn { width: 28px; height: 28px; border-radius: 8px; color: var(--bt-muted); }
|
|
85
|
+
.bt-col-account { display: grid; place-items: center; flex: none; padding: 2px; border-radius: calc(999px * var(--bt-rs, 1)); box-shadow: 0 0 0 1.5px color-mix(in srgb, var(--bt-col-account) 70%, transparent); }
|
|
86
|
+
.bt-col-btn { width: 28px; height: 28px; border-radius: calc(8px * var(--bt-rs, 1)); color: var(--bt-muted); }
|
|
87
87
|
.bt-col-btn .bt-glyph { width: 15px; height: 15px; }
|
|
88
88
|
.bt-col-btn:hover { color: var(--bt-text); }
|
|
89
89
|
.bt-col-btn.is-active { color: var(--bt-accent-ink); background: var(--bt-accent-soft); }
|
|
@@ -99,8 +99,8 @@
|
|
|
99
99
|
.bt-compose { right: 0; animation: bt-fade-in var(--bt-t3) var(--bt-ease-out) both; box-shadow: inset 0 0 0 1px rgba(29, 155, 240, .28), -18px 0 40px -24px rgba(0, 0, 0, .8); }
|
|
100
100
|
.bt-compose > .bt-compose-head { animation: bt-slide-in var(--bt-t3) var(--bt-ease-out) both; }
|
|
101
101
|
.bt-compose-glyph { --bt-col-account: var(--bt-accent); }
|
|
102
|
-
.bt-compose-accounts { display: flex; gap: 2px; padding: 2px; border-radius: 999px; background: var(--bt-field); }
|
|
103
|
-
.bt-compose-accounts button { display: grid; place-items: center; padding: 2px; border: 0; border-radius: 999px; background: transparent; cursor: pointer; opacity: .55; transition: opacity var(--bt-t1) var(--bt-ease); }
|
|
102
|
+
.bt-compose-accounts { display: flex; gap: 2px; padding: 2px; border-radius: calc(999px * var(--bt-rs, 1)); background: var(--bt-field); }
|
|
103
|
+
.bt-compose-accounts button { display: grid; place-items: center; padding: 2px; border: 0; border-radius: calc(999px * var(--bt-rs, 1)); background: transparent; cursor: pointer; opacity: .55; transition: opacity var(--bt-t1) var(--bt-ease); }
|
|
104
104
|
.bt-compose-accounts button:hover { opacity: .9; }
|
|
105
105
|
.bt-compose-accounts button.is-on { opacity: 1; box-shadow: 0 0 0 1.5px var(--bt-accent); }
|
|
106
106
|
|
|
@@ -111,18 +111,18 @@
|
|
|
111
111
|
.bt-deck-pop-head strong { font: 650 13px/1 var(--bt-ui); }
|
|
112
112
|
.bt-deck-pop-head span { margin-inline-start: auto; color: var(--bt-faint); font: 500 11.5px/1 var(--bt-ui); max-width: 55%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
113
113
|
.bt-deck-terms { display: flex; flex-direction: column; gap: 8px; padding: 0 4px 6px; }
|
|
114
|
-
.bt-deck-input { height: 32px; padding: 0 10px; border: 0; border-radius: 8px; background: var(--bt-field); box-shadow: inset 0 0 0 1px var(--bt-line); color: var(--bt-text); font: 450 12.5px/1 var(--bt-mono); outline: none; user-select: text; }
|
|
114
|
+
.bt-deck-input { height: 32px; padding: 0 10px; border: 0; border-radius: calc(8px * var(--bt-rs, 1)); background: var(--bt-field); box-shadow: inset 0 0 0 1px var(--bt-line); color: var(--bt-text); font: 450 12.5px/1 var(--bt-mono); outline: none; user-select: text; }
|
|
115
115
|
.bt-deck-input:focus { box-shadow: var(--bt-ring); }
|
|
116
116
|
.bt-deck-chips { display: flex; flex-wrap: wrap; gap: 5px; max-height: 120px; overflow-y: auto; scrollbar-width: thin; }
|
|
117
|
-
.bt-deck-chip { display: inline-flex; align-items: center; gap: 2px; max-width: 100%; height: 24px; padding-block: 0; padding-inline: 9px 2px; border-radius: 999px; background: rgba(238, 240, 247, .06); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .07); font: 500 12px/1 var(--bt-ui); }
|
|
117
|
+
.bt-deck-chip { display: inline-flex; align-items: center; gap: 2px; max-width: 100%; height: 24px; padding-block: 0; padding-inline: 9px 2px; border-radius: calc(999px * var(--bt-rs, 1)); background: rgba(238, 240, 247, .06); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .07); font: 500 12px/1 var(--bt-ui); }
|
|
118
118
|
.bt-deck-chip > span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
119
119
|
.bt-deck-chip.is-regex { font-family: var(--bt-mono); color: #d7c6ff; background: rgba(168, 85, 247, .12); box-shadow: inset 0 0 0 1px rgba(168, 85, 247, .25); }
|
|
120
|
-
.bt-menu .bt-deck-chip button { width: 20px; height: 20px; padding: 0; justify-content: center; border-radius: 999px; }
|
|
120
|
+
.bt-menu .bt-deck-chip button { width: 20px; height: 20px; padding: 0; justify-content: center; border-radius: calc(999px * var(--bt-rs, 1)); }
|
|
121
121
|
.bt-deck-chip .bt-glyph { width: 11px; height: 11px; }
|
|
122
|
-
.bt-deck-check { display: flex; align-items: flex-start; gap: 10px; padding: 7px 8px; border-radius: 8px; cursor: pointer; }
|
|
122
|
+
.bt-deck-check { display: flex; align-items: flex-start; gap: 10px; padding: 7px 8px; border-radius: calc(8px * var(--bt-rs, 1)); cursor: pointer; }
|
|
123
123
|
.bt-deck-check:hover { background: var(--bt-hover); }
|
|
124
124
|
.bt-deck-check input { position: absolute; opacity: 0; pointer-events: none; }
|
|
125
|
-
.bt-deck-check-box { display: grid; place-items: center; flex: none; width: 16px; height: 16px; margin-top: 1px; border-radius: 5px; box-shadow: inset 0 0 0 1.5px var(--bt-line-strong); color: transparent; transition: background-color var(--bt-t1) var(--bt-ease); }
|
|
125
|
+
.bt-deck-check-box { display: grid; place-items: center; flex: none; width: 16px; height: 16px; margin-top: 1px; border-radius: calc(5px * var(--bt-rs, 1)); box-shadow: inset 0 0 0 1.5px var(--bt-line-strong); color: transparent; transition: background-color var(--bt-t1) var(--bt-ease); }
|
|
126
126
|
.bt-deck-check-box .bt-glyph { width: 11px; height: 11px; stroke-width: 2.4; }
|
|
127
127
|
.bt-deck-check input:checked + .bt-deck-check-box { background: var(--bt-accent); box-shadow: none; color: #fff; }
|
|
128
128
|
.bt-deck-check input:focus-visible + .bt-deck-check-box { box-shadow: var(--bt-ring); }
|
|
@@ -131,12 +131,12 @@
|
|
|
131
131
|
.bt-deck-check-text small { color: var(--bt-muted); font: 400 11.5px/1.2 var(--bt-ui); }
|
|
132
132
|
.bt-deck-widths { display: flex; align-items: center; gap: 2px; padding-block: 4px; padding-inline: 10px 6px; color: var(--bt-muted); font: 500 12px/1 var(--bt-ui); }
|
|
133
133
|
.bt-deck-widths > span { margin-inline-end: auto; }
|
|
134
|
-
.bt-menu .bt-deck-widths button { height: 24px; padding: 0 6px; border-radius: 6px; color: var(--bt-muted); font: 500 11px/1 var(--bt-mono); }
|
|
134
|
+
.bt-menu .bt-deck-widths button { height: 24px; padding: 0 6px; border-radius: calc(6px * var(--bt-rs, 1)); color: var(--bt-muted); font: 500 11px/1 var(--bt-mono); }
|
|
135
135
|
.bt-menu .bt-deck-widths button.is-on { background: var(--bt-accent-soft); color: var(--bt-accent-ink); }
|
|
136
136
|
|
|
137
137
|
/* Buttons ----------------------------------------------------------------------------------- */
|
|
138
138
|
.bt-deck-primary, .bt-deck-secondary {
|
|
139
|
-
display: inline-flex; align-items: center; justify-content: center; gap: 7px; height: 34px; padding: 0 14px; border: 0; border-radius: 9px; cursor: pointer;
|
|
139
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 7px; height: 34px; padding: 0 14px; border: 0; border-radius: calc(9px * var(--bt-rs, 1)); cursor: pointer;
|
|
140
140
|
font: 600 13px/1 var(--bt-ui); transition: filter var(--bt-t1) var(--bt-ease), background-color var(--bt-t1) var(--bt-ease);
|
|
141
141
|
}
|
|
142
142
|
.bt-deck-primary { background: var(--bt-accent); color: #fff; box-shadow: 0 6px 18px -8px rgba(29, 155, 240, .9), inset 0 1px 0 rgba(255, 255, 255, .18); }
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
.bt-deck-empty-keys { display: flex; align-items: center; gap: 6px 18px; flex-wrap: wrap; justify-content: center; margin-top: 10px !important; font-size: 12px !important; color: var(--bt-faint) !important; }
|
|
156
156
|
.bt-deck-empty-keys > span { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
|
|
157
157
|
.bt-deck-empty-art { display: flex; gap: 6px; height: 64px; align-items: flex-end; }
|
|
158
|
-
.bt-deck-empty-art span { width: 30px; border-radius: 7px 7px 2px 2px; background: linear-gradient(180deg, rgba(79, 107, 255, .5), rgba(34, 211, 238, .12)); box-shadow: inset 0 0 0 1px rgba(159, 211, 255, .2); animation: bt-rise var(--bt-t3) var(--bt-ease-out) both; }
|
|
158
|
+
.bt-deck-empty-art span { width: 30px; border-radius: calc(7px * var(--bt-rs, 1)) calc(7px * var(--bt-rs, 1)) calc(2px * var(--bt-rs, 1)) calc(2px * var(--bt-rs, 1)); background: linear-gradient(180deg, rgba(79, 107, 255, .5), rgba(34, 211, 238, .12)); box-shadow: inset 0 0 0 1px rgba(159, 211, 255, .2); animation: bt-rise var(--bt-t3) var(--bt-ease-out) both; }
|
|
159
159
|
.bt-deck-empty-art span:nth-child(1) { height: 64px; }
|
|
160
160
|
.bt-deck-empty-art span:nth-child(2) { height: 52px; }
|
|
161
161
|
.bt-deck-empty-art span:nth-child(3) { height: 58px; }
|
|
@@ -169,7 +169,7 @@
|
|
|
169
169
|
.bt-addcol-head .bt-icon { margin-inline-start: auto; align-self: center; }
|
|
170
170
|
.bt-addcol-types { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; padding: 10px 16px 6px; }
|
|
171
171
|
.bt-addcol-type {
|
|
172
|
-
display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-height: 96px; padding: 12px; border: 0; border-radius: 11px; cursor: pointer; text-align: start;
|
|
172
|
+
display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-height: 96px; padding: 12px; border: 0; border-radius: calc(11px * var(--bt-rs, 1)); cursor: pointer; text-align: start;
|
|
173
173
|
background: rgba(238, 240, 247, .035); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .06); color: var(--bt-text-2);
|
|
174
174
|
transition: background-color var(--bt-t1) var(--bt-ease), box-shadow var(--bt-t1) var(--bt-ease), transform var(--bt-t2) var(--bt-ease-out);
|
|
175
175
|
}
|
|
@@ -178,24 +178,24 @@
|
|
|
178
178
|
.bt-addcol-type.is-on { background: var(--bt-accent-soft); box-shadow: inset 0 0 0 1.5px rgba(29, 155, 240, .6); color: var(--bt-text); }
|
|
179
179
|
.bt-addcol-type strong { font: 650 13.5px/1.1 var(--bt-ui); color: var(--bt-text); }
|
|
180
180
|
.bt-addcol-type small { color: var(--bt-muted); font: 400 11.5px/1.35 var(--bt-ui); }
|
|
181
|
-
.bt-addcol-icon { display: grid; place-items: center; width: 28px; height: 28px; border-radius: 8px; background: rgba(238, 240, 247, .06); color: var(--bt-muted); }
|
|
181
|
+
.bt-addcol-icon { display: grid; place-items: center; width: 28px; height: 28px; border-radius: calc(8px * var(--bt-rs, 1)); background: rgba(238, 240, 247, .06); color: var(--bt-muted); }
|
|
182
182
|
.bt-addcol-type.is-on .bt-addcol-icon { background: rgba(29, 155, 240, .22); color: #bfe0ff; }
|
|
183
183
|
.bt-addcol-icon .bt-glyph { width: 15px; height: 15px; }
|
|
184
184
|
.bt-addcol-value { display: flex; flex-direction: column; gap: 8px; padding: 10px 16px 4px; }
|
|
185
185
|
.bt-addcol-value label, .bt-addcol-label { color: var(--bt-faint); font: 600 10.5px/1 var(--bt-ui); letter-spacing: .08em; text-transform: uppercase; }
|
|
186
|
-
.bt-addcol-field { display: flex; align-items: center; gap: 10px; height: 42px; padding: 0 12px; border-radius: 10px; background: var(--bt-field); box-shadow: inset 0 0 0 1px var(--bt-line); }
|
|
186
|
+
.bt-addcol-field { display: flex; align-items: center; gap: 10px; height: 42px; padding: 0 12px; border-radius: calc(10px * var(--bt-rs, 1)); background: var(--bt-field); box-shadow: inset 0 0 0 1px var(--bt-line); }
|
|
187
187
|
.bt-addcol-field:focus-within { box-shadow: var(--bt-ring); }
|
|
188
188
|
.bt-addcol-field.is-bad { box-shadow: 0 0 0 1px rgba(229, 72, 77, .7); }
|
|
189
189
|
.bt-addcol-field .bt-glyph { color: var(--bt-muted); }
|
|
190
190
|
.bt-addcol-field input { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--bt-text); font: 500 14px/1 var(--bt-mono); outline: none; user-select: text; }
|
|
191
191
|
.bt-addcol-field input::placeholder { color: var(--bt-faint); }
|
|
192
192
|
.bt-addcol-chips { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
193
|
-
.bt-addcol-chips button { height: 26px; padding: 0 10px; border: 0; border-radius: 999px; background: rgba(238, 240, 247, .06); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .08); color: var(--bt-text-2); font: 500 12px/1 var(--bt-mono); cursor: pointer; }
|
|
193
|
+
.bt-addcol-chips button { height: 26px; padding: 0 10px; border: 0; border-radius: calc(999px * var(--bt-rs, 1)); background: rgba(238, 240, 247, .06); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .08); color: var(--bt-text-2); font: 500 12px/1 var(--bt-mono); cursor: pointer; }
|
|
194
194
|
.bt-addcol-chips button[aria-selected=true] { background: var(--bt-accent-soft); color: var(--bt-accent-ink); box-shadow: inset 0 0 0 1px rgba(29, 155, 240, .35); }
|
|
195
195
|
.bt-addcol-error { margin: 0; color: #ff9a9e; font-size: 12px; }
|
|
196
196
|
.bt-addcol-accounts { display: flex; flex-direction: column; gap: 8px; padding: 12px 16px 8px; }
|
|
197
197
|
.bt-addcol-accounts > div { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
198
|
-
.bt-addcol-account { display: inline-flex; align-items: center; gap: 8px; height: 34px; padding-block: 0; padding-inline: 6px 12px; border: 0; border-radius: 999px; cursor: pointer; background: rgba(238, 240, 247, .04); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .07); color: var(--bt-text-2); font: 550 12.5px/1 var(--bt-ui); }
|
|
198
|
+
.bt-addcol-account { display: inline-flex; align-items: center; gap: 8px; height: 34px; padding-block: 0; padding-inline: 6px 12px; border: 0; border-radius: calc(999px * var(--bt-rs, 1)); cursor: pointer; background: rgba(238, 240, 247, .04); box-shadow: inset 0 0 0 1px rgba(238, 240, 247, .07); color: var(--bt-text-2); font: 550 12.5px/1 var(--bt-ui); }
|
|
199
199
|
.bt-addcol-account:hover { background: rgba(238, 240, 247, .08); }
|
|
200
200
|
.bt-addcol-account.is-on { box-shadow: inset 0 0 0 1.5px var(--bt-col-account); color: var(--bt-text); background: color-mix(in srgb, var(--bt-col-account) 12%, transparent); }
|
|
201
201
|
.bt-addcol-account em { color: var(--bt-faint); font: italic 400 11px/1 var(--bt-ui); }
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Bevelled chrome: the app's own window drawn like the theme it shows when that theme is built from
|
|
3
|
+
* raised and sunken edges (a Windows 98 theme). chromeVars() sets `--wb-c-edges: bevel` and the edge
|
|
4
|
+
* colors; themeStore (and boot.js on the first frame) mirror it on `html[data-wb-edges=bevel]`.
|
|
5
|
+
*
|
|
6
|
+
* The edges are 98.css's (MIT, (c) Jordan Scales, https://github.com/jdan/98.css): a raised part has a
|
|
7
|
+
* highlight and a light line on its top and left and a shadow and a near-black line on its bottom and
|
|
8
|
+
* right; a sunken field has the same four lines the other way round. Here they come from the theme's
|
|
9
|
+
* own face color (--wb-c-face, --wb-c-bevel-*), so any palette can be bevelled.
|
|
10
|
+
*
|
|
11
|
+
* Square corners come from the radius scale (the theme's radius 0 makes --bt-rs 0); this file only
|
|
12
|
+
* draws faces, edges, the title bar and selection. Two levels: the window (title bar, caption
|
|
13
|
+
* buttons, menus, palette, scrollbars) follows the global theme on `html[data-wb-edges]`; each pane
|
|
14
|
+
* (its tabs, toolbar, address field, settings panel) follows its own theme on `.dv-groupview.wb-bevel`,
|
|
15
|
+
* which themeStore sets on every dock group whose theme (the pane's own, else the global one) is
|
|
16
|
+
* bevelled. So a Windows 98 pane is bevelled inside a flat window, and a flat pane stays flat inside
|
|
17
|
+
* a Windows 98 window.
|
|
18
|
+
*/
|
|
19
|
+
html[data-wb-edges=bevel], .dv-groupview.wb-bevel {
|
|
20
|
+
--bt-bv-face: var(--wb-c-face, #c0c0c0); --bt-bv-text: var(--wb-c-face-text, #000000);
|
|
21
|
+
--bt-bv-hi: var(--wb-c-bevel-hi, #ffffff); --bt-bv-lt: var(--wb-c-bevel-lt, #dfdfdf); --bt-bv-sh: var(--wb-c-bevel-sh, #808080); --bt-bv-dk: var(--wb-c-bevel-dk, #0a0a0a);
|
|
22
|
+
--bt-bv-out: inset -1px -1px var(--bt-bv-dk), inset 1px 1px var(--bt-bv-hi), inset -2px -2px var(--bt-bv-sh), inset 2px 2px var(--bt-bv-lt);
|
|
23
|
+
--bt-bv-window: inset -1px -1px var(--bt-bv-dk), inset 1px 1px var(--bt-bv-lt), inset -2px -2px var(--bt-bv-sh), inset 2px 2px var(--bt-bv-hi);
|
|
24
|
+
--bt-bv-in: inset -1px -1px var(--bt-bv-hi), inset 1px 1px var(--bt-bv-sh), inset -2px -2px var(--bt-bv-lt), inset 2px 2px var(--bt-bv-dk);
|
|
25
|
+
--bt-bv-pressed: inset -1px -1px var(--bt-bv-hi), inset 1px 1px var(--bt-bv-dk), inset -2px -2px var(--bt-bv-lt), inset 2px 2px var(--bt-bv-sh);
|
|
26
|
+
--bt-bv-etched: inset -1px -1px var(--bt-bv-hi), inset 1px 1px var(--bt-bv-sh), inset -2px -2px var(--bt-bv-sh), inset 2px 2px var(--bt-bv-hi);
|
|
27
|
+
--bt-bv-title: linear-gradient(90deg, var(--wb-c-title-from, #000080), var(--wb-c-title-to, #1084d0));
|
|
28
|
+
--bt-bv-title-text: var(--wb-c-title-text, #ffffff);
|
|
29
|
+
--bt-bv-select: var(--wb-c-select, #000080); --bt-bv-select-text: var(--wb-c-select-text, #ffffff);
|
|
30
|
+
/* The shell's surfaces become the face; text fields stay the theme's background. */
|
|
31
|
+
--bt-ground: var(--bt-bv-face); --bt-chrome: var(--bt-bv-face); --bt-field: var(--wb-c-ground, #ffffff); --bt-raised: var(--bt-bv-face); --bt-raised-2: var(--bt-bv-face);
|
|
32
|
+
--bt-text: var(--bt-bv-text); --bt-text-2: var(--bt-bv-text);
|
|
33
|
+
--bt-hover: transparent; --bt-press: transparent; --bt-shadow-pop: var(--bt-bv-window);
|
|
34
|
+
--bt-ring: 0 0 0 1px var(--bt-bv-dk);
|
|
35
|
+
}
|
|
36
|
+
html[data-wb-edges=bevel] :where(.bt-shell, .bt-menu, .bt-palette, .bt-media, .btp) :focus-visible { outline: 1px dotted var(--bt-bv-text); outline-offset: -4px; }
|
|
37
|
+
|
|
38
|
+
/* ------------------------------------------------------------------------------------------------
|
|
39
|
+
* Title bar: the active window's gradient across the tab row; tabs are a tab control on its floor. */
|
|
40
|
+
html[data-wb-edges=bevel] .bt-shell { background: var(--bt-bv-title) top / 100% var(--bt-titlebar-h) no-repeat, var(--bt-bv-face); }
|
|
41
|
+
html[data-wb-edges=bevel] .bt-shell--empty .bt-titlebar { background: var(--bt-bv-title); }
|
|
42
|
+
.bt-shell .dv-groupview.wb-bevel.bt-group--in-titlebar > .dv-tabs-and-actions-container { background: transparent; }
|
|
43
|
+
.bt-shell .dv-groupview.wb-bevel .dv-tabs-and-actions-container { background: var(--bt-bv-face); }
|
|
44
|
+
.bt-shell .dv-groupview.wb-bevel .dv-tabs-container .dv-tab {
|
|
45
|
+
--bt-tab-bg: var(--bt-bv-face); --bt-tab-fg: var(--bt-bv-text);
|
|
46
|
+
height: 28px; margin: 8px 2px 0 0; box-shadow: inset -1px 0 var(--bt-bv-dk), inset 1px 1px var(--bt-bv-hi), inset -2px 0 var(--bt-bv-sh), inset 2px 2px var(--bt-bv-lt);
|
|
47
|
+
}
|
|
48
|
+
.bt-shell .dv-groupview.wb-bevel.bt-group--in-titlebar .dv-tabs-container .dv-tab { height: 30px; margin-top: 14px; }
|
|
49
|
+
.bt-shell .dv-groupview.wb-bevel .dv-tabs-container .dv-tab.dv-inactive-tab:hover { --bt-tab-bg: var(--bt-bv-face); --bt-tab-fg: var(--bt-bv-text); }
|
|
50
|
+
/* The selected tab stands 2px taller and runs into the toolbar under it, like a 98 tab control. */
|
|
51
|
+
.bt-shell .dv-groupview.wb-bevel .dv-tabs-container .dv-tab.dv-active-tab,
|
|
52
|
+
.bt-shell .dv-groupview.wb-bevel.dv-inactive-group .dv-tabs-container .dv-tab.dv-active-tab {
|
|
53
|
+
--bt-tab-bg: var(--bt-bv-face); --bt-tab-fg: var(--bt-bv-text); z-index: 1; font-weight: 700;
|
|
54
|
+
box-shadow: inset -1px 0 var(--bt-bv-dk), inset 1px 1px var(--bt-bv-hi), inset -2px 0 var(--bt-bv-sh), inset 2px 2px var(--bt-bv-lt);
|
|
55
|
+
}
|
|
56
|
+
.bt-shell .dv-groupview.wb-bevel.bt-group--in-titlebar .dv-tabs-container .dv-tab.dv-active-tab { height: 32px; margin-top: 12px; }
|
|
57
|
+
.bt-shell .dv-groupview.wb-bevel .dv-tabs-container .dv-tab.dv-active-tab::after { display: none; }
|
|
58
|
+
.bt-shell .dv-groupview.wb-bevel.dv-inactive-group .dv-tabs-container .dv-tab.dv-active-tab { font-weight: 400; }
|
|
59
|
+
.bt-shell .dv-groupview.wb-bevel .dv-tabs-container .dv-tab:has(.bt-tab--pinned) + .dv-tab:not(:has(.bt-tab--pinned))::before { background: var(--bt-bv-sh); }
|
|
60
|
+
.dv-groupview.wb-bevel .bt-tab-close { color: var(--bt-bv-text); }
|
|
61
|
+
.dv-groupview.wb-bevel .bt-tab-close:hover { background: transparent; box-shadow: var(--bt-bv-out); }
|
|
62
|
+
.dv-groupview.wb-bevel .bt-tab-close:active { box-shadow: var(--bt-bv-pressed); }
|
|
63
|
+
/* Things drawn straight on the title bar take its label color. */
|
|
64
|
+
html[data-wb-edges=bevel] .bt-group--in-titlebar .bt-group-actions .bt-icon,
|
|
65
|
+
html[data-wb-edges=bevel] .bt-shell .bt-group--in-titlebar .dv-tabs-overflow-dropdown-default { color: var(--bt-bv-title-text); }
|
|
66
|
+
html[data-wb-edges=bevel] .bt-group--in-titlebar .bt-group-actions .bt-icon:hover { color: var(--bt-bv-text); background: var(--bt-bv-face); box-shadow: var(--bt-bv-out); }
|
|
67
|
+
/* Caption buttons: three small raised buttons, the close one apart. */
|
|
68
|
+
html[data-wb-edges=bevel] .bt-captions { align-items: center; gap: 2px; padding-inline-end: 6px; }
|
|
69
|
+
html[data-wb-edges=bevel] .bt-caption { width: 22px; height: 20px; color: var(--bt-bv-text); background: var(--bt-bv-face); box-shadow: var(--bt-bv-out); }
|
|
70
|
+
html[data-wb-edges=bevel] .bt-caption:hover { background: var(--bt-bv-face); color: var(--bt-bv-text); }
|
|
71
|
+
html[data-wb-edges=bevel] .bt-caption:active { box-shadow: var(--bt-bv-pressed); }
|
|
72
|
+
html[data-wb-edges=bevel] .bt-caption--close { margin-inline-start: 2px; }
|
|
73
|
+
html[data-wb-edges=bevel] .bt-caption--close:hover, html[data-wb-edges=bevel] .bt-caption--close:active { background: var(--bt-bv-face); color: var(--bt-bv-text); }
|
|
74
|
+
html[data-wb-edges=bevel] .bt-shell .bt-caption svg { width: 8px; height: 8px; stroke-width: 2; }
|
|
75
|
+
/* Titlebar buttons (account switcher, update chip, workspaces) are raised buttons on the title bar. */
|
|
76
|
+
html[data-wb-edges=bevel] :is(.bt-profile-switcher, .bt-update-chip, .bt-ws-button) { border: 0; background: var(--bt-bv-face); color: var(--bt-bv-text); box-shadow: var(--bt-bv-out); }
|
|
77
|
+
html[data-wb-edges=bevel] :is(.bt-profile-switcher, .bt-update-chip, .bt-ws-button):hover { background: var(--bt-bv-face); }
|
|
78
|
+
html[data-wb-edges=bevel] :is(.bt-profile-switcher[aria-expanded=true], .bt-update-chip:active, .bt-ws-button[aria-expanded=true]) { box-shadow: var(--bt-bv-pressed); }
|
|
79
|
+
|
|
80
|
+
/* ------------------------------------------------------------------------------------------------
|
|
81
|
+
* Toolbar: flat buttons that rise under the pointer, a sunken address field, the wB button raised. */
|
|
82
|
+
.dv-groupview.wb-bevel .bt-addressbar { background: var(--bt-bv-face); border-bottom: 0; box-shadow: inset 0 -1px var(--bt-bv-sh), inset 0 -2px var(--bt-bv-hi); }
|
|
83
|
+
.dv-groupview.wb-bevel .bt-icon { color: var(--bt-bv-text); }
|
|
84
|
+
.dv-groupview.wb-bevel .bt-icon:hover:not(:disabled) { background: transparent; box-shadow: inset -1px -1px var(--bt-bv-sh), inset 1px 1px var(--bt-bv-hi); }
|
|
85
|
+
.dv-groupview.wb-bevel .bt-icon:active:not(:disabled) { box-shadow: inset -1px -1px var(--bt-bv-hi), inset 1px 1px var(--bt-bv-sh); }
|
|
86
|
+
.dv-groupview.wb-bevel .bt-icon:disabled { color: var(--bt-bv-sh); }
|
|
87
|
+
.dv-groupview.wb-bevel .bt-omni { border: 0; background: var(--bt-field); box-shadow: var(--bt-bv-in); padding-inline: 6px; }
|
|
88
|
+
.dv-groupview.wb-bevel .bt-omni:hover { box-shadow: var(--bt-bv-in); }
|
|
89
|
+
.dv-groupview.wb-bevel .bt-omni:focus-within, .dv-groupview.wb-bevel .bt-omni:focus-visible { box-shadow: var(--bt-bv-in); }
|
|
90
|
+
.dv-groupview.wb-bevel .bt-omni-progress { background: var(--bt-bv-select); }
|
|
91
|
+
.dv-groupview.wb-bevel .bt-brand-button { border: 0; background: var(--bt-bv-face); box-shadow: var(--bt-bv-out); }
|
|
92
|
+
.dv-groupview.wb-bevel .bt-brand-button:hover { border: 0; background: var(--bt-bv-face); }
|
|
93
|
+
.dv-groupview.wb-bevel .bt-brand-button:active, .dv-groupview.wb-bevel .bt-pane-menu[aria-expanded=true] { background: var(--bt-bv-face); box-shadow: var(--bt-bv-pressed); }
|
|
94
|
+
.dv-groupview.wb-bevel .bt-brand-button:hover .bt-wb { transform: none; }
|
|
95
|
+
|
|
96
|
+
/* ------------------------------------------------------------------------------------------------
|
|
97
|
+
* Menus, the palette, popovers: a window edge on the face; the row under the pointer is selected. */
|
|
98
|
+
html[data-wb-edges=bevel] :is(.bt-menu, .bt-palette) { border: 0; background: var(--bt-bv-face); box-shadow: var(--bt-bv-window); color: var(--bt-bv-text); }
|
|
99
|
+
html[data-wb-edges=bevel] .bt-menu { padding: 3px; }
|
|
100
|
+
html[data-wb-edges=bevel] .bt-menu button:hover:not(:disabled), html[data-wb-edges=bevel] .bt-menu button:focus-visible,
|
|
101
|
+
html[data-wb-edges=bevel] .bt-menu button[aria-expanded=true] { background: var(--bt-bv-select); color: var(--bt-bv-select-text); outline: 0; }
|
|
102
|
+
html[data-wb-edges=bevel] .bt-menu button:hover:not(:disabled) :is(.bt-glyph, .bt-menu-keys, small, svg),
|
|
103
|
+
html[data-wb-edges=bevel] .bt-menu button:focus-visible :is(.bt-glyph, .bt-menu-keys, small, svg),
|
|
104
|
+
html[data-wb-edges=bevel] .bt-menu button[aria-expanded=true] :is(.bt-glyph, .bt-menu-keys, small, svg) { color: var(--bt-bv-select-text); }
|
|
105
|
+
/* Every line of a selected row (a title and its subline, as in the workspaces and accounts menus) takes the selection's ink. */
|
|
106
|
+
html[data-wb-edges=bevel] .bt-menu button:is(:hover:not(:disabled), :focus-visible, [aria-expanded=true]) * { color: var(--bt-bv-select-text) !important; }
|
|
107
|
+
html[data-wb-edges=bevel] .bt-menu button > .bt-glyph { color: var(--bt-bv-text); }
|
|
108
|
+
html[data-wb-edges=bevel] .bt-menu button:disabled { color: var(--bt-bv-sh); text-shadow: 1px 1px var(--bt-bv-hi); }
|
|
109
|
+
html[data-wb-edges=bevel] .bt-menu-keys { color: var(--bt-bv-text); }
|
|
110
|
+
html[data-wb-edges=bevel] .bt-menu hr { border-top: 1px solid var(--bt-bv-sh); border-bottom: 1px solid var(--bt-bv-hi); margin: 3px 2px; }
|
|
111
|
+
html[data-wb-edges=bevel] .bt-palette::before { display: none; }
|
|
112
|
+
html[data-wb-edges=bevel] .bt-palette-field { border-bottom: 0; box-shadow: inset 0 -1px var(--bt-bv-sh), inset 0 -2px var(--bt-bv-hi); }
|
|
113
|
+
html[data-wb-edges=bevel] .bt-palette-backdrop { background: transparent; }
|
|
114
|
+
html[data-wb-edges=bevel] .bt-kbd { background: var(--bt-bv-face); box-shadow: var(--bt-bv-out); color: var(--bt-bv-text); }
|
|
115
|
+
/* Text fields and steppers inside menus are sunken. */
|
|
116
|
+
html[data-wb-edges=bevel] .bt-menu :is(input[type=text], input:not([type]), .bt-app-zoom-step, .bt-deck-input) { border: 0; background: var(--bt-field); box-shadow: var(--bt-bv-in); }
|
|
117
|
+
|
|
118
|
+
/* ------------------------------------------------------------------------------------------------
|
|
119
|
+
* The settings panel: a dialog face, etched group boxes, raised buttons, sunken fields, a selected
|
|
120
|
+
* section in the title bar's color. */
|
|
121
|
+
.dv-groupview.wb-bevel .btp {
|
|
122
|
+
--c-ground: var(--bt-bv-face); --c-chrome: var(--bt-bv-face); --c-card: var(--bt-bv-face); --c-raise: var(--bt-bv-face); --c-popover: var(--bt-bv-face);
|
|
123
|
+
--c-text: var(--bt-bv-text); --c-line: var(--bt-bv-sh); --c-line-soft: var(--bt-bv-sh); --c-line-strong: var(--bt-bv-dk);
|
|
124
|
+
--c-accent: var(--bt-bv-select); --c-accent-ink: var(--bt-bv-select-text); --c-brush: var(--bt-bv-title);
|
|
125
|
+
letter-spacing: 0; -webkit-font-smoothing: auto;
|
|
126
|
+
}
|
|
127
|
+
.dv-groupview.wb-bevel .btp-head { background: var(--bt-bv-face); }
|
|
128
|
+
.dv-groupview.wb-bevel .btp-head::after { opacity: 1; height: 2px; background: none; box-shadow: inset 0 1px var(--bt-bv-sh), inset 0 -1px var(--bt-bv-hi); }
|
|
129
|
+
.dv-groupview.wb-bevel .btp-nav { border-bottom: 0; box-shadow: inset 0 -1px var(--bt-bv-sh), inset 0 -2px var(--bt-bv-hi); }
|
|
130
|
+
.dv-groupview.wb-bevel .btp-nav button { color: var(--bt-bv-text); }
|
|
131
|
+
.dv-groupview.wb-bevel .btp-nav button:hover { background: transparent; box-shadow: inset -1px -1px var(--bt-bv-sh), inset 1px 1px var(--bt-bv-hi); }
|
|
132
|
+
.dv-groupview.wb-bevel .btp-nav button.is-on { background: var(--bt-bv-select); color: var(--bt-bv-select-text); box-shadow: none; }
|
|
133
|
+
.dv-groupview.wb-bevel .btp-nav button.is-on svg { color: var(--bt-bv-select-text); }
|
|
134
|
+
.dv-groupview.wb-bevel .btp .bt-card { border: 0; box-shadow: var(--bt-bv-etched); padding: 2px; }
|
|
135
|
+
.dv-groupview.wb-bevel .btp :is(.bt-btn, .bt-select-button, .bt-stepper button, .bt-inputrow button) { border: 0; background: var(--bt-bv-face); color: var(--bt-bv-text); box-shadow: var(--bt-bv-out); }
|
|
136
|
+
.dv-groupview.wb-bevel .btp :is(.bt-btn, .bt-select-button, .bt-stepper button, .bt-inputrow button):hover:not(:disabled) { border: 0; background: var(--bt-bv-face); }
|
|
137
|
+
.dv-groupview.wb-bevel .btp :is(.bt-btn, .bt-stepper button, .bt-inputrow button):active:not(:disabled) { transform: none; box-shadow: var(--bt-bv-pressed); }
|
|
138
|
+
/* The default button carries the extra dark frame of a 98 dialog's default button. */
|
|
139
|
+
.dv-groupview.wb-bevel .btp .bt-btn.is-primary { box-shadow: inset 0 0 0 1px var(--bt-bv-dk), inset -2px -2px var(--bt-bv-dk), inset 2px 2px var(--bt-bv-hi), inset -3px -3px var(--bt-bv-sh), inset 3px 3px var(--bt-bv-lt); }
|
|
140
|
+
.dv-groupview.wb-bevel .btp .bt-btn.is-ghost { box-shadow: none; }
|
|
141
|
+
.dv-groupview.wb-bevel .btp .bt-btn.is-ghost:hover:not(:disabled) { box-shadow: var(--bt-bv-out); }
|
|
142
|
+
.dv-groupview.wb-bevel .btp .bt-btn:disabled { opacity: 1; color: var(--bt-bv-sh); text-shadow: 1px 1px var(--bt-bv-hi); }
|
|
143
|
+
.dv-groupview.wb-bevel .btp .bt-btn.is-danger { background: var(--bt-bv-face); color: var(--c-danger); }
|
|
144
|
+
.dv-groupview.wb-bevel .btp :is(.bt-input, .btp-input, .bt-inputrow, .bt-search, .bt-hex, .bt-code, .wb-builder-name) { border: 0; background: var(--wb-c-ground, #ffffff); box-shadow: var(--bt-bv-in); }
|
|
145
|
+
.dv-groupview.wb-bevel .btp :is(.bt-input, .btp-input, .bt-inputrow, .bt-search):is(:focus, :focus-within) { box-shadow: var(--bt-bv-in); }
|
|
146
|
+
.dv-groupview.wb-bevel .btp .bt-seg { border: 0; background: var(--bt-bv-face); box-shadow: var(--bt-bv-in); }
|
|
147
|
+
.dv-groupview.wb-bevel .btp .bt-seg-thumb { background: var(--bt-bv-face); box-shadow: var(--bt-bv-out); }
|
|
148
|
+
.dv-groupview.wb-bevel .btp .bt-toggle { box-shadow: var(--bt-bv-in); }
|
|
149
|
+
.dv-groupview.wb-bevel .btp .bt-toggle-knob { box-shadow: var(--bt-bv-out); background: var(--bt-bv-face); }
|
|
150
|
+
.dv-groupview.wb-bevel .btp :is(.bt-select-list, .bt-popover) { border: 0; background: var(--bt-bv-face); box-shadow: var(--bt-bv-window); }
|
|
151
|
+
.dv-groupview.wb-bevel .btp .bt-select-list li.is-active { background: var(--bt-bv-select); color: var(--bt-bv-select-text); }
|
|
152
|
+
|
|
153
|
+
/* Classic scrollbars: a dithered track, raised thumb and arrows. */
|
|
154
|
+
html[data-wb-edges=bevel] :is(.bt-shell, .bt-menu, .bt-palette, .btp) * { scrollbar-width: auto; scrollbar-color: auto; }
|
|
155
|
+
html[data-wb-edges=bevel] ::-webkit-scrollbar { width: 16px; height: 16px; }
|
|
156
|
+
html[data-wb-edges=bevel] ::-webkit-scrollbar-track { background: repeating-conic-gradient(var(--bt-bv-face) 0 25%, var(--bt-bv-hi) 0 50%) 0 0 / 2px 2px; }
|
|
157
|
+
html[data-wb-edges=bevel] ::-webkit-scrollbar-thumb { background: var(--bt-bv-face); box-shadow: var(--bt-bv-out); border-radius: 0; }
|
|
158
|
+
html[data-wb-edges=bevel] ::-webkit-scrollbar-button:single-button { display: block; width: 16px; height: 16px; background: var(--bt-bv-face); box-shadow: var(--bt-bv-out); }
|
|
159
|
+
html[data-wb-edges=bevel] ::-webkit-scrollbar-corner { background: var(--bt-bv-face); }
|
|
@@ -28,7 +28,7 @@ export { chromeVars, CHROME_VAR_NAMES, SHELL_UI_FONT, SHELL_MONO_FONT, type Chro
|
|
|
28
28
|
export { shell, setOverlay, scheduleSync, flushSync, isWeb, tabAction, setProfiles, type TabParams, type WebParams } from './state.ts';
|
|
29
29
|
export type { PaletteItem, PaletteAction, PaletteContext } from './paletteModel.ts';
|
|
30
30
|
export { Icon, Avatar, ICONS, type IconName } from './icons.tsx';
|
|
31
|
-
export { DEFAULT_MENU, MENU_BUILTINS, MENU_MESSAGES, menuWith, menuWithout, type BuiltinMenuItem, type MenuEntry, type MenuGroups, type MenuItemSpec, type MenuLanguages, type MenuModes, type ReportDetails, type ShellMenu, } from './menuModel.ts';
|
|
32
|
-
export { openAppMenu, type AppMenuRequest } from './AppMenu.tsx';
|
|
31
|
+
export { DEFAULT_MENU, MENU_BUILTINS, MENU_MESSAGES, menuWith, menuWithout, type AppMenuTrigger, type BuiltinMenuItem, type MenuEntry, type MenuGroups, type MenuItemSpec, type MenuLanguages, type MenuModes, type ReportDetails, type ShellMenu, } from './menuModel.ts';
|
|
32
|
+
export { menuTrigger, openAppMenu, PaneMenuButton, type AppMenuRequest } from './AppMenu.tsx';
|
|
33
33
|
export { createLanguage, resolveLocale, type Language, type LanguageOptions, type LanguagePreference } from './language.ts';
|
|
34
34
|
export { createAppI18n, type AppI18n, type AppI18nOptions, type AppLanguage } from './appI18n.ts';
|
|
@@ -37,7 +37,7 @@ export { chromeVars, CHROME_VAR_NAMES, SHELL_UI_FONT, SHELL_MONO_FONT } from "./
|
|
|
37
37
|
export { shell, setOverlay, scheduleSync, flushSync, isWeb, tabAction, setProfiles } from "./state.js";
|
|
38
38
|
export { Icon, Avatar, ICONS } from "./icons.js";
|
|
39
39
|
export { DEFAULT_MENU, MENU_BUILTINS, MENU_MESSAGES, menuWith, menuWithout, } from "./menuModel.js";
|
|
40
|
-
export { openAppMenu } from "./AppMenu.js";
|
|
40
|
+
export { menuTrigger, openAppMenu, PaneMenuButton } from "./AppMenu.js";
|
|
41
41
|
export { createLanguage, resolveLocale } from "./language.js";
|
|
42
42
|
export { createAppI18n } from "./appI18n.js";
|
|
43
43
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/index.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,kGAAkG;AAClG,+FAA+F;AAC/F,kGAAkG;AAClG,6FAA6F;AAC7F,EAAE;AACF,4GAA4G;AAC5G,uCAAuC;AAGvC,OAAO,EAAE,SAAS,EAAkB,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAkB,MAAM,WAAW,CAAC;AAC1E,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,YAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAkB,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAW/C;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAe,EAAE,OAAqB;IAChE,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,aAAa,CAAC,IAAI,CAAC,CAAC;IACpB,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,KAAK,CAAC,QAAQ,GAAG,mBAAmB,EAAE,CAAC;IACvC,UAAU,EAAE,CAAC;IACb,OAAO,KAAK,CAAC;AACf,CAAC;AAGD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAuF,MAAM,iBAAiB,CAAC;AACxI,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAoB,MAAM,kBAAkB,CAAC;AAClH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAkC,MAAM,YAAY,CAAC;AAEvI,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAiB,MAAM,YAAa,CAAC;AACjE,OAAO,EACL,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,GAElE,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAuB,MAAM,cAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/index.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,kGAAkG;AAClG,+FAA+F;AAC/F,kGAAkG;AAClG,6FAA6F;AAC7F,EAAE;AACF,4GAA4G;AAC5G,uCAAuC;AAGvC,OAAO,EAAE,SAAS,EAAkB,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,eAAe,EAAkB,MAAM,WAAW,CAAC;AAC1E,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,YAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAkB,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAW/C;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAe,EAAE,OAAqB;IAChE,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,aAAa,CAAC,IAAI,CAAC,CAAC;IACpB,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,KAAK,CAAC,QAAQ,GAAG,mBAAmB,EAAE,CAAC;IACvC,UAAU,EAAE,CAAC;IACb,OAAO,KAAK,CAAC;AACf,CAAC;AAGD,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAuF,MAAM,iBAAiB,CAAC;AACxI,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAoB,MAAM,kBAAkB,CAAC;AAClH,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAkC,MAAM,YAAY,CAAC;AAEvI,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAiB,MAAM,YAAa,CAAC;AACjE,OAAO,EACL,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,GAElE,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,cAAc,EAAuB,MAAM,cAAe,CAAC;AAC9F,OAAO,EAAE,cAAc,EAAE,aAAa,EAAgE,MAAM,eAAe,CAAC;AAC5H,OAAO,EAAE,aAAa,EAAuD,MAAM,cAAc,CAAC","sourcesContent":["// The wayBetter shell frame: `createShell(site, options)` gives an app the whole shell (tabs in the\n// titlebar row, splits, the smart address bar, the new-tab page, the command palette, the account\n// switcher, decks of site columns, workspaces, developer mode and sync chips, the media panel,\n// pane themes, overlays and the native layout sync). The app describes its site (`ShellSite`) and\n// passes its Tauri API and i18n instance; styles come with the components (`--wb-*` tokens).\n//\n// const Shell = createShell(site, { native: { invoke, listen, currentWindow: getCurrentWindow }, i18n });\n// createRoot(root).render(<Shell/>);\n\nimport type { ComponentType } from 'react';\nimport { setNative, type NativeApi } from './bridge.ts';\nimport { decks, defaultDeckSettings } from './deckStore.ts';\nimport { setShellI18n, setTextDefaults, type ShellI18n } from './i18n.ts';\nimport Shell, { setDevBuild } from './Shell.tsx';\nimport { configureSite, type ShellSite } from './site.ts';\nimport { probeLayer, shell } from './state.ts';\n\nexport type ShellOptions = {\n /** The app's Tauri API: `invoke` and `listen` from @tauri-apps/api, and `getCurrentWindow`. */\n native: NativeApi;\n /** The app's i18n instance (waybetter/i18n `createI18n`, the framework catalogs merged in). */\n i18n: ShellI18n;\n /** A development build (keeps the devtools shortcut). */\n dev?: boolean;\n};\n\n/**\n * Sets the site and the app's native API and language for every frame module, and returns the\n * shell's root component. Call once, before anything of the frame renders (the app's own panel\n * may render the frame's pieces, e.g. in a preview, without the shell).\n */\nexport function createShell(site: ShellSite, options: ShellOptions): ComponentType {\n setNative(options.native);\n setShellI18n(options.i18n);\n setTextDefaults({ site: site.name });\n configureSite(site);\n setDevBuild(!!options.dev);\n shell.homeUrl = site.homeUrl;\n decks.settings = defaultDeckSettings();\n probeLayer();\n return Shell;\n}\n\nexport type { ShellSite, DeckSite, PaletteSite, ColumnKind, ColumnFlag, DeckPreset, Completer, Suggestion } from './site.ts';\nexport { site, siteChanged } from './site.ts';\nexport type { NativeApi, Invoke, Listen, ShellWindow, MockHandler } from './bridge.ts';\nexport { invoke, listen, isNative, installPreviewMocks } from './bridge.ts';\nexport type { ShellI18n } from './i18n.ts';\nexport { setShellI18n } from './i18n.ts';\nexport { bootScript, BOOT_CACHE_KEY } from './boot.ts';\nexport { createThemeStore, type ThemeAdapter, type ThemeStore, type ThemeDoc, type InstalledFont, type Weights } from './themeStore.ts';\nexport { chromeVars, CHROME_VAR_NAMES, SHELL_UI_FONT, SHELL_MONO_FONT, type ChromeTheme } from './chromeTheme.ts';\nexport { shell, setOverlay, scheduleSync, flushSync, isWeb, tabAction, setProfiles, type TabParams, type WebParams } from './state.ts';\nexport type { PaletteItem, PaletteAction, PaletteContext } from './paletteModel.ts';\nexport { Icon, Avatar, ICONS, type IconName } from './icons.tsx';\nexport {\n DEFAULT_MENU, MENU_BUILTINS, MENU_MESSAGES, menuWith, menuWithout,\n type AppMenuTrigger, type BuiltinMenuItem, type MenuEntry, type MenuGroups, type MenuItemSpec, type MenuLanguages, type MenuModes, type ReportDetails, type ShellMenu,\n} from './menuModel.ts';\nexport { menuTrigger, openAppMenu, PaneMenuButton, type AppMenuRequest } from './AppMenu.tsx';\nexport { createLanguage, resolveLocale, type Language, type LanguageOptions, type LanguagePreference } from './language.ts';\nexport { createAppI18n, type AppI18n, type AppI18nOptions, type AppLanguage } from './appI18n.ts';\n"]}
|
|
@@ -23,6 +23,19 @@ export type TabInfo = {
|
|
|
23
23
|
url: string;
|
|
24
24
|
};
|
|
25
25
|
export declare const CLIP_MAX_LIMIT = 100;
|
|
26
|
+
/**
|
|
27
|
+
* The Media panel's key: Ctrl+Shift+G on Windows and Linux; Cmd+Shift+M on macOS, where Cmd+Shift+G
|
|
28
|
+
* is the system's Find Previous (the native Edit menu owns it).
|
|
29
|
+
*/
|
|
30
|
+
export declare function isMediaShortcut(event: {
|
|
31
|
+
key: string;
|
|
32
|
+
shiftKey: boolean;
|
|
33
|
+
ctrlKey: boolean;
|
|
34
|
+
metaKey: boolean;
|
|
35
|
+
altKey: boolean;
|
|
36
|
+
}, os: string): boolean;
|
|
37
|
+
/** The Media panel's key as shown in hints and lists. */
|
|
38
|
+
export declare const mediaShortcutLabel: (os: string) => string;
|
|
26
39
|
/** The tab an attachment goes to: the active tab if it can take one, else the most recent one that can. */
|
|
27
40
|
export declare function attachTarget(tabs: TabInfo[], activeId: string | undefined, canAttach: (url: string) => boolean, recent?: string[]): TabInfo | null;
|
|
28
41
|
/** Gallery folders shown as their last path segment (Windows or POSIX separators). */
|
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
// which pages have one).
|
|
5
5
|
import { formatNumber, t } from "./i18n.js";
|
|
6
6
|
export const CLIP_MAX_LIMIT = 100;
|
|
7
|
+
/**
|
|
8
|
+
* The Media panel's key: Ctrl+Shift+G on Windows and Linux; Cmd+Shift+M on macOS, where Cmd+Shift+G
|
|
9
|
+
* is the system's Find Previous (the native Edit menu owns it).
|
|
10
|
+
*/
|
|
11
|
+
export function isMediaShortcut(event, os) {
|
|
12
|
+
if (!event.shiftKey || event.altKey)
|
|
13
|
+
return false;
|
|
14
|
+
const key = event.key.toLowerCase();
|
|
15
|
+
if (os === 'macos')
|
|
16
|
+
return event.metaKey && !event.ctrlKey && key === 'm';
|
|
17
|
+
return (event.ctrlKey || event.metaKey) && key === 'g';
|
|
18
|
+
}
|
|
19
|
+
/** The Media panel's key as shown in hints and lists. */
|
|
20
|
+
export const mediaShortcutLabel = (os) => (os === 'macos' ? 'Cmd+Shift+M' : 'Ctrl+Shift+G');
|
|
7
21
|
/** The tab an attachment goes to: the active tab if it can take one, else the most recent one that can. */
|
|
8
22
|
export function attachTarget(tabs, activeId, canAttach, recent = []) {
|
|
9
23
|
const active = tabs.find(tab => tab.id === activeId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mediaModel.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/mediaModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure model for the Media side panel (gallery folders + clipboard history). No Tauri/DOM\n// imports, so it is unit-tested under node. The panel never posts: it only asks native code to\n// attach an image to, or insert text into, one site tab's composer (`site.media.canAttach` says\n// which pages have one).\n\nimport { formatNumber, t } from './i18n.ts';\n\nexport type GalleryImage = { path: string; name: string; folder: string; modifiedMs: number; size: number };\nexport type ClipItem = { id: string; kind: 'text' | 'image'; text?: string; file?: string; hash: string; at: number };\nexport type MediaSettings = { folders: string[]; clipboardEnabled: boolean; clipboardMax: number };\nexport type TabInfo = { id: string; url: string };\n\nexport const CLIP_MAX_LIMIT = 100;\n\n/** The tab an attachment goes to: the active tab if it can take one, else the most recent one that can. */\nexport function attachTarget(tabs: TabInfo[], activeId: string | undefined, canAttach: (url: string) => boolean, recent: string[] = []): TabInfo | null {\n const active = tabs.find(tab => tab.id === activeId);\n if (active && canAttach(active.url)) return active;\n for (const id of recent) {\n const tab = tabs.find(candidate => candidate.id === id);\n if (tab && canAttach(tab.url)) return tab;\n }\n return tabs.find(tab => canAttach(tab.url)) ?? null;\n}\n\n/** Gallery folders shown as their last path segment (Windows or POSIX separators). */\nexport function folderLabel(folder: string): string {\n const parts = folder.split(/[\\\\/]+/).filter(Boolean);\n return parts[parts.length - 1] ?? folder;\n}\n\nexport function clampClipMax(value: number): number {\n if (!Number.isFinite(value)) return 30;\n return Math.min(CLIP_MAX_LIMIT, Math.max(1, Math.round(value)));\n}\n\n/** Removing a folder is the only folder change the shell can make; adding goes through the native dialog. */\nexport function withoutFolder(settings: MediaSettings, folder: string): MediaSettings {\n return { ...settings, folders: settings.folders.filter(f => f !== folder) };\n}\n\nexport function clipPreview(item: ClipItem, max = 80): string {\n if (item.kind === 'image') return t('wb.media.image');\n const flat = (item.text ?? '').replace(/\\s+/g, ' ').trim();\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;\n}\n\nexport function relativeTime(ms: number, now = Date.now()): string {\n const seconds = Math.max(0, Math.round((now - ms) / 1000));\n if (seconds < 60) return t('wb.media.now');\n // Compact units in the active language (\"5m\", \"5 dk\", \"5分\").\n const unit = (value: number, name: 'minute' | 'hour' | 'day') => formatNumber(value, { style: 'unit', unit: name, unitDisplay: 'narrow' });\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return unit(minutes, 'minute');\n const hours = Math.round(minutes / 60);\n if (hours < 24) return unit(hours, 'hour');\n return unit(Math.round(hours / 24), 'day');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mediaModel.js","sourceRoot":"","sources":["../../../../../../shell/src/frame/mediaModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Pure model for the Media side panel (gallery folders + clipboard history). No Tauri/DOM\n// imports, so it is unit-tested under node. The panel never posts: it only asks native code to\n// attach an image to, or insert text into, one site tab's composer (`site.media.canAttach` says\n// which pages have one).\n\nimport { formatNumber, t } from './i18n.ts';\n\nexport type GalleryImage = { path: string; name: string; folder: string; modifiedMs: number; size: number };\nexport type ClipItem = { id: string; kind: 'text' | 'image'; text?: string; file?: string; hash: string; at: number };\nexport type MediaSettings = { folders: string[]; clipboardEnabled: boolean; clipboardMax: number };\nexport type TabInfo = { id: string; url: string };\n\nexport const CLIP_MAX_LIMIT = 100;\n\n/**\n * The Media panel's key: Ctrl+Shift+G on Windows and Linux; Cmd+Shift+M on macOS, where Cmd+Shift+G\n * is the system's Find Previous (the native Edit menu owns it).\n */\nexport function isMediaShortcut(event: { key: string; shiftKey: boolean; ctrlKey: boolean; metaKey: boolean; altKey: boolean }, os: string): boolean {\n if (!event.shiftKey || event.altKey) return false;\n const key = event.key.toLowerCase();\n if (os === 'macos') return event.metaKey && !event.ctrlKey && key === 'm';\n return (event.ctrlKey || event.metaKey) && key === 'g';\n}\n\n/** The Media panel's key as shown in hints and lists. */\nexport const mediaShortcutLabel = (os: string): string => (os === 'macos' ? 'Cmd+Shift+M' : 'Ctrl+Shift+G');\n\n/** The tab an attachment goes to: the active tab if it can take one, else the most recent one that can. */\nexport function attachTarget(tabs: TabInfo[], activeId: string | undefined, canAttach: (url: string) => boolean, recent: string[] = []): TabInfo | null {\n const active = tabs.find(tab => tab.id === activeId);\n if (active && canAttach(active.url)) return active;\n for (const id of recent) {\n const tab = tabs.find(candidate => candidate.id === id);\n if (tab && canAttach(tab.url)) return tab;\n }\n return tabs.find(tab => canAttach(tab.url)) ?? null;\n}\n\n/** Gallery folders shown as their last path segment (Windows or POSIX separators). */\nexport function folderLabel(folder: string): string {\n const parts = folder.split(/[\\\\/]+/).filter(Boolean);\n return parts[parts.length - 1] ?? folder;\n}\n\nexport function clampClipMax(value: number): number {\n if (!Number.isFinite(value)) return 30;\n return Math.min(CLIP_MAX_LIMIT, Math.max(1, Math.round(value)));\n}\n\n/** Removing a folder is the only folder change the shell can make; adding goes through the native dialog. */\nexport function withoutFolder(settings: MediaSettings, folder: string): MediaSettings {\n return { ...settings, folders: settings.folders.filter(f => f !== folder) };\n}\n\nexport function clipPreview(item: ClipItem, max = 80): string {\n if (item.kind === 'image') return t('wb.media.image');\n const flat = (item.text ?? '').replace(/\\s+/g, ' ').trim();\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat;\n}\n\nexport function relativeTime(ms: number, now = Date.now()): string {\n const seconds = Math.max(0, Math.round((now - ms) / 1000));\n if (seconds < 60) return t('wb.media.now');\n // Compact units in the active language (\"5m\", \"5 dk\", \"5分\").\n const unit = (value: number, name: 'minute' | 'hour' | 'day') => formatNumber(value, { style: 'unit', unit: name, unitDisplay: 'narrow' });\n const minutes = Math.round(seconds / 60);\n if (minutes < 60) return unit(minutes, 'minute');\n const hours = Math.round(minutes / 60);\n if (hours < 24) return unit(hours, 'hour');\n return unit(Math.round(hours / 24), 'day');\n}\n"]}
|