duckfn-docs-kit 0.3.0 → 0.4.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/AGENTS.md +294 -234
- package/README.md +10 -6
- package/dist/IconButton.d.ts +22 -0
- package/dist/codemirror.d.ts +29 -0
- package/dist/index.d.ts +28 -7
- package/dist/index.js +2 -2
- package/dist/mermaid/DfkMermaid.d.ts +7 -0
- package/dist/mermaid/config.d.ts +48 -0
- package/dist/mermaid/remark.d.ts +40 -0
- package/dist/mermaid/remark.js +32 -0
- package/dist/mermaid/render.d.ts +94 -0
- package/dist/mermaid/styles.d.ts +6 -0
- package/dist/mermaid/title.d.ts +23 -0
- package/dist/{register-CALCwFBv.js → register-Dev_kc3Z.js} +891 -558
- package/dist/remark.d.ts +1 -1
- package/dist/sql/client.js +1 -1
- package/dist/sql/remark.d.ts +6 -1
- package/dist/sql/renderers.d.ts +2 -0
- package/package.json +4 -1
- package/src/IconButton.ts +50 -0
- package/src/codemirror.ts +88 -0
- package/src/index.ts +31 -7
- package/src/mermaid/DfkMermaid.css +289 -0
- package/src/mermaid/DfkMermaid.ts +557 -0
- package/src/mermaid/config.ts +74 -0
- package/src/mermaid/remark.ts +98 -0
- package/src/mermaid/render.ts +178 -0
- package/src/mermaid/styles.ts +24 -0
- package/src/mermaid/title.ts +127 -0
- package/src/register.ts +3 -0
- package/src/remark.ts +1 -1
- package/src/sql/DfkSql.css +13 -10
- package/src/sql/DfkSql.ts +11 -46
- package/src/sql/remark.ts +6 -1
- package/src/sql/renderers.ts +24 -3
- package/src/sql/sql.css +13 -11
- package/dist/sql/editor.d.ts +0 -16
- package/src/sql/editor.ts +0 -75
package/dist/remark.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ import type { Plugin } from 'unified';
|
|
|
13
13
|
*/
|
|
14
14
|
export declare const DEFAULT_VERSION_PLACEHOLDER = "{{DUCKFN_VERSION}}";
|
|
15
15
|
export interface VersionPlaceholderOptions {
|
|
16
|
-
/** The real version string to substitute in, e.g. `0.0.
|
|
16
|
+
/** The real version string to substitute in, e.g. `0.0.17`. */
|
|
17
17
|
version: string;
|
|
18
18
|
/** Override the token if a site uses a different one. */
|
|
19
19
|
placeholder?: string;
|
package/dist/sql/client.js
CHANGED
package/dist/sql/remark.d.ts
CHANGED
|
@@ -34,8 +34,13 @@ export interface RunnableSqlConfig {
|
|
|
34
34
|
*
|
|
35
35
|
* `html` and `iframe` are the same renderer: both sandbox the markup in an
|
|
36
36
|
* iframe, so scripts run with an opaque origin.
|
|
37
|
+
*
|
|
38
|
+
* `mermaid` renders the column's mermaid source as a diagram through
|
|
39
|
+
* `<dfk-mermaid>` (the same element a ```mermaid fence produces), so the result
|
|
40
|
+
* gets the element's zoom, fullscreen, source editing and SVG download for
|
|
41
|
+
* free.
|
|
37
42
|
*/
|
|
38
|
-
show?: 'table' | 'html' | 'iframe' | 'svg' | 'text';
|
|
43
|
+
show?: 'table' | 'html' | 'iframe' | 'svg' | 'text' | 'mermaid';
|
|
39
44
|
/**
|
|
40
45
|
* What this block is expected to do when the docs' own SQL test suite runs it
|
|
41
46
|
* (`duckfn-docs-kit/sql/verify`). Defaults to `'ok'`; `'error'` marks a block
|
package/dist/sql/renderers.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import type { RunnableSqlConfig } from './remark';
|
|
|
5
5
|
*
|
|
6
6
|
* The registry is the seam later phases plug into. It ships `table` (VisActor
|
|
7
7
|
* VTable), a `text` fallback, the markup previews `iframe` / `html` / `svg`,
|
|
8
|
+
* `mermaid` (which hands the cell to the kit's own `<dfk-mermaid>` element, so a
|
|
9
|
+
* query can produce a diagram the reader can zoom, expand, edit and download),
|
|
8
10
|
* plus the `error` view every renderer shares.
|
|
9
11
|
*
|
|
10
12
|
* Heavy dependencies (`@visactor/vtable`) load through dynamic `import()`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "duckfn-docs-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Shared Docusaurus building blocks (TOC toggle, home-page web components, brand tokens, remark version placeholder) for duckfn-family extension docs sites.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -59,9 +59,12 @@
|
|
|
59
59
|
"@codemirror/state": "^6.7.6",
|
|
60
60
|
"@codemirror/view": "^6.43.13",
|
|
61
61
|
"@duckdb/duckdb-wasm": "1.33.1-dev64.0",
|
|
62
|
+
"@panzoom/panzoom": "^4.6.2",
|
|
62
63
|
"@visactor/vtable": "^1.26.8",
|
|
63
64
|
"codemirror": "^6.0.2",
|
|
65
|
+
"filenamify": "^7.0.3",
|
|
64
66
|
"iconify-icon": "^3.0.3",
|
|
67
|
+
"mermaid": "^12.0.0",
|
|
65
68
|
"playwright-core": "^1.63.0",
|
|
66
69
|
"sql-formatter": "^15.9.0"
|
|
67
70
|
},
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type {IconifyIconHTMLElement} from 'iconify-icon';
|
|
2
|
+
import {el} from './dom';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A compact icon-only button with a hover/focus tooltip, built once and then
|
|
6
|
+
* mutated. Shared by `<dfk-sql>`'s code-block cluster and `<dfk-mermaid>`'s
|
|
7
|
+
* diagram cluster: both want the same "floating icon row over content" idiom,
|
|
8
|
+
* and neither wants a second implementation of it.
|
|
9
|
+
*
|
|
10
|
+
* The tooltip is also the accessible name — an icon-only control has no text to
|
|
11
|
+
* fall back on. The two class names are written by this module and styled in
|
|
12
|
+
* *each* consumer's shadow-root CSS; that duplication is unavoidable (a shadow
|
|
13
|
+
* boundary stops one sheet from reaching the other tree), so the rules carry the
|
|
14
|
+
* same names and are kept in sync by hand.
|
|
15
|
+
*/
|
|
16
|
+
export class IconButton {
|
|
17
|
+
readonly root = el('button', {class: 'dfk-icon-button', type: 'button'});
|
|
18
|
+
readonly #icon: IconifyIconHTMLElement = el('iconify-icon', {
|
|
19
|
+
class: 'dfk-icon',
|
|
20
|
+
attrs: {'aria-hidden': 'true'},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
constructor(icon: string, onClick: () => void) {
|
|
24
|
+
this.root.appendChild(this.#icon);
|
|
25
|
+
this.root.addEventListener('click', onClick);
|
|
26
|
+
this.setIcon(icon);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
setIcon(icon: string): void {
|
|
30
|
+
this.#icon.setAttribute('icon', icon);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setLabel(text: string): void {
|
|
34
|
+
this.root.setAttribute('data-tip', text);
|
|
35
|
+
this.root.setAttribute('aria-label', text);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Marks a toggle as currently on (e.g. the SQL block's wrap toggle). */
|
|
39
|
+
setOn(on: boolean): void {
|
|
40
|
+
this.root.classList.toggle('dfk-icon-on', on);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
setDisabled(disabled: boolean): void {
|
|
44
|
+
if (disabled) {
|
|
45
|
+
this.root.setAttribute('disabled', '');
|
|
46
|
+
} else {
|
|
47
|
+
this.root.removeAttribute('disabled');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CodeMirror 6 editor behind the kit's editable content: the code view of a
|
|
3
|
+
* runnable SQL block (`<dfk-sql>`) and the diagram-source dialog of a
|
|
4
|
+
* `<dfk-mermaid>`. One implementation, two languages — the SQL block asks for
|
|
5
|
+
* highlighting, the diagram editor takes the plain-text default.
|
|
6
|
+
*
|
|
7
|
+
* Every CodeMirror module arrives through a dynamic `import()` inside
|
|
8
|
+
* {@link mountCodeEditor}: a page full of blocks pays nothing for the editor on
|
|
9
|
+
* its critical path, and Docusaurus' Node prerender never evaluates any of it.
|
|
10
|
+
*
|
|
11
|
+
* This is browser-only code: `document` is touched only through the container
|
|
12
|
+
* the caller hands over, and everything else is behind the `import()`s.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export interface CodeEditor {
|
|
16
|
+
getValue(): string;
|
|
17
|
+
setValue(value: string): void;
|
|
18
|
+
/** Soft-wraps long lines, or stops wrapping them (the block's wrap toggle). */
|
|
19
|
+
setWrap(wrapped: boolean): void;
|
|
20
|
+
destroy(): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface CodeEditorOptions {
|
|
24
|
+
/**
|
|
25
|
+
* Highlight the document as SQL. Omitted, the editor is plain text — which is
|
|
26
|
+
* what a mermaid diagram gets: there is no first-party CodeMirror language for
|
|
27
|
+
* it, and a docs reader is editing prose-shaped source, not writing SQL.
|
|
28
|
+
*/
|
|
29
|
+
language?: 'sql';
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function mountCodeEditor(
|
|
33
|
+
container: HTMLElement,
|
|
34
|
+
value: string,
|
|
35
|
+
onChange: (value: string) => void,
|
|
36
|
+
options: CodeEditorOptions = {},
|
|
37
|
+
): Promise<CodeEditor> {
|
|
38
|
+
const [{basicSetup}, {EditorView, keymap}, {defaultKeymap, historyKeymap}, {Compartment}] =
|
|
39
|
+
await Promise.all([
|
|
40
|
+
import('codemirror'),
|
|
41
|
+
import('@codemirror/view'),
|
|
42
|
+
import('@codemirror/commands'),
|
|
43
|
+
import('@codemirror/state'),
|
|
44
|
+
]);
|
|
45
|
+
// Loaded only for the blocks that ask for it, so a diagram editor does not pull
|
|
46
|
+
// the SQL grammar (and its lezer parsers) into the page.
|
|
47
|
+
const language =
|
|
48
|
+
options.language === 'sql' ? [(await import('@codemirror/lang-sql')).sql()] : [];
|
|
49
|
+
|
|
50
|
+
// Wrapping is toggled from the outside, and reconfiguring it must not disturb
|
|
51
|
+
// the document or the undo history — that is exactly what a compartment is
|
|
52
|
+
// for, so the extension is swapped in place rather than rebuilt.
|
|
53
|
+
const wrap = new Compartment();
|
|
54
|
+
|
|
55
|
+
const view = new EditorView({
|
|
56
|
+
doc: value,
|
|
57
|
+
extensions: [
|
|
58
|
+
basicSetup,
|
|
59
|
+
...language,
|
|
60
|
+
keymap.of([...defaultKeymap, ...historyKeymap]),
|
|
61
|
+
wrap.of([]),
|
|
62
|
+
EditorView.updateListener.of((update) => {
|
|
63
|
+
if (update.docChanged) {
|
|
64
|
+
onChange(update.state.doc.toString());
|
|
65
|
+
}
|
|
66
|
+
}),
|
|
67
|
+
],
|
|
68
|
+
parent: container,
|
|
69
|
+
// `root` is left to CodeMirror's own `getRoot(container)`. The container sits
|
|
70
|
+
// in the component's shadow root, so style-mod mounts the base theme into
|
|
71
|
+
// that same shadow root — exactly where the `.cm-*` rules are needed.
|
|
72
|
+
// Pinning it to `document` would put them outside the editor's tree instead,
|
|
73
|
+
// where a shadow boundary stops them.
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
getValue: () => view.state.doc.toString(),
|
|
78
|
+
setValue: (next: string) =>
|
|
79
|
+
view.dispatch({
|
|
80
|
+
changes: {from: 0, to: view.state.doc.length, insert: next},
|
|
81
|
+
}),
|
|
82
|
+
setWrap: (wrapped: boolean) =>
|
|
83
|
+
view.dispatch({
|
|
84
|
+
effects: wrap.reconfigure(wrapped ? EditorView.lineWrapping : []),
|
|
85
|
+
}),
|
|
86
|
+
destroy: () => view.destroy(),
|
|
87
|
+
};
|
|
88
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import type {HTMLAttributes} from 'react';
|
|
2
|
+
// Imported as well as re-exported: the `HTMLElementTagNameMap` augmentation below
|
|
3
|
+
// names the classes, and a module augmentation can only refer to local bindings.
|
|
4
|
+
import {DfkFeatures} from './home/DfkFeatures';
|
|
5
|
+
import {DfkHero} from './home/DfkHero';
|
|
6
|
+
import {DfkMermaid} from './mermaid/DfkMermaid';
|
|
7
|
+
import {DfkNextSteps} from './home/DfkNextSteps';
|
|
8
|
+
import {DfkSql} from './sql/DfkSql';
|
|
2
9
|
|
|
3
10
|
/**
|
|
4
|
-
* Browser entry for duckfn-docs-kit: the
|
|
11
|
+
* Browser entry for duckfn-docs-kit: the custom elements it registers and the
|
|
5
12
|
* value types their `set*` methods accept.
|
|
6
13
|
*
|
|
7
14
|
* The components are retained-mode (build once, then mutate held nodes) and
|
|
@@ -13,17 +20,16 @@ import type {HTMLAttributes} from 'react';
|
|
|
13
20
|
* web component, which `registerDfkElements()` registers as a side effect, so
|
|
14
21
|
* this package ships no icon data.
|
|
15
22
|
*
|
|
16
|
-
* `TocToggle` and the remark
|
|
17
|
-
* (`duckfn-docs-kit/toc-toggle/TocToggle`, `duckfn-docs-kit/remark
|
|
23
|
+
* `TocToggle` and the remark plugins keep their own subpaths
|
|
24
|
+
* (`duckfn-docs-kit/toc-toggle/TocToggle`, `duckfn-docs-kit/remark`,
|
|
25
|
+
* `duckfn-docs-kit/sql/remark`, `duckfn-docs-kit/mermaid/remark`) instead of
|
|
18
26
|
* being merged here: a Docusaurus config file must never pull browser code into
|
|
19
27
|
* Node, and a site that only wants the TOC collapse button should not pay for
|
|
20
28
|
* the bundled `iconify-icon`.
|
|
21
29
|
*/
|
|
22
|
-
export {DfkFeatures
|
|
23
|
-
export {DfkHero} from './home/DfkHero';
|
|
24
|
-
export {DfkNextSteps} from './home/DfkNextSteps';
|
|
25
|
-
export {DfkSql} from './sql/DfkSql';
|
|
30
|
+
export {DfkFeatures, DfkHero, DfkMermaid, DfkNextSteps, DfkSql};
|
|
26
31
|
export {registerDfkElements} from './register';
|
|
32
|
+
export type {DfkMermaidConfig, DfkMermaidConfigInput} from './mermaid/config';
|
|
27
33
|
export type {RunnableSqlConfig} from './sql/remark';
|
|
28
34
|
export type {
|
|
29
35
|
FeatureItem,
|
|
@@ -47,6 +53,23 @@ export type {
|
|
|
47
53
|
*/
|
|
48
54
|
export type DfkElementProps = HTMLAttributes<HTMLElement>;
|
|
49
55
|
|
|
56
|
+
/**
|
|
57
|
+
* The kit's tags in the DOM's own tag map, so `document.createElement('dfk-sql')`
|
|
58
|
+
* (and the kit's `el()` helper) is typed as the class it upgrades to. Without
|
|
59
|
+
* this, every place that builds a `dfk-*` element from scratch — `sql/renderers.ts`
|
|
60
|
+
* building a `<dfk-mermaid>` for a `mermaid` result, `docs/src/pages/index.tsx`
|
|
61
|
+
* mounting the home elements — would have to cast the result.
|
|
62
|
+
*/
|
|
63
|
+
declare global {
|
|
64
|
+
interface HTMLElementTagNameMap {
|
|
65
|
+
'dfk-hero': DfkHero;
|
|
66
|
+
'dfk-features': DfkFeatures;
|
|
67
|
+
'dfk-next-steps': DfkNextSteps;
|
|
68
|
+
'dfk-sql': DfkSql;
|
|
69
|
+
'dfk-mermaid': DfkMermaid;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
50
73
|
declare module 'react' {
|
|
51
74
|
namespace JSX {
|
|
52
75
|
interface IntrinsicElements {
|
|
@@ -54,6 +77,7 @@ declare module 'react' {
|
|
|
54
77
|
'dfk-features': DfkElementProps;
|
|
55
78
|
'dfk-next-steps': DfkElementProps;
|
|
56
79
|
'dfk-sql': DfkElementProps;
|
|
80
|
+
'dfk-mermaid': DfkElementProps;
|
|
57
81
|
}
|
|
58
82
|
}
|
|
59
83
|
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/* Shadow-root styles for `<dfk-mermaid>`: the diagram viewport, the action
|
|
2
|
+
cluster floating in its top-right corner, and the source-editing dialog.
|
|
3
|
+
|
|
4
|
+
Theme colours arrive through the inherited `--ifm-*` custom properties;
|
|
5
|
+
box-sizing must be re-declared here because the host page's universal reset
|
|
6
|
+
does not cross the shadow boundary. */
|
|
7
|
+
|
|
8
|
+
*,
|
|
9
|
+
*::before,
|
|
10
|
+
*::after {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
:host {
|
|
15
|
+
display: block;
|
|
16
|
+
margin: 1rem 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.dfk-mermaid-canvas {
|
|
20
|
+
position: relative;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* The zoom/pan viewport. Panzoom transforms `.dfk-mermaid-content` *inside* this
|
|
24
|
+
box, so the overflow stays clipped here rather than spilling over the page —
|
|
25
|
+
`overflow: hidden` is also what panzoom expects of a pan element's parent. */
|
|
26
|
+
.dfk-mermaid-viewport {
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
border: 1px solid var(--ifm-global-border-color, #e0e0e0);
|
|
29
|
+
border-radius: var(--ifm-global-radius, 0.4rem);
|
|
30
|
+
background: var(--ifm-background-surface-color, #fff);
|
|
31
|
+
padding: 0.75rem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Mermaid sizes its own `<svg>` (`width="100%"` plus an inline `max-width`), so
|
|
35
|
+
nothing here fights that: the rules only centre it once the inline cap kicks
|
|
36
|
+
in, and give it a line box so the viewport has a height. */
|
|
37
|
+
.dfk-mermaid-content > svg {
|
|
38
|
+
display: block;
|
|
39
|
+
margin: 0 auto;
|
|
40
|
+
max-width: 100%;
|
|
41
|
+
height: auto;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* --- Cursor -------------------------------------------------------------- */
|
|
45
|
+
|
|
46
|
+
/* The cursor says what a drag will actually do, which is why it is driven by the
|
|
47
|
+
zoom state rather than set on the element once and for all (panzoom's `cursor`
|
|
48
|
+
option does the latter, and it was promising a pan at fit — over text that is
|
|
49
|
+
perfectly selectable). `cursor` is inherited, so these two rules reach the
|
|
50
|
+
diagram and every label in it; the buttons override it with `pointer`. */
|
|
51
|
+
.dfk-mermaid-canvas.dfk-mermaid-zoomed {
|
|
52
|
+
cursor: grab;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.dfk-mermaid-canvas.dfk-mermaid-zoomed.dfk-mermaid-grabbing {
|
|
56
|
+
cursor: grabbing;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* --- Status line --------------------------------------------------------- */
|
|
60
|
+
|
|
61
|
+
/* Doubles as the "still rendering" placeholder: the mermaid bundle is a lazy
|
|
62
|
+
`import()`, and this line is what the reader sees while it lands (or the error
|
|
63
|
+
message, if the source does not parse). It is the component's only
|
|
64
|
+
pre-render content — a diagram's height is unknowable before it renders, so
|
|
65
|
+
the alternative would be inventing a placeholder height that is wrong for
|
|
66
|
+
every diagram but one. */
|
|
67
|
+
.dfk-mermaid-message {
|
|
68
|
+
margin: 0.5rem 0 0;
|
|
69
|
+
font-size: 0.8rem;
|
|
70
|
+
color: var(--ifm-color-emphasis-700, #666);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.dfk-mermaid-message:empty {
|
|
74
|
+
display: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.dfk-mermaid-message-error {
|
|
78
|
+
padding: 0.5rem 0.75rem;
|
|
79
|
+
border-radius: var(--ifm-global-radius, 0.25rem);
|
|
80
|
+
color: var(--ifm-color-danger-contrast, #fff);
|
|
81
|
+
background: var(--ifm-color-danger, #d32f2f);
|
|
82
|
+
font-family: var(--ifm-font-family-monospace, ui-monospace, SFMono-Regular,
|
|
83
|
+
Menlo, monospace);
|
|
84
|
+
font-size: var(--ifm-code-font-size, 95%);
|
|
85
|
+
white-space: pre-wrap;
|
|
86
|
+
word-break: break-word;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.dfk-mermaid-canvas[hidden],
|
|
90
|
+
.dfk-mermaid-message[hidden] {
|
|
91
|
+
display: none;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* --- Floating actions ---------------------------------------------------- */
|
|
95
|
+
|
|
96
|
+
/* Hover/focus-revealed, like the buttons on Docusaurus' own code blocks and the
|
|
97
|
+
ones on a runnable SQL block. The cluster is inert while hidden so an
|
|
98
|
+
invisible button is never a click target over the diagram. */
|
|
99
|
+
.dfk-mermaid-actions {
|
|
100
|
+
position: absolute;
|
|
101
|
+
top: 0.25rem;
|
|
102
|
+
right: 0.25rem;
|
|
103
|
+
z-index: 2;
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
gap: 0.15rem;
|
|
107
|
+
padding: 0.1rem 0.2rem;
|
|
108
|
+
border-radius: var(--ifm-global-radius, 0.3rem);
|
|
109
|
+
background: var(--ifm-color-emphasis-100, #f5f5f5);
|
|
110
|
+
opacity: 0;
|
|
111
|
+
pointer-events: none;
|
|
112
|
+
transition: opacity 0.12s ease;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.dfk-mermaid-canvas:hover .dfk-mermaid-actions,
|
|
116
|
+
.dfk-mermaid-canvas:focus-within .dfk-mermaid-actions {
|
|
117
|
+
opacity: 1;
|
|
118
|
+
pointer-events: auto;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* --- Icon buttons and their tooltips ------------------------------------- */
|
|
122
|
+
|
|
123
|
+
/* The class names are written by the shared `IconButton` widget
|
|
124
|
+
(`src/IconButton.ts`); the same rules live in `DfkSql.css` and `sql.css`,
|
|
125
|
+
once per shadow tree they have to reach. Keep the copies in sync. */
|
|
126
|
+
.dfk-icon-button {
|
|
127
|
+
position: relative;
|
|
128
|
+
display: inline-flex;
|
|
129
|
+
align-items: center;
|
|
130
|
+
justify-content: center;
|
|
131
|
+
width: 1.6rem;
|
|
132
|
+
height: 1.6rem;
|
|
133
|
+
padding: 0;
|
|
134
|
+
border: none;
|
|
135
|
+
border-radius: var(--ifm-global-radius, 0.25rem);
|
|
136
|
+
background: transparent;
|
|
137
|
+
color: var(--ifm-color-emphasis-700, #666);
|
|
138
|
+
cursor: pointer;
|
|
139
|
+
transition: background 0.12s ease, color 0.12s ease;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.dfk-icon-button:hover:not(:disabled),
|
|
143
|
+
.dfk-icon-button:focus-visible {
|
|
144
|
+
background: var(--ifm-color-emphasis-200, #e6e6e6);
|
|
145
|
+
color: var(--ifm-color-primary, #14459b);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.dfk-icon-button:disabled {
|
|
149
|
+
opacity: 0.45;
|
|
150
|
+
cursor: progress;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.dfk-icon-button[hidden] {
|
|
154
|
+
display: none;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.dfk-icon {
|
|
158
|
+
font-size: 1rem;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
[data-tip]::after {
|
|
162
|
+
content: attr(data-tip);
|
|
163
|
+
position: absolute;
|
|
164
|
+
top: calc(100% + 0.3rem);
|
|
165
|
+
right: 0;
|
|
166
|
+
z-index: 2;
|
|
167
|
+
padding: 0.15rem 0.4rem;
|
|
168
|
+
border-radius: var(--ifm-global-radius, 0.25rem);
|
|
169
|
+
background: var(--ifm-color-emphasis-800, #333);
|
|
170
|
+
color: var(--ifm-color-emphasis-0, #fff);
|
|
171
|
+
font-size: 0.7rem;
|
|
172
|
+
line-height: 1.4;
|
|
173
|
+
white-space: nowrap;
|
|
174
|
+
opacity: 0;
|
|
175
|
+
pointer-events: none;
|
|
176
|
+
transition: opacity 0.12s ease;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
[data-tip]:hover::after,
|
|
180
|
+
[data-tip]:focus-visible::after {
|
|
181
|
+
opacity: 1;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* --- Fullscreen ---------------------------------------------------------- */
|
|
185
|
+
|
|
186
|
+
/* The whole canvas becomes a fixed overlay. `z-index` has to clear Docusaurus'
|
|
187
|
+
navbar and its own overlays. The background must be the *surface* colour, not
|
|
188
|
+
`--ifm-background-color`: a site may legitimately define the latter as
|
|
189
|
+
`transparent` (this repository's docs site does), which would leave the
|
|
190
|
+
overlay see-through with the page showing underneath. */
|
|
191
|
+
.dfk-mermaid-expanded {
|
|
192
|
+
position: fixed;
|
|
193
|
+
inset: 0;
|
|
194
|
+
z-index: 2147483000;
|
|
195
|
+
display: flex;
|
|
196
|
+
flex-direction: column;
|
|
197
|
+
background: var(--ifm-background-surface-color, #fff);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.dfk-mermaid-expanded .dfk-mermaid-viewport {
|
|
201
|
+
flex: 1;
|
|
202
|
+
border: none;
|
|
203
|
+
border-radius: 0;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* --- Source dialog ------------------------------------------------------- */
|
|
207
|
+
|
|
208
|
+
.dfk-mermaid-dialog {
|
|
209
|
+
width: min(56rem, 92vw);
|
|
210
|
+
max-width: none;
|
|
211
|
+
padding: 0;
|
|
212
|
+
border: 1px solid var(--ifm-global-border-color, #e0e0e0);
|
|
213
|
+
border-radius: var(--ifm-global-radius, 0.4rem);
|
|
214
|
+
background: var(--ifm-background-surface-color, #fff);
|
|
215
|
+
color: var(--ifm-font-color-base, #181818);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.dfk-mermaid-dialog::backdrop {
|
|
219
|
+
background: rgb(0 0 0 / 45%);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.dfk-mermaid-dialog-body {
|
|
223
|
+
display: flex;
|
|
224
|
+
flex-direction: column;
|
|
225
|
+
gap: 0.5rem;
|
|
226
|
+
padding: 0.75rem;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.dfk-mermaid-dialog-title {
|
|
230
|
+
margin: 0;
|
|
231
|
+
font-size: 0.95rem;
|
|
232
|
+
font-weight: 600;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* CodeMirror mounts here, inside the shadow tree, so style-mod puts its base
|
|
236
|
+
theme in the same root the `.cm-*` rules are needed in (`src/codemirror.ts`).
|
|
237
|
+
The content inset is CodeMirror's own (`padding: 4px 0`) and is left alone —
|
|
238
|
+
see the note in `DfkSql.css` about `ViewState.measure()`. */
|
|
239
|
+
.dfk-mermaid-dialog-editor {
|
|
240
|
+
border: 1px solid var(--ifm-global-border-color, #e0e0e0);
|
|
241
|
+
border-radius: var(--ifm-global-radius, 0.4rem);
|
|
242
|
+
overflow: hidden;
|
|
243
|
+
background: var(--ifm-background-surface-color, #fff);
|
|
244
|
+
font-size: var(--ifm-code-font-size, 95%);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.dfk-mermaid-dialog-editor .cm-editor {
|
|
248
|
+
outline: none;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.dfk-mermaid-dialog-editor .cm-scroller {
|
|
252
|
+
max-height: 55vh;
|
|
253
|
+
font-family: var(--ifm-font-family-monospace, ui-monospace, SFMono-Regular,
|
|
254
|
+
Menlo, monospace);
|
|
255
|
+
line-height: 1.6;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.dfk-mermaid-dialog-footer {
|
|
259
|
+
display: flex;
|
|
260
|
+
justify-content: flex-end;
|
|
261
|
+
gap: 0.5rem;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.dfk-mermaid-dialog-button {
|
|
265
|
+
padding: 0.3rem 0.9rem;
|
|
266
|
+
border: 1px solid var(--ifm-global-border-color, #e0e0e0);
|
|
267
|
+
border-radius: var(--ifm-global-radius, 0.25rem);
|
|
268
|
+
background: var(--ifm-background-surface-color, #fff);
|
|
269
|
+
color: var(--ifm-font-color-base, #181818);
|
|
270
|
+
font-family: inherit;
|
|
271
|
+
font-size: 0.85rem;
|
|
272
|
+
cursor: pointer;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.dfk-mermaid-dialog-button:hover {
|
|
276
|
+
border-color: var(--ifm-color-primary, #14459b);
|
|
277
|
+
color: var(--ifm-color-primary, #14459b);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.dfk-mermaid-dialog-apply {
|
|
281
|
+
border-color: var(--ifm-color-primary, #14459b);
|
|
282
|
+
background: var(--ifm-color-primary, #14459b);
|
|
283
|
+
color: var(--ifm-button-color, #fff);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.dfk-mermaid-dialog-apply:hover {
|
|
287
|
+
color: var(--ifm-button-color, #fff);
|
|
288
|
+
filter: brightness(1.1);
|
|
289
|
+
}
|