@opencode/ui 2.1.1 → 2.1.3

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.
@@ -0,0 +1,68 @@
1
+ export declare const OpenCodeTheme: {
2
+ name: string;
3
+ appearance: "dark";
4
+ cssVariables: {
5
+ prefix: string;
6
+ };
7
+ style: {
8
+ "editor.background": string;
9
+ "editor.foreground": string;
10
+ created: string;
11
+ deleted: string;
12
+ modified: string;
13
+ syntax: {
14
+ attribute: string;
15
+ background: string;
16
+ boolean: string;
17
+ comment: string;
18
+ constant: string;
19
+ constructor: string;
20
+ "diff.minus": string;
21
+ "diff.plus": string;
22
+ embedded: string;
23
+ emphasis: string;
24
+ enum: string;
25
+ foreground: string;
26
+ function: string;
27
+ hint: string;
28
+ keyword: string;
29
+ "keyword.operator": string;
30
+ label: string;
31
+ link_text: string;
32
+ link_uri: string;
33
+ namespace: string;
34
+ number: string;
35
+ operator: string;
36
+ predictive: {
37
+ color: string;
38
+ font_style: "italic";
39
+ };
40
+ preproc: string;
41
+ primary: string;
42
+ property: string;
43
+ punctuation: string;
44
+ "punctuation.special": string;
45
+ selector: string;
46
+ "selector.class": string;
47
+ "selector.id": string;
48
+ "selector.pseudo": string;
49
+ string: string;
50
+ "string.escape": string;
51
+ "string.regex": string;
52
+ "string.special": string;
53
+ tag: string;
54
+ "tag.component.jsx": string;
55
+ text: string;
56
+ "text.literal": string;
57
+ title: {
58
+ color: string;
59
+ font_weight: 700;
60
+ };
61
+ type: string;
62
+ variable: string;
63
+ "variable.parameter": string;
64
+ "variable.special": string;
65
+ variant: string;
66
+ };
67
+ };
68
+ };
@@ -1,3 +1,3 @@
1
1
  import type { MarkedExtension } from "marked";
2
- export declare function createMarkdownParser(highlight: (code: string, language: string) => string | Promise<string>): import("marked").Marked<string, string>;
2
+ export declare function createMarkdownParser(): import("marked").Marked<string, string>;
3
3
  export declare const markdownMath: MarkedExtension;
