@conduction/nextcloud-vue
v0.1.0-beta.3
Published
Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support
Keywords
Readme
@conduction/nextcloud-vue is an npm component library that sits on top of @nextcloud/vue and provides higher-level, opinionated components for building Nextcloud apps. It handles the repetitive patterns — schema-driven tables, CRUD dialogs, paginated lists, faceted search — so each app only writes the domain-specific parts.
Used internally by Pipelinq, Procest, Larping, and other Conduction Nextcloud apps.
Requires: Vue 2.7, Pinia 2, @nextcloud/vue 8
Features
Layout & Page Components
| Component | Description |
|-----------|-------------|
| CnIndexPage | Zero-config index page with table/card views, built-in CRUD dialogs, pagination, mass actions, and faceted search |
| CnPageHeader | Page header with icon, title, and description |
| CnActionsBar | Action bar with add button, mass action triggers, view toggle (table/grid), and search |
| CnIndexSidebar | Sidebar for index pages |
Data Display
| Component | Description |
|-----------|-------------|
| CnDataTable | Sortable table with multi-select, schema-driven columns, loading states, and empty states |
| CnCardGrid | Responsive card grid for object summaries |
| CnObjectCard | Single object card with title, metadata, and actions |
| CnCellRenderer | Type-aware cell formatter for strings, numbers, dates, objects, arrays, and booleans |
| CnFacetSidebar | Faceted filter sidebar with aggregated count buckets |
| CnPagination | Full pagination with page numbers, size selector, and "go to page" |
| CnFilterBar | Search input with filter controls |
| CnKpiGrid | KPI metric cards for statistics dashboards |
Single-Object Dialogs
| Component | Description |
|-----------|-------------|
| CnFormDialog | Schema-driven form dialog for create and edit; auto-generates fields from JSON Schema |
| CnDeleteDialog | Delete confirmation with two-phase confirm/result pattern |
| CnCopyDialog | Copy dialog with naming pattern selector |
Mass-Action Dialogs
| Component | Description |
|-----------|-------------|
| CnMassDeleteDialog | Bulk delete confirmation |
| CnMassCopyDialog | Bulk copy with per-item naming |
| CnMassExportDialog | Export selected items (JSON, CSV, …) |
| CnMassImportDialog | Bulk import with file upload and format detection |
Settings & Config
| Component | Description |
|-----------|-------------|
| CnSettingsCard | Collapsible settings card with save state |
| CnSettingsSection | Container for grouping settings |
| CnConfigurationCard | Configuration card with status indicator |
| CnVersionInfoCard | Version information display |
| CnStatsBlock | Statistics block with count and breakdown |
| CnRegisterMapping | Register-to-field mapping configuration |
State Management
| Export | Description |
|--------|-------------|
| useObjectStore(id) | Generic Pinia store for OpenRegister CRUD — pagination, search, caching |
| createObjectStore(id) | Factory for custom-scoped object stores |
| createSubResourcePlugin(name) | Plugin factory for sub-resource management |
| auditTrailsPlugin | Adds audit trail state and getters |
| relationsPlugin | Manages object relations/associations |
| filesPlugin | Handles file attachments and uploads |
| lifecyclePlugin | Tracks lifecycle states (draft, published, archived) |
| registerMappingPlugin | Manages register-to-field mappings |
Composables
| Composable | Description |
|------------|-------------|
| useListView(options) | Manages list view state: search debounce, filter state, sort, pagination |
| useDetailView(options) | Manages detail view: load, edit, delete, validation |
| useSubResource(options) | Manages sub-resource operations |
Schema Utilities
| Function | Description |
|----------|-------------|
| columnsFromSchema(schema) | Auto-generate data table column definitions from JSON Schema |
| fieldsFromSchema(schema) | Auto-generate form field definitions from JSON Schema |
| filtersFromSchema(schema) | Auto-generate filter definitions from JSON Schema |
| formatValue(value, format) | Type-aware cell value formatter |
Architecture
graph TD
A[Nextcloud App] -->|imports| B[@conduction/nextcloud-vue]
B --> C[Components]
B --> D[useObjectStore]
B --> E[Composables]
B --> F[Schema Utils]
D -->|CRUD| G[OpenRegister REST API]
C -->|styles via| H[Nextcloud CSS Variables]
C -->|NL Design tokens| I[--nldesign-* CSS vars]Two-Phase Dialog Pattern
All dialogs follow a predictable confirm/result flow that keeps parent components in control of API calls:
// 1. Dialog emits @confirm with user input
// 2. Parent handles API call
// 3. Parent calls dialog.setResult(response) via $ref
// 4. Dialog shows toast and auto-closesSchema-Driven Components
Pass a JSON Schema and get a fully working table or form with zero configuration:
<CnIndexPage
:schema="caseTypeSchema"
:objects="caseTypes"
@save="onSave"
@delete="onDelete"
/>Installation
npm install @conduction/nextcloud-vueImport the CSS alongside your component imports:
import '@conduction/nextcloud-vue/dist/nextcloud-vue.css'
import { CnIndexPage, useObjectStore } from '@conduction/nextcloud-vue'Webpack Alias (for local development)
When developing against the source directly, add deduplication aliases in webpack.config.js to prevent dual-instance bugs:
config.resolve.alias = {
'@conduction/nextcloud-vue': path.resolve(__dirname, '../nextcloud-vue/src'),
'vue': path.resolve(__dirname, 'node_modules/vue'),
'pinia': path.resolve(__dirname, 'node_modules/pinia'),
'@nextcloud/vue': path.resolve(__dirname, 'node_modules/@nextcloud/vue'),
}Important: Without these aliases, webpack may resolve Vue and Pinia from the library's
node_modules, creating dual instances that break reactivity and state management.
Directory Structure
nextcloud-vue/
├── src/
│ ├── index.js # Main barrel export
│ ├── components/ # 30+ Vue 2 SFCs (one directory each)
│ │ ├── CnIndexPage/
│ │ ├── CnDataTable/
│ │ ├── CnFormDialog/
│ │ └── ...
│ ├── store/
│ │ ├── index.js # useObjectStore, createObjectStore
│ │ └── plugins/ # auditTrails, relations, files, lifecycle, registerMapping
│ ├── composables/ # useListView, useDetailView, useSubResource
│ ├── utils/ # schema, headers, errors, formatting
│ ├── css/ # Modular CSS (one file per component group)
│ └── types/index.d.ts # TypeScript definitions
├── tests/ # Jest test suite
├── dist/ # Built output (ESM, CJS, CSS)
├── rollup.config.js # Build configuration
└── package.jsonDevelopment
npm install
npm run dev # Watch mode (Rollup)
npm run build # Production build
npm test # Jest tests
npm run lint # ESLint
npm run stylelint # StylelintTech Stack
| Layer | Technology | |-------|-----------| | Framework | Vue 2.7 (Options API) | | State | Pinia 2 | | Build | Rollup 3 | | CSS | PostCSS (extracted to dist/nextcloud-vue.css) | | Testing | Jest 29, @vue/test-utils 1 | | Quality | ESLint (@nextcloud/eslint-config), Stylelint | | Release | semantic-release (automated npm publish) |
License
EUPL-1.2
Authors
Built by Conduction — open-source software for Dutch government and public sector organizations.
