@ksp-gonogo/ui-kit 0.1.0 → 0.2.0-rc.10

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 (132) hide show
  1. package/LICENSE +21 -596
  2. package/README.md +151 -0
  3. package/dist/chunk-G3PMV62Z.js +36 -0
  4. package/dist/chunk-G3PMV62Z.js.map +1 -0
  5. package/dist/chunk-KPESGDJJ.js +8611 -0
  6. package/dist/chunk-KPESGDJJ.js.map +1 -0
  7. package/dist/chunk-SHAX2WJJ.js +18 -0
  8. package/dist/chunk-SHAX2WJJ.js.map +1 -0
  9. package/dist/dist-JSEJWZKX.js +546 -0
  10. package/dist/dist-JSEJWZKX.js.map +1 -0
  11. package/dist/gridUnits.d.ts +34 -0
  12. package/dist/gridUnits.js +14 -0
  13. package/dist/gridUnits.js.map +1 -0
  14. package/dist/guards.d.ts +110 -0
  15. package/dist/guards.js +171 -0
  16. package/dist/guards.js.map +1 -0
  17. package/dist/index.d.ts +9318 -25
  18. package/dist/index.js +8098 -28
  19. package/dist/index.js.map +1 -1
  20. package/dist/magic-string.es-J7BYFTTJ.js +1309 -0
  21. package/dist/magic-string.es-J7BYFTTJ.js.map +1 -0
  22. package/dist/testing.d.ts +470 -0
  23. package/dist/testing.js +16747 -0
  24. package/dist/testing.js.map +1 -0
  25. package/dist/tokens.css +1063 -29
  26. package/dist/units-Cl-8ZdJc.d.ts +270 -0
  27. package/package.json +57 -15
  28. package/dist/ActionButton.d.ts +0 -18
  29. package/dist/ActionButton.d.ts.map +0 -1
  30. package/dist/ActionButton.js +0 -56
  31. package/dist/ActionButton.js.map +0 -1
  32. package/dist/Badge.d.ts +0 -15
  33. package/dist/Badge.d.ts.map +0 -1
  34. package/dist/Badge.js +0 -60
  35. package/dist/Badge.js.map +0 -1
  36. package/dist/Box.d.ts +0 -19
  37. package/dist/Box.d.ts.map +0 -1
  38. package/dist/Box.js +0 -27
  39. package/dist/Box.js.map +0 -1
  40. package/dist/Card.d.ts +0 -11
  41. package/dist/Card.d.ts.map +0 -1
  42. package/dist/Card.js +0 -13
  43. package/dist/Card.js.map +0 -1
  44. package/dist/Cluster.d.ts +0 -18
  45. package/dist/Cluster.d.ts.map +0 -1
  46. package/dist/Cluster.js +0 -24
  47. package/dist/Cluster.js.map +0 -1
  48. package/dist/EmptyState.d.ts +0 -16
  49. package/dist/EmptyState.d.ts.map +0 -1
  50. package/dist/EmptyState.js +0 -37
  51. package/dist/EmptyState.js.map +0 -1
  52. package/dist/GonogoTokens.d.ts +0 -16
  53. package/dist/GonogoTokens.d.ts.map +0 -1
  54. package/dist/GonogoTokens.js +0 -108
  55. package/dist/GonogoTokens.js.map +0 -1
  56. package/dist/Grid.d.ts +0 -25
  57. package/dist/Grid.d.ts.map +0 -1
  58. package/dist/Grid.js +0 -23
  59. package/dist/Grid.js.map +0 -1
  60. package/dist/Inline.d.ts +0 -20
  61. package/dist/Inline.d.ts.map +0 -1
  62. package/dist/Inline.js +0 -17
  63. package/dist/Inline.js.map +0 -1
  64. package/dist/Panel.d.ts +0 -14
  65. package/dist/Panel.d.ts.map +0 -1
  66. package/dist/Panel.js +0 -145
  67. package/dist/Panel.js.map +0 -1
  68. package/dist/ProgressBar.d.ts +0 -15
  69. package/dist/ProgressBar.d.ts.map +0 -1
  70. package/dist/ProgressBar.js +0 -31
  71. package/dist/ProgressBar.js.map +0 -1
  72. package/dist/Readout.d.ts +0 -35
  73. package/dist/Readout.d.ts.map +0 -1
  74. package/dist/Readout.js +0 -114
  75. package/dist/Readout.js.map +0 -1
  76. package/dist/Row.d.ts +0 -22
  77. package/dist/Row.d.ts.map +0 -1
  78. package/dist/Row.js +0 -32
  79. package/dist/Row.js.map +0 -1
  80. package/dist/Section.d.ts +0 -15
  81. package/dist/Section.d.ts.map +0 -1
  82. package/dist/Section.js +0 -21
  83. package/dist/Section.js.map +0 -1
  84. package/dist/Spinner.d.ts +0 -18
  85. package/dist/Spinner.d.ts.map +0 -1
  86. package/dist/Spinner.js +0 -22
  87. package/dist/Spinner.js.map +0 -1
  88. package/dist/Stack.d.ts +0 -15
  89. package/dist/Stack.d.ts.map +0 -1
  90. package/dist/Stack.js +0 -17
  91. package/dist/Stack.js.map +0 -1
  92. package/dist/StatusIndicator.d.ts +0 -27
  93. package/dist/StatusIndicator.d.ts.map +0 -1
  94. package/dist/StatusIndicator.js +0 -78
  95. package/dist/StatusIndicator.js.map +0 -1
  96. package/dist/Truncate.d.ts +0 -7
  97. package/dist/Truncate.d.ts.map +0 -1
  98. package/dist/Truncate.js +0 -14
  99. package/dist/Truncate.js.map +0 -1
  100. package/dist/Value.d.ts +0 -24
  101. package/dist/Value.d.ts.map +0 -1
  102. package/dist/Value.js +0 -42
  103. package/dist/Value.js.map +0 -1
  104. package/dist/WidgetHeader.d.ts +0 -16
  105. package/dist/WidgetHeader.d.ts.map +0 -1
  106. package/dist/WidgetHeader.js +0 -40
  107. package/dist/WidgetHeader.js.map +0 -1
  108. package/dist/defaultDarkTheme.d.ts +0 -16
  109. package/dist/defaultDarkTheme.d.ts.map +0 -1
  110. package/dist/defaultDarkTheme.js +0 -96
  111. package/dist/defaultDarkTheme.js.map +0 -1
  112. package/dist/format.d.ts +0 -11
  113. package/dist/format.d.ts.map +0 -1
  114. package/dist/format.js +0 -12
  115. package/dist/format.js.map +0 -1
  116. package/dist/index.d.ts.map +0 -1
  117. package/dist/science/ScienceExperimentRow.d.ts +0 -43
  118. package/dist/science/ScienceExperimentRow.d.ts.map +0 -1
  119. package/dist/science/ScienceExperimentRow.js +0 -61
  120. package/dist/science/ScienceExperimentRow.js.map +0 -1
  121. package/dist/test/axe.d.ts +0 -3
  122. package/dist/test/axe.d.ts.map +0 -1
  123. package/dist/test/axe.js +0 -5
  124. package/dist/test/axe.js.map +0 -1
  125. package/dist/test/setup.d.ts +0 -2
  126. package/dist/test/setup.d.ts.map +0 -1
  127. package/dist/test/setup.js +0 -12
  128. package/dist/test/setup.js.map +0 -1
  129. package/dist/theme.d.ts +0 -116
  130. package/dist/theme.d.ts.map +0 -1
  131. package/dist/theme.js +0 -15
  132. package/dist/theme.js.map +0 -1
