@dreamlake/dockit 0.2.19 → 0.2.21

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.
@@ -1,5 +1,6 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { useRef, useState } from "react";
2
+ import { useContext, useRef, useState } from "react";
3
+ import { CodeTabsContext } from "./code-tabs-context.js";
3
4
  import { useLineNumbers } from "../lib/use-line-numbers.js";
4
5
  const headerBtnStyle = (active) => ({
5
6
  display: "inline-flex",
@@ -19,6 +20,7 @@ const headerBtnStyle = (active) => ({
19
20
  transition: "color 0.12s ease, border-color 0.12s ease"
20
21
  });
21
22
  function CodeBlock({ children, filename, lang }) {
23
+ const embedded = useContext(CodeTabsContext);
22
24
  const wrapRef = useRef(null);
23
25
  const [copied, setCopied] = useState(false);
24
26
  const [showLines, setShowLines] = useLineNumbers();
@@ -39,11 +41,11 @@ function CodeBlock({ children, filename, lang }) {
39
41
  {
40
42
  ref: wrapRef,
41
43
  "data-line-numbers": showLines ? "on" : "off",
42
- className: "group relative border border-doc-template-faint bg-doc-template-code",
44
+ className: embedded ? void 0 : "group relative border border-doc-template-faint bg-doc-template-code",
43
45
  style: {
44
- margin: "18px 0 22px",
45
- borderRadius: "var(--radius-doc-template)",
46
- overflow: "hidden"
46
+ margin: embedded ? 0 : "18px 0 22px",
47
+ borderRadius: embedded ? 0 : "var(--radius-doc-template)",
48
+ overflow: embedded ? "visible" : "hidden"
47
49
  },
48
50
  children: [
49
51
  filename && /* @__PURE__ */ jsxs(
@@ -97,8 +99,25 @@ function CodeBlock({ children, filename, lang }) {
97
99
  "div",
98
100
  {
99
101
  className: "absolute top-0 right-0 z-10 flex items-center opacity-0 group-hover:opacity-100 focus-within:opacity-100 transition-opacity duration-150",
100
- style: { gap: 6, padding: "8px 8px" },
102
+ style: { gap: 6, padding: "8px 8px", isolation: "isolate" },
101
103
  children: [
104
+ /* @__PURE__ */ jsx(
105
+ "span",
106
+ {
107
+ "aria-hidden": "true",
108
+ style: {
109
+ position: "absolute",
110
+ inset: 4,
111
+ zIndex: -1,
112
+ pointerEvents: "none",
113
+ borderRadius: 6,
114
+ background: "color-mix(in srgb, var(--color-doc-template-code) 88%, transparent)",
115
+ boxShadow: "0 0 10px 6px var(--color-doc-template-code)",
116
+ backdropFilter: "blur(8px)",
117
+ WebkitBackdropFilter: "blur(8px)"
118
+ }
119
+ }
120
+ ),
102
121
  lang && /* @__PURE__ */ jsx(
103
122
  "span",
104
123
  {
@@ -0,0 +1,13 @@
1
+ import { ReactNode } from 'react';
2
+ export interface CodeExampleProps {
3
+ label: string;
4
+ children: ReactNode;
5
+ }
6
+ /** Keep ordinary fenced MDX as children so generated Markdown retains each example. */
7
+ export declare function CodeExample({ children }: CodeExampleProps): import("react").JSX.Element;
8
+ export interface CodeTabsProps {
9
+ children: ReactNode;
10
+ 'aria-label'?: string;
11
+ }
12
+ /** Equivalent fenced examples in one frame; arrow keys activate and focus tabs. */
13
+ export declare function CodeTabs({ children, 'aria-label': label }: CodeTabsProps): import("react").JSX.Element | null;
@@ -0,0 +1,60 @@
1
+ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
+ import { Children, isValidElement, useState, useId, useRef } from "react";
3
+ import { CodeTabsContext } from "./code-tabs-context.js";
4
+ function CodeExample({ children }) {
5
+ return /* @__PURE__ */ jsx(Fragment, { children });
6
+ }
7
+ function CodeTabs({ children, "aria-label": label = "Code examples" }) {
8
+ const examples = Children.toArray(children).filter(isValidElement);
9
+ const [selected, setSelected] = useState(0);
10
+ const active = Math.min(selected, Math.max(0, examples.length - 1));
11
+ const id = useId();
12
+ const buttons = useRef([]);
13
+ if (!examples.length) return null;
14
+ return /* @__PURE__ */ jsxs("div", { "data-code-tabs": true, className: "dockit-code-tabs group relative border border-doc-template-faint bg-doc-template-code", children: [
15
+ /* @__PURE__ */ jsx("div", { className: "dockit-code-tabs-header", children: /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": label, className: "dockit-code-tabs-list", children: examples.map((example, index) => /* @__PURE__ */ jsx(
16
+ "button",
17
+ {
18
+ type: "button",
19
+ role: "tab",
20
+ ref: (element) => {
21
+ buttons.current[index] = element;
22
+ },
23
+ id: `${id}-tab-${index}`,
24
+ "aria-controls": `${id}-panel-${index}`,
25
+ "aria-selected": active === index,
26
+ tabIndex: active === index ? 0 : -1,
27
+ onClick: () => setSelected(index),
28
+ onKeyDown: (event) => {
29
+ let next;
30
+ if (event.key === "ArrowRight") next = (index + 1) % examples.length;
31
+ else if (event.key === "ArrowLeft") next = (index - 1 + examples.length) % examples.length;
32
+ else if (event.key === "Home") next = 0;
33
+ else if (event.key === "End") next = examples.length - 1;
34
+ else return;
35
+ event.preventDefault();
36
+ setSelected(next);
37
+ buttons.current[next]?.focus();
38
+ },
39
+ children: example.props.label
40
+ },
41
+ example.key ?? index
42
+ )) }) }),
43
+ /* @__PURE__ */ jsx(CodeTabsContext.Provider, { value: true, children: examples.map((example, index) => /* @__PURE__ */ jsx(
44
+ "div",
45
+ {
46
+ role: "tabpanel",
47
+ id: `${id}-panel-${index}`,
48
+ "aria-labelledby": `${id}-tab-${index}`,
49
+ hidden: active !== index,
50
+ tabIndex: 0,
51
+ children: example.props.children
52
+ },
53
+ example.key ?? index
54
+ )) })
55
+ ] });
56
+ }
57
+ export {
58
+ CodeExample,
59
+ CodeTabs
60
+ };
@@ -0,0 +1,2 @@
1
+ /** Internal: a fenced block shares the surrounding tabs' frame and toolbar. */
2
+ export declare const CodeTabsContext: import('react').Context<boolean>;
@@ -0,0 +1,5 @@
1
+ import { createContext } from "react";
2
+ const CodeTabsContext = createContext(false);
3
+ export {
4
+ CodeTabsContext
5
+ };
package/dist/index.d.ts CHANGED
@@ -30,6 +30,7 @@ export { Callout } from './components/Callout';
30
30
  export { Chip, type ChipProps, type ChipVariant } from './components/Chip';
31
31
  export { ClientOnly } from './components/ClientOnly';
32
32
  export { CodeBlock } from './components/CodeBlock';
33
+ export { CodeTabs, CodeExample, type CodeTabsProps, type CodeExampleProps } from './components/CodeTabs';
33
34
  export { DocFooter } from './components/DocFooter';
34
35
  export { mdxComponents } from './components/mdx-components';
35
36
  export { Preview, type PreviewProps } from './components/Preview';
package/dist/index.js CHANGED
@@ -15,6 +15,7 @@ import { Callout } from "./components/Callout.js";
15
15
  import { Chip } from "./components/Chip.js";
16
16
  import { ClientOnly } from "./components/ClientOnly.js";
17
17
  import { CodeBlock } from "./components/CodeBlock.js";
18
+ import { CodeExample, CodeTabs } from "./components/CodeTabs.js";
18
19
  import { DocFooter } from "./components/DocFooter.js";
19
20
  import { mdxComponents } from "./components/mdx-components.js";
20
21
  import { Preview } from "./components/Preview.js";
@@ -45,6 +46,8 @@ export {
45
46
  Chip,
46
47
  ClientOnly,
47
48
  CodeBlock,
49
+ CodeExample,
50
+ CodeTabs,
48
51
  DOC_PREFIX,
49
52
  DocFooter,
50
53
  Layout,
package/dist/styles.css CHANGED
@@ -378,3 +378,39 @@
378
378
  .doc-sidebar::-webkit-scrollbar-thumb { background: var(--color-doc-template-faint-strong); border-radius: 3px; }
379
379
  .doc-sidebar .sidebar-section > span:first-child { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
380
380
  .doc-sidebar .sidebar-section > span:last-child { flex-shrink: 0; white-space: nowrap; }
381
+
382
+ /* One frame and toolbar for ordinary MDX fenced examples. Inactive panels keep
383
+ their code/control state but are absent from keyboard and accessibility flow. */
384
+ .dockit-code-tabs {
385
+ margin: 18px 0 22px;
386
+ border-radius: var(--radius-doc-template);
387
+ overflow: hidden;
388
+ }
389
+ .dockit-code-tabs-header {
390
+ border-bottom: 1px solid var(--color-doc-template-faint);
391
+ background: color-mix(in srgb, var(--color-doc-template-ink) 3%, transparent);
392
+ min-height: 40px;
393
+ padding-right: 156px;
394
+ }
395
+ .dockit-code-tabs-list { display: flex; overflow-x: auto; }
396
+ .dockit-code-tabs-list [role='tab'] {
397
+ flex-shrink: 0;
398
+ padding: 10px 14px;
399
+ border: 0;
400
+ border-bottom: 2px solid transparent;
401
+ background: transparent;
402
+ color: var(--color-doc-template-muted);
403
+ font: inherit;
404
+ font-size: 12px;
405
+ cursor: pointer;
406
+ }
407
+ .dockit-code-tabs-list [role='tab'][aria-selected='true'] {
408
+ color: var(--color-doc-template-ink);
409
+ border-bottom-color: var(--color-doc-template-accent);
410
+ }
411
+ .dockit-code-tabs-list [role='tab']:focus-visible,
412
+ .dockit-code-tabs [role='tabpanel']:focus-visible {
413
+ outline: 2px solid var(--color-doc-template-accent);
414
+ outline-offset: -3px;
415
+ }
416
+ .dockit-code-tabs [role='tabpanel'][hidden] { display: none; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dreamlake/dockit",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "description": "The DreamLake documentation shell — Vike + React + Tailwind v4 + MDX docs framework with sidebar, TOC, search, and theming",
5
5
  "license": "MIT",
6
6
  "type": "module",