@openpkg-ts/ui 0.1.6 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/docskit/index.d.ts +57 -1
- package/dist/docskit/index.js +201 -50
- package/package.json +5 -7
- package/src/styles/docskit.css +89 -0
- package/src/styles/index.ts +2 -0
- package/src/styles/tokens.css +173 -0
- package/dist/api/index.d.ts +0 -114
- package/dist/api/index.js +0 -435
package/dist/docskit/index.d.ts
CHANGED
|
@@ -408,4 +408,60 @@ declare function TooltipLink(props: {
|
|
|
408
408
|
}): React.JSX.Element;
|
|
409
409
|
import { AnnotationHandler as AnnotationHandler14 } from "codehike/code";
|
|
410
410
|
declare const wordWrap2: AnnotationHandler14;
|
|
411
|
-
|
|
411
|
+
import { ReactNode as ReactNode2 } from "react";
|
|
412
|
+
interface CodeTab {
|
|
413
|
+
/** Tab label */
|
|
414
|
+
label: string;
|
|
415
|
+
/** Tab content (code block) */
|
|
416
|
+
content: ReactNode2;
|
|
417
|
+
/** Raw code for copy button */
|
|
418
|
+
code: string;
|
|
419
|
+
}
|
|
420
|
+
interface CodeTabsProps {
|
|
421
|
+
/** Array of tabs */
|
|
422
|
+
tabs: CodeTab[];
|
|
423
|
+
/** Default selected tab index */
|
|
424
|
+
defaultIndex?: number;
|
|
425
|
+
/** Enable sticky positioning for the header */
|
|
426
|
+
sticky?: boolean;
|
|
427
|
+
/** Custom className */
|
|
428
|
+
className?: string;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Tabbed code block wrapper with copy button per tab.
|
|
432
|
+
* Uses docskit --dk-* CSS variables for consistent theming.
|
|
433
|
+
*/
|
|
434
|
+
declare function CodeTabs({ tabs, defaultIndex, sticky, className }: CodeTabsProps): React.ReactNode2;
|
|
435
|
+
interface ImportSectionProps {
|
|
436
|
+
/** Import statement text */
|
|
437
|
+
importStatement: string;
|
|
438
|
+
/** Custom className */
|
|
439
|
+
className?: string;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Displays a copyable import statement with one-click copy.
|
|
443
|
+
* Monospace styling with copy button.
|
|
444
|
+
*/
|
|
445
|
+
declare function ImportSection({ importStatement, className }: ImportSectionProps): React.ReactNode;
|
|
446
|
+
import * as React14 from "react";
|
|
447
|
+
type TypeColor = "string" | "number" | "boolean" | "null" | "undefined" | "object" | "array" | "function" | "union" | "generic" | "default";
|
|
448
|
+
/**
|
|
449
|
+
* Type coloring for syntax display.
|
|
450
|
+
* Follows Stripe-style: consistent colors for primitives vs complex types.
|
|
451
|
+
*/
|
|
452
|
+
declare const typeBadgeVariants: (props?: {
|
|
453
|
+
typeColor?: TypeColor | null;
|
|
454
|
+
className?: string;
|
|
455
|
+
}) => string;
|
|
456
|
+
interface TypeBadgeProps extends React14.HTMLAttributes<HTMLSpanElement> {
|
|
457
|
+
/** Type string to display */
|
|
458
|
+
type: string;
|
|
459
|
+
/** Override color detection */
|
|
460
|
+
typeColor?: TypeColor | null;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Inline type display with syntax coloring.
|
|
464
|
+
* Automatically detects type category and applies appropriate color.
|
|
465
|
+
*/
|
|
466
|
+
declare const TypeBadge: React14.ForwardRefExoticComponent<TypeBadgeProps & React14.RefAttributes<HTMLSpanElement>>;
|
|
467
|
+
export { wordWrap2 as wordWrap, typeBadgeVariants, tooltip, toCodeGroup, theme, mark, link, lineNumbers2 as lineNumbers, hover, flagsToOptions, expandable, endpointBadgeVariants, diff, collapse, callout, addDocsKit, WithNotes, WithHover, TypeColor, TypeBadgeProps, TypeBadge, TooltipLink, TerminalSkeleton, Terminal, TabsTrigger, TabsList, TabsContent, Tabs, SingleCode, ResponseBlockProps, ResponseBlock, ParameterListProps, ParameterList, PackageInstall, MultiCode, LanguageSelectorProps, LanguageSelector, Language, InlineCodeSkeleton, ImportSectionProps, ImportSection, HttpMethod, HoverLink, EndpointHeaderProps, EndpointHeader, EndpointBadgeProps, EndpointBadge, DocsKitInlineCode, DocsKitCode, DiffStats, CopyButton, CodeTabsSkeleton, CodeTabsProps, CodeTabs, CodeTab, CodeInfo, CodeIcon, CodeGroup, CodeExample, CodeBlockSkeleton, Code, ClientTerminal, ClientInlineCode, ClientDocsKitCode, ClientDiffCodeProps, ClientDiffCode, ClientCode, APISectionProps, APISection, APIReferencePageProps, APIReferencePage, APIParameterSchema, APIParameterItemProps, APIParameterItem, APICodePanelProps, APICodePanel };
|
package/dist/docskit/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// src/docskit/api/api-code-panel.tsx
|
|
3
3
|
import { highlight, Pre } from "codehike/code";
|
|
4
4
|
import { Check, Copy, ExternalLink } from "lucide-react";
|
|
5
|
-
import { useEffect as useEffect2, useState as
|
|
5
|
+
import { useEffect as useEffect2, useState as useState4 } from "react";
|
|
6
6
|
|
|
7
7
|
// src/lib/utils.ts
|
|
8
8
|
import { clsx } from "clsx";
|
|
@@ -11,6 +11,22 @@ function cn(...inputs) {
|
|
|
11
11
|
return twMerge(clsx(inputs));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// src/hooks/use-copy-to-clipboard.ts
|
|
15
|
+
import { useCallback, useRef, useState } from "react";
|
|
16
|
+
var COPY_FEEDBACK_MS = 1200;
|
|
17
|
+
function useCopyToClipboard(timeout = COPY_FEEDBACK_MS) {
|
|
18
|
+
const [copied, setCopied] = useState(false);
|
|
19
|
+
const timerRef = useRef();
|
|
20
|
+
const copy = useCallback((text) => {
|
|
21
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
22
|
+
setCopied(true);
|
|
23
|
+
clearTimeout(timerRef.current);
|
|
24
|
+
timerRef.current = setTimeout(() => setCopied(false), timeout);
|
|
25
|
+
});
|
|
26
|
+
}, [timeout]);
|
|
27
|
+
return [copied, copy];
|
|
28
|
+
}
|
|
29
|
+
|
|
14
30
|
// src/docskit/code.config.ts
|
|
15
31
|
var theme = "github-from-css";
|
|
16
32
|
function flagsToOptions(flags = "") {
|
|
@@ -294,7 +310,7 @@ var expandable = {
|
|
|
294
310
|
import {
|
|
295
311
|
InnerLine as InnerLine5
|
|
296
312
|
} from "codehike/code";
|
|
297
|
-
import { createContext, useContext, useState } from "react";
|
|
313
|
+
import { createContext, useContext, useState as useState2 } from "react";
|
|
298
314
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
299
315
|
|
|
300
316
|
var HoverContext = createContext({
|
|
@@ -303,7 +319,7 @@ var HoverContext = createContext({
|
|
|
303
319
|
removeHoveredName: () => {}
|
|
304
320
|
});
|
|
305
321
|
function HoverProvider({ children }) {
|
|
306
|
-
const [hoveredNames, setHoveredNames] =
|
|
322
|
+
const [hoveredNames, setHoveredNames] = useState2([]);
|
|
307
323
|
const addHoveredName = (name) => {
|
|
308
324
|
setHoveredNames((prev) => [...prev, name]);
|
|
309
325
|
};
|
|
@@ -814,9 +830,9 @@ function APICodePanel({
|
|
|
814
830
|
title,
|
|
815
831
|
className
|
|
816
832
|
}) {
|
|
817
|
-
const [selectedLang, setSelectedLang] =
|
|
818
|
-
const [copied,
|
|
819
|
-
const [highlighted, setHighlighted] =
|
|
833
|
+
const [selectedLang, setSelectedLang] = useState4(examples[0]?.languageId ?? languages[0]?.id);
|
|
834
|
+
const [copied, copy] = useCopyToClipboard();
|
|
835
|
+
const [highlighted, setHighlighted] = useState4(null);
|
|
820
836
|
const currentExample = examples.find((e) => e.languageId === selectedLang);
|
|
821
837
|
const code = currentExample?.code ?? "";
|
|
822
838
|
const lang = currentExample?.highlightLang ?? currentExample?.languageId ?? "txt";
|
|
@@ -836,9 +852,7 @@ function APICodePanel({
|
|
|
836
852
|
};
|
|
837
853
|
}, [code, lang]);
|
|
838
854
|
const handleCopy = () => {
|
|
839
|
-
|
|
840
|
-
setCopied(true);
|
|
841
|
-
setTimeout(() => setCopied(false), 1200);
|
|
855
|
+
copy(code);
|
|
842
856
|
};
|
|
843
857
|
const handlers = getHandlers({ copyButton: false });
|
|
844
858
|
return /* @__PURE__ */ jsxs10("div", {
|
|
@@ -1023,15 +1037,12 @@ EndpointBadge.displayName = "EndpointBadge";
|
|
|
1023
1037
|
// src/docskit/api/endpoint-header.tsx
|
|
1024
1038
|
import { Check as Check2, Copy as Copy2 } from "lucide-react";
|
|
1025
1039
|
import * as React4 from "react";
|
|
1026
|
-
import { useState as useState4 } from "react";
|
|
1027
1040
|
import { jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1028
1041
|
|
|
1029
1042
|
var EndpointHeader = React4.forwardRef(({ className, method, path, copyable = true, ...props }, ref) => {
|
|
1030
|
-
const [copied,
|
|
1043
|
+
const [copied, copy] = useCopyToClipboard();
|
|
1031
1044
|
const handleCopy = () => {
|
|
1032
|
-
|
|
1033
|
-
setCopied(true);
|
|
1034
|
-
setTimeout(() => setCopied(false), 1200);
|
|
1045
|
+
copy(path);
|
|
1035
1046
|
};
|
|
1036
1047
|
return /* @__PURE__ */ jsxs13("div", {
|
|
1037
1048
|
ref,
|
|
@@ -1072,15 +1083,10 @@ function NestedProperty({
|
|
|
1072
1083
|
depth = 0
|
|
1073
1084
|
}) {
|
|
1074
1085
|
const [expanded, setExpanded] = useState5(false);
|
|
1075
|
-
const [copied,
|
|
1086
|
+
const [copied, copy] = useCopyToClipboard();
|
|
1076
1087
|
const type = schema.typeString ?? schema.type ?? "unknown";
|
|
1077
1088
|
const hasNested = schema.properties && Object.keys(schema.properties).length > 0;
|
|
1078
1089
|
const _nestedCount = hasNested && schema.properties ? Object.keys(schema.properties).length : 0;
|
|
1079
|
-
const handleCopy = () => {
|
|
1080
|
-
navigator.clipboard.writeText(name);
|
|
1081
|
-
setCopied(true);
|
|
1082
|
-
setTimeout(() => setCopied(false), 1200);
|
|
1083
|
-
};
|
|
1084
1090
|
return /* @__PURE__ */ jsxs14("div", {
|
|
1085
1091
|
className: cn("border-t border-border first:border-t-0", depth > 0 && "ml-4"),
|
|
1086
1092
|
children: [
|
|
@@ -1129,7 +1135,7 @@ function NestedProperty({
|
|
|
1129
1135
|
}),
|
|
1130
1136
|
/* @__PURE__ */ jsx25("button", {
|
|
1131
1137
|
type: "button",
|
|
1132
|
-
onClick:
|
|
1138
|
+
onClick: () => copy(name),
|
|
1133
1139
|
className: "p-1 rounded text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer",
|
|
1134
1140
|
"aria-label": "Copy name",
|
|
1135
1141
|
children: copied ? /* @__PURE__ */ jsx25(Check3, {
|
|
@@ -1171,14 +1177,9 @@ function APIParameterItem({
|
|
|
1171
1177
|
className
|
|
1172
1178
|
}) {
|
|
1173
1179
|
const [expanded, setExpanded] = useState5(false);
|
|
1174
|
-
const [copied,
|
|
1180
|
+
const [copied, copy] = useCopyToClipboard();
|
|
1175
1181
|
const hasNested = children?.properties && Object.keys(children.properties).length > 0;
|
|
1176
1182
|
const _nestedCount = hasNested && children?.properties ? Object.keys(children.properties).length : 0;
|
|
1177
|
-
const handleCopy = () => {
|
|
1178
|
-
navigator.clipboard.writeText(name);
|
|
1179
|
-
setCopied(true);
|
|
1180
|
-
setTimeout(() => setCopied(false), 1200);
|
|
1181
|
-
};
|
|
1182
1183
|
return /* @__PURE__ */ jsxs14("div", {
|
|
1183
1184
|
className: cn("border-b border-border last:border-b-0", className),
|
|
1184
1185
|
children: [
|
|
@@ -1225,7 +1226,7 @@ function APIParameterItem({
|
|
|
1225
1226
|
}),
|
|
1226
1227
|
/* @__PURE__ */ jsx25("button", {
|
|
1227
1228
|
type: "button",
|
|
1228
|
-
onClick:
|
|
1229
|
+
onClick: () => copy(name),
|
|
1229
1230
|
className: "p-1 rounded text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer",
|
|
1230
1231
|
"aria-label": "Copy name",
|
|
1231
1232
|
children: copied ? /* @__PURE__ */ jsx25(Check3, {
|
|
@@ -1305,16 +1306,13 @@ function ParameterList({
|
|
|
1305
1306
|
// src/docskit/api/response-block.tsx
|
|
1306
1307
|
import { Check as Check4, Copy as Copy4 } from "lucide-react";
|
|
1307
1308
|
import * as React6 from "react";
|
|
1308
|
-
import { useState as useState7 } from "react";
|
|
1309
1309
|
import { jsx as jsx27, jsxs as jsxs16, Fragment as Fragment4 } from "react/jsx-runtime";
|
|
1310
1310
|
|
|
1311
1311
|
function ResponseBlock({ data, title, className }) {
|
|
1312
|
-
const [copied,
|
|
1312
|
+
const [copied, copy] = useCopyToClipboard();
|
|
1313
1313
|
const jsonString = JSON.stringify(data, null, 2);
|
|
1314
1314
|
const handleCopy = () => {
|
|
1315
|
-
|
|
1316
|
-
setCopied(true);
|
|
1317
|
-
setTimeout(() => setCopied(false), 1200);
|
|
1315
|
+
copy(jsonString);
|
|
1318
1316
|
};
|
|
1319
1317
|
return /* @__PURE__ */ jsxs16("div", {
|
|
1320
1318
|
className: cn("group rounded-lg border border-border overflow-hidden bg-muted/30", className),
|
|
@@ -1496,7 +1494,6 @@ import { highlight as highlight2, Pre as Pre2 } from "codehike/code";
|
|
|
1496
1494
|
|
|
1497
1495
|
// src/docskit/code.copy.tsx
|
|
1498
1496
|
import { Check as Check5, Copy as Copy5 } from "lucide-react";
|
|
1499
|
-
import { useState as useState8 } from "react";
|
|
1500
1497
|
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
1501
1498
|
|
|
1502
1499
|
function CopyButton({
|
|
@@ -1504,7 +1501,7 @@ function CopyButton({
|
|
|
1504
1501
|
className,
|
|
1505
1502
|
variant = "floating"
|
|
1506
1503
|
}) {
|
|
1507
|
-
const [copied,
|
|
1504
|
+
const [copied, copy] = useCopyToClipboard();
|
|
1508
1505
|
return /* @__PURE__ */ jsx28("button", {
|
|
1509
1506
|
type: "button",
|
|
1510
1507
|
className: cn("cursor-pointer transition-opacity duration-200", variant === "floating" && [
|
|
@@ -1512,11 +1509,7 @@ function CopyButton({
|
|
|
1512
1509
|
"rounded border border-dk-border bg-dk-background",
|
|
1513
1510
|
"opacity-0 group-hover:opacity-100"
|
|
1514
1511
|
], variant === "inline" && "rounded", className),
|
|
1515
|
-
onClick: () =>
|
|
1516
|
-
navigator.clipboard.writeText(text);
|
|
1517
|
-
setCopied(true);
|
|
1518
|
-
setTimeout(() => setCopied(false), 1200);
|
|
1519
|
-
},
|
|
1512
|
+
onClick: () => copy(text),
|
|
1520
1513
|
"aria-label": "Copy to clipboard",
|
|
1521
1514
|
children: copied ? /* @__PURE__ */ jsx28(Check5, {
|
|
1522
1515
|
size: 16,
|
|
@@ -1786,12 +1779,12 @@ import {
|
|
|
1786
1779
|
Inline,
|
|
1787
1780
|
Pre as Pre3
|
|
1788
1781
|
} from "codehike/code";
|
|
1789
|
-
import { useEffect as useEffect3, useState as
|
|
1782
|
+
import { useEffect as useEffect3, useState as useState7 } from "react";
|
|
1790
1783
|
import { jsx as jsx33, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1791
1784
|
|
|
1792
1785
|
function ClientDocsKitCode(props) {
|
|
1793
1786
|
const { codeblock, handlers: extraHandlers, className: wrapperClassName } = props;
|
|
1794
|
-
const [highlighted, setHighlighted] =
|
|
1787
|
+
const [highlighted, setHighlighted] = useState7(null);
|
|
1795
1788
|
const { title, flags } = extractFlags2(codeblock);
|
|
1796
1789
|
const options = flagsToOptions(flags);
|
|
1797
1790
|
useEffect3(() => {
|
|
@@ -1860,7 +1853,7 @@ function ClientDocsKitCode(props) {
|
|
|
1860
1853
|
}
|
|
1861
1854
|
function ClientTerminal(props) {
|
|
1862
1855
|
const { codeblock, handlers: extraHandlers } = props;
|
|
1863
|
-
const [highlighted, setHighlighted] =
|
|
1856
|
+
const [highlighted, setHighlighted] = useState7(null);
|
|
1864
1857
|
const { flags } = extractFlagsSimple(codeblock);
|
|
1865
1858
|
const options = flagsToOptions(flags);
|
|
1866
1859
|
useEffect3(() => {
|
|
@@ -1930,7 +1923,7 @@ function ClientTerminal(props) {
|
|
|
1930
1923
|
});
|
|
1931
1924
|
}
|
|
1932
1925
|
function ClientInlineCode({ codeblock }) {
|
|
1933
|
-
const [highlighted, setHighlighted] =
|
|
1926
|
+
const [highlighted, setHighlighted] = useState7(null);
|
|
1934
1927
|
useEffect3(() => {
|
|
1935
1928
|
let cancelled = false;
|
|
1936
1929
|
highlight3(codeblock, theme).then((result) => {
|
|
@@ -1965,7 +1958,7 @@ function extractFlagsSimple(codeblock) {
|
|
|
1965
1958
|
}
|
|
1966
1959
|
function ClientCode(props) {
|
|
1967
1960
|
const { codeblocks, flags: groupFlags, storage } = props;
|
|
1968
|
-
const [highlighted, setHighlighted] =
|
|
1961
|
+
const [highlighted, setHighlighted] = useState7(null);
|
|
1969
1962
|
const groupOptions = flagsToOptions(groupFlags?.startsWith("-") ? groupFlags.slice(1) : groupFlags);
|
|
1970
1963
|
const _codeBlocksKey = codeblocks.map((b) => `${b.value}|${b.lang}|${b.meta}`).join("::");
|
|
1971
1964
|
useEffect3(() => {
|
|
@@ -2109,7 +2102,7 @@ import {
|
|
|
2109
2102
|
Pre as Pre4
|
|
2110
2103
|
} from "codehike/code";
|
|
2111
2104
|
import { ChevronDown as ChevronDown3, ChevronUp } from "lucide-react";
|
|
2112
|
-
import { useEffect as useEffect4, useState as
|
|
2105
|
+
import { useEffect as useEffect4, useState as useState8 } from "react";
|
|
2113
2106
|
import { jsx as jsx34, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2114
2107
|
|
|
2115
2108
|
function StackedChevrons({ isOpen, className }) {
|
|
@@ -2135,8 +2128,8 @@ function ClientDiffCode(props) {
|
|
|
2135
2128
|
className: wrapperClassName,
|
|
2136
2129
|
defaultOpen = true
|
|
2137
2130
|
} = props;
|
|
2138
|
-
const [highlighted, setHighlighted] =
|
|
2139
|
-
const [isOpen, setIsOpen] =
|
|
2131
|
+
const [highlighted, setHighlighted] = useState8(null);
|
|
2132
|
+
const [isOpen, setIsOpen] = useState8(defaultOpen);
|
|
2140
2133
|
const { title, flags } = extractFlags3(codeblock);
|
|
2141
2134
|
const options = flagsToOptions(flags);
|
|
2142
2135
|
const filename = filenameProp || title || "file";
|
|
@@ -2266,7 +2259,7 @@ async function DocsKitInlineCode({
|
|
|
2266
2259
|
});
|
|
2267
2260
|
}
|
|
2268
2261
|
// src/docskit/code.package-install.tsx
|
|
2269
|
-
import { useState as
|
|
2262
|
+
import { useState as useState9 } from "react";
|
|
2270
2263
|
import { jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2271
2264
|
|
|
2272
2265
|
var managerLabels = {
|
|
@@ -2319,7 +2312,7 @@ function PackageInstall({
|
|
|
2319
2312
|
managers = ["npm", "bun", "pnpm", "yarn"],
|
|
2320
2313
|
copyButton = true
|
|
2321
2314
|
}) {
|
|
2322
|
-
const [activeManager, setActiveManager] =
|
|
2315
|
+
const [activeManager, setActiveManager] = useState9(managers[0]);
|
|
2323
2316
|
const command = getInstallCommand(activeManager, pkg, { dev, global: isGlobal });
|
|
2324
2317
|
return /* @__PURE__ */ jsxs21("div", {
|
|
2325
2318
|
className: "group rounded overflow-hidden border border-dk-border flex flex-col my-4 not-prose",
|
|
@@ -2539,8 +2532,163 @@ function WithNotes({ children, ...rest }) {
|
|
|
2539
2532
|
children
|
|
2540
2533
|
});
|
|
2541
2534
|
}
|
|
2535
|
+
// src/docskit/code.tabs-legacy.tsx
|
|
2536
|
+
import { Check as Check6, Copy as Copy6 } from "lucide-react";
|
|
2537
|
+
import { useState as useState10 } from "react";
|
|
2538
|
+
import { jsx as jsx40, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
2539
|
+
|
|
2540
|
+
function CodeTabs({
|
|
2541
|
+
tabs,
|
|
2542
|
+
defaultIndex = 0,
|
|
2543
|
+
sticky = false,
|
|
2544
|
+
className
|
|
2545
|
+
}) {
|
|
2546
|
+
const [activeIndex, setActiveIndex] = useState10(defaultIndex);
|
|
2547
|
+
const [copied, copy] = useCopyToClipboard();
|
|
2548
|
+
const activeTab = tabs[activeIndex];
|
|
2549
|
+
const handleCopy = () => {
|
|
2550
|
+
if (!activeTab)
|
|
2551
|
+
return;
|
|
2552
|
+
copy(activeTab.code);
|
|
2553
|
+
};
|
|
2554
|
+
if (!tabs.length)
|
|
2555
|
+
return null;
|
|
2556
|
+
return /* @__PURE__ */ jsxs23("div", {
|
|
2557
|
+
className: cn("group rounded-lg border border-dk-border bg-dk-background overflow-hidden", "selection:bg-dk-selection selection:text-current", className),
|
|
2558
|
+
children: [
|
|
2559
|
+
/* @__PURE__ */ jsxs23("div", {
|
|
2560
|
+
className: cn("flex items-center border-b border-dk-border bg-dk-tabs-background", sticky && "sticky top-0 z-10"),
|
|
2561
|
+
children: [
|
|
2562
|
+
/* @__PURE__ */ jsx40("div", {
|
|
2563
|
+
className: "flex-1 flex items-stretch",
|
|
2564
|
+
children: tabs.map((tab, index) => /* @__PURE__ */ jsx40("button", {
|
|
2565
|
+
type: "button",
|
|
2566
|
+
onClick: () => setActiveIndex(index),
|
|
2567
|
+
className: cn("px-4 py-2 text-sm font-mono transition-colors duration-200", "border-r border-dk-border last:border-r-0", index === activeIndex ? "text-dk-tab-active-foreground bg-dk-background/50" : "text-dk-tab-inactive-foreground hover:text-dk-tab-active-foreground"),
|
|
2568
|
+
children: tab.label
|
|
2569
|
+
}, tab.label))
|
|
2570
|
+
}),
|
|
2571
|
+
/* @__PURE__ */ jsx40("button", {
|
|
2572
|
+
type: "button",
|
|
2573
|
+
onClick: handleCopy,
|
|
2574
|
+
className: cn("p-2 mx-2", "text-dk-tab-inactive-foreground hover:text-dk-tab-active-foreground", "opacity-0 group-hover:opacity-100 transition-opacity", "cursor-pointer"),
|
|
2575
|
+
"aria-label": "Copy code",
|
|
2576
|
+
children: copied ? /* @__PURE__ */ jsx40(Check6, {
|
|
2577
|
+
size: 16
|
|
2578
|
+
}) : /* @__PURE__ */ jsx40(Copy6, {
|
|
2579
|
+
size: 16
|
|
2580
|
+
})
|
|
2581
|
+
})
|
|
2582
|
+
]
|
|
2583
|
+
}),
|
|
2584
|
+
/* @__PURE__ */ jsx40("div", {
|
|
2585
|
+
className: "bg-dk-background",
|
|
2586
|
+
children: activeTab?.content
|
|
2587
|
+
})
|
|
2588
|
+
]
|
|
2589
|
+
});
|
|
2590
|
+
}
|
|
2591
|
+
// src/docskit/import-section.tsx
|
|
2592
|
+
import { Check as Check7, Copy as Copy7 } from "lucide-react";
|
|
2593
|
+
import { jsx as jsx41, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2594
|
+
|
|
2595
|
+
function ImportSection({ importStatement, className }) {
|
|
2596
|
+
const [copied, copy] = useCopyToClipboard();
|
|
2597
|
+
const handleCopy = () => {
|
|
2598
|
+
copy(importStatement);
|
|
2599
|
+
};
|
|
2600
|
+
return /* @__PURE__ */ jsxs24("div", {
|
|
2601
|
+
className: cn("group flex items-center justify-between gap-3", "rounded-lg border border-border bg-muted/30 px-4 py-3", className),
|
|
2602
|
+
children: [
|
|
2603
|
+
/* @__PURE__ */ jsx41("code", {
|
|
2604
|
+
className: "font-mono text-sm text-foreground overflow-x-auto",
|
|
2605
|
+
children: importStatement
|
|
2606
|
+
}),
|
|
2607
|
+
/* @__PURE__ */ jsx41("button", {
|
|
2608
|
+
type: "button",
|
|
2609
|
+
onClick: handleCopy,
|
|
2610
|
+
className: cn("shrink-0 p-1.5 rounded", "text-muted-foreground hover:text-foreground", "opacity-0 group-hover:opacity-100 transition-opacity duration-200", "cursor-pointer"),
|
|
2611
|
+
"aria-label": "Copy import statement",
|
|
2612
|
+
children: copied ? /* @__PURE__ */ jsx41(Check7, {
|
|
2613
|
+
size: 16
|
|
2614
|
+
}) : /* @__PURE__ */ jsx41(Copy7, {
|
|
2615
|
+
size: 16
|
|
2616
|
+
})
|
|
2617
|
+
})
|
|
2618
|
+
]
|
|
2619
|
+
});
|
|
2620
|
+
}
|
|
2621
|
+
// src/docskit/type-badge.tsx
|
|
2622
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
2623
|
+
import * as React9 from "react";
|
|
2624
|
+
import { jsx as jsx42 } from "react/jsx-runtime";
|
|
2625
|
+
var typeBadgeVariants = cva2("font-mono text-sm", {
|
|
2626
|
+
variants: {
|
|
2627
|
+
typeColor: {
|
|
2628
|
+
string: "text-emerald-600 dark:text-emerald-400",
|
|
2629
|
+
number: "text-blue-600 dark:text-blue-400",
|
|
2630
|
+
boolean: "text-amber-600 dark:text-amber-400",
|
|
2631
|
+
null: "text-gray-500 dark:text-gray-400",
|
|
2632
|
+
undefined: "text-gray-500 dark:text-gray-400",
|
|
2633
|
+
object: "text-purple-600 dark:text-purple-400",
|
|
2634
|
+
array: "text-cyan-600 dark:text-cyan-400",
|
|
2635
|
+
function: "text-fuchsia-600 dark:text-fuchsia-400",
|
|
2636
|
+
union: "text-orange-600 dark:text-orange-400",
|
|
2637
|
+
generic: "text-rose-600 dark:text-rose-400",
|
|
2638
|
+
default: "text-muted-foreground"
|
|
2639
|
+
}
|
|
2640
|
+
},
|
|
2641
|
+
defaultVariants: {
|
|
2642
|
+
typeColor: "default"
|
|
2643
|
+
}
|
|
2644
|
+
});
|
|
2645
|
+
function detectTypeColor(type) {
|
|
2646
|
+
const normalized = type.toLowerCase().trim();
|
|
2647
|
+
if (normalized === "string" || normalized.startsWith('"') || normalized.startsWith("'")) {
|
|
2648
|
+
return "string";
|
|
2649
|
+
}
|
|
2650
|
+
if (normalized === "number" || /^\d+$/.test(normalized)) {
|
|
2651
|
+
return "number";
|
|
2652
|
+
}
|
|
2653
|
+
if (normalized === "boolean" || normalized === "true" || normalized === "false") {
|
|
2654
|
+
return "boolean";
|
|
2655
|
+
}
|
|
2656
|
+
if (normalized === "null") {
|
|
2657
|
+
return "null";
|
|
2658
|
+
}
|
|
2659
|
+
if (normalized === "undefined" || normalized === "void") {
|
|
2660
|
+
return "undefined";
|
|
2661
|
+
}
|
|
2662
|
+
if (normalized === "object" || normalized.startsWith("{")) {
|
|
2663
|
+
return "object";
|
|
2664
|
+
}
|
|
2665
|
+
if (normalized.endsWith("[]") || normalized.startsWith("array")) {
|
|
2666
|
+
return "array";
|
|
2667
|
+
}
|
|
2668
|
+
if (normalized.startsWith("(") || normalized.includes("=>") || normalized.startsWith("function")) {
|
|
2669
|
+
return "function";
|
|
2670
|
+
}
|
|
2671
|
+
if (normalized.includes("|")) {
|
|
2672
|
+
return "union";
|
|
2673
|
+
}
|
|
2674
|
+
if (normalized.includes("<") && normalized.includes(">")) {
|
|
2675
|
+
return "generic";
|
|
2676
|
+
}
|
|
2677
|
+
return "default";
|
|
2678
|
+
}
|
|
2679
|
+
var TypeBadge = React9.forwardRef(({ className, type, typeColor, ...props }, ref) => {
|
|
2680
|
+
const color2 = typeColor ?? detectTypeColor(type);
|
|
2681
|
+
return /* @__PURE__ */ jsx42("span", {
|
|
2682
|
+
ref,
|
|
2683
|
+
className: cn(typeBadgeVariants({ typeColor: color2 }), className),
|
|
2684
|
+
...props,
|
|
2685
|
+
children: type
|
|
2686
|
+
});
|
|
2687
|
+
});
|
|
2688
|
+
TypeBadge.displayName = "TypeBadge";
|
|
2542
2689
|
export {
|
|
2543
2690
|
wordWrap,
|
|
2691
|
+
typeBadgeVariants,
|
|
2544
2692
|
tooltip,
|
|
2545
2693
|
toCodeGroup,
|
|
2546
2694
|
theme,
|
|
@@ -2557,6 +2705,7 @@ export {
|
|
|
2557
2705
|
addDocsKit,
|
|
2558
2706
|
WithNotes,
|
|
2559
2707
|
WithHover,
|
|
2708
|
+
TypeBadge,
|
|
2560
2709
|
TooltipLink,
|
|
2561
2710
|
TerminalSkeleton,
|
|
2562
2711
|
Terminal,
|
|
@@ -2571,6 +2720,7 @@ export {
|
|
|
2571
2720
|
MultiCode,
|
|
2572
2721
|
LanguageSelector,
|
|
2573
2722
|
InlineCodeSkeleton,
|
|
2723
|
+
ImportSection,
|
|
2574
2724
|
HoverLink,
|
|
2575
2725
|
EndpointHeader,
|
|
2576
2726
|
EndpointBadge,
|
|
@@ -2578,6 +2728,7 @@ export {
|
|
|
2578
2728
|
DocsKitCode,
|
|
2579
2729
|
CopyButton,
|
|
2580
2730
|
CodeTabsSkeleton,
|
|
2731
|
+
CodeTabs,
|
|
2581
2732
|
CodeIcon,
|
|
2582
2733
|
CodeGroup,
|
|
2583
2734
|
CodeBlockSkeleton,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openpkg-ts/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "UI primitives and components for OpenPkg documentation",
|
|
5
5
|
"homepage": "https://github.com/ryanwaits/openpkg-ts#readme",
|
|
6
6
|
"repository": {
|
|
@@ -11,13 +11,10 @@
|
|
|
11
11
|
"type": "module",
|
|
12
12
|
"sideEffects": false,
|
|
13
13
|
"files": [
|
|
14
|
-
"dist"
|
|
14
|
+
"dist",
|
|
15
|
+
"src/styles"
|
|
15
16
|
],
|
|
16
17
|
"exports": {
|
|
17
|
-
"./api": {
|
|
18
|
-
"types": "./dist/api/index.d.ts",
|
|
19
|
-
"import": "./dist/api/index.js"
|
|
20
|
-
},
|
|
21
18
|
"./badge": {
|
|
22
19
|
"types": "./dist/badge/index.d.ts",
|
|
23
20
|
"import": "./dist/badge/index.js"
|
|
@@ -30,7 +27,8 @@
|
|
|
30
27
|
"types": "./dist/lib/utils.d.ts",
|
|
31
28
|
"import": "./dist/lib/utils.js"
|
|
32
29
|
},
|
|
33
|
-
"./styles/tokens.css": "./src/styles/tokens.css"
|
|
30
|
+
"./styles/tokens.css": "./src/styles/tokens.css",
|
|
31
|
+
"./styles/docskit.css": "./src/styles/docskit.css"
|
|
34
32
|
},
|
|
35
33
|
"scripts": {
|
|
36
34
|
"build": "bunup",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docskit code block styling for Tailwind v4 consumers.
|
|
3
|
+
* Includes CodeHike theme variables, dk-* Tailwind color mappings,
|
|
4
|
+
* and selection utility.
|
|
5
|
+
*
|
|
6
|
+
* Usage: @import '@openpkg-ts/ui/styles/docskit.css';
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/* CodeHike github-from-css theme (dark) */
|
|
10
|
+
:root {
|
|
11
|
+
--ch-0: dark;
|
|
12
|
+
--ch-1: #8b949e;
|
|
13
|
+
--ch-2: #79c0ff;
|
|
14
|
+
--ch-3: #ffa657;
|
|
15
|
+
--ch-4: #c9d1d9;
|
|
16
|
+
--ch-5: #d2a8ff;
|
|
17
|
+
--ch-6: #7ee787;
|
|
18
|
+
--ch-7: #ff7b72;
|
|
19
|
+
--ch-8: #a5d6ff;
|
|
20
|
+
--ch-9: #ffa198;
|
|
21
|
+
--ch-10: #f0f6fc;
|
|
22
|
+
--ch-11: #490202;
|
|
23
|
+
--ch-12: #04260f;
|
|
24
|
+
--ch-13: #5a1e02;
|
|
25
|
+
--ch-14: #161b22;
|
|
26
|
+
--ch-15: #8b949e;
|
|
27
|
+
--ch-16: #0d1117;
|
|
28
|
+
--ch-17: #6e76811a;
|
|
29
|
+
--ch-18: #ffffff0b;
|
|
30
|
+
--ch-19: #3794ff;
|
|
31
|
+
--ch-20: #264f78;
|
|
32
|
+
--ch-21: #1f6feb;
|
|
33
|
+
--ch-22: #010409;
|
|
34
|
+
--ch-23: #30363d;
|
|
35
|
+
--ch-24: #6e7681;
|
|
36
|
+
--ch-25: #6e768166;
|
|
37
|
+
--ch-26: #0d1117e6;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* CodeHike github-from-css theme (light) */
|
|
41
|
+
[data-theme="light"] {
|
|
42
|
+
--ch-0: light;
|
|
43
|
+
--ch-1: #6e7781;
|
|
44
|
+
--ch-2: #0550ae;
|
|
45
|
+
--ch-3: #953800;
|
|
46
|
+
--ch-4: #24292f;
|
|
47
|
+
--ch-5: #8250df;
|
|
48
|
+
--ch-6: #116329;
|
|
49
|
+
--ch-7: #cf222e;
|
|
50
|
+
--ch-8: #0a3069;
|
|
51
|
+
--ch-9: #82071e;
|
|
52
|
+
--ch-10: #f6f8fa;
|
|
53
|
+
--ch-11: #ffebe9;
|
|
54
|
+
--ch-12: #dafbe1;
|
|
55
|
+
--ch-13: #ffd8b5;
|
|
56
|
+
--ch-14: #eaeef2;
|
|
57
|
+
--ch-15: #57606a;
|
|
58
|
+
--ch-16: #ffffff;
|
|
59
|
+
--ch-17: #eaeef280;
|
|
60
|
+
--ch-18: #fdff0033;
|
|
61
|
+
--ch-19: #1a85ff;
|
|
62
|
+
--ch-20: #add6ff;
|
|
63
|
+
--ch-21: #0969da;
|
|
64
|
+
--ch-22: #f6f8fa;
|
|
65
|
+
--ch-23: #d0d7de;
|
|
66
|
+
--ch-24: #8c959f;
|
|
67
|
+
--ch-25: #afb8c133;
|
|
68
|
+
--ch-26: #ffffffe6;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* dk-* Tailwind v4 color theme (maps to --ch-* vars) */
|
|
72
|
+
@theme {
|
|
73
|
+
--color-dk-background: var(--ch-16);
|
|
74
|
+
--color-dk-border: var(--ch-23);
|
|
75
|
+
--color-dk-tabs-background: var(--ch-22);
|
|
76
|
+
--color-dk-tab-inactive-foreground: var(--ch-15);
|
|
77
|
+
--color-dk-tab-active-foreground: var(--ch-4);
|
|
78
|
+
--color-dk-selection: var(--ch-20);
|
|
79
|
+
--color-dk-line-number: var(--ch-24);
|
|
80
|
+
--color-dk-active-border: var(--ch-3);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Selection utility — Tailwind can't auto-generate this */
|
|
84
|
+
@layer utilities {
|
|
85
|
+
.selection\:bg-dk-selection::selection,
|
|
86
|
+
.selection\:bg-dk-selection *::selection {
|
|
87
|
+
background-color: var(--ch-20);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenPKG design tokens.
|
|
3
|
+
* Light by default, dark via .dark class, [data-theme="dark"], or prefers-color-scheme.
|
|
4
|
+
* Override any --openpkg-* variable to match your theme.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* Background colors — light default */
|
|
9
|
+
--openpkg-bg-root: #ffffff;
|
|
10
|
+
--openpkg-bg-primary: #fafafa;
|
|
11
|
+
--openpkg-bg-secondary: #f5f5f5;
|
|
12
|
+
--openpkg-bg-tertiary: #eeeeee;
|
|
13
|
+
--openpkg-bg-code: #f8f8fc;
|
|
14
|
+
--openpkg-bg-code-header: #f0f0f8;
|
|
15
|
+
--openpkg-bg-badge: #e5e5e5;
|
|
16
|
+
--openpkg-bg-chip: transparent;
|
|
17
|
+
--openpkg-bg-chip-active: transparent;
|
|
18
|
+
--openpkg-bg-collapsible: #f8f8f8;
|
|
19
|
+
--openpkg-bg-details: #fafafa;
|
|
20
|
+
|
|
21
|
+
/* Text colors */
|
|
22
|
+
--openpkg-text-primary: #1a1a1a;
|
|
23
|
+
--openpkg-text-secondary: #525252;
|
|
24
|
+
--openpkg-text-muted: #737373;
|
|
25
|
+
--openpkg-text-code: #1a1a1a;
|
|
26
|
+
|
|
27
|
+
/* Syntax highlighting — light */
|
|
28
|
+
--openpkg-syn-keyword: #8b5cf6;
|
|
29
|
+
--openpkg-syn-string: #059669;
|
|
30
|
+
--openpkg-syn-function: #dc2626;
|
|
31
|
+
--openpkg-syn-property: #7c3aed;
|
|
32
|
+
--openpkg-syn-variable: #1a1a1a;
|
|
33
|
+
--openpkg-syn-punctuation: #6b7280;
|
|
34
|
+
--openpkg-syn-number: #d97706;
|
|
35
|
+
--openpkg-syn-boolean: #be185d;
|
|
36
|
+
--openpkg-syn-comment: #9ca3af;
|
|
37
|
+
|
|
38
|
+
/* Accent colors */
|
|
39
|
+
--openpkg-accent-green: #16a34a;
|
|
40
|
+
--openpkg-accent-blue: #2563eb;
|
|
41
|
+
--openpkg-accent-purple: #7c3aed;
|
|
42
|
+
--openpkg-accent-link: #2563eb;
|
|
43
|
+
|
|
44
|
+
/* Border colors */
|
|
45
|
+
--openpkg-border-subtle: #e5e5e5;
|
|
46
|
+
--openpkg-border-medium: #d4d4d4;
|
|
47
|
+
--openpkg-border-chip: #d4d4d4;
|
|
48
|
+
--openpkg-border-chip-active: #a3a3a3;
|
|
49
|
+
|
|
50
|
+
/* Typography */
|
|
51
|
+
--openpkg-font-mono: "JetBrains Mono", "SF Mono", Consolas, monospace;
|
|
52
|
+
--openpkg-font-sans: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
|
|
53
|
+
|
|
54
|
+
/* Border radius */
|
|
55
|
+
--openpkg-radius-sm: 4px;
|
|
56
|
+
--openpkg-radius-md: 6px;
|
|
57
|
+
--openpkg-radius-lg: 8px;
|
|
58
|
+
--openpkg-radius-full: 9999px;
|
|
59
|
+
|
|
60
|
+
/* Animations */
|
|
61
|
+
--openpkg-transition-fast: 150ms ease;
|
|
62
|
+
--openpkg-transition-normal: 200ms ease;
|
|
63
|
+
--openpkg-transition-slow: 300ms ease;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Dark mode — explicit class or data attribute */
|
|
67
|
+
.dark,
|
|
68
|
+
[data-theme="dark"] {
|
|
69
|
+
--openpkg-bg-root: #0c0c0c;
|
|
70
|
+
--openpkg-bg-primary: #0f0f0f;
|
|
71
|
+
--openpkg-bg-secondary: #171717;
|
|
72
|
+
--openpkg-bg-tertiary: #1c1c1c;
|
|
73
|
+
--openpkg-bg-code: #0f0f18;
|
|
74
|
+
--openpkg-bg-code-header: #141420;
|
|
75
|
+
--openpkg-bg-badge: #262626;
|
|
76
|
+
--openpkg-bg-collapsible: #161616;
|
|
77
|
+
--openpkg-bg-details: #141414;
|
|
78
|
+
--openpkg-text-primary: #ededed;
|
|
79
|
+
--openpkg-text-secondary: #a0a0a0;
|
|
80
|
+
--openpkg-text-muted: #666666;
|
|
81
|
+
--openpkg-text-code: #e4e4e7;
|
|
82
|
+
--openpkg-accent-green: #3ecf8e;
|
|
83
|
+
--openpkg-accent-blue: #6cb6ff;
|
|
84
|
+
--openpkg-accent-purple: #c4a7e7;
|
|
85
|
+
--openpkg-accent-link: #6cb6ff;
|
|
86
|
+
--openpkg-border-subtle: #262626;
|
|
87
|
+
--openpkg-border-medium: #333333;
|
|
88
|
+
--openpkg-border-chip: #333333;
|
|
89
|
+
--openpkg-border-chip-active: #666666;
|
|
90
|
+
--openpkg-syn-keyword: #c4a7e7;
|
|
91
|
+
--openpkg-syn-string: #9ccfd8;
|
|
92
|
+
--openpkg-syn-function: #ebbcba;
|
|
93
|
+
--openpkg-syn-property: #c4a7e7;
|
|
94
|
+
--openpkg-syn-variable: #e4e4e7;
|
|
95
|
+
--openpkg-syn-punctuation: #6e6a86;
|
|
96
|
+
--openpkg-syn-number: #f6c177;
|
|
97
|
+
--openpkg-syn-boolean: #eb6f92;
|
|
98
|
+
--openpkg-syn-comment: #6e6a86;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Dark mode — system preference */
|
|
102
|
+
@media (prefers-color-scheme: dark) {
|
|
103
|
+
:root:not(.light):not([data-theme="light"]) {
|
|
104
|
+
--openpkg-bg-root: #0c0c0c;
|
|
105
|
+
--openpkg-bg-primary: #0f0f0f;
|
|
106
|
+
--openpkg-bg-secondary: #171717;
|
|
107
|
+
--openpkg-bg-tertiary: #1c1c1c;
|
|
108
|
+
--openpkg-bg-code: #0f0f18;
|
|
109
|
+
--openpkg-bg-code-header: #141420;
|
|
110
|
+
--openpkg-bg-badge: #262626;
|
|
111
|
+
--openpkg-bg-collapsible: #161616;
|
|
112
|
+
--openpkg-bg-details: #141414;
|
|
113
|
+
--openpkg-text-primary: #ededed;
|
|
114
|
+
--openpkg-text-secondary: #a0a0a0;
|
|
115
|
+
--openpkg-text-muted: #666666;
|
|
116
|
+
--openpkg-text-code: #e4e4e7;
|
|
117
|
+
--openpkg-accent-green: #3ecf8e;
|
|
118
|
+
--openpkg-accent-blue: #6cb6ff;
|
|
119
|
+
--openpkg-accent-purple: #c4a7e7;
|
|
120
|
+
--openpkg-accent-link: #6cb6ff;
|
|
121
|
+
--openpkg-border-subtle: #262626;
|
|
122
|
+
--openpkg-border-medium: #333333;
|
|
123
|
+
--openpkg-border-chip: #333333;
|
|
124
|
+
--openpkg-border-chip-active: #666666;
|
|
125
|
+
--openpkg-syn-keyword: #c4a7e7;
|
|
126
|
+
--openpkg-syn-string: #9ccfd8;
|
|
127
|
+
--openpkg-syn-function: #ebbcba;
|
|
128
|
+
--openpkg-syn-property: #c4a7e7;
|
|
129
|
+
--openpkg-syn-variable: #e4e4e7;
|
|
130
|
+
--openpkg-syn-punctuation: #6e6a86;
|
|
131
|
+
--openpkg-syn-number: #f6c177;
|
|
132
|
+
--openpkg-syn-boolean: #eb6f92;
|
|
133
|
+
--openpkg-syn-comment: #6e6a86;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Animation keyframes */
|
|
138
|
+
@keyframes openpkg-fade-in {
|
|
139
|
+
from { opacity: 0; }
|
|
140
|
+
to { opacity: 1; }
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@keyframes openpkg-slide-down {
|
|
144
|
+
from { opacity: 0; transform: translateY(-4px); }
|
|
145
|
+
to { opacity: 1; transform: translateY(0); }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@keyframes openpkg-slide-up {
|
|
149
|
+
from { opacity: 0; transform: translateY(4px); }
|
|
150
|
+
to { opacity: 1; transform: translateY(0); }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@keyframes openpkg-expand {
|
|
154
|
+
from { opacity: 0; height: 0; }
|
|
155
|
+
to { opacity: 1; height: var(--radix-collapsible-content-height); }
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@keyframes openpkg-collapse {
|
|
159
|
+
from { opacity: 1; height: var(--radix-collapsible-content-height); }
|
|
160
|
+
to { opacity: 0; height: 0; }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.openpkg-animate-fade-in {
|
|
164
|
+
animation: openpkg-fade-in var(--openpkg-transition-normal) ease-out;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.openpkg-animate-slide-down {
|
|
168
|
+
animation: openpkg-slide-down var(--openpkg-transition-normal) ease-out;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.openpkg-animate-slide-up {
|
|
172
|
+
animation: openpkg-slide-up var(--openpkg-transition-normal) ease-out;
|
|
173
|
+
}
|
package/dist/api/index.d.ts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { ReactNode as ReactNode2 } from "react";
|
|
2
|
-
interface CodeTab {
|
|
3
|
-
/** Tab label */
|
|
4
|
-
label: string;
|
|
5
|
-
/** Tab content (code block) */
|
|
6
|
-
content: ReactNode2;
|
|
7
|
-
/** Raw code for copy button */
|
|
8
|
-
code: string;
|
|
9
|
-
}
|
|
10
|
-
interface CodeTabsProps {
|
|
11
|
-
/** Array of tabs */
|
|
12
|
-
tabs: CodeTab[];
|
|
13
|
-
/** Default selected tab index */
|
|
14
|
-
defaultIndex?: number;
|
|
15
|
-
/** Enable sticky positioning for the header */
|
|
16
|
-
sticky?: boolean;
|
|
17
|
-
/** Custom className */
|
|
18
|
-
className?: string;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Tabbed code block wrapper with copy button per tab.
|
|
22
|
-
* Uses docskit --dk-* CSS variables for consistent theming.
|
|
23
|
-
*/
|
|
24
|
-
declare function CodeTabs({ tabs, defaultIndex, sticky, className }: CodeTabsProps): React.ReactNode2;
|
|
25
|
-
import * as React2 from "react";
|
|
26
|
-
type ExportKind = "function" | "type" | "variable" | "class" | "interface" | "enum";
|
|
27
|
-
/**
|
|
28
|
-
* Kind badge variants for export cards.
|
|
29
|
-
*/
|
|
30
|
-
declare const kindBadgeVariants: (props?: {
|
|
31
|
-
kind?: ExportKind | null;
|
|
32
|
-
className?: string;
|
|
33
|
-
}) => string;
|
|
34
|
-
interface ExportCardProps extends React2.AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
35
|
-
/** Export name */
|
|
36
|
-
name: string;
|
|
37
|
-
/** Description snippet */
|
|
38
|
-
description?: string;
|
|
39
|
-
/** Link to detail page */
|
|
40
|
-
href: string;
|
|
41
|
-
/** Export kind */
|
|
42
|
-
kind?: ExportKind | null;
|
|
43
|
-
/** Custom link component (for Next.js Link) */
|
|
44
|
-
as?: React2.ElementType;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Card component for displaying exports in an index grid.
|
|
48
|
-
* Features function name styling, description, kind badge, and hover effects.
|
|
49
|
-
*/
|
|
50
|
-
declare const ExportCard: React2.ForwardRefExoticComponent<ExportCardProps & React2.RefAttributes<HTMLAnchorElement>>;
|
|
51
|
-
interface ImportSectionProps {
|
|
52
|
-
/** Import statement text */
|
|
53
|
-
importStatement: string;
|
|
54
|
-
/** Custom className */
|
|
55
|
-
className?: string;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Displays a copyable import statement with one-click copy.
|
|
59
|
-
* Monospace styling with copy button.
|
|
60
|
-
*/
|
|
61
|
-
declare function ImportSection({ importStatement, className }: ImportSectionProps): React.ReactNode;
|
|
62
|
-
interface ParameterSchema {
|
|
63
|
-
/** Type name (e.g., "string", "number", "object") */
|
|
64
|
-
type?: string;
|
|
65
|
-
/** Formatted type string for display */
|
|
66
|
-
typeString?: string;
|
|
67
|
-
/** Description of the parameter/property */
|
|
68
|
-
description?: string;
|
|
69
|
-
/** Nested properties for object types */
|
|
70
|
-
properties?: Record<string, ParameterSchema>;
|
|
71
|
-
/** Required property names */
|
|
72
|
-
required?: string[];
|
|
73
|
-
}
|
|
74
|
-
interface ParameterItemProps {
|
|
75
|
-
/** Parameter name */
|
|
76
|
-
name: string;
|
|
77
|
-
/** Parameter schema */
|
|
78
|
-
schema: ParameterSchema;
|
|
79
|
-
/** Whether this parameter is required */
|
|
80
|
-
required?: boolean;
|
|
81
|
-
/** Description (overrides schema.description) */
|
|
82
|
-
description?: string;
|
|
83
|
-
/** Nesting depth for indentation */
|
|
84
|
-
depth?: number;
|
|
85
|
-
/** Custom className */
|
|
86
|
-
className?: string;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Single parameter with expand capability for nested objects.
|
|
90
|
-
* Features expandable nested params, type annotations, and required/optional badges.
|
|
91
|
-
*/
|
|
92
|
-
declare function ParameterItem({ name, schema, required: isRequired, description, depth, className }: ParameterItemProps): React.ReactNode;
|
|
93
|
-
import * as React3 from "react";
|
|
94
|
-
type TypeColor = "string" | "number" | "boolean" | "null" | "undefined" | "object" | "array" | "function" | "union" | "generic" | "default";
|
|
95
|
-
/**
|
|
96
|
-
* Type coloring for syntax display.
|
|
97
|
-
* Follows Stripe-style: consistent colors for primitives vs complex types.
|
|
98
|
-
*/
|
|
99
|
-
declare const typeBadgeVariants: (props?: {
|
|
100
|
-
typeColor?: TypeColor | null;
|
|
101
|
-
className?: string;
|
|
102
|
-
}) => string;
|
|
103
|
-
interface TypeBadgeProps extends React3.HTMLAttributes<HTMLSpanElement> {
|
|
104
|
-
/** Type string to display */
|
|
105
|
-
type: string;
|
|
106
|
-
/** Override color detection */
|
|
107
|
-
typeColor?: TypeColor | null;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Inline type display with syntax coloring.
|
|
111
|
-
* Automatically detects type category and applies appropriate color.
|
|
112
|
-
*/
|
|
113
|
-
declare const TypeBadge: React3.ForwardRefExoticComponent<TypeBadgeProps & React3.RefAttributes<HTMLSpanElement>>;
|
|
114
|
-
export { typeBadgeVariants, kindBadgeVariants, TypeBadgeProps, TypeBadge, ParameterSchema, ParameterItemProps, ParameterItem, ImportSectionProps, ImportSection, ExportKind, ExportCardProps, ExportCard, CodeTabsProps, CodeTabs, CodeTab };
|
package/dist/api/index.js
DELETED
|
@@ -1,435 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
// src/api/CodeTabs.tsx
|
|
3
|
-
import { Check, Copy } from "lucide-react";
|
|
4
|
-
import { useState } from "react";
|
|
5
|
-
|
|
6
|
-
// src/lib/utils.ts
|
|
7
|
-
import { clsx } from "clsx";
|
|
8
|
-
import { twMerge } from "tailwind-merge";
|
|
9
|
-
function cn(...inputs) {
|
|
10
|
-
return twMerge(clsx(inputs));
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// src/api/CodeTabs.tsx
|
|
14
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
-
|
|
16
|
-
function CodeTabs({
|
|
17
|
-
tabs,
|
|
18
|
-
defaultIndex = 0,
|
|
19
|
-
sticky = false,
|
|
20
|
-
className
|
|
21
|
-
}) {
|
|
22
|
-
const [activeIndex, setActiveIndex] = useState(defaultIndex);
|
|
23
|
-
const [copied, setCopied] = useState(false);
|
|
24
|
-
const activeTab = tabs[activeIndex];
|
|
25
|
-
const handleCopy = () => {
|
|
26
|
-
if (!activeTab)
|
|
27
|
-
return;
|
|
28
|
-
navigator.clipboard.writeText(activeTab.code);
|
|
29
|
-
setCopied(true);
|
|
30
|
-
setTimeout(() => setCopied(false), 1200);
|
|
31
|
-
};
|
|
32
|
-
if (!tabs.length)
|
|
33
|
-
return null;
|
|
34
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
35
|
-
className: cn("group rounded-lg border border-dk-border bg-dk-background overflow-hidden", "selection:bg-dk-selection selection:text-current", className),
|
|
36
|
-
children: [
|
|
37
|
-
/* @__PURE__ */ jsxs("div", {
|
|
38
|
-
className: cn("flex items-center border-b border-dk-border bg-dk-tabs-background", sticky && "sticky top-0 z-10"),
|
|
39
|
-
children: [
|
|
40
|
-
/* @__PURE__ */ jsx("div", {
|
|
41
|
-
className: "flex-1 flex items-stretch",
|
|
42
|
-
children: tabs.map((tab, index) => /* @__PURE__ */ jsx("button", {
|
|
43
|
-
type: "button",
|
|
44
|
-
onClick: () => setActiveIndex(index),
|
|
45
|
-
className: cn("px-4 py-2 text-sm font-mono transition-colors duration-200", "border-r border-dk-border last:border-r-0", index === activeIndex ? "text-dk-tab-active-foreground bg-dk-background/50" : "text-dk-tab-inactive-foreground hover:text-dk-tab-active-foreground"),
|
|
46
|
-
children: tab.label
|
|
47
|
-
}, tab.label))
|
|
48
|
-
}),
|
|
49
|
-
/* @__PURE__ */ jsx("button", {
|
|
50
|
-
type: "button",
|
|
51
|
-
onClick: handleCopy,
|
|
52
|
-
className: cn("p-2 mx-2", "text-dk-tab-inactive-foreground hover:text-dk-tab-active-foreground", "opacity-0 group-hover:opacity-100 transition-opacity", "cursor-pointer"),
|
|
53
|
-
"aria-label": "Copy code",
|
|
54
|
-
children: copied ? /* @__PURE__ */ jsx(Check, {
|
|
55
|
-
size: 16
|
|
56
|
-
}) : /* @__PURE__ */ jsx(Copy, {
|
|
57
|
-
size: 16
|
|
58
|
-
})
|
|
59
|
-
})
|
|
60
|
-
]
|
|
61
|
-
}),
|
|
62
|
-
/* @__PURE__ */ jsx("div", {
|
|
63
|
-
className: "bg-dk-background",
|
|
64
|
-
children: activeTab?.content
|
|
65
|
-
})
|
|
66
|
-
]
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
// src/api/ExportCard.tsx
|
|
70
|
-
import { cva } from "class-variance-authority";
|
|
71
|
-
import * as React from "react";
|
|
72
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
73
|
-
|
|
74
|
-
var kindBadgeVariants = cva("inline-flex items-center justify-center font-mono font-medium rounded shrink-0 h-5 px-1.5 text-xs", {
|
|
75
|
-
variants: {
|
|
76
|
-
kind: {
|
|
77
|
-
function: "bg-fuchsia-500/15 text-fuchsia-600 dark:text-fuchsia-400",
|
|
78
|
-
class: "bg-amber-500/15 text-amber-600 dark:text-amber-400",
|
|
79
|
-
interface: "bg-cyan-500/15 text-cyan-600 dark:text-cyan-400",
|
|
80
|
-
type: "bg-purple-500/15 text-purple-600 dark:text-purple-400",
|
|
81
|
-
enum: "bg-emerald-500/15 text-emerald-600 dark:text-emerald-400",
|
|
82
|
-
variable: "bg-blue-500/15 text-blue-600 dark:text-blue-400"
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
defaultVariants: {
|
|
86
|
-
kind: "function"
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
var kindLabels = {
|
|
90
|
-
function: "fn",
|
|
91
|
-
class: "cls",
|
|
92
|
-
interface: "int",
|
|
93
|
-
type: "type",
|
|
94
|
-
enum: "enum",
|
|
95
|
-
variable: "var"
|
|
96
|
-
};
|
|
97
|
-
var ExportCard = React.forwardRef(({ name, description, href, kind = "function", as: Component = "a", className, ...props }, ref) => {
|
|
98
|
-
const isFunction = kind === "function";
|
|
99
|
-
return /* @__PURE__ */ jsxs2(Component, {
|
|
100
|
-
ref,
|
|
101
|
-
href,
|
|
102
|
-
className: cn("group block rounded-lg border border-border bg-card/50 p-4", "transition-all duration-200", "hover:border-border/80 hover:bg-card hover:shadow-md", "hover:-translate-y-0.5", className),
|
|
103
|
-
...props,
|
|
104
|
-
children: [
|
|
105
|
-
/* @__PURE__ */ jsxs2("div", {
|
|
106
|
-
className: "flex items-center gap-2 mb-2",
|
|
107
|
-
children: [
|
|
108
|
-
/* @__PURE__ */ jsx2("span", {
|
|
109
|
-
className: kindBadgeVariants({ kind }),
|
|
110
|
-
children: kindLabels[kind]
|
|
111
|
-
}),
|
|
112
|
-
/* @__PURE__ */ jsx2("span", {
|
|
113
|
-
className: "font-mono text-base font-medium text-foreground group-hover:text-primary transition-colors",
|
|
114
|
-
children: name
|
|
115
|
-
}),
|
|
116
|
-
isFunction && /* @__PURE__ */ jsx2("span", {
|
|
117
|
-
className: "font-mono text-base text-muted-foreground",
|
|
118
|
-
children: "()"
|
|
119
|
-
})
|
|
120
|
-
]
|
|
121
|
-
}),
|
|
122
|
-
description && /* @__PURE__ */ jsx2("p", {
|
|
123
|
-
className: "text-sm text-muted-foreground line-clamp-2 leading-relaxed",
|
|
124
|
-
children: description
|
|
125
|
-
})
|
|
126
|
-
]
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
ExportCard.displayName = "ExportCard";
|
|
130
|
-
// src/api/ImportSection.tsx
|
|
131
|
-
import { Check as Check2, Copy as Copy2 } from "lucide-react";
|
|
132
|
-
import { useState as useState2 } from "react";
|
|
133
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
134
|
-
|
|
135
|
-
function ImportSection({ importStatement, className }) {
|
|
136
|
-
const [copied, setCopied] = useState2(false);
|
|
137
|
-
const handleCopy = () => {
|
|
138
|
-
navigator.clipboard.writeText(importStatement);
|
|
139
|
-
setCopied(true);
|
|
140
|
-
setTimeout(() => setCopied(false), 1200);
|
|
141
|
-
};
|
|
142
|
-
return /* @__PURE__ */ jsxs3("div", {
|
|
143
|
-
className: cn("group flex items-center justify-between gap-3", "rounded-lg border border-border bg-muted/30 px-4 py-3", className),
|
|
144
|
-
children: [
|
|
145
|
-
/* @__PURE__ */ jsx3("code", {
|
|
146
|
-
className: "font-mono text-sm text-foreground overflow-x-auto",
|
|
147
|
-
children: importStatement
|
|
148
|
-
}),
|
|
149
|
-
/* @__PURE__ */ jsx3("button", {
|
|
150
|
-
type: "button",
|
|
151
|
-
onClick: handleCopy,
|
|
152
|
-
className: cn("shrink-0 p-1.5 rounded", "text-muted-foreground hover:text-foreground", "opacity-0 group-hover:opacity-100 transition-opacity duration-200", "cursor-pointer"),
|
|
153
|
-
"aria-label": "Copy import statement",
|
|
154
|
-
children: copied ? /* @__PURE__ */ jsx3(Check2, {
|
|
155
|
-
size: 16
|
|
156
|
-
}) : /* @__PURE__ */ jsx3(Copy2, {
|
|
157
|
-
size: 16
|
|
158
|
-
})
|
|
159
|
-
})
|
|
160
|
-
]
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
// src/api/ParameterItem.tsx
|
|
164
|
-
import { ChevronRight } from "lucide-react";
|
|
165
|
-
import { useState as useState3 } from "react";
|
|
166
|
-
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
167
|
-
|
|
168
|
-
function getNestedProperties(schema) {
|
|
169
|
-
if (!schema || typeof schema !== "object")
|
|
170
|
-
return null;
|
|
171
|
-
if (schema.type === "object" && schema.properties) {
|
|
172
|
-
return schema.properties;
|
|
173
|
-
}
|
|
174
|
-
return null;
|
|
175
|
-
}
|
|
176
|
-
function getRequiredFields(schema) {
|
|
177
|
-
return schema.required ?? [];
|
|
178
|
-
}
|
|
179
|
-
function countProperties(schema) {
|
|
180
|
-
const props = getNestedProperties(schema);
|
|
181
|
-
return props ? Object.keys(props).length : 0;
|
|
182
|
-
}
|
|
183
|
-
function getTypeDisplay(schema) {
|
|
184
|
-
if (schema.typeString)
|
|
185
|
-
return schema.typeString;
|
|
186
|
-
return schema.type ?? "unknown";
|
|
187
|
-
}
|
|
188
|
-
function NestedPropertyItem({
|
|
189
|
-
name,
|
|
190
|
-
schema,
|
|
191
|
-
required = false,
|
|
192
|
-
depth = 0
|
|
193
|
-
}) {
|
|
194
|
-
const [expanded, setExpanded] = useState3(false);
|
|
195
|
-
const type = getTypeDisplay(schema);
|
|
196
|
-
const nestedProps = getNestedProperties(schema);
|
|
197
|
-
const nestedCount = countProperties(schema);
|
|
198
|
-
const hasNested = nestedCount > 0;
|
|
199
|
-
return /* @__PURE__ */ jsxs4("div", {
|
|
200
|
-
className: cn("border-t border-border first:border-t-0", depth > 0 && "ml-4"),
|
|
201
|
-
children: [
|
|
202
|
-
/* @__PURE__ */ jsx4("div", {
|
|
203
|
-
className: "py-3",
|
|
204
|
-
children: /* @__PURE__ */ jsxs4("div", {
|
|
205
|
-
className: "flex items-start gap-2",
|
|
206
|
-
children: [
|
|
207
|
-
hasNested && /* @__PURE__ */ jsx4("button", {
|
|
208
|
-
type: "button",
|
|
209
|
-
onClick: () => setExpanded(!expanded),
|
|
210
|
-
className: "mt-0.5 p-0.5 text-muted-foreground hover:text-foreground transition-colors cursor-pointer",
|
|
211
|
-
"aria-label": expanded ? "Collapse" : "Expand",
|
|
212
|
-
children: /* @__PURE__ */ jsx4(ChevronRight, {
|
|
213
|
-
size: 14,
|
|
214
|
-
className: cn("transition-transform duration-200", expanded && "rotate-90")
|
|
215
|
-
})
|
|
216
|
-
}),
|
|
217
|
-
!hasNested && /* @__PURE__ */ jsx4("div", {
|
|
218
|
-
className: "w-5"
|
|
219
|
-
}),
|
|
220
|
-
/* @__PURE__ */ jsxs4("div", {
|
|
221
|
-
className: "flex-1 min-w-0",
|
|
222
|
-
children: [
|
|
223
|
-
/* @__PURE__ */ jsxs4("div", {
|
|
224
|
-
className: "flex items-baseline gap-2 flex-wrap",
|
|
225
|
-
children: [
|
|
226
|
-
/* @__PURE__ */ jsxs4("span", {
|
|
227
|
-
className: "font-mono text-sm text-foreground",
|
|
228
|
-
children: [
|
|
229
|
-
name,
|
|
230
|
-
!required && /* @__PURE__ */ jsx4("span", {
|
|
231
|
-
className: "text-muted-foreground",
|
|
232
|
-
children: "?"
|
|
233
|
-
})
|
|
234
|
-
]
|
|
235
|
-
}),
|
|
236
|
-
/* @__PURE__ */ jsx4("span", {
|
|
237
|
-
className: "font-mono text-sm text-muted-foreground",
|
|
238
|
-
children: hasNested ? "object" : type
|
|
239
|
-
}),
|
|
240
|
-
hasNested && /* @__PURE__ */ jsxs4("button", {
|
|
241
|
-
type: "button",
|
|
242
|
-
onClick: () => setExpanded(!expanded),
|
|
243
|
-
className: "text-xs text-primary hover:underline cursor-pointer",
|
|
244
|
-
children: [
|
|
245
|
-
nestedCount,
|
|
246
|
-
" ",
|
|
247
|
-
nestedCount === 1 ? "property" : "properties"
|
|
248
|
-
]
|
|
249
|
-
})
|
|
250
|
-
]
|
|
251
|
-
}),
|
|
252
|
-
schema.description && /* @__PURE__ */ jsx4("p", {
|
|
253
|
-
className: "text-sm text-muted-foreground mt-1",
|
|
254
|
-
children: schema.description
|
|
255
|
-
})
|
|
256
|
-
]
|
|
257
|
-
})
|
|
258
|
-
]
|
|
259
|
-
})
|
|
260
|
-
}),
|
|
261
|
-
hasNested && expanded && nestedProps && /* @__PURE__ */ jsx4("div", {
|
|
262
|
-
className: "border-l border-border ml-2",
|
|
263
|
-
children: Object.entries(nestedProps).map(([propName, propSchema]) => /* @__PURE__ */ jsx4(NestedPropertyItem, {
|
|
264
|
-
name: propName,
|
|
265
|
-
schema: propSchema,
|
|
266
|
-
required: getRequiredFields(schema).includes(propName),
|
|
267
|
-
depth: depth + 1
|
|
268
|
-
}, propName))
|
|
269
|
-
})
|
|
270
|
-
]
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
function ParameterItem({
|
|
274
|
-
name,
|
|
275
|
-
schema,
|
|
276
|
-
required: isRequired = true,
|
|
277
|
-
description,
|
|
278
|
-
depth = 0,
|
|
279
|
-
className
|
|
280
|
-
}) {
|
|
281
|
-
const [expanded, setExpanded] = useState3(false);
|
|
282
|
-
const type = getTypeDisplay(schema);
|
|
283
|
-
const nestedProps = getNestedProperties(schema);
|
|
284
|
-
const nestedCount = countProperties(schema);
|
|
285
|
-
const hasNested = nestedCount > 0;
|
|
286
|
-
const displayDescription = description ?? schema.description;
|
|
287
|
-
return /* @__PURE__ */ jsxs4("div", {
|
|
288
|
-
className: cn("border-b border-border last:border-b-0", className),
|
|
289
|
-
children: [
|
|
290
|
-
/* @__PURE__ */ jsx4("div", {
|
|
291
|
-
className: "py-3",
|
|
292
|
-
children: /* @__PURE__ */ jsxs4("div", {
|
|
293
|
-
className: "flex items-start gap-2",
|
|
294
|
-
children: [
|
|
295
|
-
hasNested && /* @__PURE__ */ jsx4("button", {
|
|
296
|
-
type: "button",
|
|
297
|
-
onClick: () => setExpanded(!expanded),
|
|
298
|
-
className: "mt-0.5 p-0.5 text-muted-foreground hover:text-foreground transition-colors cursor-pointer",
|
|
299
|
-
"aria-label": expanded ? "Collapse" : "Expand",
|
|
300
|
-
children: /* @__PURE__ */ jsx4(ChevronRight, {
|
|
301
|
-
size: 14,
|
|
302
|
-
className: cn("transition-transform duration-200", expanded && "rotate-90")
|
|
303
|
-
})
|
|
304
|
-
}),
|
|
305
|
-
!hasNested && /* @__PURE__ */ jsx4("div", {
|
|
306
|
-
className: "w-5"
|
|
307
|
-
}),
|
|
308
|
-
/* @__PURE__ */ jsxs4("div", {
|
|
309
|
-
className: "flex-1 min-w-0",
|
|
310
|
-
children: [
|
|
311
|
-
/* @__PURE__ */ jsxs4("div", {
|
|
312
|
-
className: "flex items-baseline gap-2 flex-wrap",
|
|
313
|
-
children: [
|
|
314
|
-
/* @__PURE__ */ jsx4("span", {
|
|
315
|
-
className: "font-mono text-sm font-medium text-foreground",
|
|
316
|
-
children: name
|
|
317
|
-
}),
|
|
318
|
-
isRequired && /* @__PURE__ */ jsx4("span", {
|
|
319
|
-
className: "text-[10px] font-semibold px-1.5 py-0.5 rounded border border-border bg-muted text-muted-foreground uppercase tracking-wide",
|
|
320
|
-
children: "Required"
|
|
321
|
-
}),
|
|
322
|
-
/* @__PURE__ */ jsx4("span", {
|
|
323
|
-
className: "font-mono text-sm text-muted-foreground",
|
|
324
|
-
children: hasNested ? "object" : type
|
|
325
|
-
}),
|
|
326
|
-
hasNested && /* @__PURE__ */ jsxs4("button", {
|
|
327
|
-
type: "button",
|
|
328
|
-
onClick: () => setExpanded(!expanded),
|
|
329
|
-
className: "text-xs text-primary hover:underline cursor-pointer",
|
|
330
|
-
children: [
|
|
331
|
-
nestedCount,
|
|
332
|
-
" ",
|
|
333
|
-
nestedCount === 1 ? "property" : "properties"
|
|
334
|
-
]
|
|
335
|
-
})
|
|
336
|
-
]
|
|
337
|
-
}),
|
|
338
|
-
displayDescription && /* @__PURE__ */ jsx4("p", {
|
|
339
|
-
className: "text-sm text-muted-foreground mt-1",
|
|
340
|
-
children: displayDescription
|
|
341
|
-
})
|
|
342
|
-
]
|
|
343
|
-
})
|
|
344
|
-
]
|
|
345
|
-
})
|
|
346
|
-
}),
|
|
347
|
-
hasNested && expanded && nestedProps && /* @__PURE__ */ jsx4("div", {
|
|
348
|
-
className: "border-l border-border ml-2 mb-3",
|
|
349
|
-
children: Object.entries(nestedProps).map(([propName, propSchema]) => /* @__PURE__ */ jsx4(NestedPropertyItem, {
|
|
350
|
-
name: propName,
|
|
351
|
-
schema: propSchema,
|
|
352
|
-
required: getRequiredFields(schema).includes(propName),
|
|
353
|
-
depth: depth + 1
|
|
354
|
-
}, propName))
|
|
355
|
-
})
|
|
356
|
-
]
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
// src/api/TypeBadge.tsx
|
|
360
|
-
import { cva as cva2 } from "class-variance-authority";
|
|
361
|
-
import * as React2 from "react";
|
|
362
|
-
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
363
|
-
var typeBadgeVariants = cva2("font-mono text-sm", {
|
|
364
|
-
variants: {
|
|
365
|
-
typeColor: {
|
|
366
|
-
string: "text-emerald-600 dark:text-emerald-400",
|
|
367
|
-
number: "text-blue-600 dark:text-blue-400",
|
|
368
|
-
boolean: "text-amber-600 dark:text-amber-400",
|
|
369
|
-
null: "text-gray-500 dark:text-gray-400",
|
|
370
|
-
undefined: "text-gray-500 dark:text-gray-400",
|
|
371
|
-
object: "text-purple-600 dark:text-purple-400",
|
|
372
|
-
array: "text-cyan-600 dark:text-cyan-400",
|
|
373
|
-
function: "text-fuchsia-600 dark:text-fuchsia-400",
|
|
374
|
-
union: "text-orange-600 dark:text-orange-400",
|
|
375
|
-
generic: "text-rose-600 dark:text-rose-400",
|
|
376
|
-
default: "text-muted-foreground"
|
|
377
|
-
}
|
|
378
|
-
},
|
|
379
|
-
defaultVariants: {
|
|
380
|
-
typeColor: "default"
|
|
381
|
-
}
|
|
382
|
-
});
|
|
383
|
-
function detectTypeColor(type) {
|
|
384
|
-
const normalized = type.toLowerCase().trim();
|
|
385
|
-
if (normalized === "string" || normalized.startsWith('"') || normalized.startsWith("'")) {
|
|
386
|
-
return "string";
|
|
387
|
-
}
|
|
388
|
-
if (normalized === "number" || /^\d+$/.test(normalized)) {
|
|
389
|
-
return "number";
|
|
390
|
-
}
|
|
391
|
-
if (normalized === "boolean" || normalized === "true" || normalized === "false") {
|
|
392
|
-
return "boolean";
|
|
393
|
-
}
|
|
394
|
-
if (normalized === "null") {
|
|
395
|
-
return "null";
|
|
396
|
-
}
|
|
397
|
-
if (normalized === "undefined" || normalized === "void") {
|
|
398
|
-
return "undefined";
|
|
399
|
-
}
|
|
400
|
-
if (normalized === "object" || normalized.startsWith("{")) {
|
|
401
|
-
return "object";
|
|
402
|
-
}
|
|
403
|
-
if (normalized.endsWith("[]") || normalized.startsWith("array")) {
|
|
404
|
-
return "array";
|
|
405
|
-
}
|
|
406
|
-
if (normalized.startsWith("(") || normalized.includes("=>") || normalized.startsWith("function")) {
|
|
407
|
-
return "function";
|
|
408
|
-
}
|
|
409
|
-
if (normalized.includes("|")) {
|
|
410
|
-
return "union";
|
|
411
|
-
}
|
|
412
|
-
if (normalized.includes("<") && normalized.includes(">")) {
|
|
413
|
-
return "generic";
|
|
414
|
-
}
|
|
415
|
-
return "default";
|
|
416
|
-
}
|
|
417
|
-
var TypeBadge = React2.forwardRef(({ className, type, typeColor, ...props }, ref) => {
|
|
418
|
-
const color = typeColor ?? detectTypeColor(type);
|
|
419
|
-
return /* @__PURE__ */ jsx5("span", {
|
|
420
|
-
ref,
|
|
421
|
-
className: cn(typeBadgeVariants({ typeColor: color }), className),
|
|
422
|
-
...props,
|
|
423
|
-
children: type
|
|
424
|
-
});
|
|
425
|
-
});
|
|
426
|
-
TypeBadge.displayName = "TypeBadge";
|
|
427
|
-
export {
|
|
428
|
-
typeBadgeVariants,
|
|
429
|
-
kindBadgeVariants,
|
|
430
|
-
TypeBadge,
|
|
431
|
-
ParameterItem,
|
|
432
|
-
ImportSection,
|
|
433
|
-
ExportCard,
|
|
434
|
-
CodeTabs
|
|
435
|
-
};
|