npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@eisgs/modal

v2.1.0

Published

Для работы модальных окон нужно обернуть приложение в `ModalProvider` из `@eisgs/modal` и задать уникальные имена для модальных окон

Downloads

84

Readme

ModalProvider

Для работы модальных окон нужно обернуть приложение в ModalProvider из @eisgs/modal и задать уникальные имена для модальных окон

<ModalProvider>
  <App />
</ModalProvider>

ModalConfirm

confirmText и cancelText задают текст в кнопках управления модалкой. onConfirm и onCancel задают обработчик клика на соответсвующие кнопки hasAlertIcon добавляет иконку алерта

  import { ModalConfirm, useModal } from '@eisgs/modal';
  import { Button } from '@eisgs/button';
  import { Fragment } from 'react';

  const modal = useModal();
  
  const nameList = [
    {
      name: 'Title',
      title: 'Удалить документ ?',
      confirmText: 'Удалить'
    },
    {
      name: 'Title & text',
      title: 'Удалить документ ?',
      children: 'Образованные земельные участки ниже будут также удалены.',
      confirmText: 'Удалить'
    },
    {
      name: 'Alert',
      title: 'Внимание',
      hasAlertIcon: true,
      children: 'При изменении исходных земельных участков, загруженный шаблон и образованные участки ниже будут удалены.',
    },
    {
      name: 'Alert text',
      hasAlertIcon: true,
      children: 'При изменении исходных земельных участков, загруженный шаблон и образованные участки ниже будут удалены.',
    },
    {
      name: 'Alert with primary button',
      title: 'Внимание',
      confirmType: 'primary',
      confirmText: 'Закрыть',
      hasAlertIcon: true,
      children: 'При изменении исходных земельных участков, загруженный шаблон и образованные участки ниже будут удалены.',
    },
  ];
  
  <div style={{display: 'flex'}}>
    {nameList.map(({name, children, ...rest}, index) => (
      <Fragment key={name}>
        <Button 
          onClick={() => modal.open(name)} 
          {...index % 2 === 0 && {type: 'secondary'}}
          styles='margin-right: 40px'
        >
          {name}
        </Button>
        <ModalConfirm
          {...rest}
          name={name}
          onConfirm={() => modal.close(name)}
          onCancel={() => modal.close(name)}
        >
          {children}
       </ModalConfirm>
      </Fragment>
    ))}
  </div>

Управление шириной Modal

По умолчанию ширина модального окна 312px, но если заголовок модалки или ширина контента не влезают - модалка будет растянута. width позволяет явно задать ширину модального окна и исключить растягивание

  import { Modal, useModal } from '@eisgs/modal';
  import { Button } from '@eisgs/button';

  const modal = useModal();
  const sampleText = (count) => 'Съешь же ещё этих мягких французских булок, да выпей чаю. '.repeat(count);

  <>
    <div className="md-flex-row md-flex-wrap w1200">
      <Button type="primary" onClick={() => modal.open('modal_content_1')}>Модалка без контента</Button>
      <Button type="secondary" onClick={() => modal.open('modal_content_2')}>Модалка с широким контентом</Button>
      <Button type="primary" onClick={() => modal.open('modal_content_3')}>Модалка с широким контентом и явно заданной шириной</Button>
    </div>
    <Modal name="modal_content_1" />
    <Modal name="modal_content_2">{sampleText(100)}</Modal>
    <Modal name="modal_content_3" width={300}>{sampleText(100)}</Modal>
  </>

Управление цветом

isGreyModal задает серую тему для модального окна

  import { Modal, ModalHeader, useModal } from '@eisgs/modal';
  import { Button } from '@eisgs/button';

  const modal = useModal();
  const sampleText = (count) => 'Съешь же ещё этих мягких французских булок, да выпей чаю. '.repeat(count);
  const whiteBlockStyle = { backgroundColor: 'white', padding: '20px', marginBottom: '10px' };
  const greyBlockStyle = { backgroundColor: '#f8f8f8', padding: '20px', marginBottom: '10px' };

  <>
    <div className="md-flex-row md-flex-wrap w500">
      <Button type="primary" onClick={() => modal.open('modal_color_1')}>Модалка обычная</Button>
      <Button type="secondary" onClick={() => modal.open('modal_color_2')}>Модалка с серым фоном</Button>
    </div>
    <Modal name="modal_color_1" width={400}>
      <ModalHeader>Заголовок модалки</ModalHeader>
      <div style={greyBlockStyle}>
        {sampleText(2)}
      </div>
      <div style={greyBlockStyle}>
        {sampleText(2)}
      </div>
      <div style={greyBlockStyle}>
        {sampleText(2)}
      </div>
    </Modal>
    <Modal name="modal_color_2" isGreyModal width={400}>
      <ModalHeader>Заголовок модалки</ModalHeader>
      <div style={whiteBlockStyle}>
        {sampleText(2)}
      </div>
      <div style={whiteBlockStyle}>
        {sampleText(2)}
      </div>
      <div style={whiteBlockStyle}>
        {sampleText(2)}
      </div>
    </Modal>
  </>

