@evinvest/uikit 0.29.4 → 0.31.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.
Files changed (204) hide show
  1. package/README.md +294 -90
  2. package/dist/{chunk-3IPB4QQJ.js → chunk-35SPIU4U.js} +10 -6
  3. package/dist/chunk-35SPIU4U.js.map +1 -0
  4. package/dist/components/account-list.js +128 -0
  5. package/dist/components/account-list.js.map +1 -0
  6. package/dist/components/account-menu-profile.js +114 -0
  7. package/dist/components/account-menu-profile.js.map +1 -0
  8. package/dist/components/account-menu.js +50 -23
  9. package/dist/components/account-menu.js.map +1 -1
  10. package/dist/components/account-settings-dialog.js +84 -0
  11. package/dist/components/account-settings-dialog.js.map +1 -0
  12. package/dist/components/alert-dialog.js +3 -2
  13. package/dist/components/alert-dialog.js.map +1 -1
  14. package/dist/components/animated-number-columns.js +105 -0
  15. package/dist/components/animated-number-columns.js.map +1 -0
  16. package/dist/components/animated-number.js +157 -0
  17. package/dist/components/animated-number.js.map +1 -0
  18. package/dist/components/app-shell.js +9 -0
  19. package/dist/components/app-shell.js.map +1 -1
  20. package/dist/components/aside.js +140 -0
  21. package/dist/components/aside.js.map +1 -0
  22. package/dist/components/badge.js +1 -1
  23. package/dist/components/badge.js.map +1 -1
  24. package/dist/components/button.js +3 -11
  25. package/dist/components/button.js.map +1 -1
  26. package/dist/components/chat-composer.js +141 -0
  27. package/dist/components/chat-composer.js.map +1 -0
  28. package/dist/components/chat-message.js +195 -0
  29. package/dist/components/chat-message.js.map +1 -0
  30. package/dist/components/chat-panel.js +137 -0
  31. package/dist/components/chat-panel.js.map +1 -0
  32. package/dist/components/chat-stream-text.js +69 -0
  33. package/dist/components/chat-stream-text.js.map +1 -0
  34. package/dist/components/chat-typing.js +26 -0
  35. package/dist/components/chat-typing.js.map +1 -0
  36. package/dist/components/command-palette.js +119 -0
  37. package/dist/components/command-palette.js.map +1 -0
  38. package/dist/components/command.js +3 -1
  39. package/dist/components/command.js.map +1 -1
  40. package/dist/components/confirm-dialog.js +123 -0
  41. package/dist/components/confirm-dialog.js.map +1 -0
  42. package/dist/components/context-menu.js +53 -5
  43. package/dist/components/context-menu.js.map +1 -1
  44. package/dist/components/dialog.js +3 -2
  45. package/dist/components/dialog.js.map +1 -1
  46. package/dist/components/drawer.js +3 -1
  47. package/dist/components/drawer.js.map +1 -1
  48. package/dist/components/dropdown-menu.js +64 -5
  49. package/dist/components/dropdown-menu.js.map +1 -1
  50. package/dist/components/form-row.js +51 -0
  51. package/dist/components/form-row.js.map +1 -0
  52. package/dist/components/header-controls.js +149 -0
  53. package/dist/components/header-controls.js.map +1 -0
  54. package/dist/components/icon-button.js +35 -0
  55. package/dist/components/icon-button.js.map +1 -0
  56. package/dist/components/key-value.js +68 -0
  57. package/dist/components/key-value.js.map +1 -0
  58. package/dist/components/menubar.js +39 -5
  59. package/dist/components/menubar.js.map +1 -1
  60. package/dist/components/native-select.js +3 -4
  61. package/dist/components/native-select.js.map +1 -1
  62. package/dist/components/nav-collapse.js +142 -0
  63. package/dist/components/nav-collapse.js.map +1 -0
  64. package/dist/components/nav-model.js.map +1 -1
  65. package/dist/components/navigation-menu.js +4 -5
  66. package/dist/components/navigation-menu.js.map +1 -1
  67. package/dist/components/page-frame.js +2 -5
  68. package/dist/components/page-frame.js.map +1 -1
  69. package/dist/components/popover-form.js +60 -0
  70. package/dist/components/popover-form.js.map +1 -0
  71. package/dist/components/resource-error.js +1 -1
  72. package/dist/components/resource-error.js.map +1 -1
  73. package/dist/components/section-nav.js +73 -20
  74. package/dist/components/section-nav.js.map +1 -1
  75. package/dist/components/select.js +16 -6
  76. package/dist/components/select.js.map +1 -1
  77. package/dist/components/settings.js +94 -0
  78. package/dist/components/settings.js.map +1 -0
  79. package/dist/components/sheet.js +3 -2
  80. package/dist/components/sheet.js.map +1 -1
  81. package/dist/components/shell-nav.js +80 -38
  82. package/dist/components/shell-nav.js.map +1 -1
  83. package/dist/components/smart-header.js +53 -0
  84. package/dist/components/smart-header.js.map +1 -0
  85. package/dist/components/status-item.js +42 -0
  86. package/dist/components/status-item.js.map +1 -0
  87. package/dist/components/system-banner.js +22 -12
  88. package/dist/components/system-banner.js.map +1 -1
  89. package/dist/components/top-bar.js +4 -3
  90. package/dist/components/top-bar.js.map +1 -1
  91. package/dist/components/ui-icons.js +77 -0
  92. package/dist/components/ui-icons.js.map +1 -0
  93. package/dist/components/use-count-tween.js +42 -0
  94. package/dist/components/use-count-tween.js.map +1 -0
  95. package/dist/components/workspace-tab.js +140 -0
  96. package/dist/components/workspace-tab.js.map +1 -0
  97. package/dist/generated/accent.js +2 -2
  98. package/dist/generated/accent.js.map +1 -1
  99. package/dist/generated/account-list.js +35 -0
  100. package/dist/generated/account-list.js.map +1 -0
  101. package/dist/generated/account-settings-dialog.js +27 -0
  102. package/dist/generated/account-settings-dialog.js.map +1 -0
  103. package/dist/generated/alert-dialog.js +1 -1
  104. package/dist/generated/alert-dialog.js.map +1 -1
  105. package/dist/generated/alert.js +2 -2
  106. package/dist/generated/alert.js.map +1 -1
  107. package/dist/generated/aside.js +36 -0
  108. package/dist/generated/aside.js.map +1 -0
  109. package/dist/generated/badge.js +7 -6
  110. package/dist/generated/badge.js.map +1 -1
  111. package/dist/generated/band.js +1 -1
  112. package/dist/generated/band.js.map +1 -1
  113. package/dist/generated/breadcrumb.js +2 -2
  114. package/dist/generated/breadcrumb.js.map +1 -1
  115. package/dist/generated/button-group.js +2 -2
  116. package/dist/generated/button-group.js.map +1 -1
  117. package/dist/generated/button.js +4 -4
  118. package/dist/generated/button.js.map +1 -1
  119. package/dist/generated/card.js +6 -6
  120. package/dist/generated/card.js.map +1 -1
  121. package/dist/generated/chat-composer.js +21 -0
  122. package/dist/generated/chat-composer.js.map +1 -0
  123. package/dist/generated/chat-message.js +86 -0
  124. package/dist/generated/chat-message.js.map +1 -0
  125. package/dist/generated/chat-typing.js +9 -0
  126. package/dist/generated/chat-typing.js.map +1 -0
  127. package/dist/generated/command-palette.js +17 -0
  128. package/dist/generated/command-palette.js.map +1 -0
  129. package/dist/generated/command.js +3 -3
  130. package/dist/generated/command.js.map +1 -1
  131. package/dist/generated/confirm-dialog.js +28 -0
  132. package/dist/generated/confirm-dialog.js.map +1 -0
  133. package/dist/generated/context-menu.js +1 -1
  134. package/dist/generated/context-menu.js.map +1 -1
  135. package/dist/generated/date-time-picker.js +1 -1
  136. package/dist/generated/date-time-picker.js.map +1 -1
  137. package/dist/generated/dialog.js +1 -1
  138. package/dist/generated/dialog.js.map +1 -1
  139. package/dist/generated/drawer.js +1 -1
  140. package/dist/generated/drawer.js.map +1 -1
  141. package/dist/generated/dropdown-menu.js +1 -1
  142. package/dist/generated/dropdown-menu.js.map +1 -1
  143. package/dist/generated/form-row.js +17 -0
  144. package/dist/generated/form-row.js.map +1 -0
  145. package/dist/generated/header-controls.js +56 -0
  146. package/dist/generated/header-controls.js.map +1 -0
  147. package/dist/generated/icon-button.js +13 -0
  148. package/dist/generated/icon-button.js.map +1 -0
  149. package/dist/generated/key-value.js +15 -0
  150. package/dist/generated/key-value.js.map +1 -0
  151. package/dist/generated/menubar.js +1 -1
  152. package/dist/generated/menubar.js.map +1 -1
  153. package/dist/generated/navigation-menu.js +1 -1
  154. package/dist/generated/navigation-menu.js.map +1 -1
  155. package/dist/generated/popover-form.js +13 -0
  156. package/dist/generated/popover-form.js.map +1 -0
  157. package/dist/generated/section-label.js +10 -0
  158. package/dist/generated/section-label.js.map +1 -0
  159. package/dist/generated/select.js +15 -3
  160. package/dist/generated/select.js.map +1 -1
  161. package/dist/generated/settings.js +36 -0
  162. package/dist/generated/settings.js.map +1 -0
  163. package/dist/generated/sheet.js +1 -1
  164. package/dist/generated/sheet.js.map +1 -1
  165. package/dist/generated/slider.js +1 -1
  166. package/dist/generated/slider.js.map +1 -1
  167. package/dist/generated/smart-header.js +11 -0
  168. package/dist/generated/smart-header.js.map +1 -0
  169. package/dist/generated/sonner.js +4 -4
  170. package/dist/generated/sonner.js.map +1 -1
  171. package/dist/generated/status-item.js +17 -0
  172. package/dist/generated/status-item.js.map +1 -0
  173. package/dist/generated/system-banner.js +33 -0
  174. package/dist/generated/system-banner.js.map +1 -0
  175. package/dist/generated/top-bar.js +9 -0
  176. package/dist/generated/top-bar.js.map +1 -0
  177. package/dist/generated/workspace-tab.js +17 -0
  178. package/dist/generated/workspace-tab.js.map +1 -0
  179. package/dist/index.d.ts +852 -156
  180. package/dist/index.js +21 -1
  181. package/dist/lib/cn.js +8 -1
  182. package/dist/lib/cn.js.map +1 -1
  183. package/dist/lib/number-parts.js +90 -0
  184. package/dist/lib/number-parts.js.map +1 -0
  185. package/dist/palette-cli.js +1 -1
  186. package/dist/palette.d.ts +6 -4
  187. package/dist/palette.js +3 -1
  188. package/dist/primitives/dismissable-layer.js +76 -4
  189. package/dist/primitives/dismissable-layer.js.map +1 -1
  190. package/dist/primitives/focus-scope.js +20 -5
  191. package/dist/primitives/focus-scope.js.map +1 -1
  192. package/dist/primitives/use-floating.js +16 -1
  193. package/dist/primitives/use-floating.js.map +1 -1
  194. package/dist/primitives/use-reduced-motion.js +20 -0
  195. package/dist/primitives/use-reduced-motion.js.map +1 -0
  196. package/package.json +1 -1
  197. package/styles/ev.css +281 -49
  198. package/styles/theme.css +335 -39
  199. package/styles/tokens.css +643 -103
  200. package/dist/chunk-3IPB4QQJ.js.map +0 -1
  201. package/dist/components/terminal.js +0 -206
  202. package/dist/components/terminal.js.map +0 -1
  203. package/dist/generated/terminal.js +0 -70
  204. package/dist/generated/terminal.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/palette/contract.ts","../src/palette/toml.ts","../src/palette/brand.ts"],"sourcesContent":["/**\n * The colour contract, read out of the kit's own token sheet rather than\n * restated here: `@theme inline` maps every name the class tables can paint\n * (`--color-X: var(--X)`), and the derived rule lists the ones the contract\n * computes from the rest. A palette owes the difference.\n */\nexport interface Contract {\n /** Names every palette scope must declare. */\n required: readonly string[];\n /** Names the contract derives from the palette; a palette may override them. */\n derived: readonly string[];\n /** The tokens each derived default reads, so a palette's references can be checked for cycles through them. */\n derivedFrom: Readonly<Record<string, readonly string[]>>;\n}\n\n/** The `--name`s a value reads through `var()`. */\nexport function references(value: string): string[] {\n return [...value.matchAll(/var\\(--([A-Za-z0-9-]+)/g)].flatMap((m) => (m[1] ? [m[1]] : []));\n}\n\n/** The rule the derived tokens live on — see `theme.css`, the contract half of `tokens.css`. */\nexport const DERIVED_SCOPE = \":where(:root, .dark, .light, [data-brand])\";\n\nexport interface CssRule {\n selector: string;\n /** Custom properties declared directly in the rule, in source order. */\n declarations: Map<string, string>;\n}\n\n/**\n * Top-level and `@media`-nested rules of a flat sheet, comments stripped. Only\n * as much CSS as a token sheet is made of: no strings containing braces.\n */\nexport function readRules(css: string): CssRule[] {\n const rules: CssRule[] = [];\n const src = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\");\n const stack: string[] = [];\n let start = 0;\n for (let i = 0; i < src.length; i++) {\n const c = src[i];\n if (c === \"{\") {\n stack.push(src.slice(start, i).trim());\n start = i + 1;\n } else if (c === \"}\") {\n const selector = stack.pop();\n if (selector === undefined) throw new Error(\"unbalanced `}` in token sheet\");\n const body = src.slice(start, i);\n if (!body.includes(\"{\")) rules.push({ selector: normalise(selector), declarations: declarations(body) });\n start = i + 1;\n } else if (c === \";\" && stack.length === 0) {\n start = i + 1;\n }\n }\n if (stack.length > 0) throw new Error(\"unbalanced `{` in token sheet\");\n return rules;\n}\n\nfunction declarations(body: string): Map<string, string> {\n const out = new Map<string, string>();\n for (const decl of body.split(\";\")) {\n const match = /^\\s*--([A-Za-z0-9-]+)\\s*:\\s*([\\s\\S]+?)\\s*$/.exec(decl);\n if (match?.[1] && match[2]) out.set(match[1], match[2]);\n }\n return out;\n}\n\nexport function normalise(selector: string): string {\n return selector.replace(/\\s+/g, \" \").replace(/\\s*,\\s*/g, \", \").trim();\n}\n\nexport function readContract(css: string): Contract {\n const rules = readRules(css);\n const theme = rules.find((r) => r.selector === \"@theme inline\");\n if (!theme) throw new Error(\"token sheet has no `@theme inline` block — not the kit's contract\");\n const painted: string[] = [];\n for (const [name, value] of theme.declarations) {\n const match = /^color-(.+)$/.exec(name);\n if (match?.[1] && value === `var(--${match[1]})`) painted.push(match[1]);\n }\n const derivedRule = rules.find((r) => r.selector === DERIVED_SCOPE);\n if (!derivedRule) throw new Error(`token sheet has no \\`${DERIVED_SCOPE}\\` rule — not the kit's contract`);\n const derived = [...derivedRule.declarations.keys()];\n const stray = derived.filter((d) => !painted.includes(d));\n if (stray.length > 0) throw new Error(`derived tokens with no @theme mapping: ${stray.join(\", \")}`);\n const derivedFrom = Object.fromEntries([...derivedRule.declarations].map(([name, value]) => [name, references(value)]));\n return { required: painted.filter((p) => !derived.includes(p)), derived, derivedFrom };\n}\n","/**\n * The subset of TOML a brand file is written in: `[table.headers]`, bare keys,\n * and single-line values that are a basic string, a number, a boolean, or a\n * flat array of those. Anything else is an error naming the line, rather than a\n * silent misread — the kit stays dependency-free, and a brand file has no use\n * for the rest of the language.\n */\n\nexport type TomlValue = string | number | boolean | TomlValue[];\nexport interface TomlTable {\n [key: string]: TomlValue | TomlTable;\n}\n\nconst BARE_KEY = /^[A-Za-z0-9_-]+$/;\n\nexport function parseToml(text: string): TomlTable {\n const root: TomlTable = {};\n let table = root;\n const headers = new Set<string>();\n text.split(/\\r?\\n/).forEach((raw, index) => {\n const line = stripComment(raw).trim();\n if (line === \"\") return;\n const fail = (why: string): never => {\n throw new Error(`TOML line ${index + 1}: ${why}: ${raw.trim()}`);\n };\n\n if (line.startsWith(\"[\")) {\n if (!line.endsWith(\"]\") || line.startsWith(\"[[\")) fail(\"only plain [table] headers are supported\");\n const path = line.slice(1, -1).trim().split(\".\").map((part) => part.trim());\n // Re-opening a table would merge two halves of it silently.\n if (headers.has(path.join(\".\"))) fail(\"duplicate table header\");\n headers.add(path.join(\".\"));\n table = descend(root, path, fail);\n return;\n }\n\n const eq = line.indexOf(\"=\");\n if (eq < 0) fail(\"expected `key = value`\");\n const key = line.slice(0, eq).trim();\n if (!BARE_KEY.test(key)) fail(\"only bare keys are supported\");\n if (key in table) fail(`duplicate key \\`${key}\\``);\n table[key] = parseValue(line.slice(eq + 1).trim(), fail);\n });\n return root;\n}\n\nfunction descend(root: TomlTable, path: string[], fail: (why: string) => never): TomlTable {\n let table = root;\n for (const part of path) {\n const key = part.trim();\n if (!BARE_KEY.test(key)) fail(\"only bare keys are supported in a header\");\n const next = table[key] ?? {};\n if (typeof next !== \"object\" || Array.isArray(next)) fail(`\\`${key}\\` is already a value`);\n table[key] = next;\n table = next as TomlTable;\n }\n return table;\n}\n\n// A `#` inside a string is not a comment; the brand files carry `\"#rrggbb\"`.\nfunction stripComment(line: string): string {\n let quoted = false;\n for (let i = 0; i < line.length; i++) {\n const c = line[i];\n if (c === \"\\\\\" && quoted) i++;\n else if (c === '\"') quoted = !quoted;\n else if (c === \"#\" && !quoted) return line.slice(0, i);\n }\n return line;\n}\n\nfunction parseValue(src: string, fail: (why: string) => never): TomlValue {\n if (src.startsWith('\"')) {\n if (src.length < 2 || !src.endsWith('\"')) fail(\"unterminated string\");\n const body = src.slice(1, -1);\n if (/(^|[^\\\\])(\\\\\\\\)*\"/.test(body)) fail(\"one string per value\");\n // Only the escapes decoded below; `\\u…` and friends would otherwise pass through as literal text.\n if (/\\\\(?![\"\\\\nt])/.test(body.replace(/\\\\\\\\/g, \"\"))) fail(\"unsupported escape\");\n return body.replace(/\\\\([\"\\\\nt])/g, (_, c: string) => ({ n: \"\\n\", t: \"\\t\" })[c] ?? c);\n }\n if (src.startsWith(\"[\")) {\n if (!src.endsWith(\"]\")) fail(\"arrays must close on the same line\");\n const inner = src.slice(1, -1).trim();\n if (inner === \"\") return [];\n return splitTopLevel(inner).map((item) => parseValue(item.trim(), fail));\n }\n if (src === \"true\" || src === \"false\") return src === \"true\";\n if (/^[+-]?\\d+(\\.\\d+)?$/.test(src)) return Number(src);\n return fail(\"unsupported value\");\n}\n\nfunction splitTopLevel(inner: string): string[] {\n const items: string[] = [];\n let quoted = false;\n let start = 0;\n for (let i = 0; i < inner.length; i++) {\n const c = inner[i];\n if (c === \"\\\\\" && quoted) i++;\n else if (c === '\"') quoted = !quoted;\n else if (c === \",\" && !quoted) {\n items.push(inner.slice(start, i));\n start = i + 1;\n }\n }\n const last = inner.slice(start);\n if (last.trim() !== \"\") items.push(last);\n return items;\n}\n","import { references, type Contract } from \"./contract\";\nimport { parseToml, type TomlTable, type TomlValue } from \"./toml\";\n\nexport type PolarityName = \"light\" | \"dark\";\nexport const POLARITIES: readonly PolarityName[] = [\"light\", \"dark\"];\n\n/** A brand's palette: one value per contract name, for each polarity. */\nexport interface BrandConfig {\n colors: Record<PolarityName, Record<string, string>>;\n /** `--brand-mark`: the URL `<Logo>` masks. */\n mark?: string;\n /** `--brand-aspect`: the mark's width / height, e.g. `\"387 / 335\"`. */\n markAspect?: string;\n /** `--brand-font-<role>`: a family name per role; unset roles keep the kit's. */\n fonts?: Partial<Record<FontRole, string>>;\n}\n\nexport type FontRole = \"sans\" | \"display\" | \"mono\";\nexport const FONT_ROLES: readonly FontRole[] = [\"sans\", \"display\", \"mono\"];\n// aquafix's file calls the body family `text`.\nconst FONT_KEYS: Record<string, FontRole> = { sans: \"sans\", text: \"sans\", display: \"display\", mono: \"mono\" };\n\n/** Every problem with a brand file at once, so one run fixes them all. */\nexport class PaletteError extends Error {\n constructor(readonly problems: readonly string[]) {\n super(`invalid brand palette:\\n - ${problems.join(\"\\n - \")}`);\n this.name = \"PaletteError\";\n }\n}\n\n// Written into CSS verbatim, so a value is held to a shape that cannot close\n// the declaration: a hex colour, or a reference to another token.\nconst COLOUR = /^(#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{8}|var\\(--[a-z0-9-]+\\))$/;\nconst SLUG = /^[a-z0-9][a-z0-9-]*$/;\nconst ASPECT = /^\\d+(\\.\\d+)?\\s*\\/\\s*\\d+(\\.\\d+)?$/;\n// Written inside `url(\"…\")`: nothing that closes the string or the function,\n// and no markup characters for a sheet that ends up inlined in HTML.\nconst MARK_URL = /^[^\"'`\\\\\\s()<>]+$/;\nconst FAMILY = /^[A-Za-z0-9][A-Za-z0-9 _-]*$/;\n\n/**\n * Reads the aquafix `brand.toml` shape: `[colors.light]` and `[colors.dark]`\n * keyed by contract name, optional top-level `mark` / `mark-aspect`, and the\n * family names in `[fonts]` (`sans` or `text`, `display`, `mono`). The rest of\n * `[fonts]` and every other table (`[print]`, …) belong to other tools and are\n * ignored — loading the font files is the site's job, not the palette's.\n */\nexport function brandFromToml(text: string): BrandConfig {\n const doc = parseToml(text);\n const problems: string[] = [];\n const colors = table(doc[\"colors\"]);\n if (!colors) problems.push(\"no [colors] table\");\n const scope = (name: PolarityName): Record<string, string> => {\n const t = colors ? table(colors[name]) : undefined;\n if (colors && !t) problems.push(`no [colors.${name}] table`);\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(t ?? {})) {\n if (typeof value === \"string\") out[key] = value;\n else problems.push(`colors.${name}.${key} is not a string`);\n }\n return out;\n };\n for (const key of Object.keys(colors ?? {})) {\n if (!(POLARITIES as readonly string[]).includes(key)) problems.push(`[colors.${key}] is not a polarity (light, dark)`);\n }\n const config: BrandConfig = { colors: { light: scope(\"light\"), dark: scope(\"dark\") } };\n const mark = optionalString(doc[\"mark\"], \"mark\", problems);\n const markAspect = optionalString(doc[\"mark-aspect\"], \"mark-aspect\", problems);\n if (mark !== undefined) config.mark = mark;\n if (markAspect !== undefined) config.markAspect = markAspect;\n const fonts = table(doc[\"fonts\"]);\n for (const [key, role] of Object.entries(FONT_KEYS)) {\n const family = optionalString(fonts?.[key], `fonts.${key}`, problems);\n if (family !== undefined) config.fonts = { ...config.fonts, [role]: family };\n }\n if (problems.length > 0) throw new PaletteError(problems);\n return config;\n}\n\nfunction table(value: TomlValue | TomlTable | undefined): TomlTable | undefined {\n return typeof value === \"object\" && !Array.isArray(value) ? value : undefined;\n}\n\nfunction optionalString(value: TomlValue | TomlTable | undefined, key: string, problems: string[]) {\n if (value === undefined || typeof value === \"string\") return value;\n problems.push(`${key} is not a string`);\n return undefined;\n}\n\n/** The problems with `config` against `contract`; empty when it is complete. */\nexport function validateBrand(config: BrandConfig, contract: Contract): string[] {\n const problems: string[] = [];\n const known = new Set([...contract.required, ...contract.derived]);\n for (const polarity of POLARITIES) {\n const values = config.colors[polarity];\n const missing = contract.required.filter((t) => !(t in values));\n if (missing.length > 0) problems.push(`${polarity} is missing ${missing.join(\", \")}`);\n for (const [key, value] of Object.entries(values)) {\n if (!known.has(key)) problems.push(`${polarity}.${key} is not a token of the contract`);\n else if (!COLOUR.test(value)) problems.push(`${polarity}.${key} = ${JSON.stringify(value)} is not #hex or var(--token)`);\n else {\n for (const ref of references(value)) {\n if (!known.has(ref)) problems.push(`${polarity}.${key} refers to --${ref}, which is not a token of the contract`);\n }\n }\n }\n const cycle = findCycle(values, contract, known);\n if (cycle) problems.push(`${polarity} has a reference cycle: ${cycle.map((t) => `--${t}`).join(\" → \")}`);\n }\n if (config.mark !== undefined && !MARK_URL.test(config.mark)) problems.push(`mark ${JSON.stringify(config.mark)} is not a plain URL`);\n if (config.markAspect !== undefined && !ASPECT.test(config.markAspect)) {\n problems.push(`mark-aspect ${JSON.stringify(config.markAspect)} is not \"width / height\"`);\n }\n for (const [role, family] of Object.entries(config.fonts ?? {})) {\n if (!FAMILY.test(family)) problems.push(`fonts.${role} ${JSON.stringify(family)} is not a plain family name`);\n }\n return problems;\n}\n\n/**\n * A `var()` cycle makes every token on it invalid at computed-value time — the\n * same silent hole as a missing token. Edges are the palette's own references,\n * and for a derived token it leaves to the contract, the contract's formula\n * (`border` reads `ink`), so `ink = \"var(--border)\"` is caught too.\n */\nfunction findCycle(values: Record<string, string>, contract: Contract, known: Set<string>): string[] | undefined {\n const edges = (name: string): readonly string[] => {\n const value = values[name];\n if (value !== undefined) return references(value).filter((r) => known.has(r));\n return contract.derivedFrom[name] ?? [];\n };\n const done = new Set<string>();\n const path: string[] = [];\n const visit = (name: string): string[] | undefined => {\n const at = path.indexOf(name);\n if (at >= 0) return [...path.slice(at), name];\n if (done.has(name)) return undefined;\n path.push(name);\n for (const next of edges(name)) {\n const cycle = visit(next);\n if (cycle) return cycle;\n }\n path.pop();\n done.add(name);\n return undefined;\n };\n for (const name of known) {\n const cycle = visit(name);\n if (cycle) return cycle;\n }\n return undefined;\n}\n\n/**\n * A flat sheet scoping `config` under `[data-brand=\"<brand>\"]`: light is the\n * brand's default and `.light` / `.dark` beneath it pick a polarity. Selectors\n * outrank the zero-specificity EV palette, so import order does not matter.\n * Throws a {@link PaletteError} when a scope is incomplete — Tailwind answers an\n * undefined token with no rule at all, so a hole would be silent on the page.\n */\nexport function renderPalette(brand: string, config: BrandConfig, contract: Contract, source = \"a brand file\"): string {\n const problems = SLUG.test(brand) ? [] : [`brand ${JSON.stringify(brand)} is not a lowercase slug`];\n problems.push(...validateBrand(config, contract));\n if (problems.length > 0) throw new PaletteError(problems);\n\n const at = `[data-brand=\"${brand}\"]`;\n const order = [...contract.required, ...contract.derived];\n const block = (selectors: string[], polarity: PolarityName) => {\n const values = config.colors[polarity];\n const body = order.filter((t) => t in values).map((t) => ` --${t}: ${values[t]};\\n`);\n return `${selectors.join(\",\\n\")} {\\n --scheme: ${polarity};\\n${body.join(\"\")}}\\n`;\n };\n const extras: string[] = [];\n if (config.mark !== undefined) extras.push(` --brand-mark: url(\"${config.mark}\");\\n`);\n if (config.markAspect !== undefined) extras.push(` --brand-aspect: ${config.markAspect};\\n`);\n for (const role of FONT_ROLES) {\n const family = config.fonts?.[role];\n if (family !== undefined) extras.push(` --brand-font-${role}: \"${family}\";\\n`);\n }\n\n return [\n // `source` is a file name, free text as far as CSS is concerned: it must not close the comment.\n `/* GENERATED by evinvest-palette from ${source.replaceAll(\"*/\", \"*\\\\/\")} — do not edit. */\\n`,\n block([at, `${at}.light`, `${at} .light`], \"light\"),\n block([`${at}.dark`, `${at} .dark`], \"dark\"),\n ...(extras.length > 0 ? [`${at} {\\n${extras.join(\"\")}}\\n`] : []),\n ].join(\"\\n\");\n}\n"],"mappings":"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","names":["table"]}
