malinajs 0.7.2-a7 → 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
@@ -16,6 +16,9 @@
16
16
  * refactoring $onMount
17
17
  * optional deep checking for passed props: prop={value} prop|deep={value}
18
18
  * keep-alive
19
+ * malina:self
20
+ * handler for element "select"
21
+ * handler for "radio" input
19
22
 
20
23
  ## 0.6.x
21
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 || {};');
@@ -2187,7 +2215,13 @@
2187
2215
  if(n.name == 'malina' && !option.malinaElement) {
2188
2216
  let b;
2189
2217
  if(n.elArg == 'portal') b = this.attachPortal(n);
2190
- else b = this.attachHead(n);
2218
+ else if(['window', 'body', 'head'].includes(n.elArg)) b = this.attachHead(n);
2219
+ else if(n.elArg == 'self') {
2220
+ this.glob.$$selfComponent.$value();
2221
+ const label = requireLabel();
2222
+ let component = this.makeComponent(n, {self: true});
2223
+ binds.push(insertComponent(component, label));
2224
+ } else throw 'Wrong tag';
2191
2225
  b && binds.push(b);
2192
2226
  return;
2193
2227
  }
@@ -2207,23 +2241,7 @@
2207
2241
  } else {
2208
2242
  const label = requireLabel();
2209
2243
  let component = this.makeComponent(n);
2210
- binds.push(xNode('insert-component', {
2211
- component: component.bind,
2212
- reference: component.reference,
2213
- label
2214
- }, (ctx, n) => {
2215
- if(n.reference) {
2216
- ctx.write(true, `${n.reference} = `);
2217
- ctx.add(n.component);
2218
- if(n.label.node) ctx.write(true, `$runtime.insertBlock(${n.label.name}, ${n.reference});`);
2219
- else ctx.write(true, `$runtime.addBlock(${n.label.name}, ${n.reference});`);
2220
- } else {
2221
- if(n.label.node) ctx.write(true, `$runtime.insertBlock(${n.label.name}, `);
2222
- else ctx.write(true, `$runtime.addBlock(${n.label.name}, `);
2223
- ctx.add(n.component);
2224
- ctx.write(');');
2225
- }
2226
- }));
2244
+ binds.push(insertComponent(component, label));
2227
2245
  }
2228
2246
  } else {
2229
2247
  if(isRoot) requireFragment = true;
@@ -2285,8 +2303,15 @@
2285
2303
  ctx.writeLine(`$runtime.spreadAttributes(${n.el}, () => ({${n.props.join(', ')}}));`);
2286
2304
  }));
2287
2305
  }
2306
+
2307
+ if(n.name == 'input') {
2308
+ const b = radioInput.call(this, n, el);
2309
+ b && binds.push(b);
2310
+ }
2311
+
2288
2312
  let bindTail = [];
