phoenix_live_view 1.0.17 → 1.0.18

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.
@@ -70,9 +70,25 @@ export default class DOMPatch {
70
70
  }
71
71
 
72
72
  perform(isJoinPatch){
73
- let {view, liveSocket, html, container, targetContainer} = this
73
+ let {view, liveSocket, html, container} = this
74
+ let targetContainer = this.targetContainer
74
75
  if(this.isCIDPatch() && !targetContainer){ return }
75
76
 
77
+ if(this.isCIDPatch()){
78
+ // https://github.com/phoenixframework/phoenix_live_view/pull/3942
79
+ // we need to ensure that no parent is locked
80
+ const closestLock = targetContainer.closest(`[${PHX_REF_LOCK}]`)
81
+ if(closestLock){
82
+ const clonedTree = DOM.private(closestLock, PHX_REF_LOCK)
83
+ if(clonedTree){
84
+ // if a parent is locked with a cloned tree, we need to patch the cloned tree instead
85
+ targetContainer = clonedTree.querySelector(
86
+ `[data-phx-component="${this.targetCID}"]`,
87
+ )
88
+ }
89
+ }
90
+ }
91
+
76
92
  let focused = liveSocket.getActiveElement()
77
93
  let {selectionStart, selectionEnd} = focused && DOM.hasSelectionRange(focused) ? focused : {}
78
94
  let phxUpdate = liveSocket.binding(PHX_UPDATE)
@@ -665,9 +665,13 @@ export default class View {
665
665
  })
666
666
  }
667
667
 
