mirror of
https://github.com/penpot/penpot.git
synced 2026-08-07 21:38:48 +00:00
🐛 Fix microinteractions on text shape selrects for autowidth/autoheight (#11068)
This commit is contained in:
parent
11fc090bc4
commit
2392015c63
@ -0,0 +1,349 @@
|
|||||||
|
{
|
||||||
|
"~:features": {
|
||||||
|
"~#set": [
|
||||||
|
"fdata/path-data",
|
||||||
|
"plugins/runtime",
|
||||||
|
"design-tokens/v1",
|
||||||
|
"layout/grid",
|
||||||
|
"styles/v2",
|
||||||
|
"fdata/pointer-map",
|
||||||
|
"fdata/objects-map",
|
||||||
|
"components/v2",
|
||||||
|
"fdata/shape-data-type",
|
||||||
|
"text-editor/v2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"~:team-id": "~u9e6e22b2-db76-81d6-8006-75d7cdbb8bad",
|
||||||
|
"~:permissions": {
|
||||||
|
"~:type": "~:membership",
|
||||||
|
"~:is-owner": true,
|
||||||
|
"~:is-admin": true,
|
||||||
|
"~:can-edit": true,
|
||||||
|
"~:can-read": true,
|
||||||
|
"~:is-logged": true
|
||||||
|
},
|
||||||
|
"~:has-media-trimmed": false,
|
||||||
|
"~:comment-thread-seqn": 0,
|
||||||
|
"~:name": "Fixed size text",
|
||||||
|
"~:revn": 3,
|
||||||
|
"~:modified-at": "~m1753957736516",
|
||||||
|
"~:vern": 0,
|
||||||
|
"~:id": "~u238a17e0-75ff-8075-8006-934586ea2230",
|
||||||
|
"~:is-shared": false,
|
||||||
|
"~:migrations": {
|
||||||
|
"~#ordered-set": [
|
||||||
|
"legacy-2",
|
||||||
|
"legacy-3",
|
||||||
|
"legacy-5",
|
||||||
|
"legacy-6",
|
||||||
|
"legacy-7",
|
||||||
|
"legacy-8",
|
||||||
|
"legacy-9",
|
||||||
|
"legacy-10",
|
||||||
|
"legacy-11",
|
||||||
|
"legacy-12",
|
||||||
|
"legacy-13",
|
||||||
|
"legacy-14",
|
||||||
|
"legacy-16",
|
||||||
|
"legacy-17",
|
||||||
|
"legacy-18",
|
||||||
|
"legacy-19",
|
||||||
|
"legacy-25",
|
||||||
|
"legacy-26",
|
||||||
|
"legacy-27",
|
||||||
|
"legacy-28",
|
||||||
|
"legacy-29",
|
||||||
|
"legacy-31",
|
||||||
|
"legacy-32",
|
||||||
|
"legacy-33",
|
||||||
|
"legacy-34",
|
||||||
|
"legacy-36",
|
||||||
|
"legacy-37",
|
||||||
|
"legacy-38",
|
||||||
|
"legacy-39",
|
||||||
|
"legacy-40",
|
||||||
|
"legacy-41",
|
||||||
|
"legacy-42",
|
||||||
|
"legacy-43",
|
||||||
|
"legacy-44",
|
||||||
|
"legacy-45",
|
||||||
|
"legacy-46",
|
||||||
|
"legacy-47",
|
||||||
|
"legacy-48",
|
||||||
|
"legacy-49",
|
||||||
|
"legacy-50",
|
||||||
|
"legacy-51",
|
||||||
|
"legacy-52",
|
||||||
|
"legacy-53",
|
||||||
|
"legacy-54",
|
||||||
|
"legacy-55",
|
||||||
|
"legacy-56",
|
||||||
|
"legacy-57",
|
||||||
|
"legacy-59",
|
||||||
|
"legacy-62",
|
||||||
|
"legacy-65",
|
||||||
|
"legacy-66",
|
||||||
|
"legacy-67",
|
||||||
|
"0001-remove-tokens-from-groups",
|
||||||
|
"0002-normalize-bool-content-v2",
|
||||||
|
"0002-clean-shape-interactions",
|
||||||
|
"0003-fix-root-shape",
|
||||||
|
"0003-convert-path-content-v2",
|
||||||
|
"0004-clean-shadow-color",
|
||||||
|
"0005-deprecate-image-type",
|
||||||
|
"0006-fix-old-texts-fills",
|
||||||
|
"0007-clear-invalid-strokes-and-fills-v2",
|
||||||
|
"0008-fix-library-colors-v4",
|
||||||
|
"0009-clean-library-colors",
|
||||||
|
"0009-add-partial-text-touched-flags"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"~:version": 67,
|
||||||
|
"~:project-id": "~u9e6e22b2-db76-81d6-8006-75d7cdc30669",
|
||||||
|
"~:created-at": "~m1753957644225",
|
||||||
|
"~:data": {
|
||||||
|
"~:pages": [
|
||||||
|
"~u238a17e0-75ff-8075-8006-934586ea2231"
|
||||||
|
],
|
||||||
|
"~:pages-index": {
|
||||||
|
"~u238a17e0-75ff-8075-8006-934586ea2231": {
|
||||||
|
"~:objects": {
|
||||||
|
"~u00000000-0000-0000-0000-000000000000": {
|
||||||
|
"~#shape": {
|
||||||
|
"~:y": 0,
|
||||||
|
"~:hide-fill-on-export": false,
|
||||||
|
"~:transform": {
|
||||||
|
"~#matrix": {
|
||||||
|
"~:a": 1.0,
|
||||||
|
"~:b": 0.0,
|
||||||
|
"~:c": 0.0,
|
||||||
|
"~:d": 1.0,
|
||||||
|
"~:e": 0.0,
|
||||||
|
"~:f": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~:rotation": 0,
|
||||||
|
"~:name": "Root Frame",
|
||||||
|
"~:width": 0.01,
|
||||||
|
"~:type": "~:frame",
|
||||||
|
"~:points": [
|
||||||
|
{
|
||||||
|
"~#point": {
|
||||||
|
"~:x": 0.0,
|
||||||
|
"~:y": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"~#point": {
|
||||||
|
"~:x": 0.01,
|
||||||
|
"~:y": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"~#point": {
|
||||||
|
"~:x": 0.01,
|
||||||
|
"~:y": 0.01
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"~#point": {
|
||||||
|
"~:x": 0.0,
|
||||||
|
"~:y": 0.01
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"~:r2": 0,
|
||||||
|
"~:proportion-lock": false,
|
||||||
|
"~:transform-inverse": {
|
||||||
|
"~#matrix": {
|
||||||
|
"~:a": 1.0,
|
||||||
|
"~:b": 0.0,
|
||||||
|
"~:c": 0.0,
|
||||||
|
"~:d": 1.0,
|
||||||
|
"~:e": 0.0,
|
||||||
|
"~:f": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~:r3": 0,
|
||||||
|
"~:r1": 0,
|
||||||
|
"~:id": "~u00000000-0000-0000-0000-000000000000",
|
||||||
|
"~:parent-id": "~u00000000-0000-0000-0000-000000000000",
|
||||||
|
"~:frame-id": "~u00000000-0000-0000-0000-000000000000",
|
||||||
|
"~:strokes": [],
|
||||||
|
"~:x": 0,
|
||||||
|
"~:proportion": 1.0,
|
||||||
|
"~:r4": 0,
|
||||||
|
"~:selrect": {
|
||||||
|
"~#rect": {
|
||||||
|
"~:x": 0,
|
||||||
|
"~:y": 0,
|
||||||
|
"~:width": 0.01,
|
||||||
|
"~:height": 0.01,
|
||||||
|
"~:x1": 0,
|
||||||
|
"~:y1": 0,
|
||||||
|
"~:x2": 0.01,
|
||||||
|
"~:y2": 0.01
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~:fills": [
|
||||||
|
{
|
||||||
|
"~:fill-color": "#FFFFFF",
|
||||||
|
"~:fill-opacity": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"~:flip-x": null,
|
||||||
|
"~:height": 0.01,
|
||||||
|
"~:flip-y": null,
|
||||||
|
"~:shapes": [
|
||||||
|
"~ucc6f0580-449c-8019-8006-9345db077fa0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~ucc6f0580-449c-8019-8006-9345db077fa0": {
|
||||||
|
"~#shape": {
|
||||||
|
"~:y": 150,
|
||||||
|
"~:transform": {
|
||||||
|
"~#matrix": {
|
||||||
|
"~:a": 1.0,
|
||||||
|
"~:b": 0.0,
|
||||||
|
"~:c": 0.0,
|
||||||
|
"~:d": 1.0,
|
||||||
|
"~:e": 0.0,
|
||||||
|
"~:f": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~:rotation": 0,
|
||||||
|
"~:grow-type": "~:fixed",
|
||||||
|
"~:content": {
|
||||||
|
"~:type": "root",
|
||||||
|
"~:key": "1s4am1jl24s",
|
||||||
|
"~:children": [
|
||||||
|
{
|
||||||
|
"~:type": "paragraph-set",
|
||||||
|
"~:children": [
|
||||||
|
{
|
||||||
|
"~:line-height": "1.2",
|
||||||
|
"~:font-style": "normal",
|
||||||
|
"~:children": [
|
||||||
|
{
|
||||||
|
"~:line-height": "1.2",
|
||||||
|
"~:font-style": "normal",
|
||||||
|
"~:typography-ref-id": null,
|
||||||
|
"~:text-transform": "none",
|
||||||
|
"~:font-id": "sourcesanspro",
|
||||||
|
"~:key": "13p0zwl2yhc",
|
||||||
|
"~:font-size": "14",
|
||||||
|
"~:font-weight": "400",
|
||||||
|
"~:typography-ref-file": null,
|
||||||
|
"~:font-variant-id": "regular",
|
||||||
|
"~:text-decoration": "none",
|
||||||
|
"~:letter-spacing": "0",
|
||||||
|
"~:fills": [
|
||||||
|
{
|
||||||
|
"~:fill-color": "#000000",
|
||||||
|
"~:fill-opacity": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"~:font-family": "sourcesanspro",
|
||||||
|
"~:text": "Lorem ipsum"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"~:typography-ref-id": null,
|
||||||
|
"~:text-transform": "none",
|
||||||
|
"~:text-align": "left",
|
||||||
|
"~:font-id": "sourcesanspro",
|
||||||
|
"~:key": "20hf3kmyoub",
|
||||||
|
"~:font-size": "14",
|
||||||
|
"~:font-weight": "400",
|
||||||
|
"~:typography-ref-file": null,
|
||||||
|
"~:text-direction": "ltr",
|
||||||
|
"~:type": "paragraph",
|
||||||
|
"~:font-variant-id": "regular",
|
||||||
|
"~:text-decoration": "none",
|
||||||
|
"~:letter-spacing": "0",
|
||||||
|
"~:fills": [
|
||||||
|
{
|
||||||
|
"~:fill-color": "#000000",
|
||||||
|
"~:fill-opacity": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"~:font-family": "sourcesanspro"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"~:vertical-align": "top"
|
||||||
|
},
|
||||||
|
"~:hide-in-viewer": false,
|
||||||
|
"~:name": "Fixed text",
|
||||||
|
"~:width": 300,
|
||||||
|
"~:type": "~:text",
|
||||||
|
"~:points": [
|
||||||
|
{
|
||||||
|
"~#point": {
|
||||||
|
"~:x": 200,
|
||||||
|
"~:y": 150
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"~#point": {
|
||||||
|
"~:x": 500,
|
||||||
|
"~:y": 150
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"~#point": {
|
||||||
|
"~:x": 500,
|
||||||
|
"~:y": 350
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"~#point": {
|
||||||
|
"~:x": 200,
|
||||||
|
"~:y": 350
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"~:transform-inverse": {
|
||||||
|
"~#matrix": {
|
||||||
|
"~:a": 1.0,
|
||||||
|
"~:b": 0.0,
|
||||||
|
"~:c": 0.0,
|
||||||
|
"~:d": 1.0,
|
||||||
|
"~:e": 0.0,
|
||||||
|
"~:f": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~:id": "~ucc6f0580-449c-8019-8006-9345db077fa0",
|
||||||
|
"~:parent-id": "~u00000000-0000-0000-0000-000000000000",
|
||||||
|
"~:frame-id": "~u00000000-0000-0000-0000-000000000000",
|
||||||
|
"~:x": 200,
|
||||||
|
"~:selrect": {
|
||||||
|
"~#rect": {
|
||||||
|
"~:x": 200,
|
||||||
|
"~:y": 150,
|
||||||
|
"~:width": 300,
|
||||||
|
"~:height": 200,
|
||||||
|
"~:x1": 200,
|
||||||
|
"~:y1": 150,
|
||||||
|
"~:x2": 500,
|
||||||
|
"~:y2": 350
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~:flip-x": null,
|
||||||
|
"~:height": 200,
|
||||||
|
"~:flip-y": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~:id": "~u238a17e0-75ff-8075-8006-934586ea2231",
|
||||||
|
"~:name": "Page 1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"~:id": "~u238a17e0-75ff-8075-8006-934586ea2230",
|
||||||
|
"~:options": {
|
||||||
|
"~:components-v2": true,
|
||||||
|
"~:base-font-size": "16px"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,7 +9,9 @@ const FILE = {
|
|||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await WasmWorkspacePage.init(page);
|
await WasmWorkspacePage.init(page);
|
||||||
// WASM_FLAGS already enables render-wasm; add the WASM text editor on top.
|
// WASM_FLAGS already enables render-wasm; add the WASM text editor on top.
|
||||||
await WasmWorkspacePage.mockConfigFlags(page, ["enable-feature-text-editor-wasm"]);
|
await WasmWorkspacePage.mockConfigFlags(page, [
|
||||||
|
"enable-feature-text-editor-wasm",
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function openEditorAndSelectAll(workspace) {
|
async function openEditorAndSelectAll(workspace) {
|
||||||
@ -22,12 +24,12 @@ async function openEditorAndSelectAll(workspace) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test.describe("BUG 10502 - Mixed families and variants", () => {
|
test.describe("BUG 10502 - Mixed families and variants", () => {
|
||||||
test("Multiple variants of the same font family", async ({
|
test("Multiple variants of the same font family", async ({ page }) => {
|
||||||
page,
|
|
||||||
}) => {
|
|
||||||
const workspace = new WasmWorkspacePage(page, { textEditor: true });
|
const workspace = new WasmWorkspacePage(page, { textEditor: true });
|
||||||
await workspace.setupEmptyFile();
|
await workspace.setupEmptyFile();
|
||||||
await workspace.mockGetFile("text-editor/get-file-10502-mixed-variants.json");
|
await workspace.mockGetFile(
|
||||||
|
"text-editor/get-file-10502-mixed-variants.json",
|
||||||
|
);
|
||||||
|
|
||||||
await workspace.goToWorkspace(FILE);
|
await workspace.goToWorkspace(FILE);
|
||||||
await workspace.waitForFirstRender();
|
await workspace.waitForFirstRender();
|
||||||
@ -47,10 +49,14 @@ test.describe("BUG 10502 - Mixed families and variants", () => {
|
|||||||
await expect(fontVariant).toHaveText("--");
|
await expect(fontVariant).toHaveText("--");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Mixed font families appear as such in the dropdown", async ({ page }) => {
|
test("Mixed font families appear as such in the dropdown", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
const workspace = new WasmWorkspacePage(page, { textEditor: true });
|
const workspace = new WasmWorkspacePage(page, { textEditor: true });
|
||||||
await workspace.setupEmptyFile();
|
await workspace.setupEmptyFile();
|
||||||
await workspace.mockGetFile("text-editor/get-file-10502-mixed-families.json");
|
await workspace.mockGetFile(
|
||||||
|
"text-editor/get-file-10502-mixed-families.json",
|
||||||
|
);
|
||||||
// Serve a stand-in TTF for Sora so the render doesn't wait on a real fetch.
|
// Serve a stand-in TTF for Sora so the render doesn't wait on a real fetch.
|
||||||
// Glyphs are irrelevant here: the assertion only inspects the sidebar.
|
// Glyphs are irrelevant here: the assertion only inspects the sidebar.
|
||||||
await workspace.mockGoogleFont("sora", "render-wasm/assets/ebgaramond.ttf");
|
await workspace.mockGoogleFont("sora", "render-wasm/assets/ebgaramond.ttf");
|
||||||
@ -204,9 +210,94 @@ test("BUG 10531 - Entering the editor auto-selects the whole text", async ({
|
|||||||
await workspace.copy("keyboard");
|
await workspace.copy("keyboard");
|
||||||
|
|
||||||
// Assert the text was copied correctly
|
// Assert the text was copied correctly
|
||||||
const copiedText = await page.evaluate(() =>
|
const copiedText = await page.evaluate(() => navigator.clipboard.readText());
|
||||||
navigator.clipboard.readText(),
|
|
||||||
);
|
|
||||||
expect(copiedText).toBe("Lorem ipsum");
|
expect(copiedText).toBe("Lorem ipsum");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.describe("BUG 10934 - Double-clicking a text side handle sets auto-size", () => {
|
||||||
|
// Sets up the workspace and loads a text shape whose size is larger than its text
|
||||||
|
async function setupFixedSizeText(page) {
|
||||||
|
const workspace = new WasmWorkspacePage(page, { textEditor: true });
|
||||||
|
// Enable token inputs so they use the new component with accessible DOM
|
||||||
|
await workspace.mockConfigFlags(["enable-feature-token-input"]);
|
||||||
|
await workspace.setupEmptyFile();
|
||||||
|
await workspace.mockGetFile("text-editor/get-file-fixed-size-text.json");
|
||||||
|
await workspace.goToWorkspace();
|
||||||
|
await workspace.waitForFirstRender();
|
||||||
|
|
||||||
|
// Select the text and zoom to fit, so it is fully visible in the viewport
|
||||||
|
await workspace.clickLeafLayer("Fixed text");
|
||||||
|
await page.keyboard.press("Shift+1");
|
||||||
|
await workspace.waitForIdle();
|
||||||
|
|
||||||
|
return workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doubleClickSideHandle(workspace, position) {
|
||||||
|
const handle = workspace.viewport.getByTestId(
|
||||||
|
`resize-side-handler-${position}`,
|
||||||
|
);
|
||||||
|
await handle.waitFor();
|
||||||
|
const box = await handle.boundingBox();
|
||||||
|
await workspace.page.mouse.dblclick(
|
||||||
|
box.x + box.width / 2,
|
||||||
|
box.y + box.height / 2,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function measureInput(workspace, name) {
|
||||||
|
return workspace.rightSidebar
|
||||||
|
.getByRole("region", { name: "shape-measures-section" })
|
||||||
|
.getByRole("textbox", { name, exact: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
test("Double-clicking the right handle switches to auto-width", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const workspace = await setupFixedSizeText(page);
|
||||||
|
|
||||||
|
const widthInput = workspace.rightSidebar
|
||||||
|
.getByRole("region", { name: "shape-measures-section" })
|
||||||
|
.getByRole("textbox", { name: "Width", exact: true });
|
||||||
|
const initialWidth = Number(await widthInput.inputValue());
|
||||||
|
|
||||||
|
await doubleClickSideHandle(workspace, "right");
|
||||||
|
|
||||||
|
// Assert auto-width is selected and that the width has shrunk. The resize
|
||||||
|
// is debounced, so poll the value (auto-retrying) rather than reading once.
|
||||||
|
await expect(
|
||||||
|
workspace.rightSidebar.getByRole("button", {
|
||||||
|
name: "Auto width",
|
||||||
|
pressed: true,
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect
|
||||||
|
.poll(async () => Number(await widthInput.inputValue()))
|
||||||
|
.toBeLessThan(initialWidth);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Double-clicking the bottom handle switches to auto-height", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
|
const workspace = await setupFixedSizeText(page);
|
||||||
|
|
||||||
|
const heightInput = workspace.rightSidebar
|
||||||
|
.getByRole("region", { name: "shape-measures-section" })
|
||||||
|
.getByRole("textbox", { name: "Height", exact: true });
|
||||||
|
const initialHeight = Number(await heightInput.inputValue());
|
||||||
|
|
||||||
|
await doubleClickSideHandle(workspace, "bottom");
|
||||||
|
|
||||||
|
// Assert auto-height is selected and that the height has shrunk. The resize
|
||||||
|
// is debounced, so poll the value (auto-retrying) rather than reading once.
|
||||||
|
await expect(
|
||||||
|
workspace.rightSidebar.getByRole("button", {
|
||||||
|
name: "Auto height",
|
||||||
|
pressed: true,
|
||||||
|
}),
|
||||||
|
).toBeVisible();
|
||||||
|
await expect
|
||||||
|
.poll(async () => Number(await heightInput.inputValue()))
|
||||||
|
.toBeLessThan(initialHeight);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
[app.main.data.helpers :as dsh]
|
[app.main.data.helpers :as dsh]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.shapes :as dwsh]
|
[app.main.data.workspace.shapes :as dwsh]
|
||||||
|
[app.main.data.workspace.wasm-text :as dwwt]
|
||||||
|
[app.main.features :as features]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.context :as ctx]
|
[app.main.ui.context :as ctx]
|
||||||
@ -26,6 +28,7 @@
|
|||||||
[app.util.debug :as dbg]
|
[app.util.debug :as dbg]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
|
[potok.v2.core :as ptk]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def rotation-handler-size 20)
|
(def rotation-handler-size 20)
|
||||||
@ -295,13 +298,20 @@
|
|||||||
on-double-click
|
on-double-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps shape-id position shape-type)
|
(mf/deps shape-id position shape-type)
|
||||||
(fn [_event]
|
(fn [event]
|
||||||
(when (= shape-type :text)
|
(when (= shape-type :text)
|
||||||
(cond
|
;; Prevent the viewport double-click handler from entering text editor
|
||||||
(= position :right)
|
(dom/stop-propagation event)
|
||||||
(st/emit! (dwsh/update-shapes [shape-id] #(assoc % :grow-type :auto-width)))
|
(let [grow-type (case position
|
||||||
(= position :bottom)
|
:right :auto-width
|
||||||
(st/emit! (dwsh/update-shapes [shape-id] #(assoc % :grow-type :auto-height)))))))]
|
:bottom :auto-height
|
||||||
|
nil)]
|
||||||
|
(when (some? grow-type)
|
||||||
|
(st/emit! (dwsh/update-shapes [shape-id] #(assoc % :grow-type grow-type)))
|
||||||
|
;; The WASM renderer needs an explicit reflow after the grow-type change
|
||||||
|
(when (features/active-feature? @st/state "render-wasm/v1")
|
||||||
|
(st/emit! (dwwt/resize-wasm-text-all [shape-id])
|
||||||
|
(ptk/data-event :layout/update {:ids [shape-id]}))))))))]
|
||||||
|
|
||||||
[:g.resize-handler
|
[:g.resize-handler
|
||||||
(when ^boolean show-handler
|
(when ^boolean show-handler
|
||||||
@ -321,6 +331,7 @@
|
|||||||
:height height
|
:height height
|
||||||
:class cursor
|
:class cursor
|
||||||
:data-position (name position)
|
:data-position (name position)
|
||||||
|
:data-testid (dm/str "resize-side-handler-" (name position))
|
||||||
:transform transform-str
|
:transform transform-str
|
||||||
:on-pointer-down on-resize
|
:on-pointer-down on-resize
|
||||||
:on-double-click on-double-click
|
:on-double-click on-double-click
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user