@eparts/canopyalpsconfigurator
| Install | |
|---|---|
npm install @eparts/canopyalpsconfigurator |
|
| Latest Version: | 1.0.53 |
| Vue: | 3 |
| License: | ISC |
| Last Updated: | Jun 10, 2026 |
| Links: | Bitbucket · npm |
Eparts Configurator
A Vue 3 / Nuxt 4 compatible product configurator component for eparts platforms. Enables customers to configure complex products with dimensions, options, and pricing in real-time.
Features
- 🎨 PrimeVue Integration - Built with PrimeVue components and Aura theme
- 🔧 Configurable Options - Dropdowns, text inputs, dimensions, and custom options
- 💰 Real-time Pricing - Live price updates as options change
- 📦 Multi-target - Add to Cart, List, Quote, or Project
- 🎯 Quick Configure - Pre-configured product templates
- ✅ Validation - Built-in validation with error messaging
- 📱 Responsive - Mobile-friendly design
- 🌙 Dark Mode - Automatic theme support
Requirements
- Node.js: >= 22.16.0
- npm: >= 10.9.0
- Vue: ^3.5.26
- Pinia: ^3.0.4
- PrimeVue: ^4.5.4
Installation
npm install @eparts/epartsconfigurator
Or with pnpm (recommended for Nuxt 4):
pnpm add @eparts/epartsconfigurator
Usage in Nuxt 4
1. Register as a Plugin
Create a plugin file plugins/configurator.client.ts:
import { configuratorPlugin } from '@eparts/epartsconfigurator'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(configuratorPlugin)
})
2. Import Styles
Add to your nuxt.config.ts:
export default defineNuxtConfig({
css: [
'@eparts/epartsconfigurator/style.css'
]
})
Or import in your component/page:
<style>
@import '@eparts/epartsconfigurator/style.css';
</style>
3. Use in Components
Basic Usage
<template>
<EpartsConfigurator
:product-guid="productGuid"
:base-api-url="apiUrl"
:quantity="1"
target="Cart"
@complete="handleComplete"
@cancel="handleCancel"
@error="handleError"
/>
</template>
<script setup lang="ts">
import type { ConfiguredProductSelection, ConfiguratorError } from '@eparts/epartsconfigurator'
const productGuid = ref('abc-123-def-456')
const apiUrl = ref('https://api.example.com')
const handleComplete = (selection: ConfiguredProductSelection) => {
console.log('Configuration complete:', selection)
// Navigate to cart or show success message
}
const handleCancel = () => {
console.log('Configuration cancelled')
// Close modal or navigate away
}
const handleError = (error: ConfiguratorError) => {
console.error('Configuration error:', error)
// Show error notification
}
</script>
Modal/Drawer Integration
Create a modal wrapper component components/ConfiguratorModal.vue:
<template>
<Transition name="modal">
<div v-if="isOpen" class="modal-overlay" @click.self="close">
<div class="modal-container">
<div class="modal-header">
<h2>Configure Product</h2>
<button @click="close" class="close-button">×</button>
</div>
<div class="modal-body">
<EpartsConfigurator
v-if="product"
:product-guid="product.guid"
:product-id="product.id"
:base-api-url="apiUrl"
:quantity="quantity"
:target="target"
:support-email="supportEmail"
@complete="handleComplete"
@cancel="close"
@error="handleError"
/>
</div>
</div>
</div>
</Transition>
</template>
<script setup lang="ts">
import type { ConfiguredProductSelection, ConfiguratorError } from '@eparts/epartsconfigurator'
interface Props {
isOpen: boolean
product: {
id: number
guid: string
name: string
} | null
apiUrl: string
quantity?: number
target?: 'Cart' | 'List' | 'Quote' | 'Project'
supportEmail?: string
}
const props = withDefaults(defineProps<Props>(), {
quantity: 1,
target: 'Cart',
})
const emit = defineEmits<{
close: []
complete: [selection: ConfiguredProductSelection]
error: [error: ConfiguratorError]
}>()
const close = () => {
emit('close')
}
const handleComplete = (selection: ConfiguredProductSelection) => {
emit('complete', selection)
close()
}
const handleError = (error: ConfiguratorError) => {
emit('error', error)
}
</script>
<style scoped>
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal-container {
background: white;
border-radius: 8px;
max-width: 800px;
max-height: 90vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem;
border-bottom: 1px solid #e5e7eb;
}
.modal-body {
overflow-y: auto;
padding: 1.5rem;
}
.close-button {
background: none;
border: none;
font-size: 2rem;
cursor: pointer;
color: #6b7280;
line-height: 1;
}
.modal-enter-active,
.modal-leave-active {
transition: opacity 0.3s ease;
}
.modal-enter-from,
.modal-leave-to {
opacity: 0;
}
</style>
Using the Modal in a Product Page
<template>
<div class="product-page">
<div class="product-info">
<h1>{{ product.name }}</h1>
<p>{{ product.description }}</p>
<button
v-if="product.isConfigurable"
@click="openConfigurator"
class="configure-button"
>
Configure Product
</button>
</div>
<ConfiguratorModal
:is-open="configuratorOpen"
:product="configuratorProduct"
:api-url="apiUrl"
:support-email="supportEmail"
@close="configuratorOpen = false"
@complete="handleConfigurationComplete"
@error="handleConfigurationError"
/>
</div>
</template>
<script setup lang="ts">
import type { ConfiguredProductSelection, ConfiguratorError } from '@eparts/epartsconfigurator'
const product = ref({
id: 12345,
guid: 'abc-123-def-456',
name: 'Configurable Widget',
description: 'A highly customizable widget',
isConfigurable: true,
})
const apiUrl = ref('https://api.example.com')
const supportEmail = ref('support@example.com')
const configuratorOpen = ref(false)
const configuratorProduct = computed(() =>
configuratorOpen.value ? product.value : null
)
const openConfigurator = () => {
configuratorOpen.value = true
}
const handleConfigurationComplete = async (selection: ConfiguredProductSelection) => {
console.log('Product configured:', selection)
// Optional: Add to cart via API
// await addToCart(selection)
// Show success notification
// navigateTo('/cart')
}
const handleConfigurationError = (error: ConfiguratorError) => {
console.error('Configuration error:', error)
// Show error toast/notification
}
</script>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
productId |
number |
- | Product ID |
productGuid |
string |
- | Product GUID (required) |
baseApiUrl |
string |
- | Base API URL (required) |
quantity |
number |
1 |
Initial quantity |
target |
'Cart' | 'List' | 'Quote' | 'Project' |
'Cart' |
Target destination |
targetId |
number |
- | Target ID (for updates) |
lineNumber |
number |
- | Line number (for updates) |
targetAction |
string |
- | Target action |
groupingId |
number |
- | Grouping ID (for projects) |
stateId |
number |
- | State ID |
customerToken |
string |
- | Customer token |
guestCartGuid |
string |
- | Guest cart GUID |
isQuickConfigurable |
boolean |
false |
Enable quick configure |
isProductDetails |
boolean |
false |
Is product details page |
replace |
boolean |
false |
Replace mode |
supportEmail |
string |
- | Support email |
phone |
string |
- | Support phone |
saveApiUrl |
string |
- | Custom save API URL |
configuredProductString |
string |
- | Configured product JSON string |
listDetails |
string |
- | List details JSON |
miscId |
number |
- | Misc ID |
Events
complete
Emitted when configuration is successfully completed and saved.
Payload: ConfiguredProductSelection
{
Quantity: number
ConfiguredProduct: {
FormatVersion: string
ProductGuid: string
IsProductNumberOverridden: boolean
OptionalProductNumberOverride?: string
OptionalTags: string[]
OptionalDim1: Dimension | null
OptionalDim2: Dimension | null
SelectedProductOptions: SelectedProductOption[]
}
}
cancel
Emitted when user cancels configuration.
Payload: void
error
Emitted when an error occurs during configuration.
Payload: ConfiguratorError
{
type: 'api' | 'validation' | 'network'
message: string
details?: any
}
change
Emitted when configuration changes (for real-time updates).
Payload: ConfiguredProductSelection
priceUpdate
Emitted when price updates.
Payload: PriceUpdate
{
basePrice: number
unitPrice: number
cost: number | null
totalPrice: number
productNumber: string
}
Advanced Usage
Direct Store Access
For advanced use cases, you can directly access the Pinia stores:
import { useConfigStore } from '@eparts/epartsconfigurator'
const configStore = useConfigStore()
// Access product options
console.log(configStore.ProductOptions)
// Manually trigger pricing
await configStore.PriceProduct()
// Check if product is in favorites
console.log(configStore.IsInFavoriteParts)
TypeScript Support
Full TypeScript support with exported types:
import type {
ConfiguratorProps,
ConfiguredProductSelection,
ConfiguratorError,
PriceUpdate,
ProductOptions,
Dimension,
SelectedProductOption,
} from '@eparts/epartsconfigurator'
Styling
The configurator uses PrimeVue components with the Aura theme. You can customize the theme by overriding CSS variables or providing your own PrimeVue theme configuration.
Custom Theme
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@primevue/nuxt-module'],
primevue: {
options: {
theme: {
preset: YourCustomTheme,
options: {
darkModeSelector: '.dark-mode',
cssLayer: {
name: 'primevue',
order: 'tailwind-base, primevue, tailwind-utilities'
}
}
}
}
}
})
Development
# Install dependencies
npm install
# Run development server
npm run dev
# Build library
npm run build
# Run tests
npm run test:unit
# Type check
npm run type-check
License
ISC
Support
For issues or questions, contact: support@epartsservices.com
Related Packages
Everything you wish the HTML element could do, wrapped up into a lightweight, ex...
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 1.0.53 | ^3.5.26 | ISC | |
| 1.0.47 | ^3.5.26 | ISC | |
| 1.0.43 | ^3.5.26 | ISC | |
| 1.0.38 | ^3.5.26 | ISC | |
| 1.0.29 | ^3.5.26 | ISC | |
| 1.0.27 | ^3.5.26 | ISC | |
| 1.0.24 | ^3.5.26 | ISC | |
| 1.0.21 | ^3.5.26 | ISC | |
| 1.0.18 | ^3.5.26 | ISC | |
| 1.0.16 | ^3.5.26 | ISC | |
| 1.0.14 | ^3.5.26 | ISC | |
| 1.0.12 | ^3.5.26 | ISC | |
| 1.0.10 | ^3.5.26 | ISC | |
| 1.0.7 | ^3.5.26 | ISC | |
| 1.0.5 | ^3.5.26 | ISC | |
| 0.2.0 | ^3.5.26 | ISC |