Skip to content
Draft
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
2 changes: 1 addition & 1 deletion lib/strokeAlphabetText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function getAlphabetAdvanceWidth(
const advanceRatio = getAdvanceRatio(char)
const letterSpacingRatio = nextChar ? textMetrics.letterSpacingRatio : 0
const kerningAdjustmentRatio = nextChar
? (kerningRatio[char]?.[nextChar] ?? 0)
? kerningRatio[char]?.[nextChar] ?? 0
: 0

return fontSize * (advanceRatio + letterSpacingRatio + kerningAdjustmentRatio)
Expand Down
14 changes: 14 additions & 0 deletions site/components/InteractiveGraphics/InteractiveGraphics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ export const InteractiveGraphics = ({
onObjectClicked,
objectLimit,
height = 600,
stepMetadata,
alwaysShowToolbar = false,
}: {
graphics: GraphicsObject
onObjectClicked?: (event: GraphicsObjectClickEvent) => void
objectLimit?: number
height?: number
stepMetadata?: Array<{ title: string }>
alwaysShowToolbar?: boolean
}) => {
const [activeLayers, setActiveLayers] = useState<string[] | null>(null)
const [activeStep, setActiveStep] = useState<number | null>(null)
Expand Down Expand Up @@ -359,6 +363,10 @@ export const InteractiveGraphics = ({
}

const showToolbar = true
const stepTitle =
maxStep > 0
? stepMetadata?.[showLastStep ? maxStep : activeStep ?? -1]?.title
: undefined

// Use custom hooks for visibility checks and filtering
const isPointOnScreen = useIsPointOnScreen(realToScreen, size)
Expand Down Expand Up @@ -576,6 +584,12 @@ export const InteractiveGraphics = ({
/>
Enable Object Interation
</label>

{maxStep > 0 && stepTitle && (
<div style={{ marginLeft: "auto", textAlign: "right" }}>
{stepTitle}
</div>
)}
</div>
)}

Expand Down
2 changes: 1 addition & 1 deletion site/components/InteractiveGraphics/Point.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const Point = ({
0.2,
color ?? defaultColors[index % defaultColors.length],
)
: (color ?? defaultColors[index % defaultColors.length])
: color ?? defaultColors[index % defaultColors.length]
}`,
cursor: "pointer",
transition: "border-color 0.2s",
Expand Down
138 changes: 81 additions & 57 deletions site/components/InteractiveGraphicsCanvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@ interface InteractiveGraphicsCanvasProps {
showGrid?: boolean
height?: number | string
width?: number | string
stepMetadata?: Array<{ title: string }>
alwaysShowToolbar?: boolean
}

export function InteractiveGraphicsCanvas({
graphics,
showLabelsByDefault = true,
showGrid = true,
height = 500,
width = "100%",
stepMetadata,
alwaysShowToolbar = false,
}: InteractiveGraphicsCanvasProps) {
const canvasRef = useRef<HTMLCanvasElement>(null)
const containerRef = useRef<HTMLDivElement | null>(null)
Expand All @@ -43,6 +48,11 @@ export function InteractiveGraphicsCanvas({

// Calculate the maximum step value from all graphics objects
const maxStep = getMaxStep(graphics)
const showToolbar = alwaysShowToolbar || maxStep > 0 || showLabelsByDefault
const stepTitle =
maxStep > 0
? stepMetadata?.[showLastStep ? maxStep : activeStep ?? -1]?.title
: undefined

// Filter graphics objects based on step
const filteredGraphics = getGraphicsFilteredByStep(graphics, {
Expand Down Expand Up @@ -254,66 +264,80 @@ export function InteractiveGraphicsCanvas({

return (
<div style={{ display: "flex", flexDirection: "column", gap: "10px" }}>
<div style={{ display: "flex", gap: "12px", alignItems: "center" }}>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<label>
<input
type="checkbox"
style={{ marginRight: 4 }}
checked={activeStep !== null}
onChange={(e) => {
setActiveStep(e.target.checked ? 0 : null)
}}
/>
Filter by step
</label>

<input
type="number"
min={0}
max={maxStep}
value={activeStep ?? 0}
onChange={(e) => {
const value = parseInt(e.target.value)
setShowLastStep(false)
setActiveStep(Number.isNaN(value) ? 0 : Math.min(value, maxStep))
}}
disabled={activeStep === null}
style={{ width: "60px" }}
/>
{showToolbar && (
<div style={{ display: "flex", gap: "12px", alignItems: "center" }}>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
{maxStep > 0 && (
<>
<label>
<input
type="checkbox"
style={{ marginRight: 4 }}
checked={activeStep !== null}
onChange={(e) => {
setActiveStep(e.target.checked ? 0 : null)
}}
/>
Filter by step
</label>

<input
type="number"
min={0}
max={maxStep}
value={activeStep ?? 0}
onChange={(e) => {
const value = parseInt(e.target.value)
setShowLastStep(false)
setActiveStep(
Number.isNaN(value) ? 0 : Math.min(value, maxStep),
)
}}
disabled={activeStep === null}
style={{ width: "60px" }}
/>

<label>
<input
type="checkbox"
style={{ marginRight: 4 }}
checked={showLastStep}
onChange={(e) => {
setShowLastStep(e.target.checked)
setActiveStep(null)
}}
/>
Show last step
</label>
</>
)}
</div>

<label>
<input
type="checkbox"
style={{ marginRight: 4 }}
checked={showLastStep}
onChange={(e) => {
setShowLastStep(e.target.checked)
setActiveStep(null)
}}
/>
Show last step
</label>
</div>
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<label>
<input
type="checkbox"
style={{ marginRight: 4 }}
checked={enableObjectInteraction}
onChange={(event) => {
const isEnabled = event.target.checked
setEnableObjectInteraction(isEnabled)
if (!isEnabled) {
setSelectedObjectLabel(null)
}
}}
/>
Enable Object Interation
</label>
</div>

<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
<label>
<input
type="checkbox"
style={{ marginRight: 4 }}
checked={enableObjectInteraction}
onChange={(event) => {
const isEnabled = event.target.checked
setEnableObjectInteraction(isEnabled)
if (!isEnabled) {
setSelectedObjectLabel(null)
}
}}
/>
Enable Object Interation
</label>
{maxStep > 0 && stepTitle && (
<div style={{ marginLeft: "auto", textAlign: "right" }}>
{stepTitle}
</div>
)}
</div>
</div>
)}

<div
ref={(node) => {
Expand Down
Loading