-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(medium): adding react and vue examples
- Loading branch information
1 parent
5cf52ad
commit cff4418
Showing
12 changed files
with
714 additions
and
1 deletion.
There are no files selected for viewing
10 changes: 10 additions & 0 deletions
10
packages/components/medium/react/src/components/stencil-generated/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* eslint-disable */ | ||
/* tslint:disable */ | ||
/* auto-generated react proxies */ | ||
import { createReactComponent } from './react-component-lib'; | ||
|
||
import type { JSX } from '@ovhcloud/ods-component-medium/custom-elements'; | ||
|
||
import { defineCustomElement as defineOsdsMedium } from '@ovhcloud/ods-component-medium/custom-elements/osds-medium.js'; | ||
|
||
export const OsdsMedium = /*@__PURE__*/createReactComponent<JSX.OsdsMedium, HTMLOsdsMediumElement>('osds-medium', undefined, undefined, defineOsdsMedium); |
106 changes: 106 additions & 0 deletions
106
...nts/medium/react/src/components/stencil-generated/react-component-lib/createComponent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import React, { createElement } from 'react'; | ||
|
||
import { attachProps, camelToDashCase, createForwardRef, dashToPascalCase, isCoveredByReact, mergeRefs } from './utils'; | ||
|
||
export interface HTMLStencilElement extends HTMLElement { | ||
componentOnReady(): Promise<this>; | ||
} | ||
|
||
interface StencilReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> { | ||
forwardedRef: React.RefObject<ElementType>; | ||
ref?: React.Ref<any>; | ||
} | ||
|
||
export const createReactComponent = < | ||
PropType, | ||
ElementType extends HTMLStencilElement, | ||
ContextStateType = {}, | ||
ExpandedPropsTypes = {} | ||
>( | ||
tagName: string, | ||
ReactComponentContext?: React.Context<ContextStateType>, | ||
manipulatePropsFunction?: ( | ||
originalProps: StencilReactInternalProps<ElementType>, | ||
propsToPass: any | ||
) => ExpandedPropsTypes, | ||
defineCustomElement?: () => void | ||
) => { | ||
if (defineCustomElement !== undefined) { | ||
defineCustomElement(); | ||
} | ||
|
||
const displayName = dashToPascalCase(tagName); | ||
const ReactComponent = class extends React.Component<StencilReactInternalProps<ElementType>> { | ||
componentEl!: ElementType; | ||
|
||
setComponentElRef = (element: ElementType) => { | ||
this.componentEl = element; | ||
}; | ||
|
||
constructor(props: StencilReactInternalProps<ElementType>) { | ||
super(props); | ||
} | ||
|
||
componentDidMount() { | ||
this.componentDidUpdate(this.props); | ||
} | ||
|
||
componentDidUpdate(prevProps: StencilReactInternalProps<ElementType>) { | ||
attachProps(this.componentEl, this.props, prevProps); | ||
} | ||
|
||
render() { | ||
const { children, forwardedRef, style, className, ref, ...cProps } = this.props; | ||
|
||
let propsToPass = Object.keys(cProps).reduce((acc: any, name) => { | ||
const value = (cProps as any)[name]; | ||
|
||
if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) { | ||
const eventName = name.substring(2).toLowerCase(); | ||
if (typeof document !== 'undefined' && isCoveredByReact(eventName)) { | ||
acc[name] = value; | ||
} | ||
} else { | ||
// we should only render strings, booleans, and numbers as attrs in html. | ||
// objects, functions, arrays etc get synced via properties on mount. | ||
const type = typeof value; | ||
|
||
if (type === 'string' || type === 'boolean' || type === 'number') { | ||
acc[camelToDashCase(name)] = value; | ||
} | ||
} | ||
return acc; | ||
}, {} as ExpandedPropsTypes); | ||
|
||
if (manipulatePropsFunction) { | ||
propsToPass = manipulatePropsFunction(this.props, propsToPass); | ||
} | ||
|
||
const newProps: Omit<StencilReactInternalProps<ElementType>, 'forwardedRef'> = { | ||
...propsToPass, | ||
ref: mergeRefs(forwardedRef, this.setComponentElRef), | ||
style, | ||
}; | ||
|
||
/** | ||
* We use createElement here instead of | ||
* React.createElement to work around a | ||
* bug in Vite (https://github.com/vitejs/vite/issues/6104). | ||
* React.createElement causes all elements to be rendered | ||
* as <tagname> instead of the actual Web Component. | ||
*/ | ||
return createElement(tagName, newProps, children); | ||
} | ||
|
||
static get displayName() { | ||
return displayName; | ||
} | ||
}; | ||
|
||
// If context was passed to createReactComponent then conditionally add it to the Component Class | ||
if (ReactComponentContext) { | ||
ReactComponent.contextType = ReactComponentContext; | ||
} | ||
|
||
return createForwardRef<PropType, ElementType>(ReactComponent, displayName); | ||
}; |
142 changes: 142 additions & 0 deletions
142
...ium/react/src/components/stencil-generated/react-component-lib/createOverlayComponent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
|
||
import { OverlayEventDetail } from './interfaces'; | ||
import { StencilReactForwardedRef, attachProps, dashToPascalCase, defineCustomElement, setRef } from './utils'; | ||
|
||
interface OverlayElement extends HTMLElement { | ||
present: () => Promise<void>; | ||
dismiss: (data?: any, role?: string | undefined) => Promise<boolean>; | ||
} | ||
|
||
export interface ReactOverlayProps { | ||
children?: React.ReactNode; | ||
isOpen: boolean; | ||
onDidDismiss?: (event: CustomEvent<OverlayEventDetail>) => void; | ||
onDidPresent?: (event: CustomEvent<OverlayEventDetail>) => void; | ||
onWillDismiss?: (event: CustomEvent<OverlayEventDetail>) => void; | ||
onWillPresent?: (event: CustomEvent<OverlayEventDetail>) => void; | ||
} | ||
|
||
export const createOverlayComponent = <OverlayComponent extends object, OverlayType extends OverlayElement>( | ||
tagName: string, | ||
controller: { create: (options: any) => Promise<OverlayType> }, | ||
customElement?: any | ||
) => { | ||
defineCustomElement(tagName, customElement); | ||
|
||
const displayName = dashToPascalCase(tagName); | ||
const didDismissEventName = `on${displayName}DidDismiss`; | ||
const didPresentEventName = `on${displayName}DidPresent`; | ||
const willDismissEventName = `on${displayName}WillDismiss`; | ||
const willPresentEventName = `on${displayName}WillPresent`; | ||
|
||
type Props = OverlayComponent & | ||
ReactOverlayProps & { | ||
forwardedRef?: StencilReactForwardedRef<OverlayType>; | ||
}; | ||
|
||
let isDismissing = false; | ||
|
||
class Overlay extends React.Component<Props> { | ||
overlay?: OverlayType; | ||
el!: HTMLDivElement; | ||
|
||
constructor(props: Props) { | ||
super(props); | ||
if (typeof document !== 'undefined') { | ||
this.el = document.createElement('div'); | ||
} | ||
this.handleDismiss = this.handleDismiss.bind(this); | ||
} | ||
|
||
static get displayName() { | ||
return displayName; | ||
} | ||
|
||
componentDidMount() { | ||
if (this.props.isOpen) { | ||
this.present(); | ||
} | ||
} | ||
|
||
componentWillUnmount() { | ||
if (this.overlay) { | ||
this.overlay.dismiss(); | ||
} | ||
} | ||
|
||
handleDismiss(event: CustomEvent<OverlayEventDetail<any>>) { | ||
if (this.props.onDidDismiss) { | ||
this.props.onDidDismiss(event); | ||
} | ||
setRef(this.props.forwardedRef, null); | ||
} | ||
|
||
shouldComponentUpdate(nextProps: Props) { | ||
// Check if the overlay component is about to dismiss | ||
if (this.overlay && nextProps.isOpen !== this.props.isOpen && nextProps.isOpen === false) { | ||
isDismissing = true; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
async componentDidUpdate(prevProps: Props) { | ||
if (this.overlay) { | ||
attachProps(this.overlay, this.props, prevProps); | ||
} | ||
|
||
if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) { | ||
this.present(prevProps); | ||
} | ||
if (this.overlay && prevProps.isOpen !== this.props.isOpen && this.props.isOpen === false) { | ||
await this.overlay.dismiss(); | ||
isDismissing = false; | ||
|
||
/** | ||
* Now that the overlay is dismissed | ||
* we need to render again so that any | ||
* inner components will be unmounted | ||
*/ | ||
this.forceUpdate(); | ||
} | ||
} | ||
|
||
async present(prevProps?: Props) { | ||
const { children, isOpen, onDidDismiss, onDidPresent, onWillDismiss, onWillPresent, ...cProps } = this.props; | ||
const elementProps = { | ||
...cProps, | ||
ref: this.props.forwardedRef, | ||
[didDismissEventName]: this.handleDismiss, | ||
[didPresentEventName]: (e: CustomEvent) => this.props.onDidPresent && this.props.onDidPresent(e), | ||
[willDismissEventName]: (e: CustomEvent) => this.props.onWillDismiss && this.props.onWillDismiss(e), | ||
[willPresentEventName]: (e: CustomEvent) => this.props.onWillPresent && this.props.onWillPresent(e), | ||
}; | ||
|
||
this.overlay = await controller.create({ | ||
...elementProps, | ||
component: this.el, | ||
componentProps: {}, | ||
}); | ||
|
||
setRef(this.props.forwardedRef, this.overlay); | ||
attachProps(this.overlay, elementProps, prevProps); | ||
|
||
await this.overlay.present(); | ||
} | ||
|
||
render() { | ||
/** | ||
* Continue to render the component even when | ||
* overlay is dismissing otherwise component | ||
* will be hidden before animation is done. | ||
*/ | ||
return ReactDOM.createPortal(this.props.isOpen || isDismissing ? this.props.children : null, this.el); | ||
} | ||
} | ||
|
||
return React.forwardRef<OverlayType, Props>((props, ref) => { | ||
return <Overlay {...props} forwardedRef={ref} />; | ||
}); | ||
}; |
2 changes: 2 additions & 0 deletions
2
...ges/components/medium/react/src/components/stencil-generated/react-component-lib/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { createReactComponent } from './createComponent'; | ||
export { createOverlayComponent } from './createOverlayComponent'; |
34 changes: 34 additions & 0 deletions
34
...omponents/medium/react/src/components/stencil-generated/react-component-lib/interfaces.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// General types important to applications using stencil built components | ||
export interface EventEmitter<T = any> { | ||
emit: (data?: T) => CustomEvent<T>; | ||
} | ||
|
||
export interface StyleReactProps { | ||
class?: string; | ||
className?: string; | ||
style?: { [key: string]: any }; | ||
} | ||
|
||
export interface OverlayEventDetail<T = any> { | ||
data?: T; | ||
role?: string; | ||
} | ||
|
||
export interface OverlayInterface { | ||
el: HTMLElement; | ||
animated: boolean; | ||
keyboardClose: boolean; | ||
overlayIndex: number; | ||
presented: boolean; | ||
|
||
enterAnimation?: any; | ||
leaveAnimation?: any; | ||
|
||
didPresent: EventEmitter<void>; | ||
willPresent: EventEmitter<void>; | ||
willDismiss: EventEmitter<OverlayEventDetail>; | ||
didDismiss: EventEmitter<OverlayEventDetail>; | ||
|
||
present(): Promise<void>; | ||
dismiss(data?: any, role?: string): Promise<boolean>; | ||
} |
Oops, something went wrong.