wiki-formant 0.4.0 → 0.7.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 +102 -1
- package/dist/analytics.d.ts +22 -0
- package/dist/analytics.d.ts.map +1 -1
- package/dist/analytics.js +31 -1
- package/dist/analytics.js.map +1 -1
- package/dist/dom.d.ts +69 -0
- package/dist/dom.d.ts.map +1 -0
- package/dist/dom.js +167 -0
- package/dist/dom.js.map +1 -0
- package/dist/react.d.ts +216 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +470 -0
- package/dist/react.js.map +1 -0
- package/dist/sidebar.d.ts +38 -0
- package/dist/sidebar.d.ts.map +1 -0
- package/dist/sidebar.js +43 -0
- package/dist/sidebar.js.map +1 -0
- package/dist/taxonomy.d.ts +52 -0
- package/dist/taxonomy.d.ts.map +1 -1
- package/dist/taxonomy.js +95 -42
- package/dist/taxonomy.js.map +1 -1
- package/dist/tiptap.d.ts +78 -0
- package/dist/tiptap.d.ts.map +1 -0
- package/dist/tiptap.js +344 -0
- package/dist/tiptap.js.map +1 -0
- package/package.json +54 -3
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { type CSSProperties, type KeyboardEvent, type ReactNode } from 'react';
|
|
2
|
+
export interface SidebarOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Where the reader's choice is remembered, in `localStorage`. Give each wiki
|
|
5
|
+
* its own key; they are different sites and may deserve different answers.
|
|
6
|
+
*/
|
|
7
|
+
storageKey?: string;
|
|
8
|
+
/** Below this width (px) the rail defaults to closed. */
|
|
9
|
+
breakpoint?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface SidebarState {
|
|
12
|
+
open: boolean;
|
|
13
|
+
setOpen: (open: boolean) => void;
|
|
14
|
+
toggle: () => void;
|
|
15
|
+
/** True below `breakpoint`. Drives "close the rail after following a link". */
|
|
16
|
+
isMobile: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* False until the effect has read storage and matchMedia. Render the rail
|
|
19
|
+
* without its open/closed transition while this is false, so a remembered
|
|
20
|
+
* closed rail does not animate shut on every load.
|
|
21
|
+
*/
|
|
22
|
+
ready: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Collapse state for a wiki rail: remembered across loads, defaulted from the
|
|
26
|
+
* viewport only when the reader has never chosen.
|
|
27
|
+
*
|
|
28
|
+
* The reader's choice outranks the breakpoint. Someone who collapses the rail
|
|
29
|
+
* on a laptop and then narrows the window has still collapsed the rail.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useCollapsibleSidebar(options?: SidebarOptions): SidebarState;
|
|
32
|
+
export interface SidebarProviderProps extends SidebarOptions {
|
|
33
|
+
children: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
/** Wrap the layout that contains both the rail and its toggle. */
|
|
36
|
+
export declare function SidebarProvider({ children, ...options }: SidebarProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<SidebarState | null>>;
|
|
37
|
+
/**
|
|
38
|
+
* The rail's collapse state. Throws outside a provider rather than silently
|
|
39
|
+
* handing back a second, unconnected copy — two sources of truth for one rail
|
|
40
|
+
* is the failure this context exists to prevent.
|
|
41
|
+
*/
|
|
42
|
+
export declare function useSidebar(): SidebarState;
|
|
43
|
+
export interface TocHeading {
|
|
44
|
+
id: string;
|
|
45
|
+
text: string;
|
|
46
|
+
/** 1 for `<h1>`, 2 for `<h2>`, and so on. */
|
|
47
|
+
level: number;
|
|
48
|
+
}
|
|
49
|
+
export interface TocClassNames {
|
|
50
|
+
root?: string;
|
|
51
|
+
button?: string;
|
|
52
|
+
label?: string;
|
|
53
|
+
list?: string;
|
|
54
|
+
item?: string;
|
|
55
|
+
/** Applied alongside `item` on the section currently under the viewport top. */
|
|
56
|
+
itemActive?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface TableOfContentsProps {
|
|
59
|
+
/**
|
|
60
|
+
* The element holding the article. A wiki whose content streams in as blocks
|
|
61
|
+
* has to read the DOM, which is why a selector is the default route — by the
|
|
62
|
+
* time the rail mounts, the article may not be there yet.
|
|
63
|
+
*
|
|
64
|
+
* Optional when `headings` is given: a wiki that renders its article on the
|
|
65
|
+
* server already knows them and should not pay for a MutationObserver to
|
|
66
|
+
* rediscover what it just wrote.
|
|
67
|
+
*/
|
|
68
|
+
containerSelector?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Headings known ahead of time. Supplying these skips the DOM scan entirely;
|
|
71
|
+
* scroll-spy still runs, since that needs the rendered elements either way.
|
|
72
|
+
*/
|
|
73
|
+
headings?: TocHeading[];
|
|
74
|
+
/** Re-query and re-observe when this changes. Pass the pathname. */
|
|
75
|
+
resetKey?: string;
|
|
76
|
+
classNames?: TocClassNames;
|
|
77
|
+
/** Rendered before the label. Receives the current expanded state. */
|
|
78
|
+
icon?: (expanded: boolean) => ReactNode;
|
|
79
|
+
label?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Mint an id for a heading that lacks one. Wikis that inject ids server-side
|
|
82
|
+
* (see `wiki-formant/headings`) should leave this off — an id is a URL, and
|
|
83
|
+
* one minted in the browser is not the one the server published.
|
|
84
|
+
*/
|
|
85
|
+
slug?: (text: string) => string;
|
|
86
|
+
/**
|
|
87
|
+
* CSS custom property holding the sticky header's height, used to place the
|
|
88
|
+
* scroll-spy line. e.g. `'--header-height'`.
|
|
89
|
+
*/
|
|
90
|
+
offsetVar?: string;
|
|
91
|
+
/** Fallback offset in px when `offsetVar` is unset or unparseable. */
|
|
92
|
+
offsetFallback?: number;
|
|
93
|
+
/** Indent per heading level, in rem. Set 0 for a flat list. */
|
|
94
|
+
indentRem?: number;
|
|
95
|
+
/** Rendered instead of nothing when the article has no headings. */
|
|
96
|
+
empty?: ReactNode;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* An "on this page" rail with scroll-spy, read from the rendered article.
|
|
100
|
+
*
|
|
101
|
+
* Both wikis this came from had written the same thing: a debounced
|
|
102
|
+
* MutationObserver to survive content arriving late, an IntersectionObserver to
|
|
103
|
+
* track the section under the viewport top, and the same reference-stability
|
|
104
|
+
* trick so an unrelated DOM mutation (a price ticker, an RSS feed) does not tear
|
|
105
|
+
* the observer down.
|
|
106
|
+
*/
|
|
107
|
+
export declare function TableOfContents({ containerSelector, headings: providedHeadings, resetKey, classNames, icon, label, slug, offsetVar, offsetFallback, indentRem, empty, }: TableOfContentsProps): import("react").JSX.Element;
|
|
108
|
+
/**
|
|
109
|
+
* Calls `onClose` on any mousedown outside the returned ref's element.
|
|
110
|
+
*
|
|
111
|
+
* The `offsetParent` check is the whole reason this is shared. All three wikis
|
|
112
|
+
* had written this hook; only one had that line, and without it a container
|
|
113
|
+
* that is `display: none` at the current breakpoint still claims outside-clicks
|
|
114
|
+
* — so a tap anywhere on a phone dismisses a popover the reader is looking at,
|
|
115
|
+
* because the hidden desktop copy of it answered first.
|
|
116
|
+
*
|
|
117
|
+
* `onClose` is an effect dependency: wrap it in `useCallback` or hoist it, or
|
|
118
|
+
* the listener is torn down and rebuilt on every render.
|
|
119
|
+
*/
|
|
120
|
+
export declare function useClickOutside<T extends HTMLElement>(onClose: () => void): import("react").RefObject<T | null>;
|
|
121
|
+
export interface TypeaheadOptions<T> {
|
|
122
|
+
/**
|
|
123
|
+
* Runs the search. MUST be referentially stable — a module function, a server
|
|
124
|
+
* action, or something wrapped in `useCallback` — because it is an effect
|
|
125
|
+
* dependency and an inline arrow re-runs the search on every render.
|
|
126
|
+
*
|
|
127
|
+
* The `signal` is optional to implement: a REST fetcher should forward it, a
|
|
128
|
+
* server action simply declares one parameter and ignores it.
|
|
129
|
+
*/
|
|
130
|
+
fetch: (query: string, signal: AbortSignal) => Promise<T[]>;
|
|
131
|
+
onPick: (item: T) => void;
|
|
132
|
+
/** Runs after Escape has cleared the list, for surface-level dismissal. */
|
|
133
|
+
onEscape?: () => void;
|
|
134
|
+
/** Debounce, in ms. */
|
|
135
|
+
delay?: number;
|
|
136
|
+
/** Queries shorter than this never reach `fetch`. */
|
|
137
|
+
minLength?: number;
|
|
138
|
+
/** Remember results per query for this mount. */
|
|
139
|
+
cache?: boolean;
|
|
140
|
+
}
|
|
141
|
+
export interface TypeaheadState<T> {
|
|
142
|
+
query: string;
|
|
143
|
+
setQuery: (query: string) => void;
|
|
144
|
+
debouncedQuery: string;
|
|
145
|
+
items: T[];
|
|
146
|
+
highlight: number;
|
|
147
|
+
setHighlight: (index: number) => void;
|
|
148
|
+
isSearching: boolean;
|
|
149
|
+
onKeyDown: (e: KeyboardEvent<HTMLInputElement>) => void;
|
|
150
|
+
/** Drop the results, keep the query. For an outside click. */
|
|
151
|
+
clearItems: () => void;
|
|
152
|
+
/** Drop everything. For a pick, or a closing popover. */
|
|
153
|
+
reset: () => void;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The debounced-search state machine behind every typeahead on these sites.
|
|
157
|
+
*
|
|
158
|
+
* Five surfaces across the three wikis had three implementations, and no two
|
|
159
|
+
* agreed on what a search field does. This is their union, because each had a
|
|
160
|
+
* piece the others were missing:
|
|
161
|
+
*
|
|
162
|
+
* - a **request-id guard**, so a slow response cannot paint over a newer one.
|
|
163
|
+
* Two of the five surfaces had no guard at all: type fast enough and the
|
|
164
|
+
* results you are reading are for a query you have already replaced.
|
|
165
|
+
* - **keyboard navigation**. Two surfaces had none — the header dropdown of a
|
|
166
|
+
* wiki whose search is its primary navigation was mouse-only.
|
|
167
|
+
* - **abort and a per-query cache**, which only the third had. The cache is
|
|
168
|
+
* per mount, not module-level, so a stale result cannot outlive the page.
|
|
169
|
+
*
|
|
170
|
+
* The debounce is inlined rather than pulled from a package: this one is nine
|
|
171
|
+
* lines, and the point of the package is to have no runtime dependencies.
|
|
172
|
+
*/
|
|
173
|
+
export declare function useTypeahead<T>({ fetch, onPick, onEscape, delay, minLength, cache, }: TypeaheadOptions<T>): TypeaheadState<T>;
|
|
174
|
+
export interface LinkPreviewOptions<T> {
|
|
175
|
+
/**
|
|
176
|
+
* Which anchors get a card. Both wikis scope this to the article container
|
|
177
|
+
* (`a.closest('.prose-content')`) as well as testing the href, and the scope
|
|
178
|
+
* is exactly the part that differs — so the whole predicate is yours.
|
|
179
|
+
*/
|
|
180
|
+
eligible: (anchor: HTMLAnchorElement) => boolean;
|
|
181
|
+
/** Resolve a preview for a href, or null for "no card". REST or server action. */
|
|
182
|
+
fetch: (href: string) => Promise<T | null>;
|
|
183
|
+
/** Must match the class on the element you spread `cardProps` onto. */
|
|
184
|
+
cardClassName?: string;
|
|
185
|
+
cardWidth?: number;
|
|
186
|
+
/** Used to decide whether the card flips above the link. */
|
|
187
|
+
cardHeight?: number;
|
|
188
|
+
/** Hover this long before fetching, in ms. */
|
|
189
|
+
showDelay?: number;
|
|
190
|
+
/** Grace period for the cursor to travel from link to card, in ms. */
|
|
191
|
+
hideDelay?: number;
|
|
192
|
+
/** Minimum gap from the viewport edge, in px. */
|
|
193
|
+
margin?: number;
|
|
194
|
+
}
|
|
195
|
+
export interface LinkPreviewState<T> {
|
|
196
|
+
/** The resolved preview, or null when no card should render. */
|
|
197
|
+
preview: T | null;
|
|
198
|
+
/** Spread onto your card element: position, and the keep-open handlers. */
|
|
199
|
+
cardProps: {
|
|
200
|
+
style: CSSProperties;
|
|
201
|
+
onMouseEnter: () => void;
|
|
202
|
+
onMouseLeave: () => void;
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Wikipedia-style hover cards over a rendered article.
|
|
207
|
+
*
|
|
208
|
+
* One delegated listener on `document` rather than a component per link, which
|
|
209
|
+
* is what makes this viable over an article holding hundreds of anchors. Two
|
|
210
|
+
* wikis had written the same ~90 lines: the same 350ms intent delay, the same
|
|
211
|
+
* 200ms grace so the cursor can cross the gap into the card, the same
|
|
212
|
+
* viewport-clamp arithmetic, the same per-href cache. They differed in exactly
|
|
213
|
+
* three things, and those three are the options above.
|
|
214
|
+
*/
|
|
215
|
+
export declare function useLinkPreview<T>({ eligible, fetch, cardClassName, cardWidth, cardHeight, showDelay, hideDelay, margin, }: LinkPreviewOptions<T>): LinkPreviewState<T>;
|
|
216
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.tsx"],"names":[],"mappings":"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"}
|