merge master

This commit is contained in:
James
2022-09-07 11:53:02 -07:00
7 changed files with 90 additions and 33 deletions

View File

@@ -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`}

View File

@@ -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(),

View 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);
});
});

View File

@@ -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, '_')