@intentic/extension-ui 1.309.0 → 1.311.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 +27 -49
- package/dist/index.js +2 -1
- package/dist/types/extension-ui/src/index.d.ts +1 -1
- package/dist/types/ui/src/components/primitives/Code.vue.d.ts +1 -0
- package/dist/types/ui/src/components/primitives/imageView.d.ts +0 -1
- package/dist/types/ui/src/composables/useLatest.d.ts +1 -0
- package/dist/types/ui/src/index.d.ts +2 -1
- package/dist/types/ui/src/lib/fileFormat.d.ts +11 -0
- package/dist/types/ui/src/markdown/index.d.ts +1 -1
- package/dist/types/ui/src/markdown/render.d.ts +16 -0
- package/dist/types/ui/src/markdown/sourceDom.d.ts +1 -0
- package/names.mjs +2 -1
- package/package.json +1 -1
- package/src/i18n.ts +4 -2
- package/src/index.ts +5 -1
package/README.md
CHANGED
|
@@ -1,58 +1,36 @@
|
|
|
1
|
-
#
|
|
1
|
+
# extension-ui
|
|
2
2
|
|
|
3
|
-
The UI kit
|
|
3
|
+
The UI kit extensions render with: a curated slice of the editor's design system that the host supplies at runtime, so extension views use the shell's own component instances.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
[
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
kit is **host-provided**: the web app maps this module into its import map
|
|
13
|
-
([extension-host/hostModules.ts](../../_editor/web/src/extension-host/hostModules.ts)), so a third-party bundle
|
|
14
|
-
that marks it external resolves to the **shell's own** component instances and theming: one Vue, one
|
|
15
|
-
PrimeVue, one theme across the host and every extension. In-repo builtin extensions bundle this same module
|
|
16
|
-
and land on the same instances.
|
|
17
|
-
|
|
18
|
-
The scope reads oddly (an `@intentic/*` package depending on the app-side `@intentic/ui`) but it is
|
|
19
|
-
deliberate: the dependency is build-time-only (for in-repo builtins); at runtime the import map supplies the
|
|
20
|
-
shell's instances, so no second copy is shipped.
|
|
21
|
-
|
|
22
|
-
## Drift assertion
|
|
5
|
+
```mermaid
|
|
6
|
+
flowchart LR
|
|
7
|
+
ui["_editor/ui<br/>design system"] -- "re-exported by src/" --> kit(["extension-ui"])
|
|
8
|
+
kit -- "compiled into" --> host["Editor<br/>hostModules.ts"]
|
|
9
|
+
bundle["Extension bundle"] -- "import map" --> shim["/ext-shims/extension-ui.js"]
|
|
10
|
+
shim -- "globalThis.__intenticHost" --> host
|
|
11
|
+
```
|
|
23
12
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
13
|
+
- `src/index.ts` re-exports chosen components and helpers from `@intentic/ui` (`_editor/ui`) plus the PrimeVue
|
|
14
|
+
primitives extension views use. Nothing is reimplemented, so an extension view looks and behaves like the shell
|
|
15
|
+
around it. This dependency on `_editor/ui` is a recorded exception to the [`_shared/` boundary](../README.md).
|
|
16
|
+
- At runtime the host supplies the kit: `hostModules.ts` publishes the editor's own module instances on
|
|
17
|
+
`globalThis.__intenticHost`, and the import map in the editor's `index.html` resolves `@intentic/extension-ui` to a
|
|
18
|
+
shim that reads them. A second copy would render unthemed, outside the app's reactivity and its query cache.
|
|
19
|
+
- `scripts/build.mjs` compiles the published package from `_editor/ui`'s sources: declarations pruned to what the kit
|
|
20
|
+
re-exports, and a `dist/index.js` bridge that throws when loaded outside an intentic host.
|
|
21
|
+
- `names.mjs` lists the runtime export names by hand, because the `.vue` graph cannot load in Node. The editor's shim
|
|
22
|
+
generator reads it, and a dev-time assertion in `hostModules.ts` catches drift.
|
|
23
|
+
- `./diff`, `./format` and `./i18n` skip the component barrel, for extension tests that run without a Vue compiler.
|
|
27
24
|
|
|
28
25
|
## Key files
|
|
29
26
|
|
|
30
|
-
- [src/index.ts](src/index.ts)
|
|
31
|
-
- [
|
|
32
|
-
- [
|
|
33
|
-
|
|
34
|
-
`extensionT(id)` is that translator alone, bound to its own slice of the host's one message tree, and
|
|
35
|
-
`registerExtensionMessages` mounts a catalog, which is what the host does before `activate` and what a test
|
|
36
|
-
calling `activate` itself has to do instead.
|
|
37
|
-
|
|
38
|
-
## The one control worth calling out
|
|
39
|
-
|
|
40
|
-
`AgentRunButton` and `useAgentRunPick` are re-exported because five extensions start an agent for the user:
|
|
41
|
-
pipelines, deployments, maintenance, documentation, acceptance: and each had reached its own answer about how
|
|
42
|
-
you choose what that costs. Press the primary half and the run opens on the sandbox's standing model for the job
|
|
43
|
-
the caller named; use the caret and a panel opens on that run, ending in a bar that carries the button's own
|
|
44
|
-
label. Both halves emit the same `run`, because both are the same act: the press that finishes configuring the
|
|
45
|
-
run is the press that starts it.
|
|
46
|
-
|
|
47
|
-
The choice covers more than the model — the account, the harness, the tier, extended thinking and speed
|
|
48
|
-
(`AgentRunChoice`) — and every one of them is a different price. Send them on the turn you start beside `model`:
|
|
49
|
-
the sandbox fills a pinned entry's knobs in only for a run that named no model, so dropping them runs the model
|
|
50
|
-
you chose on the provider's defaults for everything else. `runPickOf(choice)` (from `@intentic/sandbox-contract`)
|
|
51
|
-
translates the whole thing into the turn's own field names in one call.
|
|
27
|
+
- [src/index.ts](src/index.ts) — the kit: every name an extension may import, with usage notes.
|
|
28
|
+
- [scripts/build.mjs](scripts/build.mjs) — builds the published types and the host bridge from `_editor/ui`.
|
|
29
|
+
- [names.mjs](names.mjs) — the runtime export names the shims and the host check read.
|
|
30
|
+
- [../../_editor/web/src/extension-host/hostModules.ts](../../_editor/web/src/extension-host/hostModules.ts) — where the shell publishes its instances to extension bundles.
|
|
52
31
|
|
|
53
|
-
|
|
54
|
-
live in a kit that knows nothing about the extension API. Pass the extension's own host handle:
|
|
32
|
+
## Commands
|
|
55
33
|
|
|
56
|
-
```
|
|
57
|
-
|
|
34
|
+
```sh
|
|
35
|
+
pnpm --filter @intentic/extension-ui build
|
|
58
36
|
```
|
package/dist/index.js
CHANGED
|
@@ -80,13 +80,13 @@ export const formatDateTime = m["formatDateTime"];
|
|
|
80
80
|
export const formatDayMonth = m["formatDayMonth"];
|
|
81
81
|
export const formatDayMonthTime = m["formatDayMonthTime"];
|
|
82
82
|
export const formatDuration = m["formatDuration"];
|
|
83
|
+
export const formatOf = m["formatOf"];
|
|
83
84
|
export const formatTime = m["formatTime"];
|
|
84
85
|
export const formatTimestamp = m["formatTimestamp"];
|
|
85
86
|
export const formatTokens = m["formatTokens"];
|
|
86
87
|
export const formatWeekdayTime = m["formatWeekdayTime"];
|
|
87
88
|
export const formatWhen = m["formatWhen"];
|
|
88
89
|
export const freshness = m["freshness"];
|
|
89
|
-
export const isRenderableImage = m["isRenderableImage"];
|
|
90
90
|
export const noticeFrom = m["noticeFrom"];
|
|
91
91
|
export const noticeOf = m["noticeOf"];
|
|
92
92
|
export const openForwardedPort = m["openForwardedPort"];
|
|
@@ -103,6 +103,7 @@ export const useAsyncAction = m["useAsyncAction"];
|
|
|
103
103
|
export const useCompact = m["useCompact"];
|
|
104
104
|
export const useDevice = m["useDevice"];
|
|
105
105
|
export const useKeyedDraft = m["useKeyedDraft"];
|
|
106
|
+
export const useLatest = m["useLatest"];
|
|
106
107
|
export const useListNavigation = m["useListNavigation"];
|
|
107
108
|
export const useLoadingReveal = m["useLoadingReveal"];
|
|
108
109
|
export const useNarrow = m["useNarrow"];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { AgentRunButton, type AgentRunAttempt, type AgentRunChoice, type AgentRunPicker, type ModelPicking, useAgentRunPick, type FixStanceLook, fixStanceLook, AnchoredOverlay, Avatar, Button, vAction, BarChart, BottomSheet, BrandMark, Card, clipboardOf, browserOwnsClick, appLink, openForwardedPort, ChangeStatusMark, type ChangeStatus, ui, Code, CodeField, ConfirmDialog, ContextMenu, CopyButton, StatusTally, type TallyItem, DagEditor, DagGraph, type DagEdge, type DagNode, DiffStat, DisclosureRow, FilterBar, Icon, type IconName, ImageView, InfoDialog, InfoHint, InfoTable,
|
|
1
|
+
export { AgentRunButton, type AgentRunAttempt, type AgentRunChoice, type AgentRunPicker, type ModelPicking, useAgentRunPick, type FixStanceLook, fixStanceLook, AnchoredOverlay, Avatar, Button, vAction, BarChart, BottomSheet, BrandMark, Card, clipboardOf, browserOwnsClick, appLink, openForwardedPort, ChangeStatusMark, type ChangeStatus, ui, Code, CodeField, ConfirmDialog, ContextMenu, CopyButton, StatusTally, type TallyItem, DagEditor, DagGraph, type DagEdge, type DagNode, DiffStat, DisclosureRow, FilterBar, Icon, type IconName, ImageView, InfoDialog, InfoHint, InfoTable, type FileFormat, formatOf, Markdown, MarkdownDocument, MarkdownFigure, Modal, type NavGroup, NavRail, NoteEditor, type NoteDraft, type NoteDraftOptions, useNoteDraft, useKeyedDraft, type NoticeModel, type NoticeTone, type NoticeAction, Notice, NoticeStack, Page, PageAction, PageHeader, ScrollFrame, PersonaFace, type PersonaLike, Picker, ProjectChip, type PickerGroup, type PickerOption, type PickerOptions, ProgressRing, RepoRail, type RepoRailAll, type RepoRailGroup, type RepoRailRow, ProseField, ResizeSeam, ResponsiveOverlay, Row, RowGroup, SearchBar, SegmentedControl, seriesColor, sinceOf, useLoadingReveal, SkeletonRows, SplitView, StatStrip, StatusBadge, type StatusVariant, StepSection, timeWindows, type TimeWindow, timeWindowWords, useCompact, useDevice, useListNavigation, useNow, useLatest, errorMessage, noticeFrom, noticeOf, useAsyncAction, useNarrow, useRailMemory, useScrollReset, type StickyTop, useStickyTop, useTheme, } from "../../ui/src/index.js";
|
|
2
2
|
export { formatBytes, formatDate, formatDateTime, formatDayMonth, formatDayMonthTime, formatDuration, formatTime, formatTimestamp, formatTokens, formatWeekdayTime, formatWhen, freshness, timeAgo, } from "./format.js";
|
|
3
3
|
export { diffSequence, pairEdits, similarity, wordDiff } from "./diff.js";
|
|
4
4
|
export { activeLocale, extensionT } from "./i18n.js";
|
|
@@ -8,6 +8,7 @@ type __VLS_Props = {
|
|
|
8
8
|
clampLines?: number;
|
|
9
9
|
scrollLines?: number;
|
|
10
10
|
scrollBottom?: boolean;
|
|
11
|
+
tail?: boolean;
|
|
11
12
|
};
|
|
12
13
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
13
14
|
copied: () => any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useLatest: () => (() => () => boolean);
|
|
@@ -29,7 +29,6 @@ export { type DagEdge, type DagNode } from "./components/charts/dagLayout.js";
|
|
|
29
29
|
export { default as FilterBar } from "./components/forms/FilterBar.vue";
|
|
30
30
|
export { default as Icon } from "./components/primitives/Icon.vue";
|
|
31
31
|
export { default as ImageView } from "./components/primitives/ImageView.vue";
|
|
32
|
-
export { isRenderableImage } from "./components/primitives/imageView.js";
|
|
33
32
|
export { default as InfoDialog } from "./components/overlays/InfoDialog.vue";
|
|
34
33
|
export { default as InfoHint } from "./components/feedback/InfoHint.vue";
|
|
35
34
|
export { default as InfoTable } from "./components/feedback/InfoTable.vue";
|
|
@@ -73,6 +72,7 @@ export { default as StatusBadge, type StatusVariant } from "./components/feedbac
|
|
|
73
72
|
export { default as StepSection } from "./components/layout/StepSection.vue";
|
|
74
73
|
export { sinceOf, timeWindows, type TimeWindow, timeWindowWords } from "./lib/timeWindow.js";
|
|
75
74
|
export { type IconName } from "./icons/iconSets.js";
|
|
75
|
+
export { type FileFormat, formatOf } from "./lib/fileFormat.js";
|
|
76
76
|
export { useDevice } from "./composables/useDevice.js";
|
|
77
77
|
export { useNarrow } from "./composables/useNarrow.js";
|
|
78
78
|
export { useListNavigation } from "./composables/useListNavigation.js";
|
|
@@ -80,6 +80,7 @@ export { useScrollReset } from "./composables/useScrollReset.js";
|
|
|
80
80
|
export { type StickyTop, useStickyTop } from "./composables/useStickyTop.js";
|
|
81
81
|
export { useRailMemory } from "./composables/useRailMemory.js";
|
|
82
82
|
export { useNow } from "./composables/useNow.js";
|
|
83
|
+
export { useLatest } from "./composables/useLatest.js";
|
|
83
84
|
export { useLoadingReveal } from "./composables/loadingReveal.js";
|
|
84
85
|
export { errorMessage, noticeFrom, noticeOf, useAsyncAction } from "./composables/useAsyncAction.js";
|
|
85
86
|
export { useTheme } from "./composables/useTheme.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type FileCategory = "code" | "style" | "config" | "data" | "image" | "audio" | "video" | "doc" | "shell" | "archive" | "lock" | "binary" | "generic";
|
|
2
|
+
export interface FileFormat {
|
|
3
|
+
readonly category: FileCategory;
|
|
4
|
+
readonly label?: string;
|
|
5
|
+
readonly binary?: true;
|
|
6
|
+
readonly reads?: "markdown" | "plain" | "table" | "document";
|
|
7
|
+
readonly sheet?: true;
|
|
8
|
+
readonly pages?: true;
|
|
9
|
+
}
|
|
10
|
+
export declare const extensionOf: (path: string) => string;
|
|
11
|
+
export declare const formatOf: (path: string) => FileFormat;
|
|
@@ -5,4 +5,4 @@ export { createMarkdownHistory, type DocumentState, type EditKind, type Markdown
|
|
|
5
5
|
export { blockBody, buildBlockElement, caretAtOffset, offsetOfCaret } from "./sourceDom.js";
|
|
6
6
|
export { type BarsFigure, type BarsFigureItem, type DagFigure, type DagFigureEdge, type DagFigureNode, type Figure, FIGURE_ACCENTS, type FigureAccent, FIGURE_LANGS, JSON_FIGURE_LANGS, type MarkdownSegment, MERMAID_LANG, type MermaidFigure, parseFigure, splitFigureSegments, type StatsFigure, type StatsFigureItem, } from "./figures.js";
|
|
7
7
|
export { type Frontmatter, type FrontmatterField, frontmatterHtml, splitFrontmatter } from "./frontmatter.js";
|
|
8
|
-
export { createStreamingMarkdown, lexBlocks, lexInline, type MarkdownDecorator, type MarkdownPart, markdownParseCount, type MarkdownToken, renderMarkdown, renderMarkdownParts, type RenderedMarkdown, settledEnd, type StreamingMarkdown, } from "./render.js";
|
|
8
|
+
export { createStreamingMarkdown, lexBlocks, lexInline, type MarkdownDecorator, type MarkdownPart, markdownParseCount, type MarkdownToken, parseMarkdownParts, type ParsedMarkdown, renderMarkdown, renderMarkdownParts, renderParsedMarkdown, type RenderedMarkdown, settledEnd, type StreamingMarkdown, } from "./render.js";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type CodeBlock } from "./code.js";
|
|
1
2
|
import { type Figure } from "./figures.js";
|
|
2
3
|
export interface MarkdownToken {
|
|
3
4
|
readonly type: string;
|
|
@@ -7,6 +8,10 @@ export interface MarkdownToken {
|
|
|
7
8
|
export declare const lexBlocks: (source: string) => readonly MarkdownToken[] | undefined;
|
|
8
9
|
export declare const lexInline: (source: string) => readonly MarkdownToken[] | undefined;
|
|
9
10
|
export type MarkdownDecorator = (fragment: DocumentFragment) => void;
|
|
11
|
+
interface MarkdownParts {
|
|
12
|
+
readonly html: string;
|
|
13
|
+
readonly blocks: readonly CodeBlock[];
|
|
14
|
+
}
|
|
10
15
|
export declare const markdownParseCount: () => number;
|
|
11
16
|
export declare const renderMarkdown: (source: string, decorate?: MarkdownDecorator) => string;
|
|
12
17
|
export type MarkdownPart = {
|
|
@@ -17,9 +22,20 @@ export type MarkdownPart = {
|
|
|
17
22
|
readonly figure: Figure;
|
|
18
23
|
};
|
|
19
24
|
export type RenderedMarkdown = readonly MarkdownPart[];
|
|
25
|
+
type ParsedPart = {
|
|
26
|
+
readonly kind: "prose";
|
|
27
|
+
readonly parts: MarkdownParts;
|
|
28
|
+
} | {
|
|
29
|
+
readonly kind: "figure";
|
|
30
|
+
readonly figure: Figure;
|
|
31
|
+
};
|
|
32
|
+
export type ParsedMarkdown = readonly ParsedPart[];
|
|
33
|
+
export declare const parseMarkdownParts: (source: string, decorate?: MarkdownDecorator) => ParsedMarkdown;
|
|
34
|
+
export declare const renderParsedMarkdown: (parsed: ParsedMarkdown) => RenderedMarkdown;
|
|
20
35
|
export declare const renderMarkdownParts: (source: string, decorate?: MarkdownDecorator) => RenderedMarkdown;
|
|
21
36
|
export declare const settledEnd: (text: string, from: number) => number;
|
|
22
37
|
export interface StreamingMarkdown {
|
|
23
38
|
readonly render: (source: string) => RenderedMarkdown;
|
|
24
39
|
}
|
|
25
40
|
export declare const createStreamingMarkdown: (decorate?: MarkdownDecorator) => StreamingMarkdown;
|
|
41
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare const blockBody: (element: Element) => string;
|
|
2
|
+
export declare const FIGURE_HOLDER = "md-code-figure";
|
|
2
3
|
export declare const buildBlockElement: (source: string) => HTMLElement;
|
|
3
4
|
export declare const offsetOfCaret: (element: HTMLElement, node: Node, offset: number) => number;
|
|
4
5
|
export declare const caretAtOffset: (element: HTMLElement, offset: number) => {
|
package/names.mjs
CHANGED
|
@@ -30,6 +30,7 @@ export const extensionUiNames = [
|
|
|
30
30
|
"FilterBar",
|
|
31
31
|
"fixStanceLook",
|
|
32
32
|
"formatBytes",
|
|
33
|
+
"formatOf",
|
|
33
34
|
"formatDate",
|
|
34
35
|
"formatDateTime",
|
|
35
36
|
"formatDayMonth",
|
|
@@ -48,7 +49,6 @@ export const extensionUiNames = [
|
|
|
48
49
|
"InfoDialog",
|
|
49
50
|
"InfoHint",
|
|
50
51
|
"InfoTable",
|
|
51
|
-
"isRenderableImage",
|
|
52
52
|
"Markdown",
|
|
53
53
|
"MarkdownDocument",
|
|
54
54
|
"MarkdownFigure",
|
|
@@ -100,6 +100,7 @@ export const extensionUiNames = [
|
|
|
100
100
|
"useNarrow",
|
|
101
101
|
"useNoteDraft",
|
|
102
102
|
"useNow",
|
|
103
|
+
"useLatest",
|
|
103
104
|
"pairEdits",
|
|
104
105
|
"useRailMemory",
|
|
105
106
|
"useScrollReset",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentic/extension-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.311.0",
|
|
4
4
|
"description": "The UI kit intentic extensions render with, host-provided at runtime (the app's own components via the import map), so extension UI is always native to the shell",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/i18n.ts
CHANGED
|
@@ -19,6 +19,8 @@ import type { Ref } from "vue";
|
|
|
19
19
|
*/
|
|
20
20
|
export type ExtensionT = (key: string, values?: Record<string, unknown>, plural?: number) => string;
|
|
21
21
|
|
|
22
|
+
const namespaceOf = (extensionId: string): string => `ext.${extensionId}`;
|
|
23
|
+
|
|
22
24
|
/**
|
|
23
25
|
* One extension's translator, bound to the slice of the message tree the host mounted its catalog under. Keys are its
|
|
24
26
|
* own — `t("panel.title")` for what lives at `ext.<id>.panel.title` — so nothing it writes can collide with the app's
|
|
@@ -34,7 +36,7 @@ export type ExtensionT = (key: string, values?: Record<string, unknown>, plural?
|
|
|
34
36
|
* The messages themselves are declared on the extension's module (`export const messages`), which the host loads for
|
|
35
37
|
* the reader's language before it calls `activate`.
|
|
36
38
|
*/
|
|
37
|
-
export const extensionT = (extensionId: string): ExtensionT => useT(
|
|
39
|
+
export const extensionT = (extensionId: string): ExtensionT => useT(namespaceOf(extensionId));
|
|
38
40
|
|
|
39
41
|
/**
|
|
40
42
|
* One extension's words in one call: the catalog the host mounts (`messages`) and the translator its components
|
|
@@ -70,7 +72,7 @@ export const extensionI18n = (
|
|
|
70
72
|
export const registerExtensionMessages = (
|
|
71
73
|
extensionId: string,
|
|
72
74
|
messages: { readonly base: MessageTree; readonly load: (locale: string) => Promise<{ readonly default: MessageTree }> },
|
|
73
|
-
): Promise<void> => registerCatalog({ namespace:
|
|
75
|
+
): Promise<void> => registerCatalog({ namespace: namespaceOf(extensionId), ...messages });
|
|
74
76
|
|
|
75
77
|
/** The language on screen, for the rare contribution that formats something itself. Read-only: change it with nothing. */
|
|
76
78
|
export const activeLocale: Readonly<Ref<Locale>> = active;
|
package/src/index.ts
CHANGED
|
@@ -65,7 +65,9 @@ export {
|
|
|
65
65
|
InfoDialog,
|
|
66
66
|
InfoHint,
|
|
67
67
|
InfoTable,
|
|
68
|
-
|
|
68
|
+
// What a file is by its name (category, label, whether it is ever text), the table the shell's own surfaces read.
|
|
69
|
+
type FileFormat,
|
|
70
|
+
formatOf,
|
|
69
71
|
Markdown,
|
|
70
72
|
// An editable markdown document (author-facing), unlike `Markdown`'s read-only render.
|
|
71
73
|
MarkdownDocument,
|
|
@@ -140,6 +142,8 @@ export {
|
|
|
140
142
|
useListNavigation,
|
|
141
143
|
// A ticking clock (`useNow`) and a busy/error flag for one mutation at a time (`useAsyncAction`).
|
|
142
144
|
useNow,
|
|
145
|
+
// Drops an answer a newer request has superseded: `const current = begin(); …; if (!current()) return;`.
|
|
146
|
+
useLatest,
|
|
143
147
|
errorMessage,
|
|
144
148
|
noticeFrom,
|
|
145
149
|
noticeOf,
|