@jjlmoya/utils-drones 1.5.0 → 1.6.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-drones",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -0,0 +1,140 @@
1
+ ---
2
+ import { Icon } from "astro-icon/components";
3
+
4
+ interface Props {
5
+ title: string;
6
+ message: string;
7
+ }
8
+
9
+ const { title, message } = Astro.props;
10
+ ---
11
+
12
+ <div class="security-warning">
13
+ <div class="warning-icon-wrapper">
14
+ <Icon name="mdi:alert-decagram" class="warning-icon" />
15
+ </div>
16
+ <div class="warning-content">
17
+ <p>
18
+ <strong class="warning-title">{title}:</strong>
19
+ <span class="warning-message">{message}</span>
20
+ </p>
21
+ </div>
22
+ <div class="warning-accent"></div>
23
+ </div>
24
+
25
+ <style>
26
+ .security-warning {
27
+ position: relative;
28
+ display: flex;
29
+ align-items: center;
30
+ gap: 1.5rem;
31
+ padding: 1.5rem 2rem;
32
+ background: rgba(239, 68, 68, 0.05);
33
+ backdrop-filter: blur(10px);
34
+ border: 1px solid rgba(239, 68, 68, 0.2);
35
+ border-radius: 24px;
36
+ overflow: hidden;
37
+ transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
38
+ margin: 2rem 0;
39
+ }
40
+
41
+ :global(.theme-dark) .security-warning {
42
+ background: rgba(239, 68, 68, 0.1);
43
+ border-color: rgba(239, 68, 68, 0.3);
44
+ }
45
+
46
+ .security-warning:hover {
47
+ transform: translateY(-4px) scale(1.01);
48
+ box-shadow: 0 20px 40px rgba(239, 68, 68, 0.15);
49
+ border-color: rgba(239, 68, 68, 0.4);
50
+ }
51
+
52
+ .warning-icon-wrapper {
53
+ flex-shrink: 0;
54
+ display: flex;
55
+ align-items: center;
56
+ justify-content: center;
57
+ width: 48px;
58
+ height: 48px;
59
+ background: linear-gradient(135deg, #ef4444, #b91c1c);
60
+ border-radius: 16px;
61
+ box-shadow: 0 8px 16px rgba(239, 68, 68, 0.3);
62
+ animation: pulse-ring 3s cubic-bezier(0.25, 0.8, 0.25, 1) infinite;
63
+ }
64
+
65
+ .warning-icon {
66
+ --icon-color: #fff;
67
+
68
+ width: 28px;
69
+ height: 28px;
70
+ color: var(--icon-color);
71
+ }
72
+
73
+ .warning-content {
74
+ flex: 1;
75
+ }
76
+
77
+ .warning-content p {
78
+ margin: 0;
79
+ color: var(--antenna-text);
80
+ font-size: 0.95rem;
81
+ line-height: 1.6;
82
+ }
83
+
84
+ .warning-title {
85
+ --warning-color: #ef4444;
86
+
87
+ color: var(--warning-color);
88
+ font-weight: 800;
89
+ text-transform: uppercase;
90
+ letter-spacing: 0.05em;
91
+ font-size: 0.85rem;
92
+ }
93
+
94
+ .warning-message {
95
+ font-weight: 500;
96
+ opacity: 0.9;
97
+ }
98
+
99
+ .warning-accent {
100
+ position: absolute;
101
+ top: 0;
102
+ left: 0;
103
+ height: 100%;
104
+ width: 4px;
105
+ background: #ef4444;
106
+ }
107
+
108
+ @keyframes pulse-ring {
109
+ 0% {
110
+ box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4);
111
+ }
112
+
113
+ 70% {
114
+ box-shadow: 0 0 0 10px rgba(239, 68, 68, 0);
115
+ }
116
+
117
+ 100% {
118
+ box-shadow: 0 0 0 0 rgba(239, 68, 68, 0);
119
+ }
120
+ }
121
+
122
+ @media (max-width: 600px) {
123
+ .security-warning {
124
+ flex-direction: column;
125
+ align-items: flex-start;
126
+ gap: 1rem;
127
+ padding: 1.5rem;
128
+ }
129
+
130
+ .warning-icon-wrapper {
131
+ width: 40px;
132
+ height: 40px;
133
+ }
134
+
135
+ .warning-icon {
136
+ width: 24px;
137
+ height: 24px;
138
+ }
139
+ }
140
+ </style>
@@ -213,26 +213,35 @@ const materials = [
213
213
  }
214
214
  }
215
215
 
