@wcstack/state 1.3.19 → 1.4.0

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/dist/index.esm.js CHANGED
@@ -1121,6 +1121,7 @@ function parseFilterArgs(argsText) {
1121
1121
  const args = [];
1122
1122
  let current = '';
1123
1123
  let inQuote = null;
1124
+ let hasQuote = false;
1124
1125
  for (let i = 0; i < argsText.length; i++) {
1125
1126
  const char = argsText[i];
1126
1127
  if (inQuote) {
@@ -1133,17 +1134,20 @@ function parseFilterArgs(argsText) {
1133
1134
  }
1134
1135
  else if (char === '"' || char === "'") {
1135
1136
  inQuote = char;
1137
+ hasQuote = true;
1136
1138
  }
1137
1139
  else if (char === ',') {
1138
1140
  args.push(current.trim());
1139
1141
  current = '';
1142
+ hasQuote = false;
1140
1143
  }
1141
1144
  else {
1142
1145
  current += char;
1143
1146
  }
1144
1147
  }
1145
- if (current.trim()) {
1146
- args.push(current.trim());
1148
+ const last = current.trim();
1149
+ if (last || hasQuote) {
1150
+ args.push(last);
1147
1151
  }
1148
1152
  return args;
1149
1153
  }
@@ -1670,10 +1674,9 @@ function isPossibleTwoWay(node, propName) {
1670
1674
  if (typeof customClass === "undefined") {
1671
1675
  raiseError(`Custom element <${customTagName}> is not defined. Cannot determine if property "${propName}" is suitable for two-way binding.`);
1672
1676
  }
1673
- const reactivityInfo = customClass.wcsReactivity;
1674
- if (reactivityInfo) {
1675
- if (reactivityInfo.properties?.includes(propName)
1676
- || (reactivityInfo.propertyMap?.[propName] ?? null) !== null) {
1677
+ const bindable = customClass.wcBindable;
1678
+ if (bindable?.protocol === "wc-bindable" && bindable?.version === 1) {
1679
+ if (bindable.properties.some(p => p.name === propName)) {
1677
1680
  return true;
1678
1681
  }
1679
1682
  }
@@ -1683,28 +1686,27 @@ function isPossibleTwoWay(node, propName) {
1683
1686
 
1684
1687
  const handlerByHandlerKey$2 = new Map();
1685
1688
  const bindingSetByHandlerKey$2 = new Map();
1686
- function getHandlerKey$2(binding, eventName) {
1689
+ const DEFAULT_GETTER = (e) => e.detail;
1690
+ function getHandlerKey$2(binding, eventName, hasGetter) {
1687
1691
  const filterKey = binding.inFilters.map(f => f.filterName + '(' + f.args.join(',') + ')').join('|');
1688
- return `${binding.stateName}::${binding.propName}::${binding.statePathName}::${eventName}::${filterKey}`;
1692
+ return `${binding.stateName}::${binding.propName}::${binding.statePathName}::${eventName}::${filterKey}::${hasGetter ? 'g' : 'n'}`;
1689
1693
  }
1690
1694
  function getEventName$2(binding) {
1691
1695
  const tagName = binding.node.tagName.toLowerCase();
1692
1696
  // 1.default event name
1693
1697
  let eventName = (tagName === 'select') ? 'change' : 'input';
1694
- // 2.protocol
1698
+ // 2.wcBindable protocol
1695
1699
  const customTagName = getCustomElement(binding.node);
1696
1700
  if (customTagName !== null) {
1697
1701
  const customClass = customElements.get(customTagName);
1698
1702
  if (typeof customClass === "undefined") {
1699
1703
  raiseError(`Custom element <${customTagName}> is not defined. Cannot determine event name for two-way binding.`);
1700
1704
  }
1701
- const reactivityInfo = customClass.wcsReactivity;
1702
- if (reactivityInfo) {
1703
- if (reactivityInfo.properties?.includes(binding.propName)) {
1704
- eventName = reactivityInfo.defaultEvent;
1705
- }
1706
- if (reactivityInfo.propertyMap?.[binding.propName]) {
1707
- eventName = reactivityInfo.propertyMap[binding.propName];
1705
+ const bindable = customClass.wcBindable;
1706
+ if (bindable?.protocol === "wc-bindable" && bindable?.version === 1) {
1707
+ const propDesc = bindable.properties.find(p => p.name === binding.propName);
1708
+ if (propDesc) {
1709
+ eventName = propDesc.event;
1708
1710
  }
1709
1711
  }
1710
1712
  }
@@ -1716,17 +1718,39 @@ function getEventName$2(binding) {
1716
1718
  }
1717
1719
  return eventName;
1718
1720
  }
1719
- const twowayEventHandlerFunction = (stateName, propName, statePathName, inFilters) => (event) => {
1721
+ function getValueGetter(binding) {
1722
+ const customTagName = getCustomElement(binding.node);
1723
+ if (customTagName !== null) {
1724
+ const customClass = customElements.get(customTagName);
1725
+ if (customClass) {
1726
+ const bindable = customClass.wcBindable;
1727
+ if (bindable?.protocol === "wc-bindable" && bindable?.version === 1) {
1728
+ const propDesc = bindable.properties.find(p => p.name === binding.propName);
1729
+ if (propDesc) {
1730
+ return propDesc.getter ?? DEFAULT_GETTER;
1731
+ }
1732
+ }
1733
+ }
1734
+ }
1735
+ return null;
1736
+ }
1737
+ const twowayEventHandlerFunction = (stateName, propName, statePathName, inFilters, valueGetter) => (event) => {
1720
1738
  const node = event.target;
1721
1739
  if (node === null) {
1722
1740
  console.warn(`[@wcstack/state] event.target is null.`);
1723
1741
  return;
1724
1742
  }
1725
- if (!(propName in node)) {
1726
- console.warn(`[@wcstack/state] Property "${propName}" does not exist on target element.`);
1727
- return;
1743
+ let newValue;
1744
+ if (valueGetter !== null) {
1745
+ newValue = valueGetter(event);
1746
+ }
1747
+ else {
1748
+ if (!(propName in node)) {
1749
+ console.warn(`[@wcstack/state] Property "${propName}" does not exist on target element.`);
1750
+ return;
1751
+ }
1752
+ newValue = node[propName];
1728
1753
  }
1729
- const newValue = node[propName];
1730
1754
  let filteredNewValue = newValue;
1731
1755
  for (const filter of inFilters) {
1732
1756
  filteredNewValue = filter.filterFn(filteredNewValue);
@@ -1756,10 +1780,11 @@ function attachTwowayEventHandler(binding) {
1756
1780
  }
1757
1781
  if (isPossibleTwoWay(binding.node, binding.propName) && binding.propModifiers.indexOf('ro') === -1) {
1758
1782
  const eventName = getEventName$2(binding);
1759
- const key = getHandlerKey$2(binding, eventName);
1783
+ const valueGetter = getValueGetter(binding);
1784
+ const key = getHandlerKey$2(binding, eventName, valueGetter !== null);
1760
1785
  let twowayEventHandler = handlerByHandlerKey$2.get(key);
1761
1786
  if (typeof twowayEventHandler === "undefined") {
1762
- twowayEventHandler = twowayEventHandlerFunction(binding.stateName, binding.propName, binding.statePathName, binding.inFilters);
1787
+ twowayEventHandler = twowayEventHandlerFunction(binding.stateName, binding.propName, binding.statePathName, binding.inFilters, valueGetter);
1763
1788
  handlerByHandlerKey$2.set(key, twowayEventHandler);
1764
1789
  }
1765
1790
  binding.node.addEventListener(eventName, twowayEventHandler);
@@ -2855,7 +2880,18 @@ function applyChangeToProperty(binding, _context, newValue) {
2855
2880
  if (propSegments.length === 1) {
2856
2881
  const firstSegment = propSegments[0];
2857
2882
  if (element[firstSegment] !== newValue) {
2858
- element[firstSegment] = newValue;
2883
+ try {
2884
+ element[firstSegment] = newValue;
2885
+ }
2886
+ catch (error) {
2887
+ if (config.debug) {
2888
+ console.warn(`Failed to set property '${firstSegment}' on element.`, {
2889
+ element,
2890
+ newValue,
2891
+ error
2892
+ });
2893
+ }
2894
+ }
2859
2895
  }
2860
2896
  return;
2861
2897
  }
@@ -2881,7 +2917,20 @@ function applyChangeToProperty(binding, _context, newValue) {
2881
2917
  }
2882
2918
  return;
2883
2919
  }
2884
- subObject[propSegments[propSegments.length - 1]] = newValue;
2920
+ try {
2921
+ subObject[propSegments[propSegments.length - 1]] = newValue;
2922
+ }
2923
+ catch (error) {
2924
+ if (config.debug) {
2925
+ console.warn(`Failed to set property on sub-object.`, {
2926
+ element,
2927
+ propSegments,
2928
+ oldValue,
2929
+ newValue,
2930
+ error
2931
+ });
2932
+ }
2933
+ }
2885
2934
  }
2886
2935
  }
2887
2936
 
@@ -5532,7 +5581,7 @@ class State extends HTMLElement {
5532
5581
  else {
5533
5582
  const script = this.querySelector('script[type="module"]');
5534
5583
  if (script) {
5535
- this._state = await loadFromInnerScript(script, `state#${this._name}`);
5584
+ this._state = await loadFromInnerScript(script, `${this._name}`);
5536
5585
  }
5537
5586
  else {
5538
5587
  const timerId = setTimeout(() => {