npm.io
1.8.0 • Published 2d ago

@devjuliovilla/jv-ui

Licence
MIT
Version
1.8.0
Deps
1
Size
3.1 MB
Vulns
0
Weekly
0

@devjuliovilla/jv-ui

Accessibility-first Angular component library built with signals and standalone APIs. Includes components, forms, data grids, dialogs, layout primitives, services, and i18n infrastructure.

Installation

npm install @devjuliovilla/jv-ui

Import the theme CSS in your angular.json or styles array:

"styles": ["@devjuliovilla/jv-ui/styles/jv-theme.css"]

Quick start

import { ApplicationConfig } from '@angular/core';
import { provideJvUi } from '@devjuliovilla/jv-ui';

export const appConfig: ApplicationConfig = {
  providers: [provideJvUi({ locale: 'en' })],
};
import { Component } from '@angular/core';
import { JvButtonComponent } from '@devjuliovilla/jv-ui';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [JvButtonComponent],
  template: '<jv-button variant="primary">Hello</jv-button>',
})
export class App {}

Components

Category Components
Buttons JvButton, JvButtonGroup, JvIconButton
Forms JvInput, JvTextarea, JvSelect, JvCheckbox, JvRadio, JvSwitch, JvFormContainer
Data Grid JvGrid — full-featured data table (see below)
Containers JvCard, JvSection, JvDivider
List JvList, JvListItem — list with title, description, icons, badges, and interactive items
Feedback JvAlert, JvBadge, JvLoader, JvToast
Dialogs JvDialog, JvConfirmDialog
Layout JvDashboardShell, JvSidebar, JvTopbar, JvBreadcrumb, JvPage
Auth Pages JvLoginPage, JvForgotPasswordPage, JvChangePasswordPage
Icon JvIcon — Lucide-based icon component with 1500+ auto-generated icons
Pagination JvPagination — standalone pagination with i18n

Grid Features

Feature Description
Sorting Client-side multi-column sorting with sort icons and aria-sort
Search Global text search across visible columns
Pagination Configurable page size, page range buttons, first/last/prev/next
Selection Checkbox row selection with selectedIds / selectionChange
Row actions Custom action buttons per row
Density modes Compact, normal, comfortable
Sticky columns Pin columns to left or right
Column resizing Drag column header borders to resize
Column reordering Drag & drop column headers
Grouped headers Multi-row header with colspan via children
Per-column filters Filter input row with operators
Inline editing Double-click or Enter to edit: text, number, select, boolean
Virtual scrolling Render only visible rows for large datasets
CSV/Excel export Built-in toolbar buttons, no external deps
Server-side mode Delegate sort/filter/page to parent component
TrackBy Custom trackBy key or function
i18n All labels configurable via translation dictionary
Grid API
import { JvGridComponent } from '@devjuliovilla/jv-ui';

Inputs:

Input Type Default Description
data T[] [] Row data array
columns JvGridColumn<T>[] [] Column definitions
actions JvGridAction<T>[] [] Row action button configs
options Partial<JvGridOptions> {} Feature toggles and config
trackBy keyof T | Function | null null Row identity
selectedIds (string | number)[] [] Controlled selection IDs

Outputs:

Output Type
rowClick T
rowDoubleClick T
actionClick { actionId: string; row: T }
selectionChange (string | number)[]
pageChange { pageIndex: number; pageSize: number }
searchChange string
sortChange { columnKey: string; direction: 'asc' | 'desc' | null }
columnFilter { columnKey: string; value: string }
columnResize { columnKey: string; width: string }
columnReorder { columnKey: string; newIndex: number }
rowEdit { row: T; column: JvGridColumn<T>; value: unknown }

JvGridColumn options:

