Создание и поддержка высококачественных веб-компонентов - тяжелая работа. Вы не только реализуете важные функции, но - для компонентов пользовательского интерфейса - вы также должны сделать так, чтобы они выглядели красиво.
И хотя возможность повторного использования является одним из основных аспектов веб-компонентов, чаще всего она связана с используемым языком дизайна: простые поля ввода, основанные на Material Design или Fluent UI, работают так же, как и другие, но выглядят иначе. Вы же не хотите реализовывать компонент дважды, так что было бы неплохо разделить функциональность и дизайн?

Введите Lion, набор веб-компонентов white label, созданный ING (также известный как ING Diba). Компоненты имеют открытый исходный код и доступны на GitHub. На данный момент Lion концентрируется на элементах управления формой и навигацией, а также на наложениях и локализации. Но помимо кнопок и входов вы также можете найти диалоги и даже календарь. Очевидно, что коллекция веб-компонентов - это побочный продукт команды разработчиков ING.

| Мы рекомендуем вам прочитать сообщение в блоге с объявлением и просмотреть живую книгу рассказов

При просмотре живого сборника рассказов первое, что бросается в глаза: компоненты не имеют стилей по умолчанию; или лучше: они используют стили браузеров по умолчанию. Это похоже на то, как если бы вы забыли включить свой CSS в веб-сайт. Но в том-то и дело! Веб-компоненты полностью функциональны, например, элементы управления формы могут быть помечены, предварительно заполнены, отключены и проверены. Но они не относятся к дизайну самоуверенно. Используйте их, и ваша единственная задача - заставить их гармонировать.

Веб-компоненты Lion основаны на lit-html / lit-element. Каждый компонент находится в отдельном репозитории npm и может быть импортирован как модуль ES. Чтобы применить директивы CSS к компоненту - или добавить функциональность - вы должны создать его подкласс. Поскольку компоненты используют Shadow DOM, глобальные стили не применяются автоматически.

Примеры в документации по Lion являются минимальным - основаны на предположении, что у вас есть готовая подходящая среда разработки. Здесь мы рассмотрим подробнее.

Мы сделаем следующее:
1. Настройте среду разработки и установите наши зависимости.
2. Расширьте компонент Lion, чтобы применить некоторые стили.
3. Создайте пакет для использования стилизованного компонента в другом месте.

Настройте среду разработки и установите наши зависимости

Наш базовый компонент будет основным входом. Создайте новую папку с именем white-label-web-components для наших проектов, запустите

npm init

и установите компонент с помощью

npm i --save @lion/input

В результате node_modules содержат довольно много пакетов, некоторые из которых находятся в подпапке @lion (наиболее важно подпапка input), а также lit-html и lit-element в качестве базовых классов. компонентов Lion.

Кроме того, загрузите index.html.

<!DOCTYPE html>
<html lang=”en”>
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>White-Label Web Components</title>
</head>
<body>
<form>
 <lion-input name="firstName" label="Input label"></lion-input>
 </form>
<script type="module" src="main.js"></script>
</body>
</html>

Дополнительно настройте однострочный main.js, который выглядит следующим образом:

import '@lion/input/lion-input.js';

Когда вы открываете индексный файл с помощью простого веб-сервера, такого как Pythons SimpleHTTPServer, встроенный сервер PHP или сервер NodeJS lite, вы не увидите * ничего *. Пути, используемые для загрузки модуля ES, и его рекурсивные зависимости не могут быть разрешены. Нам нужно будет настроить специальный сервер разработки. Возможно, вы знакомы с средой разработки LitElement, которая отлично подойдет. В качестве альтернативы вы можете использовать es-dev-server от open-wc. Вы могли заметить @open -wc как зависимость компонентов Lion в модулях node_modules. Это не совпадение, поскольку Lion и open-wc (по крайней мере частично) поддерживаются одними и теми же людьми. На данный момент мы выберем облегченный вариант и воспользуемся es-dev-server:

npm i —-save-dev es-dev-server

Это немного расширит вашу папку node_modules, но это нормально. Все дополнения не имеют ничего общего с компонентами Lion. Добавьте сценарий в package.json, чтобы запустить сервер в режиме наблюдения. Каждое изменение в исходных файлах (на которые прямо или косвенно ссылается index.html) вызовет перезагрузку окна браузера. Обратите внимание на параметр node-resolve, который исправляет пути к файлам, на которые есть ссылки, на лету:

{
 "scripts": {
 ...
   "serve": "es-dev-server --app-index index.html --node-resolve --watch --open" }
  }
}

Запуск npm run serve откроет новое окно браузера, показывающее http: // localhost: 8000 с желаемым нестилизованным вводом. Если вам интересно, откройте вкладку Сеть в инструментах разработчика и просмотрите файл с именем LionInput.js. Обратите внимание, что путь

import { LionField } from '../../form-core/index.js'; 

отличается от того, что вы видите в исходном файле в среде IDE:

import { LionField } from '@lion/form-core';

Для этого нужен es-dev-server.

Расширьте компонент Lion, чтобы применить стиль

Теперь, когда мы видим левый ввод в браузере, давайте создадим обновленную версию. Первый подкласс LionInput, базовый класс веб-компонентов lion-input: создайте файл pretty-input.js на верхнем уровне вашего проекта. , рядом с index.html и main.js.

