@ksp-gonogo/ui-kit 0.2.0-rc.12 → 0.2.0-rc.8

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/dist/index.d.ts CHANGED
@@ -25,17 +25,10 @@ interface DefaultThemeProviderProps {
25
25
  *
26
26
  * Kit components read `theme.colors` and throw without a theme in scope, so
27
27
  * wrap anything that renders them outside the app (a test, a story, a
28
- * standalone page) in this. The theme's values are CSS variables, which
29
- * `@ksp-gonogo/ui-kit/tokens.css` defines: import that sheet once, or every
30
- * colour and size is unset.
28
+ * standalone page) in this.
31
29
  *
32
30
  * @example
33
31
  * ```tsx
34
- * import "@ksp-gonogo/ui-kit/tokens.css";
35
- * import { value } from "@ksp-gonogo/sitrep-sdk";
36
- * import { DefaultThemeProvider, Meter } from "@ksp-gonogo/ui-kit";
37
- * import { render } from "@testing-library/react";
38
- *
39
32
  * render(
40
33
  * <DefaultThemeProvider>
41
34
  * <Meter label="Charge" value={value("ratio", 0.4)} />
@@ -153,9 +146,7 @@ interface UiKitTheme {
153
146
  * `default-dark`: the built-in mission-control theme, and the one the app
154
147
  * mounts. Every colour and size is a CSS variable string (such as
155
148
  * `var(--color-text-primary)`), so responsive overrides such as larger type on
156
- * a touch screen still apply when a component reads the theme. The variables
157
- * are defined by `@ksp-gonogo/ui-kit/tokens.css`, which has to be imported
158
- * once for any of them to have a value.
149
+ * a touch screen still apply when a component reads the theme.
159
150
  *
160
151
  * @category Theme
161
152
  */
@@ -927,16 +918,17 @@ type ReckoningKind = "held" | "modelled";
927
918
  */
928
919
  type MarkKind = "current" | ReckoningKind;
929
920
  /**
930
- * The spec for each kind. `held` is a square in the warning hue; `modelled`
931
- * is a triangle, point up, in the modelled hue and about a pixel larger, so
932
- * the two weigh alike at small sizes.
921
+ * The spec for each kind. `held` is a square in the warning hue, a stop sign
922
+ * for data that has stopped; `modelled` is a
923
+ * triangle, point up, in the modelled hue and about a pixel larger, so the two
924
+ * weigh alike at small sizes.
933
925
  *
934
926
  * Each also has a hollow form, drawn where the figure is `elsewhere`: of
935
927
  * something other than what its label names. Hollow says that and nothing
936
928
  * else; the shape and the hue go on saying how current the figure is. A hollow
937
- * mark is drawn larger than its filled twin, at `hollowDomSize`. `current` has
938
- * only the hollow form, a ring: a current figure of the thing its label names
939
- * carries no mark at all.
929
+ * mark is larger than its filled twin (`hollowDomSize`), because at the filled
930
+ * size the hole closes up. `current` has only the hollow form, a ring: a
931
+ * current figure of the thing its label names carries no mark at all.
940
932
  *
941
933
  * @category Unit
942
934
  */
@@ -1169,23 +1161,15 @@ interface UnitProps<UnitSymbol extends string = string> extends Omit<FormatQuant
1169
1161
  *
1170
1162
  * @example
1171
1163
  * ```tsx
1172
- * import { useTelemetry, value } from "@ksp-gonogo/sitrep-sdk";
1173
- * import { Stack, Unit } from "@ksp-gonogo/ui-kit";
1174
- *
1175
- * function Readouts(props: { bodyRadiusMetres: number }) {
1176
- * const flight = useTelemetry("vessel.flight");
1177
- * // The first three are fields of a Topic, each a whole Reading, so each
1178
- * // draws the held mark when the Topic goes quiet. The last is a bare
1179
- * // number, wrapped with its SI unit.
1180
- * return (
1181
- * <Stack>
1182
- * <Unit value={flight.altitudeAsl} />
1183
- * <Unit value={flight.verticalSpeed} decimals={1} />
1184
- * <Unit value={flight.surfaceSpeed} format="km/h" />
1185
- * <Unit value={value("m", props.bodyRadiusMetres)} />
1186
- * </Stack>
1187
- * );
1188
- * }
1164
+ * import { value } from "@ksp-gonogo/sitrep-sdk";
1165
+ * import { Unit } from "@ksp-gonogo/ui-kit";
1166
+ *
1167
+ * // A whole Reading: draws the held mark when the channel goes quiet.
1168
+ * <Unit value={rangeReading} />
1169
+ * // A bare number off a payload, wrapped with its SI unit.
1170
+ * <Unit value={value("m", body.radius)} />
1171
+ * <Unit value={value("m/s", closingSpeed)} decimals={1} />
1172
+ * <Unit value={value("m/s", surfaceSpeed)} format="km/h" />
1189
1173
  * ```
1190
1174
  *
1191
1175
  * @category Unit
@@ -1456,19 +1440,13 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
1456
1440
  *
1457
1441
  * @example
1458
1442
  * ```tsx
