experimental-hydrate-support.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. /**
  2. * @license
  3. * Copyright 2017 Google LLC
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. import { render } from 'lit-html';
  7. import { hydrate } from 'lit-html/experimental-hydrate.js';
  8. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  9. globalThis.litElementHydrateSupport = ({ LitElement, }) => {
  10. const observedAttributes = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(LitElement), 'observedAttributes').get;
  11. // Add `defer-hydration` to observedAttributes
  12. Object.defineProperty(LitElement, 'observedAttributes', {
  13. get() {
  14. return [...observedAttributes.call(this), 'defer-hydration'];
  15. },
  16. });
  17. // Enable element when 'defer-hydration' attribute is removed by calling the
  18. // super.connectedCallback()
  19. const attributeChangedCallback = LitElement.prototype.attributeChangedCallback;
  20. LitElement.prototype.attributeChangedCallback = function (name, old, value) {
  21. if (name === 'defer-hydration' && value === null) {
  22. connectedCallback.call(this);
  23. }
  24. attributeChangedCallback.call(this, name, old, value);
  25. };
  26. // Override `connectedCallback` to capture whether we need hydration, and
  27. // defer `super.connectedCallback()` if the 'defer-hydration' attribute is set
  28. const connectedCallback = LitElement.prototype.connectedCallback;
  29. LitElement.prototype.connectedCallback = function () {
  30. // If the outer scope of this element has not yet been hydrated, wait until
  31. // 'defer-hydration' attribute has been removed to enable
  32. if (!this.hasAttribute('defer-hydration')) {
  33. connectedCallback.call(this);
  34. }
  35. };
  36. // If we've been server-side rendered, just return `this.shadowRoot`, don't
  37. // call the base implementation, which would also adopt styles (for now)
  38. const createRenderRoot = LitElement.prototype.createRenderRoot;
  39. LitElement.prototype.createRenderRoot = function () {
  40. if (this.shadowRoot) {
  41. this._$needsHydration = true;
  42. return this.shadowRoot;
  43. }
  44. else {
  45. return createRenderRoot.call(this);
  46. }
  47. };
  48. // Hydrate on first update when needed
  49. const update = Object.getPrototypeOf(LitElement.prototype).update;
  50. LitElement.prototype.update = function (changedProperties) {
  51. const value = this.render();
  52. // Since this is a patch, we can't call super.update(), so we capture
  53. // it off the proto chain and call it instead
  54. update.call(this, changedProperties);
  55. if (this._$needsHydration) {
  56. this._$needsHydration = false;
  57. hydrate(value, this.renderRoot, this.renderOptions);
  58. }
  59. else {
  60. render(value, this.renderRoot, this.renderOptions);
  61. }
  62. };
  63. };
  64. //# sourceMappingURL=experimental-hydrate-support.js.map