@@ -0,0 +1,270 @@
1
+ import { DeclaredUnit, UnitDeclarations, UnitRung } from '@ksp-gonogo/sitrep-sdk';
2
+
3
+ /**
4
+ * What the declaration says `Unit` measures, or `never` for a symbol nothing
5
+ * declares.
6
+ *
7
+ * Every type in this module reads `UnitDeclarations` and nothing else, which is
8
+ * what makes a unit an Uplink merges into it indistinguishable here from a
9
+ * first-party one.
10
+ */
11
+ type KindOfSymbol<Unit extends string> = Unit extends DeclaredUnit ? UnitDeclarations[Unit] extends {
12
+ kind: infer Kind;
13
+ } ? Kind : never : never;
14
+ /** Every declared symbol that measures `Kind`. */
15
+ type SymbolsOfKind<Kind> = {
16
+ [Unit in DeclaredUnit]: KindOfSymbol<Unit> extends Kind ? Unit : never;
17
+ }[DeclaredUnit];
18
+ /** The ladder `Unit` is declared on, or `never` for a unit that climbs none. */
19
+ type LadderOfSymbol<Unit extends string> = Unit extends DeclaredUnit ? UnitDeclarations[Unit] extends {
20
+ ladder: infer Ladder extends string;
21
+ } ? Ladder : never : never;
22
+ /**
23
+ * Every symbol of kind `Kind` that exists only as a conversion TARGET (`°C`),
24
+ * which the declarations do not name and {@link kindOfConversion} still
25
+ * resolves. A pair whose source is itself undeclared is skipped, or `°C→K`
26
+ * would make every kind accept `K`.
27
+ */
28
+ type ConversionTargetsOfKind<Kind> = {
29
+ [Conversion in keyof typeof CONVERSIONS]: Conversion extends `${infer Source}→${infer Target}` ? [KindOfSymbol<Source>] extends [never] ? never : [KindOfSymbol<Source>] extends [Kind] ? Target : never : never;
30
+ }[keyof typeof CONVERSIONS];
31
+ /**
32
+ * Every unit that measures the same thing as `Unit`, which is exactly the set a
33
+ * value in `Unit` may be re-expressed in.
34
+ *
35
+ * This is what makes `format="km/h"` check on a speed and fail on a length. A
36
+ * unit an Uplink declares in `UnitDeclarations` widens the accepted set.
37
+ *
38
+ * A literal symbol nothing declares accepts no format at all, since there is no
39
+ * kind to check the request against. Only a wide `string` accepts any string.
40
+ *
41
+ * @category Unit
42
+ */
43
+ type FormatsFor<Unit extends string> = string extends Unit ? string : FormatsForKind<KindOfSymbol<Unit>>;
44
+ /**
45
+ * {@link FormatsFor}, asked of the KIND rather than of one of its units, for a
46
+ * pin addressed to a whole group that has no single unit to check against.
47
+ *
48
+ * @category Unit
49
+ */
50
+ type FormatsForKind<Kind> = SymbolsOfKind<Kind>;
51
+ /**
52
+ * Every unit a value in `Unit` may be SHOWN as, which is every unit of its kind
53
+ * plus the presentation-only ones the conversion table reaches.
54
+ *
55
+ * Wider than {@link FormatsFor} by exactly the symbols that are not on the
56
+ * wire: `format` pins a rung, `as` re-expresses, so `°C` belongs only to `as`.
57
+ * Both refuse a cross-kind request: `as="kg"` on a length is an error.
58
+ *
59
+ * @category Unit
60
+ */
61
+ type PresentableAs<Unit extends string> = string extends Unit ? string : PresentableAsKind<KindOfSymbol<Unit>>;
62
+ /**
63
+ * {@link PresentableAs}, asked of the KIND. See {@link FormatsForKind}.
64
+ *
65
+ * @category Unit
66
+ */
67
+ type PresentableAsKind<Kind> = SymbolsOfKind<Kind> | ConversionTargetsOfKind<Kind>;
68
+ /**
69
+ * What a unit measures. The kind is what makes the system checkable: it says
70
+ * `m` and `km` are interchangeable and `m` and `m/s` are not, and it selects
71
+ * the ladder and the precision rule.
72
+ *
73
+ * @category Unit
74
+ */
75
+ type KnownQuantityKind = "length" | "speed" | "acceleration" | "mass" | "force" | "pressure" | "temperature" | "time" | "universalTime" | "specificImpulse" | "irlTime" | "planeAngle" | "power" | "data" | "dataRate" | "doseRate" | "irradiance" | "level" | "density" | "massFlow" | "gravParameter" | "dimensionless" | "percent" | "scienceData" | "scienceRate" | "ratio" | "area" | "volume" | "angularSpeed" | "funds" | "science" | "reputation" | "fundsRate" | "reputationRate" | "count" | "id" | "resourceUnits" | "resourceFlow" | "text" | "flag" | "enum" | "n/a";
76
+ /**
77
+ * A quantity kind, OPEN to kinds this package has never heard of.
78
+ *
79
+ * The `string & {}` member lets a third-party Uplink introduce its own dimension
80
+ * while the known kinds still autocomplete.
81
+ *
82
+ * @category Unit
83
+ */
84
+ type QuantityKind = KnownQuantityKind | (string & {});
85
+ /**
86
+ * One step of a unit's scale: a symbol (`m`, `km`, `Mm`) and the size, in the
87
+ * base unit, from which a value is written in it. A kind's steps in order are
88
+ * its ladder, and choosing a unit for a value is choosing its rung.
89
+ *
90
+ * @category Unit
91
+ */
92
+ type Rung = UnitRung;
93
+ /**
94
+ * Every ladder (a kind's {@link Rung}s in order) a declared unit names, and
95
+ * therefore every group that settles one unit together. A unit on none of them is a group of its own: `m`, `km`
96
+ * and `Mm` are one group and `s` and `min` are two.
97
+ *
98
+ * @category Unit
99
+ */
100
+ type LadderName = {
101
+ [Unit in DeclaredUnit]: LadderOfSymbol<Unit>;
102
+ }[DeclaredUnit];
103
+ /**
104
+ * What a pin may be addressed to: one GROUP, named the way the group is formed.
105
+ *
106
+ * A unit on a ladder is named by the ladder, because every unit of it settles
107
+ * together and `m`, `km` and `Mm` are one thing to pin. Everything else is named
108
+ * by the unit, because nothing interconverts it with its siblings and a pin on
109
+ * `s` says nothing about `min`. Keyed this way, a group is pinned at most once
110
+ * by construction.
111
+ *
112
+ * @category Unit
113
+ */
114
+ type UnitGroupKey = LadderName | {
115
+ [Unit in DeclaredUnit]: [LadderOfSymbol<Unit>] extends [never] ? Unit : never;
116
+ }[DeclaredUnit];
117
+ /**
118
+ * What the group named by `Group` measures, so a pin addressed to it can be checked.
119
+ *
120
+ * A ladder key measures whatever its units do; a unit key resolves through the
121
+ * declarations the same way a lone `<Unit>` does.
122
+ *
123
+ * @category Unit
124
+ */
125
+ type KindOfGroup<Group extends UnitGroupKey> = Group extends LadderName ? {
126
+ [Unit in DeclaredUnit]: [LadderOfSymbol<Unit>] extends [Group] ? [LadderOfSymbol<Unit>] extends [never] ? never : KindOfSymbol<Unit> : never;
127
+ }[DeclaredUnit] : KindOfSymbol<Group>;
128
+
129
+ /**
130
+ * Presentation conversions: what a value may be SHOWN as, given what it IS.
131
+ *
132
+ * Keyed source→target, `target = value / per + offset`, which covers the
133
+ * offset conversions a ladder cannot. Only within a kind: `formatQuantity`
134
+ * refuses a cross-kind conversion. `as const` is load-bearing, since
135
+ * {@link PresentableAs} reads the pair KEYS.
136
+ */
137
+ declare const CONVERSIONS: {
138
+ readonly "K\u2192\u00B0C": {
139
+ readonly per: 1;
140
+ readonly offset: -273.15;
141
+ };
142
+ readonly "\u00B0C\u2192K": {
143
+ readonly per: 1;
144
+ readonly offset: 273.15;
145
+ };
146
+ readonly "m/s\u00B2\u2192g": {
147
+ readonly per: 9.80665;
148
+ readonly offset: 0;
149
+ };
150
+ readonly "g\u2192m/s\u00B2": {
151
+ readonly per: number;
152
+ readonly offset: 0;
153
+ };
154
+ readonly "rad\u2192\u00B0": {
155
+ readonly per: number;
156
+ readonly offset: 0;
157
+ };
158
+ readonly "\u00B0\u2192rad": {
159
+ readonly per: number;
160
+ readonly offset: 0;
161
+ };
162
+ };
163
+ /**
164
+ * A quantity as a screen reader should hear it: the value followed by the
165
+ * unit's WORD rather than its symbol.
166
+ *
167
+ * For the places that cannot take a node (`aria-label`, `title`, an SVG
168
+ * `aria-valuetext`), so an accessible name reads "250.0 kilometres" rather
169
+ * than "kay em". If the result is going to be rendered, use {@link Unit} or
170
+ * {@link writeQuantity}. Falls back to the symbol for a unit with no word.
171
+ *
172
+ * @category Unit
173
+ */
174
+ declare function speakQuantity(quantity: {
175
+ magnitude: number;
176
+ unit: string;
177
+ } | null | undefined, opts?: FormatQuantityOptions): string;
178
+ /**
179
+ * A quantity as it is WRITTEN: the value and the unit's symbol, `250.0 km`.
180
+ *
181
+ * For visible text that cannot take a node: an SVG `<text>`, a canvas label, a
182
+ * chart annotation measured before it is drawn. Anywhere a node fits, use
183
+ * {@link Unit}; for an accessible name, {@link speakQuantity}.
184
+ *
185
+ * An ordinary space, not the thin space `<Unit>` sets, since a U+2009 is at
186
+ * the mercy of the SVG or canvas renderer.
187
+ *
188
+ * @category Unit
189
+ */
190
+ declare function writeQuantity(quantity: {
191
+ magnitude: number;
192
+ unit: string;
193
+ } | null | undefined, opts?: FormatQuantityOptions): string;
194
+ interface FormatQuantityOptions {
195
+ /**
196
+ * Pin the unit rather than letting the ladder choose, for where convention
197
+ * beats magnitude (orbital velocity in km/s, a broadcast in km/h).
198
+ *
199
+ * Typed by KIND, so `format="km/h"` checks on a speed and is an error on a
200
+ * length. Any unit of the same kind is accepted, including ones the ladder
201
+ * would never pick.
202
+ */
203
+ format?: string;
204
+ /**
205
+ * `"auto"` climbs the kind's ladder (or uses the kind's default presentation,
206
+ * such as scientific notation or a composite duration), `"never"` holds the
207
+ * base unit and formats it as a plain number, `"scientific"` forces
208
+ * scientific notation. `"compact"` is auto, except that a kind counted like
209
+ * money writes ten thousand and over to three significant figures with a
210
+ * magnitude suffix (`1.29Mf`), for a tile with no room for every digit.
211
+ * Defaults to auto.
212
+ */
213
+ scale?: "auto" | "never" | "scientific" | "compact";
214
+ /**
215
+ * Show the value in a different unit OF THE SAME KIND: `as: "°C"` on a kelvin
216
+ * field, `as: "g"` on an m/s² one. A cross-kind request is refused and the
217
+ * value renders in its true unit.
218
+ */
219
+ as?: string;
220
+ /** Override the kind's decimal places. */
221
+ decimals?: number;
222
+ /** The rung the value was last shown at, so a value hovering on a boundary does not flicker. */
223
+ heldSymbol?: string;
224
+ }
225
+ /**
226
+ * Pin the locale every quantity is written in, or pass `undefined` to go back
227
+ * to the reader's own. One call changes every readout at once.
228
+ *
229
+ * @category Unit
230
+ */
231
+ declare function setQuantityLocale(next: string | undefined): void;
232
+ /**
233
+ * A scale: one rung, settled once, and every mark printed against it.
234
+ *
235
+ * For a moving-scale instrument (an altimeter strip, a chart axis): the marks
236
+ * carry NO symbol, the symbol is shown once at the head, and every mark sits
237
+ * on the rung settled from the value that defines the scale, so a strip never
238
+ * reads "500 m" three marks below "1.0 km".
239
+ *
240
+ * Not a general string formatter ({@link writeQuantity}, {@link Unit}), and not
241
+ * for aligning a group of readouts with no known bound ({@link UnitSharedFormat}).
242
+ *
243
+ * @category Unit
244
+ */
245
+ interface QuantityScale {
246
+ /** The unit every mark is printed in. */
247
+ readonly rung: string;
248
+ /**
249
+ * The symbol for that rung, to show ONCE beside the scale. Empty for a kind
250
+ * that displays none, in which case the scale shows no header at all.
251
+ */
252
+ readonly symbol: string;
253
+ /** One mark, as the bare number: {@link symbol} carries the unit for the whole scale. */
254
+ mark(magnitude: number | null | undefined): string;
255
+ }
256
+ /**
257
+ * Build a {@link QuantityScale} whose rung is taken from `reference`.
258
+ *
259
+ * `reference` is the value that DEFINES the scale rather than a value on it:
260
+ * the top of an altimeter strip, an axis maximum. `opts.format` pins the rung
261
+ * outright.
262
+ *
263
+ * @category Unit
264
+ */
265
+ declare function quantityScale(reference: {
266
+ magnitude: number;
267
+ unit: string;
268
+ } | null | undefined, opts?: FormatQuantityOptions): QuantityScale;
269
+
270
+ export { type FormatQuantityOptions as F, type KindOfGroup as K, type LadderName as L, type PresentableAs as P, type QuantityKind as Q, type Rung as R, type UnitGroupKey as U, type FormatsFor as a, type FormatsForKind as b, type PresentableAsKind as c, type KnownQuantityKind as d, type QuantityScale as e, speakQuantity as f, quantityScale as q, setQuantityLocale as s, writeQuantity as w };
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@ksp-gonogo/ui-kit",
3
3
  "description": "Export-safe design system for Gonogo mission-control widgets and third-party Uplinks",