@@ -1,206 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { cn } from "../lib/cn.js";
5
- import {
6
- bookDepthClasses,
7
- bookSideClasses,
8
- OPEN_ORDERS_EMPTY,
9
- ORDER_BOOK,
10
- ORDER_BOOK_DEPTH,
11
- ORDER_BOOK_HEAD,
12
- ORDER_BOOK_PRICE,
13
- ORDER_BOOK_ROW,
14
- ORDER_BOOK_SPREAD,
15
- ORDER_FORM,
16
- ORDER_FORM_LABEL,
17
- ORDER_FORM_ROW,
18
- ORDER_FORM_SUBMIT_BASE,
19
- ORDER_FORM_VALUE,
20
- orderSideClasses,
21
- TERMINAL_CHART,
22
- TERMINAL_PANE,
23
- TERMINAL_PANE_BODY,
24
- TERMINAL_PANE_HEADER,
25
- TERMINAL_ROOT,
26
- TERMINAL_TICKER,
27
- TERMINAL_TICKER_LABEL,
28
- TERMINAL_TICKER_STAT,
29
- TERMINAL_TICKER_VALUE,
30
- terminalAreaClasses,
31
- TRADES_TAPE_ROW
32
- } from "../generated/terminal.js";
33
- function Terminal({ className, ...props }) {
34
- return /* @__PURE__ */ jsx("div", { "data-slot": "terminal", className: cn(TERMINAL_ROOT, className), ...props });
35
- }
36
- function TerminalPane({ area, className, ...props }) {
37
- return /* @__PURE__ */ jsx(
38
- "section",
39
- {
40
- "data-slot": "terminal-pane",
41
- "data-area": area,
42
- className: cn(TERMINAL_PANE, terminalAreaClasses[area], className),
43
- ...props
44
- }
45
- );
46
- }
47
- function TerminalPaneHeader({ className, ...props }) {
48
- return /* @__PURE__ */ jsx(
49
- "header",
50
- {
51
- "data-slot": "terminal-pane-header",
52
- className: cn(TERMINAL_PANE_HEADER, className),
53
- ...props
54
- }
55
- );
56
- }
57
- function TerminalPaneBody({ className, ...props }) {
58
- return /* @__PURE__ */ jsx("div", { "data-slot": "terminal-pane-body", className: cn(TERMINAL_PANE_BODY, className), ...props });
59
- }
60
- const TerminalChart = React.forwardRef(function TerminalChart2({ className, ...props }, ref) {
61
- return /* @__PURE__ */ jsx(
62
- "div",
63
- {
64
- ref,
65
- "data-slot": "terminal-chart",
66
- className: cn(TERMINAL_CHART, className),
67
- ...props
68
- }
69
- );
70
- });
71
- function TerminalTicker({ className, ...props }) {
72
- return /* @__PURE__ */ jsx(
73
- "div",
74
- {
75
- "data-slot": "terminal-ticker",
76
- "data-area": "ticker",
77
- className: cn(TERMINAL_TICKER, terminalAreaClasses.ticker, className),
78
- ...props
79
- }
80
- );
81
- }
82
- function TickerStat({ label, value, className, ...props }) {
83
- return /* @__PURE__ */ jsxs("div", { "data-slot": "ticker-stat", className: TERMINAL_TICKER_STAT, ...props, children: [
84
- /* @__PURE__ */ jsx("span", { className: TERMINAL_TICKER_LABEL, children: label }),
85
- /* @__PURE__ */ jsx("span", { className: cn(TERMINAL_TICKER_VALUE, className), children: value })
86
- ] });
87
- }
88
- function OrderBook({ className, ...props }) {
89
- return /* @__PURE__ */ jsx("div", { "data-slot": "order-book", className: cn(ORDER_BOOK, className), ...props });
90
- }
91
- function OrderBookHead({ price, size, total, className, ...props }) {
92
- return /* @__PURE__ */ jsxs("div", { "data-slot": "order-book-head", className: cn(ORDER_BOOK_HEAD, className), ...props, children: [
93
- /* @__PURE__ */ jsx("span", { children: price }),
94
- /* @__PURE__ */ jsx("span", { children: size }),
95
- /* @__PURE__ */ jsx("span", { children: total })
96
- ] });
97
- }
98
- function OrderBookRow({
99
- side,
100
- price,
101
- size,
102
- total,
103
- depth = 0,
104
- className,
105
- ...props
106
- }) {
107
- return /* @__PURE__ */ jsxs(
108
- "div",
109
- {
110
- "data-slot": "order-book-row",
111
- "data-side": side,
112
- className: cn(ORDER_BOOK_ROW, className),
113
- ...props,
114
- children: [
115
- /* @__PURE__ */ jsx(
116
- "span",
117
- {
118
- "aria-hidden": "true",
119
- className: cn(ORDER_BOOK_DEPTH, bookDepthClasses[side]),
120
- style: { width: `${depthPercent(depth)}%` }
121
- }
122
- ),
123
- /* @__PURE__ */ jsx("span", { className: cn(ORDER_BOOK_PRICE, bookSideClasses[side]), children: price }),
124
- /* @__PURE__ */ jsx("span", { children: size }),
125
- /* @__PURE__ */ jsx("span", { children: total })
126
- ]
127
- }
128
- );
129
- }
130
- function depthPercent(depth) {
131
- if (Number.isNaN(depth)) return 0;
132
- return Math.round(Math.min(1, Math.max(0, depth)) * 100);
133
- }
134
- function OrderBookSpread({ className, ...props }) {
135
- return /* @__PURE__ */ jsx("div", { "data-slot": "order-book-spread", className: cn(ORDER_BOOK_SPREAD, className), ...props });
136
- }
137
- function TradesTapeRow({ side, price, size, time, className, ...props }) {
138
- return /* @__PURE__ */ jsxs(
139
- "div",
140
- {
141
- "data-slot": "trades-tape-row",
142
- "data-side": side,
143
- className: cn(TRADES_TAPE_ROW, className),
144
- ...props,
145
- children: [
146
- /* @__PURE__ */ jsx("span", { className: cn(ORDER_BOOK_PRICE, bookSideClasses[side]), children: price }),
147
- /* @__PURE__ */ jsx("span", { children: size }),
148
- /* @__PURE__ */ jsx("span", { children: time })
149
- ]
150
- }
151
- );
152
- }
153
- function OrderForm({ className, onSubmit, ...props }) {
154
- return /* @__PURE__ */ jsx(
155
- "form",
156
- {
157
- "data-slot": "order-form",
158
- className: cn(ORDER_FORM, className),
159
- onSubmit: (e) => {
160
- e.preventDefault();
161
- onSubmit?.(e);
162
- },
163
- ...props
164
- }
165
- );
166
- }
167
- function OrderFormRow({ label, value, className, ...props }) {
168
- return /* @__PURE__ */ jsxs("div", { "data-slot": "order-form-row", className: cn(ORDER_FORM_ROW, className), ...props, children: [
169
- /* @__PURE__ */ jsx("span", { className: ORDER_FORM_LABEL, children: label }),
170
- /* @__PURE__ */ jsx("span", { className: ORDER_FORM_VALUE, children: value })
171
- ] });
172
- }
173
- function OrderFormSubmit({ side = "buy", className, ...props }) {
174
- return /* @__PURE__ */ jsx(
175
- "button",
176
- {
177
- type: "submit",
178
- "data-slot": "order-form-submit",
179
- "data-side": side,
180
- className: cn(ORDER_FORM_SUBMIT_BASE, orderSideClasses[side], className),
181
- ...props
182
- }
183
- );
184
- }
185
- function OpenOrdersEmpty({ className, ...props }) {
186
- return /* @__PURE__ */ jsx("div", { "data-slot": "open-orders-empty", className: cn(OPEN_ORDERS_EMPTY, className), ...props });
187
- }
188
- export {
189
- OpenOrdersEmpty,
190
- OrderBook,
191
- OrderBookHead,
192
- OrderBookRow,
193
- OrderBookSpread,
194
- OrderForm,
195
- OrderFormRow,
196
- OrderFormSubmit,
197
- Terminal,
198
- TerminalChart,
199
- TerminalPane,
200
- TerminalPaneBody,
201
- TerminalPaneHeader,
202
- TerminalTicker,
203
- TickerStat,
204
- TradesTapeRow
205
- };
206
- //# sourceMappingURL=terminal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/components/terminal.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../lib/cn\";\nimport {\n bookDepthClasses,\n bookSideClasses,\n OPEN_ORDERS_EMPTY,\n ORDER_BOOK,\n ORDER_BOOK_DEPTH,\n ORDER_BOOK_HEAD,\n ORDER_BOOK_PRICE,\n ORDER_BOOK_ROW,\n ORDER_BOOK_SPREAD,\n ORDER_FORM,\n ORDER_FORM_LABEL,\n ORDER_FORM_ROW,\n ORDER_FORM_SUBMIT_BASE,\n ORDER_FORM_VALUE,\n orderSideClasses,\n TERMINAL_CHART,\n TERMINAL_PANE,\n TERMINAL_PANE_BODY,\n TERMINAL_PANE_HEADER,\n TERMINAL_ROOT,\n TERMINAL_TICKER,\n TERMINAL_TICKER_LABEL,\n TERMINAL_TICKER_STAT,\n TERMINAL_TICKER_VALUE,\n terminalAreaClasses,\n TRADES_TAPE_ROW,\n type BookSide,\n type OrderSide,\n type TerminalArea,\n} from \"../generated/terminal\";\n\nexport type { BookSide, OrderSide, TerminalArea };\n\n/**\n * The trading terminal — an order book over an investment product's shares,\n * laid out like a spot exchange: ticker, then chart | book | order form, then\n * the trader's own orders. Every pane is a slot; the chart host is empty on\n * purpose (the plotting engine is the consumer's), the open-orders table is\n * `Table`, the tabs over it are `Tabs`.\n */\n\n/**\n * The frame: a phone stacks the panes in DOM order, `lg` and up places them\n * by `TerminalArea` on a viewport-bound grid.\n */\nexport function Terminal({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div data-slot=\"terminal\" className={cn(TERMINAL_ROOT, className)} {...props} />;\n}\n\nexport interface TerminalPaneProps extends React.ComponentProps<\"section\"> {\n area: TerminalArea;\n}\n\n/**\n * One cell of the frame. `area` is where it sits on the desktop grid;\n * `TerminalPaneHeader` and `TerminalPaneBody` go inside.\n */\nexport function TerminalPane({ area, className, ...props }: TerminalPaneProps) {\n return (\n <section\n data-slot=\"terminal-pane\"\n data-area={area}\n className={cn(TERMINAL_PANE, terminalAreaClasses[area], className)}\n {...props}\n />\n );\n}\n\nexport function TerminalPaneHeader({ className, ...props }: React.ComponentProps<\"header\">) {\n return (\n <header\n data-slot=\"terminal-pane-header\"\n className={cn(TERMINAL_PANE_HEADER, className)}\n {...props}\n />\n );\n}\n\n/** The scrolling part of a pane. */\nexport function TerminalPaneBody({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div data-slot=\"terminal-pane-body\" className={cn(TERMINAL_PANE_BODY, className)} {...props} />\n );\n}\n\n/**\n * The sized host a plotting engine mounts into. Renders nothing itself; a\n * consumer mounts its chart on the element (via `ref`) or fills it with\n * children. `forwardRef` rather than a `ref` prop so the handle also reaches\n * the element under React 18, where function components drop `ref`.\n */\nexport const TerminalChart = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<\"div\">\n>(function TerminalChart({ className, ...props }, ref) {\n return (\n <div\n ref={ref}\n data-slot=\"terminal-chart\"\n className={cn(TERMINAL_CHART, className)}\n {...props}\n />\n );\n});\n\n/**\n * The strip across the top; holds `TickerStat`s. Already placed in the\n * `ticker` slot.\n */\nexport function TerminalTicker({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"terminal-ticker\"\n data-area=\"ticker\"\n className={cn(TERMINAL_TICKER, terminalAreaClasses.ticker, className)}\n {...props}\n />\n );\n}\n\nexport interface TickerStatProps extends Omit<React.ComponentProps<\"div\">, \"children\"> {\n label: React.ReactNode;\n value: React.ReactNode;\n}\n\n/**\n * A labelled figure in the ticker. `className` lands on the figure, so a\n * change figure passes its valence colour there.\n */\nexport function TickerStat({ label, value, className, ...props }: TickerStatProps) {\n return (\n <div data-slot=\"ticker-stat\" className={TERMINAL_TICKER_STAT} {...props}>\n <span className={TERMINAL_TICKER_LABEL}>{label}</span>\n <span className={cn(TERMINAL_TICKER_VALUE, className)}>{value}</span>\n </div>\n );\n}\n\n/** The book: `OrderBookHead`, then ask rows, `OrderBookSpread`, bid rows. */\nexport function OrderBook({ className, ...props }: React.ComponentProps<\"div\">) {\n return <div data-slot=\"order-book\" className={cn(ORDER_BOOK, className)} {...props} />;\n}\n\nexport interface OrderBookHeadProps extends Omit<React.ComponentProps<\"div\">, \"children\"> {\n price: React.ReactNode;\n size: React.ReactNode;\n total: React.ReactNode;\n}\n\n/** The three column captions — price, size, total — in the consumer's words. */\nexport function OrderBookHead({ price, size, total, className, ...props }: OrderBookHeadProps) {\n return (\n <div data-slot=\"order-book-head\" className={cn(ORDER_BOOK_HEAD, className)} {...props}>\n <span>{price}</span>\n <span>{size}</span>\n <span>{total}</span>\n </div>\n );\n}\n\nexport interface OrderBookRowProps extends Omit<React.ComponentProps<\"div\">, \"children\"> {\n side: BookSide;\n price: React.ReactNode;\n size: React.ReactNode;\n total: React.ReactNode;\n /**\n * This level's cumulative size as a fraction of the deepest level shown\n * (`0..=1`); it sizes the bar behind the figures.\n */\n depth?: number;\n}\n\n/** One price level. */\nexport function OrderBookRow({\n side,\n price,\n size,\n total,\n depth = 0,\n className,\n ...props\n}: OrderBookRowProps) {\n return (\n <div\n data-slot=\"order-book-row\"\n data-side={side}\n className={cn(ORDER_BOOK_ROW, className)}\n {...props}\n >\n <span\n aria-hidden=\"true\"\n className={cn(ORDER_BOOK_DEPTH, bookDepthClasses[side])}\n style={{ width: `${depthPercent(depth)}%` }}\n />\n <span className={cn(ORDER_BOOK_PRICE, bookSideClasses[side])}>{price}</span>\n <span>{size}</span>\n <span>{total}</span>\n </div>\n );\n}\n\n/**\n * The bar is a CSS percentage, so the fraction is clamped and rounded once\n * here; a NaN from an empty book reads as no depth rather than as `NaN%`.\n */\nfunction depthPercent(depth: number): number {\n if (Number.isNaN(depth)) return 0;\n return Math.round(Math.min(1, Math.max(0, depth)) * 100);\n}\n\n/**\n * The line between asks and bids: the consumer passes the mid and the spread\n * as it wants them formatted.\n */\nexport function OrderBookSpread({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div data-slot=\"order-book-spread\" className={cn(ORDER_BOOK_SPREAD, className)} {...props} />\n );\n}\n\nexport interface TradesTapeRowProps extends Omit<React.ComponentProps<\"div\">, \"children\"> {\n side: BookSide;\n price: React.ReactNode;\n size: React.ReactNode;\n time: React.ReactNode;\n}\n\n/** One print in the tape: price coloured by the aggressor's side, then size and time. */\nexport function TradesTapeRow({ side, price, size, time, className, ...props }: TradesTapeRowProps) {\n return (\n <div\n data-slot=\"trades-tape-row\"\n data-side={side}\n className={cn(TRADES_TAPE_ROW, className)}\n {...props}\n >\n <span className={cn(ORDER_BOOK_PRICE, bookSideClasses[side])}>{price}</span>\n <span>{size}</span>\n <span>{time}</span>\n </div>\n );\n}\n\n/**\n * The order form. Owns no state: the consumer wires the inputs and handles\n * `onSubmit`; the default is prevented here so a submit never navigates.\n */\nexport function OrderForm({ className, onSubmit, ...props }: React.ComponentProps<\"form\">) {\n return (\n <form\n data-slot=\"order-form\"\n className={cn(ORDER_FORM, className)}\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit?.(e);\n }}\n {...props}\n />\n );\n}\n\nexport interface OrderFormRowProps extends Omit<React.ComponentProps<\"div\">, \"children\"> {\n label: React.ReactNode;\n value: React.ReactNode;\n}\n\n/** A label / figure line in the order summary — cost, fee, what is available. */\nexport function OrderFormRow({ label, value, className, ...props }: OrderFormRowProps) {\n return (\n <div data-slot=\"order-form-row\" className={cn(ORDER_FORM_ROW, className)} {...props}>\n <span className={ORDER_FORM_LABEL}>{label}</span>\n <span className={ORDER_FORM_VALUE}>{value}</span>\n </div>\n );\n}\n\nexport interface OrderFormSubmitProps extends Omit<React.ComponentProps<\"button\">, \"type\"> {\n side?: OrderSide;\n}\n\n/** The submit, filled in the colour of the intent. */\nexport function OrderFormSubmit({ side = \"buy\", className, ...props }: OrderFormSubmitProps) {\n return (\n <button\n type=\"submit\"\n data-slot=\"order-form-submit\"\n data-side={side}\n className={cn(ORDER_FORM_SUBMIT_BASE, orderSideClasses[side], className)}\n {...props}\n />\n );\n}\n\n/** The open-orders pane with nothing in it. */\nexport function OpenOrdersEmpty({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div data-slot=\"open-orders-empty\" className={cn(OPEN_ORDERS_EMPTY, className)} {...props} />\n );\n}\n"],"mappings":";AAmDS,cAqFL,YArFK;AAjDT,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAgBA,SAAS,SAAS,EAAE,WAAW,GAAG,MAAM,GAAgC;AAC7E,SAAO,oBAAC,SAAI,aAAU,YAAW,WAAW,GAAG,eAAe,SAAS,GAAI,GAAG,OAAO;AACvF;AAUO,SAAS,aAAa,EAAE,MAAM,WAAW,GAAG,MAAM,GAAsB;AAC7E,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,aAAW;AAAA,MACX,WAAW,GAAG,eAAe,oBAAoB,IAAI,GAAG,SAAS;AAAA,MAChE,GAAG;AAAA;AAAA,EACN;AAEJ;AAEO,SAAS,mBAAmB,EAAE,WAAW,GAAG,MAAM,GAAmC;AAC1F,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,sBAAsB,SAAS;AAAA,MAC5C,GAAG;AAAA;AAAA,EACN;AAEJ;AAGO,SAAS,iBAAiB,EAAE,WAAW,GAAG,MAAM,GAAgC;AACrF,SACE,oBAAC,SAAI,aAAU,sBAAqB,WAAW,GAAG,oBAAoB,SAAS,GAAI,GAAG,OAAO;AAEjG;AAQO,MAAM,gBAAgB,MAAM,WAGjC,SAASA,eAAc,EAAE,WAAW,GAAG,MAAM,GAAG,KAAK;AACrD,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,aAAU;AAAA,MACV,WAAW,GAAG,gBAAgB,SAAS;AAAA,MACtC,GAAG;AAAA;AAAA,EACN;AAEJ,CAAC;AAMM,SAAS,eAAe,EAAE,WAAW,GAAG,MAAM,GAAgC;AACnF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,aAAU;AAAA,MACV,WAAW,GAAG,iBAAiB,oBAAoB,QAAQ,SAAS;AAAA,MACnE,GAAG;AAAA;AAAA,EACN;AAEJ;AAWO,SAAS,WAAW,EAAE,OAAO,OAAO,WAAW,GAAG,MAAM,GAAoB;AACjF,SACE,qBAAC,SAAI,aAAU,eAAc,WAAW,sBAAuB,GAAG,OAChE;AAAA,wBAAC,UAAK,WAAW,uBAAwB,iBAAM;AAAA,IAC/C,oBAAC,UAAK,WAAW,GAAG,uBAAuB,SAAS,GAAI,iBAAM;AAAA,KAChE;AAEJ;AAGO,SAAS,UAAU,EAAE,WAAW,GAAG,MAAM,GAAgC;AAC9E,SAAO,oBAAC,SAAI,aAAU,cAAa,WAAW,GAAG,YAAY,SAAS,GAAI,GAAG,OAAO;AACtF;AASO,SAAS,cAAc,EAAE,OAAO,MAAM,OAAO,WAAW,GAAG,MAAM,GAAuB;AAC7F,SACE,qBAAC,SAAI,aAAU,mBAAkB,WAAW,GAAG,iBAAiB,SAAS,GAAI,GAAG,OAC9E;AAAA,wBAAC,UAAM,iBAAM;AAAA,IACb,oBAAC,UAAM,gBAAK;AAAA,IACZ,oBAAC,UAAM,iBAAM;AAAA,KACf;AAEJ;AAeO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,aAAW;AAAA,MACX,WAAW,GAAG,gBAAgB,SAAS;AAAA,MACtC,GAAG;AAAA,MAEJ;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,eAAY;AAAA,YACZ,WAAW,GAAG,kBAAkB,iBAAiB,IAAI,CAAC;AAAA,YACtD,OAAO,EAAE,OAAO,GAAG,aAAa,KAAK,CAAC,IAAI;AAAA;AAAA,QAC5C;AAAA,QACA,oBAAC,UAAK,WAAW,GAAG,kBAAkB,gBAAgB,IAAI,CAAC,GAAI,iBAAM;AAAA,QACrE,oBAAC,UAAM,gBAAK;AAAA,QACZ,oBAAC,UAAM,iBAAM;AAAA;AAAA;AAAA,EACf;AAEJ;AAMA,SAAS,aAAa,OAAuB;AAC3C,MAAI,OAAO,MAAM,KAAK,EAAG,QAAO;AAChC,SAAO,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC,IAAI,GAAG;AACzD;AAMO,SAAS,gBAAgB,EAAE,WAAW,GAAG,MAAM,GAAgC;AACpF,SACE,oBAAC,SAAI,aAAU,qBAAoB,WAAW,GAAG,mBAAmB,SAAS,GAAI,GAAG,OAAO;AAE/F;AAUO,SAAS,cAAc,EAAE,MAAM,OAAO,MAAM,MAAM,WAAW,GAAG,MAAM,GAAuB;AAClG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,aAAW;AAAA,MACX,WAAW,GAAG,iBAAiB,SAAS;AAAA,MACvC,GAAG;AAAA,MAEJ;AAAA,4BAAC,UAAK,WAAW,GAAG,kBAAkB,gBAAgB,IAAI,CAAC,GAAI,iBAAM;AAAA,QACrE,oBAAC,UAAM,gBAAK;AAAA,QACZ,oBAAC,UAAM,gBAAK;AAAA;AAAA;AAAA,EACd;AAEJ;AAMO,SAAS,UAAU,EAAE,WAAW,UAAU,GAAG,MAAM,GAAiC;AACzF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,YAAY,SAAS;AAAA,MACnC,UAAU,CAAC,MAAM;AACf,UAAE,eAAe;AACjB,mBAAW,CAAC;AAAA,MACd;AAAA,MACC,GAAG;AAAA;AAAA,EACN;AAEJ;AAQO,SAAS,aAAa,EAAE,OAAO,OAAO,WAAW,GAAG,MAAM,GAAsB;AACrF,SACE,qBAAC,SAAI,aAAU,kBAAiB,WAAW,GAAG,gBAAgB,SAAS,GAAI,GAAG,OAC5E;AAAA,wBAAC,UAAK,WAAW,kBAAmB,iBAAM;AAAA,IAC1C,oBAAC,UAAK,WAAW,kBAAmB,iBAAM;AAAA,KAC5C;AAEJ;AAOO,SAAS,gBAAgB,EAAE,OAAO,OAAO,WAAW,GAAG,MAAM,GAAyB;AAC3F,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,aAAW;AAAA,MACX,WAAW,GAAG,wBAAwB,iBAAiB,IAAI,GAAG,SAAS;AAAA,MACtE,GAAG;AAAA;AAAA,EACN;AAEJ;AAGO,SAAS,gBAAgB,EAAE,WAAW,GAAG,MAAM,GAAgC;AACpF,SACE,oBAAC,SAAI,aAAU,qBAAoB,WAAW,GAAG,mBAAmB,SAAS,GAAI,GAAG,OAAO;AAE/F;","names":["TerminalChart"]}
@@ -1,70 +0,0 @@
1
- const TERMINAL_ROOT = "grid w-full grid-cols-1 gap-px bg-border text-ink text-sm lg:h-[calc(100dvh-var(--ev-shell-offset,0px))] lg:grid-cols-[minmax(0,1fr)_18rem_20rem] lg:grid-rows-[auto_minmax(0,1fr)_14rem]";
2
- const terminalAreaClasses = {
3
- "ticker": "lg:col-span-3 lg:row-start-1",
4
- "chart": "lg:col-start-1 lg:row-start-2",
5
- "book": "lg:col-start-2 lg:row-start-2",
6
- "form": "lg:col-start-3 lg:row-start-2",
7
- "orders": "lg:col-span-3 lg:row-start-3"
8
- };
9
- const TERMINAL_PANE = "flex min-h-0 min-w-0 flex-col overflow-hidden bg-card";
10
- const TERMINAL_PANE_HEADER = "flex h-9 shrink-0 items-center gap-2 border-b border-border px-3 text-xs font-medium text-ink-mid";
11
- const TERMINAL_PANE_BODY = "flex min-h-0 flex-1 flex-col overflow-auto";
12
- const TERMINAL_CHART = "relative min-h-[18rem] flex-1 overflow-hidden";
13
- const TERMINAL_TICKER = "flex min-w-0 items-center gap-6 overflow-x-auto bg-card px-4 py-2 whitespace-nowrap";
14
- const TERMINAL_TICKER_STAT = "flex shrink-0 flex-col gap-0.5";
15
- const TERMINAL_TICKER_LABEL = "text-[11px] uppercase tracking-wide text-ink-soft";
16
- const TERMINAL_TICKER_VALUE = "font-mono text-sm tabular-nums text-ink";
17
- const bookSideClasses = {
18
- "bid": "text-positive",
19
- "ask": "text-accent-error"
20
- };
21
- const bookDepthClasses = {
22
- "bid": "bg-positive/15",
23
- "ask": "bg-accent-error/15"
24
- };
25
- const ORDER_BOOK = "flex min-h-0 flex-1 flex-col font-mono text-xs tabular-nums";
26
- const ORDER_BOOK_HEAD = "grid shrink-0 grid-cols-3 gap-2 px-3 py-1.5 text-right text-[11px] text-ink-soft [&>*:first-child]:text-left";
27
- const ORDER_BOOK_ROW = "relative isolate grid cursor-pointer grid-cols-3 gap-2 px-3 py-0.5 text-right leading-5 hover:bg-hover";
28
- const ORDER_BOOK_PRICE = "text-left";
29
- const ORDER_BOOK_DEPTH = "pointer-events-none absolute inset-y-0 right-0 -z-10";
30
- const ORDER_BOOK_SPREAD = "flex shrink-0 items-center justify-between gap-2 border-y border-border bg-muted/50 px-3 py-1 text-ink-mid";
31
- const TRADES_TAPE_ROW = "grid grid-cols-3 gap-2 px-3 py-0.5 text-right font-mono text-xs leading-5 tabular-nums hover:bg-hover";
32
- const ORDER_FORM = "flex flex-col gap-3 p-3 text-sm";
33
- const ORDER_FORM_ROW = "flex items-center justify-between gap-2 text-xs";
34
- const ORDER_FORM_LABEL = "text-ink-soft";
35
- const ORDER_FORM_VALUE = "font-mono tabular-nums text-ink";
36
- const ORDER_FORM_SUBMIT_BASE = "inline-flex h-10 w-full shrink-0 cursor-pointer items-center justify-center rounded-[var(--control-radius)] text-sm font-semibold transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50";
37
- const orderSideClasses = {
38
- "buy": "bg-positive text-on-positive hover:bg-positive/90",
39
- "sell": "bg-accent-error text-on-accent-error hover:bg-accent-error/90"
40
- };
41
- const OPEN_ORDERS_EMPTY = "flex flex-1 items-center justify-center p-6 text-sm text-ink-soft";
42
- export {
43
- OPEN_ORDERS_EMPTY,
44
- ORDER_BOOK,
45
- ORDER_BOOK_DEPTH,
46
- ORDER_BOOK_HEAD,
47
- ORDER_BOOK_PRICE,
48
- ORDER_BOOK_ROW,
49
- ORDER_BOOK_SPREAD,
50
- ORDER_FORM,
51
- ORDER_FORM_LABEL,
52
- ORDER_FORM_ROW,
53
- ORDER_FORM_SUBMIT_BASE,
54
- ORDER_FORM_VALUE,
55
- TERMINAL_CHART,
56
- TERMINAL_PANE,
57
- TERMINAL_PANE_BODY,
58
- TERMINAL_PANE_HEADER,
59
- TERMINAL_ROOT,
60
- TERMINAL_TICKER,
61
- TERMINAL_TICKER_LABEL,
62
- TERMINAL_TICKER_STAT,
63
- TERMINAL_TICKER_VALUE,
64
- TRADES_TAPE_ROW,
65
- bookDepthClasses,
66
- bookSideClasses,
67
- orderSideClasses,
68
- terminalAreaClasses
69
- };
70
- //# sourceMappingURL=terminal.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/generated/terminal.ts"],"sourcesContent":["// AUTO-GENERATED by `nix run .#gen` — do not edit.\n\nexport const TERMINAL_ROOT = \"grid w-full grid-cols-1 gap-px bg-border text-ink text-sm lg:h-[calc(100dvh-var(--ev-shell-offset,0px))] lg:grid-cols-[minmax(0,1fr)_18rem_20rem] lg:grid-rows-[auto_minmax(0,1fr)_14rem]\";\n\nexport const terminalAreaClasses = {\n \"ticker\": \"lg:col-span-3 lg:row-start-1\",\n \"chart\": \"lg:col-start-1 lg:row-start-2\",\n \"book\": \"lg:col-start-2 lg:row-start-2\",\n \"form\": \"lg:col-start-3 lg:row-start-2\",\n \"orders\": \"lg:col-span-3 lg:row-start-3\",\n} as const;\nexport type TerminalArea = keyof typeof terminalAreaClasses;\n\nexport const TERMINAL_PANE = \"flex min-h-0 min-w-0 flex-col overflow-hidden bg-card\";\n\nexport const TERMINAL_PANE_HEADER = \"flex h-9 shrink-0 items-center gap-2 border-b border-border px-3 text-xs font-medium text-ink-mid\";\n\nexport const TERMINAL_PANE_BODY = \"flex min-h-0 flex-1 flex-col overflow-auto\";\n\nexport const TERMINAL_CHART = \"relative min-h-[18rem] flex-1 overflow-hidden\";\n\nexport const TERMINAL_TICKER = \"flex min-w-0 items-center gap-6 overflow-x-auto bg-card px-4 py-2 whitespace-nowrap\";\n\nexport const TERMINAL_TICKER_STAT = \"flex shrink-0 flex-col gap-0.5\";\n\nexport const TERMINAL_TICKER_LABEL = \"text-[11px] uppercase tracking-wide text-ink-soft\";\n\nexport const TERMINAL_TICKER_VALUE = \"font-mono text-sm tabular-nums text-ink\";\n\nexport const bookSideClasses = {\n \"bid\": \"text-positive\",\n \"ask\": \"text-accent-error\",\n} as const;\nexport type BookSide = keyof typeof bookSideClasses;\n\nexport const bookDepthClasses = {\n \"bid\": \"bg-positive/15\",\n \"ask\": \"bg-accent-error/15\",\n} as const;\nexport type BookDepthSide = keyof typeof bookDepthClasses;\n\nexport const ORDER_BOOK = \"flex min-h-0 flex-1 flex-col font-mono text-xs tabular-nums\";\n\nexport const ORDER_BOOK_HEAD = \"grid shrink-0 grid-cols-3 gap-2 px-3 py-1.5 text-right text-[11px] text-ink-soft [&>*:first-child]:text-left\";\n\nexport const ORDER_BOOK_ROW = \"relative isolate grid cursor-pointer grid-cols-3 gap-2 px-3 py-0.5 text-right leading-5 hover:bg-hover\";\n\nexport const ORDER_BOOK_PRICE = \"text-left\";\n\nexport const ORDER_BOOK_DEPTH = \"pointer-events-none absolute inset-y-0 right-0 -z-10\";\n\nexport const ORDER_BOOK_SPREAD = \"flex shrink-0 items-center justify-between gap-2 border-y border-border bg-muted/50 px-3 py-1 text-ink-mid\";\n\nexport const TRADES_TAPE_ROW = \"grid grid-cols-3 gap-2 px-3 py-0.5 text-right font-mono text-xs leading-5 tabular-nums hover:bg-hover\";\n\nexport const ORDER_FORM = \"flex flex-col gap-3 p-3 text-sm\";\n\nexport const ORDER_FORM_ROW = \"flex items-center justify-between gap-2 text-xs\";\n\nexport const ORDER_FORM_LABEL = \"text-ink-soft\";\n\nexport const ORDER_FORM_VALUE = \"font-mono tabular-nums text-ink\";\n\nexport const ORDER_FORM_SUBMIT_BASE = \"inline-flex h-10 w-full shrink-0 cursor-pointer items-center justify-center rounded-[var(--control-radius)] text-sm font-semibold transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50\";\n\nexport const orderSideClasses = {\n \"buy\": \"bg-positive text-on-positive hover:bg-positive/90\",\n \"sell\": \"bg-accent-error text-on-accent-error hover:bg-accent-error/90\",\n} as const;\nexport type OrderSide = keyof typeof orderSideClasses;\n\nexport const OPEN_ORDERS_EMPTY = \"flex flex-1 items-center justify-center p-6 text-sm text-ink-soft\";\n"],"mappings":"AAEO,MAAM,gBAAgB;AAEtB,MAAM,sBAAsB;AAAA,EACjC,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,UAAU;AACZ;AAGO,MAAM,gBAAgB;AAEtB,MAAM,uBAAuB;AAE7B,MAAM,qBAAqB;AAE3B,MAAM,iBAAiB;AAEvB,MAAM,kBAAkB;AAExB,MAAM,uBAAuB;AAE7B,MAAM,wBAAwB;AAE9B,MAAM,wBAAwB;AAE9B,MAAM,kBAAkB;AAAA,EAC7B,OAAO;AAAA,EACP,OAAO;AACT;AAGO,MAAM,mBAAmB;AAAA,EAC9B,OAAO;AAAA,EACP,OAAO;AACT;AAGO,MAAM,aAAa;AAEnB,MAAM,kBAAkB;AAExB,MAAM,iBAAiB;AAEvB,MAAM,mBAAmB;AAEzB,MAAM,mBAAmB;AAEzB,MAAM,oBAAoB;AAE1B,MAAM,kBAAkB;AAExB,MAAM,aAAa;AAEnB,MAAM,iBAAiB;AAEvB,MAAM,mBAAmB;AAEzB,MAAM,mBAAmB;AAEzB,MAAM,yBAAyB;AAE/B,MAAM,mBAAmB;AAAA,EAC9B,OAAO;AAAA,EACP,QAAQ;AACV;AAGO,MAAM,oBAAoB;","names":[]}