Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/site/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
mono,
playgroundUrl,
themeConfig,
useCanvasControlTracking,
} from './playground-shared'

const REPO = 'inkeep/visimer'
Expand Down Expand Up @@ -155,6 +156,7 @@ export default function App() {
const [type, setType] = useState('flowchart')
const [skin, setSkin] = useState<'light' | 'dark'>('light')
const { editor } = useMermaidEditor(PRESETS.flowchart)
useCanvasControlTracking()

// Expanding hands off to the dedicated /playground page, carrying the
// current source in the URL hash so nothing is lost in the jump.
Expand Down Expand Up @@ -705,7 +707,7 @@ export default function App() {
>
<span style={{ fontSize: 12.5, fontWeight: 600, color: paneText }}>Preview</span>
<span className="pg-hint-long" style={chromeLabel}>
click to select · double-click to edit · drag empty space to pan · pinch to zoom
click to select · double-click to edit · alt + drag to connect · pinch to zoom
</span>
<span className="pg-hint-short" style={chromeLabel}>
tap to select · double-tap to edit · pinch to zoom
Expand Down
4 changes: 3 additions & 1 deletion apps/site/src/PlaygroundPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
encodeCode,
mono,
themeConfig,
useCanvasControlTracking,
} from './playground-shared'

/**
Expand All @@ -22,6 +23,7 @@ import {
export default function PlaygroundPage() {
const initialCode = useMemo(() => codeFromHash(window.location.hash) ?? PRESETS.flowchart, [])
const { editor } = useMermaidEditor(initialCode)
useCanvasControlTracking()

const [skin, setSkin] = useState<'light' | 'dark'>('light')
const [menuOpen, setMenuOpen] = useState(false)
Expand Down Expand Up @@ -312,7 +314,7 @@ export default function PlaygroundPage() {
>
<span style={{ fontSize: 12.5, fontWeight: 600, color: paneText }}>Preview</span>
<span className="pg-hint-long" style={chromeLabel}>
click to select · double-click to edit · drag empty space to pan · pinch to zoom
click to select · double-click to edit · alt + drag to connect · pinch to zoom
</span>
<span className="pg-hint-short" style={chromeLabel}>
tap to select · double-tap to edit · pinch to zoom
Expand Down
6 changes: 6 additions & 0 deletions apps/site/src/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ if (key) {
}

export function track(event: string, properties?: Record<string, unknown>) {
// dev only: mirror event names onto the window so wiring is verifiable
// in the browser without a key or a network tap
if (import.meta.env.DEV) {
const w = window as unknown as { __phEvents?: string[] }
;(w.__phEvents ??= []).push(event)
}
if (!key) return
posthog.capture(event, properties)
}
21 changes: 21 additions & 0 deletions apps/site/src/playground-shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useEffect, useRef } from 'react'
import { EditorView } from '@codemirror/view'
import { MermaidCodeMirror } from '@visimer/codemirror'
import type { MermaidWysiwygEditor } from '@visimer/core'
import { track } from './analytics'

/** Sample diagrams + chrome shared by the inline demo and /playground. */

Expand Down Expand Up @@ -178,6 +179,26 @@ export function CodeMirrorPane({ editor }: { editor: MermaidWysiwygEditor }) {
return <div ref={hostRef} className="demo-cm" />
}

/**
* Tracks clicks on the canvas corner zoom controls (zoom in / zoom out /
* fit). The buttons are rendered by @visimer/dom, so the site listens by
* delegation instead of teaching the package about analytics.
*/
export function useCanvasControlTracking() {
useEffect(() => {
const onClick = (e: MouseEvent) => {
const btn = (e.target as Element | null)?.closest?.('.mw-zoom-btn')
if (!btn) return
const title = btn.getAttribute('title') ?? ''
const control = /out/i.test(title) ? 'zoom-out' : /in\b/i.test(title) ? 'zoom-in' : 'fit'
track('canvas_zoom_control', { control })
}
// capture phase: the package's buttons stopPropagation on their clicks
document.addEventListener('click', onClick, true)
return () => document.removeEventListener('click', onClick, true)
}, [])
}

// ---- code <-> URL hash codec ----
// The playground keeps the current source in `#code=<base64url(utf8)>` so the
// address bar is always a share link. No compression: sample-sized diagrams
Expand Down