# presentation/selectors/section.selector.ts

> 51 lines of code and 8 definitions.

Tree: Bane's Lab Site
Language: typescript
Layer: application
Canonical: https://banes-lab.com/anatomy/tree#file-presentation-selectors-section-selector-ts
Source text: https://banes-lab.com/source/tree/presentation/selectors/section.selector.ts.txt

Listed in [presentation/selectors](https://banes-lab.com/api/source/tree/presentation/selectors.md).

## Definitions

- `seedsOfTab` (lexical_declaration, line 25)
- `sectionSeedsOf` (lexical_declaration, line 47, exported)
- `rowRanges` (lexical_declaration, line 9, exported)
- `start` (lexical_declaration, line 11, exported)
- `held` (lexical_declaration, line 12, exported)
- `ranges` (lexical_declaration, line 29, exported)
- `definition` (lexical_declaration, line 48, exported)
- `{ layout, tabs }` (lexical_declaration, line 52, exported)

## Contained in

- [presentation/selectors](https://banes-lab.com/anatomy/tree/folder-presentation-selectors.md)

## Uses

- [core/assets/link.assets.ts](https://banes-lab.com/source/tree/core/assets/link.assets.ts.md)
- [domain/converters/ontology.converter.ts](https://banes-lab.com/source/tree/domain/converters/ontology.converter.ts.md)
- [presentation/renderers/ontology.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/ontology.renderer.ts.md)
- [presentation/renderers/tab.renderer.ts](https://banes-lab.com/source/tree/presentation/renderers/tab.renderer.ts.md)

## Linked from

- [core/assets](https://banes-lab.com/anatomy/tree/folder-core-assets.md)
- [domain/converters](https://banes-lab.com/anatomy/tree/folder-domain-converters.md)
- [presentation/renderers](https://banes-lab.com/anatomy/tree/folder-presentation-renderers.md)
- [presentation/selectors](https://banes-lab.com/anatomy/tree/folder-presentation-selectors.md)

## Source

```typescript
import { rowCount, rowWeights } from "#presentation/renderers/ontology.renderer";
import type { SectionSeed } from "#types/page.types";
import type { Tab } from "#types/document.types";
import { hasSectionPages } from "#presentation/renderers/tab.renderer";
import { loadedPage } from "#domain/registries/page.registry";
import { recordPageOf } from "#domain/converters/ontology.converter";
import { tabPath } from "#core/assets/link.assets";

export const rowRanges = function rowRanges(weights: readonly number[], budget: number): readonly (readonly [number, number])[] {
    const ranges: (readonly [number, number])[] = [];
    let start = 0;
    let held = 0;
    weights.forEach((weight, index) => {
        if (index > start && held + weight > budget) {
            ranges.push([start, index]);
            start = index;
            held = 0;
        }
        held += weight;
    });
    ranges.push([start, weights.length]);
    return ranges;
};

const seedsOfTab = function seedsOfTab(page: string, tabs: readonly Tab[], tab: Tab, budget: number): readonly SectionSeed[] {
    return tab.sections
        .filter((section) => rowCount(section) > 0 && recordPageOf(section.id) === null)
        .flatMap((section) => {
            const ranges = rowRanges(rowWeights(section), budget);
            return ranges.map((rows, index) => ({
                intro: section.intro ?? null,
                kind: section.kind ?? null,
                name: section.title,
                page,
                part: index + 1,
                parts: ranges.length,
                records: rowCount(section),
                rows,
                section: section.id,
                tab: tab.id,
                tabPath: tabPath(page, tabs, tab.id),
                tabTitle: tab.label,
            }));
        });
};

export const sectionSeedsOf = function sectionSeedsOf(page: string, budget: number): readonly SectionSeed[] {
    const definition = loadedPage(page);
    if (definition?.content.kind !== "tabbed") {
        return [];
    }
    const { layout, tabs } = definition.content;
    return tabs.filter((tab) => hasSectionPages(layout, tab)).flatMap((tab) => seedsOfTab(page, tabs, tab, budget));
};
```
