Skip to content

HF-122: Framework integration guides for React, Angular, Vue, Svelte#1653

Open
marcin-kordas-hoc wants to merge 25 commits intodevelopfrom
feature/hf-122-framework-integration-guides
Open

HF-122: Framework integration guides for React, Angular, Vue, Svelte#1653
marcin-kordas-hoc wants to merge 25 commits intodevelopfrom
feature/hf-122-framework-integration-guides

Conversation

@marcin-kordas-hoc
Copy link
Copy Markdown
Collaborator

@marcin-kordas-hoc marcin-kordas-hoc commented Apr 13, 2026

Summary

Expand the four framework integration pages (React, Angular, Vue, Svelte) from one-line redirects into self-contained guides with code snippets extracted from the respective Stackblitz demos.

Each guide's primary snippet is a simplified version of the demo's framework pattern — same lifecycle hooks, same service architecture, same reactivity approach — with simplified data (buildFromArray instead of Employee Table).

Design rationale

Snippets from demos, not invented patterns

Per review feedback: every code snippet must match what's in the corresponding Stackblitz demo. This ensures the snippets are tested, idiomatic, and consistent with what users see when they click the demo link. Patterns not present in demos (e.g., Angular Signals, Svelte 5 runes) are deliberately excluded until validated by a framework expert.

Framework Demo file Primary pattern in guide
React react-demo/src/lib/employee/employee.provider.tsx useRef + useEffect init/cleanup + useState
Angular angular-demo/src/app/employees/employees.service.ts @Injectable + BehaviorSubject + async pipe
Vue vue-3-demo/src/lib/employees-data-provider.ts Class wrapper with private HF field + ref
Svelte svelte-demo/src/routes/Hyperformula.svelte buildFromArray + getCellValue + on:click + onDestroy