Property Type Description
key keyof T | string Data field key
header string Column display header
sortable boolean Enable column sorting
searchable boolean Include in global search
filterable boolean Show per-column filter input
hidden boolean Hide column from display
sticky 'left' | 'right' Pin column position
editable boolean Allow inline cell editing
editType 'text' | 'number' | 'select' | 'boolean' Editor type
editOptions { label: string; value: unknown }[] Options for select editor
width string Column width (e.g. '8rem')
align 'start' | 'center' | 'end' Text alignment
type 'text' | 'number' | 'currency' | 'date' | 'datetime' | 'boolean' Data type for formatting
format (value, row) => string Custom display formatter
children JvGridColumn<T>[] Child columns for grouped headers
resizable boolean Allow column resize
cellClass string CSS class for cells
headerClass string CSS class for header

JvGridOptions:

Option Type Default Description
searchable boolean true Show search bar
sortable boolean true Enable column sorting
pageable boolean true Enable pagination
selectable boolean false Show selection checkboxes
pageSize number 20 Default page size
pageSizeOptions number[] [10, 20, 50, 100] Page size selector options
density 'compact' | 'normal' | 'comfortable' 'normal' Row density
loading boolean false Show loading spinner
emptyMessage string Empty state message
exportable boolean false Show CSV/Excel export buttons
serverSide boolean false Disable client-side processing
totalItems number 0 Total items for server-side mode
stickyColumns boolean false Enable sticky column support
resizableColumns boolean false Enable column resizing
reorderableColumns boolean false Enable column reordering
editable boolean false Enable inline editing
virtualScroll boolean false Enable virtual scrolling
virtualScrollRowHeight number 48 Row height for virtual scroll
columnFilters boolean false Show filter row below headers
rowDoubleClick boolean false Enable row double-click event
ariaLabel string Accessible label for the grid
Grid example
import { Component } from '@angular/core';
import { JvGridComponent, JvGridColumn, JvGridOptions } from '@devjuliovilla/jv-ui';

interface Product {
  id: number;
  name: string;
  price: number;
  status: string;
}

