🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

dyvix-ui

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dyvix-ui - npm Package Compare versions

Comparing version
0.2.0
to
0.2.2
+2
-0
contributors.md

@@ -14,1 +14,3 @@ # Contributors

- [@0rbiT-ai](https://github.com/0rbiT-ai)
- [@dineshg0pal](https://github.com/dineshg0pal)
- [@DevBadoory](https://github.com/DevBadoory)
+1
-1
{
"name": "dyvix-ui",
"version": "0.2.0",
"version": "0.2.2",
"description": "Dyvix is an open source, modern, config-driven, animated component UI library. Beautiful by default, customizable by design.",

@@ -5,0 +5,0 @@ "main": "src/index.jsx",

@@ -16,3 +16,2 @@ [

"ease": "elastic.out(0.8, 0.6)",
"components": ["modal"],
"from": { "scale": 0, "opacity": 0 },

@@ -26,3 +25,2 @@ "to": { "scale": 1, "opacity": 1 }

"ease": "power3.out",
"components": ["modal"],
"from": { "scale": 1.15, "opacity": 0 },

@@ -36,3 +34,2 @@ "to": { "scale": 1, "opacity": 1 }

"ease": "power2.out",
"components": ["modal"],
"from": { "scaleY": -0.1, "opacity": 0, "transformOrigin": "top center" },

@@ -46,3 +43,2 @@ "to": { "scaleY": 1, "opacity": 1 }

"ease": "power4.out",
"components": ["modal"],
"from": { "x": -60, "skewX": 40, "opacity": 0 },

@@ -56,3 +52,2 @@ "to": { "x": 0, "skewX": 0, "opacity": 1 }

"ease": "elastic.out(0.6, 0.4)",
"components": ["modal"],
"from": { "scale": 0.8, "opacity": 0, "filter": "blur(50px)" },

@@ -66,3 +61,2 @@ "to": { "scale": 1, "opacity": 1, "filter": "blur(0px)" }

"ease": "power2.out",
"components": ["modal"],
"from": { "y": 80, "opacity": 0, "filter": "blur(35px)" },

@@ -76,3 +70,2 @@ "to": { "y": 0, "opacity": 1, "filter": "blur(0px)" }

"ease": "back.out(1.2)",
"components": ["modal"],
"from": { "y": -150, "opacity": 0 },

@@ -86,3 +79,2 @@ "to": { "y": 0, "opacity": 1 }

"ease": "power2.out",
"components": ["modal"],
"from": { "rotationY": 190, "opacity": 0 },

@@ -96,6 +88,13 @@ "to": { "rotationY": 0, "opacity": 1 }

"ease": "back.out(1.7)",
"components": ["modal"],
"from": { "rotationX": -10, "opacity": 0, "scale": 0.9, "y": 30 },
"to": { "rotationX": 0, "opacity": 1, "scale": 1, "y": 0 }
},
{
"animation": "drift",
"type": "in",
"default-duration": 0.97,
"ease": "power3.inOut",
"from": { "opacity": 0.1, "scale": 0.77, "y": 60 },
"to": { "opacity": 1, "scale": 1, "y": 0 }
}
]

@@ -256,1 +256,31 @@ .dyvix-modal-lens {

}
.dyvix-modal-midnight {
background: radial-gradient(circle at center, #00024d 0%, #000000 100%);
border: 1px solid rgba(112, 168, 247, 0.3);
border-radius: 3.67rem;
box-shadow:
0 0 40px 5px rgba(99, 102, 241, 0.2),
inset 0 0 15px rgba(112, 168, 247, 0.1);
-webkit-box-shadow:
0 0 40px 5px rgba(99, 102, 241, 0.2),
inset 0 0 15px rgba(112, 168, 247, 0.1);
-moz-box-shadow:
0 0 40px 5px rgba(99, 102, 241, 0.2),
inset 0 0 15px rgba(112, 168, 247, 0.1);
transition: all 0.5s cubic-bezier(0.17, 0.88, 0.3, 1.67);
backdrop-filter: blur(10px);
}
.dyvix-modal-midnight:hover {
background: radial-gradient(circle at 40% 40%, #000375 0%, #000000 100%);
border-color: rgba(112, 168, 247, 0.6);
box-shadow:
0 0 60px 10px rgba(99, 102, 241, 0.4),
inset 0 0 20px rgba(112, 168, 247, 0.2);
-webkit-box-shadow:
0 0 60px 10px rgba(99, 102, 241, 0.4),
inset 0 0 20px rgba(112, 168, 247, 0.2);
-moz-box-shadow:
0 0 60px 10px rgba(99, 102, 241, 0.4),
inset 0 0 20px rgba(112, 168, 247, 0.2);
transform: translateY(-3px) scale(1.01);
}

@@ -61,3 +61,9 @@ [

"radiused": false
},
{
"theme": "Midnight",
"class": "dyvix-modal-midnight",
"default-animation": "drift",
"radiused": false
}
]

@@ -1,2 +0,2 @@

export default function ExecuteValidator(value, validators) {
export function ExecuteValidator(value, validators) {
for (const validator of validators) {

@@ -18,2 +18,18 @@ const [funcName, optionParam] = validator.split('(');

export function ExecuteRegex(value, Rgx, errorMsg = 'Invalid format') {
console.log(Rgx)
const Regex = new RegExp(Rgx);
return { status: Regex.test(value), error: errorMsg };
}
export function isValidRegex(pattern) {
try {
new RegExp(pattern);
return true;
}
catch(e) {
return false;
}
}
const VALIDATORS_REGISTERY = {

@@ -20,0 +36,0 @@ isEmail: (value, options = {}) => ({

@@ -6,3 +6,4 @@ import {

eleData,
validPreset
validPreset,
validRules
} from './modal';

@@ -15,2 +16,3 @@ import presetData from './dependencies/presets.json';

} from '../../utils/DyvixGuard';
import { isValidRegex } from './dependencies/validator/validators';

@@ -22,2 +24,3 @@ const defaultElement = {

className: '!/',
validation: '!/',
amount: 1

@@ -144,2 +147,11 @@ };

function validateElements(elements) {
const MAX_ROWS = 9;
if (elements.length > MAX_ROWS) {
console.warn(
`[Dyvix UI] Maximum of ${MAX_ROWS} rows allowed. Extra rows will be ignored.`
);
elements.splice(MAX_ROWS); // trims array IN-PLACE
}
for (const element of elements) {

@@ -160,3 +172,3 @@ const currentType =

status: GaurdStatus.Error,
error: `Field '${element.id}' requires an options array.`
error: `Field '${element.name}' requires an options array.`
};

@@ -172,3 +184,3 @@ }

status: GaurdStatus.Error,
error: `Amount mismatch for '${element.id}'. Expected ${element.amount} option sets.`
error: `Amount mismatch for '${element.name}'. Expected ${element.amount} option sets.`
};

@@ -222,2 +234,43 @@ }

}
// Handels Validator engine validator
// Supports regex
const rules = Array.isArray(element.validation)
? element.validation
: [element.validation];
if(rules.length > element.amount) {
return {
status: GaurdStatus.Error,
error: `Validation overflow: maximum of amount of ${element.amount} reached.`
};
}
for(const rule of rules)
{
if (rule === "!/") break;
if (!rule || typeof rule !== 'string') continue;
if (rule.startsWith('$R'))
{
const [pattern, customError] = rule.slice(2).split('|');
if(!isValidRegex(pattern))
{
return {
status: GaurdStatus.Error,
error: `Invalid Regular Expression was provided.`
};
}
}
else if (!validRules.includes(rule))
{
return {
status: GaurdStatus.Error,
error: `'${rule}' is not a recognized validator.`
};
}
}
}

@@ -224,0 +277,0 @@

@@ -11,3 +11,6 @@ import elementsData from './dependencies/elements.json';

import * as validatorsFunctions from './dependencies/validator/validators';
import ExecuteValidator from './dependencies/validator/validators';
import {
ExecuteValidator,
ExecuteRegex
} from './dependencies/validator/validators';
import React from 'react';

@@ -22,2 +25,3 @@ import { useGSAP } from '@gsap/react';

export const validPreset = presetData.map((e) => e.preset);
export const validRules = validationData.map((e) => e.preset);

@@ -56,2 +60,3 @@ export const eleData = elementsData;

const [visibility, SetVisibility] = React.useState(true);
const [status, SetStatus] = React.useState('entering');
const fields = SerializeData(

@@ -79,3 +84,3 @@ title,

function handleModalClose() {
SetVisibility(false);
SetStatus('leaving');
if (typeof onClose === 'function') {

@@ -89,20 +94,21 @@ onClose();

if (!field.validation) continue;
for (const [index, currentName] of field.name.entries()) {
const currentValidation = field.validation[index];
let currentValidation = field.validation[index];
let result = null;
if (!currentValidation) continue;
const validators = validationData.find(
(e) =>
e.preset.trim().toLowerCase() ===
currentValidation.trim().toLowerCase()
);
if (currentValidation.startsWith('$R')) {
const [pattern, customError] = currentValidation.slice(2).split('|');
result = ExecuteRegex(data[currentName], pattern, customError);
} else {
const validators = validationData.find(
(e) =>
e.preset.trim().toLowerCase() ===
currentValidation.trim().toLowerCase()
);
if (!validators) continue;
if (!validators) continue;
const result = ExecuteValidator(
data[currentName],
validators.validators
);
result = ExecuteValidator(data[currentName], validators.validators);
}
if (result) {

@@ -199,9 +205,19 @@ newErrors[currentName] = result.status ? null : result.error;

gsap.set(modalRef.current, { margin: dynamicMargin });
gsap.fromTo(modalRef.current, currentAnimation.from, {
...currentAnimation.to,
duration: currentAnimation['default-duration'],
ease: currentAnimation.ease
});
}, [currentAnimation]);
if (status === 'entering') {
gsap.fromTo(modalRef.current, currentAnimation.from, {
...currentAnimation.to,
duration: currentAnimation['default-duration'],
ease: currentAnimation.ease
});
} else {
gsap.fromTo(modalRef.current, currentAnimation.to, {
...currentAnimation.from,
duration: currentAnimation['default-duration'],
ease: currentAnimation.ease,
onComplete: () => SetVisibility(false)
});
}
}, [currentAnimation, status]);
return (

@@ -250,3 +266,3 @@ <>

const id = field.id[j];
const fontSize = field.amount === 3 ? '0.5rem' : 'normal';
const fontSize = field.amount === 3 ? '0.6rem' : 'normal';
const fontWeight = field.amount === 3 ? '520' : '200';

@@ -287,2 +303,8 @@ // Spread aria props safely to avoid runtime errors if elementDef.aria is missing or null

}
const options =
Tag === 'select' || elementDef.tag === 'DynamicSelect'
? Array.isArray(field.options[0])
? field.options[j]
: field.options
: [];

@@ -307,3 +329,3 @@ const Tagprobs = {

...(elementDef.tag === 'DynamicSelect' && {
elements: field.options[j],
elements: options,
animation: '!/',

@@ -329,3 +351,3 @@ Class: 'modal-element'

</option>
{field.options[j].map((opt, index) => (
{options.map((opt, index) => (
<option

@@ -332,0 +354,0 @@ role="option"

@@ -56,7 +56,2 @@ .dyvix-select-wrapper {

}
.dyvix-dropdown-select li:hover {
transform: scale(1.003);
background-color: #e0f7fa;
cursor: pointer;
}
.dyvix-dropdown-select li:active {

@@ -63,0 +58,0 @@ background-color: #b2ebf2;

@@ -11,2 +11,11 @@ import './dependencies/style/styles.css';

/**
* @param {Object} props
* @param {Array<Object>} props.elements - Array of select elements
* @param {Function} [props.onChange] - Change callback
* @param {('select'|'autocomplete')} props.type - Select type
* @param {string} [props.animation] - Animation name, defaults to fade
* @param {string} [props.Class] - Select class
* @param {string} [props.placeholder] - Select placeholder
*/
function DynamicSelect({

@@ -18,3 +27,3 @@ elements = [],

Class,
placeholder = 'Select...',
placeholder = '',
...props

@@ -28,3 +37,4 @@ }) {

elements: [],
selected: ''
selected: '',
activeIndex: -1
});

@@ -93,2 +103,42 @@ const selectRef = React.useRef(null);

function HandleKey(e, controller) {
if (Select.is_open == false) return;
const { key } = e;
const max = Select.elements.length - 1;
const min = -1;
const index = Select.activeIndex;
if (key === 'ArrowUp') {
if (index <= min) return;
controller((prevData) => ({
...prevData,
activeIndex: index - 1
}));
e.preventDefault();
}
if (key === 'ArrowDown') {
if (index >= max) return;
controller((prevData) => ({
...prevData,
activeIndex: index + 1
}));
e.preventDefault();
}
if (key === 'Enter') {
if (index < 0 || index > max) return;
selectRef.current.value = Select.elements[index];
controller((prevData) => ({
...prevData,
selected: Select.elements[index],
is_open: false,
activeIndex: -1
}));
e.preventDefault();
}
}
useGSAP(() => {

@@ -126,2 +176,3 @@ if (!selectRef.current || !currentAnimation) return;

}}
onKeyDown={(e) => HandleKey(e, SetSelect)}
/>

@@ -133,2 +184,3 @@ <SelectEngine

inputRef={selectRef}
activeIndex={Select.activeIndex}
ref={dropdownSelectRef}

@@ -135,0 +187,0 @@ controller={SetSelect}

@@ -15,2 +15,3 @@ import './dependencies/style/styles.css';

controller,
activeIndex,
inputRef,

@@ -32,3 +33,4 @@ OnChangeCallback,

...prevData,
is_open: false
is_open: false,
activeIndex: -1
}));

@@ -77,2 +79,8 @@

useEffect(() => {
if (activeIndex >= 0 && itemsRef.current[activeIndex]) {
itemsRef.current[activeIndex].scrollIntoView({ block: 'nearest' });
}
}, [activeIndex]);
return (

@@ -97,2 +105,7 @@ <>

key={index}
style={
index === activeIndex
? { backgroundColor: '#e0f7fa', cursor: 'pointer' }
: {}
}
onMouseDown={(e) => {

@@ -102,2 +115,8 @@ e.preventDefault();

}}
onMouseEnter={() => {
controller((prevData) => ({
...prevData,
activeIndex: index
}));
}}
>

@@ -104,0 +123,0 @@ {element}

@@ -17,3 +17,11 @@ [

"class": "dyvix-bottom-right"
},
{
"position": "top-center",
"class": "dyvix-top-center"
},
{
"position": "bottom-center",
"class": "dyvix-bottom-center"
}
]

@@ -12,2 +12,5 @@ .dyvix-toast-container {

display: flex;
flex-direction: column;
text-align: left;
gap: 4px;
width: 20rem;

@@ -17,16 +20,56 @@ min-height: 4.5rem;

height: auto;
background-color: #ff3366;
border-radius: 2rem;
border-radius: 1.5rem;
align-items: flex-start;
padding: 1rem 1.2rem;
box-sizing: border-box;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
.dyvix-toast-error {
background-color: #fcbec6;
border: 1px solid rgba(255, 51, 102, 0.3);
}
.dyvix-toast-success {
background-color: #a8fcb4;
border: 1px solid rgba(20, 206, 79, 0.3);
}
.dyvix-toast-title {
width: 100%;
font-weight: 600;
font-size: 0.9rem;
display: flex;
align-items: center;
gap: 6px;
}
.dyvix-toast-content {
width: 100%;
padding: 0 2rem;
font-size: 0.8rem;
opacity: 0.85;
padding-left: 30px;
}
.dyvix-toast-error {
background-color: #ff3366;
.dyvix-toast-icon {
border-radius: 50%;
border: 2px solid;
width: 18px;
height: 18px;
padding: 3px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
box-shadow: inset 0 0 4px rgba(1, 6, 2, 0.848);
}
.dyvix-toast-success {
background-color: green;
.toast-error {
color: #ff3366;
}
.toast-success {
color: #1df13c;
}
.toast-error .dyvix-toast-icon {
border-color: #ff3366;
box-shadow: inset 0 0 4px rgba(5, 2, 3, 0.848);
}
.toast-success .dyvix-toast-icon {
border-color: #14ce4f;
box-shadow: inset 0 0 4px rgba(2, 5, 3, 0.848);
}
/* move to positions.css ? */

@@ -49,1 +92,11 @@ .dyvix-top-right {

}
.dyvix-top-center {
top: 1rem;
left: 50%;
transform: translateX(-50%);
}
.dyvix-bottom-center {
bottom: 1rem;
left: 50%;
transform: translateX(-50%);
}

@@ -9,2 +9,3 @@ import React from 'react';

animation,
type,
onClose,

@@ -15,2 +16,3 @@ duration = 5000

const [status, SetStatus] = React.useState('entering');
const icons = { success: '✓', error: '✕', warning: '⚠', info: 'i' };
const currentAnimation = animation

@@ -38,2 +40,3 @@ ? animationsData.find(

duration: currentAnimation['default-duration'],
delay: Math.random() * 0.3,
ease: currentAnimation.ease,

@@ -59,2 +62,6 @@ onComplete: onClose

<div className={Class} ref={toastRef}>
<span className={`dyvix-toast-title toast-${type.toLowerCase()}`}>
<span className="dyvix-toast-icon">{icons[type.toLowerCase()]}</span>{' '}
{type}
</span>
<span className="dyvix-toast-content">{message}</span>

@@ -61,0 +68,0 @@ </div>

@@ -15,5 +15,12 @@ import './dependencies/style/style.css';

/**
* @param {Object} props
* @param {'top-left'|'top-right'|'top-center'|'bottom-left'|'bottom-right'|'bottom-center'} props.position - Toast postion
* @param {number} props.segments - The max amount of toast at a time
* @param {number} props.duration - The duration to show the toast for in mile seconds.
* @param {string} [props.animation] - Animation name, defaults to zoom
*/
function DyvixToastContainer({
position = 'top-right',
segments,
segments = 10,
duration = 5000,

@@ -45,3 +52,3 @@ animation = 'zoom'

<div className={`dyvix-toast-container ${currentPosition.class}`}>
{toasts.map((toast, i) => {
{toasts.slice(0, segments).map((toast, i) => {
const currentType = TypesData.find(

@@ -62,2 +69,3 @@ (e) => e.type.trim().toLowerCase() === toast.type.trim().toLowerCase()

animation={animation}
type={currentType.type}
/>

@@ -64,0 +72,0 @@ );

@@ -27,4 +27,10 @@ import {

}
if (segments <= 0 || segments > 10) {
return {
status: GaurdStatus.Error,
error: 'Please provide a segment between 1 and 10.'
};
}
return { status: GaurdStatus.Success };
}

@@ -13,3 +13,4 @@ //AUTO GENERATED BY DYVIX UI ENGINE - DO NOT MANUALLY EDIT.

OCEAN: 'Ocean',
FOREST: 'Forest'
FOREST: 'Forest',
MIDNIGHT: 'Midnight'
};

@@ -30,3 +31,4 @@ export const DYVIX_MODAL_TYPE = {

FLIP: 'flip',
GLIDE: 'glide'
GLIDE: 'glide',
DRIFT: 'drift'
};

@@ -33,0 +35,0 @@ export const DYVIX_MODAL_VALIDATION_PRESET = {