package/dist/i18n/en.d.ts CHANGED
@@ -70,10 +70,13 @@ declare const source: {
70
70
  "ui.sessionTurn.retry.attemptWaiting.other": string;
71
71
  "ui.sessionTurn.retry.attemptRetryingNow": string;
72
72
  "ui.sessionTurn.retry.geminiHot": string;
73
+ "ui.sessionTurn.freeLimit.title": string;
74
+ "ui.sessionTurn.freeLimit.lineReset": string;
73
75
  "ui.sessionTurn.error.freeUsageExceeded": string;
74
76
  "ui.sessionTurn.error.addCredits": string;
75
77
  "dialog.usageExceeded.freeTier.title": string;
76
78
  "dialog.usageExceeded.freeTier.description": string;
79
+ "dialog.usageExceeded.freeTier.reset": string;
77
80
  "dialog.usageExceeded.freeTier.actionLabel": string;
78
81
  "dialog.usageExceeded.accountRateLimit.title": string;
79
82
  "dialog.usageExceeded.accountRateLimit.description": string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencode/ui",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -235,7 +235,7 @@
235
235
  "devDependencies": {
236
236
  "@solidjs/meta": "0.29.4",
237
237
  "@tsconfig/node22": "22.0.2",
238
- "@types/bun": "1.4.0",
238
+ "@types/bun": "1.4.3",
239
239
  "@typescript/native": "npm:typescript@7.0.2",
240
240
  "solid-js": "1.9.15",
241
241
  "tailwindcss": "4.1.11",
@@ -247,16 +247,15 @@
247
247
  "dependencies": {
248
248
  "@kitlangton/solid-motion": "0.2.2",
249
249
  "@kobalte/core": "0.13.13",
250
- "@pierre/diffs": "1.5.1",
250
+ "@pierre/diffs": "1.6.1",
251
+ "@pierre/highlights": "0.2.0",
251
252
  "@solid-primitives/event-listener": "2.4.6",
252
253
  "@solid-primitives/resize-observer": "2.2.0",
253
254
  "fuzzysort": "3.1.0",
254
255
  "katex": "0.16.47",
255
256
  "marked": "18.0.11",
256
- "marked-shiki": "1.2.1",
257
257
  "motion": "12.34.5",
258
258
  "remeda": "2.26.0",
259
- "shiki": "4.4.3",
260
259
  "solid-list": "0.3.0",
261
260
  "solid-sonner": "0.3.1"
262
261
  },
@@ -0,0 +1,66 @@
1
+ import type { Theme } from "@pierre/highlights"
2
+
3
+ // A Highlights palette: each value names an app CSS variable without its `--`, so code follows the active app theme.
4
+ // Token types are grouped as in Pierre's own `pierre-dark` theme (for example, properties share the variable colour
5
+ // and all punctuation is one muted colour); each group uses the app syntax role with the same meaning.
6
+ // Token names fall back to their parent scope, so `keyword.control` uses `keyword`.
7
+ export const OpenCodeTheme = {
8
+ name: "OpenCode",
9
+ appearance: "dark",
10
+ cssVariables: { prefix: "--" },
11
+ style: {
12
+ "editor.background": "color-background-stronger",
13
+ "editor.foreground": "text-base",
14
+ created: "syntax-diff-add",
15
+ deleted: "syntax-diff-delete",
16
+ modified: "syntax-diff-unknown",
17
+ syntax: {
18
+ attribute: "syntax-property",
19
+ background: "color-background-stronger",
20
+ boolean: "syntax-constant",
21
+ comment: "syntax-comment",
22
+ constant: "syntax-constant",
23
+ constructor: "syntax-type",
24
+ "diff.minus": "syntax-diff-delete",
25
+ "diff.plus": "syntax-diff-add",
26
+ embedded: "text-base",
27
+ emphasis: "text-base",
28
+ enum: "syntax-type",
29
+ foreground: "text-base",
30
+ function: "syntax-primitive",
31
+ hint: "syntax-comment",
32
+ keyword: "syntax-keyword",
33
+ "keyword.operator": "syntax-operator",
34
+ label: "syntax-constant",
35
+ link_text: "syntax-info",
36
+ link_uri: "syntax-keyword",
37
+ namespace: "syntax-constant",
38
+ number: "syntax-constant",
39
+ operator: "syntax-operator",
40
+ predictive: { color: "syntax-comment", font_style: "italic" },
41
+ preproc: "syntax-keyword",
42
+ primary: "syntax-info",
43
+ property: "syntax-variable",
44
+ punctuation: "syntax-punctuation",
45
+ "punctuation.special": "syntax-keyword",
46
+ selector: "syntax-keyword",
47
+ "selector.class": "syntax-property",
48
+ "selector.id": "syntax-primitive",
49
+ "selector.pseudo": "syntax-operator",
50
+ string: "syntax-string",
51
+ "string.escape": "syntax-constant",
52
+ "string.regex": "syntax-regexp",
53
+ "string.special": "syntax-constant",
54
+ tag: "syntax-keyword",
55
+ "tag.component.jsx": "syntax-type",
56
+ text: "text-base",
57
+ "text.literal": "syntax-string",
58
+ title: { color: "syntax-keyword", font_weight: 700 },
59
+ type: "syntax-type",
60
+ variable: "syntax-variable",
61
+ "variable.parameter": "text-base",
62
+ "variable.special": "syntax-constant",
63
+ variant: "syntax-constant",
64
+ },
65
+ },
66
+ } satisfies Theme
@@ -1,10 +1,28 @@
1
+ import { codeToHtml, isSupportedLanguage } from "@pierre/highlights"
1
2
  import katex from "katex"
2
3
  import type { MarkedExtension, Tokens } from "marked"
3
- import markedShiki from "marked-shiki"
4
4
  import { createMarkdownBase } from "./marked-base"
5
+ import { OpenCodeTheme } from "./highlight-theme"
5
6
 
6
- export function createMarkdownParser(highlight: (code: string, language: string) => string | Promise<string>) {
7
- return createMarkdownBase().use(markdownMath, markedShiki({ highlight }))
7
+ export function createMarkdownParser() {
8
+ return createMarkdownBase().use(markdownMath, markdownCode)
9
+ }
10
+
11
+ const decoder = new TextDecoder()
12
+
13
+ // The class keeps the fence's own language, even one without a lexer, so the viewer can label it and render Mermaid.
14
+ const markdownCode: MarkedExtension = {
15
+ renderer: {
16
+ code(token) {
17
+ const language = (token.lang?.match(/^\S*/)?.[0] ?? "").toLowerCase().replace(/[^\w#+.-]/g, "") || "text"
18
+
19
+ const html = decoder.decode(
20
+ codeToHtml(token.text, { lang: isSupportedLanguage(language) ? language : "text", theme: OpenCodeTheme }),
21
+ )
22
+
23
+ return html.replace("<code>", `<code class="language-${language}">`) + "\n"
24
+ },
25
+ },
8
26
  }
9
27
 
10
28
  // `$$...$$` renders as display math anywhere in a line.
package/src/i18n/en.ts CHANGED
@@ -75,12 +75,15 @@ const source = {
75
75
  "ui.sessionTurn.retry.attemptWaiting.other": "Attempt {{attempt}} - retrying in {{count}}s",
76
76
  "ui.sessionTurn.retry.attemptRetryingNow": "Attempt {{attempt}} - retrying",
77
77
  "ui.sessionTurn.retry.geminiHot": "gemini is way too hot right now",
78
+ "ui.sessionTurn.freeLimit.title": "You've used today's free messages.",
79
+ "ui.sessionTurn.freeLimit.lineReset": "You've used today's free messages. They reset at {{time}}.",
78
80
  "ui.sessionTurn.error.freeUsageExceeded": "Free usage exceeded",
79
81
  "ui.sessionTurn.error.addCredits": "Add credits",
80
82
 
81
83
  "dialog.usageExceeded.freeTier.title": "Free limit reached",
82
84
  "dialog.usageExceeded.freeTier.description":
83
85
  "Subscribe to OpenCode Go for reliable access to the best open-source models for $10/month.",
86
+ "dialog.usageExceeded.freeTier.reset": "Your free messages reset at {{time}}.",
84
87
  "dialog.usageExceeded.freeTier.actionLabel": "Subscribe",
85
88
  "dialog.usageExceeded.accountRateLimit.title": "Go limit reached",
86
89
  "dialog.usageExceeded.accountRateLimit.description":
@@ -1 +0,0 @@
1
- export declare function registerOpenCodeTheme(): void;
@@ -1,2 +0,0 @@
1
- import type { ThemeRegistrationResolved } from "@pierre/diffs";
2
- export declare const OpenCodeTheme: ThemeRegistrationResolved;
@@ -1,2 +0,0 @@
1
- export { OpenCodeTheme } from "./marked-theme";
2
- export declare const useMarked: () => import("marked").Marked<string, string>, MarkedProvider: (props: import("solid-js").ParentProps<Record<string, any>>) => import("solid-js").JSX.Element;
@@ -1,10 +0,0 @@
1
- import { registerCustomTheme } from "@pierre/diffs"
2
- import { OpenCodeTheme } from "./marked-theme"
3
-
4
- let registered = false
5
-
6
- export function registerOpenCodeTheme() {
7
- if (registered) return
8
- registered = true
9
- registerCustomTheme("OpenCode", () => Promise.resolve(OpenCodeTheme))
10
- }
@@ -1,372 +0,0 @@
1
- import type { ThemeRegistrationResolved } from "@pierre/diffs"
2
-
3
- export const OpenCodeTheme = {
4
- name: "OpenCode",
5
- bg: "var(--color-background-stronger)",
6
- fg: "var(--text-base)",
7
- colors: {
8
- "editor.background": "var(--color-background-stronger)",
9
- "editor.foreground": "var(--text-base)",
10
- "gitDecoration.addedResourceForeground": "var(--syntax-diff-add)",
11
- "gitDecoration.deletedResourceForeground": "var(--syntax-diff-delete)",
12
- "gitDecoration.modifiedResourceForeground": "var(--syntax-diff-unknown)",
13
- // "gitDecoration.conflictingResourceForeground": "#ffca00",
14
- // "gitDecoration.modifiedResourceForeground": "#1a76d4",
15
- // "gitDecoration.untrackedResourceForeground": "#00cab1",
16
- // "gitDecoration.ignoredResourceForeground": "#84848A",
17
- // "terminal.titleForeground": "#adadb1",
18
- // "terminal.titleInactiveForeground": "#84848A",
19
- // "terminal.background": "#141415",
20
- // "terminal.foreground": "#adadb1",
21
- // "terminal.ansiBlack": "#141415",
22
- // "terminal.ansiRed": "#ff2e3f",
23
- // "terminal.ansiGreen": "#0dbe4e",
24
- // "terminal.ansiYellow": "#ffca00",
25
- // "terminal.ansiBlue": "#008cff",
26
- // "terminal.ansiMagenta": "#c635e4",
27
- // "terminal.ansiCyan": "#08c0ef",
28
- // "terminal.ansiWhite": "#c6c6c8",
29
- // "terminal.ansiBrightBlack": "#141415",
30
- // "terminal.ansiBrightRed": "#ff2e3f",
31
- // "terminal.ansiBrightGreen": "#0dbe4e",
32
- // "terminal.ansiBrightYellow": "#ffca00",
33
- // "terminal.ansiBrightBlue": "#008cff",
34
- // "terminal.ansiBrightMagenta": "#c635e4",
35
- // "terminal.ansiBrightCyan": "#08c0ef",
36
- // "terminal.ansiBrightWhite": "#c6c6c8",
37
- },
38
- tokenColors: [
39
- {
40
- scope: ["comment", "punctuation.definition.comment", "string.comment"],
41
- settings: {
42
- foreground: "var(--syntax-comment)",
43
- },
44
- },
45
- {
46
- scope: ["entity.other.attribute-name"],
47
- settings: {
48
- foreground: "var(--syntax-property)", // maybe attribute
49
- },
50
- },
51
- {
52
- scope: ["constant", "entity.name.constant", "variable.other.constant", "variable.language", "entity"],
53
- settings: {
54
- foreground: "var(--syntax-constant)",
55
- },
56
- },
57
- {
58
- scope: ["entity.name", "meta.export.default", "meta.definition.variable"],
59
- settings: {
60
- foreground: "var(--syntax-type)",
61
- },
62
- },
63
- {
64
- scope: ["meta.object.member"],
65
- settings: {
66
- foreground: "var(--syntax-primitive)",
67
- },
68
- },
69
- {
70
- scope: [
71
- "variable.parameter.function",
72
- "meta.jsx.children",
73
- "meta.block",
74
- "meta.tag.attributes",
75
- "entity.name.constant",
76
- "meta.embedded.expression",
77
- "meta.template.expression",
78
- "string.other.begin.yaml",
79
- "string.other.end.yaml",
80
- ],
81
- settings: {
82
- foreground: "var(--syntax-punctuation)",
83
- },
84
- },
85
- {
86
- scope: ["entity.name.function", "support.type.primitive"],
87
- settings: {
88
- foreground: "var(--syntax-primitive)",
89
- },
90
- },
91
- {
92
- scope: ["support.class.component"],
93
- settings: {
94
- foreground: "var(--syntax-type)",
95
- },
96
- },
97
- {
98
- scope: "keyword",
99
- settings: {
100
- foreground: "var(--syntax-keyword)",
101
- },
102
- },
103
- {
104
- scope: [
105
- "keyword.operator",
106
- "storage.type.function.arrow",
107
- "punctuation.separator.key-value.css",
108
- "entity.name.tag.yaml",
109
- "punctuation.separator.key-value.mapping.yaml",
110
- ],
111
- settings: {
112
- foreground: "var(--syntax-operator)",
113
- },
114
- },
115
- {
116
- scope: ["storage", "storage.type"],
117
- settings: {
118
- foreground: "var(--syntax-keyword)",
119
- },
120
- },
121
- {
122
- scope: ["storage.modifier.package", "storage.modifier.import", "storage.type.java"],
123
- settings: {
124
- foreground: "var(--syntax-primitive)",
125
- },
126
- },
127
- {
128
- scope: [
129
- "string",
130
- "punctuation.definition.string",
131
- "string punctuation.section.embedded source",
132
- "entity.name.tag",
133
- ],
134
- settings: {
135
- foreground: "var(--syntax-string)",
136
- },
137
- },
138
- {
139
- scope: "support",
140
- settings: {
141
- foreground: "var(--syntax-primitive)",
142
- },
143
- },
144
- {
145
- scope: ["support.type.object.module", "variable.other.object", "support.type.property-name.css"],
146
- settings: {
147
- foreground: "var(--syntax-object)",
148
- },
149
- },
150
- {
151
- scope: "meta.property-name",
152
- settings: {
153
- foreground: "var(--syntax-property)",
154
- },
155
- },
156
- {
157
- scope: "variable",
158
- settings: {
159
- foreground: "var(--syntax-variable)",
160
- },
161
- },
162
- {
163
- scope: "variable.other",
164
- settings: {
165
- foreground: "var(--syntax-variable)",
166
- },
167
- },
168
- {
169
- scope: [
170
- "invalid.broken",
171
- "invalid.illegal",
172
- "invalid.unimplemented",
173
- "invalid.deprecated",
174
- "message.error",
175
- "markup.deleted",
176
- "meta.diff.header.from-file",
177
- "punctuation.definition.deleted",
178
- "brackethighlighter.unmatched",
179
- "token.error-token",
180
- ],
181
- settings: {
182
- foreground: "var(--syntax-critical)",
183
- },
184
- },
185
- {
186
- scope: "carriage-return",
187
- settings: {
188
- foreground: "var(--syntax-keyword)",
189
- },
190
- },
191
- {
192
- scope: "string source",
193
- settings: {
194
- foreground: "var(--syntax-variable)",
195
- },
196
- },
197
- {
198
- scope: "string variable",
199
- settings: {
200
- foreground: "var(--syntax-constant)",
201
- },
202
- },
203
- {
204
- scope: [
205
- "source.regexp",
206
- "string.regexp",
207
- "string.regexp.character-class",
208
- "string.regexp constant.character.escape",
209
- "string.regexp source.ruby.embedded",
210
- "string.regexp string.regexp.arbitrary-repitition",
211
- "string.regexp constant.character.escape",
212
- ],
213
- settings: {
214
- foreground: "var(--syntax-regexp)",
215
- },
216
- },
217
- {
218
- scope: "support.constant",
219
- settings: {
220
- foreground: "var(--syntax-primitive)",
221
- },
222
- },
223
- {
224
- scope: "support.variable",
225
- settings: {
226
- foreground: "var(--syntax-variable)",
227
- },
228
- },
229
- {
230
- scope: "meta.module-reference",
231
- settings: {
232
- foreground: "var(--syntax-info)",
233
- },
234
- },
235
- {
236
- scope: "punctuation.definition.list.begin.markdown",
237
- settings: {
238
- foreground: "var(--syntax-punctuation)",
239
- },
240
- },
241
- {
242
- scope: ["markup.heading", "markup.heading entity.name"],
243
- settings: {
244
- fontStyle: "bold",
245
- foreground: "var(--syntax-info)",
246
- },
247
- },
248
- {
249
- scope: "markup.quote",
250
- settings: {
251
- foreground: "var(--syntax-info)",
252
- },
253
- },
254
- {
255
- scope: "markup.italic",
256
- settings: {
257
- fontStyle: "italic",
258
- // foreground: "",
259
- },
260
- },
261
- {
262
- scope: "markup.bold",
263
- settings: {
264
- fontStyle: "bold",
265
- foreground: "var(--text-strong)",
266
- },
267
- },
268
- {
269
- scope: [
270
- "markup.raw",
271
- "markup.inserted",
272
- "meta.diff.header.to-file",
273
- "punctuation.definition.inserted",
274
- "markup.changed",
275
- "punctuation.definition.changed",
276
- "markup.ignored",
277
- "markup.untracked",
278
- ],
279
- settings: {
280
- foreground: "var(--text-base)",
281
- },
282
- },
283
- {
284
- scope: "meta.diff.range",
285
- settings: {
286
- fontStyle: "bold",
287
- foreground: "var(--syntax-unknown)",
288
- },
289
- },
290
- {
291
- scope: "meta.diff.header",
292
- settings: {
293
- foreground: "var(--syntax-unknown)",
294
- },
295
- },
296
- {
297
- scope: "meta.separator",
298
- settings: {
299
- fontStyle: "bold",
300
- foreground: "var(--syntax-unknown)",
301
- },
302
- },
303
- {
304
- scope: "meta.output",
305
- settings: {
306
- foreground: "var(--syntax-unknown)",
307
- },
308
- },
309
- {
310
- scope: "meta.export.default",
311
- settings: {
312
- foreground: "var(--syntax-unknown)",
313
- },
314
- },
315
- {
316
- scope: [
317
- "brackethighlighter.tag",
318
- "brackethighlighter.curly",
319
- "brackethighlighter.round",
320
- "brackethighlighter.square",
321
- "brackethighlighter.angle",
322
- "brackethighlighter.quote",
323
- ],
324
- settings: {
325
- foreground: "var(--syntax-unknown)",
326
- },
327
- },
328
- {
329
- scope: ["constant.other.reference.link", "string.other.link"],
330
- settings: {
331
- fontStyle: "underline",
332
- foreground: "var(--syntax-unknown)",
333
- },
334
- },
335
- {
336
- scope: "token.info-token",
337
- settings: {
338
- foreground: "var(--syntax-info)",
339
- },
340
- },
341
- {
342
- scope: "token.warn-token",
343
- settings: {
344
- foreground: "var(--syntax-warning)",
345
- },
346
- },
347
- {
348
- scope: "token.debug-token",
349
- settings: {
350
- foreground: "var(--syntax-info)",
351
- },
352
- },
353
- ],
354
- semanticTokenColors: {
355
- comment: "var(--syntax-comment)",
356
- string: "var(--syntax-string)",
357
- number: "var(--syntax-constant)",
358
- regexp: "var(--syntax-regexp)",
359
- keyword: "var(--syntax-keyword)",
360
- variable: "var(--syntax-variable)",
361
- parameter: "var(--syntax-variable)",
362
- property: "var(--syntax-property)",
363
- function: "var(--syntax-primitive)",
364
- method: "var(--syntax-primitive)",
365
- type: "var(--syntax-type)",
366
- class: "var(--syntax-type)",
367
- namespace: "var(--syntax-type)",
368
- enumMember: "var(--syntax-primitive)",
369
- "variable.constant": "var(--syntax-constant)",
370
- "variable.defaultLibrary": "var(--syntax-unknown)",
371
- },
372
- } as unknown as ThemeRegistrationResolved
@@ -1,31 +0,0 @@
1
- import { getSharedHighlighter } from "@pierre/diffs"
2
- import { bundledLanguages, type BundledLanguage } from "shiki"
3
- import { createSimpleContext } from "./helper"
4
- import { createMarkdownParser } from "./marked-parser"
5
- import { registerOpenCodeTheme } from "./marked-theme-register"
6
-
7
- export { OpenCodeTheme } from "./marked-theme"
8
-
9
- registerOpenCodeTheme()
10
-
11
- export const { use: useMarked, provider: MarkedProvider } = createSimpleContext({
12
- name: "Marked",
13
- init: () =>
14
- createMarkdownParser(async (code, language) => {
15
- const highlighter = await getSharedHighlighter({
16
- themes: ["OpenCode"],
17
- langs: [],
18
- preferredHighlighter: "shiki-wasm",
19
- })
20
-
21
- const name = language in bundledLanguages ? language : "text"
22
-
23
- if (!highlighter.getLoadedLanguages().includes(name)) await highlighter.loadLanguage(name as BundledLanguage)
24
-
25
- return highlighter.codeToHtml(code, {
26
- lang: name,
27
- theme: "OpenCode",
28
- tabindex: false,
29
- })
30
- }),
31
- })