@Component({
  selector: 'app-products',
  standalone: true,
  imports: [JvGridComponent],
  template: `
    <jv-grid
      [data]="products"
      [columns]="columns"
      [options]="{ selectable: true, exportable: true, pageSize: 10 }"
      [trackBy]="'id'"
      [selectedIds]="selectedIds"
      (selectionChange)="selectedIds = $event"
    />
  `,
})
export class ProductsComponent {
  products: Product[] = [ /* ... */ ];
  selectedIds: (string | number)[] = [];
  columns: JvGridColumn<Product>[] = [
    { key: 'id', header: 'ID', width: '4rem' },
    { key: 'name', header: 'Product', sortable: true, filterable: true },
    { key: 'price', header: 'Price', type: 'number', align: 'end', format: (v) => '

List API

import { JvListComponent, JvListItemComponent } from '@devjuliovilla/jv-ui';

JvList inputs:

Input Type Default Description
role 'list' | 'navigation' 'list' ARIA role for the list
variant 'bordered' | null null Outer border + border-radius around the list (items always have bottom border)
ariaLabel string '' Accessible label

JvListItem inputs:

Input Type Default Description
title string (required) Primary text
description string '' Secondary text below title
leadingIcon string | null null Lucide icon name on the left
disabled boolean false Gray out and block interaction
active boolean false Highlight with primary color and left border

JvListItem outputs:

Output Type
activated void

Content projection: use the meta attribute selector for badges, icons, or any content on the right side:

<jv-list-item title="Inbox" description="New messages">
  <jv-badge tone="primary" meta>3</jv-badge>
  <jv-icon name="chevron-right" meta />
</jv-list-item>
Example
import { Component } from '@angular/core';
import { JvListComponent, JvListItemComponent, JvBadgeComponent } from '@devjuliovilla/jv-ui';

@Component({
  selector: 'app-nav-list',
  standalone: true,
  imports: [JvListComponent, JvListItemComponent, JvBadgeComponent],
  template: `
    <jv-list variant="bordered">
      <jv-list-item
        title="Dashboard"
        description="Main overview"
        leadingIcon="layout-dashboard"
        [active]="true"
      />
      <jv-list-item
        title="Notifications"
        description="3 pending"
        (activated)="onOpen()"
      >
        <jv-badge tone="primary" meta>3</jv-badge>
      </jv-list-item>
      <jv-list-item
        title="Reports"
        description="Coming soon"
        [disabled]="true"
      />
    </jv-list>
  `,
})
export class NavListComponent {
  onOpen() { /* handle activation */ }
}

Pagination API

import { JvPaginationComponent } from '@devjuliovilla/jv-ui';
Input Type Default Description
totalItems number 0 Total items
pageSize number 20 Items per page
pageSizeOptions number[] [10, 20, 50, 100] Page size options
pageIndex number 0 Current page (0-based)
maxVisiblePages number 5 Max page buttons to show
Output Type
pageChange { pageIndex: number; pageSize: number }

Textarea API

import { JvTextareaComponent } from '@devjuliovilla/jv-ui';
Input Type Default Description
placeholder string '' Placeholder text
required boolean false Mark field as required
invalid boolean false Show invalid state
readonly boolean false Make textarea read-only
rows number 3 Visible number of rows
cols number Visible width in columns
maxlength number Maximum character length
describedBy string '' ID of description/error element for aria-describedby
inputId string jv-textarea-{n} Auto-generated unique ID

Implements ControlValueAccessor — compatible with [(ngModel)] and reactive forms via formControlName.

Example
import { Component } from '@angular/core';
import { JvTextareaComponent } from '@devjuliovilla/jv-ui';
import { ReactiveFormsModule, FormBuilder } from '@angular/forms';

@Component({
  selector: 'app-profile',
  standalone: true,
  imports: [ReactiveFormsModule, JvTextareaComponent],
  template: `
    <jv-textarea
      formControlName="bio"
      placeholder="Tell us about yourself..."
      [rows]="4"
      [maxlength]="500"
    />
  `,
})
export class ProfileComponent {
  form = inject(FormBuilder).group({ bio: [''] });
}

Icon System

import { JvIconComponent, JV_LUCIDE_ICON_REGISTRY } from '@devjuliovilla/jv-ui';
Input Type Default Description
name string Icon name (from auto-generated Lucide registry)
size number 24 Width and height in pixels
strokeWidth number 2 SVG stroke width
decorative boolean true aria-hidden="true" when decorative
ariaLabel string Accessible label when not decorative

Icons are auto-generated from lucide-static via:

node tools/generate-icons.mjs

This reads all SVG files from lucide-static/icons and produces jv-icon-registry.ts with the complete set (~1500 icons). Run it after updating lucide-static to keep icons in sync.

Layout API

JvDashboardShell
import { JvDashboardShellComponent } from '@devjuliovilla/jv-ui';
Input Type Default Description
title string App / brand title
sidebarSubtitle string '' Subtitle below brand
brandIcon string 'monitor' Brand Lucide icon
navItems JvNavItem[] [] Navigation items (supports nested children)
sidebarCollapsed boolean false Desktop sidebar collapsed state
mobileSidebarOpen boolean false Mobile sidebar open/closed
topbarTitle string '' Topbar page title
topbarSubtitle string '' Topbar subtitle
currentTheme JvTheme 'light' Active theme value
themeOptions JvThemeOption[] [] Theme selector options
topbarActions JvTopbarAction[] [] Icon buttons in topbar
showThemeSelector boolean true Show theme pills
Output Description
menuClick Hamburger button clicked — toggle mobile sidebar
mobileClose Backdrop clicked or navigation selected — close mobile sidebar
sidebarCollapseToggle Collapse toggle clicked — collapse/expand sidebar
themeChange Theme pill clicked
topbarActionClick Topbar action button clicked

Mobile behavior: at viewports ≤ 900px the sidebar becomes a fixed overlay with slide-in animation (transform: translateX) and a semi-transparent backdrop. The sidebar emits mobileClose when the backdrop is clicked or a nav link is followed.

JvSidebar
Input Type Default Description
title string Brand title
subtitle string '' Brand subtitle
brandIcon string 'monitor' Brand icon
items JvNavItem[] [] Navigation items
collapsed boolean false Collapse to icon-only
mobileOpen boolean false Show on mobile
ariaLabel string 'Sidebar navigation' Accessible label
Output Description
collapseToggle Collapse button clicked
mobileClose Backdrop or nav item interaction — request close

Responsive Design

The library includes basic responsive behavior:

  • Breakpoints defined as CSS custom properties: --jv-breakpoint-sm (640px), --jv-breakpoint-md (768px), --jv-breakpoint-lg (1024px), --jv-breakpoint-xl (1280px)
  • Dashboard shell collapses to single column at ≤ 900px; sidebar becomes a slide-in overlay with backdrop
  • Topbar stacks vertically at ≤ 900px
  • Grid pagination and toolbar stack at ≤ 640px; table scrolls horizontally with overflow-x: auto
  • Flex-wrap is used extensively for natural overflow handling
  • Dialog and Toast constrain width with min() to never exceed the viewport

Services

Service Import Path Description
JvThemeService @devjuliovilla/jv-ui Light / dark / high-contrast theme switching
JvTranslationService @devjuliovilla/jv-ui Dictionary-based i18n (en/es)
JvToastService @devjuliovilla/jv-ui Toast notification system
JvLoaderService @devjuliovilla/jv-ui Full-screen loader with request counter
JvDialogService @devjuliovilla/jv-ui Programmatic confirm dialogs
JvAnnouncementService @devjuliovilla/jv-ui Screen-reader live-region announcements

Accessibility

  • WCAG 2.2 AA target
  • Keyboard navigation for all interactive components
  • Focus management with visible focus indicators
  • Screen reader announcements (loading, empty states, page changes)
  • aria-sort on sortable grid headers
  • aria-selected on selectable grid rows
  • aria-label and aria-labelledby on interactive controls
  • Supports prefers-reduced-motion

Requirements

  • Angular 21.2+
  • TypeScript 5.9+

License

MIT

+ v }, { key: 'status', header: 'Status', sortable: true }, ]; }