Other decisions

  • TypeScript in all snippets (HF ships .d.ts typings)
  • licenseKey: 'gpl-v3' in every snippet (without it, engine throws license warning)
  • SSR notes for Next.js, Nuxt, SvelteKit (HF is SSR-safe — no browser-only API dependency — but instantiating it server-side is wasted work, so each framework's SSR section defers to client lifecycle)
  • VuePress template fix — Stackblitz links use <a :href> Vue binding instead of {{ }} interpolation in markdown

Test plan

  • Render docs locally / verify all four integration pages — all 4 pages return HTTP 200 on the Netlify deploy preview for the latest commit (proxies npm run docs:dev)
  • Click each Stackblitz demo link — all 5 URLs (4 frameworks + custom-functions) reachable, each hyperformula-demos@3.2.x/<framework>-demo subdir exists
  • Verify primary snippets match demo patterns — React: useRef/useEffect/useState; Angular: @Injectable/BehaviorSubject/async pipe; Vue: class wrapper + ref (the markRaw pattern is documented in Troubleshooting, not the primary snippet); Svelte: buildFromArray/getCellValue/on:click/onDestroy
  • Verify no untested patterns remain — no Signals, no $state/$derived runes, no NgZone; Pinia is mentioned only in a Vue Troubleshooting note that warns against putting the engine into Pinia state, not as a recommended pattern
  • Confirm licenseKey: 'gpl-v3' present in every snippet — react/angular: 1× (main snippet); vue: 2× (main + Troubleshooting markRaw demo); svelte: 2× (basic + SSR variants)
  • Confirm destroy() cleanup present in every applicable component snippet — react/angular: 1× (main snippet); vue: 1× (main snippet — Troubleshooting markRaw demo is illustrative, not a full component); svelte: 2× (basic + SSR variants)

Note

Low Risk
Low risk documentation-only change that adds new framework-specific guidance and code snippets; no runtime/library behavior is modified.

Overview
Expands the framework integration docs (Angular, React, Svelte, Vue) from brief install notes into self-contained guides with concrete TypeScript-centric examples for initializing HyperFormula, surfacing calculated values in each framework’s reactivity model, and cleaning up via the appropriate lifecycle hook.

Adds SSR-specific notes for Angular Universal, Next.js, Nuxt, and SvelteKit, and standardizes demo links by switching Stackblitz URLs to Vue-bound <a :href> so the cache-busting query param renders correctly in VuePress (also applied to custom-functions).

Reviewed by Cursor Bugbot for commit 1ecce54. Bugbot is set up for automated code reviews on this repo. Configure here.

Add idiomatic code examples to React, Angular, Vue, and Svelte
integration pages showing HyperFormula initialization and reading
calculated values. Each guide uses framework-specific patterns
(React hooks, Angular service, Vue ref/markRaw, Svelte reactivity).

Closes HF-122.
Per feedback, snippets now focus on framework-specific integration
patterns (useRef/useEffect, @Injectable, markRaw/ref, Svelte reactivity)
with placeholder comments for data and configuration rather than
concrete values. The Demo section link is reworded from "Explore the
full working example" to "For a more advanced example" to signal that
the Stackblitz demo is a richer, separate project.

Part of HF-122.
Expand React, Angular, Vue and Svelte integration guides to cover
framework-specific concerns that the previous skeleton snippets omitted:

- Convert all snippets to TypeScript with HyperFormula/CellValue imports
- Add licenseKey: 'gpl-v3' to every buildFromArray call
- Inline `npm install hyperformula` install command
- React: runnable JSX with controlled inputs, try/catch around setCellContents,
  React.StrictMode note, Next.js App Router SSR section with 'use client' and
  dynamic import
- Angular: modern standalone component + inject() + DestroyRef + Signals +
  OnPush, RxJS BehaviorSubject variant with AsyncPipe import note, NgZone
  runOutsideAngular section, provider-scope + DestroyRef rationale
- Vue: <script setup lang="ts">, expanded markRaw Proxy explanation and
  shallowRef trap, Nuxt SSR snippet, Pinia store with updateCell action,
  valuesUpdated event hook, inline v-for template
- Svelte: fixes memory leak by adding onDestroy(() => hf.destroy()), Svelte 5
  runes primary example plus Svelte 4 delta, SvelteKit SSR warning banner and
  dedicated onMount section with dynamic import, wired #each template with
  updateCell handler
Point readers from each integration guide to related topics they are
likely to need next: configuration options, basic operations (CRUD),
advanced usage (multi-sheet, named expressions), and custom functions.

Identical section in all four guides so the navigation experience is
consistent when switching between frameworks.
The Stackblitz demo links used \${...} JavaScript template literal syntax,
which is not interpolated by VuePress. VuePress 1 processes markdown as
Vue templates, so the correct syntax for accessing the injected
\$page.buildDateURIEncoded variable is Vue's {{ ... }} interpolation.

config.js line 79 documents the intended syntax explicitly:
  // inject current HF buildDate URI encoded as {{ \$page.buildDateURIEncoded }} variable

Before this fix, the cache-buster query string rendered as a literal
?v=\${\$page.buildDateURIEncoded} in the URL, breaking the cache-busting
behaviour on every Stackblitz demo link.

Note: the same issue exists in docs/guide/custom-functions.md:361 from
an earlier change; that is left for a separate fix.
@qunabu
Copy link
Copy Markdown

qunabu commented Apr 13, 2026

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 13, 2026

Performance comparison of head (1ecce54) vs base (362df83)

                                     testName |   base |   head | change
------------------------------------------------------------------------
                                      Sheet A | 485.67 | 497.63 | +2.46%
                                      Sheet B | 159.85 | 158.11 | -1.09%
                                      Sheet T | 140.77 | 140.94 | +0.12%
                                Column ranges | 470.48 |  471.8 | +0.28%
Sheet A:  change value, add/remove row/column |  15.36 |  15.39 | +0.20%
 Sheet B: change value, add/remove row/column | 133.46 |  132.9 | -0.42%
                   Column ranges - add column | 147.07 | 148.11 | +0.71%
                Column ranges - without batch | 444.15 |  438.1 | -1.36%
                        Column ranges - batch | 114.06 | 113.47 | -0.52%

…ntent)

