packages/core/src/lib/components/ellipse.ts
This is the source snapshot used to build these API details. View this revision on GitHub.
1 import { definePrimitive } from '../define-primitive.js';
2 import type {
3 PibblEventFocusOptions,
4 PibblEventHandlers,
5 PibblEventParticipationOptions,
6 } from '../events/types.js';
7 import type { RenderingContext2D, SystemStyle } from '../types.js';
8 import type { PibblPhysics2DPropExtension } from '../types.js';
9 import {
10 resolveLocalOffset,
11 stripLayoutParticipation,
12 } from '../style/resolve-built-in.js';
13 import { registerOpaqueStyleProperties } from '../style/resolve-dispatch.js';
14 import type {
15 BoxStyle,
16 CursorStyle,
17 LayoutItemStyle,
18 Length,
19 PaintStyle,
20 ResolvedDrawingStyle,
21 } from '../style/types.js';
22 import {
23 resolveFiniteShapeNumber,
24 resolveNonnegativeShapeLength,
25 } from './shape-style.js';
26 import { renderPath } from './path.js';
27 import { createEllipsePath } from '../geometry/ellipse.js';
28
29 /**
30 * Authored inputs for Ellipse, including the declared data and presentation options.
31 *
32 * @see {@link PibblEventHandlers}
33 * @see {@link PibblEventParticipationOptions}
34 * @see {@link PibblPhysics2DPropExtension}
35 * @see {@link Ellipse}
36 */
37 export interface EllipseProps extends PibblEventHandlers, PibblEventFocusOptions, PibblEventParticipationOptions, PibblPhysics2DPropExtension {}
38
39 /**
40 * Supported geometry and presentation properties for Ellipse.
41 *
42 * @see {@link SystemStyle}
43 * @see {@link PaintStyle}
44 * @see {@link CursorStyle}
45 * @see {@link BoxStyle}
46 * @see {@link LayoutItemStyle}
47 * @see {@link Length}
48 * @see {@link Ellipse}
49 */
50 export interface EllipseStyle
51 extends SystemStyle, PaintStyle, CursorStyle, BoxStyle, LayoutItemStyle {
52 /** Horizontal ellipse radius. See {@link Length}. */
53 radiusX: Exclude<Length, 'auto'>;
54 /** Vertical ellipse radius. See {@link Length}. */
55 radiusY: Exclude<Length, 'auto'>;
56 /** Horizontal coordinate of the center. See {@link Length}. */
57 cx?: Exclude<Length, 'auto'>;
58 /** Vertical coordinate of the center. See {@link Length}. */
59 cy?: Exclude<Length, 'auto'>;
60 /** Rotation applied to the containing geometry. See {@link EllipseStyle}. */
61 rotation?: number;
62 /**
63 * Width used for line hit testing independently of the visible stroke width. See
64 * {@link EllipseStyle}.
65 */
66 lineInteractionWidth?: number;
67 }
68
69 type ResolvedEllipseStyle = ResolvedDrawingStyle<EllipseStyle> & {
70 radiusX: number;
71 radiusY: number;
72 cx: number;
73 cy: number;
74 rotation: number;
75 };
76
77 function renderEllipse(
78 props: EllipseProps,
79 style: Readonly<ResolvedEllipseStyle>,
80 ctx: RenderingContext2D,
81 ) {
82 const { cx, cy, radiusX, radiusY, rotation, ...pathStyle } = style;
83 const path = createEllipsePath({ cx, cy, radiusX, radiusY, rotation });
84 const halfWidth = Math.sqrt(
85 (radiusX * Math.cos(rotation)) ** 2 +
86 (radiusY * Math.sin(rotation)) ** 2,
87 );
88 const halfHeight = Math.sqrt(
89 (radiusX * Math.sin(rotation)) ** 2 +
90 (radiusY * Math.cos(rotation)) ** 2,
91 );
92
93 return renderPath({
94 ...props,
95 keyboardNavigationBounds: props.keyboardNavigationBounds ?? {
96 x: cx - halfWidth,
97 y: cy - halfHeight,
98 width: halfWidth * 2,
99 height: halfHeight * 2,
100 },
101 }, {
102 ...pathStyle,
103 d: path,
104 }, ctx);
105 }
106
107 /**
108 * Describes an ellipse primitive for JSX or createElement authoring.
109 *
110 * @param props - Authored component inputs, supplied through JSX or createElement. See the linked
111 * props and style types.
112 * @throws When called directly; Pibbl mounts this component through JSX or createElement.
113 *
114 * @see {@link EllipseProps}
115 * @see {@link EllipseStyle}
116 */
117 export const Ellipse = definePrimitive<
118 EllipseProps,
119 EllipseStyle,
120 EllipseStyle,
121 ResolvedEllipseStyle
122 >(renderEllipse, {
123 resolveStyle: (style, context) => ({
124 ...stripLayoutParticipation(style),
125 cx: resolveLocalOffset(style.cx, context.percentageBasis.width, 'cx', context),
126 cy: resolveLocalOffset(style.cy, context.percentageBasis.height, 'cy', context),
127 radiusX: resolveNonnegativeShapeLength(
128 style.radiusX,
129 context.percentageBasis.width,
130 'radiusX',
131 context,
132 ),
133 radiusY: resolveNonnegativeShapeLength(
134 style.radiusY,
135 context.percentageBasis.height,
136 'radiusY',
137 context,
138 ),
139 rotation: resolveFiniteShapeNumber(style.rotation ?? 0, 'rotation', context),
140 }) as ResolvedEllipseStyle,
141 });
142 registerOpaqueStyleProperties(Ellipse, ['fill', 'stroke', 'cursor']);
143
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.