List API

__CODE_BLOCK_6__

JvList inputs:

Input Type Default Description
__INLINE_CODE_176__ __INLINE_CODE_177__ __INLINE_CODE_178__ ARIA role for the list
__INLINE_CODE_179__ __INLINE_CODE_180__ __INLINE_CODE_181__ Outer border + border-radius around the list (items always have bottom border)
__INLINE_CODE_182__ __INLINE_CODE_183__ __INLINE_CODE_184__ Accessible label

JvListItem inputs:

Input Type Default Description
__INLINE_CODE_185__ __INLINE_CODE_186__ (required) Primary text
__INLINE_CODE_187__ __INLINE_CODE_188__ __INLINE_CODE_189__ Secondary text below title
__INLINE_CODE_190__ __INLINE_CODE_191__ __INLINE_CODE_192__ Lucide icon name on the left
__INLINE_CODE_193__ __INLINE_CODE_194__ __INLINE_CODE_195__ Gray out and block interaction
__INLINE_CODE_196__ __INLINE_CODE_197__ __INLINE_CODE_198__ Highlight with primary color and left border

JvListItem outputs:

Output Type
__INLINE_CODE_199__ __INLINE_CODE_200__

Content projection: use the __INLINE_CODE_201__ attribute selector for badges, icons, or any content on the right side:

__CODE_BLOCK_7__
Example
__CODE_BLOCK_8__

Pagination API

