diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 8e01b65..b745001 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -14,17 +14,17 @@
"fable"
]
},
- "fantomas-tool": {
- "version": "4.4.0",
- "commands": [
- "fantomas"
- ]
- },
"femto": {
"version": "0.16.0",
"commands": [
"femto"
]
+ },
+ "fantomas": {
+ "version": "6.3.9",
+ "commands": [
+ "fantomas"
+ ]
}
}
}
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
index 2bd711f..5259d7a 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,8 +5,8 @@ indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
-insert_final_newline = false
+insert_final_newline = true
-[src/Client/*.fs]
-# Feliz style
-fsharp_single_argument_web_mode=true
\ No newline at end of file
+[*.{fs,fsx}]
+fsharp_multiline_bracket_style = stroustrup
+fsharp_newline_before_multiline_computation_expression = false
diff --git a/README.md b/README.md
index 0a144ff..90cfa4d 100644
--- a/README.md
+++ b/README.md
@@ -2,14 +2,57 @@
Feliz-style bindings for [ag-grid-react](https://www.npmjs.com/package/ag-grid-react)
-## Version Compatibility
+## Versions
-### The table below gives the ranges of compatible versions of Feliz AgGrid with its dependent packages.
+### Required versions of dependencies
-| Feliz.AgGrid | ag-grid-react/community | React | Fable | Feliz |
-|- |- |- |- |- |
-| 0.0.6 | 25.x | 17.x | 3.x | 1.x |
-| 1.x | 31.x | 18.x | 4.x | 2.x |
+Note: ag-grid-react/enterprise is only required if using enterprise features.
+
+| Feliz.AgGrid | ag-grid-react/community | ag-grid-react/enterprise | React | Fable | Feliz |
+|--------------|-------------------------|--------------------------|-------|-------|-------|
+| 2.x | 31.x | 31.x | 18.x | 4.x | 2.x |
+| 1.x | 31.x | - | 18.x | 4.x | 2.x |
+| 0.0.6 | 25.x | - | 17.x | 3.x | 1.x |
+
+### Migration guides
+
+#### v1 to v2
+
+##### Import AG Grid style sheets
+
+To give you better control of your bundle, Feliz.AgGrid no longer imports styles for you, so you will need to include
+appropriate imports yourself. For example, add the following lines to your client code to import the necessary styles
+and the Balham theme.
+
+```fsharp
+importAll "ag-grid-community/styles/ag-grid.css"
+importAll "ag-grid-community/styles/ag-theme-balham.css"
+```
+
+##### Use new API
+
+Many properties have been updated to more closely reflect the AG Grid docs. In particular, functions like
+valueFormatter, valueSetter and cellRenderer now take single-parameter functions, with that parameter having properties
+on it allowing you to access the data that you need. This makes it easier for you to get started from the AG Grid docs.
+
+For example, rather than `ColumnDef.cellRenderer` giving you the value in the cell, you are now given a params object
+that has a `.value` field.
+
+```diff
+- ColumnDef.cellRenderer (fun x _ ->
++ ColumnDef.cellRenderer (fun rendererParams ->
+ Html.span [
+ Html.span [
+ prop.style [ style.fontSize 9 ]
+ prop.children [ Html.text "🏅" ]
+ ]
+- Html.textf "%i" x
++ Html.text $"%i{rendererParams.value}"
+ ])
+```
+
+You can see more examples of the required changes in [Git
+commit `cbb0102`](https://github.com/CompositionalIT/feliz-ag-grid/commit/cbb0102e9a7504d0518d32999071c1751ea85be6).
## Installation
@@ -21,7 +64,8 @@ Found in `./src`
## Demo
-Demo code is in `./demo`. You can see it running live at [https://compositionalit.github.io/feliz-ag-grid/](https://compositionalit.github.io/feliz-ag-grid/)
+Demo code is in `./demo`. You can see it running live
+at [https://compositionalit.github.io/feliz-ag-grid/](https://compositionalit.github.io/feliz-ag-grid/)
## Publishing a new package
diff --git a/demo/README.md b/demo/README.md
index ae20e35..3c02b5f 100644
--- a/demo/README.md
+++ b/demo/README.md
@@ -8,13 +8,13 @@
## Deploy
- Change the reference to the src project into a reference to the appropriate NuGet package, e.g.:
- ``` diff
-
- -
- -
- -
-
-
- +
- ```
+ ```diff
+
+ -
+ -
+ -
+
+
+ +
+ ```
- Run `npm run publish-docs`
diff --git a/demo/src/Components.fs b/demo/src/Components.fs
index 6441999..d148c69 100644
--- a/demo/src/Components.fs
+++ b/demo/src/Components.fs
@@ -9,7 +9,6 @@ open Thoth.Fetch
open Thoth.Json
open Fable.Core
-
let citDarkBlue = "#102035"
type LinkData = { Text: string; Href: string }
@@ -21,22 +20,20 @@ let container (children: ReactElement list) =
style.flexDirection.column
style.padding 50
style.maxWidth 1000
- style.margin (0,length.auto)
+ style.margin (0, length.auto)
]
prop.children children
]
let row (children: ReactElement list) =
Html.div [
- prop.style [
- style.alignItems.center
- style.display.flex
- ]
+ prop.style [ style.alignItems.center; style.display.flex ]
prop.children children
]
let navbar () =
- let logo : string = importDefault "./cit-logo.png"
+ let logo: string = importDefault "./cit-logo.png"
+
Html.div [
prop.style [
style.padding (0, 20)
@@ -59,17 +56,9 @@ let navbar () =
]
prop.children [
row [
- Html.img [
- prop.style [
- style.height 50
- ]
- prop.src logo
- ]
+ Html.img [ prop.style [ style.height 50 ]; prop.src logo ]
Bulma.title [
- prop.style [
- style.color.white
- style.fontSize (length.rem 1.5)
- ]
+ prop.style [ style.color.white; style.fontSize (length.rem 1.5) ]
prop.text "Compositional IT"
]
]
@@ -81,7 +70,7 @@ let navbar () =
let subHeading (label: string) =
Bulma.subtitle [
prop.style [
- style.borderBottom(2, borderStyle.solid, citDarkBlue)
+ style.borderBottom (2, borderStyle.solid, citDarkBlue)
style.marginTop 30
style.paddingBottom 10
]
@@ -106,18 +95,12 @@ let description (wrapperName: string) (wrappedComponent: string) links =
Bulma.content [
Html.ul [
for l in links do
- Html.li [
- link l
- ]
+ Html.li [ link l ]
]
]
]
-let headingWithContent (title: string) (children: ReactElement) =
- Html.div [
- subHeading title
- children
- ]
+let headingWithContent (title: string) (children: ReactElement) = Html.div [ subHeading title; children ]
let codeBlock (code: string) =
Html.pre [
@@ -130,174 +113,187 @@ let codeBlock (code: string) =
prop.text code
]
-type Olympian =
- { Athlete: string
- Age: int option
- Country: string
- Year: int
- Date: string
- Sport: string
- Gold: int
- Silver: int
- Bronze: int
- Total: int }
+type Olympian = {
+ Athlete: string
+ Age: int option
+ Country: string
+ Year: int
+ Date: string
+ Sport: string
+ Gold: int
+ Silver: int
+ Bronze: int
+ Total: int
+}
+
+importAll "ag-grid-community/styles/ag-grid.css"
+importAll "ag-grid-community/styles/ag-theme-balham.css"
[]
let Demo () =
- let (olympicData, setOlympicData) = React.useState(None)
- let getData (): JS.Promise =
- promise {
- let url = sprintf "https://www.ag-grid.com/example-assets/olympic-winners.json"
- return! Fetch.get(url, caseStrategy = CamelCase)
- }
+ let olympicData, setOlympicData = React.useState None
+
+ let getData () : JS.Promise = promise {
+ let url = "https://www.ag-grid.com/example-assets/olympic-winners.json"
+ return! Fetch.get (url, caseStrategy = CamelCase)
+ }
React.useEffectOnce (fun () ->
- let d = getData()
- d.``then``(fun data ->
- data
- |> Some
- |> setOlympicData)
- |> ignore)
+ let d = getData ()
+ d.``then`` (fun data -> data |> Some |> setOlympicData) |> ignore)
let updateRowAthleteName newName row =
olympicData
|> Option.iter (
Array.map (fun x -> if x = row then { row with Athlete = newName } else x)
>> Some
- >> setOlympicData)
+ >> setOlympicData
+ )
container [
Html.div [
prop.style [ style.display.flex; style.flexWrap.wrap; style.flexDirection.column ]
prop.children [
Html.div [
- description
- "Feliz.AgGrid"
- "ag-grid"
- [
- { Text = "GitHub repo"; Href = "https://github.com/CompositionalIT/feliz-ag-grid" }
- { Text = "NuGet package"; Href = "https://www.nuget.org/packages/Feliz.AgGrid" }
- { Text = "Corresponding npm package"; Href = "https://www.npmjs.com/package/ag-grid-react" }
- ]
+ description "Feliz.AgGrid" "ag-grid" [
+ {
+ Text = "GitHub repo"
+ Href = "https://github.com/CompositionalIT/feliz-ag-grid"
+ }
+ {
+ Text = "NuGet package"
+ Href = "https://www.nuget.org/packages/Feliz.AgGrid"
+ }
+ {
+ Text = "Corresponding npm package"
+ Href = "https://www.npmjs.com/package/ag-grid-react"
+ }
+ ]
headingWithContent
"Demo"
(match olympicData with
- | Some olympicData ->
- Html.div [
- prop.className ThemeClass.Balham
- prop.children [
- AgGrid.grid [
- AgGrid.rowData olympicData
- AgGrid.pagination true
- AgGrid.defaultColDef [
- ColumnDef.resizable true
- ColumnDef.sortable true
- ]
- AgGrid.domLayout AutoHeight
- AgGrid.paginationPageSize 20
- AgGrid.onColumnGroupOpened (fun x -> x.AutoSizeGroupColumns())
- AgGrid.onGridReady (fun x -> x.AutoSizeAllColumns())
- AgGrid.singleClickEdit true
- AgGrid.enableCellTextSelection true
- AgGrid.ensureDomOrder true
- AgGrid.columnDefs [
- ColumnDef.create [
- ColumnDef.filter RowFilter.Text
- ColumnDef.headerName "Athlete (editable)"
- ColumnDef.valueGetter (fun x -> x.Athlete)
- ColumnDef.editable (fun _ _ -> true)
- ColumnDef.valueSetter (fun newValue _ row -> updateRowAthleteName newValue row)
- ]
- ColumnDef.create [
- ColumnDef.filter RowFilter.Number
- ColumnDef.columnType ColumnType.NumericColumn
- ColumnDef.headerName "Age"
- ColumnDef.valueGetter (fun x -> x.Age)
- ColumnDef.valueFormatter (fun age _ ->
- match age with
- | Some age -> $"{age} years"
- | None -> "Unknown" )
- ]
- ColumnDef.create [
- ColumnDef.filter RowFilter.Text
- ColumnDef.headerName "Country"
- ColumnDef.valueGetter (fun x -> x.Country)
- ]
- ColumnDef.create [
- ColumnDef.filter RowFilter.Date
- ColumnDef.headerName "Date"
- ColumnDef.valueGetter (fun x ->
- x.Date.Split("/")
- |> function
- | [| d; m; y |] -> DateTime(int y, int m, int d)
- | _ -> DateTime.MinValue)
- ColumnDef.valueFormatter (fun d _ -> d.ToShortDateString())
- ]
- ColumnDef.create [
- ColumnDef.filter RowFilter.Text
- ColumnDef.headerName "Sport"
- ColumnDef.valueGetter (fun x -> x.Sport)
- ]
- ColumnGroup.create [
- ColumnGroup.headerName "Medal"
- ColumnGroup.marryChildren true
- ColumnGroup.openByDefault true
- ] [
- ColumnDef.create [
- ColumnDef.filter RowFilter.Number
- ColumnDef.headerName "Total"
- ColumnDef.columnType ColumnType.NumericColumn
- ColumnDef.valueGetter (fun x -> x.Total)
- ColumnDef.cellRenderer (fun x _ ->
- Html.span [
- Html.span [
- prop.style [ style.fontSize 9 ]
- prop.children [
- Html.text "🏅"
- ]
- ]
- Html.textf "%i" x
- ])
- ColumnDef.columnGroupShow true
- ]
- ColumnDef.create [
- ColumnDef.filter RowFilter.Number
- ColumnDef.headerName "Gold"
- ColumnDef.columnType ColumnType.NumericColumn
- ColumnDef.valueGetter (fun x -> x.Gold)
- ColumnDef.columnGroupShow false
- ]
- ColumnDef.create [
- ColumnDef.filter RowFilter.Number
- ColumnDef.headerName "Silver"
- ColumnDef.columnType ColumnType.NumericColumn
- ColumnDef.valueGetter (fun x -> x.Silver)
- ColumnDef.columnGroupShow false
- ]
- ColumnDef.create [
- ColumnDef.filter RowFilter.Number
- ColumnDef.headerName "Bronze"
- ColumnDef.columnType ColumnType.NumericColumn
- ColumnDef.valueGetter (fun x -> x.Bronze)
- ColumnDef.columnGroupShow false
- ]
- ]
- ]
- ]
- ]
- ]
- | None ->
- Html.div [])
+ | Some olympicData ->
+ Html.div [
+ prop.className ThemeClass.Balham
+ prop.children [
+ AgGrid.grid [
+ AgGrid.rowData olympicData
+ AgGrid.pagination true
+ AgGrid.defaultColDef [ ColumnDef.resizable true; ColumnDef.sortable true ]
+ AgGrid.domLayout AutoHeight
+ AgGrid.paginationPageSize 20
+ AgGrid.onColumnGroupOpened (fun x -> x.AutoSizeGroupColumns())
+ AgGrid.onGridReady (fun x -> x.AutoSizeAllColumns())
+ AgGrid.singleClickEdit true
+ AgGrid.enableCellTextSelection true
+ AgGrid.ensureDomOrder true
+ AgGrid.columnDefs [
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Text
+ ColumnDef.headerName "Athlete (editable)"
+ ColumnDef.valueGetter (fun x -> x.Athlete)
+ ColumnDef.editable (fun _ _ -> true)
+ ColumnDef.valueSetter (fun valueChangedParams ->
+ updateRowAthleteName
+ valueChangedParams.newValue
+ valueChangedParams.data)
+ ]
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Number
+ ColumnDef.columnType ColumnType.NumericColumn
+ ColumnDef.headerName "Age"
+ ColumnDef.valueGetter (fun x -> x.Age)
+ ColumnDef.valueFormatter (fun valueParams ->
+ match Option.flatten valueParams.value with
+ | Some age -> $"%i{age} years"
+ | None -> "Unknown")
+ ]
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Text
+ ColumnDef.headerName "Country"
+ ColumnDef.valueGetter (fun x -> x.Country)
+ ]
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Date
+ ColumnDef.headerName "Date"
+ ColumnDef.valueGetter (fun x ->
+ x.Date.Split("/")
+ |> function
+ | [| d; m; y |] -> DateTime(int y, int m, int d)
+ | _ -> DateTime.MinValue)
+ ColumnDef.valueFormatter (fun valueParams ->
+ valueParams.value
+ |> Option.map _.ToShortDateString()
+ |> Option.defaultValue "")
+ ]
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Text
+ ColumnDef.headerName "Sport"
+ ColumnDef.valueGetter (fun x -> x.Sport)
+ ]
+ ColumnGroup.create [
+ ColumnGroup.headerName "Medal"
+ ColumnGroup.marryChildren true
+ ColumnGroup.openByDefault true
+ ] [
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Number
+ ColumnDef.headerName "Total"
+ ColumnDef.columnType ColumnType.NumericColumn
+ ColumnDef.valueGetter (fun x -> x.Total)
+ ColumnDef.cellRenderer (fun rendererParams ->
+ match rendererParams.value with
+ | Some value ->
+ Html.span [
+ Html.span [
+ prop.style [ style.fontSize 9 ]
+ prop.children [ Html.text "🏅" ]
+ ]
+ Html.text $"%i{value}"
+ ]
+ | None -> React.fragment []
+ )
+ ColumnDef.columnGroupShow true
+ ]
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Number
+ ColumnDef.headerName "Gold"
+ ColumnDef.columnType ColumnType.NumericColumn
+ ColumnDef.valueGetter (fun x -> x.Gold)
+ ColumnDef.columnGroupShow false
+ ]
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Number
+ ColumnDef.headerName "Silver"
+ ColumnDef.columnType ColumnType.NumericColumn
+ ColumnDef.valueGetter (fun x -> x.Silver)
+ ColumnDef.columnGroupShow false
+ ]
+ ColumnDef.create [
+ ColumnDef.filter RowFilter.Number
+ ColumnDef.headerName "Bronze"
+ ColumnDef.columnType ColumnType.NumericColumn
+ ColumnDef.valueGetter (fun x -> x.Bronze)
+ ColumnDef.columnGroupShow false
+ ]
+ ]
+ ]
+ ]
+ ]
+ ]
+ | None -> Html.div [])
headingWithContent
"Installation"
- (codeBlock """
+ (codeBlock
+ """
cd ./project
-femto install Feliz.AgGrid""" )
+femto install Feliz.AgGrid""")
headingWithContent
"Sample Code"
- (codeBlock """
+ (codeBlock
+ """
open Feliz.AgGrid
type Olympian =
@@ -312,16 +308,16 @@ type Olympian =
Bronze: int
Total: int }
+importAll "ag-grid-community/styles/ag-grid.css"
+importAll "ag-grid-community/styles/ag-theme-balham.css"
+
Html.div [
prop.className ThemeClass.Balham
prop.children [
AgGrid.grid [
AgGrid.rowData olympicData
AgGrid.pagination true
- AgGrid.defaultColDef [
- ColumnDef.resizable true
- ColumnDef.sortable true
- ]
+ AgGrid.defaultColDef [ ColumnDef.resizable true; ColumnDef.sortable true ]
AgGrid.domLayout AutoHeight
AgGrid.paginationPageSize 20
AgGrid.onColumnGroupOpened (fun x -> x.AutoSizeGroupColumns())
@@ -330,29 +326,32 @@ Html.div [
AgGrid.enableCellTextSelection true
AgGrid.ensureDomOrder true
AgGrid.columnDefs [
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Text
ColumnDef.headerName "Athlete (editable)"
ColumnDef.valueGetter (fun x -> x.Athlete)
ColumnDef.editable (fun _ _ -> true)
- ColumnDef.valueSetter (fun newValue _ row -> updateRowAthleteName newValue row)
+ ColumnDef.valueSetter (fun valueChangedParams ->
+ updateRowAthleteName
+ valueChangedParams.newValue
+ valueChangedParams.data)
]
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Number
ColumnDef.columnType ColumnType.NumericColumn
ColumnDef.headerName "Age"
ColumnDef.valueGetter (fun x -> x.Age)
- ColumnDef.valueFormatter (fun age _ ->
- match age with
- | Some age -> $"{age} years"
- | None -> "Unknown" )
+ ColumnDef.valueFormatter (fun valueParams ->
+ match valueParams.value with
+ | Some age -> $"%i{age} years"
+ | None -> "Unknown")
]
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Text
ColumnDef.headerName "Country"
ColumnDef.valueGetter (fun x -> x.Country)
]
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Date
ColumnDef.headerName "Date"
ColumnDef.valueGetter (fun x ->
@@ -360,9 +359,11 @@ Html.div [
|> function
| [| d; m; y |] -> DateTime(int y, int m, int d)
| _ -> DateTime.MinValue)
- ColumnDef.valueFormatter (fun d _ -> d.ToShortDateString())
+ ColumnDef.valueFormatter (fun valueParams ->
+ let date: DateTime = valueParams.value
+ date.ToShortDateString())
]
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Text
ColumnDef.headerName "Sport"
ColumnDef.valueGetter (fun x -> x.Sport)
@@ -372,38 +373,36 @@ Html.div [
ColumnGroup.marryChildren true
ColumnGroup.openByDefault true
] [
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Number
ColumnDef.headerName "Total"
ColumnDef.columnType ColumnType.NumericColumn
ColumnDef.valueGetter (fun x -> x.Total)
- ColumnDef.cellRenderer (fun x _ ->
+ ColumnDef.cellRenderer (fun rendererParams ->
Html.span [
Html.span [
prop.style [ style.fontSize 9 ]
- prop.children [
- Html.text "🏅"
- ]
+ prop.children [ Html.text "🏅" ]
]
- Html.textf "%i" x
+ Html.text $"%i{rendererParams.value}"
])
ColumnDef.columnGroupShow true
]
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Number
ColumnDef.headerName "Gold"
ColumnDef.columnType ColumnType.NumericColumn
ColumnDef.valueGetter (fun x -> x.Gold)
ColumnDef.columnGroupShow false
]
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Number
ColumnDef.headerName "Silver"
ColumnDef.columnType ColumnType.NumericColumn
ColumnDef.valueGetter (fun x -> x.Silver)
ColumnDef.columnGroupShow false
]
- ColumnDef.create [
+ ColumnDef.create [
ColumnDef.filter RowFilter.Number
ColumnDef.headerName "Bronze"
ColumnDef.columnType ColumnType.NumericColumn
@@ -422,9 +421,4 @@ Html.div [
]
[]
-let Documentation () =
- Html.div [
- navbar()
- Demo()
- ]
-
+let Documentation () = Html.div [ navbar (); Demo() ]
diff --git a/demo/src/Extensions.fs b/demo/src/Extensions.fs
index f411780..f7ae0da 100644
--- a/demo/src/Extensions.fs
+++ b/demo/src/Extensions.fs
@@ -21,9 +21,11 @@ module Config =
/// Tries to find the value of the configured variable if it is defined or returns a given default value otherwise.
let variableOrDefault (key: string) (defaultValue: string) =
let foundValue = variable key
- if String.IsNullOrWhiteSpace foundValue
- then defaultValue
- else foundValue
+
+ if String.IsNullOrWhiteSpace foundValue then
+ defaultValue
+ else
+ foundValue
// Stylesheet API
// let private stylehsheet = Stylesheet.load "./fancy.css"
@@ -32,7 +34,7 @@ module Stylesheet =
type IStylesheet =
[]
- abstract Item : className:string -> string
+ abstract Item: className: string -> string
/// Loads a CSS module and makes the classes within available
- let inline load (path: string) = importDefault path
\ No newline at end of file
+ let inline load (path: string) = importDefault path
diff --git a/demo/src/Main.fs b/demo/src/Main.fs
index 2d17f0d..e969323 100644
--- a/demo/src/Main.fs
+++ b/demo/src/Main.fs
@@ -6,8 +6,6 @@ open Fable.Core.JsInterop
importSideEffects "./styles/global.scss"
-let root = ReactDOM.createRoot(document.getElementById "feliz-app")
+let root = ReactDOM.createRoot (document.getElementById "feliz-app")
-root.render(
- App.Documentation()
-)
\ No newline at end of file
+root.render (App.Documentation())
diff --git a/demo/webpack.config.js b/demo/webpack.config.js
index 6e81c83..772fe6c 100644
--- a/demo/webpack.config.js
+++ b/demo/webpack.config.js
@@ -117,6 +117,11 @@ module.exports = {
// - file-loader: Moves files referenced in the code (fonts, images) into output folder
module: {
rules: [
+ {
+ test: /\.mjs$/,
+ include: /node_modules/,
+ type: 'javascript/auto'
+ },
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
diff --git a/global.json b/global.json
index 1b8195c..c19a2e0 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "6.0.100",
+ "version": "8.0.100",
"rollForward": "latestMinor"
}
}
diff --git a/src/AgGrid.fs b/src/AgGrid.fs
index eb71e85..eb2c120 100644
--- a/src/AgGrid.fs
+++ b/src/AgGrid.fs
@@ -1,194 +1,790 @@
-// fsharplint:disable
-module Feliz.AgGrid
-
-open System
-open Fable.Core
-open Fable.Core.JsInterop
-
-open Feliz
-
-let agGrid : obj = import "AgGridReact" "ag-grid-react"
-
-importAll "ag-grid-community/styles/ag-grid.css"
-importAll "ag-grid-community/styles/ag-theme-alpine.css"
-importAll "ag-grid-community/styles/ag-theme-balham.css"
-importAll "ag-grid-community/styles/ag-theme-material.css"
-
-type RowSelection = Single | Multiple
-type RowFilter = Number | Text | Date member this.FilterText = sprintf "ag%OColumnFilter" this
-type DOMLayout =
- Normal | AutoHeight | Print
- member this.LayoutText =
- match this with
- | Normal -> "normal"
- | AutoHeight -> "autoHeight"
- | Print -> "print"
-
-module ThemeClass =
- let Alpine = "ag-theme-alpine"
- let AlpineDark = "ag-theme-alpine-dark"
- let Balham = "ag-theme-balham"
- let BalhamDark = "ag-theme-balham-dark"
- let Material = "ag-theme-material"
-
-type MenuItemDef = {
- name : string
- action : unit -> unit
- shortcut : string
- icon : obj //HtmlElement
-}
-type MenuItem =
- | BuiltIn of string
- | Custom of MenuItemDef
-
-[]
-type IColumnDefProp<'row, 'value> = interface end
-let columnDefProp<'row, 'value> = unbox>
-let columnDefProps<'row, 'value> = unbox>
-
-[]
-type IColumnDef<'row> = interface end
-
-type ColumnType = RightAligned | NumericColumn
-
-let openClosed = function | true -> "open" | false -> "closed"
-
-[]
-let CellRendererComponent<'value,'row> (render:'value -> 'row -> ReactElement, p) =
- render p?value p?data
-
-[]
-type ColumnDef<'row, 'value> =
- static member inline autoComparator = columnDefProp<'row, 'value> ("comparator" ==> compare)
- static member inline cellClass (setClass:'value -> 'row -> #seq) = columnDefProp<'row, 'value> ("cellClass" ==> fun p -> setClass p?value p?data |> Seq.toArray)
- static member inline cellClassRules (rules: (string*('value -> 'row -> bool)) list) = columnDefProp<'row, 'value> ("cellClassRules" ==> (rules |> List.map (fun (className, rule) -> className ==> fun p -> rule p?value p?data) |> createObj))
-
- []
- static member cellRendererFramework _ = failwith "cellRendererFramework isn't supported in the latest version of AgGrid. Use cellRenderer instead"
- static member cellRenderer (render:'value -> 'row -> ReactElement) = columnDefProp<'row, 'value> ("cellRenderer" ==> fun p -> CellRendererComponent(render, p))
- static member inline cellStyle (setStyle:'value -> 'row -> _) = columnDefProp<'row, 'value> ("cellStyle" ==> fun p -> setStyle p?value p?data)
- static member inline checkboxSelection (v:bool) = columnDefProp<'row, 'value> ("checkboxSelection" ==> v)
- static member inline colId (v:string) = columnDefProp<'row, 'value> ("colId" ==> v)
- static member inline columnGroupShow (v:bool) = columnDefProp<'row, 'value> ("columnGroupShow" ==> openClosed v)
- static member inline columnType ct = columnDefProp<'row, 'value> ("type" ==> match ct with RightAligned -> "rightAligned" | NumericColumn -> "numericColumn")
- static member inline comparator (callback: 'a -> 'a -> int) = columnDefProp<'row, 'value> ("comparator" ==> fun a b -> callback a b)
- static member inline create<'v> (props:seq>) = props |> unbox<_ seq> |> createObj |> unbox>
- static member inline editable (callback:'value -> 'row -> bool) = columnDefProp<'row, 'value> ("editable" ==> fun p -> callback p?value p?data)
- static member inline field (v:'a -> string) = columnDefProp<'row, 'value> ("field" ==> v (unbox null))
- static member inline field (v:string) = columnDefProp<'row, 'value> ("field" ==> v)
- static member inline filter (v:RowFilter) = columnDefProp<'row, 'value> ("filter" ==> v.FilterText)
- static member inline headerCheckboxSelection (v:bool) = columnDefProp<'row, 'value> ("headerCheckboxSelection" ==> v)
- static member inline headerClass (v:string) = columnDefProp<'row, 'value> ("headerClass" ==> v)
- static member inline headerComponentFramework (callback:'colId -> 'props -> ReactElement) = columnDefProp<'row, 'value> ("headerComponentFramework" ==> fun p -> callback p?column?colId p)
- static member inline headerName (v:string) = columnDefProp<'row, 'value> ("headerName" ==> v)
- static member inline hide (v:bool) = columnDefProp<'row, 'value> ("hide" ==> v)
- static member inline maxWidth (v:int) = columnDefProp<'row, 'value> ("maxWidth" ==> v)
- static member inline minWidth (v:int) = columnDefProp<'row, 'value> ("minWidth" ==> v)
- static member inline onCellClicked (handler:'value -> 'row -> unit) = columnDefProp<'row, 'value> ("onCellClicked" ==> (fun p -> handler p?value p?data))
- static member inline resizable (v:bool) = columnDefProp<'row, 'value> ("resizable" ==> v)
- static member inline sortable (v:bool) = columnDefProp<'row, 'value> ("sortable" ==> v)
- static member inline suppressKeyboardEvent callback = columnDefProp<'row, 'value> ("suppressKeyboardEvent" ==> fun x -> callback x?event)
- static member inline suppressMovable = columnDefProp<'row, 'value> ("suppressMovable" ==> true)
- static member inline valueFormatter (v:'value -> 'row -> string) = columnDefProp<'row, 'value> ("valueFormatter" ==> (fun p -> v p?value p?data))
- static member inline valueGetter (f:'row -> 'value) = columnDefProp<'row, 'value> ("valueGetter" ==> (fun x -> f x?data))
- static member inline valueSetter (f:string -> 'value -> 'row -> unit) = columnDefProp<'row, 'value> ("valueSetter" ==> (fun x -> f x?newValue x?oldValue x?data; false)) // return false to prevent the grid from immediately refreshing
- static member inline width (v:int) = columnDefProp<'row, 'value> ("width" ==> v)
-
-[]
-type IColumnGroupDefProp<'row> = interface end
-let columnGroupDefProp<'row> = unbox>
-
-[]
-type ColumnGroup<'row> =
- static member inline headerName (v:string) = columnGroupDefProp<'row> ("headerName" ==> v)
- static member inline marryChildren(v:bool) = columnGroupDefProp<'row> ("marryChildren" ==> v)
- static member inline openByDefault(v:bool) = columnGroupDefProp<'row> ("openByDefault" ==> v)
-
- static member inline create<'row> (props:seq>) (children:seq>) =
- props |> Seq.append [(columnGroupDefProp<'row> ("children" ==> Seq.toArray children))] |> unbox<_ seq> |> createObj |> unbox>
-
-[]
-type IAgGridProp<'row> = interface end
-let agGridProp<'row> (x:obj) = unbox> x
-
-[]
-type AgGrid() =
- static member inline onSelectionChanged (callback:'row array -> unit) = agGridProp<'row>("onSelectionChanged", fun x -> x?api?getSelectedRows() |> callback)
- static member inline onCellValueChanged callback = agGridProp<'row>("onCellValueChanged", fun x -> callback x?data)
- static member inline onRowClicked (handler:'value -> 'row -> unit) = agGridProp<'row> ("onRowClicked" ==> (fun p -> handler p?value p?data))
- static member inline singleClickEdit (v:bool) = agGridProp<'row>("singleClickEdit" ==> v)
- static member inline rowDeselection (v:bool) = agGridProp<'row>("rowDeselection", v)
- static member inline rowSelection (s:RowSelection) = agGridProp<'row>("rowSelection", s.ToString().ToLower())
- static member inline isRowSelectable (callback:'row -> bool) = agGridProp<'row>("isRowSelectable" ==> fun x -> x?data |> callback)
- static member inline suppressRowClickSelection (v:bool) = agGridProp<'row>("suppressRowClickSelection" ==> v)
- static member inline enableCellTextSelection (v:bool) = agGridProp<'row> ("enableCellTextSelection" ==> v)
- static member inline ensureDomOrder (v:bool) = agGridProp<'row> ("ensureDomOrder" ==> v)
- static member inline rowHeight (h:int) = agGridProp<'row>("rowHeight", h)
- static member inline domLayout (l:DOMLayout) = agGridProp<'row>("domLayout", l.LayoutText)
- static member inline immutableData (v:bool) = agGridProp<'row>("immutableData", v)
- static member inline rowData (data:'row array) = agGridProp<'row>("rowData", data)
- static member inline getRowNodeId (callback: 'row -> _) = agGridProp<'row>("getRowNodeId", callback)
- static member inline columnDefs (columns:IColumnDef<'row> seq) = agGridProp<'row>("columnDefs", columns |> unbox |> Seq.toArray)
- static member inline defaultColDef (defaults:IColumnDefProp<'row, 'value> seq) = agGridProp<'row>("defaultColDef", defaults |> unbox<_ seq> |> createObj)
- static member onColumnGroupOpened (callback:_ -> unit) = // This can't be inline otherwise Fable produces invalid JS
- let onColumnGroupOpened = fun ev ->
- {| AutoSizeGroupColumns = fun () ->
- // Runs the column autoSize in a 0ms timeout so that the cellRendererFramework cells render
- // before the grid calculates how large each cell is
- JS.setTimeout (fun () ->
- let colIds = ev?columnGroup?children |> Array.map (fun x -> x?colId)
- ev?columnApi?autoSizeColumns(colIds)) 0 |> ignore |}
- |> callback
- agGridProp<'row>("onColumnGroupOpened", onColumnGroupOpened)
-
- static member inline paginationPageSize (pageSize:int) = agGridProp<'row>("paginationPageSize", pageSize)
- static member inline paginationAutoPageSize (v:bool) = agGridProp<'row>("paginationAutoPageSize", v)
- static member inline pagination (v:bool) = agGridProp<'row>("pagination", v)
- static member onGridReady (callback:_ -> unit) = // This can't be inline otherwise Fable produces invalid JS
- let onGridReady = fun ev ->
- {| AutoSizeAllColumns =
- fun () ->
- // Runs the column autoSize in a 0ms timeout so that the cellRendererFramework cells render
- // before the grid calculates how large each cell is
- JS.setTimeout (fun () ->
- let colIds = ev?api?getColumns() |> Array.map (fun x -> x?colId)
- ev?api?autoSizeColumns(colIds)) 0 |> ignore
- Export = fun () -> ev?api?exportDataAsCsv(obj()) |}
- |> callback
- agGridProp<'row>("onGridReady", onGridReady)
- static member inline enableRangeHandle (v: bool) = agGridProp<'row>("enableRangeHandle", v)
- static member inline enableRangeSelection (v: bool) = agGridProp<'row>("enableRangeSelection", v)
- static member inline getContextMenuItems (callback : int -> int -> MenuItem list) = agGridProp<'row>("getContextMenuItems", fun x ->
- let menuItems = callback x?node?rowIndex x?column?colId
- [|
- for item in menuItems do
- match item with
- | BuiltIn builtInItemName -> box builtInItemName
- | Custom customMenuItem -> box customMenuItem
- |])
- static member inline headerHeight height = agGridProp<'row>("headerHeight", height)
- static member inline onCellFocused callback = agGridProp<'row>("onCellFocused", fun x -> callback x?rowIndex x?column?colId)
- static member inline onRangeSelectionChanged callback = agGridProp<'row>("onRangeSelectionChanged", fun x ->
- let selectedRange = x?api?getCellRanges()?at(0)
- let startRow = selectedRange?startRow?rowIndex
- let startColumn = selectedRange?columns?at(0)?colId
- let endRow = selectedRange?endRow?rowIndex
- let endColumn = selectedRange?columns?at(selectedRange?columns?length-1)?colId
-
- callback startRow startColumn endRow endColumn)
- static member inline popupParent parent = agGridProp<'row>("popupParent", parent)
- static member inline processDataFromClipboard (callback : string[][] -> string[][]) = agGridProp<'row>("processDataFromClipboard", fun x -> callback x?data)
- static member inline stopEditingWhenCellsLoseFocus (v: bool) = agGridProp<'row>("stopEditingWhenCellsLoseFocus", v)
- static member inline stopEditingWhenGridLosesFocus (v: bool) = agGridProp<'row>("stopEditingWhenGridLosesFocus", v)
- static member inline suppressClipboardApi (v: bool) = agGridProp<'row>("suppressClipboardApi", v)
- static member inline suppressCopyRowsToClipboard (v: bool) = agGridProp<'row>("suppressCopyRowsToClipboard", v)
- static member inline suppressCopySingleCellRanges (v: bool) = agGridProp<'row>("suppressCopySingleCellRanges", v)
- static member inline suppressMultiRangeSelection (v: bool) = agGridProp<'row>("suppressMultiRangeSelection", v)
- static member inline suppressRowHoverHighlight (v: bool) = agGridProp<'row>("suppressRowHoverHighlight", v)
- static member inline suppressScrollOnNewData (v: bool) = agGridProp<'row>("suppressScrollOnNewData", v)
-
- static member inline key (v:string) = agGridProp<'row> (prop.key v)
- static member inline key (v:int) = agGridProp<'row> (prop.key v)
- static member inline key (v:System.Guid) = agGridProp<'row> (prop.key v)
-
- static member inline grid<'row> (props:IAgGridProp<'row> seq) = Interop.reactApi.createElement (agGrid, createObj !!props)
+module Feliz.AgGrid
+
+open System
+
+open Fable.Core
+open Fable.Core.JsInterop
+open Feliz
+
+// Suppress unused value warnings - they are often necessary for Fable bindings.
+#nowarn "1182"
+
+let agGrid: obj = import "AgGridReact" "ag-grid-react"
+
+[]
+[]
+type LicenseManager =
+ static member setLicenseKey(key: string) : unit = jsNative
+
+/// See https://www.ag-grid.com/react-data-grid/row-object/.
+[]
+type IRowNode<'row> = {
+ id: string
+ data: 'row
+ updateData: 'row -> unit
+ setData: 'row -> unit
+ setSelected: bool -> unit
+ rowIndex: int
+ rowTop: int
+ displayed: bool
+ isHovered: bool
+ isFullWidthCell: bool
+ isSelected: bool
+}
+
+[]
+type ICellRange = {
+ id: string
+ startRow: obj
+ endRow: obj
+} with
+
+ member this.startRowIndex: int = this.startRow?rowIndex
+ member this.endRowIndex: int = this.endRow?rowIndex
+
+/// See https://www.ag-grid.com/react-data-grid/grid-interface/#grid-api.
+[]
+type IGridApi<'row> =
+ abstract refreshCells: unit -> unit
+ abstract redrawRows: unit -> unit
+ abstract setGridOption: string -> obj -> unit
+ abstract getSelectedNodes: unit -> IRowNode<'row>[]
+ abstract getCellRanges: unit -> ICellRange[]
+
+/// See https://www.ag-grid.com/react-data-grid/column-object/.
+[]
+type IColumn = { getColId: unit -> string }
+
+[]
+type IColumnDefProp<'row, 'value> = interface end
+
+let columnDefProp<'row, 'value> = unbox>
+
+// Although the AG Grid docs suggest that this should have two type params, we only give it one so that column defs
+// with different underlying value types can be used in the same list (for example in AgGrid.columnDefs).
+[]
+type IColumnDef<'row> = interface end
+
+let columnDef<'row> = unbox>
+
+[]
+module CallbackParams =
+ /// See https://www.ag-grid.com/react-data-grid/column-properties/#reference-editing-valueSetter.
+ /// See https://www.ag-grid.com/react-data-grid/column-properties/#reference-editing-valueParser.
+ []
+ type IValueChangedParams<'row, 'value> = {
+ oldValue: 'value
+ newValue: 'value
+ node: IRowNode<'row>
+ data: 'row
+ column: IColumn
+ colDef: IColumnDef<'row>
+ api: IGridApi<'row>
+ } with
+
+ member this.rowIndex = this.node.rowIndex
+
+ /// See https://www.ag-grid.com/react-data-grid/cell-editors/#custom-components.
+ []
+ type IValueParams<'row, 'value> = {
+ value: 'value option
+ data: 'row option
+ node: IRowNode<'row>
+ colDef: IColumnDef<'row>
+ column: IColumn
+ api: IGridApi<'row>
+ rowIndex: int
+ }
+
+ /// See https://www.ag-grid.com/react-data-grid/grid-events/#reference-selection-cellFocused.
+ []
+ type ICellFocusedEvent<'row> = {
+ api: IGridApi<'row>
+ rowIndex: int
+ column: IColumn
+ isFullWidthCell: bool
+ }
+
+ /// See https://www.ag-grid.com/react-data-grid//grid-options/#reference-rowModels-getRowId.
+ []
+ type IGetRowIdParams<'row> = {
+ data: 'row
+ level: int
+ parentKeys: string[]
+ api: IGridApi<'row>
+ context: obj
+ }
+
+ []
+ type ICellRendererParams<'row, 'value> = {
+ value: 'value option
+ data: 'row option
+ node: IRowNode<'row>
+ colDef: IColumnDef<'row>
+ column: IColumn
+ api: IGridApi<'row>
+ rowIndex: int
+ }
+
+ []
+ type IPasteEvent<'row> = {
+ source: string
+ api: IGridApi<'row>
+ context: obj
+ ``type``: string
+ }
+
+ []
+ type IProcessDataFromClipboardParams<'row> = {
+ data: string[][]
+ api: IGridApi<'row>
+ context: obj
+ }
+
+type RowSelection =
+ | Single
+ | Multiple
+
+
+
+[]
+type RowFilter =
+ | Number
+ | Text
+ | Date
+
+ member this.FilterText = sprintf "ag%OColumnFilter" this
+
+[]
+type CellDataType =
+ | Text
+ | Number
+ | Date
+ | DateString
+ | Boolean
+ | Object
+ | Custom of string
+
+ member this.CellDataTypeText =
+ match this with
+ | Text -> "text"
+ | Number -> "number"
+ | Date -> "date"
+ | DateString -> "dateString"
+ | Boolean -> "boolean"
+ | Object -> "object"
+ | Custom s -> s
+
+[]
+type AgCellEditor =
+ | SelectCellEditor
+ | NumberCellEditor
+ | DateCellEditor
+ | DateStringCellEditor
+ | CheckboxCellEditor
+ | LargeTextCellEditor
+ | TextCellEditor
+
+ member this.CellEditorText = sprintf "ag%O" this
+
+type DOMLayout =
+ | Normal
+ | AutoHeight
+ | Print
+
+ member this.LayoutText =
+ match this with
+ | Normal -> "normal"
+ | AutoHeight -> "autoHeight"
+ | Print -> "print"
+
+module ThemeClass =
+ let Alpine = "ag-theme-alpine"
+ let AlpineDark = "ag-theme-alpine-dark"
+ let Balham = "ag-theme-balham"
+ let BalhamDark = "ag-theme-balham-dark"
+ let Material = "ag-theme-material"
+
+type ColumnType =
+ | RightAligned
+ | NumericColumn
+
+let openClosed =
+ function
+ | true -> "open"
+ | false -> "closed"
+
+[]
+let CellRendererComponent<'row, 'value>
+ (render: ICellRendererParams<'row, 'value> -> ReactElement, p: ICellRendererParams<'row, 'value>)
+ =
+ render p
+
+[]
+type ColumnDef<'row> =
+ // Constrain all props for a given column to be for the same value.
+ static member inline create<'value>(props: IColumnDefProp<'row, 'value> seq) = createObj !!props |> columnDef<'row>
+
+ static member inline autoComparator() =
+ columnDefProp<'row, 'value> ("comparator" ==> compare)
+
+ static member inline cellClass(setClass: 'value -> 'row -> #seq) =
+ columnDefProp<'row, 'value> ("cellClass" ==> fun p -> setClass p?value p?data |> Seq.toArray)
+
+ static member inline cellClassRules(rules: (string * ('value -> 'row -> bool)) list) =
+ columnDefProp<'row, 'value> (
+ "cellClassRules"
+ ==> (rules
+ |> List.map (fun (className, rule) -> className ==> fun p -> rule p?value p?data)
+ |> createObj)
+ )
+
+ static member cellDataType(v: bool) =
+ columnDefProp<'row, 'value> ("cellDataType" ==> v)
+
+ static member cellDataType(v: CellDataType) =
+ columnDefProp<'row, 'value> ("cellDataType" ==> v.CellDataTypeText)
+
+ []
+ static member cellRendererFramework _ =
+ failwith "cellRendererFramework isn't supported in the latest version of AgGrid. Use cellRenderer instead"
+
+ static member cellRenderer(render: ICellRendererParams<'row, 'value> -> ReactElement) =
+ columnDefProp<'row, 'value> ("cellRenderer" ==> fun p -> CellRendererComponent(render, p))
+
+ static member cellEditor(render: ICellRendererParams<'row, 'value> -> ReactElement) =
+ columnDefProp<'row, 'value> ("cellEditor" ==> fun p -> CellRendererComponent(render, p))
+
+ static member cellEditor(v: string) =
+ columnDefProp<'row, 'value> ("cellEditor" ==> v)
+
+ static member cellEditor(v: AgCellEditor) =
+ columnDefProp<'row, 'value> ("cellEditor" ==> v.CellEditorText)
+
+ static member cellEditorParams(v: string seq) =
+ columnDefProp<'row, 'value> ("cellEditorParams" ==> {| values = v |> Seq.toArray |})
+
+ static member cellEditorParams(v: obj) =
+ columnDefProp<'row, 'value> ("cellEditorParams" ==> v)
+
+ static member cellEditorPopup(v: bool) =
+ columnDefProp<'row, 'value> ("cellEditorPopup" ==> v)
+
+ static member inline cellStyle(setStyle: 'value -> 'row -> _) =
+ columnDefProp<'row, 'value> ("cellStyle" ==> fun p -> setStyle p?value p?data)
+
+ static member inline checkboxSelection(v: bool) =
+ columnDefProp<'row, 'value> ("checkboxSelection" ==> v)
+
+ static member inline colId(v: string) =
+ columnDefProp<'row, 'value> ("colId" ==> v)
+
+ static member inline columnGroupShow(v: bool) =
+ columnDefProp<'row, 'value> ("columnGroupShow" ==> openClosed v)
+
+ static member inline columnType ct =
+ columnDefProp<'row, 'value> (
+ "type"
+ ==> match ct with
+ | RightAligned -> "rightAligned"
+ | NumericColumn -> "numericColumn"
+ )
+
+ static member inline comparator(callback: 'a -> 'a -> int) =
+ columnDefProp<'row, 'value> ("comparator" ==> fun a b -> callback a b)
+
+ static member inline editable(callback: 'value -> 'row -> bool) =
+ columnDefProp<'row, 'value> ("editable" ==> fun p -> callback p?value p?data)
+
+ static member inline editable(v: bool) =
+ columnDefProp<'row, 'value> ("editable" ==> v)
+
+ static member inline equals(callback: 'value -> 'value -> bool) =
+ columnDefProp<'row, 'value> ("equals" ==> callback)
+
+ static member inline enableRowGroup(v: bool) =
+ columnDefProp<'row, 'value> ("enableRowGroup" ==> v)
+
+ static member inline enableCellChangeFlash(v: bool) =
+ columnDefProp<'row, 'value> ("enableCellChangeFlash" ==> v)
+
+ static member inline field(v: string) =
+ columnDefProp<'row, 'value> ("field" ==> v)
+
+ /// Usage: `ColumnDef.field _.FieldName` or `ColumnDef.field (fun x -> x.FieldName)`
+ static member inline field(f: 'row -> _) =
+ let idxOfFirstDot = (string f).IndexOf('.')
+ // `ColumnDef.field _.FirstName` and `ColumnDef.field (fun x -> x.FirstName)` both result in "FirstName".
+ let field = (string f).Substring(idxOfFirstDot + 1)
+ columnDefProp<'row, 'value> ("field" ==> field)
+
+ static member inline filter(v: RowFilter) =
+ columnDefProp<'row, 'value> ("filter" ==> v.FilterText)
+
+ static member inline filter(v: bool) =
+ columnDefProp<'row, 'value> ("filter" ==> v)
+
+ static member inline floatingFilter(v: bool) =
+ columnDefProp<'row, 'value> ("floatingFilter" ==> v)
+
+ static member inline headerCheckboxSelection(v: bool) =
+ columnDefProp<'row, 'value> ("headerCheckboxSelection" ==> v)
+
+ static member inline headerClass(v: string) =
+ columnDefProp<'row, 'value> ("headerClass" ==> v)
+
+ static member inline headerComponentFramework(callback: 'colId -> 'props -> ReactElement) =
+ columnDefProp<'row, 'value> ("headerComponentFramework" ==> fun p -> callback p?column?colId p)
+
+ static member inline headerName(v: string) =
+ columnDefProp<'row, 'value> ("headerName" ==> v)
+
+ static member inline wrapHeaderText(v: bool) =
+ columnDefProp<'row, 'value> ("wrapHeaderText" ==> v)
+
+ static member inline autoHeaderHeight(v: bool) =
+ columnDefProp<'row, 'value> ("autoHeight" ==> v)
+
+ static member inline hide(v: bool) =
+ columnDefProp<'row, 'value> ("hide" ==> v)
+
+ static member inline maxWidth(v: int) =
+ columnDefProp<'row, 'value> ("maxWidth" ==> v)
+
+ static member inline minWidth(v: int) =
+ columnDefProp<'row, 'value> ("minWidth" ==> v)
+
+ static member inline onCellClicked(handler: 'value -> 'row -> unit) =
+ columnDefProp<'row, 'value> ("onCellClicked" ==> (fun p -> handler p?value p?data))
+
+ static member inline pinned(v: bool) =
+ columnDefProp<'row, 'value> ("pinned" ==> v)
+
+
+
+ static member inline resizable(v: bool) =
+ columnDefProp<'row, 'value> ("resizable" ==> v)
+
+ static member inline rowDrag(v: bool) =
+ columnDefProp<'row, 'value> ("rowDrag" ==> v)
+
+ static member inline rowGroup(v: bool) =
+ columnDefProp<'row, 'value> ("rowGroup" ==> v)
+
+ static member inline sortable(v: bool) =
+ columnDefProp<'row, 'value> ("sortable" ==> v)
+
+ static member inline suppressKeyboardEvent callback =
+ columnDefProp<'row, 'value> ("suppressKeyboardEvent" ==> fun x -> callback x?event)
+
+ static member inline suppressMovable() =
+ columnDefProp<'row, 'value> ("suppressMovable" ==> true)
+
+ static member inline valueFormatter(callback: IValueParams<'row, 'value> -> string) =
+ columnDefProp<'row, 'value> ("valueFormatter" ==> callback)
+
+ static member inline valueGetter(f: 'row -> 'value) =
+ columnDefProp<'row, 'value> ("valueGetter" ==> (fun (x:{|data: 'row option|}) -> x.data |> Option.map f ))
+
+ static member inline valueSetter(f: IValueChangedParams<'row, 'value> -> unit) =
+ columnDefProp<'row, 'value> ("valueSetter" ==> f)
+
+ static member inline valueSetter(f: IValueChangedParams<'row, 'value> -> bool) =
+ columnDefProp<'row, 'value> ("valueSetter" ==> f)
+
+ static member inline valueParser(f: IValueChangedParams<'row, 'value> -> obj) =
+ columnDefProp<'row, 'value> ("valueParser" ==> f) // Is never called by AgGrid
+
+ static member inline width(v: int) =
+ columnDefProp<'row, 'value> ("width" ==> v)
+
+[]
+type IColumnGroupDefProp<'row> = interface end
+
+let columnGroupDefProp<'row> = unbox>
+
+[]
+type ColumnGroup<'row> =
+ static member inline headerName(v: string) =
+ columnGroupDefProp<'row> ("headerName" ==> v)
+
+ static member inline marryChildren(v: bool) =
+ columnGroupDefProp<'row> ("marryChildren" ==> v)
+
+ static member inline openByDefault(v: bool) =
+ columnGroupDefProp<'row> ("openByDefault" ==> v)
+
+ static member inline create (props: seq>) (children: seq>) =
+ let combinedProps = seq {
+ yield! props
+ columnGroupDefProp<'row> ("children" ==> Seq.toArray children)
+ }
+
+ createObj !!combinedProps |> columnDef<'row>
+
+[]
+type IAgGridProp<'row> = interface end
+
+let agGridProp<'row> (x: obj) = unbox> x
+
+[]
+type AgGrid<'row> =
+ static member inline animateRows(v: bool) = agGridProp<'row> ("animateRows" ==> v)
+
+ static member inline alwaysShowVerticalScroll(v: bool) =
+ agGridProp<'row> ("alwaysShowVerticalScroll" ==> v)
+
+ static member inline columnDefs(columns: IColumnDef<'row> seq) =
+ agGridProp<'row> ("columnDefs", Seq.toArray !!columns)
+
+ static member inline copyHeadersToClipboard(v: bool) =
+ agGridProp<'row> ("copyHeadersToClipboard" ==> v)
+
+ static member inline domLayout(l: DOMLayout) =
+ agGridProp<'row> ("domLayout", l.LayoutText)
+
+ static member inline enableCellTextSelection(v: bool) =
+ agGridProp<'row> ("enableCellTextSelection" ==> v)
+
+ static member inline ensureDomOrder(v: bool) =
+ agGridProp<'row> ("ensureDomOrder" ==> v)
+
+ static member inline enterNavigatesVertically(v: bool) =
+ agGridProp<'row> ("enterNavigatesVertically" ==> v)
+
+ static member inline getRowNodeId(callback: 'row -> _) =
+ agGridProp<'row> ("getRowNodeId", callback)
+
+ static member inline getRowId(callback: IGetRowIdParams<'row> -> string) = agGridProp<'row> ("getRowId", callback)
+
+ static member inline onCellEditRequest(callback: obj -> unit) =
+ agGridProp<'row> ("onCellEditRequest", callback)
+
+ static member inline onCellValueChanged callback =
+ agGridProp<'row> ("onCellValueChanged", (fun x -> callback x?data))
+
+ static member inline onPasteStart(callback: IPasteEvent<'row> -> unit) =
+ agGridProp<'row> ("onPasteStart", callback)
+
+ static member inline onPasteEnd(callback: IPasteEvent<'row> -> unit) =
+ agGridProp<'row> ("onPasteEnd", callback)
+
+ static member inline onRowClicked(handler: 'value -> 'row -> unit) =
+ agGridProp<'row> ("onRowClicked" ==> (fun p -> handler p?value p?data))
+
+ static member inline onSelectionChanged(callback: 'row array -> unit) =
+ agGridProp<'row> ("onSelectionChanged", (fun x -> x?api?getSelectedRows () |> callback))
+
+ static member inline readOnlyEdit(v: bool) = agGridProp<'row> ("readOnlyEdit" ==> v)
+
+ static member inline singleClickEdit(v: bool) =
+ agGridProp<'row> ("singleClickEdit" ==> v)
+
+ static member inline rowDeselection(v: bool) = agGridProp<'row> ("rowDeselection", v)
+
+ static member inline rowSelection(s: RowSelection) =
+ agGridProp<'row> ("rowSelection", s.ToString().ToLower())
+
+ static member inline isRowSelectable(callback: 'row -> bool) =
+ agGridProp<'row> ("isRowSelectable" ==> fun x -> x?data |> callback)
+
+ static member inline suppressRowClickSelection(v: bool) =
+ agGridProp<'row> ("suppressRowClickSelection" ==> v)
+
+ static member inline rowHeight(h: int) = agGridProp<'row> ("rowHeight", h)
+ static member inline immutableData(v: bool) = agGridProp<'row> ("immutableData", v)
+
+ /// Converts your data to a JS array to populate the grid. (This is less efficient than passing an array.)
+ static member inline rowData(data: 'row seq) =
+ agGridProp<'row> ("rowData", Seq.toArray data)
+
+ static member inline rowData(data: 'row array) = agGridProp<'row> ("rowData", data)
+
+ static member inline rowDragManaged(v: bool) =
+ agGridProp<'row> ("rowDragManaged" ==> v)
+
+ static member inline defaultColDef(defaults: IColumnDefProp<'row, 'value> seq) =
+ agGridProp<'row> ("defaultColDef", defaults |> unbox<_ seq> |> createObj)
+
+ static member onColumnGroupOpened(callback: _ -> unit) = // This can't be inline otherwise Fable produces invalid JS
+ let onColumnGroupOpened =
+ fun ev ->
+ {|
+ AutoSizeGroupColumns =
+ fun () ->
+ // Runs the column autoSize in a 0ms timeout so that the cellRenderer cells render before
+ // the grid calculates how large each cell is
+ JS.setTimeout
+ (fun () ->
+ let colIds =
+ ev?columnGroups
+ |> Seq.head
+ |> fun cg -> cg?children
+ |> Array.map (fun x -> x?colId)
+
+ ev?api?autoSizeColumns colIds)
+ 0
+ |> ignore
+ |}
+ |> callback
+
+ agGridProp<'row> ("onColumnGroupOpened", onColumnGroupOpened)
+
+ static member inline paginationPageSize(pageSize: int) =
+ agGridProp<'row> ("paginationPageSize", pageSize)
+
+ static member inline paginationAutoPageSize(v: bool) =
+ agGridProp<'row> ("paginationAutoPageSize", v)
+
+ static member inline pagination(v: bool) = agGridProp<'row> ("pagination", v)
+
+ static member onGridReady(callback: _ -> unit) = // This can't be inline otherwise Fable produces invalid JS
+ let onGridReady =
+ fun ev ->
+ {|
+ AutoSizeAllColumns =
+ fun () ->
+ // Runs the column autoSize in a 0ms timeout so that the cellRendererFramework cells render
+ // before the grid calculates how large each cell is
+ JS.setTimeout
+ (fun () ->
+ let colIds = ev?api?getColumns () |> Array.map (fun x -> x?colId)
+ ev?api?autoSizeColumns colIds)
+ 0
+ |> ignore
+ Export = fun () -> ev?api?exportDataAsCsv (obj ())
+ |}
+ |> callback
+
+ agGridProp<'row> ("onGridReady", onGridReady)
+
+ static member inline processDataFromClipboard(callback: IProcessDataFromClipboardParams<'row> -> string[][]) =
+ agGridProp<'row> ("processDataFromClipboard", callback)
+
+ static member inline enableRangeHandle(v: bool) =
+ agGridProp<'row> ("enableRangeHandle", v)
+
+ static member inline enableRangeSelection(v: bool) =
+ agGridProp<'row> ("enableRangeSelection", v)
+
+
+ static member inline suppressAggFuncInHeader(v: bool) =
+ agGridProp<'row> ("suppressAggFuncInHeader", v)
+
+ static member inline headerHeight height =
+ agGridProp<'row> ("headerHeight", height)
+
+ static member inline groupHeaderHeight height =
+ agGridProp<'row> ("groupHeaderHeight", height)
+
+ []
+ static member inline onCellFocused callback =
+ agGridProp<'row> ("onCellFocused", (fun x -> callback (int x?rowIndex) (int x?column?colId)))
+
+ static member inline onCellFocused callback =
+ agGridProp<'row> ("onCellFocused", (fun (e: ICellFocusedEvent<'row>) -> callback e))
+
+ static member inline onRangeSelectionChanged callback =
+ agGridProp<'row> (
+ "onRangeSelectionChanged",
+ fun x ->
+ let selectedRange = x?api?getCellRanges ()?at 0
+ let startRow = selectedRange?startRow?rowIndex
+ let startColumn = selectedRange?columns?at 0?colId
+ let endRow = selectedRange?endRow?rowIndex
+ let endColumn = selectedRange?columns?at (selectedRange?columns?length - 1)?colId
+
+ callback startRow startColumn endRow endColumn
+ )
+
+ static member inline popupParent parent =
+ agGridProp<'row> ("popupParent", parent)
+
+ static member inline processDataFromClipboard(callback: string[][] -> string[][]) =
+ agGridProp<'row> ("processDataFromClipboard", (fun x -> callback x?data))
+
+ static member inline stopEditingWhenCellsLoseFocus(v: bool) =
+ agGridProp<'row> ("stopEditingWhenCellsLoseFocus", v)
+
+ static member inline stopEditingWhenGridLosesFocus(v: bool) =
+ agGridProp<'row> ("stopEditingWhenGridLosesFocus", v)
+
+ static member inline suppressClipboardApi(v: bool) =
+ agGridProp<'row> ("suppressClipboardApi", v)
+
+ static member inline suppressCopyRowsToClipboard(v: bool) =
+ agGridProp<'row> ("suppressCopyRowsToClipboard", v)
+
+ static member inline suppressCopySingleCellRanges(v: bool) =
+ agGridProp<'row> ("suppressCopySingleCellRanges", v)
+
+ static member inline suppressMultiRangeSelection(v: bool) =
+ agGridProp<'row> ("suppressMultiRangeSelection", v)
+
+ static member inline suppressRowHoverHighlight(v: bool) =
+ agGridProp<'row> ("suppressRowHoverHighlight", v)
+
+ static member inline suppressScrollOnNewData(v: bool) =
+ agGridProp<'row> ("suppressScrollOnNewData", v)
+
+ static member inline key(v: string) = agGridProp<'row> (prop.key v)
+ static member inline key(v: int) = agGridProp<'row> (prop.key v)
+ static member inline key(v: Guid) = agGridProp<'row> (prop.key v)
+
+ static member inline dataTypeDefinitions(v: obj) =
+ agGridProp<'row> ("dataTypeDefinitions", v)
+
+ static member inline enableFillHandle(v: bool) =
+ agGridProp<'row> ("enableFillHandle", v)
+
+ static member inline undoRedoCellEditing(v: bool) =
+ agGridProp<'row> ("undoRedoCellEditing", v)
+
+ static member inline undoRedoCellEditingLimit(v: int) =
+ agGridProp<'row> ("undoRedoCellEditingLimit", v)
+
+ static member inline grid(props: IAgGridProp<'row> seq) =
+ Interop.reactApi.createElement (agGrid, createObj !!props)
+
+ module Enterprise =
+
+ []
+ type RowFilter =
+ | Number
+ | Text
+ | Date
+ | Set
+ | Multi
+
+ member this.FilterText = sprintf "ag%OColumnFilter" this
+
+ []
+ type AgCellEditor =
+ | SelectCellEditor
+ | NumberCellEditor
+ | DateCellEditor
+ | DateStringCellEditor
+ | CheckboxCellEditor
+ | LargeTextCellEditor
+ | TextCellEditor
+ | RichSelectCellEditor
+
+ member this.RichCellEditorText = sprintf "ag%O" this
+
+ []
+ type RowGroupingDisplayType =
+ | SingleColumn
+ | MultipleColumns
+ | GroupRows
+ | Custom
+
+ member this.RowGroupingDisplayTypeText =
+ match this with
+ | SingleColumn -> "singleColumn"
+ | MultipleColumns -> "multipleColumns"
+ | GroupRows -> "groupRows"
+ | Custom -> "custom"
+
+ []
+ type RowGroupPanelShow =
+ | Always
+ | OnlyWhenGrouping
+ | Never
+
+ member this.RowGroupPanelShowText =
+ match this with
+ | Always -> "always"
+ | OnlyWhenGrouping -> "onlyWhenGrouping"
+ | Never -> "never"
+
+ []
+ type AggregateFunction =
+ | Sum
+ | Min
+ | Max
+ | Count
+ | Avg
+ | First
+ | Last
+
+ member this.AggregateText = (sprintf "%O" this).ToLower()
+
+ type MenuItemDef = {
+ name: string
+ action: (unit -> unit) option
+ shortcut: string option
+ icon: obj option//HtmlElement
+ }
+
+ []
+ type BuiltInMenuItem =
+ | AutoSizeAll
+ | ExpandAll
+ | ContractAll
+ | Copy
+ | CopyWithHeaders
+ | CopyWithGroupHeaders
+ | Cut
+ | Paste
+ | ResetColumns
+ | Export
+ | CsvExport
+ | ExcelExport
+ | ChartRange
+ | PivotChart
+
+ member this.BuiltInMenuItemText =
+ match this with
+ | AutoSizeAll -> "autoSizeAll"
+ | ExpandAll -> "expandAll"
+ | ContractAll -> "contractAll"
+ | Copy -> "copy"
+ | CopyWithHeaders -> "copyWithHeaders"
+ | CopyWithGroupHeaders -> "copyWithGroupHeaders"
+ | Cut -> "cut"
+ | Paste -> "paste"
+ | ResetColumns -> "resetColumns"
+ | Export -> "export"
+ | CsvExport -> "csvExport"
+ | ExcelExport -> "excelExport"
+ | ChartRange -> "chartRange"
+ | PivotChart -> "pivotChart"
+
+ type MenuItem =
+ | BuiltIn of BuiltInMenuItem
+ | Custom of MenuItemDef
+
+ []
+ type ColumnDef<'row> =
+ static member inline filter(v: RowFilter) = columnDefProp<'row, 'value> ("filter" ==> v.FilterText)
+ static member cellEditor(v: AgCellEditor) = columnDefProp<'row, 'value> ("cellEditor" ==> v.RichCellEditorText)
+ static member inline pivot(v: bool) = columnDefProp<'row, 'value> ("pivot" ==> v)
+ static member inline aggFunc(v: AggregateFunction) = columnDefProp<'row, 'value> ("aggFunc" ==> v.AggregateText)
+ static member inline rowGroup(v: bool) = columnDefProp<'row, 'value> ("rowGroup" ==> v)
+
+ []
+ type AgGrid<'row> =
+ static member inline rowGroupPanelShow(v: RowGroupPanelShow) =
+ agGridProp<'row> ("rowGroupPanelShow", v.RowGroupPanelShowText)
+
+ static member inline groupDisplayType(v: RowGroupingDisplayType) =
+ agGridProp<'row> ("groupDisplayType", v.RowGroupingDisplayTypeText)
+
+ static member inline pivotMode(v: bool) = agGridProp<'row> ("pivotMode", v)
+
+ static member inline getDataPath( v: 'row -> string array) = agGridProp<'row> ("getDataPath", v)
+ static member inline treeData(v: bool) = agGridProp<'row> ("treeData", v)
+
+ static member inline getContextMenuItems(callback: int -> int -> MenuItem list) =
+ agGridProp<'row> (
+ "getContextMenuItems",
+ fun x ->
+ let menuItems = callback x?node?rowIndex x?column?colId
+
+ [|
+ for item in menuItems do
+ match item with
+ | BuiltIn builtInItemName -> box builtInItemName.BuiltInMenuItemText
+ | Custom customMenuItem -> box customMenuItem
+ |]
+ )