tsc smoke check found that updateCell(value: unknown) does not satisfy
setCellContents which expects RawCellContent. Replace unknown with the
correct type and add missing RawCellContent imports in Angular, Vue and
Svelte guides.
Add framework-agnostic instruction file for AI coding assistants
(Claude Code, GitHub Copilot, Cursor, Gemini CLI). Covers the core
3-operation API surface, framework integration patterns with critical
rules (markRaw, onDestroy, StrictMode, DestroyRef, SSR guards),
key types, common mistakes to prevent, and project structure pointers.
@marcin-kordas-hoc marcin-kordas-hoc marked this pull request as ready for review April 14, 2026 07:18
@marcin-kordas-hoc
Copy link
Copy Markdown
Collaborator Author

Question: Automated testing for framework demos?

During this PR I ran a manual tsc smoke check on all 10 code snippets extracted from the guides — found and fixed a real type bug (unknownRawCellContent).

This raises a broader question: should we have automated tests for the framework demos (both the guide snippets and the Stackblitz demos in hyperformula-demos)?

The risk

Framework demos can silently break when:

  • A framework releases a breaking change (React 19, Angular 18, Svelte 6...)
  • HyperFormula API changes (new required params, renamed types)
  • Bundler updates (Vite, Webpack config changes)
  • Dependency drift (stale lockfile, removed transitive dep)

Currently there are no automated checks — breakage is discovered only when a user clicks a broken Stackblitz link or copy-pastes a non-compiling snippet.

Options considered

Option Where What it catches Setup cost
A: Scheduled CI in demos repo hyperformula-demos Framework breaks ~20 min
B: Cross-repo job in publish.yml HF main repo HF API breaks (before deploy) ~1h
C: Nightly scheduled in HF repo HF main repo Both (builds demos against develop) ~2h

Option A is lowest cost and most immediately useful — a weekly npm ci && npm run build per framework in the demos repo. Zero changes to HF main CI.

Option B catches the other direction (HF breaking demos) and could gate docs deployment.

Related: demo visibility for AI tools

Stackblitz links are invisible to AI coding assistants (Copilot, Cursor, Claude). AI relies solely on the inline snippets in docs/guide/integration-with-*.md. I've added AGENTS.md with framework integration patterns to make these discoverable.

A potential follow-up: vendoring a subset of demo code into docs/examples/ (where 49 examples already live) so AI tools see working examples during code search. This is a separate discussion — noting it here for visibility.

@sequba What do you think — is option A worth setting up? Or is manual verification sufficient for now?

@sequba
Copy link
Copy Markdown
Contributor

sequba commented Apr 14, 2026

@marcin-kordas-hoc I need to be sure the snippets work correctly and align with each framework's best practices, so I want them to be exact code fragments from the linked Stackblitz demos.

You can achieve this by either:

  • updating the code snippets to match the demo code
  • modifying the demos to match the code snippets (but in this case, please make sure that all demos are really well written - this is the code that other devs copy and use in their products, it must be perfect; also we will ask framework experts to review the demos before publication)

@marcin-kordas-hoc
Copy link
Copy Markdown
Collaborator Author

Following our Slack discussion where you approved keeping snippets focused on framework-specific patterns rather than extracting from the demos directly — that's the approach taken here (useEffect, BehaviorSubject, markRaw, on:click as the core of each guide, data as // your data goes here).

The reason for not extracting from demos directly: they use multi-file setup (buildEmptyaddSheet → named expressions, EmployeeRow types, helper files) — copying them produces either 60+ unreadable lines or decontextualised fragments. The Demo section caption already sets the expectation: "For a more advanced example, check out the demo on Stackblitz".

The demos themselves are unchanged.

