Skip to content

Commit ea34f5b

Browse files
committed
♻️ use string literals for floating options
1 parent bd2dcc9 commit ea34f5b

5 files changed

Lines changed: 151 additions & 69 deletions

File tree

ops.ts

Lines changed: 72 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,16 @@ export function pack(
171171
o += 4;
172172
view.setUint32(
173173
o,
174-
(f.attachTo ?? 0) |
175-
((f.attachPoints?.element ?? 0) << 8) |
176-
((f.attachPoints?.parent ?? 0) << 16) |
177-
((f.pointerCaptureMode ?? 0) << 24),
174+
encodeAttachTo(f.attachTo) |
175+
(encodeAttachPoint(f.attachPoints?.element) << 8) |
176+
(encodeAttachPoint(f.attachPoints?.parent) << 16) |
177+
(encodePointerCaptureMode(f.pointerCaptureMode) << 24),
178178
true,
179179
);
180180
o += 4;
181181
view.setUint32(
182182
o,
183-
(f.clipTo ?? 0) | (((f.zIndex ?? 0) & 0xffff) << 8),
183+
encodeClipTo(f.clipTo) | (((f.zIndex ?? 0) & 0xffff) << 8),
184184
true,
185185
);
186186
o += 4;
@@ -278,42 +278,77 @@ export interface OpenElement {
278278
y?: number;
279279
expand?: { width?: number; height?: number };
280280
parent?: number;
281-
attachTo?: number;
282-
attachPoints?: { element?: number; parent?: number };
283-
pointerCaptureMode?: number;
284-
clipTo?: number;
281+
attachTo?: AttachTo;
282+
attachPoints?: { element?: AttachPoint; parent?: AttachPoint };
283+
pointerCaptureMode?: PointerCaptureMode;
284+
clipTo?: ClipTo;
285285
zIndex?: number;
286286
};
287287
}
288288

289-
export const ATTACH_POINT = {
290-
LEFT_TOP: 0,
291-
LEFT_CENTER: 1,
292-
LEFT_BOTTOM: 2,
293-
CENTER_TOP: 3,
294-
CENTER_CENTER: 4,
295-
CENTER_BOTTOM: 5,
296-
RIGHT_TOP: 6,
297-
RIGHT_CENTER: 7,
298-
RIGHT_BOTTOM: 8,
299-
} as const;
300-
301-
export const ATTACH_TO = {
302-
NONE: 0,
303-
PARENT: 1,
304-
ELEMENT_WITH_ID: 2,
305-
ROOT: 3,
306-
} as const;
307-
308-
export const POINTER_CAPTURE_MODE = {
309-
CAPTURE: 0,
310-
PASSTHROUGH: 1,
311-
} as const;
312-
313-
export const CLIP_TO = {
314-
NONE: 0,
315-
ATTACHED_PARENT: 1,
316-
} as const;
289+
export type AttachPoint =
290+
| "left-top"
291+
| "left-center"
292+
| "left-bottom"
293+
| "center-top"
294+
| "center-center"
295+
| "center-bottom"
296+
| "right-top"
297+
| "right-center"
298+
| "right-bottom";
299+
300+
export type AttachTo = "none" | "parent" | "element" | "root";
301+
302+
export type PointerCaptureMode = "capture" | "passthrough";
303+
304+
export type ClipTo = "none" | "attached-parent";
305+
306+
const ATTACH_POINT: Record<AttachPoint, number> = {
307+
"left-top": 0,
308+
"left-center": 1,
309+
"left-bottom": 2,
310+
"center-top": 3,
311+
"center-center": 4,
312+
"center-bottom": 5,
313+
"right-top": 6,
314+
"right-center": 7,
315+
"right-bottom": 8,
316+
};
317+
318+
const ATTACH_TO: Record<AttachTo, number> = {
319+
none: 0,
320+
parent: 1,
321+
element: 2,
322+
root: 3,
323+
};
324+
325+
const POINTER_CAPTURE_MODE: Record<PointerCaptureMode, number> = {
326+
capture: 0,
327+
passthrough: 1,
328+
};
329+
330+
const CLIP_TO: Record<ClipTo, number> = {
331+
none: 0,
332+
"attached-parent": 1,
333+
};
334+
335+
function encodeAttachPoint(value: AttachPoint | undefined): number {
336+
return value === undefined ? 0 : ATTACH_POINT[value];
337+
}
338+
339+
function encodeAttachTo(value: AttachTo | undefined): number {
340+
return value === undefined ? 0 : ATTACH_TO[value];
341+
}
342+
343+
function encodePointerCaptureMode(
344+
value: PointerCaptureMode | undefined,
345+
): number {
346+
return value === undefined ? 0 : POINTER_CAPTURE_MODE[value];
347+
}
348+
349+
function encodeClipTo(value: ClipTo | undefined): number {
350+
return value === undefined ? 0 : CLIP_TO[value];
351+
}
317352

