-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from newjersey/button-component-tests
Updates to NJWDS button web component + new icon component
- Loading branch information
Showing
22 changed files
with
1,104 additions
and
412 deletions.
There are no files selected for viewing
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
125 changes: 125 additions & 0 deletions
125
packages/react-library/lib/components/stencil-generated/react-component-lib/attachProps.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,125 @@ | ||
import { camelToDashCase } from './case'; | ||
|
||
export const attachProps = (node: HTMLElement, newProps: any, oldProps: any = {}) => { | ||
// some test frameworks don't render DOM elements, so we test here to make sure we are dealing with DOM first | ||
if (node instanceof Element) { | ||
// add any classes in className to the class list | ||
const className = getClassName(node.classList, newProps, oldProps); | ||
if (className !== '') { | ||
node.className = className; | ||
} | ||
|
||
Object.keys(newProps).forEach((name) => { | ||
if ( | ||
name === 'children' || | ||
name === 'style' || | ||
name === 'ref' || | ||
name === 'class' || | ||
name === 'className' || | ||
name === 'forwardedRef' | ||
) { | ||
return; | ||
} | ||
if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) { | ||
const eventName = name.substring(2); | ||
const eventNameLc = eventName[0].toLowerCase() + eventName.substring(1); | ||
|
||
if (!isCoveredByReact(eventNameLc)) { | ||
syncEvent(node, eventNameLc, newProps[name]); | ||
} | ||
} else { | ||
(node as any)[name] = newProps[name]; | ||
const propType = typeof newProps[name]; | ||
if (propType === 'string') { | ||
node.setAttribute(camelToDashCase(name), newProps[name]); | ||
} | ||
} | ||
}); | ||
} | ||
}; | ||
|
||
export const getClassName = (classList: DOMTokenList, newProps: any, oldProps: any) => { | ||
const newClassProp: string = newProps.className || newProps.class; | ||
const oldClassProp: string = oldProps.className || oldProps.class; | ||
// map the classes to Maps for performance | ||
const currentClasses = arrayToMap(classList); | ||
const incomingPropClasses = arrayToMap(newClassProp ? newClassProp.split(' ') : []); | ||
const oldPropClasses = arrayToMap(oldClassProp ? oldClassProp.split(' ') : []); | ||
const finalClassNames: string[] = []; | ||
// loop through each of the current classes on the component | ||
// to see if it should be a part of the classNames added | ||
currentClasses.forEach((currentClass) => { | ||
if (incomingPropClasses.has(currentClass)) { | ||
// add it as its already included in classnames coming in from newProps | ||
finalClassNames.push(currentClass); | ||
incomingPropClasses.delete(currentClass); | ||
} else if (!oldPropClasses.has(currentClass)) { | ||
// add it as it has NOT been removed by user | ||
finalClassNames.push(currentClass); | ||
} | ||
}); | ||
incomingPropClasses.forEach((s) => finalClassNames.push(s)); | ||
return finalClassNames.join(' '); | ||
}; | ||
|
||
/** | ||
* Transforms a React event name to a browser event name. | ||
*/ | ||
export const transformReactEventName = (eventNameSuffix: string) => { | ||
switch (eventNameSuffix) { | ||
case 'doubleclick': | ||
return 'dblclick'; | ||
} | ||
return eventNameSuffix; | ||
}; | ||
|
||
/** | ||
* Checks if an event is supported in the current execution environment. | ||
* @license Modernizr 3.0.0pre (Custom Build) | MIT | ||
*/ | ||
export const isCoveredByReact = (eventNameSuffix: string) => { | ||
if (typeof document === 'undefined') { | ||
return true; | ||
} else { | ||
const eventName = 'on' + transformReactEventName(eventNameSuffix); | ||
let isSupported = eventName in document; | ||
|
||
if (!isSupported) { | ||
const element = document.createElement('div'); | ||
element.setAttribute(eventName, 'return;'); | ||
isSupported = typeof (element as any)[eventName] === 'function'; | ||
} | ||
|
||
return isSupported; | ||
} | ||
}; | ||
|
||
export const syncEvent = ( | ||
node: Element & { __events?: { [key: string]: ((e: Event) => any) | undefined } }, | ||
eventName: string, | ||
newEventHandler?: (e: Event) => any | ||
) => { | ||
const eventStore = node.__events || (node.__events = {}); | ||
const oldEventHandler = eventStore[eventName]; | ||
|
||
// Remove old listener so they don't double up. | ||
if (oldEventHandler) { | ||
node.removeEventListener(eventName, oldEventHandler); | ||
} | ||
|
||
// Bind new listener. | ||
node.addEventListener( | ||
eventName, | ||
(eventStore[eventName] = function handler(e: Event) { | ||
if (newEventHandler) { | ||
newEventHandler.call(this, e); | ||
} | ||
}) | ||
); | ||
}; | ||
|
||
const arrayToMap = (arr: string[] | DOMTokenList) => { | ||
const map = new Map<string, string>(); | ||
(arr as string[]).forEach((s: string) => map.set(s, s)); | ||
return map; | ||
}; |
7 changes: 7 additions & 0 deletions
7
packages/react-library/lib/components/stencil-generated/react-component-lib/case.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,7 @@ | ||
export const dashToPascalCase = (str: string) => | ||
str | ||
.toLowerCase() | ||
.split('-') | ||
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)) | ||
.join(''); | ||
export const camelToDashCase = (str: string) => str.replace(/([A-Z])/g, (m: string) => `-${m[0].toLowerCase()}`); |
14 changes: 14 additions & 0 deletions
14
packages/react-library/lib/components/stencil-generated/react-component-lib/dev.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,14 @@ | ||
export const isDevMode = () => { | ||
return process && process.env && process.env.NODE_ENV === 'development'; | ||
}; | ||
|
||
const warnings: { [key: string]: boolean } = {}; | ||
|
||
export const deprecationWarning = (key: string, message: string) => { | ||
if (isDevMode()) { | ||
if (!warnings[key]) { | ||
console.warn(message); | ||
warnings[key] = true; | ||
} | ||
} | ||
}; |
50 changes: 50 additions & 0 deletions
50
packages/react-library/lib/components/stencil-generated/react-component-lib/index.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,50 @@ | ||
import React from 'react'; | ||
|
||
import type { StyleReactProps } from '../interfaces'; | ||
|
||
export type StencilReactExternalProps<PropType, ElementType> = PropType & | ||
Omit<React.HTMLAttributes<ElementType>, 'style'> & | ||
StyleReactProps; | ||
|
||
// This will be replaced with React.ForwardedRef when react-output-target is upgraded to React v17 | ||
export type StencilReactForwardedRef<T> = ((instance: T | null) => void) | React.MutableRefObject<T | null> | null; | ||
|
||
export const setRef = (ref: StencilReactForwardedRef<any> | React.Ref<any> | undefined, value: any) => { | ||
if (typeof ref === 'function') { | ||
ref(value); | ||
} else if (ref != null) { | ||
// Cast as a MutableRef so we can assign current | ||
(ref as React.MutableRefObject<any>).current = value; | ||
} | ||
}; | ||
|
||
export const mergeRefs = ( | ||
...refs: (StencilReactForwardedRef<any> | React.Ref<any> | undefined)[] | ||
): React.RefCallback<any> => { | ||
return (value: any) => { | ||
refs.forEach((ref) => { | ||
setRef(ref, value); | ||
}); | ||
}; | ||
}; | ||
|
||
export const createForwardRef = <PropType, ElementType>(ReactComponent: any, displayName: string) => { | ||
const forwardRef = ( | ||
props: StencilReactExternalProps<PropType, ElementType>, | ||
ref: StencilReactForwardedRef<ElementType> | ||
) => { | ||
return <ReactComponent {...props} forwardedRef={ref} />; | ||
}; | ||
forwardRef.displayName = displayName; | ||
|
||
return React.forwardRef(forwardRef); | ||
}; | ||
|
||
export const defineCustomElement = (tagName: string, customElement: any) => { | ||
if (customElement !== undefined && typeof customElements !== 'undefined' && !customElements.get(tagName)) { | ||
customElements.define(tagName, customElement); | ||
} | ||
}; | ||
|
||
export * from './attachProps'; | ||
export * from './case'; |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
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
Oops, something went wrong.