wissive 0.1.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/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "wissive",
3
+ "version": "0.1.0",
4
+ "description": "Micro-librería de JavaScript/TypeScript de emojis vivos reactivos con física de resorte",
5
+ "type": "module",
6
+ "main": "./dist/wissive.cjs",
7
+ "module": "./dist/wissive.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/wissive.js",
13
+ "require": "./dist/wissive.cjs"
14
+ },
15
+ "./react": {
16
+ "types": "./dist/react.d.ts",
17
+ "import": "./dist/react.js",
18
+ "require": "./dist/react.cjs"
19
+ },
20
+ "./vue": {
21
+ "types": "./dist/vue.d.ts",
22
+ "import": "./dist/vue.js",
23
+ "require": "./dist/vue.cjs"
24
+ },
25
+ "./astro": "./src/astro/Wissive.astro"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "src/astro"
30
+ ],
31
+ "sideEffects": false,
32
+ "keywords": [
33
+ "emoji",
34
+ "animation",
35
+ "spring-physics",
36
+ "interactive",
37
+ "svg",
38
+ "typescript"
39
+ ],
40
+ "license": "MIT",
41
+ "devDependencies": {
42
+ "@types/react": "^19.2.18",
43
+ "astro": "^7.2.2",
44
+ "react": "^19.2.8",
45
+ "typescript": "^5.4.0",
46
+ "vite": "^5.2.0",
47
+ "vite-plugin-dts": "^3.8.0",
48
+ "vue": "^3.5.41"
49
+ },
50
+ "peerDependencies": {
51
+ "astro": "*",
52
+ "cuelume": "*",
53
+ "react": "*",
54
+ "vue": "*"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "astro": {
58
+ "optional": true
59
+ },
60
+ "cuelume": {
61
+ "optional": true
62
+ },
63
+ "react": {
64
+ "optional": true
65
+ },
66
+ "vue": {
67
+ "optional": true
68
+ }
69
+ },
70
+ "scripts": {
71
+ "build": "tsc && vite build && vite build --config vite.umd.config.ts",
72
+ "check:spring": "node --experimental-strip-types src/core/spring.check.ts",
73
+ "check:state": "node --experimental-strip-types src/core/state.check.ts",
74
+ "check:benchmark": "node --experimental-strip-types src/core/benchmark.check.ts",
75
+ "check:motion": "node --experimental-strip-types src/core/motion.check.ts",
76
+ "check:sequence": "node --experimental-strip-types src/core/sequence.check.ts",
77
+ "check:particles": "node --experimental-strip-types src/render/particles.check.ts",
78
+ "check:accessories": "node --experimental-strip-types src/render/accessories.check.ts",
79
+ "check:knot": "node --experimental-strip-types src/render/knot.check.ts",
80
+ "check:custom": "node --experimental-strip-types src/emojis/custom.check.ts",
81
+ "check:listeners": "node --experimental-strip-types src/events/listeners.check.ts",
82
+ "sheet": "node --experimental-strip-types scripts/contact-sheet.ts",
83
+ "check": "pnpm run check:spring && pnpm run check:state && pnpm run check:benchmark && pnpm run check:motion && pnpm run check:sequence && pnpm run check:particles && pnpm run check:accessories && pnpm run check:knot && pnpm run check:custom && pnpm run check:listeners && tsc --noEmit",
84
+ "preview": "vite preview"
85
+ }
86
+ }
@@ -0,0 +1,79 @@
1
+ ---
2
+ // Wrapper oficial para Astro — `import Wissive from 'wissive/astro'`.
3
+ // Export default, no nombrado: así es como Astro compila el template de un
4
+ // .astro (no hay forma de darle un export nombrado tipo React/Vue).
5
+ //
6
+ // A diferencia de react.tsx/vue.ts, esto no resuelve un problema de timing
7
+ // (Astro no tiene virtual DOM: el <script> de abajo ya corre client-side
8
+ // sin ceremonia, como en examples/astro/wissive-demo.astro). Resuelve dos
9
+ // cosas: repetición (no copiar el <script> en cada página) y el hueco
10
+ // vacío mientras carga el JS — renderiza el primer frame en el server.
11
+ // Import por nombre de paquete, no relativo: este .astro se publica como
12
+ // fuente sin compilar (Astro no tiene un target de build tipo Vite lib acá),
13
+ // así que solo empaquetamos este archivo — no todo src/ — y confiamos en
14
+ // que el consumidor ya tiene 'wissive' resuelto en su propio node_modules.
15
+ import type { WissiveOptions } from 'wissive';
16
+ import { getEmojiDefinition, buildFace, resolveSize } from 'wissive';
17
+
18
+ export interface Props extends Omit<WissiveOptions, 'target'> {
19
+ name: string;
20
+ }
21
+
22
+ const { name, ...options } = Astro.props;
23
+
24
+ // Primer frame renderizado en el server (buildFace es una función pura,
25
+ // sin document/window — corre en Node sin problema). Es una aproximación:
26
+ // usa la variante [0] del pool de idle, no la que el cliente sortea al
27
+ // montar, y sin el wobble de personalidad (eso depende de idleTime, que
28
+ // solo existe una vez arranca el loop de animación). Alcanza para evitar
29
+ // el hueco vacío y el salto de layout — no hace falta que sea pixel-exacto,
30
+ // createEmoji() reemplaza este frame apenas pinta el suyo (ver script).
31
+ const def = getEmojiDefinition(name);
32
+ const size = resolveSize(options.size);
33
+ const initialParams = def.expressions.idle[0];
34
+ const ssrSvg = buildFace(def.silhouette, def.baseColor, initialParams, size, {}, 0);
35
+ ---
36
+ <div class="wissive-wrap" style={`width:${size}px;height:${size}px`}>
37
+ <div class="wissive-ssr" set:html={ssrSvg} />
38
+ <div class="wissive-slot" data-name={name} data-options={JSON.stringify(options)}></div>
39
+ </div>
40
+
41
+ <script>
42
+ import { createEmoji, type WissiveInstance } from 'wissive';
43
+
44
+ function initSlots(root: ParentNode = document) {
45
+ root.querySelectorAll<HTMLElement>('.wissive-slot:not([data-wissive-init])').forEach((slot) => {
46
+ slot.dataset.wissiveInit = 'true';
47
+ const name = slot.dataset.name!;
48
+ const options = JSON.parse(slot.dataset.options || '{}');
49
+ const instance: WissiveInstance = createEmoji(name, { target: slot, ...options });
50
+
51
+ // createEmoji tarda un requestAnimationFrame en pintar su primer
52
+ // frame real (sharedLoop.add corre en el próximo tick, no ahora
53
+ // mismo) — el doble rAF espera a que ese frame ya esté pintado antes
54
+ // de sacar el frame estático del server, así el swap no se nota.
55
+ const ssr = slot.parentElement?.querySelector<HTMLElement>('.wissive-ssr');
56
+ requestAnimationFrame(() => requestAnimationFrame(() => ssr?.remove()));
57
+
58
+ // View Transitions reemplaza el DOM sin recargar la página — sin
59
+ // esto, cada navegación deja el RAF y los listeners de la instancia
60
+ // anterior colgando.
61
+ document.addEventListener('astro:before-swap', () => instance.destroy(), { once: true });
62
+ });
63
+ }
64
+
65
+ initSlots();
66
+ document.addEventListener('astro:page-load', () => initSlots());
67
+ </script>
68
+
69
+ <style>
70
+ .wissive-wrap {
71
+ position: relative;
72
+ display: inline-block;
73
+ }
74
+ .wissive-ssr,
75
+ .wissive-slot {
76
+ position: absolute;
77
+ inset: 0;
78
+ }
79
+ </style>