@sprlab/wccompiler 0.16.4 → 0.16.6

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/lib/codegen.js +24 -3
  2. package/package.json +1 -1
package/lib/codegen.js CHANGED
@@ -1596,8 +1596,9 @@ export function generateComponent(parseResult, options = {}) {
1596
1596
  lines.push(' }));');
1597
1597
  } else {
1598
1598
  // String expression: set className
1599
+ // Wrap ternary/logical expressions to prevent precedence issues
1599
1600
  lines.push(' this.__disposers.push(__effect(() => {');
1600
- lines.push(` this.${ab.varName}.className = ${expr};`);
1601
+ lines.push(` this.${ab.varName}.className = ${wrapTernaryExpr(expr)};`);
1601
1602
  lines.push(' }));');
1602
1603
  }
1603
1604
  } else if (ab.kind === 'style') {
@@ -1939,8 +1940,10 @@ export function generateComponent(parseResult, options = {}) {
1939
1940
  // _modelSet methods (one per defineModel prop — emits events on internal write)
1940
1941
  // Emits:
1941
1942
  // 1. wcc:model — canonical event for vanilla JS, WCC-to-WCC, React adapter, Vue plugin
1942
- // 2. propNameChange — for Angular [(prop)] banana-box syntax (zero-config)
1943
+ // 2. propName-changedkebab-case for Web Components standard and parent listeners
1943
1944
  for (const md of modelDefs) {
1945
+ // Convert camelCase to kebab-case for event name (e.g., userName → user-name-changed)
1946
+ const eventName = md.name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() + '-changed';
1944
1947
  lines.push(` _modelSet_${md.name}(newVal) {`);
1945
1948
  lines.push(` const oldVal = this._m_${md.name}();`);
1946
1949
  lines.push(` this._m_${md.name}(newVal);`);
@@ -1949,11 +1952,29 @@ export function generateComponent(parseResult, options = {}) {
1949
1952
  lines.push(` bubbles: true,`);
1950
1953
  lines.push(` composed: true`);
1951
1954
  lines.push(` }));`);
1952
- lines.push(` this.dispatchEvent(new CustomEvent('${md.name}Change', { detail: newVal, bubbles: true }));`);
1955
+ lines.push(` this.dispatchEvent(new CustomEvent('${eventName}', { detail: newVal, bubbles: true }));`);
1953
1956
  lines.push(' }');
1954
1957
  lines.push('');
1955
1958
  }
1956
1959
 
1960
+ // Wrapper methods for defineModel signals (dual getter/setter)
1961
+ // These act as the interface between template code and internal signals
1962
+ // - As getter (no args): returns signal value
1963
+ // - As setter (with arg): calls _modelSet_* to update and dispatch events
1964
+ if (modelDefs.length > 0) {
1965
+ lines.push(' // --- Model wrapper methods ---');
1966
+ for (const md of modelDefs) {
1967
+ lines.push(` _${md.name}(val) {`);
1968
+ lines.push(` if (arguments.length === 0) {`);
1969
+ lines.push(` return this._m_${md.name}();`);
1970
+ lines.push(` } else {`);
1971
+ lines.push(` this._modelSet_${md.name}(val);`);
1972
+ lines.push(` }`);
1973
+ lines.push(` }`);
1974
+ lines.push('');
1975
+ }
1976
+ }
1977
+
1957
1978
  // __scopedSlots instance getter and registerSlotRenderer (if scoped slots exist)
1958
1979
  if (scopedSlotNames.length > 0) {
1959
1980
  lines.push(' get __scopedSlots() { return this.constructor.__scopedSlots || []; }');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprlab/wccompiler",
3
- "version": "0.16.4",
3
+ "version": "0.16.6",
4
4
  "description": "Zero-runtime compiler that transforms .wcc single-file components into native web components with signals-based reactivity",
5
5
  "type": "module",
6
6
  "exports": {