@jjlmoya/utils-social 1.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 (85) hide show
  1. package/package.json +60 -0
  2. package/src/category/i18n/en.ts +23 -0
  3. package/src/category/i18n/es.ts +23 -0
  4. package/src/category/i18n/fr.ts +23 -0
  5. package/src/category/index.ts +13 -0
  6. package/src/category/seo.astro +15 -0
  7. package/src/components/PreviewNavSidebar.astro +116 -0
  8. package/src/components/PreviewToolbar.astro +143 -0
  9. package/src/data.ts +11 -0
  10. package/src/env.d.ts +5 -0
  11. package/src/index.ts +27 -0
  12. package/src/layouts/PreviewLayout.astro +117 -0
  13. package/src/pages/[locale]/[slug].astro +146 -0
  14. package/src/pages/[locale].astro +251 -0
  15. package/src/pages/index.astro +4 -0
  16. package/src/tests/faq_count.test.ts +19 -0
  17. package/src/tests/locale_completeness.test.ts +42 -0
  18. package/src/tests/mocks/astro_mock.js +2 -0
  19. package/src/tests/no_h1_in_components.test.ts +48 -0
  20. package/src/tests/seo_length.test.ts +22 -0
  21. package/src/tests/tool_validation.test.ts +17 -0
  22. package/src/tool/redditFormatter/bibliography.astro +14 -0
  23. package/src/tool/redditFormatter/component.astro +246 -0
  24. package/src/tool/redditFormatter/i18n/en.ts +193 -0
  25. package/src/tool/redditFormatter/i18n/es.ts +193 -0
  26. package/src/tool/redditFormatter/i18n/fr.ts +193 -0
  27. package/src/tool/redditFormatter/index.ts +34 -0
  28. package/src/tool/redditFormatter/logic.ts +24 -0
  29. package/src/tool/redditFormatter/seo.astro +14 -0
  30. package/src/tool/redditFormatter/ui.ts +13 -0
  31. package/src/tool/safeZones/bibliography.astro +14 -0
  32. package/src/tool/safeZones/component.astro +857 -0
  33. package/src/tool/safeZones/i18n/en.ts +244 -0
  34. package/src/tool/safeZones/i18n/es.ts +244 -0
  35. package/src/tool/safeZones/i18n/fr.ts +244 -0
  36. package/src/tool/safeZones/index.ts +34 -0
  37. package/src/tool/safeZones/logic.ts +137 -0
  38. package/src/tool/safeZones/seo.astro +14 -0
  39. package/src/tool/safeZones/ui.ts +34 -0
  40. package/src/tool/socialImageResizer/bibliography.astro +14 -0
  41. package/src/tool/socialImageResizer/component.astro +498 -0
  42. package/src/tool/socialImageResizer/i18n/en.ts +211 -0
  43. package/src/tool/socialImageResizer/i18n/es.ts +211 -0
  44. package/src/tool/socialImageResizer/i18n/fr.ts +211 -0
  45. package/src/tool/socialImageResizer/index.ts +34 -0
  46. package/src/tool/socialImageResizer/logic.ts +133 -0
  47. package/src/tool/socialImageResizer/seo.astro +14 -0
  48. package/src/tool/socialImageResizer/ui.ts +7 -0
  49. package/src/tool/socialValueCalculator/bibliography.astro +14 -0
  50. package/src/tool/socialValueCalculator/component.astro +829 -0
  51. package/src/tool/socialValueCalculator/i18n/en.ts +310 -0
  52. package/src/tool/socialValueCalculator/i18n/es.ts +310 -0
  53. package/src/tool/socialValueCalculator/i18n/fr.ts +310 -0
  54. package/src/tool/socialValueCalculator/index.ts +34 -0
  55. package/src/tool/socialValueCalculator/logic.ts +60 -0
  56. package/src/tool/socialValueCalculator/seo.astro +14 -0
  57. package/src/tool/socialValueCalculator/ui.ts +31 -0
  58. package/src/tool/tinderPhotoOptimizer/bibliography.astro +14 -0
  59. package/src/tool/tinderPhotoOptimizer/component.astro +1514 -0
  60. package/src/tool/tinderPhotoOptimizer/i18n/en.ts +248 -0
  61. package/src/tool/tinderPhotoOptimizer/i18n/es.ts +248 -0
  62. package/src/tool/tinderPhotoOptimizer/i18n/fr.ts +248 -0
  63. package/src/tool/tinderPhotoOptimizer/index.ts +34 -0
  64. package/src/tool/tinderPhotoOptimizer/logic.ts +199 -0
  65. package/src/tool/tinderPhotoOptimizer/seo.astro +14 -0
  66. package/src/tool/tinderPhotoOptimizer/ui.ts +37 -0
  67. package/src/tool/youtubeThumbnail/bibliography.astro +14 -0
  68. package/src/tool/youtubeThumbnail/component.astro +419 -0
  69. package/src/tool/youtubeThumbnail/i18n/en.ts +207 -0
  70. package/src/tool/youtubeThumbnail/i18n/es.ts +207 -0
  71. package/src/tool/youtubeThumbnail/i18n/fr.ts +207 -0
  72. package/src/tool/youtubeThumbnail/index.ts +34 -0
  73. package/src/tool/youtubeThumbnail/logic.ts +7 -0
  74. package/src/tool/youtubeThumbnail/seo.astro +14 -0
  75. package/src/tool/youtubeThumbnail/ui.ts +13 -0
  76. package/src/tool/youtubeThumbnailPreviewer/bibliography.astro +14 -0
  77. package/src/tool/youtubeThumbnailPreviewer/component.astro +791 -0
  78. package/src/tool/youtubeThumbnailPreviewer/i18n/en.ts +321 -0
  79. package/src/tool/youtubeThumbnailPreviewer/i18n/es.ts +321 -0
  80. package/src/tool/youtubeThumbnailPreviewer/i18n/fr.ts +321 -0
  81. package/src/tool/youtubeThumbnailPreviewer/index.ts +34 -0
  82. package/src/tool/youtubeThumbnailPreviewer/seo.astro +14 -0
  83. package/src/tool/youtubeThumbnailPreviewer/ui.ts +19 -0
  84. package/src/tools.ts +10 -0
  85. package/src/types.ts +72 -0