@marcin-kordas-hoc marcin-kordas-hoc added the Docs Improvements or additions to documentation label Apr 16, 2026
@marcin-kordas-hoc marcin-kordas-hoc self-assigned this Apr 16, 2026
marcin-kordas-hoc and others added 3 commits April 16, 2026 08:57
Angular: switch primary pattern to BehaviorSubject/Observable (module-based),
matching the angular-demo on Stackblitz. Signal-based variant moved to a
'Signals variant (Angular 17+)' note. Cleanup section expanded with both
ngOnDestroy and DestroyRef options.

Svelte: switch primary pattern to Svelte 4 style (on:click, plain let),
matching the svelte-demo on Stackblitz. Svelte 5 runes variant moved to
a '### Svelte 5 (runes)' subsection. SSR section updated to use Svelte 4
as primary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
React: fix Next.js SSR pattern — 'use client' belongs in the component
file, not on page.tsx; server page uses dynamic(..., { ssr: false })

Angular: add CommonModule/standalone imports for *ngFor + async pipe;
add @for template for signals variant; add inject() context note

Vue: replace shallowRef with ref in Nuxt SSR snippet (shallowRef vs
markRaw contradiction); add hf.off() teardown to valuesUpdated example;
remove hf from Pinia store return value (devtools serialisation risk)

Svelte: fix CellValue type for result variable; fix SSR snippet to use
onMount return for cleanup instead of separate onDestroy

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Vue: rewrite primary snippet to use class wrapper pattern matching
the vue-3-demo on Stackblitz. markRaw moved to Notes as alternative.

Angular: remove unnecessary `as CellValue[][]` casts (getSheetValues
already returns this type).

React: remove try/catch from handleCellEdit for consistency — no demo
uses error handling around setCellContents.

custom-functions.md: fix VuePress template syntax (${}→{{}}) so the
Stackblitz link renders the build date correctly.

AGENTS.md: update framework table to match actual guide primary
patterns (Angular=BehaviorSubject, Vue=class wrapper, Svelte=Svelte 4).
marcin-kordas-hoc and others added 5 commits April 16, 2026 09:57
…polation

{{ $page.buildDateURIEncoded }} inside markdown link syntax [text](url{{ }})
breaks markdown-it parsing — links render as plain text instead of clickable
links. Switch to <a :href="..."> with Vue v-bind which VuePress handles
correctly since page data is available in template scope.
Per Kuba's review feedback: snippets must match what's in the Stackblitz
demos so we can guarantee they work correctly. Removed all patterns that
have never been tested with HyperFormula:

Angular: removed Signals variant (signal, inject, DestroyRef, OnPush,
@for), NgZone.runOutsideAngular section.

Svelte: removed Svelte 5 runes ($state) section.

Vue: removed markRaw alternative, Nuxt SSR with dynamic import,
valuesUpdated event listener, Pinia store sections.

These patterns can be re-added once validated by a framework consultant
or included in updated demos.
All four Stackblitz demos use the same interaction model: "Run calculations"
and "Reset" buttons with read-only table output. Aligned guides to match:

React: replaced editable <input onChange> with button-driven calculate/reset.
The onChange-per-keystroke pattern was not from the demo and caused issues
with partial formula input.

Angular: replaced standalone component with NgModule pattern (matching demo).
Replaced updateCell with calculate/reset methods matching EmployeesService.
Added buttons to template.

Vue: replaced dead handleUpdate/updateCell with getCalculatedValues/
getRawFormulas matching EmployeesDataProvider. Added Run/Reset buttons.
AGENTS.md: Vue SSR guard updated from "onMounted + dynamic import"
to "<ClientOnly> (Nuxt)" matching the actual guide content.

Svelte: renamed "Calculate" to "Run calculations" and added "Reset"
button for consistency with React/Angular/Vue guides. Reset is pure
UI (result = null), no HF API involved.
Comment thread docs/guide/integration-with-angular.md Outdated
# Integration with Angular