import { css } from 'lit-element';
import { LionInput } from '@lion/input';
export class PrettyInput extends LionInput {
static get styles() {
  return [
    super.styles,
    css`:host{
      font-family:Segoe UI WestEuropean,Segoe UI,
      -apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,
      sans-serif;
    -webkit-font-smoothing:antialiased;
    display: inline-block;
    min-width:300px
    }
    ::slotted(input:focus) {
      border: 1px solid #33C3F0;
      outline: 0; 
    }
    ::slotted(label) {
      display: block;
      margin-bottom: .5rem; 
    }
    ::slotted([slot=help-text]){
      font-style: italic
    }
    ::slotted(input) {
      height: 38px;
      padding: 6px 10px;
      background-color: #fff;
      border: 1px solid #D1D1D1;
      border-radius: 4px;
      box-shadow: none;
      box-sizing: border-box;
      -webkit-appearance: none;
      -moz-appearance: none;
      appearance: none; 
    }`
   ];
 }
}
customElements.define('pretty-input', PrettyInput);

В pretty-input.js мы создаем класс PrettyInput как подкласс LionInput. Поэтому необходимо импортировать LionInput. Класс PrettyInput также экспортируется, поскольку мы создаем здесь новый модуль ES и, возможно, кому-то понадобится сам подкласс PrettyInput. Большая часть нашего класса - это средство получения стилей, преимущество, которое LionInput унаследовано от LitElement. Используя функцию тега css, мы можем вставлять наши директивы CSS в виде строки. Также необходимо импортировать функцию тега css. Стили изначально взяты из Skeleton, крошечной библиотеки CSS.
Селектор : host () ссылается на сам пользовательский элемент и используется для общих стилей, таких как применение красивого шрифта. для всех основных ОС. Поскольку большинство частей в элементах Shadow DOM представлены как слоты, селектор :: slotted () используется для ссылки на все части, такие как ввод или метка.
Наконец, мы определяем настраиваемый элемент с именем pretty-input на основе класса PrettyInput.

Красивый ввод готов к использованию, поэтому теперь мы расширяем наш main.js:

//main.js
import '@lion/input/lion-input.js';
import './pretty-input.js';

и файлы index.html

<!DOCTYPE html>
<html lang=”en”>
<head>
 <meta charset="UTF-8">
 <meta name="viewport” content=”width=device-width, initial-scale=1.0">
 <title>White-Label Web Components</title>
</head>
<body>
<form>
 <lion-input name="firstName" label="Input label"></lion-input>
 
 <pretty-input name="prettyInput" label="Pretty Input" >
 <div slot="help-text">This looks much nicer</div>
 </pretty-input>
</form>
<script type="module" src="main.js"></script>
</body>
</html>

Вы можете узнать больше о стилях, например о повторно используемых стилях в документации LitElement.

Создайте пакет, чтобы использовать стилизованный компонент в другом месте

Бандлинг - это отдельная тема. Большинство из вас знают Rollup, Webpack, Parcel и другие, но, возможно, вы не использовали их напрямую. Когда вы запускаете свои проекты LitElement с использованием упомянутых выше стартовых проектов Javascript / Typescript, сборщик уже включен.
Для тех из вас, кто не знаком с сборщиком: сборщик берет исходные коды вашего веб-проекта, собирает все зависимые сценарии, которые требуют d, import или на которые ссылаются теги script, дедуплицируют код, объединяют их все и выводят один файл Javascript, который будет включены в производственную версию вашего кода.

Чтобы показать, как работает наш компонент PrettyInput, мы устанавливаем Rollup через npm:

npm install rollup

Вы можете установить Rollup глобально, чтобы иметь его в своем наборе инструментов для будущих проектов:

npm install --global rollup

Rollup сталкивается с теми же проблемами при разрешении зависимостей в node_modules, но, к счастью, есть готовый плагин. Мы добавляем его в наш проект с помощью:

npm install --save-dev rollup-plugin-node-resolve

Наконец, мы пишем сценарий конфигурации для свертки, чтобы указать правильное направление:

// rollup.config.js
import resolve from 'rollup-plugin-node-resolve';
export default {
 input: 'main.js',
 output: {
   file: 'bundle.js',
   format: 'cjs'
 },
 plugins: [
   resolve({
     browser: true,
     only: [ /^@lion\/.*$/ ]
   })
 ]
}

В основном конфигурация определяет main.js как точку входа для связывания. На выходе будет файл bundle.js. Плагин node-resolve импортируется, как и любой модуль ES, и должен работать в режиме browser, что означает, что он учитывает потенциальные поля browser в package.json зависимостей.
Параметр only конфигурации разрешения полезен, когда вы хотите включить только некоторые зависимости. Все остальные зависимости будут помечены как внешние, и вы должны сами позаботиться о них. В нашем примере мы включаем только части @ lion *, поэтому LitElement не попадет в комплект. Когда вы нацеливаетесь на один файл пакета, удалите строку strting с only.

Выполнять

rollup --config

в командной строке, и пакет создается в основном каталоге white-label-web-components. Вот и все!