__CODE_BLOCK_9__
Input Type Default Description
__INLINE_CODE_202__ __INLINE_CODE_203__ __INLINE_CODE_204__ Total items
__INLINE_CODE_205__ __INLINE_CODE_206__ __INLINE_CODE_207__ Items per page
__INLINE_CODE_208__ __INLINE_CODE_209__ __INLINE_CODE_210__ Page size options
__INLINE_CODE_211__ __INLINE_CODE_212__ __INLINE_CODE_213__ Current page (0-based)
__INLINE_CODE_214__ __INLINE_CODE_215__ __INLINE_CODE_216__ Max page buttons to show
Output Type
__INLINE_CODE_217__ __INLINE_CODE_218__

Textarea API

__CODE_BLOCK_10__
Input Type Default Description
__INLINE_CODE_219__ __INLINE_CODE_220__ __INLINE_CODE_221__ Placeholder text
__INLINE_CODE_222__ __INLINE_CODE_223__ __INLINE_CODE_224__ Mark field as required
__INLINE_CODE_225__ __INLINE_CODE_226__ __INLINE_CODE_227__ Show invalid state
__INLINE_CODE_228__ __INLINE_CODE_229__ __INLINE_CODE_230__ Make textarea read-only
__INLINE_CODE_231__ __INLINE_CODE_232__ __INLINE_CODE_233__ Visible number of rows
__INLINE_CODE_234__ __INLINE_CODE_235__ Visible width in columns
__INLINE_CODE_236__ __INLINE_CODE_237__ Maximum character length
__INLINE_CODE_238__ __INLINE_CODE_239__ __INLINE_CODE_240__ ID of description/error element for aria-describedby
__INLINE_CODE_241__ __INLINE_CODE_242__ __INLINE_CODE_243__ Auto-generated unique ID

Implements __INLINE_CODE_244__ — compatible with __INLINE_CODE_245__ and reactive forms via __INLINE_CODE_246__.

Example
__CODE_BLOCK_11__

Icon System

__CODE_BLOCK_12__
Input Type Default Description
__INLINE_CODE_247__ __INLINE_CODE_248__ Icon name (from auto-generated Lucide registry)
__INLINE_CODE_249__ __INLINE_CODE_250__ __INLINE_CODE_251__ Width and height in pixels
__INLINE_CODE_252__ __INLINE_CODE_253__ __INLINE_CODE_254__ SVG stroke width
__INLINE_CODE_255__ __INLINE_CODE_256__ __INLINE_CODE_257__ __INLINE_CODE_258__ when decorative
__INLINE_CODE_259__ __INLINE_CODE_260__ Accessible label when not decorative

Icons are auto-generated from lucide-static via:

__CODE_BLOCK_13__

This reads all SVG files from __INLINE_CODE_261__ and produces __INLINE_CODE_262__ with the complete set (~1500 icons). Run it after updating __INLINE_CODE_263__ to keep icons in sync.

Layout API

JvDashboardShell
__CODE_BLOCK_14__
Input Type Default Description
__INLINE_CODE_264__ __INLINE_CODE_265__ App / brand title
__INLINE_CODE_266__ __INLINE_CODE_267__ __INLINE_CODE_268__ Subtitle below brand
__INLINE_CODE_269__ __INLINE_CODE_270__ __INLINE_CODE_271__ Brand Lucide icon
__INLINE_CODE_272__ __INLINE_CODE_273__ __INLINE_CODE_274__ Navigation items (supports nested children)
__INLINE_CODE_275__ __INLINE_CODE_276__ __INLINE_CODE_277__ Desktop sidebar collapsed state
__INLINE_CODE_278__ __INLINE_CODE_279__ __INLINE_CODE_280__ Mobile sidebar open/closed
__INLINE_CODE_281__ __INLINE_CODE_282__ __INLINE_CODE_283__ Topbar page title
__INLINE_CODE_284__ __INLINE_CODE_285__ __INLINE_CODE_286__ Topbar subtitle
__INLINE_CODE_287__ __INLINE_CODE_288__ __INLINE_CODE_289__ Active theme value
__INLINE_CODE_290__ __INLINE_CODE_291__ __INLINE_CODE_292__ Theme selector options
__INLINE_CODE_293__ __INLINE_CODE_294__ __INLINE_CODE_295__ Icon buttons in topbar
__INLINE_CODE_296__ __INLINE_CODE_297__ __INLINE_CODE_298__ Show theme pills
Output Description
__INLINE_CODE_299__ Hamburger button clicked — toggle mobile sidebar
__INLINE_CODE_300__ Backdrop clicked or navigation selected — close mobile sidebar
__INLINE_CODE_301__ Collapse toggle clicked — collapse/expand sidebar
__INLINE_CODE_302__ Theme pill clicked
__INLINE_CODE_303__ Topbar action button clicked

