@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.
Files changed (124) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +168 -2
  3. package/dist/bin/orbit.js +11666 -0
  4. package/dist/bin/orbit.js.map +60 -0
  5. package/dist/chunk-fkdfgtx9.js +17295 -0
  6. package/dist/chunk-fkdfgtx9.js.map +75 -0
  7. package/dist/chunk-y748hzcr.js +82 -0
  8. package/dist/chunk-y748hzcr.js.map +10 -0
  9. package/dist/chunk-zze4tc9n.js +408 -0
  10. package/dist/chunk-zze4tc9n.js.map +10 -0
  11. package/dist/core/auto-render.d.ts +85 -0
  12. package/dist/core/branch-colors.d.ts +57 -0
  13. package/dist/core/browser.d.ts +23 -0
  14. package/dist/core/create.d.ts +23 -0
  15. package/dist/core/diagnostics.d.ts +40 -0
  16. package/dist/core/dispatch.d.ts +23 -0
  17. package/dist/core/document-options.d.ts +18 -0
  18. package/dist/core/document-source.d.ts +128 -0
  19. package/dist/core/editing.d.ts +66 -0
  20. package/dist/core/engine/animation-clock.d.ts +40 -0
  21. package/dist/core/engine/camera.d.ts +70 -0
  22. package/dist/core/engine/colors.d.ts +51 -0
  23. package/dist/core/engine/display.d.ts +125 -0
  24. package/dist/core/engine/export.d.ts +32 -0
  25. package/dist/core/engine/glide.d.ts +34 -0
  26. package/dist/core/engine/labels.d.ts +106 -0
  27. package/dist/core/engine/node-drag.d.ts +49 -0
  28. package/dist/core/engine/scene.d.ts +160 -0
  29. package/dist/core/engine/spin.d.ts +62 -0
  30. package/dist/core/engine/surface-pattern.d.ts +20 -0
  31. package/dist/core/engine/text-measure.d.ts +116 -0
  32. package/dist/core/engine/views.d.ts +361 -0
  33. package/dist/core/extensions.d.ts +155 -0
  34. package/dist/core/format-upgrades.d.ts +33 -0
  35. package/dist/core/index.d.ts +46 -0
  36. package/dist/core/input-controller.d.ts +116 -0
  37. package/dist/core/languages.d.ts +201 -0
  38. package/dist/core/layout.d.ts +61 -0
  39. package/dist/core/map-tools/definitions.d.ts +71 -0
  40. package/dist/core/map-tools/input.d.ts +62 -0
  41. package/dist/core/map-tools/reading.d.ts +40 -0
  42. package/dist/core/map-tools/tools.d.ts +51 -0
  43. package/dist/core/markdown-writing.d.ts +87 -0
  44. package/dist/core/material.d.ts +25 -0
  45. package/dist/core/media.d.ts +42 -0
  46. package/dist/core/node-attributes.d.ts +31 -0
  47. package/dist/core/node-links.d.ts +25 -0
  48. package/dist/core/other-apps/freemind.d.ts +8 -0
  49. package/dist/core/other-apps/icons.d.ts +16 -0
  50. package/dist/core/other-apps/ideas.d.ts +76 -0
  51. package/dist/core/other-apps/import.d.ts +28 -0
  52. package/dist/core/other-apps/inflate.d.ts +22 -0
  53. package/dist/core/other-apps/markup.d.ts +51 -0
  54. package/dist/core/other-apps/notes.d.ts +80 -0
  55. package/dist/core/other-apps/opml.d.ts +26 -0
  56. package/dist/core/other-apps/reading.d.ts +36 -0
  57. package/dist/core/other-apps/xmind.d.ts +14 -0
  58. package/dist/core/other-apps/zip.d.ts +37 -0
  59. package/dist/core/parser-markdown.d.ts +42 -0
  60. package/dist/core/parser-yaml.d.ts +8 -0
  61. package/dist/core/print-layout.d.ts +70 -0
  62. package/dist/core/render-to-svg.d.ts +57 -0
  63. package/dist/core/renderer/content-painter.d.ts +30 -0
  64. package/dist/core/renderer/dom.d.ts +15 -0
  65. package/dist/core/renderer/families.d.ts +35 -0
  66. package/dist/core/renderer/label-painter.d.ts +93 -0
  67. package/dist/core/renderer/node-painter.d.ts +113 -0
  68. package/dist/core/renderer/numbers.d.ts +2 -0
  69. package/dist/core/renderer/options.d.ts +12 -0
  70. package/dist/core/renderer/rings-and-links.d.ts +23 -0
  71. package/dist/core/renderer/scene-helpers.d.ts +33 -0
  72. package/dist/core/renderer/trees.d.ts +22 -0
  73. package/dist/core/serializer-markdown.d.ts +18 -0
  74. package/dist/core/serializer-yaml.d.ts +2 -0
  75. package/dist/core/source-patch.d.ts +24 -0
  76. package/dist/core/source.d.ts +27 -0
  77. package/dist/core/styles.d.ts +6 -0
  78. package/dist/core/suggest.d.ts +8 -0
  79. package/dist/core/svg-renderer.d.ts +626 -0
  80. package/dist/core/text-layout.d.ts +54 -0
  81. package/dist/core/themes.d.ts +62 -0
  82. package/dist/core/types.d.ts +471 -0
  83. package/dist/core/ui/actions.d.ts +75 -0
  84. package/dist/core/ui/controls.d.ts +61 -0
  85. package/dist/core/ui/detail-sheet.d.ts +88 -0
  86. package/dist/core/ui/frames.d.ts +11 -0
  87. package/dist/core/ui/icons.d.ts +14 -0
  88. package/dist/core/ui/inline-editor.d.ts +79 -0
  89. package/dist/core/ui/media-players.d.ts +65 -0
  90. package/dist/core/ui/media-viewer.d.ts +169 -0
  91. package/dist/core/ui/media-zoom.d.ts +51 -0
  92. package/dist/core/ui/note-markdown.d.ts +19 -0
  93. package/dist/core/ui/outline.d.ts +44 -0
  94. package/dist/core/url-guard.d.ts +40 -0
  95. package/dist/core/utils.d.ts +23 -0
  96. package/dist/core/web-page/page.d.ts +59 -0
  97. package/dist/core/web-page/runtime.d.ts +13 -0
  98. package/dist/core/web-page/start.d.ts +1 -0
  99. package/dist/core/yaml-mini.d.ts +54 -0
  100. package/dist/index.d.ts +1 -0
  101. package/dist/index.js +4357 -0
  102. package/dist/index.js.map +29 -0
  103. package/dist/marked/index.d.ts +31 -0
  104. package/dist/marked/index.js +110 -0
  105. package/dist/marked/index.js.map +10 -0
  106. package/dist/react/index.d.ts +55 -0
  107. package/dist/react/index.js +352 -0
  108. package/dist/react/index.js.map +1 -0
  109. package/dist/web-page.d.ts +2 -0
  110. package/dist/web-page.js +130 -0
  111. package/llms-full.txt +2785 -0
  112. package/llms.txt +36 -0
  113. package/package.json +118 -4
  114. package/skills/orbit/SKILL.md +140 -0
  115. package/skills/orbit/references/editing.md +195 -0
  116. package/skills/orbit/references/extending.md +247 -0
  117. package/skills/orbit/references/format.md +331 -0
  118. package/skills/orbit/references/guide.md +546 -0
  119. package/skills/orbit/references/import-export.md +115 -0
  120. package/skills/orbit/references/languages.md +160 -0
  121. package/skills/orbit/references/map-tools.md +188 -0
  122. package/skills/orbit/references/media.md +160 -0
  123. package/skills/orbit/references/recipes.md +236 -0
  124. package/skills/orbit/references/theming.md +199 -0
