@cloudflare/kumo 1.12.1 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/.build-complete +1 -1
- package/dist/chunks/Legend-fu32ev5ph2ehbfzy.js +402 -0
- package/dist/chunks/Legend-fu32ev5ph2ehbfzy.js.map +1 -0
- package/dist/chunks/{combobox-hdstt4dqqxbtxwod.js → combobox-i3mdp6f01dvpoc5j.js} +53 -53
- package/dist/chunks/combobox-i3mdp6f01dvpoc5j.js.map +1 -0
- package/dist/code/server.js +0 -2
- package/dist/code/server.js.map +1 -1
- package/dist/code.js +0 -1
- package/dist/code.js.map +1 -1
- package/dist/components/chart.js +1 -1
- package/dist/components/combobox.js +1 -1
- package/dist/index.js +2 -2
- package/dist/src/components/chart/TimeseriesChart.d.ts +22 -7
- package/dist/src/components/chart/TimeseriesChart.d.ts.map +1 -1
- package/dist/styles/kumo-standalone.css +1 -1
- package/package.json +1 -1
- package/dist/chunks/Legend-glsgxdtqiwf3jebj.js +0 -388
- package/dist/chunks/Legend-glsgxdtqiwf3jebj.js.map +0 -1
- package/dist/chunks/combobox-hdstt4dqqxbtxwod.js.map +0 -1
|
@@ -2,50 +2,50 @@
|
|
|
2
2
|
import { jsx as o, jsxs as c } from "react/jsx-runtime";
|
|
3
3
|
import { CheckIcon as w, XIcon as d, CaretDownIcon as x } from "@phosphor-icons/react";
|
|
4
4
|
import { createContext as T, useContext as h, Fragment as V } from "react";
|
|
5
|
-
import { i as
|
|
5
|
+
import { i as u, K as P } from "./input-me56hug8sl0u650q.js";
|
|
6
6
|
import { c as a } from "./cn-ct4n7r74mh8y0f48.js";
|
|
7
7
|
import { F as j } from "./field-ftrgblg9mbmz9eo3.js";
|
|
8
8
|
import { a5 as G, a6 as L, a7 as M, a8 as F, a9 as _, aa as A, ab as p, ac as E, ad as K, ae as O, af as U, ag as W, ah as f, ai as D, aj as C, ak as N, al as H, am as X, an as q } from "./vendor-base-ui-kxxocm122zr4pipe.js";
|
|
9
9
|
P.size;
|
|
10
|
-
const
|
|
10
|
+
const b = T("base");
|
|
11
11
|
function y({
|
|
12
12
|
label: e,
|
|
13
|
-
required:
|
|
14
|
-
labelTooltip:
|
|
15
|
-
description:
|
|
16
|
-
error:
|
|
13
|
+
required: t,
|
|
14
|
+
labelTooltip: i,
|
|
15
|
+
description: r,
|
|
16
|
+
error: n,
|
|
17
17
|
children: s,
|
|
18
18
|
size: l = "base",
|
|
19
19
|
...m
|
|
20
20
|
}) {
|
|
21
|
-
const g = /* @__PURE__ */ o(
|
|
21
|
+
const g = /* @__PURE__ */ o(b.Provider, { value: l, children: /* @__PURE__ */ o(L, { ...m, children: s }) });
|
|
22
22
|
return e ? /* @__PURE__ */ o(
|
|
23
23
|
j,
|
|
24
24
|
{
|
|
25
25
|
label: e,
|
|
26
|
-
required:
|
|
27
|
-
labelTooltip:
|
|
28
|
-
description:
|
|
29
|
-
error:
|
|
26
|
+
required: t,
|
|
27
|
+
labelTooltip: i,
|
|
28
|
+
description: r,
|
|
29
|
+
error: n ? typeof n == "string" ? { message: n, match: !0 } : n : void 0,
|
|
30
30
|
children: g
|
|
31
31
|
}
|
|
32
32
|
) : g;
|
|
33
33
|
}
|
|
34
34
|
function z({
|
|
35
35
|
children: e,
|
|
36
|
-
className:
|
|
37
|
-
align:
|
|
38
|
-
sideOffset:
|
|
39
|
-
alignOffset:
|
|
36
|
+
className: t,
|
|
37
|
+
align: i = "start",
|
|
38
|
+
sideOffset: r = 4,
|
|
39
|
+
alignOffset: n,
|
|
40
40
|
side: s
|
|
41
41
|
}) {
|
|
42
42
|
return /* @__PURE__ */ o(H, { children: /* @__PURE__ */ o(
|
|
43
43
|
X,
|
|
44
44
|
{
|
|
45
45
|
className: "outline-none",
|
|
46
|
-
align:
|
|
47
|
-
sideOffset:
|
|
48
|
-
alignOffset:
|
|
46
|
+
align: i,
|
|
47
|
+
sideOffset: r,
|
|
48
|
+
alignOffset: n,
|
|
49
49
|
side: s,
|
|
50
50
|
children: /* @__PURE__ */ o(
|
|
51
51
|
q,
|
|
@@ -58,7 +58,7 @@ function z({
|
|
|
58
58
|
// background
|
|
59
59
|
"rounded-lg shadow-lg ring ring-kumo-line",
|
|
60
60
|
// border part
|
|
61
|
-
|
|
61
|
+
t
|
|
62
62
|
),
|
|
63
63
|
children: e
|
|
64
64
|
}
|
|
@@ -74,32 +74,32 @@ const B = {
|
|
|
74
74
|
};
|
|
75
75
|
function v({
|
|
76
76
|
className: e,
|
|
77
|
-
...
|
|
77
|
+
...t
|
|
78
78
|
}) {
|
|
79
|
-
const
|
|
79
|
+
const i = h(b), r = B[i];
|
|
80
80
|
return /* @__PURE__ */ c(
|
|
81
81
|
C,
|
|
82
82
|
{
|
|
83
83
|
className: a(
|
|
84
|
-
|
|
84
|
+
u({ size: i }),
|
|
85
85
|
"relative flex items-center",
|
|
86
|
-
|
|
86
|
+
r.padding,
|
|
87
87
|
e
|
|
88
88
|
),
|
|
89
89
|
children: [
|
|
90
|
-
/* @__PURE__ */ o(f, { children:
|
|
90
|
+
/* @__PURE__ */ o(f, { children: t.children }),
|
|
91
91
|
/* @__PURE__ */ o(
|
|
92
92
|
N,
|
|
93
93
|
{
|
|
94
94
|
className: a(
|
|
95
|
-
"absolute top-1/2 -translate-y-1/2 flex items-center",
|
|
96
|
-
|
|
95
|
+
"absolute top-1/2 -translate-y-1/2 flex items-center text-kumo-subtle",
|
|
96
|
+
r.iconRight
|
|
97
97
|
),
|
|
98
98
|
children: /* @__PURE__ */ o(
|
|
99
99
|
x,
|
|
100
100
|
{
|
|
101
|
-
size:
|
|
102
|
-
className: "fill-
|
|
101
|
+
size: r.iconSize,
|
|
102
|
+
className: "fill-current"
|
|
103
103
|
}
|
|
104
104
|
)
|
|
105
105
|
}
|
|
@@ -135,7 +135,7 @@ const J = {
|
|
|
135
135
|
}
|
|
136
136
|
};
|
|
137
137
|
function R(e) {
|
|
138
|
-
const
|
|
138
|
+
const t = h(b), i = J[t];
|
|
139
139
|
return /* @__PURE__ */ c(
|
|
140
140
|
"div",
|
|
141
141
|
{
|
|
@@ -145,7 +145,7 @@ function R(e) {
|
|
|
145
145
|
p,
|
|
146
146
|
{
|
|
147
147
|
...e,
|
|
148
|
-
className: a(
|
|
148
|
+
className: a(u({ size: t }), "w-full", i.padding)
|
|
149
149
|
}
|
|
150
150
|
),
|
|
151
151
|
/* @__PURE__ */ o(
|
|
@@ -153,23 +153,23 @@ function R(e) {
|
|
|
153
153
|
{
|
|
154
154
|
className: a(
|
|
155
155
|
"absolute top-1/2 flex -translate-y-1/2 cursor-pointer bg-transparent p-0",
|
|
156
|
-
|
|
156
|
+
i.clearRight
|
|
157
157
|
),
|
|
158
|
-
children: /* @__PURE__ */ o(d, { size:
|
|
158
|
+
children: /* @__PURE__ */ o(d, { size: i.iconSize })
|
|
159
159
|
}
|
|
160
160
|
),
|
|
161
161
|
/* @__PURE__ */ o(C, { className: "p-0", children: /* @__PURE__ */ o(
|
|
162
162
|
N,
|
|
163
163
|
{
|
|
164
164
|
className: a(
|
|
165
|
-
"absolute top-1/2 flex -translate-y-1/2 cursor-pointer",
|
|
166
|
-
|
|
165
|
+
"absolute top-1/2 flex -translate-y-1/2 cursor-pointer text-kumo-subtle",
|
|
166
|
+
i.caretRight
|
|
167
167
|
),
|
|
168
168
|
children: /* @__PURE__ */ o(
|
|
169
169
|
x,
|
|
170
170
|
{
|
|
171
|
-
size:
|
|
172
|
-
className: "fill-
|
|
171
|
+
size: i.iconSize,
|
|
172
|
+
className: "fill-current"
|
|
173
173
|
}
|
|
174
174
|
)
|
|
175
175
|
}
|
|
@@ -178,11 +178,11 @@ function R(e) {
|
|
|
178
178
|
}
|
|
179
179
|
);
|
|
180
180
|
}
|
|
181
|
-
function I({ children: e, ...
|
|
181
|
+
function I({ children: e, ...t }) {
|
|
182
182
|
return /* @__PURE__ */ c(
|
|
183
183
|
E,
|
|
184
184
|
{
|
|
185
|
-
...
|
|
185
|
+
...t,
|
|
186
186
|
className: "group mx-1.5 grid cursor-pointer grid-cols-[1fr_16px] gap-2 rounded px-2 py-1.5 text-base data-highlighted:bg-kumo-overlay",
|
|
187
187
|
children: [
|
|
188
188
|
/* @__PURE__ */ o("div", { className: "col-start-1", children: e }),
|
|
@@ -209,7 +209,7 @@ function Y(e) {
|
|
|
209
209
|
{
|
|
210
210
|
...e,
|
|
211
211
|
className: a(
|
|
212
|
-
|
|
212
|
+
u(),
|
|
213
213
|
"mx-1.5 w-[calc(100%-0.75rem)] shrink-0 first:mb-2",
|
|
214
214
|
e.className
|
|
215
215
|
)
|
|
@@ -218,12 +218,12 @@ function Y(e) {
|
|
|
218
218
|
}
|
|
219
219
|
function Z({
|
|
220
220
|
className: e,
|
|
221
|
-
...
|
|
221
|
+
...t
|
|
222
222
|
}) {
|
|
223
223
|
return /* @__PURE__ */ o(
|
|
224
224
|
M,
|
|
225
225
|
{
|
|
226
|
-
...
|
|
226
|
+
...t,
|
|
227
227
|
className: a(
|
|
228
228
|
"min-h-0 flex-1 overflow-y-auto overscroll-contain scroll-pt-2 scroll-pb-2",
|
|
229
229
|
e
|
|
@@ -273,22 +273,22 @@ const oe = {
|
|
|
273
273
|
};
|
|
274
274
|
function S({
|
|
275
275
|
placeholder: e,
|
|
276
|
-
renderItem:
|
|
277
|
-
className:
|
|
278
|
-
inputSide:
|
|
279
|
-
value:
|
|
276
|
+
renderItem: t,
|
|
277
|
+
className: i,
|
|
278
|
+
inputSide: r = "right",
|
|
279
|
+
value: n
|
|
280
280
|
}) {
|
|
281
|
-
const s = h(
|
|
281
|
+
const s = h(b), l = n;
|
|
282
282
|
return /* @__PURE__ */ c(
|
|
283
283
|
W,
|
|
284
284
|
{
|
|
285
285
|
className: a(
|
|
286
|
-
|
|
286
|
+
u({ size: s }),
|
|
287
287
|
a("flex flex-col", "gap-1 p-1", oe[s], "h-auto"),
|
|
288
|
-
|
|
288
|
+
i
|
|
289
289
|
),
|
|
290
290
|
children: [
|
|
291
|
-
|
|
291
|
+
r === "top" && /* @__PURE__ */ o(
|
|
292
292
|
p,
|
|
293
293
|
{
|
|
294
294
|
placeholder: e,
|
|
@@ -296,9 +296,9 @@ function S({
|
|
|
296
296
|
}
|
|
297
297
|
),
|
|
298
298
|
/* @__PURE__ */ c("div", { className: "flex flex-wrap gap-1", children: [
|
|
299
|
-
l !== void 0 && l.length > 0 && l.map((m) =>
|
|
300
|
-
/* @__PURE__ */ o(f, { children: (m) => l !== void 0 ? null : /* @__PURE__ */ o(V, { children: m.map((g) =>
|
|
301
|
-
|
|
299
|
+
l !== void 0 && l.length > 0 && l.map((m) => t(m)),
|
|
300
|
+
/* @__PURE__ */ o(f, { children: (m) => l !== void 0 ? null : /* @__PURE__ */ o(V, { children: m.map((g) => t(g)) }) }),
|
|
301
|
+
r === "right" && /* @__PURE__ */ o(
|
|
302
302
|
p,
|
|
303
303
|
{
|
|
304
304
|
placeholder: e,
|
|
@@ -339,4 +339,4 @@ const ce = Object.assign(y, {
|
|
|
339
339
|
export {
|
|
340
340
|
ce as C
|
|
341
341
|
};
|
|
342
|
-
//# sourceMappingURL=combobox-
|
|
342
|
+
//# sourceMappingURL=combobox-i3mdp6f01dvpoc5j.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combobox-i3mdp6f01dvpoc5j.js","sources":["../../src/components/combobox/combobox.tsx"],"sourcesContent":["import { Combobox as ComboboxBase } from \"@base-ui/react/combobox\";\nimport { CaretDownIcon, CheckIcon, XIcon } from \"@phosphor-icons/react\";\nimport {\n Fragment,\n createContext,\n useContext,\n type PropsWithChildren,\n type ReactNode,\n} from \"react\";\nimport {\n inputVariants,\n KUMO_INPUT_VARIANTS,\n type KumoInputSize,\n} from \"../input/input\";\nimport { cn } from \"../../utils/cn\";\nimport { Field, type FieldErrorMatch } from \"../field/field\";\n\n/** Combobox variant definitions. */\nexport const KUMO_COMBOBOX_VARIANTS = {\n size: KUMO_INPUT_VARIANTS.size,\n inputSide: {\n right: {\n classes: \"\",\n description: \"Input positioned inline to the right of chips\",\n },\n top: {\n classes: \"\",\n description: \"Input positioned above chips\",\n },\n },\n} as const;\n\nexport const KUMO_COMBOBOX_DEFAULT_VARIANTS = {\n size: \"base\",\n inputSide: \"right\",\n} as const;\n\n// Context to pass size down to sub-components\nconst ComboboxSizeContext = createContext<KumoInputSize>(\"base\");\n\n// Derived types from KUMO_COMBOBOX_VARIANTS\nexport type KumoComboboxSize = keyof typeof KUMO_COMBOBOX_VARIANTS.size;\nexport type KumoComboboxInputSide =\n keyof typeof KUMO_COMBOBOX_VARIANTS.inputSide;\n\nexport interface KumoComboboxVariantsProps {\n /**\n * Size of the combobox trigger. Matches Input component sizes.\n * - `\"xs\"` — Extra small for compact UIs (h-5 / 20px)\n * - `\"sm\"` — Small for secondary fields (h-6.5 / 26px)\n * - `\"base\"` — Default size (h-9 / 36px)\n * - `\"lg\"` — Large for prominent fields (h-10 / 40px)\n * @default \"base\"\n */\n size?: KumoComboboxSize;\n /**\n * Position of the text input relative to chips in multi-select mode.\n * - `\"right\"` — Input inline to the right of chips\n * - `\"top\"` — Input above chips\n * @default \"right\"\n */\n inputSide?: KumoComboboxInputSide;\n}\n\nexport function comboboxVariants({\n inputSide = KUMO_COMBOBOX_DEFAULT_VARIANTS.inputSide,\n}: KumoComboboxVariantsProps = {}) {\n return cn(KUMO_COMBOBOX_VARIANTS.inputSide[inputSide].classes);\n}\n\n// Legacy type alias for backwards compatibility\nexport type ComboboxInputSide = KumoComboboxInputSide;\nexport type ComboboxSize = KumoComboboxSize;\n\nexport type ComboboxRootProps<\n Value = unknown,\n Multiple extends boolean | undefined = false,\n> = ComboboxBase.Root.Props<Value, Multiple>;\n\n/**\n * Combobox component props (simplified for documentation; the actual Root is generic).\n *\n * Combobox provides an autocomplete/typeahead input with a filterable dropdown.\n * Supports single-select, multi-select with chips, grouped items, and Field wrapper integration.\n *\n * @example\n * ```tsx\n * // Single-select with search input\n * <Combobox value={value} onValueChange={setValue} items={options}>\n * <Combobox.TriggerInput placeholder=\"Search…\" />\n * <Combobox.Content>\n * <Combobox.List>\n * {(item) => <Combobox.Item value={item}>{item.label}</Combobox.Item>}\n * </Combobox.List>\n * <Combobox.Empty>No results</Combobox.Empty>\n * </Combobox.Content>\n * </Combobox>\n *\n * // Multi-select with chips\n * <Combobox multiple items={options} label=\"Tags\">\n * <Combobox.TriggerMultipleWithInput\n * placeholder=\"Add tag…\"\n * renderItem={(item) => <Combobox.Chip value={item}>{item.label}</Combobox.Chip>}\n * />\n * <Combobox.Content>\n * <Combobox.List>\n * {(item) => <Combobox.Item value={item}>{item.label}</Combobox.Item>}\n * </Combobox.List>\n * </Combobox.Content>\n * </Combobox>\n * ```\n */\nexport interface ComboboxProps extends KumoComboboxVariantsProps {\n /** Array of items to display in the dropdown */\n items: unknown[];\n /** Currently selected value(s) */\n value?: unknown;\n /** Callback when selection changes */\n onValueChange?: (value: unknown) => void;\n /** Enable multi-select mode */\n multiple?: boolean;\n /** Combobox content (trigger, content, items) */\n children: ReactNode;\n /** Additional CSS classes */\n className?: string;\n /** Label content for the combobox (enables Field wrapper) - can be a string or any React node */\n label?: ReactNode;\n /** Whether the combobox is required */\n required?: boolean;\n /** Tooltip content to display next to the label via an info icon */\n labelTooltip?: ReactNode;\n /** Helper text displayed below the combobox */\n description?: ReactNode;\n /** Error message or validation error object */\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n}\n\nfunction Root<Value, Multiple extends boolean | undefined = false>({\n label,\n required,\n labelTooltip,\n description,\n error,\n children,\n size = \"base\",\n ...props\n}: ComboboxBase.Root.Props<Value, Multiple> & {\n label?: ReactNode;\n required?: boolean;\n labelTooltip?: ReactNode;\n description?: ReactNode;\n error?: string | { message: ReactNode; match: FieldErrorMatch };\n size?: KumoComboboxSize;\n}) {\n const comboboxControl = (\n <ComboboxSizeContext.Provider value={size}>\n <ComboboxBase.Root {...props}>{children}</ComboboxBase.Root>\n </ComboboxSizeContext.Provider>\n );\n\n // Render with Field wrapper if label, description, or error are provided\n if (label) {\n return (\n <Field\n label={label}\n required={required}\n labelTooltip={labelTooltip}\n description={description}\n error={\n error\n ? typeof error === \"string\"\n ? { message: error, match: true }\n : error\n : undefined\n }\n >\n {comboboxControl}\n </Field>\n );\n }\n\n // Render bare combobox without Field wrapper\n return comboboxControl;\n}\n\nfunction Content({\n children,\n className,\n align = \"start\",\n sideOffset = 4,\n alignOffset,\n side,\n}: PropsWithChildren<{\n className?: string;\n align?: ComboboxBase.Positioner.Props[\"align\"];\n alignOffset?: ComboboxBase.Positioner.Props[\"alignOffset\"];\n side?: ComboboxBase.Positioner.Props[\"side\"];\n sideOffset?: ComboboxBase.Positioner.Props[\"sideOffset\"];\n}>) {\n return (\n <ComboboxBase.Portal>\n <ComboboxBase.Positioner\n className=\"outline-none\"\n align={align}\n sideOffset={sideOffset}\n alignOffset={alignOffset}\n side={side}\n >\n <ComboboxBase.Popup\n className={cn(\n \"flex flex-col\", // flexbox layout for sticky input + scrollable list\n \"max-h-[min(var(--available-height),24rem)] max-w-(--available-width) min-w-(--anchor-width) py-1.5\",\n \"bg-kumo-control text-kumo-default\", // background\n \"rounded-lg shadow-lg ring ring-kumo-line\", // border part\n className,\n )}\n >\n {children}\n </ComboboxBase.Popup>\n </ComboboxBase.Positioner>\n </ComboboxBase.Portal>\n );\n}\n\n// Size-dependent styles for TriggerValue icon\nconst triggerValueIconStyles: Record<\n KumoComboboxSize,\n { padding: string; iconSize: number; iconRight: string }\n> = {\n xs: { padding: \"pr-5\", iconSize: 12, iconRight: \"right-1\" },\n sm: { padding: \"pr-6\", iconSize: 14, iconRight: \"right-1.5\" },\n base: { padding: \"pr-8\", iconSize: 16, iconRight: \"right-2\" },\n lg: { padding: \"pr-10\", iconSize: 18, iconRight: \"right-3\" },\n};\n\nfunction TriggerValue({\n className,\n ...props\n}: ComboboxBase.Value.Props & { className?: string }) {\n const size = useContext(ComboboxSizeContext);\n const iconStyles = triggerValueIconStyles[size];\n\n return (\n <ComboboxBase.Trigger\n className={cn(\n inputVariants({ size }),\n \"relative flex items-center\",\n iconStyles.padding,\n className,\n )}\n >\n <ComboboxBase.Value>{props.children}</ComboboxBase.Value>\n <ComboboxBase.Icon\n className={cn(\n \"absolute top-1/2 -translate-y-1/2 flex items-center text-kumo-subtle\",\n iconStyles.iconRight,\n )}\n >\n <CaretDownIcon\n size={iconStyles.iconSize}\n className=\"fill-current\"\n />\n </ComboboxBase.Icon>\n </ComboboxBase.Trigger>\n );\n}\n\n// Size-dependent styles for TriggerInput icons\nconst triggerInputIconStyles: Record<\n KumoComboboxSize,\n { padding: string; iconSize: number; clearRight: string; caretRight: string }\n> = {\n xs: {\n padding: \"pr-7\",\n iconSize: 12,\n clearRight: \"right-5\",\n caretRight: \"right-1\",\n },\n sm: {\n padding: \"pr-9\",\n iconSize: 14,\n clearRight: \"right-6\",\n caretRight: \"right-1.5\",\n },\n base: {\n padding: \"pr-12\",\n iconSize: 16,\n clearRight: \"right-8\",\n caretRight: \"right-2\",\n },\n lg: {\n padding: \"pr-14\",\n iconSize: 18,\n clearRight: \"right-9\",\n caretRight: \"right-3\",\n },\n};\n\nfunction TriggerInput(props: ComboboxBase.Input.Props) {\n const size = useContext(ComboboxSizeContext);\n const iconStyles = triggerInputIconStyles[size];\n\n return (\n <div\n className={cn(\"relative inline-block w-full max-w-xs\", props.className)}\n >\n <ComboboxBase.Input\n {...props}\n className={cn(inputVariants({ size }), \"w-full\", iconStyles.padding)}\n />\n\n <ComboboxBase.Clear\n className={cn(\n \"absolute top-1/2 flex -translate-y-1/2 cursor-pointer bg-transparent p-0\",\n iconStyles.clearRight,\n )}\n >\n <XIcon size={iconStyles.iconSize} />\n </ComboboxBase.Clear>\n\n <ComboboxBase.Trigger className=\"p-0\">\n <ComboboxBase.Icon\n className={cn(\n \"absolute top-1/2 flex -translate-y-1/2 cursor-pointer text-kumo-subtle\",\n iconStyles.caretRight,\n )}\n >\n <CaretDownIcon\n size={iconStyles.iconSize}\n className=\"fill-current\"\n />\n </ComboboxBase.Icon>\n </ComboboxBase.Trigger>\n </div>\n );\n}\n\nfunction Item({ children, ...props }: ComboboxBase.Item.Props) {\n return (\n <ComboboxBase.Item\n {...props}\n className=\"group mx-1.5 grid cursor-pointer grid-cols-[1fr_16px] gap-2 rounded px-2 py-1.5 text-base data-highlighted:bg-kumo-overlay\"\n >\n <div className=\"col-start-1\">{children}</div>\n <ComboboxBase.ItemIndicator className=\"col-start-2 flex items-center\">\n <CheckIcon />\n </ComboboxBase.ItemIndicator>\n </ComboboxBase.Item>\n );\n}\n\nfunction Empty(props: ComboboxBase.Empty.Props) {\n return (\n <ComboboxBase.Empty\n {...props}\n className={cn(\n \"mx-1.5 shrink-0 px-4 py-2 text-[0.925rem] leading-4 text-kumo-subtle empty:m-0 empty:p-0\",\n )}\n children={props.children ?? \"No labels found.\"}\n />\n );\n}\n\nfunction Input(props: ComboboxBase.Input.Props) {\n return (\n <ComboboxBase.Input\n {...props}\n className={cn(\n inputVariants(),\n \"mx-1.5 w-[calc(100%-0.75rem)] shrink-0 first:mb-2\",\n props.className,\n )}\n />\n );\n}\n\nfunction List({\n className,\n ...props\n}: ComboboxBase.List.Props & { className?: string }) {\n return (\n <ComboboxBase.List\n {...props}\n className={cn(\n \"min-h-0 flex-1 overflow-y-auto overscroll-contain scroll-pt-2 scroll-pb-2\",\n className,\n )}\n />\n );\n}\n\nfunction GroupLabel(props: ComboboxBase.GroupLabel.Props) {\n return (\n <ComboboxBase.GroupLabel\n {...props}\n className={cn(\n \"mx-1.5 px-2 py-1.5 text-sm text-kumo-strong\",\n props.className,\n )}\n />\n );\n}\n\nfunction Group(props: ComboboxBase.Group.Props) {\n return (\n <ComboboxBase.Group\n {...props}\n className=\"border-t border-kumo-line mt-2 pt-2 first:border-t-0 first:mt-0 first:pt-0\"\n />\n );\n}\n\nfunction Chip(props: ComboboxBase.Chip.Props) {\n return (\n <ComboboxBase.Chip\n {...props}\n className=\"flex items-center gap-1 rounded-md bg-kumo-overlay px-2 py-1\"\n >\n {props.children}\n <ComboboxBase.ChipRemove className=\"cursor-pointer rounded-md p-1 hover:bg-kumo-fill-hover\">\n <XIcon size={12} weight=\"bold\" />\n </ComboboxBase.ChipRemove>\n </ComboboxBase.Chip>\n );\n}\n\n// Map size to min-height class for TriggerMultipleWithInput\nconst sizeToMinHeight: Record<KumoComboboxSize, string> = {\n xs: \"min-h-5\",\n sm: \"min-h-6.5\",\n base: \"min-h-9\",\n lg: \"min-h-10\",\n};\n\nfunction TriggerMultipleWithInput<ValueType>({\n placeholder,\n renderItem,\n className,\n inputSide = \"right\",\n value: controlledValue,\n}: {\n placeholder?: string;\n renderItem: (value: ValueType) => React.ReactNode;\n className?: string;\n inputSide?: \"right\" | \"top\";\n /** Optional controlled value for rendering chips (use when pre-selecting values) */\n value?: ValueType[];\n}) {\n const size = useContext(ComboboxSizeContext);\n // Determine which value to use for rendering chips\n const chipsToRender = controlledValue;\n\n return (\n <ComboboxBase.Chips\n className={cn(\n inputVariants({ size }),\n cn(\"flex flex-col\", \"gap-1 p-1\", sizeToMinHeight[size], \"h-auto\"),\n className,\n )}\n >\n {inputSide === \"top\" && (\n <ComboboxBase.Input\n placeholder={placeholder}\n className=\"w-full px-2 py-1 outline-none\"\n />\n )}\n {/* Chips container */}\n <div className=\"flex flex-wrap gap-1\">\n {/* Render chips from controlled value if provided */}\n {chipsToRender !== undefined &&\n chipsToRender.length > 0 &&\n chipsToRender.map((item) => renderItem(item))}\n {/* Also render from BaseUI's internal value for user selections */}\n <ComboboxBase.Value>\n {(internalValue: ValueType[]) => {\n // Skip rendering if using controlled value (to avoid duplicates)\n if (chipsToRender !== undefined) return null;\n return (\n <Fragment>\n {internalValue.map((item) => renderItem(item))}\n </Fragment>\n );\n }}\n </ComboboxBase.Value>\n {inputSide === \"right\" && (\n <ComboboxBase.Input\n placeholder={placeholder}\n className=\"min-w-[100px] flex-1 px-2 py-1 outline-none\"\n />\n )}\n </div>\n </ComboboxBase.Chips>\n );\n}\n\nRoot.displayName = \"Combobox.Root\";\nContent.displayName = \"Combobox.Content\";\nTriggerValue.displayName = \"Combobox.TriggerValue\";\nTriggerInput.displayName = \"Combobox.TriggerInput\";\nItem.displayName = \"Combobox.Item\";\nChip.displayName = \"Combobox.Chip\";\nTriggerMultipleWithInput.displayName = \"Combobox.TriggerMultipleWithInput\";\n\n/**\n * Combobox — autocomplete input with filterable dropdown list.\n *\n * Compound component: `Combobox` (Root), `.TriggerInput`, `.TriggerValue`,\n * `.TriggerMultipleWithInput`, `.Content`, `.Item`, `.Chip`, `.Input`,\n * `.Empty`, `.GroupLabel`, `.Group`, `.List`, `.Collection`.\n *\n * @example\n * ```tsx\n * <Combobox items={fruits} label=\"Fruit\">\n * <Combobox.TriggerInput placeholder=\"Pick a fruit…\" />\n * <Combobox.Content>\n * <Combobox.List>\n * {(item) => <Combobox.Item value={item}>{item}</Combobox.Item>}\n * </Combobox.List>\n * </Combobox.Content>\n * </Combobox>\n * ```\n *\n * @see https://base-ui.com/react/components/combobox\n */\nexport const Combobox = Object.assign(Root, {\n // Helper components\n Content,\n TriggerValue,\n TriggerInput,\n TriggerMultipleWithInput,\n\n // Slightly modified BaseUI\n Chip,\n Item,\n\n // Styled BaseUI\n Input,\n Empty,\n GroupLabel,\n Group,\n\n // Styled BaseUI\n List,\n\n // BaseUI\n Collection: ComboboxBase.Collection,\n});\n"],"names":["KUMO_INPUT_VARIANTS","ComboboxSizeContext","createContext","Root","label","required","labelTooltip","description","error","children","size","props","comboboxControl","jsx","ComboboxBase.Root","Field","Content","className","align","sideOffset","alignOffset","side","ComboboxBase.Portal","ComboboxBase.Positioner","ComboboxBase.Popup","cn","triggerValueIconStyles","TriggerValue","useContext","iconStyles","jsxs","ComboboxBase.Trigger","inputVariants","ComboboxBase.Value","ComboboxBase.Icon","CaretDownIcon","triggerInputIconStyles","TriggerInput","ComboboxBase.Input","ComboboxBase.Clear","XIcon","Item","ComboboxBase.Item","ComboboxBase.ItemIndicator","CheckIcon","Empty","ComboboxBase.Empty","Input","List","ComboboxBase.List","GroupLabel","ComboboxBase.GroupLabel","Group","ComboboxBase.Group","Chip","ComboboxBase.Chip","ComboboxBase.ChipRemove","sizeToMinHeight","TriggerMultipleWithInput","placeholder","renderItem","inputSide","controlledValue","chipsToRender","ComboboxBase.Chips","item","internalValue","Fragment","Combobox","ComboboxBase.Collection"],"mappings":"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"}
|
package/dist/code/server.js
CHANGED
|
@@ -27,7 +27,6 @@ async function u(t, i, r = {}) {
|
|
|
27
27
|
import("../chunks/vesper-ebfu9ns65f2v830s.js")
|
|
28
28
|
]), n = await h[i](), e = await o({
|
|
29
29
|
themes: [s.default, m.default],
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
30
|
langs: [n.default],
|
|
32
31
|
engine: a
|
|
33
32
|
}), l = e.codeToHtml(t, {
|
|
@@ -53,7 +52,6 @@ async function w(t) {
|
|
|
53
52
|
s.map((e) => h[e]())
|
|
54
53
|
), n = await i({
|
|
55
54
|
themes: [c.default, a.default],
|
|
56
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
55
|
langs: m.map((e) => e.default),
|
|
58
56
|
engine: o
|
|
59
57
|
});
|
package/dist/code/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sources":["../../src/code/server.tsx"],"sourcesContent":["/**\n * Server-side utilities for Shiki syntax highlighting.\n *\n * Use these in SSR frameworks (Next.js, Astro, Remix) or build-time scripts.\n * These functions are async and should NOT be imported in client bundles.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * // Next.js RSC\n * import { highlightCode, CodeBlock } from \"@cloudflare/kumo/code/server\";\n *\n * export default async function Page() {\n * const html = await highlightCode(`const x = 1;`, \"tsx\");\n * return <CodeBlock html={html} />;\n * }\n * ```\n */\n\nimport type { HighlighterCore } from \"shiki/core\";\nimport type { ShikiEngine, SupportedLanguage } from \"./types\";\nimport type { ReactNode } from \"react\";\n\n/**\n * Pre-bundled languages - only these languages are included in the Kumo bundle.\n * Using fine-grained imports from @shikijs/langs to minimize bundle size.\n */\nconst BUNDLED_LANGS: Record<\n SupportedLanguage,\n () => Promise<{ default: unknown }>\n> = {\n javascript: () => import(\"@shikijs/langs/javascript\"),\n typescript: () => import(\"@shikijs/langs/typescript\"),\n jsx: () => import(\"@shikijs/langs/jsx\"),\n tsx: () => import(\"@shikijs/langs/tsx\"),\n json: () => import(\"@shikijs/langs/json\"),\n jsonc: () => import(\"@shikijs/langs/jsonc\"),\n html: () => import(\"@shikijs/langs/html\"),\n css: () => import(\"@shikijs/langs/css\"),\n python: () => import(\"@shikijs/langs/python\"),\n yaml: () => import(\"@shikijs/langs/yaml\"),\n markdown: () => import(\"@shikijs/langs/markdown\"),\n graphql: () => import(\"@shikijs/langs/graphql\"),\n sql: () => import(\"@shikijs/langs/sql\"),\n bash: () => import(\"@shikijs/langs/bash\"),\n shell: () => import(\"@shikijs/langs/shellscript\"),\n diff: () => import(\"@shikijs/langs/diff\"),\n};\n\nexport interface HighlightCodeOptions {\n /** Highlighting engine (default: \"javascript\") */\n engine?: ShikiEngine;\n}\n\nexport interface CreateHighlighterOptions {\n /** Highlighting engine (default: \"javascript\") */\n engine?: ShikiEngine;\n /** Languages to support */\n languages: SupportedLanguage[];\n}\n\nexport interface ServerHighlighter {\n /** Highlight code and return HTML string */\n highlight: (code: string, lang: SupportedLanguage) => string;\n /** Dispose the highlighter when done */\n dispose: () => void;\n}\n\n/**\n * One-off highlighting for a single code snippet.\n *\n * Creates a highlighter, highlights the code, and disposes.\n * For multiple highlights, use `createServerHighlighter` instead.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * const html = await highlightCode(code, \"tsx\");\n * ```\n */\nexport async function highlightCode(\n code: string,\n lang: SupportedLanguage,\n options: HighlightCodeOptions = {},\n): Promise<string> {\n const { createHighlighterCore } = await import(\"shiki/core\");\n\n const engine = options.engine ?? \"javascript\";\n const engineInstance =\n engine === \"wasm\"\n ? await import(\"shiki/engine/oniguruma\").then((m) =>\n m.createOnigurumaEngine(import(\"shiki/wasm\")),\n )\n : await import(\"shiki/engine/javascript\").then((m) =>\n m.createJavaScriptRegexEngine(),\n );\n\n // Load themes\n const [githubLight, vesper] = await Promise.all([\n import(\"@shikijs/themes/github-light\"),\n import(\"@shikijs/themes/vesper\"),\n ]);\n\n // Load only the requested language\n const langModule = await BUNDLED_LANGS[lang]();\n\n const highlighter = await createHighlighterCore({\n themes: [githubLight.default, vesper.default],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n langs: [langModule.default] as any,\n engine: engineInstance,\n });\n\n const html = highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light\",\n dark: \"vesper\",\n },\n });\n\n highlighter.dispose();\n\n return html;\n}\n\n/**\n * Create a reusable highlighter for multiple code snippets.\n *\n * More efficient than `highlightCode` when highlighting multiple snippets.\n * Remember to call `dispose()` when done.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * const highlighter = await createServerHighlighter({\n * languages: [\"tsx\", \"bash\", \"json\"],\n * });\n *\n * const html1 = highlighter.highlight(code1, \"tsx\");\n * const html2 = highlighter.highlight(code2, \"bash\");\n *\n * highlighter.dispose();\n * ```\n */\nexport async function createServerHighlighter(\n options: CreateHighlighterOptions,\n): Promise<ServerHighlighter> {\n const { createHighlighterCore } = await import(\"shiki/core\");\n\n const engine = options.engine ?? \"javascript\";\n const engineInstance =\n engine === \"wasm\"\n ? await import(\"shiki/engine/oniguruma\").then((m) =>\n m.createOnigurumaEngine(import(\"shiki/wasm\")),\n )\n : await import(\"shiki/engine/javascript\").then((m) =>\n m.createJavaScriptRegexEngine(),\n );\n\n // Load themes\n const [githubLight, vesper] = await Promise.all([\n import(\"@shikijs/themes/github-light\"),\n import(\"@shikijs/themes/vesper\"),\n ]);\n\n // Load only the requested languages from our bundled set\n const validLanguages = options.languages.filter(\n (lang): lang is SupportedLanguage => lang in BUNDLED_LANGS,\n );\n\n const langModules = await Promise.all(\n validLanguages.map((lang) => BUNDLED_LANGS[lang]()),\n );\n\n const highlighter: HighlighterCore = await createHighlighterCore({\n themes: [githubLight.default, vesper.default],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n langs: langModules.map((m) => m.default) as any,\n engine: engineInstance,\n });\n\n return {\n highlight: (code: string, lang: SupportedLanguage): string => {\n return highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light\",\n dark: \"vesper\",\n },\n });\n },\n dispose: () => {\n highlighter.dispose();\n },\n };\n}\n\n/**\n * Props for the CodeBlock component.\n */\nexport interface CodeBlockProps {\n /** Pre-rendered HTML from highlightCode() or createServerHighlighter().highlight() */\n html: string;\n /** Additional CSS classes for the container */\n className?: string;\n}\n\n/**\n * Server component that wraps highlighted code HTML with proper styling.\n *\n * Use this with `highlightCode()` or `createServerHighlighter().highlight()`\n * to render syntax-highlighted code blocks with consistent Kumo styling.\n *\n * @example\n * ```tsx\n * import { highlightCode, CodeBlock } from \"@cloudflare/kumo/code/server\";\n *\n * export default async function Page() {\n * const html = await highlightCode(`const x = 1;`, \"tsx\");\n * return <CodeBlock html={html} />;\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With createServerHighlighter for multiple blocks\n * const highlighter = await createServerHighlighter({ languages: [\"tsx\", \"bash\"] });\n *\n * return (\n * <>\n * <CodeBlock html={highlighter.highlight(code1, \"tsx\")} />\n * <CodeBlock html={highlighter.highlight(code2, \"bash\")} />\n * </>\n * );\n *\n * highlighter.dispose();\n * ```\n */\nexport function CodeBlock({ html, className }: CodeBlockProps): ReactNode {\n const containerClass = className\n ? `group relative w-full min-w-0 rounded-md border border-kumo-fill bg-kumo-base ${className}`\n : \"group relative w-full min-w-0 rounded-md border border-kumo-fill bg-kumo-base\";\n\n return (\n <div className={containerClass}>\n <div className=\"overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </div>\n </div>\n );\n}\n"],"names":["BUNDLED_LANGS","n","highlightCode","code","lang","options","createHighlighterCore","engineInstance","m","githubLight","vesper","langModule","highlighter","html","createServerHighlighter","validLanguages","langModules","CodeBlock","className","containerClass","jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../../src/code/server.tsx"],"sourcesContent":["/**\n * Server-side utilities for Shiki syntax highlighting.\n *\n * Use these in SSR frameworks (Next.js, Astro, Remix) or build-time scripts.\n * These functions are async and should NOT be imported in client bundles.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * // Next.js RSC\n * import { highlightCode, CodeBlock } from \"@cloudflare/kumo/code/server\";\n *\n * export default async function Page() {\n * const html = await highlightCode(`const x = 1;`, \"tsx\");\n * return <CodeBlock html={html} />;\n * }\n * ```\n */\n\nimport type { HighlighterCore } from \"shiki/core\";\nimport type { ShikiEngine, SupportedLanguage } from \"./types\";\nimport type { ReactNode } from \"react\";\n\n/**\n * Pre-bundled languages - only these languages are included in the Kumo bundle.\n * Using fine-grained imports from @shikijs/langs to minimize bundle size.\n */\nconst BUNDLED_LANGS: Record<\n SupportedLanguage,\n () => Promise<{ default: unknown }>\n> = {\n javascript: () => import(\"@shikijs/langs/javascript\"),\n typescript: () => import(\"@shikijs/langs/typescript\"),\n jsx: () => import(\"@shikijs/langs/jsx\"),\n tsx: () => import(\"@shikijs/langs/tsx\"),\n json: () => import(\"@shikijs/langs/json\"),\n jsonc: () => import(\"@shikijs/langs/jsonc\"),\n html: () => import(\"@shikijs/langs/html\"),\n css: () => import(\"@shikijs/langs/css\"),\n python: () => import(\"@shikijs/langs/python\"),\n yaml: () => import(\"@shikijs/langs/yaml\"),\n markdown: () => import(\"@shikijs/langs/markdown\"),\n graphql: () => import(\"@shikijs/langs/graphql\"),\n sql: () => import(\"@shikijs/langs/sql\"),\n bash: () => import(\"@shikijs/langs/bash\"),\n shell: () => import(\"@shikijs/langs/shellscript\"),\n diff: () => import(\"@shikijs/langs/diff\"),\n};\n\nexport interface HighlightCodeOptions {\n /** Highlighting engine (default: \"javascript\") */\n engine?: ShikiEngine;\n}\n\nexport interface CreateHighlighterOptions {\n /** Highlighting engine (default: \"javascript\") */\n engine?: ShikiEngine;\n /** Languages to support */\n languages: SupportedLanguage[];\n}\n\nexport interface ServerHighlighter {\n /** Highlight code and return HTML string */\n highlight: (code: string, lang: SupportedLanguage) => string;\n /** Dispose the highlighter when done */\n dispose: () => void;\n}\n\n/**\n * One-off highlighting for a single code snippet.\n *\n * Creates a highlighter, highlights the code, and disposes.\n * For multiple highlights, use `createServerHighlighter` instead.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * const html = await highlightCode(code, \"tsx\");\n * ```\n */\nexport async function highlightCode(\n code: string,\n lang: SupportedLanguage,\n options: HighlightCodeOptions = {},\n): Promise<string> {\n const { createHighlighterCore } = await import(\"shiki/core\");\n\n const engine = options.engine ?? \"javascript\";\n const engineInstance =\n engine === \"wasm\"\n ? await import(\"shiki/engine/oniguruma\").then((m) =>\n m.createOnigurumaEngine(import(\"shiki/wasm\")),\n )\n : await import(\"shiki/engine/javascript\").then((m) =>\n m.createJavaScriptRegexEngine(),\n );\n\n // Load themes\n const [githubLight, vesper] = await Promise.all([\n import(\"@shikijs/themes/github-light\"),\n import(\"@shikijs/themes/vesper\"),\n ]);\n\n // Load only the requested language\n const langModule = await BUNDLED_LANGS[lang]();\n\n const highlighter = await createHighlighterCore({\n themes: [githubLight.default, vesper.default],\n\n langs: [langModule.default] as any,\n engine: engineInstance,\n });\n\n const html = highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light\",\n dark: \"vesper\",\n },\n });\n\n highlighter.dispose();\n\n return html;\n}\n\n/**\n * Create a reusable highlighter for multiple code snippets.\n *\n * More efficient than `highlightCode` when highlighting multiple snippets.\n * Remember to call `dispose()` when done.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * const highlighter = await createServerHighlighter({\n * languages: [\"tsx\", \"bash\", \"json\"],\n * });\n *\n * const html1 = highlighter.highlight(code1, \"tsx\");\n * const html2 = highlighter.highlight(code2, \"bash\");\n *\n * highlighter.dispose();\n * ```\n */\nexport async function createServerHighlighter(\n options: CreateHighlighterOptions,\n): Promise<ServerHighlighter> {\n const { createHighlighterCore } = await import(\"shiki/core\");\n\n const engine = options.engine ?? \"javascript\";\n const engineInstance =\n engine === \"wasm\"\n ? await import(\"shiki/engine/oniguruma\").then((m) =>\n m.createOnigurumaEngine(import(\"shiki/wasm\")),\n )\n : await import(\"shiki/engine/javascript\").then((m) =>\n m.createJavaScriptRegexEngine(),\n );\n\n // Load themes\n const [githubLight, vesper] = await Promise.all([\n import(\"@shikijs/themes/github-light\"),\n import(\"@shikijs/themes/vesper\"),\n ]);\n\n // Load only the requested languages from our bundled set\n const validLanguages = options.languages.filter(\n (lang): lang is SupportedLanguage => lang in BUNDLED_LANGS,\n );\n\n const langModules = await Promise.all(\n validLanguages.map((lang) => BUNDLED_LANGS[lang]()),\n );\n\n const highlighter: HighlighterCore = await createHighlighterCore({\n themes: [githubLight.default, vesper.default],\n\n langs: langModules.map((m) => m.default) as any,\n engine: engineInstance,\n });\n\n return {\n highlight: (code: string, lang: SupportedLanguage): string => {\n return highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light\",\n dark: \"vesper\",\n },\n });\n },\n dispose: () => {\n highlighter.dispose();\n },\n };\n}\n\n/**\n * Props for the CodeBlock component.\n */\nexport interface CodeBlockProps {\n /** Pre-rendered HTML from highlightCode() or createServerHighlighter().highlight() */\n html: string;\n /** Additional CSS classes for the container */\n className?: string;\n}\n\n/**\n * Server component that wraps highlighted code HTML with proper styling.\n *\n * Use this with `highlightCode()` or `createServerHighlighter().highlight()`\n * to render syntax-highlighted code blocks with consistent Kumo styling.\n *\n * @example\n * ```tsx\n * import { highlightCode, CodeBlock } from \"@cloudflare/kumo/code/server\";\n *\n * export default async function Page() {\n * const html = await highlightCode(`const x = 1;`, \"tsx\");\n * return <CodeBlock html={html} />;\n * }\n * ```\n *\n * @example\n * ```tsx\n * // With createServerHighlighter for multiple blocks\n * const highlighter = await createServerHighlighter({ languages: [\"tsx\", \"bash\"] });\n *\n * return (\n * <>\n * <CodeBlock html={highlighter.highlight(code1, \"tsx\")} />\n * <CodeBlock html={highlighter.highlight(code2, \"bash\")} />\n * </>\n * );\n *\n * highlighter.dispose();\n * ```\n */\nexport function CodeBlock({ html, className }: CodeBlockProps): ReactNode {\n const containerClass = className\n ? `group relative w-full min-w-0 rounded-md border border-kumo-fill bg-kumo-base ${className}`\n : \"group relative w-full min-w-0 rounded-md border border-kumo-fill bg-kumo-base\";\n\n return (\n <div className={containerClass}>\n <div className=\"overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </div>\n </div>\n );\n}\n"],"names":["BUNDLED_LANGS","n","highlightCode","code","lang","options","createHighlighterCore","engineInstance","m","githubLight","vesper","langModule","highlighter","html","createServerHighlighter","validLanguages","langModules","CodeBlock","className","containerClass","jsx"],"mappings":"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"}
|
package/dist/code.js
CHANGED
package/dist/code.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code.js","sources":["../src/code/context.ts","../src/code/provider.tsx","../src/code/use-shiki-highlighter.ts","../src/code/code-highlighted.tsx"],"sourcesContent":["import { createContext } from \"react\";\nimport type { HighlighterCore } from \"shiki/core\";\nimport type { SupportedLanguage, CodeHighlightedLabels } from \"./types\";\n\nexport interface ShikiContextValue {\n /** The initialized Shiki highlighter instance */\n highlighter: HighlighterCore | null;\n\n /** True while Shiki is loading */\n isLoading: boolean;\n\n /** Error if initialization failed */\n error: Error | null;\n\n /** Configured languages */\n languages: SupportedLanguage[];\n\n /** Localized labels for UI elements */\n labels: CodeHighlightedLabels;\n}\n\nexport const ShikiContext = createContext<ShikiContextValue | null>(null);\n","\"use client\";\n\nimport { useState, useEffect, useMemo, type ReactNode } from \"react\";\nimport { ShikiContext, type ShikiContextValue } from \"./context\";\nimport type { ShikiProviderProps, SupportedLanguage } from \"./types\";\n\n/**\n * Pre-bundled languages - only these languages are included in the Kumo bundle.\n * Using fine-grained imports from @shikijs/langs to minimize bundle size.\n */\nconst BUNDLED_LANGS: Record<\n SupportedLanguage,\n () => Promise<{ default: unknown }>\n> = {\n javascript: () => import(\"@shikijs/langs/javascript\"),\n typescript: () => import(\"@shikijs/langs/typescript\"),\n jsx: () => import(\"@shikijs/langs/jsx\"),\n tsx: () => import(\"@shikijs/langs/tsx\"),\n json: () => import(\"@shikijs/langs/json\"),\n jsonc: () => import(\"@shikijs/langs/jsonc\"),\n html: () => import(\"@shikijs/langs/html\"),\n css: () => import(\"@shikijs/langs/css\"),\n python: () => import(\"@shikijs/langs/python\"),\n yaml: () => import(\"@shikijs/langs/yaml\"),\n markdown: () => import(\"@shikijs/langs/markdown\"),\n graphql: () => import(\"@shikijs/langs/graphql\"),\n sql: () => import(\"@shikijs/langs/sql\"),\n bash: () => import(\"@shikijs/langs/bash\"),\n shell: () => import(\"@shikijs/langs/shellscript\"),\n diff: () => import(\"@shikijs/langs/diff\"),\n};\n\n/**\n * Provider component that initializes and manages Shiki highlighting.\n *\n * Shiki is lazy-loaded on first render — no JavaScript is downloaded\n * until this provider mounts. While loading, child components can\n * render code as plain text.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { ShikiProvider, CodeHighlighted } from \"@cloudflare/kumo/code\";\n *\n * function App() {\n * return (\n * <ShikiProvider\n * engine=\"javascript\"\n * languages={['tsx', 'bash', 'json']}\n * >\n * <CodeHighlighted code=\"const x = 1;\" lang=\"tsx\" />\n * </ShikiProvider>\n * );\n * }\n * ```\n */\nconst DEFAULT_LABELS = {\n copy: \"Copy\",\n copied: \"Copied!\",\n};\n\nexport function ShikiProvider({\n engine,\n languages,\n labels,\n children,\n}: ShikiProviderProps): ReactNode {\n const [state, setState] = useState<{\n highlighter: ShikiContextValue[\"highlighter\"];\n isLoading: boolean;\n error: Error | null;\n }>({\n highlighter: null,\n isLoading: true,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function initializeShiki() {\n try {\n // Dynamic import of shiki/core — only loads the core, not all languages\n const { createHighlighterCore } = await import(\"shiki/core\");\n\n // Load the appropriate engine\n const engineInstance =\n engine === \"wasm\"\n ? await import(\"shiki/engine/oniguruma\").then((m) =>\n m.createOnigurumaEngine(import(\"shiki/wasm\")),\n )\n : await import(\"shiki/engine/javascript\").then((m) =>\n m.createJavaScriptRegexEngine(),\n );\n\n // Load themes\n const [githubLight, vesper] = await Promise.all([\n import(\"@shikijs/themes/github-light\"),\n import(\"@shikijs/themes/vesper\"),\n ]);\n\n // Load only the requested languages from our bundled set\n const validLanguages = languages.filter(\n (lang): lang is SupportedLanguage => lang in BUNDLED_LANGS,\n );\n\n const langModules = await Promise.all(\n validLanguages.map((lang) => BUNDLED_LANGS[lang]()),\n );\n\n const highlighter = await createHighlighterCore({\n themes: [githubLight.default, vesper.default],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n langs: langModules.map((m) => m.default) as any,\n engine: engineInstance,\n });\n\n if (!cancelled) {\n setState({\n highlighter,\n isLoading: false,\n error: null,\n });\n }\n } catch (err) {\n if (!cancelled) {\n setState({\n highlighter: null,\n isLoading: false,\n error:\n err instanceof Error ? err : new Error(\"Failed to load Shiki\"),\n });\n }\n }\n }\n\n void initializeShiki();\n\n return () => {\n cancelled = true;\n };\n }, [engine, languages]);\n\n const mergedLabels = useMemo(\n () => ({ ...DEFAULT_LABELS, ...labels }),\n [labels],\n );\n\n const contextValue = useMemo<ShikiContextValue>(\n () => ({\n highlighter: state.highlighter,\n isLoading: state.isLoading,\n error: state.error,\n languages: languages as SupportedLanguage[],\n labels: mergedLabels,\n }),\n [state.highlighter, state.isLoading, state.error, languages, mergedLabels],\n );\n\n return (\n <ShikiContext.Provider value={contextValue}>\n {children}\n </ShikiContext.Provider>\n );\n}\n\nShikiProvider.displayName = \"ShikiProvider\";\n","\"use client\";\n\nimport { useContext, useCallback } from \"react\";\nimport { ShikiContext } from \"./context\";\nimport type { UseShikiHighlighterResult, SupportedLanguage } from \"./types\";\n\n/**\n * Hook for accessing Shiki highlighting in custom implementations.\n *\n * Must be used within a ShikiProvider.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { useShikiHighlighter } from \"@cloudflare/kumo/code\";\n *\n * function CustomCodeBlock({ code, lang }) {\n * const { highlight, isLoading, isReady, error } = useShikiHighlighter();\n *\n * if (error) {\n * return <div>Failed to load highlighter</div>;\n * }\n *\n * if (isLoading) {\n * return <pre><code>{code}</code></pre>;\n * }\n *\n * const html = highlight(code, lang);\n *\n * // null means highlighting failed — render plain text\n * if (html === null) {\n * return <pre><code>{code}</code></pre>;\n * }\n *\n * return <pre dangerouslySetInnerHTML={{ __html: html }} />;\n * }\n * ```\n */\nexport function useShikiHighlighter(): UseShikiHighlighterResult {\n const context = useContext(ShikiContext);\n\n if (!context) {\n throw new Error(\n \"useShikiHighlighter must be used within a ShikiProvider. \" +\n \"Wrap your app with <ShikiProvider> from '@cloudflare/kumo/code'.\",\n );\n }\n\n const { highlighter, isLoading, error, languages, labels } = context;\n\n const highlight = useCallback(\n (code: string, lang: SupportedLanguage): string | null => {\n if (!highlighter) {\n return null;\n }\n\n // Check if the language is supported\n if (!languages.includes(lang)) {\n console.warn(\n `[Kumo CodeHighlighted] Language \"${lang}\" is not in the ShikiProvider's languages list. ` +\n `Add it to the languages array: languages={[...existing, '${lang}']}. ` +\n `Rendering as plain text.`,\n );\n return null;\n }\n\n try {\n // Use dual theme for light/dark mode support with hardcoded themes\n const html = highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light\",\n dark: \"vesper\",\n },\n });\n\n return html;\n } catch (err) {\n console.warn(\n `[Kumo CodeHighlighted] Failed to highlight code with language \"${lang}\":`,\n err,\n );\n return null;\n }\n },\n [highlighter, languages],\n );\n\n return {\n highlight,\n isLoading,\n isReady: !isLoading && highlighter !== null,\n error,\n labels,\n };\n}\n","\"use client\";\n\nimport { useState, useCallback, useMemo, type ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"../components/button\";\nimport { useShikiHighlighter } from \"./use-shiki-highlighter\";\nimport type { CodeHighlightedProps } from \"./types\";\n\n/**\n * Syntax-highlighted code block powered by Shiki.\n *\n * Must be used within a ShikiProvider. While Shiki is loading,\n * displays code as plain text (no layout shift, immediately readable).\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { ShikiProvider, CodeHighlighted } from \"@cloudflare/kumo/code\";\n *\n * <ShikiProvider\n * engine=\"javascript\"\n * languages={['tsx', 'bash']}\n * >\n * <CodeHighlighted\n * code={`const greeting = \"Hello!\";`}\n * lang=\"tsx\"\n * showLineNumbers\n * showCopyButton\n * />\n * </ShikiProvider>\n * ```\n */\nexport function CodeHighlighted({\n code,\n lang,\n showLineNumbers = false,\n highlightLines,\n showCopyButton = false,\n labels: labelOverrides,\n className,\n}: CodeHighlightedProps): ReactNode {\n const {\n highlight,\n isLoading,\n error,\n labels: providerLabels,\n } = useShikiHighlighter();\n const [copied, setCopied] = useState(false);\n\n // Merge provider labels with component-level overrides\n const labels = useMemo(\n () => ({ ...providerLabels, ...labelOverrides }),\n [providerLabels, labelOverrides],\n );\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error(\"[Kumo CodeHighlighted] Failed to copy to clipboard:\", err);\n }\n }, [code]);\n\n // Get highlighted HTML (or null if not ready/failed)\n const html = highlight(code, lang);\n\n // Count lines for line numbers\n const lineCount = useMemo(() => code.split(\"\\n\").length, [code]);\n\n // Detect single-line code for layout adjustments\n const isSingleLine = lineCount === 1;\n\n // Container styles - use flex layout for single-line with copy button\n // Includes defensive resets (m-0, p-0) to prevent global CSS pollution\n const containerClasses = cn(\n \"group relative m-0 w-full min-w-0 rounded-md border border-kumo-fill bg-kumo-base p-0\",\n showCopyButton && isSingleLine && \"flex items-center\",\n className,\n );\n\n // Copy button - inline for single-line, absolute for multi-line\n // Hidden until hover (or when showing \"Copied!\" feedback)\n const copyButton = showCopyButton ? (\n <div\n className={cn(\n isSingleLine ? \"shrink-0 px-2\" : \"absolute right-2 top-2\",\n !copied && \"opacity-0 transition-opacity group-hover:opacity-100\",\n )}\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleCopy}\n aria-label={copied ? labels.copied : labels.copy}\n >\n {copied ? labels.copied : labels.copy}\n </Button>\n </div>\n ) : null;\n\n // Line numbers column\n const lineNumbers =\n showLineNumbers && !isSingleLine ? (\n <div\n className=\"kumo-line-numbers shrink-0 select-none py-4 pr-4 text-right font-mono text-sm opacity-40\"\n aria-hidden=\"true\"\n >\n {Array.from({ length: lineCount }, (_, i) => (\n <div key={i + 1} className=\"leading-relaxed\">\n {i + 1}\n </div>\n ))}\n </div>\n ) : null;\n\n // Error state — still show code, just log the error\n if (error) {\n console.error(\"[Kumo CodeHighlighted] Shiki initialization error:\", error);\n }\n\n // Loading or failed to highlight — show plain text\n if (isLoading || html === null) {\n return (\n <div className={containerClasses}>\n {lineNumbers && (\n <div className=\"flex\">\n {lineNumbers}\n <pre className=\"!m-0 min-w-0 flex-1 overflow-x-auto !p-4 font-mono text-sm leading-relaxed text-kumo-strong\">\n <code className=\"!m-0 !p-0\">{code}</code>\n </pre>\n </div>\n )}\n {!lineNumbers && (\n <pre className=\"!m-0 min-w-0 flex-1 overflow-x-auto !p-4 font-mono text-sm leading-relaxed text-kumo-strong\">\n <code className=\"!m-0 !p-0\">{code}</code>\n </pre>\n )}\n {copyButton}\n </div>\n );\n }\n\n // Highlighted code\n return (\n <div className={containerClasses}>\n {lineNumbers && (\n <div className=\"flex w-full\">\n {lineNumbers}\n <div className=\"min-w-0 flex-1 overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:!m-0 [&>pre]:!border-0 [&>pre]:!rounded-none [&>pre]:!bg-transparent [&>pre]:!p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed [&_code]:!m-0 [&_code]:!p-0 [&_code]:!bg-transparent [&_code]:!border-0\"\n dangerouslySetInnerHTML={{\n __html: processHighlightedHtml(html, highlightLines),\n }}\n />\n </div>\n </div>\n )}\n {!lineNumbers && (\n <div className=\"overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:!m-0 [&>pre]:!border-0 [&>pre]:!rounded-none [&>pre]:!bg-transparent [&>pre]:!p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed [&_code]:!m-0 [&_code]:!p-0 [&_code]:!bg-transparent [&_code]:!border-0\"\n dangerouslySetInnerHTML={{\n __html: processHighlightedHtml(html, highlightLines),\n }}\n />\n </div>\n )}\n {copyButton}\n </div>\n );\n}\n\nCodeHighlighted.displayName = \"CodeHighlighted\";\n\n/**\n * Process Shiki's HTML output to add line highlighting classes.\n * Does NOT modify Shiki's token structure - only adds classes to line spans.\n */\nfunction processHighlightedHtml(\n html: string,\n highlightLines?: number[],\n): string {\n // Line numbers are not yet supported - would require more complex approach\n // For now, only handle line highlighting which just adds a class\n\n if (!highlightLines?.length) {\n return html;\n }\n\n const highlightSet = new Set(highlightLines);\n let lineNumber = 0;\n\n // Only add the highlight class to lines, don't restructure the HTML\n return html.replace(/<span class=\"line\">/g, () => {\n lineNumber++;\n const isHighlighted = highlightSet.has(lineNumber);\n return isHighlighted\n ? '<span class=\"line line-highlighted\">'\n : '<span class=\"line\">';\n });\n}\n"],"names":["ShikiContext","createContext","BUNDLED_LANGS","n","DEFAULT_LABELS","ShikiProvider","engine","languages","labels","children","state","setState","useState","useEffect","cancelled","initializeShiki","createHighlighterCore","engineInstance","m","githubLight","vesper","validLanguages","lang","langModules","highlighter","err","mergedLabels","useMemo","contextValue","useShikiHighlighter","context","useContext","isLoading","error","useCallback","code","CodeHighlighted","showLineNumbers","highlightLines","showCopyButton","labelOverrides","className","highlight","providerLabels","copied","setCopied","handleCopy","html","lineCount","isSingleLine","containerClasses","cn","copyButton","jsx","Button","lineNumbers","_","i","jsxs","processHighlightedHtml","highlightSet","lineNumber"],"mappings":";;;;;AAqBO,MAAMA,IAAeC,EAAwC,IAAI,GCXlEC,IAGF;AAAA,EACF,YAAY,MAAM,OAAO,yCAA2B;AAAA,EACpD,YAAY,MAAM,OAAO,yCAA2B;AAAA,EACpD,KAAK,MAAM,OAAO,kCAAoB;AAAA,EACtC,KAAK,MAAM,OAAO,kCAAoB;AAAA,EACtC,MAAM,MAAM,OAAO,mCAAqB;AAAA,EACxC,OAAO,MAAM,OAAO,oCAAsB;AAAA,EAC1C,MAAM,MAAM,OAAO,mCAAqB;AAAA,EACxC,KAAK,MAAM,OAAO,kCAAoB;AAAA,EACtC,QAAQ,MAAM,OAAO,qCAAuB;AAAA,EAC5C,MAAM,MAAM,OAAO,mCAAqB;AAAA,EACxC,UAAU,MAAM,OAAO,uCAAyB;AAAA,EAChD,SAAS,MAAM,OAAO,sCAAwB;AAAA,EAC9C,KAAK,MAAM,OAAO,kCAAoB;AAAA,EACtC,MAAM,MAAM,OAAO,mCAAqB,EAAA,KAAA,CAAAC,MAAAA,EAAA,CAAA;AAAA,EACxC,OAAO,MAAM,OAAO,mCAA4B,EAAA,KAAA,CAAAA,MAAAA,EAAA,CAAA;AAAA,EAChD,MAAM,MAAM,OAAO,mCAAqB;AAC1C,GA2BMC,IAAiB;AAAA,EACrB,MAAM;AAAA,EACN,QAAQ;AACV;AAEO,SAASC,EAAc;AAAA,EAC5B,QAAAC;AAAA,EACA,WAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC;AACF,GAAkC;AAChC,QAAM,CAACC,GAAOC,CAAQ,IAAIC,EAIvB;AAAA,IACD,aAAa;AAAA,IACb,WAAW;AAAA,IACX,OAAO;AAAA,EAAA,CACR;AAED,EAAAC,EAAU,MAAM;AACd,QAAIC,IAAY;AAEhB,mBAAeC,IAAkB;AAC/B,UAAI;AAEF,cAAM,EAAE,uBAAAC,EAAA,IAA0B,MAAM,OAAO,mCAAY,GAGrDC,IACJX,MAAW,SACP,MAAM,OAAO,+CAAwB,EAAE;AAAA,UAAK,CAACY,MAC3CA,EAAE,sBAAsB,OAAO,mCAAY,CAAC;AAAA,QAAA,IAE9C,MAAM,OAAO,gDAAyB,EAAE;AAAA,UAAK,CAACA,MAC5CA,EAAE,4BAAA;AAAA,QAA4B,GAIhC,CAACC,GAAaC,CAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,UAC9C,OAAO,2CAA8B;AAAA,UACrC,OAAO,qCAAwB;AAAA,QAAA,CAChC,GAGKC,IAAiBd,EAAU;AAAA,UAC/B,CAACe,MAAoCA,KAAQpB;AAAA,QAAA,GAGzCqB,IAAc,MAAM,QAAQ;AAAA,UAChCF,EAAe,IAAI,CAACC,MAASpB,EAAcoB,CAAI,GAAG;AAAA,QAAA,GAG9CE,IAAc,MAAMR,EAAsB;AAAA,UAC9C,QAAQ,CAACG,EAAY,SAASC,EAAO,OAAO;AAAA;AAAA,UAE5C,OAAOG,EAAY,IAAI,CAACL,MAAMA,EAAE,OAAO;AAAA,UACvC,QAAQD;AAAA,QAAA,CACT;AAED,QAAKH,KACHH,EAAS;AAAA,UACP,aAAAa;AAAA,UACA,WAAW;AAAA,UACX,OAAO;AAAA,QAAA,CACR;AAAA,MAEL,SAASC,GAAK;AACZ,QAAKX,KACHH,EAAS;AAAA,UACP,aAAa;AAAA,UACb,WAAW;AAAA,UACX,OACEc,aAAe,QAAQA,IAAM,IAAI,MAAM,sBAAsB;AAAA,QAAA,CAChE;AAAA,MAEL;AAAA,IACF;AAEA,WAAKV,EAAA,GAEE,MAAM;AACX,MAAAD,IAAY;AAAA,IACd;AAAA,EACF,GAAG,CAACR,GAAQC,CAAS,CAAC;AAEtB,QAAMmB,IAAeC;AAAA,IACnB,OAAO,EAAE,GAAGvB,GAAgB,GAAGI;IAC/B,CAACA,CAAM;AAAA,EAAA,GAGHoB,IAAeD;AAAA,IACnB,OAAO;AAAA,MACL,aAAajB,EAAM;AAAA,MACnB,WAAWA,EAAM;AAAA,MACjB,OAAOA,EAAM;AAAA,MACb,WAAAH;AAAA,MACA,QAAQmB;AAAA,IAAA;AAAA,IAEV,CAAChB,EAAM,aAAaA,EAAM,WAAWA,EAAM,OAAOH,GAAWmB,CAAY;AAAA,EAAA;AAG3E,2BACG1B,EAAa,UAAb,EAAsB,OAAO4B,GAC3B,UAAAnB,GACH;AAEJ;AAEAJ,EAAc,cAAc;AChIrB,SAASwB,IAAiD;AAC/D,QAAMC,IAAUC,EAAW/B,CAAY;AAEvC,MAAI,CAAC8B;AACH,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAKJ,QAAM,EAAE,aAAAN,GAAa,WAAAQ,GAAW,OAAAC,GAAO,WAAA1B,GAAW,QAAAC,MAAWsB;AAwC7D,SAAO;AAAA,IACL,WAvCgBI;AAAA,MAChB,CAACC,GAAcb,MAA2C;AACxD,YAAI,CAACE;AACH,iBAAO;AAIT,YAAI,CAACjB,EAAU,SAASe,CAAI;AAC1B,yBAAQ;AAAA,YACN,oCAAoCA,CAAI,4GACsBA,CAAI;AAAA,UAAA,GAG7D;AAGT,YAAI;AAUF,iBARaE,EAAY,WAAWW,GAAM;AAAA,YACxC,MAAAb;AAAA,YACA,QAAQ;AAAA,cACN,OAAO;AAAA,cACP,MAAM;AAAA,YAAA;AAAA,UACR,CACD;AAAA,QAGH,SAASG,GAAK;AACZ,yBAAQ;AAAA,YACN,kEAAkEH,CAAI;AAAA,YACtEG;AAAA,UAAA,GAEK;AAAA,QACT;AAAA,MACF;AAAA,MACA,CAACD,GAAajB,CAAS;AAAA,IAAA;AAAA,IAKvB,WAAAyB;AAAA,IACA,SAAS,CAACA,KAAaR,MAAgB;AAAA,IACvC,OAAAS;AAAA,IACA,QAAAzB;AAAA,EAAA;AAEJ;AC/DO,SAAS4B,EAAgB;AAAA,EAC9B,MAAAD;AAAA,EACA,MAAAb;AAAA,EACA,iBAAAe,IAAkB;AAAA,EAClB,gBAAAC;AAAA,EACA,gBAAAC,IAAiB;AAAA,EACjB,QAAQC;AAAA,EACR,WAAAC;AACF,GAAoC;AAClC,QAAM;AAAA,IACJ,WAAAC;AAAA,IACA,WAAAV;AAAA,IACA,OAAAC;AAAA,IACA,QAAQU;AAAA,EAAA,IACNd,EAAA,GACE,CAACe,GAAQC,CAAS,IAAIjC,EAAS,EAAK,GAGpCJ,IAASmB;AAAA,IACb,OAAO,EAAE,GAAGgB,GAAgB,GAAGH;IAC/B,CAACG,GAAgBH,CAAc;AAAA,EAAA,GAG3BM,IAAaZ,EAAY,YAAY;AACzC,QAAI;AACF,YAAM,UAAU,UAAU,UAAUC,CAAI,GACxCU,EAAU,EAAI,GACd,WAAW,MAAMA,EAAU,EAAK,GAAG,GAAI;AAAA,IACzC,SAASpB,GAAK;AACZ,cAAQ,MAAM,uDAAuDA,CAAG;AAAA,IAC1E;AAAA,EACF,GAAG,CAACU,CAAI,CAAC,GAGHY,IAAOL,EAAUP,GAAMb,CAAI,GAG3B0B,IAAYrB,EAAQ,MAAMQ,EAAK,MAAM;AAAA,CAAI,EAAE,QAAQ,CAACA,CAAI,CAAC,GAGzDc,IAAeD,MAAc,GAI7BE,IAAmBC;AAAA,IACvB;AAAA,IACAZ,KAAkBU,KAAgB;AAAA,IAClCR;AAAA,EAAA,GAKIW,IAAab,IACjB,gBAAAc;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWF;AAAA,QACTF,IAAe,kBAAkB;AAAA,QACjC,CAACL,KAAU;AAAA,MAAA;AAAA,MAGb,UAAA,gBAAAS;AAAA,QAACC;AAAA,QAAA;AAAA,UACC,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,SAASR;AAAA,UACT,cAAYF,IAASpC,EAAO,SAASA,EAAO;AAAA,UAE3C,UAAAoC,IAASpC,EAAO,SAASA,EAAO;AAAA,QAAA;AAAA,MAAA;AAAA,IACnC;AAAA,EAAA,IAEA,MAGE+C,IACJlB,KAAmB,CAACY,IAClB,gBAAAI;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAU;AAAA,MACV,eAAY;AAAA,MAEX,gBAAM,KAAK,EAAE,QAAQL,KAAa,CAACQ,GAAGC,MACrC,gBAAAJ,EAAC,SAAgB,WAAU,mBACxB,cAAI,EAAA,GADGI,IAAI,CAEd,CACD;AAAA,IAAA;AAAA,EAAA,IAED;AAQN,SALIxB,KACF,QAAQ,MAAM,sDAAsDA,CAAK,GAIvED,KAAae,MAAS,OAEtB,gBAAAW,EAAC,OAAA,EAAI,WAAWR,GACb,UAAA;AAAA,IAAAK,KACC,gBAAAG,EAAC,OAAA,EAAI,WAAU,QACZ,UAAA;AAAA,MAAAH;AAAA,MACD,gBAAAF,EAAC,SAAI,WAAU,+FACb,4BAAC,QAAA,EAAK,WAAU,aAAa,UAAAlB,EAAA,CAAK,EAAA,CACpC;AAAA,IAAA,GACF;AAAA,IAED,CAACoB,KACA,gBAAAF,EAAC,OAAA,EAAI,WAAU,+FACb,UAAA,gBAAAA,EAAC,QAAA,EAAK,WAAU,aAAa,UAAAlB,EAAA,CAAK,GACpC;AAAA,IAEDiB;AAAA,EAAA,GACH,IAMF,gBAAAM,EAAC,OAAA,EAAI,WAAWR,GACb,UAAA;AAAA,IAAAK,KACC,gBAAAG,EAAC,OAAA,EAAI,WAAU,eACZ,UAAA;AAAA,MAAAH;AAAA,MACD,gBAAAF,EAAC,OAAA,EAAI,WAAU,kCACb,UAAA,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,yBAAyB;AAAA,YACvB,QAAQM,EAAuBZ,GAAMT,CAAc;AAAA,UAAA;AAAA,QACrD;AAAA,MAAA,EACF,CACF;AAAA,IAAA,GACF;AAAA,IAED,CAACiB,KACA,gBAAAF,EAAC,OAAA,EAAI,WAAU,mBACb,UAAA,gBAAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,yBAAyB;AAAA,UACvB,QAAQM,EAAuBZ,GAAMT,CAAc;AAAA,QAAA;AAAA,MACrD;AAAA,IAAA,GAEJ;AAAA,IAEDc;AAAA,EAAA,GACH;AAEJ;AAEAhB,EAAgB,cAAc;AAM9B,SAASuB,EACPZ,GACAT,GACQ;AAIR,MAAI,CAACA,GAAgB;AACnB,WAAOS;AAGT,QAAMa,IAAe,IAAI,IAAItB,CAAc;AAC3C,MAAIuB,IAAa;AAGjB,SAAOd,EAAK,QAAQ,wBAAwB,OAC1Cc,KACsBD,EAAa,IAAIC,CAAU,IAE7C,yCACA,sBACL;AACH;"}
|
|
1
|
+
{"version":3,"file":"code.js","sources":["../src/code/context.ts","../src/code/provider.tsx","../src/code/use-shiki-highlighter.ts","../src/code/code-highlighted.tsx"],"sourcesContent":["import { createContext } from \"react\";\nimport type { HighlighterCore } from \"shiki/core\";\nimport type { SupportedLanguage, CodeHighlightedLabels } from \"./types\";\n\nexport interface ShikiContextValue {\n /** The initialized Shiki highlighter instance */\n highlighter: HighlighterCore | null;\n\n /** True while Shiki is loading */\n isLoading: boolean;\n\n /** Error if initialization failed */\n error: Error | null;\n\n /** Configured languages */\n languages: SupportedLanguage[];\n\n /** Localized labels for UI elements */\n labels: CodeHighlightedLabels;\n}\n\nexport const ShikiContext = createContext<ShikiContextValue | null>(null);\n","\"use client\";\n\nimport { useState, useEffect, useMemo, type ReactNode } from \"react\";\nimport { ShikiContext, type ShikiContextValue } from \"./context\";\nimport type { ShikiProviderProps, SupportedLanguage } from \"./types\";\n\n/**\n * Pre-bundled languages - only these languages are included in the Kumo bundle.\n * Using fine-grained imports from @shikijs/langs to minimize bundle size.\n */\nconst BUNDLED_LANGS: Record<\n SupportedLanguage,\n () => Promise<{ default: unknown }>\n> = {\n javascript: () => import(\"@shikijs/langs/javascript\"),\n typescript: () => import(\"@shikijs/langs/typescript\"),\n jsx: () => import(\"@shikijs/langs/jsx\"),\n tsx: () => import(\"@shikijs/langs/tsx\"),\n json: () => import(\"@shikijs/langs/json\"),\n jsonc: () => import(\"@shikijs/langs/jsonc\"),\n html: () => import(\"@shikijs/langs/html\"),\n css: () => import(\"@shikijs/langs/css\"),\n python: () => import(\"@shikijs/langs/python\"),\n yaml: () => import(\"@shikijs/langs/yaml\"),\n markdown: () => import(\"@shikijs/langs/markdown\"),\n graphql: () => import(\"@shikijs/langs/graphql\"),\n sql: () => import(\"@shikijs/langs/sql\"),\n bash: () => import(\"@shikijs/langs/bash\"),\n shell: () => import(\"@shikijs/langs/shellscript\"),\n diff: () => import(\"@shikijs/langs/diff\"),\n};\n\n/**\n * Provider component that initializes and manages Shiki highlighting.\n *\n * Shiki is lazy-loaded on first render — no JavaScript is downloaded\n * until this provider mounts. While loading, child components can\n * render code as plain text.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { ShikiProvider, CodeHighlighted } from \"@cloudflare/kumo/code\";\n *\n * function App() {\n * return (\n * <ShikiProvider\n * engine=\"javascript\"\n * languages={['tsx', 'bash', 'json']}\n * >\n * <CodeHighlighted code=\"const x = 1;\" lang=\"tsx\" />\n * </ShikiProvider>\n * );\n * }\n * ```\n */\nconst DEFAULT_LABELS = {\n copy: \"Copy\",\n copied: \"Copied!\",\n};\n\nexport function ShikiProvider({\n engine,\n languages,\n labels,\n children,\n}: ShikiProviderProps): ReactNode {\n const [state, setState] = useState<{\n highlighter: ShikiContextValue[\"highlighter\"];\n isLoading: boolean;\n error: Error | null;\n }>({\n highlighter: null,\n isLoading: true,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n async function initializeShiki() {\n try {\n // Dynamic import of shiki/core — only loads the core, not all languages\n const { createHighlighterCore } = await import(\"shiki/core\");\n\n // Load the appropriate engine\n const engineInstance =\n engine === \"wasm\"\n ? await import(\"shiki/engine/oniguruma\").then((m) =>\n m.createOnigurumaEngine(import(\"shiki/wasm\")),\n )\n : await import(\"shiki/engine/javascript\").then((m) =>\n m.createJavaScriptRegexEngine(),\n );\n\n // Load themes\n const [githubLight, vesper] = await Promise.all([\n import(\"@shikijs/themes/github-light\"),\n import(\"@shikijs/themes/vesper\"),\n ]);\n\n // Load only the requested languages from our bundled set\n const validLanguages = languages.filter(\n (lang): lang is SupportedLanguage => lang in BUNDLED_LANGS,\n );\n\n const langModules = await Promise.all(\n validLanguages.map((lang) => BUNDLED_LANGS[lang]()),\n );\n\n const highlighter = await createHighlighterCore({\n themes: [githubLight.default, vesper.default],\n \n langs: langModules.map((m) => m.default) as any,\n engine: engineInstance,\n });\n\n if (!cancelled) {\n setState({\n highlighter,\n isLoading: false,\n error: null,\n });\n }\n } catch (err) {\n if (!cancelled) {\n setState({\n highlighter: null,\n isLoading: false,\n error:\n err instanceof Error ? err : new Error(\"Failed to load Shiki\"),\n });\n }\n }\n }\n\n void initializeShiki();\n\n return () => {\n cancelled = true;\n };\n }, [engine, languages]);\n\n const mergedLabels = useMemo(\n () => ({ ...DEFAULT_LABELS, ...labels }),\n [labels],\n );\n\n const contextValue = useMemo<ShikiContextValue>(\n () => ({\n highlighter: state.highlighter,\n isLoading: state.isLoading,\n error: state.error,\n languages: languages as SupportedLanguage[],\n labels: mergedLabels,\n }),\n [state.highlighter, state.isLoading, state.error, languages, mergedLabels],\n );\n\n return (\n <ShikiContext.Provider value={contextValue}>\n {children}\n </ShikiContext.Provider>\n );\n}\n\nShikiProvider.displayName = \"ShikiProvider\";\n","\"use client\";\n\nimport { useContext, useCallback } from \"react\";\nimport { ShikiContext } from \"./context\";\nimport type { UseShikiHighlighterResult, SupportedLanguage } from \"./types\";\n\n/**\n * Hook for accessing Shiki highlighting in custom implementations.\n *\n * Must be used within a ShikiProvider.\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { useShikiHighlighter } from \"@cloudflare/kumo/code\";\n *\n * function CustomCodeBlock({ code, lang }) {\n * const { highlight, isLoading, isReady, error } = useShikiHighlighter();\n *\n * if (error) {\n * return <div>Failed to load highlighter</div>;\n * }\n *\n * if (isLoading) {\n * return <pre><code>{code}</code></pre>;\n * }\n *\n * const html = highlight(code, lang);\n *\n * // null means highlighting failed — render plain text\n * if (html === null) {\n * return <pre><code>{code}</code></pre>;\n * }\n *\n * return <pre dangerouslySetInnerHTML={{ __html: html }} />;\n * }\n * ```\n */\nexport function useShikiHighlighter(): UseShikiHighlighterResult {\n const context = useContext(ShikiContext);\n\n if (!context) {\n throw new Error(\n \"useShikiHighlighter must be used within a ShikiProvider. \" +\n \"Wrap your app with <ShikiProvider> from '@cloudflare/kumo/code'.\",\n );\n }\n\n const { highlighter, isLoading, error, languages, labels } = context;\n\n const highlight = useCallback(\n (code: string, lang: SupportedLanguage): string | null => {\n if (!highlighter) {\n return null;\n }\n\n // Check if the language is supported\n if (!languages.includes(lang)) {\n console.warn(\n `[Kumo CodeHighlighted] Language \"${lang}\" is not in the ShikiProvider's languages list. ` +\n `Add it to the languages array: languages={[...existing, '${lang}']}. ` +\n `Rendering as plain text.`,\n );\n return null;\n }\n\n try {\n // Use dual theme for light/dark mode support with hardcoded themes\n const html = highlighter.codeToHtml(code, {\n lang,\n themes: {\n light: \"github-light\",\n dark: \"vesper\",\n },\n });\n\n return html;\n } catch (err) {\n console.warn(\n `[Kumo CodeHighlighted] Failed to highlight code with language \"${lang}\":`,\n err,\n );\n return null;\n }\n },\n [highlighter, languages],\n );\n\n return {\n highlight,\n isLoading,\n isReady: !isLoading && highlighter !== null,\n error,\n labels,\n };\n}\n","\"use client\";\n\nimport { useState, useCallback, useMemo, type ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\nimport { Button } from \"../components/button\";\nimport { useShikiHighlighter } from \"./use-shiki-highlighter\";\nimport type { CodeHighlightedProps } from \"./types\";\n\n/**\n * Syntax-highlighted code block powered by Shiki.\n *\n * Must be used within a ShikiProvider. While Shiki is loading,\n * displays code as plain text (no layout shift, immediately readable).\n *\n * Uses hardcoded themes: `github-light` for light mode, `vesper` for dark mode.\n *\n * @example\n * ```tsx\n * import { ShikiProvider, CodeHighlighted } from \"@cloudflare/kumo/code\";\n *\n * <ShikiProvider\n * engine=\"javascript\"\n * languages={['tsx', 'bash']}\n * >\n * <CodeHighlighted\n * code={`const greeting = \"Hello!\";`}\n * lang=\"tsx\"\n * showLineNumbers\n * showCopyButton\n * />\n * </ShikiProvider>\n * ```\n */\nexport function CodeHighlighted({\n code,\n lang,\n showLineNumbers = false,\n highlightLines,\n showCopyButton = false,\n labels: labelOverrides,\n className,\n}: CodeHighlightedProps): ReactNode {\n const {\n highlight,\n isLoading,\n error,\n labels: providerLabels,\n } = useShikiHighlighter();\n const [copied, setCopied] = useState(false);\n\n // Merge provider labels with component-level overrides\n const labels = useMemo(\n () => ({ ...providerLabels, ...labelOverrides }),\n [providerLabels, labelOverrides],\n );\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch (err) {\n console.error(\"[Kumo CodeHighlighted] Failed to copy to clipboard:\", err);\n }\n }, [code]);\n\n // Get highlighted HTML (or null if not ready/failed)\n const html = highlight(code, lang);\n\n // Count lines for line numbers\n const lineCount = useMemo(() => code.split(\"\\n\").length, [code]);\n\n // Detect single-line code for layout adjustments\n const isSingleLine = lineCount === 1;\n\n // Container styles - use flex layout for single-line with copy button\n // Includes defensive resets (m-0, p-0) to prevent global CSS pollution\n const containerClasses = cn(\n \"group relative m-0 w-full min-w-0 rounded-md border border-kumo-fill bg-kumo-base p-0\",\n showCopyButton && isSingleLine && \"flex items-center\",\n className,\n );\n\n // Copy button - inline for single-line, absolute for multi-line\n // Hidden until hover (or when showing \"Copied!\" feedback)\n const copyButton = showCopyButton ? (\n <div\n className={cn(\n isSingleLine ? \"shrink-0 px-2\" : \"absolute right-2 top-2\",\n !copied && \"opacity-0 transition-opacity group-hover:opacity-100\",\n )}\n >\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={handleCopy}\n aria-label={copied ? labels.copied : labels.copy}\n >\n {copied ? labels.copied : labels.copy}\n </Button>\n </div>\n ) : null;\n\n // Line numbers column\n const lineNumbers =\n showLineNumbers && !isSingleLine ? (\n <div\n className=\"kumo-line-numbers shrink-0 select-none py-4 pr-4 text-right font-mono text-sm opacity-40\"\n aria-hidden=\"true\"\n >\n {Array.from({ length: lineCount }, (_, i) => (\n <div key={i + 1} className=\"leading-relaxed\">\n {i + 1}\n </div>\n ))}\n </div>\n ) : null;\n\n // Error state — still show code, just log the error\n if (error) {\n console.error(\"[Kumo CodeHighlighted] Shiki initialization error:\", error);\n }\n\n // Loading or failed to highlight — show plain text\n if (isLoading || html === null) {\n return (\n <div className={containerClasses}>\n {lineNumbers && (\n <div className=\"flex\">\n {lineNumbers}\n <pre className=\"!m-0 min-w-0 flex-1 overflow-x-auto !p-4 font-mono text-sm leading-relaxed text-kumo-strong\">\n <code className=\"!m-0 !p-0\">{code}</code>\n </pre>\n </div>\n )}\n {!lineNumbers && (\n <pre className=\"!m-0 min-w-0 flex-1 overflow-x-auto !p-4 font-mono text-sm leading-relaxed text-kumo-strong\">\n <code className=\"!m-0 !p-0\">{code}</code>\n </pre>\n )}\n {copyButton}\n </div>\n );\n }\n\n // Highlighted code\n return (\n <div className={containerClasses}>\n {lineNumbers && (\n <div className=\"flex w-full\">\n {lineNumbers}\n <div className=\"min-w-0 flex-1 overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:!m-0 [&>pre]:!border-0 [&>pre]:!rounded-none [&>pre]:!bg-transparent [&>pre]:!p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed [&_code]:!m-0 [&_code]:!p-0 [&_code]:!bg-transparent [&_code]:!border-0\"\n dangerouslySetInnerHTML={{\n __html: processHighlightedHtml(html, highlightLines),\n }}\n />\n </div>\n </div>\n )}\n {!lineNumbers && (\n <div className=\"overflow-x-auto\">\n <div\n className=\"kumo-shiki [&>pre]:!m-0 [&>pre]:!border-0 [&>pre]:!rounded-none [&>pre]:!bg-transparent [&>pre]:!p-4 [&>pre]:font-mono [&>pre]:text-sm [&>pre]:leading-relaxed [&_code]:!m-0 [&_code]:!p-0 [&_code]:!bg-transparent [&_code]:!border-0\"\n dangerouslySetInnerHTML={{\n __html: processHighlightedHtml(html, highlightLines),\n }}\n />\n </div>\n )}\n {copyButton}\n </div>\n );\n}\n\nCodeHighlighted.displayName = \"CodeHighlighted\";\n\n/**\n * Process Shiki's HTML output to add line highlighting classes.\n * Does NOT modify Shiki's token structure - only adds classes to line spans.\n */\nfunction processHighlightedHtml(\n html: string,\n highlightLines?: number[],\n): string {\n // Line numbers are not yet supported - would require more complex approach\n // For now, only handle line highlighting which just adds a class\n\n if (!highlightLines?.length) {\n return html;\n }\n\n const highlightSet = new Set(highlightLines);\n let lineNumber = 0;\n\n // Only add the highlight class to lines, don't restructure the HTML\n return html.replace(/<span class=\"line\">/g, () => {\n lineNumber++;\n const isHighlighted = highlightSet.has(lineNumber);\n return isHighlighted\n ? '<span class=\"line line-highlighted\">'\n : '<span class=\"line\">';\n });\n}\n"],"names":["ShikiContext","createContext","BUNDLED_LANGS","n","DEFAULT_LABELS","ShikiProvider","engine","languages","labels","children","state","setState","useState","useEffect","cancelled","initializeShiki","createHighlighterCore","engineInstance","m","githubLight","vesper","validLanguages","lang","langModules","highlighter","err","mergedLabels","useMemo","contextValue","useShikiHighlighter","context","useContext","isLoading","error","useCallback","code","CodeHighlighted","showLineNumbers","highlightLines","showCopyButton","labelOverrides","className","highlight","providerLabels","copied","setCopied","handleCopy","html","lineCount","isSingleLine","containerClasses","cn","copyButton","jsx","Button","lineNumbers","_","i","jsxs","processHighlightedHtml","highlightSet","lineNumber"],"mappings":"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"}
|
package/dist/components/chart.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { D as ta } from "./chunks/date-range-picker-j318zxjyqz4o3dak.js";
|
|
|
8
8
|
import { C as ia } from "./chunks/checkbox-khvh0efmlzvlo6qi.js";
|
|
9
9
|
import { C as na } from "./chunks/clipboard-text-jvrlvyz5ulm49h5b.js";
|
|
10
10
|
import { C as pa, a as fa } from "./chunks/code-liq1g6f5lhee305d.js";
|
|
11
|
-
import { C as ca } from "./chunks/combobox-
|
|
11
|
+
import { C as ca } from "./chunks/combobox-i3mdp6f01dvpoc5j.js";
|
|
12
12
|
import { a as g, D as N, c as O, e as A } from "./chunks/dialog-emk68n0piw8u7hkb.js";
|
|
13
13
|
import { d as Ta, b as ua } from "./chunks/dialog-emk68n0piw8u7hkb.js";
|
|
14
14
|
import { D as _a } from "./chunks/dropdown-ejgjnn9gq3daua1h.js";
|
|
@@ -44,7 +44,7 @@ import { G as je, a as $e, c as qe, K as We, b as Xe, g as He } from "./chunks/g
|
|
|
44
44
|
import { C as Qe, a as Ye, K as Ze, P as ao, g as eo } from "./chunks/cloudflare-logo-bgts2jgsdh7sslw4.js";
|
|
45
45
|
import { D as ro } from "./chunks/date-picker-mjocqqbggb76n8rt.js";
|
|
46
46
|
import { Flow as so } from "./components/flow.js";
|
|
47
|
-
import { C as lo, a as no, b as mo, T as po } from "./chunks/Legend-
|
|
47
|
+
import { C as lo, a as no, b as mo, T as po } from "./chunks/Legend-fu32ev5ph2ehbfzy.js";
|
|
48
48
|
import { c as D } from "./chunks/cn-ct4n7r74mh8y0f48.js";
|
|
49
49
|
import { s as co } from "./chunks/cn-ct4n7r74mh8y0f48.js";
|
|
50
50
|
import { L as To, u as uo } from "./chunks/link-provider-mn2voeohon7cj9o4.js";
|
|
@@ -24,21 +24,34 @@ export interface TimeseriesChartProps {
|
|
|
24
24
|
xAxisName?: string;
|
|
25
25
|
/** Number of ticks to display on the x-axis */
|
|
26
26
|
xAxisTickCount?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Custom formatter for x-axis tick labels.
|
|
29
|
+
* Receives the raw timestamp in milliseconds and returns a display string,
|
|
30
|
+
* overriding ECharts' built-in time formatting.
|
|
31
|
+
*/
|
|
32
|
+
xAxisTickFormat?: (value: number) => string;
|
|
27
33
|
/**
|
|
28
34
|
* Custom formatter for y-axis tick labels.
|
|
29
35
|
* Receives the raw value and returns a display string.
|
|
30
36
|
* When omitted, ECharts' built-in formatter is used.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*
|
|
35
|
-
*
|
|
37
|
+
*/
|
|
38
|
+
yAxisTickFormat?: (value: number) => string;
|
|
39
|
+
/**
|
|
40
|
+
* @deprecated Use `tooltipValueFormat` instead. This prop formats tooltip
|
|
41
|
+
* values, not y-axis tick labels. It will be removed in a future major version.
|
|
36
42
|
*/
|
|
37
43
|
yAxisTickLabelFormat?: (value: number) => string;
|
|
38
44
|
/** Label for the y-axis (value axis) */
|
|
39
45
|
yAxisName?: string;
|
|
40
46
|
/** Number of ticks to display on the y-axis */
|
|
41
47
|
yAxisTickCount?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Custom formatter for tooltip values.
|
|
50
|
+
* Receives the raw y-value and returns a display string.
|
|
51
|
+
* When omitted, the raw value is shown. Takes precedence over the
|
|
52
|
+
* deprecated `yAxisTickLabelFormat` prop.
|
|
53
|
+
*/
|
|
54
|
+
tooltipValueFormat?: (value: number) => string;
|
|
42
55
|
/** Indicates incomplete data periods with optional before/after timestamps in ms */
|
|
43
56
|
incomplete?: {
|
|
44
57
|
before?: number;
|
|
@@ -84,11 +97,13 @@ export interface TimeseriesChartProps {
|
|
|
84
97
|
* echarts={echarts}
|
|
85
98
|
* data={[{ name: "Requests", data: [[Date.now(), 42]], color: "#086FFF" }]}
|
|
86
99
|
* xAxisName="Time"
|
|
87
|
-
*
|
|
100
|
+
* xAxisTickFormat={(ts) => new Date(ts).toLocaleTimeString()}
|
|
88
101
|
* yAxisName="Count"
|
|
102
|
+
* yAxisTickFormat={(value) => `${value / 1000}k`}
|
|
103
|
+
* tooltipValueFormat={(value) => `${value.toFixed(2)} req/s`}
|
|
89
104
|
* onTimeRangeChange={(from, to) => setRange([from, to])}
|
|
90
105
|
* />
|
|
91
106
|
* ```
|
|
92
107
|
*/
|
|
93
|
-
export declare function TimeseriesChart({ echarts, type, data, xAxisName, xAxisTickCount, yAxisTickLabelFormat, yAxisName, yAxisTickCount, onTimeRangeChange, height, incomplete, isDarkMode, gradient, loading, }: TimeseriesChartProps): import("react/jsx-runtime").JSX.Element;
|
|
108
|
+
export declare function TimeseriesChart({ echarts, type, data, xAxisName, xAxisTickCount, xAxisTickFormat, yAxisTickFormat, yAxisTickLabelFormat, yAxisName, yAxisTickCount, tooltipValueFormat, onTimeRangeChange, height, incomplete, isDarkMode, gradient, loading, }: TimeseriesChartProps): import("react/jsx-runtime").JSX.Element;
|
|
94
109
|
//# sourceMappingURL=TimeseriesChart.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeseriesChart.d.ts","sourceRoot":"","sources":["../../../../src/components/chart/TimeseriesChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,cAAc,CAAC;AAM7C,2DAA2D;AAC3D,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACzB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,kCAAkC;AAClC,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,EAAE,OAAO,OAAO,CAAC;IACxB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACtB,wDAAwD;IACxD,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB
|
|
1
|
+
{"version":3,"file":"TimeseriesChart.d.ts","sourceRoot":"","sources":["../../../../src/components/chart/TimeseriesChart.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,cAAc,CAAC;AAM7C,2DAA2D;AAC3D,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACzB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,kCAAkC;AAClC,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,OAAO,EAAE,OAAO,OAAO,CAAC;IACxB,yDAAyD;IACzD,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACtB,wDAAwD;IACxD,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C;;;OAGG;IACH,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACjD,wCAAwC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/C,oFAAoF;IACpF,UAAU,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,sEAAsE;IACtE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,IAAa,EACb,IAAI,EACJ,SAAS,EACT,cAAc,EACd,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,MAAY,EACZ,UAAU,EACV,UAAU,EACV,QAAQ,EACR,OAAO,GACR,EAAE,oBAAoB,2CAqPtB"}
|