1459
- * import { Button, CheckIcon, Cluster } from "@ksp-gonogo/ui-kit";
1460
- *
1461
- * function SaveBar(props: { onCancel: () => void; onSave: () => void }) {
1462
- * return (
1463
- * <Cluster justify="end">
1464
- * <Button variant="ghost" onClick={props.onCancel}>Cancel</Button>
1465
- * <Button variant="primary" onClick={props.onSave}>
1466
- * <CheckIcon />
1467
- * Save
1468
- * </Button>
1469
- * </Cluster>
1470
- * );
1471
- * }
1443
+ * <Cluster justify="end">
1444
+ * <Button variant="ghost" onClick={onCancel}>Cancel</Button>
1445
+ * <Button variant="primary" onClick={onSave}>
1446
+ * <CheckIcon />
1447
+ * Save
1448
+ * </Button>
1449
+ * </Cluster>
1472
1450
  * ```
1473
1451
  *
1474
1452
  * @category Button
@@ -1490,15 +1468,9 @@ declare const TextButton: styled_components_dist_types.IStyledComponentBase<"web
1490
1468
  *
1491
1469
  * @example
1492
1470
  * ```tsx
1493
- * import { CloseIcon, IconButton } from "@ksp-gonogo/ui-kit";
1494
- *
1495
- * function CloseButton(props: { onClose: () => void }) {
1496
- * return (
1497
- * <IconButton aria-label="Close" onClick={props.onClose}>
1498
- * <CloseIcon />
1499
- * </IconButton>
1500
- * );
1501
- * }
1471
+ * <IconButton aria-label="Close" onClick={onClose}>
1472
+ * <CloseIcon />
1473
+ * </IconButton>
1502
1474
  * ```
1503
1475
  *
1504
1476
  * @category Button
@@ -1602,8 +1574,8 @@ interface CardProps extends BlockProps {
1602
1574
  * resource's own colour, a category's hue. Not a status, which is `tone`;
1603
1575
  * a card can have both.
1604
1576
  *
1605
- * A CSS colour, not a resource name: resolve a name first with
1606
- * {@link resourceColor}, as in `identityColor={resourceColor(name)}`.
1577
+ * A CSS colour, not a resource name: resolve a name first, e.g.
1578
+ * `identityColor={resourceColor(name)}`.
1607
1579
  */
1608
1580
  identityColor?: string;
1609
1581
  /**
@@ -1796,70 +1768,49 @@ interface ComboboxListboxProps<Option extends ComboboxOption> {
1796
1768
  *
1797
1769
  * @example
1798
1770
  * ```tsx
