@mohou/panel 1.0.20

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 (113) hide show
  1. package/README.md +8 -0
  2. package/lib/types/chrome/hue.d.ts +3 -0
  3. package/lib/types/chrome/hue.d.ts.map +1 -0
  4. package/lib/types/gallery/card-style.d.ts +8 -0
  5. package/lib/types/gallery/card-style.d.ts.map +1 -0
  6. package/lib/types/gallery/client.d.ts +20 -0
  7. package/lib/types/gallery/client.d.ts.map +1 -0
  8. package/lib/types/gallery/desk.d.ts +16 -0
  9. package/lib/types/gallery/desk.d.ts.map +1 -0
  10. package/lib/types/gallery/list.d.ts +37 -0
  11. package/lib/types/gallery/list.d.ts.map +1 -0
  12. package/lib/types/gallery/sort.d.ts +24 -0
  13. package/lib/types/gallery/sort.d.ts.map +1 -0
  14. package/lib/types/gallery/state.d.ts +90 -0
  15. package/lib/types/gallery/state.d.ts.map +1 -0
  16. package/lib/types/gallery/tabs.d.ts +45 -0
  17. package/lib/types/gallery/tabs.d.ts.map +1 -0
  18. package/lib/types/gallery/view.d.ts +57 -0
  19. package/lib/types/gallery/view.d.ts.map +1 -0
  20. package/lib/types/history/client.d.ts +25 -0
  21. package/lib/types/history/client.d.ts.map +1 -0
  22. package/lib/types/history/state.d.ts +39 -0
  23. package/lib/types/history/state.d.ts.map +1 -0
  24. package/lib/types/history/view.d.ts +15 -0
  25. package/lib/types/history/view.d.ts.map +1 -0
  26. package/lib/types/index.d.ts +24 -0
  27. package/lib/types/index.d.ts.map +1 -0
  28. package/lib/types/labels.d.ts +267 -0
  29. package/lib/types/labels.d.ts.map +1 -0
  30. package/lib/types/settings/author-mcp-view.d.ts +15 -0
  31. package/lib/types/settings/author-mcp-view.d.ts.map +1 -0
  32. package/lib/types/settings/author-mcp.d.ts +4 -0
  33. package/lib/types/settings/author-mcp.d.ts.map +1 -0
  34. package/lib/types/settings/client.d.ts +198 -0
  35. package/lib/types/settings/client.d.ts.map +1 -0
  36. package/lib/types/settings/credentials-view.d.ts +15 -0
  37. package/lib/types/settings/credentials-view.d.ts.map +1 -0
  38. package/lib/types/settings/form.d.ts +27 -0
  39. package/lib/types/settings/form.d.ts.map +1 -0
  40. package/lib/types/settings/install-row.d.ts +10 -0
  41. package/lib/types/settings/install-row.d.ts.map +1 -0
  42. package/lib/types/settings/mcp-view.d.ts +14 -0
  43. package/lib/types/settings/mcp-view.d.ts.map +1 -0
  44. package/lib/types/settings/skill-dirs.d.ts +6 -0
  45. package/lib/types/settings/skill-dirs.d.ts.map +1 -0
  46. package/lib/types/settings/skill-install.d.ts +13 -0
  47. package/lib/types/settings/skill-install.d.ts.map +1 -0
  48. package/lib/types/settings/state.d.ts +94 -0
  49. package/lib/types/settings/state.d.ts.map +1 -0
  50. package/lib/types/settings/update-dialog.d.ts +56 -0
  51. package/lib/types/settings/update-dialog.d.ts.map +1 -0
  52. package/lib/types/settings/view.d.ts +26 -0
  53. package/lib/types/settings/view.d.ts.map +1 -0
  54. package/lib/types/storage/client.d.ts +15 -0
  55. package/lib/types/storage/client.d.ts.map +1 -0
  56. package/lib/types/storage/state.d.ts +42 -0
  57. package/lib/types/storage/state.d.ts.map +1 -0
  58. package/lib/types/storage/view.d.ts +16 -0
  59. package/lib/types/storage/view.d.ts.map +1 -0
  60. package/lib/types/surface/state.d.ts +42 -0
  61. package/lib/types/surface/state.d.ts.map +1 -0
  62. package/lib/types/surface/view.d.ts +34 -0
  63. package/lib/types/surface/view.d.ts.map +1 -0
  64. package/lib/types/theme/client.d.ts +45 -0
  65. package/lib/types/theme/client.d.ts.map +1 -0
  66. package/lib/types/theme/menu.d.ts +25 -0
  67. package/lib/types/theme/menu.d.ts.map +1 -0
  68. package/lib/types/theme/state.d.ts +46 -0
  69. package/lib/types/theme/state.d.ts.map +1 -0
  70. package/lib/types/theme/view.d.ts +16 -0
  71. package/lib/types/theme/view.d.ts.map +1 -0
  72. package/lib/types/ui/dialog.d.ts +12 -0
  73. package/lib/types/ui/dialog.d.ts.map +1 -0
  74. package/lib/types/ui/tooltip.d.ts +12 -0
  75. package/lib/types/ui/tooltip.d.ts.map +1 -0
  76. package/package.json +38 -0
  77. package/src/chrome/hue.ts +6 -0
  78. package/src/gallery/card-style.ts +27 -0
  79. package/src/gallery/client.ts +26 -0
  80. package/src/gallery/desk.tsx +54 -0
  81. package/src/gallery/list.ts +54 -0
  82. package/src/gallery/sort.ts +72 -0
  83. package/src/gallery/state.ts +229 -0
  84. package/src/gallery/tabs.ts +85 -0
  85. package/src/gallery/view.tsx +501 -0
  86. package/src/history/client.ts +27 -0
  87. package/src/history/state.ts +90 -0
  88. package/src/history/view.tsx +131 -0
  89. package/src/index.ts +61 -0
  90. package/src/labels.ts +536 -0
  91. package/src/settings/author-mcp-view.tsx +154 -0
  92. package/src/settings/author-mcp.ts +24 -0
  93. package/src/settings/client.ts +205 -0
  94. package/src/settings/credentials-view.tsx +195 -0
  95. package/src/settings/form.ts +27 -0
  96. package/src/settings/install-row.tsx +35 -0
  97. package/src/settings/mcp-view.tsx +793 -0
  98. package/src/settings/skill-dirs.ts +41 -0
  99. package/src/settings/skill-install.tsx +134 -0
  100. package/src/settings/state.ts +225 -0
  101. package/src/settings/update-dialog.tsx +207 -0
  102. package/src/settings/view.tsx +722 -0
  103. package/src/storage/client.ts +16 -0
  104. package/src/storage/state.ts +94 -0
  105. package/src/storage/view.tsx +190 -0
  106. package/src/surface/state.ts +72 -0
  107. package/src/surface/view.tsx +255 -0
  108. package/src/theme/client.ts +34 -0
  109. package/src/theme/menu.tsx +286 -0
  110. package/src/theme/state.ts +113 -0
  111. package/src/theme/view.tsx +73 -0
  112. package/src/ui/dialog.tsx +25 -0
  113. package/src/ui/tooltip.tsx +19 -0
