@bitvea/feedback-toolbar 0.0.1

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 (176) hide show
  1. package/README.md +262 -0
  2. package/dist/FeedbackPanel.d.ts +117 -0
  3. package/dist/FeedbackPanel.d.ts.map +1 -0
  4. package/dist/FeedbackPanel.js +622 -0
  5. package/dist/FeedbackPanel.js.map +1 -0
  6. package/dist/FeedbackToolbar.d.ts +54 -0
  7. package/dist/FeedbackToolbar.d.ts.map +1 -0
  8. package/dist/FeedbackToolbar.js +1149 -0
  9. package/dist/FeedbackToolbar.js.map +1 -0
  10. package/dist/InboxSheet.d.ts +80 -0
  11. package/dist/InboxSheet.d.ts.map +1 -0
  12. package/dist/InboxSheet.js +580 -0
  13. package/dist/InboxSheet.js.map +1 -0
  14. package/dist/PinLayer.d.ts +59 -0
  15. package/dist/PinLayer.d.ts.map +1 -0
  16. package/dist/PinLayer.js +1702 -0
  17. package/dist/PinLayer.js.map +1 -0
  18. package/dist/RichText.d.ts +6 -0
  19. package/dist/RichText.d.ts.map +1 -0
  20. package/dist/RichText.js +135 -0
  21. package/dist/RichText.js.map +1 -0
  22. package/dist/browser/entry.d.ts +3 -0
  23. package/dist/browser/entry.d.ts.map +1 -0
  24. package/dist/browser/entry.js +13 -0
  25. package/dist/browser/entry.js.map +1 -0
  26. package/dist/browser/mount.d.ts +37 -0
  27. package/dist/browser/mount.d.ts.map +1 -0
  28. package/dist/browser/mount.js +150 -0
  29. package/dist/browser/mount.js.map +1 -0
  30. package/dist/browser/toolbar.js +38 -0
  31. package/dist/browser/toolbar.js.map +7 -0
  32. package/dist/capture.d.ts +58 -0
  33. package/dist/capture.d.ts.map +1 -0
  34. package/dist/capture.js +98 -0
  35. package/dist/capture.js.map +1 -0
  36. package/dist/cli/bin.d.ts +3 -0
  37. package/dist/cli/bin.d.ts.map +1 -0
  38. package/dist/cli/bin.js +196 -0
  39. package/dist/cli/bin.js.map +1 -0
  40. package/dist/cli/fs.d.ts +16 -0
  41. package/dist/cli/fs.d.ts.map +1 -0
  42. package/dist/cli/fs.js +33 -0
  43. package/dist/cli/fs.js.map +1 -0
  44. package/dist/cli/init.d.ts +75 -0
  45. package/dist/cli/init.d.ts.map +1 -0
  46. package/dist/cli/init.js +266 -0
  47. package/dist/cli/init.js.map +1 -0
  48. package/dist/cli/register.d.ts +55 -0
  49. package/dist/cli/register.d.ts.map +1 -0
  50. package/dist/cli/register.js +84 -0
  51. package/dist/cli/register.js.map +1 -0
  52. package/dist/cli/registration.d.ts +37 -0
  53. package/dist/cli/registration.d.ts.map +1 -0
  54. package/dist/cli/registration.js +69 -0
  55. package/dist/cli/registration.js.map +1 -0
  56. package/dist/cli/strategies.d.ts +98 -0
  57. package/dist/cli/strategies.d.ts.map +1 -0
  58. package/dist/cli/strategies.js +198 -0
  59. package/dist/cli/strategies.js.map +1 -0
  60. package/dist/client.d.ts +59 -0
  61. package/dist/client.d.ts.map +1 -0
  62. package/dist/client.js +113 -0
  63. package/dist/client.js.map +1 -0
  64. package/dist/config.d.ts +92 -0
  65. package/dist/config.d.ts.map +1 -0
  66. package/dist/config.js +65 -0
  67. package/dist/config.js.map +1 -0
  68. package/dist/deepLink.d.ts +86 -0
  69. package/dist/deepLink.d.ts.map +1 -0
  70. package/dist/deepLink.js +185 -0
  71. package/dist/deepLink.js.map +1 -0
  72. package/dist/fontFace.d.ts +70 -0
  73. package/dist/fontFace.d.ts.map +1 -0
  74. package/dist/fontFace.js +88 -0
  75. package/dist/fontFace.js.map +1 -0
  76. package/dist/gating.d.ts +32 -0
  77. package/dist/gating.d.ts.map +1 -0
  78. package/dist/gating.js +49 -0
  79. package/dist/gating.js.map +1 -0
  80. package/dist/icons.d.ts +68 -0
  81. package/dist/icons.d.ts.map +1 -0
  82. package/dist/icons.js +97 -0
  83. package/dist/icons.js.map +1 -0
  84. package/dist/index.d.ts +14 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +68 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/markdown.d.ts +59 -0
  89. package/dist/markdown.d.ts.map +1 -0
  90. package/dist/markdown.js +130 -0
  91. package/dist/markdown.js.map +1 -0
  92. package/dist/motion.d.ts +178 -0
  93. package/dist/motion.d.ts.map +1 -0
  94. package/dist/motion.js +302 -0
  95. package/dist/motion.js.map +1 -0
  96. package/dist/preferences.d.ts +71 -0
  97. package/dist/preferences.d.ts.map +1 -0
  98. package/dist/preferences.js +195 -0
  99. package/dist/preferences.js.map +1 -0
  100. package/dist/rasterise.d.ts +45 -0
  101. package/dist/rasterise.d.ts.map +1 -0
  102. package/dist/rasterise.js +490 -0
  103. package/dist/rasterise.js.map +1 -0
  104. package/dist/selector.d.ts +19 -0
  105. package/dist/selector.d.ts.map +1 -0
  106. package/dist/selector.js +142 -0
  107. package/dist/selector.js.map +1 -0
  108. package/dist/session.d.ts +19 -0
  109. package/dist/session.d.ts.map +1 -0
  110. package/dist/session.js +36 -0
  111. package/dist/session.js.map +1 -0
  112. package/dist/shortcut.d.ts +88 -0
  113. package/dist/shortcut.d.ts.map +1 -0
  114. package/dist/shortcut.js +149 -0
  115. package/dist/shortcut.js.map +1 -0
  116. package/dist/tokens.d.ts +709 -0
  117. package/dist/tokens.d.ts.map +1 -0
  118. package/dist/tokens.js +749 -0
  119. package/dist/tokens.js.map +1 -0
  120. package/dist/vendor/types/account.d.ts +26 -0
  121. package/dist/vendor/types/account.d.ts.map +1 -0
  122. package/dist/vendor/types/account.js +23 -0
  123. package/dist/vendor/types/account.js.map +1 -0
  124. package/dist/vendor/types/apiKey.d.ts +38 -0
  125. package/dist/vendor/types/apiKey.d.ts.map +1 -0
  126. package/dist/vendor/types/apiKey.js +36 -0
  127. package/dist/vendor/types/apiKey.js.map +1 -0
  128. package/dist/vendor/types/auth.d.ts +10 -0
  129. package/dist/vendor/types/auth.d.ts.map +1 -0
  130. package/dist/vendor/types/auth.js +15 -0
  131. package/dist/vendor/types/auth.js.map +1 -0
  132. package/dist/vendor/types/entity.d.ts +74 -0
  133. package/dist/vendor/types/entity.d.ts.map +1 -0
  134. package/dist/vendor/types/entity.js +111 -0
  135. package/dist/vendor/types/entity.js.map +1 -0
  136. package/dist/vendor/types/feedback.d.ts +285 -0
  137. package/dist/vendor/types/feedback.d.ts.map +1 -0
  138. package/dist/vendor/types/feedback.js +286 -0
  139. package/dist/vendor/types/feedback.js.map +1 -0
  140. package/dist/vendor/types/index.d.ts +14 -0
  141. package/dist/vendor/types/index.d.ts.map +1 -0
  142. package/dist/vendor/types/index.js +16 -0
  143. package/dist/vendor/types/index.js.map +1 -0
  144. package/dist/vendor/types/invite.d.ts +42 -0
  145. package/dist/vendor/types/invite.d.ts.map +1 -0
  146. package/dist/vendor/types/invite.js +30 -0
  147. package/dist/vendor/types/invite.js.map +1 -0
  148. package/dist/vendor/types/mcpToken.d.ts +38 -0
  149. package/dist/vendor/types/mcpToken.d.ts.map +1 -0
  150. package/dist/vendor/types/mcpToken.js +39 -0
  151. package/dist/vendor/types/mcpToken.js.map +1 -0
  152. package/dist/vendor/types/organization.d.ts +13 -0
  153. package/dist/vendor/types/organization.d.ts.map +1 -0
  154. package/dist/vendor/types/organization.js +12 -0
  155. package/dist/vendor/types/organization.js.map +1 -0
  156. package/dist/vendor/types/project.d.ts +73 -0
  157. package/dist/vendor/types/project.d.ts.map +1 -0
  158. package/dist/vendor/types/project.js +117 -0
  159. package/dist/vendor/types/project.js.map +1 -0
  160. package/dist/vendor/types/role.d.ts +12 -0
  161. package/dist/vendor/types/role.d.ts.map +1 -0
  162. package/dist/vendor/types/role.js +20 -0
  163. package/dist/vendor/types/role.js.map +1 -0
  164. package/dist/vendor/types/roleDefinition.d.ts +61 -0
  165. package/dist/vendor/types/roleDefinition.d.ts.map +1 -0
  166. package/dist/vendor/types/roleDefinition.js +45 -0
  167. package/dist/vendor/types/roleDefinition.js.map +1 -0
  168. package/dist/vendor/types/team.d.ts +25 -0
  169. package/dist/vendor/types/team.d.ts.map +1 -0
  170. package/dist/vendor/types/team.js +17 -0
  171. package/dist/vendor/types/team.js.map +1 -0
  172. package/dist/vendor/types/util.d.ts +39 -0
  173. package/dist/vendor/types/util.d.ts.map +1 -0
  174. package/dist/vendor/types/util.js +31 -0
  175. package/dist/vendor/types/util.js.map +1 -0
  176. package/package.json +59 -0
