@robr0/design-system 0.9.0 → 0.11.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 (99) hide show
  1. package/README.md +16 -10
  2. package/components/AgentPlan/AgentPlan.css +14 -3
  3. package/components/AiButton/AiButton.css +1 -1
  4. package/components/Alert/Alert.css +9 -0
  5. package/components/AlertDialog/AlertDialog.css +3 -1
  6. package/components/AlertDialog/AlertDialog.js +2 -3
  7. package/components/AppSidebar/AppSidebar.css +22 -3
  8. package/components/AppSidebar/AppSidebar.d.ts +6 -2
  9. package/components/AppSidebar/AppSidebar.js +67 -36
  10. package/components/Card/Card.css +7 -2
  11. package/components/CardStack/CardStack.css +106 -0
  12. package/components/CardStack/CardStack.d.ts +44 -0
  13. package/components/CardStack/CardStack.js +140 -0
  14. package/components/Carousel/Carousel.css +9 -0
  15. package/components/Carousel/Carousel.js +37 -4
  16. package/components/Chart/AreaChart.js +6 -5
  17. package/components/Chart/BarChart.js +1 -1
  18. package/components/Chart/LineChart.js +4 -3
  19. package/components/Chart/PieChart.js +2 -15
  20. package/components/Chart/RadarChart.js +5 -4
  21. package/components/Chart/RadialChart.js +2 -15
  22. package/components/Chart/ScatterChart.js +3 -13
  23. package/components/Chart/StackedBarChart.js +2 -15
  24. package/components/Chart/Treemap.js +3 -17
  25. package/components/Chart/palette.d.ts +1 -0
  26. package/components/Chart/palette.js +19 -0
  27. package/components/ChatMarker/ChatMarker.css +9 -0
  28. package/components/ChatMessage/ChatMessage.css +16 -0
  29. package/components/ChatThread/ChatThread.js +2 -2
  30. package/components/Chip/Chip.css +9 -0
  31. package/components/CodeBlock/CodeBlock.css +10 -1
  32. package/components/CodeBlock/CodeBlock.js +2 -1
  33. package/components/ColorPicker/ColorPicker.js +10 -0
  34. package/components/Combobox/Combobox.css +9 -0
  35. package/components/CommandPalette/CommandPalette.css +9 -0
  36. package/components/CommandPalette/CommandPalette.js +31 -5
  37. package/components/Composer/Composer.css +118 -0
  38. package/components/Composer/Composer.d.ts +7 -0
  39. package/components/Composer/Composer.js +7 -1
  40. package/components/ContactCard/ContactCard.css +9 -0
  41. package/components/ContextMenu/ContextMenu.js +39 -3
  42. package/components/DatePicker/DatePicker.js +16 -0
  43. package/components/Dialog/Dialog.css +3 -1
  44. package/components/Dialog/Dialog.js +5 -4
  45. package/components/DocumentChip/DocumentChip.css +9 -0
  46. package/components/Dropdown/Dropdown.js +22 -3
  47. package/components/DropdownMenu/DropdownMenu.js +43 -6
  48. package/components/EmptyState/EmptyState.css +9 -0
  49. package/components/FileInput/FileInput.css +9 -0
  50. package/components/Globe/Globe.css +155 -0
  51. package/components/Globe/Globe.d.ts +96 -0
  52. package/components/Globe/Globe.js +415 -0
  53. package/components/InterruptCard/InterruptCard.css +27 -17
  54. package/components/InterruptCard/InterruptCard.d.ts +1 -1
  55. package/components/InterruptCard/InterruptCard.js +1 -1
  56. package/components/MapCallout/MapCallout.css +46 -0
  57. package/components/MapCallout/MapCallout.d.ts +29 -0
  58. package/components/MapCallout/MapCallout.js +17 -0
  59. package/components/MapLegend/MapLegend.css +88 -0
  60. package/components/MapLegend/MapLegend.d.ts +39 -0
  61. package/components/MapLegend/MapLegend.js +68 -0
  62. package/components/MessageActions/MessageActions.css +9 -0
  63. package/components/MessageCard/MessageCard.css +68 -16
  64. package/components/MessageCard/MessageCard.d.ts +1 -1
  65. package/components/MessageCard/MessageCard.js +6 -4
  66. package/components/ModelPicker/ModelPicker.css +4 -1
  67. package/components/ModelPicker/ModelPicker.js +43 -1
  68. package/components/NotificationCenter/NotificationCenter.css +9 -0
  69. package/components/NotificationCenter/NotificationCenter.js +26 -10
  70. package/components/NumberInput/NumberInput.css +9 -0
  71. package/components/Popover/Popover.css +3 -1
  72. package/components/Popover/Popover.js +2 -1
  73. package/components/SectionTitle/SectionTitle.css +8 -0
  74. package/components/SectionTitle/SectionTitle.d.ts +3 -1
  75. package/components/SectionTitle/SectionTitle.js +6 -1
  76. package/components/SourceChip/SourceChip.css +9 -0
  77. package/components/Stat/Stat.css +9 -0
  78. package/components/Stepper/Stepper.css +9 -0
  79. package/components/TagInput/TagInput.css +9 -0
  80. package/components/TimePicker/TimePicker.js +4 -1
  81. package/components/Toast/Toast.css +32 -11
  82. package/components/Toast/Toast.js +5 -4
  83. package/components/ToggleGroup/ToggleGroup.css +9 -0
  84. package/components/ToolCall/ToolCall.css +18 -6
  85. package/components/Tooltip/Tooltip.js +20 -16
  86. package/components/registry.json +37 -0
  87. package/components/registry.json.d.ts +37 -0
  88. package/components/registry.json.js +2 -2
  89. package/index.d.ts +4 -0
  90. package/index.js +8 -0
  91. package/package.json +5 -1
  92. package/tokens/motion.d.ts +23 -0
  93. package/tokens/motion.js +14 -0
  94. package/tokens/registry.json +17 -0
  95. package/tokens/registry.json.d.ts +17 -0
  96. package/tokens/registry.json.js +1 -1
  97. package/tokens/tokens-dark.css +28 -13
  98. package/tokens/tokens-light.css +26 -12
  99. package/tokens/tokens-typography.css +20 -0
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { jsxs, jsx } from "react/jsx-runtime";
3
- import React, { useState, useRef, useCallback, useEffect } from "react";
3
+ import React, { useState, useRef, useId, useCallback, useEffect } from "react";
4
+ import { MOTION_HOVER_HIDE_DELAY_MS } from "../../tokens/motion.js";
4
5
  import "./DropdownMenu.css";
