@connextar/house 0.4.0 → 0.5.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.
- package/README.md +109 -3
- package/dist/setup-guide/bits.d.ts +90 -0
- package/dist/setup-guide/bits.d.ts.map +1 -0
- package/dist/setup-guide/bits.js +140 -0
- package/dist/setup-guide/bits.js.map +1 -0
- package/dist/setup-guide/card.d.ts +33 -0
- package/dist/setup-guide/card.d.ts.map +1 -0
- package/dist/setup-guide/card.js +56 -0
- package/dist/setup-guide/card.js.map +1 -0
- package/dist/setup-guide/class-names.d.ts +72 -0
- package/dist/setup-guide/class-names.d.ts.map +1 -0
- package/dist/setup-guide/class-names.js +66 -0
- package/dist/setup-guide/class-names.js.map +1 -0
- package/dist/setup-guide/context.d.ts +89 -0
- package/dist/setup-guide/context.d.ts.map +1 -0
- package/dist/setup-guide/context.js +124 -0
- package/dist/setup-guide/context.js.map +1 -0
- package/dist/setup-guide/guide.d.ts +159 -0
- package/dist/setup-guide/guide.d.ts.map +1 -0
- package/dist/setup-guide/guide.js +128 -0
- package/dist/setup-guide/guide.js.map +1 -0
- package/dist/setup-guide/index.d.ts +27 -0
- package/dist/setup-guide/index.d.ts.map +1 -0
- package/dist/setup-guide/index.js +27 -0
- package/dist/setup-guide/index.js.map +1 -0
- package/dist/setup-guide/launcher.d.ts +38 -0
- package/dist/setup-guide/launcher.d.ts.map +1 -0
- package/dist/setup-guide/launcher.js +60 -0
- package/dist/setup-guide/launcher.js.map +1 -0
- package/dist/setup-guide/strip.d.ts +21 -0
- package/dist/setup-guide/strip.d.ts.map +1 -0
- package/dist/setup-guide/strip.js +42 -0
- package/dist/setup-guide/strip.js.map +1 -0
- package/package.json +5 -1
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@connextar/house/setup-guide` — the checklist a new account works through,
|
|
3
|
+
* and what finishing a step earns.
|
|
4
|
+
*
|
|
5
|
+
* It exists because the hard parts are not the checklist. They are: knowing
|
|
6
|
+
* what is done without storing it (so a thing made any other way still counts),
|
|
7
|
+
* paying for it exactly once however many tabs ask at the same moment, and
|
|
8
|
+
* saying so while the person is still looking at what they just did. Those are
|
|
9
|
+
* the same three problems in every app, and they have one right answer each.
|
|
10
|
+
*
|
|
11
|
+
* What the host supplies is everything that is genuinely its own: the steps,
|
|
12
|
+
* how each one is read from its records, where the reward is written, and what
|
|
13
|
+
* a reward is even called. This package holds no routes, makes no requests,
|
|
14
|
+
* imports no toast library and knows nothing about a database.
|
|
15
|
+
*
|
|
16
|
+
* The three surfaces are a card for a home page, a strip for the screen where
|
|
17
|
+
* an item's steps are actually done, and a launcher for the header. The panel
|
|
18
|
+
* the launcher opens is the app's own sheet — see `launcher.tsx`.
|
|
19
|
+
*/
|
|
20
|
+
export { buildGuide, doneSteps, findItem, itemProgress, rewardsOwed, stepKeysOf, stepState, stepsOf, } from "./guide.js";
|
|
21
|
+
export { DEFAULT_REWARD_WORDS, rewardWord, SetupGuideProvider, useSetupGuide, } from "./context.js";
|
|
22
|
+
export { SETUP_BAND_STYLE, SETUP_GUIDE_CLASS_NAMES } from "./class-names.js";
|
|
23
|
+
export { GuideIconLink, HowText, HowToButton, ItemHelp, MiniProgress, ProgressRing, RewardChip, RewardRing, Segments, StepCircle, useClassNames, } from "./bits.js";
|
|
24
|
+
export { SetupCard } from "./card.js";
|
|
25
|
+
export { SetupStrip } from "./strip.js";
|
|
26
|
+
export { SetupGuideList, SetupGuideSummary, SetupLauncherButton } from "./launcher.js";
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/setup-guide/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,UAAU,EACV,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,UAAU,EACV,SAAS,EACT,OAAO,GAYR,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,kBAAkB,EAClB,aAAa,GAQd,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAA6B,MAAM,kBAAkB,CAAC;AAExG,OAAO,EACL,aAAa,EACb,OAAO,EACP,WAAW,EACX,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,aAAa,GAGd,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,SAAS,EAA0C,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAwB,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ClassNameOverrides } from "./bits.js";
|
|
2
|
+
/**
|
|
3
|
+
* The header's Get started, and the contents of the panel it opens.
|
|
4
|
+
*
|
|
5
|
+
* The panel itself is the app's own — every one of them has a sheet or a drawer
|
|
6
|
+
* already, with its own idea of how a thing slides in and what closes it. So
|
|
7
|
+
* this package ships what goes *inside* one (`SetupGuideSummary`,
|
|
8
|
+
* `SetupGuideList`) and a button that opens it, and the app puts them together:
|
|
9
|
+
*
|
|
10
|
+
* ```tsx
|
|
11
|
+
* <SetupLauncherButton />
|
|
12
|
+
* <Sheet open={setup.panelOpen} onOpenChange={setup.setPanelOpen}>
|
|
13
|
+
* <SheetContent>
|
|
14
|
+
* <SetupGuideSummary />
|
|
15
|
+
* <SetupGuideList onGo={() => setup.setPanelOpen(false)} />
|
|
16
|
+
* </SheetContent>
|
|
17
|
+
* </Sheet>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
/** The pill: how far along, what has been earned, and a way into the whole guide. */
|
|
21
|
+
export declare function SetupLauncherButton({ label, className, classNames, }: {
|
|
22
|
+
label?: string;
|
|
23
|
+
className?: string;
|
|
24
|
+
classNames?: ClassNameOverrides;
|
|
25
|
+
}): import("react").JSX.Element | null;
|
|
26
|
+
/** The block at the top of the panel: the ring, the count, and one bar per item. */
|
|
27
|
+
export declare function SetupGuideSummary({ className, classNames }: {
|
|
28
|
+
className?: string;
|
|
29
|
+
classNames?: ClassNameOverrides;
|
|
30
|
+
}): import("react").JSX.Element | null;
|
|
31
|
+
/** Every item as a row, for the app's own panel. */
|
|
32
|
+
export declare function SetupGuideList({ onGo, className, classNames, }: {
|
|
33
|
+
/** Called when a row's action is followed, so the panel can close itself. */
|
|
34
|
+
onGo?: () => void;
|
|
35
|
+
className?: string;
|
|
36
|
+
classNames?: ClassNameOverrides;
|
|
37
|
+
}): import("react").JSX.Element | null;
|
|
38
|
+
//# sourceMappingURL=launcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.d.ts","sourceRoot":"","sources":["../../src/setup-guide/launcher.tsx"],"names":[],"mappings":"AAKA,OAAO,EASL,KAAK,kBAAkB,EACxB,MAAM,WAAW,CAAC;AAInB;;;;;;;;;;;;;;;;;GAiBG;AAEH,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,EAClC,KAAqB,EACrB,SAAS,EACT,UAAU,GACX,EAAE;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC,sCA6BA;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,kBAAkB,CAAA;CAAE,sCA2BnH;AAED,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,SAAS,EACT,UAAU,GACX,EAAE;IACD,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC,sCAmBA"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { ArrowRight, Sparkles } from "lucide-react";
|
|
4
|
+
import { cx } from "../internal/cx.js";
|
|
5
|
+
import { ItemHelp, MiniProgress, ProgressRing, RewardChip, RewardRing, Segments, StepCircle, useClassNames, } from "./bits.js";
|
|
6
|
+
import { rewardWord, useSetupGuide } from "./context.js";
|
|
7
|
+
/**
|
|
8
|
+
* The header's Get started, and the contents of the panel it opens.
|
|
9
|
+
*
|
|
10
|
+
* The panel itself is the app's own — every one of them has a sheet or a drawer
|
|
11
|
+
* already, with its own idea of how a thing slides in and what closes it. So
|
|
12
|
+
* this package ships what goes *inside* one (`SetupGuideSummary`,
|
|
13
|
+
* `SetupGuideList`) and a button that opens it, and the app puts them together:
|
|
14
|
+
*
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <SetupLauncherButton />
|
|
17
|
+
* <Sheet open={setup.panelOpen} onOpenChange={setup.setPanelOpen}>
|
|
18
|
+
* <SheetContent>
|
|
19
|
+
* <SetupGuideSummary />
|
|
20
|
+
* <SetupGuideList onGo={() => setup.setPanelOpen(false)} />
|
|
21
|
+
* </SheetContent>
|
|
22
|
+
* </Sheet>
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
/** The pill: how far along, what has been earned, and a way into the whole guide. */
|
|
26
|
+
export function SetupLauncherButton({ label = "Get started", className, classNames, }) {
|
|
27
|
+
const setup = useSetupGuide();
|
|
28
|
+
const c = useClassNames(classNames);
|
|
29
|
+
const guide = setup?.guide;
|
|
30
|
+
if (!setup || !guide || guide.hidden || guide.complete)
|
|
31
|
+
return null;
|
|
32
|
+
const words = setup.words;
|
|
33
|
+
const share = guide.items.length === 0 ? 0 : Math.round((guide.doneItems / guide.items.length) * 100);
|
|
34
|
+
return (_jsxs("button", { type: "button", onClick: () => setup.setPanelOpen(true), className: cx(c.launcher, className), "aria-label": `${label}: ${guide.doneItems} of ${guide.items.length} steps done, ${guide.earnedReward} of ${guide.totalReward} ${rewardWord(guide.totalReward, words)} earned`, children: [_jsx(ProgressRing, { value: share }), _jsx("span", { className: "hidden lg:inline", children: label }), _jsxs("span", { className: c.launcherChip, children: [_jsx(Sparkles, { className: "size-3", "aria-hidden": true }), guide.earnedReward, "/", guide.totalReward] }), setup.justEarned ? (_jsxs("span", { "aria-hidden": true, className: c.launcherBadge, children: ["+", setup.justEarned] })) : null] }));
|
|
35
|
+
}
|
|
36
|
+
/** The block at the top of the panel: the ring, the count, and one bar per item. */
|
|
37
|
+
export function SetupGuideSummary({ className, classNames }) {
|
|
38
|
+
const setup = useSetupGuide();
|
|
39
|
+
const guide = setup?.guide;
|
|
40
|
+
if (!setup || !guide)
|
|
41
|
+
return null;
|
|
42
|
+
const words = setup.words;
|
|
43
|
+
return (_jsxs("div", { className: cx("flex items-center gap-3.5 rounded-xl border border-border bg-muted/40 p-3.5", className), children: [_jsx(RewardRing, { earned: guide.earnedReward, total: guide.totalReward, size: 60, tone: "light", words: words, classNames: classNames }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [_jsxs("p", { className: "text-[15px] font-semibold", children: [guide.earnedReward, " of ", guide.totalReward, " ", rewardWord(guide.totalReward, words), " earned"] }), _jsxs("p", { className: "text-xs text-muted-foreground", children: [guide.doneItems, " of ", guide.items.length, " steps done"] }), _jsx(Segments, { done: guide.doneItems, total: guide.items.length, tone: "light", classNames: classNames })] })] }));
|
|
44
|
+
}
|
|
45
|
+
/** Every item as a row, for the app's own panel. */
|
|
46
|
+
export function SetupGuideList({ onGo, className, classNames, }) {
|
|
47
|
+
const setup = useSetupGuide();
|
|
48
|
+
const guide = setup?.guide;
|
|
49
|
+
if (!setup || !guide)
|
|
50
|
+
return null;
|
|
51
|
+
return (_jsx("ol", { className: className, children: guide.items.map((item, index) => (_jsx(PanelRow, { item: item, index: index, isNext: item.key === guide.nextKey, onGo: onGo, classNames: classNames }, item.key))) }));
|
|
52
|
+
}
|
|
53
|
+
function PanelRow({ item, index, isNext, onGo, classNames, }) {
|
|
54
|
+
const c = useClassNames(classNames);
|
|
55
|
+
const setup = useSetupGuide();
|
|
56
|
+
const Link = setup?.Link ?? (({ children, ...rest }) => _jsx("a", { ...rest, children: children }));
|
|
57
|
+
const paid = item.steps.length > 0 && item.steps.every((step) => step.earned);
|
|
58
|
+
return (_jsxs("li", { className: "flex gap-3 border-b border-border py-3.5 last:border-b-0", children: [_jsx(StepCircle, { state: item.done ? "done" : isNext ? "next" : "todo", n: index + 1, size: "sm", className: "mt-px", classNames: classNames }), _jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("p", { className: cx("flex-1 text-sm font-semibold", item.done && c.rowTitleDone), children: [item.title, _jsx("span", { className: c.srOnly, children: item.done ? " (done)" : " (to do)" })] }), item.reward > 0 ? (_jsx(RewardChip, { reward: item.reward, state: paid ? "earned" : "todo", classNames: classNames })) : null] }), item.done ? null : (_jsxs(_Fragment, { children: [item.steps.length > 1 ? (_jsxs(_Fragment, { children: [_jsx(MiniProgress, { done: item.doneCount, total: item.steps.length }), isNext && item.screen ? (_jsx("p", { className: "text-xs text-muted-foreground", children: "Its steps show on that screen, with a progress bar." })) : null] })) : null, _jsxs("div", { className: "flex items-center gap-1", children: [item.blocked ? (_jsx("span", { className: c.blocked, children: item.blocked })) : (_jsxs(Link, { href: item.href, onClick: onGo, className: cx(c.button, isNext ? c.buttonPrimary : c.buttonOutline), children: [item.actionLabel, isNext ? _jsx(ArrowRight, { className: "size-4", "aria-hidden": true }) : null] })), _jsx(ItemHelp, { item: item, className: "ml-auto", classNames: classNames })] })] }))] })] }));
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.js","sourceRoot":"","sources":["../../src/setup-guide/launcher.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type ClassNameOverrides } from "./bits.js";
|
|
3
|
+
export interface SetupStripProps {
|
|
4
|
+
/** Which item's steps this screen is where you do. */
|
|
5
|
+
itemKey: string;
|
|
6
|
+
/**
|
|
7
|
+
* Steps whose choices are made but not yet saved — for a flow that keeps
|
|
8
|
+
* everything until its last press. They fill the bar without being earned.
|
|
9
|
+
*/
|
|
10
|
+
ready?: ReadonlySet<string>;
|
|
11
|
+
className?: string;
|
|
12
|
+
classNames?: ClassNameOverrides;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* One item's steps, on the screen where they are done, with a progress bar.
|
|
16
|
+
*
|
|
17
|
+
* Gone as soon as every step is paid: a screen somebody uses every day should
|
|
18
|
+
* not keep a checklist on it for ever.
|
|
19
|
+
*/
|
|
20
|
+
export declare function SetupStrip({ itemKey, ready, className, classNames }: SetupStripProps): React.JSX.Element | null;
|
|
21
|
+
//# sourceMappingURL=strip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strip.d.ts","sourceRoot":"","sources":["../../src/setup-guide/strip.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAqE,KAAK,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAYvH,MAAM,WAAW,eAAe;IAC9B,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,eAAe,4BAuFpF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { ChevronDown } from "lucide-react";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { cx } from "../internal/cx.js";
|
|
6
|
+
import { GuideIconLink, HowToButton, RewardChip, StepCircle, useClassNames } from "./bits.js";
|
|
7
|
+
import { rewardWord, useSetupGuide } from "./context.js";
|
|
8
|
+
import { findItem, itemProgress, stepState } from "./guide.js";
|
|
9
|
+
// Answered by the strip's own width: beside a sidebar, the window says nothing
|
|
10
|
+
// useful about how much room this actually has.
|
|
11
|
+
const COLUMNS = {
|
|
12
|
+
3: "@2xl:grid-cols-3",
|
|
13
|
+
4: "@3xl:grid-cols-4",
|
|
14
|
+
5: "@4xl:grid-cols-5",
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* One item's steps, on the screen where they are done, with a progress bar.
|
|
18
|
+
*
|
|
19
|
+
* Gone as soon as every step is paid: a screen somebody uses every day should
|
|
20
|
+
* not keep a checklist on it for ever.
|
|
21
|
+
*/
|
|
22
|
+
export function SetupStrip({ itemKey, ready, className, classNames }) {
|
|
23
|
+
const setup = useSetupGuide();
|
|
24
|
+
const c = useClassNames(classNames);
|
|
25
|
+
const [open, setOpen] = React.useState(true);
|
|
26
|
+
const item = findItem(setup?.guide, itemKey);
|
|
27
|
+
if (!setup?.guide || setup.guide.hidden || !item)
|
|
28
|
+
return null;
|
|
29
|
+
if (item.steps.length === 0 || item.steps.every((step) => step.earned))
|
|
30
|
+
return null;
|
|
31
|
+
const words = setup.words;
|
|
32
|
+
const { progressed, total, percent, nextKey } = itemProgress(item, ready);
|
|
33
|
+
const owing = item.reward - item.earnedReward;
|
|
34
|
+
const summary = item.paysOnComplete
|
|
35
|
+
? `${progressed} of ${total} ready · ${owing} ${rewardWord(owing, words)} ${owing === 1 ? "lands" : "land"} when it is built`
|
|
36
|
+
: `${item.doneCount} of ${total} done · ${item.earnedReward} of ${item.reward} ${rewardWord(item.reward, words)} earned`;
|
|
37
|
+
return (_jsxs("section", { "aria-label": item.title, className: cx("@container", c.strip, className), children: [_jsxs("div", { className: "flex flex-wrap items-center gap-x-3.5 gap-y-3", children: [item.icon ? (_jsx("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-xl bg-secondary", children: item.icon })) : null, _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("h2", { className: c.stripTitle, children: item.title }), _jsx("p", { className: c.stripSummary, children: summary })] }), _jsxs("div", { className: "flex w-full items-center gap-3 sm:w-auto", children: [_jsx("div", { role: "progressbar", "aria-label": `${item.title}: ${percent}%`, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": percent, className: cx(c.bar, "flex-1 sm:w-56"), children: _jsx("div", { className: c.barFill, style: { width: `${percent}%` } }) }), _jsxs("span", { className: "text-[13px] font-semibold tabular-nums", children: [percent, "%"] }), _jsx("button", { type: "button", "aria-expanded": open, "aria-label": open ? "Hide the steps" : "Show the steps", onClick: () => setOpen((current) => !current), className: c.iconButton, children: _jsx(ChevronDown, { className: cx("size-4 transition-transform", !open && "-rotate-90"), "aria-hidden": true }) })] })] }), open ? (_jsx("ol", { className: cx("mt-3.5 grid gap-2.5 @md:grid-cols-2", COLUMNS[total]), children: item.steps.map((step, index) => {
|
|
38
|
+
const state = stepState(step, nextKey, ready);
|
|
39
|
+
return (_jsxs("li", { className: cx(c.stripTile, state === "next" && c.stripTileNext), children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [_jsx(StepCircle, { state: state, n: index + 1, size: "sm", classNames: classNames }), step.reward > 0 ? (_jsx(RewardChip, { reward: step.reward, state: step.earned ? "earned" : item.paysOnComplete ? "on-complete" : "todo", words: words, classNames: classNames })) : null] }), _jsxs("p", { className: cx("text-[13.5px] leading-snug font-semibold", step.done && c.rowTitleDone), children: [step.title, _jsx("span", { className: c.srOnly, children: step.done ? " (done)" : state === "ready" ? " (ready — pays when built)" : " (to do)" })] }), _jsxs("div", { className: "-ml-1.5 mt-auto flex items-center", children: [step.how ? (_jsx(HowToButton, { how: step.how, guide: step.guide, className: "size-7", classNames: classNames })) : null, _jsx(GuideIconLink, { guide: step.guide, className: "size-7", classNames: classNames }), state === "next" ? _jsx("span", { className: "ml-auto text-xs font-semibold text-primary", children: "Next" }) : null] })] }, step.key));
|
|
40
|
+
}) })) : null] }));
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=strip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strip.js","sourceRoot":"","sources":["../../src/setup-guide/strip.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@connextar/house",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "The pieces every app we build needs and none of them should own a copy of.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -58,6 +58,10 @@
|
|
|
58
58
|
"types": "./dist/wizard/react-hook-form-index.d.ts",
|
|
59
59
|
"default": "./dist/wizard/react-hook-form-index.js"
|
|
60
60
|
},
|
|
61
|
+
"./setup-guide": {
|
|
62
|
+
"types": "./dist/setup-guide/index.d.ts",
|
|
63
|
+
"default": "./dist/setup-guide/index.js"
|
|
64
|
+
},
|
|
61
65
|
"./editor": {
|
|
62
66
|
"types": "./dist/editor/index.d.ts",
|
|
63
67
|
"default": "./dist/editor/index.js"
|