@finema/core

30,651
Install
npm install @finema/core
Latest Version:3.28.0
Vue:3
License:MIT
Last Updated:Oct 20, 2026
Links: Repository  ·  npm
Maintainer: npm-finema

@finema/core

bun version bun downloads License Nuxt

Enterprise-grade Vue.js UI component library for Nuxt applications


🚀 Starting a new project? Use the starter template

[!TIP] Don't set it up by hand: start from the template. It's a Nuxt 3 project with @finema/core already installed and configured.

👉 gitlab.finema.co/finema/shared/nuxt3-template-with-uikit

git clone https://gitlab.finema.co/finema/shared/nuxt3-template-with-uikit.git my-app

Adding the kit to an existing project instead? See Installation below.


A comprehensive, production-ready UI kit that provides 20+ auto-registered components, composables, and utilities for building consistent and beautiful user interfaces. Designed specifically for Nuxt 3 with TypeScript support, automatic validation, and seamless theming.

✨ Features

  • 🎨 20+ Auto-registered Components - Forms, tables, dialogs, loaders, and more
  • 🔧 Auto-imported Composables - Dialog, notifications, form helpers, data loaders
  • ✅ Integrated Validation - vee-validate + valibot with Thai localization
  • 🎭 Theming System - Built on @nuxt/ui and Tailwind CSS
  • đŸ“Ļ Quality-of-life Features - Lodash auto-imports, masked inputs, and more
  • 📱 Mobile-first Design - Responsive components out-of-the-box
  • â™ŋ Accessibility Focused - ARIA labels, keyboard navigation, screen reader support
  • ⚡ Performance Optimized - Tree-shaking, lazy loading, virtual scrolling
  • 🔒 Type Safe - Full TypeScript support with auto-generated types

📋 Quick Links

🚀 Installation

Prerequisites

  • Nuxt 3 (Vue 3, Vite)
  • Node.js 22+ (recommended)

Install Package

# bun
bun install @finema/core

# yarn
yarn add @finema/core

# pnpm
pnpm add @finema/core

Setup Module

Add the module to your nuxt.config.ts:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: [
    '@finema/core'
  ]
})

That's it! All components and composables are now auto-imported and ready to use.

đŸŽ¯ Quick Start

Simple Form Example

<template>
  <div class="max-w-md mx-auto p-6">
    <h1 class="text-2xl font-bold mb-6">Contact Form</h1>

    <Form @submit="onSubmit">
      <FormFields :options="formFields" />

      <Button type="submit" :loading="isSubmitting" class="mt-6">
        Submit
      </Button>
    </Form>
  </div>
</template>

<script setup lang="ts">
// Form validation schema using valibot
const form = useForm({
  validationSchema: toTypedSchema(
    v.object({
      name: v.pipe(v.string(), v.minLength(2)),
      email: v.pipe(v.string(), v.email()),
      message: v.pipe(v.string(), v.minLength(10))
    })
  )
})

// Form fields configuration
const formFields = createFormFields(() => [
  {
    type: INPUT_TYPES.TEXT,
    props: {
      name: 'name',
      label: 'Full Name',
      required: true
    }
  },
  {
    type: INPUT_TYPES.TEXT,
    props: {
      name: 'email',
      label: 'Email',
      type: 'email',
      required: true
    }
  },
  {
    type: INPUT_TYPES.TEXTAREA,
    props: {
      name: 'message',
      label: 'Message',
      rows: 4,
      required: true
    }
  }
])

const isSubmitting = ref(false)
const notification = useNotification()

const onSubmit = form.handleSubmit(async (values) => {
  isSubmitting.value = true

  try {
    await $fetch('/api/contact', {
      method: 'POST',
      body: values
    })

    notification.success({
      title: 'Success!',
      description: 'Your message has been sent.'
    })

    form.resetForm()
  } catch (error) {
    notification.error({
      title: 'Error',
      description: 'Failed to send message.'
    })
  } finally {
    isSubmitting.value = false
  }
}, moveToError)
</script>

Data Table Example

<template>
  <div class="space-y-6">
    <div class="flex justify-between items-center">
      <h1 class="text-2xl font-bold">Users</h1>
      <Button @click="refreshData">Refresh</Button>
    </div>

    <Table
      :options="tableOptions"
      @pageChange="store.fetchPageChange"
      @search="store.fetchSearch"
    />
  </div>
</template>

<script setup lang="ts">
import { COLUMN_TYPES } from '#core/components/Table/types'

// Set up data store
const store = usePageLoader({
  url: '/api/users',
  transform: (response) => response.data
})

