bimba-cli 0.5.17 → 0.5.19

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 (2) hide show
  1. package/package.json +1 -1
  2. package/serve.js +28 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bimba-cli",
3
- "version": "0.5.17",
3
+ "version": "0.5.19",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/HeapVoid/bimba.git"
package/serve.js CHANGED
@@ -28,6 +28,7 @@ const hmrClient = `
28
28
  const _newClasses = new Map(); // tagName → latest class from HMR import
29
29
  const _oldNs = new Map(); // tagName → previous _ns_ (saved before _patchClass wipes it)
30
30
  let _collector = null; // when set, captures tag names defined during one HMR import
31
+ let _stableSlots = false; // when true, _patchClass skips Symbol-keyed props (CSS-only HMR)
31
32
 
32
33
  customElements.define = function(name, cls, opts) {
33
34
  if (_collector) _collector.push(name);
@@ -50,12 +51,13 @@ const hmrClient = `
50
51
 
51
52
  // Copy all own property descriptors from source to target, skipping keys
52
53
  // that match the shouldSkip predicate. Handles both string and symbol keys.
53
- function _copyDescriptors(target, source, shouldSkip) {
54
+ function _copyDescriptors(target, source, shouldSkip, skipSymbols) {
54
55
  for (const key of Object.getOwnPropertyNames(source)) {
55
56
  if (shouldSkip(key)) continue;
56
57
  const d = Object.getOwnPropertyDescriptor(source, key);
57
58
  if (d) try { Object.defineProperty(target, key, d); } catch(_) {}
58
59
  }
60
+ if (skipSymbols) return; // CSS-only: keep existing Symbol-keyed render caches
59
61
  for (const key of Object.getOwnPropertySymbols(source)) {
60
62
  const d = Object.getOwnPropertyDescriptor(source, key);
61
63
  if (d) try { Object.defineProperty(target, key, d); } catch(_) {}
@@ -63,8 +65,8 @@ const hmrClient = `
63
65
  }
64
66
 
65
67
  function _patchClass(target, source) {
66
- _copyDescriptors(target.prototype, source.prototype, k => k === 'constructor');
67
- _copyDescriptors(target, source, k => _skipStatics.has(k));
68
+ _copyDescriptors(target.prototype, source.prototype, k => k === 'constructor', _stableSlots);
69
+ _copyDescriptors(target, source, k => _skipStatics.has(k), _stableSlots);
68
70
  }
69
71
 
70
72
  // ── HMR update handler ─────────────────────────────────────────────────────
@@ -106,10 +108,12 @@ const hmrClient = `
106
108
  const collected = [];
107
109
  const prev = _collector;
108
110
  _collector = collected;
111
+ _stableSlots = (slots === 'stable');
109
112
  try {
110
113
  await import('/' + file + '?t=' + Date.now());
111
114
  } finally {
112
115
  _collector = prev;
116
+ _stableSlots = false;
113
117
  }
114
118
 
115
119
  // Sync _ns_ (CSS namespace) from the new classes. imba_defineTag sets
@@ -135,23 +139,27 @@ const hmrClient = `
135
139
  _oldNs.delete(tag);
136
140
  }
137
141
 
138
- // Destructive HMR: wipe inner DOM and re-render each collected tag
139
- for (const tag of collected) {
140
- const els = document.querySelectorAll(tag);
141
- els.forEach(el => {
142
- const state = {};
143
- for (const k of Object.keys(el)) state[k] = el[k];
144
- _disconnectDescendants(el);
145
- for (const sym of Object.getOwnPropertySymbols(el)) {
146
- if (Symbol.keyFor(sym) !== undefined) continue;
147
- try { delete el[sym]; } catch(_) {}
148
- }
149
- el.innerHTML = '';
150
- Object.assign(el, state);
151
- try { el.render && el.render(); } catch(e) { console.error('[bimba] render error:', e); }
152
- try { el.connectedCallback && el.connectedCallback(); } catch(_) {}
153
- try { el.mount && el.mount(); } catch(_) {}
154
- });
142
+ // Destructive HMR: wipe inner DOM and re-render each collected tag.
143
+ // Skip when slots === 'stable' (CSS-only change) — no template diff,
144
+ // so wiping innerHTML would destroy DOM state (inputs, focus) for nothing.
145
+ if (slots !== 'stable') {
146
+ for (const tag of collected) {
147
+ const els = document.querySelectorAll(tag);
148
+ els.forEach(el => {
149
+ const state = {};
150
+ for (const k of Object.keys(el)) state[k] = el[k];
151
+ _disconnectDescendants(el);
152
+ for (const sym of Object.getOwnPropertySymbols(el)) {
153
+ if (Symbol.keyFor(sym) !== undefined) continue;
154
+ try { delete el[sym]; } catch(_) {}
155
+ }
156
+ el.innerHTML = '';
157
+ Object.assign(el, state);
158
+ try { el.render && el.render(); } catch(e) { console.error('[bimba] render error:', e); }
159
+ try { el.connectedCallback && el.connectedCallback(); } catch(_) {}
160
+ try { el.mount && el.mount(); } catch(_) {}
161
+ });
162
+ }
155
163
  }
156
164
 
157
165
  if (typeof imba !== 'undefined') imba.commit();