@@ -0,0 +1,709 @@
1
+ import type { FeedbackStatus } from "./vendor/types/index.js";
2
+ /**
3
+ * The BitVea brand orange, as the logo draws it.
4
+ *
5
+ * It used to be the toolbar's whole action system: every primary button, the
6
+ * active bar tool, the count bubble, the avatars, the status chip and the
7
+ * checkbox were orange. That put the accent on metadata and on chrome, which
8
+ * is the one thing DESIGN.md's colour section forbids - ink carries the CTA,
9
+ * and colour is reserved. So the accent is now IDENTITY ONLY: it survives on
10
+ * the pin teardrop, which has to be findable over arbitrary host content and
11
+ * is the one object in the product that means "BitVea Feedback is here".
12
+ */
13
+ export declare const accent: {
14
+ readonly start: "#DF6520";
15
+ readonly end: "#F97316";
16
+ /** 135deg, the direction the mark's own gradient runs. */
17
+ readonly gradient: "linear-gradient(135deg, #DF6520 0%, #F97316 100%)";
18
+ readonly onAccent: "#ffffff";
19
+ };
20
+ /** A status chip's ground and the ink on it, one pair per lane. */
21
+ export interface ToolbarStatusStyle {
22
+ background: string;
23
+ color: string;
24
+ }
25
+ /**
26
+ * The status vocabulary, mirrored from the dashboard's semantic pairs so one
27
+ * product fact reads the same on both surfaces. Built from DESIGN.md's
28
+ * soft-ground / deep-ink pairs rather than from bare dot colours, because a
29
+ * bare colour has to be re-chosen for the dark polarity flip and a pair does
30
+ * not: the ground moves with the theme and carries its ink with it.
31
+ */
32
+ export type ToolbarStatusPalette = Record<FeedbackStatus, ToolbarStatusStyle>;
33
+ /**
34
+ * Every colour a surface here needs, named by role rather than by value so
35
+ * the two palettes can be swapped wholesale. `bar*` are the floating pill's
36
+ * own colours: it is a single opaque chip over arbitrary content, so it does
37
+ * not share the popovers' canvas.
38
+ */
39
+ export interface ToolbarPalette {
40
+ ink: string;
41
+ /**
42
+ * What goes ON an ink fill, which is the polarity flip and not a constant:
43
+ * `ink` is #171717 light and #ffffff dark, so a primary button that hard-
44
+ * coded white text would be white-on-white for every dark-mode reviewer.
45
+ */
46
+ onInk: string;
47
+ body: string;
48
+ mute: string;
49
+ /**
50
+ * Accent-coloured TEXT, which is not the accent itself.
51
+ *
52
+ * `accent.start` on a 14%-orange wash measures about 3.0:1, and accent text
53
+ * is never larger than 13px here - under the 18px where 3:1 would be
54
+ * allowed. So the ink on the wash is a separate value per palette: a
55
+ * darkened orange in light, a lightened one in dark, both above 4.5:1.
56
+ *
57
+ * Nothing consumes it since the accent was demoted to identity only. It
58
+ * stays because the pin teardrop is still orange and the first person to
59
+ * print a word on it will need this rather than `accent.start`.
60
+ */
61
+ accentInk: string;
62
+ /**
63
+ * DESIGN.md's link blue, and it is a PAIR rather than a constant.
64
+ *
65
+ * `#0070f3` measures 4.6:1 on the light card and about 3.2:1 on the ink one,
66
+ * which is under AA for the 14px body copy a link sits in. The dark half is
67
+ * the lighter blue the status palette already uses for the same reason, so
68
+ * the two agree rather than each picking a blue.
69
+ */
70
+ link: string;
71
+ hairline: string;
72
+ hairlineStrong: string;
73
+ canvas: string;
74
+ canvasSoft: string;
75
+ canvasSoft2: string;
76
+ error: string;
77
+ success: string;
78
+ status: ToolbarStatusPalette;
79
+ /** The floating bar. */
80
+ barSurface: string;
81
+ barBorder: string;
82
+ barInk: string;
83
+ barInkMute: string;
84
+ barHover: string;
85
+ /** The wash the picker lays over the page while an element is being chosen. */
86
+ pickTint: string;
87
+ /**
88
+ * An ink fill at the weight a wash wants: the tint inside the picking
89
+ * outline, where the accent used to be. Stated per palette because "ink at
90
+ * 8%" is #171717 in light and #ffffff in dark, and one literal cannot be
91
+ * both.
92
+ */
93
+ inkSoft: string;
94
+ /** Ring drawn around a pin marker so it separates from the content beneath. */
95
+ markerRing: string;
96
+ }
97
+ export declare const lightPalette: ToolbarPalette;
98
+ /**
99
+ * The dark palette, taken verbatim from `packages/ui/src/styles/globals.css`'s
100
+ * `.dark` block.
101
+ *
102
+ * It used to run the OPPOSITE direction from the dashboard's: canvas #0f0f0f
103
+ * was DARKER than canvasSoft #161616, while globals.css raises canvas #1f1f1f
104
+ * above canvas-soft #171717. Two dark theories in one product means every rule
105
+ * of the form "the row is canvas on a canvasSoft sheet" inverts when a
106
+ * reviewer crosses from the toolbar to the dashboard looking at the same
107
+ * feedback. One ladder, defined once, mirrored here.
108
+ */
109
+ export declare const darkPalette: ToolbarPalette;
110
+ export declare const radii: {
111
+ /** 4px. Concentric inner corner inside an 8px track, and the pin's point. */
112
+ readonly xs: "4px";
113
+ readonly sm: "6px";
114
+ readonly md: "8px";
115
+ readonly lg: "12px";
116
+ readonly pill: "100px";
117
+ };
118
+ export declare const spacing: {
119
+ readonly xxs: "4px";
120
+ readonly xs: "8px";
121
+ readonly sm: "12px";
122
+ readonly md: "16px";
123
+ readonly lg: "24px";
124
+ };
125
+ /**
126
+ * The margin an anchored surface keeps against the viewport's edge, as a
127
+ * NUMBER - the shape `DRAG_THRESHOLD` below already takes, and for the same
128
+ * reason: every use of it is arithmetic.
129
+ *
130
+ * Here rather than beside the clamps in PinLayer.tsx, which is where it began.
131
+ * The gutter appears on both axes and in both spellings - a `calc()` in a
132
+ * `maxWidth` and a `maxHeight`, and a `Math.min`/`Math.max` pair per axis in
133
+ * the code that decides where a card lands - and a token file cannot import a
134
+ * component's constant, so a copy in PinLayer meant tokens.ts held its own. It
135
+ * had five spellings between them (`16`, and four `32`s inside `calc()`
136
+ * strings) under a comment claiming they agreed "by construction". They do
137
+ * now.
138
+ *
139
+ * A card whose `maxWidth` disagreed with the clamp that positions it is
140
+ * pushed off the very edge the clamp believes it is holding it inside, which
141
+ * is not a hypothetical: it is `sizes.thread`'s own story one field down.
142
+ */
143
+ export declare const VIEWPORT_GUTTER = 16;
144
+ /**
145
+ * Box sizes that are not spacing and not radii: the handful of fixed squares
146
+ * and bubbles this package draws. They live here because every one of them
147
+ * used to be an off-grid literal spelled at its call site (13px, 14px, 9px,
148
+ * 3px), and a literal at a call site is how the next one gets invented.
149
+ */
150
+ export declare const sizes: {
151
+ /** 16px form control, so the checkbox matches the 16px icons beside it. */
152
+ readonly control: "16px";
153
+ /** 28px: the sheet's close button and the pin marker's teardrop. */
154
+ readonly icon: "28px";
155
+ /** 18px count bubble - the smallest square that holds 12px mono legibly. */
156
+ readonly badge: "18px";
157
+ /** 8px unread dot. */
158
+ readonly dot: "8px";
159
+ /**
160
+ * 24px: the square a per-message action in a thread is drawn in (issue #20),
161
+ * and the thread's own close control, which used to be an invented 20px.
162
+ * A 16px glyph on DESIGN.md's `spacing.xxs` all round, so a row of them
163
+ * matches the 24px `Avatar` opposite it.
164
+ */
165
+ readonly action: "24px";
166
+ /**
167
+ * The thread card's width, and the pin composer's - issue #20 says in as
168
+ * many words that "both the pin popover and the composer-only variant share
169
+ * the 280px constant, widen both consistently", so they share this one.
170
+ *
171
+ * 440px is the Vercel comment thread's content width the issue names. It was
172
+ * two `"280px"` string literals at two call sites, which is exactly the
173
+ * shape the header comment above warns about: a THIRD place - the composer's
174
+ * own right-edge clamp - carried `280 + padding + border` as a hard-coded
175
+ * `300`, so widening one literal would have left the clamp holding the
176
+ * composer 140px inside an edge it thought it was hugging.
177
+ *
178
+ * A `px` string rather than a number because everything else in this object
179
+ * is one; the two call sites that need arithmetic parse it, which is one
180
+ * `parseFloat` against three places to forget.
181
+ */
182
+ readonly thread: "440px";
183
+ /**
184
+ * The ceiling a thread's message list scrolls inside, rather than growing
185
+ * past the viewport - issue #20's second acceptance line.
186
+ *
187
+ * Two caps, and both are needed. The `calc()` is `VIEWPORT_GUTTER` per
188
+ * side - the same margin the card's own `maxWidth` and the clamp that
189
+ * places it are built from - and is what stops a long thread running off
190
+ * the screen. The 480px is what stops a merely
191
+ * longish one filling a tall monitor: this card floats over the element it
192
+ * is talking about, and a review tool that covers the thing under review is
193
+ * the complaint the pin layer's own dismissal comment already answers once.
194
+ */
195
+ readonly threadMaxHeight: "min(480px, calc(100vh - 32px))";
196
+ };
197
+ /**
198
+ * Motion, from DESIGN.md's `## Motion` section - which this package's need is
199
+ * what added. See the provenance note at the head of this file: the toolbar
200
+ * renders through inline style inside somebody else's page, so there is no
201
+ * cascade to read a `--duration-fast` out of and the values are reproduced
202
+ * here, exactly as the colours and the type scale are.
203
+ *
204
+ * `enterScale` and `enterShift` are tokens rather than literals on purpose.
205
+ * The acceptance criterion for issue #24 is "no inline durations", and a bare
206
+ * `0.96` spelled at four call sites is the same defect one level down - the
207
+ * fifth surface is where somebody writes 0.95 and the product has two enters.
208
+ *
209
+ * Nothing here is a keyframe or a loop. Every value is one leg of a state
210
+ * transition a reviewer caused, which is the whole of the posture DESIGN.md
211
+ * states: small, fast, over before it is noticed.
212
+ */
213
+ export declare const motion: {
214
+ readonly duration: {
215
+ /** 80ms - hover, press, a badge whose number changed. */
216
+ readonly instant: "80ms";
217
+ /** 120ms - the default, and every surface enter. */
218
+ readonly fast: "120ms";
219
+ /**
220
+ * 180ms - the ceiling, and the bar's collapse (issue #22) is its one
221
+ * consumer: it is the only transition here whose box changes shape
222
+ * underneath it, so `fast` lands before the eye has followed the pill's
223
+ * snap. Anything else reaching for this step needs the written reason
224
+ * DESIGN.md's duration table asks for.
225
+ */
226
+ readonly settle: "180ms";
227
+ };
228
+ readonly easing: {
229
+ /** Ease-out, for anything arriving. */
230
+ readonly enter: "cubic-bezier(0, 0, 0.2, 1)";
231
+ /** Ease-in, for anything leaving. */
232
+ readonly exit: "cubic-bezier(0.4, 0, 1, 1)";
233
+ /** Symmetric, for a property changing in place on a stationary element. */
234
+ readonly inOut: "cubic-bezier(0.4, 0, 0.2, 1)";
235
+ };
236
+ /** The one scale step an entering surface takes. */
237
+ readonly enterScale: 0.96;
238
+ /**
239
+ * The one squash a control takes under the pointer. Shallower than
240
+ * `enterScale` because a button that moves as far as a popover reads as
241
+ * broken rather than as pressed.
242
+ */
243
+ readonly pressScale: 0.97;
244
+ /** The one travel distance, for a surface that slides rather than scales. */
245
+ readonly enterShift: "4px";
246
+ };
247
+ /**
248
+ * One of the three steps in the table above, and nothing else.
249
+ *
250
+ * Exists so "no inline durations" - issue #24's acceptance criterion - can be
251
+ * a TYPE rather than a comment wherever a duration is passed as an argument.
252
+ * `surfaceMotion`'s `duration` option was declared `string` while its own doc
253
+ * comment claimed the only reachable values were `motion.duration` members;
254
+ * `duration: "140ms"` compiled fine, which made the claim false and the rule
255
+ * enforced by nothing. A call site that wants a fourth step now has to add it
256
+ * here first, where a reviewer sees it - which is what the comment said all
257
+ * along.
258
+ */
259
+ export type MotionDuration = (typeof motion.duration)[keyof typeof motion.duration];
260
+ /**
261
+ * "An exit is one step faster than its matching enter", as a function.
262
+ *
263
+ * DESIGN.md's duration table states that rule and issue #24's helper claimed
264
+ * to enforce it centrally - while hard-coding `instant` for every exit. That
265
+ * was one step faster for the two surfaces on `fast` and TWO steps faster for
266
+ * anything on `settle`, which is exactly the step issue #22's collapse then
267
+ * took. A rule enforced only for the durations that existed when it was
268
+ * written is not enforced.
269
+ *
270
+ * Both halves of an exit read this: the `transition` a surface leaves on, and
271
+ * the timer that then takes it out of the DOM. DESIGN.md says the removal is
272
+ * deferred "by exactly the exit duration", and two literals that happen to
273
+ * agree today is how that stops being true.
274
+ *
275
+ * `instant` has nowhere faster to go and answers itself, which is the right
276
+ * degradation - a surface entering at 80ms is already at the floor.
277
+ */
278
+ export declare function exitFor(enter: MotionDuration): MotionDuration;
279
+ /**
280
+ * A `transition` shorthand, composed rather than spelled.
281
+ *
282
+ * This is what makes "no inline durations" mechanically true instead of a
283
+ * promise: the only way to write a transition in this package is to name a
284
+ * duration token and an easing token, and a call site that wanted `140ms`
285
+ * would have to add it to `motion.duration` first, where a reviewer sees it.
286
+ *
287
+ * Deliberately not `transition: all`. `all` transitions properties nobody
288
+ * chose, `width` and `top` among them, and DESIGN.md forbids animating those
289
+ * over a host page for the reflow they cause. Every property is named.
290
+ *
291
+ * `reduced` IS REQUIRED, and that is the whole design of this signature.
292
+ * DESIGN.md's Reduced Motion rule is a system-layer promise, and the first
293
+ * draft of issue #24 kept it by writing `reduced ? [a, b] : [a, b, "transform"]`
294
+ * at seven call sites - seven independent restatements of one rule, none of
295
+ * them checked, and an eighth control added later would simply have omitted it
296
+ * and honoured nothing. Making the preference an argument nobody can leave out
297
+ * moves the rule to the token layer where the rest of this file lives: a call
298
+ * site now states the preference it read and this function decides what that
299
+ * means. Pass `false` only where there is genuinely no reviewer to ask.
300
+ */
301
+ export declare function transition(properties: readonly string[], duration: string, easing: string, reduced: boolean): string;
302
+ /**
303
+ * The transform half of the same rule, so it cannot be honoured by one and
304
+ * forgotten by the other.
305
+ *
306
+ * A reduced-motion surface is already at its final position and size on its
307
+ * first frame - so there is no offset to animate out of, which is why this
308
+ * answers `none` rather than shortening anything. `transition` above drops
309
+ * `transform` from the property list in the same breath; a call site that used
310
+ * one of these and not the other would either animate a transform it promised
311
+ * not to, or leave a surface parked at an offset with nothing to move it.
312
+ */
313
+ export declare function motionTransform(value: string, reduced: boolean): string;
314
+ /**
315
+ * How long an exit lasts, in milliseconds, for the deferred-unmount timer.
316
+ *
317
+ * A number as well as a string because a `setTimeout` cannot take "80ms" and
318
+ * hard-coding 80 beside the token is how the two drift apart. Parsed from the
319
+ * token rather than declared twice.
320
+ */
321
+ export declare function durationMs(duration: string): number;
322
+ export declare const typeScale: {
323
+ /** body-sm. The default voice of every popover. */
324
+ readonly bodySm: {
325
+ readonly fontFamily: "\"BitVea Geist\", Geist, Inter, system-ui, -apple-system, sans-serif";
326
+ readonly fontSize: "14px";
327
+ readonly fontWeight: 400;
328
+ readonly lineHeight: "20px";
329
+ readonly letterSpacing: "-0.28px";
330
+ };
331
+ /** body-sm-strong. Names, button labels, the one emphasis this UI has. */
332
+ readonly bodySmStrong: {
333
+ readonly fontFamily: "\"BitVea Geist\", Geist, Inter, system-ui, -apple-system, sans-serif";
334
+ readonly fontSize: "14px";
335
+ readonly fontWeight: 500;
336
+ readonly lineHeight: "20px";
337
+ readonly letterSpacing: "-0.28px";
338
+ };
339
+ /** display-sm, 600 - the weight ceiling, and only at 20px. */
340
+ readonly displaySm: {
341
+ readonly fontFamily: "\"BitVea Geist\", Geist, Inter, system-ui, -apple-system, sans-serif";
342
+ readonly fontSize: "20px";
343
+ readonly fontWeight: 600;
344
+ readonly lineHeight: "28px";
345
+ readonly letterSpacing: "-0.6px";
346
+ };
347
+ /** caption. Footnotes and secondary lines that are not technical facts. */
348
+ readonly caption: {
349
+ readonly fontFamily: "\"BitVea Geist\", Geist, Inter, system-ui, -apple-system, sans-serif";
350
+ readonly fontSize: "12px";
351
+ readonly fontWeight: 400;
352
+ readonly lineHeight: "16px";
353
+ readonly letterSpacing: "0px";
354
+ };
355
+ /** caption-mono. Every identifier: branch, commit, path, timestamp, status. */
356
+ readonly captionMono: {
357
+ readonly fontFamily: "\"BitVea Geist Mono\", \"Geist Mono\", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace";
358
+ readonly fontSize: "12px";
359
+ readonly fontWeight: 400;
360
+ readonly lineHeight: "16px";
361
+ readonly letterSpacing: "0px";
362
+ };
363
+ /** code, 13px/20px. The captured selector, and nothing else so far. */
364
+ readonly code: {
365
+ readonly fontFamily: "\"BitVea Geist Mono\", \"Geist Mono\", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace";
366
+ readonly fontSize: "13px";
367
+ readonly fontWeight: 400;
368
+ readonly lineHeight: "20px";
369
+ readonly letterSpacing: "0px";
370
+ };
371
+ };
372
+ /**
373
+ * The two faces, for the places that need a family without a whole role.
374
+ *
375
+ * NOT `Geist`. No `@font-face` in this repo registers that family: `next/font`
376
+ * exposes a hashed name through `--font-geist` and nothing else, so naming
377
+ * "Geist" here has never rendered the brand face on any surface, the preview
378
+ * harness included - it silently fell through to Inter or to system-ui. These
379
+ * are DESIGN.md's own sanctioned substitutes ("Note on Font Substitutes":
380
+ * Inter 400/500/600 for the geometric sans, a monospace of the same voice for
381
+ * the technical layer). Self-hosting the real faces inside this bundle is
382
+ * blocked on a licence decision and on CLAUDE.md section 8's size ceiling.
383
+ *
384
+ * And NOT `var(--font-geist)` at the head of the stack either. A `var()`
385
+ * reference to an undefined custom property makes the whole declaration
386
+ * invalid at computed-value time; `font-family` is inherited, so the toolbar
387
+ * would then inherit the HOST page's typeface on every site that does not
388
+ * define that variable - while looking correct inside apps/web, which does.
389
+ */
390
+ export declare const fonts: {
391
+ readonly sans: "\"BitVea Geist\", Geist, Inter, system-ui, -apple-system, sans-serif";
392
+ readonly mono: "\"BitVea Geist Mono\", \"Geist Mono\", ui-monospace, SFMono-Regular, Menlo, Monaco, monospace";
393
+ };
394
+ /**
395
+ * The properties a host page's own element rules can set on markup this
396
+ * package renders unstyled, spread FIRST into every `form`, `label`, `header`,
397
+ * `section` and `p` here.
398
+ *
399
+ * The package ships no stylesheet, so nothing leaks OUT. Nothing stopped a
400
+ * host's `form { margin: 0 0 1rem; padding: 1rem; border: 1px solid #ccc }`
401
+ * from leaking IN and repainting the composer, which is the same class of bug
402
+ * as the `box-sizing` note in FeedbackToolbar.tsx and was invisible on the
403
+ * preview route only because apps/web loads Tailwind's preflight.
404
+ */
405
+ export declare const resetBox: {
406
+ readonly margin: 0;
407
+ readonly padding: 0;
408
+ readonly border: 0;
409
+ readonly background: "transparent";
410
+ readonly boxSizing: "border-box";
411
+ };
412
+ /**
413
+ * Visually hidden, still in the accessibility tree AND still in `textContent`.
414
+ *
415
+ * An icon-only control needs a name, and `aria-label` alone would give it one
416
+ * only for a screen reader: `toHaveText` and `Node.textContent` - which is how
417
+ * both the e2e suite and the unit tests read the resolve control's label - see
418
+ * nothing an `aria-label` says. So the label is real text, clipped.
419
+ *
420
+ * Clipped rather than `display: none` or `visibility: hidden`, because both of
421
+ * those take the text OUT of the accessibility tree and out of `textContent`,
422
+ * which is the whole thing being preserved. The `clip` / `clipPath` pair is
423
+ * belt and braces: `clip` is deprecated and `clip-path` is what actually
424
+ * applies in a modern engine, and this package cannot rely on a host stylesheet
425
+ * to have shipped either.
426
+ */
427
+ export declare const srOnly: {
428
+ readonly position: "absolute";
429
+ readonly width: "1px";
430
+ readonly height: "1px";
431
+ readonly margin: "-1px";
432
+ readonly padding: 0;
433
+ readonly border: 0;
434
+ readonly overflow: "hidden";
435
+ readonly clip: "rect(0 0 0 0)";
436
+ readonly clipPath: "inset(50%)";
437
+ readonly whiteSpace: "nowrap";
438
+ };
439
+ /** The bar's fixed geometry, from the reference's computed CSS. */
440
+ export declare const bar: {
441
+ readonly radius: "8px";
442
+ readonly padding: "4px";
443
+ readonly gap: "8px";
444
+ /** 36x36 icon buttons, so a 4px-padded bar lands at the reference height. */
445
+ readonly button: "36px";
446
+ /**
447
+ * The bar's height, in BOTH forms: a 36px button, 4px of padding either
448
+ * side and the 1px hairline, which is also the collapsed circle's diameter.
449
+ *
450
+ * Written down rather than left implicit because the layout now has to do
451
+ * arithmetic with it: a mid-edge dock centres the BAR on the viewport, and
452
+ * doing that without moving it when a popover opens means offsetting the
453
+ * dock's own padding by half this. See `dockLayout`.
454
+ */
455
+ readonly height: "46px";
456
+ /**
457
+ * Issue #21's "standard viewport inset", on all four sides.
458
+ *
459
+ * It was `bottom`, because the bottom edge was the only dock there was. The
460
+ * dock is now a box inset from every edge by this one value, which is what
461
+ * makes "the bar always ends flush to an edge with the standard viewport
462
+ * inset" one number rather than four pieces of per-edge arithmetic.
463
+ */
464
+ readonly inset: "8px";
465
+ };
466
+ /**
467
+ * How far a pointer has to travel before a press on the bar is a DRAG rather
468
+ * than a click. Issue #21.
469
+ *
470
+ * A hit-test distance, deliberately not `motion.enterShift`: that is how far
471
+ * an entering surface travels, and the two agreeing on 4px today is not a
472
+ * reason for one to be defined in terms of the other. 6px swallows the wobble
473
+ * a trackpad click or a thumb tap produces, and is well inside the collapsed
474
+ * dot's own 46px box - so a reviewer who means to drag the dot has crossed it
475
+ * long before the pointer leaves the control.
476
+ */
477
+ export declare const DRAG_THRESHOLD = 6;
478
+ /**
479
+ * Where the bar sits. Issue #21.
480
+ *
481
+ * Eight discrete positions rather than a stored pixel coordinate, and that is
482
+ * the whole design: "snap targets are discrete, not free-floating - the bar
483
+ * always ends flush to an edge with the standard viewport inset". Two of the
484
+ * issue's acceptance criteria - "dragging never leaves the bar off-screen" and
485
+ * "a resize that would strand the bar re-docks it" - are then satisfied
486
+ * STRUCTURALLY. There is no coordinate to fall outside a viewport, so there is
487
+ * no resize listener and nothing to re-clamp; every value here is flush to an
488
+ * edge at every viewport size.
489
+ *
490
+ * Spelled `<vertical>-<horizontal>`, which is the vocabulary the tests written
491
+ * against issue #22 already pinned (`bottom-right`, `top-left`). The nine
492
+ * combinations less `middle-center`, which is not an edge - the issue calls the
493
+ * two survivors "the two vertical mid-edges".
494
+ */
495
+ export type ToolbarDock = "top-left" | "top-center" | "top-right" | "middle-left" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right";
496
+ /** Which horizontal band of the viewport a dock is in. */
497
+ export type DockVertical = "top" | "middle" | "bottom";
498
+ /** Which vertical band. */
499
+ export type DockHorizontal = "left" | "center" | "right";
500
+ /**
501
+ * The dock a reviewer who has never dragged anything gets, and the one issue
502
+ * #21 calls the default.
503
+ */
504
+ export declare const DEFAULT_DOCK: ToolbarDock;
505
+ /**
506
+ * Every dock, in the reading order the keyboard control lays them out: three
507
+ * across the top, the two mid-edges, three across the bottom. Exported so the
508
+ * 3x3 grid in the account surface and the tests do not each spell the list.
509
+ */
510
+ export declare const TOOLBAR_DOCKS: readonly ToolbarDock[];
511
+ /**
512
+ * Beside `isThemeMode`, and for the same reason: this value comes back out of
513
+ * the HOST's `localStorage`, so it can be anything their code, an extension or
514
+ * a newer build of this toolbar wrote there. `hasOwnProperty` rather than
515
+ * `in`, which would accept `"toString"`.
516
+ */
517
+ export declare function isToolbarDock(value: unknown): value is ToolbarDock;
518
+ /** The one place a per-edge answer is decided. See `dockLayout`. */
519
+ export interface DockLayout {
520
+ vertical: DockVertical;
521
+ horizontal: DockHorizontal;
522
+ /**
523
+ * The dock is one flex column, and the DIRECTION is what flips for a top
524
+ * edge. The children are laid out switcher, popover, pill; reversed, the
525
+ * pill is visually first and the popover falls beneath it - which is the
526
+ * whole of "a top-docked bar opens its popover downwards".
527
+ */
528
+ flexDirection: "column" | "column-reverse";
529
+ /**
530
+ * How far the dock's own bottom padding holds the stack off the viewport's
531
+ * bottom edge - `bar.inset` at seven of the eight docks, and at the two
532
+ * mid-edges the offset that centres the BAR rather than the stack.
533
+ *
534
+ * This is the whole of how a mid-edge dock avoids moving the bar when a
535
+ * popover opens, and it was a real defect rather than a hypothetical: the
536
+ * dock packed the stack with `justifyContent: center`, so opening the
537
+ * composer at `middle-right` slid the bar 130px down the viewport and out
538
+ * from under the pointer that had just clicked it. The column now always
539
+ * packs against the bar's own edge - the popover grows away from the pill
540
+ * and the pill does not move - and "middle" is expressed as a padding
541
+ * instead: half the viewport, less half the bar, puts the pill's CENTRE on
542
+ * the centre line whatever is stacked above it. `vh` because the dock is a
543
+ * `position: fixed` box inset to all four edges, so its box is the
544
+ * viewport's.
545
+ */
546
+ paddingBottom: string;
547
+ /** Which side of the viewport the stack hugs. */
548
+ alignItems: "flex-start" | "center" | "flex-end";
549
+ /**
550
+ * `transform-origin` for the popover: DESIGN.md's rule that "a surface
551
+ * anchored to a control grows from the edge it is attached to", which is the
552
+ * edge FACING the bar and therefore flips with the dock.
553
+ */
554
+ popoverOrigin: string;
555
+ /** The longhand carrying the popover's gap to the pill, on that same edge. */
556
+ popoverGap: "marginTop" | "marginBottom";
557
+ /**
558
+ * Where the collapsed dot's unread indicator sits: the corner facing AWAY
559
+ * from the docked edge, so a circle - which has no orientation of its own -
560
+ * still answers issue #22's "the collapsed form follows the dock edge".
561
+ * Nothing is ever clipped; the dock keeps `bar.inset` on every side.
562
+ */
563
+ badge: {
564
+ top?: 0;
565
+ bottom?: 0;
566
+ left?: 0;
567
+ right?: 0;
568
+ };
569
+ /** Degrees to turn the collapse chevron by, so it points at the dock edge. */
570
+ chevron: number;
571
+ }
572
+ /**
573
+ * Everything that changes with the dock, derived in one place.
574
+ *
575
+ * Four call sites used to be four independent decisions waiting to disagree -
576
+ * the dock's flex triple, the popover's origin, the popover's gap and the
577
+ * badge's corner. They are all the same two facts (which vertical band, which
578
+ * horizontal band), so they are answered together.
579
+ */
580
+ export declare function dockLayout(dock: ToolbarDock): DockLayout;
581
+ export interface ToolbarShadows {
582
+ /**
583
+ * The bar's elevation is an outward GLOW rather than a drop shadow: the bar
584
+ * floats over content it does not belong to, and a directional shadow makes
585
+ * it look pasted onto the page instead of hovering above it.
586
+ */
587
+ bar: string;
588
+ popover: string;
589
+ marker: string;
590
+ /**
591
+ * DESIGN.md's Level 1: the inset hairline ring, on its own. Exported
592
+ * because three surfaces drew their own `0 0 0 1px <hairline>` ring by
593
+ * hand and one drew a raw `rgba(255,255,255,0.08)` literal.
594
+ */
595
+ insetHairline: string;
596
+ /**
597
+ * The keyboard focus ring. There was not one `outline`, `:focus` or focus
598
+ * state in this entire package, so any host shipping `*:focus { outline:
599
+ * none }` erased keyboard focus from a review tool - WCAG 2.4.7, failed by
600
+ * inheritance. Ink-based rather than link-blue, mirroring `--ring`'s ROLE
601
+ * (the highest-contrast ring the palette has) rather than its literal, since
602
+ * this palette has no link blue in it.
603
+ */
604
+ focusRing: string;
605
+ }
606
+ /** What the reviewer chose, which is not the same as what gets rendered. */
607
+ export type ToolbarThemeMode = "system" | "light" | "dark";
608
+ /** What gets rendered, after `system` has been resolved against the host. */
609
+ export type ResolvedTheme = "light" | "dark";
610
+ export interface ToolbarTheme {
611
+ resolved: ResolvedTheme;
612
+ colors: ToolbarPalette;
613
+ shadows: ToolbarShadows;
614
+ }
615
+ export declare const lightTheme: ToolbarTheme;
616
+ export declare const darkTheme: ToolbarTheme;
617
+ export declare function themeFor(resolved: ResolvedTheme): ToolbarTheme;
618
+ /**
619
+ * Where the reviewer's manual override is remembered. `localStorage` on the
620
+ * host origin, because the preference belongs to this person on this app and
621
+ * there is nowhere else to put it that survives a reload without a round trip
622
+ * the disabled-build requirement forbids.
623
+ */
624
+ export declare const THEME_STORAGE_KEY = "bitvea.feedback-toolbar.theme";
625
+ /** Media query the default follows, read from the host document. */
626
+ export declare const DARK_SCHEME_QUERY = "(prefers-color-scheme: dark)";
627
+ /**
628
+ * The other preference the toolbar reads from the HOST document, beside it
629
+ * because they are answered the same way - one `matchMedia` subscription each,
630
+ * through `useSyncExternalStore` so there is a server snapshot.
631
+ *
632
+ * It is the host's document rather than ours because there is only one: the
633
+ * reviewer's own OS setting, which the page the toolbar is injected into has
634
+ * no say in. See `usePrefersReducedMotion` in motion.ts.
635
+ */
636
+ export declare const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
637
+ export declare function isThemeMode(value: unknown): value is ToolbarThemeMode;
638
+ /**
639
+ * Above almost everything. Host apps routinely use z-indexes in the thousands
640
+ * for their own modals; the toolbar has to sit above those to be usable at
641
+ * all, and it is the reviewer's own overlay rather than part of the page.
642
+ */
643
+ export declare const Z_INDEX = 2147483000;
644
+ /**
645
+ * The toolbar's own internal stacking order, inside the root that `Z_INDEX`
646
+ * lifts above the host page.
647
+ *
648
+ * This exists because every one of these surfaces used to pick its own number
649
+ * and the bar picked none at all - it inherited `z-index: auto`, which loses
650
+ * to any positive value in the same stacking context. The consequences were
651
+ * not cosmetic: the picking overlay painted over the bar and swallowed the
652
+ * click that cancels picking, leaving a reviewer with no way out of crosshair
653
+ * mode, and the inbox sheet covered the account button on any viewport under
654
+ * about 1024px.
655
+ *
656
+ * So the order is written down once, and the rule it encodes is that THE BAR
657
+ * IS ALWAYS REACHABLE. It is the only persistent chrome the toolbar has; every
658
+ * other surface is something the bar opened and the bar has to be able to
659
+ * close. Everything else stacks under it, most transient first.
660
+ *
661
+ * `thread` sits above `surface` rather than tying with it, and issue #23 is
662
+ * why. A z-index only orders the siblings that declare one; equal values fall
663
+ * back to DOM order, and the inbox sheet is rendered after the pin layer in
664
+ * FeedbackToolbar.tsx - so a thread parked at `surface` loses to the sheet on
665
+ * any pin under its 340px. That is the common case rather than the exotic one:
666
+ * `focusPin` deliberately leaves the sheet open when a reviewer clicks a row,
667
+ * because they are working down a list, and the thread they just asked for is
668
+ * then the surface they are reading. It goes above the list they asked from.
669
+ *
670
+ * The other half of #23 was that an anchored thread never reached this ladder
671
+ * at all. It renders inside its marker's wrapper, and that wrapper is
672
+ * `position: fixed` with a z-index - a stacking context whatever its opacity -
673
+ * so the rung a thread paints at is the one the WRAPPER declares, not one the
674
+ * thread could set on itself. `PinMarker` therefore moves its wrapper between
675
+ * `marker` and `thread` as the thread opens, and nothing inside that wrapper
676
+ * declares a z-index of its own. Read this list as the order that actually
677
+ * renders; when it stops being that, the code is what is wrong.
678
+ *
679
+ * WHAT IS DELIBERATELY NOT IN THIS LADDER: the note and account popovers.
680
+ * `surface` used to be documented as "threads, composers, popovers and the
681
+ * inbox sheet" and only the sheet was ever really there - the popovers are
682
+ * children of the DOCK, so they ride its `bar` rung and have never declared
683
+ * one of their own. Splitting `thread` out of `surface` for issue #23 made
684
+ * that list true for threads and composers and left the popovers unmentioned,
685
+ * which is worse than the wrong entry: a reader could not place them at all.
686
+ * They are chrome rather than surfaces. They are anchored to the bar, opened
687
+ * and closed by the button beside them, and clamped to the same strip, so
688
+ * "above everything, with the bar" is the whole of their layering and a rung
689
+ * would be a second place to state it.
690
+ */
691
+ export declare const layers: {
692
+ /** The picking wash. Under everything, including its own markers. */
693
+ readonly picker: number;
694
+ /** Pin markers: part of the page's review state, so below any open surface. */
695
+ readonly marker: number;
696
+ /** Panels the bar opened and the bar closes again: the inbox sheet. */
697
+ readonly surface: number;
698
+ /**
699
+ * The one thread the reviewer is reading, and the composer they are writing
700
+ * the next one in - a composer is a thread that does not exist yet, so it
701
+ * shares this rung and wins the tie by being rendered last.
702
+ */
703
+ readonly thread: number;
704
+ /** Alerts that must be seen over an open surface. */
705
+ readonly alert: number;
706
+ /** The floating bar. Nothing the toolbar renders may cover it. */
707
+ readonly bar: 2147483000;
708
+ };
709
+ //# sourceMappingURL=tokens.d.ts.map