@stacksjs/stx 0.2.96 → 0.2.98

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.
@@ -99,8 +99,9 @@ function generateWebComponentCode(options) {
99
99
  class ${name.replace(/\W/g, "")} extends ${baseElement} {
100
100
  constructor() {
101
101
  super()
102
+ this._initialized = false
103
+ ${shadowDOM ? "" : "this._slotContent = []"}
102
104
  ${shadowDOM ? 'this.attachShadow({ mode: "open" })' : ""}
103
- ${template ? "this._createTemplate()" : "this._render()"}
104
105
  }
105
106
 
106
107
  ${template ? `
@@ -130,32 +131,28 @@ class ${name.replace(/\W/g, "")} extends ${baseElement} {
130
131
  })
131
132
  })` : `// Manual slot processing for non-shadow DOM mode
132
133
  const slots = this.querySelectorAll('[data-slot]')
133
- const lightDOMChildren = Array.from(this.childNodes).filter(
134
- node => node.nodeType === Node.ELEMENT_NODE && !node.hasAttribute('data-slot')
135
- )
136
134
 
137
135
  // Process named slots
138
136
  slots.forEach(slotEl => {
139
137
  const slotName = slotEl.getAttribute('data-slot')
140
- const slottedContent = this.querySelector(\`[slot="\${slotName}"]\`)
141
- if (slottedContent) {
142
- // Replace slot placeholder with actual content
138
+ const slottedContent = this._slotContent.filter(
139
+ node => node.nodeType === Node.ELEMENT_NODE && node.getAttribute('slot') === slotName
140
+ )
141
+ if (slottedContent.length > 0) {
143
142
  slotEl.innerHTML = ''
144
- slotEl.appendChild(slottedContent.cloneNode(true))
143
+ slottedContent.forEach(content => slotEl.appendChild(content))
145
144
  }
146
145
  })
147
146
 
148
147
  // Process default slot
149
148
  const defaultSlot = this.querySelector('[data-slot=""]') || this.querySelector('[data-default-slot]')
150
149
  if (defaultSlot) {
151
- const unslottedContent = Array.from(this.children).filter(
152
- child => !child.hasAttribute('slot') && child !== defaultSlot
150
+ const unslottedContent = this._slotContent.filter(
151
+ node => node.nodeType !== Node.ELEMENT_NODE || !node.hasAttribute('slot')
153
152
  )
154
153
  if (unslottedContent.length > 0) {
155
154
  defaultSlot.innerHTML = ''
156
- unslottedContent.forEach(content => {
157
- defaultSlot.appendChild(content.cloneNode(true))
158
- })
155
+ unslottedContent.forEach(content => defaultSlot.appendChild(content))
159
156
  }
160
157
  }`}
161
158
  }
@@ -168,13 +165,16 @@ class ${name.replace(/\W/g, "")} extends ${baseElement} {
168
165
  attributeChangedCallback(name, oldValue, newValue) {
169
166
  if (oldValue !== newValue) {
170
167
  this[name] = newValue
171
- ${template ? "" : "this._render()"}
168
+ ${template ? "" : "if (this._initialized) this._render()"}
172
169
  }
173
170
  }
174
171
  ` : ""}
175
172
 
176
173
  connectedCallback() {
177
- // Component connected to the DOM
174
+ if (this._initialized) return
175
+ ${shadowDOM ? "" : "this._slotContent = Array.from(this.childNodes)"}
176
+ this._initialized = true
177
+ ${template ? "this._createTemplate()" : "this._render()"}
178
178
  }
179
179
 
180
180
  disconnectedCallback() {
@@ -254,7 +254,7 @@ ${attributes.map((attr) => {
254
254
  if (oldValue !== newValue) {
255
255
  const camelCase = name.replace(/-([a-z])/g, (_: string, letter: string) => letter.toUpperCase());
256
256
  (this as unknown as Record<string, unknown>)[\`_\${camelCase}\`] = this._parseAttributeValue(name, newValue);
257
- ${template ? "" : "this._render();"}
257
+ ${template ? "" : "if (this._initialized) this._render();"}
258
258
  }
259
259
  }
260
260
 
@@ -306,11 +306,12 @@ ${propsInterface}
306
306
  */
307
307
  export class ${className} extends ${baseElement} {
308
308
  ${propertyDeclarations}
309
+ private _initialized = false;
310
+ ${shadowDOM ? "" : "private _slotContent: Node[] = [];"}
309
311
 
310
312
  constructor() {
311
313
  super();
312
314
  ${shadowDOM ? 'this.attachShadow({ mode: "open" });' : ""}
313
- ${template ? "this._createTemplate();" : "this._render();"}
314
315
  }
315
316
  ${templateMethod}
316
317
  ${shadowDOM ? `
@@ -330,19 +331,34 @@ ${shadowDOM ? `
330
331
  slots.forEach((slotEl) => {
331
332
  const slotName = slotEl.getAttribute('data-slot');
332
333
  if (slotName) {
333
- const slottedContent = this.querySelector(\`[slot="\${slotName}"]\`);
334
- if (slottedContent) {
334
+ const slottedContent = this._slotContent.filter(
335
+ node => node.nodeType === Node.ELEMENT_NODE && (node as Element).getAttribute('slot') === slotName
336
+ );
337
+ if (slottedContent.length > 0) {
335
338
  slotEl.innerHTML = '';
336
- slotEl.appendChild(slottedContent.cloneNode(true));
339
+ slottedContent.forEach(content => slotEl.appendChild(content));
337
340
  }
338
341
  }
339
342
  });
343
+ const defaultSlot = this.querySelector('[data-slot=""]') || this.querySelector('[data-default-slot]');
344
+ if (defaultSlot) {
345
+ const unslottedContent = this._slotContent.filter(
346
+ node => node.nodeType !== Node.ELEMENT_NODE || !(node as Element).hasAttribute('slot')
347
+ );
348
+ if (unslottedContent.length > 0) {
349
+ defaultSlot.innerHTML = '';
350
+ unslottedContent.forEach(content => defaultSlot.appendChild(content));
351
+ }
352
+ }
340
353
  }`}
341
354
  ${observedAttributesCode}
342
355
  ${gettersSetters}
343
356
 
344
357
  connectedCallback(): void {
345
- // Component connected to the DOM
358
+ if (this._initialized) return;
359
+ ${shadowDOM ? "" : "this._slotContent = Array.from(this.childNodes);"}
360
+ this._initialized = true;
361
+ ${template ? "this._createTemplate();" : "this._render();"}
346
362
  }
347
363
 
348
364
  disconnectedCallback(): void {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stacksjs/stx",
3
3
  "type": "module",
4
- "version": "0.2.96",
4
+ "version": "0.2.98",
5
5
  "description": "A performant UI Framework. Powered by Bun.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",
@@ -117,16 +117,16 @@
117
117
  "dependencies": {
118
118
  "@cwcss/crosswind": "^0.2.6",
119
119
  "@stacksjs/clapp": "^0.2.0",
120
- "@stacksjs/sanitizer": "0.2.96",
120
+ "@stacksjs/sanitizer": "0.2.98",
121
121
  "@stacksjs/ts-i18n": "^0.1.11",
122
- "bun-plugin-stx": "0.2.96",
123
- "bunfig": "^0.15.14",
124
- "stx-router": "0.2.96",
122
+ "bun-plugin-stx": "0.2.98",
123
+ "bunfig": "^0.15.15",
124
+ "stx-router": "0.2.98",
125
125
  "ts-broadcasting": "^0.0.8",
126
126
  "ts-images": "^0.1.9",
127
127
  "ts-syntax-highlighter": "^0.2.1"
128
128
  },
129
129
  "optionalDependencies": {
130
- "@stacksjs/desktop": "0.2.96"
130
+ "@stacksjs/desktop": "0.2.98"
131
131
  }
132
132
  }