Skip to content

packages/core/src/lib/components/arc.ts

Read as Markdown

This is the source snapshot used to build these API details. View this revision on GitHub.

Back to reference

1 import { definePrimitive } from "../define-primitive.js";
2 import type {
3   PibblEventFocusOptions,
4   PibblEventHandlers,
5   PibblEventParticipationOptions,
6 } from "../events/types.js";
7 import {
8   resolveLocalOffset,
9   stripLayoutParticipation,
10 } from "../style/resolve-built-in.js";
11 import { registerOpaqueStyleProperties } from "../style/resolve-dispatch.js";
12 import type {
13   BoxStyle,
14   CursorStyle,
15   LayoutItemStyle,
16   Length,
17   PaintStyle,
18   ResolvedDrawingStyle,
19 } from "../style/types.js";
20 import type { RenderingContext2D, SystemStyle } from "../types.js";
21 import type { PibblPhysics2DPropExtension } from "../types.js";
22 import { arcBounds } from "./arc-geometry.js";
23 import {
24   createArcPath,
25   resolveCircularSweep,
26 } from "../geometry/circular-sweep.js";
27 import { renderPath } from "./path.js";
28 import {
29   circularPercentageBasis,
30   resolveFiniteShapeNumber,
31   resolveNonnegativeShapeLength,
32 } from "./shape-style.js";
33 
34 /**
35  * Authored inputs for Arc, including the declared data and presentation options.
36  *
37  * @see {@link PibblEventHandlers}
38  * @see {@link PibblEventParticipationOptions}
39  * @see {@link PibblPhysics2DPropExtension}
40  * @see {@link Arc}
41  */
42 export interface ArcProps extends PibblEventHandlers, PibblEventFocusOptions, PibblEventParticipationOptions, PibblPhysics2DPropExtension {}
43 
44 /**
45  * Supported geometry and presentation properties for Arc.
46  *
47  * @see {@link SystemStyle}
48  * @see {@link PaintStyle}
49  * @see {@link CursorStyle}
50  * @see {@link BoxStyle}
51  * @see {@link LayoutItemStyle}
52  * @see {@link Length}
53  * @see {@link Arc}
54  */
55 export interface ArcStyle
56   extends SystemStyle, Omit<PaintStyle, "fill">, CursorStyle, BoxStyle, LayoutItemStyle {
57   /** Radius in the coordinate system of this geometry or effect. See {@link Length}. */
58   radius: Exclude<Length, "auto">;
59   /** Angle at which the arc or slice begins. See {@link ArcStyle}. */
60   startAngle: number;
61   /** Angle at which the arc or slice ends. See {@link ArcStyle}. */
62   endAngle: number;
63   /** Horizontal coordinate of the center. See {@link Length}. */
64   cx?: Exclude<Length, "auto">;
65   /** Vertical coordinate of the center. See {@link Length}. */
66   cy?: Exclude<Length, "auto">;
67   /** Whether the arc follows the counterclockwise direction. See {@link ArcStyle}. */
68   counterclockwise?: boolean;
69   /**
70    * Width used for line hit testing independently of the visible stroke width. See
71    * {@link ArcStyle}.
72    */
73   lineInteractionWidth?: number;
74 }
75 
76 type ResolvedArcStyle = ResolvedDrawingStyle<ArcStyle> & {
77   radius: number;
78   startAngle: number;
79   endAngle: number;
80   cx: number;
81   cy: number;
82   counterclockwise: boolean;
83 };
84 
85 function renderArc(
86   props: ArcProps,
87   style: Readonly<ResolvedArcStyle>,
88   ctx: RenderingContext2D,
89 ) {
90   const {
91     cx,
92     cy,
93     radius,
94     startAngle,
95     endAngle,
96     counterclockwise,
97     stroke,
98     strokeWidth,
99     opacity,
100     cursor,
101     lineInteractionWidth,
102   } = style;
103   const sweep = resolveCircularSweep(startAngle, endAngle, counterclockwise);
104   const path = createArcPath({
105     cx,
106     cy,
107     radius,
108     startAngle,
109     endAngle,
110     counterclockwise,
111   });
112 
113   return renderPath(
114     {
115       ...props,
116       keyboardNavigationBounds:
117         props.keyboardNavigationBounds ?? arcBounds(cx, cy, radius, sweep),
118     },
119     {
120       d: path,
121       stroke,
122       strokeWidth,
123       opacity,
124       cursor,
125       lineInteractionWidth,
126     },
127     ctx,
128   );
129 }
130 
131 /**
132  * Describes an open circular arc primitive for JSX or createElement authoring.
133  *
134  * @param props - Authored component inputs, supplied through JSX or createElement. See the linked
135  * props and style types.
136  * @throws When called directly; Pibbl mounts this component through JSX or createElement.
137  *
138  * @see {@link ArcProps}
139  * @see {@link ArcStyle}
140  */
141 export const Arc = definePrimitive<
142   ArcProps,
143   ArcStyle,
144   ArcStyle,
145   ResolvedArcStyle
146 >(renderArc, {
147   resolveStyle: (style, context) =>
148     ({
149       ...stripLayoutParticipation(style),
150       cx: resolveLocalOffset(
151         style.cx,
152         context.percentageBasis.width,
153         "cx",
154         context,
155       ),
156       cy: resolveLocalOffset(
157         style.cy,
158         context.percentageBasis.height,
159         "cy",
160         context,
161       ),
162       radius: resolveNonnegativeShapeLength(
163         style.radius,
164         circularPercentageBasis(context),
165         "radius",
166         context,
167       ),
168       startAngle: resolveFiniteShapeNumber(
169         style.startAngle,
170         "startAngle",
171         context,
172       ),
173       endAngle: resolveFiniteShapeNumber(style.endAngle, "endAngle", context),
174       counterclockwise: style.counterclockwise ?? false,
175     }) as ResolvedArcStyle,
176 });
177 registerOpaqueStyleProperties(Arc, ["stroke", "cursor"]);
178 

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.