4
- "license": "GPL-3.0-only",
5
- "version": "0.1.0",
4
+ "license": "MIT",
5
+ "version": "0.2.0-rc.10",
6
6
  "type": "module",
7
7
  "repository": {
8
8
  "type": "git",
@@ -22,36 +22,78 @@
22
22
  "import": "./dist/index.js"
23
23
  },
24
24
  "./tokens.css": "./dist/tokens.css",
25
- "./theme": {
26
- "types": "./dist/theme.d.ts",
27
- "import": "./dist/theme.js"
25
+ "./testing": {
26
+ "types": "./dist/testing.d.ts",
27
+ "import": "./dist/testing.js"
28
+ },
29
+ "./grid": {
30
+ "types": "./dist/gridUnits.d.ts",
31
+ "import": "./dist/gridUnits.js"
32
+ },
33
+ "./guards": {
34
+ "types": "./dist/guards.d.ts",
35
+ "import": "./dist/guards.js"
28
36
  }
29
37
  },
30
38
  "types": "./dist/index.d.ts",
31
39
  "files": [
32
40
  "dist"
33
41
  ],
42
+ "scripts": {
43
+ "build": "tsup && node scripts/extend-package-specifiers.mjs && cp node_modules/@ksp-gonogo/theme/dist/tokens.css dist/tokens.css",
44
+ "dev": "tsup --watch",
45
+ "lint": "tsc --noEmit",
46
+ "render:markers": "node scripts/render-markers.ts",
47
+ "test": "vitest run",
48
+ "test:coverage": "vitest run --coverage",
49
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.test-d.json && tsc -p tsconfig.scripts.json",
50
+ "render:line-graph-reckoning": "node scripts/render-line-graph-reckoning.ts",
51
+ "render:meter-bands": "node scripts/render-meter-bands.ts",
52
+ "render:unit-currency": "node scripts/render-unit-currency.ts",
53
+ "render:band-ladder": "node scripts/render-band-ladder.ts",
54
+ "render:instrument-readings": "node scripts/render-instrument-readings.ts"
55
+ },
34
56
  "devDependencies": {
57
+ "@fontsource/jetbrains-mono": "^5.2.8",
58
+ "@ksp-gonogo/sitrep-sdk": "workspace:*",
59
+ "@ksp-gonogo/theme": "workspace:*",
35
60
  "@testing-library/jest-dom": "^6.9.1",
36
61
  "@testing-library/react": "^16.3.2",
37
62
  "@testing-library/user-event": "^14.6.1",
38
63
  "@types/jest-axe": "^3.5.9",
64
+ "@types/node": "^22.0.0",
39
65
  "@types/react": "^18.0.0",
66
+ "@vitest/coverage-v8": "^4.1.4",
67
+ "esbuild": "^0.28.0",
40
68
  "jest-axe": "^10.0.0",
41
69
  "jsdom": "^29.0.2",
70
+ "lucide-react": "^1.14.0",
71
+ "playwright": "^1.60.0",
72
+ "tsup": "^8.5.0",
42
73
  "typescript": "^5.0.0",
43
- "vitest": "^4.1.4",
44
- "@ksp-gonogo/sitrep-sdk": "0.0.1"
74
+ "vitest": "^4.1.4"
45
75
  },
