@brett_lamy/docstream 1.7.0 → 1.9.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/README.md +18 -0
- package/dist/demo/DemoViewer.d.ts +8 -0
- package/dist/demo/DemoViewer.d.ts.map +1 -1
- package/dist/demo/DemoViewer.js +76 -3
- package/dist/demo/DemoViewer.js.map +1 -1
- package/dist/demo/PathBreadcrumb.d.ts +54 -0
- package/dist/demo/PathBreadcrumb.d.ts.map +1 -0
- package/dist/demo/PathBreadcrumb.js +245 -0
- package/dist/demo/PathBreadcrumb.js.map +1 -0
- package/dist/docs/DocsRenderer.d.ts +9 -2
- package/dist/docs/DocsRenderer.d.ts.map +1 -1
- package/dist/docs/DocsRenderer.js +13 -6
- package/dist/docs/DocsRenderer.js.map +1 -1
- package/dist/docs/DocumentProperties.d.ts +11 -0
- package/dist/docs/DocumentProperties.d.ts.map +1 -0
- package/dist/docs/DocumentProperties.js +63 -0
- package/dist/docs/DocumentProperties.js.map +1 -0
- package/dist/docs/TaskCheckbox.d.ts +24 -0
- package/dist/docs/TaskCheckbox.d.ts.map +1 -0
- package/dist/docs/TaskCheckbox.js +103 -0
- package/dist/docs/TaskCheckbox.js.map +1 -0
- package/dist/docs/properties.css +28 -0
- package/dist/docs/tasks.css +13 -0
- package/dist/gitbook/ast.d.ts +14 -0
- package/dist/gitbook/ast.d.ts.map +1 -1
- package/dist/gitbook/ast.js.map +1 -1
- package/dist/gitbook/index.d.ts +3 -0
- package/dist/gitbook/index.d.ts.map +1 -1
- package/dist/gitbook/index.js +2 -0
- package/dist/gitbook/index.js.map +1 -1
- package/dist/gitbook/parse.d.ts.map +1 -1
- package/dist/gitbook/parse.js +17 -3
- package/dist/gitbook/parse.js.map +1 -1
- package/dist/gitbook/properties.d.ts +15 -0
- package/dist/gitbook/properties.d.ts.map +1 -0
- package/dist/gitbook/properties.js +45 -0
- package/dist/gitbook/properties.js.map +1 -0
- package/dist/gitbook/serialize.d.ts.map +1 -1
- package/dist/gitbook/serialize.js +5 -2
- package/dist/gitbook/serialize.js.map +1 -1
- package/dist/gitbook/tasks.d.ts +11 -0
- package/dist/gitbook/tasks.d.ts.map +1 -0
- package/dist/gitbook/tasks.js +21 -0
- package/dist/gitbook/tasks.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/streamdown.d.ts +1 -1
- package/dist/streamdown.d.ts.map +1 -1
- package/dist/streamdown.js +2 -2
- package/dist/streamdown.js.map +1 -1
- package/dist/styles.css +228 -4
- package/package.json +15 -1
- package/src/demo/DemoViewer.tsx +98 -4
- package/src/demo/PathBreadcrumb.tsx +367 -0
- package/src/docs/DocsRenderer.tsx +22 -5
- package/src/docs/DocumentProperties.tsx +84 -0
- package/src/docs/TaskCheckbox.tsx +111 -0
- package/src/docs/properties.css +28 -0
- package/src/docs/tasks.css +13 -0
- package/src/gitbook/ast.ts +16 -0
- package/src/gitbook/index.ts +3 -0
- package/src/gitbook/parse.ts +15 -3
- package/src/gitbook/properties.ts +49 -0
- package/src/gitbook/serialize.ts +5 -2
- package/src/gitbook/tasks.ts +25 -0
- package/src/index.ts +7 -0
- package/src/streamdown.tsx +4 -0
- package/src/styles.css +228 -4
package/dist/streamdown.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamdown.d.ts","sourceRoot":"","sources":["../src/streamdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAKjI,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACnG,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACtG,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAA;AACtH,YAAY,EAAE,eAAe,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAE1G,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,mBAAmB,CAAA;IAClC,cAAc,CAAC,EAAE,uBAAuB,CAAA;IACxC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,SAAS,EACT,WAAW,EACX,WAAmB,EACnB,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,WAAW,
|
|
1
|
+
{"version":3,"file":"streamdown.d.ts","sourceRoot":"","sources":["../src/streamdown.tsx"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,gBAAgB,EAAE,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAKjI,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACnD,YAAY,EAAE,aAAa,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AACnG,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACtG,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,QAAQ,CAAA;AACtH,YAAY,EAAE,eAAe,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAA;AAE1G,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,mBAAmB,CAAA;IAClC,cAAc,CAAC,EAAE,uBAAuB,CAAA;IACxC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,SAAS,EACT,WAAW,EACX,WAAmB,EACnB,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,kBAAkB,EAClB,iBAAiB,GAClB,EAAE,sBAAsB,+BA6BxB"}
|
package/dist/streamdown.js
CHANGED
|
@@ -7,9 +7,9 @@ import { parseMarkdown, trimPartialInlineToken } from "./gitbook/parse.js";
|
|
|
7
7
|
export { CitationSources, DocstreamRefContext, InlineReference } from "./docs/reference.js";
|
|
8
8
|
export { DocPageActions } from "./docs/PageActions.js";
|
|
9
9
|
export { DocstreamDemoContext, DocstreamDemoRuntimeContext, DemoFullscreen, DemoViewer } from "./demo/index.js";
|
|
10
|
-
export function GitbookStreamdown({ children, className, isAnimating, isStreaming = false, markdown, liveRenderer, sourceRenderer, demoResolver, demoRuntime, demoDependencies, demoVFS, pageActions, }) {
|
|
10
|
+
export function GitbookStreamdown({ children, className, isAnimating, isStreaming = false, markdown, liveRenderer, sourceRenderer, demoResolver, demoRuntime, demoDependencies, demoVFS, pageActions, documentProperties, onTaskStateChange, }) {
|
|
11
11
|
const content = markdown ?? children ?? "";
|
|
12
12
|
const gitbookDoc = useMemo(() => parseMarkdown(isStreaming ? trimPartialInlineToken(content) : content), [content, isStreaming]);
|
|
13
|
-
return (_jsx("div", { "aria-busy": isAnimating ?? isStreaming, className: className, "data-docstream": "", "data-streaming": isStreaming ? "" : undefined, children: _jsx(DocsRenderer, { doc: gitbookDoc, markdown: content, liveRenderer: liveRenderer, sourceRenderer: sourceRenderer, demoResolver: demoResolver, demoRuntime: demoRuntime, demoDependencies: demoDependencies, demoVFS: demoVFS, pageActions: isStreaming ? false : pageActions }) }));
|
|
13
|
+
return (_jsx("div", { "aria-busy": isAnimating ?? isStreaming, className: className, "data-docstream": "", "data-streaming": isStreaming ? "" : undefined, children: _jsx(DocsRenderer, { doc: gitbookDoc, markdown: content, liveRenderer: liveRenderer, sourceRenderer: sourceRenderer, demoResolver: demoResolver, demoRuntime: demoRuntime, demoDependencies: demoDependencies, demoVFS: demoVFS, pageActions: isStreaming ? false : pageActions, documentProperties: documentProperties, onTaskStateChange: onTaskStateChange }) }));
|
|
14
14
|
}
|
|
15
15
|
//# sourceMappingURL=streamdown.js.map
|
package/dist/streamdown.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamdown.js","sourceRoot":"","sources":["../src/streamdown.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAiF,MAAM,qBAAqB,CAAA;AACjI,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAEvE,uEAAuE;AACvE,yDAAyD;AACzD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGnD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AActG,MAAM,UAAU,iBAAiB,CAAC,EAChC,QAAQ,EACR,SAAS,EACT,WAAW,EACX,WAAW,GAAG,KAAK,EACnB,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,WAAW,
|
|
1
|
+
{"version":3,"file":"streamdown.js","sourceRoot":"","sources":["../src/streamdown.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAiF,MAAM,qBAAqB,CAAA;AACjI,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAEvE,uEAAuE;AACvE,yDAAyD;AACzD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACxF,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAGnD,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AActG,MAAM,UAAU,iBAAiB,CAAC,EAChC,QAAQ,EACR,SAAS,EACT,WAAW,EACX,WAAW,GAAG,KAAK,EACnB,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,kBAAkB,EAClB,iBAAiB,GACM;IACvB,MAAM,OAAO,GAAG,QAAQ,IAAI,QAAQ,IAAI,EAAE,CAAA;IAC1C,MAAM,UAAU,GAAG,OAAO,CACxB,GAAG,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAC5E,CAAC,OAAO,EAAE,WAAW,CAAC,CACvB,CAAA;IAED,OAAO,CACL,2BACa,WAAW,IAAI,WAAW,EACrC,SAAS,EAAE,SAAS,oBACL,EAAE,oBACD,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,YAE5C,KAAC,YAAY,IACX,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,OAAO,EACjB,YAAY,EAAE,YAAY,EAC1B,cAAc,EAAE,cAAc,EAC9B,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,WAAW,EACxB,gBAAgB,EAAE,gBAAgB,EAClC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,EAC9C,kBAAkB,EAAE,kBAAkB,EACtC,iBAAiB,EAAE,iBAAiB,GACpC,GACE,CACP,CAAA;AACH,CAAC"}
|
package/dist/styles.css
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
@import "./docs/properties.css";
|
|
2
|
+
@import "./docs/tasks.css";
|
|
1
3
|
|
|
2
4
|
[data-docstream],
|
|
3
5
|
.docs-article {
|
|
@@ -2064,13 +2066,76 @@
|
|
|
2064
2066
|
.docs-demo-files {
|
|
2065
2067
|
flex-shrink: 0;
|
|
2066
2068
|
box-sizing: border-box;
|
|
2067
|
-
|
|
2069
|
+
/* --docs-demo-files-w is set (px) once the reader drags the handle; 188px until then. */
|
|
2070
|
+
width: var(--docs-demo-files-w, 188px);
|
|
2068
2071
|
padding: 8px;
|
|
2069
2072
|
overflow-y: auto;
|
|
2070
2073
|
border-right: 1px solid var(--gb-border);
|
|
2071
2074
|
background: var(--gb-muted);
|
|
2072
2075
|
}
|
|
2073
2076
|
|
|
2077
|
+
/* The drag handle between the file list and the source: zero layout width, with a wider hit area
|
|
2078
|
+
and the same grip as the preview handle straddling the divider. */
|
|
2079
|
+
.docs-demo-files-handle {
|
|
2080
|
+
position: relative;
|
|
2081
|
+
z-index: 2;
|
|
2082
|
+
flex: 0 0 0;
|
|
2083
|
+
width: 0;
|
|
2084
|
+
cursor: col-resize;
|
|
2085
|
+
touch-action: none;
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
.docs-demo-files-handle::before {
|
|
2089
|
+
position: absolute;
|
|
2090
|
+
top: 0;
|
|
2091
|
+
bottom: 0;
|
|
2092
|
+
left: -5px;
|
|
2093
|
+
width: 10px;
|
|
2094
|
+
content: "";
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
.docs-demo-files-handle::after {
|
|
2098
|
+
position: absolute;
|
|
2099
|
+
top: 50%;
|
|
2100
|
+
left: -2.5px;
|
|
2101
|
+
width: 5px;
|
|
2102
|
+
height: 40px;
|
|
2103
|
+
margin-top: -20px;
|
|
2104
|
+
border-radius: 3px;
|
|
2105
|
+
background: var(--gb-stage-dot);
|
|
2106
|
+
content: "";
|
|
2107
|
+
opacity: 0;
|
|
2108
|
+
transition: opacity 150ms ease, background 150ms ease, height 200ms ease, margin 200ms ease;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
.docs-demo-code:hover .docs-demo-files-handle::after {
|
|
2112
|
+
opacity: 1;
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
.docs-demo-files-handle:hover::after,
|
|
2116
|
+
.docs-demo-files-handle:focus-visible::after,
|
|
2117
|
+
.docs-demo-files-handle[data-dragging]::after {
|
|
2118
|
+
height: 56px;
|
|
2119
|
+
margin-top: -28px;
|
|
2120
|
+
background: var(--gb-primary);
|
|
2121
|
+
opacity: 1;
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
.docs-demo-files-handle:focus-visible {
|
|
2125
|
+
outline: none;
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
.docs-demo-files-handle:focus-visible::before {
|
|
2129
|
+
outline: 2px solid var(--gb-primary);
|
|
2130
|
+
outline-offset: -1px;
|
|
2131
|
+
border-radius: 2px;
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
.docs-demo-code[data-dragging] {
|
|
2135
|
+
cursor: col-resize;
|
|
2136
|
+
user-select: none;
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2074
2139
|
.docs-demo-files-h {
|
|
2075
2140
|
padding: 6px 8px 8px;
|
|
2076
2141
|
color: var(--gb-muted-foreground);
|
|
@@ -2143,18 +2208,174 @@
|
|
|
2143
2208
|
align-items: center;
|
|
2144
2209
|
justify-content: space-between;
|
|
2145
2210
|
gap: 8px;
|
|
2146
|
-
padding: 5px 6px 5px
|
|
2211
|
+
padding: 5px 6px 5px 8px;
|
|
2147
2212
|
border-bottom: 1px solid var(--gb-border);
|
|
2148
2213
|
color: var(--gb-muted-foreground);
|
|
2149
2214
|
font: 12px/1 var(--docs-demo-mono);
|
|
2150
2215
|
}
|
|
2151
2216
|
|
|
2152
|
-
|
|
2217
|
+
/* Breadcrumb path: one button per segment. The list is clipped to the header; the fit logic in
|
|
2218
|
+
PathBreadcrumb collapses the middle to a "…" before that matters. */
|
|
2219
|
+
.docs-demo-crumbs {
|
|
2220
|
+
position: relative;
|
|
2221
|
+
flex: 1;
|
|
2222
|
+
min-width: 0;
|
|
2223
|
+
overflow: hidden;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
.docs-demo-crumbs > .docs-demo-crumbs-list {
|
|
2227
|
+
display: flex;
|
|
2228
|
+
align-items: center;
|
|
2229
|
+
margin: 0;
|
|
2230
|
+
padding: 0;
|
|
2231
|
+
list-style: none;
|
|
2232
|
+
white-space: nowrap;
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
.docs-demo-crumbs > .docs-demo-crumbs-measure {
|
|
2236
|
+
position: absolute;
|
|
2237
|
+
top: 0;
|
|
2238
|
+
left: 0;
|
|
2239
|
+
height: 0;
|
|
2240
|
+
visibility: hidden;
|
|
2241
|
+
pointer-events: none;
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
.docs-demo-crumbs-list > .docs-demo-crumb-item {
|
|
2245
|
+
display: flex;
|
|
2246
|
+
flex: 0 0 auto;
|
|
2247
|
+
align-items: center;
|
|
2248
|
+
min-width: 0;
|
|
2249
|
+
margin: 0;
|
|
2250
|
+
padding: 0;
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
.docs-demo-crumbs-list > .docs-demo-crumb-item[data-last] {
|
|
2254
|
+
flex: 0 1 auto;
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
.docs-demo-crumb-sep {
|
|
2258
|
+
flex-shrink: 0;
|
|
2259
|
+
color: var(--gb-muted-foreground);
|
|
2260
|
+
opacity: 0.7;
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
.docs-demo-crumb {
|
|
2264
|
+
display: inline-flex;
|
|
2265
|
+
align-items: center;
|
|
2266
|
+
gap: 5px;
|
|
2267
|
+
min-width: 0;
|
|
2268
|
+
box-sizing: border-box;
|
|
2269
|
+
height: 24px;
|
|
2270
|
+
padding: 0 6px;
|
|
2271
|
+
border: 0;
|
|
2272
|
+
border-radius: 6px;
|
|
2273
|
+
background: none;
|
|
2274
|
+
color: var(--gb-muted-foreground);
|
|
2275
|
+
font: inherit;
|
|
2276
|
+
cursor: pointer;
|
|
2277
|
+
transition: background 150ms ease, color 150ms ease;
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
.docs-demo-crumb svg {
|
|
2281
|
+
flex-shrink: 0;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
.docs-demo-crumb-text {
|
|
2153
2285
|
overflow: hidden;
|
|
2154
2286
|
text-overflow: ellipsis;
|
|
2155
2287
|
white-space: nowrap;
|
|
2156
2288
|
}
|
|
2157
2289
|
|
|
2290
|
+
.docs-demo-crumb:hover,
|
|
2291
|
+
.docs-demo-crumb[aria-expanded="true"] {
|
|
2292
|
+
background: var(--gb-hover);
|
|
2293
|
+
color: var(--gb-panel-foreground);
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
.docs-demo-crumb[data-current] {
|
|
2297
|
+
color: var(--gb-panel-foreground);
|
|
2298
|
+
font-weight: 600;
|
|
2299
|
+
}
|
|
2300
|
+
|
|
2301
|
+
.docs-demo-crumb[data-current] svg {
|
|
2302
|
+
color: var(--gb-primary);
|
|
2303
|
+
}
|
|
2304
|
+
|
|
2305
|
+
.docs-demo-crumb:focus-visible {
|
|
2306
|
+
outline: 2px solid var(--gb-primary);
|
|
2307
|
+
outline-offset: -2px;
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
/* The sibling / hidden-segment menu. Portalled next to the docs root (so it isn't clipped by the
|
|
2311
|
+
viewer) and fixed under its trigger; --crumb-x / --crumb-y are set from the trigger's rect. */
|
|
2312
|
+
.docs-demo-crumb-menu {
|
|
2313
|
+
position: fixed;
|
|
2314
|
+
top: var(--crumb-y, 0);
|
|
2315
|
+
left: var(--crumb-x, 0);
|
|
2316
|
+
z-index: 60;
|
|
2317
|
+
box-sizing: border-box;
|
|
2318
|
+
min-width: 160px;
|
|
2319
|
+
max-width: min(320px, calc(100vw - 16px));
|
|
2320
|
+
max-height: min(320px, calc(100vh - 16px));
|
|
2321
|
+
padding: 4px;
|
|
2322
|
+
overflow-y: auto;
|
|
2323
|
+
border: 1px solid var(--gb-border);
|
|
2324
|
+
border-radius: 10px;
|
|
2325
|
+
background: var(--gb-panel);
|
|
2326
|
+
box-shadow: var(--gb-menu-shadow);
|
|
2327
|
+
color: var(--gb-panel-foreground);
|
|
2328
|
+
font: 12.5px/1.3 var(--docs-demo-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
2329
|
+
}
|
|
2330
|
+
|
|
2331
|
+
.docs-demo-crumb-option {
|
|
2332
|
+
display: flex;
|
|
2333
|
+
align-items: center;
|
|
2334
|
+
gap: 7px;
|
|
2335
|
+
box-sizing: border-box;
|
|
2336
|
+
width: 100%;
|
|
2337
|
+
padding: 6px 8px;
|
|
2338
|
+
border: 0;
|
|
2339
|
+
border-radius: 6px;
|
|
2340
|
+
background: none;
|
|
2341
|
+
color: inherit;
|
|
2342
|
+
font: inherit;
|
|
2343
|
+
text-align: left;
|
|
2344
|
+
cursor: pointer;
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
.docs-demo-crumb-option svg {
|
|
2348
|
+
flex-shrink: 0;
|
|
2349
|
+
color: var(--gb-muted-foreground);
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2352
|
+
.docs-demo-crumb-option:hover,
|
|
2353
|
+
.docs-demo-crumb-option:focus-visible {
|
|
2354
|
+
outline: none;
|
|
2355
|
+
background: var(--gb-hover);
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
.docs-demo-crumb-option[data-current] {
|
|
2359
|
+
color: var(--gb-primary);
|
|
2360
|
+
font-weight: 600;
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
.docs-demo-crumb-option[data-current] svg {
|
|
2364
|
+
color: var(--gb-primary);
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
.docs-demo-crumb-option-text {
|
|
2368
|
+
flex: 1;
|
|
2369
|
+
min-width: 0;
|
|
2370
|
+
overflow: hidden;
|
|
2371
|
+
text-overflow: ellipsis;
|
|
2372
|
+
white-space: nowrap;
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2375
|
+
.docs-demo-crumb-option .docs-demo-crumb-check {
|
|
2376
|
+
margin-left: auto;
|
|
2377
|
+
}
|
|
2378
|
+
|
|
2158
2379
|
.docs-demo-source-body {
|
|
2159
2380
|
flex: 1;
|
|
2160
2381
|
min-height: 0;
|
|
@@ -2195,7 +2416,8 @@
|
|
|
2195
2416
|
}
|
|
2196
2417
|
|
|
2197
2418
|
.docs-demo-files-h,
|
|
2198
|
-
.docs-demo-dir
|
|
2419
|
+
.docs-demo-dir,
|
|
2420
|
+
.docs-demo-files-handle {
|
|
2199
2421
|
display: none;
|
|
2200
2422
|
}
|
|
2201
2423
|
|
|
@@ -2338,6 +2560,8 @@
|
|
|
2338
2560
|
}
|
|
2339
2561
|
|
|
2340
2562
|
.docs-demo-handle::after,
|
|
2563
|
+
.docs-demo-files-handle::after,
|
|
2564
|
+
.docs-demo-crumb,
|
|
2341
2565
|
.docs-page-actions-more svg {
|
|
2342
2566
|
transition: none;
|
|
2343
2567
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brett_lamy/docstream",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "GitBook-aware readonly markdown and AI stream renderer.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -38,6 +38,20 @@
|
|
|
38
38
|
"import": "./dist/gitbook/index.js",
|
|
39
39
|
"default": "./dist/gitbook/index.js"
|
|
40
40
|
},
|
|
41
|
+
"./properties": {
|
|
42
|
+
"source": "./src/docs/DocumentProperties.tsx",
|
|
43
|
+
"types": "./dist/docs/DocumentProperties.d.ts",
|
|
44
|
+
"import": "./dist/docs/DocumentProperties.js",
|
|
45
|
+
"default": "./dist/docs/DocumentProperties.js"
|
|
46
|
+
},
|
|
47
|
+
"./properties/styles.css": "./dist/docs/properties.css",
|
|
48
|
+
"./tasks": {
|
|
49
|
+
"source": "./src/docs/TaskCheckbox.tsx",
|
|
50
|
+
"types": "./dist/docs/TaskCheckbox.d.ts",
|
|
51
|
+
"import": "./dist/docs/TaskCheckbox.js",
|
|
52
|
+
"default": "./dist/docs/TaskCheckbox.js"
|
|
53
|
+
},
|
|
54
|
+
"./tasks/styles.css": "./dist/docs/tasks.css",
|
|
41
55
|
"./streamdown": {
|
|
42
56
|
"source": "./src/streamdown.tsx",
|
|
43
57
|
"types": "./dist/streamdown.d.ts",
|
package/src/demo/DemoViewer.tsx
CHANGED
|
@@ -35,9 +35,10 @@ import { CollapsibleCode } from "../docs/CollapsibleCode"
|
|
|
35
35
|
import { HighlightedCode } from "../docs/HighlightedCode"
|
|
36
36
|
import { CopyButton } from "../docs/copy"
|
|
37
37
|
import { PillTabs, Segmented, rovingKeyDown } from "../docs/controls"
|
|
38
|
-
import { useDemoResolver, useDemoRuntime } from "./context"
|
|
38
|
+
import { DocstreamDemoContext, useDemoResolver, useDemoRuntime } from "./context"
|
|
39
39
|
import { createDocstreamClipboard, type DemoSourceSnapshot, type DocstreamClipboard } from "./clipboard"
|
|
40
40
|
import { CopyDemoButton } from "./copy-demo"
|
|
41
|
+
import { PathBreadcrumb } from "./PathBreadcrumb"
|
|
41
42
|
import { languageForPath } from "./glob"
|
|
42
43
|
import { useDemoVFSContext, useDemoVFSEntry, type DemoVFS } from "./vfs"
|
|
43
44
|
import { cssToSurface, surfaceStyle, surfaceToCss } from "./surface"
|
|
@@ -455,6 +456,22 @@ function fileTree(files: DemoFile[]): TreeRow[] {
|
|
|
455
456
|
return rows
|
|
456
457
|
}
|
|
457
458
|
|
|
459
|
+
export const FILES_DEFAULT_WIDTH = 188
|
|
460
|
+
export const FILES_MIN_WIDTH = 140
|
|
461
|
+
/** The file list never takes more than this share of the viewer, so the source pane can't collapse. */
|
|
462
|
+
export const FILES_MAX_SHARE = 0.6
|
|
463
|
+
|
|
464
|
+
/** The widest the file list may be inside a viewer `container` px wide (never below the minimum). */
|
|
465
|
+
export function filesMaxWidth(container: number): number {
|
|
466
|
+
return Math.max(FILES_MIN_WIDTH, Math.floor(container * FILES_MAX_SHARE))
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/** Clamp a file list width to [min, 60% of the viewer]. An unmeasured viewer (0) only enforces the minimum. */
|
|
470
|
+
export function clampFilesWidth(width: number, container: number): number {
|
|
471
|
+
const max = container > 0 ? filesMaxWidth(container) : Infinity
|
|
472
|
+
return Math.round(Math.min(max, Math.max(FILES_MIN_WIDTH, width)))
|
|
473
|
+
}
|
|
474
|
+
|
|
458
475
|
function CodeView({ src, files, height, id }: { src: string; files: DemoFile[]; height: string; id: string }) {
|
|
459
476
|
const [active, setActive] = useState(files[0]?.path ?? "")
|
|
460
477
|
useEffect(() => {
|
|
@@ -465,8 +482,67 @@ function CodeView({ src, files, height, id }: { src: string; files: DemoFile[];
|
|
|
465
482
|
const paths = files.map((f) => f.path)
|
|
466
483
|
const tabId = (path: string) => `${id}-file-${paths.indexOf(path)}`
|
|
467
484
|
const panelId = `${id}-source`
|
|
485
|
+
|
|
486
|
+
// The file list width is the user's choice (null: the default). It lives here, so it survives file switches.
|
|
487
|
+
const code = useRef<HTMLDivElement | null>(null)
|
|
488
|
+
const [chosen, setChosen] = useState<number | null>(null)
|
|
489
|
+
const [container, setContainer] = useState(0)
|
|
490
|
+
const [dragging, setDragging] = useState(false)
|
|
491
|
+
useEffect(() => {
|
|
492
|
+
const el = code.current
|
|
493
|
+
if (!el || typeof ResizeObserver === "undefined") return
|
|
494
|
+
const observer = new ResizeObserver(() => setContainer(Math.round(el.getBoundingClientRect().width)))
|
|
495
|
+
observer.observe(el)
|
|
496
|
+
return () => observer.disconnect()
|
|
497
|
+
}, [])
|
|
498
|
+
const width = clampFilesWidth(chosen ?? FILES_DEFAULT_WIDTH, container)
|
|
499
|
+
const max = container > 0 ? filesMaxWidth(container) : undefined
|
|
500
|
+
|
|
501
|
+
const startDrag = (event: ReactPointerEvent<HTMLDivElement>) => {
|
|
502
|
+
const el = code.current
|
|
503
|
+
if (!el || event.button !== 0) return
|
|
504
|
+
event.preventDefault()
|
|
505
|
+
const handle = event.currentTarget
|
|
506
|
+
const pointer = event.pointerId
|
|
507
|
+
try {
|
|
508
|
+
handle.setPointerCapture(pointer)
|
|
509
|
+
} catch {
|
|
510
|
+
/* not capturable (synthetic event): the window listeners still follow the drag */
|
|
511
|
+
}
|
|
512
|
+
const left = el.getBoundingClientRect().left
|
|
513
|
+
setDragging(true)
|
|
514
|
+
const move = (ev: PointerEvent) => setChosen(clampFilesWidth(ev.clientX - left, el.getBoundingClientRect().width))
|
|
515
|
+
const up = () => {
|
|
516
|
+
setDragging(false)
|
|
517
|
+
if (handle.hasPointerCapture?.(pointer)) handle.releasePointerCapture(pointer)
|
|
518
|
+
window.removeEventListener("pointermove", move)
|
|
519
|
+
window.removeEventListener("pointerup", up)
|
|
520
|
+
window.removeEventListener("pointercancel", up)
|
|
521
|
+
}
|
|
522
|
+
window.addEventListener("pointermove", move)
|
|
523
|
+
window.addEventListener("pointerup", up)
|
|
524
|
+
window.addEventListener("pointercancel", up)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const onResizeKey = (event: ReactKeyboardEvent<HTMLDivElement>) => {
|
|
528
|
+
const step = event.shiftKey ? 50 : 10
|
|
529
|
+
let next: number | undefined
|
|
530
|
+
if (event.key === "ArrowLeft") next = width - step
|
|
531
|
+
else if (event.key === "ArrowRight") next = width + step
|
|
532
|
+
else if (event.key === "Home") next = FILES_MIN_WIDTH
|
|
533
|
+
else if (event.key === "End") next = max ?? width
|
|
534
|
+
if (next === undefined) return
|
|
535
|
+
event.preventDefault()
|
|
536
|
+
setChosen(clampFilesWidth(next, container))
|
|
537
|
+
}
|
|
538
|
+
|
|
468
539
|
return (
|
|
469
|
-
<div
|
|
540
|
+
<div
|
|
541
|
+
ref={code}
|
|
542
|
+
className="docs-demo-code"
|
|
543
|
+
style={{ height, ...(chosen === null ? null : { "--docs-demo-files-w": `${width}px` }) } as CSSProperties}
|
|
544
|
+
data-dragging={dragging || undefined}
|
|
545
|
+
>
|
|
470
546
|
<div
|
|
471
547
|
className="docs-demo-files"
|
|
472
548
|
role="tablist"
|
|
@@ -502,9 +578,25 @@ function CodeView({ src, files, height, id }: { src: string; files: DemoFile[];
|
|
|
502
578
|
),
|
|
503
579
|
)}
|
|
504
580
|
</div>
|
|
581
|
+
<div
|
|
582
|
+
className="docs-demo-files-handle"
|
|
583
|
+
role="separator"
|
|
584
|
+
tabIndex={0}
|
|
585
|
+
aria-orientation="vertical"
|
|
586
|
+
aria-label="Resize file list"
|
|
587
|
+
aria-controls={panelId}
|
|
588
|
+
aria-valuemin={FILES_MIN_WIDTH}
|
|
589
|
+
aria-valuemax={max}
|
|
590
|
+
aria-valuenow={width}
|
|
591
|
+
aria-valuetext={`${width} pixels wide`}
|
|
592
|
+
data-dragging={dragging || undefined}
|
|
593
|
+
onPointerDown={startDrag}
|
|
594
|
+
onKeyDown={onResizeKey}
|
|
595
|
+
onDoubleClick={() => setChosen(null)}
|
|
596
|
+
/>
|
|
505
597
|
<div className="docs-demo-source" role="tabpanel" id={panelId} aria-labelledby={file ? tabId(file.path) : undefined}>
|
|
506
598
|
<div className="docs-demo-source-h">
|
|
507
|
-
|
|
599
|
+
{file ? <PathBreadcrumb src={src} path={file.path} paths={paths} onSelect={setActive} /> : <span className="docs-demo-crumbs" />}
|
|
508
600
|
{file ? <CopyButton text={file.content} label={`Copy ${file.path}`} /> : null}
|
|
509
601
|
</div>
|
|
510
602
|
<div className="docs-demo-source-body" tabIndex={0} aria-label={file ? `${file.path} source` : undefined}>
|
|
@@ -954,7 +1046,9 @@ export function DemoFullscreen({ src, resolver: override, variant, className, st
|
|
|
954
1046
|
if (!resolver) return <DemoError message={`No demo resolver for ${src}`} />
|
|
955
1047
|
return (
|
|
956
1048
|
<div className={className ? `docs-demo-fullscreen ${className}` : "docs-demo-fullscreen"} style={style} data-demo-src={src}>
|
|
957
|
-
<
|
|
1049
|
+
<DocstreamDemoContext.Provider value={resolver}>
|
|
1050
|
+
<DemoCanvas src={src} preview={{ kind: "component", component }} variant={chosen} bleed={metaValue?.bleed} look={metaValue} />
|
|
1051
|
+
</DocstreamDemoContext.Provider>
|
|
958
1052
|
</div>
|
|
959
1053
|
)
|
|
960
1054
|
}
|