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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@studio-west/component-sw

v0.12.23

Published

Vue components of Component-SW collection.

Readme

Component SW - UI компоненты с поддержкой светлой и темной системной темы

Библиотека компонентов Component SW предоставляет набор готовых UI-компонентов на vue 3 для быстрой разработки интерфейсов. Каждый компонент имеет набор свойств, которые можно настраивать для достижения желаемого поведения и внешнего вида. Имеет поддержку светлой и темной системной темы. А также имеет поддержку мобильных систем разработки.


Component SW - UI Components with Light and Dark Theme Support

The Component SW library provides a set of ready-to-use UI components on Vue 3 for rapid interface development. Each component has a set of properties that can be customized to achieve the desired behavior and appearance. It supports both light and dark system themes. And also has support for mobile development systems.


Содержание / Table of Contents

Интерактивный плейграунд последней версии с живыми примерами, демонстрацией компонентов в браузере: studiowest.ru/component-sw.

Interactive playground of the latest version with live examples, demonstration of components in the browser: studiowest.ru/component-sw.


Установка / Install

npm install @studio-west/component-sw 

Глобальное подключение / global add to main.js

import { Library } from '@studio-west/component-sw';
import '@studio-west/component-sw/dist/component-sw.css';

app.use(Library)

Локальное подключение / Local add:

import { components } from '@studio-west/component-sw';
import '@studio-west/component-sw/dist/component-sw.css';
const { 
  SwSlider,
  SwInput
} = components;

Установка в ручную светлой и темной темы - добавление к тегу html классов dark или light / Installation in a manual light and dark theme - adding to the tag html classes dark or light

Пример использования / Example Usage

const mode = ref((getTheme() === 'dark' || getTheme() !== 'light' && window.matchMedia('(prefers-color-scheme: dark)').matches)? 'light-theme': 'dark-theme')
const darkMode = () => {
    if(mode.value === 'dark-theme') { // name icon
        document.querySelector('html').classList.remove('light')
        document.querySelector('html').classList.add('dark')
        setTheme('dark') // set cookies
    }
    else {
        document.querySelector('html').classList.remove('dark')
        document.querySelector('html').classList.add('light')
        setTheme('light') // set cookies
    }
    mode.value = (document.querySelector('html').classList.contains('dark')) ? 'light-theme' : 'dark-theme'
}

SSR / Server-Side Rendering

Начиная с версии 0.12.11 библиотеку можно безопасно импортировать на сервере: сборка dist/index.jsdist/index.cjs) больше не обращается к document/window/navigator на верхнем уровне. Инициализация Alert выполняется лениво и защищена проверкой окружения, поэтому импорт модуля в Node/SSR не падает.

Since version 0.12.11 the library is safe to import on the server: the dist/index.js (and dist/index.cjs) bundle no longer touches document/window/navigator at the top level. Alert initialization is lazy and environment-guarded, so importing the module in Node/SSR does not throw.

Исходники самодостаточны (используют относительные импорты вместо алиаса @/), поэтому при необходимости компоненты можно подключать напрямую из src без настройки алиасов в проекте-потребителе. / The source files are self-contained (relative imports instead of the @/ alias), so components can be registered directly from src without configuring aliases in the consumer project.

// SSR: безопасный импорт собранной библиотеки / SSR-safe import of the built library
import { Library } from '@studio-west/component-sw'
import '@studio-west/component-sw/dist/component-sw.css'

app.use(Library)

// $Alert использует DOM, поэтому вызывайте его только на клиенте /
// $Alert touches the DOM, so call it on the client only
if (typeof document !== 'undefined') {
  const Alert = inject('Alert')
  Alert({ message: 'Готово / Done', type: 'success' })
}

SwAlert

Функция / Компонент SwAlert система всплывающих сообщений. Сообщения могут быть с разным типом и временем показа. Могут иметь футер с кнопками.

Свойства / Properties

