@lowdefy/blocks-table 0.0.0-experimental-20260929110023
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/LICENSE +201 -0
- package/README.md +12 -0
- package/dist/blocks/Table/Table.js +25 -0
- package/dist/blocks/Table/Table.lazy.js +33 -0
- package/dist/blocks/Table/TableFallback.js +35 -0
- package/dist/blocks/Table/e2e.js +47 -0
- package/dist/blocks/Table/gallery.yaml +836 -0
- package/dist/blocks/Table/meta.js +964 -0
- package/dist/blocks/Table/tests/Table.e2e.yaml +434 -0
- package/dist/blocks/Table/tests/TableFeatures.e2e.yaml +291 -0
- package/dist/blocks/Table/tests/TableLinkTarget.e2e.yaml +25 -0
- package/dist/blocks/Table/tests/TableParity.e2e.yaml +101 -0
- package/dist/blocks/Table/tests/bulk.e2e.yaml +271 -0
- package/dist/blocks/Table/tests/deals.yaml +30 -0
- package/dist/blocks/Table/tests/deals_columns.yaml +37 -0
- package/dist/blocks/Table/tests/editing.e2e.yaml +501 -0
- package/dist/blocks/Table/tests/expandable.e2e.yaml +87 -0
- package/dist/blocks/Table/tests/filtering.e2e.yaml +251 -0
- package/dist/blocks/Table/tests/grouping.e2e.yaml +272 -0
- package/dist/blocks/Table/tests/grouping_deals.yaml +24 -0
- package/dist/blocks/Table/tests/grouping_deals_columns.yaml +32 -0
- package/dist/blocks/Table/tests/headerMenu.e2e.yaml +134 -0
- package/dist/blocks/Table/tests/parity_properties.yaml +144 -0
- package/dist/blocks/Table/tests/people.yaml +39 -0
- package/dist/blocks/Table/tests/people_columns.yaml +22 -0
- package/dist/blocks/Table/tests/polish.e2e.yaml +372 -0
- package/dist/blocks/Table/tests/server-mongodb.e2e.yaml +169 -0
- package/dist/blocks/Table/tests/server.e2e.yaml +267 -0
- package/dist/blocks/Table/tests/toolbar.e2e.yaml +140 -0
- package/dist/blocks/Table/tests/tree.e2e.yaml +245 -0
- package/dist/blocks/Table/tests/views.e2e.yaml +235 -0
- package/dist/blocks/TableInput/TableInput.js +24 -0
- package/dist/blocks/TableInput/TableInput.lazy.js +17 -0
- package/dist/blocks/TableInput/TableInputRoot.js +65 -0
- package/dist/blocks/TableInput/e2e.js +16 -0
- package/dist/blocks/TableInput/gallery.yaml +153 -0
- package/dist/blocks/TableInput/meta.js +93 -0
- package/dist/blocks/TableInput/tests/TableInput.e2e.yaml +272 -0
- package/dist/blocks.js +16 -0
- package/dist/core/Body.js +112 -0
- package/dist/core/Cell.js +86 -0
- package/dist/core/Chevron.js +32 -0
- package/dist/core/EmptyState.js +32 -0
- package/dist/core/Grid.js +219 -0
- package/dist/core/GroupHeaderRow.js +81 -0
- package/dist/core/HeaderCell.js +58 -0
- package/dist/core/HeaderRow.js +76 -0
- package/dist/core/HeaderTitle.js +49 -0
- package/dist/core/LazyCell.js +71 -0
- package/dist/core/LoadingRows.js +38 -0
- package/dist/core/RenderProbeContext.js +19 -0
- package/dist/core/Row.js +98 -0
- package/dist/core/SkeletonRow.js +42 -0
- package/dist/core/SummaryRow.js +86 -0
- package/dist/core/TableRoot.js +195 -0
- package/dist/core/aggregateShortLabels.js +25 -0
- package/dist/core/applyLayoutVars.js +22 -0
- package/dist/core/buildGroupSegments.js +36 -0
- package/dist/core/collectBodyOverlays.js +20 -0
- package/dist/core/collectCellLeads.js +21 -0
- package/dist/core/collectClaimedViewKeys.js +26 -0
- package/dist/core/collectGridHandlers.js +29 -0
- package/dist/core/collectHeaderParts.js +20 -0
- package/dist/core/collectRowRenderers.js +21 -0
- package/dist/core/collectSliceDefinitions.js +29 -0
- package/dist/core/computeLayout.js +133 -0
- package/dist/core/createAccessor.js +39 -0
- package/dist/core/createApi.js +86 -0
- package/dist/core/createCellActivity.js +47 -0
- package/dist/core/createColumnDefs.js +42 -0
- package/dist/core/createFeatureActions.js +24 -0
- package/dist/core/createFeatureSet.js +39 -0
- package/dist/core/createInitialState.js +63 -0
- package/dist/core/createKeyIndex.js +26 -0
- package/dist/core/createMethodStubs.js +30 -0
- package/dist/core/createSliceHandlers.js +26 -0
- package/dist/core/createStableCoreRowModel.js +91 -0
- package/dist/core/createTanstackFeatures.js +24 -0
- package/dist/core/createTextMeasure.js +106 -0
- package/dist/core/densityHeights.js +20 -0
- package/dist/core/deriveValue.js +53 -0
- package/dist/core/dispatchGridEvent.js +21 -0
- package/dist/core/distributeFlex.js +28 -0
- package/dist/core/getCellFit.js +34 -0
- package/dist/core/getHeaderCellProps.js +21 -0
- package/dist/core/getHeaderLevels.js +50 -0
- package/dist/core/getRecordCount.js +23 -0
- package/dist/core/getSummaryLabel.js +35 -0
- package/dist/core/getValueSignature.js +26 -0
- package/dist/core/isDataItem.js +21 -0
- package/dist/core/isDefaultViewColumns.js +36 -0
- package/dist/core/isRowEqual.js +40 -0
- package/dist/core/isSameSignature.js +19 -0
- package/dist/core/lazyCellTypes.js +33 -0
- package/dist/core/lazyComponent.js +30 -0
- package/dist/core/loadOptionalFeature.js +35 -0
- package/dist/core/normalizeViewColumn.js +29 -0
- package/dist/core/pickViewPart.js +23 -0
- package/dist/core/renderRegion.js +21 -0
- package/dist/core/resolveMountValue.js +31 -0
- package/dist/core/resolveViewColumns.js +65 -0
- package/dist/core/someColumnConfig.js +30 -0
- package/dist/core/stabilizeData.js +90 -0
- package/dist/core/table.css +557 -0
- package/dist/core/useFeatureData.js +35 -0
- package/dist/core/useFeatureFragments.js +55 -0
- package/dist/core/useFeatureItems.js +78 -0
- package/dist/core/useFeatureMethods.js +29 -0
- package/dist/core/useFeatureRows.js +36 -0
- package/dist/core/useFeatureSet.js +54 -0
- package/dist/core/useForeignKeys.js +38 -0
- package/dist/core/useGridFeatures.js +26 -0
- package/dist/core/useStableConfig.js +34 -0
- package/dist/core/useSummary.js +73 -0
- package/dist/core/useTableConfig.js +189 -0
- package/dist/core/useTableState.js +150 -0
- package/dist/core/useViewportSize.js +40 -0
- package/dist/e2e.js +16 -0
- package/dist/features/bulk/BulkBar.js +46 -0
- package/dist/features/bulk/bulk.css +57 -0
- package/dist/features/bulk/bulkFeature.js +28 -0
- package/dist/features/bulk/countSelection.js +27 -0
- package/dist/features/bulk/createSelectAllMatching.js +43 -0
- package/dist/features/bulk/useBulkBar.js +42 -0
- package/dist/features/clipboard/clipboardFeature.js +24 -0
- package/dist/features/clipboard/createPasteCells.js +61 -0
- package/dist/features/clipboard/getCopyText.js +57 -0
- package/dist/features/clipboard/handleCopyKeyDown.js +37 -0
- package/dist/features/clipboard/parseTsv.js +70 -0
- package/dist/features/clipboard/pasteFeature.js +26 -0
- package/dist/features/clipboard/planPaste.js +101 -0
- package/dist/features/clipboard/serializeTsv.js +25 -0
- package/dist/features/clipboard/usePasteListener.js +45 -0
- package/dist/features/columnManager/ColumnManager.js +253 -0
- package/dist/features/columnManager/ColumnManagerPopover.js +37 -0
- package/dist/features/columnManager/DragHandleIcon.js +39 -0
- package/dist/features/columnManager/LazyColumnManagerPopover.js +19 -0
- package/dist/features/columnManager/applyManagerRegions.js +43 -0
- package/dist/features/columnManager/boundaryIds.js +21 -0
- package/dist/features/columnManager/buildManagerSequence.js +38 -0
- package/dist/features/columnManager/columnManager.css +155 -0
- package/dist/features/columnManager/columnManagerFeature.js +37 -0
- package/dist/features/columnManager/createCloseColumnManager.js +21 -0
- package/dist/features/columnManager/createOpenColumnManager.js +21 -0
- package/dist/features/columnManager/createResetColumns.js +43 -0
- package/dist/features/columnManager/getColumnManagerMenuItems.js +26 -0
- package/dist/features/columnManager/getListRoom.js +31 -0
- package/dist/features/columnManager/getManagerEntries.js +31 -0
- package/dist/features/columnManager/moveSequenceEntry.js +25 -0
- package/dist/features/columnManager/sequenceToRegions.js +38 -0
- package/dist/features/columnManager/snapListHeight.js +35 -0
- package/dist/features/columnManager/updateScrollHints.js +23 -0
- package/dist/features/columnManager/useColumnManager.js +36 -0
- package/dist/features/density/densityFeature.js +39 -0
- package/dist/features/density/densityToValue.js +23 -0
- package/dist/features/density/getViewWrapColumn.js +53 -0
- package/dist/features/density/initDensity.js +27 -0
- package/dist/features/density/initWrap.js +23 -0
- package/dist/features/editing/AddRowButton.js +28 -0
- package/dist/features/editing/CellEditor.js +284 -0
- package/dist/features/editing/EditMarker.js +38 -0
- package/dist/features/editing/EditingLayer.js +148 -0
- package/dist/features/editing/RowControlsCell.js +89 -0
- package/dist/features/editing/RowControlsHeader.js +18 -0
- package/dist/features/editing/SelectedTag.js +33 -0
- package/dist/features/editing/addChangeRow.js +34 -0
- package/dist/features/editing/applyChangeUpdates.js +28 -0
- package/dist/features/editing/applyChanges.js +90 -0
- package/dist/features/editing/applyMoveOverlay.js +44 -0
- package/dist/features/editing/applyMoveToChanges.js +66 -0
- package/dist/features/editing/applyOverlay.js +41 -0
- package/dist/features/editing/coerceCellValue.js +187 -0
- package/dist/features/editing/collectRawColumns.js +38 -0
- package/dist/features/editing/computeEditTargets.js +108 -0
- package/dist/features/editing/computeRowMove.js +78 -0
- package/dist/features/editing/createAddRow.js +68 -0
- package/dist/features/editing/createCancelEdit.js +29 -0
- package/dist/features/editing/createCommitEdit.js +124 -0
- package/dist/features/editing/createDeleteRow.js +39 -0
- package/dist/features/editing/createEditSpecs.js +80 -0
- package/dist/features/editing/createEmptyChanges.js +23 -0
- package/dist/features/editing/createMoveRow.js +65 -0
- package/dist/features/editing/createNewRow.js +32 -0
- package/dist/features/editing/createResetChanges.js +29 -0
- package/dist/features/editing/createSaveCellEdit.js +113 -0
- package/dist/features/editing/createSaveRowMove.js +90 -0
- package/dist/features/editing/createStartEdit.js +57 -0
- package/dist/features/editing/createStepHistory.js +33 -0
- package/dist/features/editing/createUndoStack.js +67 -0
- package/dist/features/editing/createValueStore.js +34 -0
- package/dist/features/editing/createWriteCell.js +34 -0
- package/dist/features/editing/createWriteChanges.js +43 -0
- package/dist/features/editing/editing.css +223 -0
- package/dist/features/editing/editingFeature.js +66 -0
- package/dist/features/editing/findCellByKey.js +23 -0
- package/dist/features/editing/findInvalidCells.js +41 -0
- package/dist/features/editing/findNextEditableCell.js +54 -0
- package/dist/features/editing/focusCell.js +28 -0
- package/dist/features/editing/fromDateValue.js +29 -0
- package/dist/features/editing/fromEditorDraft.js +45 -0
- package/dist/features/editing/generateRowKey.js +25 -0
- package/dist/features/editing/getDataGap.js +28 -0
- package/dist/features/editing/getEditOptions.js +33 -0
- package/dist/features/editing/getEditorKind.js +36 -0
- package/dist/features/editing/getEventError.js +24 -0
- package/dist/features/editing/getKeyField.js +23 -0
- package/dist/features/editing/getReorderBlock.js +33 -0
- package/dist/features/editing/handleEditDoubleClick.js +34 -0
- package/dist/features/editing/handleEditKeyDown.js +123 -0
- package/dist/features/editing/handleRowControlsClick.js +29 -0
- package/dist/features/editing/handleRowDragPointerDown.js +95 -0
- package/dist/features/editing/isCellEditable.js +20 -0
- package/dist/features/editing/isPrintableKey.js +22 -0
- package/dist/features/editing/isSameTargets.js +19 -0
- package/dist/features/editing/matchOption.js +21 -0
- package/dist/features/editing/needsEditing.js +26 -0
- package/dist/features/editing/normalizeChanges.js +37 -0
- package/dist/features/editing/positionBetween.js +30 -0
- package/dist/features/editing/pruneOverlay.js +39 -0
- package/dist/features/editing/removeChangeRow.js +48 -0
- package/dist/features/editing/reorderByKeys.js +34 -0
- package/dist/features/editing/rowControlsColumn.js +33 -0
- package/dist/features/editing/setChangeField.js +72 -0
- package/dist/features/editing/setRowField.js +23 -0
- package/dist/features/editing/sortByPosition.js +31 -0
- package/dist/features/editing/toDateValue.js +38 -0
- package/dist/features/editing/toEditorDraft.js +56 -0
- package/dist/features/editing/toSelectOptions.js +39 -0
- package/dist/features/editing/useEditingData.js +199 -0
- package/dist/features/editing/useEditingFragments.js +77 -0
- package/dist/features/editing/useEditingGrid.js +25 -0
- package/dist/features/editing/validateCellValue.js +25 -0
- package/dist/features/editing/valuesEqual.js +31 -0
- package/dist/features/editing/warnMissingEvent.js +23 -0
- package/dist/features/events/createActivateRow.js +54 -0
- package/dist/features/events/eventsFeature.js +35 -0
- package/dist/features/events/getBodyTarget.js +27 -0
- package/dist/features/events/getRowIndex.js +24 -0
- package/dist/features/events/handleAuxClick.js +38 -0
- package/dist/features/events/handlePointerDown.js +22 -0
- package/dist/features/events/handleRowClick.js +57 -0
- package/dist/features/events/handleRowDoubleClick.js +45 -0
- package/dist/features/events/isTextDrag.js +30 -0
- package/dist/features/events/openRowLink.js +29 -0
- package/dist/features/expandable/DetailRow.js +57 -0
- package/dist/features/expandable/ExpandToggle.js +34 -0
- package/dist/features/expandable/expandable.css +40 -0
- package/dist/features/expandable/expandableFeature.js +34 -0
- package/dist/features/expandable/handleExpandClick.js +25 -0
- package/dist/features/expandable/needsExpandable.js +20 -0
- package/dist/features/expandable/normalizeExpandable.js +52 -0
- package/dist/features/expandable/useExpandableItems.js +101 -0
- package/dist/features/expansion/createToggleRowExpanded.js +52 -0
- package/dist/features/expansion/expansionFeature.js +31 -0
- package/dist/features/expansion/getExpandedIds.js +26 -0
- package/dist/features/expansion/initExpanded.js +22 -0
- package/dist/features/export/buildCsv.js +39 -0
- package/dist/features/export/createExportCsv.js +59 -0
- package/dist/features/export/exportFeature.js +25 -0
- package/dist/features/export/toCsvField.js +20 -0
- package/dist/features/filtering/ChoiceFilter.js +30 -0
- package/dist/features/filtering/CloseIcon.js +29 -0
- package/dist/features/filtering/ColumnFilter.js +192 -0
- package/dist/features/filtering/ColumnFilterPopover.js +38 -0
- package/dist/features/filtering/DateFilter.js +80 -0
- package/dist/features/filtering/DraftInput.js +37 -0
- package/dist/features/filtering/DraftInputNumber.js +36 -0
- package/dist/features/filtering/FilterBuilder.js +45 -0
- package/dist/features/filtering/FilterGroup.js +116 -0
- package/dist/features/filtering/FilterIcon.js +26 -0
- package/dist/features/filtering/FilterIndicator.js +40 -0
- package/dist/features/filtering/FilterLeaf.js +86 -0
- package/dist/features/filtering/LazyColumnFilterPopover.js +19 -0
- package/dist/features/filtering/LazyFilterBuilder.js +19 -0
- package/dist/features/filtering/NumberFilter.js +43 -0
- package/dist/features/filtering/OptionsFilter.js +72 -0
- package/dist/features/filtering/RelativeDateEditor.js +90 -0
- package/dist/features/filtering/TextFilter.js +51 -0
- package/dist/features/filtering/ValueEditor.js +210 -0
- package/dist/features/filtering/buildColumnFilter.js +95 -0
- package/dist/features/filtering/changeLeafOperator.js +46 -0
- package/dist/features/filtering/createApplyFiltering.js +78 -0
- package/dist/features/filtering/createClearFilters.js +24 -0
- package/dist/features/filtering/createCloseColumnFilter.js +28 -0
- package/dist/features/filtering/createConditionFilteredRowModel.js +40 -0
- package/dist/features/filtering/createDefaultLeaf.js +31 -0
- package/dist/features/filtering/createOpenColumnFilter.js +25 -0
- package/dist/features/filtering/createRowTest.js +32 -0
- package/dist/features/filtering/createSearchMatcher.js +35 -0
- package/dist/features/filtering/createSetFilter.js +27 -0
- package/dist/features/filtering/createSetSearch.js +29 -0
- package/dist/features/filtering/createUpdateColumnFilter.js +29 -0
- package/dist/features/filtering/defaultRelativeDate.js +20 -0
- package/dist/features/filtering/filterRowModel.js +66 -0
- package/dist/features/filtering/filtering.css +151 -0
- package/dist/features/filtering/filteringFeature.js +82 -0
- package/dist/features/filtering/filteringToValue.js +23 -0
- package/dist/features/filtering/formatFilterDate.js +24 -0
- package/dist/features/filtering/getColumnConditions.js +24 -0
- package/dist/features/filtering/getConditionKeys.js +31 -0
- package/dist/features/filtering/getDistinctOptions.js +52 -0
- package/dist/features/filtering/getFilterKind.js +37 -0
- package/dist/features/filtering/getFilterResultKey.js +26 -0
- package/dist/features/filtering/getFilterResults.js +53 -0
- package/dist/features/filtering/getFilteredKeys.js +31 -0
- package/dist/features/filtering/getFilteringHeaderProps.js +22 -0
- package/dist/features/filtering/getFilteringMenuItems.js +42 -0
- package/dist/features/filtering/getFilteringTableOptions.js +33 -0
- package/dist/features/filtering/getGroupOperator.js +23 -0
- package/dist/features/filtering/getOperatorLabel.js +50 -0
- package/dist/features/filtering/getPlainTitle.js +26 -0
- package/dist/features/filtering/getSearchColumns.js +23 -0
- package/dist/features/filtering/getSearchKey.js +19 -0
- package/dist/features/filtering/getSearchText.js +57 -0
- package/dist/features/filtering/getTopLevelConditions.js +25 -0
- package/dist/features/filtering/getValueShape.js +30 -0
- package/dist/features/filtering/handleFilterIndicatorClick.js +25 -0
- package/dist/features/filtering/initFilter.js +25 -0
- package/dist/features/filtering/initSearch.js +24 -0
- package/dist/features/filtering/isColumnCondition.js +22 -0
- package/dist/features/filtering/isCompleteLeaf.js +45 -0
- package/dist/features/filtering/isServerMode.js +21 -0
- package/dist/features/filtering/normalizeSearch.js +21 -0
- package/dist/features/filtering/parseColumnFilter.js +128 -0
- package/dist/features/filtering/parseFilterDate.js +24 -0
- package/dist/features/filtering/prepareFilterResult.js +63 -0
- package/dist/features/filtering/pruneCondition.js +35 -0
- package/dist/features/filtering/setColumnFilter.js +51 -0
- package/dist/features/filtering/textFilterOperators.js +26 -0
- package/dist/features/filtering/toRootGroup.js +34 -0
- package/dist/features/filtering/useDraft.js +65 -0
- package/dist/features/filtering/useFilteringState.js +32 -0
- package/dist/features/filtering/useSyncedState.js +45 -0
- package/dist/features/grouping/GroupCell.js +72 -0
- package/dist/features/grouping/GroupCheckbox.js +38 -0
- package/dist/features/grouping/GroupLabel.js +73 -0
- package/dist/features/grouping/GroupRow.js +103 -0
- package/dist/features/grouping/StickyGroupRow.js +136 -0
- package/dist/features/grouping/buildGroupTree.js +138 -0
- package/dist/features/grouping/buildStickyLevels.js +35 -0
- package/dist/features/grouping/countGroupSelection.js +26 -0
- package/dist/features/grouping/createAggregateColumns.js +38 -0
- package/dist/features/grouping/createCollapseAllGroups.js +26 -0
- package/dist/features/grouping/createExpandAllGroups.js +23 -0
- package/dist/features/grouping/createGroupLevels.js +46 -0
- package/dist/features/grouping/createSetCollapsedGroups.js +27 -0
- package/dist/features/grouping/createSetGroup.js +35 -0
- package/dist/features/grouping/createSetGroupKeys.js +27 -0
- package/dist/features/grouping/createToggleGroup.js +38 -0
- package/dist/features/grouping/createToggleGroupSelected.js +49 -0
- package/dist/features/grouping/findGroupIndices.js +25 -0
- package/dist/features/grouping/flattenGroups.js +58 -0
- package/dist/features/grouping/getGroupLabel.js +34 -0
- package/dist/features/grouping/getStickyGroups.js +60 -0
- package/dist/features/grouping/groupRowsFeature.js +57 -0
- package/dist/features/grouping/grouping.css +128 -0
- package/dist/features/grouping/groupingFeature.js +48 -0
- package/dist/features/grouping/groupingHeaderMenuItems.js +44 -0
- package/dist/features/grouping/groupingToValue.js +26 -0
- package/dist/features/grouping/handleGroupClick.js +51 -0
- package/dist/features/grouping/handleGroupKeyDown.js +60 -0
- package/dist/features/grouping/initAggregates.js +36 -0
- package/dist/features/grouping/initCollapsedGroups.js +29 -0
- package/dist/features/grouping/initGrouping.js +34 -0
- package/dist/features/grouping/needsGroupRows.js +23 -0
- package/dist/features/grouping/orderGroups.js +49 -0
- package/dist/features/grouping/resolveAggregates.js +29 -0
- package/dist/features/grouping/toGroupIdentity.js +24 -0
- package/dist/features/grouping/toGroupKeys.js +24 -0
- package/dist/features/grouping/useGrouping.js +91 -0
- package/dist/features/headerMenu/HeaderMenuDropdown.js +86 -0
- package/dist/features/headerMenu/HeaderMenuTrigger.js +44 -0
- package/dist/features/headerMenu/LazyHeaderMenuDropdown.js +19 -0
- package/dist/features/headerMenu/MenuIcon.js +38 -0
- package/dist/features/headerMenu/collectHeaderMenuItems.js +69 -0
- package/dist/features/headerMenu/createAutosizeColumn.js +35 -0
- package/dist/features/headerMenu/createCloseHeaderMenu.js +28 -0
- package/dist/features/headerMenu/createOpenHeaderMenu.js +30 -0
- package/dist/features/headerMenu/focusHeaderControl.js +31 -0
- package/dist/features/headerMenu/freezeColumns.js +31 -0
- package/dist/features/headerMenu/getChromeMenuItems.js +144 -0
- package/dist/features/headerMenu/getVisibleOrder.js +19 -0
- package/dist/features/headerMenu/handleHeaderButtonPointerDown.js +27 -0
- package/dist/features/headerMenu/handleHeaderMenuClick.js +26 -0
- package/dist/features/headerMenu/handleHeaderMenuKeyDown.js +28 -0
- package/dist/features/headerMenu/headerMenu.css +122 -0
- package/dist/features/headerMenu/headerMenuFeature.js +46 -0
- package/dist/features/headerMenu/measureColumnWidth.js +51 -0
- package/dist/features/headerMenu/pinColumn.js +27 -0
- package/dist/features/headerMenu/sectionOrder.js +25 -0
- package/dist/features/headerMenu/useHeaderMenuState.js +27 -0
- package/dist/features/index.js +149 -0
- package/dist/features/keyboard/findCellElement.js +21 -0
- package/dist/features/keyboard/getNextCell.js +74 -0
- package/dist/features/keyboard/handleGridFocus.js +31 -0
- package/dist/features/keyboard/handleGridKeyDown.js +72 -0
- package/dist/features/keyboard/isCellRendered.js +22 -0
- package/dist/features/keyboard/keyboardFeature.js +26 -0
- package/dist/features/keyboard/useKeyboard.js +84 -0
- package/dist/features/lazyCells/getBodyRowKey.js +19 -0
- package/dist/features/lazyCells/handlePointerLeave.js +21 -0
- package/dist/features/lazyCells/handlePointerOver.js +22 -0
- package/dist/features/lazyCells/handleRowBlur.js +22 -0
- package/dist/features/lazyCells/handleRowFocus.js +26 -0
- package/dist/features/lazyCells/lazyCellsFeature.js +33 -0
- package/dist/features/lazyCells/useFastScroll.js +57 -0
- package/dist/features/ordering/getColumnClientBounds.js +32 -0
- package/dist/features/ordering/handleReorderPointerDown.js +137 -0
- package/dist/features/ordering/initColumnOrder.js +18 -0
- package/dist/features/ordering/moveKeys.js +27 -0
- package/dist/features/ordering/orderingFeature.js +35 -0
- package/dist/features/pagination/TablePagination.js +31 -0
- package/dist/features/pagination/initPageSize.js +28 -0
- package/dist/features/pagination/paginationFeature.js +36 -0
- package/dist/features/pagination/paginationToValue.js +24 -0
- package/dist/features/pagination/usePager.js +32 -0
- package/dist/features/pagination/usePagination.js +58 -0
- package/dist/features/pinning/initColumnPinning.js +21 -0
- package/dist/features/pinning/pinningFeature.js +33 -0
- package/dist/features/pinning/pinningToViewColumn.js +24 -0
- package/dist/features/queue/createAfterRowAction.js +40 -0
- package/dist/features/queue/findNextRowId.js +26 -0
- package/dist/features/queue/findRowAction.js +77 -0
- package/dist/features/queue/handleRowActionKey.js +44 -0
- package/dist/features/queue/queueFeature.js +27 -0
- package/dist/features/selection/SelectAllHeader.js +40 -0
- package/dist/features/selection/SelectCell.js +30 -0
- package/dist/features/selection/countSelectedRows.js +31 -0
- package/dist/features/selection/createClearSelection.js +29 -0
- package/dist/features/selection/createToggleAllRowsSelected.js +60 -0
- package/dist/features/selection/createToggleRowSelected.js +86 -0
- package/dist/features/selection/getRawRowKey.js +23 -0
- package/dist/features/selection/getSelectAllExcept.js +23 -0
- package/dist/features/selection/getSelectAllState.js +42 -0
- package/dist/features/selection/handleSelectionClick.js +30 -0
- package/dist/features/selection/initRowSelection.js +36 -0
- package/dist/features/selection/initSelectionMode.js +19 -0
- package/dist/features/selection/initSelectionView.js +35 -0
- package/dist/features/selection/isSelectAllValue.js +19 -0
- package/dist/features/selection/isSelectionViewCurrent.js +22 -0
- package/dist/features/selection/notifySelectionChange.js +32 -0
- package/dist/features/selection/pruneRowSelection.js +26 -0
- package/dist/features/selection/selectionFeature.js +69 -0
- package/dist/features/selection/selectionToValue.js +48 -0
- package/dist/features/selection/useSelection.js +77 -0
- package/dist/features/serverData/buildServerItems.js +109 -0
- package/dist/features/serverData/createBlockCache.js +205 -0
- package/dist/features/serverData/createRefresh.js +23 -0
- package/dist/features/serverData/createServerStore.js +360 -0
- package/dist/features/serverData/getBlockRange.js +29 -0
- package/dist/features/serverData/getListKey.js +20 -0
- package/dist/features/serverData/getNeededBlocks.js +45 -0
- package/dist/features/serverData/needsServerData.js +20 -0
- package/dist/features/serverData/normalizeServerData.js +41 -0
- package/dist/features/serverData/pickServerView.js +43 -0
- package/dist/features/serverData/readFetchResult.js +36 -0
- package/dist/features/serverData/serverData.css +21 -0
- package/dist/features/serverData/serverDataFeature.js +38 -0
- package/dist/features/serverData/serverRangeFeature.js +22 -0
- package/dist/features/serverData/useServerData.js +48 -0
- package/dist/features/serverData/useServerItems.js +35 -0
- package/dist/features/serverData/useServerRange.js +35 -0
- package/dist/features/serverData/useServerView.js +70 -0
- package/dist/features/sizing/ResizeHandle.js +24 -0
- package/dist/features/sizing/handleResizePointerDown.js +66 -0
- package/dist/features/sizing/initColumnSizing.js +23 -0
- package/dist/features/sizing/sizingFeature.js +39 -0
- package/dist/features/sizing/sizingToViewColumn.js +24 -0
- package/dist/features/sorting/SortIndicator.js +37 -0
- package/dist/features/sorting/buildSortKeys.js +52 -0
- package/dist/features/sorting/collectSortKeys.js +30 -0
- package/dist/features/sorting/createClearSort.js +21 -0
- package/dist/features/sorting/createIndexSortedRowModel.js +33 -0
- package/dist/features/sorting/createSetSort.js +43 -0
- package/dist/features/sorting/createSortKeyCollector.js +59 -0
- package/dist/features/sorting/createToggleSort.js +42 -0
- package/dist/features/sorting/getCachedSortKeys.js +19 -0
- package/dist/features/sorting/getSortHeaderProps.js +25 -0
- package/dist/features/sorting/getSortKeys.js +38 -0
- package/dist/features/sorting/handleSortClick.js +27 -0
- package/dist/features/sorting/initSorting.js +37 -0
- package/dist/features/sorting/isNumericSortType.js +21 -0
- package/dist/features/sorting/prepareSortKeys.js +92 -0
- package/dist/features/sorting/rankSortKeys.js +33 -0
- package/dist/features/sorting/setCachedSortKeys.js +24 -0
- package/dist/features/sorting/sortInSlices.js +69 -0
- package/dist/features/sorting/sortIndices.js +40 -0
- package/dist/features/sorting/sortKeysCache.js +19 -0
- package/dist/features/sorting/sortRowModel.js +84 -0
- package/dist/features/sorting/sortingFeature.js +62 -0
- package/dist/features/sorting/sortingToValue.js +27 -0
- package/dist/features/sorting/toFloatSortKeys.js +24 -0
- package/dist/features/sorting/yieldToMain.js +27 -0
- package/dist/features/toolbar/ColumnTitle.js +28 -0
- package/dist/features/toolbar/DensityToggle.js +53 -0
- package/dist/features/toolbar/FilterButton.js +56 -0
- package/dist/features/toolbar/GroupButton.js +51 -0
- package/dist/features/toolbar/OptionsQuickFilter.js +72 -0
- package/dist/features/toolbar/QuickFilter.js +46 -0
- package/dist/features/toolbar/RecordCount.js +27 -0
- package/dist/features/toolbar/SaveViewAs.js +66 -0
- package/dist/features/toolbar/SortButton.js +94 -0
- package/dist/features/toolbar/Toolbar.js +88 -0
- package/dist/features/toolbar/ToolbarCount.js +25 -0
- package/dist/features/toolbar/ToolbarIcon.js +28 -0
- package/dist/features/toolbar/ToolbarList.js +100 -0
- package/dist/features/toolbar/ToolbarSearch.js +63 -0
- package/dist/features/toolbar/ViewActions.js +41 -0
- package/dist/features/toolbar/ViewTabLabel.js +39 -0
- package/dist/features/toolbar/ViewTabMenu.js +48 -0
- package/dist/features/toolbar/ViewTabs.js +44 -0
- package/dist/features/toolbar/countConditions.js +25 -0
- package/dist/features/toolbar/formatRecordCount.js +19 -0
- package/dist/features/toolbar/getQuickFilterValues.js +25 -0
- package/dist/features/toolbar/getRootConditions.js +25 -0
- package/dist/features/toolbar/handleToolbarKeyDown.js +28 -0
- package/dist/features/toolbar/isDefaultSorting.js +26 -0
- package/dist/features/toolbar/isQuickFilterLeaf.js +20 -0
- package/dist/features/toolbar/moveItem.js +25 -0
- package/dist/features/toolbar/needsToolbar.js +21 -0
- package/dist/features/toolbar/normalizeToolbar.js +61 -0
- package/dist/features/toolbar/setQuickFilterValues.js +35 -0
- package/dist/features/toolbar/toolbar.css +185 -0
- package/dist/features/toolbar/toolbarFeature.js +27 -0
- package/dist/features/toolbar/useToolbar.js +41 -0
- package/dist/features/toolbar/validateQuickFilters.js +28 -0
- package/dist/features/transactions/applyTransactionToRows.js +56 -0
- package/dist/features/transactions/createApplyTransaction.js +26 -0
- package/dist/features/transactions/normalizeTransaction.js +49 -0
- package/dist/features/transactions/transactionsFeature.js +24 -0
- package/dist/features/transactions/useTransactionData.js +44 -0
- package/dist/features/tree/TreeToggle.js +39 -0
- package/dist/features/tree/buildTreeIndex.js +60 -0
- package/dist/features/tree/buildTreeItems.js +96 -0
- package/dist/features/tree/flattenTreeData.js +45 -0
- package/dist/features/tree/getDescendantIds.js +28 -0
- package/dist/features/tree/handleTreeClick.js +25 -0
- package/dist/features/tree/handleTreeKeyDown.js +58 -0
- package/dist/features/tree/needsTree.js +20 -0
- package/dist/features/tree/normalizeTree.js +41 -0
- package/dist/features/tree/rowNeedsChildren.js +25 -0
- package/dist/features/tree/tree.css +55 -0
- package/dist/features/tree/treeFeature.js +35 -0
- package/dist/features/tree/useTreeData.js +33 -0
- package/dist/features/tree/useTreeItems.js +61 -0
- package/dist/features/views/compactView.js +30 -0
- package/dist/features/views/createViewsApi.js +74 -0
- package/dist/features/views/decodeViewParam.js +30 -0
- package/dist/features/views/encodeViewParam.js +25 -0
- package/dist/features/views/findActiveView.js +23 -0
- package/dist/features/views/getStorageKey.js +20 -0
- package/dist/features/views/getViewKey.js +27 -0
- package/dist/features/views/getViewSliceDeps.js +27 -0
- package/dist/features/views/isViewDirty.js +34 -0
- package/dist/features/views/mountViewValue.js +36 -0
- package/dist/features/views/needsViews.js +23 -0
- package/dist/features/views/normalizePersist.js +27 -0
- package/dist/features/views/normalizeViews.js +41 -0
- package/dist/features/views/notifyViewSelect.js +29 -0
- package/dist/features/views/readMountPayload.js +31 -0
- package/dist/features/views/readPersistedView.js +45 -0
- package/dist/features/views/sanitizePersistedView.js +49 -0
- package/dist/features/views/stableStringify.js +27 -0
- package/dist/features/views/useViews.js +136 -0
- package/dist/features/views/viewKeys.js +28 -0
- package/dist/features/views/viewsFeature.js +26 -0
- package/dist/features/views/writePersistedView.js +42 -0
- package/dist/features/virtualization/computeRowOffsets.js +29 -0
- package/dist/features/virtualization/computeWindow.js +92 -0
- package/dist/features/virtualization/createScrollToRow.js +36 -0
- package/dist/features/virtualization/firstIndexAbove.js +30 -0
- package/dist/features/virtualization/getMeasureKey.js +23 -0
- package/dist/features/virtualization/isMeasuredColumn.js +20 -0
- package/dist/features/virtualization/isSameRange.js +18 -0
- package/dist/features/virtualization/positionedRowsFeature.js +22 -0
- package/dist/features/virtualization/scrollToCell.js +49 -0
- package/dist/features/virtualization/shiftRowOffsets.js +35 -0
- package/dist/features/virtualization/usePositionedRows.js +37 -0
- package/dist/features/virtualization/useRowOffsets.js +123 -0
- package/dist/features/virtualization/useScrollWindow.js +114 -0
- package/dist/features/virtualization/useTanstackRowWindow.js +43 -0
- package/dist/features/virtualization/useVirtualization.js +64 -0
- package/dist/features/virtualization/virtualizationFeature.js +24 -0
- package/dist/features/virtualization/writeScrollEdges.js +33 -0
- package/dist/features/visibility/initColumnVisibility.js +22 -0
- package/dist/features/visibility/visibilityFeature.js +31 -0
- package/dist/features/visibility/visibilityToViewColumn.js +20 -0
- package/dist/metas.js +16 -0
- package/dist/types.js +17 -0
- package/package.json +91 -0
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import getBlockRange from './getBlockRange.js';
|
|
16
|
+
function getBlockId({ listKey, index }) {
|
|
17
|
+
return `${listKey}#${index}`;
|
|
18
|
+
}
|
|
19
|
+
// Rows of one server view, in blocks of `blockSize` per list (the root list and each expanded
|
|
20
|
+
// group's list). Blocks are evicted least recently used beyond `maxBlocks` loaded blocks, never
|
|
21
|
+
// one the caller still needs (`keep`) or one that is loading.
|
|
22
|
+
//
|
|
23
|
+
// `generation` counts invalidations. A load records the generation it started in and its
|
|
24
|
+
// response is only accepted if nothing invalidated the cache since (triggerEvent cannot be
|
|
25
|
+
// aborted, so stale responses are ignored instead). An invalidated block keeps its rows on screen
|
|
26
|
+
// until its reload lands.
|
|
27
|
+
function createBlockCache({ blockSize, maxBlocks }) {
|
|
28
|
+
const lists = new Map();
|
|
29
|
+
// Map iteration order is insertion order: touching a block re-inserts it, so the first entry
|
|
30
|
+
// is always the least recently used.
|
|
31
|
+
const blocks = new Map();
|
|
32
|
+
let generation = 0;
|
|
33
|
+
let loadedCount = 0;
|
|
34
|
+
function getList(listKey) {
|
|
35
|
+
let list = lists.get(listKey);
|
|
36
|
+
if (!list) {
|
|
37
|
+
list = {
|
|
38
|
+
total: null,
|
|
39
|
+
aggregates: null,
|
|
40
|
+
error: null
|
|
41
|
+
};
|
|
42
|
+
lists.set(listKey, list);
|
|
43
|
+
}
|
|
44
|
+
return list;
|
|
45
|
+
}
|
|
46
|
+
function evict(keep) {
|
|
47
|
+
for (const [id, block] of blocks){
|
|
48
|
+
if (loadedCount <= maxBlocks) return;
|
|
49
|
+
if (block.status !== 'loaded' || keep?.has(id)) continue;
|
|
50
|
+
blocks.delete(id);
|
|
51
|
+
loadedCount -= 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function setStatus(block, status) {
|
|
55
|
+
if (block.status === 'loaded') loadedCount -= 1;
|
|
56
|
+
if (status === 'loaded') loadedCount += 1;
|
|
57
|
+
block.status = status;
|
|
58
|
+
}
|
|
59
|
+
const cache = {
|
|
60
|
+
blockSize,
|
|
61
|
+
getBlockId,
|
|
62
|
+
get generation () {
|
|
63
|
+
return generation;
|
|
64
|
+
},
|
|
65
|
+
get loadedCount () {
|
|
66
|
+
return loadedCount;
|
|
67
|
+
},
|
|
68
|
+
getTotal (listKey) {
|
|
69
|
+
return lists.get(listKey)?.total ?? null;
|
|
70
|
+
},
|
|
71
|
+
getAggregates (listKey) {
|
|
72
|
+
return lists.get(listKey)?.aggregates ?? null;
|
|
73
|
+
},
|
|
74
|
+
getError (listKey) {
|
|
75
|
+
return lists.get(listKey)?.error ?? null;
|
|
76
|
+
},
|
|
77
|
+
hasList (listKey) {
|
|
78
|
+
return lists.has(listKey);
|
|
79
|
+
},
|
|
80
|
+
getBlock (listKey, index) {
|
|
81
|
+
return blocks.get(getBlockId({
|
|
82
|
+
listKey,
|
|
83
|
+
index
|
|
84
|
+
}));
|
|
85
|
+
},
|
|
86
|
+
getRow (listKey, rowIndex) {
|
|
87
|
+
const block = blocks.get(getBlockId({
|
|
88
|
+
listKey,
|
|
89
|
+
index: Math.floor(rowIndex / blockSize)
|
|
90
|
+
}));
|
|
91
|
+
return block?.rows?.[rowIndex % blockSize];
|
|
92
|
+
},
|
|
93
|
+
touch (listKey, index) {
|
|
94
|
+
const id = getBlockId({
|
|
95
|
+
listKey,
|
|
96
|
+
index
|
|
97
|
+
});
|
|
98
|
+
const block = blocks.get(id);
|
|
99
|
+
if (!block) return;
|
|
100
|
+
blocks.delete(id);
|
|
101
|
+
blocks.set(id, block);
|
|
102
|
+
},
|
|
103
|
+
// A block needs a load when it is missing or from an earlier generation. A block loading in
|
|
104
|
+
// this generation, or one that failed in it, does not (a refresh retries failures).
|
|
105
|
+
needsLoad (listKey, index) {
|
|
106
|
+
const block = blocks.get(getBlockId({
|
|
107
|
+
listKey,
|
|
108
|
+
index
|
|
109
|
+
}));
|
|
110
|
+
return !block || block.generation !== generation;
|
|
111
|
+
},
|
|
112
|
+
getMissingBlocks ({ listKey, startRow, endRow }) {
|
|
113
|
+
const { first, last } = getBlockRange({
|
|
114
|
+
startRow,
|
|
115
|
+
endRow,
|
|
116
|
+
blockSize,
|
|
117
|
+
total: cache.getTotal(listKey)
|
|
118
|
+
});
|
|
119
|
+
const missing = [];
|
|
120
|
+
for(let index = first; index <= last; index++){
|
|
121
|
+
if (cache.needsLoad(listKey, index)) missing.push(index);
|
|
122
|
+
}
|
|
123
|
+
return missing;
|
|
124
|
+
},
|
|
125
|
+
startLoad (listKey, index) {
|
|
126
|
+
getList(listKey);
|
|
127
|
+
const id = getBlockId({
|
|
128
|
+
listKey,
|
|
129
|
+
index
|
|
130
|
+
});
|
|
131
|
+
let block = blocks.get(id);
|
|
132
|
+
if (!block) {
|
|
133
|
+
block = {
|
|
134
|
+
listKey,
|
|
135
|
+
index,
|
|
136
|
+
status: 'loading',
|
|
137
|
+
rows: null,
|
|
138
|
+
generation
|
|
139
|
+
};
|
|
140
|
+
blocks.set(id, block);
|
|
141
|
+
} else {
|
|
142
|
+
// An invalidated block keeps its rows (and status) on screen while it reloads.
|
|
143
|
+
block.generation = generation;
|
|
144
|
+
if (block.status !== 'loaded') setStatus(block, 'loading');
|
|
145
|
+
block.reloading = true;
|
|
146
|
+
}
|
|
147
|
+
return {
|
|
148
|
+
generation
|
|
149
|
+
};
|
|
150
|
+
},
|
|
151
|
+
finishLoad ({ listKey, index, generation: loadGeneration, rows, total, aggregates, keep }) {
|
|
152
|
+
if (loadGeneration !== generation) return false;
|
|
153
|
+
const block = blocks.get(getBlockId({
|
|
154
|
+
listKey,
|
|
155
|
+
index
|
|
156
|
+
}));
|
|
157
|
+
if (!block || block.generation !== loadGeneration) return false;
|
|
158
|
+
block.rows = rows;
|
|
159
|
+
block.reloading = false;
|
|
160
|
+
setStatus(block, 'loaded');
|
|
161
|
+
const list = getList(listKey);
|
|
162
|
+
list.total = total;
|
|
163
|
+
list.aggregates = aggregates ?? null;
|
|
164
|
+
list.error = null;
|
|
165
|
+
cache.touch(listKey, index);
|
|
166
|
+
evict(keep);
|
|
167
|
+
return true;
|
|
168
|
+
},
|
|
169
|
+
failLoad ({ listKey, index, generation: loadGeneration, error }) {
|
|
170
|
+
if (loadGeneration !== generation) return false;
|
|
171
|
+
const block = blocks.get(getBlockId({
|
|
172
|
+
listKey,
|
|
173
|
+
index
|
|
174
|
+
}));
|
|
175
|
+
if (!block || block.generation !== loadGeneration) return false;
|
|
176
|
+
block.reloading = false;
|
|
177
|
+
if (block.status !== 'loaded') setStatus(block, 'error');
|
|
178
|
+
getList(listKey).error = error;
|
|
179
|
+
return true;
|
|
180
|
+
},
|
|
181
|
+
invalidate () {
|
|
182
|
+
generation += 1;
|
|
183
|
+
},
|
|
184
|
+
// Visits the loaded rows of every list: `fn(rows, block)`.
|
|
185
|
+
forEachLoaded (fn) {
|
|
186
|
+
blocks.forEach((block)=>{
|
|
187
|
+
if (block.rows) fn(block.rows, block);
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
// Replaces a loaded block's rows (a transaction); `total` changes with removed rows.
|
|
191
|
+
setBlockRows ({ listKey, index, rows }) {
|
|
192
|
+
const block = blocks.get(getBlockId({
|
|
193
|
+
listKey,
|
|
194
|
+
index
|
|
195
|
+
}));
|
|
196
|
+
if (block) block.rows = rows;
|
|
197
|
+
},
|
|
198
|
+
adjustTotal (listKey, delta) {
|
|
199
|
+
const list = lists.get(listKey);
|
|
200
|
+
if (list && typeof list.total === 'number') list.total = Math.max(0, list.total + delta);
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
return cache;
|
|
204
|
+
}
|
|
205
|
+
export default createBlockCache;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ // Block method `refresh()`: in server mode, purges the block cache and refetches the visible
|
|
16
|
+
// blocks (rows stay on screen until they land). In client mode `data` is the app's, so there is
|
|
17
|
+
// nothing to refetch.
|
|
18
|
+
function createRefresh(api) {
|
|
19
|
+
return function refresh() {
|
|
20
|
+
api.serverStore?.refresh();
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export default createRefresh;
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import applyTransactionToRows from '../transactions/applyTransactionToRows.js';
|
|
16
|
+
import buildServerItems from './buildServerItems.js';
|
|
17
|
+
import createBlockCache from './createBlockCache.js';
|
|
18
|
+
import getBlockRange from './getBlockRange.js';
|
|
19
|
+
import getListKey from './getListKey.js';
|
|
20
|
+
import getNeededBlocks from './getNeededBlocks.js';
|
|
21
|
+
import readFetchResult from './readFetchResult.js';
|
|
22
|
+
const ROOT = getListKey([]);
|
|
23
|
+
// Range changes faster than this (rows per millisecond, about 2000px/s at 40px rows) are a fast
|
|
24
|
+
// scroll or a scrollbar jump: loads wait until the range settles.
|
|
25
|
+
const FAST_ROWS_PER_MS = 0.05;
|
|
26
|
+
const SETTLE_MS = 120;
|
|
27
|
+
// Server mode's data source (D9). It owns the block cache of the current view, fetches blocks
|
|
28
|
+
// through the table's internal `__tableFetch` event, and keeps the previous view's cache on
|
|
29
|
+
// screen (dimmed) until the new view's first block lands. React subscribes to `version`.
|
|
30
|
+
function createServerStore({ api, server }) {
|
|
31
|
+
const { blockSize, maxBlocks } = server;
|
|
32
|
+
const listeners = new Set();
|
|
33
|
+
const store = {
|
|
34
|
+
cache: createBlockCache({
|
|
35
|
+
blockSize,
|
|
36
|
+
maxBlocks
|
|
37
|
+
}),
|
|
38
|
+
previous: null,
|
|
39
|
+
view: null,
|
|
40
|
+
viewKey: null,
|
|
41
|
+
groupKey: null,
|
|
42
|
+
selected: undefined,
|
|
43
|
+
expandedGroups: new Set(),
|
|
44
|
+
segments: [],
|
|
45
|
+
visible: new Set(),
|
|
46
|
+
lastRange: null,
|
|
47
|
+
timer: null,
|
|
48
|
+
version: 0,
|
|
49
|
+
requestCount: 0,
|
|
50
|
+
loadedRows: {
|
|
51
|
+
version: -1,
|
|
52
|
+
rows: [],
|
|
53
|
+
indices: new Map()
|
|
54
|
+
},
|
|
55
|
+
itemCache: new WeakMap()
|
|
56
|
+
};
|
|
57
|
+
function notify() {
|
|
58
|
+
store.version += 1;
|
|
59
|
+
listeners.forEach((listener)=>listener());
|
|
60
|
+
}
|
|
61
|
+
// The cache on screen: the current view's, or the previous view's until the first block of
|
|
62
|
+
// the current one lands.
|
|
63
|
+
function getDisplayCache() {
|
|
64
|
+
if (store.previous && store.cache.getTotal(ROOT) === null && !store.cache.getError(ROOT)) {
|
|
65
|
+
return store.previous;
|
|
66
|
+
}
|
|
67
|
+
return store.cache;
|
|
68
|
+
}
|
|
69
|
+
function fetchBlock({ listKey, groupPath, index }) {
|
|
70
|
+
const { cache } = store;
|
|
71
|
+
if (!cache.needsLoad(listKey, index)) return;
|
|
72
|
+
const { generation } = cache.startLoad(listKey, index);
|
|
73
|
+
const isGroupLevel = groupPath.length < (store.view.group ?? []).length;
|
|
74
|
+
store.requestCount += 1;
|
|
75
|
+
const event = {
|
|
76
|
+
startRow: index * blockSize,
|
|
77
|
+
endRow: (index + 1) * blockSize,
|
|
78
|
+
view: store.view,
|
|
79
|
+
groupPath,
|
|
80
|
+
selected: store.selected
|
|
81
|
+
};
|
|
82
|
+
Promise.resolve(api.methods.triggerEvent({
|
|
83
|
+
name: '__tableFetch',
|
|
84
|
+
event
|
|
85
|
+
})).then((result)=>{
|
|
86
|
+
// A later view has its own cache: this response belongs to a superseded view.
|
|
87
|
+
if (cache !== store.cache) return;
|
|
88
|
+
if (result?.success !== true) {
|
|
89
|
+
if (cache.failLoad({
|
|
90
|
+
listKey,
|
|
91
|
+
index,
|
|
92
|
+
generation,
|
|
93
|
+
error: result?.error ?? true
|
|
94
|
+
})) notify();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
let read;
|
|
98
|
+
try {
|
|
99
|
+
read = readFetchResult({
|
|
100
|
+
result,
|
|
101
|
+
isGroupLevel
|
|
102
|
+
});
|
|
103
|
+
} catch (error) {
|
|
104
|
+
cache.failLoad({
|
|
105
|
+
listKey,
|
|
106
|
+
index,
|
|
107
|
+
generation,
|
|
108
|
+
error
|
|
109
|
+
});
|
|
110
|
+
notify();
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
const accepted = cache.finishLoad({
|
|
114
|
+
listKey,
|
|
115
|
+
index,
|
|
116
|
+
generation,
|
|
117
|
+
rows: read.entries,
|
|
118
|
+
total: read.total,
|
|
119
|
+
aggregates: read.aggregates,
|
|
120
|
+
keep: store.visible
|
|
121
|
+
});
|
|
122
|
+
if (!accepted) return;
|
|
123
|
+
if (listKey === ROOT) store.previous = null;
|
|
124
|
+
notify();
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function loadVisible() {
|
|
128
|
+
store.timer = null;
|
|
129
|
+
const range = store.lastRange;
|
|
130
|
+
if (!range || !store.view) return;
|
|
131
|
+
let needed;
|
|
132
|
+
if (getDisplayCache() !== store.cache) {
|
|
133
|
+
// The items on screen belong to the previous view; only the new root list maps to them.
|
|
134
|
+
const { first, last } = getBlockRange({
|
|
135
|
+
startRow: range.rowStart,
|
|
136
|
+
endRow: range.rowEnd,
|
|
137
|
+
blockSize
|
|
138
|
+
});
|
|
139
|
+
needed = [];
|
|
140
|
+
for(let index = first; index <= last; index++){
|
|
141
|
+
needed.push({
|
|
142
|
+
listKey: ROOT,
|
|
143
|
+
groupPath: [],
|
|
144
|
+
index
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
} else {
|
|
148
|
+
needed = getNeededBlocks({
|
|
149
|
+
segments: store.segments,
|
|
150
|
+
rowStart: range.rowStart,
|
|
151
|
+
rowEnd: range.rowEnd,
|
|
152
|
+
blockSize
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
store.visible = new Set(needed.map((block)=>store.cache.getBlockId(block)));
|
|
156
|
+
needed.forEach((block)=>{
|
|
157
|
+
store.cache.touch(block.listKey, block.index);
|
|
158
|
+
fetchBlock(block);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
Object.assign(store, {
|
|
162
|
+
subscribe (listener) {
|
|
163
|
+
listeners.add(listener);
|
|
164
|
+
return ()=>listeners.delete(listener);
|
|
165
|
+
},
|
|
166
|
+
isLoading () {
|
|
167
|
+
const display = getDisplayCache();
|
|
168
|
+
return display.getTotal(ROOT) === null && !display.getError(ROOT);
|
|
169
|
+
},
|
|
170
|
+
isPending () {
|
|
171
|
+
return getDisplayCache() !== store.cache;
|
|
172
|
+
},
|
|
173
|
+
getAggregates () {
|
|
174
|
+
return getDisplayCache().getAggregates(ROOT);
|
|
175
|
+
},
|
|
176
|
+
getTotal () {
|
|
177
|
+
return getDisplayCache().getTotal(ROOT);
|
|
178
|
+
},
|
|
179
|
+
// The rows the view matches (the toolbar's record count). A grouped view's root list holds
|
|
180
|
+
// groups, whose counts add up to the rows; before the first block lands it is null.
|
|
181
|
+
getRecordCount () {
|
|
182
|
+
const display = getDisplayCache();
|
|
183
|
+
const total = display.getTotal(ROOT);
|
|
184
|
+
if (total === null || (store.view?.group ?? []).length === 0) return total;
|
|
185
|
+
let count = 0;
|
|
186
|
+
display.forEachLoaded((entries, block)=>{
|
|
187
|
+
if (block.listKey !== ROOT) return;
|
|
188
|
+
entries.forEach((entry)=>{
|
|
189
|
+
count += entry.count;
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
return count;
|
|
193
|
+
},
|
|
194
|
+
// The view the request receives: `{ sort, filter, search, group, aggregates }`. A new view
|
|
195
|
+
// gets a new cache and starts from the top; the old rows stay until its first block lands.
|
|
196
|
+
setView ({ view, viewKey }) {
|
|
197
|
+
if (viewKey === store.viewKey) return;
|
|
198
|
+
const initial = store.viewKey === null;
|
|
199
|
+
const groupKey = JSON.stringify(view.group ?? []);
|
|
200
|
+
if (groupKey !== store.groupKey) store.expandedGroups = new Set();
|
|
201
|
+
store.groupKey = groupKey;
|
|
202
|
+
store.view = view;
|
|
203
|
+
store.viewKey = viewKey;
|
|
204
|
+
if (!initial) {
|
|
205
|
+
if (getDisplayCache() === store.cache) store.previous = store.cache;
|
|
206
|
+
store.cache = createBlockCache({
|
|
207
|
+
blockSize,
|
|
208
|
+
maxBlocks
|
|
209
|
+
});
|
|
210
|
+
const scroller = api.scrollerRef.current;
|
|
211
|
+
if (scroller) scroller.scrollTop = 0;
|
|
212
|
+
store.lastRange = null;
|
|
213
|
+
}
|
|
214
|
+
fetchBlock({
|
|
215
|
+
listKey: ROOT,
|
|
216
|
+
groupPath: [],
|
|
217
|
+
index: 0
|
|
218
|
+
});
|
|
219
|
+
notify();
|
|
220
|
+
},
|
|
221
|
+
onRange ({ rowStart, rowEnd }) {
|
|
222
|
+
const now = performance.now();
|
|
223
|
+
const last = store.lastRange;
|
|
224
|
+
if (last && last.rowStart === rowStart && last.rowEnd === rowEnd) {
|
|
225
|
+
// The same range with new items under it (a block landed, a group opened). A fast scroll
|
|
226
|
+
// still waiting to settle keeps waiting: loading here would load every position a
|
|
227
|
+
// landing block happens to find the scroll at.
|
|
228
|
+
if (!store.timer) loadVisible();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const velocity = last ? Math.abs(rowStart - last.rowStart) / Math.max(1, now - last.time) : 0;
|
|
232
|
+
store.lastRange = {
|
|
233
|
+
rowStart,
|
|
234
|
+
rowEnd,
|
|
235
|
+
time: now
|
|
236
|
+
};
|
|
237
|
+
if (store.timer) clearTimeout(store.timer);
|
|
238
|
+
if (velocity <= FAST_ROWS_PER_MS) {
|
|
239
|
+
loadVisible();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
store.timer = setTimeout(loadVisible, SETTLE_MS);
|
|
243
|
+
},
|
|
244
|
+
buildItems ({ rowsById, getId }) {
|
|
245
|
+
const built = buildServerItems({
|
|
246
|
+
blockCache: getDisplayCache(),
|
|
247
|
+
groupKeys: (store.view?.group ?? []).map((entry)=>entry.key),
|
|
248
|
+
expandedGroups: store.expandedGroups,
|
|
249
|
+
rowsById,
|
|
250
|
+
getId,
|
|
251
|
+
itemCache: store.itemCache
|
|
252
|
+
});
|
|
253
|
+
store.segments = built.segments;
|
|
254
|
+
return built;
|
|
255
|
+
},
|
|
256
|
+
// Leaf rows of the cache on screen, for TanStack (selection, row lookup, events), and each
|
|
257
|
+
// one's index in its list on the server.
|
|
258
|
+
getLoadedRows () {
|
|
259
|
+
if (store.loadedRows.version === store.version) return store.loadedRows.rows;
|
|
260
|
+
const levels = (store.view?.group ?? []).length;
|
|
261
|
+
const display = getDisplayCache();
|
|
262
|
+
const rows = [];
|
|
263
|
+
const indices = new Map();
|
|
264
|
+
display.forEachLoaded((blockRows, block)=>{
|
|
265
|
+
if (JSON.parse(block.listKey).length < levels) return;
|
|
266
|
+
blockRows.forEach((row, offset)=>{
|
|
267
|
+
rows.push(row);
|
|
268
|
+
indices.set(String(api.config.getKey(row)), block.index * display.blockSize + offset);
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
store.loadedRows = {
|
|
272
|
+
version: store.version,
|
|
273
|
+
rows,
|
|
274
|
+
indices
|
|
275
|
+
};
|
|
276
|
+
return rows;
|
|
277
|
+
},
|
|
278
|
+
getRowIndex (rowKey) {
|
|
279
|
+
store.getLoadedRows();
|
|
280
|
+
return store.loadedRows.indices.get(String(rowKey)) ?? null;
|
|
281
|
+
},
|
|
282
|
+
toggleGroup ({ key, expanded }) {
|
|
283
|
+
const next = expanded ?? !store.expandedGroups.has(key);
|
|
284
|
+
if (next === store.expandedGroups.has(key)) return;
|
|
285
|
+
if (next) {
|
|
286
|
+
store.expandedGroups.add(key);
|
|
287
|
+
fetchBlock({
|
|
288
|
+
listKey: key,
|
|
289
|
+
groupPath: JSON.parse(key),
|
|
290
|
+
index: 0
|
|
291
|
+
});
|
|
292
|
+
} else {
|
|
293
|
+
store.expandedGroups.delete(key);
|
|
294
|
+
}
|
|
295
|
+
notify();
|
|
296
|
+
},
|
|
297
|
+
collapseAllGroups () {
|
|
298
|
+
if (store.expandedGroups.size === 0) return false;
|
|
299
|
+
store.expandedGroups = new Set();
|
|
300
|
+
notify();
|
|
301
|
+
return true;
|
|
302
|
+
},
|
|
303
|
+
// Purges the cache: every block reloads when it is next visible, the visible ones now. Rows
|
|
304
|
+
// stay on screen until their reload lands.
|
|
305
|
+
refresh () {
|
|
306
|
+
store.cache.invalidate();
|
|
307
|
+
if (store.timer) clearTimeout(store.timer);
|
|
308
|
+
fetchBlock({
|
|
309
|
+
listKey: ROOT,
|
|
310
|
+
groupPath: [],
|
|
311
|
+
index: 0
|
|
312
|
+
});
|
|
313
|
+
loadVisible();
|
|
314
|
+
notify();
|
|
315
|
+
},
|
|
316
|
+
// Updates merge into loaded rows in place. Removed rows leave their block at once; adds and
|
|
317
|
+
// removes shift the server's row positions, so the cache is invalidated and the visible
|
|
318
|
+
// blocks reload.
|
|
319
|
+
applyTransaction (transaction) {
|
|
320
|
+
const changed = {
|
|
321
|
+
added: transaction.add.length,
|
|
322
|
+
updated: 0,
|
|
323
|
+
removed: 0
|
|
324
|
+
};
|
|
325
|
+
const levels = (store.view?.group ?? []).length;
|
|
326
|
+
store.cache.forEachLoaded((rows, block)=>{
|
|
327
|
+
if (JSON.parse(block.listKey).length < levels) return;
|
|
328
|
+
const result = applyTransactionToRows({
|
|
329
|
+
rows,
|
|
330
|
+
transaction: {
|
|
331
|
+
...transaction,
|
|
332
|
+
add: []
|
|
333
|
+
},
|
|
334
|
+
getKey: api.config.getKey
|
|
335
|
+
});
|
|
336
|
+
if (result.changed.updated === 0 && result.changed.removed === 0) return;
|
|
337
|
+
changed.updated += result.changed.updated;
|
|
338
|
+
changed.removed += result.changed.removed;
|
|
339
|
+
store.cache.setBlockRows({
|
|
340
|
+
listKey: block.listKey,
|
|
341
|
+
index: block.index,
|
|
342
|
+
rows: result.rows
|
|
343
|
+
});
|
|
344
|
+
store.cache.adjustTotal(block.listKey, -result.changed.removed);
|
|
345
|
+
});
|
|
346
|
+
if (transaction.add.length > 0 || changed.removed > 0) {
|
|
347
|
+
store.refresh();
|
|
348
|
+
} else {
|
|
349
|
+
notify();
|
|
350
|
+
}
|
|
351
|
+
return changed;
|
|
352
|
+
},
|
|
353
|
+
dispose () {
|
|
354
|
+
if (store.timer) clearTimeout(store.timer);
|
|
355
|
+
listeners.clear();
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
return store;
|
|
359
|
+
}
|
|
360
|
+
export default createServerStore;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ // The block indexes that hold rows `startRow` (inclusive) to `endRow` (exclusive), clipped to
|
|
16
|
+
// `total` when it is known. `first > last` when the range is empty.
|
|
17
|
+
function getBlockRange({ startRow, endRow, blockSize, total }) {
|
|
18
|
+
const end = typeof total === 'number' ? Math.min(endRow, total) : endRow;
|
|
19
|
+
const start = Math.max(0, startRow);
|
|
20
|
+
if (end <= start) return {
|
|
21
|
+
first: 0,
|
|
22
|
+
last: -1
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
first: Math.floor(start / blockSize),
|
|
26
|
+
last: Math.floor((end - 1) / blockSize)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export default getBlockRange;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ // A server list is the rows (or groups) under one group path; the root list has path []. The key
|
|
16
|
+
// is also the group item's key, so an expanded group's key names its child list.
|
|
17
|
+
function getListKey(groupPath) {
|
|
18
|
+
return JSON.stringify(groupPath);
|
|
19
|
+
}
|
|
20
|
+
export default getListKey;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/ import getBlockRange from './getBlockRange.js';
|
|
16
|
+
// The blocks behind display items `rowStart` to `rowEnd` (exclusive). `segments` map runs of
|
|
17
|
+
// display items to the list rows they show: `{ itemStart, length, listKey, groupPath,
|
|
18
|
+
// listStart }`, in item order.
|
|
19
|
+
function getNeededBlocks({ segments, rowStart, rowEnd, blockSize }) {
|
|
20
|
+
const needed = [];
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
segments.forEach((segment)=>{
|
|
23
|
+
const segmentEnd = segment.itemStart + segment.length;
|
|
24
|
+
if (segmentEnd <= rowStart || segment.itemStart >= rowEnd) return;
|
|
25
|
+
const from = Math.max(rowStart, segment.itemStart) - segment.itemStart + segment.listStart;
|
|
26
|
+
const to = Math.min(rowEnd, segmentEnd) - segment.itemStart + segment.listStart;
|
|
27
|
+
const { first, last } = getBlockRange({
|
|
28
|
+
startRow: from,
|
|
29
|
+
endRow: to,
|
|
30
|
+
blockSize
|
|
31
|
+
});
|
|
32
|
+
for(let index = first; index <= last; index++){
|
|
33
|
+
const id = `${segment.listKey}#${index}`;
|
|
34
|
+
if (seen.has(id)) continue;
|
|
35
|
+
seen.add(id);
|
|
36
|
+
needed.push({
|
|
37
|
+
listKey: segment.listKey,
|
|
38
|
+
groupPath: segment.groupPath,
|
|
39
|
+
index
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
return needed;
|
|
44
|
+
}
|
|
45
|
+
export default getNeededBlocks;
|