@burdenoff/microfe-vibecontrols 2026.624.2 → 2026.624.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/VibeControlsRoutes.js +1 -1
  2. package/dist/VibeControlsRoutes.js.map +1 -1
  3. package/dist/components/agents/AgentStatusBadge.js +1 -1
  4. package/dist/components/agents/AgentStatusBadge.js.map +1 -1
  5. package/dist/components/agents/ConnectionLogPanel.js +1 -1
  6. package/dist/components/agents/ConnectionLogPanel.js.map +1 -1
  7. package/dist/components/agents/PluginUIPanel.js +1 -1
  8. package/dist/components/agents/PluginUIPanel.js.map +1 -1
  9. package/dist/components/audit/AuditLogTable.js +1 -1
  10. package/dist/components/audit/AuditLogTable.js.map +1 -1
  11. package/dist/components/docs/DocsFullScreenViewer.js +1 -1
  12. package/dist/components/docs/DocsFullScreenViewer.js.map +1 -1
  13. package/dist/components/notes/NoteEditor.js +1 -1
  14. package/dist/components/notes/NoteEditor.js.map +1 -1
  15. package/dist/components/sessions/TerminalPanel.js +3 -3
  16. package/dist/components/sessions/TerminalPanel.js.map +1 -1
  17. package/dist/components/shared/ActionMenu.js +1 -1
  18. package/dist/components/shared/ActionMenu.js.map +1 -1
  19. package/dist/components/shared/ErrorState.js +1 -1
  20. package/dist/components/shared/ErrorState.js.map +1 -1
  21. package/dist/components/vibecalendar/ScheduleTaskModal.js +3 -3
  22. package/dist/components/vibecalendar/ScheduleTaskModal.js.map +1 -1
  23. package/dist/components/vibecalendar/types.js +5 -5
  24. package/dist/components/vibecalendar/types.js.map +1 -1
  25. package/dist/pages/NoteDetailsPage.js +2 -2
  26. package/dist/pages/NoteDetailsPage.js.map +1 -1
  27. package/dist/pages/SessionDetailsPage.js +1 -1
  28. package/dist/pages/SessionDetailsPage.js.map +1 -1
  29. package/dist/pages/TargetsPage.js +3 -3
  30. package/dist/pages/TargetsPage.js.map +1 -1
  31. package/package.json +1 -1
