Insert Link Editor

Add and remove hyperlinks in cells

Insert Link editor
import { CanvasGrid, SpreadsheetProvider } from "@rowsncolumns/spreadsheet"
import { useSpreadsheet, InsertLinkDialog, InsertLinkEditor } from "@rowsncolumns/spreadsheet-state"

const Spreadsheet = () => {
  const {
    activeSheetId,
    activeCell,
    selections,
    onInsertLink,
    onRequestInsertLink
  } = useSpreadsheetState({})

  return (
    <>
      <button onClick={() => onRequestInsertLink()}>Insert link</button>
      <InsertLinkDialog>
        <InsertLinkEditor
          sheetId={activeSheetId}
          activeCell={activeCell}
          selections={selections}
          onInsertLink={onInsertLink}
        />
      </InsertLinkDialog>
    </>
  )
}

const App = () => (
  <SpreadsheetProvider>
    <Spreadsheet />
  </SpreadsheetProvider>
)

Use the onRemoveLink callback to remove hyperlinks from cells:

import { CanvasGrid, SpreadsheetProvider } from "@rowsncolumns/spreadsheet"
import { useSpreadsheetState } from "@rowsncolumns/spreadsheet-state"

const Spreadsheet = () => {
  const {
    activeSheetId,
    activeCell,
    selections,
    onInsertLink,
    onRemoveLink,
    onRequestInsertLink
  } = useSpreadsheetState({})

  const handleRemoveLink = () => {
    onRemoveLink?.(activeSheetId, activeCell, selections);
  };

  return (
    <>
      <button onClick={() => onRequestInsertLink()}>Insert Link</button>
      <button onClick={handleRemoveLink}>Remove Link</button>

      <CanvasGrid
        sheetId={activeSheetId}
        activeCell={activeCell}
        selections={selections}
        onRemoveLink={onRemoveLink}
        // ... other props
      />
    </>
  )
}

Complete Example with Context Menu

import React, { useState } from "react";
import {
  SpreadsheetProvider,
  CanvasGrid,
  Sheet,
} from "@rowsncolumns/spreadsheet";
import {
  useSpreadsheetState,
  SheetData,
  CellData,
  InsertLinkDialog,
  InsertLinkEditor,
} from "@rowsncolumns/spreadsheet-state";

function SpreadsheetWithLinks() {
  const [sheets, setSheets] = useState<Sheet[]>([
    { sheetId: 1, rowCount: 100, columnCount: 26, title: "Sheet 1" }
  ]);
  const [sheetData, setSheetData] = useState<SheetData<CellData>>({});

  const {
    activeCell,
    activeSheetId,
    selections,
    getCellData,
    onChangeActiveCell,
    onChangeSelections,
    onInsertLink,
    onRemoveLink,
    onRequestInsertLink,
  } = useSpreadsheetState({
    sheets,
    sheetData,
    onChangeSheets: setSheets,
    onChangeSheetData: setSheetData,
  });

  // Check if active cell has a link
  const cellData = getCellData(
    activeSheetId,
    activeCell.rowIndex,
    activeCell.columnIndex
  );
  const hasLink = !!cellData?.hyperlink;

  return (
    <SpreadsheetProvider>
      <div className="flex flex-col h-screen">
        <div className="p-2 border-b">
          <button
            onClick={() => onRequestInsertLink()}
            className="px-3 py-1 bg-blue-500 text-white rounded mr-2"
          >
            Insert Link
          </button>
          <button
            onClick={() => onRemoveLink?.(activeSheetId, activeCell, selections)}
            disabled={!hasLink}
            className="px-3 py-1 bg-red-500 text-white rounded disabled:opacity-50"
          >
            Remove Link
          </button>
        </div>

        <div className="flex-1">
          <CanvasGrid
            sheetId={activeSheetId}
            activeCell={activeCell}
            selections={selections}
            getCellData={getCellData}
            onChangeActiveCell={onChangeActiveCell}
            onChangeSelections={onChangeSelections}
            onRemoveLink={onRemoveLink}
          />
        </div>

        <InsertLinkDialog>
          <InsertLinkEditor
            sheetId={activeSheetId}
            activeCell={activeCell}
            selections={selections}
            onInsertLink={onInsertLink}
          />
        </InsertLinkDialog>
      </div>
    </SpreadsheetProvider>
  );
}

export default SpreadsheetWithLinks;

Function Signatures

type OnInsertLink = (
  sheetId: number,
  activeCell: CellInterface,
  selections: SelectionArea<SelectionAttributes>[],
  url: string,
  text?: string
) => void;
type OnRemoveLink = (
  sheetId: number,
  activeCell: CellInterface,
  selections: SelectionArea<SelectionAttributes>[]
) => void;

Use Cases

// Link to documentation
onInsertLink(sheetId, activeCell, selections, "https://docs.example.com", "Docs");

// Link to related file
onInsertLink(sheetId, activeCell, selections, "/files/report.pdf", "View Report");

Remove links from multiple cells:

const removeBatchLinks = () => {
  // Remove links from all selected cells
  selections.forEach((selection) => {
    onRemoveLink?.(activeSheetId, activeCell, [selection]);
  });
};

Best Practices

  1. Validate URLs: Ensure URLs are properly formatted before insertion

  2. Provide Feedback: Show visual indicators for cells with links

  3. Handle Errors: Gracefully handle invalid or broken links

  4. Keyboard Shortcuts: Support Ctrl/Cmd+K for inserting links

  5. Context Menu: Add link operations to the cell context menu

Last updated

Was this helpful?