@einblick/sdk 0.6.0 → 0.6.2

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.
@@ -83,6 +83,9 @@ function isTextInputEvent(event) {
83
83
  event.key === 'Backspace' ||
84
84
  event.key === 'Delete');
85
85
  }
86
+ function isRecordEditableBinding(binding) {
87
+ return Boolean(binding?.recordId);
88
+ }
86
89
  function fieldTypeAllowsMultiline(binding) {
87
90
  return binding.fieldType === 'text' || binding.fieldType === 'markdown';
88
91
  }
@@ -110,43 +113,41 @@ function injectRuntimeStyles() {
110
113
  scroll-margin-top: 96px;
111
114
  }
112
115
 
113
- [data-einblick-edit-outline],
114
- [data-einblick-edit-field-outline] {
115
- position: fixed;
116
- z-index: 2147483643;
117
- box-sizing: border-box;
118
- pointer-events: none;
119
- border-radius: var(--einblick-overlay-radius, 0.35rem);
116
+ [data-einblick-editable="true"][data-einblick-hover-active="true"] {
117
+ outline: 1px solid ${EINBLICK_ACCENT_BORDER};
118
+ outline-offset: -1px;
119
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.72);
120
120
  }
121
121
 
122
- [data-einblick-edit-outline] {
123
- border: 1px solid ${EINBLICK_ACCENT_BORDER};
124
- box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.7);
122
+ [data-einblick-editable="true"][data-einblick-field-hover-active="true"] {
123
+ outline: 1px dashed rgba(${EINBLICK_ACCENT_RGB}, 0.78);
124
+ outline-offset: -1px;
125
125
  }
126
126
 