216
- function calculate() {
217
- const freq = parseFloat(freqInput.value);
218
- const vf = parseFloat(vfInput.value);
219
- const waveType = getWaveType();
220
-
221
- if (!freq || freq <= 0) return;
216
+ function validateInputs() {
217
+ if (!freqInput || !(freqInput as HTMLInputElement).value || !vfInput) return null;
218
+ const freq = parseFloat((freqInput as HTMLInputElement).value);
219
+ const vf = parseFloat((vfInput as HTMLSelectElement).value);
220
+ return freq > 0 ? { freq, vf } : null;
221
+ }
222
222
 
223
+ function calculateLengths(freq, vf, waveType) {
223
224
  const lambda = 300000 / freq;
224
225
  const totalPhysicalLambda = lambda * vf;
225
-
226
226
  const totalLen = waveType === 'half' ? totalPhysicalLambda / 2 : totalPhysicalLambda / 4;
227
227
  const branchLen = waveType === 'half' ? totalLen / 2 : totalLen;
228
+ return { totalLen, branchLen };
229
+ }
228
230
 
229
- updateLayerVisibility(waveType);
230
- updateVisuals(waveType, waveType === 'half' ? branchLen : totalLen);
231
-
231
+ function displayLengths(totalLen, branchLen) {
232
232
  if (elements.total) elements.total.textContent = Math.round(totalLen).toString();
233
233
  if (elements.branch) elements.branch.textContent = Math.round(branchLen).toString();
234
+ }
234
235
 
235
- updateHarmonics(freq);
236
+ function calculate() {
237
+ const inputs = validateInputs();
238
+ if (!inputs) return;
239
+ const waveType = getWaveType();
240
+ const { totalLen, branchLen } = calculateLengths(inputs.freq, inputs.vf, waveType);
241
+ updateLayerVisibility(waveType);
242
+ updateVisuals(waveType, waveType === 'half' ? branchLen : totalLen);
243
+ displayLengths(totalLen, branchLen);
244
+ updateHarmonics(inputs.freq);
236
245
  }
237
246
 
238
247
  function setArmAttributes(x, isLeft) {
@@ -1005,7 +1014,8 @@ const materials = [
1005
1014
  box-shadow: 0 2px 5px rgba(0,0,0,0.02);
1006
1015
  }
1007
1016
 
1008
- :global(.dark) .custom-select-premium {
1017
+ :global([data-theme="dark"]) .custom-select-premium,
1018
+ :global(.theme-dark) .custom-select-premium {
1009
1019
  background-color: rgba(15, 23, 42, 0.4);
1010
1020
  border-color: rgba(255,255,255,0.1);
1011
1021
  color: white;
@@ -1024,7 +1034,54 @@ const materials = [
1024
1034
  letter-spacing: 0.1em;
1025
1035
  }
1026
1036
 
1027
- :global(.dark) .svg-label-text {
1037
+ :global([data-theme="dark"]) .svg-label-text,
1038
+ :global(.theme-dark) .svg-label-text {
1028
1039
  fill: #666;
1029
1040
  }
1041
+ .antenna-calculator-ui .security-warning {
1042
+ margin-top: 2rem;
1043
+ padding: 1.5rem 2rem;
1044
+ background: rgba(239, 68, 68, 0.05);
1045
+ border: 1px solid rgba(239, 68, 68, 0.2);
1046
+ border-left: 4px solid #ef4444;
1047
+ border-radius: 20px;
1048
+ display: flex;
1049
+ align-items: flex-start;
1050
+ gap: 1.25rem;
1051
+ transition: all 0.3s ease;
1052
+ }
1053
+
1054
+ :global([data-theme="dark"]) .antenna-calculator-ui .security-warning,
1055
+ :global(.theme-dark) .antenna-calculator-ui .security-warning {
1056
+ background: rgba(239, 68, 68, 0.1);
1057
+ border-color: rgba(239, 68, 68, 0.3);
1058
+ }
1059
+
1060
+ .antenna-calculator-ui .security-warning:hover {
1061
+ transform: translateY(-2px);
1062
+ background: rgba(239, 68, 68, 0.08);
1063
+ box-shadow: 0 15px 30px rgba(239, 68, 68, 0.1);
1064
+ }
1065
+
1066
+ .antenna-calculator-ui .security-warning [data-icon] {
1067
+ width: 24px;
1068
+ height: 24px;
1069
+ color: #ef4444;
1070
+ flex-shrink: 0;
1071
+ }
1072
+
1073
+ .antenna-calculator-ui .security-warning p {
1074
+ margin: 0;
1075
+ font-size: 0.95rem;
1076
+ line-height: 1.6;
1077
+ color: var(--antenna-text);
1078
+ font-weight: 500;
1079
+ }
1080
+
1081
+ .antenna-calculator-ui .security-warning strong {
1082
+ color: #ef4444;
1083
+ font-weight: 800;
1084
+ text-transform: uppercase;
1085
+ letter-spacing: 0.02em;
1086
+ }
1030
1087
  </style>