5
6
  import "../../fonts/material-symbols.css";
6
7
  function collectItems(entries) {
@@ -15,7 +16,7 @@ function collectItems(entries) {
15
16
  }
16
17
  return result;
17
18
  }
18
- const SubMenuItem = ({ item, baseClass, focused, size, onActivate }) => {
19
+ const SubMenuItem = ({ item, baseClass, itemId, focused, size, onActivate }) => {
19
20
  const [subOpen, setSubOpen] = useState(false);
20
21
  const timeoutRef = useRef(null);
21
22
  const handleMouseEnter = () => {
@@ -23,7 +24,7 @@ const SubMenuItem = ({ item, baseClass, focused, size, onActivate }) => {
23
24
  setSubOpen(true);
24
25
  };
25
26
  const handleMouseLeave = () => {
26
- timeoutRef.current = setTimeout(() => setSubOpen(false), 150);
27
+ timeoutRef.current = setTimeout(() => setSubOpen(false), MOTION_HOVER_HIDE_DELAY_MS);
27
28
  };
28
29
  useEffect(() => {
29
30
  return () => {
@@ -45,6 +46,7 @@ const SubMenuItem = ({ item, baseClass, focused, size, onActivate }) => {
45
46
  return /* @__PURE__ */ jsxs(
46
47
  "li",
47
48
  {
49
+ id: itemId,
48
50
  className: classes,
49
51
  role: "menuitem",
50
52
  "aria-haspopup": "menu",
@@ -67,6 +69,7 @@ const SubMenuItem = ({ item, baseClass, focused, size, onActivate }) => {
67
69
  {
68
70
  entries: item.children,
69
71
  baseClass,
72
+ itemIdBase: `${itemId}-sub`,
70
73
  size,
71
74
  isSubmenu: true,
72
75
  onItemActivate: onActivate
@@ -79,6 +82,7 @@ const SubMenuItem = ({ item, baseClass, focused, size, onActivate }) => {
79
82
  const MenuPanel = ({
80
83
  entries,
81
84
  baseClass,
85
+ itemIdBase,
82
86
  size,
83
87
  isSubmenu = false,
84
88
  onItemActivate
@@ -88,14 +92,15 @@ const MenuPanel = ({
88
92
  isSubmenu ? `${baseClass}__submenu` : "",
89
93
  size === "compact" ? `${baseClass}__panel--compact` : ""
90
94
  ].filter(Boolean).join(" ");
91
- const renderEntry = (entry, index) => {
95
+ const renderEntry = (entry, index, idBase) => {
96
+ const entryId = `${idBase}-${index}`;
92
97
  if (entry.type === "separator") {
93
98
  return /* @__PURE__ */ jsx("li", { className: `${baseClass}__separator`, role: "separator" }, `sep-${index}`);
94
99
  }
95
100
  if (entry.type === "group") {
96
101
  return /* @__PURE__ */ jsxs("li", { className: `${baseClass}__group`, role: "group", "aria-label": entry.label, children: [
97
102
  /* @__PURE__ */ jsx("span", { className: `${baseClass}__group-label`, children: entry.label }),
98
- /* @__PURE__ */ jsx("ul", { className: `${baseClass}__group-list`, role: "group", children: entry.items.map((subEntry, subIndex) => renderEntry(subEntry, subIndex)) })
103
+ /* @__PURE__ */ jsx("ul", { className: `${baseClass}__group-list`, role: "group", children: entry.items.map((subEntry, subIndex) => renderEntry(subEntry, subIndex, entryId)) })
99
104
  ] }, `group-${index}`);
100
105
  }
101
106
  if (entry.children && entry.children.length > 0) {
@@ -104,6 +109,7 @@ const MenuPanel = ({
104
109
  {
105
110
  item: entry,
106
111
  baseClass,
112
+ itemId: entryId,
107
113
  focused: false,
108
114
  size,
109
115
  onActivate: onItemActivate
@@ -119,6 +125,7 @@ const MenuPanel = ({
119
125
  return /* @__PURE__ */ jsxs(
120
126
  "li",
121
127
  {
128
+ id: entryId,
122
129
  className: itemClasses,
123
130
  role: "menuitem",
124
131
  "aria-disabled": entry.disabled || void 0,
@@ -140,7 +147,7 @@ const MenuPanel = ({
140
147
  `item-${index}`
141
148
  );
142
149
  };
143
- return /* @__PURE__ */ jsx("ul", { className: panelClasses, role: "menu", children: entries.map((entry, index) => renderEntry(entry, index)) });
150
+ return /* @__PURE__ */ jsx("ul", { className: panelClasses, role: "menu", children: entries.map((entry, index) => renderEntry(entry, index, itemIdBase)) });
144
151
  };
145
152
  const DropdownMenu = ({
146
153
  trigger,
@@ -153,9 +160,12 @@ const DropdownMenu = ({
153
160
  const [focusedIndex, setFocusedIndex] = useState(-1);
154
161
  const rootRef = useRef(null);
155
162
  const panelRef = useRef(null);
163
+ const generatedId = useId();
156
164
  const baseClass = "ds-dropdown-menu";
157
165
  const classes = [baseClass, className].filter(Boolean).join(" ");
158
166
  const flatItems = collectItems(items);
167
+ const menuId = `${generatedId}-menu`;
168
+ const activeDescendantId = isOpen && focusedIndex >= 0 ? `${generatedId}-item-${focusedIndex}` : void 0;
159
169
  const handleToggle = () => {
160
170
  setIsOpen((prev) => {
161
171
  if (!prev) setFocusedIndex(-1);
@@ -214,6 +224,26 @@ const DropdownMenu = ({
214
224
  });
215
225
  }
216
226
  break;
227
+ case "Home":
228
+ if (isOpen) {
229
+ e.preventDefault();
230
+ setFocusedIndex((prev) => {
231
+ let next = 0;
232
+ while (next < flatItems.length && flatItems[next].disabled) next++;
233
+ return next < flatItems.length ? next : prev;
234
+ });
235
+ }
236
+ break;
237
+ case "End":
238
+ if (isOpen) {
239
+ e.preventDefault();
240
+ setFocusedIndex((prev) => {
241
+ let next = flatItems.length - 1;
242
+ while (next >= 0 && flatItems[next].disabled) next--;
243
+ return next >= 0 ? next : prev;
244
+ });
245
+ }
246
+ break;
217
247
  case "Escape":
218
248
  case "Tab":
219
249
  handleClose();
@@ -248,6 +278,7 @@ const DropdownMenu = ({
248
278
  {
249
279
  item: entry,
250
280
  baseClass,
281
+ itemId: `${generatedId}-item-${myIndex}`,
251
282
  focused: isFocused,
252
283
  size,
253
284
  onActivate: handleClose
@@ -264,6 +295,7 @@ const DropdownMenu = ({
264
295
  return /* @__PURE__ */ jsxs(
265
296
  "li",
266
297
  {
298
+ id: `${generatedId}-item-${myIndex}`,
267
299
  className: itemClasses,
268
300
  role: "menuitem",
269
301
  "aria-disabled": entry.disabled || void 0,
@@ -295,6 +327,8 @@ const DropdownMenu = ({
295
327
  /* @__PURE__ */ jsx("div", { className: `${baseClass}__trigger`, children: React.isValidElement(trigger) ? React.cloneElement(trigger, {
296
328
  "aria-haspopup": "menu",
297
329
  "aria-expanded": isOpen,
330
+ "aria-controls": isOpen ? menuId : void 0,
331
+ "aria-activedescendant": activeDescendantId,
298
332
  onClick: handleToggle,
299
333
  onKeyDown: handleKeyDown
300
334
  }) : /* @__PURE__ */ jsx(
@@ -303,6 +337,8 @@ const DropdownMenu = ({
303
337
  type: "button",
304
338
  "aria-haspopup": "menu",
305
339
  "aria-expanded": isOpen,
340
+ "aria-controls": isOpen ? menuId : void 0,
341
+ "aria-activedescendant": activeDescendantId,
306
342
  onClick: handleToggle,
307
343
  onKeyDown: handleKeyDown,
308
344
  children: trigger
@@ -311,6 +347,7 @@ const DropdownMenu = ({
311
347
  isOpen && /* @__PURE__ */ jsx(
312
348
  "ul",
313
349
  {
350
+ id: menuId,
314
351
  className: panelClasses,
315
352
  role: "menu",
316
353
  ref: (el) => {
@@ -113,3 +113,12 @@
113
113
  line-height: var(--font-paragraph-em-line-height);
114
114
  letter-spacing: var(--font-paragraph-em-letter-spacing);
115
115
  }
116
+
117
+ /* Icons take the colour of the text around them. Explicit, not just
118
+ inherited by default: a consumer stylesheet that sets a colour on
119
+ .material-symbols-rounded itself (a common global default) would
120
+ otherwise override inheritance and detach the icon from the state
121
+ colours this component sets on its parents. */
122
+ .ds-empty-state .material-symbols-rounded {
123
+ color: inherit;
124
+ }
@@ -270,3 +270,12 @@
270
270
  .ds-file-input--compact .ds-file-input__file {
271
271
  padding: var(--padding-xs) var(--padding-sm); /* 6px 8px */
272
272
  }
273
+
274
+ /* Icons take the colour of the text around them. Explicit, not just
275
+ inherited by default: a consumer stylesheet that sets a colour on
276
+ .material-symbols-rounded itself (a common global default) would
277
+ otherwise override inheritance and detach the icon from the state
278
+ colours this component sets on its parents. */
279
+ .ds-file-input .material-symbols-rounded {
280
+ color: inherit;
281
+ }
@@ -0,0 +1,155 @@
1
+ /* ============================================
2
+ GLOBE COMPONENT
3
+ An orthographic globe: graticule, markers and
4
+ great-circle arcs. Every colour is a token; the
5
+ stroke widths are SVG geometry in viewBox units,
6
+ like Sparkline's, and scale with the drawing.
7
+ ============================================ */
8
+
9
+ /* Base */
10
+
11
+ .ds-globe {
12
+ position: relative;
13
+ display: block;
14
+ width: 100%;
15
+ aspect-ratio: 1;
16
+ color: var(--color-text-primary);
17
+ border-radius: var(--radius-md);
18
+ outline: none;
19
+ touch-action: none;
20
+ user-select: none;
21
+ -webkit-user-select: none;
22
+ }
23
+
24
+ .ds-globe:focus-visible {
25
+ outline: var(--border-md) solid var(--color-action-primary-bg);
26
+ outline-offset: var(--padding-xxs);
27
+ }
28
+
29
+ .ds-globe--interactive {
30
+ cursor: grab;
31
+ }
32
+
33
+ .ds-globe--dragging {
34
+ cursor: grabbing;
35
+ }
36
+
37
+ .ds-globe__svg {
38
+ display: block;
39
+ width: 100%;
40
+ height: 100%;
41
+ overflow: visible;
42
+ }
43
+
44
+ /* Sphere */
45
+
46
+ .ds-globe__limb {
47
+ fill: none;
48
+ stroke: var(--color-text-tertiary);
49
+ stroke-width: 1;
50
+ opacity: 0.6;
51
+ }
52
+
53
+ .ds-globe__graticule {
54
+ fill: none;
55
+ stroke: var(--color-divider);
56
+ stroke-width: 1;
57
+ }
58
+
59
+ .ds-globe__graticule-back {
60
+ fill: none;
61
+ stroke: var(--color-divider);
62
+ stroke-width: 1;
63
+ stroke-dasharray: 2 4;
64
+ opacity: 0.5;
65
+ }
66
+
67
+ /* Arcs — the default gradient runs along the cobalt-to-violet end of the
68
+ chart series; a per-arc `color` replaces it with a flat stroke. */
69
+
70
+ .ds-globe__arc-stop-start {
71
+ stop-color: var(--color-chart-series-7);
72
+ }
73
+
74
+ .ds-globe__arc-stop-end {
75
+ stop-color: var(--color-chart-series-5);
76
+ }
77
+
78
+ .ds-globe__arc {
79
+ fill: none;
80
+ stroke-width: 1.5;
81
+ stroke-linecap: round;
82
+ stroke-linejoin: round;
83
+ }
84
+
85
+ .ds-globe__arc-back {
86
+ fill: none;
87
+ stroke-width: 1;
88
+ stroke-linecap: round;
89
+ opacity: 0.15;
90
+ }
91
+
92
+ /* Markers */
93
+
94
+ .ds-globe__point {
95
+ color: var(--color-text-secondary);
96
+ transition: color var(--motion-duration-fast) var(--motion-ease-standard);
97
+ }
98
+
99
+ .ds-globe__point--back {
100
+ opacity: 0.3;
101
+ }
102
+
103
+ .ds-globe__point--active,
104
+ .ds-globe__point:hover {
105
+ color: var(--color-text-primary);
106
+ }
107
+
108
+ .ds-globe__hit {
109
+ fill: transparent;
110
+ stroke: none;
111
+ pointer-events: all;
112
+ }
113
+
114
+ .ds-globe--interactive .ds-globe__point {
115
+ cursor: pointer;
116
+ }
117
+
118
+ .ds-globe__glyph {
119
+ fill: none;
120
+ stroke: currentColor;
121
+ stroke-width: 1.5;
122
+ stroke-linecap: round;
123
+ transform-box: fill-box;
124
+ transform-origin: center;
125
+ transition: transform var(--motion-duration-fast) var(--motion-ease-emphasized);
126
+ }
127
+
128
+ .ds-globe__point--active .ds-globe__glyph {
129
+ transform: scale(1.4);
130
+ }
131
+
132
+ .ds-globe__label {
133
+ font-family: var(--font-family-code);
134
+ font-size: var(--font-caption-size);
135
+ fill: var(--color-text-tertiary);
136
+ pointer-events: none;
137
+ }
138
+
139
+ .ds-globe__point--active .ds-globe__label {
140
+ fill: var(--color-text-primary);
141
+ }
142
+
143
+ /* Callout overlay — positioned at the marker, opening away from the centre. */
144
+
145
+ .ds-globe__callout {
146
+ position: absolute;
147
+ pointer-events: none;
148
+ padding: 0 var(--padding-md);
149
+ transform: translate(0, -100%);
150
+ white-space: nowrap;
151
+ }
152
+
153
+ .ds-globe__callout[data-side='left'] {
154
+ transform: translate(-100%, -100%);
155
+ }
@@ -0,0 +1,96 @@
1
+ import { default as React } from 'react';
2
+ /** A place on the globe. */
3
+ export interface GlobePoint {
4
+ /** Stable identifier, referenced by arcs and by `activePointId`. */
5
+ id: string;
6
+ /** Latitude in degrees, north positive. */
7
+ lat: number;
8
+ /** Longitude in degrees, east positive. */
9
+ lng: number;
10
+ /** Short label drawn beside the marker when `showLabels` is on. */
11
+ label?: string;
12
+ /**
13
+ * Marker glyph. `point` is a cross (something that moves or listens),
14
+ * `anchor` is a square (something fixed). The glyph is the only difference.
15
+ */
16
+ kind?: 'point' | 'anchor';
17
+ }
18
+ /** A great-circle arc between two points. */
19
+ export interface GlobeArc {
20
+ /** `id` of the point the arc leaves. */
21
+ from: string;
22
+ /** `id` of the point the arc reaches. */
23
+ to: string;
24
+ /**
25
+ * Stroke colour, any CSS colour (`var(--color-chart-series-3)` works).
26
+ * Omit for the default cobalt-to-violet gradient along the arc.
27
+ */
28
+ color?: string;
29
+ /** How far the arc lifts off the surface at its midpoint, as a fraction of the radius. */
30
+ altitude?: number;
31
+ }
32
+ /** Where the globe is looking: `[longitude, latitude]` of the centre, in degrees. */
33
+ export type GlobeRotation = [number, number];
34
+ /** Props owned by Globe itself — everything else falls through to the root `<div>`. */
35
+ type GlobeOwnProps = {
36
+ /** The places to mark. */
37
+ points?: GlobePoint[];
38
+ /** The arcs to draw between them. An arc whose endpoint is not in `points` is skipped. */
39
+ arcs?: GlobeArc[];
40
+ /**
41
+ * Controlled view: `[longitude, latitude]` of the centre, in degrees.
42
+ * Pair with `onRotationChange`. Omit to let the globe own its rotation.
43
+ */
44
+ rotation?: GlobeRotation;
45
+ /** Initial view when uncontrolled. */
46
+ defaultRotation?: GlobeRotation;
47
+ /** Fires whenever the view changes — drag, keys, or the auto-rotation. */
48
+ onRotationChange?: (rotation: GlobeRotation) => void;
49
+ /**
50
+ * Spin slowly on its own, in degrees per second. Pauses while the pointer
51
+ * is over the globe or it has focus, and never runs under
52
+ * `prefers-reduced-motion`. `0` switches it off.
53
+ */
54
+ autoRotate?: number;
55
+ /** Drag to rotate, and rotate with the arrow keys (or W, A, S, D) when focused. */
56
+ interactive?: boolean;
57
+ /** Degrees between graticule lines. `0` removes the graticule. */
58
+ graticuleStep?: number;
59
+ /** Draw each point's `label` beside its marker. */
60
+ showLabels?: boolean;
61
+ /** The point to single out: its marker enlarges and its callout renders. */
62
+ activePointId?: string;
63
+ /** Fires as the pointer enters a marker, and with `null` as it leaves. */
64
+ onPointHover?: (point: GlobePoint | null) => void;
65
+ /** Fires when a marker is clicked. */
66
+ onPointClick?: (point: GlobePoint) => void;
67
+ /**
68
+ * Renders the annotation for the active (or hovered) point. It is placed
69
+ * beside the marker in an HTML overlay, so any markup works; MapCallout is
70
+ * the intended filling. The overlay carries `data-side="left"|"right"` for
71
+ * which side of the marker it sits on.
72
+ */
73
+ renderCallout?: (point: GlobePoint) => React.ReactNode;
74
+ /**
75
+ * Accessible name for the globe, e.g. "Listening points across the
76
+ * network". The point and arc counts are appended for screen readers.
77
+ */
78
+ label?: string;
79
+ /** Additional CSS classes */
80
+ className?: string;
81
+ };
82
+ export interface GlobeProps extends GlobeOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof GlobeOwnProps | 'children'> {
83
+ }
84
+ /**
85
+ * Globe — an orthographic globe drawn in SVG, for showing where things are
86
+ * and what connects them: a graticule, markers at lat/lng, and great-circle
87
+ * arcs between them. No map library, no tile server, no land data; the
88
+ * graticule alone gives the sphere its shape, which is the point — this is
89
+ * for the geometry of a network, not for navigation.
90
+ *
91
+ * Colour comes from the tokens: the graticule in the divider colour, markers
92
+ * in the text colours, arcs along the cobalt-to-violet chart series. Rotate
93
+ * it by dragging, with the arrow keys when focused, or let it turn on its own.
94
+ */
95
+ export declare const Globe: React.ForwardRefExoticComponent<GlobeProps & React.RefAttributes<HTMLDivElement>>;
96
+ export {};