1799
- * import { useId, useState } from "react";
1800
- * import {
1801
- * type ComboboxOption,
1802
- * ComboboxListbox,
1803
- * filterComboboxOptions,
1804
- * flattenComboboxGroups,
1805
- * groupComboboxOptions,
1806
- * Input,
1807
- * moveComboboxActiveIndex,
1808
- * } from "@ksp-gonogo/ui-kit";
1809
- *
1810
- * function BodyPicker(props: {
1811
- * options: readonly ComboboxOption[];
1812
- * selected: string | undefined;
1813
- * onPick: (key: string) => void;
1814
- * }) {
1815
- * const [query, setQuery] = useState("");
1816
- * const [open, setOpen] = useState(false);
1817
- * const [active, setActive] = useState(-1);
1818
- * const listId = useId();
1819
- * const optionId = (key: string) => `${listId}-${key}`;
1820
- * const groups = groupComboboxOptions(filterComboboxOptions(props.options, query));
1821
- * const flat = flattenComboboxGroups(groups);
1822
- * // The list can shrink under the highlighted row, so it is looked up, never assumed.
1823
- * const activeOption = flat[active];
1824
- *
1825
- * return (
1826
- * <div style={{ position: "relative" }}>
1827
- * <Input
1828
- * role="combobox"
1829
- * aria-label="Body"
1830
- * aria-expanded={open}
1831
- * aria-controls={listId}
1832
- * aria-autocomplete="list"
1833
- * aria-activedescendant={activeOption ? optionId(activeOption.key) : undefined}
1834
- * value={query}
1835
- * onFocus={() => setOpen(true)}
1836
- * onBlur={() => setOpen(false)}
1837
- * onChange={(e) => {
1838
- * setQuery(e.target.value);
1839
- * setActive(-1);
1840
- * }}
1841
- * onKeyDown={(e) => {
1842
- * if (e.key === "ArrowDown") setActive((i) => moveComboboxActiveIndex(i, 1, flat.length));
1843
- * if (e.key === "ArrowUp") setActive((i) => moveComboboxActiveIndex(i, -1, flat.length));
1844
- * if (e.key === "Enter" && activeOption) props.onPick(activeOption.key);
1845
- * if (e.key === "Escape") setOpen(false);
1846
- * }}
1847
- * />
1848
- * {open && (
1849
- * <ComboboxListbox
1850
- * id={listId}
1851
- * groups={groups}
1852
- * flatOptions={flat}
1853
- * activeIndex={active}
1854
- * selectedKey={props.selected}
1855
- * getOptionId={optionId}
1856
- * onHoverIndex={setActive}
1857
- * onSelectKey={props.onPick}
1858
- * />
1859
- * )}
1860
- * </div>
1861
- * );
1862
- * }
1771
+ * const [query, setQuery] = useState("");
1772
+ * const [open, setOpen] = useState(false);
1773
+ * const [active, setActive] = useState(-1);
1774
+ * const listId = useId();
1775
+ * const optionId = (key: string) => `${listId}-${key}`;
1776
+ * const groups = groupComboboxOptions(filterComboboxOptions(options, query));
1777
+ * const flat = flattenComboboxGroups(groups);
1778
+ *
1779
+ * <div style={{ position: "relative" }}>
1780
+ * <Input
1781
+ * role="combobox"
1782
+ * aria-label="Body"
1783
+ * aria-expanded={open}
1784
+ * aria-controls={listId}
1785
+ * aria-autocomplete="list"
1786
+ * aria-activedescendant={active >= 0 ? optionId(flat[active].key) : undefined}
1787
+ * value={query}
1788
+ * onFocus={() => setOpen(true)}
1789
+ * onBlur={() => setOpen(false)}
1790
+ * onChange={(e) => {
1791
+ * setQuery(e.target.value);
1792
+ * setActive(-1);
1793
+ * }}
1794
+ * onKeyDown={(e) => {
1795
+ * if (e.key === "ArrowDown") setActive((i) => moveComboboxActiveIndex(i, 1, flat.length));
1796
+ * if (e.key === "ArrowUp") setActive((i) => moveComboboxActiveIndex(i, -1, flat.length));
1797
+ * if (e.key === "Enter" && flat[active]) onPick(flat[active].key);
1798
+ * if (e.key === "Escape") setOpen(false);
1799
+ * }}
1800
+ * />
1801
+ * {open && (
1802
+ * <ComboboxListbox
1803
+ * id={listId}
1804
+ * groups={groups}
1805
+ * flatOptions={flat}
1806
+ * activeIndex={active}
1807
+ * selectedKey={selected}
1808
+ * getOptionId={optionId}
1809
+ * onHoverIndex={setActive}
1810
+ * onSelectKey={onPick}
1811
+ * />
1812
+ * )}
1813
+ * </div>
1863
1814
  * ```
1864
1815
  *
1865
1816
  * @category Form
@@ -3572,8 +3523,21 @@ interface ContributionSlotEntry {
3572
3523
  * Uplink fills any widget's header badges by contributing to
3573
3524
  * `"<widget-id>.badges"` with its handle's `registerContribution`, without the
3574
3525
  * widget declaring the slot. `compute` returns {@link BadgeEntry} items. How
3575
- * the panel draws them, and a whole example, are under Standard slots on
3576
- * {@link Panel}.
3526
+ * the panel draws them is under Standard slots on {@link Panel}.
3527
+ *
3528
+ * @example
3529
+ * ```ts
3530
+ * EXAMPLE.registerContribution({
3531
+ * id: "cadence-badge",
3532
+ * contributes: "space-center-status.badges",
3533
+ * deps: ["example.heartbeat"],
3534
+ * requires: "example",
3535
+ * compute: (topics) =>
3536
+ * topics["example.heartbeat"]
3537
+ * ? [{ id: "cadence", label: "Publishing", tone: "info" as const }]
3538
+ * : null,
3539
+ * });
3540
+ * ```
3577
3541
  *
3578
3542
  * @category Panel
3579
3543
  */
@@ -3957,27 +3921,21 @@ interface DialProps<Unit extends string = string> {
3957
3921
  *
3958
3922
  * @example A heading compass
3959
3923
  * ```tsx
3960
- * import { useTelemetry, value } from "@ksp-gonogo/sitrep-sdk";
3961
- * import { Dial } from "@ksp-gonogo/ui-kit";
3924
+ * import { value } from "@ksp-gonogo/sitrep-sdk";
3962
3925
  *
