@ydtb/tk-scope-app 0.19.3 → 0.20.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/dist/src/client/launchpad/LaunchpadCard.d.ts +23 -0
- package/dist/src/client/launchpad/LaunchpadCard.d.ts.map +1 -0
- package/dist/src/client/launchpad/LaunchpadCard.js +42 -0
- package/dist/src/client/launchpad/LaunchpadCard.js.map +1 -0
- package/dist/src/client/launchpad/LaunchpadDetailPanel.d.ts +22 -0
- package/dist/src/client/launchpad/LaunchpadDetailPanel.d.ts.map +1 -0
- package/dist/src/client/launchpad/LaunchpadDetailPanel.js +24 -0
- package/dist/src/client/launchpad/LaunchpadDetailPanel.js.map +1 -0
- package/dist/src/client/launchpad/LaunchpadList.d.ts +39 -0
- package/dist/src/client/launchpad/LaunchpadList.d.ts.map +1 -0
- package/dist/src/client/launchpad/LaunchpadList.js +157 -0
- package/dist/src/client/launchpad/LaunchpadList.js.map +1 -0
- package/dist/src/client/launchpad/SetupProgressCard.d.ts +15 -0
- package/dist/src/client/launchpad/SetupProgressCard.d.ts.map +1 -0
- package/dist/src/client/launchpad/SetupProgressCard.js +10 -0
- package/dist/src/client/launchpad/SetupProgressCard.js.map +1 -0
- package/dist/src/client/launchpad/index.d.ts +13 -0
- package/dist/src/client/launchpad/index.d.ts.map +1 -0
- package/dist/src/client/launchpad/index.js +13 -0
- package/dist/src/client/launchpad/index.js.map +1 -0
- package/dist/src/client/launchpad/launchpad-registry.d.ts +13 -0
- package/dist/src/client/launchpad/launchpad-registry.d.ts.map +1 -0
- package/dist/src/client/launchpad/launchpad-registry.js +11 -0
- package/dist/src/client/launchpad/launchpad-registry.js.map +1 -0
- package/dist/src/client/launchpad/sortWidgets.d.ts +18 -0
- package/dist/src/client/launchpad/sortWidgets.d.ts.map +1 -0
- package/dist/src/client/launchpad/sortWidgets.js +83 -0
- package/dist/src/client/launchpad/sortWidgets.js.map +1 -0
- package/dist/src/components/ErrorBoundary.d.ts +1 -1
- package/dist/src/create-app.d.ts.map +1 -1
- package/dist/src/create-app.js +26 -14
- package/dist/src/create-app.js.map +1 -1
- package/dist/src/lib/platform-api.d.ts +82 -2
- package/dist/src/lib/platform-api.d.ts.map +1 -1
- package/dist/src/lib/platform-api.js +2 -0
- package/dist/src/lib/platform-api.js.map +1 -1
- package/dist/src/lib/types.d.ts +64 -0
- package/dist/src/lib/types.d.ts.map +1 -1
- package/dist/src/lib/types.js.map +1 -1
- package/package.json +16 -8
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LaunchpadCard — one card per widget in the list view.
|
|
3
|
+
*
|
|
4
|
+
* Handles both modes:
|
|
5
|
+
* - `inline`: card body renders the widget component in place (expanded card)
|
|
6
|
+
* - `detail`: card is clickable; triggers `onOpenDetail` (consumer routes to detail)
|
|
7
|
+
*
|
|
8
|
+
* Completion state shows a "completed" pill + revisit affordance.
|
|
9
|
+
*/
|
|
10
|
+
import type { LaunchpadWidgetDefinition } from "../../lib/types.ts";
|
|
11
|
+
interface LaunchpadCardProps {
|
|
12
|
+
widget: LaunchpadWidgetDefinition;
|
|
13
|
+
isCompleted: boolean;
|
|
14
|
+
isExpanded: boolean;
|
|
15
|
+
metadata?: Record<string, unknown>;
|
|
16
|
+
onOpenDetail: () => void;
|
|
17
|
+
onToggleInline: () => void;
|
|
18
|
+
onComplete: () => void;
|
|
19
|
+
onCancelInline: () => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function LaunchpadCard({ widget, isCompleted, isExpanded, metadata, onOpenDetail, onToggleInline, onComplete, onCancelInline, }: LaunchpadCardProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=LaunchpadCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LaunchpadCard.d.ts","sourceRoot":"","sources":["../../../../src/client/launchpad/LaunchpadCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,oBAAoB,CAAA;AAE3B,UAAU,kBAAkB;IAC1B,MAAM,EAAE,yBAAyB,CAAA;IACjC,WAAW,EAAE,OAAO,CAAA;IACpB,UAAU,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B;AAED,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,WAAW,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,GACf,EAAE,kBAAkB,2CAsEpB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* LaunchpadCard — one card per widget in the list view.
|
|
4
|
+
*
|
|
5
|
+
* Handles both modes:
|
|
6
|
+
* - `inline`: card body renders the widget component in place (expanded card)
|
|
7
|
+
* - `detail`: card is clickable; triggers `onOpenDetail` (consumer routes to detail)
|
|
8
|
+
*
|
|
9
|
+
* Completion state shows a "completed" pill + revisit affordance.
|
|
10
|
+
*/
|
|
11
|
+
import { Check, ChevronRight } from "lucide-react";
|
|
12
|
+
export function LaunchpadCard({ widget, isCompleted, isExpanded, metadata, onOpenDetail, onToggleInline, onComplete, onCancelInline, }) {
|
|
13
|
+
const isInline = widget.mode === "inline";
|
|
14
|
+
const canRevisit = isCompleted && widget.revisitable === true;
|
|
15
|
+
const handleHeaderClick = () => {
|
|
16
|
+
if (isInline) {
|
|
17
|
+
onToggleInline();
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
onOpenDetail();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const headerLabel = isCompleted
|
|
24
|
+
? canRevisit
|
|
25
|
+
? (widget.revisitActionLabel ?? "Revisit")
|
|
26
|
+
: "Completed"
|
|
27
|
+
: isInline
|
|
28
|
+
? (widget.mode === "inline" && widget.actionLabel) || "Open"
|
|
29
|
+
: "Open";
|
|
30
|
+
return (_jsxs("article", { className: "rounded-lg border bg-card shadow-sm transition-shadow hover:shadow-md", "data-completed": isCompleted ? "true" : undefined, children: [_jsxs("button", { type: "button", onClick: handleHeaderClick, className: "flex w-full items-center justify-between gap-4 p-5 text-left", "aria-expanded": isInline ? isExpanded : undefined, children: [_jsxs("div", { className: "flex min-w-0 items-start gap-3", children: [_jsx("div", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-full border bg-background", "aria-hidden": "true", children: isCompleted ? (_jsx(Check, { className: "h-3.5 w-3.5 text-primary" })) : (_jsx("span", { className: "h-2 w-2 rounded-full bg-muted-foreground/40" })) }), _jsxs("div", { className: "min-w-0", children: [_jsx("h3", { className: "truncate text-base font-medium", children: widget.label }), widget.description ? (_jsx("p", { className: "mt-0.5 line-clamp-2 text-sm text-muted-foreground", children: widget.description })) : null] })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2 text-sm text-muted-foreground", children: [_jsx("span", { children: headerLabel }), !isInline ? _jsx(ChevronRight, { className: "h-4 w-4", "aria-hidden": "true" }) : null] })] }), isInline && isExpanded ? (_jsx("div", { className: "border-t px-5 pb-5 pt-4", children: _jsx(InlineWidgetBody, { widget: widget, isCompleted: isCompleted, metadata: metadata, onComplete: onComplete, onCancel: onCancelInline }) })) : null] }));
|
|
31
|
+
}
|
|
32
|
+
function InlineWidgetBody({ widget, isCompleted, metadata, onComplete, onCancel, }) {
|
|
33
|
+
const Component = widget.component;
|
|
34
|
+
const props = {
|
|
35
|
+
onComplete,
|
|
36
|
+
onCancel,
|
|
37
|
+
isCompleted,
|
|
38
|
+
metadata,
|
|
39
|
+
};
|
|
40
|
+
return _jsx(Component, { ...props });
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=LaunchpadCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LaunchpadCard.js","sourceRoot":"","sources":["../../../../src/client/launchpad/LaunchpadCard.tsx"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAiBlD,MAAM,UAAU,aAAa,CAAC,EAC5B,MAAM,EACN,WAAW,EACX,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,GACK;IACnB,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAA;IACzC,MAAM,UAAU,GAAG,WAAW,IAAI,MAAM,CAAC,WAAW,KAAK,IAAI,CAAA;IAE7D,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,IAAI,QAAQ,EAAE,CAAC;YACb,cAAc,EAAE,CAAA;QAClB,CAAC;aAAM,CAAC;YACN,YAAY,EAAE,CAAA;QAChB,CAAC;IACH,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,WAAW;QAC7B,CAAC,CAAC,UAAU;YACV,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,IAAI,SAAS,CAAC;YAC1C,CAAC,CAAC,WAAW;QACf,CAAC,CAAC,QAAQ;YACR,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM;YAC5D,CAAC,CAAC,MAAM,CAAA;IAEZ,OAAO,CACL,mBACE,SAAS,EAAC,uEAAuE,oBACjE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,aAEhD,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAC,8DAA8D,mBACzD,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,aAEhD,eAAK,SAAS,EAAC,gCAAgC,aAC7C,cACE,SAAS,EAAC,4FAA4F,iBAC1F,MAAM,YAEjB,WAAW,CAAC,CAAC,CAAC,CACb,KAAC,KAAK,IAAC,SAAS,EAAC,0BAA0B,GAAG,CAC/C,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,6CAA6C,GAAG,CACjE,GACG,EACN,eAAK,SAAS,EAAC,SAAS,aACtB,aAAI,SAAS,EAAC,gCAAgC,YAAE,MAAM,CAAC,KAAK,GAAM,EACjE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CACpB,YAAG,SAAS,EAAC,mDAAmD,YAC7D,MAAM,CAAC,WAAW,GACjB,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,IACF,EACN,eAAK,SAAS,EAAC,gEAAgE,aAC7E,yBAAO,WAAW,GAAQ,EACzB,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAC,YAAY,IAAC,SAAS,EAAC,SAAS,iBAAa,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,IACvE,IACC,EAER,QAAQ,IAAI,UAAU,CAAC,CAAC,CAAC,CACxB,cAAK,SAAS,EAAC,yBAAyB,YACtC,KAAC,gBAAgB,IACf,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,cAAc,GACxB,GACE,CACP,CAAC,CAAC,CAAC,IAAI,IACA,CACX,CAAA;AACH,CAAC;AAUD,SAAS,gBAAgB,CAAC,EACxB,MAAM,EACN,WAAW,EACX,QAAQ,EACR,UAAU,EACV,QAAQ,GACc;IACtB,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAA;IAClC,MAAM,KAAK,GAA+B;QACxC,UAAU;QACV,QAAQ;QACR,WAAW;QACX,QAAQ;KACT,CAAA;IACD,OAAO,KAAC,SAAS,OAAK,KAAK,GAAI,CAAA;AACjC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LaunchpadDetailPanel — slide-out panel that hosts a `mode: "detail"` widget.
|
|
3
|
+
*
|
|
4
|
+
* The list compresses into a left rail and this panel takes the remaining
|
|
5
|
+
* width. Framer-motion handles the slide-in animation; `useReducedMotion`
|
|
6
|
+
* collapses the animation to an instant swap when the OS asks for it.
|
|
7
|
+
*/
|
|
8
|
+
import type { LaunchpadWidgetDefinition } from "../../lib/types.ts";
|
|
9
|
+
interface LaunchpadDetailPanelProps {
|
|
10
|
+
widget: LaunchpadWidgetDefinition & {
|
|
11
|
+
mode: "detail";
|
|
12
|
+
};
|
|
13
|
+
isCompleted: boolean;
|
|
14
|
+
metadata?: Record<string, unknown>;
|
|
15
|
+
stepIndex?: number;
|
|
16
|
+
totalSteps?: number;
|
|
17
|
+
onComplete: () => void;
|
|
18
|
+
onClose: () => void;
|
|
19
|
+
}
|
|
20
|
+
export declare function LaunchpadDetailPanel({ widget, isCompleted, metadata, stepIndex, totalSteps, onComplete, onClose, }: LaunchpadDetailPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=LaunchpadDetailPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LaunchpadDetailPanel.d.ts","sourceRoot":"","sources":["../../../../src/client/launchpad/LaunchpadDetailPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,oBAAoB,CAAA;AAE3B,UAAU,yBAAyB;IACjC,MAAM,EAAE,yBAAyB,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAA;IACtD,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,IAAI,CAAA;IACtB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED,wBAAgB,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,QAAQ,EACR,SAAS,EACT,UAAU,EACV,UAAU,EACV,OAAO,GACR,EAAE,yBAAyB,2CAoD3B"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* LaunchpadDetailPanel — slide-out panel that hosts a `mode: "detail"` widget.
|
|
4
|
+
*
|
|
5
|
+
* The list compresses into a left rail and this panel takes the remaining
|
|
6
|
+
* width. Framer-motion handles the slide-in animation; `useReducedMotion`
|
|
7
|
+
* collapses the animation to an instant swap when the OS asks for it.
|
|
8
|
+
*/
|
|
9
|
+
import { motion, useReducedMotion } from "framer-motion";
|
|
10
|
+
import { X } from "lucide-react";
|
|
11
|
+
export function LaunchpadDetailPanel({ widget, isCompleted, metadata, stepIndex, totalSteps, onComplete, onClose, }) {
|
|
12
|
+
const reducedMotion = useReducedMotion();
|
|
13
|
+
const Component = widget.component;
|
|
14
|
+
const props = {
|
|
15
|
+
onComplete,
|
|
16
|
+
onCancel: onClose,
|
|
17
|
+
isCompleted,
|
|
18
|
+
metadata,
|
|
19
|
+
stepIndex,
|
|
20
|
+
totalSteps,
|
|
21
|
+
};
|
|
22
|
+
return (_jsxs(motion.section, { initial: reducedMotion ? { opacity: 0 } : { opacity: 0, x: 40 }, animate: reducedMotion ? { opacity: 1 } : { opacity: 1, x: 0 }, exit: reducedMotion ? { opacity: 0 } : { opacity: 0, x: 40 }, transition: { duration: reducedMotion ? 0.1 : 0.28, ease: "easeOut" }, className: "flex h-full flex-col rounded-lg border bg-card shadow-sm", "aria-labelledby": `launchpad-detail-${widget.id}-title`, children: [_jsxs("header", { className: "flex items-start justify-between gap-4 border-b px-6 py-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("h2", { id: `launchpad-detail-${widget.id}-title`, className: "truncate text-xl font-semibold tracking-tight", children: widget.label }), widget.description ? (_jsx("p", { className: "mt-1 line-clamp-2 text-sm text-muted-foreground", children: widget.description })) : null] }), _jsx("button", { type: "button", onClick: onClose, className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground", "aria-label": "Close", children: _jsx(X, { className: "h-5 w-5", "aria-hidden": "true" }) })] }), _jsx("div", { className: "flex-1 overflow-auto px-6 py-6", children: _jsx(Component, { ...props }) })] }, widget.id));
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=LaunchpadDetailPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LaunchpadDetailPanel.js","sourceRoot":"","sources":["../../../../src/client/launchpad/LaunchpadDetailPanel.tsx"],"names":[],"mappings":";AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AACxD,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AAgBhC,MAAM,UAAU,oBAAoB,CAAC,EACnC,MAAM,EACN,WAAW,EACX,QAAQ,EACR,SAAS,EACT,UAAU,EACV,UAAU,EACV,OAAO,GACmB;IAC1B,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAA;IAExC,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAA;IAClC,MAAM,KAAK,GAA+B;QACxC,UAAU;QACV,QAAQ,EAAE,OAAO;QACjB,WAAW;QACX,QAAQ;QACR,SAAS;QACT,UAAU;KACX,CAAA;IAED,OAAO,CACL,MAAC,MAAM,CAAC,OAAO,IAEb,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAC/D,OAAO,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAC9D,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAC5D,UAAU,EAAE,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EACrE,SAAS,EAAC,0DAA0D,qBACnD,oBAAoB,MAAM,CAAC,EAAE,QAAQ,aAEtD,kBAAQ,SAAS,EAAC,2DAA2D,aAC3E,eAAK,SAAS,EAAC,SAAS,aACtB,aACE,EAAE,EAAE,oBAAoB,MAAM,CAAC,EAAE,QAAQ,EACzC,SAAS,EAAC,+CAA+C,YAExD,MAAM,CAAC,KAAK,GACV,EACJ,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CACpB,YAAG,SAAS,EAAC,iDAAiD,YAC3D,MAAM,CAAC,WAAW,GACjB,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,EACN,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,gGAAgG,gBAC/F,OAAO,YAElB,KAAC,CAAC,IAAC,SAAS,EAAC,SAAS,iBAAa,MAAM,GAAG,GACrC,IACF,EAET,cAAK,SAAS,EAAC,gCAAgC,YAC7C,KAAC,SAAS,OAAK,KAAK,GAAI,GACpB,KAlCD,MAAM,CAAC,EAAE,CAmCC,CAClB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LaunchpadList — platform renderer for the Launchpad surface.
|
|
3
|
+
*
|
|
4
|
+
* Consumes widget contributions (declared client-side via
|
|
5
|
+
* `defineClient({ launchpad: { widgetsByScope: ... } })`) and renders them
|
|
6
|
+
* as a card-stack list. Detail-mode widgets surface in a slide-out panel
|
|
7
|
+
* (URL-keyed via consumer-controlled `selectedWidgetId` / `onSelectWidget`);
|
|
8
|
+
* inline-mode widgets expand in place.
|
|
9
|
+
*
|
|
10
|
+
* Server state for per-widget completions and the scope-level "all complete"
|
|
11
|
+
* marker comes from `launchpadApi.checkStatus`. Routing is consumer-controlled
|
|
12
|
+
* so the same component works in single-page contexts that don't want a URL
|
|
13
|
+
* segment per widget.
|
|
14
|
+
*/
|
|
15
|
+
import type { LaunchpadWidgetDefinition } from "../../lib/types.ts";
|
|
16
|
+
export interface LaunchpadListProps {
|
|
17
|
+
/** Scope type for which widgets are gathered (e.g., "client"). */
|
|
18
|
+
scope: string;
|
|
19
|
+
/** Scope entity id. */
|
|
20
|
+
scopeId: string;
|
|
21
|
+
/** Optional override — bypass contribution collection. */
|
|
22
|
+
widgets?: LaunchpadWidgetDefinition[];
|
|
23
|
+
/**
|
|
24
|
+
* Currently-selected detail widget id (consumer-controlled — typically wired
|
|
25
|
+
* to a URL segment via TanStack Router). `null` shows the list only.
|
|
26
|
+
*/
|
|
27
|
+
selectedWidgetId?: string | null;
|
|
28
|
+
/** Called when a detail-mode card is opened or the detail is closed. */
|
|
29
|
+
onSelectWidget?: (widgetId: string | null) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Called after `launchpadApi.complete` succeeds — the scope has graduated.
|
|
32
|
+
* Consumer typically navigates to the post-graduation surface.
|
|
33
|
+
*/
|
|
34
|
+
onComplete?: () => void;
|
|
35
|
+
/** Optional userId for `condition` evaluation. Defaults to empty string. */
|
|
36
|
+
userId?: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function LaunchpadList({ scope, scopeId, widgets: widgetsOverride, selectedWidgetId, onSelectWidget, onComplete, userId, }: LaunchpadListProps): import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
//# sourceMappingURL=LaunchpadList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LaunchpadList.d.ts","sourceRoot":"","sources":["../../../../src/client/launchpad/LaunchpadList.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAOnE,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAA;IACb,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAA;IACf,0DAA0D;IAC1D,OAAO,CAAC,EAAE,yBAAyB,EAAE,CAAA;IACrC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAChC,wEAAwE;IACxE,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAClD;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,OAAO,EACP,OAAO,EAAE,eAAe,EACxB,gBAAuB,EACvB,cAAc,EACd,UAAU,EACV,MAAW,GACZ,EAAE,kBAAkB,2CAmOpB"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* LaunchpadList — platform renderer for the Launchpad surface.
|
|
4
|
+
*
|
|
5
|
+
* Consumes widget contributions (declared client-side via
|
|
6
|
+
* `defineClient({ launchpad: { widgetsByScope: ... } })`) and renders them
|
|
7
|
+
* as a card-stack list. Detail-mode widgets surface in a slide-out panel
|
|
8
|
+
* (URL-keyed via consumer-controlled `selectedWidgetId` / `onSelectWidget`);
|
|
9
|
+
* inline-mode widgets expand in place.
|
|
10
|
+
*
|
|
11
|
+
* Server state for per-widget completions and the scope-level "all complete"
|
|
12
|
+
* marker comes from `launchpadApi.checkStatus`. Routing is consumer-controlled
|
|
13
|
+
* so the same component works in single-page contexts that don't want a URL
|
|
14
|
+
* segment per widget.
|
|
15
|
+
*/
|
|
16
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
17
|
+
import { AnimatePresence, motion, useReducedMotion } from "framer-motion";
|
|
18
|
+
import { Loader2 } from "lucide-react";
|
|
19
|
+
import { useMutation, useQuery, useQueryClient } from "@ydtb/tk-scope-query-client";
|
|
20
|
+
import { useContributions } from "@ydtb/tk-scope/client";
|
|
21
|
+
import { launchpadApi } from "../../lib/platform-api.js";
|
|
22
|
+
import { LaunchpadCard } from "./LaunchpadCard.js";
|
|
23
|
+
import { LaunchpadDetailPanel } from "./LaunchpadDetailPanel.js";
|
|
24
|
+
import { SetupProgressCard } from "./SetupProgressCard.js";
|
|
25
|
+
import { getLaunchpadWidgets } from "./launchpad-registry.js";
|
|
26
|
+
import { sortWidgets } from "./sortWidgets.js";
|
|
27
|
+
export function LaunchpadList({ scope, scopeId, widgets: widgetsOverride, selectedWidgetId = null, onSelectWidget, onComplete, userId = "", }) {
|
|
28
|
+
const queryClient = useQueryClient();
|
|
29
|
+
const contributions = useContributions("launchpad");
|
|
30
|
+
const statusQuery = useQuery({
|
|
31
|
+
...launchpadApi.checkStatus.queryOptions({ input: { scope, scopeId } }),
|
|
32
|
+
});
|
|
33
|
+
const completedMap = useMemo(() => {
|
|
34
|
+
const m = new Map();
|
|
35
|
+
for (const row of statusQuery.data?.completedWidgets ?? []) {
|
|
36
|
+
m.set(row.widgetId, { completedAt: row.completedAt, metadata: row.metadata });
|
|
37
|
+
}
|
|
38
|
+
return m;
|
|
39
|
+
}, [statusQuery.data?.completedWidgets]);
|
|
40
|
+
const completedIds = useMemo(() => Array.from(completedMap.keys()), [completedMap]);
|
|
41
|
+
const sortedWidgets = useMemo(() => {
|
|
42
|
+
const collected = widgetsOverride ?? getLaunchpadWidgets(scope, contributions);
|
|
43
|
+
return sortWidgets(collected);
|
|
44
|
+
}, [widgetsOverride, contributions, scope]);
|
|
45
|
+
const activeWidgets = useMemo(() => {
|
|
46
|
+
return sortedWidgets.filter((widget) => {
|
|
47
|
+
if (!widget.condition)
|
|
48
|
+
return true;
|
|
49
|
+
return widget.condition({
|
|
50
|
+
previouslyCompletedWidgets: completedIds,
|
|
51
|
+
launchpadMetadata: {},
|
|
52
|
+
scope,
|
|
53
|
+
scopeId,
|
|
54
|
+
userId,
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}, [sortedWidgets, completedIds, scope, scopeId, userId]);
|
|
58
|
+
const requiredWidgets = useMemo(() => activeWidgets.filter((w) => (w.priority ?? "required") === "required"), [activeWidgets]);
|
|
59
|
+
const completedCount = useMemo(() => activeWidgets.filter((w) => completedMap.has(w.id)).length, [activeWidgets, completedMap]);
|
|
60
|
+
const allRequiredComplete = requiredWidgets.length > 0 &&
|
|
61
|
+
requiredWidgets.every((w) => completedMap.has(w.id));
|
|
62
|
+
const completeWidgetMutation = useMutation({
|
|
63
|
+
...launchpadApi.completeWidget.mutationOptions(),
|
|
64
|
+
onSuccess: () => {
|
|
65
|
+
void queryClient.invalidateQueries({
|
|
66
|
+
queryKey: launchpadApi.checkStatus.queryOptions({
|
|
67
|
+
input: { scope, scopeId },
|
|
68
|
+
}).queryKey,
|
|
69
|
+
});
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
const completeMutation = useMutation({
|
|
73
|
+
...launchpadApi.complete.mutationOptions(),
|
|
74
|
+
onSuccess: () => {
|
|
75
|
+
void queryClient.invalidateQueries({
|
|
76
|
+
queryKey: launchpadApi.checkStatus.queryOptions({
|
|
77
|
+
input: { scope, scopeId },
|
|
78
|
+
}).queryKey,
|
|
79
|
+
});
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
// Fire `complete` once when all required widgets are done; gated by the
|
|
83
|
+
// server's allCompletedAt so re-renders don't re-fire after the first call
|
|
84
|
+
// and an idempotent server response keeps this safe across races.
|
|
85
|
+
const completionFiredRef = useRef(false);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (allRequiredComplete &&
|
|
88
|
+
!statusQuery.data?.allCompletedAt &&
|
|
89
|
+
!completionFiredRef.current &&
|
|
90
|
+
!completeMutation.isPending) {
|
|
91
|
+
completionFiredRef.current = true;
|
|
92
|
+
void completeMutation.mutateAsync({ scope, scopeId });
|
|
93
|
+
}
|
|
94
|
+
}, [
|
|
95
|
+
allRequiredComplete,
|
|
96
|
+
statusQuery.data?.allCompletedAt,
|
|
97
|
+
completeMutation,
|
|
98
|
+
scope,
|
|
99
|
+
scopeId,
|
|
100
|
+
]);
|
|
101
|
+
// Surface graduation upward once the marker is set server-side.
|
|
102
|
+
const onCompleteRef = useRef(onComplete);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
onCompleteRef.current = onComplete;
|
|
105
|
+
});
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
if (statusQuery.data?.allCompletedAt)
|
|
108
|
+
onCompleteRef.current?.();
|
|
109
|
+
}, [statusQuery.data?.allCompletedAt]);
|
|
110
|
+
const [expandedInlineId, setExpandedInlineId] = useState(null);
|
|
111
|
+
const handleOpenDetail = useCallback((widgetId) => {
|
|
112
|
+
onSelectWidget?.(widgetId);
|
|
113
|
+
}, [onSelectWidget]);
|
|
114
|
+
const handleCloseDetail = useCallback(() => {
|
|
115
|
+
onSelectWidget?.(null);
|
|
116
|
+
}, [onSelectWidget]);
|
|
117
|
+
const handleToggleInline = useCallback((widgetId) => {
|
|
118
|
+
setExpandedInlineId((prev) => (prev === widgetId ? null : widgetId));
|
|
119
|
+
}, []);
|
|
120
|
+
const handleWidgetComplete = useCallback(async (widgetId, metadata) => {
|
|
121
|
+
await completeWidgetMutation.mutateAsync({
|
|
122
|
+
scope,
|
|
123
|
+
scopeId,
|
|
124
|
+
widgetId,
|
|
125
|
+
metadata,
|
|
126
|
+
});
|
|
127
|
+
}, [completeWidgetMutation, scope, scopeId]);
|
|
128
|
+
const selectedWidget = useMemo(() => {
|
|
129
|
+
if (!selectedWidgetId)
|
|
130
|
+
return null;
|
|
131
|
+
const found = activeWidgets.find((w) => w.id === selectedWidgetId);
|
|
132
|
+
return found && found.mode === "detail" ? found : null;
|
|
133
|
+
}, [selectedWidgetId, activeWidgets]);
|
|
134
|
+
const reducedMotion = useReducedMotion();
|
|
135
|
+
const detailOpen = selectedWidget !== null;
|
|
136
|
+
const listClassName = detailOpen
|
|
137
|
+
? "w-full max-w-sm shrink-0"
|
|
138
|
+
: "mx-auto w-full max-w-2xl";
|
|
139
|
+
if (statusQuery.isPending) {
|
|
140
|
+
return (_jsx("div", { className: "flex min-h-[40vh] items-center justify-center", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }));
|
|
141
|
+
}
|
|
142
|
+
if (activeWidgets.length === 0) {
|
|
143
|
+
return (_jsxs("div", { className: "mx-auto w-full max-w-2xl px-4 py-12", children: [_jsx(SetupProgressCard, { completedCount: 0, totalCount: 0, showEmpty: true }), _jsxs("p", { className: "mt-6 text-center text-sm text-muted-foreground", children: ["No Launchpad widgets contributed for scope ", _jsx("code", { className: "font-mono", children: scope }), "."] })] }));
|
|
144
|
+
}
|
|
145
|
+
return (_jsxs("div", { className: "flex w-full gap-6 px-4 py-8", children: [_jsxs(motion.div, { layout: !reducedMotion, className: listClassName, transition: { duration: reducedMotion ? 0 : 0.28, ease: "easeOut" }, children: [_jsx(SetupProgressCard, { completedCount: completedCount, totalCount: activeWidgets.length }), _jsx("ul", { className: "mt-4 flex flex-col gap-3", children: activeWidgets.map((widget) => {
|
|
146
|
+
const completed = completedMap.has(widget.id);
|
|
147
|
+
const isExpanded = expandedInlineId === widget.id;
|
|
148
|
+
return (_jsx("li", { children: _jsx(LaunchpadCard, { widget: widget, isCompleted: completed, isExpanded: isExpanded, metadata: completedMap.get(widget.id)?.metadata, onOpenDetail: () => handleOpenDetail(widget.id), onToggleInline: () => handleToggleInline(widget.id), onComplete: () => {
|
|
149
|
+
void handleWidgetComplete(widget.id);
|
|
150
|
+
setExpandedInlineId(null);
|
|
151
|
+
}, onCancelInline: () => setExpandedInlineId(null) }) }, widget.id));
|
|
152
|
+
}) })] }), _jsx(AnimatePresence, { mode: "wait", children: selectedWidget ? (_jsx(motion.div, { layout: !reducedMotion, className: "min-w-0 flex-1", children: _jsx(LaunchpadDetailPanel, { widget: selectedWidget, isCompleted: completedMap.has(selectedWidget.id), metadata: completedMap.get(selectedWidget.id)?.metadata, onComplete: () => {
|
|
153
|
+
void handleWidgetComplete(selectedWidget.id);
|
|
154
|
+
handleCloseDetail();
|
|
155
|
+
}, onClose: handleCloseDetail }) }, "detail-host")) : null })] }));
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=LaunchpadList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LaunchpadList.js","sourceRoot":"","sources":["../../../../src/client/launchpad/LaunchpadList.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup progress card — renders at the top of the Launchpad list.
|
|
3
|
+
*
|
|
4
|
+
* Shows "X of Y complete" with a progress bar. Operator-config-driven text
|
|
5
|
+
* (title / pep line) is a future addition; v1 uses static labels.
|
|
6
|
+
*/
|
|
7
|
+
interface SetupProgressCardProps {
|
|
8
|
+
completedCount: number;
|
|
9
|
+
totalCount: number;
|
|
10
|
+
/** Show even when there are no widgets (e.g., empty launchpad). Defaults to false. */
|
|
11
|
+
showEmpty?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function SetupProgressCard({ completedCount, totalCount, showEmpty, }: SetupProgressCardProps): import("react/jsx-runtime").JSX.Element | null;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=SetupProgressCard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SetupProgressCard.d.ts","sourceRoot":"","sources":["../../../../src/client/launchpad/SetupProgressCard.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,UAAU,sBAAsB;IAC9B,cAAc,EAAE,MAAM,CAAA;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,sFAAsF;IACtF,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,cAAc,EACd,UAAU,EACV,SAAiB,GAClB,EAAE,sBAAsB,kDAoCxB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function SetupProgressCard({ completedCount, totalCount, showEmpty = false, }) {
|
|
3
|
+
if (totalCount === 0 && !showEmpty)
|
|
4
|
+
return null;
|
|
5
|
+
const ratio = totalCount === 0 ? 0 : completedCount / totalCount;
|
|
6
|
+
const percent = Math.round(ratio * 100);
|
|
7
|
+
const isComplete = totalCount > 0 && completedCount === totalCount;
|
|
8
|
+
return (_jsxs("div", { className: "rounded-lg border bg-card p-6 shadow-sm", role: "region", "aria-label": "Setup progress", children: [_jsxs("div", { className: "flex items-baseline justify-between gap-4", children: [_jsx("h2", { className: "text-lg font-semibold tracking-tight", children: isComplete ? "All set up" : "Get set up" }), _jsxs("span", { className: "text-sm tabular-nums text-muted-foreground", children: [completedCount, " of ", totalCount, " complete"] })] }), _jsx("div", { className: "mt-4 h-2 overflow-hidden rounded-full bg-muted", role: "progressbar", "aria-valuenow": percent, "aria-valuemin": 0, "aria-valuemax": 100, children: _jsx("div", { className: "h-full bg-primary transition-[width] duration-500 ease-out", style: { width: `${percent}%` } }) })] }));
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=SetupProgressCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SetupProgressCard.js","sourceRoot":"","sources":["../../../../src/client/launchpad/SetupProgressCard.tsx"],"names":[],"mappings":";AAcA,MAAM,UAAU,iBAAiB,CAAC,EAChC,cAAc,EACd,UAAU,EACV,SAAS,GAAG,KAAK,GACM;IACvB,IAAI,UAAU,KAAK,CAAC,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAA;IAE/C,MAAM,KAAK,GAAG,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,GAAG,UAAU,CAAA;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAA;IACvC,MAAM,UAAU,GAAG,UAAU,GAAG,CAAC,IAAI,cAAc,KAAK,UAAU,CAAA;IAElE,OAAO,CACL,eACE,SAAS,EAAC,yCAAyC,EACnD,IAAI,EAAC,QAAQ,gBACF,gBAAgB,aAE3B,eAAK,SAAS,EAAC,2CAA2C,aACxD,aAAI,SAAS,EAAC,sCAAsC,YACjD,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,GACtC,EACL,gBAAM,SAAS,EAAC,4CAA4C,aACzD,cAAc,UAAM,UAAU,iBAC1B,IACH,EAEN,cACE,SAAS,EAAC,gDAAgD,EAC1D,IAAI,EAAC,aAAa,mBACH,OAAO,mBACP,CAAC,mBACD,GAAG,YAElB,cACE,SAAS,EAAC,4DAA4D,EACtE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,OAAO,GAAG,EAAE,GAC/B,GACE,IACF,CACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ydtb/tk-scope-app/client/launchpad — Launchpad surface renderer.
|
|
3
|
+
*
|
|
4
|
+
* Composes Launchpad widget contributions (`defineClient({ launchpad: ... })`)
|
|
5
|
+
* into a card-stack list with optional URL-keyed detail panel.
|
|
6
|
+
*/
|
|
7
|
+
export { LaunchpadList, type LaunchpadListProps } from "./LaunchpadList.tsx";
|
|
8
|
+
export { LaunchpadCard } from "./LaunchpadCard.tsx";
|
|
9
|
+
export { LaunchpadDetailPanel } from "./LaunchpadDetailPanel.tsx";
|
|
10
|
+
export { SetupProgressCard } from "./SetupProgressCard.tsx";
|
|
11
|
+
export { sortWidgets } from "./sortWidgets.ts";
|
|
12
|
+
export { getLaunchpadWidgets, type LaunchpadContribution } from "./launchpad-registry.ts";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/client/launchpad/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,mBAAmB,EAAE,KAAK,qBAAqB,EAAE,MAAM,yBAAyB,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ydtb/tk-scope-app/client/launchpad — Launchpad surface renderer.
|
|
3
|
+
*
|
|
4
|
+
* Composes Launchpad widget contributions (`defineClient({ launchpad: ... })`)
|
|
5
|
+
* into a card-stack list with optional URL-keyed detail panel.
|
|
6
|
+
*/
|
|
7
|
+
export { LaunchpadList } from "./LaunchpadList.js";
|
|
8
|
+
export { LaunchpadCard } from "./LaunchpadCard.js";
|
|
9
|
+
export { LaunchpadDetailPanel } from "./LaunchpadDetailPanel.js";
|
|
10
|
+
export { SetupProgressCard } from "./SetupProgressCard.js";
|
|
11
|
+
export { sortWidgets } from "./sortWidgets.js";
|
|
12
|
+
export { getLaunchpadWidgets } from "./launchpad-registry.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/client/launchpad/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAA2B,MAAM,oBAAqB,CAAA;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAqB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA4B,CAAA;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAyB,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,mBAAmB,EAA8B,MAAM,yBAAyB,CAAA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Launchpad widget contribution accessor.
|
|
3
|
+
*
|
|
4
|
+
* Tools contribute widgets declaratively via `defineClient({ launchpad: ... })`.
|
|
5
|
+
* This helper flattens the contribution set for a given scope. Mirrors
|
|
6
|
+
* `onboarding-registry.ts`.
|
|
7
|
+
*/
|
|
8
|
+
import type { LaunchpadWidgetDefinition, LaunchpadWidgetsByScope } from "../../lib/types.ts";
|
|
9
|
+
export interface LaunchpadContribution {
|
|
10
|
+
widgetsByScope?: LaunchpadWidgetsByScope;
|
|
11
|
+
}
|
|
12
|
+
export declare function getLaunchpadWidgets(scope: string, contributions: LaunchpadContribution[]): LaunchpadWidgetDefinition[];
|
|
13
|
+
//# sourceMappingURL=launchpad-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launchpad-registry.d.ts","sourceRoot":"","sources":["../../../../src/client/launchpad/launchpad-registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,yBAAyB,EACzB,uBAAuB,EACxB,MAAM,oBAAoB,CAAA;AAE3B,MAAM,WAAW,qBAAqB;IACpC,cAAc,CAAC,EAAE,uBAAuB,CAAA;CACzC;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,qBAAqB,EAAE,GACrC,yBAAyB,EAAE,CAE7B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Launchpad widget contribution accessor.
|
|
3
|
+
*
|
|
4
|
+
* Tools contribute widgets declaratively via `defineClient({ launchpad: ... })`.
|
|
5
|
+
* This helper flattens the contribution set for a given scope. Mirrors
|
|
6
|
+
* `onboarding-registry.ts`.
|
|
7
|
+
*/
|
|
8
|
+
export function getLaunchpadWidgets(scope, contributions) {
|
|
9
|
+
return contributions.flatMap((c) => c.widgetsByScope?.[scope] ?? []);
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=launchpad-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launchpad-registry.js","sourceRoot":"","sources":["../../../../src/client/launchpad/launchpad-registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAWH,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,aAAsC;IAEtC,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;AACtE,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LaunchpadWidgetDefinition } from "../../lib/types.ts";
|
|
2
|
+
/**
|
|
3
|
+
* Sort Launchpad widgets topologically — Kahn's algorithm.
|
|
4
|
+
*
|
|
5
|
+
* Rules:
|
|
6
|
+
* - `dependsOn` is the hard constraint — a widget cannot appear before all its
|
|
7
|
+
* listed dependencies
|
|
8
|
+
* - `order` is the tiebreaker within the same dependency level (lower first)
|
|
9
|
+
* - Missing dependency ids (filtered out by `condition`, not registered yet)
|
|
10
|
+
* are treated as satisfied
|
|
11
|
+
* - Throws on circular dependency
|
|
12
|
+
*
|
|
13
|
+
* Mirrors `sortSteps` in `../../onboarding/sortSteps.ts` — kept as a separate
|
|
14
|
+
* file rather than a shared generic because the two sort orders may diverge
|
|
15
|
+
* (e.g., Launchpad might add a "priority bucket" tiebreaker before order).
|
|
16
|
+
*/
|
|
17
|
+
export declare function sortWidgets(widgets: LaunchpadWidgetDefinition[]): LaunchpadWidgetDefinition[];
|
|
18
|
+
//# sourceMappingURL=sortWidgets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sortWidgets.d.ts","sourceRoot":"","sources":["../../../../src/client/launchpad/sortWidgets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAEnE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,yBAAyB,EAAE,GACnC,yBAAyB,EAAE,CAqE7B"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sort Launchpad widgets topologically — Kahn's algorithm.
|
|
3
|
+
*
|
|
4
|
+
* Rules:
|
|
5
|
+
* - `dependsOn` is the hard constraint — a widget cannot appear before all its
|
|
6
|
+
* listed dependencies
|
|
7
|
+
* - `order` is the tiebreaker within the same dependency level (lower first)
|
|
8
|
+
* - Missing dependency ids (filtered out by `condition`, not registered yet)
|
|
9
|
+
* are treated as satisfied
|
|
10
|
+
* - Throws on circular dependency
|
|
11
|
+
*
|
|
12
|
+
* Mirrors `sortSteps` in `../../onboarding/sortSteps.ts` — kept as a separate
|
|
13
|
+
* file rather than a shared generic because the two sort orders may diverge
|
|
14
|
+
* (e.g., Launchpad might add a "priority bucket" tiebreaker before order).
|
|
15
|
+
*/
|
|
16
|
+
export function sortWidgets(widgets) {
|
|
17
|
+
if (widgets.length === 0)
|
|
18
|
+
return [];
|
|
19
|
+
const widgetIds = new Set(widgets.map((w) => w.id));
|
|
20
|
+
const inDegree = new Map();
|
|
21
|
+
const dependents = new Map();
|
|
22
|
+
for (const widget of widgets) {
|
|
23
|
+
if (!inDegree.has(widget.id))
|
|
24
|
+
inDegree.set(widget.id, 0);
|
|
25
|
+
if (!dependents.has(widget.id))
|
|
26
|
+
dependents.set(widget.id, []);
|
|
27
|
+
}
|
|
28
|
+
for (const widget of widgets) {
|
|
29
|
+
if (!widget.dependsOn)
|
|
30
|
+
continue;
|
|
31
|
+
for (const depId of widget.dependsOn) {
|
|
32
|
+
if (!widgetIds.has(depId))
|
|
33
|
+
continue;
|
|
34
|
+
inDegree.set(widget.id, (inDegree.get(widget.id) ?? 0) + 1);
|
|
35
|
+
dependents.get(depId).push(widget.id);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const ready = [];
|
|
39
|
+
for (const widget of widgets) {
|
|
40
|
+
if (inDegree.get(widget.id) === 0)
|
|
41
|
+
ready.push(widget);
|
|
42
|
+
}
|
|
43
|
+
ready.sort((a, b) => a.order - b.order);
|
|
44
|
+
const result = [];
|
|
45
|
+
const widgetById = new Map(widgets.map((w) => [w.id, w]));
|
|
46
|
+
while (ready.length > 0) {
|
|
47
|
+
const current = ready.shift();
|
|
48
|
+
result.push(current);
|
|
49
|
+
const nextBatch = [];
|
|
50
|
+
for (const depId of dependents.get(current.id) ?? []) {
|
|
51
|
+
const newDegree = (inDegree.get(depId) ?? 0) - 1;
|
|
52
|
+
inDegree.set(depId, newDegree);
|
|
53
|
+
if (newDegree === 0) {
|
|
54
|
+
const depWidget = widgetById.get(depId);
|
|
55
|
+
if (depWidget)
|
|
56
|
+
nextBatch.push(depWidget);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (nextBatch.length > 0) {
|
|
60
|
+
nextBatch.sort((a, b) => a.order - b.order);
|
|
61
|
+
for (const widget of nextBatch) {
|
|
62
|
+
let inserted = false;
|
|
63
|
+
for (let i = 0; i < ready.length; i++) {
|
|
64
|
+
if (widget.order < ready[i].order) {
|
|
65
|
+
ready.splice(i, 0, widget);
|
|
66
|
+
inserted = true;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (!inserted)
|
|
71
|
+
ready.push(widget);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (result.length !== widgets.length) {
|
|
76
|
+
const remaining = widgets
|
|
77
|
+
.filter((w) => !result.find((r) => r.id === w.id))
|
|
78
|
+
.map((w) => w.id);
|
|
79
|
+
throw new Error(`Circular dependency detected in launchpad widgets: ${remaining.join(", ")}`);
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=sortWidgets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sortWidgets.js","sourceRoot":"","sources":["../../../../src/client/launchpad/sortWidgets.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,WAAW,CACzB,OAAoC;IAEpC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAEnC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAEnD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAkB,CAAA;IAC1C,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAA;IAE9C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;QACxD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAAE,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IAC/D,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,SAAQ;QAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;gBAAE,SAAQ;YACnC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC3D,UAAU,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACxC,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAgC,EAAE,CAAA;IAC7C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACvD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;IAEvC,MAAM,MAAM,GAAgC,EAAE,CAAA;IAC9C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IAEzD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAG,CAAA;QAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAEpB,MAAM,SAAS,GAAgC,EAAE,CAAA;QACjD,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YACrD,MAAM,SAAS,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YAChD,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;YAC9B,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;gBACpB,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;gBACvC,IAAI,SAAS;oBAAE,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;QAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAA;YAC3C,KAAK,MAAM,MAAM,IAAI,SAAS,EAAE,CAAC;gBAC/B,IAAI,QAAQ,GAAG,KAAK,CAAA;gBACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACtC,IAAI,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC,KAAK,EAAE,CAAC;wBACnC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAA;wBAC1B,QAAQ,GAAG,IAAI,CAAA;wBACf,MAAK;oBACP,CAAC;gBACH,CAAC;gBACD,IAAI,CAAC,QAAQ;oBAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,OAAO;aACtB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACjD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACnB,MAAM,IAAI,KAAK,CAAC,sDAAsD,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC/F,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -11,7 +11,7 @@ export declare class ErrorBoundary extends Component<Props, State> {
|
|
|
11
11
|
constructor(props: Props);
|
|
12
12
|
static getDerivedStateFromError(error: Error): State;
|
|
13
13
|
componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
|
|
14
|
-
render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> |
|
|
14
|
+
render(): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null | undefined;
|
|
15
15
|
}
|
|
16
16
|
export {};
|
|
17
17
|
//# sourceMappingURL=ErrorBoundary.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-app.d.ts","sourceRoot":"","sources":["../../src/create-app.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAQpE,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,wBAAwB,CAAA;AAKtE,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAA;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAuBhD,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,yDAAyD;IACzD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,KAAK,CAAC;QACvB,EAAE,EAAE,MAAM,CAAA;QACV,SAAS,EAAE,aAAa,CAAC;YAAE,QAAQ,EAAE,SAAS,CAAA;SAAE,CAAC,CAAA;QACjD,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAC,CAAA;CACH;AA8DD;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"create-app.d.ts","sourceRoot":"","sources":["../../src/create-app.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAY,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAQpE,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,wBAAwB,CAAA;AAKtE,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAA;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAuBhD,MAAM,WAAW,gBAAgB;IAC/B,iFAAiF;IACjF,MAAM,CAAC,EAAE,eAAe,CAAA;IACxB,yDAAyD;IACzD,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,KAAK,CAAC;QACvB,EAAE,EAAE,MAAM,CAAA;QACV,SAAS,EAAE,aAAa,CAAC;YAAE,QAAQ,EAAE,SAAS,CAAA;SAAE,CAAC,CAAA;QACjD,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAC,CAAA;CACH;AA8DD;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,qyDAsPlD"}
|