humanmap-vas 1.0.2 → 1.0.22

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.
@@ -117,19 +117,113 @@
117
117
  this._view=this.getAttribute('view') || 'head_right';
118
118
  this._zones=ZONES;
119
119
  this._selected=new Set();
120
- this._bg={
121
- head_right:'src/img/head_right.svg',
122
- head_left:'src/img/head_left.svg',
123
- neck_right:'src/img/neck_right.svg',
124
- neck_left:'src/img/neck_left.svg',
125
- thorax_front:'src/img/torax_front.svg',
126
- thorax_back:'src/img/torax_back.svg'
120
+
121
+ this._upgradeProperty('selectedIds');
122
+ this._upgradeProperty('selectedZones');
123
+
124
+
125
+ // Detectar automáticamente la ruta base del script (compatible con todos los entornos)
126
+ let scriptBase = '';
127
+ try {
128
+ if (document.currentScript && document.currentScript.src) {
129
+ scriptBase = document.currentScript.src.split('/').slice(0, -1).join('/') + '/';
130
+ } else {
131
+ const scripts = document.getElementsByTagName('script');
132
+ if (scripts.length > 0) {
133
+ const last = scripts[scripts.length - 1];
134
+ scriptBase = last.src.split('/').slice(0, -1).join('/') + '/';
135
+ }
136
+ }
137
+ } catch (err) {
138
+ console.warn('⚠️ No se pudo detectar ruta base del script:', err);
139
+ }
140
+
141
+ // Definir la raíz de imágenes (desde atributo o autodetectada)
142
+ this._imgRoot = this.getAttribute('img-root') || (scriptBase + 'src/img/');
143
+
144
+ // Configurar rutas base
145
+ this._bg = {
146
+ head_right: this._imgRoot + 'head_right.svg',
147
+ head_left: this._imgRoot + 'head_left.svg',
148
+ neck_right: this._imgRoot + 'neck_right.svg',
149
+ neck_left: this._imgRoot + 'neck_left.svg',
150
+ thorax_front: this._imgRoot + 'torax_front.svg',
151
+ thorax_back: this._imgRoot + 'torax_back.svg'
127
152
  };
128
153
  }
129
154
 
130
- connectedCallback(){this._renderShell();this._renderCanvas();}
131
- static get observedAttributes() { return ['view']; }
132
- attributeChangedCallback(n,o,v){if(o!==v&&n==='view'){this._view=v;if(this._root)this._renderCanvas();}}
155
+ // Captura valores asignados *antes* de que el custom element se registre
156
+ _upgradeProperty(prop) {
157
+ if (this.hasOwnProperty(prop)) {
158
+ const value = this[prop];
159
+ delete this[prop]; // elimina la propiedad “propia” del elemento “no mejorado”
160
+ this[prop] = value; // re-ejecuta el setter ya del elemento mejorado
161
+ }
162
+ }
163
+
164
+ connectedCallback(){this._renderShell();this._renderCanvas();this.dispatchEvent(new CustomEvent('human-map-vas:ready'));}
165
+
166
+ static get observedAttributes() { return ['view', 'img-root']; }
167
+
168
+ attributeChangedCallback (name, oldValue, newValue) {
169
+ if (oldValue === newValue) return;
170
+
171
+ if (name === 'view') {
172
+ this._view = newValue;
173
+ if (this._root) this._renderCanvas();
174
+ return;
175
+ }
176
+
177
+ if (name === 'img-root' && newValue) {
178
+ this._imgRoot = newValue.endsWith('/') ? newValue : newValue + '/';
179
+ this._bg = {
180
+ head_right: this._imgRoot + 'head_right.svg',
181
+ head_left: this._imgRoot + 'head_left.svg',
182
+ neck_right: this._imgRoot + 'neck_right.svg',
183
+ neck_left: this._imgRoot + 'neck_left.svg',
184
+ thorax_front: this._imgRoot + 'torax_front.svg',
185
+ thorax_back: this._imgRoot + 'torax_back.svg'
186
+ };
187
+ if (this._root) this._renderCanvas();
188
+ return;
189
+ }
190
+ }
191
+
192
+ // Devuelve solo IDs seleccionados
193
+ get selectedIds() {
194
+ return Array.from(this._selected);
195
+ }
196
+
197
+ // Asigna selección por IDs (array de strings)
198
+ set selectedIds(ids) {
199
+ if (!Array.isArray(ids)) return;
200
+ this._selected = new Set(ids);
201
+ if (this._root) { this._renderZones(); this._emit(); }
202
+ }
203
+
204
+ // Devuelve objetos completos (id, code, label, view)
205
+ get selectedZones() {
206
+ const map = new Map(this._zones.map(z => [z.id, z]));
207
+ return this.selectedIds.map(id => {
208
+ const z = map.get(id);
209
+ return z ? { id: z.id, code: z.code, label: z.label, view: z.view } : { id };
210
+ });
211
+ }
212
+
213
+ // Asigna selección pasando objetos (tomamos los IDs)
214
+ set selectedZones(zones) {
215
+ if (!Array.isArray(zones)) return;
216
+ const ids = zones.map(z => z && z.id).filter(Boolean);
217
+ this.selectedIds = ids; // reutiliza el setter de IDs para redibujar y emitir
218
+ }
219
+
220
+ get selectedCodes() {
221
+ const map = new Map(this._zones.map(z => [z.id, z]));
222
+ return this.selectedIds.map(id => {
223
+ const z = map.get(id);
224
+ return z ? z.code : { id };
225
+ });
226
+ }
133
227
 
134
228
  getSelected(){
135
229
  const map=new Map(this._zones.map(z=>[z.id,z]));
@@ -142,8 +236,12 @@
142
236
  clear(){this._selected.clear();this._renderZones();this._emit();}
143
237
 
144
238
  _renderShell(){
145
- const style=document.createElement('style');style.textContent=STYLE;
146
- this._root=document.createElement('div');this._root.className='hm';
239
+ const style=document.createElement('style');
240
+ style.textContent=STYLE;
241
+
242
+ this._root=document.createElement('div');
243
+ this._root.className='hm';
244
+
147
245
  const opts=VIEWS.map(v=>`<option value="${v.id}">${v.label}</option>`).join('');
148
246
  this._root.innerHTML=`
149
247
  <div class="hm-toolbar">
@@ -163,6 +261,7 @@
163
261
  </svg>
164
262
  </div>`;
165
263
  this.shadowRoot.append(style,this._root);
264
+
166
265
  this._els={
167
266
  cur:this.shadowRoot.getElementById('cur'),
168
267
  picker:this.shadowRoot.getElementById('picker'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "humanmap-vas",
3
- "version": "1.0.2",
3
+ "version": "1.0.22",
4
4
  "description": "**HumanMap VAS** es una librería web que permite graficar el cuerpo humano con vistas anatómicas interactivas para identificar zonas según el sistema VAS. Desarrollada como *Web Component standalone*, puede integrarse fácilmente en proyectos **HTML**, **Django**, o **Vue.js**.",
5
5
  "main": "humanmap-vas-standalone.js",
6
6
  "files": [