@@ -47,7 +47,7 @@ var _ = "text-status-error-text focus:text-status-error-text", v = ({ items: v,
47
47
  onClick: () => {
48
48
  O(!1), e.onSelect();
49
49
  },
50
- className: `flex min-h-12 w-full items-center gap-3 rounded-button px-3 text-left text-base transition-colors active:scale-[0.98] disabled:opacity-50 ${e.variant === "danger" ? "text-status-error-text hover:bg-status-error-bg-subtle" : "text-text-primary hover:bg-bg-sunken"}`,
50
+ className: `flex min-h-12 w-full items-center gap-3 rounded-button px-3 text-left text-base transition-colors disabled:opacity-50 ${e.variant === "danger" ? "text-status-error-text hover:bg-status-error-bg-subtle" : "text-text-primary hover:bg-bg-sunken"}`,
51
51
  children: [t ? /* @__PURE__ */ o(t, {
52
52
  className: "size-5 shrink-0",
53
53
  "aria-hidden": "true"
@@ -1 +1 @@
1
- {"version":3,"file":"ActionMenu.js","names":[],"sources":["../../../src/components/shared/ActionMenu.tsx"],"sourcesContent":["import {\n cloneElement,\n isValidElement,\n useState,\n type FC,\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport type { LucideIcon } from 'lucide-react';\nimport { MoreVertical } from 'lucide-react';\nimport {\n BottomSheet,\n BottomSheetContent,\n BottomSheetHeader,\n BottomSheetTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { useBreakpoint } from '@burdenoff/fe-libs/shared/hooks';\n\nexport interface ActionMenuItem {\n key: string;\n label: string;\n icon?: LucideIcon;\n onSelect: () => void;\n variant?: 'default' | 'danger';\n disabled?: boolean;\n /** Render a separator above this item (desktop dropdown only). */\n separatorBefore?: boolean;\n}\n\nexport interface ActionMenuProps {\n items: ActionMenuItem[];\n /** Accessible name for the trigger button, e.g. \"Agent actions\". */\n ariaLabel: string;\n /** Sheet heading on mobile; defaults to ariaLabel. */\n title?: string;\n align?: 'start' | 'end';\n /** Custom trigger node; defaults to a kebab icon button. */\n trigger?: ReactNode;\n triggerClassName?: string;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DANGER_ITEM_CLASS = 'text-status-error-text focus:text-status-error-text';\n\n/**\n * Canonical overflow/kebab menu for the module: a Radix DropdownMenu on\n * >= md viewports and a BottomSheet action list on mobile. Replaces all\n * hand-rolled useState dropdowns (keyboard nav, Escape, outside-click,\n * aria-expanded and focus return come from the primitives).\n *\n * Safe to embed inside clickable cards: trigger and content stop click\n * propagation so menu interaction never activates the card underneath.\n */\nexport const ActionMenu: FC<ActionMenuProps> = ({\n items,\n ariaLabel,\n title,\n align = 'end',\n trigger,\n triggerClassName,\n onOpenChange,\n}) => {\n const [open, setOpen] = useState(false);\n const { isMobile } = useBreakpoint();\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next);\n onOpenChange?.(next);\n };\n\n const triggerNode = trigger ?? (\n <button\n type=\"button\"\n className={\n triggerClassName ??\n 'inline-flex size-9 max-md:size-11 items-center justify-center rounded-button text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus'\n }\n aria-label={ariaLabel}\n >\n <MoreVertical className=\"size-4\" aria-hidden=\"true\" />\n </button>\n );\n\n if (isMobile) {\n const sheetTitle = title ?? ariaLabel;\n const mobileTriggerProps = {\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': open,\n onClick: (event: ReactMouseEvent) => {\n event.stopPropagation();\n handleOpenChange(true);\n },\n onKeyDown: (event: ReactKeyboardEvent) => event.stopPropagation(),\n };\n return (\n <>\n {isValidElement(triggerNode) ? (\n cloneElement(triggerNode as ReactElement<Record<string, unknown>>, {\n ...mobileTriggerProps,\n })\n ) : (\n <span {...mobileTriggerProps} className=\"contents\">\n {triggerNode}\n </span>\n )}\n <BottomSheet open={open} onOpenChange={handleOpenChange}>\n <BottomSheetContent\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n <BottomSheetHeader>\n <BottomSheetTitle>{sheetTitle}</BottomSheetTitle>\n </BottomSheetHeader>\n <div className=\"flex flex-col gap-1 pb-2\" role=\"group\" aria-label={sheetTitle}>\n {items.map((item) => {\n const Icon = item.icon;\n return (\n <button\n key={item.key}\n type=\"button\"\n disabled={item.disabled}\n onClick={() => {\n handleOpenChange(false);\n item.onSelect();\n }}\n className={`flex min-h-12 w-full items-center gap-3 rounded-button px-3 text-left text-base transition-colors active:scale-[0.98] disabled:opacity-50 ${\n item.variant === 'danger'\n ? 'text-status-error-text hover:bg-status-error-bg-subtle'\n : 'text-text-primary hover:bg-bg-sunken'\n }`}\n >\n {Icon ? <Icon className=\"size-5 shrink-0\" aria-hidden=\"true\" /> : null}\n <span className=\"min-w-0 truncate\">{item.label}</span>\n </button>\n );\n })}\n </div>\n </BottomSheetContent>\n </BottomSheet>\n </>\n );\n }\n\n return (\n <DropdownMenu open={open} onOpenChange={handleOpenChange}>\n <DropdownMenuTrigger\n asChild\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n {triggerNode}\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align={align}\n className=\"min-w-44\"\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n {items.map((item) => {\n const Icon = item.icon;\n return (\n <div key={item.key} className=\"contents\">\n {item.separatorBefore ? <DropdownMenuSeparator /> : null}\n <DropdownMenuItem\n disabled={item.disabled}\n onSelect={() => item.onSelect()}\n className={`cursor-pointer gap-2 ${item.variant === 'danger' ? DANGER_ITEM_CLASS : ''}`}\n >\n {Icon ? <Icon className=\"size-4 shrink-0\" aria-hidden=\"true\" /> : null}\n <span className=\"min-w-0 truncate\">{item.label}</span>\n </DropdownMenuItem>\n </div>\n );\n })}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n"],"mappings":";;;;;;AAiDA,IAAM,IAAoB,uDAWb,KAAmC,EAC9C,UACA,cACA,UACA,WAAQ,OACR,YACA,qBACA,sBACI;CACJ,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,EAAE,gBAAa,GAAe,EAE9B,KAAoB,MAAkB;AAE1C,EADA,EAAQ,EAAK,EACb,IAAe,EAAK;IAGhB,IAAc,KAClB,kBAAC,UAAD;EACE,MAAK;EACL,WACE,KACA;EAEF,cAAY;YAEZ,kBAAC,GAAD;GAAc,WAAU;GAAS,eAAY;GAAS,CAAA;EAC/C,CAAA;AAGX,KAAI,GAAU;EACZ,IAAM,IAAa,KAAS,GACtB,IAAqB;GACzB,iBAAiB;GACjB,iBAAiB;GACjB,UAAU,MAA2B;AAEnC,IADA,EAAM,iBAAiB,EACvB,EAAiB,GAAK;;GAExB,YAAY,MAA8B,EAAM,iBAAiB;GAClE;AACD,SACE,kBAAA,GAAA,EAAA,UAAA,CACG,EAAe,EAAY,GAC1B,EAAa,GAAsD,EACjE,GAAG,GACJ,CAAC,GAEF,kBAAC,QAAD;GAAM,GAAI;GAAoB,WAAU;aACrC;GACI,CAAA,EAET,kBAAC,GAAD;GAAmB;GAAM,cAAc;aACrC,kBAAC,GAAD;IACE,UAAU,MAAU,EAAM,iBAAiB;IAC3C,YAAY,MAAU,EAAM,iBAAiB;cAF/C,CAIE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAmB,GAA8B,CAAA,EAC/B,CAAA,EACpB,kBAAC,OAAD;KAAK,WAAU;KAA2B,MAAK;KAAQ,cAAY;eAChE,EAAM,KAAK,MAAS;MACnB,IAAM,IAAO,EAAK;AAClB,aACE,kBAAC,UAAD;OAEE,MAAK;OACL,UAAU,EAAK;OACf,eAAe;AAEb,QADA,EAAiB,GAAM,EACvB,EAAK,UAAU;;OAEjB,WAAW,6IACT,EAAK,YAAY,WACb,2DACA;iBAXR,CAcG,IAAO,kBAAC,GAAD;QAAM,WAAU;QAAkB,eAAY;QAAS,CAAA,GAAG,MAClE,kBAAC,QAAD;QAAM,WAAU;kBAAoB,EAAK;QAAa,CAAA,CAC/C;SAfF,EAAK,IAeH;OAEX;KACE,CAAA,CACa;;GACT,CAAA,CACb,EAAA,CAAA;;AAIP,QACE,kBAAC,GAAD;EAAoB;EAAM,cAAc;YAAxC,CACE,kBAAC,GAAD;GACE,SAAA;GACA,UAAU,MAAU,EAAM,iBAAiB;GAC3C,YAAY,MAAU,EAAM,iBAAiB;aAE5C;GACmB,CAAA,EACtB,kBAAC,GAAD;GACS;GACP,WAAU;GACV,UAAU,MAAU,EAAM,iBAAiB;GAC3C,YAAY,MAAU,EAAM,iBAAiB;aAE5C,EAAM,KAAK,MAAS;IACnB,IAAM,IAAO,EAAK;AAClB,WACE,kBAAC,OAAD;KAAoB,WAAU;eAA9B,CACG,EAAK,kBAAkB,kBAAC,GAAD,EAAyB,CAAA,GAAG,MACpD,kBAAC,GAAD;MACE,UAAU,EAAK;MACf,gBAAgB,EAAK,UAAU;MAC/B,WAAW,wBAAwB,EAAK,YAAY,WAAW,IAAoB;gBAHrF,CAKG,IAAO,kBAAC,GAAD;OAAM,WAAU;OAAkB,eAAY;OAAS,CAAA,GAAG,MAClE,kBAAC,QAAD;OAAM,WAAU;iBAAoB,EAAK;OAAa,CAAA,CACrC;QACf;OAVI,EAAK,IAUT;KAER;GACkB,CAAA,CACT"}
1
+ {"version":3,"file":"ActionMenu.js","names":[],"sources":["../../../src/components/shared/ActionMenu.tsx"],"sourcesContent":["import {\n cloneElement,\n isValidElement,\n useState,\n type FC,\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport type { LucideIcon } from 'lucide-react';\nimport { MoreVertical } from 'lucide-react';\nimport {\n BottomSheet,\n BottomSheetContent,\n BottomSheetHeader,\n BottomSheetTitle,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { useBreakpoint } from '@burdenoff/fe-libs/shared/hooks';\n\nexport interface ActionMenuItem {\n key: string;\n label: string;\n icon?: LucideIcon;\n onSelect: () => void;\n variant?: 'default' | 'danger';\n disabled?: boolean;\n /** Render a separator above this item (desktop dropdown only). */\n separatorBefore?: boolean;\n}\n\nexport interface ActionMenuProps {\n items: ActionMenuItem[];\n /** Accessible name for the trigger button, e.g. \"Agent actions\". */\n ariaLabel: string;\n /** Sheet heading on mobile; defaults to ariaLabel. */\n title?: string;\n align?: 'start' | 'end';\n /** Custom trigger node; defaults to a kebab icon button. */\n trigger?: ReactNode;\n triggerClassName?: string;\n onOpenChange?: (open: boolean) => void;\n}\n\nconst DANGER_ITEM_CLASS = 'text-status-error-text focus:text-status-error-text';\n\n/**\n * Canonical overflow/kebab menu for the module: a Radix DropdownMenu on\n * >= md viewports and a BottomSheet action list on mobile. Replaces all\n * hand-rolled useState dropdowns (keyboard nav, Escape, outside-click,\n * aria-expanded and focus return come from the primitives).\n *\n * Safe to embed inside clickable cards: trigger and content stop click\n * propagation so menu interaction never activates the card underneath.\n */\nexport const ActionMenu: FC<ActionMenuProps> = ({\n items,\n ariaLabel,\n title,\n align = 'end',\n trigger,\n triggerClassName,\n onOpenChange,\n}) => {\n const [open, setOpen] = useState(false);\n const { isMobile } = useBreakpoint();\n\n const handleOpenChange = (next: boolean) => {\n setOpen(next);\n onOpenChange?.(next);\n };\n\n const triggerNode = trigger ?? (\n <button\n type=\"button\"\n className={\n triggerClassName ??\n 'inline-flex size-9 max-md:size-11 items-center justify-center rounded-button text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus'\n }\n aria-label={ariaLabel}\n >\n <MoreVertical className=\"size-4\" aria-hidden=\"true\" />\n </button>\n );\n\n if (isMobile) {\n const sheetTitle = title ?? ariaLabel;\n const mobileTriggerProps = {\n 'aria-haspopup': 'dialog' as const,\n 'aria-expanded': open,\n onClick: (event: ReactMouseEvent) => {\n event.stopPropagation();\n handleOpenChange(true);\n },\n onKeyDown: (event: ReactKeyboardEvent) => event.stopPropagation(),\n };\n return (\n <>\n {isValidElement(triggerNode) ? (\n cloneElement(triggerNode as ReactElement<Record<string, unknown>>, {\n ...mobileTriggerProps,\n })\n ) : (\n <span {...mobileTriggerProps} className=\"contents\">\n {triggerNode}\n </span>\n )}\n <BottomSheet open={open} onOpenChange={handleOpenChange}>\n <BottomSheetContent\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n <BottomSheetHeader>\n <BottomSheetTitle>{sheetTitle}</BottomSheetTitle>\n </BottomSheetHeader>\n <div className=\"flex flex-col gap-1 pb-2\" role=\"group\" aria-label={sheetTitle}>\n {items.map((item) => {\n const Icon = item.icon;\n return (\n <button\n key={item.key}\n type=\"button\"\n disabled={item.disabled}\n onClick={() => {\n handleOpenChange(false);\n item.onSelect();\n }}\n className={`flex min-h-12 w-full items-center gap-3 rounded-button px-3 text-left text-base transition-colors disabled:opacity-50 ${\n item.variant === 'danger'\n ? 'text-status-error-text hover:bg-status-error-bg-subtle'\n : 'text-text-primary hover:bg-bg-sunken'\n }`}\n >\n {Icon ? <Icon className=\"size-5 shrink-0\" aria-hidden=\"true\" /> : null}\n <span className=\"min-w-0 truncate\">{item.label}</span>\n </button>\n );\n })}\n </div>\n </BottomSheetContent>\n </BottomSheet>\n </>\n );\n }\n\n return (\n <DropdownMenu open={open} onOpenChange={handleOpenChange}>\n <DropdownMenuTrigger\n asChild\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n {triggerNode}\n </DropdownMenuTrigger>\n <DropdownMenuContent\n align={align}\n className=\"min-w-44\"\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => event.stopPropagation()}\n >\n {items.map((item) => {\n const Icon = item.icon;\n return (\n <div key={item.key} className=\"contents\">\n {item.separatorBefore ? <DropdownMenuSeparator /> : null}\n <DropdownMenuItem\n disabled={item.disabled}\n onSelect={() => item.onSelect()}\n className={`cursor-pointer gap-2 ${item.variant === 'danger' ? DANGER_ITEM_CLASS : ''}`}\n >\n {Icon ? <Icon className=\"size-4 shrink-0\" aria-hidden=\"true\" /> : null}\n <span className=\"min-w-0 truncate\">{item.label}</span>\n </DropdownMenuItem>\n </div>\n );\n })}\n </DropdownMenuContent>\n </DropdownMenu>\n );\n};\n"],"mappings":";;;;;;AAiDA,IAAM,IAAoB,uDAWb,KAAmC,EAC9C,UACA,cACA,UACA,WAAQ,OACR,YACA,qBACA,sBACI;CACJ,IAAM,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,EAAE,gBAAa,GAAe,EAE9B,KAAoB,MAAkB;AAE1C,EADA,EAAQ,EAAK,EACb,IAAe,EAAK;IAGhB,IAAc,KAClB,kBAAC,UAAD;EACE,MAAK;EACL,WACE,KACA;EAEF,cAAY;YAEZ,kBAAC,GAAD;GAAc,WAAU;GAAS,eAAY;GAAS,CAAA;EAC/C,CAAA;AAGX,KAAI,GAAU;EACZ,IAAM,IAAa,KAAS,GACtB,IAAqB;GACzB,iBAAiB;GACjB,iBAAiB;GACjB,UAAU,MAA2B;AAEnC,IADA,EAAM,iBAAiB,EACvB,EAAiB,GAAK;;GAExB,YAAY,MAA8B,EAAM,iBAAiB;GAClE;AACD,SACE,kBAAA,GAAA,EAAA,UAAA,CACG,EAAe,EAAY,GAC1B,EAAa,GAAsD,EACjE,GAAG,GACJ,CAAC,GAEF,kBAAC,QAAD;GAAM,GAAI;GAAoB,WAAU;aACrC;GACI,CAAA,EAET,kBAAC,GAAD;GAAmB;GAAM,cAAc;aACrC,kBAAC,GAAD;IACE,UAAU,MAAU,EAAM,iBAAiB;IAC3C,YAAY,MAAU,EAAM,iBAAiB;cAF/C,CAIE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAmB,GAA8B,CAAA,EAC/B,CAAA,EACpB,kBAAC,OAAD;KAAK,WAAU;KAA2B,MAAK;KAAQ,cAAY;eAChE,EAAM,KAAK,MAAS;MACnB,IAAM,IAAO,EAAK;AAClB,aACE,kBAAC,UAAD;OAEE,MAAK;OACL,UAAU,EAAK;OACf,eAAe;AAEb,QADA,EAAiB,GAAM,EACvB,EAAK,UAAU;;OAEjB,WAAW,yHACT,EAAK,YAAY,WACb,2DACA;iBAXR,CAcG,IAAO,kBAAC,GAAD;QAAM,WAAU;QAAkB,eAAY;QAAS,CAAA,GAAG,MAClE,kBAAC,QAAD;QAAM,WAAU;kBAAoB,EAAK;QAAa,CAAA,CAC/C;SAfF,EAAK,IAeH;OAEX;KACE,CAAA,CACa;;GACT,CAAA,CACb,EAAA,CAAA;;AAIP,QACE,kBAAC,GAAD;EAAoB;EAAM,cAAc;YAAxC,CACE,kBAAC,GAAD;GACE,SAAA;GACA,UAAU,MAAU,EAAM,iBAAiB;GAC3C,YAAY,MAAU,EAAM,iBAAiB;aAE5C;GACmB,CAAA,EACtB,kBAAC,GAAD;GACS;GACP,WAAU;GACV,UAAU,MAAU,EAAM,iBAAiB;GAC3C,YAAY,MAAU,EAAM,iBAAiB;aAE5C,EAAM,KAAK,MAAS;IACnB,IAAM,IAAO,EAAK;AAClB,WACE,kBAAC,OAAD;KAAoB,WAAU;eAA9B,CACG,EAAK,kBAAkB,kBAAC,GAAD,EAAyB,CAAA,GAAG,MACpD,kBAAC,GAAD;MACE,UAAU,EAAK;MACf,gBAAgB,EAAK,UAAU;MAC/B,WAAW,wBAAwB,EAAK,YAAY,WAAW,IAAoB;gBAHrF,CAKG,IAAO,kBAAC,GAAD;OAAM,WAAU;OAAkB,eAAY;OAAS,CAAA,GAAG,MAClE,kBAAC,QAAD;OAAM,WAAU;iBAAoB,EAAK;OAAa,CAAA,CACrC;QACf;OAVI,EAAK,IAUT;KAER;GACkB,CAAA,CACT"}
@@ -109,7 +109,7 @@ function s({ title: s, message: c, onRetry: l, action: u }) {
109
109
  children: [l && /* @__PURE__ */ o("button", {
110
110
  type: "button",
111
111
  onClick: l,
112
- className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover active:scale-[0.98] transition-[colors,transform] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
112
+ className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover transition-[colors,transform] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus",
113
113
  children: [/* @__PURE__ */ a(n, {
114
114
  className: "size-4",
115
115
  "aria-hidden": "true"
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorState.js","names":[],"sources":["../../../src/components/shared/ErrorState.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { AlertTriangle, RefreshCw } from 'lucide-react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface ErrorStateProps {\n title?: string;\n message: string;\n onRetry?: () => void;\n action?: ReactNode;\n}\n\nexport function ErrorState({ title, message, onRetry, action }: ErrorStateProps) {\n const tr = useTr();\n const resolvedTitle = title ?? tr('vibecontrols.shared.errorState.title', 'Something went wrong');\n const shouldReduceMotion = useReducedMotion();\n\n if (shouldReduceMotion) {\n return (\n <div className=\"flex flex-col items-center justify-center py-12 px-4 text-center\">\n <div className=\"size-16 rounded-full bg-status-error-bg-subtle flex items-center justify-center mb-5\">\n <AlertTriangle className=\"size-8 text-status-error-text\" aria-hidden=\"true\" />\n </div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-1.5 tracking-tight\">\n {resolvedTitle}\n </h3>\n <p className=\"text-sm text-text-secondary mb-5 max-w-md\">{message}</p>\n <div className=\"flex items-center gap-3\">\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n <RefreshCw className=\"size-4\" />\n {tr('vibecontrols.shared.errorState.tryAgain', 'Try Again')}\n </button>\n )}\n {action}\n </div>\n </div>\n );\n }\n\n return (\n <motion.div\n className=\"flex flex-col items-center justify-center py-12 px-4 text-center\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.25 }}\n >\n <motion.div\n className=\"size-16 rounded-full bg-status-error-bg-subtle flex items-center justify-center mb-5\"\n initial={{ scale: 0.5, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{\n type: 'spring',\n stiffness: 400,\n damping: 15,\n delay: 0.1,\n }}\n >\n <AlertTriangle className=\"size-8 text-status-error-text\" aria-hidden=\"true\" />\n </motion.div>\n <motion.h3\n className=\"text-lg font-semibold text-text-primary mb-1.5 tracking-tight\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.25, delay: 0.2 }}\n >\n {resolvedTitle}\n </motion.h3>\n <motion.p\n className=\"text-sm text-text-secondary mb-5 max-w-md\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.25, delay: 0.3 }}\n >\n {message}\n </motion.p>\n <motion.div\n className=\"flex items-center gap-3\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.25, delay: 0.4 }}\n >\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover active:scale-[0.98] transition-[colors,transform] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n <RefreshCw className=\"size-4\" aria-hidden=\"true\" />\n {tr('vibecontrols.shared.errorState.tryAgain', 'Try Again')}\n </button>\n )}\n {action}\n </motion.div>\n </motion.div>\n );\n}\n"],"mappings":";;;;;AAYA,SAAgB,EAAW,EAAE,UAAO,YAAS,YAAS,aAA2B;CAC/E,IAAM,IAAK,GAAO,EACZ,IAAgB,KAAS,EAAG,wCAAwC,uBAAuB;AA8BjG,QA7B2B,GAAkB,GAIzC,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAe,WAAU;KAAgC,eAAY;KAAS,CAAA;IAC1E,CAAA;GACN,kBAAC,MAAD;IAAI,WAAU;cACX;IACE,CAAA;GACL,kBAAC,KAAD;IAAG,WAAU;cAA6C;IAAY,CAAA;GACtE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KACC,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA,EAC/B,EAAG,2CAA2C,YAAY,CACpD;QAEV,EACG;;GACF;MAKR,kBAAC,EAAO,KAAR;EACE,WAAU;EACV,SAAS,EAAE,SAAS,GAAG;EACvB,SAAS,EAAE,SAAS,GAAG;EACvB,YAAY,EAAE,UAAU,KAAM;YAJhC;GAME,kBAAC,EAAO,KAAR;IACE,WAAU;IACV,SAAS;KAAE,OAAO;KAAK,SAAS;KAAG;IACnC,SAAS;KAAE,OAAO;KAAG,SAAS;KAAG;IACjC,YAAY;KACV,MAAM;KACN,WAAW;KACX,SAAS;KACT,OAAO;KACR;cAED,kBAAC,GAAD;KAAe,WAAU;KAAgC,eAAY;KAAS,CAAA;IACnE,CAAA;GACb,kBAAC,EAAO,IAAR;IACE,WAAU;IACV,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,YAAY;KAAE,UAAU;KAAM,OAAO;KAAK;cAEzC;IACS,CAAA;GACZ,kBAAC,EAAO,GAAR;IACE,WAAU;IACV,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,YAAY;KAAE,UAAU;KAAM,OAAO;KAAK;cAEzC;IACQ,CAAA;GACX,kBAAC,EAAO,KAAR;IACE,WAAU;IACV,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,YAAY;KAAE,UAAU;KAAM,OAAO;KAAK;cAJ5C,CAMG,KACC,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAHZ,CAKE,kBAAC,GAAD;MAAW,WAAU;MAAS,eAAY;MAAS,CAAA,EAClD,EAAG,2CAA2C,YAAY,CACpD;QAEV,EACU;;GACF"}
1
+ {"version":3,"file":"ErrorState.js","names":[],"sources":["../../../src/components/shared/ErrorState.tsx"],"sourcesContent":["import type { ReactNode } from 'react';\nimport { AlertTriangle, RefreshCw } from 'lucide-react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { useTr } from '../../shared/hooks/useTr';\n\ninterface ErrorStateProps {\n title?: string;\n message: string;\n onRetry?: () => void;\n action?: ReactNode;\n}\n\nexport function ErrorState({ title, message, onRetry, action }: ErrorStateProps) {\n const tr = useTr();\n const resolvedTitle = title ?? tr('vibecontrols.shared.errorState.title', 'Something went wrong');\n const shouldReduceMotion = useReducedMotion();\n\n if (shouldReduceMotion) {\n return (\n <div className=\"flex flex-col items-center justify-center py-12 px-4 text-center\">\n <div className=\"size-16 rounded-full bg-status-error-bg-subtle flex items-center justify-center mb-5\">\n <AlertTriangle className=\"size-8 text-status-error-text\" aria-hidden=\"true\" />\n </div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-1.5 tracking-tight\">\n {resolvedTitle}\n </h3>\n <p className=\"text-sm text-text-secondary mb-5 max-w-md\">{message}</p>\n <div className=\"flex items-center gap-3\">\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n <RefreshCw className=\"size-4\" />\n {tr('vibecontrols.shared.errorState.tryAgain', 'Try Again')}\n </button>\n )}\n {action}\n </div>\n </div>\n );\n }\n\n return (\n <motion.div\n className=\"flex flex-col items-center justify-center py-12 px-4 text-center\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n transition={{ duration: 0.25 }}\n >\n <motion.div\n className=\"size-16 rounded-full bg-status-error-bg-subtle flex items-center justify-center mb-5\"\n initial={{ scale: 0.5, opacity: 0 }}\n animate={{ scale: 1, opacity: 1 }}\n transition={{\n type: 'spring',\n stiffness: 400,\n damping: 15,\n delay: 0.1,\n }}\n >\n <AlertTriangle className=\"size-8 text-status-error-text\" aria-hidden=\"true\" />\n </motion.div>\n <motion.h3\n className=\"text-lg font-semibold text-text-primary mb-1.5 tracking-tight\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.25, delay: 0.2 }}\n >\n {resolvedTitle}\n </motion.h3>\n <motion.p\n className=\"text-sm text-text-secondary mb-5 max-w-md\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.25, delay: 0.3 }}\n >\n {message}\n </motion.p>\n <motion.div\n className=\"flex items-center gap-3\"\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.25, delay: 0.4 }}\n >\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover transition-[colors,transform] duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-focus\"\n >\n <RefreshCw className=\"size-4\" aria-hidden=\"true\" />\n {tr('vibecontrols.shared.errorState.tryAgain', 'Try Again')}\n </button>\n )}\n {action}\n </motion.div>\n </motion.div>\n );\n}\n"],"mappings":";;;;;AAYA,SAAgB,EAAW,EAAE,UAAO,YAAS,YAAS,aAA2B;CAC/E,IAAM,IAAK,GAAO,EACZ,IAAgB,KAAS,EAAG,wCAAwC,uBAAuB;AA8BjG,QA7B2B,GAAkB,GAIzC,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KAAe,WAAU;KAAgC,eAAY;KAAS,CAAA;IAC1E,CAAA;GACN,kBAAC,MAAD;IAAI,WAAU;cACX;IACE,CAAA;GACL,kBAAC,KAAD;IAAG,WAAU;cAA6C;IAAY,CAAA;GACtE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KACC,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAHZ,CAKE,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA,EAC/B,EAAG,2CAA2C,YAAY,CACpD;QAEV,EACG;;GACF;MAKR,kBAAC,EAAO,KAAR;EACE,WAAU;EACV,SAAS,EAAE,SAAS,GAAG;EACvB,SAAS,EAAE,SAAS,GAAG;EACvB,YAAY,EAAE,UAAU,KAAM;YAJhC;GAME,kBAAC,EAAO,KAAR;IACE,WAAU;IACV,SAAS;KAAE,OAAO;KAAK,SAAS;KAAG;IACnC,SAAS;KAAE,OAAO;KAAG,SAAS;KAAG;IACjC,YAAY;KACV,MAAM;KACN,WAAW;KACX,SAAS;KACT,OAAO;KACR;cAED,kBAAC,GAAD;KAAe,WAAU;KAAgC,eAAY;KAAS,CAAA;IACnE,CAAA;GACb,kBAAC,EAAO,IAAR;IACE,WAAU;IACV,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,YAAY;KAAE,UAAU;KAAM,OAAO;KAAK;cAEzC;IACS,CAAA;GACZ,kBAAC,EAAO,GAAR;IACE,WAAU;IACV,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,YAAY;KAAE,UAAU;KAAM,OAAO;KAAK;cAEzC;IACQ,CAAA;GACX,kBAAC,EAAO,KAAR;IACE,WAAU;IACV,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,SAAS;KAAE,SAAS;KAAG,GAAG;KAAG;IAC7B,YAAY;KAAE,UAAU;KAAM,OAAO;KAAK;cAJ5C,CAMG,KACC,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAHZ,CAKE,kBAAC,GAAD;MAAW,WAAU;MAAS,eAAY;MAAS,CAAA,EAClD,EAAG,2CAA2C,YAAY,CACpD;QAEV,EACU;;GACF"}
@@ -72,7 +72,7 @@ function m({ isOpen: m, onClose: h, onSubmit: g, loading: _, prefillActionId: v
72
72
  G && W && /* @__PURE__ */ u("div", {
73
73
  className: "flex items-start gap-3 p-3 rounded-lg border border-border-default bg-bg-surface",
74
74
  children: [/* @__PURE__ */ l("div", {
75
- className: "p-1.5 rounded-md bg-primary/10 text-primary flex-shrink-0",
75
+ className: "p-1.5 rounded-md bg-action-primary-bg/10 text-primary flex-shrink-0",
76
76
  children: /* @__PURE__ */ l(s, { size: 16 })
77
77
  }), /* @__PURE__ */ u("div", {
78
78
  className: "flex-1 min-w-0",
@@ -141,12 +141,12 @@ function m({ isOpen: m, onClose: h, onSubmit: g, loading: _, prefillActionId: v
141
141
  return /* @__PURE__ */ l("button", {
142
142
  type: "button",
143
143
  onClick: () => x(e.id),
144
- className: `w-full text-left px-3 py-2.5 hover:bg-bg-surface transition-colors ${t ? "bg-primary/5" : ""}`,
144
+ className: `w-full text-left px-3 py-2.5 hover:bg-bg-surface transition-colors ${t ? "bg-action-primary-bg/5" : ""}`,
145
145
  children: /* @__PURE__ */ u("div", {
146
146
  className: "flex items-start gap-2.5",
147
147
  children: [
148
148
  /* @__PURE__ */ l("div", {
149
- className: `p-1 rounded-md flex-shrink-0 ${t ? "bg-primary/10 text-primary" : "bg-bg-sunken text-text-tertiary"}`,
149
+ className: `p-1 rounded-md flex-shrink-0 ${t ? "bg-action-primary-bg/10 text-primary" : "bg-bg-sunken text-text-tertiary"}`,
150
150
  children: /* @__PURE__ */ l(s, { size: 14 })
151
151
  }),
152
152
  /* @__PURE__ */ u("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"ScheduleTaskModal.js","names":[],"sources":["../../../src/components/vibecalendar/ScheduleTaskModal.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { X, Zap, Search } from 'lucide-react';\nimport { useListActionsQuery } from '@/generated/wspace-operations';\nimport type { Action } from '@/generated/wspace-types';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { ActionAgentTargetNotice } from '../common/ActionAgentTargetNotice';\n\ntype ActionPickItem = Pick<\n Action,\n | 'id'\n | 'name'\n | 'displayName'\n | 'description'\n | 'actionType'\n | 'triggerType'\n | 'targetAgentId'\n | 'targetPlatformFilter'\n>;\n\ninterface ScheduleTaskModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSubmit: (input: ScheduleTaskInput) => void;\n // Legacy prop kept for compatibility; unused in Action-only mode.\n agents?: Array<{ id: string; name: string }>;\n loading?: boolean;\n // When provided, the picker is locked to this action (user navigated\n // in from \"Add to calendar\" on the Actions page). Otherwise the user\n // picks from a searchable dropdown of their actions.\n prefillActionId?: string;\n}\n\n/**\n * Calendar entries always delegate execution to a VibeControls Action.\n * Agent, command, script, and webhook fields come from the Action\n * definition at execution time — this modal only collects the calendar\n * metadata and the schedule.\n */\nexport interface ScheduleTaskInput {\n calendarId: string;\n title: string;\n description?: string;\n scheduleType: 'ONE_TIME' | 'CRON' | 'RRULE' | 'FIXED_INTERVAL';\n scheduledAt?: string;\n cronExpression?: string;\n rrule?: string;\n interval?: number;\n intervalUnit?: string;\n timezone: string;\n actionId: string;\n}\n\nconst INPUT_CLASS =\n 'w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-lg text-sm text-text-primary placeholder-text-placeholder focus:outline-none focus:border-border-default';\nconst MONO_INPUT_CLASS = `${INPUT_CLASS} font-mono`;\nconst LABEL_CLASS = 'block text-sm font-medium text-text-secondary mb-1';\n\nexport function ScheduleTaskModal({\n isOpen,\n onClose,\n onSubmit,\n loading,\n prefillActionId,\n}: ScheduleTaskModalProps) {\n const tr = useTr();\n const [selectedActionId, setSelectedActionId] = useState<string>(prefillActionId ?? '');\n const [actionSearch, setActionSearch] = useState('');\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState('');\n const [scheduleType, setScheduleType] = useState<\n 'ONE_TIME' | 'CRON' | 'RRULE' | 'FIXED_INTERVAL'\n >('ONE_TIME');\n const [scheduledAt, setScheduledAt] = useState('');\n const [cronExpression, setCronExpression] = useState('');\n const [interval, setInterval] = useState(60);\n const [intervalUnit, setIntervalUnit] = useState('minutes');\n const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone);\n\n const { data: actionsData, loading: actionsLoading } = useListActionsQuery({\n variables: { pagination: { limit: 100 } },\n skip: !isOpen,\n fetchPolicy: 'cache-and-network',\n });\n\n const allActions = useMemo<ActionPickItem[]>(\n () => (actionsData?.actions?.items ?? []) as ActionPickItem[],\n [actionsData?.actions?.items]\n );\n\n const filteredActions = useMemo(() => {\n if (!actionSearch.trim()) return allActions;\n const q = actionSearch.trim().toLowerCase();\n return allActions.filter(\n (a: ActionPickItem) =>\n a.name?.toLowerCase().includes(q) ||\n a.displayName?.toLowerCase().includes(q) ||\n a.description?.toLowerCase().includes(q)\n );\n }, [allActions, actionSearch]);\n\n const selectedAction = useMemo(\n () => allActions.find((a: ActionPickItem) => a.id === selectedActionId),\n [allActions, selectedActionId]\n );\n\n if (!isOpen) return null;\n\n const isActionLocked = Boolean(prefillActionId);\n const canSubmit = Boolean(selectedActionId) && !loading;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!selectedActionId) return;\n onSubmit({\n calendarId: '',\n title,\n description: description || undefined,\n scheduleType,\n scheduledAt: scheduleType === 'ONE_TIME' ? new Date(scheduledAt).toISOString() : undefined,\n cronExpression: scheduleType === 'CRON' ? cronExpression : undefined,\n interval: scheduleType === 'FIXED_INTERVAL' ? interval : undefined,\n intervalUnit: scheduleType === 'FIXED_INTERVAL' ? intervalUnit : undefined,\n timezone,\n actionId: selectedActionId,\n });\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (onClose as (...a: unknown[]) => unknown)();\n }\n }}\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={onClose}\n />\n <div className=\"relative bg-bg-surface border border-border-default rounded-xl shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {isActionLocked\n ? tr('vibecontrols.calendar.schedule.addActionToCalendar', 'Add Action to Calendar')\n : tr(\n 'vibecontrols.calendar.schedule.scheduleActionOnCalendar',\n 'Schedule Action on Calendar'\n )}\n </h2>\n <button type=\"button\" onClick={onClose} className=\"p-1 rounded hover:bg-bg-surface\">\n <X size={18} />\n </button>\n </div>\n\n {/* Form */}\n <form onSubmit={handleSubmit} className=\"px-6 py-4 space-y-4\">\n {/* Action Picker — always required */}\n <div className=\"space-y-2\">\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.actionToSchedule', 'Action to Schedule')} *\n </label>\n <p className=\"text-xs text-text-tertiary -mt-1\">\n Calendar entries trigger VibeControls Actions. Agent, command, and webhook details\n come from the Action definition.\n </p>\n\n {isActionLocked && selectedAction && (\n <div className=\"flex items-start gap-3 p-3 rounded-lg border border-border-default bg-bg-surface\">\n <div className=\"p-1.5 rounded-md bg-primary/10 text-primary flex-shrink-0\">\n <Zap size={16} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {selectedAction.displayName || selectedAction.name}\n </p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {selectedAction.actionType} · {selectedAction.triggerType}\n </p>\n {selectedAction.description && (\n <p className=\"text-xs text-text-tertiary mt-1 line-clamp-2\">\n {selectedAction.description}\n </p>\n )}\n </div>\n </div>\n )}\n\n {isActionLocked && !selectedAction && actionsLoading && (\n <div className=\"p-3 rounded-lg border border-border-default bg-bg-surface text-xs text-text-secondary\">\n Loading action…\n </div>\n )}\n\n {isActionLocked && !selectedAction && !actionsLoading && (\n <div className=\"p-3 rounded-lg border border-status-error-border bg-status-error-bg-subtle text-xs text-status-error-text\">\n Action not found. It may have been deleted.\n </div>\n )}\n\n {!isActionLocked && (\n <>\n <div className=\"relative\">\n <Search\n size={16}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-tertiary\"\n />\n <input\n aria-label=\"Search actions by name…\"\n type=\"text\"\n value={actionSearch}\n onChange={(e) => setActionSearch(e.target.value)}\n placeholder=\"Search actions by name…\"\n className={`${INPUT_CLASS} pl-9`}\n />\n </div>\n\n <div className=\"max-h-40 overflow-y-auto border border-border-default rounded-lg divide-y divide-border-default\">\n {actionsLoading && allActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n Loading actions…\n </div>\n )}\n {!actionsLoading && allActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n No actions yet. Create an Action in VibeControls first, then come back to\n schedule it.\n </div>\n )}\n {!actionsLoading && allActions.length > 0 && filteredActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n No actions match \"{actionSearch}\".\n </div>\n )}\n {filteredActions.map((action: ActionPickItem) => {\n const isSelected = action.id === selectedActionId;\n return (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => setSelectedActionId(action.id)}\n className={`w-full text-left px-3 py-2.5 hover:bg-bg-surface transition-colors ${\n isSelected ? 'bg-primary/5' : ''\n }`}\n >\n <div className=\"flex items-start gap-2.5\">\n <div\n className={`p-1 rounded-md flex-shrink-0 ${\n isSelected\n ? 'bg-primary/10 text-primary'\n : 'bg-bg-sunken text-text-tertiary'\n }`}\n >\n <Zap size={14} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {action.displayName || action.name}\n </p>\n <p className=\"text-xs text-text-tertiary mt-0.5\">\n {action.actionType} · {action.triggerType}\n </p>\n </div>\n {isSelected && (\n <span className=\"text-xs font-medium text-primary flex-shrink-0\">\n Selected\n </span>\n )}\n </div>\n </button>\n );\n })}\n </div>\n </>\n )}\n\n {/* Tell the user which agent this action runs on, and warn if that\n agent is unhealthy or gone — before the schedule is created. */}\n {selectedAction && <ActionAgentTargetNotice action={selectedAction} />}\n </div>\n\n {/* Title */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.title', 'Title')}\n </label>\n <input\n aria-label=\"e.g. Run test suite\"\n type=\"text\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. Run test suite\"\n className={INPUT_CLASS}\n required\n />\n </div>\n\n {/* Description */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.description', 'Description')}\n </label>\n <input\n aria-label=\"Optional description\"\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Optional description\"\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Schedule Type */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.schedule', 'Schedule')}\n </label>\n <select\n value={scheduleType}\n onChange={(e) => setScheduleType(e.target.value as typeof scheduleType)}\n className={INPUT_CLASS}\n >\n <option value=\"ONE_TIME\">One Time</option>\n <option value=\"CRON\">Cron Expression</option>\n <option value=\"FIXED_INTERVAL\">Fixed Interval</option>\n </select>\n </div>\n\n {/* Schedule-specific fields */}\n {scheduleType === 'ONE_TIME' && (\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.runAt', 'Run At')}\n </label>\n <input\n aria-label=\"control\"\n type=\"datetime-local\"\n value={scheduledAt}\n onChange={(e) => setScheduledAt(e.target.value)}\n className={INPUT_CLASS}\n required\n />\n </div>\n )}\n\n {scheduleType === 'CRON' && (\n <div>\n <label htmlFor=\"scheduletaskmodal-40\" className={LABEL_CLASS}>\n Cron Expression\n </label>\n <input\n id=\"scheduletaskmodal-40\"\n aria-label=\"*/5 * * * * (every 5 minutes)\"\n type=\"text\"\n value={cronExpression}\n onChange={(e) => setCronExpression(e.target.value)}\n placeholder=\"*/5 * * * * (every 5 minutes)\"\n className={MONO_INPUT_CLASS}\n required\n />\n </div>\n )}\n\n {scheduleType === 'FIXED_INTERVAL' && (\n <div className=\"flex gap-2\">\n <div className=\"flex-1\">\n <label htmlFor=\"scheduletaskmodal-39\" className={LABEL_CLASS}>\n Every\n </label>\n <input\n id=\"scheduletaskmodal-39\"\n aria-label=\"control\"\n type=\"number\"\n value={interval}\n onChange={(e) => setInterval(Number(e.target.value))}\n min={1}\n className={INPUT_CLASS}\n required\n />\n </div>\n <div className=\"flex-1\">\n <label htmlFor=\"scheduletaskmodal-38\" className={LABEL_CLASS}>\n Unit\n </label>\n <select\n id=\"scheduletaskmodal-38\"\n value={intervalUnit}\n onChange={(e) => setIntervalUnit(e.target.value)}\n className={INPUT_CLASS}\n >\n <option value=\"seconds\">Seconds</option>\n <option value=\"minutes\">Minutes</option>\n <option value=\"hours\">Hours</option>\n <option value=\"days\">Days</option>\n </select>\n </div>\n </div>\n )}\n\n {/* Timezone */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.timezone', 'Timezone')}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={timezone}\n onChange={(e) => setTimezone(e.target.value)}\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center justify-end gap-3 pt-4 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr('vibecontrols.calendar.schedule.cancel', 'Cancel')}\n </button>\n <button\n type=\"submit\"\n disabled={!canSubmit}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed\"\n title={\n !selectedActionId\n ? tr('vibecontrols.calendar.schedule.selectActionFirst', 'Select an Action first')\n : undefined\n }\n >\n {loading\n ? tr('vibecontrols.calendar.schedule.creating', 'Creating...')\n : tr('vibecontrols.calendar.schedule.scheduleBtn', 'Schedule')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ScheduleTaskModal.js","names":[],"sources":["../../../src/components/vibecalendar/ScheduleTaskModal.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport { X, Zap, Search } from 'lucide-react';\nimport { useListActionsQuery } from '@/generated/wspace-operations';\nimport type { Action } from '@/generated/wspace-types';\nimport { useTr } from '../../shared/hooks/useTr';\nimport { ActionAgentTargetNotice } from '../common/ActionAgentTargetNotice';\n\ntype ActionPickItem = Pick<\n Action,\n | 'id'\n | 'name'\n | 'displayName'\n | 'description'\n | 'actionType'\n | 'triggerType'\n | 'targetAgentId'\n | 'targetPlatformFilter'\n>;\n\ninterface ScheduleTaskModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSubmit: (input: ScheduleTaskInput) => void;\n // Legacy prop kept for compatibility; unused in Action-only mode.\n agents?: Array<{ id: string; name: string }>;\n loading?: boolean;\n // When provided, the picker is locked to this action (user navigated\n // in from \"Add to calendar\" on the Actions page). Otherwise the user\n // picks from a searchable dropdown of their actions.\n prefillActionId?: string;\n}\n\n/**\n * Calendar entries always delegate execution to a VibeControls Action.\n * Agent, command, script, and webhook fields come from the Action\n * definition at execution time — this modal only collects the calendar\n * metadata and the schedule.\n */\nexport interface ScheduleTaskInput {\n calendarId: string;\n title: string;\n description?: string;\n scheduleType: 'ONE_TIME' | 'CRON' | 'RRULE' | 'FIXED_INTERVAL';\n scheduledAt?: string;\n cronExpression?: string;\n rrule?: string;\n interval?: number;\n intervalUnit?: string;\n timezone: string;\n actionId: string;\n}\n\nconst INPUT_CLASS =\n 'w-full px-3 py-2 bg-bg-sunken border border-border-default rounded-lg text-sm text-text-primary placeholder-text-placeholder focus:outline-none focus:border-border-default';\nconst MONO_INPUT_CLASS = `${INPUT_CLASS} font-mono`;\nconst LABEL_CLASS = 'block text-sm font-medium text-text-secondary mb-1';\n\nexport function ScheduleTaskModal({\n isOpen,\n onClose,\n onSubmit,\n loading,\n prefillActionId,\n}: ScheduleTaskModalProps) {\n const tr = useTr();\n const [selectedActionId, setSelectedActionId] = useState<string>(prefillActionId ?? '');\n const [actionSearch, setActionSearch] = useState('');\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState('');\n const [scheduleType, setScheduleType] = useState<\n 'ONE_TIME' | 'CRON' | 'RRULE' | 'FIXED_INTERVAL'\n >('ONE_TIME');\n const [scheduledAt, setScheduledAt] = useState('');\n const [cronExpression, setCronExpression] = useState('');\n const [interval, setInterval] = useState(60);\n const [intervalUnit, setIntervalUnit] = useState('minutes');\n const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone);\n\n const { data: actionsData, loading: actionsLoading } = useListActionsQuery({\n variables: { pagination: { limit: 100 } },\n skip: !isOpen,\n fetchPolicy: 'cache-and-network',\n });\n\n const allActions = useMemo<ActionPickItem[]>(\n () => (actionsData?.actions?.items ?? []) as ActionPickItem[],\n [actionsData?.actions?.items]\n );\n\n const filteredActions = useMemo(() => {\n if (!actionSearch.trim()) return allActions;\n const q = actionSearch.trim().toLowerCase();\n return allActions.filter(\n (a: ActionPickItem) =>\n a.name?.toLowerCase().includes(q) ||\n a.displayName?.toLowerCase().includes(q) ||\n a.description?.toLowerCase().includes(q)\n );\n }, [allActions, actionSearch]);\n\n const selectedAction = useMemo(\n () => allActions.find((a: ActionPickItem) => a.id === selectedActionId),\n [allActions, selectedActionId]\n );\n\n if (!isOpen) return null;\n\n const isActionLocked = Boolean(prefillActionId);\n const canSubmit = Boolean(selectedActionId) && !loading;\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!selectedActionId) return;\n onSubmit({\n calendarId: '',\n title,\n description: description || undefined,\n scheduleType,\n scheduledAt: scheduleType === 'ONE_TIME' ? new Date(scheduledAt).toISOString() : undefined,\n cronExpression: scheduleType === 'CRON' ? cronExpression : undefined,\n interval: scheduleType === 'FIXED_INTERVAL' ? interval : undefined,\n intervalUnit: scheduleType === 'FIXED_INTERVAL' ? intervalUnit : undefined,\n timezone,\n actionId: selectedActionId,\n });\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n (onClose as (...a: unknown[]) => unknown)();\n }\n }}\n className=\"absolute inset-0 bg-bg-overlay\"\n onClick={onClose}\n />\n <div className=\"relative bg-bg-surface border border-border-default rounded-xl shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {isActionLocked\n ? tr('vibecontrols.calendar.schedule.addActionToCalendar', 'Add Action to Calendar')\n : tr(\n 'vibecontrols.calendar.schedule.scheduleActionOnCalendar',\n 'Schedule Action on Calendar'\n )}\n </h2>\n <button type=\"button\" onClick={onClose} className=\"p-1 rounded hover:bg-bg-surface\">\n <X size={18} />\n </button>\n </div>\n\n {/* Form */}\n <form onSubmit={handleSubmit} className=\"px-6 py-4 space-y-4\">\n {/* Action Picker — always required */}\n <div className=\"space-y-2\">\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.actionToSchedule', 'Action to Schedule')} *\n </label>\n <p className=\"text-xs text-text-tertiary -mt-1\">\n Calendar entries trigger VibeControls Actions. Agent, command, and webhook details\n come from the Action definition.\n </p>\n\n {isActionLocked && selectedAction && (\n <div className=\"flex items-start gap-3 p-3 rounded-lg border border-border-default bg-bg-surface\">\n <div className=\"p-1.5 rounded-md bg-action-primary-bg/10 text-primary flex-shrink-0\">\n <Zap size={16} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary\">\n {selectedAction.displayName || selectedAction.name}\n </p>\n <p className=\"text-xs text-text-secondary mt-0.5\">\n {selectedAction.actionType} · {selectedAction.triggerType}\n </p>\n {selectedAction.description && (\n <p className=\"text-xs text-text-tertiary mt-1 line-clamp-2\">\n {selectedAction.description}\n </p>\n )}\n </div>\n </div>\n )}\n\n {isActionLocked && !selectedAction && actionsLoading && (\n <div className=\"p-3 rounded-lg border border-border-default bg-bg-surface text-xs text-text-secondary\">\n Loading action…\n </div>\n )}\n\n {isActionLocked && !selectedAction && !actionsLoading && (\n <div className=\"p-3 rounded-lg border border-status-error-border bg-status-error-bg-subtle text-xs text-status-error-text\">\n Action not found. It may have been deleted.\n </div>\n )}\n\n {!isActionLocked && (\n <>\n <div className=\"relative\">\n <Search\n size={16}\n className=\"absolute left-3 top-1/2 -translate-y-1/2 text-text-tertiary\"\n />\n <input\n aria-label=\"Search actions by name…\"\n type=\"text\"\n value={actionSearch}\n onChange={(e) => setActionSearch(e.target.value)}\n placeholder=\"Search actions by name…\"\n className={`${INPUT_CLASS} pl-9`}\n />\n </div>\n\n <div className=\"max-h-40 overflow-y-auto border border-border-default rounded-lg divide-y divide-border-default\">\n {actionsLoading && allActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n Loading actions…\n </div>\n )}\n {!actionsLoading && allActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n No actions yet. Create an Action in VibeControls first, then come back to\n schedule it.\n </div>\n )}\n {!actionsLoading && allActions.length > 0 && filteredActions.length === 0 && (\n <div className=\"px-3 py-4 text-xs text-text-secondary text-center\">\n No actions match \"{actionSearch}\".\n </div>\n )}\n {filteredActions.map((action: ActionPickItem) => {\n const isSelected = action.id === selectedActionId;\n return (\n <button\n key={action.id}\n type=\"button\"\n onClick={() => setSelectedActionId(action.id)}\n className={`w-full text-left px-3 py-2.5 hover:bg-bg-surface transition-colors ${\n isSelected ? 'bg-action-primary-bg/5' : ''\n }`}\n >\n <div className=\"flex items-start gap-2.5\">\n <div\n className={`p-1 rounded-md flex-shrink-0 ${\n isSelected\n ? 'bg-action-primary-bg/10 text-primary'\n : 'bg-bg-sunken text-text-tertiary'\n }`}\n >\n <Zap size={14} />\n </div>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-text-primary truncate\">\n {action.displayName || action.name}\n </p>\n <p className=\"text-xs text-text-tertiary mt-0.5\">\n {action.actionType} · {action.triggerType}\n </p>\n </div>\n {isSelected && (\n <span className=\"text-xs font-medium text-primary flex-shrink-0\">\n Selected\n </span>\n )}\n </div>\n </button>\n );\n })}\n </div>\n </>\n )}\n\n {/* Tell the user which agent this action runs on, and warn if that\n agent is unhealthy or gone — before the schedule is created. */}\n {selectedAction && <ActionAgentTargetNotice action={selectedAction} />}\n </div>\n\n {/* Title */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.title', 'Title')}\n </label>\n <input\n aria-label=\"e.g. Run test suite\"\n type=\"text\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. Run test suite\"\n className={INPUT_CLASS}\n required\n />\n </div>\n\n {/* Description */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.description', 'Description')}\n </label>\n <input\n aria-label=\"Optional description\"\n type=\"text\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Optional description\"\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Schedule Type */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.schedule', 'Schedule')}\n </label>\n <select\n value={scheduleType}\n onChange={(e) => setScheduleType(e.target.value as typeof scheduleType)}\n className={INPUT_CLASS}\n >\n <option value=\"ONE_TIME\">One Time</option>\n <option value=\"CRON\">Cron Expression</option>\n <option value=\"FIXED_INTERVAL\">Fixed Interval</option>\n </select>\n </div>\n\n {/* Schedule-specific fields */}\n {scheduleType === 'ONE_TIME' && (\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.runAt', 'Run At')}\n </label>\n <input\n aria-label=\"control\"\n type=\"datetime-local\"\n value={scheduledAt}\n onChange={(e) => setScheduledAt(e.target.value)}\n className={INPUT_CLASS}\n required\n />\n </div>\n )}\n\n {scheduleType === 'CRON' && (\n <div>\n <label htmlFor=\"scheduletaskmodal-40\" className={LABEL_CLASS}>\n Cron Expression\n </label>\n <input\n id=\"scheduletaskmodal-40\"\n aria-label=\"*/5 * * * * (every 5 minutes)\"\n type=\"text\"\n value={cronExpression}\n onChange={(e) => setCronExpression(e.target.value)}\n placeholder=\"*/5 * * * * (every 5 minutes)\"\n className={MONO_INPUT_CLASS}\n required\n />\n </div>\n )}\n\n {scheduleType === 'FIXED_INTERVAL' && (\n <div className=\"flex gap-2\">\n <div className=\"flex-1\">\n <label htmlFor=\"scheduletaskmodal-39\" className={LABEL_CLASS}>\n Every\n </label>\n <input\n id=\"scheduletaskmodal-39\"\n aria-label=\"control\"\n type=\"number\"\n value={interval}\n onChange={(e) => setInterval(Number(e.target.value))}\n min={1}\n className={INPUT_CLASS}\n required\n />\n </div>\n <div className=\"flex-1\">\n <label htmlFor=\"scheduletaskmodal-38\" className={LABEL_CLASS}>\n Unit\n </label>\n <select\n id=\"scheduletaskmodal-38\"\n value={intervalUnit}\n onChange={(e) => setIntervalUnit(e.target.value)}\n className={INPUT_CLASS}\n >\n <option value=\"seconds\">Seconds</option>\n <option value=\"minutes\">Minutes</option>\n <option value=\"hours\">Hours</option>\n <option value=\"days\">Days</option>\n </select>\n </div>\n </div>\n )}\n\n {/* Timezone */}\n <div>\n <label className={LABEL_CLASS}>\n {tr('vibecontrols.calendar.schedule.timezone', 'Timezone')}\n </label>\n <input\n aria-label=\"control\"\n type=\"text\"\n value={timezone}\n onChange={(e) => setTimezone(e.target.value)}\n className={INPUT_CLASS}\n />\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center justify-end gap-3 pt-4 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr('vibecontrols.calendar.schedule.cancel', 'Cancel')}\n </button>\n <button\n type=\"submit\"\n disabled={!canSubmit}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-lg hover:opacity-90 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed\"\n title={\n !selectedActionId\n ? tr('vibecontrols.calendar.schedule.selectActionFirst', 'Select an Action first')\n : undefined\n }\n >\n {loading\n ? tr('vibecontrols.calendar.schedule.creating', 'Creating...')\n : tr('vibecontrols.calendar.schedule.scheduleBtn', 'Schedule')}\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -4,14 +4,14 @@ var e = {
4
4
  RUNNING: "bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border/30",
5
5
  COMPLETED: "bg-status-success-bg-subtle text-status-success-text border-status-success-border/30",
6
6
  FAILED: "bg-status-error-bg-subtle text-status-error-text border-status-error-border/30",
7
- PAUSED: "bg-bg-muted/10 text-text-tertiary border-border-subtle/30",
8
- CANCELLED: "bg-bg-muted/10 text-text-tertiary border-border-subtle/30",
9
- DRAFT: "bg-bg-muted/10 text-text-tertiary border-border-subtle/30",
7
+ PAUSED: "bg-bg-sunken/10 text-text-tertiary border-border-subtle/30",
8
+ CANCELLED: "bg-bg-sunken/10 text-text-tertiary border-border-subtle/30",
9
+ DRAFT: "bg-bg-sunken/10 text-text-tertiary border-border-subtle/30",
10
10
  TIMEOUT: "bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border/30",
11
11
  MANUAL: "bg-accent-purple-subtle text-text-primary border-accent-purple/30",
12
12
  SCHEDULE: "bg-status-info-bg-subtle text-status-info-text border-status-info-border/30",
13
- ARCHIVED: "bg-bg-muted/10 text-text-tertiary border-border-subtle/30",
14
- DISABLED: "bg-bg-muted/10 text-text-tertiary border-border-subtle/30"
13
+ ARCHIVED: "bg-bg-sunken/10 text-text-tertiary border-border-subtle/30",
14
+ DISABLED: "bg-bg-sunken/10 text-text-tertiary border-border-subtle/30"
15
15
  };
16
16
  //#endregion
17
17
  export { e as STATUS_COLORS };
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../../../src/components/vibecalendar/types.ts"],"sourcesContent":["export type CalendarViewMode = 'month' | 'week' | 'day' | 'agenda';\n\n// Where a calendar tile's data originally came from. Set by\n// client-side mappers ONLY — never present on the GraphQL response.\n// Page handlers branch on this to pick the matching subgraph for\n// mutations and the matching detail route. Omitted = default\n// `vibeCalendarTask` (rows from wspace-calendar-svc).\nexport type VibeCalendarTaskSource = 'scheduledJob' | 'vibeCalendarTask';\n\nexport interface VibeCalendarTask {\n id: string;\n /**\n * Set by client-side mappers (e.g. `jobToVibeCalendarTask`). Reading\n * code branches on this to pick the correct mutation/route. Omitted\n * for real VibeCalendarTask rows fetched from wspace-calendar-svc —\n * treat `undefined` as `'vibeCalendarTask'`.\n */\n source?: VibeCalendarTaskSource;\n title: string;\n description: string | null;\n calendarId: string;\n calendarEventId: string;\n agentId: string;\n taskConfig: {\n taskType: string;\n command?: string | null;\n script?: string | null;\n interpreter?: string | null;\n cwd?: string | null;\n env?: Record<string, string> | null;\n timeout?: number | null;\n webhookUrl?: string | null;\n webhookMethod?: string | null;\n webhookHeaders?: Record<string, string> | null;\n webhookAuthType?: string | null;\n webhookPayload?: Record<string, unknown> | null;\n };\n cronExpression: string | null;\n rrule: string | null;\n scheduledAt: string | null;\n timezone: string;\n nextExecutionAt: string | null;\n lastExecutedAt: string | null;\n status: string;\n totalExecutions: number;\n consecutiveFailures: number;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface VibeCalendarExecution {\n id: string;\n taskId: string;\n status: string;\n output: string | null;\n exitCode: number | null;\n webhookStatusCode: number | null;\n startedAt: string | null;\n completedAt: string | null;\n error: string | null;\n}\n\nexport interface CalendarOccurrence {\n task: VibeCalendarTask;\n occurrenceAt: string;\n isPast: boolean;\n execution: VibeCalendarExecution | null;\n}\n\nexport const STATUS_COLORS: Record<string, string> = {\n PENDING: 'bg-status-info-bg-subtle text-status-info-text border-status-info-border/30',\n RUNNING: 'bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border/30',\n COMPLETED: 'bg-status-success-bg-subtle text-status-success-text border-status-success-border/30',\n FAILED: 'bg-status-error-bg-subtle text-status-error-text border-status-error-border/30',\n PAUSED: 'bg-bg-muted/10 text-text-tertiary border-border-subtle/30',\n CANCELLED: 'bg-bg-muted/10 text-text-tertiary border-border-subtle/30',\n DRAFT: 'bg-bg-muted/10 text-text-tertiary border-border-subtle/30',\n TIMEOUT: 'bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border/30',\n MANUAL: 'bg-accent-purple-subtle text-text-primary border-accent-purple/30',\n SCHEDULE: 'bg-status-info-bg-subtle text-status-info-text border-status-info-border/30',\n // Scheduler-svc JobStatus exclusives — without these the badge\n // silently falls back to PENDING styling on archived/disabled jobs.\n ARCHIVED: 'bg-bg-muted/10 text-text-tertiary border-border-subtle/30',\n DISABLED: 'bg-bg-muted/10 text-text-tertiary border-border-subtle/30',\n};\n"],"mappings":";AAqEA,IAAa,IAAwC;CACnD,SAAS;CACT,SAAS;CACT,WAAW;CACX,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,OAAO;CACP,SAAS;CACT,QAAQ;CACR,UAAU;CAGV,UAAU;CACV,UAAU;CACX"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../../../src/components/vibecalendar/types.ts"],"sourcesContent":["export type CalendarViewMode = 'month' | 'week' | 'day' | 'agenda';\n\n// Where a calendar tile's data originally came from. Set by\n// client-side mappers ONLY — never present on the GraphQL response.\n// Page handlers branch on this to pick the matching subgraph for\n// mutations and the matching detail route. Omitted = default\n// `vibeCalendarTask` (rows from wspace-calendar-svc).\nexport type VibeCalendarTaskSource = 'scheduledJob' | 'vibeCalendarTask';\n\nexport interface VibeCalendarTask {\n id: string;\n /**\n * Set by client-side mappers (e.g. `jobToVibeCalendarTask`). Reading\n * code branches on this to pick the correct mutation/route. Omitted\n * for real VibeCalendarTask rows fetched from wspace-calendar-svc —\n * treat `undefined` as `'vibeCalendarTask'`.\n */\n source?: VibeCalendarTaskSource;\n title: string;\n description: string | null;\n calendarId: string;\n calendarEventId: string;\n agentId: string;\n taskConfig: {\n taskType: string;\n command?: string | null;\n script?: string | null;\n interpreter?: string | null;\n cwd?: string | null;\n env?: Record<string, string> | null;\n timeout?: number | null;\n webhookUrl?: string | null;\n webhookMethod?: string | null;\n webhookHeaders?: Record<string, string> | null;\n webhookAuthType?: string | null;\n webhookPayload?: Record<string, unknown> | null;\n };\n cronExpression: string | null;\n rrule: string | null;\n scheduledAt: string | null;\n timezone: string;\n nextExecutionAt: string | null;\n lastExecutedAt: string | null;\n status: string;\n totalExecutions: number;\n consecutiveFailures: number;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface VibeCalendarExecution {\n id: string;\n taskId: string;\n status: string;\n output: string | null;\n exitCode: number | null;\n webhookStatusCode: number | null;\n startedAt: string | null;\n completedAt: string | null;\n error: string | null;\n}\n\nexport interface CalendarOccurrence {\n task: VibeCalendarTask;\n occurrenceAt: string;\n isPast: boolean;\n execution: VibeCalendarExecution | null;\n}\n\nexport const STATUS_COLORS: Record<string, string> = {\n PENDING: 'bg-status-info-bg-subtle text-status-info-text border-status-info-border/30',\n RUNNING: 'bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border/30',\n COMPLETED: 'bg-status-success-bg-subtle text-status-success-text border-status-success-border/30',\n FAILED: 'bg-status-error-bg-subtle text-status-error-text border-status-error-border/30',\n PAUSED: 'bg-bg-sunken/10 text-text-tertiary border-border-subtle/30',\n CANCELLED: 'bg-bg-sunken/10 text-text-tertiary border-border-subtle/30',\n DRAFT: 'bg-bg-sunken/10 text-text-tertiary border-border-subtle/30',\n TIMEOUT: 'bg-status-warning-bg-subtle text-status-warning-text border-status-warning-border/30',\n MANUAL: 'bg-accent-purple-subtle text-text-primary border-accent-purple/30',\n SCHEDULE: 'bg-status-info-bg-subtle text-status-info-text border-status-info-border/30',\n // Scheduler-svc JobStatus exclusives — without these the badge\n // silently falls back to PENDING styling on archived/disabled jobs.\n ARCHIVED: 'bg-bg-sunken/10 text-text-tertiary border-border-subtle/30',\n DISABLED: 'bg-bg-sunken/10 text-text-tertiary border-border-subtle/30',\n};\n"],"mappings":";AAqEA,IAAa,IAAwC;CACnD,SAAS;CACT,SAAS;CACT,WAAW;CACX,QAAQ;CACR,QAAQ;CACR,WAAW;CACX,OAAO;CACP,SAAS;CACT,QAAQ;CACR,UAAU;CAGV,UAAU;CACV,UAAU;CACX"}
@@ -60,7 +60,7 @@ function b() {
60
60
  children: j.vibe && /* @__PURE__ */ v("button", {
61
61
  type: "button",
62
62
  onClick: () => C(`/vibes/${j.vibe?.id}`),
63
- className: "inline-flex items-center gap-2 px-3 py-2 rounded-md border border-border-default bg-bg-surface hover:bg-bg-muted text-sm text-text-primary transition-colors",
63
+ className: "inline-flex items-center gap-2 px-3 py-2 rounded-md border border-border-default bg-bg-surface hover:bg-bg-sunken text-sm text-text-primary transition-colors",
64
64
  children: [/* @__PURE__ */ _(d, { className: "size-4" }), x("noteDetails.openVibe", "Open Vibe")]
65
65
  })
66
66
  })
@@ -126,7 +126,7 @@ function b() {
126
126
  }), j.tags.length > 0 ? /* @__PURE__ */ _("div", {
127
127
  className: "flex flex-wrap gap-2",
128
128
  children: j.tags.map((e) => /* @__PURE__ */ v("span", {
129
- className: "inline-flex items-center gap-1 rounded-full bg-bg-muted px-2 py-1 text-xs text-text-secondary",
129
+ className: "inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2 py-1 text-xs text-text-secondary",
130
130
  children: [/* @__PURE__ */ _(m, { className: "size-3" }), e]
131
131
  }, e))
132
132
  }) : /* @__PURE__ */ _("p", {
@@ -1 +1 @@
1
- {"version":3,"file":"NoteDetailsPage.js","names":[],"sources":["../../src/pages/NoteDetailsPage.tsx"],"sourcesContent":["import { useCallback } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { ArrowLeft, ExternalLink, FileText, Pin, Tag } from 'lucide-react';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Card, EmptyState, ErrorState, PageHeader } from '@/components/shared';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useGetNoteQuery } from '@/generated/wspace-operations';\nimport { useParams } from 'react-router-dom';\n\nexport function NoteDetailsPage() {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n const { id } = useParams<{ id: string }>();\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n\n const canReadNote = hasPermission(VIBE_PERMISSIONS.NOTE_READ);\n const { data, loading, error, refetch } = useGetNoteQuery({\n variables: { id: id || '' },\n skip: !id || permissionsLoading || !canReadNote,\n fetchPolicy: 'cache-and-network',\n });\n\n const note = data?.note;\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">\n {tr('noteDetails.loadingPermissions', 'Loading permissions...')}\n </p>\n </div>\n );\n if (!canReadNote)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('noteDetails.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr('noteDetails.accessDeniedDesc', \"You don't have permission to access this page.\")}\n </p>\n </div>\n </div>\n );\n\n if (loading && !note) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={() => navigate('/vibes')}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('noteDetails.back', 'Back')}\n </button>\n <PageSkeleton variant=\"detail\" />\n </MotionPage>\n );\n }\n\n if (error && !note) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={() => navigate('/vibes')}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n Back\n </button>\n <ErrorState\n title={tr('noteDetails.failedLoad', 'Failed to load note')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n if (!note) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={() => navigate('/vibes')}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n Back\n </button>\n <EmptyState\n icon={<FileText className=\"size-8 text-text-secondary\" />}\n title={tr('noteDetails.notFound', 'Note not found')}\n description={tr(\n 'noteDetails.notFoundDesc',\n 'This note may have been deleted or you may no longer have access to it.'\n )}\n />\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <PageHeader\n title={note.title}\n description={\n note.vibe\n ? `${tr('noteDetails.attachedTo', 'Attached to')} ${note.vibe.name}`\n : tr('noteDetails.workspaceNote', 'Workspace note')\n }\n actions={\n <div className=\"flex items-center gap-2\">\n {note.vibe && (\n <button\n type=\"button\"\n onClick={() => navigate(`/vibes/${note.vibe?.id}`)}\n className=\"inline-flex items-center gap-2 px-3 py-2 rounded-md border border-border-default bg-bg-surface hover:bg-bg-muted text-sm text-text-primary transition-colors\"\n >\n <ExternalLink className=\"size-4\" />\n {tr('noteDetails.openVibe', 'Open Vibe')}\n </button>\n )}\n </div>\n }\n />\n\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_320px]\">\n <Card>\n <div className=\"p-5 space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-text-tertiary\">\n {note.isPinned && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-primary-default/10 px-2 py-1 text-primary-default\">\n <Pin className=\"size-3.5\" />\n {tr('noteDetails.pinned', 'Pinned')}\n </span>\n )}\n <span>\n {tr('noteDetails.created', 'Created')} {new Date(note.createdAt).toLocaleString()}\n </span>\n <span>\n {tr('noteDetails.updated', 'Updated')} {new Date(note.updatedAt).toLocaleString()}\n </span>\n </div>\n\n <div className=\"rounded-lg border border-border-default bg-bg-canvas p-4\">\n <pre className=\"whitespace-pre-wrap break-words text-sm text-text-primary font-sans leading-6\">\n {note.content}\n </pre>\n </div>\n </div>\n </Card>\n\n <div className=\"space-y-6\">\n <Card>\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-sm font-semibold text-text-primary\">\n {tr('noteDetails.details', 'Details')}\n </h2>\n <div className=\"space-y-3 text-sm\">\n <div>\n <div className=\"text-text-tertiary\">{tr('noteDetails.noteId', 'Note ID')}</div>\n <div className=\"font-mono text-text-primary break-all\">{note.id}</div>\n </div>\n {note.vibe && (\n <div>\n <div className=\"text-text-tertiary\">{tr('noteDetails.vibe', 'Vibe')}</div>\n <button\n type=\"button\"\n onClick={() => navigate(`/vibes/${note.vibe?.id}`)}\n className=\"text-primary-default hover:underline\"\n >\n {note.vibe.name}\n </button>\n </div>\n )}\n </div>\n </div>\n </Card>\n\n <Card>\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-sm font-semibold text-text-primary\">\n {tr('noteDetails.tags', 'Tags')}\n </h2>\n {note.tags.length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {note.tags.map((tag: string) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 rounded-full bg-bg-muted px-2 py-1 text-xs text-text-secondary\"\n >\n <Tag className=\"size-3\" />\n {tag}\n </span>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-tertiary\">\n {tr('noteDetails.noTags', 'No tags assigned.')}\n </p>\n )}\n </div>\n </Card>\n </div>\n </div>\n </MotionPage>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"NoteDetailsPage.js","names":[],"sources":["../../src/pages/NoteDetailsPage.tsx"],"sourcesContent":["import { useCallback } from 'react';\nimport { usePermissions } from '@burdenoff/fe-libs/shared/providers/shell';\nimport { VIBE_PERMISSIONS } from '../constants/permissions';\nimport { ArrowLeft, ExternalLink, FileText, Pin, Tag } from 'lucide-react';\nimport { MotionPage } from '@burdenoff/fe-libs/shared/motion';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Card, EmptyState, ErrorState, PageHeader } from '@/components/shared';\nimport { PageSkeleton } from '@/components/shared/PageSkeleton';\nimport { useVibeNavigate } from '@/providers/VibeControlsProvider';\nimport { useGetNoteQuery } from '@/generated/wspace-operations';\nimport { useParams } from 'react-router-dom';\n\nexport function NoteDetailsPage() {\n const { t } = useI18n();\n const tr = useCallback(\n (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n },\n [t]\n );\n const { id } = useParams<{ id: string }>();\n const navigate = useVibeNavigate();\n const { hasPermission, isLoading: permissionsLoading } = usePermissions();\n\n const canReadNote = hasPermission(VIBE_PERMISSIONS.NOTE_READ);\n const { data, loading, error, refetch } = useGetNoteQuery({\n variables: { id: id || '' },\n skip: !id || permissionsLoading || !canReadNote,\n fetchPolicy: 'cache-and-network',\n });\n\n const note = data?.note;\n\n if (permissionsLoading)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <p className=\"text-text-secondary\">\n {tr('noteDetails.loadingPermissions', 'Loading permissions...')}\n </p>\n </div>\n );\n if (!canReadNote)\n return (\n <div className=\"flex items-center justify-center min-h-[400px]\">\n <div className=\"text-center space-y-2\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('noteDetails.accessDenied', 'Access Denied')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr('noteDetails.accessDeniedDesc', \"You don't have permission to access this page.\")}\n </p>\n </div>\n </div>\n );\n\n if (loading && !note) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={() => navigate('/vibes')}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n {tr('noteDetails.back', 'Back')}\n </button>\n <PageSkeleton variant=\"detail\" />\n </MotionPage>\n );\n }\n\n if (error && !note) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={() => navigate('/vibes')}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n Back\n </button>\n <ErrorState\n title={tr('noteDetails.failedLoad', 'Failed to load note')}\n message={error.message}\n onRetry={() => refetch()}\n />\n </MotionPage>\n );\n }\n\n if (!note) {\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <button\n type=\"button\"\n onClick={() => navigate('/vibes')}\n className=\"flex items-center gap-2 text-text-secondary hover:text-text-primary transition-colors\"\n >\n <ArrowLeft className=\"size-4\" />\n Back\n </button>\n <EmptyState\n icon={<FileText className=\"size-8 text-text-secondary\" />}\n title={tr('noteDetails.notFound', 'Note not found')}\n description={tr(\n 'noteDetails.notFoundDesc',\n 'This note may have been deleted or you may no longer have access to it.'\n )}\n />\n </MotionPage>\n );\n }\n\n return (\n <MotionPage className=\"space-y-6 px-6 lg:px-8 py-6 bg-bg-canvas min-h-screen\">\n <PageHeader\n title={note.title}\n description={\n note.vibe\n ? `${tr('noteDetails.attachedTo', 'Attached to')} ${note.vibe.name}`\n : tr('noteDetails.workspaceNote', 'Workspace note')\n }\n actions={\n <div className=\"flex items-center gap-2\">\n {note.vibe && (\n <button\n type=\"button\"\n onClick={() => navigate(`/vibes/${note.vibe?.id}`)}\n className=\"inline-flex items-center gap-2 px-3 py-2 rounded-md border border-border-default bg-bg-surface hover:bg-bg-sunken text-sm text-text-primary transition-colors\"\n >\n <ExternalLink className=\"size-4\" />\n {tr('noteDetails.openVibe', 'Open Vibe')}\n </button>\n )}\n </div>\n }\n />\n\n <div className=\"grid gap-6 lg:grid-cols-[minmax(0,1fr)_320px]\">\n <Card>\n <div className=\"p-5 space-y-4\">\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-text-tertiary\">\n {note.isPinned && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-primary-default/10 px-2 py-1 text-primary-default\">\n <Pin className=\"size-3.5\" />\n {tr('noteDetails.pinned', 'Pinned')}\n </span>\n )}\n <span>\n {tr('noteDetails.created', 'Created')} {new Date(note.createdAt).toLocaleString()}\n </span>\n <span>\n {tr('noteDetails.updated', 'Updated')} {new Date(note.updatedAt).toLocaleString()}\n </span>\n </div>\n\n <div className=\"rounded-lg border border-border-default bg-bg-canvas p-4\">\n <pre className=\"whitespace-pre-wrap break-words text-sm text-text-primary font-sans leading-6\">\n {note.content}\n </pre>\n </div>\n </div>\n </Card>\n\n <div className=\"space-y-6\">\n <Card>\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-sm font-semibold text-text-primary\">\n {tr('noteDetails.details', 'Details')}\n </h2>\n <div className=\"space-y-3 text-sm\">\n <div>\n <div className=\"text-text-tertiary\">{tr('noteDetails.noteId', 'Note ID')}</div>\n <div className=\"font-mono text-text-primary break-all\">{note.id}</div>\n </div>\n {note.vibe && (\n <div>\n <div className=\"text-text-tertiary\">{tr('noteDetails.vibe', 'Vibe')}</div>\n <button\n type=\"button\"\n onClick={() => navigate(`/vibes/${note.vibe?.id}`)}\n className=\"text-primary-default hover:underline\"\n >\n {note.vibe.name}\n </button>\n </div>\n )}\n </div>\n </div>\n </Card>\n\n <Card>\n <div className=\"p-5 space-y-4\">\n <h2 className=\"text-sm font-semibold text-text-primary\">\n {tr('noteDetails.tags', 'Tags')}\n </h2>\n {note.tags.length > 0 ? (\n <div className=\"flex flex-wrap gap-2\">\n {note.tags.map((tag: string) => (\n <span\n key={tag}\n className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2 py-1 text-xs text-text-secondary\"\n >\n <Tag className=\"size-3\" />\n {tag}\n </span>\n ))}\n </div>\n ) : (\n <p className=\"text-sm text-text-tertiary\">\n {tr('noteDetails.noTags', 'No tags assigned.')}\n </p>\n )}\n </div>\n </Card>\n </div>\n </div>\n </MotionPage>\n );\n}\n"],"mappings":"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"}
@@ -895,7 +895,7 @@ function S() {
895
895
  type: "button",
896
896
  onClick: un,
897
897
  disabled: z,
898
- className: "mt-4 px-4 py-2 bg-bg-muted text-text-primary text-sm rounded-md hover:bg-bg-sunken transition-colors disabled:opacity-50",
898
+ className: "mt-4 px-4 py-2 bg-bg-sunken text-text-primary text-sm rounded-md hover:bg-bg-sunken transition-colors disabled:opacity-50",
899
899
  children: z ? C("sessionDetails.opening", "Opening...") : C("sessionDetails.openTerminal", "Open Terminal")
900
900
  })
901
901
  ]