diff --git a/.changeset/tidy-lemons-bow.md b/.changeset/tidy-lemons-bow.md new file mode 100644 index 0000000000..f360fe0bf5 --- /dev/null +++ b/.changeset/tidy-lemons-bow.md @@ -0,0 +1,8 @@ +--- +"@lynx-js/web-mainthread-apis": patch +"@lynx-js/web-core": patch +--- + +feat: support mts event with target methods + +After this commit, developers are allowed to invoke `event.target.setStyleProperty` in mts handler diff --git a/packages/web-platform/web-constants/src/types/EventType.ts b/packages/web-platform/web-constants/src/types/EventType.ts index 87cef778d1..0913d96661 100644 --- a/packages/web-platform/web-constants/src/types/EventType.ts +++ b/packages/web-platform/web-constants/src/types/EventType.ts @@ -31,6 +31,17 @@ export interface LynxCrossThreadEvent< [key: string]: string | number | undefined | null | {}; } +export interface MainThreadScriptEvent< + T = { + [key: string]: string | number | undefined | null; + }, +> extends LynxCrossThreadEvent { + target: LynxCrossThreadEventTarget & { elementRefptr: unknown }; + currentTarget: + | (LynxCrossThreadEventTarget & { elementRefptr: unknown }) + | null; +} + export type ExposureEventDetail = { 'exposure-id': string; 'exposure-scene': string; diff --git a/packages/web-platform/web-mainthread-apis/src/elementAPI/event/eventFunctions.ts b/packages/web-platform/web-mainthread-apis/src/elementAPI/event/eventFunctions.ts index aa497e9ac5..9ca70176b7 100644 --- a/packages/web-platform/web-mainthread-apis/src/elementAPI/event/eventFunctions.ts +++ b/packages/web-platform/web-mainthread-apis/src/elementAPI/event/eventFunctions.ts @@ -8,6 +8,7 @@ import { lynxTagAttribute, W3cEventNameToLynx, type LynxEventType, + type MainThreadScriptEvent, } from '@lynx-js/web-constants'; import { elementToRuntimeInfoMap, @@ -30,12 +31,12 @@ export function createEventFunctions(runtime: MainThreadRuntime) { ?.handler : runtimeInfo.eventHandlerMap[lynxEventName]?.bind ?.handler; + const crossThreadEvent = createCrossThreadEvent( + runtime, + event, + lynxEventName, + ); if (typeof hname === 'string') { - const crossThreadEvent = createCrossThreadEvent( - runtime, - event, - lynxEventName, - ); const parentComponentUniqueId = runtimeInfo.parentComponentUniqueId; const parentComponent = runtime[getElementByUniqueId]( Number(parentComponentUniqueId), @@ -58,7 +59,13 @@ export function createEventFunctions(runtime: MainThreadRuntime) { } return true; } else if (hname) { - runtime.runWorklet?.(hname.value, []); + (crossThreadEvent as MainThreadScriptEvent).target.elementRefptr = + event.target; + if (crossThreadEvent.currentTarget) { + (crossThreadEvent as MainThreadScriptEvent).currentTarget! + .elementRefptr = event.currentTarget; + } + runtime.runWorklet?.(hname.value, [crossThreadEvent]); } return false; }; diff --git a/packages/web-platform/web-mainthread-apis/src/elementAPI/style/styleFunctions.ts b/packages/web-platform/web-mainthread-apis/src/elementAPI/style/styleFunctions.ts index e844206be7..5840a4da30 100644 --- a/packages/web-platform/web-mainthread-apis/src/elementAPI/style/styleFunctions.ts +++ b/packages/web-platform/web-mainthread-apis/src/elementAPI/style/styleFunctions.ts @@ -66,13 +66,18 @@ export function createStyleFunctions( key: number | string, value: string | number | null | undefined, ): void { - const lynxStyleInfo = queryCSSProperty(Number(key)); + let dashName: string | undefined; + if (typeof key === 'number') { + dashName = queryCSSProperty(key).dashName; + } else { + dashName = key; + } const valueStr = typeof value === 'number' ? value.toString() : value; if (!valueStr) { // null or undefined - element.style.removeProperty(lynxStyleInfo.dashName); + element.style.removeProperty(dashName); } else { const { transformedStyle } = transfromParsedStyles([[ - lynxStyleInfo.dashName, + dashName, valueStr, ]]); for (const [property, value] of transformedStyle) { diff --git a/packages/web-platform/web-tests/tests/main-thread-apis.test.ts b/packages/web-platform/web-tests/tests/main-thread-apis.test.ts index 299b5c1bce..db20db0269 100644 --- a/packages/web-platform/web-tests/tests/main-thread-apis.test.ts +++ b/packages/web-platform/web-tests/tests/main-thread-apis.test.ts @@ -518,6 +518,16 @@ test.describe('main thread api tests', () => { await expect(pageElement).toHaveCSS('height', '80px'); }); + test('__AddInlineStyle_key_is_name', async ({ page }, { title }) => { + await page.evaluate(() => { + let root = globalThis.__CreatePage('page', 0); + globalThis.__AddInlineStyle(root, 'height', '80px'); + globalThis.__FlushElementTree(); + }); + const pageElement = page.locator(`[lynx-tag='page']`); + await expect(pageElement).toHaveCSS('height', '80px'); + }); + test('__AddInlineStyle_raw_string', async ({ page }, { title }) => { await page.evaluate(() => { let root = globalThis.__CreatePage('page', 0); diff --git a/packages/web-platform/web-tests/tests/react.spec.ts b/packages/web-platform/web-tests/tests/react.spec.ts index b7b9a61cc8..af01a05889 100644 --- a/packages/web-platform/web-tests/tests/react.spec.ts +++ b/packages/web-platform/web-tests/tests/react.spec.ts @@ -281,6 +281,16 @@ test.describe('reactlynx3 tests', () => { await wait(100); expect(eventHandlerTriggered).toBe(true); }); + test( + 'basic-mts-bindtap-change-element-background', + async ({ page }, { title }) => { + await goto(page, title); + await wait(100); + const target = page.locator('#target'); + await target.click(); + await expect(target).toHaveCSS('background-color', 'rgb(0, 128, 0)'); // green + }, + ); }); test.describe('basic-css', () => { test('basic-css-asset-in-css', async ({ page }, { title }) => { diff --git a/packages/web-platform/web-tests/tests/react/basic-mts-bindtap-change-element-background/index.jsx b/packages/web-platform/web-tests/tests/react/basic-mts-bindtap-change-element-background/index.jsx new file mode 100644 index 0000000000..a5397986e7 --- /dev/null +++ b/packages/web-platform/web-tests/tests/react/basic-mts-bindtap-change-element-background/index.jsx @@ -0,0 +1,21 @@ +// Copyright 2023 The Lynx Authors. All rights reserved. +// Licensed under the Apache License Version 2.0 that can be found in the +// LICENSE file in the root directory of this source tree. +import { root } from '@lynx-js/react'; +function App() { + return ( + { + 'main thread'; + event.currentTarget.setStyleProperty('background-color', 'green'); + }} + style={{ + height: '100px', + width: '100px', + background: 'pink', + }} + /> + ); +} +root.render();