@sunboard/react 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.mts +11 -26
- package/dist/index.mjs +16 -136
- package/dist/styles.css +0 -68
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -207,7 +207,7 @@ Call `useLauncher()` once for your help menu and pass what it returns down.
|
|
|
207
207
|
| `tourRunning` | `true` while a tour runs. |
|
|
208
208
|
| `opened()` | Call it when your menu opens, so the open counts in Analytics. |
|
|
209
209
|
| `start(guideKey, replyId?)` | Starts a guide. Pass the id of the answer that offered it, and the conversation gets a line after that answer when the tour ends. |
|
|
210
|
-
| `messages` | The conversation with the assistant, oldest first. Each `Message` has an `id` and a `kind`: `question`, `waiting`, `reply`, `error` or `tour`. A `reply` holds an `AskReply` with the answer's text in `answer
|
|
210
|
+
| `messages` | The conversation with the assistant, oldest first. Each `Message` has an `id` and a `kind`: `question`, `waiting`, `reply`, `error` or `tour`. A `reply` holds an `AskReply` with the answer's text in `answer` and `guideKey` when it offers a guide to start. |
|
|
211
211
|
| `waiting` | `true` while a question is out and its answer has not come back. |
|
|
212
212
|
| `rateLimitedUntil` | While the user has asked too many questions this hour, the time they can ask again, as an ISO string. Otherwise `undefined`. |
|
|
213
213
|
| `handedOff` | `true` while a tour started from the conversation runs. It turns `false` when the tour ends, the moment to show your panel again. |
|
package/dist/index.d.mts
CHANGED
|
@@ -332,22 +332,11 @@ type GuideEventReport = {
|
|
|
332
332
|
});
|
|
333
333
|
/**
|
|
334
334
|
* ANSWERED is an answer written from the docs and checked against them.
|
|
335
|
-
* UNSUPPORTED is one the check did not back, so the visitor
|
|
336
|
-
*
|
|
337
|
-
* GUIDE offers a tour, with an answer when
|
|
335
|
+
* UNSUPPORTED is one the check did not back twice, so the visitor gets the
|
|
336
|
+
* not-covered reply. NONE found nothing to answer with.
|
|
337
|
+
* GUIDE offers a tour, with an answer when one was written and backed.
|
|
338
338
|
*/
|
|
339
339
|
type AskOutcome = "GUIDE" | "ANSWERED" | "UNSUPPORTED" | "NONE";
|
|
340
|
-
/** One section the answer came from. */
|
|
341
|
-
interface AskArticle {
|
|
342
|
-
/** The section's id. */
|
|
343
|
-
id: string;
|
|
344
|
-
/** The article's title. */
|
|
345
|
-
title: string;
|
|
346
|
-
/** Where the article is read. An article written in Sunboard has none. */
|
|
347
|
-
url?: string;
|
|
348
|
-
/** The section's heading, when it has one. */
|
|
349
|
-
heading?: string;
|
|
350
|
-
}
|
|
351
340
|
/** `id` is the stored question's id. `answer` is the whole text to show. */
|
|
352
341
|
interface AskReply {
|
|
353
342
|
id: string;
|
|
@@ -356,11 +345,13 @@ interface AskReply {
|
|
|
356
345
|
/** This question opened its conversation, so the widget greets the visitor. */
|
|
357
346
|
firstTurn: boolean;
|
|
358
347
|
outcome: AskOutcome;
|
|
359
|
-
/**
|
|
348
|
+
/**
|
|
349
|
+
* Plain text with blank lines between paragraphs, `1.` and `-` lists, and
|
|
350
|
+
* `**bold**`. Empty when a guide is offered with nothing written.
|
|
351
|
+
*/
|
|
360
352
|
answer: string;
|
|
361
|
-
/** At most three, in the order the answer used them. */
|
|
362
|
-
sources: AskArticle[];
|
|
363
353
|
guideKey?: string;
|
|
354
|
+
/** Set when the answer is the not-covered sentence and the project has a support link. */
|
|
364
355
|
supportUrl?: string;
|
|
365
356
|
}
|
|
366
357
|
/** What the server is doing while the visitor waits, in this order. */
|
|
@@ -402,8 +393,6 @@ interface Labels {
|
|
|
402
393
|
send: string;
|
|
403
394
|
/** The pill that scrolls back down to the newest message. */
|
|
404
395
|
latest: string;
|
|
405
|
-
/** On an older reply whose sources are folded away. */
|
|
406
|
-
sourcesCount: (count: number) => string;
|
|
407
396
|
/** Over the first answer of a conversation. `name` is the connection's `user.firstName`. */
|
|
408
397
|
greeting: (name?: string) => string;
|
|
409
398
|
/** Under an answer that offers a guide, above Show me how. */
|
|
@@ -428,8 +417,6 @@ interface Labels {
|
|
|
428
417
|
/** After six seconds of waiting. */
|
|
429
418
|
slow: string;
|
|
430
419
|
};
|
|
431
|
-
/** The name of the group of sections an answer came from, for a screen reader. */
|
|
432
|
-
sources: string;
|
|
433
420
|
/** Over the guides listed before the first question, this page's first. */
|
|
434
421
|
commonQuestions: string;
|
|
435
422
|
/** The one button under an answer that has a guide behind it. */
|
|
@@ -447,12 +434,10 @@ interface Labels {
|
|
|
447
434
|
lostBody: string;
|
|
448
435
|
tryAgain: string;
|
|
449
436
|
/**
|
|
450
|
-
* What the server answers when nothing
|
|
451
|
-
* section,
|
|
437
|
+
* What the server answers when there is nothing to show: no guide and no
|
|
438
|
+
* section, or no guide and an answer the check did not back twice.
|
|
452
439
|
*/
|
|
453
440
|
notCovered: (product: string) => string;
|
|
454
|
-
coveredBy: (article: string, heading?: string) => string;
|
|
455
|
-
guideFound: string;
|
|
456
441
|
closeAria: string;
|
|
457
442
|
poweredBy: string;
|
|
458
443
|
};
|
|
@@ -970,4 +955,4 @@ interface LauncherProps {
|
|
|
970
955
|
}
|
|
971
956
|
export declare function Launcher({ inline }?: LauncherProps): import("react").JSX.Element | null;
|
|
972
957
|
//#endregion
|
|
973
|
-
export type { ActiveTour, Anchor, AnchorElementState, AnchorMatch,
|
|
958
|
+
export type { ActiveTour, Anchor, AnchorElementState, AnchorMatch, AskFailure, AskOutcome, AskQuestion, AskReply, AskResult, AskScript, AskStage, BootstrapAnswer, BootstrapData, BootstrapOff, ComponentSettings, GuideContent, GuideStep, GuideType, GuidesApi, GuidesTransport, HttpTransportConfig, LabelOverrides, Labels, LauncherList, LauncherOptions, LauncherProps, MemoryTransportOptions, Message, Palette, PinPosition, ScriptedReply, StepPlacement, StepPrimitive, SunboardOverlayProps, SunboardProviderProps, Theme, ThemeMode, ThemeModeSetting, TourEnd, TourEnding, UserState, VisitorDetails };
|
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { createContext, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
|
|
4
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { FloatingArrow, FloatingPortal, arrow, autoUpdate, flip, offset, shift, useFloating } from "@floating-ui/react";
|
|
6
|
-
import { flushSync } from "react-dom";
|
|
7
6
|
//#region src/debug.ts
|
|
8
7
|
const noLog = () => {};
|
|
9
8
|
function consoleLogger() {
|
|
@@ -220,7 +219,6 @@ const enLabels = {
|
|
|
220
219
|
cancel: "Cancel",
|
|
221
220
|
send: "Send",
|
|
222
221
|
latest: "Latest",
|
|
223
|
-
sourcesCount: (count) => `${count} ${count === 1 ? "source" : "sources"}`,
|
|
224
222
|
greeting: (name) => name ? `Hey ${name},` : "Hey there,",
|
|
225
223
|
guideClosing: "I put together a guide for you that walks you through it.",
|
|
226
224
|
tourFinishedAsk: "Tour finished, how was your experience?",
|
|
@@ -236,7 +234,6 @@ const enLabels = {
|
|
|
236
234
|
checking: "Checking it against the docs",
|
|
237
235
|
slow: "Taking a little longer than usual"
|
|
238
236
|
},
|
|
239
|
-
sources: "Sources",
|
|
240
237
|
commonQuestions: "Common questions",
|
|
241
238
|
showMeHow: "Show me how",
|
|
242
239
|
newTab: "(opens in a new tab)",
|
|
@@ -249,8 +246,6 @@ const enLabels = {
|
|
|
249
246
|
lostBody: "Check your connection and try again.",
|
|
250
247
|
tryAgain: "Try again",
|
|
251
248
|
notCovered: (product) => `The ${product} help docs don't cover this yet.`,
|
|
252
|
-
coveredBy: (article, heading) => heading ? `The section "${heading}" of the article "${article}" covers this.` : `The article "${article}" covers this.`,
|
|
253
|
-
guideFound: "There is a guide for this.",
|
|
254
249
|
closeAria: "Close help",
|
|
255
250
|
poweredBy: "Powered by"
|
|
256
251
|
},
|
|
@@ -1654,39 +1649,20 @@ function stringOrUndefined(value) {
|
|
|
1654
1649
|
function optionalString(value) {
|
|
1655
1650
|
return value === void 0 || typeof value === "string";
|
|
1656
1651
|
}
|
|
1657
|
-
function parseSource(value) {
|
|
1658
|
-
if (!isRecord$1(value)) return void 0;
|
|
1659
|
-
const { id, title, url, heading } = value;
|
|
1660
|
-
if (typeof id !== "string" || typeof title !== "string") return void 0;
|
|
1661
|
-
if (!optionalString(url) || !optionalString(heading)) return void 0;
|
|
1662
|
-
return {
|
|
1663
|
-
id,
|
|
1664
|
-
title,
|
|
1665
|
-
...url === void 0 ? {} : { url },
|
|
1666
|
-
...heading === void 0 ? {} : { heading }
|
|
1667
|
-
};
|
|
1668
|
-
}
|
|
1669
1652
|
/** A reply as the server sends it, or as the thread kept it in session storage. */
|
|
1670
1653
|
function parseReply(value) {
|
|
1671
1654
|
if (!isRecord$1(value)) return void 0;
|
|
1672
|
-
const { id, conversationId, firstTurn, outcome, answer,
|
|
1655
|
+
const { id, conversationId, firstTurn, outcome, answer, guideKey, supportUrl } = value;
|
|
1673
1656
|
if (typeof id !== "string" || typeof conversationId !== "string") return void 0;
|
|
1674
1657
|
if (typeof firstTurn !== "boolean") return void 0;
|
|
1675
1658
|
if (!isAskOutcome(outcome) || typeof answer !== "string") return void 0;
|
|
1676
|
-
if (!
|
|
1677
|
-
const parsed = [];
|
|
1678
|
-
for (const source of sources) {
|
|
1679
|
-
const article = parseSource(source);
|
|
1680
|
-
if (!article) return void 0;
|
|
1681
|
-
parsed.push(article);
|
|
1682
|
-
}
|
|
1659
|
+
if (!optionalString(guideKey) || !optionalString(supportUrl)) return void 0;
|
|
1683
1660
|
return {
|
|
1684
1661
|
id,
|
|
1685
1662
|
conversationId,
|
|
1686
1663
|
firstTurn,
|
|
1687
1664
|
outcome,
|
|
1688
1665
|
answer,
|
|
1689
|
-
sources: parsed,
|
|
1690
1666
|
...guideKey === void 0 ? {} : { guideKey },
|
|
1691
1667
|
...supportUrl === void 0 ? {} : { supportUrl }
|
|
1692
1668
|
};
|
|
@@ -2720,12 +2696,6 @@ function PlayIcon() {
|
|
|
2720
2696
|
children: /* @__PURE__ */ jsx("path", { d: "M7 4.5v15l12-7.5z" })
|
|
2721
2697
|
});
|
|
2722
2698
|
}
|
|
2723
|
-
function DocIcon() {
|
|
2724
|
-
return /* @__PURE__ */ jsxs(Glyph, {
|
|
2725
|
-
width: 1.8,
|
|
2726
|
-
children: [/* @__PURE__ */ jsx("path", { d: "M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z" }), /* @__PURE__ */ jsx("path", { d: "M14 3v5h5M9 13h6M9 17h4" })]
|
|
2727
|
-
});
|
|
2728
|
-
}
|
|
2729
2699
|
function ExternalIcon() {
|
|
2730
2700
|
return /* @__PURE__ */ jsx(Glyph, {
|
|
2731
2701
|
width: 1.8,
|
|
@@ -2763,12 +2733,6 @@ function RestartIcon() {
|
|
|
2763
2733
|
function SendIcon() {
|
|
2764
2734
|
return /* @__PURE__ */ jsx(Glyph, { children: /* @__PURE__ */ jsx("path", { d: "M12 19V5M5 12l7-7 7 7" }) });
|
|
2765
2735
|
}
|
|
2766
|
-
function ChevronDownIcon() {
|
|
2767
|
-
return /* @__PURE__ */ jsx(Glyph, {
|
|
2768
|
-
width: 1.8,
|
|
2769
|
-
children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
|
|
2770
|
-
});
|
|
2771
|
-
}
|
|
2772
2736
|
function CheckIcon() {
|
|
2773
2737
|
return /* @__PURE__ */ jsx(Glyph, {
|
|
2774
2738
|
width: 1.8,
|
|
@@ -4022,16 +3986,6 @@ function QuestionPanel({ inline, launcher, close, focusBox }) {
|
|
|
4022
3986
|
followRef.current = false;
|
|
4023
3987
|
measure();
|
|
4024
3988
|
}, [messages]);
|
|
4025
|
-
const keepInPlace = (change) => {
|
|
4026
|
-
const box = scrollRef.current;
|
|
4027
|
-
const before = box ? {
|
|
4028
|
-
height: box.scrollHeight,
|
|
4029
|
-
top: box.scrollTop
|
|
4030
|
-
} : null;
|
|
4031
|
-
flushSync(change);
|
|
4032
|
-
if (box && before && anchored) box.scrollTop = before.top - (box.scrollHeight - before.height);
|
|
4033
|
-
measure();
|
|
4034
|
-
};
|
|
4035
3989
|
useEffect(() => {
|
|
4036
3990
|
const seen = seenRef.current;
|
|
4037
3991
|
let finished = null;
|
|
@@ -4040,7 +3994,7 @@ function QuestionPanel({ inline, launcher, close, focusBox }) {
|
|
|
4040
3994
|
if (message.kind === "waiting") continue;
|
|
4041
3995
|
seen.add(message.id);
|
|
4042
3996
|
if (message.kind === "reply") {
|
|
4043
|
-
const { greeting, closing } = replyWords(message,
|
|
3997
|
+
const { greeting, closing } = replyWords(message, api.firstName, L);
|
|
4044
3998
|
finished = [
|
|
4045
3999
|
greeting,
|
|
4046
4000
|
plainAnswer(message.reply.answer),
|
|
@@ -4230,10 +4184,9 @@ function QuestionPanel({ inline, launcher, close, focusBox }) {
|
|
|
4230
4184
|
latest: item.question.id === latestQuestion,
|
|
4231
4185
|
fresh: !seenRef.current.has(item.response.id),
|
|
4232
4186
|
guide: guideFor(item.response, listed),
|
|
4233
|
-
words: replyWords(item.response,
|
|
4187
|
+
words: replyWords(item.response, api.firstName, L),
|
|
4234
4188
|
labels: L,
|
|
4235
|
-
onShowMe: inline ? void 0 : start
|
|
4236
|
-
keepInPlace
|
|
4189
|
+
onShowMe: inline ? void 0 : start
|
|
4237
4190
|
}, item.response.id),
|
|
4238
4191
|
item.response?.kind === "error" && /* @__PURE__ */ jsx(FailureNote, {
|
|
4239
4192
|
message: item.response,
|
|
@@ -4311,16 +4264,15 @@ function guideFor(message, listed) {
|
|
|
4311
4264
|
return key === void 0 ? void 0 : listed.find((guide) => guide.key === key);
|
|
4312
4265
|
}
|
|
4313
4266
|
/**
|
|
4314
|
-
* The assistant's own lines around a
|
|
4315
|
-
*
|
|
4316
|
-
*
|
|
4267
|
+
* The assistant's own lines around a reply: the greeting on the first reply
|
|
4268
|
+
* of a conversation that offers a guide or an answer, and the closing under
|
|
4269
|
+
* any reply that offers a guide.
|
|
4317
4270
|
*/
|
|
4318
|
-
function replyWords(
|
|
4319
|
-
const
|
|
4320
|
-
if (reply.outcome === "NONE") return {};
|
|
4271
|
+
function replyWords({ reply }, name, labels) {
|
|
4272
|
+
const offers = reply.outcome === "GUIDE" || reply.outcome === "ANSWERED";
|
|
4321
4273
|
return {
|
|
4322
|
-
greeting: reply.firstTurn ? labels.greeting(name) : void 0,
|
|
4323
|
-
closing:
|
|
4274
|
+
greeting: reply.firstTurn && offers ? labels.greeting(name) : void 0,
|
|
4275
|
+
closing: reply.guideKey !== void 0 ? labels.guideClosing : void 0
|
|
4324
4276
|
};
|
|
4325
4277
|
}
|
|
4326
4278
|
const SUGGESTION_LIMIT = 4;
|
|
@@ -4414,7 +4366,7 @@ function Waiting({ stage, since, labels, productName }) {
|
|
|
4414
4366
|
]
|
|
4415
4367
|
});
|
|
4416
4368
|
}
|
|
4417
|
-
function ReplyArticle({ message, latest, fresh, guide, words, labels, onShowMe
|
|
4369
|
+
function ReplyArticle({ message, latest, fresh, guide, words, labels, onShowMe }) {
|
|
4418
4370
|
const { reply } = message;
|
|
4419
4371
|
const primary = latest && !message.toured;
|
|
4420
4372
|
const [arrived] = useState(fresh);
|
|
@@ -4428,7 +4380,7 @@ function ReplyArticle({ message, latest, fresh, guide, words, labels, onShowMe,
|
|
|
4428
4380
|
className: "sb-reply-greeting",
|
|
4429
4381
|
children: words.greeting
|
|
4430
4382
|
}),
|
|
4431
|
-
/* @__PURE__ */ jsx(AnswerText, { text: reply.answer }),
|
|
4383
|
+
reply.answer !== "" && /* @__PURE__ */ jsx(AnswerText, { text: reply.answer }),
|
|
4432
4384
|
words.closing && /* @__PURE__ */ jsx("p", {
|
|
4433
4385
|
className: "sb-reply-closing",
|
|
4434
4386
|
children: words.closing
|
|
@@ -4444,7 +4396,7 @@ function ReplyArticle({ message, latest, fresh, guide, words, labels, onShowMe,
|
|
|
4444
4396
|
children: [/* @__PURE__ */ jsx(PlayIcon, {}), labels.showMeHow]
|
|
4445
4397
|
})
|
|
4446
4398
|
}),
|
|
4447
|
-
reply.
|
|
4399
|
+
reply.supportUrl && /* @__PURE__ */ jsxs("div", {
|
|
4448
4400
|
className: "sb-support",
|
|
4449
4401
|
children: [/* @__PURE__ */ jsx("span", { children: labels.supportOffer }), /* @__PURE__ */ jsxs("a", {
|
|
4450
4402
|
className: "sb-support-link",
|
|
@@ -4460,82 +4412,10 @@ function ReplyArticle({ message, latest, fresh, guide, words, labels, onShowMe,
|
|
|
4460
4412
|
})
|
|
4461
4413
|
]
|
|
4462
4414
|
})]
|
|
4463
|
-
})
|
|
4464
|
-
reply.sources.length > 0 && (latest ? /* @__PURE__ */ jsx(Sources, {
|
|
4465
|
-
sources: reply.sources,
|
|
4466
|
-
labels
|
|
4467
|
-
}) : /* @__PURE__ */ jsx(FoldedSources, {
|
|
4468
|
-
sources: reply.sources,
|
|
4469
|
-
labels,
|
|
4470
|
-
keepInPlace
|
|
4471
|
-
}))
|
|
4415
|
+
})
|
|
4472
4416
|
]
|
|
4473
4417
|
});
|
|
4474
4418
|
}
|
|
4475
|
-
function Sources({ sources, labels }) {
|
|
4476
|
-
return /* @__PURE__ */ jsx("div", {
|
|
4477
|
-
className: "sb-sources",
|
|
4478
|
-
role: "group",
|
|
4479
|
-
"aria-label": labels.sources,
|
|
4480
|
-
children: /* @__PURE__ */ jsx(SourceRows, {
|
|
4481
|
-
sources,
|
|
4482
|
-
labels
|
|
4483
|
-
})
|
|
4484
|
-
});
|
|
4485
|
-
}
|
|
4486
|
-
function FoldedSources({ sources, labels, keepInPlace }) {
|
|
4487
|
-
const [open, setOpen] = useState(false);
|
|
4488
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
4489
|
-
className: "sb-sources",
|
|
4490
|
-
role: "group",
|
|
4491
|
-
"aria-label": labels.sources,
|
|
4492
|
-
children: [/* @__PURE__ */ jsxs("button", {
|
|
4493
|
-
type: "button",
|
|
4494
|
-
className: "sb-sources-toggle",
|
|
4495
|
-
"aria-expanded": open,
|
|
4496
|
-
onClick: () => keepInPlace(() => setOpen((now) => !now)),
|
|
4497
|
-
children: [
|
|
4498
|
-
/* @__PURE__ */ jsx(DocIcon, {}),
|
|
4499
|
-
/* @__PURE__ */ jsx("span", { children: labels.sourcesCount(sources.length) }),
|
|
4500
|
-
/* @__PURE__ */ jsx(ChevronDownIcon, {})
|
|
4501
|
-
]
|
|
4502
|
-
}), open && /* @__PURE__ */ jsx(SourceRows, {
|
|
4503
|
-
sources,
|
|
4504
|
-
labels
|
|
4505
|
-
})]
|
|
4506
|
-
});
|
|
4507
|
-
}
|
|
4508
|
-
function SourceRows({ sources, labels }) {
|
|
4509
|
-
return /* @__PURE__ */ jsx(Fragment, { children: sources.map((source) => {
|
|
4510
|
-
const name = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DocIcon, {}), /* @__PURE__ */ jsxs("span", {
|
|
4511
|
-
className: "sb-doc-text",
|
|
4512
|
-
children: [source.heading !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
4513
|
-
className: "sb-doc-trail",
|
|
4514
|
-
children: `${source.title} › `
|
|
4515
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
4516
|
-
className: "sb-doc-title",
|
|
4517
|
-
children: source.heading ?? source.title
|
|
4518
|
-
})]
|
|
4519
|
-
})] });
|
|
4520
|
-
return source.url === void 0 ? /* @__PURE__ */ jsx("div", {
|
|
4521
|
-
className: "sb-doc",
|
|
4522
|
-
children: name
|
|
4523
|
-
}, source.id) : /* @__PURE__ */ jsxs("a", {
|
|
4524
|
-
className: "sb-doc",
|
|
4525
|
-
href: source.url,
|
|
4526
|
-
target: "_blank",
|
|
4527
|
-
rel: "noreferrer",
|
|
4528
|
-
children: [
|
|
4529
|
-
name,
|
|
4530
|
-
/* @__PURE__ */ jsx(ExternalIcon, {}),
|
|
4531
|
-
/* @__PURE__ */ jsx("span", {
|
|
4532
|
-
className: "sb-sr",
|
|
4533
|
-
children: labels.newTab
|
|
4534
|
-
})
|
|
4535
|
-
]
|
|
4536
|
-
}, source.id);
|
|
4537
|
-
}) });
|
|
4538
|
-
}
|
|
4539
4419
|
function FailureNote({ message, fresh, labels, onRetry }) {
|
|
4540
4420
|
const { failure } = message;
|
|
4541
4421
|
const lost = failure.kind === "lost";
|
package/dist/styles.css
CHANGED
|
@@ -560,74 +560,6 @@
|
|
|
560
560
|
color: var(--sb-accent);
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
.sb-root .sb-sources {
|
|
564
|
-
display: flex;
|
|
565
|
-
flex-direction: column;
|
|
566
|
-
border: 1px solid var(--sb-border);
|
|
567
|
-
border-radius: var(--sb-r2);
|
|
568
|
-
overflow: hidden;
|
|
569
|
-
}
|
|
570
|
-
.sb-root .sb-doc,
|
|
571
|
-
.sb-root .sb-sources-toggle {
|
|
572
|
-
width: 100%;
|
|
573
|
-
min-height: 44px;
|
|
574
|
-
display: flex;
|
|
575
|
-
align-items: center;
|
|
576
|
-
gap: 10px;
|
|
577
|
-
padding: 0 12px;
|
|
578
|
-
font-size: calc(var(--sb-size-base) - 1px);
|
|
579
|
-
}
|
|
580
|
-
.sb-root .sb-doc {
|
|
581
|
-
color: var(--sb-text);
|
|
582
|
-
text-decoration: none;
|
|
583
|
-
}
|
|
584
|
-
.sb-root .sb-doc + .sb-doc,
|
|
585
|
-
.sb-root .sb-sources-toggle + .sb-doc {
|
|
586
|
-
border-top: 1px solid var(--sb-border);
|
|
587
|
-
}
|
|
588
|
-
.sb-root a.sb-doc:hover,
|
|
589
|
-
.sb-root .sb-sources-toggle:hover {
|
|
590
|
-
background: var(--sb-surface-hover);
|
|
591
|
-
}
|
|
592
|
-
.sb-root .sb-doc > svg {
|
|
593
|
-
flex-shrink: 0;
|
|
594
|
-
width: 15px;
|
|
595
|
-
height: 15px;
|
|
596
|
-
color: var(--sb-text-muted);
|
|
597
|
-
}
|
|
598
|
-
.sb-root .sb-doc-text + svg {
|
|
599
|
-
width: 14px;
|
|
600
|
-
height: 14px;
|
|
601
|
-
}
|
|
602
|
-
.sb-root .sb-doc-text {
|
|
603
|
-
flex: 1;
|
|
604
|
-
min-width: 0;
|
|
605
|
-
overflow: hidden;
|
|
606
|
-
text-overflow: ellipsis;
|
|
607
|
-
white-space: nowrap;
|
|
608
|
-
}
|
|
609
|
-
.sb-root .sb-doc-trail {
|
|
610
|
-
color: var(--sb-text-muted);
|
|
611
|
-
}
|
|
612
|
-
.sb-root .sb-sources-toggle {
|
|
613
|
-
border: 0;
|
|
614
|
-
background: transparent;
|
|
615
|
-
color: var(--sb-text-muted);
|
|
616
|
-
text-align: left;
|
|
617
|
-
cursor: pointer;
|
|
618
|
-
}
|
|
619
|
-
.sb-root .sb-sources-toggle span {
|
|
620
|
-
flex: 1;
|
|
621
|
-
}
|
|
622
|
-
.sb-root .sb-sources-toggle svg {
|
|
623
|
-
flex-shrink: 0;
|
|
624
|
-
width: 15px;
|
|
625
|
-
height: 15px;
|
|
626
|
-
}
|
|
627
|
-
.sb-root .sb-sources-toggle[aria-expanded="true"] svg:last-child {
|
|
628
|
-
transform: rotate(180deg);
|
|
629
|
-
}
|
|
630
|
-
|
|
631
563
|
.sb-root .sb-support {
|
|
632
564
|
display: flex;
|
|
633
565
|
align-items: center;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sunboard/react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Product tours, tooltips and a Help launcher with an assistant, for your React app. Sunboard creates the guides from your docs and keeps them working as your app changes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://sunboardhq.com",
|