Управление заголовком в модальном окне

Для управления заголовком следует использовать компонент <ModalHeader>который принимает children в качестве контента и fontType - тип шрифта (h1, h2, h3, h4, p1, p2, p3, p2compact, caption, button, plink, link), fontWeight - вес шрифта ('bold', 'bolder', 'lighter', 'normal', 500, 700), ellipsisMaxLines - обрезку текста в заголовке (число линий);

  import { Modal, ModalHeader, useModal } from '@eisgs/modal';
  import { Button } from '@eisgs/button';
  import { Input } from '@eisgs/input';

  const modal = useModal();

  <>
    <div className="md-flex-row md-flex-wrap w1200">
      <Button type="primary" onClick={() => modal.open('modal_header_1')}>Модалка с заголовком h1</Button>
      <Button type="secondary" onClick={() => modal.open('modal_header_2')}>Модалка с заголовком h2</Button>
      <Button type="primary" onClick={() => modal.open('modal_header_3')}>Модалка с заголовком h3</Button>
      <Button type="secondary" onClick={() => modal.open('modal_header_4')}>Модалка с заголовком h4</Button>
    </div>
    <div className="md-flex-row md-flex-wrap w1200">
      <Button type="secondary" onClick={() => modal.open('modal_header_5')}>Модалка со стандартным заголовком</Button>
      <Button type="primary" onClick={() => modal.open('modal_header_6')}>Модалка с кастомный весом шрифта</Button>
      <Button type="secondary" onClick={() => modal.open('modal_header_7')}>Модалка с обрезкой текста 1</Button>
    </div>
    <div className="md-flex-row md-flex-wrap w1200">
      <Button type="primary" onClick={() => modal.open('modal_header_8')}>Модалка с обрезкой текста 2</Button>
    </div>
    <Modal name="modal_header_1">
      <ModalHeader fontType='h1'>Заголовок модалки h1</ModalHeader>
      <Input label="инпут 1" value="значение 1" />
    </Modal>
    <Modal name="modal_header_2">
      <ModalHeader fontType='h2'>Заголовок модалки h2</ModalHeader>
      <Input label="инпут 1" value="значение 1" />
    </Modal>
    <Modal name="modal_header_3">
      <ModalHeader fontType='h3'>Заголовок модалки h3</ModalHeader>
      <Input label="инпут 1" value="значение 1" />
    </Modal>
    <Modal name="modal_header_4">
      <ModalHeader fontType='h4'>Заголовок модалки h4</ModalHeader>
      <Input label="инпут 1" value="значение 1" />
    </Modal>
    <Modal name="modal_header_5">
      <ModalHeader>Стандартный заголовок модалки p1 bold</ModalHeader>
      <Input label="инпут 1" value="значение 1" />
    </Modal>
    <Modal name="modal_header_6">
      <ModalHeader fontWeight='normal'>Кастомный вес шрифта</ModalHeader>
      <Input label="инпут 1" value="значение 1" />
    </Modal>
    <Modal width={200} name="modal_header_7">
      <ModalHeader ellipsisMaxLines={1} >Очень длинный заголовок модалки и его обрезка</ModalHeader>
      <Input label="инпут 1" value="значение 1" />
    </Modal>
    <Modal width={200} name="modal_header_8">
      <ModalHeader ellipsisMaxLines={2}>Очень длинный заголовок модалки и его обрезка при превышении ширины</ModalHeader>
      <Input label="инпут 1" value="значение 1" />
    </Modal>
  </>