Installing HyperFormula in an Angular application works the same as with vanilla JavaScript.
The HyperFormula API is identical in an Angular app and in plain JavaScript. What changes is where the engine lives (typically an injectable service), how it is cleaned up, and how you bridge its values into the change-detection cycle.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The HyperFormula API is identical in an Angular app and in plain JavaScript. What changes is where the engine lives (typically an injectable service), how it is cleaned up, and how you bridge its values into the change-detection cycle.
The HyperFormula API is identical in an Angular app and in plain JavaScript. This guide demonstrates how HyperFormula is integrated with an Angular app (typically as an injectable service), how it is cleaned up, and how you bridge its values into the change-detection cycle.

I don't like the phrase "What changes is..."

Copy link
Copy Markdown
Collaborator Author

@marcin-kordas-hoc marcin-kordas-hoc Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adopted verbatim in b080681. Better wording — thanks.

Comment thread docs/guide/integration-with-react.md Outdated
# Integration with React

Installing HyperFormula in a React application works the same as with vanilla JavaScript.
The HyperFormula API is identical in a React app and in plain JavaScript. What changes is where the engine lives in a component tree and how its lifecycle maps to React hooks.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The HyperFormula API is identical in a React app and in plain JavaScript. What changes is where the engine lives in a component tree and how its lifecycle maps to React hooks.
The HyperFormula API is identical in a React app and in plain JavaScript. This guide demonstrates how HyperFormula is integrated with the React component tree and how its lifecycle maps to React hooks.

Copy link
Copy Markdown
Collaborator Author

@marcin-kordas-hoc marcin-kordas-hoc Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adopted verbatim in b080681. Better wording — thanks.

Comment thread docs/guide/integration-with-svelte.md Outdated
# Integration with Svelte

Installing HyperFormula in a Svelte application works the same as with vanilla JavaScript.
The HyperFormula API is identical in a Svelte app and in plain JavaScript. What changes is how you scope the engine to a component's lifetime and how you bridge its values into Svelte's reactivity.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The HyperFormula API is identical in a Svelte app and in plain JavaScript. What changes is how you scope the engine to a component's lifetime and how you bridge its values into Svelte's reactivity.
The HyperFormula API is identical in a Svelte app and in plain JavaScript. This guide demonstrates how HyperFormula integrates with the Svelte component's lifecycle and how you bridge its values into Svelte's reactivity.

Copy link
Copy Markdown
Collaborator Author

@marcin-kordas-hoc marcin-kordas-hoc Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adopted verbatim in b080681. Better wording — thanks.

Comment thread docs/guide/integration-with-vue.md Outdated
# Integration with Vue

Installing HyperFormula in a Vue application works the same as with vanilla JavaScript.
The HyperFormula API is identical in a Vue 3 app and in plain JavaScript. What changes is how you keep the engine out of Vue's reactivity system and how you surface its values into the template.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The HyperFormula API is identical in a Vue 3 app and in plain JavaScript. What changes is how you keep the engine out of Vue's reactivity system and how you surface its values into the template.
The HyperFormula API is identical in a Vue 3 app and in plain JavaScript. This guide demonstrates how HyperFormula integrates with the Vue reactivity system and how to surface its values in the template.

Copy link
Copy Markdown
Collaborator Author

@marcin-kordas-hoc marcin-kordas-hoc Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adopted verbatim in b080681. Better wording — thanks.

Comment thread docs/guide/integration-with-svelte.md Outdated

Declare the engine at the top of `<script>` so it lives for the component's lifetime. Call `getCellValue` on demand and display results in the template. Release the engine with `onDestroy`.

```svelte
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```svelte
```html

Copy link
Copy Markdown
Collaborator Author

@marcin-kordas-hoc marcin-kordas-hoc Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied — switched both Svelte fences to html in b080681. VuePress 1's highlighter does not recognize svelte, so it was rendering as plain text.

Comment thread docs/guide/integration-with-svelte.md Outdated

HyperFormula depends on browser-only APIs. In SvelteKit, initialize the engine inside `onMount` so the code never runs during SSR:

```svelte
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
```svelte
```html

Copy link
Copy Markdown
Collaborator Author

@marcin-kordas-hoc marcin-kordas-hoc Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied — switched both Svelte fences to html in b080681. VuePress 1's highlighter does not recognize svelte, so it was rendering as plain text.