// Configure table
const tableOptions = useTable({
  repo: store,
  options: {
    isEnabledSearch: true
  },
  columns: () => [
    {
      accessorKey: 'name',
      header: 'Name'
    },
    {
      accessorKey: 'email',
      header: 'Email',
      type: COLUMN_TYPES.TEXT,
      meta: { max: 30 }
    },
    {
      accessorKey: 'avatar',
      header: 'Avatar',
      type: COLUMN_TYPES.IMAGE
    },
    {
      accessorKey: 'createdAt',
      header: 'Created',
      type: COLUMN_TYPES.DATE_TIME
    }
  ]
})

// Load initial data
onMounted(() => {
  store.fetchPage()
})

const refreshData = () => {
  store.fetchPage()
}
</script>

Dialog and Notification Example

<template>
  <div class="space-y-4">
    <Button @click="showDialog">Show Dialog</Button>
    <Button @click="showNotification">Show Notification</Button>
  </div>
</template>

<script setup lang="ts">
const dialog = useDialog()
const notification = useNotification()

const showDialog = async () => {
  const confirmed = await dialog.confirm({
    title: 'Confirm Action',
    description: 'Are you sure you want to proceed?',
    confirmText: 'Yes, proceed',
    cancelText: 'Cancel'
  })

  if (confirmed) {
    notification.success({
      title: 'Action Confirmed',
      description: 'The action was completed successfully.'
    })
  }
}

const showNotification = () => {
  notification.info({
    title: 'Information',
    description: 'This is an informational message.',
    duration: 5000
  })
}
</script>

🧩 Available Components

Form Components

  • Form - Main form wrapper with validation
  • FormFields - Dynamic field renderer
  • Input Types - Text, Number, Select, Date, File Upload, WYSIWYG, and more

Data Display

  • Table - Advanced data tables with sorting, pagination, and search
  • FlexDeck - Flexible grid layouts with pagination
  • Image - Optimized image component with loading states

Feedback

  • Dialog - Modal dialogs for confirmations and alerts
  • Notification - Toast notifications
  • Loader - Loading indicators
  • Empty - Empty state components

Layout

  • App - Application wrapper with global configuration

🔧 Available Composables

UI Composables

  • useDialog() - Modal dialog management
  • useNotification() - Toast notification system
  • useApp() - Global app state management

Form Composables

  • useForm() - Form state and validation (vee-validate)
  • createFormFields() - Reactive field configuration
  • moveToError() - Navigate to validation errors

Data Loading

  • usePageLoader() - Server-side pagination and CRUD operations
  • useListLoader() - Client-side list operations
  • useObjectLoader() - Single object operations
  • useTable() - Table configuration and state

Configuration

  • useCoreConfig() - Access app configuration
  • useUiConfig() - Theme configuration utilities

🎨 Theming

The UI kit is built on top of @nuxt/ui and Tailwind CSS, providing extensive theming capabilities:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@finema/core'],

  appConfig: {
    core: {
      site_name: 'My App',
      color: '#3B82F6'
    },
    ui: {
      colors: {
        primary: 'blue',
        secondary: 'gray'
      }
    }
  }
})

đŸ•šī¸ Playground

Explore live examples and experiment with components in the playground:

# Clone the repository
git clone <repository-url>
cd ui-kit

# Install dependencies
bun install

# Run playground
bun run dev

Visit the playground at different routes:

  • / - Component overview
  • /form - Form examples
  • /table - Table examples
  • /dialog - Dialog examples
  • /notification - Notification examples

đŸ› ī¸ Development Scripts

# Development
bun run dev              # Run playground in development
bun run dev:build        # Build playground
bun run dev:prepare      # Prepare development environment

# Quality
bun run check            # oxfmt --check + oxlint + nuxt-oxclint check-vue (rules from @finema/nuxt-oxclint)
bun run lint             # oxlint only
bun run lint:fix         # Fix linting issues
bun run format           # oxfmt, writes in place
bun run test             # Run tests
bun run test:watch       # Run tests in watch mode
bun run test:types       # Type checking

# Release
bun run release          # Create new release (check, test, build, publish)

📚 Documentation

🤝 Contributing

We welcome contributions! Please see our contributing guidelines for details on:

  • Code style and conventions
  • Development workflow
  • Testing requirements
  • Pull request process

📄 License

MIT License - see the LICENSE file for details.

đŸĸ About Finema

This UI kit is developed and maintained by the Finema Dev Core Team for building consistent, accessible, and beautiful user interfaces across all Finema projects.

Related Packages

@finema/nuxt-oxclint

Shared oxlint + oxfmt configuration and Vue conventions checker for Finema Nuxt...

414
@finema/finework-layer

A comprehensive Nuxt Layer providing reusable components, composables, layouts,...

51,878

Version History

Version Released License
3.28.0 MIT
3.27.1 MIT
3.27.0 MIT
3.26.2 MIT
3.26.1 MIT