duckfn-docs-kit 0.1.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.
Files changed (65) hide show
  1. package/AGENTS.md +689 -0
  2. package/LICENSE +21 -0
  3. package/README.md +107 -0
  4. package/dist/dom.d.ts +69 -0
  5. package/dist/home/DfkFeatures.d.ts +20 -0
  6. package/dist/home/DfkHero.d.ts +25 -0
  7. package/dist/home/DfkNextSteps.d.ts +16 -0
  8. package/dist/home/styles.d.ts +8 -0
  9. package/dist/index.d.ts +50 -0
  10. package/dist/index.js +2 -0
  11. package/dist/register-DKLiYs-F.js +2324 -0
  12. package/dist/register.d.ts +10 -0
  13. package/dist/remark.d.ts +21 -0
  14. package/dist/remark.js +15 -0
  15. package/dist/runtimeConfig-Bokbb8VH.js +106 -0
  16. package/dist/sql/DfkSql.d.ts +7 -0
  17. package/dist/sql/PreviewTabs.d.ts +37 -0
  18. package/dist/sql/client.d.ts +1 -0
  19. package/dist/sql/client.js +4 -0
  20. package/dist/sql/editor.d.ts +16 -0
  21. package/dist/sql/extensions.d.ts +108 -0
  22. package/dist/sql/extensions.js +198 -0
  23. package/dist/sql/remark.d.ts +88 -0
  24. package/dist/sql/remark.js +69 -0
  25. package/dist/sql/renderers.d.ts +44 -0
  26. package/dist/sql/runtime.d.ts +105 -0
  27. package/dist/sql/runtimeConfig.d.ts +80 -0
  28. package/dist/sql/styles.d.ts +6 -0
  29. package/dist/toc-toggle/TocToggle.d.ts +46 -0
  30. package/dist/toc-toggle/TocToggle.js +69 -0
  31. package/dist/toc-toggle/client.d.ts +1 -0
  32. package/dist/toc-toggle/client.js +9 -0
  33. package/dist/toc-toggle/plugin.d.ts +36 -0
  34. package/dist/toc-toggle/plugin.js +13 -0
  35. package/dist/types.d.ts +42 -0
  36. package/package.json +73 -0
  37. package/src/dom.ts +109 -0
  38. package/src/home/DfkFeatures.ts +78 -0
  39. package/src/home/DfkHero.ts +128 -0
  40. package/src/home/DfkNextSteps.ts +73 -0
  41. package/src/home/home.css +520 -0
  42. package/src/home/styles.ts +28 -0
  43. package/src/index.ts +59 -0
  44. package/src/kit.css +19 -0
  45. package/src/register.ts +39 -0
  46. package/src/remark.ts +60 -0
  47. package/src/sql/DfkSql.css +226 -0
  48. package/src/sql/DfkSql.ts +620 -0
  49. package/src/sql/PreviewTabs.ts +169 -0
  50. package/src/sql/client.ts +16 -0
  51. package/src/sql/editor.ts +75 -0
  52. package/src/sql/extensions.ts +470 -0
  53. package/src/sql/remark.ts +213 -0
  54. package/src/sql/renderers.ts +916 -0
  55. package/src/sql/runtime.ts +348 -0
  56. package/src/sql/runtimeConfig.ts +249 -0
  57. package/src/sql/sql.css +397 -0
  58. package/src/sql/styles.ts +24 -0
  59. package/src/theme/tokens.css +75 -0
  60. package/src/toc-toggle/TocToggle.css +69 -0
  61. package/src/toc-toggle/TocToggle.ts +172 -0
  62. package/src/toc-toggle/client.ts +20 -0
  63. package/src/toc-toggle/plugin.ts +54 -0
  64. package/src/types.ts +47 -0
  65. package/src/vite-env.d.ts +8 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 shijianjs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # duckfn-docs-kit