@@ -0,0 +1,133 @@
1
+ interface Preset {
2
+ id: string;
3
+ name: string;
4
+ width: number;
5
+ height: number;
6
+ platform: string;
7
+ }
8
+
9
+ export class SocialResizer {
10
+ private canvas: HTMLCanvasElement;
11
+ private ctx: CanvasRenderingContext2D;
12
+ private image: HTMLImageElement | null = null;
13
+ private currentPreset: Preset;
14
+
15
+ private scale: number = 1.0;
16
+ private posX: number = 0;
17
+ private posY: number = 0;
18
+ private isDragging: boolean = false;
19
+ private lastMouseX: number = 0;
20
+ private lastMouseY: number = 0;
21
+
22
+ public zoomRangeEl: HTMLInputElement | null = null;
23
+
24
+ constructor(canvasId: string) {
25
+ this.canvas = document.getElementById(canvasId) as HTMLCanvasElement;
26
+ this.ctx = this.canvas.getContext('2d')!;
27
+ this.currentPreset = { id: 'ig-square', name: 'Post Cuadrado', width: 1080, height: 1080, platform: 'Instagram' };
28
+ this.initEventListeners();
29
+ }
30
+
31
+ private initEventListeners() {
32
+ this.canvas.addEventListener('mousedown', (e) => this.onMouseDown(e));
33
+ window.addEventListener('mousemove', (e) => this.onMouseMove(e));
34
+ window.addEventListener('mouseup', () => this.onMouseUp());
35
+ this.canvas.addEventListener('wheel', (e) => this.onWheel(e), { passive: false });
36
+ }
37
+
38
+ public loadImage(file: File): Promise<void> {
39
+ return new Promise((resolve) => {
40
+ const reader = new FileReader();
41
+ reader.onload = (e) => {
42
+ const img = new Image();
43
+ img.onload = () => {
44
+ this.image = img;
45
+ this.resetPosition();
46
+ this.draw();
47
+ resolve();
48
+ };
49
+ img.src = e.target?.result as string;
50
+ };
51
+ reader.readAsDataURL(file);
52
+ });
53
+ }
54
+
55
+ private resetPosition() {
56
+ if (!this.image) return;
57
+ const presetRatio = this.currentPreset.width / this.currentPreset.height;
58
+ const imgRatio = this.image.width / this.image.height;
59
+ if (imgRatio > presetRatio) {
60
+ this.scale = this.currentPreset.height / this.image.height;
61
+ } else {
62
+ this.scale = this.currentPreset.width / this.image.width;
63
+ }
64
+ this.posX = (this.currentPreset.width - this.image.width * this.scale) / 2;
65
+ this.posY = (this.currentPreset.height - this.image.height * this.scale) / 2;
66
+ }
67
+
68
+ public setPreset(preset: Preset) {
69
+ this.currentPreset = preset;
70
+ this.canvas.width = preset.width;
71
+ this.canvas.height = preset.height;
72
+ this.resetPosition();
73
+ this.draw();
74
+ }
75
+
76
+ public setScale(newScale: number) {
77
+ const oldScale = this.scale;
78
+ this.scale = newScale;
79
+ const centerX = this.currentPreset.width / 2;
80
+ const centerY = this.currentPreset.height / 2;
81
+ this.posX = centerX - (centerX - this.posX) * (this.scale / oldScale);
82
+ this.posY = centerY - (centerY - this.posY) * (this.scale / oldScale);
83
+ this.draw();
84
+ }
85
+
86
+ private draw() {
87
+ if (!this.image) return;
88
+ this.ctx.fillStyle = '#ffffff';
89
+ this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
90
+ this.ctx.drawImage(this.image, this.posX, this.posY, this.image.width * this.scale, this.image.height * this.scale);
91
+ }
92
+
93
+ private onMouseDown(e: MouseEvent) {
94
+ this.isDragging = true;
95
+ this.lastMouseX = e.clientX;
96
+ this.lastMouseY = e.clientY;
97
+ }
98
+
99
+ private onMouseMove(e: MouseEvent) {
100
+ if (!this.isDragging || !this.image) return;
101
+ const deltaX = e.clientX - this.lastMouseX;
102
+ const deltaY = e.clientY - this.lastMouseY;
103
+ const rect = this.canvas.getBoundingClientRect();
104
+ const factorX = this.canvas.width / rect.width;
105
+ const factorY = this.canvas.height / rect.height;
106
+ this.posX += deltaX * factorX;
107
+ this.posY += deltaY * factorY;
108
+ this.lastMouseX = e.clientX;
109
+ this.lastMouseY = e.clientY;
110
+ this.draw();
111
+ }
112
+
113
+ private onMouseUp() {
114
+ this.isDragging = false;
115
+ }
116
+
117
+ private onWheel(e: WheelEvent) {
118
+ e.preventDefault();
119
+ const delta = e.deltaY > 0 ? 0.95 : 1.05;
120
+ this.setScale(this.scale * delta);
121
+ if (this.zoomRangeEl) {
122
+ this.zoomRangeEl.value = (this.scale * 100).toString();
123
+ }
124
+ }
125
+
126
+ public download() {
127
+ if (!this.image) return;
128
+ const link = document.createElement('a');
129
+ link.download = `jjlmoya-${this.currentPreset.id}.jpg`;
130
+ link.href = this.canvas.toDataURL('image/jpeg', 0.9);
131
+ link.click();
132
+ }
133
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { socialImageResizer } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await socialImageResizer.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+ <SEORenderer content={{ locale: locale as string, sections: content.seo }} />
@@ -0,0 +1,7 @@
1
+ export interface SocialImageResizerUI {
2
+ sidebarTitle: string;
3
+ uploadTitle: string;
4
+ uploadSubtitle: string;
5
+ btnReset: string;
6
+ btnDownload: string;
7
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { socialValueCalculator } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'es' } = Astro.props;
11
+ const content = await socialValueCalculator.i18n[locale]?.();
12
+ ---
13
+
14
+ {content && <SharedBibliography links={content.bibliography} />}