@doccov/ui 0.2.3 → 0.3.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.
@@ -231,4 +231,175 @@ declare function TooltipLink(props: {
231
231
  });
232
232
  import { AnnotationHandler as AnnotationHandler13 } from "codehike/code";
233
233
  declare const wordWrap2: AnnotationHandler13;
234
- export { wordWrap2 as wordWrap, tooltip, toCodeGroup, theme, mark, link, lineNumbers2 as lineNumbers, hover, flagsToOptions, expandable, diff, collapse, callout, addDocsKit, WithNotes, WithHover, TooltipLink, TerminalSkeleton, Terminal, TabsTrigger, TabsList, TabsContent, Tabs, SingleCode, PackageInstall, MultiCode, InlineCodeSkeleton, HoverLink, DocsKitInlineCode, DocsKitCode, DiffStats, CopyButton, CodeTabsSkeleton, CodeInfo, CodeIcon, CodeGroup, CodeBlockSkeleton, Code, ClientTerminal, ClientInlineCode, ClientDocsKitCode, ClientDiffCodeProps, ClientDiffCode, ClientCode };
234
+ import { VariantProps } from "class-variance-authority";
235
+ import * as React5 from "react";
236
+ type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
237
+ declare const endpointBadgeVariants: unknown;
238
+ interface EndpointBadgeProps extends React5.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof endpointBadgeVariants> {
239
+ method: HttpMethod;
240
+ }
241
+ declare const EndpointBadge: unknown;
242
+ import * as React6 from "react";
243
+ interface EndpointHeaderProps extends React6.HTMLAttributes<HTMLDivElement> {
244
+ /** HTTP method */
245
+ method: HttpMethod;
246
+ /** API path (e.g., "/v1/customers") */
247
+ path: string;
248
+ /** Show copy button on hover */
249
+ copyable?: boolean;
250
+ }
251
+ declare const EndpointHeader: unknown;
252
+ import * as React7 from "react";
253
+ interface APIParameterSchema {
254
+ /** Type name */
255
+ type?: string;
256
+ /** Formatted type string */
257
+ typeString?: string;
258
+ /** Description */
259
+ description?: string;
260
+ /** Nested properties for object types */
261
+ properties?: Record<string, APIParameterSchema>;
262
+ /** Required property names */
263
+ required?: string[];
264
+ }
265
+ interface APIParameterItemProps {
266
+ /** Parameter name */
267
+ name: string;
268
+ /** Type string (e.g., "string", "object") */
269
+ type: string;
270
+ /** Is required */
271
+ required?: boolean;
272
+ /** Description */
273
+ description?: string;
274
+ /** Nested children (for expandable objects) */
275
+ children?: APIParameterSchema;
276
+ /** Nesting depth */
277
+ depth?: number;
278
+ /** Custom className */
279
+ className?: string;
280
+ }
281
+ /**
282
+ * Single parameter row with name, type, required badge, description, and expandable children.
283
+ * Stripe-style API reference parameter display.
284
+ */
285
+ declare function APIParameterItem({ name, type, required, description, children, depth, className }: APIParameterItemProps): React7.ReactNode;
286
+ import * as React8 from "react";
287
+ interface ParameterListProps {
288
+ /** Title above the list (e.g., "Body parameters") */
289
+ title?: string;
290
+ /** Number of items to show before collapsing */
291
+ collapseAfter?: number;
292
+ /** Child parameter items */
293
+ children: React8.ReactNode;
294
+ /** Custom className */
295
+ className?: string;
296
+ }
297
+ /**
298
+ * Container for parameter items with optional "More parameters" collapse.
299
+ */
300
+ declare function ParameterList({ title, collapseAfter, children, className }: ParameterListProps): React8.ReactNode;
301
+ import * as React9 from "react";
302
+ interface ResponseBlockProps {
303
+ /** Response JSON data */
304
+ data: object;
305
+ /** Optional title (e.g., "Response", "200 OK") */
306
+ title?: string;
307
+ /** Custom className */
308
+ className?: string;
309
+ }
310
+ /**
311
+ * JSON response preview with syntax highlighting.
312
+ * Displays formatted JSON with copy functionality.
313
+ */
314
+ declare function ResponseBlock({ data, title, className }: ResponseBlockProps): React9.ReactNode;
315
+ import * as React10 from "react";
316
+ interface Language {
317
+ /** Language identifier (e.g., "curl", "node", "python") */
318
+ id: string;
319
+ /** Display label (e.g., "cURL", "Node.js", "Python") */
320
+ label: string;
321
+ }
322
+ interface LanguageSelectorProps {
323
+ /** Available languages */
324
+ languages: Language[];
325
+ /** Currently selected language id */
326
+ value: string;
327
+ /** Callback when language changes */
328
+ onChange: (languageId: string) => void;
329
+ /** Custom className */
330
+ className?: string;
331
+ }
332
+ /**
333
+ * Dropdown selector for choosing code example language.
334
+ * Used in APICodePanel to switch between language examples.
335
+ */
336
+ declare function LanguageSelector({ languages, value, onChange, className }: LanguageSelectorProps): React10.ReactNode;
337
+ import * as React11 from "react";
338
+ interface CodeExample {
339
+ /** Language identifier */
340
+ languageId: string;
341
+ /** Code content */
342
+ code: string;
343
+ /** Optional syntax highlighting language (defaults to languageId) */
344
+ highlightLang?: string;
345
+ }
346
+ interface APICodePanelProps {
347
+ /** Available languages for the selector */
348
+ languages: Language[];
349
+ /** Code examples keyed by language id */
350
+ examples: CodeExample[];
351
+ /** Optional external link (e.g., to API playground) */
352
+ externalLink?: string;
353
+ /** Optional title shown in header */
354
+ title?: string;
355
+ /** Custom className */
356
+ className?: string;
357
+ }
358
+ /**
359
+ * Right-side sticky code panel for API documentation.
360
+ * Features language dropdown, copy button, and dark bg with syntax highlighting.
361
+ */
362
+ declare function APICodePanel({ languages, examples, externalLink, title, className }: APICodePanelProps): React11.ReactNode;
363
+ import * as React12 from "react";
364
+ interface APISectionProps {
365
+ /** Section title (e.g., "Create a customer", "The Customer object") */
366
+ title: string;
367
+ /** Optional anchor id for deep linking */
368
+ id?: string;
369
+ /** Optional description */
370
+ description?: React12.ReactNode;
371
+ /** Left column content (parameters, returns, etc.) */
372
+ children: React12.ReactNode;
373
+ /** Languages for code panel */
374
+ languages: Language[];
375
+ /** Code examples for the right panel */
376
+ examples: CodeExample[];
377
+ /** Optional external link for code panel */
378
+ externalLink?: string;
379
+ /** Optional code panel title */
380
+ codePanelTitle?: string;
381
+ /** Custom className */
382
+ className?: string;
383
+ }
384
+ /**
385
+ * Single API section with two-column layout.
386
+ * Docs/params on left, sticky code panel on right.
387
+ */
388
+ declare function APISection({ title, id, description, children, languages, examples, externalLink, codePanelTitle, className }: APISectionProps): React12.ReactNode;
389
+ import * as React13 from "react";
390
+ interface APIReferencePageProps {
391
+ /** Page title */
392
+ title: string;
393
+ /** Optional page description */
394
+ description?: React13.ReactNode;
395
+ /** API sections as children */
396
+ children: React13.ReactNode;
397
+ /** Custom className */
398
+ className?: string;
399
+ }
400
+ /**
401
+ * Full page wrapper for API reference documentation.
402
+ * Provides max-width container and consistent spacing.
403
+ */
404
+ declare function APIReferencePage({ title, description, children, className }: APIReferencePageProps): React13.ReactNode;
405
+ export { wordWrap2 as wordWrap, tooltip, toCodeGroup, theme, mark, link, lineNumbers2 as lineNumbers, hover, flagsToOptions, expandable, endpointBadgeVariants, diff, collapse, callout, addDocsKit, WithNotes, WithHover, TooltipLink, TerminalSkeleton, Terminal, TabsTrigger, TabsList, TabsContent, Tabs, SingleCode, ResponseBlockProps, ResponseBlock, ParameterListProps, ParameterList, PackageInstall, MultiCode, LanguageSelectorProps, LanguageSelector, Language, InlineCodeSkeleton, HttpMethod, HoverLink, EndpointHeaderProps, EndpointHeader, EndpointBadgeProps, EndpointBadge, DocsKitInlineCode, DocsKitCode, DiffStats, CopyButton, CodeTabsSkeleton, CodeInfo, CodeIcon, CodeGroup, CodeExample, CodeBlockSkeleton, Code, ClientTerminal, ClientInlineCode, ClientDocsKitCode, ClientDiffCodeProps, ClientDiffCode, ClientCode, APISectionProps, APISection, APIReferencePageProps, APIReferencePage, APIParameterSchema, APIParameterItemProps, APIParameterItem, APICodePanelProps, APICodePanel };
@@ -5341,6 +5341,750 @@ function WithNotes({ children, ...rest }) {
5341
5341
  children
5342
5342
  });
