• v0.31.0 1358d846f7

    v0.31.0 Stable

    pienter-release-bot released this 2026-09-21 13:53:52 +00:00 | 38 commits to main since this release

    Added

    • Index and DataTable show records that carry a parent and a manual order
      as a two-level tree, and move them by click-to-place (ADR 0011). This is for
      an index that doubles as the menu editor, such as Pages.
      • The project adds two typed columns, { key, label, type: 'level' } and
        { key, label, type: 'move' }, and names the parent field with
        parentKey. The level column draws the hierarchy, so every other column
        stays aligned. Rows must arrive in manual order; nothing orders them.
      • A row's move button opens a placing state in which every legal
        destination is a button that says where it leads ("Top level",
        "Inside About"). Hovering or focusing one previews the row in that
        place. There is no drag and drop. Escape, Cancel or the move button
        again leaves the state.
      • Index takes loadTree({ signal }), returning { data } with every
        record, and uses it instead of load while no search, filter or sort is
        active; pagination hides in that view. Every other view is the flat
        paginated list without the two typed columns. useIndexQuery takes the
        same option and exposes tree.
      • Index takes move({ id, parentId, index, siblingIds }), an async
        function. The move is applied at once, rolled back with the rejection's
        message shown and announced if it rejects, and the tree is reloaded if
        it resolves. DataTable emits the same intent as move and never
        reorders rows; applyMove from @[secure]/ui/utils applies one.
      • canMove(row) and canParent(row) remove move buttons and "inside"
        destinations a backend would refuse. The package itself enforces two
        levels. rowLabel(row) names a row and moveLabels overrides any of
        the English strings; they are functions so a translation owns its word
        order.
      • Table gains an after slot, rendered inside the wrap after the
        <table>.
      • The HTTP side is in docs/cms/backend-contract.md under "Manual order
        and moves".
    Downloads