malinajs 0.7.2-a8 → 0.7.2-a9

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.
package/CHANGELOG.md CHANGED
@@ -17,6 +17,8 @@
17
17
  * optional deep checking for passed props: prop={value} prop|deep={value}
18
18
  * keep-alive
19
19
  * malina:self
20
+ * handler for element "select"
21
+ * handler for "radio" input
20
22
 
21
23
  ## 0.6.x
22
24
 
package/malina.js CHANGED
@@ -1852,6 +1852,34 @@
1852
1852
  });
1853
1853
  };
1854
1854
 
1855
+ function radioInput(node, el) {
1856
+ assert(node.name == 'input');
1857
+ const aType = node.attributes.find(a => a.name == 'type');
1858
+ if(!aType || aType.value != 'radio') return null;
1859
+ const aName = node.attributes.find(a => a.name == 'name');
1860
+ if(!aName.value.startsWith('{')) return null;
1861
+ const aValue = node.attributes.find(a => a.name == 'value');
1862
+
1863
+ aName._skip = true;
1864
+ aValue._skip = true;
1865
+
1866
+ const name = unwrapExp(aName.value);
1867
+ assert(detectExpressionType(name) == 'identifier', 'Wrong name for radio input');
1868
+ let value = aValue.value;
1869
+ if(value.match(/^\{.+\}$/)) value = unwrapExp(aValue.value);
1870
+ else value = '`' + value + '`';
1871
+
1872
+ this.require('apply');
1873
+
1874
+ return xNode('radioInput', {
1875
+ name,
1876
+ value,
1877
+ el: el.bindName()
1878
+ }, (ctx, n) => {
1879
+ ctx.write(true, `$runtime.radioButton(${n.el}, () => (${n.value}), () => (${n.name}), ($$) => {${n.name} = $$; $$apply();});`);
1880
+ });
1881
+ }
1882
+
1855
1883
  function buildRuntime() {
1856
1884
  this.module.head.push(xNode('$events', (ctx) => {
1857
1885
  if(this.inuse.$events) ctx.write(true, 'const $events = $option.events || {};');
@@ -2275,8 +2303,15 @@
2275
2303
  ctx.writeLine(`$runtime.spreadAttributes(${n.el}, () => ({${n.props.join(', ')}}));`);
2276
2304
  }));
2277
2305
  }
2306
+
2307
+ if(n.name == 'input') {
2308
+ const b = radioInput.call(this, n, el);
2309
+ b && binds.push(b);
2310
+ }
2311
+
2278
2312
  let bindTail = [];
2279
2313
  n.attributes.forEach(p => {
2314
+ if(p._skip) return;
2280
2315
  let b = this.bindProp(p, n, el);
2281
2316
  if(b) {
2282
2317
  if(b.bind) binds.push(b.bind);
@@ -5400,7 +5435,7 @@
5400
5435
  ctx.write(');');
5401
5436
  })
5402
5437
  };
5403
- } else if(name == 'bind') {
5438
+ } else if(name == 'bind' && arg) {
5404
5439
  if(this.script.readOnly) {
5405
5440
  this.warning('script read-only conflicts with bind: ' + node.openTag);
5406
5441
  return;
@@ -5428,18 +5463,34 @@
5428
5463
  }
5429
5464
 
5430
5465
  assert(['value', 'checked', 'valueAsNumber', 'valueAsDate', 'selectedIndex'].includes(attr), 'Not supported: ' + prop.content);
5431
- assert(arg.length == 0);
5432
5466
  assert(detectExpressionType(exp) == 'identifier', 'Wrong bind name: ' + prop.content);
5433
- if(attr == 'value' && ['number', 'range'].includes(inputType)) attr = 'valueAsNumber';
5467
+ assert(arg.length == 0);
5434
5468
  this.detectDependency(exp);
5469
+ let argName = '$$a' + (this.uniqIndex++);
5470
+
5471
+ if(node.name == 'select' && attr == 'value') {
5472
+ return {
5473
+ bind: xNode('bindInput', {
5474
+ el: element.bindName(),
5475
+ exp,
5476
+ attr,
5477
+ argName
5478
+ }, (ctx, n) => {
5479
+ ctx.write(true, `$runtime.selectElement(${n.el}, () => ${n.exp}, ${n.argName} => {${n.exp} = ${n.argName}; $$apply();});`);
5480
+ })
5481
+ }
5482
+ }
5435
5483
 
5436
- let argName = 'a' + (this.uniqIndex++);
5484
+ if(attr == 'value' && ['number', 'range'].includes(inputType)) attr = 'valueAsNumber';
5437
5485
 
5438
5486
  return {
5439
5487
  bind: xNode('bindInput', {
5440
- el: element.bindName()
5488
+ el: element.bindName(),
5489
+ exp,
5490
+ attr,
5491
+ argName
5441
5492
  }, (ctx, n) => {
5442
- ctx.writeLine(`$runtime.bindInput(${n.el}, '${attr}', () => ${exp}, ${argName} => {${exp} = ${argName}; $$apply();});`);
5493
+ ctx.write(true, `$runtime.bindInput(${n.el}, '${n.attr}', () => ${n.exp}, ${n.argName} => {${n.exp} = ${n.argName}; $$apply();});`);
5443
5494
  })
5444
5495
  };
5445
5496
  } else if(name == 'style' && arg) {
@@ -5671,6 +5722,17 @@
5671
5722
 
5672
5723
  if(node.spreading) return node.spreading.push(`${name}: ${exp}`);
5673
5724
 
5725
+ if(node.name == 'option' && name == 'value') {
5726
+ return {
5727
+ bind: xNode('bindOptionValue', {
5728
+ el: element.bindName(),
5729
+ exp
5730
+ }, (ctx, n) => {
5731
+ ctx.write(true, `$runtime.selectOption(${n.el}, () => (${n.exp}));`);
5732
+ })
5733
+ }
5734
+ }
5735
+
5674
5736
  const propList = {
5675
5737
  hidden: true,
5676
5738
  checked: true,
@@ -6760,7 +6822,7 @@
6760
6822
  });