3963
- * function HeadingCompass() {
3964
- * const attitude = useTelemetry("vessel.attitude");
3965
- * return (
3966
- * <Dial
3967
- * value={attitude.heading}
3968
- * min={value("°", 0)}
3969
- * max={value("°", 360)}
3970
- * wrap
3971
- * ticks={[
3972
- * { value: value("°", 0), label: "N" },
3973
- * { value: value("°", 90), label: "E" },
3974
- * { value: value("°", 180), label: "S" },
3975
- * { value: value("°", 270), label: "W" },
3976
- * ]}
3977
- * ariaLabel="Heading"
3978
- * />
3979
- * );
3980
- * }
3926
+ * <Dial
3927
+ * value={headingReading}
3928
+ * min={value("°", 0)}
3929
+ * max={value("°", 360)}
3930
+ * wrap
3931
+ * ticks={[
3932
+ * { value: value("°", 0), label: "N" },
3933
+ * { value: value("°", 90), label: "E" },
3934
+ * { value: value("°", 180), label: "S" },
3935
+ * { value: value("°", 270), label: "W" },
3936
+ * ]}
3937
+ * ariaLabel="Heading"
3938
+ * />
3981
3939
  * ```
3982
3940
  *
3983
3941
  * @category Gauge
@@ -4510,11 +4468,7 @@ interface FitLabelButtonProps extends Omit<ComponentPropsWithoutRef<"button">, "
4510
4468
  *
4511
4469
  * @example
4512
4470
  * ```tsx
4513
- * import { FitLabelButton, SettingsIcon } from "@ksp-gonogo/ui-kit";
4514
- *
4515
- * function SettingsButton(props: { onOpen: () => void }) {
4516
- * return <FitLabelButton label="Settings" icon={<SettingsIcon />} onClick={props.onOpen} />;
4517
- * }
4471
+ * <FitLabelButton label="Settings" icon={<SettingsIcon />} onClick={onOpen} />
4518
4472
  * ```
4519
4473
  *
4520
4474
  * @category Button
@@ -4806,7 +4760,7 @@ interface GraphNoticeProps extends HTMLAttributes<HTMLDivElement> {
4806
4760
  * "unknown body"). `pointer-events: none`, so it never intercepts the graph's
4807
4761
  * clicks. `role="status"` by default; override via `role`.
4808
4762
  *
4809
- * @example Over a graph in a `Fill`
4763
+ * @example Over a graph in a {@link Fill}
4810
4764
  * ```tsx
4811
4765
  * <Fill>
4812
4766
  * <LineGraph series={series} ariaLabel="Altitude trend" />
