diff --git a/.vscode/settings.json b/.vscode/settings.json
index c5632ba..5f69485 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,30 +1,53 @@
{
// Enable the ESlint flat config support
"eslint.experimental.useFlatConfig": true,
-
// Disable the default formatter, use eslint instead
"prettier.enable": false,
"editor.formatOnSave": false,
-
// Auto fix
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "never"
},
-
// Silent the stylistic rules in you IDE, but still auto fix them
"eslint.rules.customizations": [
- { "rule": "style/*", "severity": "off" },
- { "rule": "*-indent", "severity": "off" },
- { "rule": "*-spacing", "severity": "off" },
- { "rule": "*-spaces", "severity": "off" },
- { "rule": "*-order", "severity": "off" },
- { "rule": "*-dangle", "severity": "off" },
- { "rule": "*-newline", "severity": "off" },
- { "rule": "*quotes", "severity": "off" },
- { "rule": "*semi", "severity": "off" }
+ {
+ "rule": "style/*",
+ "severity": "off"
+ },
+ {
+ "rule": "*-indent",
+ "severity": "off"
+ },
+ {
+ "rule": "*-spacing",
+ "severity": "off"
+ },
+ {
+ "rule": "*-spaces",
+ "severity": "off"
+ },
+ {
+ "rule": "*-order",
+ "severity": "off"
+ },
+ {
+ "rule": "*-dangle",
+ "severity": "off"
+ },
+ {
+ "rule": "*-newline",
+ "severity": "off"
+ },
+ {
+ "rule": "*quotes",
+ "severity": "off"
+ },
+ {
+ "rule": "*semi",
+ "severity": "off"
+ }
],
-
// Enable eslint for all supported languages
"eslint.validate": [
"javascript",
diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts
index 9b07bf6..74d2a85 100644
--- a/docs/.vitepress/config.ts
+++ b/docs/.vitepress/config.ts
@@ -1,5 +1,8 @@
import { defineConfig } from 'vitepress'
import { transformerTwoslash } from 'vitepress-plugin-twoslash'
+import container from 'markdown-it-container'
+import { renderSandbox } from 'vitepress-plugin-sandpack'
+import Unocss from 'unocss/vite'
// https://vitepress.dev/reference/site-config
export default defineConfig({
@@ -13,12 +16,26 @@ export default defineConfig({
codeTransformers: [
transformerTwoslash(),
],
+ config(md) {
+ md
+ .use(container, 'sandbox', {
+ render(tokens, idx) {
+ return renderSandbox(tokens, idx, 'sandbox')
+ },
+ })
+ .use(container, 'code-sandbox', {
+ render(tokens, idx) {
+ return renderSandbox(tokens, idx, 'code-sandbox')
+ },
+ })
+ },
},
lastUpdated: true,
ignoreDeadLinks: true,
cleanUrls: true,
- titleTemplate: ':title - Typed-xlsx',
+ titleTemplate: 'Typed-xlsx | :title',
themeConfig: {
+ aside: true,
logo: '/images/logo.png',
editLink: {
pattern: 'https://github.com/ChronicStone/typed-xlsx/edit/main/docs/:path',
@@ -47,31 +64,40 @@ export default defineConfig({
{
text: 'Schema Builder',
items: [
- { text: 'Columns', link: '/schema-builder/columns' },
+ { text: 'Create schema', link: '/schema-builder/create-schema' },
+ { text: 'Define columns', link: '/schema-builder/columns' },
{ text: 'Dynamic Columns', link: '/schema-builder/dynamic-columns' },
{ text: 'Global Transformers', link: '/schema-builder/global-transformers' },
{ text: 'Build Schema', link: '/schema-builder/build-schema' },
],
},
- {
- text: 'Column Definition',
- items: [
- { text: 'Header', link: '/column-definition/header' },
- { text: 'Value Transformation', link: '/column-definition/value-transformation' },
- { text: 'Key & Value', link: '/column-definition/key-value' },
- { text: 'Default Value', link: '/column-definition/default-value' },
- { text: 'Cell Format', link: '/column-definition/cell-format' },
- { text: 'Cell Style', link: '/column-definition/cell-style' },
- { text: 'Summary', link: '/column-definition/summary' },
- ],
- },
+ // {
+ // text: 'Column Definition',
+ // items: [
+ // { text: 'Header', link: '/column-definition/header' },
+ // { text: 'Value Transformation', link: '/column-definition/value-transformation' },
+ // { text: 'Key & Value', link: '/column-definition/key-value' },
+ // { text: 'Default Value', link: '/column-definition/default-value' },
+ // { text: 'Cell Format', link: '/column-definition/cell-format' },
+ // { text: 'Cell Style', link: '/column-definition/cell-style' },
+ // { text: 'Summary', link: '/column-definition/summary' },
+ // ],
+ // },
{
text: 'File Builder',
items: [
+ { text: 'Create file builder', link: '/file-builder/create-file-builder' },
{ text: 'Define Sheets', link: '/file-builder/define-sheets' },
{ text: 'Define Tables', link: '/file-builder/define-tables' },
+ { text: 'Build excel file', link: '/file-builder/build-excel-file' },
],
},
],
},
+ vite: {
+ plugins: [
+ // @ts-expect-error unknown ts issue
+ Unocss({}),
+ ],
+ },
})
diff --git a/docs/.vitepress/theme/components/CodeSandbox.vue b/docs/.vitepress/theme/components/CodeSandbox.vue
new file mode 100644
index 0000000..d77b224
--- /dev/null
+++ b/docs/.vitepress/theme/components/CodeSandbox.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts
index 12e61f4..72908a5 100644
--- a/docs/.vitepress/theme/index.ts
+++ b/docs/.vitepress/theme/index.ts
@@ -3,10 +3,20 @@ import TwoslashFloatingVue from 'vitepress-plugin-twoslash/client'
import 'vitepress-plugin-twoslash/style.css'
import type { EnhanceAppContext } from 'vitepress'
import './style.css'
+import 'vitepress-plugin-sandpack/dist/style.css'
+import { Sandbox } from 'vitepress-plugin-sandpack'
+import vitepressNprogress from 'vitepress-plugin-nprogress'
+import CodeSandbox from './components/CodeSandbox.vue'
+import 'vitepress-plugin-nprogress/lib/css/index.css'
+import 'uno.css'
export default {
...DefaultTheme,
- enhanceApp({ app }: EnhanceAppContext) {
- app.use(TwoslashFloatingVue)
+ enhanceApp(ctx: EnhanceAppContext) {
+ ctx.app.use(TwoslashFloatingVue)
+ DefaultTheme.enhanceApp?.(ctx)
+ vitepressNprogress(ctx)
+ ctx.app.component('Sandbox', Sandbox)
+ ctx.app.component('CodeSandbox', CodeSandbox)
},
}
diff --git a/docs/.vitepress/theme/style.css b/docs/.vitepress/theme/style.css
index 7ab65fc..36c936d 100644
--- a/docs/.vitepress/theme/style.css
+++ b/docs/.vitepress/theme/style.css
@@ -190,4 +190,4 @@ body {
.VPHero.has-image .image {
display: none;
}
-}
\ No newline at end of file
+}
diff --git a/docs/file-builder/build-excel-file.md b/docs/file-builder/build-excel-file.md
new file mode 100644
index 0000000..e909d5b
--- /dev/null
+++ b/docs/file-builder/build-excel-file.md
@@ -0,0 +1,122 @@
+# Build Excel File
+
+After defining the sheets and tables, the final step is to build the Excel file using the `build()` method. This method allows you to specify various parameters to customize the output. Here's a detailed explanation of each parameter:
+
+## Build Method
+
+To build the Excel file, call the `build()` method on the ExcelBuilder instance :
+
+```ts twoslash
+// @noErrors
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const excelFile = ExcelBuilder.create()
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'buffer' })
+```
+
+## Parameters
+
+### `output`
+- **Description:** Specifies the format of the output.
+- **Type:** `'buffer' | 'workbook' | 'base64' | 'file'`
+- **Required:** Yes
+- **Example:**
+ ```ts twoslash
+ // @noErrors
+ import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+ // ---cut-before---
+ const buffer = ExcelBuilder.create()
+ // ^?
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'buffer' })
+
+ const workbook = ExcelBuilder.create()
+ // ^?
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'workbook' })
+
+ const base64 = ExcelBuilder.create()
+ // ^?
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'base64' })
+
+ const file = ExcelBuilder.create()
+ // ^?
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'file' })
+ ```
+
+
+### `rtl`
+- **Description:** Specifies whether the Excel file should be rendered in right-to-left (RTL) mode.
+- **Type:** `boolean`
+- **Required:** No
+- **Default:** `false`
+- **Example:**
+
+
+```ts twoslash
+// @noErrors
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const excelFile = ExcelBuilder.create()
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'buffer', rtl: true })
+```
+
+### `extraLength`
+- **Description:** Specifies the extra length each cell should be rendered with.
+- **Type:** `number`
+- **Required:** No
+- **Default:** `10`
+- **Example:**
+
+```ts twoslash
+// @noErrors
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const excelFile = ExcelBuilder.create()
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'buffer', extraLength: 5 })
+```
+
+### `rowHeight`
+- **Description:** Specifies the height of each row in the Excel file.
+- **Type:** `number`
+- **Required:** No
+- **Default:** `30`
+- **Example:**
+
+```ts twoslash
+// @noErrors
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const excelFile = ExcelBuilder.create()
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'buffer', rowHeight: 30 })
+ ```
+
+### `bordered`
+- **Description:** Specifies whether the Excel file should have borders.
+- **Type:** `boolean`
+- **Required:** No
+- **Default:** `true`
+- **Example:**
+
+```ts twoslash
+// @noErrors
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const excelFile = ExcelBuilder.create()
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'buffer', bordered: false })
\ No newline at end of file
diff --git a/docs/file-builder/create-file-builder.md b/docs/file-builder/create-file-builder.md
new file mode 100644
index 0000000..34e54b1
--- /dev/null
+++ b/docs/file-builder/create-file-builder.md
@@ -0,0 +1,52 @@
+# Create File Builder
+
+To construct an Excel file with `typed-xlsx`, start by creating an instance of the file builder using `ExcelBuilder`. This class facilitates the construction of Excel files through a method chaining approach that allows you to configure properties and behaviors sequentially.
+
+## Importing ExcelBuilder
+
+First, ensure that `ExcelBuilder` is imported from the `typed-xlsx` package:
+
+```ts twoslash
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+```
+
+## Creating an ExcelBuilder Instance
+
+To start building an Excel file, create a new instance of ExcelBuilder by calling create(). This method initializes a new Excel file builder instance:
+
+```ts twoslash
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const excelFile = ExcelBuilder.create()
+```
+
+## Method Chaining
+
+ExcelBuilder utilizes method chaining to streamline the configuration of your Excel file, to preserve type-safety and ensure consistency.
+
+```ts twoslash
+// @noErrors
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const excelFile = ExcelBuilder.create()
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .build({ output: 'buffer' })
+```
+
+## Multiple Sheets
+
+In typed-xlsx, you can define multiple sheets in a single workbook. You just need to chain the method calls for each sheet you want to add:
+
+```ts twoslash
+// @noErrors
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const excelFile = ExcelBuilder.create()
+ .sheet('Sheet1')
+ .addTable({ data, schema, })
+ .sheet('Sheet2')
+ .addTable({ data, schema, })
+ .build({ output: 'buffer' })
+```
+
diff --git a/docs/file-builder/define-sheets.md b/docs/file-builder/define-sheets.md
index dd5231d..9ac986f 100644
--- a/docs/file-builder/define-sheets.md
+++ b/docs/file-builder/define-sheets.md
@@ -1 +1,37 @@
# Define Sheets
+
+In `typed-xlsx`, sheets in an Excel workbook are defined using the `.sheet()` method on an `ExcelBuilder` instance. This method allows you to configure individual sheets with specific settings that control the layout and organization of tables within the sheet.
+
+## Method Usage
+
+To add a sheet to your Excel workbook, call the `.sheet()` method with the name of the sheet as the first argument. This name will appear as the tab name in the Excel file:
+
+```ts twoslash
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const workbook = ExcelBuilder.create()
+ .sheet('Sales Data')
+ ```
+
+ ## Optional Parameters
+
+The `.sheet()` method accepts a second optional parameter, an object that allows you to specify additional settings for how tables are laid out within the sheet:
+
+- **tableSeparatorWidth** (`number`): Defines the width of the separator between tables when multiple tables are placed on a single sheet. This is measured in Excel's column width units.
+- **tablesPerRow** (`number`): Specifies the number of tables to display in a single row. This is useful for organizing multiple tables side by side within the same sheet.
+
+### Example with Optional Parameters
+
+Hereโs how to use these optional parameters to customize the layout of tables in a sheet:
+
+```ts twoslash
+import { ExcelBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const workbook = ExcelBuilder.create()
+ .sheet('Financial Overview', {
+ tableSeparatorWidth: 2, // Adds a gap equivalent to 2 columns between tables
+ tablesPerRow: 2 // Places two tables per row
+ })
+```
+
+In this example, the sheet named "Financial Overview" is configured to place two tables per row, separated by a width equivalent to two standard Excel columns.
\ No newline at end of file
diff --git a/docs/file-builder/define-tables.md b/docs/file-builder/define-tables.md
index 5a8d76a..7bc0ed8 100644
--- a/docs/file-builder/define-tables.md
+++ b/docs/file-builder/define-tables.md
@@ -1 +1,171 @@
# Define Tables
+
+In `typed-xlsx`, tables within a sheet are defined to organize and display data effectively. Each table can be customized with various properties to control its presentation and behavior. Here's a detailed look at each property and how to use them:
+
+## Table Properties
+
+### `schema`
+- **Description:** The `ExcelSchemaBuilder` schema you want to use for the table.
+- **Type:** `ExcelSchema`
+- **Required:** Yes
+
+```ts twoslash
+import { ExcelBuilder, ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const userSchema = ExcelSchemaBuilder.create<{ firstName: string, lastName: string }>()
+ .column('firstName', { key: 'firstName' })
+ .column('lastName', { key: 'lastName' })
+ .build()
+
+const file = ExcelBuilder.create()
+ .sheet('Users')
+ .addTable({
+ data: [] as Array<{ firstName: string, lastName: string }>,
+ schema: userSchema,
+ })
+ .build({ output: 'buffer' })
+```
+
+### data
+- **Description:** The data to be displayed in the table.
+- **Type:** `T[]`
+- **Required:** Yes
+
+```ts twoslash
+import { ExcelBuilder, ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const userSchema = ExcelSchemaBuilder.create<{ firstName: string, lastName: string }>()
+ .column('firstName', { key: 'firstName' })
+ .column('lastName', { key: 'lastName' })
+ .build()
+
+const file = ExcelBuilder.create()
+ .sheet('Users')
+ .addTable({
+ data: [{ firstName: 'John', lastName: 'Doe' }],
+ schema: userSchema,
+ })
+ .build({ output: 'buffer' })
+```
+
+### select
+- **Description:** A map of column keys to boolean values that determines which columns to include in the table.
+- **Type:** `{ [key in ColKeys]?: boolean }`
+- **Required:** No
+
+```ts twoslash
+import { ExcelBuilder, ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+const userSchema = ExcelSchemaBuilder.create<{ firstName: string, lastName: string }>()
+ .column('firstName', { key: 'firstName' })
+ .column('lastName', { key: 'lastName' })
+ .build()
+
+const file = ExcelBuilder.create()
+ .sheet('Users')
+ .addTable({
+ data: [{ firstName: 'John', lastName: 'Doe' }],
+ schema: userSchema,
+ select: { firstName: true },
+ // There are thruthy values, so only columns set to true will be returned (firstName and lastName) are included
+ })
+ .addTable({
+ data: [{ firstName: 'John', lastName: 'Doe' }],
+ schema: userSchema,
+ select: { firstName: false },
+ // All values are false, so ALL columns are included except firstName
+ })
+ .build({ output: 'buffer' })
+```
+
+### context
+- **Description:** A map of column keys to values that can be used to dynamically generate the table.
+- **Type:** `{ [Key in GroupColKey]: GroupColumnContext[Key] }`
+- **Required:** Depends on the schema & selected columns
+
+```ts twoslash
+// @errors: 2741
+import { ExcelBuilder, ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+
+interface Organization { id: string, name: string }
+
+const userSchema = ExcelSchemaBuilder.create<{ firstName: string, lastName: string, organizations: Organization[] }>()
+ .column('firstName', { key: 'firstName' })
+ .column('lastName', { key: 'lastName' })
+ .group('group:org', (builder, context: Organization[]) => {
+ for (const org of context) {
+ builder
+ .column(`orga-${org.id}`, {
+ label: `User in ${org.name}`,
+ key: 'organizations',
+ transform: orgs => orgs.some(o => o.id === org.id) ? 'YES' : 'NO',
+ cellStyle: data => ({
+ font: {
+ color: { rgb: data.organizations.some(o => o.id === org.id)
+ ? '61eb34'
+ : 'd10808' },
+ },
+ }),
+ })
+ }
+ })
+ .build()
+
+const organizations: Organization[] = [{ id: '1', name: 'Org 1' }, { id: '2', name: 'Org 2' }, { id: '3', name: 'Org 3' }]
+
+const file = ExcelBuilder.create()
+ .sheet('Users')
+ .addTable({
+ data: [{ firstName: 'John', lastName: 'Doe', organizations: [{ id: '1', name: 'Org 1' }] }],
+ schema: userSchema,
+ context: { },
+ })
+ .build({ output: 'buffer' })
+```
+
+
+### summary
+- **Description:** Enable or disable the summary of the table.
+- **Type:** `boolean`
+- **Required:** No
+
+```ts twoslash
+import { ExcelBuilder, ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+const schema = ExcelSchemaBuilder.create<{ firstName: string, lastName: string }>()
+ .column('firstName', { key: 'firstName' })
+ .column('lastName', { key: 'lastName' })
+ .build()
+
+const data: Array<{ firstName: string, lastName: string }> = []
+
+// ---cut-before---
+const file = ExcelBuilder.create()
+ .sheet('Users')
+ .addTable({ data, schema, summary: false, })
+ // The summary is disabled, so the table will not have a summary
+ .build({ output: 'buffer' })
+```
+
+## Multiple Tables per Sheets
+
+In typed-xlsx, you can define multiple tables per sheet, arranged in various layouts. Below is an example of displaying four tables, arranged in a row of two:
+
+```ts twoslash
+import { ExcelBuilder, ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+const schema = ExcelSchemaBuilder.create<{ firstName: string, lastName: string }>()
+ .column('firstName', { key: 'firstName' })
+ .column('lastName', { key: 'lastName' })
+ .build()
+
+const data: Array<{ firstName: string, lastName: string }> = []
+
+// ---cut-before---
+const file = ExcelBuilder.create()
+ .sheet('Users', { tablesPerRow: 2 })
+ .addTable({ data, schema, title: 'Table 1', })
+ .addTable({ data, schema, title: 'Table 2', })
+ .addTable({ data, schema, title: 'Table 3', })
+ .addTable({ data, schema, title: 'Table 4', })
+ .build({ output: 'buffer' })
+```
\ No newline at end of file
diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md
index 48c5ea9..7bc6d5d 100644
--- a/docs/getting-started/installation.md
+++ b/docs/getting-started/installation.md
@@ -1,6 +1,65 @@
----
-layout: doc
----
-
# Installation
+To install `typed-xlsx` into your project, follow these straightforward steps:
+
+## 1. Install the package
+
+Choose your preferred package manager and run the corresponding command to add `typed-xlsx` to your project:
+
+::: code-group
+```sh [npm]
+npm install @chronicstone/typed-xlsx
+```
+
+```sh [yarn]
+yarn add @chronicstone/typed-xlsx
+```
+
+```sh [pnpm]
+pnpm add @chronicstone/typed-xlsx
+```
+
+```sh [bun]
+bun add @chronicstone/typed-xlsx
+```
+:::
+
+## 2. Import the library
+
+With the package installed, you can now import `ExcelBuilder` and `ExcelSchemaBuilder` into your project:
+
+```ts twoslash
+// @errors: 2345
+import { ExcelBuilder, ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+
+interface User {
+ id: number
+ name: string
+ email: string
+ posts: Array<{
+ id: number
+ title: string
+ likes: number
+ }>
+}
+
+const schema = ExcelSchemaBuilder.create()
+ .column('ID', { key: 'id' })
+ .column('Name', { key: 'name' })
+ .column('Email', { key: 'email' })
+ .column('Posts.ID', { key: 'posts', transform: row => row.map(post => post.id) })
+ .column('Posts.Title', { key: 'posts', transform: row => row.map(post => post.title) })
+ .column('Posts.Likes', { key: 'posts', transform: row => row.map(post => post.likes) })
+ .build()
+
+const users: User[] = []
+const excelFile = ExcelBuilder.create()
+ .sheet('Sheet1')
+ .addTable({
+ data: users,
+ schema,
+ })
+ .build({ output: 'buffer' })
+```
+
+After completing these steps, `typed-xlsx` will be set up and ready to generate sophisticated Excel reports with ease.
diff --git a/docs/getting-started/key-benefits-why.md b/docs/getting-started/key-benefits-why.md
index 188fcd6..3bd15ce 100644
--- a/docs/getting-started/key-benefits-why.md
+++ b/docs/getting-started/key-benefits-why.md
@@ -1 +1,40 @@
# Key Benefits & Why
+
+`typed-xlsx` aims to transform the complexity of generating type-safe and feature-rich Excel reports in TypeScript into a simplified and efficient process. This document outlines the core advantages of adopting `typed-xlsx` for your reporting needs.
+
+## Overcoming Common Challenges
+
+### The Complexity of Excel Report Generation
+Creating Excel reports in TypeScript often entails a steep learning curve and extensive coding due to the low-level nature of powerful libraries like SheetJs. While these libraries are powerful, their complexity can overshadow their utility, making them less developer-friendly.
+
+### Custom Wrappers: A Time Sink
+In a typical scenario, developers find themselves writing extensive custom wrappers to make the existing libraries more accessible and to provide essential features that aren't available out-of-the-box. This process is time-consuming and detracts from the actual goal of report generation.
+
+## The `typed-xlsx` Advantage
+
+### High-Level API with Essential Features
+`typed-xlsx` addresses these pain points by offering a high-level API that wraps SheetJs, retaining its robust capabilities while greatly improving type-safety and the developer experience. It comes equipped with essential features needed for modern report generation, including:
+
+- **Multi-Sheet Support:** Organize complex data sets across multiple sheets within a single workbook.
+- **Multi-Tables Per Sheet:** Easily manage and display multiple data tables on individual sheets.
+- **Enhanced Cell Styling and Formatting:** Apply styles and formats to cells directly within your TypeScript code.
+- **Type-Safe Data Serialization & Validation:** Ensure that your data adheres to expected types, reducing errors and improving report reliability.
+- **Automated Column Summaries:** Generate summaries for data columns, facilitating quick analysis and insights.
+- And many more...
+
+### Developer Experience Focused
+`typed-xlsx` is designed with the developer in mind, simplifying the API and abstracting the complexities, which results in:
+
+- A cleaner and more intuitive codebase.
+- Reduced development time thanks to easy-to-use features.
+- An overall improvement in code maintainability and readability.
+
+## Selecting the Right Tool for the Job
+
+While `typed-xlsx` provides a comprehensive solution for Excel report generation, it's essential to consider the scope of your project when selecting a library.
+
+### Dynamic Reports and Lower-Level Libraries
+If your project involves generating highly dynamic reports with unknown data and structures, lower-level libraries like SheetJs might be the preferred tool due to their extensive configurability and direct control over the Excel features.
+
+### Structured Data and Rapid Development
+For projects with well-defined data structures, `typed-xlsx` excels by enabling developers to create high-quality, aesthetically pleasing reports with speed and type-safety. It's all about building reports 100x faster without compromising on quality or safety.
diff --git a/docs/index.md b/docs/index.md
index 84ef834..81d41c1 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,13 +1,16 @@
---
layout: home
+title: Feature-rich Type-safe Excel Reporting
hero:
name: "Typed-xlsx"
text: "Feature-rich Type-safe Excel Reporting"
tagline: "Craft complex Excel reports with ease in a type-safe manner."
image:
- src: /images/logo.png
+ src: /images/logo.svg
alt: Typed-xlsx
+ style:
+ margin-left: 50px
actions:
- theme: brand
text: Get Started
@@ -18,34 +21,37 @@ hero:
features:
- title: Type-safe Schema Builder
- details: Construct spreadsheet schemas with TypeScript, ensuring the structure of your reports matches the data types they represent.
+ details: Construct type-safe spreadsheet schemas with TypeScript
icon: "๐ "
- title: Dynamic Cell Styling/Formatting
- details: Tailor cell styles and formats dynamically, allowing per-row customization that responds to your data.
+ details: Tailor cell styles and formats dynamically, allowing advanced per-row customization
icon: "๐จ"
- title: Multi-sheet Support
- details: Manage complex datasets easily with support for multiple sheets within a single workbook, organizing data logically and efficiently.
+ details: Manage complex datasets easily with support for multiple sheets within a single workbook
icon: "๐"
- title: Advanced Row Structures
- details: Leverage sophisticated row layouts that support sub-rows and automatic merging, presenting intricate data in a clear, hierarchical format.
+ details: Leverage sophisticated row layouts that support sub-rows and automatic merging
icon: "๐งฉ"
- title: Serializing Complex Data Types
- details: Serialize arrays, booleans, and more with type-safe methods, transforming your raw data into a user-friendly Excel format.
+ details: Serialize arrays, booleans, and more in a 100% type-safe way
icon: "๐"
- title: Easy Default Value Management
- details: Set and manage default values for your cells effortlessly, ensuring consistency and clarity in reports lacking certain data points.
+ details: Simple default / fallback values management for your cells
icon: "๐ฏ"
- title: Multiple Tables Per Sheet
- details: Include numerous tables on a single sheet, complete with dynamic layouts whether linear or grid-like, catering to diverse reporting needs.
+ details: Include numerous tables on a single sheet, with deep layout customization (linear or grid-like)
icon: "๐๏ธ"
- title: Dynamic Column Mapping
- details: Map your data fields to columns with contextual type-safety, providing a seamless transition from database to spreadsheet.
+ details: Use type-safe context to generate columns based on your data
icon: "๐บ๏ธ"
- title: Column Summaries
- details: Automatically calculate and insert column summaries to analyze data at a glance, saving time and adding analytical value to your spreadsheets.
+ details: Automatically calculate and insert column summaries to analyze data at a glance
icon: "๐งฎ"
footer:
message: "Licensed under the MIT License. Created by Cyprien Thao. Extendable and customizable for developers."
---
+
+::: code-sandbox {template=vue3-ts}
+:::
diff --git a/docs/public/images/logo.svg b/docs/public/images/logo.svg
new file mode 100644
index 0000000..f4e5696
--- /dev/null
+++ b/docs/public/images/logo.svg
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/docs/schema-builder/build-schema.md b/docs/schema-builder/build-schema.md
index 783ef3d..3abde2f 100644
--- a/docs/schema-builder/build-schema.md
+++ b/docs/schema-builder/build-schema.md
@@ -1 +1,18 @@
# Build Schema
+
+To finalize your schema definition in `typed-xlsx`, simply call the `.build()` method after defining all your columns. This method compiles the schema and prepares it for use in generating Excel reports.
+
+## Example
+
+Here's how you complete a schema setup:
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+
+const schema = ExcelSchemaBuilder.create<{ firstName: string, lastName: string }>()
+ .column('firstName', { key: 'firstName' })
+ .column('lastName', { key: 'lastName' })
+ .build() // Finalize the schema
+```
+
+The .build() method finalizes the schema configuration and ensures it is ready for use with ExcelBuilder to generate Excel files. It's essential to call .build() after all columns are added to lock in the configuration and prevent further modifications.
\ No newline at end of file
diff --git a/docs/schema-builder/columns.md b/docs/schema-builder/columns.md
index 1be3abf..8a7bc77 100644
--- a/docs/schema-builder/columns.md
+++ b/docs/schema-builder/columns.md
@@ -1 +1,139 @@
-# Columns
+# Define Column
+
+In `typed-xlsx`, defining a column is a straightforward process that sets the foundation for the structure of your Excel report. Let's go through the syntax and the properties you can define for a column.
+
+## Column Syntax
+
+To define a column, use the `column` method provided by `ExcelSchemaBuilder`:
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+
+// Instantiate a schema with a single column
+const schema = ExcelSchemaBuilder.create<{ firstName: string }>()
+ .column('First Name', { key: 'firstName' })
+```
+
+## Column Properties
+
+Each column in `typed-xlsx` can be configured with a variety of properties to fine-tune its behavior and presentation:
+
+## Label (optional)
+
+The `label` property specifies the column's header text in the Excel file.
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+
+ExcelSchemaBuilder.create<{ firstName: string, lastName: string }>()
+ .column('First Name', { key: 'firstName', label: 'First Name' })
+```
+
+## Key (required)
+
+The `key` property is a path to the value in the data object. It can also be a nested path, supporting deep access to the value.
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+ExcelSchemaBuilder.create<{ personal: { firstName: string, lastName: string } }>()
+ .column('First Name', { key: 'personal.firstName' }) // For nested objects
+```
+
+If the key points to an array, `typed-xlsx` automatically handles sub-rows and merging.
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+ExcelSchemaBuilder.create<{ aliases: string[] }>()
+ .column('Aliases', { key: 'aliases' })
+```
+
+## Transform (optional)
+
+The `transform` property allows you to specify how to process the data before it's output to the cell.
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+ExcelSchemaBuilder.create<{ isActive: boolean, name: { first: string, last: string } }>()
+ .withTransformers({ booleanToString: (value: boolean) => value ? 'Yes' : 'No' })
+// Using a shared transformer
+ .column('Active', { key: 'isActive', transform: 'booleanToString' })
+
+// Using a custom transformer function
+ .column('Full Name', {
+ key: 'name',
+ transform: name => `${name.first} ${name.last}`
+ })
+```
+
+If the key points to a non-primitive value, which can't be serialized into a cell value, transformer will be necessary, and required by typescript :
+
+```ts twoslash
+// @errors: 2345
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+
+ExcelSchemaBuilder.create<{ name: { first: string, last: string } }>()
+ .column('Full Name', {
+ key: 'name',
+ })
+```
+
+## Default (optional)
+
+The `default` property sets a fallback value for the cell if the original value is `undefined`.
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+ExcelSchemaBuilder.create<{ middleName: string }>()
+ .column('Middle Name', { key: 'middleName', default: 'N/A' })
+```
+
+##Format (optional)
+
+The `format` property specifies the cell format, such as for currency or dates.
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+ExcelSchemaBuilder.create<{ salary: number }>()
+ .column('Salary', { key: 'salary', format: '$#,##0.00;[Red]-$#,##0.00' })
+```
+
+## CellStyle (optional)
+
+Define the style for the cell, either as a static `CellStyle` object or a function for dynamic styling.
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+
+ExcelSchemaBuilder.create<{ status: string }>()
+ .column('Status', {
+ key: 'status',
+ cellStyle: { fill: { fgColor: { rgb: 'FFFF00' } } }
+ // ^?
+ })
+```
+
+## Summary (optional)
+
+Summaries provide aggregate information at the end of the table.
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// ---cut-before---
+ExcelSchemaBuilder.create<{ value: number }>()
+ .column('Total', {
+ key: 'value',
+ summary: [{
+ value: rows => rows.reduce((sum, row) => sum + row.value, 0)
+ }]
+ })
+```
+
+By setting these properties, you can tailor each column to fit the specific needs of your report, ensuring both the data integrity and the aesthetic quality of the final output.
diff --git a/docs/schema-builder/create-schema.md b/docs/schema-builder/create-schema.md
new file mode 100644
index 0000000..f509d50
--- /dev/null
+++ b/docs/schema-builder/create-schema.md
@@ -0,0 +1,48 @@
+# Create Schema
+
+Creating a well-defined schema is crucial for generating consistent and type-safe Excel reports. `ExcelSchemaBuilder` is a class provided by `typed-xlsx` that enables you to construct such schemas with ease.
+
+## What is ExcelSchemaBuilder?
+
+`ExcelSchemaBuilder` is a builder class designed to create a type-safe schema that represents the structure of the tables you plan to export to an Excel file.
+
+## Instantiating a Schema
+
+To begin defining a schema, instantiate an `ExcelSchemaBuilder` object using the `create` method. You need to provide a type parameter that describes the shape of the data you'll be working with.
+
+Here's how to instantiate a schema for a table with `firstName` and `lastName` fields:
+
+```ts twoslash
+import { ExcelSchemaBuilder } from '@chronicstone/typed-xlsx'
+// @noErrors
+const schema = ExcelSchemaBuilder.create