@brandup/ui-textbox
v1.0.58
Published
Textbox control type and styles.
Maintainers
Readme
@brandup/ui-textbox
Компонент текстового поля. Заменяет стандартные <input> и <textarea>, добавляя расширенное поведение: счётчик символов, кнопку копирования, фильтрацию ввода по типу, валидацию и опциональное форматирование текста (жирный, курсив, зачёркивание, подчёркивание).
Вся работа с редактируемой областью вынесена в @brandup/ui-richeditor: TextBox создаёт скрытое поле формы и компонует над ним RichEditor. Экземпляр редактора доступен через свойство editor.
Установка
npm i @brandup/ui-textboxИспользование
<input id="name" type="text" placeholder="Введите имя" />import TextBox from "@brandup/ui-textbox";
import { TEXTBOX, ChangeEventData } from "@brandup/ui-textbox";
const inputElem = document.getElementById("name") as HTMLInputElement;
const textbox = new TextBox(inputElem);
textbox.on(TEXTBOX.EVENT.CHANGE, (data: ChangeEventData) => {
console.log(data.value);
});Поддерживаемые типы
TextBox принимает <input> со следующими значениями атрибута type:
| Тип | Поведение |
| --- | --- |
| text | Обычный текст |
| email | Оставляет буквы, цифры и . - _ + @; ограничивает длину до 256 символов (RFC 5321) — свой maxlength применяется, если он строже |
| url | URL-адрес |
| tel | Телефон |
| number | Только цифры (целые неотрицательные), вставка фильтруется |
Для многострочного ввода передайте <textarea>.
Data-атрибуты
| Атрибут | Описание |
| --- | --- |
| data-symbolcounter | Показывает счётчик введённых символов (и максимума, если задан maxlength) |
| data-autofocus | Автофокус при инициализации; то же делает нативный autofocus. Отменяется, если поле выключено или только для чтения, вводят пальцем, пользователь уже прокрутил страницу либо фокус занят другим полем ввода |
| data-caret | Куда встаёт каретка при фокусе из кода — автофокусом или вызовом focus(): end (по умолчанию), start, all (выделить весь текст) |
| data-copy-button | Добавляет кнопку копирования значения в буфер обмена |
| data-allow-empty-strings | Разрешает значение из одних пробелов |
| data-readonly | Альтернативный способ задать режим только для чтения |
| data-format | Включает форматирование текста (только для type="text") |
| data-format-tools | Состав инструментов форматирования через пробел (по умолчанию все): bold italic strike underline spoiler code |
| data-editor-actions | Кнопки действий в панели через пробел (по умолчанию нет): erase undo redo |
| data-blocks | Типы блоков многострочного поля через пробел: quote code. Подключаются только объявлением — без атрибута поле остаётся обычным текстом, и панель не показывается |
| data-format-storage | Формат хранения значения: html (по умолчанию) или markdown |
| data-format-md-<tool> | Markdown-маркер инструмента: bold — **, italic — _, strike — ~, underline — __, spoiler — \|\|, code — ` |
Форматирование текста
Атрибут data-format включает панель форматирования с инструментами: жирный, курсив, зачёркивание, подчёркивание, спойлер, моноширинный. Панель всплывает над контролом, пока он в фокусе (класс состояния focused). Работает поверх существующего contenteditable-редактора, поэтому доступно только для текстового ввода (type="text" и <textarea>).
<!-- все инструменты, хранение в HTML -->
<textarea data-content-script="textbox" data-format></textarea>
<!-- только жирный и курсив, хранение в Markdown -->
<input
type="text"
data-content-script="textbox"
data-format
data-format-tools="bold italic"
data-format-storage="markdown"
/>Состав инструментов — data-format-tools
Список через пробел из значений bold, italic, strike, underline, spoiler, code. Неизвестные значения игнорируются. Если атрибут не задан — включаются все инструменты.
Кнопки действий — data-editor-actions
Список через пробел из значений erase (очистить форматирование), undo (отменить), redo (повторить). В отличие от инструментов, действия подключаются явно: без атрибута кнопок действий нет. Они добавляются в панель после инструментов форматирования, в один ряд с ними — всё это правка оформления, — и блокируются, когда действие недоступно (нечего отменять или очищать).
erase снимает все форматы с выделения, а без выделения — со слова под кареткой. Чтобы очистить всё поле, выделите текст целиком (Ctrl+A) и нажмите кнопку.
Блоки — data-blocks
В многострочном поле (<textarea>) верхний уровень состоит из блоков. Обычный текст доступен всегда, а цитата (quote) и блок кода (code) подключаются явно — списком через пробел:
<textarea data-content-script="textbox" data-format data-blocks="quote"></textarea>Без атрибута поле остаётся обычным текстом, и панель форматирования сама по себе не появляется — как и действия, блоки включают объявлением. Пустое значение атрибута равносильно его отсутствию.
Enter внутри блока заканчивает его, Shift+Enter переносит строку внутри, Backspace в начале блока возвращает обычный текст. Разбор, хранение и правку блоков описывает @brandup/ui-richeditor.
Применение формата
- Формат — переключатель (toggle): повторное применение к уже отформатированному тексту снимает его.
- Форматирование применяется к слову целиком: если курсор стоит внутри слова без выделения или выделена лишь его часть — формат охватывает всё слово. При выделении части нескольких слов каждая граница доводится до целого слова. Исходное выделение/каретка после применения сохраняются (слово не выделяется автоматически).
- Режим набора: если под кареткой нет слова (курсор между пробелами или поле пустое), кнопка/хоткей не форматируют текст, а включают «ожидающий» формат — он подсветится активным и применится к следующему введённому тексту. Режим сбрасывается при перемещении каретки, клике или потере фокуса.
- Кнопка инструмента подсвечивается (
active), когда выделение целиком отформатировано этим инструментом или активен режим набора. - Внутри моноширинного разметки нет: значение берёт оттуда голый текст, поэтому остальные инструменты там недоступны, а попавшее внутрь форматирование снимается.
- Реализация работает на стандартном Selection/Range API — без устаревшего
document.execCommand, поэтому разметка всегда семантическая (<b>,<i>,<s>,<u>,<spoiler>,<code>) и предсказуема между браузерами.
Хоткеи
Ctrl/Cmd+B — жирный, Ctrl/Cmd+I — курсив, Ctrl/Cmd+U — подчёркивание. Зачёркивание включается только кнопкой. Хоткеи отключённых инструментов перехватываются, чтобы не срабатывало форматирование браузера.
Формат хранения — data-format-storage
Значение синхронизируется в скрытое поле в выбранном формате:
| Значение | Хранение | Поддерживаемые теги/маркеры |
| --- | --- | --- |
| html (по умолчанию) | Санитизированный HTML | <b>, <i>, <s>, <u>, <spoiler>, <code>, переводы строк через <br> |
| markdown | Лёгкая разметка | **жирный**, _курсив_, ~зачёркнутый~, __подчёркнутый__, \|\|спойлер\|\|, `моноширинный` |
Маркеры для каждого инструмента настраиваются атрибутами data-format-md-<tool> (актуально только при data-format-storage="markdown"):
<textarea
data-content-script="textbox"
data-format
data-format-storage="markdown"
data-format-md-italic="_"
data-format-md-bold="__"
></textarea>При разборе маркеры применяются по убыванию длины, поэтому более длинный маркер (__) срабатывает раньше короткого-префикса (_). Маркеры разных инструментов должны различаться.
Разметку чужих диалектов редактор понимает наравне со своей и возвращает в значение такой же, какой она пришла: *жирный* из WhatsApp остаётся *жирный*, а настроенный маркер ставится только на то, что отформатировали в поле.
Глубоко вложенные комбинации форматов (например, жирный внутри курсива) гарантированно сохраняются только в режиме
html.
API
Методы
| Метод | Описание |
| --- | --- |
| getValue(): string | Возвращает текущее значение (обрезает пробелы по краям) |
| setValue(value: string): void | Устанавливает значение программно |
| hasValue(): boolean | true, если значение не пустое |
| validate(): boolean | Валидирует значение, добавляет/снимает класс invalid |
| focus(): void | Ведёт фокус в редактор и прокручивает контрол в видимую область. В выключенном поле ничего не делает — как нативный disabled input; поле только для чтения фокусируется |
| destroy(): void | Восстанавливает исходный DOM-элемент и освобождает ресурсы |
Свойства
| Свойство | Тип | Описание |
| --- | --- | --- |
| type | TextBoxType | Тип ввода: "text" | "email" | "url" | "tel" | "number" |
| multyline | boolean | true для <textarea> |
| maxlength | number | Максимальная длина (из атрибута maxlength) |
| copyButton | boolean | Наличие кнопки копирования |
| symbolCounter | boolean | Наличие счётчика символов |
| placeholder | string \| null | Текст-заглушка |
| format | boolean | Включено ли форматирование |
| formatStorage | FormatStorage | Формат хранения: "html" | "markdown" |
| formatTools | FormatTool[] | Включённые инструменты форматирования |
| formatMarkers | FormatMarkers | Markdown-маркеры по инструментам (с учётом переопределений) |
| editor | RichEditor | Встроенный редактор: выделение, вставка текста, блоки |
Событие ui:textbox:change
Генерируется при каждом изменении значения.
import { TEXTBOX, ChangeEventData } from "@brandup/ui-textbox";
textbox.on(TEXTBOX.EVENT.CHANGE, (data: ChangeEventData) => {
console.log(data.value); // текущее значение
console.log(data.textbox); // ссылка на экземпляр TextBox
});
// Или через helper-метод
textbox.onChange((data) => { ... });Нормализация пробелов
Когда редактирование логически завершено (поле теряет фокус), а также после инициализации и setValue, текст нормализуется:
- повторяющиеся пробелы/табы схлопываются в один;
- пробелы по краям каждой строки обрезаются.
Форматирование и переносы строк (<br>/блоки) при этом сохраняются. Во время набора текста пробелы не трогаются — нормализация выполняется только по завершении. Если нормализация изменила значение, при потере фокуса генерируется событие ui:textbox:change.
CSS-классы состояний
| Класс | Условие |
| --- | --- |
| focused | Поле в фокусе |
| invalid | Значение не прошло валидацию |
| incorrect | Введён недопустимый символ (мигает, затем снимается) |
| required | Атрибут required задан |
| readonly | Режим только для чтения |
| disabled | Элемент отключён |
| active | На кнопке панели форматирования — формат активен для текущего выделения |
