@eduardoalvarez/arrecife 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.
Files changed (44) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/LICENSE +21 -0
  3. package/README.md +520 -0
  4. package/assets/brand/face-annoyed.png +0 -0
  5. package/assets/brand/face-confused.png +0 -0
  6. package/assets/brand/face-hearts.png +0 -0
  7. package/assets/brand/face-laughing.png +0 -0
  8. package/assets/brand/face-shades.png +0 -0
  9. package/assets/brand/face-waiting.png +0 -0
  10. package/assets/brand/face-wink.png +0 -0
  11. package/assets/brand/fin-foam.png +0 -0
  12. package/assets/brand/fin.png +0 -0
  13. package/assets/brand/pose-desk.png +0 -0
  14. package/assets/brand/pose-laptop-coffee.png +0 -0
  15. package/assets/brand/pose-peek.png +0 -0
  16. package/assets/brand/pose-surf.png +0 -0
  17. package/dist/brand/index.cjs +228 -0
  18. package/dist/brand/index.d.cts +63 -0
  19. package/dist/brand/index.d.ts +63 -0
  20. package/dist/brand/index.js +3 -0
  21. package/dist/catalogo-Du5ID-Hi.d.cts +77 -0
  22. package/dist/catalogo-Du5ID-Hi.d.ts +77 -0
  23. package/dist/chunk-22OXRTAL.js +22 -0
  24. package/dist/chunk-DHF63QNM.js +231 -0
  25. package/dist/chunk-E3OMP2DL.js +36 -0
  26. package/dist/chunk-ZL5X6XO7.js +102 -0
  27. package/dist/index.cjs +3191 -0
  28. package/dist/index.d.cts +1024 -0
  29. package/dist/index.d.ts +1024 -0
  30. package/dist/index.js +2624 -0
  31. package/dist/og/index.cjs +322 -0
  32. package/dist/og/index.d.cts +164 -0
  33. package/dist/og/index.d.ts +164 -0
  34. package/dist/og/index.js +242 -0
  35. package/dist/shiki/index.cjs +127 -0
  36. package/dist/shiki/index.d.cts +16 -0
  37. package/dist/shiki/index.d.ts +16 -0
  38. package/dist/shiki/index.js +95 -0
  39. package/dist/tokens/index.cjs +263 -0
  40. package/dist/tokens/index.d.cts +623 -0
  41. package/dist/tokens/index.d.ts +623 -0
  42. package/dist/tokens/index.js +2 -0
  43. package/dist/tokens/theme.css +266 -0
  44. package/package.json +128 -0