6761
6823
  }
6762
6824
 
6763
- const version = '0.7.2-a8';
6825
+ const version = '0.7.2-a9';
6764
6826
 
6765
6827
 
6766
6828
  async function compile(source, config = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "malinajs",
3
- "version": "0.7.2-a8",
3
+ "version": "0.7.2-a9",
4
4
  "license": "MIT",
5
5
  "scripts": {
6
6
  "prepare": "npm run build",
package/runtime.js CHANGED
@@ -1285,4 +1285,37 @@ const keepAlive = (store, keyFn, builder) => {
1285
1285
  }
1286
1286
  };
1287
1287
 
1288
- export { $$eachBlock, $context, $digest, $onDestroy, $onMount, $tick, $watch, WatchObject, __app_onerror, __bindActionSubscribe, addBlock, addClass, addEvent, addStyles, attachAnchor, attachBlock, attachDynComponent, autoSubscribe, awaitBlock, bindAction, bindAttribute, bindAttributeBase, bindClass, bindClassExp, bindInput, bindStyle, bindText, callComponent, callComponentDyn, callExportedFragment, cd_attach, cd_component, cd_detach, cd_new, cloneDeep, compareArray, compareDeep, configure, createTextNode, current_cd, current_component, current_destroyList, current_mountList, deepComparator, destroyResults, eachDefaultKey, exportFragment, fire, htmlBlock, htmlBlockStatic, htmlToFragment, htmlToFragmentClean, ifBlock, ifBlockReadOnly, insertAfter, insertBlock, invokeSlot, invokeSlotBase, isArray, isFunction, iterNodes, keepAlive, keyComparator, makeAnchor, makeApply, makeBlock, makeBlockBound, makeClassResolver, makeComponent, makeEachBlock, makeEachElseBlock, makeEachSingleBlock, makeEmitter, makeExternalProperty, makeRootEvent, makeSlot, mergeAllEvents, mergeEvents, mount, mountStatic, noop, prefixPush, refer, removeElements, removeItem, setClassToElement, spreadAttributes, svgToFragment, unwrapProps };
1288
+ const selectElement = (el, getter, setter) => {
1289
+ addEvent(el, 'change', () => {
1290
+ let op = el.querySelector(':checked');
1291
+ if(op?.$$value) {
1292
+ let value = op.$$value();
1293
+ setter(value);
1294
+ w.value = value;
1295
+ }
1296
+ });
1297
+ let w = $watch(getter, (value) => {
1298
+ for(let op of el.options) {
1299
+ if(op.$$value?.() === value) {
1300
+ op.selected = true;
1301
+ return;
1302
+ }
1303
+ }
1304
+ el.selectedIndex = -1;
1305
+ });
1306
+ };
1307
+
1308
+ const selectOption = (op, getter) => {
1309
+ op.$$value = getter;
1310
+ };
1311
+
1312
+ const radioButton = (el, getValue, getter, setter) => {
1313
+ let w = $watch(getter, (value) => {
1314
+ el.checked = getValue() === value;
1315
+ });
1316
+ addEvent(el, 'change', () => {
1317
+ if(el.checked) setter(w.value = getValue());
1318
+ });
1319
+ };
1320
+
1321
+ export { $$eachBlock, $context, $digest, $onDestroy, $onMount, $tick, $watch, WatchObject, __app_onerror, __bindActionSubscribe, addBlock, addClass, addEvent, addStyles, attachAnchor, attachBlock, attachDynComponent, autoSubscribe, awaitBlock, bindAction, bindAttribute, bindAttributeBase, bindClass, bindClassExp, bindInput, bindStyle, bindText, callComponent, callComponentDyn, callExportedFragment, cd_attach, cd_component, cd_detach, cd_new, cloneDeep, compareArray, compareDeep, configure, createTextNode, current_cd, current_component, current_destroyList, current_mountList, deepComparator, destroyResults, eachDefaultKey, exportFragment, fire, htmlBlock, htmlBlockStatic, htmlToFragment, htmlToFragmentClean, ifBlock, ifBlockReadOnly, insertAfter, insertBlock, invokeSlot, invokeSlotBase, isArray, isFunction, iterNodes, keepAlive, keyComparator, makeAnchor, makeApply, makeBlock, makeBlockBound, makeClassResolver, makeComponent, makeEachBlock, makeEachElseBlock, makeEachSingleBlock, makeEmitter, makeExternalProperty, makeRootEvent, makeSlot, mergeAllEvents, mergeEvents, mount, mountStatic, noop, prefixPush, radioButton, refer, removeElements, removeItem, selectElement, selectOption, setClassToElement, spreadAttributes, svgToFragment, unwrapProps };