318353
export interface Text {
319354
directive: typeof OP_TEXT;

specs/renderer-spec.md

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -622,22 +622,44 @@ floating?: {
622622
y?: number;
623623
expand?: { width?: number; height?: number };
624624
parent?: number;
625-
attachTo?: number;
625+
attachTo?: "none" | "parent" | "element" | "root";
626626
attachPoints?: {
627-
element?: number;
628-
parent?: number;
627+
element?:
628+
| "left-top"
629+
| "left-center"
630+
| "left-bottom"
631+
| "center-top"
632+
| "center-center"
633+
| "center-bottom"
634+
| "right-top"
635+
| "right-center"
636+
| "right-bottom";
637+
parent?:
638+
| "left-top"
639+
| "left-center"
640+
| "left-bottom"
641+
| "center-top"
642+
| "center-center"
643+
| "center-bottom"
644+
| "right-top"
645+
| "right-center"
646+
| "right-bottom";
629647
};
630-
pointerCaptureMode?: number;
631-
clipTo?: number;
648+
pointerCaptureMode?: "capture" | "passthrough";
649+
clipTo?: "none" | "attached-parent";
632650
zIndex?: number;
633651
}
634652
```
635653

636-
This shape extends the earlier floating surface in two ways. First,
637-
`attachPoints` is structured as separate element and parent anchor values
638-
instead of a single packed enum. Second, the surface exposes additional Clay
639-
floating controls that were previously unavailable at the TypeScript layer:
640-
`expand`, `pointerCaptureMode`, and `clipTo`.
654+
The `floating` object configures Clay floating layout behavior. `x` and `y`
655+
provide the floating offset. `expand` expands the floating bounds. `parent`
656+
identifies the target element when `attachTo` is `"element"`. `attachTo` selects
657+
whether the element is attached to no target, its parent, an element, or the
658+
layout root. `attachPoints.element` describes the anchor on the floating
659+
element, and `attachPoints.parent` describes the anchor on the attached target.
660+
`pointerCaptureMode` controls whether the floating element captures pointer
661+
input or lets it pass through, `clipTo` controls inherited clipping, and
662+
`zIndex` controls floating order.
641663

642664
The `text()` constructor currently accepts: `color`, `fontSize`,
643665
`letterSpacing`, `lineHeight`, and attribute flags (`bold`, `italic`,

test/term.test.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
import { beforeEach, describe, expect, it } from "./suite.ts";
22
import { createTerm, type Term } from "../term.ts";
3-
import {
4-
ATTACH_POINT,
5-
ATTACH_TO,
6-
close,
7-
fixed,
8-
grow,
9-
open,
10-
rgba,
11-
text,
12-
} from "../ops.ts";
3+
import { close, fixed, grow, open, rgba, text } from "../ops.ts";
134
import { print } from "./print.ts";
145

156
const decode = (bytes: Uint8Array) => new TextDecoder().decode(bytes);
@@ -224,10 +215,10 @@ describe("term", () => {
224215
floating: {
225216
x: 3,
226217
y: 1,
227-
attachTo: ATTACH_TO.ROOT,
218+
attachTo: "root",
228219
attachPoints: {
229-
element: ATTACH_POINT.CENTER_CENTER,
230-
parent: ATTACH_POINT.CENTER_CENTER,
220+
element: "center-center",
221+
parent: "center-center",
231222
},
232223
},
233224
}),

test/validate.test.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ describe("validate", () => {
8383
expect(validate([
8484
open("x", {
8585
floating: {
86-
attachPoints: { element: 4, parent: 4 },
86+
attachPoints: { element: "center-center", parent: "center-center" },
8787
},
8888
}),
8989
close(),
@@ -95,16 +95,21 @@ describe("validate", () => {
9595
open("x", {
9696
floating: {
9797
expand: { width: 2, height: 3 },
98-
pointerCaptureMode: 1,
99-
clipTo: 1,
98+
pointerCaptureMode: "passthrough",
99+
clipTo: "attached-parent",
100100
zIndex: 1024,
101101
},
102102
}),
103103
close(),
104104
])).toBe(true);
105105
});
106106

107-
it("rejects numeric floating attachPoints legacy shape", () => {
107+
it("rejects numeric floating enum values", () => {
108+
expect(validate([
109+
// deno-lint-ignore no-explicit-any
110+
open("x", { floating: { attachTo: 3 as any } }),
111+
close(),
112+
])).toBe(false);
108113
expect(validate([
109114
// deno-lint-ignore no-explicit-any
110115
open("x", { floating: { attachPoints: 4 as any } }),

validate.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,35 @@ const Clip = Type.Object({
8080
vertical: Type.Optional(Type.Boolean()),
8181
});
8282

83+
const AttachPoint = Type.Union([
84+
Type.Literal("left-top"),
85+
Type.Literal("left-center"),
86+
Type.Literal("left-bottom"),
87+
Type.Literal("center-top"),
88+
Type.Literal("center-center"),
89+
Type.Literal("center-bottom"),
90+
Type.Literal("right-top"),
91+
Type.Literal("right-center"),
92+
Type.Literal("right-bottom"),
93+
]);
94+
95+
const AttachTo = Type.Union([
96+
Type.Literal("none"),
97+
Type.Literal("parent"),
98+
Type.Literal("element"),
99+
Type.Literal("root"),
100+
]);
101+
102+
const PointerCaptureMode = Type.Union([
103+
Type.Literal("capture"),
104+
Type.Literal("passthrough"),
105+
]);
106+
107+
const ClipTo = Type.Union([
108+
Type.Literal("none"),
109+
Type.Literal("attached-parent"),
110+
]);
111+
83112
const Floating = Type.Object({
84113
x: Type.Optional(Type.Number()),
85114
y: Type.Optional(Type.Number()),
@@ -88,13 +117,13 @@ const Floating = Type.Object({
88117
height: Type.Optional(Type.Number()),
89118
})),
90119
parent: Type.Optional(Type.Integer({ minimum: 0 })),
91-
attachTo: Type.Optional(u8),
120+
attachTo: Type.Optional(AttachTo),
92121
attachPoints: Type.Optional(Type.Object({
93-
element: Type.Optional(u8),
94-
parent: Type.Optional(u8),
122+
element: Type.Optional(AttachPoint),
123+
parent: Type.Optional(AttachPoint),
95124
})),
96-
pointerCaptureMode: Type.Optional(u8),
97-
clipTo: Type.Optional(u8),
125+
pointerCaptureMode: Type.Optional(PointerCaptureMode),
126+
clipTo: Type.Optional(ClipTo),
98127
zIndex: Type.Optional(u16),
99128
});
100129

0 commit comments

Comments
 (0)