Простые и вложенные модальные окна

  import { Modal, ModalHeader, useModal } from '@eisgs/modal';
  import { Button } from '@eisgs/button';
  
  const modal = useModal();

  <>
    <div className="md-flex-row md-flex-wrap w1000">
      <Button type="primary" onClick={() => modal.open('modal_options_1')}>Открыть простую модалку</Button>
      <Button type="secondary" onClick={() => modal.open('modal_options_2')}>Открыть модалку, в которой есть вложенная модалка</Button>
    </div>
    <Modal name='modal_options_1'>
      <ModalHeader>Простая модалка 1</ModalHeader>
    </Modal>
    <Modal name='modal_options_2'>
      <>
        <ModalHeader>Простая модалка 2</ModalHeader>
        <Button type="primary" onClick={() => modal.open('modal_options_3')}>Открыть вложенную модалку</Button>
        <Modal name='modal_options_3'>
          <ModalHeader>Модалка 3</ModalHeader>
        </Modal>
      </>
    </Modal>
  </>

Кнопки в модальном окне

<ModalFooter> позволяет сделать обертку для кнопок c flex-контейнером и отсупом 32px сверху. Для позиционирования кнопок используются justifyContent и alignItems со значениями как в обычном flex

  import { Modal, ModalHeader, ModalFooter, useModal } from '@eisgs/modal';
  import { Button } from '@eisgs/button';

  const modal = useModal();
  const sampleText = (count) => 'Съешь же ещё этих мягких французских булок, да выпей чаю. '.repeat(count);

  <>
    <div>
      <Button type="secondary" onClick={() => modal.open('modal_footer_1')}>Кнопки в модалке</Button>
      <Button type="primary" onClick={() => modal.open('modal_footer_2')} styles={`margin-top: 20px`}>Кнопки в модалке 2</Button>
    </div>
    <Modal name='modal_footer_1' width={444}>
      <ModalHeader>Кнопки в модалке</ModalHeader>
      <ModalFooter justifyContent='flex-start'>
        <Button type="primary">Сохранить</Button>
        <Button type="secondary" >Отмена</Button>
      </ModalFooter>
    </Modal>
    <Modal name='modal_footer_2' width={444}>
      <ModalHeader>Кнопки в модалке 2</ModalHeader>
      <ModalFooter justifyContent='flex-end'>
        <Button type="primary">Отправить</Button>
        <Button type="secondary" >Отмена</Button>
      </ModalFooter>
    </Modal>
  </>

Закрытие модального окна при нажатии на Escape

По умолчанию модальное окно закрывается при нажатии на Escape, если данное поведение нежелательно, то можно передать closeOnEsc=false


import { Modal, ModalHeader, ModalFooter, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
import { Fragment } from 'react';

const modal = useModal();

const items = [
  {
    name: 'Поведение по умолчанию'
  },
  {
    name: 'closeOnEsc=false',
    closeOnEsc: false,
  }
];

<div>
  {items.map(({name, ...props}, index) => (
    <Fragment key={name}>
      <Button 
        onClick={() => modal.open(name)}
        type={index === 1 ? 'secondary' : 'primary'}
        {...index === 1 && { styles: `margin-top: 20px`}}
      >
        {name}
      </Button>
      <Modal name={name} {...props}>
        <ModalHeader>{name}</ModalHeader>
      </Modal>
    </Fragment>
  ))}
</div>

Возможность закрытия модального окна

С помощью параметра isClosable можно управлять возможностью закрытия модального окна.

При передаче значения false модальное окно будет недоступно для закрытия.


import { useState } from 'react';
import { Modal, ModalHeader, ModalFooter, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';
import { Switch } from '@eisgs/switch';

const name = 'isClosable';

const [isClosable, setIsClosable] = useState(false);
const modal = useModal();

<>
  <Button onClick={() => modal.open(name)}>{`isClosable=${isClosable}`}</Button>
  <Modal name={name} isClosable={isClosable} onClose={() => setIsClosable(false)}>
    <ModalHeader>{name}</ModalHeader>
    <Switch isChecked={isClosable} onChange={setIsClosable}>
      {`isClosable: ${isClosable}`}
    </Switch>
  </Modal>
</>

Закрытие модального окна при клике на overlay

Параметр disableOverlayClick позволяет блокировать закрытие модального окна при клике на overlay.

import { Modal, ModalHeader, useModal } from '@eisgs/modal';
import { Button } from '@eisgs/button';

const name = 'disableOverlayClick';

const modal = useModal();

<>
  <Button onClick={() => modal.open(name)}>{name}</Button>
  <Modal name={name} disableOverlayClick>
    <ModalHeader>
      {name}
    </ModalHeader>
  </Modal>
</>