@@ -5436,13 +5390,7 @@ interface LineGraphSeries {
5436
5390
  label?: string;
5437
5391
  /** CSS colour for the stroke, e.g. `var(--color-nogo-mark)`. */
5438
5392
  color: string;
5439
- /**
5440
- * The line's points, ascending by `x`. Fewer than two renders no line for
5441
- * this series. `x` and `y` are bare numbers in whatever unit the caller
5442
- * chose, the same for every series: the chart scales each axis linearly
5443
- * across the range it is given and labels neither. For a trend over time
5444
- * pass seconds as `x`, a UT or seconds ago.
5445
- */
5393
+ /** Ascending by `x`. Fewer than two points renders no line for this series. */
5446
5394
  points: ReadonlyArray<{
5447
5395
  x: number;
5448
5396
  y: number;
@@ -5512,7 +5460,6 @@ interface LineGraphProps {
5512
5460
  * renders `aria-hidden`.
5513
5461
  */
5514
5462
  ariaLabel?: string;
5515
- /** Placed on the chart's root element, for a caller's own sizing or layout. */
5516
5463
  className?: string;
5517
5464
  /**
5518
5465
  * `"chart"` (default): quarter gridlines and bare strokes. `"sparkline"`: no
@@ -5600,25 +5547,9 @@ interface LiveRegionProps {
5600
5547
  *
5601
5548
  * Polite unless `assertive`, which interrupts and is kept for ABORT-class states.
5602
5549
  *
5603
- * @example Mounted with the control, empty until there is an outcome to say
5550
+ * @example
5604
5551
  * ```tsx
5605
- * import { Button, LiveRegion } from "@ksp-gonogo/ui-kit";
5606
- * import { useState } from "react";
5607
- *
5608
- * function Deploy(props: { onDeploy: () => Promise<void> }) {
5609
- * const [outcome, setOutcome] = useState("");
5610
- * const deploy = () =>
5611
- * props.onDeploy().then(
5612
- * () => setOutcome("Deployed"),
5613
- * () => setOutcome("Deploy refused"),
5614
- * );
5615
- * return (
5616
- * <>
5617
- * <Button onClick={() => void deploy()}>Deploy</Button>
5618
- * <LiveRegion>{outcome}</LiveRegion>
5619
- * </>
5620
- * );
5621
- * }
5552
+ * <LiveRegion>{outcome}</LiveRegion>
5622
5553
  * ```
5623
5554
  *
5624
5555
  * @category Typography
@@ -5636,7 +5567,6 @@ interface LockSummary {
5636
5567
  reason: string;
5637
5568
  /** "45 science to research", or "Needs Building level 2". */
5638
5569
  hint?: string;
5639
- /** Every lock the summary was made from. Each is `{ capability, missing, detail? }`: the capability that is locked, the unlocks it still needs, and a sentence for when it names none. */
5640
5570
  locks: readonly CapabilityLock[];
5641
5571
  }
5642
5572
  /**
@@ -5931,9 +5861,9 @@ interface MeterCommonProps extends Omit<HTMLAttributes<HTMLDivElement>, "childre
5931
5861
  */
5932
5862
  tone?: Tone;
5933
5863
  /**
5934
- * Arbitrary CSS colour for the fill, such as a resource's own from
5935
- * {@link resourceColor}, for meters whose fill carries an identity rather than
5936
- * a status. Wins over `tone` for the fill colour only.
5864
+ * Arbitrary CSS colour for the fill (e.g. `resourceColor(name)`), for meters
5865
+ * whose fill carries an identity rather than a status. Wins over `tone` for
5866
+ * the fill colour only.
5937
5867
  */
5938
5868
  fillColor?: string;
5939
5869
  /**
@@ -6021,9 +5951,6 @@ interface MeterProps<UnitSymbol extends string = string> extends MeterCommonProp
6021
5951
  *
6022
5952
  * @example A fraction on its own, which must be a `ratio`
6023
5953
  * ```tsx
6024
- * import { value } from "@ksp-gonogo/sitrep-sdk";
6025
- * import { Meter } from "@ksp-gonogo/ui-kit";
6026
- *
6027
5954
  * <Meter label="Shielding" value={value("ratio", 0.72)} tone="go" />
6028
5955
  * ```
6029
5956
  *
@@ -6034,20 +5961,14 @@ interface MeterProps<UnitSymbol extends string = string> extends MeterCommonProp
6034
5961
  *
6035
5962
  * @example A bar alone with its statement under it, as work advances toward a total that can move
6036
5963
  * ```tsx
6037
- * <Meter
6038
- * hideLabel
6039
- * statement
6040
- * label="Nodes researched"
6041
- * value={value("count", 3)}
6042
- * capacity={value("count", 8)}
6043
- * />
5964
+ * <Meter hideLabel statement label="Nodes researched" value={done} capacity={queued} />
6044
5965
  * ```
6045
5966
  *
6046
5967
  * @example Row meters in a stack, sharing columns so every bar lines up
6047
5968
  * ```tsx
6048
5969
  * <MeterStack>
6049
- * <Meter label="LF" layout="row" value={value("units", 320)} capacity={value("units", 400)} />
6050
- * <Meter label="Ox" layout="row" value={value("units", 391)} capacity={value("units", 489)} />
5970
+ * <Meter label="LF" layout="row" value={liquidFuel} capacity={liquidFuelMax} />
5971
+ * <Meter label="Ox" layout="row" value={oxidizer} capacity={oxidizerMax} />
6051
5972
  * </MeterStack>
6052
5973
  * ```
6053
5974
  *
@@ -6070,9 +5991,9 @@ declare function MeterStack({ children, ...rest }: HTMLAttributes<HTMLDivElement
6070
5991
  */
6071
5992
  declare const MeterRowGroup: styled_components_dist_types.IStyledComponentBase<"web", styled_components.FastOmit<styled_components.FastOmit<react.DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref" | "key" | keyof HTMLAttributes<HTMLDivElement>> & Omit<react.DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
6072
5993
  ref?: ((instance: HTMLDivElement | null) => void | react.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof react.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | react.RefObject<HTMLDivElement> | null | undefined;
6073
- }, "id" | "title" | "about" | "resource" | "nonce" | "children" | "results" | "slot" | "style" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "enterKeyHint" | "hidden" | "lang" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "security" | "unselectable" | "inputMode" | "is" | "exportparts" | "part" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture"> & Partial<Pick<styled_components.FastOmit<react.DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref" | "key" | keyof HTMLAttributes<HTMLDivElement>> & Omit<react.DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
5994
+ }, "slot" | "style" | "title" | "dir" | "id" | "about" | "resource" | "nonce" | "children" | "results" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "className" | "contentEditable" | "contextMenu" | "draggable" | "enterKeyHint" | "hidden" | "lang" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "security" | "unselectable" | "inputMode" | "is" | "exportparts" | "part" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture"> & Partial<Pick<styled_components.FastOmit<react.DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref" | "key" | keyof HTMLAttributes<HTMLDivElement>> & Omit<react.DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
6074
5995
  ref?: ((instance: HTMLDivElement | null) => void | react.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof react.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | react.RefObject<HTMLDivElement> | null | undefined;
6075
- }, "id" | "title" | "about" | "resource" | "nonce" | "children" | "results" | "slot" | "style" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "enterKeyHint" | "hidden" | "lang" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "security" | "unselectable" | "inputMode" | "is" | "exportparts" | "part" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture">>> & string;
5996
+ }, "slot" | "style" | "title" | "dir" | "id" | "about" | "resource" | "nonce" | "children" | "results" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoCapitalize" | "autoFocus" | "className" | "contentEditable" | "contextMenu" | "draggable" | "enterKeyHint" | "hidden" | "lang" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "rev" | "typeof" | "vocab" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "security" | "unselectable" | "inputMode" | "is" | "exportparts" | "part" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture">>> & string;
6076
5997
 