| Имя | Тип | по умолчанию | Значения/Описание | |------------|----------|-------------------|-----------------------------------------------------------------------------------| | class | String | sw-alert | Добавляет пользовательский CSS-класс к компоненту. | | size | String | | Размер сообщения: `'large'`, `'small'`. | | `type` | `String` | `info` | Тип сообщения: `'primary'`, `'success'`, `'info'`, `'warning'`, `'danger'`. | | `message` | `String` | `Default message` | Само сообщение. | | `duration` | `Number` | `6000` | Время отображения в миллисекундах. | | `before` | `String` | | Иконка в начале: имя из SVG-спрайта или URL (https://…). См. SwIcon. | | after | String | `` | Иконка в конце (кнопка закрыть): имя из спрайта или URL. См. SwIcon. |

Слоты / Slots

Default - текст описания или модуль / модули

#prefix - Вставка перед текстом (если не передан before)

#suffix - Вставка после текста (если не передан after)

#footer - Нижний блок

Пример использования / Example Usage

// .js addons
import { Alert, components } from "@studio-west/component-sw"
import { h } from 'vue'
Alert({message: 'Message', type: 'danger', duration:10000, before:'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/bell.svg', footer: h(components.SwButton, { onClick: () => console.log('Клик по кнопке в футере') }, () => 'OK')})

// Composition API else <script setup>:
import { inject, h } from "vue"
import { components } from "@studio-west/component-sw"
const Alert = inject('Alert')
Alert({message: 'Alarm!', type: 'warning', suffix: h(components.SwIcon, { iconClass: 'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/info-circle.svg' })})

//Options API:
this.$Alert({message: 'Welcome!', type: 'success', prefix: 'Дополнительная информация'});

SwButton

Компонент SwButton представляет собой кнопку с различными настраиваемыми параметрами.

Свойства / Properties

| Имя | Тип | по умолчанию | Значения/Описание | |------------|-----------|--------------|----------------------------------------------------------------------------------------| | class | String | sw-button | Добавляет пользовательский CSS-класс к компоненту. | | size | String | | Размер кнопки: `'large'`, `'small'`. | | `type` | `String` | `info` | Тип кнопки: `'primary'`, `'success'`, `'info'`, `'warning'`, `'danger'`. | | `round` | `Boolean` | `false` | Делает кнопку визуально закругленной. | | `text` | `Boolean` | `false` | Делает кнопку визуально похожей на текст (без фона только граница). | | `link` | `Boolean` | `false` | Преобразует кнопку в ссылку(без фона и границ). | | `href` | `String` | | URL, на который будет перенаправлен пользователь при клике (если link=true). | | disabled | Boolean | false | Блокирует кнопку, делая её неактивной. | | label | String | | Текст кнопки (альтернатива содержимому слота). | | `prefix` | `String` | | Иконка перед текстом: имя из SVG-спрайта или URL (https://…). См. SwIcon. | | postfix | String | `` | Иконка после текста: имя из спрайта или URL. См. SwIcon. |

Слоты / Slots

Default - содержимое кнопки (текст, иконки или другие элементы). Если не указано, используется label, prefix и postfix.

Пример использования / Example Usage

Базовый пример:

<sw-button
  class="custom-class"
  size="large"
  type="primary"
  round
  text
  link
  href="https://example.com"
>
  Нажми меня / Click Me
</sw-button>

С иконками и label:

<sw-button
  label="Сохранить"
  prefix="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/device-floppy.svg"
  postfix="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/arrow-right.svg"
  type="success"
/>

Отключенная кнопка:

<sw-button
  disabled="true"
  type="primary"
>
  Недоступно
</sw-button>

SwButtonGroup

Компонент SwButtonGroup представляет собой группу кнопок с возможностью включения режима "Radio".

Свойства / Properties

| Имя | Тип | по умолчанию | Значения/Описание | |------------|-----------|--------------|--------------------------------------------------------------| | class | String | sw-button | Добавляет пользовательский CSS-класс к компоненту. | | vertical | Boolean | false | Вертикальное расположение кнопок. | | radio | Boolean | false | Режим "Radio" неактивные кнопки будут иметь класс 'sw-text'. | | round | Boolean | false | Делает группу кнопок визуально закругленной. |

Модель / Model

model - индекс активной кнопки.

Особенности реализации

  • Автоматическое отслеживание изменений в слоте через MutationObserver
  • В режиме radio кнопки автоматически получают обработчики кликов
  • Динамическое обновление классов при изменении модели

Пример использования / Example Usage

<script>let active = 0 </script>
<sw-button-group
  class="custom-class"
  radio
  v-model="active"
  vertical
>
    <sw-button type="primary" size="small">Нажми меня 1 / Click Me 1</sw-button>
    <sw-button type="primary" >Нажми меня 2 / Click Me 2</sw-button>
    <sw-button type="danger">Нажми меня 3 / Click Me 3</sw-button>
</sw-button-group>

SwCollapse

Компонент SwCollapse представляет собой аналог тегов <details> + <summary> , но с анимацией.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |----------|-----------|--------------|-------------------| | visual | Boolean | true | Видимость |

Слоты / Slots

Default - Контент для скрытия

Особенности реализации

  • Плавная анимация открытия/закрытия с использованием CSS transitions
  • Автоматический расчет высоты контента через ResizeObserver
  • Адаптивное изменение размеров при динамическом контенте

Пример использования / Example Usage

<script setup>
import { ref } from 'vue'

const open = ref(true)
</script>

<sw-button label="Показать / скрыть" type="primary" @click="open = !open" />

<sw-collapse :visual="open">
  <p>Скрываемый контент / Collapsible content</p>
</sw-collapse>

SwDatePicker

Компонент SwDatePicker представляет собой панель с календарем.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |--------------|------------------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | data | Object | new Date() | Начальные данные - диапазон ( при 'solid' - используется только 'startDate') изначальных выбранных дат {firstDate: '01-04-2025', endDate: '14-04-2025', startDate:'30-03-2025', holiday: { preholidays: ["2020-03-30"], holidays: ["2020-03-30"], holiday: ["2020-03-30"], nowork: ["2020-03-30"] }}, ограничение не более 2х месяцев. firstDate - выбор месяца календаря при отсутствии startDate | | limitation | Boolean, Array | false | Массив ограничений дат: [{endDate: '14-04-2025', startDate:'30-03-2025'}]. | | range | String | solid | Тип календаря: 'decades','year','range', 'solid'. |

События / Events

input - событие выбора с данными {dateStart: "11.11.2011", dateEnd: "14-12-2011" ( при range), count: 1 }

Слоты / Slots

#double-arrow - для двойной стрелки по умолчанию «

#arrow - для одинарной стрелки по умолчанию

Особенности реализации

  • Поддержка множественных режимов отображения: дни, месяцы, годы, десятилетия
  • Автоматическая подсветка праздников и выходных дней
  • Интеллектуальная фильтрация недоступных дат
  • Проверка пересечения диапазонов ограничений
  • Поддержка инвертированных диапазонов (когда endDate < startDate)
  • Локализация названий месяцев и дней недели

Пример использования / Example Usage

<script>const addDateStart = (date) => {console.log(date)}</script>
<sw-date-picker
  :data="{startDate: '11.11.2011', endDate: '14-12-2011'}"
  :limitation="[{endDate: '14-04-2025', startDate:'30-03-2025'}]"
  range="range"
  @input="addDateStart"
>
  <template #double-arrow>«</template>
  <template #arrow>‹</template>
</sw-date-picker>

SwDropdown

Компонент SwDropdown это всплывающее меню с возможностью настройки места относительного всплытия и типа Триггера.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |-------------|-----------|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| | class | String | sw-dropdown | Добавляет пользовательский CSS-класс к компоненту. | | size | String | `` | Размер поля: 'large', 'small'. | | type | String | info | 'primary', 'success', 'info', 'warning', 'danger'. | | trigger | String | click | Способ открытия: 'click' — по клику, 'hover' — при наведении, 'context' — по правому клику, 'none' — только через model, без автотриггера. | | placement | String | bottom-left | Относительное место всплытия 'bottom-left', 'bottom', 'bottom-right', 'top-left', 'top', 'top-right', 'left', 'right'. | | maxWidth | Number | 0 | Максимальная ширина меню в пикселях. 0 - без ограничений. |

Слоты / Slots

Default - текст описания или модуль / модули

#dropdown - контент всплывающего окна

Модель / Model

model - состояние меню, булевое значение открыто - true

Пример использования / Example Usage

<sw-dropdown class="custom-class" :max-width="250">
  <sw-button label="Меню" type="primary" />
  <template #dropdown>
    <sw-dropdown-item>содержание / context</sw-dropdown-item>
  </template>
</sw-dropdown>

SwDropdownItem

Компонент SwDropdownItem это пункт во всплывающем меню с возможностью добавления в начало иконки.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |---------------|----------|--------------------|------------------------------------------------------------------| | class | String | sw-dropdown-item | Добавляет пользовательский CSS-класс к компоненту. | | size | String | | Размер поля: `'large'`, `'small'`. | | `type` | `String` | `info` | `'primary'`, `'success'`, `'info'`, `'warning'`, `'danger'`. | | `iconBefore` | `String` | | Иконка в начале: имя из спрайта или URL. См. SwIcon. |

Слоты / Slots

Default - текст названия или модуль

Пример использования / Example Usage

<sw-dropdown class="custom-class" :max-width="250">
  <sw-button label="Меню" type="primary" />
  <template #dropdown>
    <sw-dropdown-item icon-before="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/files.svg">содержание / context</sw-dropdown-item>
  </template>
</sw-dropdown>

SwIcon

Компонент SwIcon отображает SVG-иконку из встроенного спрайта или по внешнему URL.

Если iconClass начинается с http://, https://, иконка загружается как внешний SVG через CSS mask (класс sw-external-icon). Иначе используется символ из спрайта: #prefix-iconClass.

Компонент используется внутри SwButton (prefix, postfix), SwInput и SwAlert (before, after), SwDropdownItem (iconBefore), SwSection и SwMessage (iconAfter) — во всех этих props можно передавать как имя из спрайта, так и полный URL.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |-------------|----------|--------------|-------------------------------------------------| | iconClass | String | required | Имя иконки в спрайте или URL (https://…). | | prefix | String | icon | Префикс символа в спрайте: #prefix-iconClass. | | className | String | `` | Дополнительный CSS-класс для элемента <svg>. |

Пример использования / Example Usage

<!-- из спрайта -->
<sw-icon icon-class="star" />

<!-- внешний URL (Tabler Icons) -->
<sw-icon icon-class="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/star.svg" />

SwGide

Компонент SwGide Создает затенение вокруг блока по заданному тегу, и выводит SwDropdown с управляющими кнопками, переключающими по массиву из параметров steps

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |--------------|-----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------| | steps | Array | () => [] | Массив шагов обучения. [{header: 'заголовок',text: 'текст сообщения',tag: 'тег,якорь или класс', placement: 'место всплытия', img: 'src картинки' }], | | iconClose | String | `` | Иконка закрытия: имя из спрайта или URL. См. SwIcon. | | maxWidth | Number | 250 | Ширина всплывающего окна в px (без картинки). по умолчанию 250 |

Слоты / Slots

#header - заголовок окна

Default - текст сообщения с картинкой

#arrow - слот для стрелок

Модель / Model

model - массив обьектов шагов обучения

Пример использования / Example Usage

<script setup>
import { ref } from 'vue'

const settings = ref({ gide: true })
const step = ref(0)
const steps = ref([
    {header: 'заголовок',
     text: 'текст сообщения',
     tag: 'nav', 
     placement: 'bottom',
     img: 'assets/teme_sw/images/sw.png'
    }
])
</script>
<sw-gide v-if="settings.gide" :steps="steps" v-model="step" @close="settings.gide=false" icon-close="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/x.svg">
    <template #header>
        Блок {{ steps[step].header }} 
        <sw-button type="primary" link @click="settings.gide=false"><sw-icon icon-class="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/x.svg" /></sw-button>
    </template>
    <template #arrow><sw-icon icon-class="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/chevron-left.svg" /></template>
</sw-gide>

SwInput

Компонент SwInput представляет собой поле ввода с возможностью настройки внешнего вида и поведения.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |---------------|-----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------| | name | String | required | Обязателен! нужен для связывания через id input и label. | | class | String | sw-input | Добавляет пользовательский CSS-класс к компоненту. | | size | String | | Размер поля: `'large'`, `'small'`. | | `type` | `String` | `text` | Тип поля: `'text'`, `'phone'` (маска `+_ (___) ___-__-__` встроена в компонент), `'password'` | | `inputMode` | `String` | `text` | Мобильная клавиатура: `'text'`- стандартная, `'search'`- поиск, `'numeric'`- цифры, `'decimal'` - числа, `'tel'` - телефон, `'url'` - адреса, `'email'` - почта | | `before` | `String` | | Иконка в начале: имя из спрайта или URL. См. SwIcon. | | after | String | | Иконка в конце: имя из спрайта или URL. См. [SwIcon](#swicon). | | `placeholder` | `String` | | Текст Placeholder. | | required | Boolean | false | Признак обязательно ли для заполнения. | | label | String | `` | Текст в Label. | | maxlength | Number | 128 | Параметр атрибута max-length. Минимальное количество символов разрешённых в тексте. | | minlength | Number | 1 | Параметр атрибута min-length. Минимальное количество символов разрешённых в тексте. | | inputSize | Number | 60 | Параметр атрибута size - ширина текстового поля. |

Слоты / Slots

#prefix - вставка при отсутствии before не обязательно.

#suffix - вставка при отсутствии after не обязательно.

Модель / Model

model - значение поля ввода

События / Events

prefix - клик иконке before

suffix - клик иконке after

focusInput - focus на поле ввода

Пример использования / Example Usage

<script setup>
import { ref } from 'vue'

const model = ref('')
</script>

<sw-input 
  v-model="model"
  name="input"
  class="custom-class" 
  size="large" 
  type="phone"
  before="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/phone.svg"
  placeholder="+0 (___) ___-__-__"
  label="Телефон"
  @prefix="console.log('before')"
>
  <template #suffix>#</template>
</sw-input>

SwMenu

Компонент SwMenu представляет собой динамическое меню, которое генерируется на основе конфигурационного объекта или массива. Поддерживает рендеринг любых компонентов с возможностью настройки слотов и свойств.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |-------------|------------------------|--------------|--------------------------------------------------------------------------------| | menuItems | Object \| Array | required | Конфигурация меню. Объект или массив объектов с компонентами и их настройками. | | class | String | '' | Добавляет пользовательский CSS-класс к компоненту. |

Модель / Model

model - массив булевых значений для двусторонней привязки (v-model) с компонентами первого уровня.

События / Events

click - событие клика по компоненту. Параметры: { index, componentName, event, value }

change - событие изменения значения компонента. Параметры: { index, componentName, event?, value }

Формат конфигурации menuItems

Вариант 1: Объект

{
  'SwButton': {
    label: 'Кнопка',
    type: 'primary',
    slot: 'Текст кнопки'
  },
  'SwSwitch': [
    { 
      label: 'Переключатель 1',
      on: 'Вкл',
      off: 'Выкл'
    },
    { 
      label: 'Переключатель 2',
      checkbox: true
    }
  ]
}

Вариант 2: Массив

[
  { 
    'SwButton': { 
      label: 'Кнопка 1', 
      type: 'success' 
    } 
  },
  { 
    'SwInput': { 
      name: 'input1',
      placeholder: 'Введите текст',
      before: 'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/search.svg'
    } 
  }
]

Использование слотов

Для добавления контента в слоты компонентов используйте свойство slot:

{
  'SwDropdown': {
    trigger: 'click',
    'slot.dropdown': {
      'SwDropdownItem': {
        slot: 'Пункт меню'
      }
    }
  }
}

Или используйте префикс slot. для именованных слотов:

{
  'SwSection': {
    name: 'Секция',
    slot: 'Содержимое секции',
    'slot.footer': {
      'SwButton': {
        label: 'Сохранить',
        type: 'primary'
      }
    }
  }
}

Особенности реализации

  • Автоматический рендеринг компонентов на основе конфигурации
  • Поддержка вложенных компонентов через слоты
  • Двусторонняя привязка (v-model) для компонентов первого уровня
  • Эмит событий click и change для всех компонентов
  • Рекурсивная обработка конфигурации любой сложности
  • Поддержка как объектного, так и массивного формата menuItems

Пример использования / Example Usage

Базовый пример с объектом:

<script setup>
import { ref } from 'vue'

const menuState = ref([false, false])

const menuConfig = {
  'SwButton': {
    label: 'Нажми меня',
    type: 'primary',
    prefix: 'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/star.svg'
  },
  'SwSwitch': [
    { 
      label: 'Уведомления',
      on: 'Вкл',
      off: 'Выкл'
    },
    { 
      label: 'Звук',
      checkbox: true
    }
  ]
}

const handleClick = (data) => {
  console.log('Clicked:', data)
}

const handleChange = (data) => {
  console.log('Changed:', data)
}
</script>

<style>
.demo-menu {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  padding: 12px;
}
</style>

<sw-menu 
  class="demo-menu"
  :menu-items="menuConfig" 
  v-model="menuState"
  @click="handleClick"
  @change="handleChange"
/>

Пример с массивом:

<script setup>
import { ref } from 'vue'

const menuItems = [
  { 
    'SwButton': { 
      label: 'Главная', 
      type: 'info',
      link: true,
      href: '/'
    } 
  },
  { 
    'SwButton': { 
      label: 'О нас', 
      type: 'info',
      link: true,
      href: '/about'
    } 
  },
  { 
    'SwInput': { 
      name: 'search',
      placeholder: 'Поиск...',
      before: 'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/search.svg',
      size: 'small'
    } 
  }
]
</script>

<style>
.demo-menu {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  padding: 12px;
}
</style>

<sw-menu 
  class="demo-menu"
  :menu-items="menuItems"
/>

Пример с вложенными компонентами:

<script setup>
import { ref } from 'vue'

const dropdownMenu = {
  'SwDropdown': {
    trigger: 'hover',
    placement: 'bottom-left',
    slot: {
      'SwButton': {
        label: 'Меню',
        type: 'primary',
        postfix: 'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/chevron-down.svg'
      }
    },
    'slot.dropdown': [
      {
        'SwDropdownItem': {
          iconBefore: 'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/user.svg',
          slot: 'Профиль'
        }
      },
      {
        'SwDropdownItem': {
          iconBefore: 'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/settings.svg',
          slot: 'Настройки'
        }
      }
    ]
  }
}
</script>

<style>
.demo-menu {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  padding: 12px;
}
</style>

<sw-menu class="demo-menu" :menu-items="dropdownMenu" />

Пример с использованием слотов:

<script setup>
import { h } from 'vue'
import { components } from '@studio-west/component-sw'

const complexMenu = {
  'SwSection': {
    name: 'Панель управления',
    iconAfter: 'https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/chevron-down.svg',
    slot: 'Основное содержимое секции',
    'slot.footer': {
      'SwButtonGroup': {
        radio: true,
        slot: [
          {
            'SwButton': {
              label: 'Опция 1',
              type: 'primary'
            }
          },
          {
            'SwButton': {
              label: 'Опция 2'
            }
          }
        ]
      }
    }
  }
}
</script>

<style>
.demo-menu {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  padding: 12px;
}
</style>

<sw-menu class="demo-menu" :menu-items="complexMenu" />

SwMessage

Компонент SwMessage это выплывающее окно, центрируется по центру.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |-------------|-----------|--------------|-----------------------------------------------------------------------------------------| | name | String | | Добавляет текстовый заголовок, при отсутствии реализован слот `"header"`. | | `class` | `String` | `sw-section` | Добавляет пользовательский CSS-класс к компоненту. | | `iconAfter` | `String` | | Иконка кнопки закрытия (при заголовке): имя из спрайта или URL. См. SwIcon. |

Слоты / Slots

#header - слот для заголовка окна.

Default - текст описания или модуль / модулия

#footer - слот для подвала.

Модель / Model

model - состояние компонента булевое значение, при true - окно открыто, при false - закрыто.

Пример использования / Example Usage

<script>let model = false</script>

<sw-button label="Показать сообщение" type="primary" @click="model = true" />

<sw-message
  v-model="model"
  name="Message"
  class="custom-class"
  icon-after="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/x.svg"
>
  <p>Описание / Description</p>
</sw-message>

SwSection

Компонент SwSection это тег section с шаблоном из слотов, по умолчанию в слот #header добавлено заголовок и иконка.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |-------------|-----------|--------------|---------------------------------------------------------------------| | name | String | | Добавляет заголовок в секцию. | | `class` | `String` | `sw-section` | Добавляет пользовательский CSS-класс к компоненту. | | `iconAfter` | `String` | | Иконка в заголовке: имя из спрайта или URL. См. SwIcon. |

Слоты / Slots

#header - слот для заголовка секции.

Default - содержимое секции

#footer - слот для подвала секции.

События / Events

header - клик по всему Header

Пример использования / Example Usage

<sw-section
  name="section"
  class="custom-class"
  icon-after="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/x.svg"
>
  <p>Содержимое / Content</p>
  <template #footer>
    <p>Footer!</p> 
  </template>
</sw-section>

SwSelect

Компонент SwSelect - реализация подсказок для https://dadata.ru/api/suggest/address/.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |----------------|-----------|--------------|-----------------------------------------------| | class | String | | Добавляет пользовательский CSS-класс к popup. | | `size` | `String` | `large` | Размер поля: `'large'`, `'small'`. | | `placeholder` | `String` | | Добавляет в placeholder описание. | | token | String | `` | API-ключ для DADATA. |

Модель / Model

model - текст ввода или выбора из списка

Пример использования / Example Usage

<script setup>
import { ref } from 'vue'

const model = ref({ text: '', coords: [0, 0] })
const token = ref('') // API-ключ DADATA
</script>

<sw-select
  v-model="model"
  class="custom-class"
  placeholder="Введите адрес"
  :token="token"
/>

SwSkeleton

Компонент SwSkeleton используется для анимации загрузки данных, выступая оболочкой компонента SwSkeletonItem или пользовательского компонента при использовании слота #skeleton, по умолчанию в слот #skeleton добавлен 1 SwSkeletonItem с базовыми настройками

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |----------|-----------|----------------|----------------------------------------------------| | class | String | sw-skeleton | Добавляет пользовательский CSS-класс к компоненту. | | visual | Boolean | false | Тригер на переключение. |

Слоты / Slots

Default - Содержимое

#skeleton - слот для skeleton

Пример использования / Example Usage

<sw-skeleton
  :visual="visual"
>
  <p>Содержимое / Content</p>
</sw-skeleton>

SwSkeletonItem

Компонент SwSkeletonItem представляет собой полоску псевдо данных с возможностью анимирования.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |------------|-----------|--------------------|----------------------------------------------------| | width | String | 100 | Ширина элемента в процентах. | | class | String | sw-skeleton-item | Добавляет пользовательский CSS-класс к компоненту. | | animate | String | false | Добавляет анимацию в элемент. | | size | String | `` | Размер поля: 'large', 'small'. |

Пример использования / Example Usage

<sw-skeleton-item
  animate
  class="custom-class"
  size="small"
  width="60"
 />

SwSlider

Компонент SwSlider представляет собой Мультислайдер с возможностью настройки внешнего вида ползунка. Количество ползунков зависит от входных данных 1 - число. n - массив из n чисел.

  • отображения значений в виде всплывающих подсказок при наведении на бегунки:
  • Поддержка как горизонтальной, так и вертикальной ориентации
  • Адаптивное позиционирование подсказок в зависимости от доступного пространства
  • Поддержка сенсорных устройств (touch events)

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |--------------|-----------|--------------|----------------------------------------------------| | vertical | Boolean | false | Вертикальная ориентация слайдера. | | class | String | sw-switch | Добавляет пользовательский CSS-класс к компоненту. | | size | String | small | Размер бегунка: 'large', 'small'. | | min | Number | 0 | Минимальное значение переменной. | | max | Number | 100 | Максимальное значение переменной. | | step | Number | 1 | Шаг в приросте переменной. | | show-value | Boolean | false | Добавляет всплывающее окно с текущим значением. |

Слоты / Slots

Default - текст, картинка, svg - содержимое бегунка.

Модель / Model

model - значение слайдера (число, массив чисел)

Пример использования / Example Usage


<script>let model = [5, 50]</script>
<sw-slider 
  v-model="model"
  :min="0" 
  :max="100" 
  :step="5"
  show-value
  class="custom-class"
  vertical
>
    <sw-icon icon-class="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/icons/outline/components.svg" />
</sw-slider>

SwSwitch

Компонент SwSwitch представляет собой чекбокс с возможностью настройки внешнего вида галочка | переключатель | переключатель с подписью и поведения.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |------------|-----------|--------------|----------------------------------------------------| | name | String | | Добавляет в атрибут `'name'`. | | `class` | `String` | `sw-switch` | Добавляет пользовательский CSS-класс к компоненту. | | `size` | `String` | | Размер поля: 'large', 'small'. | | id | String | checkbox | Добавляет в атрибут 'id'. | | on | String | | Текст при true. | | `off` | `String` | | Текст при false. | | checkbox | Boolean | false | Визуализирует как обычный чекбокс. |

Слоты / Slots

Default - текст описания

Модель / Model

model - состояние чекбокса (checked ) булевое значение

Пример использования / Example Usage

<sw-switch 
  v-model="model"
  name="switch"
  class="custom-class"
  id="switch"
  on="on"
  off="off"
>
  <p>Описание / Description</p>
</sw-switch>

SwTable

Компонент SwTable — динамическая таблица с вложенными заголовками, объединением ячеек (rowspan / colspan), кастомизацией через слоты, подсветкой строк и столбцов при наведении, изменением ширины колонок и фиксацией крайних колонок при горизонтальном скролле.

The SwTable component is a dynamic table with nested headers, cell merging (rowspan / colspan), slot-based customization, row and column hover highlighting, column resizing, and sticky edge columns during horizontal scroll.

Колонки описываются дочерним компонентом SwTableColumn.

Columns are defined with the child SwTableColumn component.

Свойства SwTable / SwTable Properties

| Имя | Тип | По умолчанию | Значения/Описание | |-------------|----------------------|--------------|---------------------------------------------------------------------------------------------------------------| | data | Array | required | Данные таблицы — массив объектов. | | resizable | Boolean | true | Разрешить изменение ширины колонок перетаскиванием края заголовка. | | maxWidth | String | Number | — | Максимальная ширина контейнера таблицы. При переполнении — горизонтальный скролл и активация fixed-колонок. |

События SwTable / SwTable Events

| Имя | Параметрыd | Описание | |-----------------|-------------------|----------------------------------------------------| | column-resize | { prop, width } | Срабатывает после изменения ширины колонки (в px). |

Свойства SwTableColumn / SwTableColumn Properties

| Имя | Тип | По умолчанию | Значения / Описание | |-------------|----------------------|--------------|----------------------------------------------------------------------------------| | prop | String | — | Ключ поля в объекте строки. Поддерживает вложенные пути: speed.midl. | | label | String | '' | Заголовок колонки. | | width | String | Number | 'auto' | Ширина колонки, например 180 или '180px'. | | height | String | Number | 'auto' | Минимальная высота ячейки заголовка. | | resizable | Boolean | — | Разрешить ресайз конкретной колонки. По умолчанию наследует resizable таблицы. | | minWidth | String | Number | 48 | Минимальная ширина при ресайзе (px). | | fixed | String | — | 'left' | 'right' — фиксация колонки при горизонтальном скролле. |

SwTableColumn без prop используется как групповой заголовок; внутри него задаются дочерние SwTableColumn.

A SwTableColumn without prop is a group header; place child SwTableColumn components inside it.

Подсветка при наведении / Hover highlight

  • Row — при наведении на строку в tbody подсвечиваются все её ячейки (учитывается rowspan).
  • Column — при наведении на ячейку заголовка подсвечивается весь столбец; для группового заголовка с colspan — все вложенные колонки.

Стили подсветки заданы в component-sw.css (классы row-hover, col-hover).

Фиксированные колонки / Fixed columns

Фиксация включается, когда одновременно:

  1. задан max-width у SwTable;
  2. у колонок указан fixed="left" или fixed="right";
  3. суммарная ширина таблицы превышает контейнер.

Групповой заголовок фиксируется, если все его дочерние колонки имеют одинаковое значение fixed.

Слоты / Slots

#<prop> — именованный слот для конкретной колонки (приоритет выше cell). Параметры: { row, $index, value }

#cell — универсальный слот для всех колонок (default-слот занят SwTableColumn). Параметры: { row, $index, column, value }

  • row — весь объект строки данных
  • $index — индекс строки (начиная с 0)
  • column — имя колонки (prop)
  • value — значение ячейки

Пример использования / Example Usage

Базовый пример с вложенными колонками:

<script>
    let table = [
        {city:{label:'Moscow', rowspan:2},district:'Center',speed:{max:80,min:50,midl:70}},
        {city:'Moscow',district:'MRCR',speed:{max:130,min:90,midl:120}},
    ]
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="table">
  <sw-table-column label="Label">
      <sw-table-column label="City" prop="city"/>
      <sw-table-column label="District" prop="district"/>
  </sw-table-column>
  <sw-table-column label="Speed" prop="speed.midl"/>
</sw-table>

Ресайз колонок:

<script setup>
const users = [
  { name: 'Иван', age: 25 },
  { name: 'Мария', age: 30 },
  { name: 'Петр', age: 35 }
]

function onColumnResize({ prop, width }) {
  console.log(prop, width)
}
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="users" @column-resize="onColumnResize">
  <sw-table-column prop="name" label="Имя" width="180px" />
  <sw-table-column prop="age" label="Возраст" width="100px" />
  <sw-table-column
    prop="actions"
    label="Действия"
    width="150px"
    :resizable="false"
  />
</sw-table>

Фиксированные крайние колонки:

<script setup>
const rows = [
  { id: 1, name: 'Иван', email: '[email protected]', note: 'Примечание 1' },
  { id: 2, name: 'Мария', email: '[email protected]', note: 'Примечание 2' },
  { id: 3, name: 'Петр', email: '[email protected]', note: 'Примечание 3' }
]
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="rows" max-width="520px">
  <sw-table-column prop="id" label="ID" width="70px" fixed="left" />
  <sw-table-column prop="name" label="Имя" width="160px" fixed="left" />
  <sw-table-column prop="email" label="Email" width="200px" />
  <sw-table-column prop="note" label="Примечание" width="180px" fixed="right" />
</sw-table>

Пример с v-for для динамических колонок:

<script setup>
import { ref } from 'vue'

const columns = ref([
  { prop: 'name', label: 'Имя', width: '150px' },
  { prop: 'age', label: 'Возраст', width: '100px' },
  { prop: 'email', label: 'Email', width: '200px' }
])

const tableData = ref([
  { name: 'Иван', age: 25, email: '[email protected]' },
  { name: 'Мария', age: 30, email: '[email protected]' },
  { name: 'Петр', age: 35, email: '[email protected]' }
])
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="tableData">
  <sw-table-column 
    v-for="column in columns" 
    :key="column.prop"
    :prop="column.prop"
    :label="column.label"
    :width="column.width"
  />
</sw-table>

Пример с кастомизацией через слоты:

<script setup>
import { ref } from 'vue'

const users = ref([
  { id: 1, name: 'Иван Петров', age: 25, status: 'active', email: '[email protected]' },
  { id: 2, name: 'Мария Сидорова', age: 30, status: 'inactive', email: '[email protected]' },
  { id: 3, name: 'Петр Иванов', age: 35, status: 'active', email: '[email protected]' }
])

const deleteUser = (id) => {
  console.log('Delete user:', id)
}
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="users">
  <sw-table-column prop="name" label="Имя" />
  <sw-table-column prop="age" label="Возраст" />
  <sw-table-column prop="status" label="Статус" />
  <sw-table-column prop="actions" label="Действия" width="150px" />
  
  <!-- Именованный слот для конкретной колонки -->
  <template #name="{ row, value }">
    <strong>{{ value }}</strong>
  </template>
  
  <template #age="{ value }">
    <span style="color: blue">{{ value }} лет</span>
  </template>
  
  <template #status="{ value }">
    <span :style="{ color: value === 'active' ? 'green' : 'red' }">
      {{ value === 'active' ? '✓ Активен' : '✗ Неактивен' }}
    </span>
  </template>
  
  <!-- Default слот для колонки actions -->
  <template #actions="{ row }">
    <button @click="deleteUser(row.id)">Удалить</button>
    <a :href="`mailto:${row.email}`">Написать</a>
  </template>
</sw-table>

Пример с универсальным слотом cell:

<script setup>
import { ref } from 'vue'

const products = ref([
  { name: 'Товар 1', price: 1000, quantity: 5 },
  { name: 'Товар 2', price: 2500, quantity: 3 },
  { name: 'Товар 3', price: 750, quantity: 10 }
])
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="products">
  <sw-table-column prop="name" label="Название" />
  <sw-table-column prop="price" label="Цена" />
  <sw-table-column prop="quantity" label="Количество" />

  <template #cell="{ column, value }">
    <span v-if="column === 'price'" style="font-weight: bold">
      {{ value }} ₽
    </span>
    <span v-else-if="column === 'quantity' && value < 5" style="color: red">
      {{ value }} ⚠️ Мало
    </span>
    <span v-else>{{ value }}</span>
  </template>
</sw-table>

Пример с объединением ячеек (rowspan/colspan):

<script setup>
import { ref } from 'vue'

const complexData = ref([
  {
    city: { label: 'Москва', rowspan: 2 },
    district: 'Центр',
    population: 500000
  },
  {
    city: 'Москва', // будет скрыта из-за rowspan
    district: 'Север',
    population: 300000
  },
  {
    city: { label: 'Общая статистика', colspan: 2 },
    population: 800000
  }
])
</script>

<style>
.sw-table th, .sw-table td { border: 1px solid #d6d6d6; padding: 6px 10px; }
</style>

<sw-table :data="complexData">
  <sw-table-column label="Город" prop="city" />
  <sw-table-column label="Район" prop="district" />
  <sw-table-column label="Население" prop="population" />
</sw-table>

SwTabs

Компонент SwTabs представляет собой панель вкладок SwTabsPane.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |---------|-----------|--------------|----------------------------------------------------| | class | String | sw-tabs | Добавляет пользовательский CSS-класс к компоненту. |

Слоты / Slots

Default - для компонентов SwTabsPane

header - Дополнительное место во вкладках

Модель / Model

model - индекс активной вкладки (по порядку в коде с 0)

Пример использования / Example Usage

<script>let activeTabId = 0</script>

<sw-tabs v-model="activeTabId" class="custom-class">
  <sw-tabs-pane label="Профиль" title="profile">
    <p>Содержимое вкладки профиля / Profile tab</p>
  </sw-tabs-pane>
  <sw-tabs-pane label="Настройки" title="settings">
    <p>Содержимое вкладки настроек / Settings tab</p>
  </sw-tabs-pane>
</sw-tabs>

SwTabsPane

Компонент SwTabsPane представляет собой оболочку для вкладок.

Свойства / Properties

| Имя | Тип | По умолчанию | Значения/Описание | |---------|----------|--------------|-----------------------------------------------------------------------------------------| | title | String | | Название унификатор - обязателен при отсутствии `label` будет взят за название вкладки. | | `label` | `String` | | Название вкладки при отсутствии возьмется из title. |

Слоты / Slots

Default - для вкладок

Пример использования / Example Usage

<script>let activeTabId = 0</script>

<sw-tabs v-model="activeTabId" class="custom-class">
  <sw-tabs-pane label="Профиль" title="profile">
    <p>Содержимое вкладки профиля / Profile tab</p>
  </sw-tabs-pane>
  <sw-tabs-pane label="Настройки" title="settings">
    <p>Содержимое вкладки настроек / Settings tab</p>
  </sw-tabs-pane>
</sw-tabs>

Изменения / Changelog

0.12.13

SwTable

  • Подсветка строки при наведении на строку в tbody (с учётом rowspan).
  • Подсветка столбца при наведении на ячейку заголовка; для группового заголовка с colspan — все вложенные колонки.
  • Изменение ширины колонок перетаскиванием края заголовка; проп resizable у таблицы и колонки, событие column-resize.
  • Фиксация крайних колонок (fixed="left" | fixed="right" на SwTableColumn) при горизонтальном скролле; prop maxWidth у SwTable.
  • Колонки снова регистрируются корректно: SwTable и SwTableColumn монтируют слот через скрытый контейнер (provide / inject).

  • Row highlight on tbody row hover (rowspan supported).
  • Column highlight on header cell hover; grouped headers with colspan highlight all nested columns.
  • Resize leaf columns by dragging the header edge; table/column resizable prop and column-resize event.
  • Sticky edge columns (fixed="left" | fixed="right" on SwTableColumn) during horizontal scroll; maxWidth prop on SwTable.
  • Columns register correctly again: SwTable and SwTableColumn mount the slot via a hidden container (provide / inject).

Лицензия / License

Этот проект распространяется под лицензией MIT. Подробности см. в файле LICENSE . / This project is distributed under the MIT License. For details, see the LICENSE file.


Если у вас есть вопросы или предложения, пожалуйста, создайте issue на почту [email protected]. / If you have any questions or suggestions, please create an issue to E-mail [email protected].