@lvce-editor/settings-view 2.29.0 → 2.29.1

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.
@@ -1379,10 +1379,13 @@ const terminate = () => {
1379
1379
  };
1380
1380
 
1381
1381
  const computeScrollBar = (height, totalItemCount, itemHeight, scrollOffset, scrollBarMinHeight) => {
1382
- const totalHeight = totalItemCount * itemHeight;
1383
- const scrollable = Math.max(0, totalHeight - height);
1384
- const thumbTrack = Math.max(0, height);
1385
- const thumbHeight = totalHeight > 0 ? Math.max(scrollBarMinHeight, Math.floor(height / Math.max(totalHeight, 1) * height)) : height;
1382
+ const safeHeight = Math.max(0, height);
1383
+ const safeItemHeight = Math.max(0, itemHeight);
1384
+ const totalHeight = totalItemCount * safeItemHeight;
1385
+ const scrollable = Math.max(0, totalHeight - safeHeight);
1386
+ const thumbTrack = safeHeight;
1387
+ const proportionalThumbHeight = totalHeight > 0 ? Math.floor(safeHeight / Math.max(totalHeight, 1) * safeHeight) : safeHeight;
1388
+ const thumbHeight = totalHeight > 0 ? Math.min(safeHeight, Math.max(scrollBarMinHeight, proportionalThumbHeight)) : safeHeight;
1386
1389
  const thumbMaxTop = Math.max(0, thumbTrack - thumbHeight);
1387
1390
  const thumbTop = scrollable > 0 ? Math.min(thumbMaxTop, Math.floor(scrollOffset / scrollable * thumbMaxTop)) : 0;
1388
1391
  return {
@@ -1394,8 +1397,9 @@ const computeScrollBar = (height, totalItemCount, itemHeight, scrollOffset, scro
1394
1397
  const computeVisibleItems = (items, height, scrollOffset, itemHeight) => {
1395
1398
  const safeItemHeight = itemHeight <= 0 ? 1 : itemHeight;
1396
1399
  const totalItems = items.length;
1397
- const minLineY = Math.max(0, Math.floor(scrollOffset / safeItemHeight));
1398
- const itemsPerViewport = Math.max(1, Math.ceil(height / safeItemHeight));
1400
+ const safeHeight = Math.max(0, height);
1401
+ const minLineY = Math.max(0, Math.floor(Math.max(0, scrollOffset) / safeItemHeight));
1402
+ const itemsPerViewport = Math.max(1, Math.ceil(safeHeight / safeItemHeight) + 1);
1399
1403
  const maxLineY = Math.min(totalItems, minLineY + itemsPerViewport);
1400
1404
  const visibleItems = items.slice(minLineY, maxLineY);
1401
1405
  return {
@@ -1476,6 +1480,13 @@ const getFilteredItems = (items, tabs, searchValue, modifiedSettings, preference
1476
1480
  return parsedQuery.modified ? validated.filter(item => item.modified) : validated;
1477
1481
  };
1478
1482
 
1483
+ // The worker receives the height of the complete settings view. Account for
1484
+ // the search header, content padding, and content heading before measuring rows.
1485
+ const settingsContentChromeHeight = 114;
1486
+ const getSettingsViewportHeight = height => {
1487
+ return Math.max(0, height - settingsContentChromeHeight);
1488
+ };
1489
+
1479
1490
  const User = 1;
1480
1491
  const Script = 2;
1481
1492
 
@@ -1491,6 +1502,7 @@ const clear$1 = state => {
1491
1502
  scrollBarMinHeight,
1492
1503
  tabs
1493
1504
  } = state;
1505
+ const viewportHeight = getSettingsViewportHeight(height);
1494
1506
  const newSearchValue = '';
1495
1507
  const filteredItems = getFilteredItems(items, tabs, newSearchValue, modifiedSettings, preferences);
1496
1508
  const nextScrollOffset = 0;
@@ -1498,11 +1510,11 @@ const clear$1 = state => {
1498
1510
  maxLineY,
1499
1511
  minLineY,
1500
1512
  visibleItems
1501
- } = computeVisibleItems(filteredItems, height, nextScrollOffset, itemHeight);
1513
+ } = computeVisibleItems(filteredItems, viewportHeight, nextScrollOffset, itemHeight);
1502
1514
  const {
1503
1515
  thumbHeight,
1504
1516
  thumbTop
1505
- } = computeScrollBar(height, filteredItems.length, itemHeight, nextScrollOffset, scrollBarMinHeight);
1517
+ } = computeScrollBar(viewportHeight, filteredItems.length, itemHeight, nextScrollOffset, scrollBarMinHeight);
1506
1518
  return {
1507
1519
  ...state,
1508
1520
  deltaY: 0,
@@ -1578,7 +1590,7 @@ const create$1 = (id, uri, x, y, width, height) => {
1578
1590
  };
1579
1591
 
1580
1592
  const isEqual$4 = (oldState, newState) => {
1581
- return oldState.sideBarWidth === newState.sideBarWidth && oldState.scrollBarThumbHeight === newState.scrollBarThumbHeight && oldState.scrollBarThumbTop === newState.scrollBarThumbTop;
1593
+ return oldState.sideBarWidth === newState.sideBarWidth && oldState.filteredItems.length === newState.filteredItems.length && oldState.itemHeight === newState.itemHeight && oldState.scrollOffset === newState.scrollOffset && oldState.scrollBarThumbHeight === newState.scrollBarThumbHeight && oldState.scrollBarThumbTop === newState.scrollBarThumbTop;
1582
1594
  };
1583
1595
 
1584
1596
  const isEqual$3 = (oldState, newState) => {
@@ -1698,6 +1710,7 @@ const handleInput = (state, value, inputSource = User) => {
1698
1710
  preferences,
1699
1711
  tabs
1700
1712
  } = state;
1713
+ const viewportHeight = getSettingsViewportHeight(height);
1701
1714
  const filteredItems = getFilteredItems(items, tabs, value, modifiedSettings, preferences);
1702
1715
  // Reset scroll when filter value changes so the user sees results from the top
1703
1716
  const nextScrollOffset = 0;
@@ -1705,14 +1718,14 @@ const handleInput = (state, value, inputSource = User) => {
1705
1718
  maxLineY,
1706
1719
  minLineY,
1707
1720
  visibleItems
1708
- } = computeVisibleItems(filteredItems, height, nextScrollOffset, itemHeight);
1721
+ } = computeVisibleItems(filteredItems, viewportHeight, nextScrollOffset, itemHeight);
1709
1722
  const {
1710
1723
  scrollBarMinHeight
1711
1724
  } = state;
1712
1725
  const {
1713
1726
  thumbHeight,
1714
1727
  thumbTop
1715
- } = computeScrollBar(height, filteredItems.length, itemHeight, nextScrollOffset, scrollBarMinHeight);
1728
+ } = computeScrollBar(viewportHeight, filteredItems.length, itemHeight, nextScrollOffset, scrollBarMinHeight);
1716
1729
  const {
1717
1730
  newHistory,
1718
1731
  newHistoryIndex
@@ -2762,20 +2775,23 @@ const handleClickTab = (state, name = '') => {
2762
2775
  searchValue,
2763
2776
  tabs
2764
2777
  } = state;
2778
+ const viewportHeight = getSettingsViewportHeight(height);
2765
2779
  const updatedTabs = getUpdatedTabs(tabs, name);
2766
2780
  const filteredItems = getFilteredItems(items, updatedTabs, searchValue, modifiedSettings, preferences);
2781
+ const maxScrollable = Math.max(0, filteredItems.length * itemHeight - viewportHeight);
2782
+ const nextScrollOffset = Math.min(Math.max(0, scrollOffset), maxScrollable);
2767
2783
  const {
2768
2784
  maxLineY,
2769
2785
  minLineY,
2770
2786
  visibleItems
2771
- } = computeVisibleItems(filteredItems, height, scrollOffset, itemHeight);
2787
+ } = computeVisibleItems(filteredItems, viewportHeight, nextScrollOffset, itemHeight);
2772
2788
  const {
2773
2789
  scrollBarMinHeight
2774
2790
  } = state;
2775
2791
  const {
2776
2792
  thumbHeight,
2777
2793
  thumbTop
2778
- } = computeScrollBar(height, filteredItems.length, itemHeight, scrollOffset, scrollBarMinHeight);
2794
+ } = computeScrollBar(viewportHeight, filteredItems.length, itemHeight, nextScrollOffset, scrollBarMinHeight);
2779
2795
  return {
2780
2796
  ...state,
2781
2797
  filteredItems,
@@ -2783,6 +2799,7 @@ const handleClickTab = (state, name = '') => {
2783
2799
  minLineY,
2784
2800
  scrollBarThumbHeight: thumbHeight,
2785
2801
  scrollBarThumbTop: thumbTop,
2802
+ scrollOffset: nextScrollOffset,
2786
2803
  tabs: updatedTabs,
2787
2804
  visibleItems
2788
2805
  };
@@ -2990,6 +3007,7 @@ const handleWheel = (state, eventDeltaY, inputSource = User) => {
2990
3007
  height,
2991
3008
  itemHeight = 1
2992
3009
  } = state;
3010
+ const viewportHeight = getSettingsViewportHeight(height);
2993
3011
  const itemCount = filteredItems.length;
2994
3012
  const stepLimit = itemCount === 0 ? 10 : Infinity;
2995
3013
  const limitedEventDelta = Math.max(-stepLimit, Math.min(stepLimit, eventDeltaY));
@@ -2997,21 +3015,21 @@ const handleWheel = (state, eventDeltaY, inputSource = User) => {
2997
3015
  // Prevent scrolling beyond the available content height. If content is smaller
2998
3016
  // than the viewport, the maximum scroll is zero.
2999
3017
  const totalContentHeight = itemCount * itemHeight;
3000
- const maxScrollable = Math.max(0, totalContentHeight - height);
3018
+ const maxScrollable = Math.max(0, totalContentHeight - viewportHeight);
3001
3019
  const clampedDeltaY = clamp(total, 0, maxScrollable);
3002
3020
  const scrollOffset = clampedDeltaY;
3003
3021
  const {
3004
3022
  maxLineY,
3005
3023
  minLineY,
3006
3024
  visibleItems
3007
- } = computeVisibleItems(filteredItems, height, scrollOffset, itemHeight);
3025
+ } = computeVisibleItems(filteredItems, viewportHeight, scrollOffset, itemHeight);
3008
3026
  const {
3009
3027
  scrollBarMinHeight
3010
3028
  } = state;
3011
3029
  const {
3012
3030
  thumbHeight,
3013
3031
  thumbTop
3014
- } = computeScrollBar(height, filteredItems.length, itemHeight, scrollOffset, scrollBarMinHeight);
3032
+ } = computeScrollBar(viewportHeight, filteredItems.length, itemHeight, scrollOffset, scrollBarMinHeight);
3015
3033
  return {
3016
3034
  ...state,
3017
3035
  deltaY: clampedDeltaY,
@@ -3194,18 +3212,21 @@ const loadContent = async (state, savedState) => {
3194
3212
  height,
3195
3213
  itemHeight
3196
3214
  } = state;
3215
+ const viewportHeight = getSettingsViewportHeight(height);
3216
+ const maxScrollable = Math.max(0, filteredItems.length * itemHeight - viewportHeight);
3217
+ const nextScrollOffset = Math.min(Math.max(0, scrollOffset), maxScrollable);
3197
3218
  const {
3198
3219
  maxLineY,
3199
3220
  minLineY,
3200
3221
  visibleItems
3201
- } = computeVisibleItems(filteredItems, height, scrollOffset, itemHeight);
3222
+ } = computeVisibleItems(filteredItems, viewportHeight, nextScrollOffset, itemHeight);
3202
3223
  const {
3203
3224
  scrollBarMinHeight
3204
3225
  } = state;
3205
3226
  const {
3206
3227
  thumbHeight,
3207
3228
  thumbTop
3208
- } = computeScrollBar(height, filteredItems.length, itemHeight, scrollOffset, scrollBarMinHeight);
3229
+ } = computeScrollBar(viewportHeight, filteredItems.length, itemHeight, nextScrollOffset, scrollBarMinHeight);
3209
3230
  return {
3210
3231
  ...state,
3211
3232
  filteredItems,
@@ -3220,7 +3241,7 @@ const loadContent = async (state, savedState) => {
3220
3241
  schemaErrors,
3221
3242
  scrollBarThumbHeight: thumbHeight,
3222
3243
  scrollBarThumbTop: thumbTop,
3223
- scrollOffset,
3244
+ scrollOffset: nextScrollOffset,
3224
3245
  searchValue,
3225
3246
  sideBarWidth,
3226
3247
  tabs: newTabs,
@@ -3228,13 +3249,17 @@ const loadContent = async (state, savedState) => {
3228
3249
  };
3229
3250
  };
3230
3251
 
3231
- const getCss = (sideBarWidth, scrollBarThumbHeight, scrollBarThumbTop) => {
3252
+ const getCss = (sideBarWidth, scrollBarThumbHeight, scrollBarThumbTop, itemHeight, totalItemCount, scrollOffset) => {
3232
3253
  const rounded = Math.round(sideBarWidth);
3254
+ const settingsLayoutCss = typeof itemHeight === 'number' && typeof totalItemCount === 'number' && typeof scrollOffset === 'number' ? `
3255
+ --SettingsItemHeight: ${itemHeight}px;
3256
+ --SettingsItemsHeight: ${itemHeight * totalItemCount}px;
3257
+ --SettingsItemsTranslateY: ${-scrollOffset}px;` : '';
3233
3258
  return `
3234
3259
  .Settings {
3235
3260
  --SettingsSideBarWidth: ${rounded}px;
3236
3261
  --ScrollBarThumbHeight: ${scrollBarThumbHeight}px;
3237
- --ScrollBarThumbTop: ${scrollBarThumbTop}px;
3262
+ --ScrollBarThumbTop: ${scrollBarThumbTop}px;${settingsLayoutCss}
3238
3263
  }
3239
3264
 
3240
3265
  .SettingsSideBar{
@@ -3245,12 +3270,15 @@ const getCss = (sideBarWidth, scrollBarThumbHeight, scrollBarThumbTop) => {
3245
3270
 
3246
3271
  const renderCss = (oldState, newState) => {
3247
3272
  const {
3273
+ filteredItems,
3248
3274
  id,
3275
+ itemHeight,
3249
3276
  scrollBarThumbHeight,
3250
3277
  scrollBarThumbTop,
3278
+ scrollOffset,
3251
3279
  sideBarWidth
3252
3280
  } = newState;
3253
- const css = getCss(sideBarWidth, scrollBarThumbHeight, scrollBarThumbTop);
3281
+ const css = getCss(sideBarWidth, scrollBarThumbHeight, scrollBarThumbTop, itemHeight, filteredItems.length, scrollOffset);
3254
3282
  return [SetCss, id, css];
3255
3283
  };
3256
3284
 
@@ -3298,6 +3326,7 @@ const SettingsItem = 'SettingsItem';
3298
3326
  const SettingsItemCheckBox = 'SettingsItemCheckBox';
3299
3327
  const SettingsItemHeading = 'SettingsItemHeading';
3300
3328
  const SettingsItems = 'SettingsItems';
3329
+ const SettingsItemsSpacer = 'SettingsItemsSpacer';
3301
3330
  const SettingsItemWrapper = 'SettingsItemWrapper';
3302
3331
  const SettingsMain = 'SettingsMain';
3303
3332
  const SettingsNoResults = 'SettingsNoResults';
@@ -3833,7 +3862,7 @@ const getItemVirtualDom = (item, preferences) => {
3833
3862
  return fn(item, preferences);
3834
3863
  };
3835
3864
 
3836
- const settingsItemsNode = {
3865
+ const settingsItemsNode$1 = {
3837
3866
  childCount: 1,
3838
3867
  className: SettingsItems,
3839
3868
  onContextMenu: HandleContextMenu,
@@ -3845,19 +3874,47 @@ const noResultsNode = {
3845
3874
  type: P
3846
3875
  };
3847
3876
  const getSettingsNoResultsDom = searchValue => {
3848
- return [settingsItemsNode, noResultsNode, text(noSettingsMatching(searchValue))];
3877
+ return [settingsItemsNode$1, noResultsNode, text(noSettingsMatching(searchValue))];
3878
+ };
3879
+
3880
+ const getSpacerDom = height => {
3881
+ return [{
3882
+ childCount: 0,
3883
+ className: SettingsItemsSpacer,
3884
+ height: `${height}px;`,
3885
+ type: Div
3886
+ }];
3849
3887
  };
3850
3888
 
3851
- const getSettingsItemsDom = (items, searchValue, preferences = {}) => {
3889
+ const settingsItemsNode = {
3890
+ childCount: 0,
3891
+ className: SettingsItems,
3892
+ onContextMenu: HandleContextMenu,
3893
+ type: Div
3894
+ };
3895
+ const getSettingsItemsChildren = (items, preferences, topSpacerHeight, bottomSpacerHeight) => {
3896
+ const children = items.flatMap(item => getItemVirtualDom(item, preferences));
3897
+ if (topSpacerHeight !== 0) {
3898
+ children.unshift(...getSpacerDom(topSpacerHeight));
3899
+ }
3900
+ if (bottomSpacerHeight !== 0) {
3901
+ children.push(...getSpacerDom(bottomSpacerHeight));
3902
+ }
3903
+ return children;
3904
+ };
3905
+ const getSettingsItemsDom = (items, searchValue, preferences = {}, topSpacerHeight = 0, bottomSpacerHeight = 0) => {
3852
3906
  if (items.length === 0 && searchValue && searchValue.trim()) {
3853
3907
  return getSettingsNoResultsDom(searchValue);
3854
3908
  }
3909
+ if (items.length === 0) {
3910
+ return [settingsItemsNode];
3911
+ }
3912
+ const hasVirtualSpacers = topSpacerHeight !== 0 || bottomSpacerHeight !== 0;
3913
+ const childCount = items.length + (hasVirtualSpacers ? 2 : 0);
3855
3914
  return [{
3856
- childCount: items.length,
3857
- className: SettingsItems,
3858
- onContextMenu: HandleContextMenu,
3859
- type: Div
3860
- }, ...items.flatMap(item => getItemVirtualDom(item, preferences))];
3915
+ ...settingsItemsNode,
3916
+ childCount
3917
+ }, ...getSettingsItemsChildren(items, preferences, topSpacerHeight, bottomSpacerHeight)];
3861
3918
  };
3862
3919
 
3863
3920
  const settingsContentNode = {
@@ -3871,10 +3928,10 @@ const settingsItemWrapperNode = {
3871
3928
  className: SettingsItemWrapper,
3872
3929
  type: Div
3873
3930
  };
3874
- const getSettingsContentDom = (visibleItems, tabs, searchValue, showScrollBar, schemaErrors = [], preferences = {}) => {
3931
+ const getSettingsContentDom = (visibleItems, tabs, searchValue, showScrollBar, schemaErrors = [], preferences = {}, topSpacerHeight = 0, bottomSpacerHeight = 0) => {
3875
3932
  const selectedTab = tabs.find(tab => tab.selected);
3876
3933
  const headerText = selectedTab ? selectedTab.label : settingsContent();
3877
- return [settingsContentNode, ...getContentHeadingDom(headerText), settingsItemWrapperNode, ...(selectedTab?.id === SchemaErrorsTab ? getSchemaErrorsDom(schemaErrors) : getSettingsItemsDom(visibleItems, searchValue, preferences)), ...getScrollBarDom(showScrollBar)];
3934
+ return [settingsContentNode, ...getContentHeadingDom(headerText), settingsItemWrapperNode, ...(selectedTab?.id === SchemaErrorsTab ? getSchemaErrorsDom(schemaErrors) : getSettingsItemsDom(visibleItems, searchValue, preferences, topSpacerHeight, bottomSpacerHeight)), ...getScrollBarDom(showScrollBar)];
3878
3935
  };
3879
3936
 
3880
3937
  const selectedTabClassName = mergeClassNames(Tab, TabSelected);
@@ -3919,10 +3976,11 @@ const settingsMainNode = {
3919
3976
  className: SettingsMain,
3920
3977
  type: Div
3921
3978
  };
3922
- const getSettingsMainDom = (tabs, visibleItems, totalItemCount, searchValue, height, itemHeight, schemaErrors = [], preferences = {}) => {
3979
+ const getSettingsMainDom = (tabs, visibleItems, totalItemCount, searchValue, height, itemHeight, minLineY, maxLineY, schemaErrors = [], preferences = {}) => {
3980
+ const viewportHeight = getSettingsViewportHeight(height);
3923
3981
  const totalHeight = totalItemCount * itemHeight;
3924
- const showScrollBar = totalHeight > height;
3925
- return [settingsMainNode, ...getSettingsSideBarDom(tabs), ...getResizerVirtualDom(), ...getSettingsContentDom(visibleItems, tabs, searchValue, showScrollBar, schemaErrors, preferences)];
3982
+ const showScrollBar = totalHeight > viewportHeight;
3983
+ return [settingsMainNode, ...getSettingsSideBarDom(tabs), ...getResizerVirtualDom(), ...getSettingsContentDom(visibleItems, tabs, searchValue, showScrollBar, schemaErrors, preferences, minLineY * itemHeight, Math.max(0, totalHeight - maxLineY * itemHeight))];
3926
3984
  };
3927
3985
 
3928
3986
  const parentNode = {
@@ -3951,7 +4009,11 @@ const getSettingsDom = state => {
3951
4009
  const hasSearchValue = searchValue.trim().length > 0;
3952
4010
  const filteredSchemaErrors = getFilteredSchemaErrors(schemaErrors, searchValue);
3953
4011
  const filteredItemsCount = getFilteredItemsCount(isSchemaErrorsTab, filteredSchemaErrors.length, filteredItems.length);
3954
- const mainDom = getSettingsMainDom(tabs, visibleItems, filteredItemsCount, searchValue, height, itemHeight, filteredSchemaErrors, preferences);
4012
+ const {
4013
+ maxLineY,
4014
+ minLineY
4015
+ } = state;
4016
+ const mainDom = getSettingsMainDom(tabs, visibleItems, filteredItemsCount, searchValue, height, itemHeight, minLineY, maxLineY, filteredSchemaErrors, preferences);
3955
4017
  return [parentNode, ...getSettingsHeaderDom(filteredItemsCount, hasSearchValue), ...mainDom];
3956
4018
  };
3957
4019
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/settings-view",
3
- "version": "2.29.0",
3
+ "version": "2.29.1",
4
4
  "description": "Explorer Worker",
5
5
  "repository": {
6
6
  "type": "git",