46
76
  "peerDependencies": {
77
+ "@fontsource/jetbrains-mono": "^5.0.0",
78
+ "esbuild": "^0.25.0 || ^0.28.0",
79
+ "jest-axe": "^10.0.0",
80
+ "playwright": "^1.50.0",
47
81
  "react": "^18.0.0",
48
- "styled-components": "^6.0.0"
82
+ "styled-components": "^6.0.0",
83
+ "@ksp-gonogo/sitrep-sdk": "0.2.0-rc.10"
49
84
  },
50
- "scripts": {
51
- "build": "tsc -p tsconfig.json && cp src/tokens.css dist/tokens.css",
52
- "dev": "tsc -p tsconfig.json --watch",
53
- "lint": "tsc --noEmit",
54
- "test": "vitest run",
55
- "typecheck": "tsc --noEmit && tsc -p tsconfig.test-d.json"
85
+ "peerDependenciesMeta": {
86
+ "jest-axe": {
87
+ "optional": true
88
+ },
89
+ "esbuild": {
90
+ "optional": true
91
+ },
92
+ "playwright": {
93
+ "optional": true
94
+ },
95
+ "@fontsource/jetbrains-mono": {
96
+ "optional": true
97
+ }
56
98
  }
57
- }
99
+ }
@@ -1,18 +0,0 @@
1
- import type { ButtonHTMLAttributes, ReactNode } from "react";
2
- export type ActionButtonTone = "ghost" | "go";
3
- export interface ActionButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
4
- /**
5
- * `ghost` (default) is the neutral compact button. `go` is the go-toned
6
- * confirm variant — a filled green button that pulses to draw the eye to a
7
- * pending confirmation (e.g. "confirm transmit").
8
- */
9
- tone?: ActionButtonTone;
10
- children?: ReactNode;
11
- }
12
- /**
13
- * Compact row-level action button. Extracted from ScienceOfficer's
14
- * `ActionButton` + `ConfirmTransmitButton` — the `go` tone replaces the
15
- * latter.
16
- */
17
- export declare function ActionButton({ tone, children, ...rest }: ActionButtonProps): import("react/jsx-runtime").JSX.Element;
18
- //# sourceMappingURL=ActionButton.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ActionButton.d.ts","sourceRoot":"","sources":["../src/ActionButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAG7D,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,IAAI,CAAC;AAE9C,MAAM,WAAW,iBACf,SAAQ,oBAAoB,CAAC,iBAAiB,CAAC;IAC/C;;;;OAIG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC;IACxB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAc,EACd,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,iBAAiB,2CAMnB"}
@@ -1,56 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import styled, { css, keyframes } from "styled-components";
3
- /**
4
- * Compact row-level action button. Extracted from ScienceOfficer's
5
- * `ActionButton` + `ConfirmTransmitButton` — the `go` tone replaces the
6
- * latter.
7
- */
8
- export function ActionButton({ tone = "ghost", children, ...rest }) {
9
- return (_jsx(ActionButton__Root, { "$tone": tone, ...rest, children: children }));
10
- }
11
- const transmitPulse = keyframes `
12
- 0%,
13
- 100% {
14
- opacity: 1;
15
- }
16
- 50% {
17
- opacity: 0.6;
18
- }
19
- `;
20
- const ActionButton__Root = styled.button `
21
- font-size: 10px;
22
- font-weight: 600;
23
- letter-spacing: 0.04em;
24
- padding: 2px 8px;
25
- border-radius: 2px;
26
- border: 1px solid var(--color-surface-raised);
27
- background: transparent;
28
- color: var(--color-text-muted);
29
- cursor: pointer;
30
- font-family: inherit;
31
- display: inline-flex;
32
- align-items: center;
33
- gap: 4px;
34
-
35
- &:hover:not(:disabled) {
36
- color: var(--color-text-primary);
37
- border-color: var(--color-accent-fg);
38
- }
39
-
40
- &:disabled {
41
- cursor: not-allowed;
42
- opacity: 0.7;
43
- }
44
-
45
- ${({ $tone }) => $tone === "go" &&
46
- css `
47
- background: var(--color-status-go-bg);
48
- color: var(--color-status-go-fg);
49
- border-color: transparent;
50
-
51
- @media (prefers-reduced-motion: no-preference) {
52
- animation: ${transmitPulse} 1s ease-in-out infinite;
53
- }
54
- `}
55
- `;
56
- //# sourceMappingURL=ActionButton.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ActionButton.js","sourceRoot":"","sources":["../src/ActionButton.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAe3D;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,IAAI,GAAG,OAAO,EACd,QAAQ,EACR,GAAG,IAAI,EACW;IAClB,OAAO,CACL,KAAC,kBAAkB,aAAQ,IAAI,KAAM,IAAI,YACtC,QAAQ,GACU,CACtB,CAAC;AACJ,CAAC;AAED,MAAM,aAAa,GAAG,SAAS,CAAA;;;;;;;;CAQ9B,CAAC;AAEF,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAA6B;;;;;;;;;;;;;;;;;;;;;;;;;IAyBjE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACd,KAAK,KAAK,IAAI;IACd,GAAG,CAAA;;;;;;qBAMc,aAAa;;KAE7B;CACJ,CAAC"}
package/dist/Badge.d.ts DELETED
@@ -1,15 +0,0 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
2
- export type BadgeTone = "neutral" | "go" | "nogo" | "warn" | "info";
3
- export type BadgeSize = "sm" | "md";
4
- export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
5
- tone?: BadgeTone;
6
- size?: BadgeSize;
7
- children: ReactNode;
8
- }
9
- /**
10
- * Compact label/state pill. This is the kit's canonical badge — the single
11
- * tone/size vocabulary every widget's state chips should map onto, replacing
12
- * bespoke styled spans (e.g. a widget's own `KindBadge`/`StateTag`).
13
- */
14
- export declare function Badge({ tone, size, children, ...rest }: BadgeProps): import("react/jsx-runtime").JSX.Element;
15
- //# sourceMappingURL=Badge.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../src/Badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvD,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACpE,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpC,MAAM,WAAW,UAAW,SAAQ,cAAc,CAAC,eAAe,CAAC;IACjE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,EACpB,IAAgB,EAChB,IAAW,EACX,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,UAAU,2CAMZ"}
package/dist/Badge.js DELETED
@@ -1,60 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import styled, { css } from "styled-components";
3
- /**
4
- * Compact label/state pill. This is the kit's canonical badge — the single
5
- * tone/size vocabulary every widget's state chips should map onto, replacing
6
- * bespoke styled spans (e.g. a widget's own `KindBadge`/`StateTag`).
7
- */
8
- export function Badge({ tone = "neutral", size = "md", children, ...rest }) {
9
- return (_jsx(Badge__Body, { "$tone": tone, "$size": size, ...rest, children: children }));
10
- }
11
- const TONE_STYLES = {
12
- neutral: css `
13
- background: var(--color-surface-raised);
14
- border-color: var(--color-border-subtle);
15
- color: var(--color-text-muted);
16
- `,
17
- go: css `
18
- background: var(--color-status-go-bg);
19
- border-color: var(--color-status-go-bg);
20
- color: var(--color-status-go-fg);
21
- `,
22
- nogo: css `
23
- background: var(--color-status-nogo-bg);
24
- border-color: var(--color-status-nogo-bg);
25
- color: var(--color-status-nogo-fg);
26
- `,
27
- warn: css `
28
- background: var(--color-status-warning-bg);
29
- border-color: var(--color-status-warning-bg);
30
- color: var(--color-status-warning-fg);
31
- `,
32
- info: css `
33
- background: var(--color-status-info-bg);
34
- border-color: var(--color-status-info-bg);
35
- color: var(--color-status-info-fg);
36
- `,
37
- };
38
- const SIZE_STYLES = {
39
- sm: css `
40
- font-size: 10px;
41
- padding: 1px 4px;
42
- `,
43
- md: css `
44
- font-size: var(--font-size-xs);
45
- padding: 1px 6px;
46
- `,
47
- };
48
- const Badge__Body = styled.span `
49
- display: inline-block;
50
- border: 1px solid;
51
- border-radius: 3px;
52
- font-weight: 600;
53
- letter-spacing: 0.08em;
54
- text-transform: uppercase;
55
- white-space: nowrap;
56
-
57
- ${({ $size }) => SIZE_STYLES[$size]}
58
- ${({ $tone }) => TONE_STYLES[$tone]}
59
- `;
60
- //# sourceMappingURL=Badge.js.map
package/dist/Badge.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"Badge.js","sourceRoot":"","sources":["../src/Badge.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAWhD;;;;GAIG;AACH,MAAM,UAAU,KAAK,CAAC,EACpB,IAAI,GAAG,SAAS,EAChB,IAAI,GAAG,IAAI,EACX,QAAQ,EACR,GAAG,IAAI,EACI;IACX,OAAO,CACL,KAAC,WAAW,aAAQ,IAAI,WAAS,IAAI,KAAM,IAAI,YAC5C,QAAQ,GACG,CACf,CAAC;AACJ,CAAC;AAED,MAAM,WAAW,GAAG;IAClB,OAAO,EAAE,GAAG,CAAA;;;;GAIX;IACD,EAAE,EAAE,GAAG,CAAA;;;;GAIN;IACD,IAAI,EAAE,GAAG,CAAA;;;;GAIR;IACD,IAAI,EAAE,GAAG,CAAA;;;;GAIR;IACD,IAAI,EAAE,GAAG,CAAA;;;;GAIR;CACO,CAAC;AAEX,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,GAAG,CAAA;;;GAGN;IACD,EAAE,EAAE,GAAG,CAAA;;;GAGN;CACO,CAAC;AAEX,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAwC;;;;;;;;;IASnE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC;IACjC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC;CACpC,CAAC"}
package/dist/Box.d.ts DELETED
@@ -1,19 +0,0 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
2
- import type { SpaceToken } from "./Stack";
3
- export type BoxSurface = "app" | "panel" | "raised" | "sunken";
4
- export type BoxRadius = "xs" | "sm" | "md" | "pill";
5
- export type BoxPad = SpaceToken | [SpaceToken, SpaceToken];
6
- export interface BoxProps extends HTMLAttributes<HTMLDivElement> {
7
- /** Background surface tier. Omit for a transparent box. */
8
- surface?: BoxSurface;
9
- /** Padding on all sides, or a `[vertical, horizontal]` pair. */
10
- pad?: BoxPad;
11
- /** Adds a `1px solid` subtle border. Defaults to `false`. */
12
- bordered?: boolean;
13
- /** Corner radius. Omit for square corners. */
14
- radius?: BoxRadius;
15
- children?: ReactNode;
16
- }
17
- /** Background/border/padding/radius wrapper — the generic surface primitive. */
18
- export declare function Box({ surface, pad, bordered, radius, children, ...rest }: BoxProps): import("react/jsx-runtime").JSX.Element;
19
- //# sourceMappingURL=Box.d.ts.map
package/dist/Box.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"Box.d.ts","sourceRoot":"","sources":["../src/Box.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAC/D,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AACpD,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AAE3D,MAAM,WAAW,QAAS,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC9D,2DAA2D;IAC3D,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AASD,gFAAgF;AAChF,wBAAgB,GAAG,CAAC,EAClB,OAAO,EACP,GAAG,EACH,QAAgB,EAChB,MAAM,EACN,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,QAAQ,2CAYV"}
package/dist/Box.js DELETED
@@ -1,27 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import styled from "styled-components";
3
- const SURFACE_VAR = {
4
- app: "var(--color-surface-app)",
5
- panel: "var(--color-surface-panel)",
6
- raised: "var(--color-surface-raised)",
7
- sunken: "var(--color-surface-sunken)",
8
- };
9
- /** Background/border/padding/radius wrapper — the generic surface primitive. */
10
- export function Box({ surface, pad, bordered = false, radius, children, ...rest }) {
11
- return (_jsx(Box__Root, { "$surface": surface, "$pad": pad, "$bordered": bordered, "$radius": radius, ...rest, children: children }));
12
- }
13
- const Box__Root = styled.div `
14
- ${({ $surface }) => $surface && `background: ${SURFACE_VAR[$surface]};`}
15
- ${({ $bordered }) => $bordered && `border: 1px solid var(--color-border-subtle);`}
16
- ${({ theme, $radius }) => $radius && `border-radius: ${theme.radii[$radius]};`}
17
- ${({ theme, $pad }) => {
18
- if (!$pad)
19
- return "";
20
- if (Array.isArray($pad)) {
21
- const [y, x] = $pad;
22
- return `padding: ${theme.space[y]} ${theme.space[x]};`;
23
- }
24
- return `padding: ${theme.space[$pad]};`;
25
- }}
26
- `;
27
- //# sourceMappingURL=Box.js.map
package/dist/Box.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"Box.js","sourceRoot":"","sources":["../src/Box.tsx"],"names":[],"mappings":";AACA,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAmBvC,MAAM,WAAW,GAA+B;IAC9C,GAAG,EAAE,0BAA0B;IAC/B,KAAK,EAAE,4BAA4B;IACnC,MAAM,EAAE,6BAA6B;IACrC,MAAM,EAAE,6BAA6B;CACtC,CAAC;AAEF,gFAAgF;AAChF,MAAM,UAAU,GAAG,CAAC,EAClB,OAAO,EACP,GAAG,EACH,QAAQ,GAAG,KAAK,EAChB,MAAM,EACN,QAAQ,EACR,GAAG,IAAI,EACE;IACT,OAAO,CACL,KAAC,SAAS,gBACE,OAAO,UACX,GAAG,eACE,QAAQ,aACV,MAAM,KACX,IAAI,YAEP,QAAQ,GACC,CACb,CAAC;AACJ,CAAC;AAED,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAK1B;IACE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,IAAI,eAAe,WAAW,CAAC,QAAQ,CAAC,GAAG;IACrE,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,SAAS,IAAI,+CAA+C;IAC/E,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,IAAI,kBAAkB,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG;IAC5E,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE;IACpB,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;QACpB,OAAO,YAAY,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;IACzD,CAAC;IACD,OAAO,YAAY,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;AAC1C,CAAC;CACF,CAAC"}
package/dist/Card.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
2
- export interface CardProps extends HTMLAttributes<HTMLDivElement> {
3
- children?: ReactNode;
4
- }
5
- /**
6
- * Sunken inset card — a nested surface for a single record inside a list
7
- * (a tracked vessel, a fleet entry). Extracted from the Scanning widget's
8
- * `VesselCard`.
9
- */
10
- export declare const Card: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("styled-components").FastOmit<import("react").DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof CardProps> & CardProps, never> & Partial<Pick<import("styled-components").FastOmit<import("react").DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof CardProps> & CardProps, never>>> & string;
11
- //# sourceMappingURL=Card.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../src/Card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvD,MAAM,WAAW,SAAU,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC/D,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,IAAI,6bAKhB,CAAC"}
package/dist/Card.js DELETED
@@ -1,13 +0,0 @@
1
- import styled from "styled-components";
2
- /**
3
- * Sunken inset card — a nested surface for a single record inside a list
4
- * (a tracked vessel, a fleet entry). Extracted from the Scanning widget's
5
- * `VesselCard`.
6
- */
7
- export const Card = styled.div `
8
- background: var(--color-surface-sunken);
9
- border: 1px solid var(--color-border-subtle);
10
- border-radius: 3px;
11
- padding: 6px 8px;
12
- `;
13
- //# sourceMappingURL=Card.js.map
package/dist/Card.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"Card.js","sourceRoot":"","sources":["../src/Card.tsx"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAMvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAW;;;;;CAKxC,CAAC"}
package/dist/Cluster.d.ts DELETED
@@ -1,18 +0,0 @@
1
- import type { HTMLAttributes, ReactNode } from "react";
2
- import type { SpaceToken } from "./Stack";
3
- export type ClusterJustify = "between" | "start" | "end";
4
- export interface ClusterProps extends HTMLAttributes<HTMLDivElement> {
5
- /** `justify-content` shorthand. Defaults to `between`. */
6
- justify?: ClusterJustify;
7
- /** Gap between children, snapped to the space scale. Defaults to `md`. */
8
- gap?: SpaceToken;
9
- children?: ReactNode;
10
- }
11
- /**
12
- * The single most-repeated block in the dashboard: a horizontal row with
13
- * centred items, spread-out justification, and a `min-width: 0` so a
14
- * truncating child inside actually truncates instead of overflowing the flex
15
- * item. Verbatim source: ScienceOfficer's `TitleRow` and `LabHeader`.
16
- */
17
- export declare function Cluster({ justify, gap, children, ...rest }: ClusterProps): import("react/jsx-runtime").JSX.Element;
18
- //# sourceMappingURL=Cluster.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Cluster.d.ts","sourceRoot":"","sources":["../src/Cluster.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,OAAO,GAAG,KAAK,CAAC;AAEzD,MAAM,WAAW,YAAa,SAAQ,cAAc,CAAC,cAAc,CAAC;IAClE,0DAA0D;IAC1D,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,0EAA0E;IAC1E,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAQD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EACtB,OAAmB,EACnB,GAAU,EACV,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,YAAY,2CAMd"}