127
- [data-einblick-edit-field-outline] {
128
- border: 1px dashed rgba(${EINBLICK_ACCENT_RGB}, 0.78);
129
- background: rgba(${EINBLICK_ACCENT_RGB}, 0.04);
127
+ [data-einblick-editable="true"][data-einblick-inline-editing="true"] {
128
+ outline: 2px solid ${EINBLICK_ACCENT_COLOR};
129
+ outline-offset: -2px;
130
130
  }
131
131
 
132
132
  [data-einblick-edit-controls] {
133
- position: fixed;
133
+ position: absolute;
134
134
  z-index: 2147483644;
135
135
  display: inline-flex;
136
136
  align-items: center;
137
- gap: 0.45rem;
137
+ gap: 0;
138
138
  }
139
139
 
140
140
  [data-einblick-edit-button],
141
141
  [data-einblick-create-button],
142
142
  [data-einblick-field-button] {
143
143
  border: 1px solid ${EINBLICK_ACCENT_COLOR};
144
- border-radius: 999px;
145
- padding: 0.3rem 0.7rem;
144
+ border-radius: 0;
145
+ min-height: 2rem;
146
+ padding: 0 0.72rem;
146
147
  font: 600 12px/1 system-ui, sans-serif;
147
- letter-spacing: 0.01em;
148
+ letter-spacing: 0;
148
149
  cursor: pointer;
149
- box-shadow: 0 8px 20px rgba(15, 23, 42, 0.16);
150
+ box-shadow: 0 8px 18px rgba(15, 23, 42, 0.16);
150
151
  }
151
152
 
152
153
  [data-einblick-edit-button],
@@ -156,7 +157,6 @@ function injectRuntimeStyles() {
156
157
  }
157
158
 
158
159
  [data-einblick-edit-button] {
159
- padding: 0.42rem 0.85rem;
160
160
  font-size: 13px;
161
161
  }
162
162
 
@@ -174,19 +174,19 @@ function injectRuntimeStyles() {
174
174
  }
175
175
 
176
176
  [data-einblick-field-overlays] {
177
- position: fixed;
178
- inset: 0;
177
+ position: absolute;
178
+ left: 0;
179
+ top: 0;
179
180
  z-index: 2147483644;
180
181
  pointer-events: none;
181
182
  }
182
183
 
183
184
  [data-einblick-field-button] {
184
- position: fixed;
185
+ position: absolute;
185
186
  z-index: 2147483644;
186
187
  pointer-events: auto;
187
- padding: 0.24rem 0.58rem;
188
188
  font-size: 11px;
189
- box-shadow: 0 8px 18px rgba(15, 23, 42, 0.12);
189
+ min-height: 1.65rem;
190
190
  }
191
191
 
192
192
  [data-einblick-brand-badge] {
@@ -431,7 +431,6 @@ class EinblickEditRuntime {
431
431
  bridgeFrame = null;
432
432
  bridgePingInterval = null;
433
433
  activeElement = null;
434
- activeOutline = null;
435
434
  hoverButtonContainer = null;
436
435
  hoverButton = null;
437
436
  hoverCreateButton = null;
@@ -570,8 +569,6 @@ class EinblickEditRuntime {
570
569
  this.bridgeFrame?.remove();
571
570
  this.bridgeFrame = null;
572
571
  this.setActiveElement(null);
573
- this.activeOutline?.remove();
574
- this.activeOutline = null;
575
572
  this.hoverButtonContainer?.remove();
576
573
  this.hoverButtonContainer = null;
577
574
  this.hoverButton?.remove();
@@ -720,8 +717,6 @@ class EinblickEditRuntime {
720
717
  };
721
718
  handleViewportChange = () => {
722
719
  if (this.currentInlineTarget?.isConnected) {
723
- this.ensureActiveOutline();
724
- this.positionOutline(this.activeOutline, this.currentInlineTarget);
725
720
  return;
726
721
  }
727
722
  if (this.activeElement && !this.activeElement.isConnected) {
@@ -774,7 +769,8 @@ class EinblickEditRuntime {
774
769
  return;
775
770
  }
776
771
  const binding = readBindingFromElement(this.activeElement);
777
- if (!binding) {
772
+ if (!isRecordEditableBinding(binding) ||
773
+ !this.shouldShowEditButton(this.activeElement, binding)) {
778
774
  return;
779
775
  }
780
776
  if (binding.fieldKey && isMediaEditableBinding(binding)) {
@@ -1020,16 +1016,19 @@ class EinblickEditRuntime {
1020
1016
  });
1021
1017
  }
1022
1018
  else if (this.editorBinding) {
1023
- const nextBinding = {
1024
- ...this.editorBinding,
1025
- sourceType: message.sourceType ?? this.editorBinding.sourceType ?? 'cms',
1026
- recordId: message.recordId ?? this.editorBinding.recordId,
1027
- };
1028
- void this.callbacks.onSave?.({
1029
- binding: nextBinding,
1030
- value: message.fields,
1031
- source: 'drawer',
1032
- });
1019
+ const nextRecordId = message.recordId ?? this.editorBinding.recordId;
1020
+ if (nextRecordId) {
1021
+ const nextBinding = {
1022
+ ...this.editorBinding,
1023
+ sourceType: message.sourceType ?? this.editorBinding.sourceType ?? 'cms',
1024
+ recordId: nextRecordId,
1025
+ };
1026
+ void this.callbacks.onSave?.({
1027
+ binding: nextBinding,
1028
+ value: message.fields,
1029
+ source: 'drawer',
1030
+ });
1031
+ }
1033
1032
  }
1034
1033
  this.closeDrawer();
1035
1034
  return;
@@ -1283,6 +1282,7 @@ class EinblickEditRuntime {
1283
1282
  min-width: 0;
1284
1283
  height: 2rem;
1285
1284
  margin: 0;
1285
+ border: 0;
1286
1286
  border-radius: 0.35rem;
1287
1287
  background: #ffffff;
1288
1288
  color: #fa693e;
@@ -1476,78 +1476,23 @@ class EinblickEditRuntime {
1476
1476
  ? this.messages.brand.authenticatedHint
1477
1477
  : this.messages.brand.unauthenticatedHint;
1478
1478
  }
1479
- collectBottomBarResources() {
1480
- const resources = new Map();
1481
- for (const hint of this.resourceHints) {
1482
- const key = `${hint.sourceType}:${hint.resourceSlug}`;
1483
- if (hint.showInBottomBar === false) {
1484
- resources.delete(key);
1485
- continue;
1486
- }
1487
- resources.set(key, hint);
1488
- }
1489
- if (typeof document !== 'undefined') {
1490
- const elements = document.querySelectorAll('[data-einblick-editable="true"][data-einblick-resource]');
1491
- elements.forEach((element) => {
1492
- const binding = readBindingFromElement(element);
1493
- if (!binding?.resourceSlug)
1494
- return;
1495
- const sourceType = binding.sourceType ?? 'cms';
1496
- const key = `${sourceType}:${binding.resourceSlug}`;
1497
- if (resources.has(key)) {
1498
- const current = resources.get(key);
1499
- if (binding.recordId &&
1500
- !current.recordIds?.includes(binding.recordId)) {
1501
- current.recordIds = [...(current.recordIds ?? []), binding.recordId];
1502
- }
1503
- return;
1504
- }
1505
- resources.set(key, {
1506
- sourceType,
1507
- resourceSlug: binding.resourceSlug,
1508
- label: binding.label,
1509
- mode: binding.resourceMode,
1510
- recordIds: binding.recordId ? [binding.recordId] : undefined,
1511
- });
1512
- });
1513
- }
1514
- return [...resources.values()];
1515
- }
1516
1479
  updateBottomBarResources() {
1517
1480
  if (!this.bottomBarResourceList) {
1518
1481
  return;
1519
1482
  }
1520
1483
  this.bottomBarResourceList.replaceChildren();
1521
- const resources = this.collectBottomBarResources();
1522
- if (resources.length === 0) {
1523
- const button = document.createElement('button');
1524
- button.type = 'button';
1525
- button.className = 'resource-button';
1526
- button.textContent = this.messages.actions.cmsCollections;
1527
- button.setAttribute('aria-expanded', this.isNavigatorOpen() ? 'true' : 'false');
1528
- button.addEventListener('click', (event) => {
1529
- event.preventDefault();
1530
- event.stopPropagation();
1531
- this.setBottomBarMenuOpen(false);
1532
- this.setNavigatorOpen(!this.isNavigatorOpen());
1533
- });
1534
- this.bottomBarResourceList.append(button);
1535
- return;
1536
- }
1537
- for (const resource of resources) {
1538
- const button = document.createElement('button');
1539
- button.type = 'button';
1540
- button.className = 'resource-button';
1541
- button.textContent = resource.label ?? resource.resourceSlug;
1542
- button.title = button.textContent;
1543
- button.addEventListener('click', (event) => {
1544
- event.preventDefault();
1545
- event.stopPropagation();
1546
- this.setBottomBarMenuOpen(false);
1547
- this.openNavigator(resource);
1548
- });
1549
- this.bottomBarResourceList.append(button);
1550
- }
1484
+ const button = document.createElement('button');
1485
+ button.type = 'button';
1486
+ button.className = 'resource-button';
1487
+ button.textContent = this.messages.actions.cmsCollections;
1488
+ button.setAttribute('aria-expanded', this.isNavigatorOpen() ? 'true' : 'false');
1489
+ button.addEventListener('click', (event) => {
1490
+ event.preventDefault();
1491
+ event.stopPropagation();
1492
+ this.setBottomBarMenuOpen(false);
1493
+ this.setNavigatorOpen(!this.isNavigatorOpen());
1494
+ });
1495
+ this.bottomBarResourceList.append(button);
1551
1496
  }
1552
1497
  updateBottomBar() {
1553
1498
  if (!this.bottomBarHost) {
@@ -1817,6 +1762,9 @@ class EinblickEditRuntime {
1817
1762
  this.updateHoverChrome();
1818
1763
  return;
1819
1764
  }
1765
+ if (this.activeElement) {
1766
+ delete this.activeElement.dataset.einblickHoverActive;
1767
+ }
1820
1768
  this.activeElement = element;
1821
1769
  if (!element ||
1822
1770
  !this.hoverButton ||
@@ -1825,34 +1773,27 @@ class EinblickEditRuntime {
1825
1773
  if (this.hoverButtonContainer) {
1826
1774
  this.hoverButtonContainer.hidden = true;
1827
1775
  }
1828
- this.activeOutline?.remove();
1829
- this.activeOutline = null;
1830
1776
  this.clearQuickFieldOverlays();
1777
+ if (this.hoverButton) {
1778
+ this.hoverButton.hidden = true;
1779
+ }
1831
1780
  if (this.hoverCreateButton) {
1832
1781
  this.hoverCreateButton.hidden = true;
1833
1782
  }
1834
1783
  return;
1835
1784
  }
1836
- this.ensureActiveOutline();
1785
+ element.dataset.einblickHoverActive = 'true';
1837
1786
  this.hoverButtonContainer.hidden = false;
1838
1787
  this.updateHoverButtonLabel();
1839
1788
  this.updateHoverButtonVisibility(element);
1840
1789
  this.renderQuickFieldOverlays(element);
1841
1790
  this.updateHoverChrome();
1842
1791
  }
1843
- ensureActiveOutline() {
1844
- if (this.activeOutline || typeof document === 'undefined') {
1845
- return;
1846
- }
1847
- const outline = document.createElement('div');
1848
- outline.setAttribute('data-einblick-edit-outline', 'true');
1849
- document.body.append(outline);
1850
- this.activeOutline = outline;
1851
- }
1852
1792
  updateHoverChrome() {
1853
1793
  if (!this.activeElement || !this.state.isAuthenticated) {
1854
- this.activeOutline?.remove();
1855
- this.activeOutline = null;
1794
+ if (this.activeElement) {
1795
+ delete this.activeElement.dataset.einblickHoverActive;
1796
+ }
1856
1797
  if (this.hoverButtonContainer) {
1857
1798
  this.hoverButtonContainer.hidden = true;
1858
1799
  }
@@ -1863,10 +1804,9 @@ class EinblickEditRuntime {
1863
1804
  this.setActiveElement(null);
1864
1805
  return;
1865
1806
  }
1866
- this.ensureActiveOutline();
1867
1807
  const rect = this.activeElement.getBoundingClientRect();
1868
- const isVisible = this.positionOutline(this.activeOutline, this.activeElement);
1869
- if (!isVisible || rect.width <= 0 || rect.height <= 0) {
1808
+ const isVisible = this.isElementRectVisible(rect);
1809
+ if (!isVisible) {
1870
1810
  if (this.hoverButtonContainer) {
1871
1811
  this.hoverButtonContainer.hidden = true;
1872
1812
  }
@@ -1878,38 +1818,32 @@ class EinblickEditRuntime {
1878
1818
  this.positionHoverControls(rect);
1879
1819
  this.updateQuickFieldOverlayPositions();
1880
1820
  }
1881
- positionOutline(outline, target) {
1882
- if (!outline) {
1883
- return false;
1884
- }
1885
- const rect = target.getBoundingClientRect();
1886
- if (rect.width <= 0 || rect.height <= 0) {
1887
- outline.hidden = true;
1888
- return false;
1889
- }
1890
- const style = window.getComputedStyle(target);
1891
- outline.hidden = false;
1892
- outline.style.setProperty('--einblick-overlay-radius', style.borderRadius || '0.35rem');
1893
- outline.style.left = `${Math.round(rect.left)}px`;
1894
- outline.style.top = `${Math.round(rect.top)}px`;
1895
- outline.style.width = `${Math.round(rect.width)}px`;
1896
- outline.style.height = `${Math.round(rect.height)}px`;
1897
- return true;
1821
+ isElementRectVisible(rect) {
1822
+ return (rect.width > 0 &&
1823
+ rect.height > 0 &&
1824
+ rect.bottom >= 0 &&
1825
+ rect.right >= 0 &&
1826
+ rect.top <= window.innerHeight &&
1827
+ rect.left <= window.innerWidth);
1898
1828
  }
1899
1829
  positionHoverControls(rect) {
1900
1830
  if (!this.hoverButtonContainer) {
1901
1831
  return;
1902
1832
  }
1903
1833
  this.hoverButtonContainer.hidden = false;
1904
- const margin = 8;
1905
1834
  const width = this.hoverButtonContainer.offsetWidth || 180;
1906
1835
  const height = this.hoverButtonContainer.offsetHeight || 32;
1907
- const left = clamp(rect.right - width - margin, margin, Math.max(margin, window.innerWidth - width - margin));
1908
- const top = clamp(rect.top + margin, margin, Math.max(margin, window.innerHeight - height - margin));
1836
+ const scrollX = window.scrollX || document.documentElement.scrollLeft;
1837
+ const scrollY = window.scrollY || document.documentElement.scrollTop;
1838
+ const left = clamp(rect.right + scrollX - width, scrollX, Math.max(scrollX, scrollX + window.innerWidth - width));
1839
+ const top = clamp(rect.top + scrollY, scrollY, Math.max(scrollY, scrollY + window.innerHeight - height));
1909
1840
  this.hoverButtonContainer.style.left = `${Math.round(left)}px`;
1910
1841
  this.hoverButtonContainer.style.top = `${Math.round(top)}px`;
1911
1842
  }
1912
1843
  clearQuickFieldOverlays() {
1844
+ for (const overlay of this.quickFieldOverlays) {
1845
+ delete overlay.target.dataset.einblickFieldHoverActive;
1846
+ }
1913
1847
  this.quickFieldOverlayContainer?.remove();
1914
1848
  this.quickFieldOverlayContainer = null;
1915
1849
  this.quickFieldOverlays = [];
@@ -1924,13 +1858,13 @@ class EinblickEditRuntime {
1924
1858
  container.setAttribute('data-einblick-field-overlays', 'true');
1925
1859
  this.quickFieldOverlays = targets.map((target) => {
1926
1860
  const binding = readBindingFromElement(target);
1927
- const outline = document.createElement('div');
1928
- outline.setAttribute('data-einblick-edit-field-outline', 'true');
1861
+ const isMediaBinding = isRecordEditableBinding(binding) && isMediaEditableBinding(binding);
1862
+ target.dataset.einblickFieldHoverActive = 'true';
1929
1863
  const button = document.createElement('button');
1930
1864
  button.type = 'button';
1931
- button.setAttribute('data-einblick-field-button', binding && isMediaEditableBinding(binding) ? 'media' : 'text');
1865
+ button.setAttribute('data-einblick-field-button', isMediaBinding ? 'media' : 'text');
1932
1866
  button.textContent =
1933
- binding && isMediaEditableBinding(binding)
1867
+ isMediaBinding
1934
1868
  ? getMediaActionLabel(binding, this.messages)
1935
1869
  : this.messages.actions.editText;
1936
1870
  button.addEventListener('pointerdown', (event) => {
@@ -1939,7 +1873,7 @@ class EinblickEditRuntime {
1939
1873
  button.addEventListener('click', (event) => {
1940
1874
  stopEvent(event);
1941
1875
  const nextBinding = readBindingFromElement(target);
1942
- if (!nextBinding) {
1876
+ if (!isRecordEditableBinding(nextBinding)) {
1943
1877
  return;
1944
1878
  }
1945
1879
  if (isMediaEditableBinding(nextBinding)) {
@@ -1948,8 +1882,8 @@ class EinblickEditRuntime {
1948
1882
  }
1949
1883
  this.openInlineEditor(target, nextBinding);
1950
1884
  });
1951
- container.append(outline, button);
1952
- return { target, outline, button };
1885
+ container.append(button);
1886
+ return { target, button };
1953
1887
  });
1954
1888
  document.body.append(container);
1955
1889
  this.quickFieldOverlayContainer = container;
@@ -1961,21 +1895,21 @@ class EinblickEditRuntime {
1961
1895
  }
1962
1896
  for (const overlay of this.quickFieldOverlays) {
1963
1897
  if (!overlay.target.isConnected) {
1964
- overlay.outline.hidden = true;
1965
1898
  overlay.button.hidden = true;
1966
1899
  continue;
1967
1900
  }
1968
1901
  const rect = overlay.target.getBoundingClientRect();
1969
- const isVisible = this.positionOutline(overlay.outline, overlay.target);
1902
+ const isVisible = this.isElementRectVisible(rect);
1970
1903
  overlay.button.hidden = !isVisible;
1971
1904
  if (!isVisible) {
1972
1905
  continue;
1973
1906
  }
1974
- const margin = 4;
1975
1907
  const width = overlay.button.offsetWidth || 96;
1976
1908
  const height = overlay.button.offsetHeight || 26;
1977
- const left = clamp(rect.left + margin, margin, Math.max(margin, window.innerWidth - width - margin));
1978
- const top = clamp(rect.top + margin, margin, Math.max(margin, window.innerHeight - height - margin));
1909
+ const scrollX = window.scrollX || document.documentElement.scrollLeft;
1910
+ const scrollY = window.scrollY || document.documentElement.scrollTop;
1911
+ const left = clamp(rect.right + scrollX - width, scrollX, Math.max(scrollX, scrollX + window.innerWidth - width));
1912
+ const top = clamp(rect.top + scrollY, scrollY, Math.max(scrollY, scrollY + window.innerHeight - height));
1979
1913
  overlay.button.style.left = `${Math.round(left)}px`;
1980
1914
  overlay.button.style.top = `${Math.round(top)}px`;
1981
1915
  }
@@ -2068,7 +2002,12 @@ class EinblickEditRuntime {
2068
2002
  url.searchParams.set('returnTo', window.location.href);
2069
2003
  url.searchParams.set('sourceType', binding.sourceType ?? 'cms');
2070
2004
  url.searchParams.set('resourceSlug', binding.resourceSlug);
2071
- url.searchParams.set('recordId', binding.recordId);
2005
+ if (binding.recordId) {
2006
+ url.searchParams.set('recordId', binding.recordId);
2007
+ }
2008
+ else if (intent !== 'create') {
2009
+ throw new Error(this.messages.errors.openEditorFailed);
2010
+ }
2072
2011
  if (intent === 'create') {
2073
2012
  url.searchParams.set('intent', intent);
2074
2013
  }
@@ -2119,11 +2058,23 @@ class EinblickEditRuntime {
2119
2058
  return url.toString();
2120
2059
  }
2121
2060
  updateHoverButtonVisibility(element) {
2122
- if (!this.hoverCreateButton) {
2061
+ if (!this.hoverButton || !this.hoverCreateButton) {
2123
2062
  return;
2124
2063
  }
2125
2064
  const binding = element ? readBindingFromElement(element) : null;
2126
- this.hoverCreateButton.hidden = !this.shouldShowCreateButton(element, binding);
2065
+ const canCreate = this.shouldShowCreateButton(element, binding);
2066
+ const canEdit = this.shouldShowEditButton(element, binding);
2067
+ this.hoverButton.hidden = !canEdit;
2068
+ this.hoverCreateButton.hidden = !canCreate;
2069
+ if (this.hoverButtonContainer) {
2070
+ this.hoverButtonContainer.hidden = !canEdit && !canCreate;
2071
+ }
2072
+ }
2073
+ shouldShowEditButton(element, binding) {
2074
+ if (element?.dataset.einblickKind === 'collection') {
2075
+ return false;
2076
+ }
2077
+ return isRecordEditableBinding(binding);
2127
2078
  }
2128
2079
  shouldShowCreateButton(element, binding) {
2129
2080
  if (!element || !binding || !this.state.isAuthenticated) {
@@ -2132,29 +2083,8 @@ class EinblickEditRuntime {
2132
2083
  if (binding.fieldKey) {
2133
2084
  return false;
2134
2085
  }
2135
- if (binding.resourceMode === 'singleton') {
2136
- return false;
2137
- }
2138
- if (binding.resourceMode === 'collection') {
2139
- return true;
2140
- }
2141
- if (element.dataset.einblickKind === 'text') {
2142
- return false;
2143
- }
2144
- const selector = [
2145
- '[data-einblick-editable="true"]',
2146
- `[data-einblick-source-type="${CSS.escape(binding.sourceType ?? 'cms')}"]`,
2147
- `[data-einblick-resource="${CSS.escape(binding.resourceSlug)}"]`,
2148
- ].join('');
2149
- const elements = document.querySelectorAll(selector);
2150
- const recordIds = new Set();
2151
- elements.forEach((candidate) => {
2152
- const recordId = candidate.dataset.einblickRecordId?.trim();
2153
- if (recordId) {
2154
- recordIds.add(recordId);
2155
- }
2156
- });
2157
- return recordIds.size > 1;
2086
+ return (element.dataset.einblickKind === 'collection' &&
2087
+ binding.resourceMode === 'collection');
2158
2088
  }
2159
2089
  findEditableTarget(target) {
2160
2090
  if (!(target instanceof Element)) {
@@ -2196,6 +2126,9 @@ class EinblickEditRuntime {
2196
2126
  ? [element]
2197
2127
  : [];
2198
2128
  }
2129
+ if (!binding.recordId) {
2130
+ return [];
2131
+ }
2199
2132
  const selector = [
2200
2133
  '[data-einblick-editable="true"]',
2201
2134
  `[data-einblick-source-type="${CSS.escape(binding.sourceType ?? 'cms')}"]`,
@@ -2219,7 +2152,6 @@ class EinblickEditRuntime {
2219
2152
  }
2220
2153
  return (!!this.hoverButtonContainer?.contains(target) ||
2221
2154
  !!this.quickFieldOverlayContainer?.contains(target) ||
2222
- !!this.activeOutline?.contains(target) ||
2223
2155
  !!this.brandBadge?.contains(target) ||
2224
2156
  !!this.brandPopover?.contains(target) ||
2225
2157
  !!this.bottomBarHost?.contains(target) ||
@@ -2230,7 +2162,9 @@ class EinblickEditRuntime {
2230
2162
  '[data-einblick-editable="true"]',
2231
2163
  `[data-einblick-source-type="${CSS.escape(binding.sourceType ?? 'cms')}"]`,
2232
2164
  `[data-einblick-resource="${CSS.escape(binding.resourceSlug)}"]`,
2233
- `[data-einblick-record-id="${CSS.escape(binding.recordId)}"]`,
2165
+ binding.recordId
2166
+ ? `[data-einblick-record-id="${CSS.escape(binding.recordId)}"]`
2167
+ : '',
2234
2168
  binding.fieldKey
2235
2169
  ? `[data-einblick-field-key="${CSS.escape(binding.fieldKey)}"]`
2236
2170
  : '',
@@ -2326,9 +2260,6 @@ class EinblickEditRuntime {
2326
2260
  restoreState.cleanup.push(() => target.removeEventListener('click', handleClick, true), () => target.removeEventListener('keydown', handleKeyDown, true), () => target.removeEventListener('paste', handlePaste, true), () => target.removeEventListener('blur', handleBlur, true));
2327
2261
  this.currentInlineTarget = target;
2328
2262
  this.currentInlineBinding = binding;
2329
- this.ensureActiveOutline();
2330
- this.activeOutline?.setAttribute('data-einblick-inline-active', 'true');
2331
- this.positionOutline(this.activeOutline, target);
2332
2263
  window.setTimeout(() => {
2333
2264
  target.focus({ preventScroll: true });
2334
2265
  this.placeCaretAtEnd(target);
@@ -2354,11 +2285,6 @@ class EinblickEditRuntime {
2354
2285
  this.currentInlineTarget = null;
2355
2286
  this.currentInlineBinding = null;
2356
2287
  this.inlineSaveInFlight = null;
2357
- this.activeOutline?.removeAttribute('data-einblick-inline-active');
2358
- if (!this.activeElement) {
2359
- this.activeOutline?.remove();
2360
- this.activeOutline = null;
2361
- }
2362
2288
  }
2363
2289
  restoreInlineTargetAttributes(target, restoreState) {
2364
2290
  if (restoreState.contentEditable === null) {