@restless-dreams/orbit 0.0.0-stage → 0.2.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/LICENSE +21 -0
- package/README.md +168 -2
- package/dist/bin/orbit.js +11666 -0
- package/dist/bin/orbit.js.map +60 -0
- package/dist/chunk-fkdfgtx9.js +17295 -0
- package/dist/chunk-fkdfgtx9.js.map +75 -0
- package/dist/chunk-y748hzcr.js +82 -0
- package/dist/chunk-y748hzcr.js.map +10 -0
- package/dist/chunk-zze4tc9n.js +408 -0
- package/dist/chunk-zze4tc9n.js.map +10 -0
- package/dist/core/auto-render.d.ts +85 -0
- package/dist/core/branch-colors.d.ts +57 -0
- package/dist/core/browser.d.ts +23 -0
- package/dist/core/create.d.ts +23 -0
- package/dist/core/diagnostics.d.ts +40 -0
- package/dist/core/dispatch.d.ts +23 -0
- package/dist/core/document-options.d.ts +18 -0
- package/dist/core/document-source.d.ts +128 -0
- package/dist/core/editing.d.ts +66 -0
- package/dist/core/engine/animation-clock.d.ts +40 -0
- package/dist/core/engine/camera.d.ts +70 -0
- package/dist/core/engine/colors.d.ts +51 -0
- package/dist/core/engine/display.d.ts +125 -0
- package/dist/core/engine/export.d.ts +32 -0
- package/dist/core/engine/glide.d.ts +34 -0
- package/dist/core/engine/labels.d.ts +106 -0
- package/dist/core/engine/node-drag.d.ts +49 -0
- package/dist/core/engine/scene.d.ts +160 -0
- package/dist/core/engine/spin.d.ts +62 -0
- package/dist/core/engine/surface-pattern.d.ts +20 -0
- package/dist/core/engine/text-measure.d.ts +116 -0
- package/dist/core/engine/views.d.ts +361 -0
- package/dist/core/extensions.d.ts +155 -0
- package/dist/core/format-upgrades.d.ts +33 -0
- package/dist/core/index.d.ts +46 -0
- package/dist/core/input-controller.d.ts +116 -0
- package/dist/core/languages.d.ts +201 -0
- package/dist/core/layout.d.ts +61 -0
- package/dist/core/map-tools/definitions.d.ts +71 -0
- package/dist/core/map-tools/input.d.ts +62 -0
- package/dist/core/map-tools/reading.d.ts +40 -0
- package/dist/core/map-tools/tools.d.ts +51 -0
- package/dist/core/markdown-writing.d.ts +87 -0
- package/dist/core/material.d.ts +25 -0
- package/dist/core/media.d.ts +42 -0
- package/dist/core/node-attributes.d.ts +31 -0
- package/dist/core/node-links.d.ts +25 -0
- package/dist/core/other-apps/freemind.d.ts +8 -0
- package/dist/core/other-apps/icons.d.ts +16 -0
- package/dist/core/other-apps/ideas.d.ts +76 -0
- package/dist/core/other-apps/import.d.ts +28 -0
- package/dist/core/other-apps/inflate.d.ts +22 -0
- package/dist/core/other-apps/markup.d.ts +51 -0
- package/dist/core/other-apps/notes.d.ts +80 -0
- package/dist/core/other-apps/opml.d.ts +26 -0
- package/dist/core/other-apps/reading.d.ts +36 -0
- package/dist/core/other-apps/xmind.d.ts +14 -0
- package/dist/core/other-apps/zip.d.ts +37 -0
- package/dist/core/parser-markdown.d.ts +42 -0
- package/dist/core/parser-yaml.d.ts +8 -0
- package/dist/core/print-layout.d.ts +70 -0
- package/dist/core/render-to-svg.d.ts +57 -0
- package/dist/core/renderer/content-painter.d.ts +30 -0
- package/dist/core/renderer/dom.d.ts +15 -0
- package/dist/core/renderer/families.d.ts +35 -0
- package/dist/core/renderer/label-painter.d.ts +93 -0
- package/dist/core/renderer/node-painter.d.ts +113 -0
- package/dist/core/renderer/numbers.d.ts +2 -0
- package/dist/core/renderer/options.d.ts +12 -0
- package/dist/core/renderer/rings-and-links.d.ts +23 -0
- package/dist/core/renderer/scene-helpers.d.ts +33 -0
- package/dist/core/renderer/trees.d.ts +22 -0
- package/dist/core/serializer-markdown.d.ts +18 -0
- package/dist/core/serializer-yaml.d.ts +2 -0
- package/dist/core/source-patch.d.ts +24 -0
- package/dist/core/source.d.ts +27 -0
- package/dist/core/styles.d.ts +6 -0
- package/dist/core/suggest.d.ts +8 -0
- package/dist/core/svg-renderer.d.ts +626 -0
- package/dist/core/text-layout.d.ts +54 -0
- package/dist/core/themes.d.ts +62 -0
- package/dist/core/types.d.ts +471 -0
- package/dist/core/ui/actions.d.ts +75 -0
- package/dist/core/ui/controls.d.ts +61 -0
- package/dist/core/ui/detail-sheet.d.ts +88 -0
- package/dist/core/ui/frames.d.ts +11 -0
- package/dist/core/ui/icons.d.ts +14 -0
- package/dist/core/ui/inline-editor.d.ts +79 -0
- package/dist/core/ui/media-players.d.ts +65 -0
- package/dist/core/ui/media-viewer.d.ts +169 -0
- package/dist/core/ui/media-zoom.d.ts +51 -0
- package/dist/core/ui/note-markdown.d.ts +19 -0
- package/dist/core/ui/outline.d.ts +44 -0
- package/dist/core/url-guard.d.ts +40 -0
- package/dist/core/utils.d.ts +23 -0
- package/dist/core/web-page/page.d.ts +59 -0
- package/dist/core/web-page/runtime.d.ts +13 -0
- package/dist/core/web-page/start.d.ts +1 -0
- package/dist/core/yaml-mini.d.ts +54 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4357 -0
- package/dist/index.js.map +29 -0
- package/dist/marked/index.d.ts +31 -0
- package/dist/marked/index.js +110 -0
- package/dist/marked/index.js.map +10 -0
- package/dist/react/index.d.ts +55 -0
- package/dist/react/index.js +352 -0
- package/dist/react/index.js.map +1 -0
- package/dist/web-page.d.ts +2 -0
- package/dist/web-page.js +130 -0
- package/llms-full.txt +2785 -0
- package/llms.txt +36 -0
- package/package.json +118 -4
- package/skills/orbit/SKILL.md +140 -0
- package/skills/orbit/references/editing.md +195 -0
- package/skills/orbit/references/extending.md +247 -0
- package/skills/orbit/references/format.md +331 -0
- package/skills/orbit/references/guide.md +546 -0
- package/skills/orbit/references/import-export.md +115 -0
- package/skills/orbit/references/languages.md +160 -0
- package/skills/orbit/references/map-tools.md +188 -0
- package/skills/orbit/references/media.md +160 -0
- package/skills/orbit/references/recipes.md +236 -0
- package/skills/orbit/references/theming.md +199 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { OrbitSVGRenderer } from './svg-renderer.js';
|
|
2
|
+
import type { OrbitMediaOptions, RendererOptions } from './types.js';
|
|
3
|
+
import { type OrbitDiagnostic } from './diagnostics.js';
|
|
4
|
+
export interface AutoRenderOptions extends RendererOptions {
|
|
5
|
+
selector?: string;
|
|
6
|
+
height?: number;
|
|
7
|
+
strict?: boolean;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Detail of the `orbit-error` event dispatched on an element whose map couldn't be drawn. */
|
|
11
|
+
export interface OrbitRenderErrorDetail {
|
|
12
|
+
message: string;
|
|
13
|
+
line?: number;
|
|
14
|
+
error: Error | null;
|
|
15
|
+
diagnostics: OrbitDiagnostic[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The `<orbit-map>` element's API, for code that holds a reference to one.
|
|
19
|
+
* It also dispatches the map's events (`orbit-focus-change`,
|
|
20
|
+
* `orbit-view-mode-change`, `orbit-node-click`, `orbit-action`,
|
|
21
|
+
* `orbit-spin-settle`, `orbit-media-open`, `orbit-media-close`,
|
|
22
|
+
* `orbit-media-state` and the rest) and `orbit-error`.
|
|
23
|
+
*/
|
|
24
|
+
export interface OrbitMapElement extends HTMLElement {
|
|
25
|
+
/** The markdown or YAML the map is drawn from. Setting it updates the `source` attribute. */
|
|
26
|
+
source: string;
|
|
27
|
+
/** The renderer drawing the map, or null before the first render or after an error. */
|
|
28
|
+
readonly renderer: OrbitSVGRenderer | null;
|
|
29
|
+
/** Re-reads the source and redraws the map, keeping the reader's place when it can. */
|
|
30
|
+
refresh(): void;
|
|
31
|
+
/** Flies to a node by id, in focus mode. Returns false when the map has no such node. */
|
|
32
|
+
flyTo(nodeId: string): boolean;
|
|
33
|
+
/** Flies out to the overview of the whole map. */
|
|
34
|
+
overview(): void;
|
|
35
|
+
/** Shows a node's picture or video in the media viewer (see `OrbitSVGRenderer.openMedia`). Returns false when there's nothing to show. */
|
|
36
|
+
openMedia(nodeId: string, options?: OrbitMediaOptions): boolean;
|
|
37
|
+
/** Closes the media viewer. */
|
|
38
|
+
closeMedia(): void;
|
|
39
|
+
/** Plays the video in the media viewer. Returns false when it shows none it can play. */
|
|
40
|
+
playMedia(): boolean;
|
|
41
|
+
/** Pauses the video in the media viewer. Returns false when it shows none it can pause. */
|
|
42
|
+
pauseMedia(): boolean;
|
|
43
|
+
/** Moves the video in the media viewer to `seconds` from its start. Returns false when it shows none it can move. */
|
|
44
|
+
seekMedia(seconds: number): boolean;
|
|
45
|
+
/** Turns on the sound of the video in the media viewer, from a press. Returns false when it shows none it can drive. */
|
|
46
|
+
unmuteMedia(): boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Renders an orbit map into the given element. Problems in the document never
|
|
50
|
+
* throw: parse warnings go to the console, and a map that can't be drawn is
|
|
51
|
+
* replaced by an error card and an `orbit-error` event on the element.
|
|
52
|
+
*
|
|
53
|
+
* Callers who later detach the element should invoke
|
|
54
|
+
* `OrbitSVGRenderer.unmount(element)` to release RAF loops and the
|
|
55
|
+
* ResizeObserver. The `<orbit-map>` web component does this automatically.
|
|
56
|
+
*/
|
|
57
|
+
export declare const renderOrbitElement: (element: Element, options?: AutoRenderOptions) => OrbitSVGRenderer | null;
|
|
58
|
+
/**
|
|
59
|
+
* Renders every orbit block under `root` (default: the whole document). Each
|
|
60
|
+
* block is independent: one that fails shows its error card and the rest
|
|
61
|
+
* still render.
|
|
62
|
+
*/
|
|
63
|
+
export declare const renderOrbitMarkdownBlocks: (root?: ParentNode, options?: AutoRenderOptions) => OrbitSVGRenderer[];
|
|
64
|
+
/**
|
|
65
|
+
* Registers the `<orbit-map>` element. Write the map as the element's
|
|
66
|
+
* content (indent it however you like, `<!-- orbit … -->` comments included),
|
|
67
|
+
* inside a `<script type="text/orbit">` child, or in a `source` attribute.
|
|
68
|
+
* The map renders in a shadow root, so the raw markdown is never displayed,
|
|
69
|
+
* and it redraws when the content or an attribute changes.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```html
|
|
73
|
+
* <script type="module">
|
|
74
|
+
* import { defineOrbitMapElement } from '@restless-dreams/orbit';
|
|
75
|
+
* defineOrbitMapElement();
|
|
76
|
+
* </script>
|
|
77
|
+
*
|
|
78
|
+
* <orbit-map height="420" theme="night">
|
|
79
|
+
* # Launch
|
|
80
|
+
* ## Research <!-- orbit status: active -->
|
|
81
|
+
* ## Build
|
|
82
|
+
* </orbit-map>
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
export declare const defineOrbitMapElement: (tagName?: string) => void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which of the palette's colors each top-level node takes, and how edits
|
|
3
|
+
* keep them. The root takes the palette's first color, and top-level nodes
|
|
4
|
+
* take the others in turn, cycling. A node with a `paletteColor` takes that
|
|
5
|
+
* one instead and gives up its turn, so the nodes after it keep theirs.
|
|
6
|
+
* Edits write a `paletteColor` where a node's turn would change, so adding,
|
|
7
|
+
* moving or removing a node never gives the others new colors.
|
|
8
|
+
*/
|
|
9
|
+
import type { OrbitNode } from './types.js';
|
|
10
|
+
/** A node's own color, or its type's: what it shows instead of the palette's. */
|
|
11
|
+
export type OwnColor = (node: OrbitNode) => string | undefined;
|
|
12
|
+
/** What an edit needs to keep top-level nodes' colors. */
|
|
13
|
+
export interface BranchColorRules {
|
|
14
|
+
/** How many colors top-level nodes take turns with: the palette's, after the root's (see `branchPalette`). */
|
|
15
|
+
count: number;
|
|
16
|
+
/** A node's own color or its type's, which it shows instead of the palette's. Default: its `color`. */
|
|
17
|
+
ownColor?: OwnColor;
|
|
18
|
+
}
|
|
19
|
+
/** Each top-level node's palette number before an edit, from `branchColorsBefore`. */
|
|
20
|
+
export type BranchColors = Map<OrbitNode, number>;
|
|
21
|
+
/** The node an edit was about, for `keepBranchColors`. */
|
|
22
|
+
export interface EditedBranch {
|
|
23
|
+
node: OrbitNode;
|
|
24
|
+
/** Whether the node keeps the color it had (a move), rather than taking one no other top-level node has (a new node). */
|
|
25
|
+
keepsColor: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** The colors top-level nodes take turns with: every palette color after the root's, or the only one. */
|
|
28
|
+
export declare const branchPalette: (palette: readonly string[]) => string[];
|
|
29
|
+
/** Whether a value is a palette number: a whole number from 1. */
|
|
30
|
+
export declare const isPaletteNumber: (value: unknown) => value is number;
|
|
31
|
+
/** The color a palette number names among `colors` (from `branchPalette`), cycling. */
|
|
32
|
+
export declare const paletteColorOf: (colors: readonly string[], paletteNumber: number) => string;
|
|
33
|
+
/**
|
|
34
|
+
* The palette number each of `branches` takes its color from: its
|
|
35
|
+
* `paletteColor`, or else the next number in turn that none of them has as
|
|
36
|
+
* its `paletteColor`. Nodes with a color or type of their own take a turn
|
|
37
|
+
* too, so the nodes after them have the colors they'd have without one.
|
|
38
|
+
*/
|
|
39
|
+
export declare const branchNumbers: (branches: readonly OrbitNode[], count: number) => Map<OrbitNode, number>;
|
|
40
|
+
/** Each top-level node's palette number, to keep through an edit with `keepBranchColors`. */
|
|
41
|
+
export declare const branchColorsBefore: (root: OrbitNode, rules: BranchColorRules) => BranchColors;
|
|
42
|
+
/**
|
|
43
|
+
* After an edit, gives every top-level node that was there before the color
|
|
44
|
+
* it had, writing its palette number as its `paletteColor` where its turn
|
|
45
|
+
* changed. The node the edit was about keeps its color when it moved within
|
|
46
|
+
* the top level, takes one no other top-level node has when it's new there
|
|
47
|
+
* (while there is one), and drops its `paletteColor` when it left the top
|
|
48
|
+
* level, to take its new branch's color. Nodes showing a color or type of
|
|
49
|
+
* their own are left as they are, and a `paletteColor` is written only where
|
|
50
|
+
* a color would change otherwise.
|
|
51
|
+
*
|
|
52
|
+
* An edit that would write more numbers than the palette has colors writes
|
|
53
|
+
* none: that happens only where the top level has more nodes than colors,
|
|
54
|
+
* which repeat there anyway, and a big orbit's every node would get one.
|
|
55
|
+
* Returns the nodes it changed.
|
|
56
|
+
*/
|
|
57
|
+
export declare const keepBranchColors: (root: OrbitNode, before: BranchColors, rules: BranchColorRules, edited?: EditedBranch) => OrbitNode[];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the browser draws with, checked once. A few effects need newer CSS:
|
|
3
|
+
* older browsers, such as the WebViews of phones that don't update theirs,
|
|
4
|
+
* get plainer versions of them instead of broken ones. Outside a browser (on
|
|
5
|
+
* a server, or tests without a DOM) everything counts as there.
|
|
6
|
+
*/
|
|
7
|
+
export declare const browser: {
|
|
8
|
+
/** CSS `color-mix()` (Chromium 111, Safari 16.2, Firefox 113). Without it, siblings keep their branch's own color. */
|
|
9
|
+
mixesColors: boolean;
|
|
10
|
+
/** The `translate` property (Chromium 104, Safari 14.1, Firefox 72). Without it, overlays are centered through their transform. */
|
|
11
|
+
translates: boolean;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Whether `element`'s page is used with a finger (`pointer: coarse`), where
|
|
15
|
+
* the stylesheet makes buttons bigger. The query is made once per window.
|
|
16
|
+
*/
|
|
17
|
+
export declare const pointsCoarsely: (element: Element) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* The transform that puts an overlay at `x`, `y`. `centering` is the
|
|
20
|
+
* stylesheet's `translate` for it, as `translate()` takes it: where the
|
|
21
|
+
* browser lacks that property, the transform moves the overlay instead.
|
|
22
|
+
*/
|
|
23
|
+
export declare const overlayTransform: (x: number, y: number, centering: string) => string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { OrbitSVGRenderer } from './svg-renderer.js';
|
|
2
|
+
import type { OrbitDocument, OrbitNode, RendererOptions } from './types.js';
|
|
3
|
+
export interface CreateOrbitMapOptions extends RendererOptions {
|
|
4
|
+
/** Throw on the first problem in the source instead of working around it. */
|
|
5
|
+
strict?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Draws a map into `target` in one call: markdown or YAML source, a parsed
|
|
9
|
+
* document or a node tree. Returns the renderer, to listen for events
|
|
10
|
+
* (`renderer.on('focus-change', …)`), draw new versions (`renderer.render(source)`)
|
|
11
|
+
* and clean up (`renderer.destroy()`).
|
|
12
|
+
*
|
|
13
|
+
* The map fills `target`, so give it a height.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { createOrbitMap } from '@restless-dreams/orbit';
|
|
18
|
+
*
|
|
19
|
+
* const map = createOrbitMap(document.querySelector('#map')!, '# Launch\n## Research\n## Build', { theme: 'auto' });
|
|
20
|
+
* map.on('focus-change', ({ node }) => console.log(node.text));
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const createOrbitMap: (target: HTMLElement, source: string | OrbitDocument | OrbitNode, options?: CreateOrbitMapOptions) => OrbitSVGRenderer;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse diagnostics. Parsers are forgiving by default: a problem they can
|
|
3
|
+
* recover from is recorded as a diagnostic and parsing continues. In strict
|
|
4
|
+
* mode (`{ strict: true }`, used by `orbit validate`) the first such
|
|
5
|
+
* problem throws an `OrbitParseError` instead.
|
|
6
|
+
*/
|
|
7
|
+
import type { OrbitDocument } from './types.js';
|
|
8
|
+
/** Every kind of problem the parsers report. */
|
|
9
|
+
export declare const DIAGNOSTIC_CODES: readonly ["empty-document", "no-structure", "synthetic-root", "invalid-frontmatter", "unknown-frontmatter-key", "unsupported-schema-version", "format-upgraded", "invalid-attributes", "unknown-attribute", "invalid-option-value", "media-missing-source", "unknown-content-type", "caption-without-media", "unknown-link-target", "invalid-yaml", "unknown-yaml-key", "ignored-node-entry", "misnamed-node-key", "comment-without-orbit", "attributes-after-list"];
|
|
10
|
+
export type OrbitDiagnosticCode = (typeof DIAGNOSTIC_CODES)[number];
|
|
11
|
+
export type OrbitDiagnosticSeverity = 'error' | 'warning';
|
|
12
|
+
export interface OrbitDiagnostic {
|
|
13
|
+
code: OrbitDiagnosticCode;
|
|
14
|
+
message: string;
|
|
15
|
+
/** 1-based line in the source passed to the parser, when known. */
|
|
16
|
+
line?: number;
|
|
17
|
+
severity: OrbitDiagnosticSeverity;
|
|
18
|
+
}
|
|
19
|
+
export declare class OrbitParseError extends Error {
|
|
20
|
+
readonly code: OrbitDiagnosticCode;
|
|
21
|
+
readonly line: number;
|
|
22
|
+
constructor(message: string, line: number, code?: OrbitDiagnosticCode);
|
|
23
|
+
}
|
|
24
|
+
export declare const formatDiagnostic: (diagnostic: OrbitDiagnostic) => string;
|
|
25
|
+
/**
|
|
26
|
+
* Reports a parsed document's problems to the console, the same signal from
|
|
27
|
+
* every entry point: each error as an error, then the other problems as one
|
|
28
|
+
* warning. A document without diagnostics reports its warnings alone.
|
|
29
|
+
*/
|
|
30
|
+
export declare const reportParseDiagnostics: (doc: OrbitDocument) => void;
|
|
31
|
+
export declare class DiagnosticCollector {
|
|
32
|
+
readonly diagnostics: OrbitDiagnostic[];
|
|
33
|
+
private readonly strict;
|
|
34
|
+
constructor(strict: boolean);
|
|
35
|
+
/** A problem the parser works around: thrown in strict mode, recorded otherwise. */
|
|
36
|
+
recover(code: OrbitDiagnosticCode, message: string, line?: number, severity?: OrbitDiagnosticSeverity): void;
|
|
37
|
+
/** Worth knowing but never fatal, even in strict mode. */
|
|
38
|
+
note(code: OrbitDiagnosticCode, message: string, line?: number): void;
|
|
39
|
+
get warnings(): string[];
|
|
40
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ParsedOrbitDocument } from './types.js';
|
|
2
|
+
import type { ParseOptions } from './parser-markdown.js';
|
|
3
|
+
/**
|
|
4
|
+
* Parses an orbit document in either flavor. Markdown is the default; a
|
|
5
|
+
* document is read as YAML when its first line is a top-level YAML key
|
|
6
|
+
* (`nodes:`, `title:`, `view:`, …), it has a top-level `nodes:` list, or its
|
|
7
|
+
* frontmatter says `flavor: yaml`. A fenced ```orbit block is unwrapped first.
|
|
8
|
+
*
|
|
9
|
+
* Problems the parser can work around are listed in `diagnostics` (each with
|
|
10
|
+
* a `code`, `line`, `severity` and a message that says how to fix it); pass
|
|
11
|
+
* `{ strict: true }` to throw an `OrbitParseError` on the first one instead.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* import { parseOrbit } from '@restless-dreams/orbit';
|
|
16
|
+
*
|
|
17
|
+
* const { root, diagnostics } = parseOrbit('# Launch\n## Research <!-- orbit status: active -->');
|
|
18
|
+
* for (const problem of diagnostics ?? []) console.warn(`line ${problem.line}: ${problem.message}`);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare const parseOrbit: (input: string, options?: ParseOptions) => ParsedOrbitDocument;
|
|
22
|
+
/** The flavor `parseOrbit` reads a document as: `markdown` or `yaml`. */
|
|
23
|
+
export declare const orbitFlavor: (input: string) => "markdown" | "yaml";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { OrbitDocumentOptions, RendererOptions } from './types.js';
|
|
2
|
+
/** Document-level options accepted in markdown frontmatter and as YAML top-level keys. */
|
|
3
|
+
export declare const DOCUMENT_OPTION_KEYS: Set<string>;
|
|
4
|
+
/** Words people (and agents) reach for instead of a theme's name. */
|
|
5
|
+
export declare const THEME_SYNONYMS: Record<string, string>;
|
|
6
|
+
/** The message for a key that isn't a document option, with the option it probably means. */
|
|
7
|
+
export declare const unknownOptionMessage: (key: string, place: "frontmatter" | "top-level") => string;
|
|
8
|
+
/**
|
|
9
|
+
* Sets one document option from its frontmatter (or YAML top-level) value.
|
|
10
|
+
* A value that can't be used is left out and described to `report`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const applyDocumentOption: (options: OrbitDocumentOptions, key: string, value: unknown, report?: (message: string) => void) => void;
|
|
13
|
+
/**
|
|
14
|
+
* The renderer options a document asks for in its frontmatter (or YAML
|
|
15
|
+
* top-level keys). `title` becomes the map's accessible label. Container
|
|
16
|
+
* concerns (`height`, `className`) are left to the caller.
|
|
17
|
+
*/
|
|
18
|
+
export declare const documentToRendererOptions: (options: OrbitDocumentOptions) => RendererOptions;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a markdown document came from: its text, and which lines each node
|
|
3
|
+
* owns. Saving uses it to write back only what an edit changed, so a map
|
|
4
|
+
* written by hand (or by another app) keeps its own formatting, and
|
|
5
|
+
* everything Orbit doesn't read, through edits.
|
|
6
|
+
*/
|
|
7
|
+
import type { OrbitDocument, OrbitDocumentOptions, OrbitNode } from './types.js';
|
|
8
|
+
/** What a line is to the node that owns it. */
|
|
9
|
+
export type LineRole =
|
|
10
|
+
/** The frontmatter block, and blank lines before it. */
|
|
11
|
+
'frontmatter'
|
|
12
|
+
/** A heading or list item line (a setext heading's underline too), or the paragraph that names a generated root. */
|
|
13
|
+
| 'title'
|
|
14
|
+
/** An `<!-- orbit … -->` block. */
|
|
15
|
+
| 'attributes'
|
|
16
|
+
/** A picture or video line, and the comment after it that sets its caption or content type. */
|
|
17
|
+
| 'media'
|
|
18
|
+
/** Text of the node's note: paragraphs, quotes, code, or headings under a list item. */
|
|
19
|
+
| 'note'
|
|
20
|
+
/**
|
|
21
|
+
* The end of the document, which stays at its end: link and footnote
|
|
22
|
+
* definitions there (the root's note), and the blank lines around them.
|
|
23
|
+
*/
|
|
24
|
+
| 'end'
|
|
25
|
+
/** Text Orbit keeps without reading: other HTML comments, rules, attribute blocks it couldn't read. */
|
|
26
|
+
| 'foreign' | 'blank';
|
|
27
|
+
/** How a node was written. */
|
|
28
|
+
export type NodeShape = {
|
|
29
|
+
kind: 'heading';
|
|
30
|
+
level: number;
|
|
31
|
+
setext: boolean;
|
|
32
|
+
}
|
|
33
|
+
/** `indent` is the marker's column, `content` the column its text starts at. */
|
|
34
|
+
| {
|
|
35
|
+
kind: 'item';
|
|
36
|
+
indent: number;
|
|
37
|
+
marker: string;
|
|
38
|
+
content: number;
|
|
39
|
+
}
|
|
40
|
+
/** A root Orbit made up: named after the title or a lead paragraph (`lead`), or "Untitled map". */
|
|
41
|
+
| {
|
|
42
|
+
kind: 'generated';
|
|
43
|
+
lead: boolean;
|
|
44
|
+
};
|
|
45
|
+
/** A node's own fields, as they were read: to tell which ones an edit changed. */
|
|
46
|
+
export type NodeFields = Pick<OrbitNode, 'id' | 'text' | 'icon' | 'link' | 'status' | 'tags' | 'color' | 'paletteColor' | 'priority' | 'collapsed' | 'type' | 'typeVersion' | 'note' | 'noteFormat' | 'image' | 'video' | 'embed' | 'attrs'>;
|
|
47
|
+
export interface NodeRecord {
|
|
48
|
+
shape: NodeShape;
|
|
49
|
+
/** The title line, 0-based; null for a generated root without a lead paragraph. */
|
|
50
|
+
titleLine: number | null;
|
|
51
|
+
/** The lines the node and everything under it span, 0-based, end exclusive. */
|
|
52
|
+
start: number;
|
|
53
|
+
end: number;
|
|
54
|
+
/** Whether every line in the span is the node's or under it, so the span can be written back as one piece. */
|
|
55
|
+
contiguous: boolean;
|
|
56
|
+
/** Its children, in their order in the source. */
|
|
57
|
+
children: OrbitNode[];
|
|
58
|
+
fields: NodeFields;
|
|
59
|
+
/** Whether the node's id was written as an attribute (or would have to be). */
|
|
60
|
+
explicitId: boolean;
|
|
61
|
+
}
|
|
62
|
+
export interface DocumentSource {
|
|
63
|
+
/** The lines as the parser read them: line endings as `\n`, without a byte-order mark or shared indentation. */
|
|
64
|
+
lines: string[];
|
|
65
|
+
/** For each line, the node it belongs to (null for the frontmatter) and what it is there. */
|
|
66
|
+
owners: (OrbitNode | null)[];
|
|
67
|
+
roles: LineRole[];
|
|
68
|
+
records: WeakMap<OrbitNode, NodeRecord>;
|
|
69
|
+
root: OrbitNode;
|
|
70
|
+
/** The options as read, to tell which ones changed. */
|
|
71
|
+
options: OrbitDocumentOptions;
|
|
72
|
+
/** The frontmatter keys Orbit doesn't read, as read, to tell which ones changed. */
|
|
73
|
+
extra: Record<string, unknown>;
|
|
74
|
+
/** The frontmatter's fences, 0-based, when the document has frontmatter. */
|
|
75
|
+
frontmatter: {
|
|
76
|
+
open: number;
|
|
77
|
+
close: number;
|
|
78
|
+
} | null;
|
|
79
|
+
/** How the file was written, so it's written back the same way. */
|
|
80
|
+
encoding: SourceEncoding;
|
|
81
|
+
}
|
|
82
|
+
export interface SourceEncoding {
|
|
83
|
+
lineEnding: '\n' | '\r\n';
|
|
84
|
+
byteOrderMark: boolean;
|
|
85
|
+
/** Indentation every line shared (a map indented inside HTML or a template), put back on save. */
|
|
86
|
+
indentation: string;
|
|
87
|
+
/** Lines around the map that the parser unwrapped: a ```` ```orbit ```` fence. */
|
|
88
|
+
before: string[];
|
|
89
|
+
after: string[];
|
|
90
|
+
}
|
|
91
|
+
/** How a text is written: its line endings and byte-order mark. Indentation and wrapping are set where they're found. */
|
|
92
|
+
export declare const encodingOf: (text: string) => SourceEncoding;
|
|
93
|
+
/**
|
|
94
|
+
* The source a document's tree was read from, when it was read from
|
|
95
|
+
* markdown. Kept by the tree's root, off the document itself, so documents
|
|
96
|
+
* stay plain data that JSON leaves out, and a copy of a document with other
|
|
97
|
+
* options (or a map holding the tree) still saves from its source.
|
|
98
|
+
*/
|
|
99
|
+
export declare const documentSource: (document: Pick<OrbitDocument, "root">) => DocumentSource | undefined;
|
|
100
|
+
/** Remembers where a document's tree came from (see `documentSource`). */
|
|
101
|
+
export declare const setDocumentSource: (document: Pick<OrbitDocument, "root">, source: DocumentSource) => void;
|
|
102
|
+
/** A copy of a node's own fields, deep enough that edits to the node don't reach it. */
|
|
103
|
+
export declare const nodeFields: (node: OrbitNode) => NodeFields;
|
|
104
|
+
/**
|
|
105
|
+
* Collects, while a document is parsed, which node owns each line and what
|
|
106
|
+
* the line is, then works out each node's span.
|
|
107
|
+
*/
|
|
108
|
+
export declare class SourceRecorder {
|
|
109
|
+
readonly owners: (OrbitNode | null)[];
|
|
110
|
+
readonly roles: (LineRole | undefined)[];
|
|
111
|
+
private readonly lines;
|
|
112
|
+
private readonly shapes;
|
|
113
|
+
constructor(lines: string[]);
|
|
114
|
+
/** Lines `first` to `last` (1-based, inclusive) belong to `node` as `role`. */
|
|
115
|
+
mark(first: number, last: number, node: OrbitNode | null, role: LineRole): void;
|
|
116
|
+
/** A line's text (1-based), as read. */
|
|
117
|
+
line(line: number): string;
|
|
118
|
+
/** How `node` was written, and its title line (1-based), if it has one. */
|
|
119
|
+
shape(node: OrbitNode, shape: NodeShape, titleLine: number | null): void;
|
|
120
|
+
/**
|
|
121
|
+
* The finished source. Blank lines nothing claimed go with the text they
|
|
122
|
+
* lead up to (an idea moved takes the blank line before it, and the
|
|
123
|
+
* paragraph after a list keeps the blank line that keeps it out of the
|
|
124
|
+
* list); at the end of the document, with the line above. Every line has
|
|
125
|
+
* an owner, so spans cover the whole document.
|
|
126
|
+
*/
|
|
127
|
+
finish(root: OrbitNode, options: OrbitDocumentOptions, extra: Record<string, unknown>, frontmatter: DocumentSource['frontmatter'], explicitIds: ReadonlySet<OrbitNode>): DocumentSource;
|
|
128
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changes to a map's tree, behind the renderer's `addNode`, `updateNode`,
|
|
3
|
+
* `removeNode` and `moveNode`, and the map tools, which make them on a map
|
|
4
|
+
* that isn't drawn too. Ids follow the parsers' rules, so a map saved with
|
|
5
|
+
* `toMarkdown()` reads back with the same ids. Given the palette's rules,
|
|
6
|
+
* each change keeps the colors of the top-level nodes it doesn't change
|
|
7
|
+
* (see `keepBranchColors`).
|
|
8
|
+
*/
|
|
9
|
+
import type { OrbitNewNode, OrbitNode, OrbitNodeInput } from './types.js';
|
|
10
|
+
import { type BranchColorRules } from './branch-colors.js';
|
|
11
|
+
/** Every id in the tree. */
|
|
12
|
+
export declare const nodeIds: (root: OrbitNode) => Set<string>;
|
|
13
|
+
/** `base` when no node has it, otherwise `base-2`, `base-3`…, the way the parsers number repeated titles. */
|
|
14
|
+
export declare const uniqueId: (base: string, taken: ReadonlySet<string>) => string;
|
|
15
|
+
/**
|
|
16
|
+
* A new node with `input`'s text, attributes and children, each with an id
|
|
17
|
+
* from its text that no node in `taken` has, numbered in reading order as
|
|
18
|
+
* the parsers number repeated titles.
|
|
19
|
+
*/
|
|
20
|
+
export declare const createNode: (input: OrbitNewNode, taken: ReadonlySet<string>) => OrbitNode;
|
|
21
|
+
/** What `createNode` takes to add a copy of `node`: its text, attributes and children, without its id or its place in a source. */
|
|
22
|
+
export declare const newNodeFrom: (node: OrbitNode) => OrbitNewNode;
|
|
23
|
+
/** Sets the text and attributes `changes` names. An attribute set to `undefined` is removed. */
|
|
24
|
+
export declare const assignAttributes: (node: OrbitNode, changes: OrbitNodeInput) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the node's id was made from its text, as the parsers make ids,
|
|
27
|
+
* rather than set with an `id` attribute: `research`, or `research-2` for
|
|
28
|
+
* a second "Research". Suffixes start at 2 (the parsers never make `-1`),
|
|
29
|
+
* so a hand-set `foo-1` is explicit.
|
|
30
|
+
*/
|
|
31
|
+
export declare const hasTextId: (node: OrbitNode) => boolean;
|
|
32
|
+
/** Whether a link in the map, a node's link or one in a note, points at `node`. */
|
|
33
|
+
export declare const isLinkedTo: (root: OrbitNode, node: OrbitNode) => boolean;
|
|
34
|
+
/** Puts `node` among `parent`'s children at `index` (clamped; default last), with its levels and parent links. */
|
|
35
|
+
export declare const insertChild: (parent: OrbitNode, node: OrbitNode, parentLevel: number, index?: number) => void;
|
|
36
|
+
/** Takes `node` out of `parent`'s children. */
|
|
37
|
+
export declare const detachChild: (parent: OrbitNode, node: OrbitNode) => void;
|
|
38
|
+
/** Adds `input`, with its children, under `parentId` at `index` among its children (default: last). Null when there's no such parent. */
|
|
39
|
+
export declare const addToTree: (root: OrbitNode, parentId: string, input: OrbitNewNode, index?: number, colors?: BranchColorRules) => {
|
|
40
|
+
node: OrbitNode;
|
|
41
|
+
parent: OrbitNode;
|
|
42
|
+
} | null;
|
|
43
|
+
/**
|
|
44
|
+
* Sets the text and attributes `changes` names on `id`. New text gives the
|
|
45
|
+
* node a new id when its id came from its text and no link points at it,
|
|
46
|
+
* so the saved map needs no id attribute. Null when there's no such node.
|
|
47
|
+
*/
|
|
48
|
+
export declare const updateInTree: (root: OrbitNode, id: string, changes: OrbitNodeInput, colors?: BranchColorRules) => {
|
|
49
|
+
node: OrbitNode;
|
|
50
|
+
previousId: string;
|
|
51
|
+
} | null;
|
|
52
|
+
/** Takes `id` and everything under it out of the tree. Null when there's no such node, or for the root. */
|
|
53
|
+
export declare const removeFromTree: (root: OrbitNode, id: string, colors?: BranchColorRules) => {
|
|
54
|
+
node: OrbitNode;
|
|
55
|
+
parent: OrbitNode;
|
|
56
|
+
} | null;
|
|
57
|
+
/**
|
|
58
|
+
* Moves `id`, with everything under it, under `parentId` at `index` among
|
|
59
|
+
* its children (default: last). Null when either node is missing, the node
|
|
60
|
+
* is the root, or `parentId` is inside it.
|
|
61
|
+
*/
|
|
62
|
+
export declare const moveInTree: (root: OrbitNode, id: string, parentId: string, index?: number, colors?: BranchColorRules) => {
|
|
63
|
+
node: OrbitNode;
|
|
64
|
+
from: OrbitNode;
|
|
65
|
+
to: OrbitNode;
|
|
66
|
+
} | null;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One animation loop per map. Tasks (camera flights, spin, transitions,
|
|
3
|
+
* glides) advance with real elapsed time, then the map paints once per
|
|
4
|
+
* frame. The loop sleeps as soon as nothing is moving.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Advances one animation. Returns `true` while it still has work to do,
|
|
8
|
+
* `false` once it's done, or `'hold'` to keep running without anything to
|
|
9
|
+
* paint this frame (a motion too slow to show on every frame). A task that
|
|
10
|
+
* throws is reported and dropped, so the loop carries on.
|
|
11
|
+
*/
|
|
12
|
+
export type FrameTask = (now: number, elapsed: number) => boolean | 'hold';
|
|
13
|
+
type Scheduler = (callback: (now: number) => void) => number;
|
|
14
|
+
type Canceller = (handle: number) => void;
|
|
15
|
+
export declare class AnimationClock {
|
|
16
|
+
private readonly paint;
|
|
17
|
+
private readonly schedule;
|
|
18
|
+
private readonly cancel;
|
|
19
|
+
private readonly tasks;
|
|
20
|
+
private frameHandle;
|
|
21
|
+
private previousTime;
|
|
22
|
+
private paintRequested;
|
|
23
|
+
constructor(paint: () => void, schedule?: Scheduler, cancel?: Canceller);
|
|
24
|
+
/** Runs `task` every frame until it returns false. Returns a function that removes it. */
|
|
25
|
+
add(task: FrameTask): () => void;
|
|
26
|
+
/** Paints once on the next frame, without adding a task. */
|
|
27
|
+
requestPaint(): void;
|
|
28
|
+
get isRunning(): boolean;
|
|
29
|
+
stop(): void;
|
|
30
|
+
private wake;
|
|
31
|
+
private readonly tick;
|
|
32
|
+
}
|
|
33
|
+
/** Ease-in-out cubic, for camera flights and node morphs. */
|
|
34
|
+
export declare const easeInOutCubic: (progress: number) => number;
|
|
35
|
+
/** Ease-out cubic, for entrances and small settles. */
|
|
36
|
+
export declare const easeOutCubic: (progress: number) => number;
|
|
37
|
+
/** Maps `progress` from the window [start, end] to [0, 1], clamped. */
|
|
38
|
+
export declare const within: (progress: number, start: number, end: number) => number;
|
|
39
|
+
export declare const interpolate: (from: number, to: number, progress: number) => number;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Camera math. A camera is the world point shown at the viewport's center
|
|
3
|
+
* and a zoom factor. Everything is plain geometry so it can be unit-tested
|
|
4
|
+
* without a DOM.
|
|
5
|
+
*/
|
|
6
|
+
export interface Camera {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
scale: number;
|
|
10
|
+
}
|
|
11
|
+
export interface Viewport {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
}
|
|
15
|
+
export interface Point {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
}
|
|
19
|
+
/** Maps world points onto the screen: `p ↦ (p − center) × scale + viewport center`. */
|
|
20
|
+
export declare const worldToScreen: (camera: Camera, viewport: Viewport, point: Point) => Point;
|
|
21
|
+
export declare const screenToWorld: (camera: Camera, viewport: Viewport, point: Point) => Point;
|
|
22
|
+
/** SVG `transform` for the world group. */
|
|
23
|
+
export declare const cameraTransform: (camera: Camera, viewport: Viewport) => string;
|
|
24
|
+
/** Zooms by `factor` keeping the world point under `anchor` (screen coordinates) in place. */
|
|
25
|
+
export declare const zoomAround: (camera: Camera, viewport: Viewport, factor: number, anchor: Point) => Camera;
|
|
26
|
+
/** Moves the camera so the content shifts by a screen-space delta. */
|
|
27
|
+
export declare const panBy: (camera: Camera, deltaX: number, deltaY: number) => Camera;
|
|
28
|
+
/**
|
|
29
|
+
* A camera that keeps `center` at the middle of the viewport and fits
|
|
30
|
+
* content reaching `extent` away from it on each axis, inside `padding`.
|
|
31
|
+
*/
|
|
32
|
+
/** Room the page's own controls take at the viewport's edges, in px. */
|
|
33
|
+
export interface Insets {
|
|
34
|
+
top: number;
|
|
35
|
+
right: number;
|
|
36
|
+
bottom: number;
|
|
37
|
+
left: number;
|
|
38
|
+
}
|
|
39
|
+
export declare const NO_INSETS: Insets;
|
|
40
|
+
/**
|
|
41
|
+
* The camera that shows `extent` around `center`, `padding` px from the
|
|
42
|
+
* edges of what `insets` leave of the viewport, and centered there.
|
|
43
|
+
*/
|
|
44
|
+
export declare const fitAround: (center: Point, extent: Point, viewport: Viewport, padding: number, maximumScale: number, insets?: Insets) => Camera;
|
|
45
|
+
/** A similarity transform `p ↦ p × scale + (x, y)`, used to place one scene inside another. */
|
|
46
|
+
export interface Similarity {
|
|
47
|
+
scale: number;
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
}
|
|
51
|
+
export declare const IDENTITY: Similarity;
|
|
52
|
+
export declare const applySimilarity: (transform: Similarity, point: Point) => Point;
|
|
53
|
+
export declare const invertSimilarity: (transform: Similarity) => Similarity;
|
|
54
|
+
/** `outer ∘ inner`: apply `inner` first, then `outer`. */
|
|
55
|
+
export declare const composeSimilarity: (outer: Similarity, inner: Similarity) => Similarity;
|
|
56
|
+
/** The same view expressed in coordinates transformed by `transform`. */
|
|
57
|
+
export declare const transformCamera: (transform: Similarity, camera: Camera) => Camera;
|
|
58
|
+
export interface CameraPath {
|
|
59
|
+
/** The camera at `progress` ∈ [0, 1]. */
|
|
60
|
+
at(progress: number): Camera;
|
|
61
|
+
/** Path length in the paper's units; flights take time proportional to it. */
|
|
62
|
+
length: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Van Wijk & Nuij, "Smooth and efficient zooming and panning" (2003): the
|
|
66
|
+
* path that zooms out a little, travels, then zooms in, so the start and the
|
|
67
|
+
* destination stay in view for as long as possible. It is the same path
|
|
68
|
+
* d3's `interpolateZoom` follows.
|
|
69
|
+
*/
|
|
70
|
+
export declare const smoothZoomPath: (from: Camera, to: Camera, viewport: Viewport) => CameraPath;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small color helpers: parse the formats browsers report for computed
|
|
3
|
+
* colors, mix in OKLab like CSS `color-mix(in oklab, …)`, measure WCAG
|
|
4
|
+
* contrast to choose label colors, and resolve the map's theme tokens into
|
|
5
|
+
* plain hex colors for exports that leave the page.
|
|
6
|
+
*/
|
|
7
|
+
/** sRGB channels and alpha, each 0–1. */
|
|
8
|
+
export interface Rgb {
|
|
9
|
+
red: number;
|
|
10
|
+
green: number;
|
|
11
|
+
blue: number;
|
|
12
|
+
alpha: number;
|
|
13
|
+
}
|
|
14
|
+
export declare const parseColor: (input: string) => Rgb | null;
|
|
15
|
+
export declare const toHex: (color: Rgb) => string;
|
|
16
|
+
/** A color's OKLCH coordinates: lightness (0–1), chroma and hue in degrees. */
|
|
17
|
+
export interface Oklch {
|
|
18
|
+
lightness: number;
|
|
19
|
+
chroma: number;
|
|
20
|
+
hue: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const toOklch: (color: Rgb) => Oklch;
|
|
23
|
+
/**
|
|
24
|
+
* A color of `hue` (OKLCH degrees) at a Material tone: as much of `chroma` as
|
|
25
|
+
* sRGB can show at that luminance, so every hue at one tone has the same
|
|
26
|
+
* contrast with every other tone.
|
|
27
|
+
*/
|
|
28
|
+
export declare const toneColor: (hue: number, chroma: number, tone: number) => Rgb;
|
|
29
|
+
/** `color-mix(in oklab, first amount, second)` with `amount` from 0 to 1. */
|
|
30
|
+
export declare const mixOklab: (first: Rgb, second: Rgb, amount: number) => Rgb;
|
|
31
|
+
/** WCAG relative luminance (0–1) of a color's sRGB channels, ignoring alpha. */
|
|
32
|
+
export declare const relativeLuminance: (color: Rgb) => number;
|
|
33
|
+
/** WCAG contrast ratio (1–21) between two opaque colors. */
|
|
34
|
+
export declare const contrastRatio: (first: Rgb, second: Rgb) => number;
|
|
35
|
+
/**
|
|
36
|
+
* Whether `lightText` reads better than `darkText` on `fill`: the one with
|
|
37
|
+
* more contrast wins, a tie going to the light text. When the text colors
|
|
38
|
+
* can't be parsed, light text goes on fills darker than mid-gray.
|
|
39
|
+
*/
|
|
40
|
+
export declare const prefersLightText: (fill: string, lightText: string, darkText: string) => boolean;
|
|
41
|
+
/** A color as an opaque hex value and an opacity, for SVG attributes that design tools read. */
|
|
42
|
+
export declare const splitAlpha: (color: string) => {
|
|
43
|
+
color: string;
|
|
44
|
+
opacity: number;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Resolves `var(--_orbit-token)` references and `color-mix(in oklab, …)`
|
|
48
|
+
* into a hex color using concrete token values. Returns the input unchanged
|
|
49
|
+
* when part of it can't be resolved.
|
|
50
|
+
*/
|
|
51
|
+
export declare const resolveColor: (value: string, tokens: Record<string, string>) => string;
|