@@ -0,0 +1,46 @@
1
+ export { parseOrbitMarkdown, SUPPORTED_SCHEMA_VERSION } from './parser-markdown.js';
2
+ export { DIAGNOSTIC_CODES, OrbitParseError, formatDiagnostic } from './diagnostics.js';
3
+ export type { OrbitDiagnostic, OrbitDiagnosticCode, OrbitDiagnosticSeverity } from './diagnostics.js';
4
+ export type { ParseOptions } from './parser-markdown.js';
5
+ export { parseOrbitYAML } from './parser-yaml.js';
6
+ export type { ParseYamlOptions } from './parser-yaml.js';
7
+ export { serializeOrbitMarkdown } from './serializer-markdown.js';
8
+ export type { SerializeOptions } from './serializer-markdown.js';
9
+ export { serializeOrbitYAML } from './serializer-yaml.js';
10
+ export { documentToRendererOptions } from './document-options.js';
11
+ export { OrbitSVGRenderer } from './svg-renderer.js';
12
+ export { createOrbitMap } from './create.js';
13
+ export { renderToSVGString } from './render-to-svg.js';
14
+ export { PRINT_THEMES, printTheme, renderPrintLayout } from './print-layout.js';
15
+ export type { OrbitPrintOptions } from './print-layout.js';
16
+ export { exportWebPage } from './web-page/page.js';
17
+ export type { OrbitWebPageOptions } from './web-page/page.js';
18
+ export { createMapTools } from './map-tools/tools.js';
19
+ export type { MapTools, MapToolsOptions, MapToolResult } from './map-tools/tools.js';
20
+ export type { MapToolDefinition, MapToolFormats, MapToolName, MapToolProvider } from './map-tools/definitions.js';
21
+ export type { MapToolProperty, MapToolSchema } from './map-tools/input.js';
22
+ export type { RenderToSVGOptions } from './render-to-svg.js';
23
+ export { detectImportFormat, importMap } from './other-apps/import.js';
24
+ export { importOPML, exportOPML } from './other-apps/opml.js';
25
+ export type { OrbitOPMLOptions } from './other-apps/opml.js';
26
+ export { importFreeMind } from './other-apps/freemind.js';
27
+ export { importXMind } from './other-apps/xmind.js';
28
+ export { IMPORT_ERROR_CODES, IMPORT_WARNING_CODES, OrbitImportError } from './other-apps/ideas.js';
29
+ export type { OrbitImportErrorCode, OrbitImportWarning, OrbitImportWarningCode } from './other-apps/ideas.js';
30
+ export type { OrbitImport, OrbitImportedMap, OrbitImportFormat, OrbitImportOptions } from './other-apps/reading.js';
31
+ export { renderNoteMarkdown } from './ui/note-markdown.js';
32
+ export type { NoteRenderContext as OrbitNoteOptions } from './ui/note-markdown.js';
33
+ export type { CreateOrbitMapOptions } from './create.js';
34
+ export { defineOrbitMapElement, renderOrbitElement, renderOrbitMarkdownBlocks } from './auto-render.js';
35
+ export type { AutoRenderOptions, OrbitMapElement, OrbitRenderErrorDetail } from './auto-render.js';
36
+ export { findNodeById, getNodePath } from './utils.js';
37
+ export { ORBIT_THEME_PRESETS, THEME_TOKENS, isOrbitThemePreset, isThemeName, registerTheme, themeNames, themeTokens } from './themes.js';
38
+ export type { OrbitThemeName, OrbitThemeToken, OrbitThemeTokens } from './themes.js';
39
+ export { MATERIAL_SEED, materialTheme } from './material.js';
40
+ export type { MaterialThemeOptions } from './material.js';
41
+ export { registerAction, registerNodeType, registerStatus, upgradeNodeTypes } from './extensions.js';
42
+ export { languageTags, registerLanguage } from './languages.js';
43
+ export type { OrbitPluralText, OrbitStrings } from './languages.js';
44
+ export type { OrbitAction, OrbitNodeType, OrbitStatusStyle, OrbitStatusTone } from './extensions.js';
45
+ export type { OrbitDocument, OrbitDocumentOptions, ParsedOrbitDocument, OrbitNode, OrbitActionEvent, OrbitActionDetail, OrbitContentAction, OrbitEdit, OrbitEditorEvent, OrbitEventMap, OrbitEventName, OrbitInsets, OrbitMediaEvent, OrbitMediaOptions, OrbitMediaState, OrbitNewNode, OrbitNodeContextEvent, OrbitNodeDragEvent, OrbitNodeInput, OrbitRendererTheme, OrbitSpinOptions, OrbitThemePreset, OrbitZoomOptions, RendererOptions, ViewMode, } from './types.js';
46
+ export { parseOrbit } from './dispatch.js';
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Pointer gestures for the map: tap, long press, spin (focus mode), pan
3
+ * (overview), pinch, wheel, double tap, and dragging a node that a held
4
+ * press lifted. The controller only recognizes gestures; the renderer
5
+ * decides what they do.
6
+ *
7
+ * Two properties are load-bearing for touch: pointerdown is never
8
+ * preventDefault-ed (that would suppress the `click` every tap relies on),
9
+ * and native scrolling is managed with `touch-action` in the stylesheet.
10
+ * Pointer capture is taken only once a drag engages, so taps keep native
11
+ * targeting.
12
+ */
13
+ export interface Point {
14
+ x: number;
15
+ y: number;
16
+ }
17
+ /** What a one-finger drag starting at a point does. */
18
+ export type DragGesture = 'spin' | 'pan' | 'none';
19
+ export interface GestureCallbacks {
20
+ isInteractive(): boolean;
21
+ /** What dragging from this point (container coordinates) does. */
22
+ dragGesture(point: Point): DragGesture;
23
+ /** The orbit's center on screen. */
24
+ spinCenter(): Point;
25
+ /** True while the orbit coasts: the next press catches it. */
26
+ isCoasting(): boolean;
27
+ onCatch(): void;
28
+ onSpinStart(time: number, angle: number): void;
29
+ onSpinMove(time: number, angle: number): void;
30
+ /** `cancelled` when the browser took the pointer over (to scroll, say): no fling. */
31
+ onSpinEnd(time: number, cancelled: boolean): void;
32
+ onPanStart(time: number): void;
33
+ onPan(deltaX: number, deltaY: number, time: number): void;
34
+ onPanEnd(time: number, cancelled: boolean): void;
35
+ /** Zoom by `factor` around `center`, and pan by how far the center moved. */
36
+ onPinch(factor: number, center: Point, deltaX: number, deltaY: number): void;
37
+ onPinchEnd(): void;
38
+ onWheel(event: WheelEvent, point: Point): void;
39
+ onDoubleTap(point: Point, target: EventTarget | null): void;
40
+ /**
41
+ * A touch or pen held still on `target`. Returns whether the map took it:
42
+ * the press then neither taps nor spins.
43
+ */
44
+ onLongPress(point: Point, target: EventTarget | null): boolean;
45
+ /**
46
+ * A press held still on `target`: whether it lifted a node, which moving
47
+ * the press then drags (see `onNodeDrag`). Touches and pens get here after
48
+ * `onLongPress`; a mouse held still gets here alone, with no menu.
49
+ */
50
+ onHold(point: Point, target: EventTarget | null): boolean;
51
+ /**
52
+ * The lifted node follows the press: `move` as it moves, then `drop` where
53
+ * it's let go (moved or not), or `cancel` when the press is taken away.
54
+ */
55
+ onNodeDrag(point: Point, phase: 'move' | 'drop' | 'cancel'): void;
56
+ /** How long (ms) a still touch takes to become a long press. */
57
+ longPressDelay(): number;
58
+ onDraggingChange(dragging: boolean): void;
59
+ }
60
+ export declare class InputController {
61
+ private element;
62
+ private readonly container;
63
+ private readonly callbacks;
64
+ private readonly pointers;
65
+ private gesture;
66
+ private engaged;
67
+ private startPoint;
68
+ private lastPoint;
69
+ /**
70
+ * Where the map was on the page when the pointers now down first touched
71
+ * it. Asking again on every move would make the browser lay out the whole
72
+ * map each time, thousands of elements on a big one, and a pointer can
73
+ * move several times a frame.
74
+ */
75
+ private gestureRectangle;
76
+ private lastPinchDistance;
77
+ private lastPinchCenter;
78
+ private suppressNextClick;
79
+ private lastTap;
80
+ private longPress;
81
+ /** The press became a long press: lifting it is no tap. */
82
+ private pressTaken;
83
+ /** The held press lifted a node: moving it drags the node. */
84
+ private lifted;
85
+ constructor(container: HTMLElement, callbacks: GestureCallbacks);
86
+ attach(element: Element): void;
87
+ detach(): void;
88
+ private reset;
89
+ private localPoint;
90
+ private angleOf;
91
+ private pinchDistance;
92
+ private pinchCenter;
93
+ private readonly handleClickCapture;
94
+ private readonly handlePointerDown;
95
+ private startLongPress;
96
+ private cancelLongPress;
97
+ private readonly handlePointerMove;
98
+ private readonly handlePointerUp;
99
+ private detectDoubleTap;
100
+ private readonly handleDoubleClick;
101
+ /**
102
+ * A lifted node is dragged, not the page: the browser mustn't scroll it
103
+ * from under the press, as it would where `touch-action` lets one finger
104
+ * scroll the page (Chromium doesn't apply `touch-action` to the shapes
105
+ * inside an SVG, so the canvas's own decides).
106
+ */
107
+ private readonly handleTouchMove;
108
+ private readonly handleWheel;
109
+ }
110
+ /**
111
+ * Zoom factor for a wheel event: the same zoom per scrolled pixel for mouse
112
+ * wheels and trackpads. Trackpad pinches arrive as wheel events with
113
+ * `ctrlKey` and small pixel deltas, so they get a stronger multiplier; a
114
+ * mouse wheel turned with Ctrl held sends large deltas and keeps the normal one.
115
+ */
116
+ export declare const wheelZoomFactor: (event: Pick<WheelEvent, "deltaY" | "deltaMode" | "ctrlKey">, pageHeight: number) => number;
@@ -0,0 +1,201 @@
1
+ /**
2
+ * The words Orbit shows and says: the controls, the detail sheet, the
3
+ * outline and what it announces, what a screen reader hears about each
4
+ * idea, the media viewer and the empty map. English and Spanish are built
5
+ * in; `registerLanguage` adds others, or changes words of one Orbit has.
6
+ *
7
+ * A map speaks the language its `language` option names, or else the one
8
+ * its element is in: the closest `lang` attribute around it, through shadow
9
+ * roots, then the document's. A language Orbit doesn't have falls back to
10
+ * its base (es-MX reads es), then to English.
11
+ */
12
+ /**
13
+ * Text that depends on a number: one form for each plural category the
14
+ * language uses (see `Intl.PluralRules`), `other` for any it leaves out.
15
+ * `{count}` is the number, written the language's way.
16
+ */
17
+ export interface OrbitPluralText {
18
+ zero?: string;
19
+ one?: string;
20
+ two?: string;
21
+ few?: string;
22
+ many?: string;
23
+ other: string;
24
+ }
25
+ /**
26
+ * Everything Orbit says, in one language. `{name}`-style placeholders are
27
+ * filled in as described on each; keep them in a translation, in any order.
28
+ */
29
+ export interface OrbitStrings {
30
+ /** The map's name for assistive technology, and an exported SVG's title, when it has no `ariaLabel` and its root no text. */
31
+ mindMap: string;
32
+ /** What assistive technology calls the map (`aria-roledescription`), in lower case. */
33
+ mindMapRole: string;
34
+ /** An idea with no text, wherever its name shows. */
35
+ untitled: string;
36
+ /** The root Orbit makes up for a map that's just a list, or has several top headings, and no title. */
37
+ untitledMap: string;
38
+ /** The message on a map with nothing in it. */
39
+ emptyMap: string;
40
+ /** The hint under it. */
41
+ emptyMapHint: string;
42
+ /** The title of the card shown where a map couldn't be drawn. */
43
+ mapNotDrawn: string;
44
+ /** The card's message when the problem came with none of its own. */
45
+ mapNotDrawnReason: string;
46
+ /** The card's message for a problem on a line of the map's source: `{line}` and `{message}`, which stays as Orbit wrote it. */
47
+ problemOnLine: string;
48
+ /** The breadcrumbs, for assistive technology. */
49
+ mapPath: string;
50
+ /** The back button, when the idea it goes back to has no name. */
51
+ back: string;
52
+ /** The back button's label: `{name}` is the idea it goes back to. */
53
+ backTo: string;
54
+ /** The back button's label when that idea has no text. */
55
+ backToParent: string;
56
+ /** The group of view buttons. */
57
+ view: string;
58
+ /** The button that shows the focused idea with the ideas around it. */
59
+ focus: string;
60
+ /** The button that shows the whole map at once. */
61
+ overview: string;
62
+ /** The button that shows the map as a list. */
63
+ showOutline: string;
64
+ /** The group of zoom buttons. */
65
+ zoom: string;
66
+ zoomIn: string;
67
+ zoomOut: string;
68
+ /** The button that zooms to fit the view. */
69
+ fitMap: string;
70
+ /** Shown when the wheel scrolls the page over a map: `{key}` is Ctrl, or ⌘ on Apple devices. */
71
+ scrollToZoom: string;
72
+ /** The map as a list, for assistive technology. */
73
+ outline: string;
74
+ /** Announced when the overview opens. */
75
+ overviewAnnouncement: string;
76
+ /** How many ideas an idea holds, as announced and in its description: `{count}`. */
77
+ ideaCount: OrbitPluralText;
78
+ /** Announced when an idea is added: `{name}`. */
79
+ added: string;
80
+ /** Announced when an idea is deleted: `{name}`. */
81
+ removed: string;
82
+ /** Announced when an idea moves: `{name}` into `{parent}`. */
83
+ moved: string;
84
+ /** Announced when an idea moves to a parent with no text: `{name}`. */
85
+ movedToTop: string;
86
+ /** `{name}` in those announcements when the idea has no text. */
87
+ anIdea: string;
88
+ /** Part of an idea's description: `{status}` is its status word. */
89
+ status: string;
90
+ /** The status in the tooltip: `{status}`. */
91
+ statusLabel: string;
92
+ /** Part of an idea's description: `{list}` lists what it has, from the words below. */
93
+ has: string;
94
+ hasDetails: string;
95
+ hasNote: string;
96
+ hasImage: string;
97
+ hasVideo: string;
98
+ hasEmbed: string;
99
+ hasLink: string;
100
+ /** The text field over an idea being renamed: `{name}`. */
101
+ textOf: string;
102
+ /** The text field for a new idea: `{name}` is the idea it goes into. */
103
+ newIdeaFor: string;
104
+ /** The empty text field's placeholder for a new idea. */
105
+ newIdea: string;
106
+ /** The + in an orbit: `{name}` is the idea it adds to. */
107
+ addIdeaTo: string;
108
+ /** Where an idea being moved would land: `{name}` is that idea. */
109
+ moveHere: string;
110
+ /** `{name}` in the text fields and the + when the idea has no text. */
111
+ thisIdea: string;
112
+ /** `{name}` in `moveHere` when the idea has no text. */
113
+ theIdea: string;
114
+ /** The buttons under an idea: `{name}`. */
115
+ ideaActions: string;
116
+ /** The buttons under an idea with no text. */
117
+ ideaActionsUntitled: string;
118
+ showDetails: string;
119
+ viewImage: string;
120
+ /** The picture in the detail sheet, which opens the viewer: `{description}` is its alternative text. */
121
+ viewImageOf: string;
122
+ playVideo: string;
123
+ openEmbed: string;
124
+ readNote: string;
125
+ openLink: string;
126
+ /** A link to another idea of the map: `{name}` is that idea, or `theIdea` when it has no text. */
127
+ goTo: string;
128
+ /** The same link printed, where it can't be followed: `{name}` is that idea. */
129
+ seeIdea: string;
130
+ /** The detail sheet's name when the idea has no text. */
131
+ details: string;
132
+ close: string;
133
+ previous: string;
134
+ next: string;
135
+ /** The button that presents a map shared as a web page, one idea at a time with its note as a caption. */
136
+ present: string;
137
+ /** The priority chip: `{priority}`. */
138
+ priority: string;
139
+ /** The button over a video in the detail sheet. */
140
+ expand: string;
141
+ /** That button, for assistive technology. */
142
+ expandVideo: string;
143
+ /** A picture's name in the viewer when it has no description or caption. */
144
+ picture: string;
145
+ /** A video's name in the viewer when it has no caption. */
146
+ video: string;
147
+ /** Where the viewer is among the map's pictures and videos: `{index}` of `{total}`. */
148
+ position: string;
149
+ /** The viewer's button that zooms the picture to fit. */
150
+ fitPicture: string;
151
+ pictureUnavailable: string;
152
+ videoUnavailable: string;
153
+ /** A video its site doesn't let other pages play. */
154
+ videoUnavailableHere: string;
155
+ openPictureInNewTab: string;
156
+ openVideoInNewTab: string;
157
+ /** A video's link to its site: `{provider}` is YouTube or Vimeo. */
158
+ watchOn: string;
159
+ }
160
+ type TextKey = {
161
+ [Key in keyof OrbitStrings]: OrbitStrings[Key] extends string ? Key : never;
162
+ }[keyof OrbitStrings];
163
+ type CountKey = {
164
+ [Key in keyof OrbitStrings]: OrbitStrings[Key] extends OrbitPluralText ? Key : never;
165
+ }[keyof OrbitStrings];
166
+ type Values = Record<string, string | number>;
167
+ /**
168
+ * Adds a language for every map, by its BCP 47 tag (`fr`, `pt-BR`), or
169
+ * changes some words of one Orbit has. Words it leaves out come from the
170
+ * language it narrows (`pt` for `pt-BR`), then English. Returns a function
171
+ * that puts the language back as it was.
172
+ */
173
+ export declare const registerLanguage: (language: string, strings: Partial<OrbitStrings>) => () => void;
174
+ /** The tags of the languages every map can speak: the built-in ones and the registered ones. */
175
+ export declare const languageTags: () => string[];
176
+ /**
177
+ * The language an element is in: the closest `lang` attribute around it,
178
+ * through shadow roots, then the document's. Null when none says.
179
+ */
180
+ export declare const languageOf: (element: Element | null | undefined) => string | null;
181
+ /** The words of one map: its language's, with the `strings` it was given on top. */
182
+ export declare class OrbitWords {
183
+ /** The tag of the language the words come from: `es` for a map asked for `es-MX`. */
184
+ readonly language: string;
185
+ /** The tag numbers, plurals and lists are written for: `es-MX` there. */
186
+ readonly locale: string;
187
+ private readonly table;
188
+ constructor(requested?: string | null, strings?: Partial<OrbitStrings>);
189
+ /** Whether these words are the same as `other`'s: the same language and the same table. */
190
+ sameAs(other: OrbitWords | null): boolean;
191
+ text(key: TextKey, values?: Values): string;
192
+ /** A text with a number in it, in the form the number takes in the language. */
193
+ count(key: CountKey, count: number, values?: Values): string;
194
+ /** Items as the language lists them: "a, b and c". */
195
+ list(items: string[]): string;
196
+ number(value: number): string;
197
+ private fill;
198
+ }
199
+ /** The words a map speaks when it's asked for `requested`, or for the language around `element`. */
200
+ export declare const wordsFor: (requested: string | undefined, element: Element | null | undefined, strings?: Partial<OrbitStrings>) => OrbitWords;
201
+ export {};
@@ -0,0 +1,61 @@
1
+ import type { OrbitNode } from './types.js';
2
+ /** Where the layout puts the map and how much room it has. */
3
+ export interface LayoutConfig {
4
+ cx: number;
5
+ cy: number;
6
+ containerWidth: number;
7
+ containerHeight: number;
8
+ /** Levels below the layout root to render; deeper nodes are omitted. */
9
+ maxDepth?: number;
10
+ /**
11
+ * Focus layouts: ring radii to keep where the orbit has as many rings,
12
+ * instead of making room for the moons again. A drag along the orbit keeps
13
+ * the rings it began with. Rings never come out smaller than the planets need.
14
+ */
15
+ keptRings?: number[];
16
+ }
17
+ /** A node with its place in the layout. */
18
+ export interface PositionedNode extends OrbitNode {
19
+ x: number;
20
+ y: number;
21
+ radius: number;
22
+ /** Degrees: 0 is right, -90 is up. */
23
+ angle: number;
24
+ /** Distance from the parent. */
25
+ orbitRadius: number;
26
+ }
27
+ /** Moons drawn around a planet; more children show as "+N". */
28
+ export declare const MOON_LIMIT = 6;
29
+ /** Where a planet's moons go: `distance` from its center, at `offsets` degrees from the direction away from the sun. */
30
+ export interface MoonPlacement {
31
+ distance: number;
32
+ radius: number;
33
+ offsets: number[];
34
+ }
35
+ /** The moons of a planet fan out on its outer side, 30° apart, 150° at most. */
36
+ export declare const moonPlacement: (planetRadius: number, moonCount: number) => MoonPlacement;
37
+ /**
38
+ * Calculate layout for focus mode (center sun + direct children).
39
+ * The orbit radius is never clamped below the collision-free radius. If the
40
+ * result is wider than the container, the renderer auto-fits the whole group.
41
+ */
42
+ export declare const calculateFocusLayout: (focusedNode: OrbitNode, config: LayoutConfig) => {
43
+ sun: PositionedNode;
44
+ planets: PositionedNode[];
45
+ orbitRadius: number;
46
+ orbitRings: number[];
47
+ };
48
+ /**
49
+ * Calculate layout for all mode. Each node owns a measured subtree circle; a
50
+ * parent's child orbit is sized so sibling subtree circles cannot overlap.
51
+ */
52
+ export declare const calculateAllLayout: (node: OrbitNode, config: LayoutConfig, parentAngle?: number) => PositionedNode[];
53
+ /**
54
+ * The rings of the overview: one around each node with children, through them.
55
+ */
56
+ export declare const getOrbitRings: (positionedNodes: PositionedNode[]) => {
57
+ centerId: string;
58
+ cx: number;
59
+ cy: number;
60
+ r: number;
61
+ }[];
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The map tools as a model sees them: names, descriptions and inputs, and
3
+ * the shapes each provider's API takes them in.
4
+ */
5
+ import { type Fields, type MapToolSchema } from './input.js';
6
+ export type MapToolName = 'read_map' | 'find_nodes' | 'read_node' | 'add_nodes' | 'update_node' | 'move_node' | 'reorder_children' | 'remove_node' | 'show_node';
7
+ /** A tool as `MapTools.definitions` lists it: the shape MCP uses, and the data to build any other. */
8
+ export type MapToolDefinition = {
9
+ name: MapToolName;
10
+ description: string;
11
+ /** The tool's input, as JSON Schema. */
12
+ inputSchema: MapToolSchema;
13
+ /** Hints for clients that ask before running some tools: whether it only reads, and whether it can remove or overwrite what's there. */
14
+ annotations: {
15
+ readOnlyHint: boolean;
16
+ destructiveHint: boolean;
17
+ };
18
+ };
19
+ /** The tools in the shape each provider's API takes them. */
20
+ export type MapToolFormats = {
21
+ /** Anthropic's Messages API (`tools`). */
22
+ anthropic: {
23
+ name: string;
24
+ description: string;
25
+ input_schema: MapToolSchema;
26
+ }[];
27
+ /** OpenAI's Responses API (`tools`). */
28
+ openai: {
29
+ type: 'function';
30
+ name: string;
31
+ description: string;
32
+ parameters: MapToolSchema;
33
+ strict: false;
34
+ }[];
35
+ /** OpenAI's Chat Completions API (`tools`), which most other providers and local servers take too. */
36
+ 'openai-chat': {
37
+ type: 'function';
38
+ function: {
39
+ name: string;
40
+ description: string;
41
+ parameters: MapToolSchema;
42
+ };
43
+ }[];
44
+ /** Google's Gemini API (`config.tools` in `@google/genai`). */
45
+ gemini: {
46
+ functionDeclarations: {
47
+ name: string;
48
+ description: string;
49
+ parametersJsonSchema: MapToolSchema;
50
+ }[];
51
+ }[];
52
+ };
53
+ export type MapToolProvider = keyof MapToolFormats;
54
+ /** A tool, before it's written as a definition. */
55
+ export interface ToolSpec {
56
+ name: MapToolName;
57
+ description: string;
58
+ fields: Fields;
59
+ /** Other names models give its fields, lowercase. */
60
+ synonyms?: Record<string, string>;
61
+ readOnly: boolean;
62
+ destructive: boolean;
63
+ }
64
+ /** The attributes `update_node` sets and `clear` removes. */
65
+ export declare const ATTRIBUTES: readonly ["note", "status", "priority", "tags", "icon", "color", "link", "image", "video", "embed", "collapsed"];
66
+ export type ToolAttribute = (typeof ATTRIBUTES)[number];
67
+ /** Every tool, in the order they're offered. `show_node` is only for a map on screen. */
68
+ export declare const TOOL_SPECS: readonly ToolSpec[];
69
+ export declare const definitionOf: (spec: ToolSpec) => MapToolDefinition;
70
+ /** The definitions in the shape `provider`'s API takes. */
71
+ export declare const formatDefinitions: <Provider extends MapToolProvider>(definitions: readonly MapToolDefinition[], provider: Provider) => MapToolFormats[Provider];
@@ -0,0 +1,62 @@
1
+ /**
2
+ * What each map tool takes, written once: as the JSON Schema a model reads,
3
+ * and as the checks a call goes through before anything changes. The checks
4
+ * forgive what models often send (a number as text, a list as words
5
+ * separated by commas, null for a field they leave out, a field's usual
6
+ * other name) and explain the rest in words a model can act on.
7
+ */
8
+ export type FieldType = 'string' | 'integer' | 'number' | 'boolean' | 'list' | 'record';
9
+ export interface Field {
10
+ type: FieldType;
11
+ description: string;
12
+ required?: boolean;
13
+ /** The words a list takes. */
14
+ values?: readonly string[];
15
+ /** The smallest number it takes. */
16
+ minimum?: number;
17
+ /** A record's own fields. Text alone stands for the first one: a picture's address for `{ src }`. */
18
+ fields?: Fields;
19
+ }
20
+ export type Fields = Record<string, Field>;
21
+ /** A property of a tool's input, as JSON Schema. */
22
+ export type MapToolProperty = {
23
+ type: 'string' | 'integer' | 'number' | 'boolean' | 'array' | 'object';
24
+ description: string;
25
+ minimum?: number;
26
+ items?: {
27
+ type: 'string';
28
+ enum?: string[];
29
+ };
30
+ properties?: Record<string, MapToolProperty>;
31
+ required?: string[];
32
+ };
33
+ /** A tool's input, as JSON Schema: an object with the tool's fields. */
34
+ export type MapToolSchema = {
35
+ type: 'object';
36
+ properties: Record<string, MapToolProperty>;
37
+ required?: string[];
38
+ };
39
+ /** The JSON Schema for an object with `fields`. */
40
+ export declare const schemaOf: (fields: Fields) => MapToolSchema;
41
+ /** A call's input, read: its values, and the fields it gave that the tool doesn't take, which were left out. */
42
+ export interface ReadInput {
43
+ values: Record<string, unknown>;
44
+ ignored: string[];
45
+ }
46
+ /** Thrown with a message for the model when a call's input can't be used. */
47
+ export declare class InputError extends Error {
48
+ }
49
+ /**
50
+ * Reads a call's input for `tool`: an object, or the JSON text of one, as
51
+ * OpenAI sends it. Null stands for a field left out. A field under another
52
+ * name it often goes by (`synonyms`) counts as that field; one that looks
53
+ * like a misspelled field is an error, so nothing changes by mistake; any
54
+ * other is left out, and reported.
55
+ */
56
+ export declare const readInput: (tool: string, fields: Fields, input: unknown, synonyms?: Readonly<Record<string, string>>) => ReadInput;
57
+ /** Whether `record` has `key` of its own, not one every object inherits, such as `constructor`. */
58
+ export declare const owns: (record: object, key: string) => boolean;
59
+ /** A value, as an error message names it. */
60
+ export declare const describe: (value: unknown) => string;
61
+ /** "a, b and c" */
62
+ export declare const list: (words: readonly string[]) => string;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The map as the tools describe it to a model: an outline with each node's
3
+ * id, everything about one node, and search results. Plain text, short on
4
+ * tokens: a line a node, with what an edit needs to know.
5
+ */
6
+ import type { OrbitNode } from '../types.js';
7
+ /** A node as the tools name it in a sentence: its title and id. */
8
+ export declare const nameOf: (node: OrbitNode) => string;
9
+ /** A node's line in an outline: its title, its id, and its attributes. */
10
+ export declare const outlineLine: (node: OrbitNode, depth: number) => string;
11
+ /** A node and `levels` levels under it as outline lines; what's further down is counted. */
12
+ export declare const outlineOf: (node: OrbitNode, depth?: number, levels?: number) => string[];
13
+ /**
14
+ * The outline read_map gives: `start` and up to `levels` levels under it,
15
+ * as many whole levels as fit in `limit` nodes, so the shape of a big map
16
+ * shows, with what's left out counted. `complete` when nothing asked for
17
+ * was left out.
18
+ */
19
+ export declare const readOutline: (start: OrbitNode, levels: number, limit: number) => {
20
+ lines: string[];
21
+ complete: boolean;
22
+ };
23
+ /** How many nodes are under a node, at any depth. */
24
+ export declare const descendants: (node: OrbitNode) => number;
25
+ /** "1 node", "3 nodes" */
26
+ export declare const count: (amount: number, one: string, many?: string) => string;
27
+ /** Everything about a node, for read_node. */
28
+ export declare const nodeDetails: (root: OrbitNode, node: OrbitNode, path: OrbitNode[]) => string;
29
+ /** The nodes whose link, or a link in whose note, points at `target`. */
30
+ export declare const nodesLinkingTo: (root: OrbitNode, target: OrbitNode) => OrbitNode[];
31
+ /** Text as search compares it: lowercase, without accents. */
32
+ export declare const searchable: (text: string) => string;
33
+ /** What find_nodes looks for. */
34
+ export interface Search {
35
+ query?: string;
36
+ status?: string;
37
+ tag?: string;
38
+ }
39
+ /** The nodes that match, titles matching first, as find_nodes lists them. */
40
+ export declare const findNodes: (root: OrbitNode, search: Search) => string;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Map tools: what a language model needs to read a map and change it, from
3
+ * any provider. The definitions come in each provider's shape, and `run`
4
+ * carries out a call on a map on screen, where each change animates into
5
+ * place and fires `edit` as anyone's would, or on a document without one,
6
+ * on a server. A call that can't be carried out changes nothing and says
7
+ * why, in words a model can act on: the id it meant, a move that can't be
8
+ * made, a value the map can't use.
9
+ */
10
+ import type { OrbitDocument } from '../types.js';
11
+ import type { OrbitSVGRenderer } from '../svg-renderer.js';
12
+ import { type MapToolDefinition, type MapToolFormats, type MapToolProvider } from './definitions.js';
13
+ export interface MapToolsOptions {
14
+ /** Offer only the tools that read the map, for an assistant that answers questions about it. Default false. */
15
+ readOnly?: boolean;
16
+ /** The most nodes `read_map` shows at once; a bigger map is cut short, whole levels first. Default 250. */
17
+ readLimit?: number;
18
+ }
19
+ /** What a tool call did, to send back to the model. */
20
+ export interface MapToolResult {
21
+ /** False when the call couldn't be carried out: nothing changed, and `text` says why and what to send instead. */
22
+ ok: boolean;
23
+ /** What happened, for the model, with the ids to use next. */
24
+ text: string;
25
+ /** Whether the map changed. */
26
+ changed: boolean;
27
+ }
28
+ /** Map tools for one map (see `createMapTools`). */
29
+ export interface MapTools {
30
+ /** The tools: name, description, input as JSON Schema, and hints. The shape MCP takes, and the data for any other. */
31
+ readonly definitions: MapToolDefinition[];
32
+ /** How to use the tools, to add to the model's system prompt. */
33
+ readonly instructions: string;
34
+ /** The tools in the shape a provider's API takes: `anthropic`, `openai` (Responses), `openai-chat` (Chat Completions, and most other providers) or `gemini`. */
35
+ for<Provider extends MapToolProvider>(provider: Provider): MapToolFormats[Provider];
36
+ /**
37
+ * Carries out a tool call: its name, and its input as an object or as
38
+ * the JSON text OpenAI sends. Never throws for a call a model gets wrong:
39
+ * the result says what went wrong instead.
40
+ */
41
+ run(name: string, input?: unknown): MapToolResult;
42
+ /** The map as it is now. Edits change it in place. */
43
+ readonly document: OrbitDocument | null;
44
+ }
45
+ /**
46
+ * Tools a language model calls to read and edit a map: on screen (an
47
+ * `OrbitSVGRenderer`, such as `createOrbitMap` returns or `<orbit-map>`'s
48
+ * `renderer`), where each change animates and fires `edit`, or a document
49
+ * (or its markdown or YAML), which they change in place.
50
+ */
51
+ export declare const createMapTools: (map: OrbitSVGRenderer | OrbitDocument | string, options?: MapToolsOptions) => MapTools;