@tutti-os/workbench-launchpad 0.0.58 → 0.0.60
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/index.d.ts +1 -1
- package/dist/index.js +7 -14
- package/dist/index.js.map +1 -1
- package/dist/styles/workbench-launchpad.css +18 -6
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -166,7 +166,7 @@ declare function resolveWorkbenchLaunchpadWheelNavigation(input: {
|
|
|
166
166
|
timestamp: number;
|
|
167
167
|
}): WorkbenchLaunchpadWheelNavigationResult;
|
|
168
168
|
|
|
169
|
-
declare function createWorkbenchLaunchpadDockIcon(
|
|
169
|
+
declare function createWorkbenchLaunchpadDockIcon(_input: {
|
|
170
170
|
tileIconUrls: readonly string[];
|
|
171
171
|
}): ReactNode;
|
|
172
172
|
declare function createWorkbenchLaunchpadDockEntry(input: {
|
package/dist/index.js
CHANGED
|
@@ -761,26 +761,19 @@ function classNames(...values) {
|
|
|
761
761
|
|
|
762
762
|
// src/workbenchLaunchpadDockEntry.ts
|
|
763
763
|
import { createElement } from "react";
|
|
764
|
-
function createWorkbenchLaunchpadDockIcon(
|
|
764
|
+
function createWorkbenchLaunchpadDockIcon(_input) {
|
|
765
765
|
return createElement(
|
|
766
766
|
"span",
|
|
767
767
|
{
|
|
768
768
|
"aria-hidden": "true",
|
|
769
769
|
className: "workspace-launchpad-dock-icon"
|
|
770
770
|
},
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
},
|
|
778
|
-
createElement("img", {
|
|
779
|
-
alt: "",
|
|
780
|
-
draggable: false,
|
|
781
|
-
src
|
|
782
|
-
})
|
|
783
|
-
)
|
|
771
|
+
createElement(
|
|
772
|
+
"span",
|
|
773
|
+
{
|
|
774
|
+
className: "workspace-launchpad-dock-icon__label"
|
|
775
|
+
},
|
|
776
|
+
"ALL"
|
|
784
777
|
)
|
|
785
778
|
);
|
|
786
779
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/WorkbenchLaunchpadOverlay.tsx","../src/launchpadModel.ts","../src/launchpadWheelNavigation.ts","../src/workbenchLaunchpadDockEntry.ts"],"sourcesContent":["import type * as React from \"react\";\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState\n} from \"react\";\nimport type { WorkbenchDockPlacement } from \"@tutti-os/workbench-surface\";\nimport {\n CloseIcon,\n NavApplicationsFilledIcon,\n SearchIcon\n} from \"@tutti-os/ui-system\";\nimport {\n filterWorkbenchLaunchpadItems,\n paginateWorkbenchLaunchpadItems,\n resolveWorkbenchLaunchpadGrid,\n type WorkbenchLaunchpadGridMetrics,\n type WorkbenchLaunchpadItem\n} from \"./launchpadModel.ts\";\nimport {\n createWorkbenchLaunchpadWheelNavigationState,\n resolveWorkbenchLaunchpadWheelNavigation\n} from \"./launchpadWheelNavigation.ts\";\n\nexport interface WorkbenchLaunchpadOverlayCopy {\n clearSearch: string;\n empty: string;\n installAction?: string;\n installingAction?: string;\n label: string;\n pageDot?: (input: { page: number; pageCount: number }) => string;\n pages?: string;\n refreshAction?: string;\n searchPlaceholder: string;\n syncAction?: string;\n unavailableItem?: (input: { reason: string; title: string }) => string;\n}\n\nexport interface WorkbenchLaunchpadOverlayProps<\n TProvider extends string = string\n> {\n copy: WorkbenchLaunchpadOverlayCopy;\n dockPlacement?: WorkbenchDockPlacement;\n getAgentActionPending?: (\n item: Extract<WorkbenchLaunchpadItem<TProvider>, { kind: \"agent\" }>,\n actionId: string\n ) => boolean;\n getAgentActionLabel?: (actionId: string) => string;\n getAgentReason?: (\n item: Extract<WorkbenchLaunchpadItem<TProvider>, { kind: \"agent\" }>\n ) => string | null;\n items: readonly WorkbenchLaunchpadItem<TProvider>[];\n onClose: () => void;\n onLaunchItem: (item: WorkbenchLaunchpadItem<TProvider>) => void;\n onPageChange?: (input: { pageIndex: number; totalPages: number }) => void;\n onRunAgentAction?: (\n item: Extract<WorkbenchLaunchpadItem<TProvider>, { kind: \"agent\" }>,\n actionId: string\n ) => void;\n onSearch?: (input: { queryLength: number; resultCount: number }) => void;\n open: boolean;\n}\n\nconst defaultLaunchpadGrid: WorkbenchLaunchpadGridMetrics = {\n columns: 5,\n pageSize: 15,\n rows: 3\n};\nconst launchpadExitAnimationMs = 180;\nconst launchpadHoverPanelViewportInsetPx = 16;\n\ntype WorkbenchLaunchpadAgentItem<TProvider extends string = string> = Extract<\n WorkbenchLaunchpadItem<TProvider>,\n { kind: \"agent\" }\n>;\n\nexport function WorkbenchLaunchpadOverlay<TProvider extends string = string>({\n copy,\n dockPlacement = \"bottom\",\n getAgentActionLabel,\n getAgentActionPending,\n getAgentReason,\n items,\n onClose,\n onLaunchItem,\n onPageChange,\n onRunAgentAction,\n onSearch,\n open\n}: WorkbenchLaunchpadOverlayProps<TProvider>) {\n const [query, setQuery] = useState(\"\");\n const [pageIndex, setPageIndex] = useState(0);\n const [shouldRender, setShouldRender] = useState(open);\n const searchInputRef = useRef<HTMLInputElement | null>(null);\n const wheelNavigationRef = useRef(\n createWorkbenchLaunchpadWheelNavigationState()\n );\n const { grid, ref: gridViewportRef } = useLaunchpadGridMetrics(open);\n const isClosing = shouldRender && !open;\n const filteredItems = useMemo(\n () => filterWorkbenchLaunchpadItems(items, query),\n [items, query]\n );\n const page = useMemo(\n () =>\n paginateWorkbenchLaunchpadItems(filteredItems, {\n page: pageIndex,\n pageSize: grid.pageSize\n }),\n [filteredItems, grid.pageSize, pageIndex]\n );\n\n useEffect(() => {\n if (open) {\n setShouldRender(true);\n return undefined;\n }\n if (!shouldRender) {\n return undefined;\n }\n const timeoutId = window.setTimeout(() => {\n setShouldRender(false);\n }, launchpadExitAnimationMs);\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [open, shouldRender]);\n\n useEffect(() => {\n if (!open) {\n wheelNavigationRef.current =\n createWorkbenchLaunchpadWheelNavigationState();\n return;\n }\n setQuery(\"\");\n setPageIndex(0);\n window.setTimeout(() => searchInputRef.current?.focus(), 0);\n }, [open]);\n\n useEffect(() => {\n setPageIndex(0);\n wheelNavigationRef.current = createWorkbenchLaunchpadWheelNavigationState();\n }, [query]);\n\n useEffect(() => {\n if (!open || !onSearch) {\n return undefined;\n }\n const queryLength = query.trim().length;\n if (queryLength === 0) {\n return undefined;\n }\n const timeoutId = window.setTimeout(() => {\n onSearch({\n queryLength,\n resultCount: filteredItems.length\n });\n }, 300);\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [filteredItems.length, onSearch, open, query]);\n\n const changePage = useCallback(\n (nextPageIndex: number) => {\n setPageIndex((currentPageIndex) => {\n const clampedPageIndex = Math.max(\n 0,\n Math.min(nextPageIndex, page.pageCount - 1)\n );\n if (clampedPageIndex !== currentPageIndex) {\n onPageChange?.({\n pageIndex: clampedPageIndex,\n totalPages: page.pageCount\n });\n }\n return clampedPageIndex;\n });\n },\n [onPageChange, page.pageCount]\n );\n\n useEffect(() => {\n if (!open) {\n return undefined;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n onClose();\n return;\n }\n if (isTextInputTarget(event.target)) {\n return;\n }\n if (event.key === \"ArrowRight\" && page.pageCount > 1) {\n event.preventDefault();\n changePage(page.currentPage + 1);\n return;\n }\n if (event.key === \"ArrowLeft\" && page.pageCount > 1) {\n event.preventDefault();\n changePage(page.currentPage - 1);\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [changePage, onClose, open, page.currentPage, page.pageCount]);\n\n const handleOverlayClick = useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (isClosing || isLaunchpadInteractiveTarget(event.target)) {\n return;\n }\n onClose();\n },\n [isClosing, onClose]\n );\n const handleOverlayWheel = useCallback(\n (event: React.WheelEvent<HTMLDivElement>) => {\n if (!open || isClosing || isLaunchpadWheelIgnoredTarget(event.target)) {\n return;\n }\n\n const result = resolveWorkbenchLaunchpadWheelNavigation({\n currentPage: page.currentPage,\n deltaMode: event.deltaMode,\n deltaX: event.deltaX,\n deltaY: event.deltaY,\n pageCount: page.pageCount,\n state: wheelNavigationRef.current,\n timestamp: event.timeStamp\n });\n wheelNavigationRef.current = result.state;\n if (result.shouldPreventDefault) {\n event.preventDefault();\n }\n if (result.nextPageIndex !== null) {\n changePage(result.nextPageIndex);\n }\n },\n [changePage, isClosing, open, page.currentPage, page.pageCount]\n );\n\n if (!shouldRender) {\n return null;\n }\n\n return (\n <div\n aria-label={copy.label}\n aria-modal=\"false\"\n className={classNames(\n \"workspace-launchpad-overlay\",\n isClosing && \"workspace-launchpad-overlay--closing\"\n )}\n role=\"dialog\"\n onClick={handleOverlayClick}\n onWheel={handleOverlayWheel}\n >\n <button\n aria-hidden=\"true\"\n className=\"workspace-launchpad-overlay__dismiss\"\n tabIndex={-1}\n type=\"button\"\n onClick={onClose}\n />\n <div\n className=\"workspace-launchpad-overlay__content\"\n data-dock-placement={dockPlacement}\n >\n <div className=\"workspace-launchpad-overlay__topbar\">\n <div className=\"workspace-launchpad-search\">\n <span\n aria-hidden=\"true\"\n className=\"workspace-launchpad-search__icon\"\n >\n <SearchIcon />\n </span>\n <input\n ref={searchInputRef}\n aria-label={copy.searchPlaceholder}\n className=\"workspace-launchpad-search__input\"\n placeholder={copy.searchPlaceholder}\n type=\"search\"\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n />\n {query ? (\n <button\n aria-label={copy.clearSearch}\n className=\"workspace-launchpad-search__clear\"\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n setQuery(\"\");\n searchInputRef.current?.focus();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n >\n <CloseIcon />\n </button>\n ) : null}\n </div>\n </div>\n <div\n ref={gridViewportRef}\n className=\"workspace-launchpad-grid-viewport\"\n >\n {filteredItems.length === 0 ? (\n <div className=\"workspace-launchpad-empty\">{copy.empty}</div>\n ) : (\n <div\n className=\"workspace-launchpad-grid\"\n style={{\n gridTemplateColumns: `repeat(${grid.columns}, minmax(96px, 136px))`\n }}\n >\n {page.pageItems.map((item, index) => (\n <WorkbenchLaunchpadItemButton\n key={item.id}\n animationIndex={index}\n animationRisePx={18 + (index % grid.columns) * 3}\n copy={copy}\n getAgentActionLabel={getAgentActionLabel}\n getAgentReason={getAgentReason}\n isAgentActionPending={getAgentActionPending}\n item={item}\n onLaunch={onLaunchItem}\n onRunAgentAction={onRunAgentAction}\n />\n ))}\n </div>\n )}\n </div>\n {page.pageCount > 1 ? (\n <div\n aria-label={copy.pages ?? \"Pages\"}\n className=\"workspace-launchpad-pages\"\n >\n {Array.from({ length: page.pageCount }, (_, index) => (\n <button\n key={index}\n aria-label={\n copy.pageDot?.({\n page: index + 1,\n pageCount: page.pageCount\n }) ?? `${index + 1} / ${page.pageCount}`\n }\n className=\"workspace-launchpad-page-dot\"\n data-active={index === page.currentPage ? \"true\" : undefined}\n type=\"button\"\n onClick={() => changePage(index)}\n />\n ))}\n </div>\n ) : (\n <div aria-hidden=\"true\" className=\"workspace-launchpad-pages\" />\n )}\n </div>\n </div>\n );\n}\n\nfunction WorkbenchLaunchpadItemButton<TProvider extends string = string>({\n animationIndex,\n animationRisePx,\n copy,\n getAgentActionLabel,\n getAgentReason,\n isAgentActionPending,\n item,\n onLaunch,\n onRunAgentAction\n}: {\n animationIndex: number;\n animationRisePx: number;\n copy: WorkbenchLaunchpadOverlayCopy;\n getAgentActionLabel?: (actionId: string) => string;\n getAgentReason?: (\n item: WorkbenchLaunchpadAgentItem<TProvider>\n ) => string | null;\n isAgentActionPending?: (\n item: WorkbenchLaunchpadAgentItem<TProvider>,\n actionId: string\n ) => boolean;\n item: WorkbenchLaunchpadItem<TProvider>;\n onLaunch: (item: WorkbenchLaunchpadItem<TProvider>) => void;\n onRunAgentAction?: (\n item: WorkbenchLaunchpadAgentItem<TProvider>,\n actionId: string\n ) => void;\n}) {\n const disabledLabel =\n item.disabledReason === undefined\n ? null\n : (copy.unavailableItem?.({\n reason: item.disabledReason,\n title: item.label\n }) ?? item.disabledReason);\n const [hoverPanelOpen, setHoverPanelOpen] = useState(false);\n const [hoverPanelShift, setHoverPanelShift] = useState(0);\n const hoverPanelRef = useRef<HTMLDivElement | null>(null);\n const hoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const agentActions =\n item.kind === \"agent\" && !item.launchEnabled\n ? resolveLaunchpadAgentActions(item)\n : [];\n const agentReason =\n item.kind === \"agent\"\n ? (getAgentReason?.(item) ?? item.reason ?? null)\n : null;\n const showComingSoonTooltip =\n item.kind === \"agent\" && item.comingSoon === true && agentReason !== null;\n const showAgentHoverPanel =\n item.kind === \"agent\" &&\n item.comingSoon !== true &&\n !item.launchEnabled &&\n hoverPanelOpen &&\n (agentActions.length > 0 || agentReason !== null);\n const clearHoverTimer = useCallback(() => {\n if (hoverTimerRef.current === null) {\n return;\n }\n clearTimeout(hoverTimerRef.current);\n hoverTimerRef.current = null;\n }, []);\n\n useEffect(\n () => () => {\n clearHoverTimer();\n },\n [clearHoverTimer]\n );\n\n useLayoutEffect(() => {\n if (!showAgentHoverPanel || typeof window === \"undefined\") {\n setHoverPanelShift(0);\n return undefined;\n }\n\n const frameId = window.requestAnimationFrame(() => {\n const panel = hoverPanelRef.current;\n if (!panel) {\n return;\n }\n\n const rect = panel.getBoundingClientRect();\n const maxRight = window.innerWidth - launchpadHoverPanelViewportInsetPx;\n const nextShift =\n rect.left < launchpadHoverPanelViewportInsetPx\n ? launchpadHoverPanelViewportInsetPx - rect.left\n : rect.right > maxRight\n ? maxRight - rect.right\n : 0;\n\n setHoverPanelShift((current) =>\n current === nextShift ? current : nextShift\n );\n });\n\n return () => {\n window.cancelAnimationFrame(frameId);\n };\n }, [agentActions.length, agentReason, showAgentHoverPanel]);\n\n const handlePointerEnter = useCallback(() => {\n if (item.kind !== \"agent\" || item.launchEnabled || item.comingSoon) {\n return;\n }\n clearHoverTimer();\n hoverTimerRef.current = setTimeout(() => {\n hoverTimerRef.current = null;\n setHoverPanelOpen(true);\n }, 500);\n }, [clearHoverTimer, item]);\n const handlePointerLeave = useCallback(() => {\n clearHoverTimer();\n setHoverPanelOpen(false);\n }, [clearHoverTimer]);\n const animationStyle = {\n \"--workspace-launchpad-item-delay\": `${Math.min(animationIndex, 24) * 28}ms`,\n \"--workspace-launchpad-item-rise\": `${animationRisePx}px`\n } as React.CSSProperties;\n const itemNode = (\n <div\n className=\"workspace-launchpad-item-wrap\"\n style={animationStyle}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n >\n <button\n aria-label={disabledLabel ?? item.label}\n className={classNames(\n \"workspace-launchpad-item\",\n !item.launchEnabled && \"workspace-launchpad-item--disabled\"\n )}\n disabled={!item.launchEnabled}\n title={\n showComingSoonTooltip ? undefined : (disabledLabel ?? item.label)\n }\n type=\"button\"\n onClick={() => onLaunch(item)}\n >\n <span\n aria-hidden=\"true\"\n className=\"workspace-launchpad-item__icon\"\n data-workspace-app-icon={item.iconUrl ? \"true\" : undefined}\n >\n {item.iconUrl ? (\n <img alt=\"\" draggable={false} src={item.iconUrl} />\n ) : (\n <NavApplicationsFilledIcon className=\"size-10\" />\n )}\n </span>\n <span className=\"workspace-launchpad-item__label\">{item.label}</span>\n </button>\n {showAgentHoverPanel ? (\n <div\n ref={hoverPanelRef}\n className=\"desktop-dock__hover-panel workspace-launchpad-dock-hover-panel\"\n role=\"group\"\n style={\n {\n \"--workspace-launchpad-hover-panel-shift\": `${Math.round(\n hoverPanelShift\n )}px`\n } as React.CSSProperties\n }\n >\n <div className=\"desktop-dock__hover-panel-title\">{item.label}</div>\n {agentReason ? (\n <div className=\"desktop-dock__hover-panel-description\">\n {agentReason}\n </div>\n ) : null}\n {agentActions.length ? (\n <div className=\"desktop-dock__hover-actions\">\n {agentActions.map((action) => {\n const isPending =\n isAgentActionPending?.(item, action.id) ?? false;\n return (\n <button\n key={action.id}\n aria-busy={isPending || undefined}\n className=\"desktop-dock__hover-action\"\n disabled={isPending}\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (isPending) {\n return;\n }\n onRunAgentAction?.(item, action.id);\n }}\n >\n {resolveAgentActionLabel(\n isPending && action.id === \"install\"\n ? \"installing\"\n : action.id,\n copy,\n getAgentActionLabel\n )}\n </button>\n );\n })}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n\n return showComingSoonTooltip ? (\n <span\n className=\"workspace-launchpad-tooltip-host\"\n title={agentReason ?? undefined}\n >\n {itemNode}\n </span>\n ) : (\n itemNode\n );\n}\n\nfunction useLaunchpadGridMetrics(open: boolean): {\n grid: WorkbenchLaunchpadGridMetrics;\n ref: React.RefObject<HTMLDivElement | null>;\n} {\n const ref = useRef<HTMLDivElement | null>(null);\n const [grid, setGrid] =\n useState<WorkbenchLaunchpadGridMetrics>(defaultLaunchpadGrid);\n\n useEffect(() => {\n if (!open) {\n return undefined;\n }\n const element = ref.current;\n if (!element) {\n return undefined;\n }\n\n const update = () => {\n const rect = element.getBoundingClientRect();\n setGrid(\n resolveWorkbenchLaunchpadGrid({\n height: rect.height,\n width: rect.width\n })\n );\n };\n update();\n\n const resizeObserver = new ResizeObserver(update);\n resizeObserver.observe(element);\n return () => {\n resizeObserver.disconnect();\n };\n }, [open]);\n\n return { grid, ref };\n}\n\nfunction resolveLaunchpadAgentActions<TProvider extends string>(\n item: WorkbenchLaunchpadAgentItem<TProvider>\n) {\n if (item.comingSoon) {\n return [];\n }\n if (item.actions?.length) {\n return item.actions;\n }\n if (item.action) {\n return [{ id: item.action }];\n }\n return [];\n}\n\nfunction resolveAgentActionLabel(\n actionId: string,\n copy: WorkbenchLaunchpadOverlayCopy,\n getAgentActionLabel: ((actionId: string) => string) | undefined\n): string {\n if (getAgentActionLabel) {\n return getAgentActionLabel(actionId);\n }\n switch (actionId) {\n case \"install\":\n return copy.installAction ?? actionId;\n case \"installing\":\n return copy.installingAction ?? copy.installAction ?? actionId;\n case \"sync\":\n return copy.syncAction ?? actionId;\n default:\n return copy.refreshAction ?? actionId;\n }\n}\n\nfunction isTextInputTarget(target: EventTarget | null): boolean {\n return (\n target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n (target instanceof HTMLElement && target.isContentEditable)\n );\n}\n\nfunction isLaunchpadInteractiveTarget(target: EventTarget | null): boolean {\n return (\n target instanceof HTMLElement &&\n Boolean(\n target.closest(\n \".workspace-launchpad-overlay__topbar, .workspace-launchpad-search, .workspace-launchpad-item, .desktop-dock__hover-panel, .workspace-launchpad-pages\"\n )\n )\n );\n}\n\nfunction isLaunchpadWheelIgnoredTarget(target: EventTarget | null): boolean {\n return (\n isTextInputTarget(target) ||\n (target instanceof HTMLElement &&\n Boolean(\n target.closest(\n \".workspace-launchpad-overlay__topbar, .workspace-launchpad-search, .desktop-dock__hover-panel, .workspace-launchpad-pages\"\n )\n ))\n );\n}\n\nfunction classNames(\n ...values: readonly (string | false | null | undefined)[]\n): string {\n return values.filter(Boolean).join(\" \");\n}\n","export const workbenchLaunchpadDockActionId = \"open-launchpad\";\nexport const workbenchLaunchpadDockEntryId = \"workspace-launchpad\";\n\nexport interface WorkbenchLaunchpadAppDescriptor {\n appId: string;\n disabledReason?: string;\n iconUrl?: string | null;\n id?: string;\n label: string;\n launchEnabled: boolean;\n}\n\nexport interface WorkbenchLaunchpadNodeDescriptor {\n dockEntryId: string;\n disabledReason?: string;\n iconUrl: string;\n id: string;\n label: string;\n launchEnabled?: boolean;\n typeId: string;\n}\n\nexport interface WorkbenchLaunchpadAgentDescriptor<\n TProvider extends string = string\n> {\n action?: string | null;\n actions?: readonly WorkbenchLaunchpadAgentAction[];\n comingSoon?: boolean;\n disabledReason?: string;\n iconUrl: string;\n id?: string;\n label: string;\n launchEnabled: boolean;\n provider: TProvider;\n reason?: string | null;\n}\n\nexport interface WorkbenchLaunchpadAgentAction {\n id: string;\n}\n\nexport type WorkbenchLaunchpadItem<TProvider extends string = string> =\n | {\n appId: string;\n disabledReason?: string;\n iconUrl?: string | null;\n id: string;\n kind: \"app\";\n label: string;\n launchEnabled: boolean;\n }\n | {\n dockEntryId: string;\n disabledReason?: string;\n iconUrl: string;\n id: string;\n kind: \"node\";\n label: string;\n launchEnabled: boolean;\n typeId: string;\n }\n | {\n action?: string | null;\n actions?: readonly WorkbenchLaunchpadAgentAction[];\n comingSoon?: boolean;\n disabledReason?: string;\n iconUrl: string;\n id: string;\n kind: \"agent\";\n label: string;\n launchEnabled: boolean;\n provider: TProvider;\n reason?: string | null;\n };\n\nexport interface WorkbenchLaunchpadGridMetrics {\n columns: number;\n pageSize: number;\n rows: number;\n}\n\nexport interface WorkbenchLaunchpadPage<TItem> {\n currentPage: number;\n pageCount: number;\n pageItems: readonly TItem[];\n}\n\nconst launchpadPreviewIconCount = 4;\nconst launchpadMinColumns = 2;\nconst launchpadMaxColumns = 7;\nconst launchpadMinRows = 1;\nconst launchpadMaxRows = 5;\nconst launchpadTileWidth = 136;\nconst launchpadTileHeight = 138;\n\nexport function buildWorkbenchLaunchpadItems<\n TProvider extends string = string\n>(input: {\n agentDescriptors?: readonly WorkbenchLaunchpadAgentDescriptor<TProvider>[];\n apps?: readonly WorkbenchLaunchpadAppDescriptor[];\n nodeDescriptors?: readonly WorkbenchLaunchpadNodeDescriptor[];\n}): WorkbenchLaunchpadItem<TProvider>[] {\n const nodeItems = (input.nodeDescriptors ?? []).map((node) => ({\n disabledReason: node.disabledReason,\n dockEntryId: node.dockEntryId,\n iconUrl: node.iconUrl,\n id: `node:${node.id}`,\n kind: \"node\" as const,\n label: node.label,\n launchEnabled: node.launchEnabled ?? true,\n typeId: node.typeId\n }));\n const pinnedNodeItems = nodeItems.slice(0, 2);\n const remainingNodeItems = nodeItems.slice(2);\n return [\n ...pinnedNodeItems,\n ...(input.apps ?? []).map((app) => ({\n appId: app.appId,\n disabledReason: app.disabledReason,\n iconUrl: app.iconUrl,\n id: app.id ?? `app:${app.appId}`,\n kind: \"app\" as const,\n label: app.label,\n launchEnabled: app.launchEnabled\n })),\n ...remainingNodeItems,\n ...(input.agentDescriptors ?? []).map((agent) => ({\n action: agent.action,\n actions: agent.actions,\n comingSoon: agent.comingSoon,\n disabledReason: agent.disabledReason,\n iconUrl: agent.iconUrl,\n id: agent.id ?? `agent:${agent.provider}`,\n kind: \"agent\" as const,\n label: agent.label,\n launchEnabled: agent.launchEnabled,\n provider: agent.provider,\n reason: agent.reason\n }))\n ];\n}\n\nexport function filterWorkbenchLaunchpadItems<TItem extends { label: string }>(\n items: readonly TItem[],\n query: string\n): TItem[] {\n const normalizedQuery = normalizeLaunchpadSearchText(query);\n if (!normalizedQuery) {\n return [...items];\n }\n return items.filter((item) =>\n normalizeLaunchpadSearchText(item.label).includes(normalizedQuery)\n );\n}\n\nexport function paginateWorkbenchLaunchpadItems<TItem>(\n items: readonly TItem[],\n input: {\n page: number;\n pageSize: number;\n }\n): WorkbenchLaunchpadPage<TItem> {\n const pageSize = Math.max(1, Math.floor(input.pageSize));\n const pageCount = Math.max(1, Math.ceil(items.length / pageSize));\n const currentPage = clampInteger(input.page, 0, pageCount - 1);\n const pageStart = currentPage * pageSize;\n return {\n currentPage,\n pageCount,\n pageItems: items.slice(pageStart, pageStart + pageSize)\n };\n}\n\nexport function resolveWorkbenchLaunchpadGrid(input: {\n height: number;\n width: number;\n}): WorkbenchLaunchpadGridMetrics {\n const columns = clampInteger(\n Math.floor(input.width / launchpadTileWidth),\n launchpadMinColumns,\n launchpadMaxColumns\n );\n const rows = clampInteger(\n Math.floor(input.height / launchpadTileHeight),\n launchpadMinRows,\n launchpadMaxRows\n );\n return {\n columns,\n pageSize: Math.max(1, columns * rows),\n rows\n };\n}\n\nexport function resolveWorkbenchLaunchpadPreviewIconUrls(input: {\n agentIcons?: readonly string[];\n appIcons?: readonly (string | null | undefined)[];\n fallbackIconUrl: string;\n nodeIconUrls?: readonly string[];\n}): string[] {\n const icons = uniqueLaunchpadPreviewIconUrls([\n ...(input.appIcons ?? []),\n ...(input.nodeIconUrls ?? []),\n ...(input.agentIcons ?? [])\n ]).slice(0, launchpadPreviewIconCount);\n while (icons.length < launchpadPreviewIconCount) {\n icons.push(input.fallbackIconUrl);\n }\n return icons;\n}\n\nfunction uniqueLaunchpadPreviewIconUrls(\n iconUrls: readonly (string | null | undefined)[]\n): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n for (const iconUrl of iconUrls) {\n const normalizedIconUrl = iconUrl?.trim();\n if (!normalizedIconUrl || seen.has(normalizedIconUrl)) {\n continue;\n }\n seen.add(normalizedIconUrl);\n result.push(normalizedIconUrl);\n }\n return result;\n}\n\nfunction normalizeLaunchpadSearchText(value: string): string {\n return value.trim().toLocaleLowerCase();\n}\n\nfunction clampInteger(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) {\n return min;\n }\n return Math.min(Math.max(Math.floor(value), min), max);\n}\n","const wheelDeltaLinePx = 16;\nconst wheelDeltaPagePx = 360;\nconst launchpadWheelNavigationThresholdPx = 64;\nconst launchpadWheelNavigationCooldownMs = 420;\nconst launchpadWheelHorizontalIntentRatio = 1.2;\n\nexport interface WorkbenchLaunchpadWheelNavigationState {\n accumulatedDeltaX: number;\n lastNavigationAt: number;\n}\n\nexport interface WorkbenchLaunchpadWheelNavigationResult {\n nextPageIndex: number | null;\n shouldPreventDefault: boolean;\n state: WorkbenchLaunchpadWheelNavigationState;\n}\n\nexport function createWorkbenchLaunchpadWheelNavigationState(): WorkbenchLaunchpadWheelNavigationState {\n return {\n accumulatedDeltaX: 0,\n lastNavigationAt: 0\n };\n}\n\nexport function resolveWorkbenchLaunchpadWheelNavigation(input: {\n currentPage: number;\n deltaMode?: number;\n deltaX: number;\n deltaY: number;\n pageCount: number;\n state: WorkbenchLaunchpadWheelNavigationState;\n timestamp: number;\n}): WorkbenchLaunchpadWheelNavigationResult {\n if (input.pageCount <= 1) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: false,\n state: createWorkbenchLaunchpadWheelNavigationState()\n };\n }\n\n const delta = normalizeWorkbenchLaunchpadWheelDelta(input);\n const absDeltaX = Math.abs(delta.x);\n const absDeltaY = Math.abs(delta.y);\n const isHorizontalIntent =\n absDeltaX > 0 &&\n absDeltaX >= absDeltaY * launchpadWheelHorizontalIntentRatio;\n\n if (!isHorizontalIntent) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: false,\n state: {\n accumulatedDeltaX: 0,\n lastNavigationAt: input.state.lastNavigationAt\n }\n };\n }\n\n const direction = delta.x > 0 ? 1 : -1;\n const previousDirection = input.state.accumulatedDeltaX > 0 ? 1 : -1;\n const accumulatedDeltaX =\n input.state.accumulatedDeltaX !== 0 && previousDirection === direction\n ? input.state.accumulatedDeltaX + delta.x\n : delta.x;\n\n if (\n input.timestamp - input.state.lastNavigationAt <\n launchpadWheelNavigationCooldownMs\n ) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: true,\n state: {\n accumulatedDeltaX: 0,\n lastNavigationAt: input.state.lastNavigationAt\n }\n };\n }\n\n if (Math.abs(accumulatedDeltaX) < launchpadWheelNavigationThresholdPx) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: true,\n state: {\n accumulatedDeltaX,\n lastNavigationAt: input.state.lastNavigationAt\n }\n };\n }\n\n const nextPageIndex = input.currentPage + direction;\n if (nextPageIndex < 0 || nextPageIndex >= input.pageCount) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: true,\n state: {\n accumulatedDeltaX: 0,\n lastNavigationAt: input.timestamp\n }\n };\n }\n\n return {\n nextPageIndex,\n shouldPreventDefault: true,\n state: {\n accumulatedDeltaX: 0,\n lastNavigationAt: input.timestamp\n }\n };\n}\n\nfunction normalizeWorkbenchLaunchpadWheelDelta(input: {\n deltaMode?: number;\n deltaX: number;\n deltaY: number;\n}): { x: number; y: number } {\n const unit =\n input.deltaMode === 1\n ? wheelDeltaLinePx\n : input.deltaMode === 2\n ? wheelDeltaPagePx\n : 1;\n return {\n x: input.deltaX * unit,\n y: input.deltaY * unit\n };\n}\n","import { createElement, type ReactNode } from \"react\";\nimport type { WorkbenchHostDockEntry } from \"@tutti-os/workbench-surface\";\nimport {\n workbenchLaunchpadDockActionId,\n workbenchLaunchpadDockEntryId\n} from \"./launchpadModel.ts\";\n\nexport function createWorkbenchLaunchpadDockIcon(input: {\n tileIconUrls: readonly string[];\n}): ReactNode {\n return createElement(\n \"span\",\n {\n \"aria-hidden\": \"true\",\n className: \"workspace-launchpad-dock-icon\"\n },\n input.tileIconUrls.map((src, index) =>\n createElement(\n \"span\",\n {\n className: \"workspace-launchpad-dock-icon__tile\",\n key: `${src}:${index}`\n },\n createElement(\"img\", {\n alt: \"\",\n draggable: false,\n src\n })\n )\n )\n );\n}\n\nexport function createWorkbenchLaunchpadDockEntry(input: {\n label: string;\n order?: number;\n tileIconUrls: readonly string[];\n}): WorkbenchHostDockEntry {\n return {\n clickActionId: workbenchLaunchpadDockActionId,\n icon: createWorkbenchLaunchpadDockIcon({\n tileIconUrls: input.tileIconUrls\n }),\n id: workbenchLaunchpadDockEntryId,\n label: input.label,\n launchBehavior: \"enabled\",\n order: input.order ?? 0,\n sectionId: \"launchpad\",\n typeId: workbenchLaunchpadDockEntryId,\n visibility: \"always\"\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/WorkbenchLaunchpadOverlay.tsx","../src/launchpadModel.ts","../src/launchpadWheelNavigation.ts","../src/workbenchLaunchpadDockEntry.ts"],"sourcesContent":["import type * as React from \"react\";\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState\n} from \"react\";\nimport type { WorkbenchDockPlacement } from \"@tutti-os/workbench-surface\";\nimport {\n CloseIcon,\n NavApplicationsFilledIcon,\n SearchIcon\n} from \"@tutti-os/ui-system\";\nimport {\n filterWorkbenchLaunchpadItems,\n paginateWorkbenchLaunchpadItems,\n resolveWorkbenchLaunchpadGrid,\n type WorkbenchLaunchpadGridMetrics,\n type WorkbenchLaunchpadItem\n} from \"./launchpadModel.ts\";\nimport {\n createWorkbenchLaunchpadWheelNavigationState,\n resolveWorkbenchLaunchpadWheelNavigation\n} from \"./launchpadWheelNavigation.ts\";\n\nexport interface WorkbenchLaunchpadOverlayCopy {\n clearSearch: string;\n empty: string;\n installAction?: string;\n installingAction?: string;\n label: string;\n pageDot?: (input: { page: number; pageCount: number }) => string;\n pages?: string;\n refreshAction?: string;\n searchPlaceholder: string;\n syncAction?: string;\n unavailableItem?: (input: { reason: string; title: string }) => string;\n}\n\nexport interface WorkbenchLaunchpadOverlayProps<\n TProvider extends string = string\n> {\n copy: WorkbenchLaunchpadOverlayCopy;\n dockPlacement?: WorkbenchDockPlacement;\n getAgentActionPending?: (\n item: Extract<WorkbenchLaunchpadItem<TProvider>, { kind: \"agent\" }>,\n actionId: string\n ) => boolean;\n getAgentActionLabel?: (actionId: string) => string;\n getAgentReason?: (\n item: Extract<WorkbenchLaunchpadItem<TProvider>, { kind: \"agent\" }>\n ) => string | null;\n items: readonly WorkbenchLaunchpadItem<TProvider>[];\n onClose: () => void;\n onLaunchItem: (item: WorkbenchLaunchpadItem<TProvider>) => void;\n onPageChange?: (input: { pageIndex: number; totalPages: number }) => void;\n onRunAgentAction?: (\n item: Extract<WorkbenchLaunchpadItem<TProvider>, { kind: \"agent\" }>,\n actionId: string\n ) => void;\n onSearch?: (input: { queryLength: number; resultCount: number }) => void;\n open: boolean;\n}\n\nconst defaultLaunchpadGrid: WorkbenchLaunchpadGridMetrics = {\n columns: 5,\n pageSize: 15,\n rows: 3\n};\nconst launchpadExitAnimationMs = 180;\nconst launchpadHoverPanelViewportInsetPx = 16;\n\ntype WorkbenchLaunchpadAgentItem<TProvider extends string = string> = Extract<\n WorkbenchLaunchpadItem<TProvider>,\n { kind: \"agent\" }\n>;\n\nexport function WorkbenchLaunchpadOverlay<TProvider extends string = string>({\n copy,\n dockPlacement = \"bottom\",\n getAgentActionLabel,\n getAgentActionPending,\n getAgentReason,\n items,\n onClose,\n onLaunchItem,\n onPageChange,\n onRunAgentAction,\n onSearch,\n open\n}: WorkbenchLaunchpadOverlayProps<TProvider>) {\n const [query, setQuery] = useState(\"\");\n const [pageIndex, setPageIndex] = useState(0);\n const [shouldRender, setShouldRender] = useState(open);\n const searchInputRef = useRef<HTMLInputElement | null>(null);\n const wheelNavigationRef = useRef(\n createWorkbenchLaunchpadWheelNavigationState()\n );\n const { grid, ref: gridViewportRef } = useLaunchpadGridMetrics(open);\n const isClosing = shouldRender && !open;\n const filteredItems = useMemo(\n () => filterWorkbenchLaunchpadItems(items, query),\n [items, query]\n );\n const page = useMemo(\n () =>\n paginateWorkbenchLaunchpadItems(filteredItems, {\n page: pageIndex,\n pageSize: grid.pageSize\n }),\n [filteredItems, grid.pageSize, pageIndex]\n );\n\n useEffect(() => {\n if (open) {\n setShouldRender(true);\n return undefined;\n }\n if (!shouldRender) {\n return undefined;\n }\n const timeoutId = window.setTimeout(() => {\n setShouldRender(false);\n }, launchpadExitAnimationMs);\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [open, shouldRender]);\n\n useEffect(() => {\n if (!open) {\n wheelNavigationRef.current =\n createWorkbenchLaunchpadWheelNavigationState();\n return;\n }\n setQuery(\"\");\n setPageIndex(0);\n window.setTimeout(() => searchInputRef.current?.focus(), 0);\n }, [open]);\n\n useEffect(() => {\n setPageIndex(0);\n wheelNavigationRef.current = createWorkbenchLaunchpadWheelNavigationState();\n }, [query]);\n\n useEffect(() => {\n if (!open || !onSearch) {\n return undefined;\n }\n const queryLength = query.trim().length;\n if (queryLength === 0) {\n return undefined;\n }\n const timeoutId = window.setTimeout(() => {\n onSearch({\n queryLength,\n resultCount: filteredItems.length\n });\n }, 300);\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [filteredItems.length, onSearch, open, query]);\n\n const changePage = useCallback(\n (nextPageIndex: number) => {\n setPageIndex((currentPageIndex) => {\n const clampedPageIndex = Math.max(\n 0,\n Math.min(nextPageIndex, page.pageCount - 1)\n );\n if (clampedPageIndex !== currentPageIndex) {\n onPageChange?.({\n pageIndex: clampedPageIndex,\n totalPages: page.pageCount\n });\n }\n return clampedPageIndex;\n });\n },\n [onPageChange, page.pageCount]\n );\n\n useEffect(() => {\n if (!open) {\n return undefined;\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n event.preventDefault();\n onClose();\n return;\n }\n if (isTextInputTarget(event.target)) {\n return;\n }\n if (event.key === \"ArrowRight\" && page.pageCount > 1) {\n event.preventDefault();\n changePage(page.currentPage + 1);\n return;\n }\n if (event.key === \"ArrowLeft\" && page.pageCount > 1) {\n event.preventDefault();\n changePage(page.currentPage - 1);\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [changePage, onClose, open, page.currentPage, page.pageCount]);\n\n const handleOverlayClick = useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (isClosing || isLaunchpadInteractiveTarget(event.target)) {\n return;\n }\n onClose();\n },\n [isClosing, onClose]\n );\n const handleOverlayWheel = useCallback(\n (event: React.WheelEvent<HTMLDivElement>) => {\n if (!open || isClosing || isLaunchpadWheelIgnoredTarget(event.target)) {\n return;\n }\n\n const result = resolveWorkbenchLaunchpadWheelNavigation({\n currentPage: page.currentPage,\n deltaMode: event.deltaMode,\n deltaX: event.deltaX,\n deltaY: event.deltaY,\n pageCount: page.pageCount,\n state: wheelNavigationRef.current,\n timestamp: event.timeStamp\n });\n wheelNavigationRef.current = result.state;\n if (result.shouldPreventDefault) {\n event.preventDefault();\n }\n if (result.nextPageIndex !== null) {\n changePage(result.nextPageIndex);\n }\n },\n [changePage, isClosing, open, page.currentPage, page.pageCount]\n );\n\n if (!shouldRender) {\n return null;\n }\n\n return (\n <div\n aria-label={copy.label}\n aria-modal=\"false\"\n className={classNames(\n \"workspace-launchpad-overlay\",\n isClosing && \"workspace-launchpad-overlay--closing\"\n )}\n role=\"dialog\"\n onClick={handleOverlayClick}\n onWheel={handleOverlayWheel}\n >\n <button\n aria-hidden=\"true\"\n className=\"workspace-launchpad-overlay__dismiss\"\n tabIndex={-1}\n type=\"button\"\n onClick={onClose}\n />\n <div\n className=\"workspace-launchpad-overlay__content\"\n data-dock-placement={dockPlacement}\n >\n <div className=\"workspace-launchpad-overlay__topbar\">\n <div className=\"workspace-launchpad-search\">\n <span\n aria-hidden=\"true\"\n className=\"workspace-launchpad-search__icon\"\n >\n <SearchIcon />\n </span>\n <input\n ref={searchInputRef}\n aria-label={copy.searchPlaceholder}\n className=\"workspace-launchpad-search__input\"\n placeholder={copy.searchPlaceholder}\n type=\"search\"\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n />\n {query ? (\n <button\n aria-label={copy.clearSearch}\n className=\"workspace-launchpad-search__clear\"\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n setQuery(\"\");\n searchInputRef.current?.focus();\n }}\n onMouseDown={(event) => {\n event.preventDefault();\n event.stopPropagation();\n }}\n >\n <CloseIcon />\n </button>\n ) : null}\n </div>\n </div>\n <div\n ref={gridViewportRef}\n className=\"workspace-launchpad-grid-viewport\"\n >\n {filteredItems.length === 0 ? (\n <div className=\"workspace-launchpad-empty\">{copy.empty}</div>\n ) : (\n <div\n className=\"workspace-launchpad-grid\"\n style={{\n gridTemplateColumns: `repeat(${grid.columns}, minmax(96px, 136px))`\n }}\n >\n {page.pageItems.map((item, index) => (\n <WorkbenchLaunchpadItemButton\n key={item.id}\n animationIndex={index}\n animationRisePx={18 + (index % grid.columns) * 3}\n copy={copy}\n getAgentActionLabel={getAgentActionLabel}\n getAgentReason={getAgentReason}\n isAgentActionPending={getAgentActionPending}\n item={item}\n onLaunch={onLaunchItem}\n onRunAgentAction={onRunAgentAction}\n />\n ))}\n </div>\n )}\n </div>\n {page.pageCount > 1 ? (\n <div\n aria-label={copy.pages ?? \"Pages\"}\n className=\"workspace-launchpad-pages\"\n >\n {Array.from({ length: page.pageCount }, (_, index) => (\n <button\n key={index}\n aria-label={\n copy.pageDot?.({\n page: index + 1,\n pageCount: page.pageCount\n }) ?? `${index + 1} / ${page.pageCount}`\n }\n className=\"workspace-launchpad-page-dot\"\n data-active={index === page.currentPage ? \"true\" : undefined}\n type=\"button\"\n onClick={() => changePage(index)}\n />\n ))}\n </div>\n ) : (\n <div aria-hidden=\"true\" className=\"workspace-launchpad-pages\" />\n )}\n </div>\n </div>\n );\n}\n\nfunction WorkbenchLaunchpadItemButton<TProvider extends string = string>({\n animationIndex,\n animationRisePx,\n copy,\n getAgentActionLabel,\n getAgentReason,\n isAgentActionPending,\n item,\n onLaunch,\n onRunAgentAction\n}: {\n animationIndex: number;\n animationRisePx: number;\n copy: WorkbenchLaunchpadOverlayCopy;\n getAgentActionLabel?: (actionId: string) => string;\n getAgentReason?: (\n item: WorkbenchLaunchpadAgentItem<TProvider>\n ) => string | null;\n isAgentActionPending?: (\n item: WorkbenchLaunchpadAgentItem<TProvider>,\n actionId: string\n ) => boolean;\n item: WorkbenchLaunchpadItem<TProvider>;\n onLaunch: (item: WorkbenchLaunchpadItem<TProvider>) => void;\n onRunAgentAction?: (\n item: WorkbenchLaunchpadAgentItem<TProvider>,\n actionId: string\n ) => void;\n}) {\n const disabledLabel =\n item.disabledReason === undefined\n ? null\n : (copy.unavailableItem?.({\n reason: item.disabledReason,\n title: item.label\n }) ?? item.disabledReason);\n const [hoverPanelOpen, setHoverPanelOpen] = useState(false);\n const [hoverPanelShift, setHoverPanelShift] = useState(0);\n const hoverPanelRef = useRef<HTMLDivElement | null>(null);\n const hoverTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const agentActions =\n item.kind === \"agent\" && !item.launchEnabled\n ? resolveLaunchpadAgentActions(item)\n : [];\n const agentReason =\n item.kind === \"agent\"\n ? (getAgentReason?.(item) ?? item.reason ?? null)\n : null;\n const showComingSoonTooltip =\n item.kind === \"agent\" && item.comingSoon === true && agentReason !== null;\n const showAgentHoverPanel =\n item.kind === \"agent\" &&\n item.comingSoon !== true &&\n !item.launchEnabled &&\n hoverPanelOpen &&\n (agentActions.length > 0 || agentReason !== null);\n const clearHoverTimer = useCallback(() => {\n if (hoverTimerRef.current === null) {\n return;\n }\n clearTimeout(hoverTimerRef.current);\n hoverTimerRef.current = null;\n }, []);\n\n useEffect(\n () => () => {\n clearHoverTimer();\n },\n [clearHoverTimer]\n );\n\n useLayoutEffect(() => {\n if (!showAgentHoverPanel || typeof window === \"undefined\") {\n setHoverPanelShift(0);\n return undefined;\n }\n\n const frameId = window.requestAnimationFrame(() => {\n const panel = hoverPanelRef.current;\n if (!panel) {\n return;\n }\n\n const rect = panel.getBoundingClientRect();\n const maxRight = window.innerWidth - launchpadHoverPanelViewportInsetPx;\n const nextShift =\n rect.left < launchpadHoverPanelViewportInsetPx\n ? launchpadHoverPanelViewportInsetPx - rect.left\n : rect.right > maxRight\n ? maxRight - rect.right\n : 0;\n\n setHoverPanelShift((current) =>\n current === nextShift ? current : nextShift\n );\n });\n\n return () => {\n window.cancelAnimationFrame(frameId);\n };\n }, [agentActions.length, agentReason, showAgentHoverPanel]);\n\n const handlePointerEnter = useCallback(() => {\n if (item.kind !== \"agent\" || item.launchEnabled || item.comingSoon) {\n return;\n }\n clearHoverTimer();\n hoverTimerRef.current = setTimeout(() => {\n hoverTimerRef.current = null;\n setHoverPanelOpen(true);\n }, 500);\n }, [clearHoverTimer, item]);\n const handlePointerLeave = useCallback(() => {\n clearHoverTimer();\n setHoverPanelOpen(false);\n }, [clearHoverTimer]);\n const animationStyle = {\n \"--workspace-launchpad-item-delay\": `${Math.min(animationIndex, 24) * 28}ms`,\n \"--workspace-launchpad-item-rise\": `${animationRisePx}px`\n } as React.CSSProperties;\n const itemNode = (\n <div\n className=\"workspace-launchpad-item-wrap\"\n style={animationStyle}\n onPointerEnter={handlePointerEnter}\n onPointerLeave={handlePointerLeave}\n >\n <button\n aria-label={disabledLabel ?? item.label}\n className={classNames(\n \"workspace-launchpad-item\",\n !item.launchEnabled && \"workspace-launchpad-item--disabled\"\n )}\n disabled={!item.launchEnabled}\n title={\n showComingSoonTooltip ? undefined : (disabledLabel ?? item.label)\n }\n type=\"button\"\n onClick={() => onLaunch(item)}\n >\n <span\n aria-hidden=\"true\"\n className=\"workspace-launchpad-item__icon\"\n data-workspace-app-icon={item.iconUrl ? \"true\" : undefined}\n >\n {item.iconUrl ? (\n <img alt=\"\" draggable={false} src={item.iconUrl} />\n ) : (\n <NavApplicationsFilledIcon className=\"size-10\" />\n )}\n </span>\n <span className=\"workspace-launchpad-item__label\">{item.label}</span>\n </button>\n {showAgentHoverPanel ? (\n <div\n ref={hoverPanelRef}\n className=\"desktop-dock__hover-panel workspace-launchpad-dock-hover-panel\"\n role=\"group\"\n style={\n {\n \"--workspace-launchpad-hover-panel-shift\": `${Math.round(\n hoverPanelShift\n )}px`\n } as React.CSSProperties\n }\n >\n <div className=\"desktop-dock__hover-panel-title\">{item.label}</div>\n {agentReason ? (\n <div className=\"desktop-dock__hover-panel-description\">\n {agentReason}\n </div>\n ) : null}\n {agentActions.length ? (\n <div className=\"desktop-dock__hover-actions\">\n {agentActions.map((action) => {\n const isPending =\n isAgentActionPending?.(item, action.id) ?? false;\n return (\n <button\n key={action.id}\n aria-busy={isPending || undefined}\n className=\"desktop-dock__hover-action\"\n disabled={isPending}\n type=\"button\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n if (isPending) {\n return;\n }\n onRunAgentAction?.(item, action.id);\n }}\n >\n {resolveAgentActionLabel(\n isPending && action.id === \"install\"\n ? \"installing\"\n : action.id,\n copy,\n getAgentActionLabel\n )}\n </button>\n );\n })}\n </div>\n ) : null}\n </div>\n ) : null}\n </div>\n );\n\n return showComingSoonTooltip ? (\n <span\n className=\"workspace-launchpad-tooltip-host\"\n title={agentReason ?? undefined}\n >\n {itemNode}\n </span>\n ) : (\n itemNode\n );\n}\n\nfunction useLaunchpadGridMetrics(open: boolean): {\n grid: WorkbenchLaunchpadGridMetrics;\n ref: React.RefObject<HTMLDivElement | null>;\n} {\n const ref = useRef<HTMLDivElement | null>(null);\n const [grid, setGrid] =\n useState<WorkbenchLaunchpadGridMetrics>(defaultLaunchpadGrid);\n\n useEffect(() => {\n if (!open) {\n return undefined;\n }\n const element = ref.current;\n if (!element) {\n return undefined;\n }\n\n const update = () => {\n const rect = element.getBoundingClientRect();\n setGrid(\n resolveWorkbenchLaunchpadGrid({\n height: rect.height,\n width: rect.width\n })\n );\n };\n update();\n\n const resizeObserver = new ResizeObserver(update);\n resizeObserver.observe(element);\n return () => {\n resizeObserver.disconnect();\n };\n }, [open]);\n\n return { grid, ref };\n}\n\nfunction resolveLaunchpadAgentActions<TProvider extends string>(\n item: WorkbenchLaunchpadAgentItem<TProvider>\n) {\n if (item.comingSoon) {\n return [];\n }\n if (item.actions?.length) {\n return item.actions;\n }\n if (item.action) {\n return [{ id: item.action }];\n }\n return [];\n}\n\nfunction resolveAgentActionLabel(\n actionId: string,\n copy: WorkbenchLaunchpadOverlayCopy,\n getAgentActionLabel: ((actionId: string) => string) | undefined\n): string {\n if (getAgentActionLabel) {\n return getAgentActionLabel(actionId);\n }\n switch (actionId) {\n case \"install\":\n return copy.installAction ?? actionId;\n case \"installing\":\n return copy.installingAction ?? copy.installAction ?? actionId;\n case \"sync\":\n return copy.syncAction ?? actionId;\n default:\n return copy.refreshAction ?? actionId;\n }\n}\n\nfunction isTextInputTarget(target: EventTarget | null): boolean {\n return (\n target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n (target instanceof HTMLElement && target.isContentEditable)\n );\n}\n\nfunction isLaunchpadInteractiveTarget(target: EventTarget | null): boolean {\n return (\n target instanceof HTMLElement &&\n Boolean(\n target.closest(\n \".workspace-launchpad-overlay__topbar, .workspace-launchpad-search, .workspace-launchpad-item, .desktop-dock__hover-panel, .workspace-launchpad-pages\"\n )\n )\n );\n}\n\nfunction isLaunchpadWheelIgnoredTarget(target: EventTarget | null): boolean {\n return (\n isTextInputTarget(target) ||\n (target instanceof HTMLElement &&\n Boolean(\n target.closest(\n \".workspace-launchpad-overlay__topbar, .workspace-launchpad-search, .desktop-dock__hover-panel, .workspace-launchpad-pages\"\n )\n ))\n );\n}\n\nfunction classNames(\n ...values: readonly (string | false | null | undefined)[]\n): string {\n return values.filter(Boolean).join(\" \");\n}\n","export const workbenchLaunchpadDockActionId = \"open-launchpad\";\nexport const workbenchLaunchpadDockEntryId = \"workspace-launchpad\";\n\nexport interface WorkbenchLaunchpadAppDescriptor {\n appId: string;\n disabledReason?: string;\n iconUrl?: string | null;\n id?: string;\n label: string;\n launchEnabled: boolean;\n}\n\nexport interface WorkbenchLaunchpadNodeDescriptor {\n dockEntryId: string;\n disabledReason?: string;\n iconUrl: string;\n id: string;\n label: string;\n launchEnabled?: boolean;\n typeId: string;\n}\n\nexport interface WorkbenchLaunchpadAgentDescriptor<\n TProvider extends string = string\n> {\n action?: string | null;\n actions?: readonly WorkbenchLaunchpadAgentAction[];\n comingSoon?: boolean;\n disabledReason?: string;\n iconUrl: string;\n id?: string;\n label: string;\n launchEnabled: boolean;\n provider: TProvider;\n reason?: string | null;\n}\n\nexport interface WorkbenchLaunchpadAgentAction {\n id: string;\n}\n\nexport type WorkbenchLaunchpadItem<TProvider extends string = string> =\n | {\n appId: string;\n disabledReason?: string;\n iconUrl?: string | null;\n id: string;\n kind: \"app\";\n label: string;\n launchEnabled: boolean;\n }\n | {\n dockEntryId: string;\n disabledReason?: string;\n iconUrl: string;\n id: string;\n kind: \"node\";\n label: string;\n launchEnabled: boolean;\n typeId: string;\n }\n | {\n action?: string | null;\n actions?: readonly WorkbenchLaunchpadAgentAction[];\n comingSoon?: boolean;\n disabledReason?: string;\n iconUrl: string;\n id: string;\n kind: \"agent\";\n label: string;\n launchEnabled: boolean;\n provider: TProvider;\n reason?: string | null;\n };\n\nexport interface WorkbenchLaunchpadGridMetrics {\n columns: number;\n pageSize: number;\n rows: number;\n}\n\nexport interface WorkbenchLaunchpadPage<TItem> {\n currentPage: number;\n pageCount: number;\n pageItems: readonly TItem[];\n}\n\nconst launchpadPreviewIconCount = 4;\nconst launchpadMinColumns = 2;\nconst launchpadMaxColumns = 7;\nconst launchpadMinRows = 1;\nconst launchpadMaxRows = 5;\nconst launchpadTileWidth = 136;\nconst launchpadTileHeight = 138;\n\nexport function buildWorkbenchLaunchpadItems<\n TProvider extends string = string\n>(input: {\n agentDescriptors?: readonly WorkbenchLaunchpadAgentDescriptor<TProvider>[];\n apps?: readonly WorkbenchLaunchpadAppDescriptor[];\n nodeDescriptors?: readonly WorkbenchLaunchpadNodeDescriptor[];\n}): WorkbenchLaunchpadItem<TProvider>[] {\n const nodeItems = (input.nodeDescriptors ?? []).map((node) => ({\n disabledReason: node.disabledReason,\n dockEntryId: node.dockEntryId,\n iconUrl: node.iconUrl,\n id: `node:${node.id}`,\n kind: \"node\" as const,\n label: node.label,\n launchEnabled: node.launchEnabled ?? true,\n typeId: node.typeId\n }));\n const pinnedNodeItems = nodeItems.slice(0, 2);\n const remainingNodeItems = nodeItems.slice(2);\n return [\n ...pinnedNodeItems,\n ...(input.apps ?? []).map((app) => ({\n appId: app.appId,\n disabledReason: app.disabledReason,\n iconUrl: app.iconUrl,\n id: app.id ?? `app:${app.appId}`,\n kind: \"app\" as const,\n label: app.label,\n launchEnabled: app.launchEnabled\n })),\n ...remainingNodeItems,\n ...(input.agentDescriptors ?? []).map((agent) => ({\n action: agent.action,\n actions: agent.actions,\n comingSoon: agent.comingSoon,\n disabledReason: agent.disabledReason,\n iconUrl: agent.iconUrl,\n id: agent.id ?? `agent:${agent.provider}`,\n kind: \"agent\" as const,\n label: agent.label,\n launchEnabled: agent.launchEnabled,\n provider: agent.provider,\n reason: agent.reason\n }))\n ];\n}\n\nexport function filterWorkbenchLaunchpadItems<TItem extends { label: string }>(\n items: readonly TItem[],\n query: string\n): TItem[] {\n const normalizedQuery = normalizeLaunchpadSearchText(query);\n if (!normalizedQuery) {\n return [...items];\n }\n return items.filter((item) =>\n normalizeLaunchpadSearchText(item.label).includes(normalizedQuery)\n );\n}\n\nexport function paginateWorkbenchLaunchpadItems<TItem>(\n items: readonly TItem[],\n input: {\n page: number;\n pageSize: number;\n }\n): WorkbenchLaunchpadPage<TItem> {\n const pageSize = Math.max(1, Math.floor(input.pageSize));\n const pageCount = Math.max(1, Math.ceil(items.length / pageSize));\n const currentPage = clampInteger(input.page, 0, pageCount - 1);\n const pageStart = currentPage * pageSize;\n return {\n currentPage,\n pageCount,\n pageItems: items.slice(pageStart, pageStart + pageSize)\n };\n}\n\nexport function resolveWorkbenchLaunchpadGrid(input: {\n height: number;\n width: number;\n}): WorkbenchLaunchpadGridMetrics {\n const columns = clampInteger(\n Math.floor(input.width / launchpadTileWidth),\n launchpadMinColumns,\n launchpadMaxColumns\n );\n const rows = clampInteger(\n Math.floor(input.height / launchpadTileHeight),\n launchpadMinRows,\n launchpadMaxRows\n );\n return {\n columns,\n pageSize: Math.max(1, columns * rows),\n rows\n };\n}\n\nexport function resolveWorkbenchLaunchpadPreviewIconUrls(input: {\n agentIcons?: readonly string[];\n appIcons?: readonly (string | null | undefined)[];\n fallbackIconUrl: string;\n nodeIconUrls?: readonly string[];\n}): string[] {\n const icons = uniqueLaunchpadPreviewIconUrls([\n ...(input.appIcons ?? []),\n ...(input.nodeIconUrls ?? []),\n ...(input.agentIcons ?? [])\n ]).slice(0, launchpadPreviewIconCount);\n while (icons.length < launchpadPreviewIconCount) {\n icons.push(input.fallbackIconUrl);\n }\n return icons;\n}\n\nfunction uniqueLaunchpadPreviewIconUrls(\n iconUrls: readonly (string | null | undefined)[]\n): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n for (const iconUrl of iconUrls) {\n const normalizedIconUrl = iconUrl?.trim();\n if (!normalizedIconUrl || seen.has(normalizedIconUrl)) {\n continue;\n }\n seen.add(normalizedIconUrl);\n result.push(normalizedIconUrl);\n }\n return result;\n}\n\nfunction normalizeLaunchpadSearchText(value: string): string {\n return value.trim().toLocaleLowerCase();\n}\n\nfunction clampInteger(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) {\n return min;\n }\n return Math.min(Math.max(Math.floor(value), min), max);\n}\n","const wheelDeltaLinePx = 16;\nconst wheelDeltaPagePx = 360;\nconst launchpadWheelNavigationThresholdPx = 64;\nconst launchpadWheelNavigationCooldownMs = 420;\nconst launchpadWheelHorizontalIntentRatio = 1.2;\n\nexport interface WorkbenchLaunchpadWheelNavigationState {\n accumulatedDeltaX: number;\n lastNavigationAt: number;\n}\n\nexport interface WorkbenchLaunchpadWheelNavigationResult {\n nextPageIndex: number | null;\n shouldPreventDefault: boolean;\n state: WorkbenchLaunchpadWheelNavigationState;\n}\n\nexport function createWorkbenchLaunchpadWheelNavigationState(): WorkbenchLaunchpadWheelNavigationState {\n return {\n accumulatedDeltaX: 0,\n lastNavigationAt: 0\n };\n}\n\nexport function resolveWorkbenchLaunchpadWheelNavigation(input: {\n currentPage: number;\n deltaMode?: number;\n deltaX: number;\n deltaY: number;\n pageCount: number;\n state: WorkbenchLaunchpadWheelNavigationState;\n timestamp: number;\n}): WorkbenchLaunchpadWheelNavigationResult {\n if (input.pageCount <= 1) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: false,\n state: createWorkbenchLaunchpadWheelNavigationState()\n };\n }\n\n const delta = normalizeWorkbenchLaunchpadWheelDelta(input);\n const absDeltaX = Math.abs(delta.x);\n const absDeltaY = Math.abs(delta.y);\n const isHorizontalIntent =\n absDeltaX > 0 &&\n absDeltaX >= absDeltaY * launchpadWheelHorizontalIntentRatio;\n\n if (!isHorizontalIntent) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: false,\n state: {\n accumulatedDeltaX: 0,\n lastNavigationAt: input.state.lastNavigationAt\n }\n };\n }\n\n const direction = delta.x > 0 ? 1 : -1;\n const previousDirection = input.state.accumulatedDeltaX > 0 ? 1 : -1;\n const accumulatedDeltaX =\n input.state.accumulatedDeltaX !== 0 && previousDirection === direction\n ? input.state.accumulatedDeltaX + delta.x\n : delta.x;\n\n if (\n input.timestamp - input.state.lastNavigationAt <\n launchpadWheelNavigationCooldownMs\n ) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: true,\n state: {\n accumulatedDeltaX: 0,\n lastNavigationAt: input.state.lastNavigationAt\n }\n };\n }\n\n if (Math.abs(accumulatedDeltaX) < launchpadWheelNavigationThresholdPx) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: true,\n state: {\n accumulatedDeltaX,\n lastNavigationAt: input.state.lastNavigationAt\n }\n };\n }\n\n const nextPageIndex = input.currentPage + direction;\n if (nextPageIndex < 0 || nextPageIndex >= input.pageCount) {\n return {\n nextPageIndex: null,\n shouldPreventDefault: true,\n state: {\n accumulatedDeltaX: 0,\n lastNavigationAt: input.timestamp\n }\n };\n }\n\n return {\n nextPageIndex,\n shouldPreventDefault: true,\n state: {\n accumulatedDeltaX: 0,\n lastNavigationAt: input.timestamp\n }\n };\n}\n\nfunction normalizeWorkbenchLaunchpadWheelDelta(input: {\n deltaMode?: number;\n deltaX: number;\n deltaY: number;\n}): { x: number; y: number } {\n const unit =\n input.deltaMode === 1\n ? wheelDeltaLinePx\n : input.deltaMode === 2\n ? wheelDeltaPagePx\n : 1;\n return {\n x: input.deltaX * unit,\n y: input.deltaY * unit\n };\n}\n","import { createElement, type ReactNode } from \"react\";\nimport type { WorkbenchHostDockEntry } from \"@tutti-os/workbench-surface\";\nimport {\n workbenchLaunchpadDockActionId,\n workbenchLaunchpadDockEntryId\n} from \"./launchpadModel.ts\";\n\nexport function createWorkbenchLaunchpadDockIcon(_input: {\n tileIconUrls: readonly string[];\n}): ReactNode {\n return createElement(\n \"span\",\n {\n \"aria-hidden\": \"true\",\n className: \"workspace-launchpad-dock-icon\"\n },\n createElement(\n \"span\",\n {\n className: \"workspace-launchpad-dock-icon__label\"\n },\n \"ALL\"\n )\n );\n}\n\nexport function createWorkbenchLaunchpadDockEntry(input: {\n label: string;\n order?: number;\n tileIconUrls: readonly string[];\n}): WorkbenchHostDockEntry {\n return {\n clickActionId: workbenchLaunchpadDockActionId,\n icon: createWorkbenchLaunchpadDockIcon({\n tileIconUrls: input.tileIconUrls\n }),\n id: workbenchLaunchpadDockEntryId,\n label: input.label,\n launchBehavior: \"enabled\",\n order: input.order ?? 0,\n sectionId: \"launchpad\",\n typeId: workbenchLaunchpadDockEntryId,\n visibility: \"always\"\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,29 +1,40 @@
|
|
|
1
1
|
.workspace-launchpad-dock-icon {
|
|
2
|
-
--workspace-launchpad-dock-icon-bg: var(--transparency-block);
|
|
3
2
|
--workspace-launchpad-dock-icon-border: var(--line-1);
|
|
4
3
|
box-sizing: border-box;
|
|
5
4
|
display: grid;
|
|
5
|
+
place-items: center;
|
|
6
6
|
width: 44px;
|
|
7
7
|
height: 44px;
|
|
8
|
-
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
9
|
-
gap: 2px;
|
|
10
8
|
padding: 3px;
|
|
11
9
|
border: 1px solid var(--workspace-launchpad-dock-icon-border);
|
|
12
10
|
border-radius: 8px;
|
|
13
|
-
background: var(--
|
|
11
|
+
background: var(--background-fronted);
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
.desktop-dock__slot[data-wallpaper-tone="dark"] .workspace-launchpad-dock-icon {
|
|
17
|
-
--workspace-launchpad-dock-icon-bg: rgb(255 255 255 / 18%);
|
|
18
15
|
--workspace-launchpad-dock-icon-border: rgb(255 255 255 / 15%);
|
|
19
16
|
}
|
|
20
17
|
|
|
21
18
|
.desktop-dock__slot[data-wallpaper-tone="light"]
|
|
22
19
|
.workspace-launchpad-dock-icon {
|
|
23
|
-
--workspace-launchpad-dock-icon-bg: rgb(0 0 0 / 10%);
|
|
24
20
|
--workspace-launchpad-dock-icon-border: rgb(0 0 0 / 10%);
|
|
25
21
|
}
|
|
26
22
|
|
|
23
|
+
.workspace-launchpad-dock-icon__label {
|
|
24
|
+
display: block;
|
|
25
|
+
color: var(--text-primary);
|
|
26
|
+
font-family: "Lexend Variable", "Lexend", var(--font-sans-system);
|
|
27
|
+
font-size: 14px;
|
|
28
|
+
font-weight: 700;
|
|
29
|
+
line-height: 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.workspace-launchpad-dock-icon--tiles {
|
|
33
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
34
|
+
gap: 2px;
|
|
35
|
+
place-items: stretch;
|
|
36
|
+
}
|
|
37
|
+
|
|
27
38
|
.workspace-launchpad-dock-icon__tile {
|
|
28
39
|
display: block;
|
|
29
40
|
overflow: visible;
|
|
@@ -37,6 +48,7 @@
|
|
|
37
48
|
display: block;
|
|
38
49
|
width: 100%;
|
|
39
50
|
height: 100%;
|
|
51
|
+
border-radius: 999px;
|
|
40
52
|
object-fit: contain;
|
|
41
53
|
object-position: center;
|
|
42
54
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tutti-os/workbench-launchpad",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.60",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"directory": "packages/workbench/launchpad"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@tutti-os/ui-system": "0.0.
|
|
25
|
-
"@tutti-os/workbench-surface": "0.0.
|
|
24
|
+
"@tutti-os/ui-system": "0.0.60",
|
|
25
|
+
"@tutti-os/workbench-surface": "0.0.60"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^24.0.1",
|