6077
5998
  /**
6078
5999
  * Which clock an instant is on. Under signal delay they differ for the same
@@ -6107,9 +6028,8 @@ type TimeContext =
6107
6028
  interface MissionDateProps {
6108
6029
  /**
6109
6030
  * Universal time: seconds since the game's epoch, not a duration. A plain
6110
- * number is accepted for the client-interpolated view clock. A `Value<"s">`
6111
- * is accepted too and is read the same way, as seconds since the epoch: it
6112
- * is never drawn as a length of time here. For a length of time use `Unit`.
6031
+ * number is accepted for the client-interpolated view clock, and a
6032
+ * `Value<"s">` renders a date measured from the epoch.
6113
6033
  */
6114
6034
  value: Value<"ut"> | Value<"s"> | Reading<Value<"ut">> | Reading<Value<"s">> | number | null | undefined;
6115
6035
  /**
@@ -6228,9 +6148,8 @@ interface ModalContextValue {
6228
6148
  }
6229
6149
  /**
6230
6150
  * Holds the stack of open modal dialogs and renders them into `document.body`.
6231
- * The dashboard mounts one at its root, so a widget on the dashboard calls
6232
- * {@link useModal} without mounting its own. Anywhere else, such as a test or
6233
- * a page of your own, wrap the tree in one: `useModal` needs it above it.
6151
+ * The dashboard mounts one at its root, so a widget calls {@link useModal}
6152
+ * without mounting its own.
6234
6153
  *
6235
6154
  * Each dialog has a title bar with a close button, a scrolling body, and an
6236
6155
  * optional sticky footer set with {@link useModalSaveBar} or
@@ -6335,27 +6254,15 @@ interface ModalSaveBarOptions<Draft> {
6335
6254
  *
6336
6255
  * @example
6337
6256
  * ```tsx
6338
- * import { useMemo, useState } from "react";
6339
- * import type { ConfigComponentProps } from "@ksp-gonogo/sitrep-sdk";
6340
- * import { ConfigForm, Switch, useModalSaveBar } from "@ksp-gonogo/ui-kit";
6341
- *
6342
- * interface NavballConfig {
6343
- * controlMode?: boolean;
6344
- * }
6345
- *
6346
6257
  * function NavballConfigForm({ config, onSave }: ConfigComponentProps<NavballConfig>) {
6347
- * const [controlMode, setControlMode] = useState(config.controlMode === true);
6258
+ * const [controlMode, setControlMode] = useState(config?.controlMode === true);
6348
6259
  * const candidate = useMemo(() => ({ controlMode }), [controlMode]);
6349
6260
  * useModalSaveBar({
6350
6261
  * onSave: () => onSave(candidate),
6351
6262
  * value: candidate,
6352
- * saved: config,
6263
+ * saved: config ?? {},
6353
6264
  * });
6354
- * return (
6355
- * <ConfigForm>
6356
- * <Switch label="Control mode" checked={controlMode} onChange={setControlMode} />
6357
- * </ConfigForm>
6358
- * );
6265
+ * return <ConfigForm>...</ConfigForm>;
6359
6266
  * }
6360
6267
  * ```
6361
6268
  *
@@ -6708,8 +6615,8 @@ declare function PanelGlow({ children, railBandAbove, ...rest }: ComponentPropsW
6708
6615
  interface PanelProps extends ComponentPropsWithoutRef<"div"> {
6709
6616
  /**
6710
6617
  * The panel's heading. With it set, the panel draws its own header and pads
6711
- * its body. It is not `title`: that is the HTML tooltip attribute, which
6712
- * goes through to the panel's element like any other.
6618
+ * its body. Named `panelTitle` so it does not clash with the HTML `title`
6619
+ * tooltip attribute.
6713
6620
  */