5343
5343
  }
5344
+ // src/components/docskit/api/endpoint-badge.tsx
5345
+ import { cva } from "class-variance-authority";
5346
+ import * as React29 from "react";
5347
+ import { jsx as jsx44 } from "react/jsx-runtime";
5348
+ var endpointBadgeVariants = cva("inline-flex items-center justify-center font-mono font-bold uppercase tracking-wide rounded shrink-0", {
5349
+ variants: {
5350
+ method: {
5351
+ GET: "bg-emerald-500/15 text-emerald-500",
5352
+ POST: "bg-blue-500/15 text-blue-500",
5353
+ PUT: "bg-amber-500/15 text-amber-500",
5354
+ DELETE: "bg-rose-500/15 text-rose-500",
5355
+ PATCH: "bg-violet-500/15 text-violet-500"
5356
+ },
5357
+ size: {
5358
+ sm: "h-5 px-1.5 text-[10px]",
5359
+ md: "h-6 px-2 text-xs"
5360
+ }
5361
+ },
5362
+ defaultVariants: {
5363
+ method: "GET",
5364
+ size: "md"
5365
+ }
5366
+ });
5367
+ var EndpointBadge = React29.forwardRef(({ className, method, size: size4, ...props }, ref) => {
5368
+ return /* @__PURE__ */ jsx44("span", {
5369
+ ref,
5370
+ className: cn(endpointBadgeVariants({ method, size: size4, className })),
5371
+ ...props,
5372
+ children: method
5373
+ });
5374
+ });
5375
+ EndpointBadge.displayName = "EndpointBadge";
5376
+ // src/components/docskit/api/endpoint-header.tsx
5377
+ import { Copy as Copy2, Check as Check2 } from "lucide-react";
5378
+ import * as React30 from "react";
5379
+ import { useState as useState15 } from "react";
5380
+ import { jsx as jsx45, jsxs as jsxs16 } from "react/jsx-runtime";
5381
+
5382
+ var EndpointHeader = React30.forwardRef(({ className, method, path, copyable = true, ...props }, ref) => {
5383
+ const [copied, setCopied] = useState15(false);
5384
+ const handleCopy = () => {
5385
+ navigator.clipboard.writeText(path);
5386
+ setCopied(true);
5387
+ setTimeout(() => setCopied(false), 1200);
5388
+ };
5389
+ return /* @__PURE__ */ jsxs16("div", {
5390
+ ref,
5391
+ className: cn("group flex items-center gap-3 py-2 px-3 rounded-lg bg-muted/50 border border-border", className),
5392
+ ...props,
5393
+ children: [
5394
+ /* @__PURE__ */ jsx45(EndpointBadge, {
5395
+ method
5396
+ }),
5397
+ /* @__PURE__ */ jsx45("code", {
5398
+ className: "font-mono text-sm text-foreground flex-1",
5399
+ children: path
5400
+ }),
5401
+ copyable && /* @__PURE__ */ jsx45("button", {
5402
+ type: "button",
5403
+ onClick: handleCopy,
5404
+ className: cn("p-1.5 rounded text-muted-foreground hover:text-foreground", "opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer"),
5405
+ "aria-label": "Copy path",
5406
+ children: copied ? /* @__PURE__ */ jsx45(Check2, {
5407
+ size: 14
5408
+ }) : /* @__PURE__ */ jsx45(Copy2, {
5409
+ size: 14
5410
+ })
5411
+ })
5412
+ ]
5413
+ });
5414
+ });
5415
+ EndpointHeader.displayName = "EndpointHeader";
5416
+ // src/components/docskit/api/parameter-item.tsx
5417
+ import { ChevronRight, Copy as Copy3, Check as Check3 } from "lucide-react";
5418
+ import { useState as useState16 } from "react";
5419
+ import { jsx as jsx46, jsxs as jsxs17 } from "react/jsx-runtime";
5420
+
5421
+ function NestedProperty({
5422
+ name,
5423
+ schema,
5424
+ required = false,
5425
+ depth = 0
5426
+ }) {
5427
+ const [expanded, setExpanded] = useState16(false);
5428
+ const [copied, setCopied] = useState16(false);
5429
+ const type = schema.typeString ?? schema.type ?? "unknown";
5430
+ const hasNested = schema.properties && Object.keys(schema.properties).length > 0;
5431
+ const nestedCount = hasNested ? Object.keys(schema.properties).length : 0;
5432
+ const handleCopy = () => {
5433
+ navigator.clipboard.writeText(name);
5434
+ setCopied(true);
5435
+ setTimeout(() => setCopied(false), 1200);
5436
+ };
5437
+ return /* @__PURE__ */ jsxs17("div", {
5438
+ className: cn("border-t border-border first:border-t-0", depth > 0 && "ml-4"),
5439
+ children: [
5440
+ /* @__PURE__ */ jsx46("div", {
5441
+ className: "group py-4",
5442
+ children: /* @__PURE__ */ jsxs17("div", {
5443
+ className: "flex items-start gap-2",
5444
+ children: [
5445
+ hasNested ? /* @__PURE__ */ jsx46("button", {
5446
+ type: "button",
5447
+ onClick: () => setExpanded(!expanded),
5448
+ className: "mt-0.5 p-0.5 text-muted-foreground hover:text-foreground transition-colors cursor-pointer",
5449
+ "aria-label": expanded ? "Collapse" : "Expand",
5450
+ children: /* @__PURE__ */ jsx46(ChevronRight, {
5451
+ size: 14,
5452
+ className: cn("transition-transform duration-200", expanded && "rotate-90")
5453
+ })
5454
+ }) : /* @__PURE__ */ jsx46("div", {
5455
+ className: "w-5"
5456
+ }),
5457
+ /* @__PURE__ */ jsxs17("div", {
5458
+ className: "flex-1 min-w-0",
5459
+ children: [
5460
+ /* @__PURE__ */ jsxs17("div", {
5461
+ className: "flex items-center gap-2 flex-wrap",
5462
+ children: [
5463
+ /* @__PURE__ */ jsxs17("span", {
5464
+ className: "font-mono text-sm font-medium text-foreground",
5465
+ children: [
5466
+ name,
5467
+ !required && /* @__PURE__ */ jsx46("span", {
5468
+ className: "text-muted-foreground",
5469
+ children: "?"
5470
+ })
5471
+ ]
5472
+ }),
5473
+ /* @__PURE__ */ jsx46("span", {
5474
+ className: "font-mono text-xs text-muted-foreground",
5475
+ children: type
5476
+ }),
5477
+ hasNested && /* @__PURE__ */ jsx46("button", {
5478
+ type: "button",
5479
+ onClick: () => setExpanded(!expanded),
5480
+ className: "text-xs text-primary hover:underline cursor-pointer",
5481
+ children: "Show child parameters"
5482
+ }),
5483
+ /* @__PURE__ */ jsx46("button", {
5484
+ type: "button",
5485
+ onClick: handleCopy,
5486
+ className: "p-1 rounded text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer",
5487
+ "aria-label": "Copy name",
5488
+ children: copied ? /* @__PURE__ */ jsx46(Check3, {
5489
+ size: 12
5490
+ }) : /* @__PURE__ */ jsx46(Copy3, {
5491
+ size: 12
5492
+ })
5493
+ })
5494
+ ]
5495
+ }),
5496
+ schema.description && /* @__PURE__ */ jsx46("p", {
5497
+ className: "text-sm text-muted-foreground mt-1",
5498
+ children: schema.description
5499
+ })
5500
+ ]
5501
+ })
5502
+ ]
5503
+ })
5504
+ }),
5505
+ hasNested && expanded && schema.properties && /* @__PURE__ */ jsx46("div", {
5506
+ className: "border-l border-border ml-2 mb-3",
5507
+ children: Object.entries(schema.properties).map(([propName, propSchema]) => /* @__PURE__ */ jsx46(NestedProperty, {
5508
+ name: propName,
5509
+ schema: propSchema,
5510
+ required: schema.required?.includes(propName),
5511
+ depth: depth + 1
5512
+ }, propName))
5513
+ })
5514
+ ]
5515
+ });
5516
+ }
5517
+ function APIParameterItem({
5518
+ name,
5519
+ type,
5520
+ required = false,
5521
+ description,
5522
+ children,
5523
+ depth = 0,
5524
+ className
5525
+ }) {
5526
+ const [expanded, setExpanded] = useState16(false);
5527
+ const [copied, setCopied] = useState16(false);
5528
+ const hasNested = children?.properties && Object.keys(children.properties).length > 0;
5529
+ const nestedCount = hasNested ? Object.keys(children.properties).length : 0;
5530
+ const handleCopy = () => {
5531
+ navigator.clipboard.writeText(name);
5532
+ setCopied(true);
5533
+ setTimeout(() => setCopied(false), 1200);
5534
+ };
5535
+ return /* @__PURE__ */ jsxs17("div", {
5536
+ className: cn("border-b border-border last:border-b-0", className),
5537
+ children: [
5538
+ /* @__PURE__ */ jsx46("div", {
5539
+ className: "group py-4",
5540
+ children: /* @__PURE__ */ jsxs17("div", {
5541
+ className: "flex items-start gap-2",
5542
+ children: [
5543
+ hasNested ? /* @__PURE__ */ jsx46("button", {
5544
+ type: "button",
5545
+ onClick: () => setExpanded(!expanded),
5546
+ className: "mt-0.5 p-0.5 text-muted-foreground hover:text-foreground transition-colors cursor-pointer",
5547
+ "aria-label": expanded ? "Collapse" : "Expand",
5548
+ children: /* @__PURE__ */ jsx46(ChevronRight, {
5549
+ size: 14,
5550
+ className: cn("transition-transform duration-200", expanded && "rotate-90")
5551
+ })
5552
+ }) : /* @__PURE__ */ jsx46("div", {
5553
+ className: "w-5"
5554
+ }),
5555
+ /* @__PURE__ */ jsxs17("div", {
5556
+ className: "flex-1 min-w-0",
5557
+ children: [
5558
+ /* @__PURE__ */ jsxs17("div", {
5559
+ className: "flex items-center gap-2 flex-wrap",
5560
+ children: [
5561
+ /* @__PURE__ */ jsx46("span", {
5562
+ className: "font-mono text-sm font-medium text-foreground",
5563
+ children: name
5564
+ }),
5565
+ required && /* @__PURE__ */ jsx46("span", {
5566
+ className: "text-[10px] font-semibold px-1.5 py-0.5 rounded border border-border bg-muted text-muted-foreground uppercase tracking-wide",
5567
+ children: "Required"
5568
+ }),
5569
+ /* @__PURE__ */ jsx46("span", {
5570
+ className: "font-mono text-xs text-muted-foreground",
5571
+ children: type
5572
+ }),
5573
+ hasNested && /* @__PURE__ */ jsx46("button", {
5574
+ type: "button",
5575
+ onClick: () => setExpanded(!expanded),
5576
+ className: "text-xs text-primary hover:underline cursor-pointer",
5577
+ children: "Show child parameters"
5578
+ }),
5579
+ /* @__PURE__ */ jsx46("button", {
5580
+ type: "button",
5581
+ onClick: handleCopy,
5582
+ className: "p-1 rounded text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer",
5583
+ "aria-label": "Copy name",
5584
+ children: copied ? /* @__PURE__ */ jsx46(Check3, {
5585
+ size: 12
5586
+ }) : /* @__PURE__ */ jsx46(Copy3, {
5587
+ size: 12
5588
+ })
5589
+ })
5590
+ ]
5591
+ }),
5592
+ description && /* @__PURE__ */ jsx46("p", {
5593
+ className: "text-sm text-muted-foreground mt-1",
5594
+ children: description
5595
+ })
5596
+ ]
5597
+ })
5598
+ ]
5599
+ })
5600
+ }),
5601
+ hasNested && expanded && children?.properties && /* @__PURE__ */ jsx46("div", {
5602
+ className: "border-l border-border ml-2 mb-3",
5603
+ children: Object.entries(children.properties).map(([propName, propSchema]) => /* @__PURE__ */ jsx46(NestedProperty, {
5604
+ name: propName,
5605
+ schema: propSchema,
5606
+ required: children.required?.includes(propName),
5607
+ depth: depth + 1
5608
+ }, propName))
5609
+ })
5610
+ ]
5611
+ });
5612
+ }
5613
+ // src/components/docskit/api/parameter-list.tsx
5614
+ import { ChevronDown as ChevronDown2 } from "lucide-react";
5615
+ import * as React31 from "react";
5616
+ import { useState as useState17 } from "react";
5617
+ import { jsx as jsx47, jsxs as jsxs18 } from "react/jsx-runtime";
5618
+
5619
+ function ParameterList({
5620
+ title,
5621
+ collapseAfter,
5622
+ children,
5623
+ className
5624
+ }) {
5625
+ const [expanded, setExpanded] = useState17(false);
5626
+ const childArray = React31.Children.toArray(children);
5627
+ const shouldCollapse = collapseAfter !== undefined && childArray.length > collapseAfter;
5628
+ const visibleChildren = shouldCollapse && !expanded ? childArray.slice(0, collapseAfter) : childArray;
5629
+ const hiddenCount = shouldCollapse ? childArray.length - collapseAfter : 0;
5630
+ return /* @__PURE__ */ jsxs18("div", {
5631
+ className: cn("", className),
5632
+ children: [
5633
+ title && /* @__PURE__ */ jsx47("h3", {
5634
+ className: "text-sm font-medium text-foreground mb-3 uppercase tracking-wide",
5635
+ children: title
5636
+ }),
5637
+ /* @__PURE__ */ jsx47("div", {
5638
+ className: "divide-y divide-border border-t border-b border-border",
5639
+ children: visibleChildren
5640
+ }),
5641
+ shouldCollapse && !expanded && /* @__PURE__ */ jsxs18("button", {
5642
+ type: "button",
5643
+ onClick: () => setExpanded(true),
5644
+ className: "flex items-center gap-1 mt-3 text-sm text-primary hover:underline cursor-pointer",
5645
+ children: [
5646
+ /* @__PURE__ */ jsx47(ChevronDown2, {
5647
+ size: 14
5648
+ }),
5649
+ "Show ",
5650
+ hiddenCount,
5651
+ " more ",
5652
+ hiddenCount === 1 ? "parameter" : "parameters"
5653
+ ]
5654
+ })
5655
+ ]
5656
+ });
5657
+ }
5658
+ // src/components/docskit/api/response-block.tsx
5659
+ import { Check as Check4, Copy as Copy4 } from "lucide-react";
5660
+ import * as React32 from "react";
5661
+ import { useState as useState18 } from "react";
5662
+ import { jsx as jsx48, jsxs as jsxs19, Fragment as Fragment4 } from "react/jsx-runtime";
5663
+
5664
+ function ResponseBlock({ data, title, className }) {
5665
+ const [copied, setCopied] = useState18(false);
5666
+ const jsonString = JSON.stringify(data, null, 2);
5667
+ const handleCopy = () => {
5668
+ navigator.clipboard.writeText(jsonString);
5669
+ setCopied(true);
5670
+ setTimeout(() => setCopied(false), 1200);
5671
+ };
5672
+ return /* @__PURE__ */ jsxs19("div", {
5673
+ className: cn("group rounded-lg border border-border overflow-hidden bg-muted/30", className),
5674
+ children: [
5675
+ title && /* @__PURE__ */ jsxs19("div", {
5676
+ className: "flex items-center justify-between px-4 py-2 border-b border-border bg-muted/50",
5677
+ children: [
5678
+ /* @__PURE__ */ jsx48("span", {
5679
+ className: "text-xs font-medium text-muted-foreground uppercase tracking-wide",
5680
+ children: title
5681
+ }),
5682
+ /* @__PURE__ */ jsx48("button", {
5683
+ type: "button",
5684
+ onClick: handleCopy,
5685
+ className: "p-1 rounded text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer",
5686
+ "aria-label": "Copy response",
5687
+ children: copied ? /* @__PURE__ */ jsx48(Check4, {
5688
+ size: 14
5689
+ }) : /* @__PURE__ */ jsx48(Copy4, {
5690
+ size: 14
5691
+ })
5692
+ })
5693
+ ]
5694
+ }),
5695
+ /* @__PURE__ */ jsxs19("div", {
5696
+ className: "relative",
5697
+ children: [
5698
+ /* @__PURE__ */ jsx48("pre", {
5699
+ className: "p-4 overflow-auto text-sm font-mono leading-relaxed",
5700
+ children: /* @__PURE__ */ jsx48("code", {
5701
+ children: /* @__PURE__ */ jsx48(JsonHighlight, {
5702
+ json: data
5703
+ })
5704
+ })
5705
+ }),
5706
+ !title && /* @__PURE__ */ jsx48("button", {
5707
+ type: "button",
5708
+ onClick: handleCopy,
5709
+ className: "absolute top-3 right-3 p-1.5 rounded text-muted-foreground hover:text-foreground opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer",
5710
+ "aria-label": "Copy response",
5711
+ children: copied ? /* @__PURE__ */ jsx48(Check4, {
5712
+ size: 14
5713
+ }) : /* @__PURE__ */ jsx48(Copy4, {
5714
+ size: 14
5715
+ })
5716
+ })
5717
+ ]
5718
+ })
5719
+ ]
5720
+ });
5721
+ }
5722
+ function JsonHighlight({ json, depth = 0 }) {
5723
+ const indent = " ".repeat(depth);
5724
+ const nextIndent = " ".repeat(depth + 1);
5725
+ if (json === null) {
5726
+ return /* @__PURE__ */ jsx48("span", {
5727
+ className: "text-orange-400",
5728
+ children: "null"
5729
+ });
5730
+ }
5731
+ if (typeof json === "boolean") {
5732
+ return /* @__PURE__ */ jsx48("span", {
5733
+ className: "text-orange-400",
5734
+ children: json ? "true" : "false"
5735
+ });
5736
+ }
5737
+ if (typeof json === "number") {
5738
+ return /* @__PURE__ */ jsx48("span", {
5739
+ className: "text-cyan-400",
5740
+ children: json
5741
+ });
5742
+ }
5743
+ if (typeof json === "string") {
5744
+ return /* @__PURE__ */ jsxs19("span", {
5745
+ className: "text-emerald-400",
5746
+ children: [
5747
+ '"',
5748
+ json,
5749
+ '"'
5750
+ ]
5751
+ });
5752
+ }
5753
+ if (Array.isArray(json)) {
5754
+ if (json.length === 0) {
5755
+ return /* @__PURE__ */ jsx48("span", {
5756
+ className: "text-foreground",
5757
+ children: "[]"
5758
+ });
5759
+ }
5760
+ return /* @__PURE__ */ jsxs19(Fragment4, {
5761
+ children: [
5762
+ /* @__PURE__ */ jsx48("span", {
5763
+ className: "text-foreground",
5764
+ children: "["
5765
+ }),
5766
+ `
5767
+ `,
5768
+ json.map((item, i) => /* @__PURE__ */ jsxs19(React32.Fragment, {
5769
+ children: [
5770
+ nextIndent,
5771
+ /* @__PURE__ */ jsx48(JsonHighlight, {
5772
+ json: item,
5773
+ depth: depth + 1
5774
+ }),
5775
+ i < json.length - 1 && /* @__PURE__ */ jsx48("span", {
5776
+ className: "text-foreground",
5777
+ children: ","
5778
+ }),
5779
+ `
5780
+ `
5781
+ ]
5782
+ }, i)),
5783
+ indent,
5784
+ /* @__PURE__ */ jsx48("span", {
5785
+ className: "text-foreground",
5786
+ children: "]"
5787
+ })
5788
+ ]
5789
+ });
5790
+ }
5791
+ if (typeof json === "object") {
5792
+ const entries = Object.entries(json);
5793
+ if (entries.length === 0) {
5794
+ return /* @__PURE__ */ jsx48("span", {
5795
+ className: "text-foreground",
5796
+ children: "{}"
5797
+ });
5798
+ }
5799
+ return /* @__PURE__ */ jsxs19(Fragment4, {
5800
+ children: [
5801
+ /* @__PURE__ */ jsx48("span", {
5802
+ className: "text-foreground",
5803
+ children: "{"
5804
+ }),
5805
+ `
5806
+ `,
5807
+ entries.map(([key, value], i) => /* @__PURE__ */ jsxs19(React32.Fragment, {
5808
+ children: [
5809
+ nextIndent,
5810
+ /* @__PURE__ */ jsxs19("span", {
5811
+ className: "text-blue-400",
5812
+ children: [
5813
+ '"',
5814
+ key,
5815
+ '"'
5816
+ ]
5817
+ }),
5818
+ /* @__PURE__ */ jsx48("span", {
5819
+ className: "text-foreground",
5820
+ children: ": "
5821
+ }),
5822
+ /* @__PURE__ */ jsx48(JsonHighlight, {
5823
+ json: value,
5824
+ depth: depth + 1
5825
+ }),
5826
+ i < entries.length - 1 && /* @__PURE__ */ jsx48("span", {
5827
+ className: "text-foreground",
5828
+ children: ","
5829
+ }),
5830
+ `
5831
+ `
5832
+ ]
5833
+ }, key)),
5834
+ indent,
5835
+ /* @__PURE__ */ jsx48("span", {
5836
+ className: "text-foreground",
5837
+ children: "}"
5838
+ })
5839
+ ]
5840
+ });
5841
+ }
5842
+ return /* @__PURE__ */ jsx48("span", {
5843
+ className: "text-foreground",
5844
+ children: String(json)
5845
+ });
5846
+ }
5847
+ // src/components/docskit/api/language-selector.tsx
5848
+ import { ChevronDown as ChevronDown3 } from "lucide-react";
5849
+ import * as React33 from "react";
5850
+ import { jsx as jsx49, jsxs as jsxs20 } from "react/jsx-runtime";
5851
+
5852
+ function LanguageSelector({
5853
+ languages,
5854
+ value,
5855
+ onChange,
5856
+ className
5857
+ }) {
5858
+ const [open, setOpen] = React33.useState(false);
5859
+ const containerRef = React33.useRef(null);
5860
+ const selectedLanguage = languages.find((l) => l.id === value);
5861
+ React33.useEffect(() => {
5862
+ const handleClickOutside = (e) => {
5863
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
5864
+ setOpen(false);
5865
+ }
5866
+ };
5867
+ document.addEventListener("mousedown", handleClickOutside);
5868
+ return () => document.removeEventListener("mousedown", handleClickOutside);
5869
+ }, []);
5870
+ return /* @__PURE__ */ jsxs20("div", {
5871
+ ref: containerRef,
5872
+ className: cn("relative", className),
5873
+ children: [
5874
+ /* @__PURE__ */ jsxs20("button", {
5875
+ type: "button",
5876
+ onClick: () => setOpen(!open),
5877
+ className: cn("flex items-center gap-1.5 px-2.5 py-1.5 rounded-md text-sm font-medium", "bg-muted/50 hover:bg-muted text-foreground transition-colors cursor-pointer"),
5878
+ children: [
5879
+ selectedLanguage?.label ?? value,
5880
+ /* @__PURE__ */ jsx49(ChevronDown3, {
5881
+ size: 14,
5882
+ className: cn("transition-transform", open && "rotate-180")
5883
+ })
5884
+ ]
5885
+ }),
5886
+ open && /* @__PURE__ */ jsx49("div", {
5887
+ className: cn("absolute top-full left-0 mt-1 z-50 min-w-[120px]", "bg-popover border border-border rounded-md shadow-lg overflow-hidden"),
5888
+ children: languages.map((lang) => /* @__PURE__ */ jsx49("button", {
5889
+ type: "button",
5890
+ onClick: () => {
5891
+ onChange(lang.id);
5892
+ setOpen(false);
5893
+ },
5894
+ className: cn("w-full px-3 py-2 text-sm text-left transition-colors cursor-pointer", lang.id === value ? "bg-primary/10 text-primary" : "text-foreground hover:bg-muted"),
5895
+ children: lang.label
5896
+ }, lang.id))
5897
+ })
5898
+ ]
5899
+ });
5900
+ }
5901
+ // src/components/docskit/api/api-code-panel.tsx
5902
+ import { Pre as Pre5, highlight as highlight6 } from "codehike/code";
5903
+ import { Check as Check5, Copy as Copy5, ExternalLink } from "lucide-react";
5904
+ import { useEffect as useEffect12, useState as useState20 } from "react";
5905
+ import { jsx as jsx50, jsxs as jsxs21 } from "react/jsx-runtime";
5906
+
5907
+ function APICodePanel({
5908
+ languages,
5909
+ examples,
5910
+ externalLink,
5911
+ title,
5912
+ className
5913
+ }) {
5914
+ const [selectedLang, setSelectedLang] = useState20(examples[0]?.languageId ?? languages[0]?.id);
5915
+ const [copied, setCopied] = useState20(false);
5916
+ const [highlighted, setHighlighted] = useState20(null);
5917
+ const currentExample = examples.find((e) => e.languageId === selectedLang);
5918
+ const code = currentExample?.code ?? "";
5919
+ const lang = currentExample?.highlightLang ?? currentExample?.languageId ?? "txt";
5920
+ useEffect12(() => {
5921
+ let cancelled = false;
5922
+ highlight6({
5923
+ value: code,
5924
+ lang: lang === "curl" ? "bash" : lang,
5925
+ meta: ""
5926
+ }, theme).then((result) => {
5927
+ if (!cancelled) {
5928
+ setHighlighted(result);
5929
+ }
5930
+ });
5931
+ return () => {
5932
+ cancelled = true;
5933
+ };
5934
+ }, [code, lang]);
5935
+ const handleCopy = () => {
5936
+ navigator.clipboard.writeText(code);
5937
+ setCopied(true);
5938
+ setTimeout(() => setCopied(false), 1200);
5939
+ };
5940
+ const handlers = getHandlers({ copyButton: false });
5941
+ return /* @__PURE__ */ jsxs21("div", {
5942
+ className: cn("rounded-lg overflow-hidden border border-dk-border", "bg-dk-background text-gray-100", "sticky top-20", className),
5943
+ children: [
5944
+ /* @__PURE__ */ jsxs21("div", {
5945
+ className: "flex items-center justify-between px-4 py-3 border-b border-dk-border bg-dk-tabs-background",
5946
+ children: [
5947
+ /* @__PURE__ */ jsxs21("div", {
5948
+ className: "flex items-center gap-3",
5949
+ children: [
5950
+ languages.length > 1 && /* @__PURE__ */ jsx50(LanguageSelector, {
5951
+ languages,
5952
+ value: selectedLang,
5953
+ onChange: setSelectedLang,
5954
+ className: "[&_button]:bg-white/5 [&_button]:hover:bg-white/10 [&_button]:text-gray-200"
5955
+ }),
5956
+ title && /* @__PURE__ */ jsx50("span", {
5957
+ className: "text-sm text-dk-tab-inactive-foreground",
5958
+ children: title
5959
+ })
5960
+ ]
5961
+ }),
5962
+ /* @__PURE__ */ jsxs21("div", {
5963
+ className: "flex items-center gap-2",
5964
+ children: [
5965
+ /* @__PURE__ */ jsx50("button", {
5966
+ type: "button",
5967
+ onClick: handleCopy,
5968
+ className: "p-1.5 rounded text-dk-tab-inactive-foreground hover:text-gray-200 transition-colors cursor-pointer",
5969
+ "aria-label": "Copy code",
5970
+ children: copied ? /* @__PURE__ */ jsx50(Check5, {
5971
+ size: 16
5972
+ }) : /* @__PURE__ */ jsx50(Copy5, {
5973
+ size: 16
5974
+ })
5975
+ }),
5976
+ externalLink && /* @__PURE__ */ jsx50("a", {
5977
+ href: externalLink,
5978
+ target: "_blank",
5979
+ rel: "noopener noreferrer",
5980
+ className: "p-1.5 rounded text-dk-tab-inactive-foreground hover:text-gray-200 transition-colors",
5981
+ "aria-label": "Open in playground",
5982
+ children: /* @__PURE__ */ jsx50(ExternalLink, {
5983
+ size: 16
5984
+ })
5985
+ })
5986
+ ]
5987
+ })
5988
+ ]
5989
+ }),
5990
+ /* @__PURE__ */ jsx50("div", {
5991
+ className: "overflow-auto max-h-[60vh] lg:max-h-none",
5992
+ children: highlighted ? /* @__PURE__ */ jsx50(Pre5, {
5993
+ code: highlighted,
5994
+ className: "overflow-auto px-4 py-3 m-0 rounded-none !bg-dk-background selection:bg-dk-selection selection:text-current text-sm",
5995
+ style: highlighted.style,
5996
+ handlers
5997
+ }) : /* @__PURE__ */ jsx50(CodeBlockSkeleton, {
5998
+ lines: code.split(`
5999
+ `).length
6000
+ })
6001
+ })
6002
+ ]
6003
+ });
6004
+ }
6005
+ // src/components/docskit/api/api-section.tsx
6006
+ import { jsx as jsx51, jsxs as jsxs22 } from "react/jsx-runtime";
6007
+
6008
+ function APISection({
6009
+ title,
6010
+ id,
6011
+ description,
6012
+ children,
6013
+ languages,
6014
+ examples,
6015
+ externalLink,
6016
+ codePanelTitle,
6017
+ className
6018
+ }) {
6019
+ return /* @__PURE__ */ jsx51("section", {
6020
+ id,
6021
+ className: cn("py-8 border-b border-border last:border-b-0", className),
6022
+ children: /* @__PURE__ */ jsxs22("div", {
6023
+ className: "grid grid-cols-1 lg:grid-cols-2 gap-8 lg:gap-12",
6024
+ children: [
6025
+ /* @__PURE__ */ jsxs22("div", {
6026
+ className: "space-y-6",
6027
+ children: [
6028
+ /* @__PURE__ */ jsxs22("div", {
6029
+ children: [
6030
+ /* @__PURE__ */ jsx51("h2", {
6031
+ className: "text-2xl font-semibold text-foreground",
6032
+ children: title
6033
+ }),
6034
+ description && /* @__PURE__ */ jsx51("div", {
6035
+ className: "mt-3 text-muted-foreground prose prose-sm dark:prose-invert",
6036
+ children: description
6037
+ })
6038
+ ]
6039
+ }),
6040
+ children
6041
+ ]
6042
+ }),
6043
+ /* @__PURE__ */ jsx51("div", {
6044
+ className: "lg:pl-4",
6045
+ children: /* @__PURE__ */ jsx51(APICodePanel, {
6046
+ languages,
6047
+ examples,
6048
+ externalLink,
6049
+ title: codePanelTitle,
6050
+ className: "max-h-[400px] lg:max-h-none"
6051
+ })
6052
+ })
6053
+ ]
6054
+ })
6055
+ });
6056
+ }
6057
+ // src/components/docskit/api/api-reference-page.tsx
6058
+ import { jsx as jsx52, jsxs as jsxs23 } from "react/jsx-runtime";
6059
+
6060
+ function APIReferencePage({
6061
+ title,
6062
+ description,
6063
+ children,
6064
+ className
6065
+ }) {
6066
+ return /* @__PURE__ */ jsxs23("div", {
6067
+ className: cn("max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", className),
6068
+ children: [
6069
+ /* @__PURE__ */ jsxs23("header", {
6070
+ className: "py-8 border-b border-border",
6071
+ children: [
6072
+ /* @__PURE__ */ jsx52("h1", {
6073
+ className: "text-3xl font-bold text-foreground",
6074
+ children: title
6075
+ }),
6076
+ description && /* @__PURE__ */ jsx52("div", {
6077
+ className: "mt-4 text-lg text-muted-foreground prose prose-lg dark:prose-invert max-w-none",
6078
+ children: description
6079
+ })
6080
+ ]
6081
+ }),
6082
+ /* @__PURE__ */ jsx52("div", {
6083
+ children
6084
+ })
6085
+ ]
6086
+ });
6087
+ }
5344
6088
  export {
5345
6089
  wordWrap,
5346
6090
  tooltip,
@@ -5352,6 +6096,7 @@ export {
5352
6096
  hover,
5353
6097
  flagsToOptions,
5354
6098
  expandable,
6099
+ endpointBadgeVariants,
5355
6100
  diff,
5356
6101
  collapse,
5357
6102
  callout,
@@ -5366,10 +6111,15 @@ export {
5366
6111
  TabsContent,
5367
6112
  Tabs,
5368
6113
  SingleCode,
6114
+ ResponseBlock,
6115
+ ParameterList,
5369
6116
  PackageInstall,
5370
6117
  MultiCode,
6118
+ LanguageSelector,
5371
6119
  InlineCodeSkeleton,
5372
6120
  HoverLink,
6121
+ EndpointHeader,
6122
+ EndpointBadge,
5373
6123
  DocsKitInlineCode,
5374
6124
  DocsKitCode,
5375
6125
  CopyButton,
@@ -5382,5 +6132,9 @@ export {
5382
6132
  ClientInlineCode,
5383
6133
  ClientDocsKitCode,
5384
6134
  ClientDiffCode,
5385
- ClientCode
6135
+ ClientCode,
6136
+ APISection,
6137
+ APIReferencePage,
6138
+ APIParameterItem,
6139
+ APICodePanel
5386
6140
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doccov/ui",
3
- "version": "0.2.3",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "files": [