Skip to content

Donghyun-git/react-table-mapping

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

39 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

React Table Mapping

πŸ“‹ Changelog

Changelog

πŸ“Ί DEMO

DEMO

πŸš€ Features

  • 🎯 Drag & Drop: Intuitive mapping creation with visual feedback
  • 🎨 Visual Connection Lines: Beautiful Bezier curves showing mapping relationships
  • πŸŒ™ Dark Mode: Automatic light/dark theme switching
  • ⚑ TypeScript: Full type safety and excellent developer experience
  • πŸŽ›οΈ Customizable: Support for various field types such as string, input, select

πŸ“¦ Installation

npm install react-table-mapping
# or
yarn add react-table-mapping
# or
pnpm add react-table-mapping

πŸ“‹ Requirements

"react": "^19.0.0",
"react-dom": "^19.0.0",

Peer Dependencies

"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-slot": "^1.1.1"

engines

"node": ">=22.0.0"

Import Styles

import 'react-table-mapping/styles';

🎯 Quick Start

import React from 'react';
import { TableMapping } from 'react-table-mapping';
import type { FieldItemInput, TableMappingRef } from 'react-table-mapping';

function App() {
  const tableMappingRef = React.useRef<TableMappingRef>(null);
  // Define source table columns
  const sourceColumns = [{ title: 'Name', key: 'name' }];

  // Define target table columns
  const targetColumns = [
    { title: 'Name', key: 'name' },
    { title: 'Data', key: 'data' },
    { title: 'Function', key: 'func' },
  ];

  // Source field data
  const sourceFields = [
    {
      name: {
        type: 'input',
        columnKey: 'name',
        value: 'USER_ID',
        attributes: {
          //you can custom input attributes
          style: {
            height: '36px', //like this
          },
        },
        onChange: (value) => console.log('Source name changed:', value),
      },
      id: 'source-0',
      key: 'source-0',
    },
  ] satisfies FieldItemInput[];

  // Target field data
  const targetFields = [
    {
      name: {
        type: 'input',
        columnKey: 'name',
        value: 'KEY',
        onChange: (value) => console.log('Target name changed:', value),
      },
      data: {
        type: 'input',
        columnKey: 'data',
        value: '',
        onChange: (value) => console.log('Target data changed:', value),
      },
      func: {
        type: 'select',
        columnKey: 'func',
        defaultValue: 'NONE',
        options: [
          { label: 'NONE', value: 'NONE' },
          { label: 'CONCAT', value: 'CONCAT' },
          { label: 'SUM', value: 'SUM' },
        ],
        onChange: (value) => console.log('Target func changed:', value),
      },
      id: 'target-0',
      key: 'target-0',
    },
  ] satisfies FieldItemInput[];

  // Initial mapping relationships
  const initialMappings = [
    {
      id: 'mapping-source-0-target-0',
      source: 'source-0',
      target: 'target-0',
    },
  ];

  return (
    <TableMapping
      ref={tableMappingRef}
      lineType="bezier"
      sourceColumns={sourceColumns}
      targetColumns={targetColumns}
      sources={sourceFields}
      targets={targetFields}
      initialMappings={initialMappings}
      onMappingChange={(mappings) => {
        // you can get mappings, sources, targets, action
        console.info('mappings', mappings);
      }}
    />
  );
}

export default App;

πŸ“š API Reference

TableMapping Props

Prop Type Default Description
lineType 'straight' | 'bezier' | 'step' 'bezier' Type of connection lines
sourceColumns HeaderColumnProps[] [] Source table header columns
targetColumns HeaderColumnProps[] [] Target table header columns
sources FieldItemInput[] [] Source field data
targets FieldItemInput[] [] Target field data
initialMappings Mapping[] [] Initial mapping relationships

HeaderColumnProps

interface HeaderColumnProps {
  title: string;
  key: string;
}

FieldItemInput

interface FieldItemInput {
  id?: string;
  key?: string;
  [field: string]:
    | {
        type: 'string';
        columnKey: string;
        value: string;
      }
    | {
        type: 'input';
        columnKey: string;
        value?: string;
        defaultValue?: string;
        attributes?: Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'>;
        onChange?: (value: string) => void;
      }
    | {
        type: 'select';
        columnKey: string;
        value?: string;
        defaultValue?: string;
        attributes?: Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'onChange'>;
        options: {
          label: string;
          value: string;
          disabled?: boolean;
        }[];
        onChange?: (value: string) => void;
      }
    | string;
}

Mapping

interface Mapping {
  id: string;
  source: string; // Source field ID
  target: string; // Target field ID
}

🎨 Field Types

String Field

Display static text in table cells:

{
  name: {
    type: 'string',
    columnKey: 'name',
    value: 'Static Text'
  }
}

