@opencode-ai/theme 0.0.0-next-16413

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,437 @@
1
+ export const DEFAULT_CATEGORICAL = [
2
+ "blue",
3
+ "purple",
4
+ "green",
5
+ "orange",
6
+ "red",
7
+ "cyan",
8
+ ];
9
+ export const DEFAULT_THEME = {
10
+ version: 2,
11
+ light: {
12
+ hue: {
13
+ gray: {
14
+ 100: "#f3f4f6",
15
+ 200: "#e5e7eb",
16
+ 300: "#d1d5db",
17
+ 400: "#9ca3af",
18
+ 500: "#6b7280",
19
+ 600: "#4b5563",
20
+ 700: "#374151",
21
+ 800: "#1f2937",
22
+ 900: "#111827",
23
+ },
24
+ red: {
25
+ 100: "#fee2e2",
26
+ 200: "#fecaca",
27
+ 300: "#fca5a5",
28
+ 400: "#f87171",
29
+ 500: "#ef4444",
30
+ 600: "#dc2626",
31
+ 700: "#b91c1c",
32
+ 800: "#991b1b",
33
+ 900: "#7f1d1d",
34
+ },
35
+ orange: {
36
+ 100: "#ffedd5",
37
+ 200: "#fed7aa",
38
+ 300: "#fdba74",
39
+ 400: "#fb923c",
40
+ 500: "#f97316",
41
+ 600: "#ea580c",
42
+ 700: "#c2410c",
43
+ 800: "#9a3412",
44
+ 900: "#7c2d12",
45
+ },
46
+ yellow: {
47
+ 100: "#fef9c3",
48
+ 200: "#fef08a",
49
+ 300: "#fde047",
50
+ 400: "#facc15",
51
+ 500: "#eab308",
52
+ 600: "#ca8a04",
53
+ 700: "#a16207",
54
+ 800: "#854d0e",
55
+ 900: "#713f12",
56
+ },
57
+ green: {
58
+ 100: "#dcfce7",
59
+ 200: "#bbf7d0",
60
+ 300: "#86efac",
61
+ 400: "#4ade80",
62
+ 500: "#22c55e",
63
+ 600: "#16a34a",
64
+ 700: "#15803d",
65
+ 800: "#166534",
66
+ 900: "#14532d",
67
+ },
68
+ cyan: {
69
+ 100: "#cffafe",
70
+ 200: "#a5f3fc",
71
+ 300: "#67e8f9",
72
+ 400: "#22d3ee",
73
+ 500: "#06b6d4",
74
+ 600: "#0891b2",
75
+ 700: "#0e7490",
76
+ 800: "#155e75",
77
+ 900: "#164e63",
78
+ },
79
+ blue: {
80
+ 100: "#dbeafe",
81
+ 200: "#bfdbfe",
82
+ 300: "#93c5fd",
83
+ 400: "#60a5fa",
84
+ 500: "#3b82f6",
85
+ 600: "#2563eb",
86
+ 700: "#1d4ed8",
87
+ 800: "#1e40af",
88
+ 900: "#1e3a8a",
89
+ },
90
+ purple: {
91
+ 100: "#f3e8ff",
92
+ 200: "#e9d5ff",
93
+ 300: "#d8b4fe",
94
+ 400: "#c084fc",
95
+ 500: "#a855f7",
96
+ 600: "#9333ea",
97
+ 700: "#7e22ce",
98
+ 800: "#6b21a8",
99
+ 900: "#581c87",
100
+ },
101
+ accent: "$hue.blue",
102
+ interactive: "$hue.blue",
103
+ neutral: "$hue.gray",
104
+ },
105
+ categorical: DEFAULT_CATEGORICAL,
106
+ text: {
107
+ default: "$hue.neutral.800",
108
+ subdued: "$hue.neutral.600",
109
+ action: {
110
+ primary: { default: "$hue.neutral.200", $disabled: "$hue.neutral.500" },
111
+ destructive: { default: "$hue.red.200", $disabled: "$hue.neutral.500" },
112
+ },
113
+ formfield: {
114
+ default: "$hue.neutral.800",
115
+ $focused: "$text.action.primary.default",
116
+ $pressed: "$hue.neutral.200",
117
+ $disabled: "$hue.neutral.500",
118
+ $selected: "$hue.interactive.700",
119
+ },
120
+ feedback: {
121
+ error: { default: "$hue.red.700", subdued: "$hue.red.600" },
122
+ warning: { default: "$hue.yellow.800", subdued: "$hue.yellow.700" },
123
+ success: { default: "$hue.green.700", subdued: "$hue.green.600" },
124
+ info: { default: "$hue.cyan.700", subdued: "$hue.cyan.600" },
125
+ },
126
+ },
127
+ background: {
128
+ default: "$hue.neutral.200",
129
+ surface: {
130
+ offset: "$hue.neutral.300",
131
+ overlay: "$hue.neutral.400",
132
+ },
133
+ action: {
134
+ primary: {
135
+ default: "$hue.interactive.600",
136
+ $hovered: "$hue.interactive.700",
137
+ $focused: "$hue.interactive.700",
138
+ $pressed: "$hue.interactive.800",
139
+ $selected: "$hue.interactive.700",
140
+ $disabled: "$hue.neutral.300",
141
+ },
142
+ destructive: {
143
+ default: "$hue.red.600",
144
+ $hovered: "$hue.red.700",
145
+ $focused: "$hue.red.700",
146
+ $pressed: "$hue.red.800",
147
+ $selected: "$hue.red.700",
148
+ $disabled: "$hue.neutral.300",
149
+ },
150
+ },
151
+ formfield: {
152
+ default: "$background.default",
153
+ $hovered: "$background.surface.offset",
154
+ $focused: "$background.action.primary.default",
155
+ $pressed: "$hue.interactive.800",
156
+ $disabled: "$background.default",
157
+ $selected: "$background.formfield.default",
158
+ },
159
+ feedback: {
160
+ error: { default: "$background.default" },
161
+ warning: { default: "$background.default" },
162
+ success: { default: "$background.default" },
163
+ info: { default: "$background.default" },
164
+ },
165
+ },
166
+ border: { default: "$hue.neutral.300" },
167
+ scrollbar: { default: "$hue.neutral.400" },
168
+ diff: {
169
+ text: {
170
+ added: "$hue.green.700",
171
+ removed: "$hue.red.700",
172
+ context: "$hue.neutral.900",
173
+ hunkHeader: "$hue.purple.600",
174
+ },
175
+ background: { added: "$hue.green.100", removed: "$hue.red.100", context: "$hue.neutral.100" },
176
+ highlight: { added: "$hue.green.600", removed: "$hue.red.600" },
177
+ lineNumber: {
178
+ text: "$hue.neutral.600",
179
+ background: { added: "$hue.green.200", removed: "$hue.red.200" },
180
+ },
181
+ },
182
+ syntax: {
183
+ comment: "$hue.neutral.600",
184
+ keyword: "$hue.purple.600",
185
+ function: "$hue.accent.600",
186
+ variable: "$hue.neutral.900",
187
+ string: "$hue.green.700",
188
+ number: "$hue.yellow.800",
189
+ type: "$hue.yellow.500",
190
+ operator: "$hue.cyan.600",
191
+ punctuation: "$hue.neutral.900",
192
+ },
193
+ markdown: {
194
+ text: "$hue.neutral.900",
195
+ heading: "$hue.purple.600",
196
+ link: "$hue.accent.600",
197
+ linkText: "$hue.cyan.600",
198
+ code: "$hue.green.700",
199
+ blockQuote: "$hue.neutral.600",
200
+ emphasis: "$hue.yellow.500",
201
+ strong: "$hue.neutral.900",
202
+ horizontalRule: "$hue.neutral.300",
203
+ listItem: "$hue.accent.600",
204
+ listEnumeration: "$hue.cyan.600",
205
+ image: "$hue.accent.600",
206
+ imageText: "$hue.cyan.600",
207
+ codeBlock: "$hue.neutral.900",
208
+ },
209
+ "@context:elevated": {
210
+ text: { action: { primary: { default: "$hue.neutral.100" } } },
211
+ background: {
212
+ default: "$background.surface.offset",
213
+ action: { primary: { default: "$hue.interactive.500", $hovered: "$background.surface.overlay" } },
214
+ },
215
+ },
216
+ "@context:overlay": {
217
+ text: { action: { primary: { default: "$hue.neutral.100" } } },
218
+ background: {
219
+ default: "$background.surface.overlay",
220
+ action: { primary: { default: "$hue.interactive.500" } },
221
+ },
222
+ },
223
+ },
224
+ dark: {
225
+ hue: {
226
+ gray: {
227
+ 100: "#f3f4f6",
228
+ 200: "#e5e7eb",
229
+ 300: "#d1d5db",
230
+ 400: "#9ca3af",
231
+ 500: "#6b7280",
232
+ 600: "#4b5563",
233
+ 700: "#374151",
234
+ 800: "#1f2937",
235
+ 900: "#111827",
236
+ },
237
+ red: {
238
+ 100: "#fee2e2",
239
+ 200: "#fecaca",
240
+ 300: "#fca5a5",
241
+ 400: "#f87171",
242
+ 500: "#ef4444",
243
+ 600: "#dc2626",
244
+ 700: "#b91c1c",
245
+ 800: "#991b1b",
246
+ 900: "#7f1d1d",
247
+ },
248
+ orange: {
249
+ 100: "#ffedd5",
250
+ 200: "#fed7aa",
251
+ 300: "#fdba74",
252
+ 400: "#fb923c",
253
+ 500: "#f97316",
254
+ 600: "#ea580c",
255
+ 700: "#c2410c",
256
+ 800: "#9a3412",
257
+ 900: "#7c2d12",
258
+ },
259
+ yellow: {
260
+ 100: "#fef9c3",
261
+ 200: "#fef08a",
262
+ 300: "#fde047",
263
+ 400: "#facc15",
264
+ 500: "#eab308",
265
+ 600: "#ca8a04",
266
+ 700: "#a16207",
267
+ 800: "#854d0e",
268
+ 900: "#713f12",
269
+ },
270
+ green: {
271
+ 100: "#dcfce7",
272
+ 200: "#bbf7d0",
273
+ 300: "#86efac",
274
+ 400: "#4ade80",
275
+ 500: "#22c55e",
276
+ 600: "#16a34a",
277
+ 700: "#15803d",
278
+ 800: "#166534",
279
+ 900: "#14532d",
280
+ },
281
+ cyan: {
282
+ 100: "#cffafe",
283
+ 200: "#a5f3fc",
284
+ 300: "#67e8f9",
285
+ 400: "#22d3ee",
286
+ 500: "#06b6d4",
287
+ 600: "#0891b2",
288
+ 700: "#0e7490",
289
+ 800: "#155e75",
290
+ 900: "#164e63",
291
+ },
292
+ blue: {
293
+ 100: "#dbeafe",
294
+ 200: "#bfdbfe",
295
+ 300: "#93c5fd",
296
+ 400: "#60a5fa",
297
+ 500: "#3b82f6",
298
+ 600: "#2563eb",
299
+ 700: "#1d4ed8",
300
+ 800: "#1e40af",
301
+ 900: "#1e3a8a",
302
+ },
303
+ purple: {
304
+ 100: "#f3e8ff",
305
+ 200: "#e9d5ff",
306
+ 300: "#d8b4fe",
307
+ 400: "#c084fc",
308
+ 500: "#a855f7",
309
+ 600: "#9333ea",
310
+ 700: "#7e22ce",
311
+ 800: "#6b21a8",
312
+ 900: "#581c87",
313
+ },
314
+ accent: "$hue.blue",
315
+ interactive: "$hue.blue",
316
+ neutral: "$hue.gray",
317
+ },
318
+ categorical: DEFAULT_CATEGORICAL,
319
+ text: {
320
+ default: "$hue.neutral.200",
321
+ subdued: "$hue.neutral.400",
322
+ action: {
323
+ primary: { default: "$hue.neutral.200", $disabled: "$hue.neutral.500" },
324
+ destructive: { default: "$hue.red.200", $disabled: "$hue.neutral.500" },
325
+ },
326
+ formfield: {
327
+ default: "$hue.neutral.200",
328
+ $focused: "$text.action.primary.default",
329
+ $pressed: "$hue.neutral.200",
330
+ $disabled: "$hue.neutral.500",
331
+ $selected: "$hue.interactive.500",
332
+ },
333
+ feedback: {
334
+ error: { default: "$hue.red.300", subdued: "$hue.red.400" },
335
+ warning: { default: "$hue.yellow.200", subdued: "$hue.yellow.300" },
336
+ success: { default: "$hue.green.300", subdued: "$hue.green.400" },
337
+ info: { default: "$hue.cyan.300", subdued: "$hue.cyan.400" },
338
+ },
339
+ },
340
+ background: {
341
+ default: "$hue.neutral.800",
342
+ surface: {
343
+ offset: "$hue.neutral.700",
344
+ overlay: "$hue.neutral.600",
345
+ },
346
+ action: {
347
+ primary: {
348
+ default: "$hue.interactive.500",
349
+ $hovered: "$hue.interactive.600",
350
+ $focused: "$hue.interactive.600",
351
+ $pressed: "$hue.interactive.800",
352
+ $selected: "$hue.interactive.600",
353
+ $disabled: "$hue.neutral.800",
354
+ },
355
+ destructive: {
356
+ default: "$hue.red.600",
357
+ $hovered: "$hue.red.700",
358
+ $focused: "$hue.red.700",
359
+ $pressed: "$hue.red.800",
360
+ $selected: "$hue.red.700",
361
+ $disabled: "$hue.neutral.800",
362
+ },
363
+ },
364
+ formfield: {
365
+ default: "$background.default",
366
+ $hovered: "$background.surface.offset",
367
+ $focused: "$background.action.primary.default",
368
+ $pressed: "$hue.interactive.800",
369
+ $disabled: "$background.default",
370
+ $selected: "$background.formfield.default",
371
+ },
372
+ feedback: {
373
+ error: { default: "$background.default" },
374
+ warning: { default: "$background.default" },
375
+ success: { default: "$background.default" },
376
+ info: { default: "$background.default" },
377
+ },
378
+ },
379
+ border: { default: "$hue.neutral.700" },
380
+ scrollbar: { default: "$hue.neutral.600" },
381
+ diff: {
382
+ text: {
383
+ added: "$hue.green.300",
384
+ removed: "$hue.red.300",
385
+ context: "$hue.neutral.100",
386
+ hunkHeader: "$hue.purple.400",
387
+ },
388
+ background: { added: "$hue.green.900", removed: "$hue.red.900", context: "$hue.neutral.900" },
389
+ highlight: { added: "$hue.green.400", removed: "$hue.red.400" },
390
+ lineNumber: {
391
+ text: "$hue.neutral.400",
392
+ background: { added: "$hue.green.800", removed: "$hue.red.800" },
393
+ },
394
+ },
395
+ syntax: {
396
+ comment: "$hue.neutral.400",
397
+ keyword: "$hue.purple.400",
398
+ function: "$hue.accent.400",
399
+ variable: "$hue.neutral.100",
400
+ string: "$hue.green.300",
401
+ number: "$hue.yellow.200",
402
+ type: "$hue.yellow.500",
403
+ operator: "$hue.cyan.400",
404
+ punctuation: "$hue.neutral.100",
405
+ },
406
+ markdown: {
407
+ text: "$hue.neutral.100",
408
+ heading: "$hue.purple.400",
409
+ link: "$hue.accent.400",
410
+ linkText: "$hue.cyan.400",
411
+ code: "$hue.green.300",
412
+ blockQuote: "$hue.neutral.400",
413
+ emphasis: "$hue.yellow.500",
414
+ strong: "$hue.neutral.100",
415
+ horizontalRule: "$hue.neutral.700",
416
+ listItem: "$hue.accent.400",
417
+ listEnumeration: "$hue.cyan.400",
418
+ image: "$hue.accent.400",
419
+ imageText: "$hue.cyan.400",
420
+ codeBlock: "$hue.neutral.100",
421
+ },
422
+ "@context:elevated": {
423
+ text: { action: { primary: { default: "$hue.neutral.200" } } },
424
+ background: {
425
+ default: "$background.surface.offset",
426
+ action: { primary: { default: "$hue.interactive.400", $hovered: "$background.surface.overlay" } },
427
+ },
428
+ },
429
+ "@context:overlay": {
430
+ text: { action: { primary: { default: "$hue.neutral.200" } } },
431
+ background: {
432
+ default: "$background.surface.overlay",
433
+ action: { primary: { default: "$hue.interactive.400" } },
434
+ },
435
+ },
436
+ },
437
+ };
@@ -0,0 +1,4 @@
1
+ import type { ModeDefinition, ThemeTokensDefinition } from "./index.js";
2
+ export declare function expandTheme<Definition extends ModeDefinition>(definition: Definition): Definition;
3
+ export declare function expandTokens(definition: ThemeTokensDefinition): ThemeTokensDefinition;
4
+ export declare function mergeTheme(...values: unknown[]): Record<string, unknown>;
@@ -0,0 +1,87 @@
1
+ import { ActionState } from "./schema.js";
2
+ export function expandTheme(definition) {
3
+ return {
4
+ ...definition,
5
+ ...expandTokens(definition),
6
+ ...Object.fromEntries(Object.entries(definition)
7
+ .filter(([key]) => key.startsWith("@context:"))
8
+ .map(([key, value]) => [key, expandTokens(value)])),
9
+ };
10
+ }
11
+ export function expandTokens(definition) {
12
+ return {
13
+ ...definition,
14
+ text: expandText(definition.text),
15
+ background: expandBackground(definition.background),
16
+ };
17
+ }
18
+ export function mergeTheme(...values) {
19
+ return values.reduce((result, value) => {
20
+ if (!isRecord(value))
21
+ return result;
22
+ return Object.entries(value).reduce((next, [key, item]) => {
23
+ if (item === undefined || key === "mergeMode")
24
+ return next;
25
+ return {
26
+ ...next,
27
+ [key]: isRecord(item) ? mergeTheme(next[key], item) : item,
28
+ };
29
+ }, result);
30
+ }, {});
31
+ }
32
+ function expandText(definition) {
33
+ if (!definition)
34
+ return;
35
+ return {
36
+ ...definition,
37
+ subdued: definition.subdued ?? (definition.default ? "$text.default" : undefined),
38
+ action: expandActions(definition.action, "text.action"),
39
+ formfield: expandFormfield(definition.formfield, "text.formfield"),
40
+ feedback: definition.feedback
41
+ ? Object.fromEntries(Object.entries(definition.feedback).map(([kind, feedback]) => {
42
+ return [
43
+ kind,
44
+ {
45
+ ...feedback,
46
+ subdued: feedback.subdued ?? (feedback.default ? `$text.feedback.${kind}.default` : undefined),
47
+ },
48
+ ];
49
+ }))
50
+ : undefined,
51
+ };
52
+ }
53
+ function expandBackground(definition) {
54
+ if (!definition)
55
+ return;
56
+ return {
57
+ ...definition,
58
+ action: expandActions(definition.action, "background.action"),
59
+ formfield: expandFormfield(definition.formfield, "background.formfield"),
60
+ };
61
+ }
62
+ function expandFormfield(definition, path) {
63
+ if (!definition?.default)
64
+ return definition;
65
+ return {
66
+ ...definition,
67
+ ...Object.fromEntries(ActionState.literals.map((state) => [`$${state}`, definition[`$${state}`] ?? `$${path}.default`])),
68
+ };
69
+ }
70
+ function expandActions(definition, path) {
71
+ if (!definition)
72
+ return;
73
+ return Object.fromEntries(Object.entries(definition).map(([variant, value]) => {
74
+ if (!value?.default)
75
+ return [variant, value];
76
+ return [
77
+ variant,
78
+ {
79
+ ...value,
80
+ ...Object.fromEntries(ActionState.literals.map((state) => [`$${state}`, value[`$${state}`] ?? `$${path}.${variant}.default`])),
81
+ },
82
+ ];
83
+ }));
84
+ }
85
+ function isRecord(value) {
86
+ return typeof value === "object" && value !== null && !Array.isArray(value);
87
+ }
@@ -0,0 +1,2 @@
1
+ import type { ThemeTokensDefinition } from "./index.js";
2
+ export declare function fallback(): ThemeTokensDefinition;
@@ -0,0 +1,54 @@
1
+ import { ActionVariant, FeedbackKind } from "./schema.js";
2
+ export function fallback() {
3
+ const red = "#ff0000";
4
+ return {
5
+ text: {
6
+ default: red,
7
+ action: Object.fromEntries(ActionVariant.literals.map((variant) => [variant, { default: red }])),
8
+ formfield: { default: red },
9
+ feedback: Object.fromEntries(FeedbackKind.literals.map((kind) => [kind, { default: red }])),
10
+ },
11
+ background: {
12
+ default: red,
13
+ surface: { offset: red, overlay: red },
14
+ action: Object.fromEntries(ActionVariant.literals.map((variant) => [variant, { default: red }])),
15
+ formfield: { default: red },
16
+ feedback: Object.fromEntries(FeedbackKind.literals.map((kind) => [kind, { default: red }])),
17
+ },
18
+ border: { default: red },
19
+ scrollbar: { default: red },
20
+ diff: {
21
+ text: { added: red, removed: red, context: red, hunkHeader: red },
22
+ background: { added: red, removed: red, context: red },
23
+ highlight: { added: red, removed: red },
24
+ lineNumber: { text: red, background: { added: red, removed: red } },
25
+ },
26
+ syntax: {
27
+ comment: red,
28
+ keyword: red,
29
+ function: red,
30
+ variable: red,
31
+ string: red,
32
+ number: red,
33
+ type: red,
34
+ operator: red,
35
+ punctuation: red,
36
+ },
37
+ markdown: {
38
+ text: red,
39
+ heading: red,
40
+ link: red,
41
+ linkText: red,
42
+ code: red,
43
+ blockQuote: red,
44
+ emphasis: red,
45
+ strong: red,
46
+ horizontalRule: red,
47
+ listItem: red,
48
+ listEnumeration: red,
49
+ image: red,
50
+ imageText: red,
51
+ codeBlock: red,
52
+ },
53
+ };
54
+ }
@@ -0,0 +1,7 @@
1
+ export { ActionState, type ActionStateKey, ActionVariant, BaseHue, CategoricalDefinition, FeedbackKind, FormfieldState, type FormfieldStateKey, HueAlias, HueName, HueStep, MarkdownDefinition, MarkdownToken, ModeDefinition, SyntaxDefinition, SyntaxToken, ThemeDefinition, ThemeDocument, type BackgroundDefinition, type DiffDefinition, type FileThemeDefinition, type FormfieldColorDefinition, type HueDefinition, type HueOverrideDefinition, type MergeModeDefinition, type Mode, type StatefulColorDefinition, type ContextKey, type TextDefinition, type ThemeTokensDefinition, } from "./schema.js";
2
+ export type { Categorical, FormfieldColor, Hue, HueSource, HueScale, ResolvedActionState, ResolvedFormfieldState, ResolvedTheme, ResolvedThemeView, StatefulColor, } from "./types.js";
3
+ export { DEFAULT_CATEGORICAL, DEFAULT_THEME } from "./defaults.js";
4
+ export { migrateV1 } from "./v1-migrate.js";
5
+ export { resolveTheme, resolveThemeDocument, themeDecodeError } from "./resolve.js";
6
+ export { selectTheme, selectThemeMode, supportsThemeMode, themeModes } from "./select.js";
7
+ export { generateSyntax } from "./syntax.js";
@@ -0,0 +1,6 @@
1
+ export { ActionState, ActionVariant, BaseHue, CategoricalDefinition, FeedbackKind, FormfieldState, HueAlias, HueName, HueStep, MarkdownDefinition, MarkdownToken, ModeDefinition, SyntaxDefinition, SyntaxToken, ThemeDefinition, ThemeDocument, } from "./schema.js";
2
+ export { DEFAULT_CATEGORICAL, DEFAULT_THEME } from "./defaults.js";
3
+ export { migrateV1 } from "./v1-migrate.js";
4
+ export { resolveTheme, resolveThemeDocument, themeDecodeError } from "./resolve.js";
5
+ export { selectTheme, selectThemeMode, supportsThemeMode, themeModes } from "./select.js";
6
+ export { generateSyntax } from "./syntax.js";
@@ -0,0 +1,5 @@
1
+ import { ThemeDefinition, ThemeDocument } from "./schema.js";
2
+ import type { ResolvedTheme } from "./index.js";
3
+ export declare function themeDecodeError(error: unknown, name: string): Error;
4
+ export declare function resolveThemeDocument(document: ThemeDocument, mode?: "light" | "dark"): ResolvedTheme;
5
+ export declare function resolveTheme(definition: ThemeDefinition): ResolvedTheme;