rip-lang 3.13.30 → 3.13.32

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.
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rip-lang",
3
- "version": "3.13.30",
3
+ "version": "3.13.32",
4
4
  "description": "A modern language that compiles to JavaScript",
5
5
  "type": "module",
6
6
  "main": "src/compiler.js",
package/src/components.js CHANGED
@@ -700,7 +700,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
700
700
  for (const { name, value, isPublic } of stateVars) {
701
701
  const val = this.generateInComponent(value, 'value');
702
702
  lines.push(isPublic
703
- ? ` this.${name} = __state(props.${name} ?? ${val});`
703
+ ? ` this.${name} = __state(props.__bind_${name}__ ?? props.${name} ?? ${val});`
704
704
  : ` this.${name} = __state(${val});`);
705
705
  }
706
706
 
@@ -952,6 +952,14 @@ export function installComponentSupport(CodeGenerator, Lexer) {
952
952
  return this.generateChildComponent(headStr, rest);
953
953
  }
954
954
 
955
+ // Slot projection — replace <slot> with @children in component render
956
+ if (headStr === 'slot' && this.componentMembers) {
957
+ const s = this._self;
958
+ const slotVar = this.newElementVar('slot');
959
+ this._createLines.push(`${slotVar} = ${s}.children instanceof Node ? ${s}.children : (${s}.children != null ? document.createTextNode(String(${s}.children)) : document.createComment(''));`);
960
+ return slotVar;
961
+ }
962
+
955
963
  // HTML tag (possibly with #id, e.g. div#content)
956
964
  if (headStr && this.isHtmlTag(headStr)) {
957
965
  let [tagName, id] = headStr.split('#');
@@ -1636,13 +1644,18 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1636
1644
  this._pendingAutoWire = false;
1637
1645
  const instVar = this.newElementVar('inst');
1638
1646
  const elVar = this.newElementVar('el');
1639
- const { propsCode, reactiveProps, childrenSetupLines } = this.buildComponentProps(args);
1647
+ const { propsCode, reactiveProps, eventBindings, childrenSetupLines } = this.buildComponentProps(args);
1640
1648
 
1641
1649
  const s = this._self;
1642
1650
  this._createLines.push(`${instVar} = new ${componentName}(${propsCode});`);
1643
- this._createLines.push(`${elVar} = ${instVar}._create();`);
1651
+ this._createLines.push(`${elVar} = ${instVar}._root = ${instVar}._create();`);
1644
1652
  this._createLines.push(`(${s}._children || (${s}._children = [])).push(${instVar});`);
1645
1653
 
1654
+ for (const { event, value } of eventBindings) {
1655
+ const handlerCode = this.generateInComponent(value, 'value');
1656
+ this._createLines.push(`${elVar}.addEventListener('${event}', (e) => __batch(() => (${handlerCode})(e)));`);
1657
+ }
1658
+
1646
1659
  this._setupLines.push(`try { if (${instVar}._setup) ${instVar}._setup(); if (${instVar}.mounted) ${instVar}.mounted(); } catch (__e) { __handleComponentError(__e, ${instVar}); }`);
1647
1660
 
1648
1661
  for (const { key, valueCode } of reactiveProps) {
@@ -1663,12 +1676,17 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1663
1676
  proto.buildComponentProps = function(args) {
1664
1677
  const props = [];
1665
1678
  const reactiveProps = [];
1679
+ const eventBindings = [];
1666
1680
  let childrenVar = null;
1667
1681
  const childrenSetupLines = [];
1668
1682
 
1669
1683
  // Simple reactive values pass the signal directly for shared reactivity;
1670
1684
  // complex expressions use normal .value unwrapping to compute the value.
1671
1685
  const addProp = (key, value) => {
1686
+ if (key.startsWith('@')) {
1687
+ eventBindings.push({ event: key.slice(1).split('.')[0], value });
1688
+ return;
1689
+ }
1672
1690
  const isDirectSignal = this.reactiveMembers && (
1673
1691
  (typeof value === 'string' && this.reactiveMembers.has(value)) ||
1674
1692
  (Array.isArray(value) && value[0] === '.' && value[1] === 'this' && typeof value[2] === 'string' && this.reactiveMembers.has(value[2]))
@@ -1688,7 +1706,11 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1688
1706
  const addObjectProps = (objExpr) => {
1689
1707
  for (let i = 1; i < objExpr.length; i++) {
1690
1708
  const [key, value] = objExpr[i];
1691
- if (typeof key === 'string') addProp(key, value);
1709
+ if (typeof key === 'string') {
1710
+ addProp(key, value);
1711
+ } else if (Array.isArray(key) && key[0] === '.' && key[1] === 'this' && typeof key[2] === 'string') {
1712
+ eventBindings.push({ event: key[2], value });
1713
+ }
1692
1714
  }
1693
1715
  };
1694
1716
 
@@ -1735,7 +1757,7 @@ export function installComponentSupport(CodeGenerator, Lexer) {
1735
1757
  }
1736
1758
 
1737
1759
  const propsCode = props.length > 0 ? `{ ${props.join(', ')} }` : '{}';
1738
- return { propsCode, reactiveProps, childrenSetupLines };
1760
+ return { propsCode, reactiveProps, eventBindings, childrenSetupLines };
1739
1761
  };
1740
1762
 
1741
1763
  // --------------------------------------------------------------------------
@@ -2075,6 +2097,11 @@ class __Component {
2075
2097
  this._root.parentNode.removeChild(this._root);
2076
2098
  }
2077
2099
  }
2100
+ emit(name, detail) {
2101
+ if (this._root) {
2102
+ this._root.dispatchEvent(new CustomEvent(name, { detail, bubbles: true }));
2103
+ }
2104
+ }
2078
2105
  static mount(target = 'body') {
2079
2106
  return new this().mount(target);
2080
2107
  }