packages/core/src/lib/components/regular-polygon.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 {
8 resolveRegularPolygonGeometry,
9 type RegularPolygonPathOptions,
10 } from '../geometry/regular-polygon.js';
11 import {
12 integerAtLeast,
13 type GeometryErrorFactory,
14 } from '../geometry/validation.js';
15 import {
16 resolveLocalOffset,
17 stripLayoutParticipation,
18 } from '../style/resolve-built-in.js';
19 import { registerOpaqueStyleProperties } from '../style/resolve-dispatch.js';
20 import type {
21 BoxStyle,
22 CursorStyle,
23 LayoutItemStyle,
24 Length,
25 PaintStyle,
26 RoundedCornerStyle,
27 } from '../style/types.js';
28 import type { RenderingContext2D, SystemStyle } from '../types.js';
29 import type { PibblPhysics2DPropExtension } from '../types.js';
30 import { renderPath } from './path.js';
31 import { resolveRoundedCornerStyle } from './rounded-corner-style.js';
32 import {
33 circularPercentageBasis,
34 resolveFiniteShapeNumber,
35 resolveNonnegativeShapeLength,
36 shapeGeometryErrorFactory,
37 } from './shape-style.js';
38
39 /**
40 * Authored inputs for RegularPolygon, including the declared data and presentation options.
41 *
42 * @see {@link PibblEventHandlers}
43 * @see {@link PibblEventParticipationOptions}
44 * @see {@link PibblPhysics2DPropExtension}
45 * @see {@link RegularPolygon}
46 */
47 export interface RegularPolygonProps
48 extends PibblEventHandlers, PibblEventFocusOptions, PibblEventParticipationOptions, PibblPhysics2DPropExtension {}
49
50 /**
51 * Center, side count, rotation, and paint shared by regular-polygon size variants.
52 *
53 * @see {@link RegularPolygonStyle}
54 */
55 interface RegularPolygonCommonStyle extends RoundedCornerStyle {
56 /** Number of sides of the regular polygon. See {@link RegularPolygonCommonStyle}. */
57 sides: number;
58 /** Horizontal coordinate of the center. See {@link Length}. */
59 cx?: Exclude<Length, 'auto'>;
60 /** Vertical coordinate of the center. See {@link Length}. */
61 cy?: Exclude<Length, 'auto'>;
62 /** Rotation applied to the containing geometry. See {@link RegularPolygonCommonStyle}. */
63 rotation?: number;
64 /**
65 * Width used for line hit testing independently of the visible stroke width. See
66 * {@link RegularPolygonCommonStyle}.
67 */
68 lineInteractionWidth?: number;
69 }
70
71 /**
72 * Exactly one declared size measure for a regular polygon.
73 *
74 * @see {@link RegularPolygonStyle}
75 */
76 type RegularPolygonSizeStyle =
77 | {
78 /** Distance from the polygon center to a vertex. See {@link Length}. */
79 circumradius: Exclude<Length, 'auto'>;
80 /**
81 * Not accepted in this variant; use the alternative fields instead. See
82 * {@link RegularPolygonSizeStyle}.
83 */
84 inradius?: never;
85 /**
86 * Not accepted in this variant; use the alternative fields instead. See
87 * {@link RegularPolygonSizeStyle}.
88 */
89 sideLength?: never;
90 }
91 | {
92 /**
93 * Not accepted in this variant; use the alternative fields instead. See
94 * {@link RegularPolygonSizeStyle}.
95 */
96 circumradius?: never;
97 /** Distance from the polygon center to an edge. See {@link Length}. */
98 inradius: Exclude<Length, 'auto'>;
99 /**
100 * Not accepted in this variant; use the alternative fields instead. See
101 * {@link RegularPolygonSizeStyle}.
102 */
103 sideLength?: never;
104 }
105 | {
106 /**
107 * Not accepted in this variant; use the alternative fields instead. See
108 * {@link RegularPolygonSizeStyle}.
109 */
110 circumradius?: never;
111 /**
112 * Not accepted in this variant; use the alternative fields instead. See
113 * {@link RegularPolygonSizeStyle}.
114 */
115 inradius?: never;
116 /** Length of one polygon edge. See {@link Length}. */
117 sideLength: Exclude<Length, 'auto'>;
118 };
119
120 /**
121 * Supported geometry and presentation properties for RegularPolygon.
122 *
123 * @see {@link SystemStyle}
124 * @see {@link PaintStyle}
125 * @see {@link CursorStyle}
126 * @see {@link BoxStyle}
127 * @see {@link LayoutItemStyle}
128 * @see {@link RegularPolygon}
129 */
130 export type RegularPolygonStyle = RegularPolygonCommonStyle &
131 RegularPolygonSizeStyle &
132 SystemStyle &
133 PaintStyle &
134 CursorStyle &
135 BoxStyle &
136 LayoutItemStyle;
137
138 interface ResolvedRegularPolygonStyle
139 extends SystemStyle, PaintStyle, CursorStyle {
140 sides: number;
141 cx: number;
142 cy: number;
143 rotation: number;
144 circumradius?: number;
145 inradius?: number;
146 sideLength?: number;
147 cornerRadius?: number;
148 cornerRadii?: readonly (number | null | undefined)[];
149 lineInteractionWidth?: number;
150 geometryErrorFactory: GeometryErrorFactory;
151 }
152
153 function renderRegularPolygon(
154 props: RegularPolygonProps,
155 style: Readonly<ResolvedRegularPolygonStyle>,
156 ctx: RenderingContext2D,
157 ) {
158 const {
159 sides,
160 cx,
161 cy,
162 rotation,
163 circumradius,
164 inradius,
165 sideLength,
166 cornerRadius,
167 cornerRadii,
168 geometryErrorFactory,
169 ...pathStyle
170 } = style;
171 const geometry = resolveRegularPolygonGeometry({
172 sides,
173 cx,
174 cy,
175 rotation,
176 ...(circumradius === undefined ? {} : { circumradius }),
177 ...(inradius === undefined ? {} : { inradius }),
178 ...(sideLength === undefined ? {} : { sideLength }),
179 cornerRadius,
180 cornerRadii,
181 } as RegularPolygonPathOptions, geometryErrorFactory);
182
183 return renderPath({
184 ...props,
185 keyboardNavigationBounds: props.keyboardNavigationBounds ?? geometry.bounds,
186 }, {
187 ...pathStyle,
188 d: geometry.path,
189 }, ctx);
190 }
191
192 /**
193 * Describes a regular-polygon primitive for JSX or createElement authoring.
194 *
195 * @param props - Authored component inputs, supplied through JSX or createElement. See the linked
196 * props and style types.
197 * @throws When called directly; Pibbl mounts this component through JSX or createElement.
198 *
199 * @see {@link RegularPolygonProps}
200 * @see {@link RegularPolygonStyle}
201 */
202 export const RegularPolygon = definePrimitive<
203 RegularPolygonProps,
204 RegularPolygonStyle,
205 RegularPolygonStyle,
206 ResolvedRegularPolygonStyle
207 >(renderRegularPolygon, {
208 resolveStyle: (style, context) => {
209 const errorFactory = shapeGeometryErrorFactory(context);
210 const sides = integerAtLeast(style.sides, 3, 'sides', errorFactory);
211 const basis = circularPercentageBasis(context);
212 return {
213 ...stripLayoutParticipation(style),
214 sides,
215 cx: resolveLocalOffset(
216 style.cx,
217 context.percentageBasis.width,
218 'cx',
219 context,
220 ),
221 cy: resolveLocalOffset(
222 style.cy,
223 context.percentageBasis.height,
224 'cy',
225 context,
226 ),
227 rotation: resolveFiniteShapeNumber(
228 style.rotation ?? -Math.PI / 2,
229 'rotation',
230 context,
231 ),
232 ...(style.circumradius === undefined ? {} : {
233 circumradius: resolveNonnegativeShapeLength(
234 style.circumradius,
235 basis,
236 'circumradius',
237 context,
238 ),
239 }),
240 ...(style.inradius === undefined ? {} : {
241 inradius: resolveNonnegativeShapeLength(
242 style.inradius,
243 basis,
244 'inradius',
245 context,
246 ),
247 }),
248 ...(style.sideLength === undefined ? {} : {
249 sideLength: resolveNonnegativeShapeLength(
250 style.sideLength,
251 basis,
252 'sideLength',
253 context,
254 ),
255 }),
256 ...resolveRoundedCornerStyle(sides, style, context),
257 geometryErrorFactory: errorFactory,
258 } as ResolvedRegularPolygonStyle;
259 },
260 });
261 registerOpaqueStyleProperties(RegularPolygon, ['fill', 'stroke', 'cursor']);
262
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.