## Working demo

Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/custom-functions?v=${$page.buildDateURIEncoded}).
Explore the full working example on <a :href="'https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/custom-functions?v=' + $page.buildDateURIEncoded">Stackblitz</a>.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was it changed?

Copy link
Copy Markdown
Collaborator Author

@marcin-kordas-hoc marcin-kordas-hoc Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry — that's me leaving the rationale out of the commit. The original markdown link was [Stackblitz](https://...?v=${$page.buildDateURIEncoded}), and VuePress 1 only interpolates $page Vue values inside element bindings, not inside markdown link href text — so the rendered URL was the literal string ?v=${$page.buildDateURIEncoded}. Switched to a Vue <a :href="..."> so the binding actually evaluates. Same fix applied to all five guides in 76bcfdd2.

@marcin-kordas-hoc
Copy link
Copy Markdown
Collaborator Author

Push update: 7 new commits on top of the previous review pass (ed7..3183 base → 7015b949). Quick map:

Sequba review threads — all 7 inline threads addressed inline above with reply links to commits. Summary:

  • 4× framework-guide intro lines: adopted your wording verbatim (This guide demonstrates how HyperFormula is integrated…).
  • 2× Svelte fenced blocks: switched sveltehtml (VuePress 1 highlighter doesn't recognize svelte).
  • custom-functions.md:361: explained inline — original markdown-link syntax broke Vue $page.buildDateURIEncoded interpolation, switched to <a :href>.

Bugs surfaced by Kuba's Claude expert reviews (#1657#1660) — incorporated the bug fixes only, not the framework-modernization refactors:

Snippet ↔ demo alignment kept as the foundation per the 2026-04-10 Slack ruling: snippets demonstrate framework patterns at the same abstraction level as the existing Stackblitz demos, so a developer can read the snippet, click the Demo link, and recognize the same shape. The framework-modernization refactors in #1657 (Vue composables), #1658 (Angular standalone+signals+@if/@for), and #1659 (Svelte 5 runes) all break that parity, so they're parked for the consultant pass per the closing of the 2026-04-20 thread ("to przeglądnij to, zmień to co uważasz i po prostu wciągniemy to już, a potem zrobię taski na review tego przez konsultantów specjalistów").

Re-requesting review.

marcin-kordas-hoc added a commit that referenced this pull request Apr 28, 2026
The Basic Usage sections added in earlier HF-85 commits duplicate the
framework integration guides being delivered in PR #1653 (HF-122).
Reverting them here keeps HF-85's scope strictly to D-functions and
avoids three-way conflict when #1653 merges first.
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 28, 2026

Deploy Preview for hyperformula-docs ready!

Name Link
🔨 Latest commit 1ecce54
🔍 Latest deploy log https://app.netlify.com/projects/hyperformula-docs/deploys/69fb28dc00a4550008262647
😎 Deploy Preview https://deploy-preview-1653--hyperformula-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

marcin-kordas-hoc added a commit that referenced this pull request Apr 29, 2026
The Basic Usage sections added in earlier HF-85 commits duplicate the
framework integration guides being delivered in PR #1653 (HF-122).
Reverting them here keeps HF-85's scope strictly to D-functions and
avoids three-way conflict when #1653 merges first.
marcin-kordas-hoc and others added 2 commits May 5, 2026 07:52
…t cleanup

Tested each guide's primary snippet by scaffolding a fresh project per
framework (React, Angular, Vue, Svelte) across three seniority levels and
copy-pasting the snippet verbatim. Angular and Vue primaries built and
ran without changes — aligned with the demo patterns already. Three real
bugs surfaced only in React and Svelte:

React — the primary snippet's
  import { HyperFormula, CellValue } from 'hyperformula';
breaks Vite's `react-ts` template because it sets
`verbatimModuleSyntax: true` by default; `CellValue` is a type and must
be imported with `import type`. Split the import accordingly.

React — the snippet declared `export function SpreadsheetComponent`
(named), but Vite's `main.tsx` imports `App` as a default export, so a
verbatim copy-paste failed at runtime. Switched to
`export default function SpreadsheetComponent`.

React — the Next.js App Router example called
`dynamic(..., { ssr: false })` from a server component (`page.tsx`),
which Next 14+/15 rejects at build time. Moved the dynamic call into a
`'use client'` wrapper (`SpreadsheetLazy.tsx`) imported from the server
page. Also reframed the intro: the engine has no browser-only API
dependency — the component is already SSR-safe because HyperFormula is
constructed in `useEffect`. The `ssr: false` wrapper is a bundle-size
optimization, not a compatibility requirement.

Svelte — the SvelteKit SSR snippet returned a cleanup function from an
async `onMount` callback. That return is silently ignored because an
async function always returns a `Promise`, not the cleanup. Split into
`onMount` for init and a separate `onDestroy` for teardown.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…React 18 qualifier

The React guide was updated to reframe SSR as "wasted server-side
initialization" rather than a "browser-only API dependency" (the engine
has no window/document/navigator references at module scope or runtime).
Propagate that framing to the rest of the guides and to AGENTS.md so all
four guides + agent docs tell the same story:

