Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@

#### :house: Internal

- Developer playground: Make panes resizable with wrapping text. https://github.com/rescript-lang/rescript/pull/8628
- Merge the duplicate Lam intermediate representation into Lambda, removing the conversion layer and obsolete supporting infrastructure. Lambda is now a single private, normalized representation, with generated JavaScript remaining semantically unchanged. https://github.com/rescript-lang/rescript/pull/8608
- Add genType and source map controls and output to the developer playground. https://github.com/rescript-lang/rescript/pull/8448
- Rework the object-type representation end to end: object rows are plain field chains carrying a per-field mutability state (no phantom setter members), object literals are typed directly and property access and assignment are first-class AST and Lambda nodes shared between the Lambda and JS pipelines, and dead class-system remnants (the field-presence lattice, the class-abbreviation memo on object types, method-send typing) are removed. https://github.com/rescript-lang/rescript/pull/8597
Expand Down
2 changes: 1 addition & 1 deletion packages/dev-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"prepare-pages-site": "node scripts/prepare-pages-site.mjs",
"res:build": "rescript",
"res:watch": "rescript -w",
"test": "rescript && node --test scripts/source-map-navigation.test.mjs",
"test": "rescript && node --test scripts/source-map-navigation.test.mjs scripts/pane-layout.test.mjs",
"dev": "vite --host 127.0.0.1",
"build": "rescript && vite build",
"preview": "vite preview --host 127.0.0.1"
Expand Down
64 changes: 64 additions & 0 deletions packages/dev-playground/scripts/pane-layout.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import assert from "node:assert/strict";
import test from "node:test";

import {
current,
finishDrag,
make,
moveDrag,
nudge,
orientationForWidth,
ratioForPosition,
setOrientation,
startDrag,
} from "../src/PaneLayout.res.mjs";

const closeTo = (actual, expected) =>
assert.ok(
Math.abs(actual - expected) < 0.000001,
`${actual} is not close to ${expected}`,
);

test("switches to stacked panes from the container width", () => {
assert.equal(orientationForWidth(901), "Columns");
assert.equal(orientationForWidth(900), "Rows");
});

test("calculates a divider ratio and respects both pane minimums", () => {
closeTo(ratioForPosition(500, 1000, 360, 420), 0.5);
closeTo(ratioForPosition(0, 1000, 360, 420), 360 / 992);
closeTo(ratioForPosition(1000, 1000, 360, 420), 1 - 420 / 992);
closeTo(ratioForPosition(100, 300, 180, 180), 0.5);
});

test("keeps drag and ratio state isolated between layout instances", () => {
const first = make();
const second = make();

assert.notEqual(first.containerId, second.containerId);
startDrag(first, 7, 600, 1000, 360, 420);

assert.equal(current(first).dragging, true);
assert.equal(current(second).dragging, false);
assert.equal(current(second).columnRatio, 0.5);

const draggedRatio = current(first).columnRatio;
moveDrag(first, 8, 450);
assert.equal(current(first).columnRatio, draggedRatio);
finishDrag(first, 8);
assert.equal(current(first).dragging, true);
finishDrag(first, 7);
assert.equal(current(first).dragging, false);
});

test("stores independent ratios for columns and stacked rows", () => {
const layout = make();

nudge(layout, 0.025, 1000, 360, 420);
closeTo(current(layout).columnRatio, 0.525);

setOrientation(layout, orientationForWidth(600));
nudge(layout, -0.025, 800, 180, 180);
closeTo(current(layout).columnRatio, 0.525);
closeTo(current(layout).rowRatio, 0.475);
});
50 changes: 45 additions & 5 deletions packages/dev-playground/src/Bindings.res
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,13 @@ module Url = {

module Event = {
@get external target: Dom.event => {..} = "target"
@get external currentTarget: Dom.event => Dom.element = "currentTarget"
@get external key: Dom.event => string = "key"
@get external button: Dom.event => int = "button"
@get external clientX: Dom.event => float = "clientX"
@get external clientY: Dom.event => float = "clientY"
@get external pointerId: Dom.event => int = "pointerId"
@get external detail: Dom.event => int = "detail"
@send external preventDefault: Dom.event => unit = "preventDefault"

let value = (event: Dom.event): string => (event->target)["value"]
Expand All @@ -129,11 +135,6 @@ module Event = {
let scrollTop: float = (event->target)["scrollTop"]
scrollTop->Math.round->Float.toInt
}

let scrollLeft = (event: Dom.event): int => {
let scrollLeft: float = (event->target)["scrollLeft"]
scrollLeft->Math.round->Float.toInt
}
}

module EventTarget = {
Expand All @@ -150,6 +151,7 @@ module EventTarget = {
module CssStyle = {
type t

@send external setProperty: (t, string, string) => unit = "setProperty"
@set external setPosition: (t, string) => unit = "position"
@set external setTop: (t, string) => unit = "top"
@set external setLeft: (t, string) => unit = "left"
Expand All @@ -160,6 +162,20 @@ type scrollIntoViewOptions = {
inline: string,
}

type boundingRect = {
left: float,
top: float,
width: float,
height: float,
}

type classList

module ClassList = {
@send external add: (classList, string) => unit = "add"
@send external remove: (classList, string) => unit = "remove"
}

module Element = {
@send external setAttribute: (Dom.element, string, string) => unit = "setAttribute"
@send
Expand All @@ -170,6 +186,15 @@ module Element = {
@send external appendChild: (Dom.element, Dom.element) => unit = "appendChild"
@send external removeChild: (Dom.element, Dom.element) => unit = "removeChild"
@send external focus: Dom.element => unit = "focus"
@send external setPointerCapture: (Dom.element, int) => unit = "setPointerCapture"
@send external releasePointerCapture: (Dom.element, int) => unit = "releasePointerCapture"
@send external hasPointerCapture: (Dom.element, int) => bool = "hasPointerCapture"
@send external getBoundingClientRect: Dom.element => boundingRect = "getBoundingClientRect"
@get external classList: Dom.element => classList = "classList"
@send @return(nullable)
external querySelector: (Dom.element, string) => option<Dom.element> = "querySelector"
@get @return(nullable)
external parentElement: Dom.element => option<Dom.element> = "parentElement"
@send
external scrollIntoView: (Dom.element, scrollIntoViewOptions) => unit = "scrollIntoView"
@get external style: Dom.element => CssStyle.t = "style"
Expand All @@ -181,6 +206,20 @@ module Element = {
"__devPlaygroundScrollHandler"
}

type resizeObserver
type resizeObserverEntry

module ResizeObserverEntry = {
@get external contentRect: resizeObserverEntry => boundingRect = "contentRect"
}

module ResizeObserver = {
@val external supported: option<unknown> = "globalThis.ResizeObserver"
@new external make: (array<resizeObserverEntry> => unit) => resizeObserver = "ResizeObserver"
@send external observe: (resizeObserver, Dom.element) => unit = "observe"
@send external disconnect: resizeObserver => unit = "disconnect"
}

module ScriptElement = {
@set external setSrc: (Dom.element, string) => unit = "src"
@set external setAsync: (Dom.element, bool) => unit = "async"
Expand All @@ -193,6 +232,7 @@ module TextAreaElement = {
@send external select: Dom.element => unit = "select"
@send external setSelectionRange: (Dom.element, int, int) => unit = "setSelectionRange"
@get external clientHeight: Dom.element => int = "clientHeight"
@get external clientWidth: Dom.element => int = "clientWidth"
@get external scrollTop: Dom.element => int = "scrollTop"
@set external setScrollTop: (Dom.element, int) => unit = "scrollTop"
}
Expand Down
Loading
Loading