6714
6621
  panelTitle?: ReactNode;
6715
6622
  /**
@@ -6730,9 +6637,8 @@ interface PanelProps extends ComponentPropsWithoutRef<"div"> {
6730
6637
  *
6731
6638
  * A widget that is wholly a drawing (a map, a globe) passes one
6732
6639
  * `<Section fill>` holding it. Not to be confused with the boolean
6733
- * `panelSections`, which is about the augment slot. A bare boolean is a
6734
- * type error: for a section that is sometimes absent, pass `null` in its
6735
- * place, as in `cond ? <Section /> : null`.
6640
+ * `panelSections`, which is about the augment slot. A bare boolean is
6641
+ * rejected so `sections={false}` cannot render an empty panel.
6736
6642
  */
6737
6643
  sections?: Exclude<ReactNode, boolean> | readonly ReactNode[];
6738
6644
  /**
@@ -6965,8 +6871,8 @@ declare function PanelRoot(props: PanelProps): ReactElement;
6965
6871
  *
6966
6872
  * ## Parts
6967
6873
  *
6968
- * `Panel` is built entirely from the parts below and draws nothing they do
6969
- * not, so a widget can compose a variant by hand from `Panel.Container` (the bordered frame),
6874
+ * `Panel` renders its parts and draws no markup of its own, so a widget can
6875
+ * compose a variant by hand from `Panel.Container` (the bordered frame),
6970
6876
  * `Panel.Context` (links the body's scroller to the glow), `Panel.Delay` (the
6971
6877
  * delay rail), `Panel.Header`, `Panel.Title`, `Panel.Toolbar`, `Panel.Glow`,
6972
6878
  * `Panel.Body` (the scrolling, inset content box), `Panel.Section`,
@@ -7499,39 +7405,25 @@ interface StackProps extends HTMLAttributes<HTMLDivElement> {
7499
7405
  * label/value table, and a {@link Box} for an inset well.
7500
7406
  *
7501
7407
  * @example
7502
- * `gap="section"` sets the three blocks further apart than the default
7503
- * `related` gap would.
7504
7408
  * ```tsx
7505
- * import { Box, Button, Cluster, Grid, Inline, Stack, Text } from "@ksp-gonogo/ui-kit";
7506
- *
7507
- * function TargetBody(props: {
7508
- * apoapsis: string;
7509
- * periapsis: string;
7510
- * notes: string;
7511
- * onSet: () => void;
7512
- * onClear: () => void;
7513
- * }) {
7514
- * return (
7515
- * <Stack gap="section">
7516
- * <Cluster>
7517
- * <Text>Target</Text>
7518
- * <Inline>
7519
- * <Button onClick={props.onSet}>Set</Button>
7520
- * <Button onClick={props.onClear}>Clear</Button>
7521
- * </Inline>
7522
- * </Cluster>
7523
- * <Grid cols="auto 1fr" gap="label-value" rowGap="readout-row" align="baseline">
7524
- * <Text level="muted">Apoapsis</Text>
7525
- * <Text>{props.apoapsis}</Text>
7526
- * <Text level="muted">Periapsis</Text>
7527
- * <Text>{props.periapsis}</Text>
7528
- * </Grid>
7529
- * <Box surface="sunken" pad="surface" radius="regular">
7530
- * {props.notes}
7531
- * </Box>
7532
- * </Stack>
7533
- * );
7534
- * }
7409
+ * <Stack gap="section">
7410
+ * <Cluster>
7411
+ * <Text>Target</Text>
7412
+ * <Inline>
7413
+ * <Button onClick={onSet}>Set</Button>
7414
+ * <Button onClick={onClear}>Clear</Button>
7415
+ * </Inline>
7416
+ * </Cluster>
7417
+ * <Grid cols="auto 1fr" gap="label-value" rowGap="readout-row" align="baseline">
7418
+ * <Text level="muted">Apoapsis</Text>
7419
+ * <Text>{apoapsis}</Text>
7420
+ * <Text level="muted">Periapsis</Text>
7421
+ * <Text>{periapsis}</Text>
7422
+ * </Grid>
7423
+ * <Box surface="sunken" pad="surface" radius="regular">
7424
+ * {notes}
7425
+ * </Box>
7426
+ * </Stack>
7535
7427
  * ```
7536
7428
  *
7537
7429
  * @category Layout
@@ -7994,25 +7886,16 @@ declare const PanelStatusStoreProvider: (props: {
7994
7886
  declare const usePanelStatusStore: () => PanelStatusStore | null;
7995
7887
 
7996
7888
  /**
7997
- * The short uppercase word a badge or caption prints for a `StreamStatusValue`,
7998
- * or `null` for `"live"`, which shows nothing:
7999
- *
8000
- * - `"held"`: HELD
8001
- * - `"disconnected"`: OFFLINE
8002
- * - `"last-before-blackout"`: BLACKOUT
8003
- * - `"recorded"`: RECORDED
8004
- * - `"loading"`: LOADING
8005
- * - `"no-game"`: NO GAME
8006
- * - `"resyncing"`: SYNCING
8007
- * - `"absent"`: NO DATA
7889
+ * The short uppercase word a badge or caption prints for a `StreamStatusValue`
7890
+ * (HELD, OFFLINE, BLACKOUT, RECORDED, LOADING, NO GAME, SYNCING, NO DATA), or `null` for `"live"`,
7891
+ * which shows nothing.
8008
7892
  *
8009
7893
  * @category Badge
8010
7894
  */