- vue.md (Nuxt section): class is SSR-safe; <ClientOnly> wraps it to
  skip wasted server-side instantiation, not to avoid a runtime crash.
- svelte.md (SvelteKit section): top-level <script> runs server-side,
  but the engine is SSR-safe; onMount defers to the client to skip
  wasted SSR work.
- AGENTS.md (SSR rule + common-mistakes bullet): drop the "depends on
  browser-only APIs" / "server crash" claims; reframe as wasted
  server-side initialization.

Also drop the dated "React 18" qualifier from the StrictMode note in
react.md — React 19 has identical dev-only double-invocation semantics.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 36aa583. Configure here.

Comment thread docs/guide/integration-with-angular.md Outdated
Cursor Bugbot caught the Angular guide rendering an empty <table> after
clicking Reset. The original *ngIf="(values$ | async) as values" is
truthy for [], so the table stays in the DOM with no rows. React and
Vue guides correctly hide the table via values.length > 0 / v-if.

Wrap the async unwrap in <ng-container> and put the length check on
the <table> *ngIf to match the React / Vue behavior.
These changes were claimed as "Adopted verbatim" in PR #1653 review
replies on 2026-04-28, but the commits that made them lived only on a
parallel worktree branch (hf-122-final-fixes) and never reached upstream.
Applying them now so the PR matches what the replies promised:

- 4× framework guide intro lines: replace "What changes is..." with
  sequba's exact suggested wording ("This guide demonstrates how
  HyperFormula is integrated/integrates with...")
- 2× Svelte fenced-block labels: ```svelte → ```html (VuePress 1's
  highlighter does not recognize svelte and was rendering as plain text)
The AGENTS.md file (universal AI assistant instructions) is repo-wide
guidance that doesn't belong to HF-122 ("Add basic code snippet to
React, Angular, Vue and Svelte guides"). It was added in 2f8b2be
during framework-guides work because the file's "Framework integration
patterns" table cross-references the four guides — but the rest of the
content (project structure, adding a function, key types, common
mistakes, build/test, contributing) is not framework-integration scope.

The natural home is HF-154 (agent-friendly docs / llms.txt / Skills
for AI), which has its own ClickUp task and design draft.

Removing here to keep the PR scope aligned with the original task
description; AGENTS.md will be re-added under HF-154.
All four framework guides now expose Server-side rendering as a top-level
H2 section for parity. Angular gains a brief SSR note pointing at
isPlatformBrowser, mirroring the Nuxt/SvelteKit/Next.js coverage.
@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.16%. Comparing base (362df83) to head (1ecce54).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #1653      +/-   ##
===========================================
+ Coverage    95.76%   97.16%   +1.39%     
===========================================
  Files          175      175              
  Lines        15319    15319              
  Branches      3287     3287              
===========================================
+ Hits         14670    14884     +214     
+ Misses         649      435     -214     

see 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Docs Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants