duckfn-docs-kit 0.4.0 → 0.4.2

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/AGENTS.md CHANGED
@@ -73,8 +73,9 @@ is compiled.
73
73
  `extensions` for the extension the site documents.
74
74
  - **Errors are a result, not a broken block.** A failing statement renders its message in the result
75
75
  area and keeps whatever the reader typed.
76
- - **Every result has a tab strip** (even a plain table), and the fullscreen toggle lives at its right
77
- end. Table results bring sorting, resizable rows/columns, a right-click menu and header drag.
76
+ - **Every result has a tab strip** (even a plain table), and all of its result-wide chrome sits at the
77
+ strip's right end — see *The strip at the right of the tabs*. Table results bring sorting, resizable
78
+ rows/columns, a right-click menu and header drag.
78
79
 
79
80
  ### Result renderers
80
81
 
@@ -83,8 +84,8 @@ is compiled.
83
84
  | `table` | The result grid. | — |
84
85
  | `text` | A bare scalar, as one line. | A single column/row result. |
85
86
  | `html` / `iframe` | One tab per row; the markup goes into a sandboxed `iframe` (`srcdoc`), with a trailing `Table` tab that is always last. | `field` (unless the result has exactly one column). `tab_name` to label tabs. |
86
- | `svg` | The markup is spliced **into the page** (one tab per row, trailing `Table` tab). | Same as above. |
87
- | `mermaid` | The cell is handed to `<dfk-mermaid>`, so the reader gets a real diagram with zoom, fullscreen, source editing and SVG download. One tab per row, trailing `Table` tab. | Same as above. |
87
+ | `svg` | The markup is spliced **into the page** (one tab per row, trailing `Table` tab). Zoom and pan open in fullscreen, where the tab strip also offers **reset zoom** / **edit source**. | Same as above. |
88
+ | `mermaid` | The cell is handed to `<dfk-mermaid>`, which renders in its **embedded** mode: no frame of its own and no floating cluster — **reset zoom** and **edit source** join the result's tab strip instead. One tab per row, trailing `Table` tab. | Same as above. |
88
89
 
89
90
  Two facts worth knowing before you pick one:
90
91
 
@@ -95,6 +96,32 @@ Two facts worth knowing before you pick one:
95
96
  - `svg` shares the page, so anything that could execute or navigate — `script`, `foreignObject`,
96
97
  `on*` handlers, `javascript:` links — is stripped before insertion.
97
98
 
99
+ ### The strip at the right of the tabs
100
+
101
+ Every result — a plain table included — carries the same tab strip, and the right end of it is where
102
+ the result-wide controls live, in this order: **the active tab's own buttons**, **download**, then
103
+ the **fullscreen** toggle.
104
+
105
+ | Active tab | Controls |
106
+ | --- | --- |
107
+ | `Table` | Search, copy table, column-width mode, reset view, unfreeze columns |
108
+ | `svg` / `mermaid` | Reset zoom, edit source |
109
+ | `html` / `iframe` / `text` | — |
110
+
111
+ - Those table buttons are the "whole table" half of the grid's right-click menu, placed where they
112
+ cannot cover a cell; the menu itself keeps the per-cell items (copy this cell, wrap this
113
+ row/column, freeze up to this column). Freezing, column widths and the current view therefore
114
+ survive a switch to another tab and back. **Unfreeze columns** is hidden until a column has
115
+ actually been frozen, so it does not sit there as a dead control.
116
+ - **Search** opens as an input in the strip rather than floating over the cells it searches, because
117
+ the table spans the full width. It highlights every hit, shows `3/12`, and steps with the arrows;
118
+ it is per result, not shared between blocks.
119
+ - **Download** saves whatever the active tab shows, in that tab's format: `.csv` for a table, `.svg`
120
+ for `svg` / `mermaid`, `.html` for `html` / `iframe`, `.txt` for `text`. It is hidden only while
121
+ there is nothing to save yet (a figure that has not rendered).
122
+ - **Fullscreen** makes the result fill the viewport; the same button (now "Exit fullscreen") stays
123
+ put, and <kbd>Esc</kbd> works too. It is also the only place a figure zooms or pans.
124
+
98
125
  ### Examples
99
126
 
100
127
  A table result, and a scalar that degrades to text:
@@ -162,9 +189,9 @@ browser** (mermaid is a lazy `import()`, so a page with no diagram never downloa
162
189
  also install `@docusaurus/theme-mermaid` or list it in `themes`, and do not set `markdown.mermaid`:
163
190
  the kit's element replaces both, and two renderers on one page would fight.
164
191
 
165
- What the reader gets, in the element's top-right corner on hover: **reset zoom** (wheel zooms,
166
- dragging pans once zoomed), **fullscreen**, **edit the source** in a CodeMirror dialog, and
167
- **download SVG**.
192
+ What the reader gets, in the element's top-right corner on hover: **reset zoom**, **fullscreen**,
193
+ **edit the source** in a CodeMirror dialog, and **download SVG**. Zoom and pan are off until the
194
+ diagram is expanded — fullscreen is what turns the wheel into a zoom and a drag into a pan.
168
195
 
169
196
  - **The file is named after the section it sits in.** `1. Expansion.svg`, not
170
197
  `mermaid-diagram.svg`, in a cascade that walks from the most specific source to the most general:
@@ -173,10 +200,15 @@ dragging pans once zoomed), **fullscreen**, **edit the source** in a CodeMirror
173
200
  lives under; give it a frontmatter `title:` when the heading is not the name you want. The name
174
201
  goes through `filenamify`, so nothing a filesystem chokes on (`:`, `?`, `*`, `|`, …) reaches the
175
202
  file.
176
- - **The diagram is inert until it is zoomed.** At fit the pointer is the browser's: the cursor is
177
- the normal one (an I-beam over a label), and dragging selects text — the labels are still text,
178
- and copying one should work. Zooming in is what turns the pointer into a `grab` hand and gives a
179
- drag to panning; **Reset zoom** hands it back. There is no mode switch to remember.
203
+ - **The diagram on the page is a picture, not a viewport.** The cursor is the browser's (an I-beam
204
+ over a label), the wheel scrolls the page, and dragging selects text — labels are still text, and
205
+ copying one works. Expanding the diagram is what turns the pointer into a `grab` hand and gives a
206
+ drag to panning; **Reset zoom** returns it to fit without leaving fullscreen, and zooming is off
207
+ again the moment the diagram is back inline. There is no select/drag mode to remember.
208
+ - **A `show: "mermaid"` result reuses the same element**, in an *embedded* mode: the result panel
209
+ already draws the frame and the strip, so the element renders neither a frame nor a floating
210
+ cluster, and **reset zoom** / **edit source** move into the tab strip. See *The strip at the right
211
+ of the tabs*.
180
212
 
181
213
  - **The palette is a site choice, not a page one.** The kit's default is the `neo` look with
182
214
  `redux-color` / `redux-dark-color`; a site overrides it in its own config, which also keeps the
File without changes
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Saving something the kit rendered to a file: the payload shape, the click that
3
+ * performs the save, and how the file is named.
4
+ *
5
+ * Shared by `<dfk-mermaid>` (a downloaded diagram) and the SQL result chrome (a
6
+ * downloaded result of any kind), so a docs page has one definition of "what a
7
+ * download is" rather than one per component.
8
+ *
9
+ * This is browser-only code.
10
+ */
11
+ /** One file's worth of text, ready to save. */
12
+ export interface DownloadPayload {
13
+ /** The file name, extension included. */
14
+ name: string;
15
+ /** The blob's MIME type. */
16
+ mime: string;
17
+ /** The file's contents — text for every format the kit produces. */
18
+ text: string;
19
+ }
20
+ /**
21
+ * Saves a payload through a temporary object URL.
22
+ *
23
+ * The anchor is in the document for the click — some browsers ignore a detached
24
+ * one — and the URL is revoked on the next tick, once the download has been
25
+ * handed to the browser.
26
+ */
27
+ export declare function saveDownload(payload: DownloadPayload): void;
28
+ /**
29
+ * What a downloaded figure is called.
30
+ *
31
+ * The name is derived from the page, not from the figure: a diagram or an SVG
32
+ * result has no name of its own, and the reader downloading one is after "the
33
+ * figure from that section", not `diagram.svg`.
34
+ *
35
+ * Three sources, most specific first, each falling back to the next:
36
+ *
37
+ * 1. **The figure's own title** — mermaid's frontmatter (`---\ntitle: …\n---`,
38
+ * which mermaid itself draws above the diagram); only read when `options.source`
39
+ * is given.
40
+ * 2. **The nearest heading above it** — the section the figure belongs to, which
41
+ * on a docs page is what a reader would call it.
42
+ * 3. **The document title** — the browser tab's title, for a figure that sits
43
+ * above every heading on its page.
44
+ *
45
+ * Nothing found → `options.fallback` (or {@link DEFAULT_BASE}), with `extension`
46
+ * appended either way.
47
+ */
48
+ export declare function sectionFileName(element: Element, extension: string, options?: {
49
+ source?: string;
50
+ fallback?: string;
51
+ }): string;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as e, i as t, n, o as r, r as i, t as a } from "./register-Dev_kc3Z.js";
1
+ import { a as e, i as t, n, o as r, r as i, t as a } from "./register-wdwf0LC4.js";
2
2
  export { r as DfkFeatures, e as DfkHero, t as DfkMermaid, i as DfkNextSteps, n as DfkSql, a as registerDfkElements };
@@ -1,7 +1,25 @@
1
1
  import { HTMLElementBase } from '../dom';
2
+ import { type DownloadPayload } from '../download';
2
3
  export declare class DfkMermaid extends HTMLElementBase {
3
4
  #private;
4
5
  constructor();
6
+ /**
7
+ * The zoom/source controls an embedded diagram offers, for the host to place in
8
+ * its own chrome. Empty (and unused) when standalone — the element keeps them.
9
+ */
10
+ get actions(): HTMLElement;
5
11
  connectedCallback(): void;
6
12
  disconnectedCallback(): void;
13
+ /**
14
+ * Turns zoom/pan on or off for an embedded diagram. The host calls this with its
15
+ * own fullscreen state: an embedded diagram zooms exactly where its result area
16
+ * is expanded, and fills that area while it is.
17
+ */
18
+ setFullscreen(value: boolean): void;
19
+ /**
20
+ * The file this diagram would be saved as, or `null` while nothing is rendered.
21
+ * An embedded diagram hands this to the result chrome's download button, which
22
+ * is why the element does not save it itself.
23
+ */
24
+ downloadPayload(): DownloadPayload | null;
7
25
  }
@@ -68,8 +68,6 @@ export declare function watchColorMode(listener: () => void): () => void;
68
68
  * error instead of an empty box.
69
69
  */
70
70
  export declare function parseMermaidSvg(owner: Document, svg: string): SVGElement | null;
71
- /** The pan/zoom library, loaded once on first use (see `DfkMermaid`). */
72
- export declare function loadPanzoom(): Promise<typeof import('@panzoom/panzoom')['default']>;
73
71
  /**
74
72
  * Serialises a rendered diagram into standalone SVG markup.
75
73
  *
@@ -0,0 +1,17 @@
1
+ export declare class PanZoomView {
2
+ #private;
3
+ constructor(viewport: HTMLElement, content: HTMLElement);
4
+ /** Whether the figure is enlarged past its fit-to-box size. */
5
+ get zoomed(): boolean;
6
+ /** Replaces the figure on screen and returns the view to fit. */
7
+ setContent(node: Node | null): void;
8
+ /**
9
+ * Turns wheel zoom and dragging on or off. Activating loads panzoom on first
10
+ * use (a figure nobody zooms never pays for the chunk); deactivating leaves the
11
+ * view at fit, so the figure a reader returns to is the whole one.
12
+ */
13
+ setActive(active: boolean): void;
14
+ reset(): void;
15
+ /** Releases the panzoom instance and returns the viewport to its idle state. */
16
+ destroy(): void;
17
+ }