8011
7895
  declare function formatStreamStatus(status: StreamStatusValue): string | null;
8012
7896
  /**
8013
- * The word for a held reading's grade, the same word {@link formatStreamStatus}
8014
- * gives the status of that name, or HELD when no grade is given, as for a
8015
- * value combined from several readings.
7897
+ * The word for a held reading's grade (HELD, OFFLINE, BLACKOUT, RECORDED, LOADING or NO GAME), or
7898
+ * HELD when no grade is given, as for a value combined from several readings.
8016
7899
  *
8017
7900
  * @category Badge
8018
7901
  */
@@ -8602,9 +8485,7 @@ declare function Tooltip({ text, children, focusable, announce, }: TooltipProps)
8602
8485
  /**
8603
8486
  * An orbit path that may not be drawn, and the reason: no horizon was stated
8604
8487
  * for it, the instant on screen is past its horizon, its shape was not stated,
8605
- * the frame asked for cannot be built, or it could not be sampled. It is the
8606
- * `withheld` member of `OrbitTrajectory`, which `useOrbitTrajectory` from
8607
- * `@ksp-gonogo/sitrep-sdk/frames` returns.
8488
+ * the frame asked for cannot be built, or it could not be sampled.
8608
8489
  *
8609
8490
  * @category EmptyState
8610
8491
  */
@@ -8757,40 +8638,34 @@ interface UnitInputProps<Unit extends string = string> {
8757
8638
  * @example
8758
8639
  * ```tsx
8759
8640
  * import { value } from "@ksp-gonogo/sitrep-sdk";
8760
- * import { Stack, UnitInput } from "@ksp-gonogo/ui-kit";
8761
- * import { useState } from "react";
8641
+ * import { UnitInput } from "@ksp-gonogo/ui-kit";
8762
8642
  *
8763
- * function NodeEditor() {
8764
- * const [prograde, setPrograde] = useState(value("m/s", 0));
8765
- * const [burn, setBurn] = useState(value("s", 0));
8766
- * const [nodeUt, setNodeUt] = useState(value("ut", 0));
8767
- * return (
8768
- * <Stack>
8769
- * <UnitInput
8770
- * label="Prograde"
8771
- * unit="m/s"
8772
- * value={prograde}
8773
- * onChange={setPrograde}
8774
- * />
8775
- * <UnitInput
8776
- * // A duration typed as hours, minutes and seconds, emitted in seconds.
8777
- * label="Burn time"
8778
- * unit="s"
8779
- * rungs={["h", "min", "s"]}
8780
- * value={burn}
8781
- * onChange={setBurn}
8782
- * />
8783
- * <UnitInput
8784
- * // A node time on the game calendar, nudged with a rate wheel.
8785
- * label="Node UT"
8786
- * unit="ut"
8787
- * value={nodeUt}
8788
- * rate={{ step: 60 }}
8789
- * onChange={setNodeUt}
8790
- * />
8791
- * </Stack>
8792
- * );
8793
- * }
8643
+ * const [prograde, setPrograde] = useState(value("m/s", 0));
8644
+ *
8645
+ * <UnitInput
8646
+ * label="Prograde"
8647
+ * unit="m/s"
8648
+ * value={prograde}
8649
+ * onChange={setPrograde}
8650
+ * />
8651
+ *
8652
+ * // A duration typed as hours, minutes and seconds, emitted in seconds.
8653
+ * <UnitInput
8654
+ * label="Burn time"
8655
+ * unit="s"
8656
+ * rungs={["h", "min", "s"]}
8657
+ * value={burn}
8658
+ * onChange={setBurn}
8659
+ * />
8660
+ *
8661
+ * // A node time on the game calendar, nudged with a rate wheel.
8662
+ * <UnitInput
8663
+ * label="Node UT"
8664
+ * unit="ut"
8665
+ * value={nodeUt}
8666
+ * rate={{ step: 60 }}
8667
+ * onChange={setNodeUt}
8668
+ * />
8794
8669
  * ```
8795
8670
  *
8796
8671
  * @category Form