2
+
3
+ Shared building blocks for [duckfn](https://github.com/shijianjs/duckfn)-family
4
+ DuckDB extension documentation sites: runnable SQL blocks, extension preloading,
5
+ a TOC collapse control, the home-page web components and the version-placeholder
6
+ remark plugin. Each one is a self-contained entry point that a Docusaurus 3 site
7
+ wires into its own config — the alternative is copying the same glue into every
8
+ extension's docs site.
9
+
10
+ Plain TypeScript over the native DOM: no React and no UI framework of its own.
11
+ The components are retained-mode classes — they build their DOM once, expose
12
+ named domain setters and render into shadow roots, so a site's global CSS and the
13
+ kit's never leak into each other.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install duckfn-docs-kit
19
+ ```
20
+
21
+ ## Entry points
22
+
23
+ | Import | Runs in | What it provides |
24
+ | --- | --- | --- |
25
+ | `duckfn-docs-kit` | browser | Home-page custom elements (`<dfk-hero>`, `<dfk-features>`, `<dfk-next-steps>`, `<dfk-sql>`), `registerDfkElements()` and the value types their setters accept |
26
+ | `duckfn-docs-kit/remark` | Node (build) | `remarkVersionPlaceholder`: replaces `{{DUCKFN_VERSION}}` inside `text` / `inlineCode` / `code` nodes |
27
+ | `duckfn-docs-kit/sql/remark` | Node (build) | `remarkRunnableSql`: turns fenced `sql run` blocks into `<dfk-sql>` elements |
28
+ | `duckfn-docs-kit/sql/extensions` | Node (build) | `dfkExtensions()` Docusaurus plugin: preloads a site's DuckDB extensions before the first block runs |
29
+ | `duckfn-docs-kit/toc-toggle/plugin` | Node (build) | `dfkTocToggle()` Docusaurus plugin: adds the TOC collapse control |
30
+ | `duckfn-docs-kit/toc-toggle/TocToggle` | browser | The TOC collapse class, for a site that drives it itself |
31
+ | `duckfn-docs-kit/src/kit.css` | CSS | Brand tokens plus the styles a shadow boundary cannot host |
32
+
33
+ The two plugins inject their own browser glue (`dfk-*` element registration and
34
+ the TOC toggle) on every page, so a site needs no `clientModules` file of its
35
+ own. `duckfn-docs-kit/sql/client` and `duckfn-docs-kit/toc-toggle/client` are
36
+ that glue — plugins use them, sites should not import them directly.
37
+
38
+ ## Wiring it up
39
+
40
+ ```ts
41
+ // docusaurus.config.ts
42
+ import {dfkExtensions} from 'duckfn-docs-kit/sql/extensions';
43
+ import {dfkTocToggle} from 'duckfn-docs-kit/toc-toggle/plugin';
44
+ import {remarkVersionPlaceholder} from 'duckfn-docs-kit/remark';
45
+ import {remarkRunnableSql} from 'duckfn-docs-kit/sql/remark';
46
+ import {DUCKFN_VERSION} from './duckfn-version';
47
+
48
+ export default {
49
+ presets: [
50
+ [
51
+ 'classic',
52
+ {
53
+ docs: {
54
+ remarkPlugins: [
55
+ [remarkVersionPlaceholder, {version: DUCKFN_VERSION}],
56
+ remarkRunnableSql,
57
+ ],
58
+ },
59
+ },
60
+ ],
61
+ ],
62
+ plugins: [
63
+ dfkExtensions({
64
+ allowUnsignedExtensions: true,
65
+ preload: [
66
+ {
67
+ url: 'duckdb-extensions/duckfn.duckdb_extension.wasm',
68
+ release: {
69
+ repository: 'shijianjs/duckfn',
70
+ asset: 'duckfn-wasm_eh.duckdb_extension.wasm',
71
+ },
72
+ },
73
+ ],
74
+ }),
75
+ dfkTocToggle(),
76
+ ],
77
+ };
78
+ ```
79
+
80
+ The global CSS is a single import in the site's own stylesheet:
81
+
82
+ ```css
83
+ /* src/css/custom.css */
84
+ @import 'duckfn-docs-kit/src/kit.css';
85
+ ```
86
+
87
+ `kit.css` aggregates the `--duckfn-*` brand tokens and the styles a shadow
88
+ boundary cannot host (the TOC toggle). The `dfk-*` components carry their own
89
+ styles inside the JS bundle, so they need nothing here.
90
+
91
+ ## Requirements
92
+
93
+ - Node ≥ 20 and Docusaurus 3.x.
94
+ - `@duckdb/duckdb-wasm` is pinned to an exact version because the WebAssembly
95
+ extensions a site loads have to stay ABI-compatible with the DuckDB build
96
+ inside the wasm bundle. Keep the pin and the extension build in lockstep.
97
+
98
+ ## Documentation
99
+
100
+ The user guide lives at <https://shijianjs.github.io/duckfn/docs/docs-kit>. The
101
+ conventions this package is written to — retained-mode components, shadow DOM,
102
+ SSR safety, the SQL rendering contract — are documented in
103
+ [`AGENTS.md`](./AGENTS.md), which ships inside the package.
104
+
105
+ ## License
106
+
107
+ MIT
package/dist/dom.d.ts ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * DOM helpers shared by the custom elements.
3
+ *
4
+ * `HTMLElementBase` is the whole reason this module exists: the element classes
5
+ * `extend` it, but Docusaurus imports this package into Node during static
6
+ * prerendering, where the global `HTMLElement` does not exist and evaluating
7
+ * `class X extends HTMLElement` would throw. Falling back to an empty base
8
+ * class keeps module evaluation safe on the server; the real `HTMLElement` is
9
+ * picked up in the browser, where the elements are actually defined and run.
10
+ */
11
+ export declare const HTMLElementBase: typeof HTMLElement;
12
+ /**
13
+ * The tag's props that hold a value `el()` can assign as-is — `href`, `src`,
14
+ * `alt`, `width`, `hidden`, and so on.
15
+ *
16
+ * Methods and object-valued props are filtered out, so an options bag can never
17
+ * carry `appendChild`, `style`, `dataset` or `classList`. Getter-only props
18
+ * (`origin`, `clientWidth`) do pass the filter; assigning one throws in strict
19
+ * mode, which is loud enough to be caught the first time it runs.
20
+ */
21
+ type ValueProps<T> = {
22
+ [P in keyof T as T[P] extends Function ? never : T[P] extends object ? never : P]?: T[P];
23
+ };
24
+ /**
25
+ * Options for `el()`: the tag's own props, narrowed to that tag, plus two
26
+ * shorthands and the attribute escape hatch.
27
+ */
28
+ export type ElOptions<T extends Element> = ValueProps<T> & {
29
+ /** Shorthand for `className`. */
30
+ class?: string;
31
+ /** Shorthand for `textContent`. */
32
+ text?: string;
33
+ /**
34
+ * Attributes that have no matching prop: `aria-*`, `data-*`, and
35
+ * custom-element attributes. Everything else goes through a property, so a
36
+ * boolean or a number keeps its real type instead of being stringified.
37
+ */
38
+ attrs?: Record<string, string>;
39
+ };
40
+ /**
41
+ * `document.createElement` with per-tag typed options and an optional `init`
42
+ * callback.
43
+ *
44
+ * The one sanctioned way to build nodes in this package: it returns a live
45
+ * element (held in a class field by the caller), never an HTML string.
46
+ *
47
+ * The options are narrowed to the tag, so a typo, a wrong value type, a method
48
+ * name or an object-valued prop is a compile error:
49
+ *
50
+ * ```ts
51
+ * el('img', {class: 'dfk-logo', alt: '', width: 480});
52
+ * ```
53
+ *
54
+ * `init` describes a subtree in place, for structure that is never referenced
55
+ * again and therefore needs no field:
56
+ *
57
+ * ```ts
58
+ * this.root.append(
59
+ * el('span', {class: 'dfk-next-card-body'}, (body) => body.append(this.#title, this.#details)),
60
+ * this.#arrow,
61
+ * );
62
+ * ```
63
+ *
64
+ * Nodes touched later stay in fields. A field initializer must not read a
65
+ * `#field` declared below it (initializers run in declaration order, so that is
66
+ * a TDZ error) — pass `init` from the constructor, where every field is ready.
67
+ */
68
+ export declare function el<K extends keyof HTMLElementTagNameMap>(tag: K, options?: ElOptions<HTMLElementTagNameMap[K]> | ((node: HTMLElementTagNameMap[K]) => void), init?: (node: HTMLElementTagNameMap[K]) => void): HTMLElementTagNameMap[K];
69
+ export {};
@@ -0,0 +1,20 @@
1
+ import { HTMLElementBase } from '../dom';
2
+ import type { FeatureItem } from '../types';
3
+ /**
4
+ * `<dfk-features>` — the "Why duckfn" grid of feature cards. Ported from the
5
+ * home page's `Features()`.
6
+ *
7
+ * Retained-mode: the grid is built once and each card (a {@link DfkFeatureCard})
8
+ * holds its own nodes. `setFeatures()` grows or shrinks the list to the new
9
+ * length and mutates the cards in place — the grid is never cleared and rebuilt.
10
+ *
11
+ * The tree lives in a shadow root (adopting the shared `homeStyles()` sheet);
12
+ * see `DfkHero` for why the theme crosses the boundary through custom
13
+ * properties.
14
+ */
15
+ export declare class DfkFeatures extends HTMLElementBase {
16
+ #private;
17
+ constructor();
18
+ setSectionTitle(text: string): void;
19
+ setFeatures(items: readonly FeatureItem[]): void;
20
+ }
@@ -0,0 +1,25 @@
1
+ import { HTMLElementBase } from '../dom';
2
+ import type { HeroAction, HeroBadge, HeroLink } from '../types';
3
+ /**
4
+ * `<dfk-hero>` — the landing hero: logo, title, tagline, the two call-to-action
5
+ * buttons and the badge row. Ported from the Docusaurus home page's `Hero()`.
6
+ *
7
+ * Retained-mode: every node is held in a field, the structure is assembled once
8
+ * in the constructor and the `set*` methods only mutate the nodes they own.
9
+ *
10
+ * The tree lives in a shadow root (adopting the shared `homeStyles()` sheet), so
11
+ * the site's global CSS cannot reach it; theme colours cross the boundary
12
+ * through the inherited `--duckfn-*` / `--ifm-*` custom properties.
13
+ */
14
+ export declare class DfkHero extends HTMLElementBase {
15
+ #private;
16
+ constructor();
17
+ setLogo(src: string): void;
18
+ setTitle(text: string): void;
19
+ setTagline(text: string): void;
20
+ /** The "Get started" button: an internal link, so it stays in the same tab. */
21
+ setPrimaryAction(link: HeroLink): void;
22
+ /** The GitHub button: always external, always carries the glyph. */
23
+ setSecondaryAction(action: HeroAction): void;
24
+ setBadges(badges: readonly HeroBadge[]): void;
25
+ }
@@ -0,0 +1,16 @@
1
+ import { HTMLElementBase } from '../dom';
2
+ import type { NextStepItem } from '../types';
3
+ /**
4
+ * `<dfk-next-steps>` — the "Where to go next" row of link cards. Ported from
5
+ * the home page's `NextSteps()`.
6
+ *
7
+ * Same retained-mode shape as `DfkFeatures`: the grid is built once, each card
8
+ * holds its own nodes, `setSteps()` grows/shrinks the list and mutates in place.
9
+ * The tree lives in a shadow root like the other `dfk-*` elements.
10
+ */
11
+ export declare class DfkNextSteps extends HTMLElementBase {
12
+ #private;
13
+ constructor();
14
+ setSectionTitle(text: string): void;
15
+ setSteps(items: readonly NextStepItem[]): void;
16
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The one parsed stylesheet shared by every `dfk-*` shadow root.
3
+ *
4
+ * Created lazily: Docusaurus imports this module into Node during
5
+ * prerendering, where `CSSStyleSheet` does not exist — only the browser ever
6
+ * calls this.
7
+ */
8
+ export declare function homeStyles(): CSSStyleSheet;
@@ -0,0 +1,50 @@
1
+ import type { HTMLAttributes } from 'react';
2
+ /**
3
+ * Browser entry for duckfn-docs-kit: the home-page custom elements and the
4
+ * value types their `set*` methods accept.
5
+ *
6
+ * The components are retained-mode (build once, then mutate held nodes) and
7
+ * expose named setters such as `setTitle()` / `setBadges()`. They render into
8
+ * shadow roots and inject their own stylesheet, so the consuming site imports
9
+ * only the global CSS the kit cannot host in a shadow (`src/kit.css`: brand
10
+ * tokens + TOC toggle, imported as `duckfn-docs-kit/src/kit.css`). Icons are
11
+ * rendered by the official `<iconify-icon>`
12
+ * web component, which `registerDfkElements()` registers as a side effect, so
13
+ * this package ships no icon data.
14
+ *
15
+ * `TocToggle` and the remark plugin keep their own subpaths
16
+ * (`duckfn-docs-kit/toc-toggle/TocToggle`, `duckfn-docs-kit/remark`) instead of
17
+ * being merged here: a Docusaurus config file must never pull browser code into
18
+ * Node, and a site that only wants the TOC collapse button should not pay for
19
+ * the bundled `iconify-icon`.
20
+ */
21
+ export { DfkFeatures } from './home/DfkFeatures';
22
+ export { DfkHero } from './home/DfkHero';
23
+ export { DfkNextSteps } from './home/DfkNextSteps';
24
+ export { DfkSql } from './sql/DfkSql';
25
+ export { registerDfkElements } from './register';
26
+ export type { RunnableSqlConfig } from './sql/remark';
27
+ export type { FeatureItem, HeroAction, HeroBadge, HeroLink, NextStepItem, } from './types';
28
+ /**
29
+ * Props accepted by the `dfk-*` tags when they are created from React.
30
+ *
31
+ * The content is *not* passed as a prop — an object prop would never reach the
32
+ * component through hydration (React only reconciles strings onto custom
33
+ * elements). The caller mounts the element and drives it through its setters
34
+ * from a callback ref, so all React needs to know about is `ref`.
35
+ *
36
+ * The alias is exported (rather than written inline) because the emitted `.d.ts`
37
+ * for a module augmentation can only name types that are themselves reachable
38
+ * from the declaration file.
39
+ */
40
+ export type DfkElementProps = HTMLAttributes<HTMLElement>;
41
+ declare module 'react' {
42
+ namespace JSX {
43
+ interface IntrinsicElements {
44
+ 'dfk-hero': DfkElementProps;
45
+ 'dfk-features': DfkElementProps;
46
+ 'dfk-next-steps': DfkElementProps;
47
+ 'dfk-sql': DfkElementProps;
48
+ }
49
+ }
50
+ }
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import { a as e, i as t, n, r, t as i } from "./register-DKLiYs-F.js";
2
+ export { e as DfkFeatures, t as DfkHero, r as DfkNextSteps, n as DfkSql, i as registerDfkElements };