react#useImperativeHandle JavaScript Examples
The following examples show how to use
react#useImperativeHandle.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SkillsDisplay.js From skills-client with Apache License 2.0 | 6 votes |
SkillDisplay = forwardRef(({ theme = null, version = null, userId = null, handleRouteChanged = null, options = {} }, ref) => {
useEffect(() => {
clientDisplay = new SkillsDisplayJS({
options,
theme,
version,
userId,
handleRouteChanged,
});
clientDisplay.attachTo(document.getElementById('clientSkillsDisplayContainer'));
return () => {
destroy(clientDisplay);
};
}, [theme, version, userId, handleRouteChanged, options]);
useImperativeHandle(ref, () => ({
navigate(path) {
if (clientDisplay) {
clientDisplay.navigate(path);
}
},
}), []);
return (<div id='clientSkillsDisplayContainer'/>);
})
Example #2
Source File: Avatar.jsx From chat-ui-kit-react with MIT License | 6 votes |
function AvatarInner(
{ name, src, size, status, className, active, children, ...rest },
ref
) {
const cName = `${prefix}-avatar`;
const sizeClass = typeof size !== "undefined" ? ` ${cName}--${size}` : "";
const avatarRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => avatarRef.current.focus(),
}));
return (
<div
ref={avatarRef}
{...rest}
className={classNames(
`${cName}${sizeClass}`,
{ [`${cName}--active`]: active },
className
)}
>
{children ? (
children
) : (
<>
<img src={src} alt={name} />
{typeof status === "string" && (
<Status status={status} size={size} />
)}{" "}
</>
)}
</div>
);
}
Example #3
Source File: BlockFooter.jsx From konsta with MIT License | 6 votes |
BlockFooter = forwardRef((props, ref) => {
const {
component = 'div',
className,
ios,
material,
// Children
children,
// Rest
...rest
} = props;
const elRef = useRef(null);
useImperativeHandle(ref, () => ({
el: elRef.current,
}));
const Component = component;
const attrs = {
...rest,
};
const themeClasses = useThemeClasses({ ios, material });
const c = themeClasses(BlockFooterClasses(), className);
return (
<Component ref={elRef} className={c.base} {...attrs}>
{children}
</Component>
);
})
Example #4
Source File: Accordion.js From lundium with MIT License | 6 votes |
Accordion = forwardRef(({ openItemIndex, className, children }, ref) => {
const [indexOpen, setIndexOpen] = useState(openItemIndex);
useEffect(() => {
if (!isNaN(openItemIndex)) {
setIndexOpen(openItemIndex);
}
}, [openItemIndex]);
useImperativeHandle(ref, () => ({ setActiveIndex: setIndexOpen }));
return (
<Box className={cx('accordion', className)}>
{Children.map(children, (child, index) =>
cond([
[
o(equals(AccordionItem), prop('type')),
clone({ index, indexOpen, setIndexOpen }),
],
[T, identity],
])(child),
)}
</Box>
);
})
Example #5
Source File: SearchInput.js From lx-music-mobile with Apache License 2.0 | 6 votes |
SearchInput = (props, ref) => {
const textInputRef = useRef()
useImperativeHandle(ref, () => ({
blur() {
if (!textInputRef.current) return
textInputRef.current.blur()
},
}))
return (
<View style={{ ...styles.container, ...props.styles }}>
<Input {...props} ref={textInputRef} />
</View>
)
}
Example #6
Source File: modal.js From stakeit.space with GNU Affero General Public License v3.0 | 6 votes |
Modal = forwardRef( (props, ref) => {
const [display, setDisplay] = useState(false);
useImperativeHandle(ref, () => {
return {
openMod: () => open(),
closeMod: () => close()
}
})
const open = () => {
setDisplay(true);
};
const close = () => {
setDisplay(false);
};
if (display) {
return ReactDOM.createPortal(
<ModalWrapper>
<ModalBackdrop onClick={close} />
<ModalWindow>{props.children}</ModalWindow>
</ModalWrapper>,
document.getElementById("modal_root")
);
} else {
return null;
}
})
Example #7
Source File: StripeInput.jsx From rysolv with GNU Affero General Public License v3.0 | 6 votes |
StripeInput = ({ component: Component, inputRef, ...restProps }) => {
const elementRef = useRef();
useImperativeHandle(inputRef, () => ({
focus: () => elementRef.current.focus,
}));
return (
<Component
onReady={element => (elementRef.current = element)}
{...restProps}
/>
);
}
Example #8
Source File: index.js From react-native-echarts-pro with MIT License | 6 votes |
function APP(props, ref) {
const chartRef = useRef();
useImperativeHandle(ref, () => ({
setNewOption(option, optionSetting) {
chartRef.current.setNewOption(option, optionSetting);
},
/**
* 触发ECharts 中支持的图表行为
* Chart actions supported by ECharts are triggered through dispatchAction.
* @param {object|array} action
*/
dispatchAction(action) {
chartRef.current.dispatchAction(action);
},
/**
* Get echarts instance support function.
* @param {string} functionName
* @param {object} params
*/
async getInstance(functionName, params) {
return await chartRef.current.getInstance(functionName, params);
},
}));
return (
<Container width={props.width}>
<Echarts {...props} ref={chartRef} />
</Container>
);
}
Example #9
Source File: StripeInput.js From turqV2 with GNU General Public License v3.0 | 6 votes |
StripeInput = (
{ component: Component, inputRef, ...props }
) => { const elementRef = useRef();
useImperativeHandle(inputRef, () => ({
focus: () => elementRef.current.focus
})); return (
<Component
onReady={element => (elementRef.current = element)}
{...props}
/>
)
}
Example #10
Source File: MarkdownEditor.component.jsx From Stackoverflow-Clone-Frontend with MIT License | 5 votes |
MarkdownEditor = forwardRef((props, ref) => {
const [value, setValue] = useState(RichTextEditor.createEmptyValue());
useImperativeHandle(ref, () => ({
cleanEditorState() {
setValue(RichTextEditor.createEmptyValue());
},
}));
const onChange = (newValue) => {
setValue(newValue);
if (props.onChange) {
// Send the changes up to the parent component as an HTML string.
// This is here to demonstrate using `.toString()` but in a real app it
// would be better to avoid generating a string on each change.
props.onChange(newValue.toString('html'));
}
};
// The toolbarConfig object allows you to specify custom buttons, reorder buttons and to add custom css classes.
// Supported inline styles: https://github.com/facebook/draft-js/blob/master/docs/Advanced-Topics-Inline-Styles.md
// Supported block types: https://github.com/facebook/draft-js/blob/master/docs/Advanced-Topics-Custom-Block-Render.md#draft-default-block-render-map
const toolbarConfig = {
// Optionally specify the groups to display (displayed in the order listed).
display: [
'INLINE_STYLE_BUTTONS',
'BLOCK_TYPE_BUTTONS',
'LINK_BUTTONS',
// 'BLOCK_TYPE_DROPDOWN',
// 'HISTORY_BUTTONS',
],
INLINE_STYLE_BUTTONS: [
{label: 'Bold', style: 'BOLD', className: 'button-format'},
{label: 'Italic', style: 'ITALIC', className: 'button-format'},
{label: 'Underline', style: 'UNDERLINE', className: 'button-format'},
// {label: 'Monospace', style: 'CODE', className: 'button-format'},
],
// BLOCK_TYPE_DROPDOWN: [
// {label: 'Normal', style: 'unstyled'},
// {label: 'Heading Large', style: 'header-one'},
// {label: 'Heading Medium', style: 'header-two'},
// {label: 'Heading Small', style: 'header-three'},
// ],
BLOCK_TYPE_BUTTONS: [
{label: 'UL', style: 'unordered-list-item', className: 'button-format'},
{label: 'OL', style: 'ordered-list-item', className: 'button-format'},
{label: 'Blockquote', style: 'blockquote', className: 'button-format'},
{
label: 'Code Block',
style: 'code-block',
className: 'button-format code-block',
},
],
};
return (
<RichTextEditor
className='rich-text-editor-root'
toolbarClassName='rich-text-editor-toolbar'
editorClassName='rich-text-editor-editor'
toolbarConfig={toolbarConfig}
value={value}
onChange={onChange}
/>
);
})
Example #11
Source File: DateSelect.js From actual with MIT License | 5 votes |
DatePicker = React.forwardRef(
({ value, dateFormat, onUpdate, onSelect }, ref) => {
let picker = useRef(null);
let mountPoint = useRef(null);
useImperativeHandle(
ref,
() => ({
handleInputKeyDown(e) {
let newDate = null;
switch (e.keyCode) {
case 37:
e.preventDefault();
newDate = d.subDays(picker.current.getDate(), 1);
break;
case 38:
e.preventDefault();
newDate = d.subDays(picker.current.getDate(), 7);
break;
case 39:
e.preventDefault();
newDate = d.addDays(picker.current.getDate(), 1);
break;
case 40:
e.preventDefault();
newDate = d.addDays(picker.current.getDate(), 7);
break;
default:
}
if (newDate) {
picker.current.setDate(newDate, true);
onUpdate && onUpdate(newDate);
}
}
}),
[]
);
useLayoutEffect(() => {
picker.current = new Pikaday({
theme: 'actual-date-picker',
keyboardInput: false,
defaultDate: value
? d.parse(value, dateFormat, new Date())
: new Date(),
setDefaultDate: true,
toString(date) {
return d.format(date, dateFormat);
},
parse(dateString) {
return d.parse(dateString, dateFormat, new Date());
},
onSelect
});
mountPoint.current.appendChild(picker.current.el);
return () => {
picker.current.destroy();
};
}, []);
useEffect(() => {
if (picker.current.getDate() !== value) {
picker.current.setDate(d.parse(value, dateFormat, new Date()), true);
}
}, [value, dateFormat]);
return (
<View style={[pickerStyles, { flex: 1 }]} innerRef={mountPoint}></View>
);
}
)
Example #12
Source File: Search.jsx From chat-ui-kit-react with MIT License | 5 votes |
function SearchInner(
{ placeholder, value, onChange, onClearClick, className, disabled, ...rest },
ref
) {
const cName = `${prefix}-search`;
const isControlled = useMemo(() => typeof value !== "undefined", []);
const [searchValue, setSearchValue] = useControlledOrNot("", value);
const [clearActive, setClearActive] = useState(
isControlled ? searchValue.length > 0 : false
);
if (isControlled !== (typeof value !== "undefined")) {
throw "Search: Changing from controlled to uncontrolled component and vice versa is not allowed";
}
const inputRef = useRef(undefined);
// Public API
const focus = () => {
if (typeof inputRef.current !== "undefined") {
inputRef.current.focus();
}
};
// Return object with public Api
useImperativeHandle(ref, () => ({
focus,
}));
const handleChange = (e) => {
const value = e.target.value;
setClearActive(value.length > 0);
if (isControlled === false) {
setSearchValue(value);
}
onChange(value);
};
const handleClearClick = () => {
if (isControlled === false) {
setSearchValue("");
}
setClearActive(false);
onClearClick();
};
return (
<div
{...rest}
className={classNames(
cName,
{ [`${cName}--disabled`]: disabled },
className
)}
>
<FontAwesomeIcon icon={faSearch} className={`${cName}__search-icon`} />
<input
ref={inputRef}
type="text"
className={`${cName}__input`}
placeholder={placeholder}
onChange={handleChange}
disabled={disabled}
value={searchValue}
/>
<FontAwesomeIcon
icon={faTimes}
className={classNames(`${cName}__clear-icon`, {
[`${cName}__clear-icon--active`]: clearActive,
})}
onClick={handleClearClick}
/>
</div>
);
}
Example #13
Source File: DropZone.js From sailplane-web with GNU General Public License v3.0 | 5 votes |
export function DropZone({children, sharedFs, currentDirectory}, ref) {
const styles = {
container: {
cursor: 'pointer',
textAlign: 'center',
color: primary5,
fontSize: 16,
fontWeight: 200,
fontFamily: 'Open Sans',
outline: 0,
userSelect: 'none',
height: '100%',
},
};
const dispatch = useDispatch();
const onDrop = useCallback(
async (acceptedFiles) => {
dispatch(setStatus({message: 'Uploading'}));
const listSource = fileListSource(acceptedFiles, {preserveMtime: true});
const totalSize = acceptedFiles.reduce((prev, cur) => cur.size + prev, 0);
try {
await sharedFs.current.upload(currentDirectory, listSource, {
progress: (length) => {
dispatch(
setStatus({
message: `[${getPercent(length, totalSize)}%] Uploading files`,
}),
);
},
});
dispatch(setStatus({}));
} catch (e) {
// will add sharedFs.canWrite method later for richer ux
dispatch(
setStatus({
message: `Missing write permissions.`,
isError: true,
}),
);
delay(4000).then(() => dispatch(setStatus({})));
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[currentDirectory],
);
const {getRootProps, getInputProps, isDragActive, open} = useDropzone({
onDrop,
noClick: true,
});
useImperativeHandle(ref, () => ({
openUpload: () => {
open();
},
}));
return (
<div {...getRootProps()} style={styles.container} id={'dropZone'}>
<input {...getInputProps()} id={'fileUpload'} />
{isDragActive ? <FileDragBlock isActive={true} /> : <div>{children}</div>}
</div>
);
}
Example #14
Source File: Actions.jsx From konsta with MIT License | 5 votes |
Actions = forwardRef((props, ref) => {
const {
component = 'div',
className,
ios,
material,
opened,
backdrop = true,
onBackdropClick,
// Children
children,
// Rest
...rest
} = props;
const elRef = useRef(null);
useImperativeHandle(ref, () => ({
el: elRef.current,
}));
const state = opened ? 'opened' : 'closed';
const Component = component;
const attrs = {
...rest,
};
const themeClasses = useThemeClasses({ ios, material });
const c = themeClasses(ActionsClasses(props, className), className);
return (
<>
{backdrop && (
<div className={c.backdrop[state]} onClick={onBackdropClick} />
)}
<Component ref={elRef} className={c.base[state]} {...attrs}>
{children}
</Component>
</>
);
})
Example #15
Source File: Input.js From lx-music-mobile with Apache License 2.0 | 5 votes |
Input = ({ onChangeText, onClearText, clearBtn, style, ...props }, ref) => {
const inputRef = useRef()
const theme = useGetter('common', 'theme')
// const scaleClearBtn = useRef(new Animated.Value(0)).current
useImperativeHandle(ref, () => ({
blur() {
if (!inputRef.current) return
inputRef.current.blur()
},
focus() {
if (!inputRef.current) return
inputRef.current.focus()
},
clear() {
inputRef.current.clear()
},
isFocused() {
return inputRef.current.isFocused()
},
}))
// const showClearBtn = useCallback(() => {
// Animated.timing(scaleClearBtn, {
// toValue: 1,
// duration: 200,
// useNativeDriver: true,
// }).start()
// }, [scaleClearBtn])
// const hideClearBtn = useCallback(() => {
// Animated.timing(scaleClearBtn, {
// toValue: 0,
// duration: 200,
// useNativeDriver: true,
// }).start()
// }, [scaleClearBtn])
const clearText = useCallback(() => {
inputRef.current.clear()
// hideClearBtn()
onChangeText && onChangeText('')
onClearText && onClearText()
}, [onChangeText, onClearText])
const changeText = useCallback(text => {
// if (text.length) {
// showClearBtn()
// } else {
// hideClearBtn()
// }
onChangeText && onChangeText(text)
}, [onChangeText])
return (
<View style={styles.content}>
<TextInput
autoCapitalize="none"
onChangeText={changeText}
autoCompleteType="off"
style={{ ...styles.input, color: theme.normal, ...style }}
placeholderTextColor={theme.normal50}
selectionColor={theme.secondary10}
ref={inputRef} {...props} />
{/* <View style={styles.clearBtnContent}>
<Animated.View style={{ ...styles.clearBtnContent, transform: [{ scale: scaleClearBtn }] }}> */}
{clearBtn
? <View style={styles.clearBtnContent}>
<TouchableOpacity style={styles.clearBtn} onPress={clearText}>
<Icon name="remove" style={{ fontSize: 14, color: theme.normal50 }} />
</TouchableOpacity>
</View>
: null
}
{/* </Animated.View>
</View> */}
</View>
)
}
Example #16
Source File: index.js From rainbow-modules with MIT License | 5 votes |
DatePickerCarouselInput = React.forwardRef((props, ref) => {
const {
id,
className,
style,
readOnly,
required,
disabled,
name,
label,
value,
locale,
onLabelClick,
onChange,
formatStyle,
selectionType,
minDate,
maxDate,
} = props;
const currentLocale = useLocale(locale);
const inputRef = useRef();
const labelRef = useRef();
const formattedDate = useFormatDate({
value,
formatStyle,
locale: currentLocale,
selectionType,
});
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
click: () => {
labelRef.current.click();
},
blur: () => {
inputRef.current.blur();
},
}));
return (
<StyledContainer id={id} className={className} style={style} readOnly={readOnly}>
<StyledLabelContainer>
<StyledLabel
ref={labelRef}
onClick={onLabelClick}
data-cy="carousel-input__label-button"
>
{label}
<ChevronDown />
</StyledLabel>
<input
type="hidden"
value={formattedDate}
required={required}
disabled={disabled}
name={name}
/>
</StyledLabelContainer>
<CarouselCalendar
ref={inputRef}
value={value}
locale={currentLocale}
onChange={onChange}
minDate={minDate}
maxDate={maxDate}
/>
</StyledContainer>
);
})
Example #17
Source File: Menu.js From react-menu with MIT License | 5 votes |
Menu = /*#__PURE__*/forwardRef(function Menu(_ref, externalRef) {
var ariaLabel = _ref['aria-label'],
menuButton = _ref.menuButton,
instanceRef = _ref.instanceRef,
onMenuChange = _ref.onMenuChange,
restProps = _objectWithoutPropertiesLoose(_ref, _excluded);
var _useMenuStateAndFocus = useMenuStateAndFocus(restProps),
stateProps = _useMenuStateAndFocus[0],
toggleMenu = _useMenuStateAndFocus[1],
openMenu = _useMenuStateAndFocus[2];
var isOpen = isMenuOpen(stateProps.state);
var skipOpen = useRef(false);
var buttonRef = useRef(null);
var handleClose = useCallback(function (e) {
toggleMenu(false);
if (e.key) buttonRef.current.focus();
}, [toggleMenu]);
var handleClick = function handleClick(e) {
if (skipOpen.current) return;
openMenu(e.detail === 0 ? FocusPositions.FIRST : undefined);
};
var handleKeyDown = function handleKeyDown(e) {
var handled = false;
switch (e.key) {
case Keys.UP:
openMenu(FocusPositions.LAST);
handled = true;
break;
case Keys.DOWN:
openMenu(FocusPositions.FIRST);
handled = true;
break;
}
if (handled) e.preventDefault();
};
var button = safeCall(menuButton, {
open: isOpen
});
if (!button || !button.type) throw new Error('Menu requires a menuButton prop.');
var buttonProps = _extends({
ref: useCombinedRef(button.ref, buttonRef)
}, attachHandlerProps({
onClick: handleClick,
onKeyDown: handleKeyDown
}, button.props));
if (getName(button.type) === 'MenuButton') {
buttonProps.isOpen = isOpen;
}
var renderButton = /*#__PURE__*/cloneElement(button, buttonProps);
useMenuChange(onMenuChange, isOpen);
useImperativeHandle(instanceRef, function () {
return {
openMenu: openMenu,
closeMenu: function closeMenu() {
return toggleMenu(false);
}
};
});
return /*#__PURE__*/jsxs(Fragment, {
children: [renderButton, /*#__PURE__*/jsx(ControlledMenu, _extends({}, restProps, stateProps, {
"aria-label": ariaLabel || (typeof button.props.children === 'string' ? button.props.children : 'Menu'),
anchorRef: buttonRef,
ref: externalRef,
onClose: handleClose,
skipOpen: skipOpen
}))]
});
})
Example #18
Source File: SelectDropdown.js From react-native-select-dropdown with MIT License | 4 votes |
SelectDropdown = (
{
data /* array */,
onSelect /* function */,
defaultButtonText /* String */,
buttonTextAfterSelection /* function */,
rowTextForSelection /* function */,
defaultValue /* any */,
defaultValueByIndex /* integer */,
disabled /* boolean */,
disableAutoScroll /* boolean */,
onFocus /* function */,
onBlur /* function */,
/////////////////////////////
buttonStyle /* style object for button */,
buttonTextStyle /* style object for button text */,
renderCustomizedButtonChild /* function returns React component for customized button */,
/////////////////////////////
renderDropdownIcon,
dropdownIconPosition,
statusBarTranslucent,
dropdownStyle,
dropdownOverlayColor /* string */,
/////////////////////////////
rowStyle /* style object for row */,
rowTextStyle /* style object for row text */,
selectedRowStyle /* style object for selected row */,
selectedRowTextStyle /* style object for selected row text */,
renderCustomizedRowChild /* function returns React component for customized row */,
/////////////////////////////
search /* boolean */,
searchInputStyle /* style object for search input */,
searchInputTxtColor /* text color for search input */,
searchPlaceHolder /* placeholder text for search input */,
searchPlaceHolderColor /* text color for search input placeholder */,
renderSearchInputLeftIcon /* function returns React component for search input icon */,
renderSearchInputRightIcon /* function returns React component for search input icon */,
},
ref,
) => {
///////////////////////////////////////////////////////
useImperativeHandle(ref, () => ({
reset: () => {
reset();
},
openDropdown: () => {
openDropdown();
},
closeDropdown: () => {
closeDropdown();
},
}));
///////////////////////////////////////////////////////
const DropdownButton = useRef(); // button ref to get positions
const [isVisible, setIsVisible] = useState(false); // dropdown visible ?
const [buttonLayout, setButtonLayout] = useState(null);
const [dropdownPX, setDropdownPX] = useState(0); // position x
const [dropdownPY, setDropdownPY] = useState(0); // position y
const [dropdownHEIGHT, setDropdownHEIGHT] = useState(() => {
return calculateDropdownHeight(dropdownStyle, rowStyle, data?.length || 0, search);
}); // dropdown height
const [dropdownWIDTH, setDropdownWIDTH] = useState(0); // dropdown width
///////////////////////////////////////////////////////
const [selectedItem, setSelectedItem] = useState(null); // selected item from dropdown
const [selectedIndex, setSelectedIndex] = useState(-1); // index of selected item from dropdown
const dropDownFlatlistRef = useRef(null); // ref to the drop down flatlist
///////////////////////////////////////////////////////
const [searchTxt, setSearchTxt] = useState('');
const keyboardHeight = useKeyboardHeight();
const remainigHeightAvoidKeyboard = height - keyboardHeight;
const safeDropdownViewUnderKeyboard = rowStyle && rowStyle.height ? rowStyle.height * 3 : 50 * 3;
/* ******************* useEffect ******************* */
// data array changes
useEffect(() => {
if (!data || data.length == 0) {
reset();
}
}, [data]);
// default value by index added or changed
useEffect(() => {
// defaultValueByIndex may be equals zero
if (isExist(defaultValueByIndex)) {
if (data && isExist(data[defaultValueByIndex])) {
setDefault(defaultValueByIndex);
}
}
}, [defaultValueByIndex]);
// default value added or changed
useEffect(() => {
// defaultValue may be equals zero
if (isExist(defaultValue)) {
if (data && findIndexInArr(defaultValue, data) >= 0) {
setDefault(findIndexInArr(defaultValue, data));
}
}
}, [defaultValue]);
// for height changes
useEffect(() => {
setDropdownHEIGHT(calculateDropdownHeight(dropdownStyle, rowStyle, data?.length || 0, search));
}, [dropdownStyle, rowStyle, data]);
///////////////////////////////////////////////////////
/* ******************** Methods ******************** */
const openDropdown = () => {
DropdownButton.current.measure((fx, fy, w, h, px, py) => {
// console.log('position y => ', py, '\nheight', h, '\nposition x => ', px)
setButtonLayout({w, h, px, py});
if (height - 18 < py + h + dropdownHEIGHT) {
setDropdownPX(px);
setDropdownPY(py - 2 - dropdownHEIGHT);
} else {
setDropdownPX(px);
setDropdownPY(py + h + 2);
}
setDropdownWIDTH(dropdownStyle?.width || w);
setIsVisible(true);
onFocus && onFocus();
});
};
const closeDropdown = () => {
setIsVisible(false);
setSearchTxt('');
onBlur && onBlur();
};
const reset = () => {
setSelectedItem(null);
setSelectedIndex(-1);
setSearchTxt('');
};
const setDefault = index => {
setSelectedItem(data[index]);
setSelectedIndex(index);
};
const getItemLayout = (data, index) => ({
index,
length: data?.length || 0,
offset: rowStyle && rowStyle.height ? rowStyle.height * index : 50 * index,
});
const onLayout = () => {
if (disableAutoScroll) {
return;
}
if (selectedIndex >= 3 && dropDownFlatlistRef) {
dropDownFlatlistRef.current.scrollToOffset({
offset: rowStyle && rowStyle.height ? rowStyle.height * selectedIndex : 50 * selectedIndex,
animated: true,
});
}
};
const onSelectItem = (item, index) => {
closeDropdown();
onSelect(item, index);
setSelectedItem(item);
setSelectedIndex(index);
};
///////////////////////////////////////////////////////
/* ******************** Render Methods ******************** */
const renderSearchView = () => {
return (
search && (
<View style={{...styles.searchViewStyle, ...{width: buttonLayout.w}}}>
<Input
value={searchTxt}
valueColor={searchInputTxtColor}
placeholder={searchPlaceHolder}
placeholderTextColor={searchPlaceHolderColor}
onChangeText={setSearchTxt}
inputStyle={searchInputStyle}
renderLeft={renderSearchInputLeftIcon}
renderRight={renderSearchInputRightIcon}
/>
</View>
)
);
};
const renderFlatlistItem = ({item, index}) => {
return item ? (
<TouchableOpacity
activeOpacity={0.8}
style={{...styles.dropdownRow, ...rowStyle, ...(index == selectedIndex && selectedRowStyle)}}
onPress={() => onSelectItem(item, index)}>
{renderCustomizedRowChild ? (
<View style={styles.dropdownCustomizedRowParent}>{renderCustomizedRowChild(item, index)}</View>
) : (
<Text
numberOfLines={1}
allowFontScaling={false}
style={{...styles.dropdownRowText, ...rowTextStyle, ...(index == selectedIndex && selectedRowTextStyle)}}>
{rowTextForSelection ? rowTextForSelection(item, index) : item.toString()}
</Text>
)}
</TouchableOpacity>
) : (
<></>
);
};
const renderDropdown = () => {
return (
isVisible && (
<Modal
supportedOrientations={['portrait', 'landscape']}
animationType="none"
transparent={true}
statusBarTranslucent={statusBarTranslucent || false}
visible={isVisible}>
<TouchableOpacity
activeOpacity={1}
onPress={() => closeDropdown()}
style={{
...styles.dropdownOverlay,
...(dropdownOverlayColor && {
backgroundColor: dropdownOverlayColor,
}),
}}
/>
<View
style={{
...styles.dropdownOverlayView,
...styles.shadow,
...dropdownStyle,
...{
position: 'absolute',
top:
remainigHeightAvoidKeyboard < dropdownPY + safeDropdownViewUnderKeyboard
? remainigHeightAvoidKeyboard - safeDropdownViewUnderKeyboard
: dropdownPY,
height: dropdownHEIGHT,
width: dropdownWIDTH,
borderTopWidth: 0,
overflow: 'hidden',
},
...(I18nManager.isRTL
? {right: dropdownStyle?.right || dropdownPX}
: {left: dropdownStyle?.left || dropdownPX}),
}}>
{!data || data.length == 0 ? (
<View style={styles.dropdownActivityIndicatorView}>
<ActivityIndicator size="small" color={'#999999'} />
</View>
) : (
<FlatList
data={searchTxt ? deepSearchInArr(searchTxt, data) : data}
keyExtractor={(item, index) => index.toString()}
ref={ref => (dropDownFlatlistRef.current = ref)}
renderItem={renderFlatlistItem}
getItemLayout={getItemLayout}
onLayout={onLayout}
ListHeaderComponent={renderSearchView()}
stickyHeaderIndices={search && [0]}
keyboardShouldPersistTaps="always"
/>
)}
</View>
</Modal>
)
);
};
///////////////////////////////////////////////////////
return (
<TouchableOpacity
ref={DropdownButton}
disabled={disabled}
activeOpacity={0.8}
style={{
...styles.dropdownButton,
...(dropdownIconPosition == 'left' ? {flexDirection: 'row'} : {flexDirection: 'row-reverse'}),
...buttonStyle,
}}
onPress={openDropdown}>
{renderDropdown()}
{renderDropdownIcon && renderDropdownIcon(isVisible)}
{renderCustomizedButtonChild ? (
<View style={styles.dropdownCustomizedButtonParent}>
{renderCustomizedButtonChild(selectedItem, selectedIndex)}
</View>
) : (
<Text numberOfLines={1} allowFontScaling={false} style={{...styles.dropdownButtonText, ...buttonTextStyle}}>
{isExist(selectedItem)
? buttonTextAfterSelection
? buttonTextAfterSelection(selectedItem, selectedIndex)
: selectedItem.toString()
: defaultButtonText || 'Select an option.'}
</Text>
)}
</TouchableOpacity>
);
}
Example #19
Source File: Player.js From spotify-clone-client with MIT License | 4 votes |
Player = React.forwardRef(({ token }, ref) => {
const setMessage = useContext(MessageContext);
const [playbackState, setPlaybackState] = useState({
play: false,
shuffle: false,
repeat: false,
progress: 0,
total_time: 0,
});
const [scrubPb, setScrubPb] = useState(null);
const [playback, setPlayback] = useState(0);
const [volume, setVolume] = useState(1);
const [connectTip, setConnectTip] = useState(false);
const [playInfo, setPlayInfo] = useState({
album: {},
artists: [],
name: "",
id: "",
});
const timerRef = useRef(null);
let player = useRef(null);
useEffect(() => {
loadScript();
apiUpdate();
window.onSpotifyWebPlaybackSDKReady = () => playerInit();
return () => {
source.cancel();
clearTimeout(timerRef.current);
player.disconnect();
};
// eslint-disable-next-line
}, []);
const loadScript = () => {
const script = document.createElement("script");
script.id = "spotify-player";
script.type = "text/javascript";
script.async = "async";
script.defer = "defer";
script.src = "https://sdk.scdn.co/spotify-player.js";
document.body.appendChild(script);
};
const playerInit = () => {
console.log("player init");
player = new window.Spotify.Player({
name: "Spotify Clone Player",
getOAuthToken: (cb) => {
cb(token);
},
});
// Error handling
player.addListener("initialization_error", ({ message }) => {
setMessage(message);
});
player.addListener("authentication_error", ({ message }) => {
setMessage(message);
});
player.addListener("account_error", ({ message }) => {
setMessage(message);
});
player.addListener("playback_error", ({ message }) => {
setMessage(message);
});
// Playback status updates
player.addListener("player_state_changed", (state) => {
console.log(state);
try {
const {
duration,
position,
paused,
shuffle,
repeat_mode,
track_window,
} = state;
const { current_track } = track_window;
setPlayInfo(current_track);
setPlayback(position / duration);
setPlaybackState((state) => ({
...state,
play: !paused,
shuffle: shuffle,
repeat: repeat_mode !== 0,
progress: position,
total_time: duration,
}));
} catch (error) {
console.log(error);
}
});
// Ready
player.addListener("ready", ({ device_id }) => {
console.log("Ready with Device ID", device_id);
const tipAccess = localStorage.getItem("tipAccess");
if (!tipAccess) {
localStorage.setItem("tipAccess", "true");
setConnectTip(true);
}
});
// Not Ready
player.addListener("not_ready", ({ device_id }) => {
console.log("Device ID has gone offline", device_id);
});
// Connect to the player!
player.connect();
};
//Reference for parent component to use updateState
useImperativeHandle(ref, () => ({
updateState: () => {
setPlaybackState((state) => ({ ...state, play: true }));
updateState();
},
}));
//Use for other components to update the player state only if not connected to the web player
const updateState = () => {
if (!player.current) {
apiUpdate();
}
};
const apiUpdate = () => {
console.log("hello");
if (timerRef.current) {
clearTimeout(timerRef.current);
}
const requestInfo = reqWithToken(
"https://api.spotify.com/v1/me/player",
token,
source
);
requestInfo()
.then((response) => {
if (response.status === 200) {
const {
repeat_state,
shuffle_state,
is_playing,
progress_ms,
item,
device,
} = response.data;
setPlayback(progress_ms / item.duration_ms);
timerRef.current = setTimeout(
() => updateState(),
item.duration_ms - progress_ms + 10
);
setVolume(device.volume_percent / 100);
setPlaybackState((state) => ({
...state,
play: is_playing,
shuffle: shuffle_state,
repeat: repeat_state !== "off",
progress: progress_ms,
total_time: item.duration_ms,
}));
setPlayInfo(item);
} else if (response.status === 204) {
setMessage(
"Player is not working, select a device to start listening"
);
setConnectTip(true);
} else {
setMessage(
`ERROR: server response with ${response}. Player feature is unavailable!`
);
}
})
.catch((error) => console.log(error));
};
const updatePlayback = () => {
const interval = 500 / playbackState.total_time;
setPlayback((playback) => playback + interval);
setPlaybackState((state) => ({ ...state, progress: state.progress + 500 }));
};
const source = axios.CancelToken.source();
const togglePlay = () => {
const url = playbackState.play
? "https://api.spotify.com/v1/me/player/pause"
: "https://api.spotify.com/v1/me/player/play";
const request = putWithToken(url, token, source);
request()
.then((response) => {
if (response.status !== 204) {
setMessage(
`ERROR: Something went wrong! Server response: ${response}`
);
} else {
setPlaybackState((state) => ({ ...state, play: !state.play }));
updateState();
}
})
.catch((error) => setMessage(`ERROR: ${error}`));
};
const toggleShuffle = () => {
const request = putWithToken(
`https://api.spotify.com/v1/me/player/shuffle?state=${!playbackState.shuffle}`,
token,
source
);
request()
.then((response) => {
if (response.status === 204) {
setMessage(`Shuffle ${playbackState.shuffle ? "Off" : "On"}`);
setPlaybackState((state) => ({ ...state, shuffle: !state.shuffle }));
updateState();
} else {
setMessage(
`ERROR: Something went wrong! Server response: ${response.status}`
);
}
})
.catch((error) => setMessage(`ERROR: ${error}`));
};
const toggleRepeat = () => {
const url = playbackState.repeat
? "https://api.spotify.com/v1/me/player/repeat?state=off"
: "https://api.spotify.com/v1/me/player/repeat?state=track";
const request = putWithToken(url, token, source);
request()
.then((response) => {
if (response.status === 204) {
setMessage(`Repeat Track ${playbackState.repeat ? "Off" : "On"}`);
setPlaybackState((state) => ({ ...state, repeat: !state.repeat }));
updateState();
} else {
setMessage(
`ERROR: Something went wrong! Server response: ${response.status}`
);
}
})
.catch((error) => setMessage(`ERROR: ${error}`));
};
const skipNext = () => {
const request = putWithToken(
"https://api.spotify.com/v1/me/player/next",
token,
source,
{},
"POST"
);
request()
.then((response) => {
if (response.status !== 204) {
setMessage(
`ERROR: Something went wrong! Server response: ${response.status}`
);
return;
}
updateState();
})
.catch((error) => setMessage(`ERROR: ${error}`));
};
const skipPrev = () => {
const request = putWithToken(
"https://api.spotify.com/v1/me/player/previous",
token,
source,
{},
"POST"
);
request()
.then((response) => {
if (response.status !== 204) {
setMessage(
`ERROR: Something went wrong! Server response: ${response.status}`
);
return;
}
updateState();
})
.catch((error) => setMessage(`ERROR: ${error}`));
};
const seekPlayback = (ratio) => {
const time = Math.round(ratio * playbackState.total_time);
const request = putWithToken(
`https://api.spotify.com/v1/me/player/seek?position_ms=${time}`,
token,
source,
{}
);
request()
.then((response) => {
if (response.status === 204) {
setPlayback(ratio);
setPlaybackState((state) => ({ ...state, progress: time }));
updateState();
} else {
setMessage(
`ERROR: Something went wrong! Server response: ${response.status}`
);
}
})
.catch((error) => setMessage(`ERROR: ${error}`));
setScrubPb(null);
};
const scrubPlayback = (ratio) => {
const time = ratio * playbackState.total_time;
setScrubPb(time);
};
const seekVolume = (ratio) => {
const integer = Math.round(ratio * 100);
const request = putWithToken(
`https://api.spotify.com/v1/me/player/volume?volume_percent=${integer}`,
token,
source,
null
);
request()
.then((response) => {
if (response.status === 204) {
setVolume(ratio);
} else {
setMessage(
`ERROR: Something went wrong! Server response: ${response.status}`
);
}
})
.catch((error) => setMessage(`ERROR: ${error}`));
};
return (
<>
{/* {playbackState.play ? null:<Heartbeat heartbeatFunction={updateState} heartbeatInterval={10000}/>} */}
{playbackState.play ? (
<Heartbeat heartbeatFunction={updatePlayback} heartbeatInterval={500} />
) : null}
<div className="player">
<div className="player-left">
<NowPlaying playInfo={playInfo} />
</div>
<div className="player-center">
<div className="player-control-buttons">
<ControlButton
title="Toggle Shuffle"
icon="Shuffle"
active={playbackState.shuffle}
onClick={toggleShuffle}
/>
<ControlButton
title="Previous"
icon="TrackBack"
size="x-smaller"
onClick={skipPrev}
/>
<ControlButton
title={playbackState.play ? "Pause" : "Play"}
icon={playbackState.play ? "Pause" : "Play"}
size={playbackState.play ? "smaller" : "larger"}
extraClass="circle-border"
onClick={togglePlay}
/>
<ControlButton
title="Next"
icon="TrackNext"
size="x-smaller"
onClick={skipNext}
/>
<ControlButton
title="Toggle Repeat"
icon="Repeat"
active={playbackState.repeat}
onClick={toggleRepeat}
/>
</div>
<div className="player-playback" draggable="false">
<div className="playback-time" draggable="false">
{scrubPb
? msTimeFormat(scrubPb)
: msTimeFormat(playbackState.progress)}
</div>
<ProgressBar
extraClass="playback"
value={playback}
engageClass="engage"
setValue={(ratio) => seekPlayback(ratio)}
scrubFunction={scrubPlayback}
/>
<div className="playback-time" draggable="false">
{msTimeFormat(playbackState.total_time)}
</div>
</div>
</div>
<div className="player-right">
<div className="extra-controls">
<span className="connect-devices-wrapper">
{connectTip && (
<ConnectDevices
token={token}
closeTip={() => setConnectTip(false)}
/>
)}
<ControlButton
title="Devices"
icon="Speaker"
size="x-larger"
onClick={() => setConnectTip(!connectTip)}
active={playbackState.play}
/>
</span>
<div className="volume-control">
<ControlButton
title="Volume"
icon="Volume"
size="x-larger"
extraClass="volume"
/>
<div style={{ width: "100%" }}>
<ProgressBar
extraClass="volume"
value={volume}
engageClass="engage"
setValue={(ratio) => seekVolume(ratio)}
/>
</div>
</div>
</div>
</div>
</div>
</>
);
})
Example #20
Source File: payees.js From actual with MIT License | 4 votes |
ManagePayees = React.forwardRef(
(
{
modalProps,
payees,
ruleCounts,
categoryGroups,
tableNavigatorOpts,
initialSelectedIds,
ruleActions,
onBatchChange,
onViewRules,
onCreateRule,
...props
},
ref
) => {
let [highlightedRows, setHighlightedRows] = useState(null);
let [filter, setFilter] = useState('');
let table = useRef(null);
let scrollTo = useRef(null);
let resetAnimation = useRef(false);
let filteredPayees = useMemo(
() =>
filter === ''
? payees
: payees.filter(p =>
p.name.toLowerCase().includes(filter.toLowerCase())
),
[payees, filter]
);
let selected = useSelected('payees', filteredPayees, initialSelectedIds);
function applyFilter(f) {
if (filter !== f) {
table.current && table.current.setRowAnimation(false);
setFilter(f);
resetAnimation.current = true;
}
}
function _scrollTo(id) {
applyFilter('');
scrollTo.current = id;
}
useEffect(() => {
if (resetAnimation.current) {
// Very annoying, for some reason it's as if the table doesn't
// actually update its contents until the next tick or
// something? The table keeps being animated without this
setTimeout(() => {
table.current && table.current.setRowAnimation(true);
}, 0);
resetAnimation.current = false;
}
});
useImperativeHandle(ref, () => ({
selectRows: (ids, scroll) => {
tableNavigator.onEdit(null);
selected.dispatch({ type: 'select-all', ids });
setHighlightedRows(null);
if (scroll && ids.length > 0) {
_scrollTo(ids[0]);
}
},
highlightRow: id => {
tableNavigator.onEdit(null);
setHighlightedRows(new Set([id]));
_scrollTo(id);
}
}));
// `highlightedRows` should only ever be true once, and we
// immediately discard it. This triggers an animation.
useEffect(() => {
if (highlightedRows) {
setHighlightedRows(null);
}
}, [highlightedRows]);
useLayoutEffect(() => {
if (scrollTo.current) {
table.current.scrollTo(scrollTo.current);
scrollTo.current = null;
}
});
let onUpdate = useStableCallback((id, name, value) => {
let payee = payees.find(p => p.id === id);
if (payee[name] !== value) {
onBatchChange({ updated: [{ id, [name]: value }] });
}
});
let getSelectableIds = useCallback(() => {
return filteredPayees.filter(p => p.transfer_acct == null).map(p => p.id);
}, [filteredPayees]);
function onDelete() {
onBatchChange({ deleted: [...selected.items].map(id => ({ id })) });
selected.dispatch({ type: 'select-none' });
}
async function onMerge() {
let ids = [...selected.items];
await props.onMerge(ids);
tableNavigator.onEdit(ids[0], 'name');
selected.dispatch({ type: 'select-none' });
_scrollTo(ids[0]);
}
let buttonsDisabled = selected.items.size === 0;
let tableNavigator = useTableNavigator(
filteredPayees,
item =>
['select', 'name', 'rule-count'].filter(name => {
switch (name) {
case 'select':
return item.transfer_acct == null;
default:
return true;
}
}),
tableNavigatorOpts
);
let payeesById = getPayeesById(payees);
return (
<Modal
title="Payees"
padding={0}
{...modalProps}
style={[modalProps.style, { flex: 'inherit', maxWidth: '90%' }]}
>
<View
style={{
maxWidth: '100%',
width: 900,
height: 550
}}
>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
padding: '0 10px'
}}
>
<Component initialState={{ menuOpen: false }}>
{({ state, setState }) => (
<View>
<Button
bare
style={{ marginRight: 10 }}
disabled={buttonsDisabled}
onClick={() => setState({ menuOpen: true })}
>
{buttonsDisabled
? 'No payees selected'
: selected.items.size +
' ' +
plural(selected.items.size, 'payee', 'payees')}
<ExpandArrow
width={8}
height={8}
style={{ marginLeft: 5 }}
/>
</Button>
{state.menuOpen && (
<PayeeMenu
payeesById={payeesById}
selectedPayees={selected.items}
onClose={() => setState({ menuOpen: false })}
onDelete={onDelete}
onMerge={onMerge}
/>
)}
</View>
)}
</Component>
<View style={{ flex: 1 }} />
<Input
placeholder="Filter payees..."
value={filter}
onChange={e => {
applyFilter(e.target.value);
tableNavigator.onEdit(null);
}}
style={{
width: 350,
borderColor: 'transparent',
backgroundColor: colors.n11,
':focus': {
backgroundColor: 'white',
'::placeholder': { color: colors.n8 }
}
}}
/>
</View>
<SelectedProvider instance={selected} fetchAllIds={getSelectableIds}>
<View
style={{
flex: 1,
border: '1px solid ' + colors.border,
borderRadius: 4,
overflow: 'hidden',
margin: 5
}}
>
<PayeeTableHeader />
{filteredPayees.length === 0 ? (
<EmptyMessage text="No payees" style={{ marginTop: 15 }} />
) : (
<PayeeTable
ref={table}
payees={filteredPayees}
ruleCounts={ruleCounts}
categoryGroups={categoryGroups}
highlightedRows={highlightedRows}
navigator={tableNavigator}
onUpdate={onUpdate}
onViewRules={onViewRules}
onCreateRule={onCreateRule}
/>
)}
</View>
</SelectedProvider>
</View>
</Modal>
);
}
)
Example #21
Source File: DEFViewer.js From EDAViewer with MIT License | 4 votes |
DEFViewer = (props) => {
const {
design,
layerVisibility,
onResetDirtyLayers,
settings,
zoom,
width,
height,
metalLayerColors,
setSelectedComponentName,
exportDialogOpen,
exportDialogType,
setExportDialogOpen,
forwardedRef,
showCellDialog,
showViaDialog,
showWireDialog,
showPortDialog,
} = props;
const classes = useStyles();
const [isLoading, setIsLoading] = React.useState(true);
const {
Geometries: geometries,
InstancePins: pins,
RoutingVias: routingVias,
ViaDefinitions: viaDefs,
Die: die,
} = design;
const geometryMap = {};
geometries.forEach((geom) => {
geometryMap[geom.ID] = geom;
});
const pinMap = {};
pins.forEach((pin) => {
pinMap[pin.ID] = pin;
});
const viaMap = {};
routingVias.forEach((via) => {
viaMap[via.ID] = via;
});
viaDefs.forEach((via) => {
viaMap[via.ID] = via;
});
const scaleFactorX =
(width - settings.shapes.chip.strokeWidth * 2) / (die.XMax - die.XMin);
const scaleFactorY =
(height - settings.shapes.chip.strokeWidth * 2) / (die.YMax - die.YMin);
const originOffsetX =
-die.XMin * scaleFactorX + settings.shapes.chip.strokeWidth;
const originOffsetY =
die.YMin * scaleFactorY - settings.shapes.chip.strokeWidth;
const internalConfig = {
width,
height,
scaleFactorX,
scaleFactorY,
originOffsetX,
originOffsetY,
metalLayerColors,
};
const config = Object.assign({}, internalConfig, settings);
const appRef = useRef({
app: null,
viewport: null,
chip: null,
cells: null,
wires: null,
ports: null,
gcells: null,
rows: null,
tracks: null,
width,
height,
});
const ref = React.createRef();
const onCellClicked = (cell) => {
setSelectedComponentName(
<span>
Cell: <b>{cell.Name}</b>
</span>
);
};
const onCellDoubleClicked = (cell) => showCellDialog(cell);
const onWireClicked = (wire) => {
setSelectedComponentName(
<span>
Wire: <b>{wire.Name}</b>
</span>
);
};
const onWireDoubleClicked = (wire) => showWireDialog(wire);
const onViaClicked = (via) => {
setSelectedComponentName(
<span>
Via: <b>{via.Name}</b>
</span>
);
};
const onViaDoubleClicked = (via) => showViaDialog(via);
const onPortClicked = (port) => {
setSelectedComponentName(
<span>
Port: <b>{port.Name}</b>
</span>
);
};
const onPortDoubleClicked = (port) => showPortDialog(port);
const onExportCancel = () => {
setExportDialogOpen(false);
};
const onExport = () => {
setExportDialogOpen(false);
if (appRef.current.app) {
const extract = appRef.current.app.renderer.plugins.extract;
const tempLink = document.createElement("a");
document.body.append(tempLink);
tempLink.download = design.Name + "." + exportDialogType;
tempLink.href = extract.base64(
appRef.current.viewport,
"image/" + exportDialogType
);
tempLink.click();
tempLink.remove();
}
};
const resetViewport = (clearState = true) => {
if (!appRef.current.viewport) {
return;
}
["tracks", "rows", "gcells", "ports", "wires", "cells", "chip"].forEach(
(layer) => {
if (appRef.current[layer]) {
appRef.current.viewport.removeChild(appRef.current[layer]);
appRef.current[layer].destroy(true);
appRef.current[layer] = null;
}
}
);
appRef.current.app.stage.removeChild(appRef.current.viewport);
appRef.current.viewport.destroy(true);
appRef.current.viewport = null;
appRef.current.app.stage.destroy(true);
appRef.current.app.destroy(false, true);
appRef.current.app = null;
if (clearState) {
setSelectedComponentName(null);
onResetDirtyLayers();
}
};
useEffect(
createDesignApp(
design,
{
config,
layerVisibility,
pins: pinMap,
vias: viaMap,
geometries: geometryMap,
handlers: {
resetViewport,
onResetDirtyLayers,
onCellClicked,
onCellDoubleClicked,
onWireClicked,
onWireDoubleClicked,
onViaClicked,
onViaDoubleClicked,
onPortClicked,
onPortDoubleClicked,
setIsLoading,
},
},
appRef,
ref
),
[
layerVisibility,
zoom,
settings,
internalConfig.width,
internalConfig.height,
]
);
useImperativeHandle(forwardedRef, () => ({
zoomIn: () => {
if (appRef.current.viewport) {
appRef.current.viewport.setZoom(
appRef.current.viewport.scaled * config.scaleStepFactor,
true
);
}
},
zoomOut: () => {
if (appRef.current.viewport) {
appRef.current.viewport.setZoom(
appRef.current.viewport.scaled / config.scaleStepFactor,
true
);
}
},
fit: () => {
if (appRef.current.viewport) {
appRef.current.viewport.setZoom(1);
appRef.current.viewport.position.set(0, 0);
}
},
reset: () => {
resetViewport();
},
}));
return (
<React.Fragment>
<ExportDesignDialog
open={exportDialogOpen}
type={exportDialogType}
onExport={onExport}
onCancel={onExportCancel}
/>
{isLoading && (
<div
className={classes.viewerProgressBar}
style={{ width, height }}
>
<CircularProgress className={classes.progress} />
</div>
)}
<canvas
id="defviewer"
ref={ref}
width={width}
height={height}
className={classes.defViewerCanvas}
style={{
...(config.viewportBorder
? { border: "1px dashed #0000006e" }
: {}),
}}
></canvas>
</React.Fragment>
);
}
Example #22
Source File: PhoneNumberInput.js From rakning-c19-app with MIT License | 4 votes |
PhoneNumberInput = forwardRef(({ onSendPin, onPressFlag }, ref) => {
const [state, dispatch] = useReducer(reducer, initialState);
const { createAlert } = useAlert();
const phoneInputRef = useRef();
const numberInputRef = useRef();
const [tosAccepted, setTosAccepted] = useState(false);
const dimensions = useWindowDimensions();
const fontScale = isNaN(dimensions.fontScale) ? 1 : dimensions.fontScale;
const inputHeight = scale(fontScale <= 1 ? 50 : 50 * Math.min(fontScale, 2));
const { t, i18n } = useTranslation();
useImperativeHandle(ref, () => ({
onSelectCountry,
phoneNumberInputFocus,
cca2,
}));
const onChangePhoneNumber = phoneNumber => {
dispatch({ type: 'updatePhoneNumber', phoneNumber });
};
const onChangeCallingCode = callingCode => {
dispatch({ type: 'updateCallingCode', callingCode });
};
function onSelectCountry({ cca2, callingCode }) {
phoneInputRef.current.selectCountry(cca2.toLowerCase());
dispatch({ type: 'updateLocation', cca2, callingCode });
}
const phoneNumberInputFocus = () => {
numberInputRef?.current?.focus();
};
const cca2 = () => state.cca2;
const acceptTOS = () => {
setTosAccepted(!tosAccepted);
};
const openPP = () => {
WebBrowser.openBrowserAsync(privacyUrls[i18n.language] || privacyUrls.en);
};
const getPinNumber = async () => {
const { phoneNumber } = state;
const countryCode = phoneInputRef.current;
if (!isValid(countryCode.getCountryCode(), phoneNumber)) {
createAlert({
message: t('phoneValidationMessage'),
type: 'error',
});
return;
}
try {
const pinToken = await getPin(countryCode.getCountryCode(), phoneNumber);
onSendPin(countryCode.getCountryCode(), phoneNumber, pinToken);
} catch (error) {
createAlert({
message: t('genericErrorMessage'),
type: 'error',
});
}
};
const linkHitSlop = {
top: linkTouchPadding,
right: linkTouchPadding,
bottom: linkTouchPadding,
left: linkTouchPadding,
};
const Link = ({ children, onPress }) => {
return (
<TouchableWithoutFeedback onPress={onPress} hitSlop={linkHitSlop}>
<TOSLink>{children[0]}</TOSLink>
</TouchableWithoutFeedback>
);
};
return (
<>
<Vertical unit={1} />
<View
style={{
...styles.phoneInputContainer,
...(fontScale <= 1 && {
flexDirection: 'row',
}),
}}
>
<PhoneInput
ref={phoneInputRef}
onPressFlag={onPressFlag}
initialCountry="is"
style={{
...styles.phoneViewStyle,
minHeight: inputHeight,
width: fontScale <= 1 ? '40%' : '100%',
}}
textStyle={{
...styles.codeTextStyle,
minHeight: inputHeight,
textAlign: isRTL() ? 'right' : 'left',
}}
flagStyle={styles.flag}
offset={6}
onChangePhoneNumber={onChangeCallingCode}
/>
<TextInput
ref={numberInputRef}
placeholder={t('phoneNr')}
keyboardType="phone-pad"
returnKeyType="done"
autoCapitalize="none"
placeholderTextColor={Colors.placeholder}
autoCorrect={false}
style={{
...styles.phoneViewStyle,
...styles.phoneTextStyle,
minHeight: inputHeight,
textAlign: isRTL() ? 'right' : 'left',
width: fontScale <= 1 ? '60%' : '100%',
}}
onChangeText={onChangePhoneNumber}
/>
</View>
<Vertical unit={1} />
<Checkbox checked={tosAccepted} onPress={acceptTOS}>
<Trans i18nKey="tosAcceptance">
I agree to the <Link onPress={openPP}>Privacy Policy</Link>.
</Trans>
</Checkbox>
<Vertical fill />
<CtaButton
disabled={!tosAccepted || state.phoneNumber.length <= 0}
onPress={getPinNumber}
image={covidIcon}
imageDimensions={{ height: scale(28), width: scale(24) }}
>
{t('next')}
</CtaButton>
</>
);
})
Example #23
Source File: MessageInput.jsx From chat-ui-kit-react with MIT License | 4 votes |
function MessageInputInner(
{
value,
onSend,
onChange,
autoFocus,
placeholder,
fancyScroll,
className,
activateAfterChange,
disabled,
sendDisabled,
sendOnReturnDisabled,
attachDisabled,
sendButton,
attachButton,
onAttachClick,
...rest
},
ref
) {
const scrollRef = useRef();
const msgRef = useRef();
const [stateValue, setStateValue] = useControllableState(value, "");
const [stateSendDisabled, setStateSendDisabled] = useControllableState(
sendDisabled,
true
);
// Public API
const focus = () => {
if (typeof msgRef.current !== "undefined") {
msgRef.current.focus();
}
};
// Return object with public Api
useImperativeHandle(ref, () => ({
focus,
}));
// Set focus
useEffect(() => {
if (autoFocus === true) {
focus();
}
}, []);
// Update scroll
useEffect(() => {
if (typeof scrollRef.current.updateScroll === "function") {
scrollRef.current.updateScroll();
}
});
const getContent = () => {
// Direct reference to contenteditable div
const contentEditableRef = msgRef.current.msgRef.current;
return [
contentEditableRef.textContent,
contentEditableRef.innerText,
contentEditableRef.cloneNode(true).childNodes,
];
};
const send = () => {
if (stateValue.length > 0) {
// Clear input only when it's uncontrolled mode
if (value === undefined) {
setStateValue("");
}
// Disable send button only when it's uncontrolled mode
if (typeof sendDisabled === "undefined") {
setStateSendDisabled(true);
}
const content = getContent();
onSend(stateValue, content[0], content[1], content[2]);
}
};
const handleKeyPress = (evt) => {
if (
evt.key === "Enter" &&
evt.shiftKey === false &&
sendOnReturnDisabled === false
) {
evt.preventDefault();
send();
}
};
const handleChange = (innerHTML, textContent, innerText) => {
setStateValue(innerHTML);
if (typeof sendDisabled === "undefined") {
setStateSendDisabled(textContent.length === 0);
}
if (typeof scrollRef.current.updateScroll === "function") {
scrollRef.current.updateScroll();
}
const content = getContent();
onChange(innerHTML, textContent, innerText, content[2]);
};
const cName = `${prefix}-message-input`,
ph = typeof placeholder === "string" ? placeholder : "";
return (
<div
{...rest}
className={classNames(
cName,
{ [`${cName}--disabled`]: disabled },
className
)}
>
{attachButton === true && (
<div className={`${cName}__tools`}>
<AttachmentButton
onClick={onAttachClick}
disabled={disabled === true || attachDisabled === true}
/>
</div>
)}
<div className={`${cName}__content-editor-wrapper`}>
<EditorContainer
fancyScroll={fancyScroll}
ref={scrollRef}
className={`${cName}__content-editor-container`}
>
<ContentEditable
ref={msgRef}
className={`${cName}__content-editor`}
disabled={disabled}
placeholder={ph}
onKeyPress={handleKeyPress}
onChange={handleChange}
activateAfterChange={activateAfterChange}
value={stateValue}
/>
</EditorContainer>
</div>
{sendButton === true && (
<div className={`${cName}__tools`}>
<SendButton
onClick={send}
disabled={disabled === true || stateSendDisabled === true}
/>
</div>
)}
</div>
);
}
Example #24
Source File: ChartContainer.js From react-orgchart with MIT License | 4 votes |
ChartContainer = forwardRef(
(
{
datasource,
pan,
zoom,
zoomoutLimit,
zoominLimit,
containerClass,
chartClass,
NodeTemplate,
draggable,
collapsible,
multipleSelect,
onClickNode,
onClickChart
},
ref
) => {
const container = useRef();
const chart = useRef();
const downloadButton = useRef();
const [startX, setStartX] = useState(0);
const [startY, setStartY] = useState(0);
const [transform, setTransform] = useState("");
const [panning, setPanning] = useState(false);
const [cursor, setCursor] = useState("default");
const [exporting, setExporting] = useState(false);
const [dataURL, setDataURL] = useState("");
const [download, setDownload] = useState("");
const attachRel = (data, flags) => {
data.relationship =
flags + (data.children && data.children.length > 0 ? 1 : 0);
if (data.children) {
data.children.forEach(function(item) {
attachRel(item, "1" + (data.children.length > 1 ? 1 : 0));
});
}
return data;
};
const [ds, setDS] = useState(datasource);
useEffect(() => {
setDS(datasource);
}, [datasource]);
const dsDigger = new JSONDigger(datasource, "id", "children");
const clickChartHandler = event => {
if (!event.target.closest(".oc-node")) {
if (onClickChart) {
onClickChart();
}
selectNodeService.clearSelectedNodeInfo();
}
};
const panEndHandler = () => {
setPanning(false);
setCursor("default");
};
const panHandler = e => {
let newX = 0;
let newY = 0;
if (!e.targetTouches) {
// pand on desktop
newX = e.pageX - startX;
newY = e.pageY - startY;
} else if (e.targetTouches.length === 1) {
// pan on mobile device
newX = e.targetTouches[0].pageX - startX;
newY = e.targetTouches[0].pageY - startY;
} else if (e.targetTouches.length > 1) {
return;
}
if (transform === "") {
if (transform.indexOf("3d") === -1) {
setTransform("matrix(1,0,0,1," + newX + "," + newY + ")");
} else {
setTransform(
"matrix3d(1,0,0,0,0,1,0,0,0,0,1,0," + newX + ", " + newY + ",0,1)"
);
}
} else {
let matrix = transform.split(",");
if (transform.indexOf("3d") === -1) {
matrix[4] = newX;
matrix[5] = newY + ")";
} else {
matrix[12] = newX;
matrix[13] = newY;
}
setTransform(matrix.join(","));
}
};
const panStartHandler = e => {
if (e.target.closest(".oc-node")) {
setPanning(false);
return;
} else {
setPanning(true);
setCursor("move");
}
let lastX = 0;
let lastY = 0;
if (transform !== "") {
let matrix = transform.split(",");
if (transform.indexOf("3d") === -1) {
lastX = parseInt(matrix[4]);
lastY = parseInt(matrix[5]);
} else {
lastX = parseInt(matrix[12]);
lastY = parseInt(matrix[13]);
}
}
if (!e.targetTouches) {
// pand on desktop
setStartX(e.pageX - lastX);
setStartY(e.pageY - lastY);
} else if (e.targetTouches.length === 1) {
// pan on mobile device
setStartX(e.targetTouches[0].pageX - lastX);
setStartY(e.targetTouches[0].pageY - lastY);
} else if (e.targetTouches.length > 1) {
return;
}
};
const updateChartScale = newScale => {
let matrix = [];
let targetScale = 1;
if (transform === "") {
setTransform("matrix(" + newScale + ", 0, 0, " + newScale + ", 0, 0)");
} else {
matrix = transform.split(",");
if (transform.indexOf("3d") === -1) {
targetScale = Math.abs(window.parseFloat(matrix[3]) * newScale);
if (targetScale > zoomoutLimit && targetScale < zoominLimit) {
matrix[0] = "matrix(" + targetScale;
matrix[3] = targetScale;
setTransform(matrix.join(","));
}
} else {
targetScale = Math.abs(window.parseFloat(matrix[5]) * newScale);
if (targetScale > zoomoutLimit && targetScale < zoominLimit) {
matrix[0] = "matrix3d(" + targetScale;
matrix[5] = targetScale;
setTransform(matrix.join(","));
}
}
}
};
const zoomHandler = e => {
let newScale = 1 + (e.deltaY > 0 ? -0.2 : 0.2);
updateChartScale(newScale);
};
const exportPDF = (canvas, exportFilename) => {
const canvasWidth = Math.floor(canvas.width);
const canvasHeight = Math.floor(canvas.height);
const doc =
canvasWidth > canvasHeight
? new jsPDF({
orientation: "landscape",
unit: "px",
format: [canvasWidth, canvasHeight]
})
: new jsPDF({
orientation: "portrait",
unit: "px",
format: [canvasHeight, canvasWidth]
});
doc.addImage(canvas.toDataURL("image/jpeg", 1.0), "JPEG", 0, 0);
doc.save(exportFilename + ".pdf");
};
const exportPNG = (canvas, exportFilename) => {
const isWebkit = "WebkitAppearance" in document.documentElement.style;
const isFf = !!window.sidebar;
const isEdge =
navigator.appName === "Microsoft Internet Explorer" ||
(navigator.appName === "Netscape" &&
navigator.appVersion.indexOf("Edge") > -1);
if ((!isWebkit && !isFf) || isEdge) {
window.navigator.msSaveBlob(canvas.msToBlob(), exportFilename + ".png");
} else {
setDataURL(canvas.toDataURL());
setDownload(exportFilename + ".png");
downloadButton.current.click();
}
};
const changeHierarchy = async (draggedItemData, dropTargetId) => {
await dsDigger.removeNode(draggedItemData.id);
await dsDigger.addChildren(dropTargetId, draggedItemData);
setDS({ ...dsDigger.ds });
};
useImperativeHandle(ref, () => ({
exportTo: (exportFilename, exportFileextension) => {
exportFilename = exportFilename || "OrgChart";
exportFileextension = exportFileextension || "png";
setExporting(true);
const originalScrollLeft = container.current.scrollLeft;
container.current.scrollLeft = 0;
const originalScrollTop = container.current.scrollTop;
container.current.scrollTop = 0;
html2canvas(chart.current, {
width: chart.current.clientWidth,
height: chart.current.clientHeight,
onclone: function(clonedDoc) {
clonedDoc.querySelector(".orgchart").style.background = "none";
clonedDoc.querySelector(".orgchart").style.transform = "";
}
}).then(
canvas => {
if (exportFileextension.toLowerCase() === "pdf") {
exportPDF(canvas, exportFilename);
} else {
exportPNG(canvas, exportFilename);
}
setExporting(false);
container.current.scrollLeft = originalScrollLeft;
container.current.scrollTop = originalScrollTop;
},
() => {
setExporting(false);
container.current.scrollLeft = originalScrollLeft;
container.current.scrollTop = originalScrollTop;
}
);
},
expandAllNodes: () => {
chart.current
.querySelectorAll(
".oc-node.hidden, .oc-hierarchy.hidden, .isSiblingsCollapsed, .isAncestorsCollapsed"
)
.forEach(el => {
el.classList.remove(
"hidden",
"isSiblingsCollapsed",
"isAncestorsCollapsed"
);
});
}
}));
return (
<div
ref={container}
className={"orgchart-container " + containerClass}
onWheel={zoom ? zoomHandler : undefined}
onMouseUp={pan && panning ? panEndHandler : undefined}
>
<div
ref={chart}
className={"orgchart " + chartClass}
style={{ transform: transform, cursor: cursor }}
onClick={clickChartHandler}
onMouseDown={pan ? panStartHandler : undefined}
onMouseMove={pan && panning ? panHandler : undefined}
>
<ul>
<ChartNode
datasource={attachRel(ds, "00")}
NodeTemplate={NodeTemplate}
draggable={draggable}
collapsible={collapsible}
multipleSelect={multipleSelect}
changeHierarchy={changeHierarchy}
onClickNode={onClickNode}
/>
</ul>
</div>
<a
className="oc-download-btn hidden"
ref={downloadButton}
href={dataURL}
download={download}
>
</a>
<div className={`oc-mask ${exporting ? "" : "hidden"}`}>
<i className="oci oci-spinner spinner"></i>
</div>
</div>
);
}
)
Example #25
Source File: TopologyGraph.js From ThreatMapper with Apache License 2.0 | 4 votes |
TopologyGraph = forwardRef(
({ data, onNodeExpanded, onNodeCollapsed, onNodeClicked, onHover }, ref) => {
const [container, setContainer] = useState(null);
const [width, height] = useDOMSize(container);
const { graph } = useGraph(container, data || {});
const visible = useVisibilityState();
const layoutManagerRef = useRef(null);
const updateManagerRef = useRef(null);
const trackedItem = useRef(null);
const setTrackedItem = (item) => {
trackedItem.current = item;
};
const graphRef = useRef(graph);
useImperativeHandle(ref, () => ({
updateRootNodes: (delta) => {
updateManagerRef.current.updateRootNodes(delta);
},
updateNode: (node_id, delta) => {
updateManagerRef.current.updateNode(node_id, delta);
},
updateEdges: (delta) => {
updateManagerRef.current.updateEdges(delta);
},
findById: (node_id) => {
const graph = graphRef.current;
return graph.findById(node_id);
},
getParents: (node_id) => {
const graph = graphRef.current;
const item = graph.findById(node_id);
return getParents(graph, item);
},
expandNode: (node_id) => {
const graph = graphRef.current;
const item = graph.findById(node_id);
if (!itemIsExpanded(item)) {
expandNode(graph, item);
if (onNodeExpanded) {
onNodeExpanded(item);
}
}
},
collapseNode: (node_id) => {
const graph = graphRef.current;
const item = graph.findById(node_id);
if (itemIsExpanded(item)) {
collapseNode(graph, item, onNodeCollapsed);
}
},
}));
useEffect(() => {
// update the graph size when the container element is resized
if (graph !== null) {
// WTF something keeps resizing the container!?
if (height < 1000) {
graph.changeSize(width, height);
}
return;
}
}, [width, height]);
useEffect(() => {
if (layoutManagerRef.current) {
if (visible) {
layoutManagerRef.current.resume();
} else {
layoutManagerRef.current.pause();
}
}
}, [visible]);
useEffect(() => {
if (graph === null) {
return;
}
// this is used by the exported imperative API
graphRef.current = graph;
layoutManagerRef.current = new LayoutManager(graph, {
tick: debounce(() => {
if (trackedItem.current) {
nodeToFront(trackedItem.current);
graph.focusItem(trackedItem.current, true);
}
}, 500),
onLayoutStart: () => {
updateManagerRef.current.pause();
},
onLayoutEnd: () => {
updateManagerRef.current.resume();
},
});
updateManagerRef.current = new GraphUpdateManager(
graph,
layoutManagerRef.current
);
graph.on("node:mouseenter", (e) => {
if (onHover) {
onHover(e.item, true);
}
});
graph.on("node:mouseleave", (e) => {
if (onHover) {
onHover(e.item, false);
}
});
graph.on("node:drag", (e) => {
e.preventDefault();
});
graph.on("combo:drag", (e) => {
e.preventDefault();
});
graph.on("combo:dragend", (e) => {
try {
const combo = e.item;
fixCombo(graph, combo);
} catch (e) {
console.error("exception handling dragend", e);
}
});
graph.on("combo:click", (e) => {
graph.focusItem(e.item, true);
});
graph.on("node:click", (e) => {
try {
const item = e.item;
if (onNodeClicked) {
const model = item.get("model");
onNodeClicked(model);
}
if (itemExpands(item)) {
if (itemIsExpanded(item)) {
collapseNode(graph, item, onNodeCollapsed);
} else {
expandNode(graph, item);
if (onNodeExpanded) {
onNodeExpanded(item);
}
}
}
} catch (e) {
console.error("exception handling click", e);
}
});
graph.on("dragstart", () => {
setTrackedItem(null);
});
graph.on("df-track-item", (e) => {
setTrackedItem(e.item);
});
graph.on("beforeremoveitem", (e) => {
const item = e.item;
if (trackedItem.current?.get("model")?.id === item.id) {
setTrackedItem(null);
}
});
}, [graph, onNodeExpanded]);
return <div className="TopologyGraph" ref={setContainer}></div>;
}
)
Example #26
Source File: Video.js From react-native-tv-demo with MIT License | 4 votes |
Video = forwardRef((props, ref) => {
const {
source,
poster,
paused,
autoplay,
controls,
muted,
repeat,
inline,
volume,
rate,
onLoad,
onLoadStart,
onReadyForDisplay,
onPlaybackRateChange,
onProgress,
onSeek,
onEnd,
onError,
onExitFullscreen,
} = props;
// State
const [format, setFormat] = useState(FORMAT_HTML5);
const [shakaPlayer, setShakaPlayer] = useState(null);
// Video ref
const video = useRef(null);
useEffect(() => {
//console.log('Video.useEffect([])');
// Bind listeners
bindListeners();
return () => {
// Destroy shaka palyer
if (shakaPlayer) {
shakaPlayer.destroy();
}
// Unbind listeners
unbindListeners();
};
}, []);
useEffect(() => {
if (source) {
// Get file extension from source
const extension = source.split(/[#?]/)[0].split('.').pop().trim();
// Get format
let format = FORMAT_HTML5;
if (extension === 'm3u8') {
format = FORMAT_HLS;
} else if (extension === 'mpd') {
format = FORMAT_DASH;
setShakaPlayer(new shaka.Player(video.current));
}
setFormat(format);
}
}, [source]);
useEffect(() => {
//console.log('Video.useEffect([shakaPlayer, source])');
if (shakaPlayer && source) {
shakaPlayer.load(source);
}
}, [shakaPlayer, source]);
useEffect(() => {
//console.log("Video.useEffect([paused])", paused);
// Toggle play / pause from parent
if (paused === false) {
play();
} else if (paused === true) {
pause();
}
}, [paused]);
useEffect(() => {
console.log('rate: ', rate);
if (rate) {
if (rate === 0) {
pause();
} else {
play();
// TODO: handle rate < 1
}
}
}, [rate]);
useEffect(() => {
if (volume >= 0 && volume <= 1) {
video.current.volume = volume;
}
}, [volume]);
// Private methods
function play() {
//console.log('Video.play()');
if (video.current.paused) {
if (video.current.currentTime > 0 || !autoplay) {
// Handle old exception
let playPromise = null;
try {
playPromise = video.current.play();
} catch (error) {
onError(error);
}
// Handle promise
if (playPromise !== undefined) {
playPromise
.then(() => {
// playback started
})
.catch((error) => {
onError(error);
});
}
}
}
}
function pause() {
//console.log('Video.pause()');
if (!video.current.paused) {
video.current.pause();
}
}
// react-native-video API (public methods)
useImperativeHandle(ref, () => ({
/**
* react-native-video seek() method requires seconds
*
* @param seconds
*/
seek: (seconds) => {
//console.log('Video.seek(' + seconds + ')');
if (seconds) {
if (seconds >= 0 && seconds < video.current.duration) {
video.current.currentTime = seconds;
}
}
},
presentFullscrenPlayer: () => {
//console.log('Video.presentFullscreenPlayer()');
if (video) {
if (video.current.requestFullscreen) {
video.current.requestFullscreen();
}
// Deprecated
else if (video.current.enterFullscreen) {
video.current.enterFullscreen();
} else if (video.current.webkitEnterFullscreen) {
video.current.webkitEnterFullscreen();
}
}
},
dismissFullscreenPlayer: () => {
//console.log('Video.dismissFullscreenPlayer()');
if (document.exitFullscreen) {
document.exitFullscreen();
}
},
}));
// react-native-video callback proxy
/**
* loadedmetadata => onLoad
*/
function onVideoLoadedMetadata() {
//console.log('Video.onVideoLoadedMetadata()');
if (onLoad && video) {
onLoad({
currentPosition: 0,
duration: video.current.duration,
// TODO: naturalSize, audioTracks, textTracks
});
}
}
/**
* loadstart => onLoadStart
*/
function onVideoLoadStart() {
if (source) {
//console.log('Video.onVideoLoadStart()');
if (onLoadStart && video) {
onLoadStart({
isNetwork: true,
type: '',
uri: source.uri,
});
}
}
}
/**
* waiting => onLoadStart
*/
function onVideoWaiting() {
//console.log('Video.onVideoWaiting()');
if (onLoadStart && video) {
onLoadStart({
isNetwork: true,
type: '',
uri: source.uri,
});
}
}
/**
* canplaythrough => onReadyForDisplay
*/
function onVideoCanPlayThrough() {
//console.log('Video.onVideoCanPlayThrough()');
if (video) {
if (onReadyForDisplay) {
onReadyForDisplay();
}
}
}
/**
* play => onPlaybackRateChange
*/
function onVideoPlay() {
//console.log('Video.onVideoPlay()');
if (onPlaybackRateChange) {
onPlaybackRateChange({playbackRate: 1});
}
}
/**
* pause => onPlaybackRateChange
*/
function onVideoPause() {
//console.log('Video.onVideoPause()');
if (onPlaybackRateChange) {
onPlaybackRateChange({playbackRate: 0});
}
}
/**
* ratechange => onPlaybackRateChange
*/
function onVideoRateChange() {
//console.log('Video.onVideoRateChange()');
if (onPlaybackRateChange && video) {
onPlaybackRateChange({
playbackRate: video.current.playbackRate,
});
}
}
/**
* timeupdate => onProgress
*/
function onVideoTimeUpdate() {
//console.log('Video.onVideoTimeUpdate()');
if (onProgress && video) {
onProgress({
seekableDuration: video.current.duration,
playbableDuration: video.current.duration,
currentTime: video.current.currentTime,
});
}
}
/**
* seeked => onSeek
*/
function onVideoSeeked() {
//console.log('Video.onVideoSeeked()');
if (onSeek && video) {
onSeek({
currentTime: video.current.currentTime,
seekTime: video.current.currentTime,
});
}
}
/**
* ended => onEnd
*/
function onVideoEnded() {
//console.log('Video.onVideoEnded()');
if (onEnd) {
onEnd();
}
}
/**
* error => onError
*/
function onVideoError() {
if (source) {
//console.log('Video.onVideoError()');
let error = {};
// TODO: return same errors as react-native-video
if (onError) {
onError(error);
}
}
}
/**
* Get exit fullscreen event for webkit
*/
function onVideoEndFullscreen() {
//console.log('Video.onVideoEndFullscreen()');
if (onExitFullscreen) {
onExitFullscreen();
}
}
/**
* get exit fullscreen event for firefox
*/
function onVideoFullscreenChange(e) {
//console.log('Video.onVideoEndFullscreen()');
if (document.fullscreenElement) {
// enter fullscreen
} else if (onExitFullscreen) {
onExitFullscreen();
}
}
// Listeners
function bindListeners() {
//console.log('Video.bindListeners()');
if (video && video.current) {
// Unsupported native listeners
video.current.addEventListener(
'webkitendfullscreen',
onVideoEndFullscreen,
);
}
// Listeners on document
document.addEventListener('fullscreenchange', onVideoFullscreenChange);
}
function unbindListeners() {
//console.log('Video.unbindListeners()');
if (video && video.current) {
// Unsupported native listeners
video.current.removeEventListener(
'webkitendfullscreen',
onVideoEndFullscreen,
);
// Listeners on document
document.removeEventListener('fullscreenchange', onVideoFullscreenChange);
}
}
// Optional params
let controlsProp = controls ? {controls: 'controls'} : {};
let autoPlayProp = autoplay ? {autoplay: 'autoplay'} : {};
let mutedProp = muted ? {muted: 'muted'} : {};
let repeatProp = repeat ? {loop: 'loop'} : {};
let playsInlineProp = inline ? {playsInline: 'playsInline'} : {};
// Build <video> element
return (
<video
className="video"
ref={video}
src={source.uri || source}
poster={poster}
{...controlsProp}
{...autoPlayProp}
{...mutedProp}
{...repeatProp}
{...playsInlineProp}
onLoadedMetadata={onVideoLoadedMetadata}
onLoadStart={onVideoLoadStart}
onWaiting={onVideoWaiting}
onCanPlayThrough={onVideoCanPlayThrough}
onPlay={onVideoPlay}
onPause={onVideoPause}
onRateChange={onVideoRateChange}
onSeeked={onVideoSeeked}
onTimeUpdate={onVideoTimeUpdate}
onEnded={onVideoEnded}
onError={onVideoError}
style={{width: '100%', height: '100%'}}
/>
);
})
Example #27
Source File: navBar.js From AgileTC with Apache License 2.0 | 4 votes |
NavBar = (props, ref) => {
const { minder } = props;
const [zoomValue, setZoomValue] = useState(100);
// const [showMini, setShowMini] = useState(true);
if (minder !== null) {
minder.setDefaultOptions({ zoom });
}
const iconStyle = {
width: 24,
height: 24,
};
const handleClick = (key) => {
minder.execCommand(key);
};
const handleCameraClick = () => {
minder.execCommand('camera', minder.getRoot(), 600);
};
if (minder) {
minder.on('zoom', () => {
setZoomValue(minder.queryCommandValue('zoom'));
});
}
// useEffect(() => {
// if (props.minder) {
// // 画布,渲染缩略图
// const paper = new kity.Paper(document.getElementsByClassName('nav-previewer')[0]);
// // // 用两个路径来挥之节点和连线的缩略图
// const nodeThumb = paper.put(new kity.Path());
// const connectionThumb = paper.put(new kity.Path());
// // // 表示可视区域的矩形
// const visibleRect = paper.put(new kity.Rect(100, 100).stroke('red', '1%'));
// let contentView = new kity.Box();
// let visibleView = new kity.Box();
// let pathHandler = getPathHandler(props.minder.getTheme());
// // 主题切换事件
// props.minder.on('themechange', (e) => {
// pathHandler = getPathHandler(e.theme);
// });
// function getPathHandler(theme) {
// switch (theme) {
// case 'tianpan':
// case 'tianpan-compact':
// return function (nodePathData, x, y, width, height) {
// const r = width >> 1;
// nodePathData.push('M', x, y + r, 'a', r, r, 0, 1, 1, 0, 0.01, 'z');
// };
// default: {
// return function (nodePathData, x, y, width, height) {
// nodePathData.push('M', x, y, 'h', width, 'v', height, 'h', -width, 'z');
// };
// }
// }
// }
// function bind() {
// props.minder.on('layout layoutallfinish', updateContentView);
// props.minder.on('viewchange', updateVisibleView);
// }
// bind();
// function updateContentView() {
// const view = props.minder.getRenderContainer().getBoundaryBox();
// contentView = view;
// const padding = 30;
// paper.setViewBox(
// view.x - padding - 0.5,
// view.y - padding - 0.5,
// view.width + padding * 2 + 1,
// view.height + padding * 2 + 1
// );
// const nodePathData = [];
// const connectionThumbData = [];
// props.minder.getRoot().traverse(function (node) {
// const box = node.getLayoutBox();
// pathHandler(nodePathData, box.x, box.y, box.width, box.height);
// if (node.getConnection() && node.parent && node.parent.isExpanded()) {
// connectionThumbData.push(node.getConnection().getPathData());
// }
// });
// paper.setStyle('background', props.minder.getStyle('background'));
// if (nodePathData.length) {
// nodeThumb.fill(props.minder.getStyle('root-background')).setPathData(nodePathData);
// } else {
// nodeThumb.setPathData(null);
// }
// if (connectionThumbData.length) {
// connectionThumb
// .stroke(props.minder.getStyle('connect-color'), '0.5%')
// .setPathData(connectionThumbData);
// } else {
// connectionThumb.setPathData(null);
// }
// updateVisibleView();
// }
// updateContentView();
// function updateVisibleView() {
// visibleView = props.minder.getViewDragger().getView();
// visibleRect.setBox(visibleView.intersect(contentView));
// }
// updateVisibleView();
// }
// }, [props]);
useImperativeHandle(ref, () => ({
// 暴露给父组件的方法
handleClick,
}));
return (
<div className="nav-bar">
<a onClick={() => handleClick('ZoomIn')} title="放大">
<CustomIcon type="zoomIn" style={iconStyle} />
</a>
<span className="zoom-text">{zoomValue}%</span>
<a onClick={() => handleClick('ZoomOut')} title="缩小">
<CustomIcon type="zoomOut" style={iconStyle} />
</a>
<a style={{ marginLeft: 8 }} onClick={handleCameraClick} title="定位根节点">
<CustomIcon type="target" style={iconStyle} />
</a>
{/* <a
style={{ marginLeft: 8 }}
onClick={() => {
setShowMini(!showMini);
}}
title="展示/隐藏缩略图"
>
<Icon type="eye" style={{ fontSize: 24, color: 'rgba(0, 0, 0, 0.85)' }} />
</a>
<div className="nav-previewer" style={{ visibility: showMini ? 'visible' : 'hidden' }}></div> */}
</div>
);
}
Example #28
Source File: Recaptcha.js From react-native-recaptcha-that-works with MIT License | 4 votes |
Recaptcha = forwardRef(({
headerComponent,
footerComponent,
loadingComponent,
webViewProps,
modalProps,
onVerify,
onExpire,
onError,
onClose,
onLoad,
theme,
size,
siteKey,
baseUrl,
lang,
style,
enterprise,
recaptchaDomain,
gstaticDomain
}, $ref,
) => {
const $isClosed = useRef(true);
const $webView = useRef();
const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(true);
const isInvisibleSize = size === 'invisible';
const html = useMemo(() => {
return getTemplate({
siteKey,
size,
theme,
lang,
}, enterprise, recaptchaDomain, gstaticDomain);
}, [siteKey, size, theme, lang, enterprise]);
const handleLoad = useCallback((...args) => {
onLoad && onLoad(...args);
if (isInvisibleSize) {
$webView.current.injectJavaScript(`
window.rnRecaptcha.execute();
`);
}
setLoading(false);
}, [onLoad, isInvisibleSize]);
const handleClose = useCallback((...args) => {
if ($isClosed.current) {
return;
}
$isClosed.current = true;
setVisible(false);
onClose && onClose(...args);
}, [onClose]);
const handleMessage = useCallback((content) => {
try {
const payload = JSON.parse(content.nativeEvent.data);
if (payload.close && isInvisibleSize) {
handleClose();
}
if (payload.load) {
handleLoad(...payload.load);
}
if (payload.expire) {
onExpire && onExpire(...payload.expire);
}
if (payload.error) {
handleClose();
onError && onError(...payload.error);
}
if (payload.verify) {
handleClose();
onVerify && onVerify(...payload.verify);
}
} catch (err) {
console.warn(err);
}
}, [onVerify, onExpire, onError, handleClose, handleLoad, isInvisibleSize]);
const source = useMemo(() => ({
html,
baseUrl,
}), [html, baseUrl]);
useImperativeHandle($ref, () => ({
open: () => {
setVisible(true);
setLoading(true);
$isClosed.current = false;
},
close: handleClose,
}), [handleClose]);
const handleNavigationStateChange = useCallback(() => {
// prevent navigation on Android
if (!loading) {
$webView.current.stopLoading();
}
}, [loading]);
const handleShouldStartLoadWithRequest = useCallback(event => {
// prevent navigation on iOS
return event.navigationType === 'other';
}, [loading]);
const webViewStyles = useMemo(() => [
styles.webView,
style,
], [style]);
const renderLoading = () => {
if (!loading && source) {
return null;
}
return (
<View style={styles.loadingContainer}>
{loadingComponent || <ActivityIndicator size="large" />}
</View>
);
};
return (
<Modal
transparent
{...modalProps}
visible={visible}
onRequestClose={handleClose}
>
{headerComponent}
<WebView
bounces={false}
allowsBackForwardNavigationGestures={false}
{...webViewProps}
source={source}
style={webViewStyles}
originWhitelist={originWhitelist}
onMessage={handleMessage}
onShouldStartLoadWithRequest={handleShouldStartLoadWithRequest}
onNavigationStateChange={handleNavigationStateChange}
ref={$webView}
/>
{footerComponent}
{renderLoading()}
</Modal>
);
})
Example #29
Source File: index.js From eosio-components with MIT License | 4 votes |
Backdrop = forwardRef(
(
{
frontLayer,
backLayer,
layerHeightUp,
classes: extraClasses,
className,
headerText,
backgroundColor,
isStaticPage,
layerHeightDown
},
ref
) => {
const theme = useTheme()
const classes = useStyles()
const rootClasses = useRootStyles({ color: backgroundColor })
const isMobile = useMediaQuery(theme.breakpoints.down('xs'))
const isLandscape = useMediaQuery('(orientation: landscape)')
const [frontLayerHeight, setFrontLayerHeight] = useState(layerHeightUp)
const [transaction, setTransaction] = useState(false)
const [isArrowUp, setIsArrowUp] = useState(false)
const [showHeader, setShowHeader] = useState(false)
const handleOnClick = () => {
const height = window.innerHeight
const contentHeight = isArrowUp
? height - layerHeightDown
: height - (height - layerHeightUp)
setIsArrowUp(!isArrowUp)
setNewHeight(contentHeight)
}
useImperativeHandle(ref, () => ({
toggleOnClickMobile: () => {
if (isMobile) {
handleOnClick()
}
}
}))
const setNewHeight = useCallback(async (value) => {
setTransaction(true)
setFrontLayerHeight(value)
setTimeout(() => {
setTransaction(false)
}, TRANSITION_DURATION)
}, [])
useEffect(() => {
const height = window.innerHeight
setShowHeader(
(height < MIN_HEIGHT_TO_COLLAPSE && isLandscape) ||
(isMobile && !isStaticPage)
)
if (isStaticPage) {
setNewHeight(height - (height - layerHeightUp))
return
}
if (isMobile) {
setNewHeight(height - layerHeightDown)
return
}
if (!isMobile) {
setNewHeight(
isLandscape && height < MIN_HEIGHT_TO_COLLAPSE
? height - layerHeightDown
: height - (height - layerHeightUp)
)
}
}, [
isMobile,
layerHeightDown,
layerHeightUp,
setNewHeight,
isStaticPage,
isLandscape
])
return (
<div className={clsx(className, rootClasses.root, extraClasses.root)}>
<div
className={clsx(
classes.backLayer,
transaction ? classes.backlayerTransition : null,
extraClasses.backLayer
)}
style={{
height: frontLayerHeight
}}
>
{backLayer}
</div>
<Paper className={clsx(classes.frontLayer, extraClasses.frontLayer)}>
<div className={clsx(classes.headerBox, extraClasses.headerBox)}>
{headerText}
{showHeader && (
<IconButton
aria-label=""
classes={{ root: classes.iconDrop }}
onClick={handleOnClick}
>
{isArrowUp ? <DropDown /> : <DropUp />}
</IconButton>
)}
</div>
<div className={classes.contentWrapper}>
<div className={classes.frontLayerContent}>{frontLayer}</div>
</div>
</Paper>
</div>
)
}
)