Mobile behavior: at viewports ≤ 900px the sidebar becomes a fixed overlay with slide-in animation (__INLINE_CODE_304__) and a semi-transparent backdrop. The sidebar emits __INLINE_CODE_305__ when the backdrop is clicked or a nav link is followed.

JvSidebar
Input Type Default Description
__INLINE_CODE_306__ __INLINE_CODE_307__ Brand title
__INLINE_CODE_308__ __INLINE_CODE_309__ __INLINE_CODE_310__ Brand subtitle
__INLINE_CODE_311__ __INLINE_CODE_312__ __INLINE_CODE_313__ Brand icon
__INLINE_CODE_314__ __INLINE_CODE_315__ __INLINE_CODE_316__ Navigation items
__INLINE_CODE_317__ __INLINE_CODE_318__ __INLINE_CODE_319__ Collapse to icon-only
__INLINE_CODE_320__ __INLINE_CODE_321__ __INLINE_CODE_322__ Show on mobile
__INLINE_CODE_323__ __INLINE_CODE_324__ __INLINE_CODE_325__ Accessible label
Output Description
__INLINE_CODE_326__ Collapse button clicked
__INLINE_CODE_327__ Backdrop or nav item interaction — request close

Responsive Design

The library includes basic responsive behavior:

  • Breakpoints defined as CSS custom properties: __INLINE_CODE_328__ (640px), __INLINE_CODE_329__ (768px), __INLINE_CODE_330__ (1024px), __INLINE_CODE_331__ (1280px)
  • Dashboard shell collapses to single column at ≤ 900px; sidebar becomes a slide-in overlay with backdrop
  • Topbar stacks vertically at ≤ 900px
  • Grid pagination and toolbar stack at ≤ 640px; table scrolls horizontally with __INLINE_CODE_332__
  • Flex-wrap is used extensively for natural overflow handling
  • Dialog and Toast constrain width with __INLINE_CODE_333__ to never exceed the viewport

Services

Service Import Path Description
__INLINE_CODE_334__ __INLINE_CODE_335__ Light / dark / high-contrast theme switching
__INLINE_CODE_336__ __INLINE_CODE_337__ Dictionary-based i18n (en/es)
__INLINE_CODE_338__ __INLINE_CODE_339__ Toast notification system
__INLINE_CODE_340__ __INLINE_CODE_341__ Full-screen loader with request counter
__INLINE_CODE_342__ __INLINE_CODE_343__ Programmatic confirm dialogs
__INLINE_CODE_344__ __INLINE_CODE_345__ Screen-reader live-region announcements

Accessibility

  • WCAG 2.2 AA target
  • Keyboard navigation for all interactive components
  • Focus management with visible focus indicators
  • Screen reader announcements (loading, empty states, page changes)
  • __INLINE_CODE_346__ on sortable grid headers
  • __INLINE_CODE_347__ on selectable grid rows
  • __INLINE_CODE_348__ and __INLINE_CODE_349__ on interactive controls
  • Supports __INLINE_CODE_350__

Requirements

  • Angular 21.2+
  • TypeScript 5.9+

License

MIT

Keywords