668
- update(diff, events){
668
+ update(diff, events, isPending=false){
669
669
  if(this.isJoinPending() || (this.liveSocket.hasPendingLink() && this.root.isMain())){
670
- return this.pendingDiffs.push({diff, events})
670
+ // don't mutate if this is already a pending diff
671
+ if(!isPending){
672
+ this.pendingDiffs.push({diff, events})
673
+ }
674
+ return false
671
675
  }
672
676
 
673
677
  this.rendered.mergeDiff(diff)
@@ -693,6 +697,8 @@ export default class View {
693
697
 
694
698
  this.liveSocket.dispatchEvents(events)
695
699
  if(phxChildrenAdded){ this.joinNewChildren() }
700
+
701
+ return true
696
702
  }
697
703
 
698
704
  renderContainer(diff, kind){
@@ -758,15 +764,13 @@ export default class View {
758
764
  }
759
765
 
760
766
  applyPendingUpdates(){
761
- // prevent race conditions where we might still be pending a new
762
- // navigation after applying the current one;
763
- // if we call update and a pendingDiff is not applied, it would
764
- // be silently dropped otherwise, as update would push it back to
765
- // pendingDiffs, but we clear it immediately after
766
- if(this.liveSocket.hasPendingLink() && this.root.isMain()){ return }
767
- this.pendingDiffs.forEach(({diff, events}) => this.update(diff, events))
768
- this.pendingDiffs = []
769
- this.eachChild(child => child.applyPendingUpdates())
767
+ // To prevent race conditions where we might still be pending a new
768
+ // navigation or the join is still pending, `this.update` returns false
769
+ // if the diff was not applied.
770
+ this.pendingDiffs = this.pendingDiffs.filter(
771
+ ({diff, events}) => !this.update(diff, events, true),
772
+ )
773
+ this.eachChild((child) => child.applyPendingUpdates())
770
774
  }
771
775
 
772
776
  eachChild(callback){
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phoenix_live_view",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
4
4
  "description": "The Phoenix LiveView JavaScript client.",
5
5
  "license": "MIT",
6
6
  "module": "./priv/static/phoenix_live_view.esm.js",
@@ -24,7 +24,7 @@
24
24
  "assets/js/phoenix_live_view/*"
25
25
  ],
26
26
  "dependencies": {
27
- "morphdom": "2.7.5"
27
+ "morphdom": "2.7.7"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@babel/cli": "7.27.0",
@@ -1675,6 +1675,10 @@ var specialElHandlers = {
1675
1675
  if (nodeName === "OPTGROUP") {
1676
1676
  optgroup = curChild;
1677
1677
  curChild = optgroup.firstChild;
1678
+ if (!curChild) {
1679
+ curChild = optgroup.nextSibling;
1680
+ optgroup = null;
1681
+ }
1678
1682
  } else {
1679
1683
  if (nodeName === "OPTION") {
1680
1684
  if (curChild.hasAttribute("selected")) {
@@ -2049,10 +2053,22 @@ var DOMPatch = class {
2049
2053
  });
2050
2054
  }
2051
2055
  perform(isJoinPatch) {
2052
- let { view, liveSocket, html, container, targetContainer } = this;
2056
+ let { view, liveSocket, html, container } = this;
2057
+ let targetContainer = this.targetContainer;
2053
2058
  if (this.isCIDPatch() && !targetContainer) {
2054
2059
  return;
2055
2060
  }
2061
+ if (this.isCIDPatch()) {
2062
+ const closestLock = targetContainer.closest(`[${PHX_REF_LOCK}]`);
2063
+ if (closestLock) {
2064
+ const clonedTree = dom_default.private(closestLock, PHX_REF_LOCK);
2065
+ if (clonedTree) {
2066
+ targetContainer = clonedTree.querySelector(
2067
+ `[data-phx-component="${this.targetCID}"]`
2068
+ );
2069
+ }
2070
+ }
2071
+ }
2056
2072
  let focused = liveSocket.getActiveElement();
2057
2073
  let { selectionStart, selectionEnd } = focused && dom_default.hasSelectionRange(focused) ? focused : {};
2058
2074
  let phxUpdate = liveSocket.binding(PHX_UPDATE);
@@ -3925,9 +3941,12 @@ var View = class _View {
3925
3941
  this.pendingJoinOps = [];
3926
3942
  });
3927
3943
  }
3928
- update(diff, events) {
3944
+ update(diff, events, isPending = false) {
3929
3945
  if (this.isJoinPending() || this.liveSocket.hasPendingLink() && this.root.isMain()) {
3930
- return this.pendingDiffs.push({ diff, events });
3946
+ if (!isPending) {
3947
+ this.pendingDiffs.push({ diff, events });
3948
+ }
3949
+ return false;
3931
3950
  }
3932
3951
  this.rendered.mergeDiff(diff);
3933
3952
  let phxChildrenAdded = false;
@@ -3951,6 +3970,7 @@ var View = class _View {
3951
3970
  if (phxChildrenAdded) {
3952
3971
  this.joinNewChildren();
3953
3972
  }
3973
+ return true;
3954
3974
  }
3955
3975
  renderContainer(diff, kind) {
3956
3976
  return this.liveSocket.time(`toString diff (${kind})`, () => {
@@ -4005,11 +4025,9 @@ var View = class _View {
4005
4025
  delete this.viewHooks[hookId];
4006
4026
  }
4007
4027
  applyPendingUpdates() {
4008
- if (this.liveSocket.hasPendingLink() && this.root.isMain()) {
4009
- return;
4010
- }
4011
- this.pendingDiffs.forEach(({ diff, events }) => this.update(diff, events));
4012
- this.pendingDiffs = [];
4028
+ this.pendingDiffs = this.pendingDiffs.filter(
4029
+ ({ diff, events }) => !this.update(diff, events, true)
4030
+ );
4013
4031
  this.eachChild((child) => child.applyPendingUpdates());
4014
4032
  }
4015
4033
  eachChild(callback) {
@@ -4865,7 +4883,7 @@ var LiveSocket = class {
4865
4883
  }
4866
4884
  // public
4867
4885
  version() {
4868
- return "1.0.17";
4886
+ return "1.0.18";
4869
4887
  }
4870
4888
  isProfileEnabled() {
4871
4889
  return this.sessionStorage.getItem(PHX_LV_PROFILE) === "true";