morphicons 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -7
- package/dist/vue.d.ts +121 -0
- package/dist/vue.js +158 -0
- package/package.json +25 -4
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ The usual icon morphs either interpolate raw coordinates (shapes shrink and shea
|
|
|
36
36
|
bun add morphicons # or npm install / pnpm add
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
ESM only. `react`
|
|
39
|
+
ESM only. `react` (>= 18) and `vue` (>= 3.3) are optional peers — only needed for `morphicons/react` and `morphicons/vue`.
|
|
40
40
|
|
|
41
41
|
## Usage
|
|
42
42
|
|
|
@@ -60,6 +60,34 @@ ref.current?.set(X); // jumps without animating
|
|
|
60
60
|
|
|
61
61
|
Drop-in replacement for lucide-react: `size`, `strokeWidth`, `absoluteStrokeWidth`, `color`, `className` and the rest of the `<svg>` props pass straight through. Correct accessibility by default: `aria-hidden` unless you pass `label` (→ `role="img"` + `<title>`). Clean SSR: the server emits the exact static SVG (zero flash, zero layout shift); the runtime is born on hydration. `prefers-reduced-motion` degrades to an instant swap.
|
|
62
62
|
|
|
63
|
+
### Vue — same three modes
|
|
64
|
+
|
|
65
|
+
```vue
|
|
66
|
+
<script setup lang="ts">
|
|
67
|
+
import { ref } from "vue";
|
|
68
|
+
import { MorphIcon, type MorphHandle } from "morphicons/vue";
|
|
69
|
+
import { Menu, X, Check } from "lucide"; // data, not components
|
|
70
|
+
|
|
71
|
+
const open = ref(false);
|
|
72
|
+
const morph = ref<MorphHandle | null>(null);
|
|
73
|
+
// morph.value?.morphTo(Check) → animates
|
|
74
|
+
// morph.value?.set(X) → jumps without animating
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<template>
|
|
78
|
+
<!-- 1. Uncontrolled (90% of uses): change the prop and morphicons animates -->
|
|
79
|
+
<MorphIcon :icon="open ? X : Menu" spring="snappy" />
|
|
80
|
+
|
|
81
|
+
<!-- 2. Controlled (gestures, scroll): explicit progress, no spring -->
|
|
82
|
+
<MorphIcon :from="Menu" :to="X" :progress="dragProgress" />
|
|
83
|
+
|
|
84
|
+
<!-- 3. Imperative (sequences): template ref → morphTo / set -->
|
|
85
|
+
<MorphIcon ref="morph" :icon="Menu" />
|
|
86
|
+
</template>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Same surface as the React binding: presentation props (`size`, `strokeWidth`, `absoluteStrokeWidth`, `color`; `class`, `style` and the rest of the `<svg>` attrs fall through), the same accessibility defaults (`aria-hidden` unless you pass `label`) and the same clean SSR — works with Nuxt out of the box: the server emits the exact static SVG and the runtime is born on hydration. The binding is a plain render function; no SFC compiler or JSX involved.
|
|
90
|
+
|
|
63
91
|
### Vanilla (no React)
|
|
64
92
|
|
|
65
93
|
```ts
|
|
@@ -103,7 +131,7 @@ morphicons has no per-library adapters — any icon set that meets these require
|
|
|
103
131
|
const bell = fitIcon(teenySmallBell, 15); // also "0 0 15 15" or [0, 0, 15, 15]
|
|
104
132
|
```
|
|
105
133
|
|
|
106
|
-
It returns a plain `d`, so it goes anywhere an icon is accepted. Call it at module scope, not per render. Skipping it doesn't throw — Procrustes is similarity-invariant, so the grid mismatch never reads as false rotation; it lands in σ as an unwanted zoom, and the target draws outside the canvas. The React
|
|
134
|
+
It returns a plain `d`, so it goes anywhere an icon is accepted. Call it at module scope, not per render. Skipping it doesn't throw — Procrustes is similarity-invariant, so the grid mismatch never reads as false rotation; it lands in σ as an unwanted zoom, and the target draws outside the canvas. The React and Vue bindings default to `viewBox="0 0 24 24"`, overridable via props.
|
|
107
135
|
4. **Uniform stroke.** Cosmetic rather than structural: a consistent stroke width and round caps/joins make in-flight shapes look native. These live on the `<svg>`, not in morphicons.
|
|
108
136
|
|
|
109
137
|
Beyond the libraries in the playground, sets known to qualify on the 24×24 grid — no fitting needed: **Heroicons** (outline style), **Iconoir** (1.5px stroke), **Akar Icons**, **Untitled UI** and **Hugeicons** (stroke style). Off-grid packs work through `fitIcon`: **Teenyicons** (15×15), **Carbon** (32×32), **Heroicons solid** (20×20).
|
|
@@ -114,7 +142,7 @@ This also covers the [shadcn registry](https://www.shadcn.io/icons), which re-pu
|
|
|
114
142
|
|
|
115
143
|
```
|
|
116
144
|
┌─────────────────────────────────────────────┐
|
|
117
|
-
│ bindings react
|
|
145
|
+
│ bindings react · vue │ thin: ref + createMorph
|
|
118
146
|
├─────────────────────────────────────────────┤
|
|
119
147
|
│ drivers dom (setAttribute + rAF) │ singleton scheduler
|
|
120
148
|
├─────────────────────────────────────────────┤
|
|
@@ -125,7 +153,7 @@ This also covers the [shadcn registry](https://www.shadcn.io/icons), which re-pu
|
|
|
125
153
|
└─────────────────────────────────────────────┘
|
|
126
154
|
```
|
|
127
155
|
|
|
128
|
-
The hard rule: **the core never touches the DOM**. Pure functions consume icon data and produce `d` strings. Direct consequence: a React Native driver over `react-native-svg` + Reanimated is just another adapter, not a rewrite. One package with subpath exports (`.` core, `./dom`, `./react`), ESM only, `sideEffects: false`.
|
|
156
|
+
The hard rule: **the core never touches the DOM**. Pure functions consume icon data and produce `d` strings. Direct consequence: a React Native driver over `react-native-svg` + Reanimated is just another adapter, not a rewrite. One package with subpath exports (`.` core, `./dom`, `./react`, `./vue`), ESM only, `sideEffects: false`.
|
|
129
157
|
|
|
130
158
|
The plan is the central artifact:
|
|
131
159
|
|
|
@@ -266,6 +294,7 @@ CI budget (size-limit, gzip) as an anti-regression tripwire — gates carry ~10%
|
|
|
266
294
|
| `morphicons` (core) | 6.60 KB | 7 KB |
|
|
267
295
|
| `morphicons/dom` (core + driver) | 7.04 KB | 7.5 KB |
|
|
268
296
|
| `morphicons/react` (all, react external) | 7.77 KB | 8.5 KB |
|
|
297
|
+
| `morphicons/vue` (all, vue external) | 7.81 KB | 8.5 KB |
|
|
269
298
|
|
|
270
299
|
## Playground
|
|
271
300
|
|
|
@@ -278,15 +307,27 @@ bun run play # → http://localhost:3000
|
|
|
278
307
|
## Development
|
|
279
308
|
|
|
280
309
|
```bash
|
|
281
|
-
bun test #
|
|
282
|
-
bun run typecheck # strict ×
|
|
310
|
+
bun test # 92 tests / ~13,500 asserts
|
|
311
|
+
bun run typecheck # strict ×4: core+dom without lib DOM, playground, react, vue
|
|
283
312
|
bun run format # biome
|
|
284
|
-
bun run build # tsdown → dist/ (entries index, dom, react)
|
|
313
|
+
bun run build # tsdown → dist/ (entries index, dom, react, vue)
|
|
285
314
|
bun run size # size gates
|
|
286
315
|
```
|
|
287
316
|
|
|
288
317
|
Icons shown in the playground belong to their authors: [Lucide](https://lucide.dev) (ISC), [Feather](https://feathericons.com) (MIT), [Tabler](https://tabler.io/icons) (MIT).
|
|
289
318
|
|
|
319
|
+
## Star history
|
|
320
|
+
|
|
321
|
+
<p align="center">
|
|
322
|
+
<a href="https://star-history.com/#guillermolg00/morphicons&Date">
|
|
323
|
+
<picture>
|
|
324
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=guillermolg00/morphicons&type=Date&theme=dark">
|
|
325
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=guillermolg00/morphicons&type=Date">
|
|
326
|
+
<img alt="Star history chart of morphicons" src="https://api.star-history.com/svg?repos=guillermolg00/morphicons&type=Date" width="640">
|
|
327
|
+
</picture>
|
|
328
|
+
</a>
|
|
329
|
+
</p>
|
|
330
|
+
|
|
290
331
|
---
|
|
291
332
|
|
|
292
333
|
MIT © [Guillermo](https://guillermolg.com) — made by [guillermolg.com](https://guillermolg.com)
|
package/dist/vue.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { a as Sampled, c as SpringPreset, n as IconInput, r as IconNode } from "./types-JAF3s76Y.js";
|
|
2
|
+
import { Morph, MorphOptions, PathEl } from "./dom.js";
|
|
3
|
+
import { PropType } from "vue";
|
|
4
|
+
//#region src/vue/index.d.ts
|
|
5
|
+
/** Imperative surface exposed on the component instance (template ref). */
|
|
6
|
+
interface MorphHandle {
|
|
7
|
+
morphTo(icon: IconInput, spring?: SpringPreset | MorphOptions): void;
|
|
8
|
+
set(icon: IconInput): void;
|
|
9
|
+
}
|
|
10
|
+
declare const MorphIcon: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
11
|
+
/** Uncontrolled mode: the current icon; changing the prop animates. */
|
|
12
|
+
icon: {
|
|
13
|
+
type: PropType<IconInput>;
|
|
14
|
+
default: undefined;
|
|
15
|
+
};
|
|
16
|
+
/** Controlled mode: source endpoint of the pair. */
|
|
17
|
+
from: {
|
|
18
|
+
type: PropType<IconInput>;
|
|
19
|
+
default: undefined;
|
|
20
|
+
};
|
|
21
|
+
/** Controlled mode: target endpoint of the pair. */
|
|
22
|
+
to: {
|
|
23
|
+
type: PropType<IconInput>;
|
|
24
|
+
default: undefined;
|
|
25
|
+
};
|
|
26
|
+
/** Controlled mode: 0..1 progress of the frozen morph (no spring). */
|
|
27
|
+
progress: {
|
|
28
|
+
type: NumberConstructor;
|
|
29
|
+
default: undefined;
|
|
30
|
+
};
|
|
31
|
+
/** Physics for uncontrolled/imperative mode: preset or custom spring. */
|
|
32
|
+
spring: {
|
|
33
|
+
type: PropType<SpringPreset | MorphOptions>;
|
|
34
|
+
default: undefined;
|
|
35
|
+
};
|
|
36
|
+
size: {
|
|
37
|
+
type: (NumberConstructor | StringConstructor)[];
|
|
38
|
+
default: number;
|
|
39
|
+
};
|
|
40
|
+
color: {
|
|
41
|
+
type: StringConstructor;
|
|
42
|
+
default: string;
|
|
43
|
+
};
|
|
44
|
+
strokeWidth: {
|
|
45
|
+
type: (NumberConstructor | StringConstructor)[];
|
|
46
|
+
default: number;
|
|
47
|
+
};
|
|
48
|
+
/** Like lucide: stroke width does not scale with `size`. */
|
|
49
|
+
absoluteStrokeWidth: {
|
|
50
|
+
type: BooleanConstructor;
|
|
51
|
+
default: boolean;
|
|
52
|
+
};
|
|
53
|
+
/** Accessibility: with label → role="img" + <title>; without → aria-hidden. */
|
|
54
|
+
label: {
|
|
55
|
+
type: StringConstructor;
|
|
56
|
+
default: undefined;
|
|
57
|
+
};
|
|
58
|
+
}>, () => import("vue").VNode<import("vue").RendererNode, import("vue").RendererElement, {
|
|
59
|
+
[key: string]: any;
|
|
60
|
+
}>, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
|
|
61
|
+
/** Uncontrolled mode: the current icon; changing the prop animates. */
|
|
62
|
+
icon: {
|
|
63
|
+
type: PropType<IconInput>;
|
|
64
|
+
default: undefined;
|
|
65
|
+
};
|
|
66
|
+
/** Controlled mode: source endpoint of the pair. */
|
|
67
|
+
from: {
|
|
68
|
+
type: PropType<IconInput>;
|
|
69
|
+
default: undefined;
|
|
70
|
+
};
|
|
71
|
+
/** Controlled mode: target endpoint of the pair. */
|
|
72
|
+
to: {
|
|
73
|
+
type: PropType<IconInput>;
|
|
74
|
+
default: undefined;
|
|
75
|
+
};
|
|
76
|
+
/** Controlled mode: 0..1 progress of the frozen morph (no spring). */
|
|
77
|
+
progress: {
|
|
78
|
+
type: NumberConstructor;
|
|
79
|
+
default: undefined;
|
|
80
|
+
};
|
|
81
|
+
/** Physics for uncontrolled/imperative mode: preset or custom spring. */
|
|
82
|
+
spring: {
|
|
83
|
+
type: PropType<SpringPreset | MorphOptions>;
|
|
84
|
+
default: undefined;
|
|
85
|
+
};
|
|
86
|
+
size: {
|
|
87
|
+
type: (NumberConstructor | StringConstructor)[];
|
|
88
|
+
default: number;
|
|
89
|
+
};
|
|
90
|
+
color: {
|
|
91
|
+
type: StringConstructor;
|
|
92
|
+
default: string;
|
|
93
|
+
};
|
|
94
|
+
strokeWidth: {
|
|
95
|
+
type: (NumberConstructor | StringConstructor)[];
|
|
96
|
+
default: number;
|
|
97
|
+
};
|
|
98
|
+
/** Like lucide: stroke width does not scale with `size`. */
|
|
99
|
+
absoluteStrokeWidth: {
|
|
100
|
+
type: BooleanConstructor;
|
|
101
|
+
default: boolean;
|
|
102
|
+
};
|
|
103
|
+
/** Accessibility: with label → role="img" + <title>; without → aria-hidden. */
|
|
104
|
+
label: {
|
|
105
|
+
type: StringConstructor;
|
|
106
|
+
default: undefined;
|
|
107
|
+
};
|
|
108
|
+
}>> & Readonly<{}>, {
|
|
109
|
+
icon: IconInput;
|
|
110
|
+
from: IconInput;
|
|
111
|
+
to: IconInput;
|
|
112
|
+
progress: number;
|
|
113
|
+
spring: "bouncy" | "smooth" | "snappy" | MorphOptions;
|
|
114
|
+
size: string | number;
|
|
115
|
+
color: string;
|
|
116
|
+
strokeWidth: string | number;
|
|
117
|
+
absoluteStrokeWidth: boolean;
|
|
118
|
+
label: string;
|
|
119
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
120
|
+
//#endregion
|
|
121
|
+
export { type IconInput, type IconNode, type Morph, MorphHandle, MorphIcon, type MorphOptions, type PathEl, type Sampled, type SpringPreset };
|
package/dist/vue.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { a as buildPlan, f as interpPolar, l as serialize, r as resampleIcon, u as allocOutputs } from "./spring-BTcHiHR5.js";
|
|
2
|
+
import { canonicalD, createMorph } from "./dom.js";
|
|
3
|
+
import { defineComponent, h, onBeforeUnmount, onMounted, shallowRef, watch } from "vue";
|
|
4
|
+
//#region src/vue/index.ts
|
|
5
|
+
/** Frozen shape of the from→to pair at t, using the pure core (SSR-safe).
|
|
6
|
+
* At exact endpoints returns the canonical `d` (real curves, not polyline). */
|
|
7
|
+
function frozenD(from, to, t) {
|
|
8
|
+
if (t <= 0) return canonicalD(from);
|
|
9
|
+
if (t >= 1) return canonicalD(to);
|
|
10
|
+
const plan = buildPlan(resampleIcon(from), resampleIcon(to));
|
|
11
|
+
const out = allocOutputs(plan);
|
|
12
|
+
interpPolar(plan, t, out);
|
|
13
|
+
return serialize(out, plan.items.map((it) => it.closed));
|
|
14
|
+
}
|
|
15
|
+
const MorphIcon = defineComponent({
|
|
16
|
+
name: "MorphIcon",
|
|
17
|
+
props: {
|
|
18
|
+
/** Uncontrolled mode: the current icon; changing the prop animates. */
|
|
19
|
+
icon: {
|
|
20
|
+
type: [String, Array],
|
|
21
|
+
default: void 0
|
|
22
|
+
},
|
|
23
|
+
/** Controlled mode: source endpoint of the pair. */
|
|
24
|
+
from: {
|
|
25
|
+
type: [String, Array],
|
|
26
|
+
default: void 0
|
|
27
|
+
},
|
|
28
|
+
/** Controlled mode: target endpoint of the pair. */
|
|
29
|
+
to: {
|
|
30
|
+
type: [String, Array],
|
|
31
|
+
default: void 0
|
|
32
|
+
},
|
|
33
|
+
/** Controlled mode: 0..1 progress of the frozen morph (no spring). */
|
|
34
|
+
progress: {
|
|
35
|
+
type: Number,
|
|
36
|
+
default: void 0
|
|
37
|
+
},
|
|
38
|
+
/** Physics for uncontrolled/imperative mode: preset or custom spring. */
|
|
39
|
+
spring: {
|
|
40
|
+
type: [String, Object],
|
|
41
|
+
default: void 0
|
|
42
|
+
},
|
|
43
|
+
size: {
|
|
44
|
+
type: [Number, String],
|
|
45
|
+
default: 24
|
|
46
|
+
},
|
|
47
|
+
color: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: "currentColor"
|
|
50
|
+
},
|
|
51
|
+
strokeWidth: {
|
|
52
|
+
type: [Number, String],
|
|
53
|
+
default: 2
|
|
54
|
+
},
|
|
55
|
+
/** Like lucide: stroke width does not scale with `size`. */
|
|
56
|
+
absoluteStrokeWidth: {
|
|
57
|
+
type: Boolean,
|
|
58
|
+
default: false
|
|
59
|
+
},
|
|
60
|
+
/** Accessibility: with label → role="img" + <title>; without → aria-hidden. */
|
|
61
|
+
label: {
|
|
62
|
+
type: String,
|
|
63
|
+
default: void 0
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
setup(props, { expose }) {
|
|
67
|
+
const initialD = (() => {
|
|
68
|
+
const { icon, from, to, progress } = props;
|
|
69
|
+
if (from !== void 0 && to !== void 0) return frozenD(from, to, progress ?? 0);
|
|
70
|
+
const first = icon ?? from ?? to;
|
|
71
|
+
return first !== void 0 ? canonicalD(first) : "";
|
|
72
|
+
})();
|
|
73
|
+
const pathEl = shallowRef(null);
|
|
74
|
+
let morph = null;
|
|
75
|
+
let based = false;
|
|
76
|
+
let pair = null;
|
|
77
|
+
onMounted(() => {
|
|
78
|
+
const el = pathEl.value;
|
|
79
|
+
const { icon, from, to, progress } = props;
|
|
80
|
+
const controlled = from !== void 0 && to !== void 0;
|
|
81
|
+
const initialIcon = icon ?? from ?? to;
|
|
82
|
+
if (!el || initialIcon === void 0) return;
|
|
83
|
+
const m = createMorph(el, controlled ? from : initialIcon);
|
|
84
|
+
morph = m;
|
|
85
|
+
if (controlled) {
|
|
86
|
+
pair = [from, to];
|
|
87
|
+
const t = progress ?? 0;
|
|
88
|
+
if (t <= 0) m.set(from);
|
|
89
|
+
else if (t >= 1) m.set(to);
|
|
90
|
+
else {
|
|
91
|
+
m.seek(to, t);
|
|
92
|
+
based = true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
onBeforeUnmount(() => {
|
|
97
|
+
morph?.destroy();
|
|
98
|
+
morph = null;
|
|
99
|
+
based = false;
|
|
100
|
+
pair = null;
|
|
101
|
+
});
|
|
102
|
+
watch(() => props.icon, (icon) => {
|
|
103
|
+
if (icon !== void 0) morph?.morphTo(icon, props.spring);
|
|
104
|
+
});
|
|
105
|
+
watch(() => [
|
|
106
|
+
props.from,
|
|
107
|
+
props.to,
|
|
108
|
+
props.progress
|
|
109
|
+
], () => {
|
|
110
|
+
const m = morph;
|
|
111
|
+
const { from, to, progress } = props;
|
|
112
|
+
if (!m || from === void 0 || to === void 0) return;
|
|
113
|
+
const t = progress ?? 0;
|
|
114
|
+
if (!pair || pair[0] !== from || pair[1] !== to) {
|
|
115
|
+
pair = [from, to];
|
|
116
|
+
based = false;
|
|
117
|
+
}
|
|
118
|
+
if (t <= 0) {
|
|
119
|
+
m.set(from);
|
|
120
|
+
based = false;
|
|
121
|
+
} else if (t >= 1) {
|
|
122
|
+
m.set(to);
|
|
123
|
+
based = false;
|
|
124
|
+
} else {
|
|
125
|
+
if (!based) {
|
|
126
|
+
m.set(from);
|
|
127
|
+
based = true;
|
|
128
|
+
}
|
|
129
|
+
m.seek(to, t);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
expose({
|
|
133
|
+
morphTo: (i, s) => morph?.morphTo(i, s ?? props.spring),
|
|
134
|
+
set: (i) => morph?.set(i)
|
|
135
|
+
});
|
|
136
|
+
return () => {
|
|
137
|
+
const sw = props.absoluteStrokeWidth ? Number(props.strokeWidth) * 24 / Number(props.size) : props.strokeWidth;
|
|
138
|
+
return h("svg", {
|
|
139
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
140
|
+
width: props.size,
|
|
141
|
+
height: props.size,
|
|
142
|
+
viewBox: "0 0 24 24",
|
|
143
|
+
fill: "none",
|
|
144
|
+
stroke: props.color,
|
|
145
|
+
"stroke-width": sw,
|
|
146
|
+
"stroke-linecap": "round",
|
|
147
|
+
"stroke-linejoin": "round",
|
|
148
|
+
role: props.label ? "img" : void 0,
|
|
149
|
+
"aria-hidden": props.label ? void 0 : "true"
|
|
150
|
+
}, [props.label ? h("title", props.label) : null, h("path", {
|
|
151
|
+
ref: pathEl,
|
|
152
|
+
d: initialD
|
|
153
|
+
})]);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
//#endregion
|
|
158
|
+
export { MorphIcon };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "morphicons",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Universal morphing for stroke-based icons with spring physics — zero runtime dependencies",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Guillermo (https://guillermolg.com)",
|
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
"shadcn",
|
|
30
30
|
"feather",
|
|
31
31
|
"react",
|
|
32
|
+
"vue",
|
|
33
|
+
"lucide-vue-next",
|
|
32
34
|
"icon-animation"
|
|
33
35
|
],
|
|
34
36
|
"type": "module",
|
|
@@ -48,14 +50,22 @@
|
|
|
48
50
|
"./react": {
|
|
49
51
|
"types": "./dist/react.d.ts",
|
|
50
52
|
"default": "./dist/react.js"
|
|
53
|
+
},
|
|
54
|
+
"./vue": {
|
|
55
|
+
"types": "./dist/vue.d.ts",
|
|
56
|
+
"default": "./dist/vue.js"
|
|
51
57
|
}
|
|
52
58
|
},
|
|
53
59
|
"peerDependencies": {
|
|
54
|
-
"react": ">=18"
|
|
60
|
+
"react": ">=18",
|
|
61
|
+
"vue": ">=3.3"
|
|
55
62
|
},
|
|
56
63
|
"peerDependenciesMeta": {
|
|
57
64
|
"react": {
|
|
58
65
|
"optional": true
|
|
66
|
+
},
|
|
67
|
+
"vue": {
|
|
68
|
+
"optional": true
|
|
59
69
|
}
|
|
60
70
|
},
|
|
61
71
|
"files": [
|
|
@@ -63,7 +73,7 @@
|
|
|
63
73
|
],
|
|
64
74
|
"scripts": {
|
|
65
75
|
"test": "bun test",
|
|
66
|
-
"typecheck": "tsc --noEmit && tsc -p playground --noEmit && tsc -p tsconfig.react.json --noEmit",
|
|
76
|
+
"typecheck": "tsc --noEmit && tsc -p playground --noEmit && tsc -p tsconfig.react.json --noEmit && tsc -p tsconfig.vue.json --noEmit",
|
|
67
77
|
"play": "bun ./playground/index.html",
|
|
68
78
|
"lint": "biome check .",
|
|
69
79
|
"format": "biome check --write .",
|
|
@@ -95,6 +105,16 @@
|
|
|
95
105
|
],
|
|
96
106
|
"limit": "8.5 KB",
|
|
97
107
|
"gzip": true
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"name": "core + dom + vue (MorphIcon, vue external)",
|
|
111
|
+
"path": "dist/vue.js",
|
|
112
|
+
"import": "*",
|
|
113
|
+
"ignore": [
|
|
114
|
+
"vue"
|
|
115
|
+
],
|
|
116
|
+
"limit": "8.5 KB",
|
|
117
|
+
"gzip": true
|
|
98
118
|
}
|
|
99
119
|
],
|
|
100
120
|
"devDependencies": {
|
|
@@ -110,6 +130,7 @@
|
|
|
110
130
|
"react-dom": "^19.2.8",
|
|
111
131
|
"size-limit": "^13.0.3",
|
|
112
132
|
"tsdown": "^0.22.14",
|
|
113
|
-
"typescript": "^7.0.2"
|
|
133
|
+
"typescript": "^7.0.2",
|
|
134
|
+
"vue": "^3.5.40"
|
|
114
135
|
}
|
|
115
136
|
}
|