@@ -0,0 +1,242 @@
1
+ import { RUTA_ASSETS, caras, poses, aletas } from '../chunk-E3OMP2DL.js';
2
+ import { fonts, dark, light, naming, gradient, tagline, typeScale } from '../chunk-DHF63QNM.js';
3
+
4
+ // src/og/plantillas.ts
5
+ var OG = {
6
+ width: 1200,
7
+ height: 630,
8
+ margen: 64,
9
+ /** Alto máximo de la mascota. */
10
+ mascota: 430,
11
+ /** La aleta de la firma. */
12
+ aletaFirma: 34,
13
+ /**
14
+ * Hueco que deja la columna cuando la pose va a la izquierda (curso).
15
+ *
16
+ * Son 560 y no 420 porque una pose completa a 430 de alto mide ~534 de ancho:
17
+ * con el hueco justo, el tiburón se comía el titular. La reserva se mide por
18
+ * el ancho real de la pose, no por el margen.
19
+ */
20
+ reservaMascota: 560
21
+ };
22
+ function el(type, props, children) {
23
+ return { type, props: children === void 0 ? props : { ...props, children } };
24
+ }
25
+ function caja(style, children) {
26
+ return el("div", { style: { display: "flex", ...style } }, children);
27
+ }
28
+ function texto(style, contenido) {
29
+ return el("div", { style: { display: "flex", ...style } }, contenido);
30
+ }
31
+ function eyebrow(contenido, color) {
32
+ return texto(
33
+ {
34
+ fontFamily: fonts.mono,
35
+ fontSize: 20,
36
+ letterSpacing: typeScale.eyebrow.tracking,
37
+ textTransform: "uppercase",
38
+ color
39
+ },
40
+ contenido
41
+ );
42
+ }
43
+ function titular(contenido, color) {
44
+ return texto(
45
+ {
46
+ fontFamily: fonts.display,
47
+ fontSize: 58,
48
+ fontWeight: 800,
49
+ lineHeight: 1.06,
50
+ letterSpacing: typeScale.h1.tracking,
51
+ color,
52
+ // 70 % del LIENZO, no de la columna. Con la mascota en su propia columna
53
+ // el 70 % relativo daba ~400px y el titular se truncaba a media palabra.
54
+ maxWidth: OG.width * 0.7,
55
+ display: "-webkit-box",
56
+ WebkitBoxOrient: "vertical",
57
+ WebkitLineClamp: 3,
58
+ overflow: "hidden",
59
+ textOverflow: "ellipsis"
60
+ },
61
+ contenido
62
+ );
63
+ }
64
+ function firma(contenido, color, modo, base) {
65
+ return caja({ alignItems: "center", gap: 14 }, [
66
+ el("img", {
67
+ alt: "",
68
+ src: `${base}/${modo === "oscuro" ? aletas.espuma : aletas.color}`,
69
+ height: OG.aletaFirma,
70
+ style: { height: OG.aletaFirma }
71
+ }),
72
+ texto({ fontFamily: fonts.mono, fontSize: 21, color }, contenido)
73
+ ]);
74
+ }
75
+ function tarjeta(opciones) {
76
+ const columna = caja(
77
+ {
78
+ position: "relative",
79
+ flexDirection: "column",
80
+ justifyContent: "space-between",
81
+ width: "100%",
82
+ height: "100%",
83
+ padding: OG.margen,
84
+ // Cuando la pose va a la izquierda hay que dejarle el hueco: es lo único
85
+ // que cambia de la retícula, y solo lo hace la plantilla de curso.
86
+ paddingLeft: opciones.mascotaIzquierda ? OG.reservaMascota : OG.margen
87
+ },
88
+ [
89
+ eyebrow(opciones.eyebrow.texto, opciones.eyebrow.color),
90
+ caja({ flexDirection: "column", gap: 18 }, [
91
+ titular(opciones.title, opciones.tinta),
92
+ opciones.bajada ? texto(
93
+ {
94
+ fontFamily: fonts.sans,
95
+ fontSize: 26,
96
+ color: opciones.tintaSecundaria,
97
+ maxWidth: OG.width * 0.7
98
+ },
99
+ opciones.bajada
100
+ ) : null
101
+ ]),
102
+ firma(opciones.firma, opciones.firmaColor, opciones.modo, opciones.base)
103
+ ]
104
+ );
105
+ return caja(
106
+ {
107
+ position: "relative",
108
+ width: OG.width,
109
+ height: OG.height,
110
+ backgroundImage: opciones.fondo,
111
+ backgroundColor: opciones.modo === "oscuro" ? dark.background : light.background,
112
+ fontFamily: fonts.sans,
113
+ overflow: "hidden"
114
+ },
115
+ [
116
+ opciones.mascota ? caja(
117
+ {
118
+ position: "absolute",
119
+ bottom: 0,
120
+ ...opciones.mascotaIzquierda ? { left: 0 } : { right: 0 },
121
+ alignItems: "flex-end"
122
+ },
123
+ opciones.mascota
124
+ ) : null,
125
+ columna
126
+ ]
127
+ );
128
+ }
129
+ function mascotaPose(pose, base, alto = OG.mascota) {
130
+ return el("img", { alt: "", src: `${base}/${poses[pose]}`, height: alto, style: { height: alto } });
131
+ }
132
+ function plantillaArticulo(datos) {
133
+ const base = datos.basePath ?? RUTA_ASSETS;
134
+ const cara = datos.expresion ?? "hearts";
135
+ const meta = [datos.category, datos.readingMinutes ? `${datos.readingMinutes} min` : void 0].filter(Boolean).join(" \xB7 ");
136
+ return tarjeta({
137
+ modo: "oscuro",
138
+ fondo: gradient.dark.og,
139
+ eyebrow: { texto: meta || "art\xEDculo", color: dark.warm },
140
+ title: datos.title,
141
+ firma: naming.domain,
142
+ firmaColor: dark.textSecondary,
143
+ base,
144
+ tinta: dark.textPrimary,
145
+ tintaSecundaria: dark.textSecondary,
146
+ mascota: el("img", {
147
+ alt: "",
148
+ src: `${base}/${caras[cara]}`,
149
+ height: 300,
150
+ style: { height: 300, marginBottom: OG.margen, marginRight: OG.margen }
151
+ })
152
+ });
153
+ }
154
+ function plantillaCurso(datos) {
155
+ const base = datos.basePath ?? RUTA_ASSETS;
156
+ const meta = [datos.modules ? `${datos.modules} m\xF3dulos` : void 0, datos.duration].filter(Boolean).join(" \xB7 ");
157
+ return tarjeta({
158
+ modo: "claro",
159
+ fondo: gradient.light.og,
160
+ eyebrow: { texto: "nuevo curso", color: light.warm },
161
+ title: datos.title,
162
+ bajada: meta || void 0,
163
+ firma: datos.url ?? `cursos.${naming.domain}`,
164
+ firmaColor: light.warm,
165
+ base,
166
+ tinta: light.textPrimary,
167
+ tintaSecundaria: light.textSecondary,
168
+ mascotaIzquierda: true,
169
+ mascota: mascotaPose(datos.pose ?? "desk", base)
170
+ });
171
+ }
172
+ function plantillaCharla(datos) {
173
+ const base = datos.basePath ?? RUTA_ASSETS;
174
+ const cabeza = ["charla", datos.event, datos.year].filter(Boolean).join(" \xB7 ");
175
+ const pie = [datos.location, datos.event ? void 0 : naming.domain].filter(Boolean).join(" \xB7 ");
176
+ return tarjeta({
177
+ modo: "oscuro",
178
+ fondo: "none",
179
+ eyebrow: { texto: cabeza, color: dark.accent },
180
+ title: datos.title,
181
+ bajada: datos.summary,
182
+ firma: pie || naming.domain,
183
+ firmaColor: dark.textSecondary,
184
+ base,
185
+ tinta: dark.textPrimary,
186
+ tintaSecundaria: dark.textSecondary,
187
+ // Sangra: se sale por abajo y por la derecha, como la portada de slide.
188
+ mascota: el("img", {
189
+ alt: "",
190
+ src: `${base}/${poses[datos.pose ?? "surf"]}`,
191
+ height: 470,
192
+ style: { height: 470, marginBottom: -46, marginRight: -36 }
193
+ })
194
+ });
195
+ }
196
+ function plantillaDefecto(datos = {}) {
197
+ const base = datos.basePath ?? RUTA_ASSETS;
198
+ return caja(
199
+ {
200
+ width: OG.width,
201
+ height: OG.height,
202
+ alignItems: "center",
203
+ backgroundColor: dark.background,
204
+ fontFamily: fonts.sans
205
+ },
206
+ [
207
+ // Columna de la aleta: 290 de ancho, que es donde cae el divisor.
208
+ caja(
209
+ { width: 290, height: "100%", alignItems: "center", justifyContent: "center" },
210
+ // El halo. Un círculo de bioluz al 12 % detrás de la aleta.
211
+ caja(
212
+ {
213
+ width: 260,
214
+ height: 260,
215
+ borderRadius: 999,
216
+ backgroundColor: `${dark.accent}1F`,
217
+ alignItems: "center",
218
+ justifyContent: "center"
219
+ },
220
+ el("img", { alt: "", src: `${base}/${aletas.espuma}`, height: 200, style: { height: 200 } })
221
+ )
222
+ ),
223
+ // El divisor, exactamente en x=290.
224
+ caja({ width: 1, height: 340, backgroundColor: dark.border }),
225
+ caja(
226
+ { flexDirection: "column", gap: 20, paddingLeft: OG.margen, paddingRight: OG.margen, flex: 1 },
227
+ [
228
+ texto(
229
+ { fontFamily: fonts.sans, fontSize: 72, fontWeight: 700, color: dark.textPrimary, lineHeight: 1.05 },
230
+ datos.title ?? naming.wordmark
231
+ ),
232
+ texto(
233
+ { fontFamily: fonts.sans, fontSize: 28, fontWeight: 400, color: dark.textSecondary, lineHeight: 1.4 },
234
+ datos.description ?? tagline.corto
235
+ )
236
+ ]
237
+ )
238
+ ]
239
+ );
240
+ }
241
+
242
+ export { OG, plantillaArticulo, tarjeta as plantillaBase, plantillaCharla, plantillaCurso, plantillaDefecto };
@@ -0,0 +1,127 @@
1
+ 'use strict';
2
+
3
+ // src/tokens/tokens.ts
4
+ var dark = {
5
+ // hairline en hover de tarjeta
6
+ textPrimary: "#EDF4F3",
7
+ // bruma 9.50:1
8
+ textMuted: "#71919C",
9
+ // plancton 5.57:1 nunca bajo 13px
10
+ accent: "#35D6C0",
11
+ // tinta sobre bioluz
12
+ warm: "#F2A65A",
13
+ error: "#E15757"
14
+ // 4.51:1 sobre surface
15
+ };
16
+ var brand = {
17
+ /** Casco · contorno y fondo de bloques de código. */
18
+ hull: "#0B1524"
19
+ };
20
+ var sintaxis = {
21
+ /** El casco. Es el fondo del bloque en los dos modos. */
22
+ fondo: brand.hull,
23
+ /** Identificadores, funciones, tipos, variables. */
24
+ identificador: dark.textPrimary,
25
+ /** Cadenas, números, booleanos, null. */
26
+ literal: dark.accent,
27
+ /** Palabras clave, control de flujo, `import`, `this`. */
28
+ palabraClave: dark.warm,
29
+ /** Comentarios y puntuación. */
30
+ comentario: dark.textMuted,
31
+ /** `markup.deleted`, `invalid`. */
32
+ invalido: dark.error
33
+ };
34
+
35
+ // src/shiki/tema.ts
36
+ var arrecife = {
37
+ name: "arrecife",
38
+ type: "dark",
39
+ colors: {
40
+ "editor.background": sintaxis.fondo,
41
+ "editor.foreground": sintaxis.identificador
42
+ },
43
+ tokenColors: [
44
+ {
45
+ scope: ["comment", "punctuation.definition.comment", "string.comment"],
46
+ settings: { foreground: sintaxis.comentario, fontStyle: "italic" }
47
+ },
48
+ {
49
+ scope: [
50
+ "keyword",
51
+ "keyword.control",
52
+ "keyword.operator.new",
53
+ "keyword.operator.expression",
54
+ "storage",
55
+ "storage.type",
56
+ "storage.modifier",
57
+ "meta.import keyword",
58
+ "keyword.control.import",
59
+ "keyword.control.from",
60
+ "variable.language.this",
61
+ "variable.language.super"
62
+ ],
63
+ settings: { foreground: sintaxis.palabraClave }
64
+ },
65
+ {
66
+ scope: [
67
+ "string",
68
+ "string.quoted",
69
+ "string.template",
70
+ "punctuation.definition.string",
71
+ "string.regexp",
72
+ "constant.character.escape",
73
+ "constant.numeric",
74
+ "constant.language",
75
+ "constant.language.boolean",
76
+ "constant.language.null",
77
+ "constant.language.undefined",
78
+ "support.constant"
79
+ ],
80
+ settings: { foreground: sintaxis.literal }
81
+ },
82
+ {
83
+ scope: [
84
+ "entity.name.function",
85
+ "support.function",
86
+ "variable.function",
87
+ "entity.name.type",
88
+ "entity.name.class",
89
+ "entity.name.namespace",
90
+ "entity.other.inherited-class",
91
+ "support.type",
92
+ "support.class",
93
+ "entity.name.tag",
94
+ "variable",
95
+ "variable.other",
96
+ "variable.parameter",
97
+ "meta.object-literal.key",
98
+ "support.variable.property",
99
+ "entity.other.attribute-name"
100
+ ],
101
+ settings: { foreground: sintaxis.identificador }
102
+ },
103
+ {
104
+ scope: [
105
+ "keyword.operator",
106
+ "punctuation",
107
+ "meta.brace",
108
+ "punctuation.separator",
109
+ "punctuation.terminator"
110
+ ],
111
+ settings: { foreground: sintaxis.comentario }
112
+ },
113
+ { scope: ["markup.inserted"], settings: { foreground: sintaxis.literal } },
114
+ {
115
+ scope: ["markup.deleted", "invalid", "invalid.illegal"],
116
+ settings: { foreground: sintaxis.invalido }
117
+ },
118
+ {
119
+ scope: ["markup.heading", "entity.name.section"],
120
+ settings: { foreground: sintaxis.palabraClave, fontStyle: "bold" }
121
+ },
122
+ { scope: ["markup.bold"], settings: { fontStyle: "bold" } },
123
+ { scope: ["markup.italic"], settings: { fontStyle: "italic" } }
124
+ ]
125
+ };
126
+
127
+ exports.arrecife = arrecife;
@@ -0,0 +1,16 @@
1
+ /** La forma que Shiki espera. Se declara aquí para no depender del paquete. */
2
+ type TemaShiki = {
3
+ name: string;
4
+ type: 'dark' | 'light';
5
+ colors: Record<string, string>;
6
+ tokenColors: readonly {
7
+ scope: readonly string[];
8
+ settings: {
9
+ foreground?: string;
10
+ fontStyle?: string;
11
+ };
12
+ }[];
13
+ };
14
+ declare const arrecife: TemaShiki;
15
+
16
+ export { type TemaShiki, arrecife };
@@ -0,0 +1,16 @@
1
+ /** La forma que Shiki espera. Se declara aquí para no depender del paquete. */
2
+ type TemaShiki = {
3
+ name: string;
4
+ type: 'dark' | 'light';
5
+ colors: Record<string, string>;
6
+ tokenColors: readonly {
7
+ scope: readonly string[];
8
+ settings: {
9
+ foreground?: string;
10
+ fontStyle?: string;
11
+ };
12
+ }[];
13
+ };
14
+ declare const arrecife: TemaShiki;
15
+
16
+ export { type TemaShiki, arrecife };
@@ -0,0 +1,95 @@
1
+ import { sintaxis } from '../chunk-DHF63QNM.js';
2
+
3
+ // src/shiki/tema.ts
4
+ var arrecife = {
5
+ name: "arrecife",
6
+ type: "dark",
7
+ colors: {
8
+ "editor.background": sintaxis.fondo,
9
+ "editor.foreground": sintaxis.identificador
10
+ },
11
+ tokenColors: [
12
+ {
13
+ scope: ["comment", "punctuation.definition.comment", "string.comment"],
14
+ settings: { foreground: sintaxis.comentario, fontStyle: "italic" }
15
+ },
16
+ {
17
+ scope: [
18
+ "keyword",
19
+ "keyword.control",
20
+ "keyword.operator.new",
21
+ "keyword.operator.expression",
22
+ "storage",
23
+ "storage.type",
24
+ "storage.modifier",
25
+ "meta.import keyword",
26
+ "keyword.control.import",
27
+ "keyword.control.from",
28
+ "variable.language.this",
29
+ "variable.language.super"
30
+ ],
31
+ settings: { foreground: sintaxis.palabraClave }
32
+ },
33
+ {
34
+ scope: [
35
+ "string",
36
+ "string.quoted",
37
+ "string.template",
38
+ "punctuation.definition.string",
39
+ "string.regexp",
40
+ "constant.character.escape",
41
+ "constant.numeric",
42
+ "constant.language",
43
+ "constant.language.boolean",
44
+ "constant.language.null",
45
+ "constant.language.undefined",
46
+ "support.constant"
47
+ ],
48
+ settings: { foreground: sintaxis.literal }
49
+ },
50
+ {
51
+ scope: [
52
+ "entity.name.function",
53
+ "support.function",
54
+ "variable.function",
55
+ "entity.name.type",
56
+ "entity.name.class",
57
+ "entity.name.namespace",
58
+ "entity.other.inherited-class",
59
+ "support.type",
60
+ "support.class",
61
+ "entity.name.tag",
62
+ "variable",
63
+ "variable.other",
64
+ "variable.parameter",
65
+ "meta.object-literal.key",
66
+ "support.variable.property",
67
+ "entity.other.attribute-name"
68
+ ],
69
+ settings: { foreground: sintaxis.identificador }
70
+ },
71
+ {
72
+ scope: [
73
+ "keyword.operator",
74
+ "punctuation",
75
+ "meta.brace",
76
+ "punctuation.separator",
77
+ "punctuation.terminator"
78
+ ],
79
+ settings: { foreground: sintaxis.comentario }
80
+ },
81
+ { scope: ["markup.inserted"], settings: { foreground: sintaxis.literal } },
82
+ {
83
+ scope: ["markup.deleted", "invalid", "invalid.illegal"],
84
+ settings: { foreground: sintaxis.invalido }
85
+ },
86
+ {
87
+ scope: ["markup.heading", "entity.name.section"],
88
+ settings: { foreground: sintaxis.palabraClave, fontStyle: "bold" }
89
+ },
90
+ { scope: ["markup.bold"], settings: { fontStyle: "bold" } },
91
+ { scope: ["markup.italic"], settings: { fontStyle: "italic" } }
92
+ ]
93
+ };
94
+
95
+ export { arrecife };