Input Field

Editable text input with change handling:

{
  name: {
    type: 'input',
    columnKey: 'name',
    value: 'Initial Value',
    onChange: (value) => console.log('New value:', value)
  }
}

Select Field

Dropdown selection with options:

{
  func: {
    type: 'select',
    columnKey: 'func',
    defaultValue: 'CONCAT',
    options: [
      { label: 'None', value: 'NONE' },
      { label: 'Concatenate', value: 'CONCAT' },
      { label: 'Sum', value: 'SUM' }
    ],
    onChange: (value) => console.log('Selected:', value)
  }
}

Actions

The onMappingChange callback provides detailed information about state changes through action objects. Each action contains a type and payload with relevant data.

Action Types

Mapping Actions

ADD_MAPPING

{
  type: 'ADD_MAPPING',
  payload: {
    sourceId: string,
    targetId: string,
    mapping: Mapping
  }
}

REMOVE_MAPPING

{
  type: 'REMOVE_MAPPING',
  payload: {
    mappingId: string,
    removedMapping: Mapping | undefined
  }
}

CLEAR_MAPPINGS

{
  type: 'CLEAR_MAPPINGS',
  payload: {
    clearedMappings: Mapping[]
  }
}

UPDATE_MAPPINGS

{
  type: 'UPDATE_MAPPINGS',
  payload: {
    previousMappings: Mapping[],
    newMappings: Mapping[]
  }
}

SAME_LINE_MAPPING

{
  type: 'SAME_LINE_MAPPING',
  payload: {
    createdMappings: Mapping[]
  }
}

SAME_NAME_MAPPING

{
  type: 'SAME_NAME_MAPPING',
  payload: {
    columnKey: string,
    createdMappings: Mapping[]
  }
}

Source Field Actions

APPEND_SOURCE

{
  type: 'APPEND_SOURCE',
  payload: {
    sourceField: FieldItem
  }
}

REMOVE_SOURCE

{
  type: 'REMOVE_SOURCE',
  payload: {
    sourceId: string,
    removedMappings: Mapping[]
  }
}

UPDATE_SOURCE_FIELDS

{
  type: 'UPDATE_SOURCE_FIELDS',
  payload: {
    previousSources: FieldItem[],
    newSources: FieldItem[]
  }
}

UPDATE_SOURCE_FIELD_VALUE

{
  type: 'UPDATE_SOURCE_FIELD_VALUE',
  payload: {
    sourceId: string,
    fieldKey: string,
    previousValue: string,
    newValue: string
  }
}

Target Field Actions

APPEND_TARGET

{
  type: 'APPEND_TARGET',
  payload: {
    targetField: FieldItem
  }
}

REMOVE_TARGET

{
  type: 'REMOVE_TARGET',
  payload: {
    targetId: string,
    removedMappings: Mapping[]
  }
}

UPDATE_TARGET_FIELDS

{
  type: 'UPDATE_TARGET_FIELDS',
  payload: {
    previousTargets: FieldItem[],
    newTargets: FieldItem[]
  }
}

UPDATE_TARGET_FIELD_VALUE

{
  type: 'UPDATE_TARGET_FIELD_VALUE',
  payload: {
    targetId: string,
    fieldKey: string,
    previousValue: string,
    newValue: string
  }
}

🎨 Styling & Theming

The library uses CSS variables for theming and supports both light and dark modes automatically:

/* Custom theme variables */
:root {
  --color-bg-mapping-primary: #ffffff;
  --color-bg-mapping-secondary: #f3f4f9;
  --color-text-default: #151826;
  --color-border-default: #d3d6ea;
}

.dark {
  --color-bg-mapping-primary: #242632;
  --color-bg-mapping-secondary: #151826;
  --color-text-default: #f3f4f9;
  --color-border-default: #545667;
}

Custom Field Components

const customFields = [
  {
    name: {
      type: 'input',
      columnKey: 'name',
      value: 'Custom Field',
      attributes: {
        placeholder: 'Enter field name...',
        maxLength: 50,
      },
      onChange: (value) => {
        // Custom validation
        if (value.length > 50) return;
        console.log('Valid input:', value);
      },
    },
  },
];

πŸ› οΈ Development

Setup

# Clone the repository
$ git clone https://github.com/react-table-mapping/react-table-mapping.git

# Install dependencies
$ npm install
#or
$ yarn

# Start development server
$ npm run dev
# or
$ yarn dev

# Start storybook example
$ npm run storybook
# or
$ yarn storybook

πŸ“ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ‘¨β€πŸ’» Author

donghyun-git - [email protected]

πŸ”— Links


Made with ❀️ by donghyun-git

About

react-table-mapping

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 80.2%
  • CSS 18.4%
  • Other 1.4%