@prmichaelsen/acp-visualizer 0.13.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prmichaelsen/acp-visualizer",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "type": "module",
5
5
  "description": "Browser-based dashboard for visualizing ACP progress.yaml data",
6
6
  "bin": {
@@ -18,13 +18,23 @@ interface SidePanelContextValue {
18
18
  const SidePanelContext = createContext<SidePanelContextValue | undefined>(undefined)
19
19
 
20
20
  const MIN_WIDTH = 300
21
- const MAX_WIDTH = 800
22
21
  const DEFAULT_WIDTH = 500
22
+ const STORAGE_KEY = 'acp-visualizer.side-panel-size'
23
+
24
+ function loadWidth(): number {
25
+ if (typeof window === 'undefined') return DEFAULT_WIDTH
26
+ const stored = localStorage.getItem(STORAGE_KEY)
27
+ if (stored) {
28
+ const parsed = Number(stored)
29
+ if (!isNaN(parsed) && parsed >= MIN_WIDTH) return parsed
30
+ }
31
+ return DEFAULT_WIDTH
32
+ }
23
33
 
24
34
  export function SidePanelProvider({ children }: { children: ReactNode }) {
25
35
  const [content, setContent] = useState<PanelContent>(null)
26
36
  const [isOpen, setIsOpen] = useState(false)
27
- const [width, setWidthState] = useState(DEFAULT_WIDTH)
37
+ const [width, setWidthState] = useState(loadWidth)
28
38
 
29
39
  const openMilestone = (id: string) => {
30
40
  setContent({ type: 'milestone', id })
@@ -42,8 +52,9 @@ export function SidePanelProvider({ children }: { children: ReactNode }) {
42
52
  }
43
53
 
44
54
  const setWidth = (newWidth: number) => {
45
- const clampedWidth = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, newWidth))
46
- setWidthState(clampedWidth)
55
+ const clamped = Math.max(MIN_WIDTH, newWidth)
56
+ setWidthState(clamped)
57
+ localStorage.setItem(STORAGE_KEY, String(clamped))
47
58
  }
48
59
 
49
60
  return (
@@ -217,8 +217,9 @@ function normalizeTasks(raw: unknown, milestones: Milestone[]): Record<string, T
217
217
  // The task key might be the milestone ID itself, or "milestone_N"
218
218
  keyToMilestoneId.set(m.id, m.id)
219
219
  keyToMilestoneId.set(m.id.toLowerCase(), m.id)
220
- keyToMilestoneId.set(`milestone_${i + 1}`, m.id)
221
- // Also handle "milestone_N" where N matches the numeric part of "MN"
220
+ // Map "milestone_N" where N matches the numeric part of the milestone ID (e.g. M1 milestone_1)
221
+ // NOTE: Do NOT use array index (i+1) here milestones may be out of order in the YAML,
222
+ // so array position does not reliably correspond to milestone number.
222
223
  const numMatch = m.id.match(/(\d+)/)
223
224
  if (numMatch) {
224
225
  keyToMilestoneId.set(`milestone_${numMatch[1]}`, m.id)