From 2022e7d1dfe4b0df3a830c8dbaacad15a30d2028 Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Tue, 25 Jun 2024 14:59:12 -0700 Subject: [PATCH 1/5] Deprecate property 't' in in favor of 'domain'. Add 'domain' property to and so that users can apply their own limits to the plots. --- src/display/Plot/OfX.tsx | 14 +++++++++----- src/display/Plot/OfY.tsx | 14 +++++++++----- src/display/Plot/Parametric.tsx | 30 +++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/display/Plot/OfX.tsx b/src/display/Plot/OfX.tsx index 4e8cd138..13b42e58 100644 --- a/src/display/Plot/OfX.tsx +++ b/src/display/Plot/OfX.tsx @@ -3,20 +3,24 @@ import { usePaneContext } from "../../context/PaneContext" import { Parametric, ParametricProps } from "./Parametric" import { vec } from "../../vec" -export interface OfXProps extends Omit { +export interface OfXProps extends Omit { y: (x: number) => number + domain?: {min?: number, max?: number} svgPathProps?: React.SVGProps } -export function OfX({ y, ...props }: OfXProps) { +export function OfX({ y, domain, ...props }: OfXProps) { const { - xPaneRange: [xMin, xMax], + xPaneRange: [xpMin, xpMax], } = usePaneContext() + // Determine the most restrictive range values (either user-provided or the pane context) + const xMin = Math.max(xpMin, domain?.min ?? -Infinity) + const xMax = Math.min(xpMax, domain?.max ?? Infinity) const xy = React.useCallback((x) => [x, y(x)], [y]) - const t = React.useMemo(() => [xMin, xMax], [xMin, xMax]) + const parametricDomain = React.useMemo(() => [xMin, xMax], [xMin, xMax]) - return + return } OfX.displayName = "Plot.OfX" diff --git a/src/display/Plot/OfY.tsx b/src/display/Plot/OfY.tsx index 273ab363..88771864 100644 --- a/src/display/Plot/OfY.tsx +++ b/src/display/Plot/OfY.tsx @@ -3,20 +3,24 @@ import { usePaneContext } from "../../context/PaneContext" import { Parametric, ParametricProps } from "./Parametric" import { vec } from "../../vec" -export interface OfYProps extends Omit { +export interface OfYProps extends Omit { x: (y: number) => number + domain?: {min?: number, max?: number} svgPathProps?: React.SVGProps } -export function OfY({ x, ...props }: OfYProps) { +export function OfY({ x, domain, ...props }: OfYProps) { const { - yPaneRange: [yMin, yMax], + yPaneRange: [ypMin, ypMax], } = usePaneContext() + // Determine the most restrictive range values (either user-provided or the pane context) + const yMin = Math.max(ypMin, domain?.min ?? -Infinity) + const yMax = Math.min(ypMax, domain?.max ?? Infinity) const xy = React.useCallback((y) => [x(y), y], [x]) - const t = React.useMemo(() => [yMin, yMax], [yMin, yMax]) + const parametricDomain = React.useMemo(() => [yMin, yMax], [yMin, yMax]) - return + return } OfY.displayName = "Plot.OfY" diff --git a/src/display/Plot/Parametric.tsx b/src/display/Plot/Parametric.tsx index d0abc9c1..a3055b77 100644 --- a/src/display/Plot/Parametric.tsx +++ b/src/display/Plot/Parametric.tsx @@ -4,10 +4,14 @@ import { Stroked } from "../Theme" import { useTransformContext } from "../../context/TransformContext" import { sampleParametric } from "./PlotUtils" -export interface ParametricProps extends Stroked { +interface ParametricPropsLegacy extends Stroked { /** A function that takes a `t` value and returns a point. */ xy: (t: number) => vec.Vector2 - /** The domain `t` between which to evaluate `xy`. */ + /** The domain between which to evaluate `xy`. */ + domain?: never + /** + * @deprecated - use the `domain` prop. + */ t: vec.Vector2 /** The minimum recursive depth of the sampling algorithm. */ minSamplingDepth?: number @@ -17,8 +21,28 @@ export interface ParametricProps extends Stroked { svgPathProps?: React.SVGProps } +interface ParametricPropsNew extends Stroked { + /** A function that takes a `t` value and returns a point. */ + xy: (t: number) => vec.Vector2 + /** The domain between which to evaluate `xy`. */ + domain: vec.Vector2 + /** + * @deprecated - use the `domain` prop. + */ + t?: never + /** The minimum recursive depth of the sampling algorithm. */ + minSamplingDepth?: number + /** The maximum recursive depth of the sampling algorithm. */ + maxSamplingDepth?: number + + svgPathProps?: React.SVGProps +} + +export type ParametricProps = ParametricPropsNew | ParametricPropsLegacy + export function Parametric({ xy, + domain, t, color, style = "solid", @@ -33,7 +57,7 @@ export function Parametric({ // Negative because the y-axis is flipped in the SVG coordinate system. const pixelsPerSquare = -vec.det(viewTransform) - const [tMin, tMax] = t + const [tMin, tMax] = domain || t const errorThreshold = 0.1 / pixelsPerSquare const svgPath = React.useMemo( From d07cc7513b7f68266b60b66dea9a7a4af581f93b Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Wed, 26 Jun 2024 09:26:47 -0700 Subject: [PATCH 2/5] Add comment to remove legacy interface definition in 1 year. --- src/display/Plot/Parametric.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/display/Plot/Parametric.tsx b/src/display/Plot/Parametric.tsx index a3055b77..dfccc8f0 100644 --- a/src/display/Plot/Parametric.tsx +++ b/src/display/Plot/Parametric.tsx @@ -4,6 +4,10 @@ import { Stroked } from "../Theme" import { useTransformContext } from "../../context/TransformContext" import { sampleParametric } from "./PlotUtils" +// TODO: In 1-year's time from this change (written 6/26/2024), +// remove the Legacy interface and just have the new props interface (renamed, of course). +// Also, remove the `t` property at that time. +// The 1 year timeline gives consumers time to update their code. interface ParametricPropsLegacy extends Stroked { /** A function that takes a `t` value and returns a point. */ xy: (t: number) => vec.Vector2 From dbb3ec35d8de03fa168e533124133bfce4abf553 Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Thu, 27 Jun 2024 09:20:17 -0700 Subject: [PATCH 3/5] Modify 'TODO' comment to reference a version instead of a date to make the referenced change in code. --- src/display/Plot/Parametric.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/display/Plot/Parametric.tsx b/src/display/Plot/Parametric.tsx index dfccc8f0..c618e44e 100644 --- a/src/display/Plot/Parametric.tsx +++ b/src/display/Plot/Parametric.tsx @@ -4,10 +4,11 @@ import { Stroked } from "../Theme" import { useTransformContext } from "../../context/TransformContext" import { sampleParametric } from "./PlotUtils" -// TODO: In 1-year's time from this change (written 6/26/2024), +// TODO: (v1.0.0) When the project has it's first major (breaking) update, // remove the Legacy interface and just have the new props interface (renamed, of course). // Also, remove the `t` property at that time. -// The 1 year timeline gives consumers time to update their code. +// Waiting until the major update to batch them together, +// and to give time for consumers to update their usage. interface ParametricPropsLegacy extends Stroked { /** A function that takes a `t` value and returns a point. */ xy: (t: number) => vec.Vector2 From 5253d7f47573ce888bace83462fc2bc3c036f574 Mon Sep 17 00:00:00 2001 From: Mark Fitzgerald Date: Thu, 27 Jun 2024 11:00:58 -0700 Subject: [PATCH 4/5] Change 'domain' property in "OfX/OfY" components to be a tuple (matching current 't' property). --- src/display/Plot/OfX.tsx | 7 ++++--- src/display/Plot/OfY.tsx | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/display/Plot/OfX.tsx b/src/display/Plot/OfX.tsx index 13b42e58..e9cc76a2 100644 --- a/src/display/Plot/OfX.tsx +++ b/src/display/Plot/OfX.tsx @@ -5,17 +5,18 @@ import { vec } from "../../vec" export interface OfXProps extends Omit { y: (x: number) => number - domain?: {min?: number, max?: number} + domain?: vec.Vector2 svgPathProps?: React.SVGProps } export function OfX({ y, domain, ...props }: OfXProps) { + const [xuMin, xuMax] = domain ?? [-Infinity, Infinity] const { xPaneRange: [xpMin, xpMax], } = usePaneContext() // Determine the most restrictive range values (either user-provided or the pane context) - const xMin = Math.max(xpMin, domain?.min ?? -Infinity) - const xMax = Math.min(xpMax, domain?.max ?? Infinity) + const xMin = Math.max(xuMin, xpMin) + const xMax = Math.min(xuMax, xpMax) const xy = React.useCallback((x) => [x, y(x)], [y]) const parametricDomain = React.useMemo(() => [xMin, xMax], [xMin, xMax]) diff --git a/src/display/Plot/OfY.tsx b/src/display/Plot/OfY.tsx index 88771864..c3c36472 100644 --- a/src/display/Plot/OfY.tsx +++ b/src/display/Plot/OfY.tsx @@ -5,17 +5,18 @@ import { vec } from "../../vec" export interface OfYProps extends Omit { x: (y: number) => number - domain?: {min?: number, max?: number} + domain?: vec.Vector2 svgPathProps?: React.SVGProps } export function OfY({ x, domain, ...props }: OfYProps) { + const [yuMin, yuMax] = domain ?? [-Infinity, Infinity] const { yPaneRange: [ypMin, ypMax], } = usePaneContext() // Determine the most restrictive range values (either user-provided or the pane context) - const yMin = Math.max(ypMin, domain?.min ?? -Infinity) - const yMax = Math.min(ypMax, domain?.max ?? Infinity) + const yMin = Math.max(yuMin, ypMin) + const yMax = Math.min(yuMax, ypMax) const xy = React.useCallback((y) => [x(y), y], [x]) const parametricDomain = React.useMemo(() => [yMin, yMax], [yMin, yMax]) From 19c7b91cd531bc73c9865a2c565a0cb92f8bc56f Mon Sep 17 00:00:00 2001 From: Steven Petryk Date: Sat, 20 Jul 2024 18:33:58 -0700 Subject: [PATCH 5/5] t -> domain --- docs/components/guide-examples/examples/ProjectileMotion.tsx | 2 +- docs/components/guide-examples/plots/twisty-boi.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/components/guide-examples/examples/ProjectileMotion.tsx b/docs/components/guide-examples/examples/ProjectileMotion.tsx index 22fabd3e..c233031a 100644 --- a/docs/components/guide-examples/examples/ProjectileMotion.tsx +++ b/docs/components/guide-examples/examples/ProjectileMotion.tsx @@ -75,7 +75,7 @@ export default function ProjectileMotion() { <> diff --git a/docs/components/guide-examples/plots/twisty-boi.tsx b/docs/components/guide-examples/plots/twisty-boi.tsx index 74fefe8c..5974e73c 100644 --- a/docs/components/guide-examples/plots/twisty-boi.tsx +++ b/docs/components/guide-examples/plots/twisty-boi.tsx @@ -20,7 +20,7 @@ export default function TwistyBoi() { [Math.cos(t), (t / k) * Math.sin(t)]} />