@@ -0,0 +1,131 @@
1
+ import { useEffect, useReducer, type ReactNode } from 'react'
2
+
3
+ import { panelText, type PanelLabelMode, type PanelLocale } from '../labels.ts'
4
+ import type { HistoryClient, HistoryCommit, HistoryFile } from './client.ts'
5
+ import { Tooltip } from '../ui/tooltip.tsx'
6
+ import { historyState, loadCommit, loadHistory, reduceHistory } from './state.ts'
7
+
8
+ /**
9
+ * Read-only history. Hidden when Host exposes no history client. No route string lives here.
10
+ * @param props - client, app, chrome locale, and the pane close control
11
+ */
12
+ export function PanelHistory(props: {
13
+ readonly client?: HistoryClient
14
+ readonly appId: string
15
+ readonly locale: PanelLocale
16
+ readonly mode: PanelLabelMode
17
+ readonly onClose?: () => void
18
+ }): ReactNode {
19
+ const [state, dispatch] = useReducer(reduceHistory, undefined, historyState)
20
+ useEffect(() => {
21
+ if (props.client === undefined) return
22
+ void loadHistory(props.client, props.appId, dispatch)
23
+ }, [props.client, props.appId])
24
+ if (props.client === undefined) return null
25
+ const label = (key: string) => panelText(props.locale, key, props.mode)
26
+ const client = props.client
27
+ return (
28
+ <section className="flex min-h-0 flex-1 flex-col bg-background text-foreground">
29
+ <header className="flex items-center justify-between gap-3 border-b bg-card px-4 py-3">
30
+ <h3 className="text-[15px] font-semibold">{label('history')}</h3>
31
+ <PaneClose label={label('pane-close')} onClose={props.onClose} />
32
+ </header>
33
+ <div className="grid min-h-0 flex-1 grid-cols-1 min-[720px]:grid-cols-[17rem_minmax(0,1fr)]">
34
+ <div className="min-h-0 overflow-auto border-b p-3 min-[720px]:border-r min-[720px]:border-b-0">
35
+ {state.failed ? <p className="text-sm text-destructive">{state.error !== undefined && state.error.length > 0 ? state.error : label('history-failed')}</p> : null}
36
+ {!state.failed && state.commits.length === 0 ? <p className="text-sm text-muted-foreground">{label('history-empty')}</p> : null}
37
+ <ul className="flex flex-col gap-2">
38
+ {state.commits.map(commit => (
39
+ <li key={commit.id}>
40
+ <CommitRow
41
+ commit={commit}
42
+ pressed={state.selected === commit.id}
43
+ onSelect={() => { void loadCommit(client, props.appId, commit.id, dispatch) }}
44
+ />
45
+ </li>
46
+ ))}
47
+ </ul>
48
+ </div>
49
+ <div className="min-h-0 overflow-auto p-4">
50
+ {state.detailFailed ? <p className="text-sm text-destructive">{state.detailError !== undefined && state.detailError.length > 0 ? state.detailError : label('history-failed')}</p> : null}
51
+ {state.detail === undefined ? <p className="text-sm text-muted-foreground">{label('history-pick')}</p> : (
52
+ <div className="flex flex-col gap-3">
53
+ <div>
54
+ <h4 className="text-sm font-semibold">{state.detail.message}</h4>
55
+ <p className="mt-1 font-mono text-[11px] text-muted-foreground">{state.selected}</p>
56
+ <time className="mt-1 block text-[11px] text-muted-foreground">{clock(state.detail.time)}</time>
57
+ </div>
58
+ {state.detail.files.map(file => (
59
+ <FilePreview key={file.path} file={file} />
60
+ ))}
61
+ </div>
62
+ )}
63
+ </div>
64
+ </div>
65
+ </section>
66
+ )
67
+ }
68
+
69
+ function CommitRow(props: {
70
+ readonly commit: HistoryCommit
71
+ readonly pressed: boolean
72
+ readonly onSelect: () => void
73
+ }): ReactNode {
74
+ return (
75
+ <Tooltip text={props.commit.id} className="w-full">
76
+ <button
77
+ type="button"
78
+ className="w-full rounded-xl border bg-card px-3 py-2.5 text-left data-[on=1]:border-primary"
79
+ aria-pressed={props.pressed}
80
+ data-on={props.pressed ? '1' : '0'}
81
+ data-commit={props.commit.id}
82
+ onClick={props.onSelect}
83
+ >
84
+ <span className="flex items-baseline justify-between gap-2">
85
+ <span className="min-w-0 truncate text-sm font-semibold">{props.commit.message.length > 0 ? props.commit.message : props.commit.id.slice(0, 7)}</span>
86
+ <time className="shrink-0 text-[11px] text-muted-foreground">{clock(props.commit.time)}</time>
87
+ </span>
88
+ <span className="mt-1 block font-mono text-[11px] text-muted-foreground">{props.commit.id.slice(0, 7)}</span>
89
+ </button>
90
+ </Tooltip>
91
+ )
92
+ }
93
+
94
+ function FilePreview(props: { readonly file: HistoryFile }): ReactNode {
95
+ const lines = props.file.preview.length === 0 ? [] : props.file.preview.split('\n')
96
+ return (
97
+ <article className="overflow-hidden rounded-xl border bg-card">
98
+ <header className="flex items-center justify-between gap-3 border-b px-3 py-2">
99
+ <span className="min-w-0 truncate font-mono text-xs">{props.file.path}</span>
100
+ <span className="shrink-0 font-mono text-[11px] text-muted-foreground">{`+${props.file.add} −${props.file.del}`}</span>
101
+ </header>
102
+ {lines.length === 0 ? null : (
103
+ <pre className="max-h-80 overflow-auto p-3 font-mono text-[12px] leading-5">
104
+ {lines.map((line, index) => (
105
+ <span key={`${props.file.path}:${index}`} className={lineClass(line)}>{line.length === 0 ? ' ' : line}</span>
106
+ ))}
107
+ </pre>
108
+ )}
109
+ </article>
110
+ )
111
+ }
112
+
113
+ function PaneClose(props: { readonly label: string; readonly onClose?: (() => void) | undefined }): ReactNode {
114
+ if (props.onClose === undefined) return null
115
+ return (
116
+ <button type="button" className="h-8 rounded-lg border bg-background px-3 text-sm hover:bg-muted" onClick={props.onClose}>{props.label}</button>
117
+ )
118
+ }
119
+
120
+ function lineClass(line: string): string {
121
+ if (line.startsWith('+')) return 'block text-primary'
122
+ if (line.startsWith('-')) return 'block text-destructive'
123
+ return 'block text-muted-foreground'
124
+ }
125
+
126
+ function clock(iso: string): string {
127
+ const date = new Date(iso)
128
+ if (Number.isNaN(date.getTime())) return iso
129
+ const pad = (value: number) => String(value).padStart(2, '0')
130
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}`
131
+ }
package/src/index.ts ADDED
@@ -0,0 +1,61 @@
1
+ /** Panel chrome labels. Not the app's own strings. @module @mohou/panel */
2
+
3
+ export const packageId = '@mohou/panel' as const
4
+
5
+ export {
6
+ isPanelLocale,
7
+ panelLocales,
8
+ panelText,
9
+ type PanelLabelKey,
10
+ type PanelLabelMode,
11
+ type PanelLocale,
12
+ } from './labels.ts'
13
+ export { admitPanelPort, panelLanguageFields, panelPortBound, type PanelPortResult } from './settings/form.ts'
14
+ export {
15
+ filterGallery,
16
+ galleryCardStyles,
17
+ galleryKind,
18
+ isGalleryCardStyle,
19
+ type GalleryApp,
20
+ type GalleryCardStyle,
21
+ type GalleryKind,
22
+ } from './gallery/list.ts'
23
+ export {
24
+ closeTab,
25
+ deletePrompt,
26
+ initialTabs,
27
+ openAppTab,
28
+ switchTab,
29
+ type AppTab,
30
+ type DeletePrompt,
31
+ type PanelTab,
32
+ type PanelTabs,
33
+ type TabChange,
34
+ } from './gallery/tabs.ts'
35
+ export { PanelClientError, type PanelClient } from './gallery/client.ts'
36
+ export {
37
+ loadGallery,
38
+ loadTrash,
39
+ galleryState,
40
+ reduceGallery,
41
+ viewKind,
42
+ visibleApps,
43
+ type GalleryAction,
44
+ type PanelShell,
45
+ type GalleryState,
46
+ } from './gallery/state.ts'
47
+ export { PanelGallery } from './gallery/view.tsx'
48
+ export { panelUpdateFailureCodes, type McpCheckResult, type McpServerDraft, type PanelAbout, type PanelCredential, type PanelCredentials, type PanelMcpFailure, type PanelMcpList, type PanelAuthorMcpAgent, type PanelAuthorMcpStatus, type PanelPolicy, type PanelPolicyWrite, type PanelProbe, type PanelRuntime, type PanelSettingsClient, type PanelSkillAgent, type PanelSkillStatus, type PanelUpdateAttempt, type PanelUpdateCheck, type PanelUpdateFailureCode } from './settings/client.ts'
49
+ export { loadSettings, reduceSettings, settingsDraft, settingsState, type SettingsAction, type SettingsState } from './settings/state.ts'
50
+ export { PanelSettings } from './settings/view.tsx'
51
+ export type { HistoryClient, HistoryCommit, HistoryDetail, HistoryFile } from './history/client.ts'
52
+ export { historyState, loadCommit, loadHistory, reduceHistory, type HistoryAction, type HistoryState } from './history/state.ts'
53
+ export { PanelHistory } from './history/view.tsx'
54
+ export type { StorageClient, StorageSummary, StorageTable } from './storage/client.ts'
55
+ export { loadStorage, loadTable, reduceStorage, storageState, type StorageAction, type StorageState } from './storage/state.ts'
56
+ export { PanelStorage } from './storage/view.tsx'
57
+ export type { IgnoredPalette, PaletteChip, ThemeClient, ThemePin } from './theme/client.ts'
58
+ export { loadPalettes, reduceTheme, savePin, themeState, type ThemeAction, type ThemeState } from './theme/state.ts'
59
+ export { PanelTheme } from './theme/view.tsx'
60
+ export { reduceSurface, surfaceState, panelSections, type PanelSection, type SurfaceAction, type SurfaceState } from './surface/state.ts'
61
+ export { PanelSurface, type PanelControls } from './surface/view.tsx'