2289
2313
  n.attributes.forEach(p => {
2314
+ if(p._skip) return;
2290
2315
  let b = this.bindProp(p, n, el);
2291
2316
  if(b) {
2292
2317
  if(b.bind) binds.push(b.bind);
@@ -2644,6 +2669,26 @@
2644
2669
  throw e;
2645
2670
  }
2646
2671
 
2672
+ function insertComponent(component, label) {
2673
+ return xNode('insert-component', {
2674
+ component: component.bind,
2675
+ reference: component.reference,
2676
+ label
2677
+ }, (ctx, n) => {
2678
+ if(n.reference) {
2679
+ ctx.write(true, `${n.reference} = `);
2680
+ ctx.add(n.component);
2681
+ if(n.label.node) ctx.write(true, `$runtime.insertBlock(${n.label.name}, ${n.reference});`);
2682
+ else ctx.write(true, `$runtime.addBlock(${n.label.name}, ${n.reference});`);
2683
+ } else {
2684
+ if(n.label.node) ctx.write(true, `$runtime.insertBlock(${n.label.name}, `);
2685
+ else ctx.write(true, `$runtime.addBlock(${n.label.name}, `);
2686
+ ctx.add(n.component);
2687
+ ctx.write(');');
2688
+ }
2689
+ })
2690
+ }
2691
+
2647
2692
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
2648
2693
 
2649
2694
  function createCommonjsModule(fn, basedir, module) {
@@ -4882,7 +4927,7 @@
4882
4927
  return result;
4883
4928
  };
4884
4929
 
4885
- function makeComponent(node) {
4930
+ function makeComponent(node, option={}) {
4886
4931
  let propList = node.attributes;
4887
4932
 
4888
4933
  this.require('$context');
@@ -4892,8 +4937,8 @@
4892
4937
  let slotBlocks = [];
4893
4938
  let anchorBlocks = [];
4894
4939
 
4895
- let componentName = node.name;
4896
- if(componentName != 'component' && this.config.autoimport) {
4940
+ let componentName = option.self ? '$$selfComponent' : node.name;
4941
+ if(componentName != 'component' && this.config.autoimport && !option.self) {
4897
4942
  let imported = this.script.autoimport[componentName] || this.script.importedNames.includes(componentName) ||
4898
4943
  this.script.rootVariables[componentName] || this.script.rootFunctions[componentName];
4899
4944
 
@@ -5390,7 +5435,7 @@
5390
5435
  ctx.write(');');
5391
5436
  })
5392
5437
  };
5393
- } else if(name == 'bind') {
5438
+ } else if(name == 'bind' && arg) {
5394
5439
  if(this.script.readOnly) {
5395
5440
  this.warning('script read-only conflicts with bind: ' + node.openTag);
5396
5441
  return;
@@ -5418,18 +5463,34 @@
5418
5463
  }
5419
5464
 
5420
5465
  assert(['value', 'checked', 'valueAsNumber', 'valueAsDate', 'selectedIndex'].includes(attr), 'Not supported: ' + prop.content);
5421
- assert(arg.length == 0);
5422
5466
  assert(detectExpressionType(exp) == 'identifier', 'Wrong bind name: ' + prop.content);
5423
- if(attr == 'value' && ['number', 'range'].includes(inputType)) attr = 'valueAsNumber';
5467
+ assert(arg.length == 0);
5424
5468
  this.detectDependency(exp);
5469
+ let argName = '$$a' + (this.uniqIndex++);
5425
5470
 
5426
- let argName = 'a' + (this.uniqIndex++);
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
+ }
5483
+
5484
+ if(attr == 'value' && ['number', 'range'].includes(inputType)) attr = 'valueAsNumber';
5427
5485
 
5428
5486
  return {
5429
5487
  bind: xNode('bindInput', {
5430
- el: element.bindName()
5488
+ el: element.bindName(),
5489
+ exp,
5490
+ attr,
5491
+ argName
5431
5492
  }, (ctx, n) => {
5432
- 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();});`);
5433
5494
  })
5434
5495
  };
5435
5496
  } else if(name == 'style' && arg) {
@@ -5661,6 +5722,17 @@
5661
5722
 
5662
5723
  if(node.spreading) return node.spreading.push(`${name}: ${exp}`);
5663
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
+
5664
5736
  const propList = {
5665
5737
  hidden: true,
5666
5738
  checked: true,
@@ -6750,7 +6822,7 @@
6750
6822
  });
6751
6823
  }
6752
6824
 
6753
- const version = '0.7.2-a7';
6825
+ const version = '0.7.2-a9';
6754
6826
 
6755
6827
 
6756
6828
  async function compile(source, config = {}) {
@@ -6805,7 +6877,8 @@
6805
6877
  rootCD: xNode('root-cd', false),
6806
6878
  apply: xNode('apply', false),
6807
6879
  componentFn: xNode('componentFn', false),
6808
- $onMount: xNode('$onMount', false)
6880
+ $onMount: xNode('$onMount', false),
6881
+ $$selfComponent: xNode('$$selfComponent', false)
6809
6882
  },
6810
6883
  require: function(...args) {
6811
6884
  for(let name of args) {
@@ -6902,10 +6975,21 @@
6902
6975
  $compile: [ctx.module.head, ctx.module.code, ctx.module.body, ctx.glob.rootCD],
6903
6976
  name: config.name,
6904
6977
  componentFn: ctx.glob.componentFn
6905
- }, (ctx, n) => {
6906
- if(config.exportDefault) ctx.write(true, 'export default ');
6907
- else ctx.write(true, `const ${n.name} = `);
6908
- ctx.add(n.componentFn);
6978
+ }, (ctx2, n) => {
6979
+ if(config.exportDefault) {
6980
+ if(ctx.glob.$$selfComponent.value) {
6981
+ ctx2.write(true, 'const $$selfComponent = ');
6982
+ ctx2.add(n.componentFn);
6983
+ ctx2.write(true, 'export default $$selfComponent;');
6984
+ } else {
6985
+ ctx2.write(true, 'export default ');
6986
+ ctx2.add(n.componentFn);
6987
+ }
6988
+ } else {
6989
+ assert(!ctx.glob.$$selfComponent.value, 'Not supported');
6990
+ ctx2.write(true, `const ${n.name} = `);
6991
+ ctx2.add(n.componentFn);
6992
+ }
6909
6993
  }));
6910
6994
 
6911
6995
  ctx.result = xBuild(result);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "malinajs",
3
- "version": "0.7.2-a7",
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 };