mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-24 11:01:54 +00:00
Update & format
This commit is contained in:
parent
97dc7b77f4
commit
a6f7e31bb9
29 changed files with 127 additions and 98 deletions
|
@ -20,7 +20,7 @@ function parse_accepted_toml(file: string): string[] {
|
|||
|
||||
function check_licenses(themes: ThemeConfig[]) {
|
||||
for (const theme of themes) {
|
||||
if (!theme.licenseFile) {
|
||||
if (!theme.license_file) {
|
||||
throw Error(`Theme ${theme.name} should have a LICENSE file`)
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ function check_licenses(themes: ThemeConfig[]) {
|
|||
function generate_license_file(themes: ThemeConfig[]) {
|
||||
check_licenses(themes)
|
||||
for (const theme of themes) {
|
||||
const license_text = fs.readFileSync(theme.licenseFile).toString()
|
||||
const license_text = fs.readFileSync(theme.license_file).toString()
|
||||
write_license(theme.name, license_text, theme.license_url)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,13 +3,11 @@ import { tmpdir } from "os"
|
|||
import * as path from "path"
|
||||
import app from "./style_tree/app"
|
||||
import { ColorScheme, create_color_scheme } from "./theme/color_scheme"
|
||||
import snakeCase from "./utils/snake_case"
|
||||
import { themes } from "./themes"
|
||||
|
||||
const assets_directory = `${__dirname}/../../assets`
|
||||
const temp_directory = fs.mkdtempSync(path.join(tmpdir(), "build-themes"))
|
||||
|
||||
// Clear existing themes
|
||||
function clear_themes(theme_directory: string) {
|
||||
if (!fs.existsSync(theme_directory)) {
|
||||
fs.mkdirSync(theme_directory, { recursive: true })
|
||||
|
@ -22,22 +20,24 @@ function clear_themes(theme_directory: string) {
|
|||
}
|
||||
}
|
||||
|
||||
function write_themes(color_schemes: ColorScheme[], output_directory: string) {
|
||||
function write_themes(themes: ColorScheme[], output_directory: string) {
|
||||
clear_themes(output_directory)
|
||||
for (const color_scheme of color_schemes) {
|
||||
const style_tree = snakeCase(app(color_scheme))
|
||||
for (const color_scheme of themes) {
|
||||
const style_tree = app(color_scheme)
|
||||
const style_tree_json = JSON.stringify(style_tree, null, 2)
|
||||
const temp_path = path.join(temp_directory, `${color_scheme.name}.json`)
|
||||
const out_path = path.join(output_directory, `${color_scheme.name}.json`)
|
||||
const out_path = path.join(
|
||||
output_directory,
|
||||
`${color_scheme.name}.json`
|
||||
)
|
||||
fs.writeFileSync(temp_path, style_tree_json)
|
||||
fs.renameSync(temp_path, out_path)
|
||||
console.log(`- ${out_path} created`)
|
||||
}
|
||||
}
|
||||
|
||||
const color_schemes: ColorScheme[] = themes.map((theme) =>
|
||||
const all_themes: ColorScheme[] = themes.map((theme) =>
|
||||
create_color_scheme(theme)
|
||||
)
|
||||
|
||||
// Write new themes to theme directory
|
||||
write_themes(color_schemes, `${assets_directory}/themes`)
|
||||
write_themes(all_themes, `${assets_directory}/themes`)
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as path from "path"
|
|||
import { ColorScheme, create_color_scheme } from "./common"
|
||||
import { themes } from "./themes"
|
||||
import { slugify } from "./utils/slugify"
|
||||
import { colorSchemeTokens as color_scheme_tokens } from "./theme/tokens/color_scheme"
|
||||
import { theme_tokens } from "./theme/tokens/color_scheme"
|
||||
|
||||
const TOKENS_DIRECTORY = path.join(__dirname, "..", "target", "tokens")
|
||||
const TOKENS_FILE = path.join(TOKENS_DIRECTORY, "$themes.json")
|
||||
|
@ -60,7 +60,7 @@ function write_tokens(themes: ColorScheme[], tokens_directory: string) {
|
|||
|
||||
for (const theme of themes) {
|
||||
const file_name = slugify(theme.name) + ".json"
|
||||
const tokens = color_scheme_tokens(theme)
|
||||
const tokens = theme_tokens(theme)
|
||||
const tokens_json = JSON.stringify(tokens, null, 2)
|
||||
const out_path = path.join(tokens_directory, file_name)
|
||||
fs.writeFileSync(out_path, tokens_json, { mode: 0o644 })
|
||||
|
|
|
@ -12,12 +12,10 @@ export const font_sizes = {
|
|||
xs: 12,
|
||||
sm: 14,
|
||||
md: 16,
|
||||
lg: 18
|
||||
lg: 18,
|
||||
}
|
||||
|
||||
export type FontWeight =
|
||||
| "normal"
|
||||
| "bold"
|
||||
export type FontWeight = "normal" | "bold"
|
||||
|
||||
export const font_weights: { [key: string]: FontWeight } = {
|
||||
normal: "normal",
|
||||
|
|
|
@ -11,9 +11,9 @@ export type Margin = {
|
|||
|
||||
interface IconButtonOptions {
|
||||
layer?:
|
||||
| ColorScheme["lowest"]
|
||||
| ColorScheme["middle"]
|
||||
| ColorScheme["highest"]
|
||||
| ColorScheme["lowest"]
|
||||
| ColorScheme["middle"]
|
||||
| ColorScheme["highest"]
|
||||
color?: keyof ColorScheme["lowest"]
|
||||
margin?: Partial<Margin>
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ import { Margin } from "./icon_button"
|
|||
|
||||
interface TextButtonOptions {
|
||||
layer?:
|
||||
| ColorScheme["lowest"]
|
||||
| ColorScheme["middle"]
|
||||
| ColorScheme["highest"]
|
||||
| ColorScheme["lowest"]
|
||||
| ColorScheme["middle"]
|
||||
| ColorScheme["highest"]
|
||||
color?: keyof ColorScheme["lowest"]
|
||||
margin?: Partial<Margin>
|
||||
text_properties?: TextProperties
|
||||
|
|
|
@ -181,7 +181,7 @@ export default function assistant(theme: ColorScheme): any {
|
|||
},
|
||||
},
|
||||
}),
|
||||
savedAt: {
|
||||
saved_at: {
|
||||
margin: { left: 8 },
|
||||
...text(theme.highest, "sans", "default", { size: "xs" }),
|
||||
},
|
||||
|
|
|
@ -6,7 +6,9 @@ import { toggleable } from "../element"
|
|||
export default function command_palette(theme: ColorScheme): any {
|
||||
const key = toggleable({
|
||||
base: {
|
||||
text: text(theme.highest, "mono", "variant", "default", { size: "xs" }),
|
||||
text: text(theme.highest, "mono", "variant", "default", {
|
||||
size: "xs",
|
||||
}),
|
||||
corner_radius: 2,
|
||||
background: background(theme.highest, "on"),
|
||||
padding: {
|
||||
|
@ -23,7 +25,9 @@ export default function command_palette(theme: ColorScheme): any {
|
|||
},
|
||||
state: {
|
||||
active: {
|
||||
text: text(theme.highest, "mono", "on", "default", { size: "xs" }),
|
||||
text: text(theme.highest, "mono", "on", "default", {
|
||||
size: "xs",
|
||||
}),
|
||||
background: with_opacity(background(theme.highest, "on"), 0.2),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
import {
|
||||
font_families,
|
||||
font_sizes,
|
||||
FontWeight,
|
||||
} from "../common"
|
||||
import { font_families, font_sizes, FontWeight } from "../common"
|
||||
import { Layer, Styles, StyleSets, Style } from "../theme/color_scheme"
|
||||
|
||||
function is_style_set(key: any): key is StyleSets {
|
||||
|
|
|
@ -17,7 +17,9 @@ export default function contact_finder(theme: ColorScheme): any {
|
|||
background: background(theme.middle, "on"),
|
||||
corner_radius: 6,
|
||||
text: text(theme.middle, "mono"),
|
||||
placeholder_text: text(theme.middle, "mono", "on", "disabled", { size: "xs" }),
|
||||
placeholder_text: text(theme.middle, "mono", "on", "disabled", {
|
||||
size: "xs",
|
||||
}),
|
||||
selection: theme.players[0],
|
||||
border: border(theme.middle),
|
||||
padding: {
|
||||
|
|
|
@ -29,7 +29,9 @@ export default function context_menu(theme: ColorScheme): any {
|
|||
state: {
|
||||
hovered: {
|
||||
background: background(theme.middle, "hovered"),
|
||||
label: text(theme.middle, "sans", "hovered", { size: "sm" }),
|
||||
label: text(theme.middle, "sans", "hovered", {
|
||||
size: "sm",
|
||||
}),
|
||||
keystroke: {
|
||||
...text(theme.middle, "sans", "hovered", {
|
||||
size: "sm",
|
||||
|
|
|
@ -2,7 +2,6 @@ import { ColorScheme } from "../theme/color_scheme"
|
|||
import { background, border, foreground, svg, text } from "./components"
|
||||
import { interactive } from "../element"
|
||||
export default function copilot(theme: ColorScheme): any {
|
||||
|
||||
const content_width = 264
|
||||
|
||||
const cta_button =
|
||||
|
@ -61,7 +60,10 @@ export default function copilot(theme: ColorScheme): any {
|
|||
modal: {
|
||||
title_text: {
|
||||
default: {
|
||||
...text(theme.middle, "sans", { size: "xs", weight: "bold" }),
|
||||
...text(theme.middle, "sans", {
|
||||
size: "xs",
|
||||
weight: "bold",
|
||||
}),
|
||||
},
|
||||
},
|
||||
titlebar: {
|
||||
|
@ -163,7 +165,10 @@ export default function copilot(theme: ColorScheme): any {
|
|||
},
|
||||
|
||||
hint: {
|
||||
...text(theme.middle, "sans", { size: "xs", color: "#838994" }),
|
||||
...text(theme.middle, "sans", {
|
||||
size: "xs",
|
||||
color: "#838994",
|
||||
}),
|
||||
margin: {
|
||||
top: 6,
|
||||
bottom: 2,
|
||||
|
@ -271,7 +276,10 @@ export default function copilot(theme: ColorScheme): any {
|
|||
},
|
||||
|
||||
hint: {
|
||||
...text(theme.middle, "sans", { size: "xs", color: "#838994" }),
|
||||
...text(theme.middle, "sans", {
|
||||
size: "xs",
|
||||
color: "#838994",
|
||||
}),
|
||||
margin: {
|
||||
top: 24,
|
||||
bottom: 4,
|
||||
|
|
|
@ -191,20 +191,12 @@ export default function editor(theme: ColorScheme): any {
|
|||
item: autocomplete_item,
|
||||
hovered_item: {
|
||||
...autocomplete_item,
|
||||
match_highlight: foreground(
|
||||
theme.middle,
|
||||
"accent",
|
||||
"hovered"
|
||||
),
|
||||
match_highlight: foreground(theme.middle, "accent", "hovered"),
|
||||
background: background(theme.middle, "hovered"),
|
||||
},
|
||||
selected_item: {
|
||||
...autocomplete_item,
|
||||
match_highlight: foreground(
|
||||
theme.middle,
|
||||
"accent",
|
||||
"active"
|
||||
),
|
||||
match_highlight: foreground(theme.middle, "accent", "active"),
|
||||
background: background(theme.middle, "active"),
|
||||
},
|
||||
},
|
||||
|
|
|
@ -34,7 +34,9 @@ export default function feedback(theme: ColorScheme): any {
|
|||
},
|
||||
}),
|
||||
button_margin: 8,
|
||||
info_text_default: text(theme.highest, "sans", "default", { size: "xs" }),
|
||||
info_text_default: text(theme.highest, "sans", "default", {
|
||||
size: "xs",
|
||||
}),
|
||||
link_text_default: text(theme.highest, "sans", "default", {
|
||||
size: "xs",
|
||||
underline: true,
|
||||
|
|
|
@ -39,7 +39,9 @@ export default function hover_popover(theme: ColorScheme): any {
|
|||
padding: { top: 4 },
|
||||
},
|
||||
prose: text(theme.middle, "sans", { size: "sm" }),
|
||||
diagnostic_source_highlight: { color: foreground(theme.middle, "accent") },
|
||||
diagnostic_source_highlight: {
|
||||
color: foreground(theme.middle, "accent"),
|
||||
},
|
||||
highlight: theme.ramps.neutral(0.5).alpha(0.2).hex(), // TODO: blend was used here. Replace with something better
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,10 @@ export default function incoming_call_notification(
|
|||
margin: { top: -3 },
|
||||
},
|
||||
worktree_roots: {
|
||||
...text(theme.middle, "sans", "variant", { size: "xs", weight: "bold" }),
|
||||
...text(theme.middle, "sans", "variant", {
|
||||
size: "xs",
|
||||
weight: "bold",
|
||||
}),
|
||||
margin: { top: -3 },
|
||||
},
|
||||
button_width: 96,
|
||||
|
|
|
@ -173,7 +173,9 @@ export default function project_panel(theme: ColorScheme): any {
|
|||
{
|
||||
default: {
|
||||
background: background(theme.middle, "active"),
|
||||
text: text(theme.middle, "mono", "disabled", { size: "sm" }),
|
||||
text: text(theme.middle, "mono", "disabled", {
|
||||
size: "sm",
|
||||
}),
|
||||
},
|
||||
}
|
||||
),
|
||||
|
|
|
@ -29,7 +29,10 @@ export default function project_shared_notification(
|
|||
margin: { top: -3 },
|
||||
},
|
||||
worktree_roots: {
|
||||
...text(theme.middle, "sans", "variant", { size: "xs", weight: "bold" }),
|
||||
...text(theme.middle, "sans", "variant", {
|
||||
size: "xs",
|
||||
weight: "bold",
|
||||
}),
|
||||
margin: { top: -3 },
|
||||
},
|
||||
button_width: 96,
|
||||
|
|
|
@ -33,7 +33,10 @@ export default function search(theme: ColorScheme): any {
|
|||
|
||||
return {
|
||||
// TODO: Add an activeMatchBackground on the rust side to differentiate between active and inactive
|
||||
match_background: with_opacity(foreground(theme.highest, "accent"), 0.4),
|
||||
match_background: with_opacity(
|
||||
foreground(theme.highest, "accent"),
|
||||
0.4
|
||||
),
|
||||
option_button: toggleable({
|
||||
base: interactive({
|
||||
base: {
|
||||
|
|
|
@ -2,9 +2,7 @@ import { ColorScheme } from "../theme/color_scheme"
|
|||
import { background, border, foreground, text } from "./components"
|
||||
import { interactive } from "../element"
|
||||
|
||||
export default function simple_message_notification(
|
||||
theme: ColorScheme
|
||||
): any {
|
||||
export default function simple_message_notification(theme: ColorScheme): any {
|
||||
const header_padding = 8
|
||||
|
||||
return {
|
||||
|
|
|
@ -43,7 +43,9 @@ export default function dropdown_menu(theme: ColorScheme): any {
|
|||
state: {
|
||||
hovered: {
|
||||
background: background(theme.middle, "hovered"),
|
||||
...text(theme.middle, "sans", "hovered", { size: "sm" }),
|
||||
...text(theme.middle, "sans", "hovered", {
|
||||
size: "sm",
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
|
|
@ -2,7 +2,6 @@ import { ColorScheme } from "../theme/color_scheme"
|
|||
import { foreground, text } from "./components"
|
||||
import { interactive } from "../element"
|
||||
|
||||
|
||||
export default function update_notification(theme: ColorScheme): any {
|
||||
const header_padding = 8
|
||||
|
||||
|
|
|
@ -32,7 +32,12 @@ export default function welcome(theme: ColorScheme): any {
|
|||
|
||||
return {
|
||||
page_width: 320,
|
||||
logo: svg(foreground(theme.highest, "default"), "icons/logo_96.svg", 64, 64),
|
||||
logo: svg(
|
||||
foreground(theme.highest, "default"),
|
||||
"icons/logo_96.svg",
|
||||
64,
|
||||
64
|
||||
),
|
||||
logo_subheading: {
|
||||
...text(theme.highest, "sans", "variant", { size: "md" }),
|
||||
margin: {
|
||||
|
@ -54,7 +59,10 @@ export default function welcome(theme: ColorScheme): any {
|
|||
},
|
||||
checkbox_group: {
|
||||
border: border(theme.highest, "variant"),
|
||||
background: with_opacity(background(theme.highest, "hovered"), 0.25),
|
||||
background: with_opacity(
|
||||
background(theme.highest, "hovered"),
|
||||
0.25
|
||||
),
|
||||
corner_radius: 4,
|
||||
padding: {
|
||||
left: 12,
|
||||
|
@ -77,11 +85,21 @@ export default function welcome(theme: ColorScheme): any {
|
|||
left: 7,
|
||||
right: 7,
|
||||
},
|
||||
...text(theme.highest, "sans", "default", interactive_text_size),
|
||||
...text(
|
||||
theme.highest,
|
||||
"sans",
|
||||
"default",
|
||||
interactive_text_size
|
||||
),
|
||||
},
|
||||
state: {
|
||||
hovered: {
|
||||
...text(theme.highest, "sans", "default", interactive_text_size),
|
||||
...text(
|
||||
theme.highest,
|
||||
"sans",
|
||||
"default",
|
||||
interactive_text_size
|
||||
),
|
||||
background: background(theme.highest, "hovered"),
|
||||
},
|
||||
},
|
||||
|
@ -106,7 +124,12 @@ export default function welcome(theme: ColorScheme): any {
|
|||
...text(theme.highest, "sans", interactive_text_size),
|
||||
// Also supports margin, container, border, etc.
|
||||
},
|
||||
icon: svg(foreground(theme.highest, "on"), "icons/check_12.svg", 12, 12),
|
||||
icon: svg(
|
||||
foreground(theme.highest, "on"),
|
||||
"icons/check_12.svg",
|
||||
12,
|
||||
12
|
||||
),
|
||||
default: {
|
||||
...checkbox_base,
|
||||
background: background(theme.highest, "default"),
|
||||
|
|
|
@ -140,18 +140,10 @@ export default function workspace(theme: ColorScheme): any {
|
|||
state: {
|
||||
hovered: {
|
||||
color: foreground(theme.highest, "on", "hovered"),
|
||||
background: background(
|
||||
theme.highest,
|
||||
"on",
|
||||
"hovered"
|
||||
),
|
||||
background: background(theme.highest, "on", "hovered"),
|
||||
},
|
||||
disabled: {
|
||||
color: foreground(
|
||||
theme.highest,
|
||||
"on",
|
||||
"disabled"
|
||||
),
|
||||
color: foreground(theme.highest, "on", "disabled"),
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
@ -170,11 +162,7 @@ export default function workspace(theme: ColorScheme): any {
|
|||
state: {
|
||||
hovered: {
|
||||
color: foreground(theme.highest, "on", "hovered"),
|
||||
background: background(
|
||||
theme.highest,
|
||||
"on",
|
||||
"hovered"
|
||||
),
|
||||
background: background(theme.highest, "on", "hovered"),
|
||||
},
|
||||
},
|
||||
}),
|
||||
|
@ -194,6 +182,9 @@ export default function workspace(theme: ColorScheme): any {
|
|||
width: 400,
|
||||
margin: { right: 10, bottom: 10 },
|
||||
},
|
||||
drop_target_overlay_color: with_opacity(foreground(theme.lowest, "variant"), 0.5),
|
||||
drop_target_overlay_color: with_opacity(
|
||||
foreground(theme.lowest, "variant"),
|
||||
0.5
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,7 +291,10 @@ function build_default_syntax(color_scheme: ColorScheme): Syntax {
|
|||
return default_syntax
|
||||
}
|
||||
|
||||
function merge_syntax(default_syntax: Syntax, color_scheme: ColorScheme): Syntax {
|
||||
function merge_syntax(
|
||||
default_syntax: Syntax,
|
||||
color_scheme: ColorScheme
|
||||
): Syntax {
|
||||
if (!color_scheme.syntax) {
|
||||
return default_syntax
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ import {
|
|||
SyntaxHighlightStyle,
|
||||
ThemeSyntax,
|
||||
} from "../color_scheme"
|
||||
import { LayerToken, layerToken } from "./layer"
|
||||
import { PlayersToken, playersToken } from "./players"
|
||||
import { colorToken } from "./token"
|
||||
import { LayerToken, layer_token } from "./layer"
|
||||
import { PlayersToken, players_token } from "./players"
|
||||
import { color_token } from "./token"
|
||||
import { Syntax } from "../syntax"
|
||||
import editor from "../../style_tree/editor"
|
||||
|
||||
|
@ -64,13 +64,11 @@ function syntax_highlight_style_color_tokens(
|
|||
if (!syntax[style_key] || typeof syntax[style_key] === "function")
|
||||
return acc
|
||||
const { color } = syntax[style_key] as Required<SyntaxHighlightStyle>
|
||||
return { ...acc, [style_key]: colorToken(style_key, color) }
|
||||
return { ...acc, [style_key]: color_token(style_key, color) }
|
||||
}, {} as ThemeSyntaxColorTokens)
|
||||
}
|
||||
|
||||
const syntax_tokens = (
|
||||
theme: ColorScheme
|
||||
): ColorSchemeTokens["syntax"] => {
|
||||
const syntax_tokens = (theme: ColorScheme): ColorSchemeTokens["syntax"] => {
|
||||
const syntax = editor(theme).syntax
|
||||
|
||||
return syntax_highlight_style_color_tokens(syntax)
|
||||
|
@ -88,12 +86,12 @@ export function theme_tokens(theme: ColorScheme): ColorSchemeTokens {
|
|||
value: theme.is_light ? "light" : "dark",
|
||||
type: TokenTypes.OTHER,
|
||||
},
|
||||
lowest: layerToken(theme.lowest, "lowest"),
|
||||
middle: layerToken(theme.middle, "middle"),
|
||||
highest: layerToken(theme.highest, "highest"),
|
||||
lowest: layer_token(theme.lowest, "lowest"),
|
||||
middle: layer_token(theme.middle, "middle"),
|
||||
highest: layer_token(theme.highest, "highest"),
|
||||
popover_shadow: popover_shadow_token(theme),
|
||||
modal_shadow: modal_shadow_token(theme),
|
||||
players: playersToken(theme),
|
||||
players: players_token(theme),
|
||||
syntax: syntax_tokens(theme),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,7 @@ export type PlayerToken = Record<"selection" | "cursor", SingleColorToken>
|
|||
|
||||
export type PlayersToken = Record<keyof Players, PlayerToken>
|
||||
|
||||
function build_player_token(
|
||||
theme: ColorScheme,
|
||||
index: number
|
||||
): PlayerToken {
|
||||
function build_player_token(theme: ColorScheme, index: number): PlayerToken {
|
||||
const player_number = index.toString() as keyof Players
|
||||
|
||||
return {
|
||||
|
|
|
@ -25,7 +25,8 @@ export const theme: ThemeConfig = {
|
|||
author: "simurai",
|
||||
appearance: ThemeAppearance.Dark,
|
||||
license_type: ThemeLicenseType.MIT,
|
||||
license_url: "https://github.com/atom/atom/tree/master/packages/one-dark-ui",
|
||||
license_url:
|
||||
"https://github.com/atom/atom/tree/master/packages/one-dark-ui",
|
||||
license_file: `${__dirname}/LICENSE`,
|
||||
input_color: {
|
||||
neutral: chroma
|
||||
|
|
|
@ -5,8 +5,8 @@ import { snakeCase } from "case-anything"
|
|||
// Typescript magic to convert any string from camelCase to snake_case at compile time
|
||||
type SnakeCase<S> = S extends string
|
||||
? S extends `${infer T}${infer U}`
|
||||
? `${T extends Capitalize<T> ? "_" : ""}${Lowercase<T>}${SnakeCase<U>}`
|
||||
: S
|
||||
? `${T extends Capitalize<T> ? "_" : ""}${Lowercase<T>}${SnakeCase<U>}`
|
||||
: S
|
||||
: S
|
||||
|
||||
type SnakeCased<Type> = {
|
||||
|
|
Loading…
Reference in a new issue