merge master
This commit is contained in:
@@ -1,12 +1,10 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useWindowInfo } from '@faceless-ui/window-info';
|
||||
import { useScrollInfo } from '@faceless-ui/scroll-info';
|
||||
import { Props } from './types';
|
||||
|
||||
import useThrottledEffect from '../../../hooks/useThrottledEffect';
|
||||
import PopupButton from './PopupButton';
|
||||
|
||||
import './index.scss';
|
||||
import useIntersect from '../../../hooks/useIntersect';
|
||||
|
||||
const baseClass = 'popup';
|
||||
|
||||
@@ -30,26 +28,29 @@ const Popup: React.FC<Props> = (props) => {
|
||||
boundingRef,
|
||||
} = props;
|
||||
|
||||
const { width: windowWidth, height: windowHeight } = useWindowInfo();
|
||||
const [intersectionRef, intersectionEntry] = useIntersect({
|
||||
threshold: 1,
|
||||
rootMargin: '-100px 0px 0px 0px',
|
||||
root: boundingRef?.current || null,
|
||||
});
|
||||
|
||||
const buttonRef = useRef(null);
|
||||
const contentRef = useRef(null);
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [active, setActive] = useState(initActive);
|
||||
const [verticalAlign, setVerticalAlign] = useState(verticalAlignFromProps);
|
||||
const [horizontalAlign, setHorizontalAlign] = useState(horizontalAlignFromProps);
|
||||
|
||||
const { y: scrollY } = useScrollInfo();
|
||||
const { height: windowHeight, width: windowWidth } = useWindowInfo();
|
||||
|
||||
const handleClickOutside = useCallback((e) => {
|
||||
if (contentRef.current.contains(e.target)) {
|
||||
return;
|
||||
}
|
||||
|
||||
setActive(false);
|
||||
}, []);
|
||||
}, [contentRef]);
|
||||
|
||||
useThrottledEffect(() => {
|
||||
if (contentRef.current && buttonRef.current) {
|
||||
useEffect(() => {
|
||||
if (contentRef.current) {
|
||||
const {
|
||||
left: contentLeftPos,
|
||||
right: contentRightPos,
|
||||
@@ -79,13 +80,11 @@ const Popup: React.FC<Props> = (props) => {
|
||||
|
||||
if (contentTopPos < boundingTopPos && contentBottomPos < boundingBottomPos) {
|
||||
setVerticalAlign('bottom');
|
||||
} else if (contentBottomPos > boundingBottomPos && contentTopPos < boundingTopPos) {
|
||||
} else if (contentBottomPos > boundingBottomPos && contentTopPos > boundingTopPos) {
|
||||
setVerticalAlign('top');
|
||||
}
|
||||
|
||||
setMounted(true);
|
||||
}
|
||||
}, 500, [scrollY, windowHeight, windowWidth]);
|
||||
}, [boundingRef, intersectionEntry, windowHeight, windowWidth]);
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof onToggleOpen === 'function') onToggleOpen(active);
|
||||
@@ -112,7 +111,7 @@ const Popup: React.FC<Props> = (props) => {
|
||||
`${baseClass}--color-${color}`,
|
||||
`${baseClass}--v-align-${verticalAlign}`,
|
||||
`${baseClass}--h-align-${horizontalAlign}`,
|
||||
(active && mounted) && `${baseClass}--active`,
|
||||
(active) && `${baseClass}--active`,
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
@@ -144,6 +143,7 @@ const Popup: React.FC<Props> = (props) => {
|
||||
>
|
||||
<div
|
||||
className={`${baseClass}__wrap`}
|
||||
ref={intersectionRef}
|
||||
>
|
||||
<div
|
||||
className={`${baseClass}__scroll`}
|
||||
|
||||
@@ -131,13 +131,15 @@ export const code = baseField.keys({
|
||||
export const select = baseField.keys({
|
||||
type: joi.string().valid('select').required(),
|
||||
name: joi.string().required(),
|
||||
options: joi.array().items(joi.alternatives().try(
|
||||
joi.string(),
|
||||
joi.object({
|
||||
value: joi.string().required().allow(''),
|
||||
label: joi.string().required(),
|
||||
}),
|
||||
)).required(),
|
||||
options: joi.array().min(1).items(
|
||||
joi.alternatives().try(
|
||||
joi.string(),
|
||||
joi.object({
|
||||
value: joi.string().required().allow(''),
|
||||
label: joi.string().required(),
|
||||
}),
|
||||
),
|
||||
).required(),
|
||||
hasMany: joi.boolean().default(false),
|
||||
defaultValue: joi.alternatives().try(
|
||||
joi.string().allow(''),
|
||||
@@ -153,13 +155,15 @@ export const select = baseField.keys({
|
||||
export const radio = baseField.keys({
|
||||
type: joi.string().valid('radio').required(),
|
||||
name: joi.string().required(),
|
||||
options: joi.array().items(joi.alternatives().try(
|
||||
joi.string(),
|
||||
joi.object({
|
||||
value: joi.string().required().allow(''),
|
||||
label: joi.string().required(),
|
||||
}),
|
||||
)).required(),
|
||||
options: joi.array().min(1).items(
|
||||
joi.alternatives().try(
|
||||
joi.string(),
|
||||
joi.object({
|
||||
value: joi.string().required().allow(''),
|
||||
label: joi.string().required(),
|
||||
}),
|
||||
),
|
||||
).required(),
|
||||
defaultValue: joi.alternatives().try(
|
||||
joi.string().allow(''),
|
||||
joi.func(),
|
||||
|
||||
18
src/graphql/utilities/formatName.spec.ts
Normal file
18
src/graphql/utilities/formatName.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/* eslint-disable indent */
|
||||
/* eslint-disable jest/prefer-strict-equal */
|
||||
import formatName from './formatName';
|
||||
|
||||
describe('formatName', () => {
|
||||
it.each`
|
||||
char | expected
|
||||
${'á'} | ${'a'}
|
||||
${'è'} | ${'e'}
|
||||
${'í'} | ${'i'}
|
||||
${'ó'} | ${'o'}
|
||||
${'ú'} | ${'u'}
|
||||
${'ñ'} | ${'n'}
|
||||
${'ü'} | ${'u'}
|
||||
`('should convert accented character: $char', ({ char, expected }) => {
|
||||
expect(formatName(char)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
@@ -10,6 +10,10 @@ const formatName = (string: string): string => {
|
||||
}
|
||||
|
||||
const formatted = sanitizedString
|
||||
// Convert accented characters
|
||||
.normalize('NFKD')
|
||||
.replace(/[\u0300-\u036f]/g, '')
|
||||
|
||||
.replace(/\./g, '_')
|
||||
.replace(/-|\//g, '_')
|
||||
.replace(/\+/g, '_')
|
||||
|
||||
Reference in New Issue
Block a user