dev-copy-wrap
v1.0.7
Published
> Vue 3 developer utility component — wrap any component to instantly copy its usage code to clipboard.
Downloads
1,050
Readme
DevCopyWrap
Vue 3 developer utility component — wrap any component to instantly copy its usage code to clipboard.
What is this?
DevCopyWrap is a developer-only wrapper component. Place it around any component in your dev environment — hover to reveal a badge, click to copy ready-to-paste Vue template code to your clipboard.
It automatically:
- detects the component name from the slot vnode
- reads props passed to the inner component
- filters out event handlers, reactive internals, and Vue-specific bindings
- chooses the right format —
:data="{...}"for data-prop components, full attribute syntax for everything else
No configuration required for the basic use case.
Installation
npm install dev-copy-wrapyarn add dev-copy-wrappnpm add dev-copy-wrapPeer dependency: Vue 3.x must be installed in your project.
Setup
Global registration (recommended)
Register once in main.ts and use anywhere without imports:
// main.ts
import { createApp } from 'vue'
import { DevCopyWrap } from 'dev-copy-wrap'
import App from './App.vue'
const app = createApp(App)
app.component('DevCopyWrap', DevCopyWrap)
app.mount('#app')Local registration
<script setup lang="ts">
import { DevCopyWrap } from 'dev-copy-wrap'
</script>Dev-only setup (recommended for production builds)
Since this is a development utility, you should exclude it from production builds:
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
if (import.meta.env.DEV) {
import('dev-copy-wrap').then(({ DevCopyWrap }) => {
app.component('DevCopyWrap', DevCopyWrap)
})
}
app.mount('#app')Or with a no-op stub for production:
// plugins/devtools.ts
import type { App } from 'vue'
export function installDevTools(app: App) {
if (!import.meta.env.DEV) return
import('dev-copy-wrap').then(({ DevCopyWrap }) => {
app.component('DevCopyWrap', DevCopyWrap)
})
}// main.ts
import { installDevTools } from './plugins/devtools'
const app = createApp(App)
installDevTools(app)
app.mount('#app')Basic usage
Just wrap any component — DevCopyWrap does the rest:
<DevCopyWrap>
<CardsProduct :data="card" />
</DevCopyWrap>Hover over the component → a </> badge appears in the top-right corner.
Click → copied to clipboard → badge turns ✓.
How format is chosen automatically
DevCopyWrap inspects the vnode of its slot content and decides the output format:
| Inner component props | Auto format | Output |
|---|---|---|
| Single :data="..." prop | data | :data="{...}" inline object |
| Multiple props (label, disabled, etc.) | template | Full attribute per line |
| No props | template | Self-closing tag |
Output examples
Component with a single data prop
<!-- Usage -->
<DevCopyWrap>
<CardsProduct :data="card" />
</DevCopyWrap>Copied result:
<CardsProduct :data="{
to: '/product',
title: 'Творог 5%',
description: 'Рассыпчатый творог...',
imageSrc: '/images/card.png',
imageAlt: 'card',
size: 'large',
tags: [
{
type: 'blue',
text: 'Хит продаж'
},
{
type: 'white',
text: 'Идеально для сырников'
}
],
volume: '180гр'
}" />Component with multiple props
<!-- Usage -->
<DevCopyWrap>
<UiUpload
v-model="document"
accept=".pdf,.doc,.docx"
:max-size="10 * 1024 * 1024"
:disabled="isUploading"
label="Документ"
hint="Поддерживаемые форматы: PDF, DOC, DOCX"
@change="handleDocumentChange"
@error="handleUploadError"
/>
</DevCopyWrap>Copied result (event handlers and v-model internals are automatically stripped):
<UiUpload
accept=".pdf,.doc,.docx"
:max-size="10485760"
:disabled="false"
label="Документ"
hint="Поддерживаемые форматы: PDF, DOC, DOCX"
/>List of components
<DevCopyWrap v-for="card in cards" :key="card.id">
<CardsProduct :data="card" />
</DevCopyWrap>Each card gets its own copy button with its own data — no extra configuration.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| code | string | — | Raw string to copy as-is. Bypasses all auto-detection. |
| componentName | string | auto | Override the component name in the output. |
| data | any | auto | Override the data object. Used as :data value in output. |
| format | 'auto' \| 'data' \| 'template' | 'auto' | Force a specific output format. |
Format override
format="data" — force :data="{...}" output
<DevCopyWrap format="data">
<UiCard title="Hello" :count="5" />
</DevCopyWrap><!-- Result -->
<UiCard :data="{
title: 'Hello',
count: 5
}" />format="template" — force full attribute output
<DevCopyWrap format="template">
<CardsProduct :data="card" />
</DevCopyWrap><!-- Result -->
<CardsProduct
:data="{
title: 'Творог 5%',
...
}"
/>code — copy arbitrary text
Useful for snippets, import lines, or anything that isn't a component:
<DevCopyWrap code="import { CardsProduct } from '@/components/cards'">
<CardsProduct :data="card" />
</DevCopyWrap>componentName — override detected name
<DevCopyWrap component-name="MyCard">
<CardsProduct :data="card" />
</DevCopyWrap>data — override detected data
<DevCopyWrap :data="{ title: 'Custom', size: 'large' }">
<CardsProduct :data="card" />
</DevCopyWrap>What gets filtered out automatically
DevCopyWrap reads props from the vnode at runtime and strips:
| Category | Examples | Reason |
|---|---|---|
| Event listeners | onChange, onError, onClick | Functions, not serializable |
| v-model internals | modelValue, onUpdate:modelValue | Runtime binding |
| Vue internals | key, ref, class, style | Not component props |
| Reactive objects | Vue Ref, Reactive instances | Can't be serialized to static code |
| Functions | Any () => {} value | Not representable as static template |
Only plain serializable values are kept: string, number, boolean, null, plain arrays and plain objects.
Composable
If you need the copy logic separately, you can import the composable directly:
import { useCopyCode } from 'dev-copy-wrap'
const { copy, copiedKey } = useCopyCode()
// copy(text, uniqueKey)
copy('const x = 1', 'my-snippet')
// copiedKey — Ref<string | null>, holds the key of the last copied itemStyling
The component uses scoped styles and doesn't affect your layout. It wraps the slot in an inline-flex container.
Default behavior
- Dashed outline appears on hover (
#93c5fd— blue) - Outline turns green on copy (
#4ade80) </>badge appears top-right on hover, turns✓after copy
Overriding styles
The component exposes CSS classes you can target globally:
/* In your global CSS or the parent component without scoped */
.dev-copy-wrap {
/* wrapper */
}
.dev-copy-wrap:hover {
/* hover state */
}
.dev-copy-wrap--copied {
/* after copy */
}
.dev-copy-wrap__badge {
/* the </> badge */
}Example — make the badge larger and reposition it:
.dev-copy-wrap__badge {
font-size: 11px;
top: -12px;
right: -12px;
padding: 3px 6px;
}TypeScript
The package ships with full TypeScript declarations. Props are typed:
interface DevCopyWrapProps {
code?: string
componentName?: string
data?: any
format?: 'auto' | 'data' | 'template'
}Limitations
| Limitation | Details |
|---|---|
| Slot must have a single root element | Only the first vnode in the slot is inspected |
| Dynamic prop values become static | :max-size="10 * 1024 * 1024" becomes :max-size="10485760" |
| v-model is stripped | The bound variable is not recoverable at runtime |
| Functional components | __name may not be available; use component-name override |
| Deeply nested reactive data | Refs/Reactives inside plain objects may be missed; use :data override |
Recommended project setup
For a component library or design system, add DevCopyWrap to your dev storybook/sandbox layout globally so every component preview is instantly copyable:
<!-- layouts/DevLayout.vue -->
<script setup lang="ts">
// DevCopyWrap is registered globally in dev mode
</script>
<template>
<div class="dev-layout">
<slot />
</div>
</template><!-- pages/sandbox/cards.vue -->
<template>
<div class="grid">
<DevCopyWrap v-for="card in mockCards" :key="card.id">
<CardsProduct :data="card" />
</DevCopyWrap>
</div>
</template>Changelog
1.0.0
- Initial release
- Auto-detection of component name and props from slot vnode
- Automatic format selection (
datavstemplate) - Filtering of event handlers and Vue internals
format,code,data,componentNameprop overridesuseCopyCodecomposable export
License
MIT © your-name
