# JS: Viewport Height


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

## generate_viewport_height_js

Delegates to `cjm-fasthtml-viewport-fit` for the core measurement
algorithm.

The card stack uses the library’s **individual generator functions**
(not the top-level IIFE compositor) because the card stack has its own
IIFE in `core.py` that coordinates resize across multiple subsystems
(viewport height, width, scale, scroll, touch, auto-adjust).

**What the card stack coordinator handles (not delegated to
viewport-fit):** - IIFE wrapper — the card stack has its own in
`core.py` - HTMX settle — coordinator’s `_afterSettleHandler` with
card-stack-specific filtering

**What viewport-fit provides:** - Debug helpers (conditional logging via
`window.viewportFitDebug_{prefix}`) - Space-below DOM walker -
Collapse-measure-apply height calculation (with box-sizing awareness) -
Debounced resize handler with auto-adjust callback - Sibling observation
via ResizeObserver (auto-recalculates when siblings resize) -
Initialization with scroll-to-top for consistent HTMX SPA measurements

------------------------------------------------------------------------

<a
href="https://github.com/cj-mills/cjm-fasthtml-card-stack/blob/main/cjm_fasthtml_card_stack/js/viewport.py#L21"
target="_blank" style="float:right; font-size:smaller">source</a>

### generate_viewport_height_js

``` python

def generate_viewport_height_js(
    ids:CardStackHtmlIds, # HTML IDs for this card stack instance
    container_id:str='', # Unused — kept for API compatibility
)->str: # JavaScript code fragment for viewport height calculation

```

*Generate JS for dynamic viewport height calculation via
cjm-fasthtml-viewport-fit.*

Delegates to the viewport-fit library’s individual generator functions.
The card stack coordinator handles HTMX settle events separately.

``` python
# Test that the generator produces valid JS referencing correct IDs
ids = CardStackHtmlIds(prefix="cs0")
js = generate_viewport_height_js(ids, container_id="my-container")
assert ids.card_stack in js
assert ids.card_stack_inner in js
assert "ns.recalculateHeight" in js
assert "_calculateAndSetHeight" in js

# Verify position-based measurement approach
assert "spaceAbove" in js
assert "spaceBelow" in js
assert "_calculateSpaceBelow" in js

# Verify temporary collapse approach for accurate measurement
assert "'0px'" in js
assert "offsetHeight" in js  # Force reflow

# Verify position-based sibling detection (beside vs below)
assert "siblingRect.top < currentRect.bottom" in js

# Verify debug mode uses viewport-fit convention
assert f"viewportFitDebug_{ids.prefix}" in js
assert f"[vf:{ids.prefix}]" in js

# Verify auto-adjust trigger in resize handler
assert "ns.triggerAutoAdjust" in js

# Verify resize listener uses remove-and-replace
handler_key = f"_vfResizeHandler_{ids.prefix.replace('-', '_')}"
assert f"window.{handler_key}" in js
assert "removeEventListener" in js

# Verify sibling observer
assert "_setupSiblingObserver" in js
assert "ResizeObserver" in js
assert "ns._setupSiblingObserver" in js

# Verify init with scroll-to-top
assert "window.scrollTo(0, 0)" in js

# Verify section comment for core.py composition
assert "Viewport Height" in js

print("Viewport height JS generator tests passed!")
```

    Viewport height JS generator tests passed!

``` python
# container_id is unused — both paths produce identical output
js_no_container = generate_viewport_height_js(ids)
assert js == js_no_container
# Verify position-based measurement is present
assert "spaceAbove" in js_no_container
assert "_calculateSpaceBelow" in js_no_container
print("Viewport height JS container_id compatibility test passed!")
```

    Viewport height JS container_id compatibility test passed!
