npm.io
0.51.5 • Published 5 months ago

@esportsplus/ui

Licence
Version
0.51.5
Deps
7
Size
13.6 MB
Vulns
0
Weekly
0
Stars
1

@esportsplus/ui

A reactive component library built on compile-time template transformations. Provides typed, tree-shakeable UI components with integrated SCSS theming.

Installation

pnpm add @esportsplus/ui

Dependencies

  • @esportsplus/frontend - Tagged template literals with compile-time transforms and reactive state management
  • @esportsplus/action - Response/error handling
  • @esportsplus/utilities - Core utilities

Quick Start

import { button, form, input, select } from '@esportsplus/ui';
import { html } from '@esportsplus/frontend';

// Simple component
html`${button({}, 'Click Me')}`;

// Form with validation
html`
  ${form.action({
    action: async ({ input: data }) => {
      const result = await api.submit(data);
      return result.ok ? { errors: [] } : { errors: result.errors };
    }
  }, html`
    ${input({ name: 'email', type: 'email' })}
    ${button({}, 'Submit')}
  `)}
`;

// Select with reactive state
html`
  ${select({
    options: { a: 'Option A', b: 'Option B' },
    selected: 'a'
  }, (state) => html`Selected: ${state.selected}`)}
`;

Components

Form Controls
Component Description Variants
input Text input with validation state -
textarea Multi-line text input -
checkbox Checkbox with label -
radio Radio button group -
range Range slider -
select Dropdown with custom options -
switch Toggle switch -
form Form wrapper form.action, form.input
Interactive
Component Description Variants
button Standard button button.hold
tooltip Popup content tooltip.menu, tooltip.onclick, tooltip.onhover
accordion Collapsible sections -
clipboard Copy to clipboard clipboard.onclick, clipboard.write
alert Notifications error, info, success types
Display
Component Description
counter Animated number with currency formatting
loader Loading spinner
loading Border loading indicator
typewriter Animated typing effect
highlight Viewport intersection highlight
ellipsis Animated dots
icon SVG sprite wrapper
number Number formatting
truncate Text truncation
json JSON display
Layout
Component Description
scrollbar Custom scrollbar container
frame Scrollable frame
sidebar Side navigation
site Site wrapper
overlay Modal/overlay container
Utility
Component Description
back Back navigation link
root Global event coordination (root.onclick)
template Template factory helper

Component Patterns

Factory Pattern

Components use template.factory() supporting flexible call signatures:

// No arguments
component()

// Attributes only
component({ class: 'custom' })

// Content only
component(html`<span>Content</span>`)

// Both
component({ class: 'custom' }, html`<span>Content</span>`)
Reactive State

Components can accept and return reactive state:

import { reactive } from '@esportsplus/frontend';

let state = reactive({ active: false });

accordion({ state }, html`
  ${() => state.active ? 'Open' : 'Closed'}
`);
Form Integration
form.action({
  action: async ({ input, response }) => {
    // input: parsed FormData with dot-notation support
    // response: error handling utilities
    return { errors: [] };
  }
}, content);

// Input with error state
form.input(element, { error: 'Required field' });

Styling

CSS Layers

Styles are organized into layers for proper cascade:

@layer normalize
@layer components
@layer themes
@layer css-utilities
Importing Styles
// All component styles
@use '@esportsplus/ui/*.scss';

// Specific component
@use '@esportsplus/ui/button.scss';

// CSS utilities
@use '@esportsplus/ui/css-utilities.scss';

// Design tokens
@use '@esportsplus/ui/tokens.scss';

// Theme
@use '@esportsplus/ui/themes/dark/*.scss';
Design Tokens

Located in tokens.scss:

  • Colors: --color-{name}-{300|400|500} (black, white, red, green, blue, purple, yellow, grey)
  • Sizing: --size-{300-800} (12px-80px)
  • Spacing: --spacing-{0-600}
  • Border: --border-radius-{100-900}, --border-width-{100-700}
  • Typography: --font-size-*, --font-weight-*, --line-height-*
CSS Utilities
<!-- Layout -->
<div class="--flex --flex-center --gap-200">

<!-- Spacing -->
<div class="--margin-400 --padding-200">

<!-- Typography -->
<p class="--text-uppercase --color-grey-400">

<!-- States -->
<div class="--skeleton --disabled --hidden">
Component Variables

Each component exposes CSS custom properties:

.ui-button {
  --background: var(--color-blue-400);
  --color: var(--color-white);
  --border-radius: var(--border-radius-300);
  --padding-horizontal: 16px;
  --padding-vertical: 8px;
}

Theming

// JavaScript
import '@esportsplus/ui/themes/dark';

// SCSS
@use '@esportsplus/ui/themes/dark/*.scss';

Themes override component variables. Create custom themes by overriding CSS custom properties.

Build

pnpm build         # Full build (SCSS + TypeScript)
pnpm build:vite    # SCSS compilation only
pnpm build:ts      # TypeScript compilation only
Output Structure
build/
├── components/
│   ├── {component}/
│   │   ├── index.js
│   │   ├── index.d.ts
│   │   └── scss/index.scss
│   └── index.js
├── css-utilities/
├── themes/
│   ├── dark/
│   └── light/
└── fonts/

TypeScript

Full type safety with zero any types:

import type { Attributes } from '@esportsplus/frontend';

// Components are generic
template.factory<A extends Attributes, C>(fn);

// State types are explicit
type State = {
  active: boolean;
  error: string;
};

Performance

  • Compile-time transforms: Template expressions optimized at build
  • Tree-shakeable: Import only what you use
  • WeakMap caching: Memoized formatters and icons
  • Object pooling: Reused queue structures
  • RAF batching: Coalesced DOM updates
  • CSS layers: Efficient cascade resolution

License

MIT