diff --git a/custom-elements-manifest.config.js b/custom-elements-manifest.config.js index d2c73153c..e9b941472 100644 --- a/custom-elements-manifest.config.js +++ b/custom-elements-manifest.config.js @@ -116,6 +116,7 @@ export default { if (classDoc?.events) { classDoc.events.forEach(event => { event.reactName = `on${pascalCase(event.name)}`; + event.eventName = `${pascalCase(event.name)}Event`; }); } } diff --git a/docs/pages/frameworks/react.md b/docs/pages/frameworks/react.md index 5084bd158..b4a91473c 100644 --- a/docs/pages/frameworks/react.md +++ b/docs/pages/frameworks/react.md @@ -83,6 +83,25 @@ function MyComponent() { export default MyComponent; ``` +You can also import the event type for use in your callbacks, shown below. + +```tsx +import { useCallback, useState } from 'react'; +import { SlInput, SlInputEvent } from '@shoelace-style/shoelace/%NPMDIR%/react'; +import type SlInputElement from '@shoelace-style/shoelace/%NPMDIR%/components/input/input'; + +function MyComponent() { + const [value, setValue] = useState(''); + const onInput = useCallback((event: SlInputEvent) => { + setValue(event.detail); + }, []); + + return setValue((event.target as SlInputElement).value)} />; +} + +export default MyComponent; +``` + ## Testing with Jest Testing with web components can be challenging if your test environment runs in a Node environment (i.e. it doesn't run in a real browser). Fortunately, [Jest](https://jestjs.io/) has made a number of strides to support web components and provide additional browser APIs. However, it's still not a complete replication of a browser environment. diff --git a/scripts/make-react.js b/scripts/make-react.js index d56491de4..da7691f39 100644 --- a/scripts/make-react.js +++ b/scripts/make-react.js @@ -25,7 +25,14 @@ components.map(component => { const componentDir = path.join(reactDir, tagWithoutPrefix); const componentFile = path.join(componentDir, 'index.ts'); const importPath = component.path; - const events = (component.events || []).map(event => `${event.reactName}: '${event.name}'`).join(',\n'); + const eventImports = (component.events || []) + .map(event => `import { ${event.eventName} } from '../../../src/events/events';`) + .join('\n'); + const eventNameImport = + (component.events || []).length > 0 ? `import { type EventName } from '@lit-labs/react';` : ``; + const events = (component.events || []) + .map(event => `${event.reactName}: '${event.name}' as EventName<${event.eventName}>`) + .join(',\n'); fs.mkdirSync(componentDir, { recursive: true }); @@ -35,6 +42,9 @@ components.map(component => { import { createComponent } from '@lit-labs/react'; import Component from '../../${importPath}'; + ${eventNameImport} + ${eventImports} + export default createComponent({ tagName: '${component.tagName}', elementClass: Component, diff --git a/src/events/events.ts b/src/events/events.ts index 400c3ab62..913ee9870 100644 --- a/src/events/events.ts +++ b/src/events/events.ts @@ -28,7 +28,7 @@ export type { default as SlResizeEvent } from './sl-resize'; export type { default as SlSelectEvent } from './sl-select'; export type { default as SlSelectionChangeEvent } from './sl-selection-change'; export type { default as SlShowEvent } from './sl-show'; -export type { default as SlSlideChange } from './sl-slide-change'; +export type { default as SlSlideChangeEvent } from './sl-slide-change'; export type { default as SlStartEvent } from './sl-start'; export type { default as SlTabHideEvent } from './sl-tab-hide'; export type { default as SlTabShowEvent } from './sl-tab-show'; diff --git a/src/events/sl-slide-change.ts b/src/events/sl-slide-change.ts index cbbc2902a..36d545b81 100644 --- a/src/events/sl-slide-change.ts +++ b/src/events/sl-slide-change.ts @@ -1,11 +1,11 @@ import type SlCarouselItem from '../components/carousel-item/carousel-item'; -type SlSlideChange = CustomEvent<{ index: number; slide: SlCarouselItem }>; +type SlSlideChangeEvent = CustomEvent<{ index: number; slide: SlCarouselItem }>; declare global { interface GlobalEventHandlersEventMap { - 'sl-slide-change': SlSlideChange; + 'sl-slide-change': SlSlideChangeEvent; } } -export default SlSlideChange; +export default SlSlideChangeEvent;