@tsed/react-formio 3.0.0-rc.14 → 3.0.0-rc.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/molecules/table/components/DefaultBooleanCell.js +3 -3
- package/dist/molecules/table/components/DefaultBooleanCell.js.map +1 -1
- package/dist/molecules/table/filters/SelectFilter.js +16 -15
- package/dist/molecules/table/filters/SelectFilter.js.map +1 -1
- package/dist/molecules/table/filters/TextFieldFilter.js +8 -8
- package/dist/molecules/table/filters/TextFieldFilter.js.map +1 -1
- package/dist/molecules/table/hooks/useUniqValues.d.ts +3 -3
- package/dist/molecules/table/hooks/useUniqValues.js +16 -6
- package/dist/molecules/table/hooks/useUniqValues.js.map +1 -1
- package/dist/molecules/table/utils/mapFormToColumns.d.ts +5 -1
- package/dist/molecules/table/utils/mapFormToColumns.js +39 -23
- package/dist/molecules/table/utils/mapFormToColumns.js.map +1 -1
- package/dist/organisms/table/submissions/SubmissionsTable.js +1 -1
- package/dist/organisms/table/submissions/SubmissionsTable.js.map +1 -1
- package/package.json +3 -3
- package/src/molecules/table/Table.stories.tsx +72 -66
- package/src/molecules/table/components/DefaultBooleanCell.spec.tsx +2 -2
- package/src/molecules/table/components/DefaultBooleanCell.tsx +1 -1
- package/src/molecules/table/filters/SelectFilter.tsx +3 -2
- package/src/molecules/table/filters/TextFieldFilter.tsx +1 -1
- package/src/molecules/table/hooks/useUniqValues.spec.tsx +51 -0
- package/src/molecules/table/hooks/useUniqValues.tsx +21 -5
- package/src/molecules/table/utils/mapFormToColumns.spec.tsx +66 -5
- package/src/molecules/table/utils/mapFormToColumns.tsx +42 -7
- package/src/organisms/table/submissions/SubmissionsTable.tsx +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as r } from "react/jsx-runtime";
|
|
2
2
|
import { registerComponent as o } from "../../../registries/components.js";
|
|
3
|
-
function l({ getValue:
|
|
4
|
-
const
|
|
5
|
-
return /* @__PURE__ */ r("span", { children: String(
|
|
3
|
+
function l({ getValue: n, column: { columnDef: e } }) {
|
|
4
|
+
const t = n();
|
|
5
|
+
return /* @__PURE__ */ r("span", { children: String(t ? e.meta?.labels?.yes || "Yes" : e.meta?.labels?.no || "No") });
|
|
6
6
|
}
|
|
7
7
|
o("Cell.boolean", l);
|
|
8
8
|
o("Cell.checkbox", l);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultBooleanCell.js","sources":["../../../../src/molecules/table/components/DefaultBooleanCell.tsx"],"sourcesContent":["import { CellContext } from \"@tanstack/react-table\";\n\nimport { registerComponent } from \"../../../registries/components\";\n\nexport function DefaultCellBoolean<Data extends object>({ getValue, column: { columnDef } }: CellContext<Data, boolean>) {\n const value = getValue();\n return <span>{String(value ? columnDef.meta?.labels?.[\"yes\"] || \"Yes\" : columnDef.meta?.labels?.[\"
|
|
1
|
+
{"version":3,"file":"DefaultBooleanCell.js","sources":["../../../../src/molecules/table/components/DefaultBooleanCell.tsx"],"sourcesContent":["import { CellContext } from \"@tanstack/react-table\";\n\nimport { registerComponent } from \"../../../registries/components\";\n\nexport function DefaultCellBoolean<Data extends object>({ getValue, column: { columnDef } }: CellContext<Data, boolean>) {\n const value = getValue();\n return <span>{String(value ? columnDef.meta?.labels?.[\"yes\"] || \"Yes\" : columnDef.meta?.labels?.[\"no\"] || \"No\")}</span>;\n}\n\nregisterComponent(\"Cell.boolean\", DefaultCellBoolean);\nregisterComponent(\"Cell.checkbox\", DefaultCellBoolean);\n"],"names":["DefaultCellBoolean","getValue","columnDef","value","registerComponent"],"mappings":";;AAIO,SAASA,EAAwC,EAAE,UAAAC,GAAU,QAAQ,EAAE,WAAAC,EAAA,KAA2C;AACvH,QAAMC,IAAQF,EAAA;AACd,2BAAQ,QAAA,EAAM,UAAA,OAAOE,IAAQD,EAAU,MAAM,QAAS,OAAU,QAAQA,EAAU,MAAM,QAAS,MAAS,IAAI,GAAE;AAClH;AAEAE,EAAkB,gBAAgBJ,CAAkB;AACpDI,EAAkB,iBAAiBJ,CAAkB;"}
|
|
@@ -1,34 +1,35 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { registerComponent as
|
|
1
|
+
import { jsx as t, Fragment as a } from "react/jsx-runtime";
|
|
2
|
+
import { registerComponent as o, getComponent as p } from "../../../registries/components.js";
|
|
3
3
|
import { useUniqValues as f } from "../hooks/useUniqValues.js";
|
|
4
|
-
function
|
|
5
|
-
const
|
|
4
|
+
function n({ header: e, options: l }) {
|
|
5
|
+
const c = p("Select"), i = e.column.getFilterValue(), u = f({ header: e }), m = l.layout === "choicesjs" ? {
|
|
6
6
|
placeholder: void 0
|
|
7
7
|
} : {
|
|
8
|
-
placeholder: `Filter by ${
|
|
8
|
+
placeholder: `Filter by ${e.column.columnDef.header}`
|
|
9
9
|
}, r = [
|
|
10
10
|
{
|
|
11
|
-
label: `Filter by ${
|
|
11
|
+
label: `Filter by ${e.column.columnDef.header}`,
|
|
12
12
|
value: ""
|
|
13
13
|
}
|
|
14
|
-
].concat(
|
|
15
|
-
return /* @__PURE__ */
|
|
16
|
-
|
|
14
|
+
].concat(l.options || u);
|
|
15
|
+
return /* @__PURE__ */ t(a, { children: /* @__PURE__ */ t(
|
|
16
|
+
c,
|
|
17
17
|
{
|
|
18
18
|
size: "small",
|
|
19
|
-
...
|
|
19
|
+
...l,
|
|
20
20
|
...m,
|
|
21
21
|
autoComplete: "off",
|
|
22
22
|
options: r,
|
|
23
|
-
name: `filter_${
|
|
24
|
-
"data-testid": `filter_${
|
|
23
|
+
name: `filter_${e.column.id}`,
|
|
24
|
+
"data-testid": `filter_${e.column.id}`,
|
|
25
25
|
value: i,
|
|
26
|
-
onChange: (
|
|
26
|
+
onChange: (F, s) => e.column.setFilterValue(s)
|
|
27
27
|
}
|
|
28
28
|
) });
|
|
29
29
|
}
|
|
30
|
-
|
|
30
|
+
o("Filter.select", n);
|
|
31
|
+
o("Filter.boolean", n);
|
|
31
32
|
export {
|
|
32
|
-
|
|
33
|
+
n as SelectFilter
|
|
33
34
|
};
|
|
34
35
|
//# sourceMappingURL=SelectFilter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectFilter.js","sources":["../../../../src/molecules/table/filters/SelectFilter.tsx"],"sourcesContent":["import { getComponent, registerComponent } from \"../../../registries/components\";\nimport type { Select as DefaultSelect } from \"../../forms/select/Select\";\nimport { SelectOptionProps } from \"../../forms/select/Select.interface\";\nimport type { FilterProps } from \"../components/DefaultFilter\";\nimport { useUniqValues } from \"../hooks/useUniqValues\";\nimport { FilterSelectOptions } from \"./Filters\";\n\nexport function SelectFilter<Data = any>({ header, options }: FilterProps<Data, FilterSelectOptions>) {\n const Select = getComponent<typeof DefaultSelect>(\"Select\");\n const columnFilterValue = header.column.getFilterValue();\n const uniqValues = useUniqValues<Data>({ header
|
|
1
|
+
{"version":3,"file":"SelectFilter.js","sources":["../../../../src/molecules/table/filters/SelectFilter.tsx"],"sourcesContent":["import { getComponent, registerComponent } from \"../../../registries/components\";\nimport type { Select as DefaultSelect } from \"../../forms/select/Select\";\nimport { SelectOptionProps } from \"../../forms/select/Select.interface\";\nimport type { FilterProps } from \"../components/DefaultFilter\";\nimport { useUniqValues } from \"../hooks/useUniqValues\";\nimport { FilterSelectOptions } from \"./Filters\";\n\nexport function SelectFilter<Data = any>({ header, options }: FilterProps<Data, FilterSelectOptions>) {\n const Select = getComponent<typeof DefaultSelect>(\"Select\");\n const columnFilterValue = header.column.getFilterValue();\n const uniqValues = useUniqValues<Data>({ header });\n\n const opts =\n options.layout === \"choicesjs\"\n ? {\n placeholder: undefined\n }\n : {\n placeholder: `Filter by ${header.column.columnDef.header}`\n };\n\n const listOptions = (\n [\n {\n label: `Filter by ${header.column.columnDef.header}`,\n value: \"\"\n }\n ] as SelectOptionProps[]\n ).concat(options.options || uniqValues);\n\n return (\n <>\n <Select<string>\n size='small'\n {...(options as any)}\n {...opts}\n autoComplete='off'\n options={listOptions}\n name={`filter_${header.column.id}`}\n data-testid={`filter_${header.column.id}`}\n value={columnFilterValue as string}\n onChange={(_, value) => header.column.setFilterValue(value)}\n />\n </>\n );\n}\n\nregisterComponent(\"Filter.select\", SelectFilter);\nregisterComponent(\"Filter.boolean\", SelectFilter);\n"],"names":["SelectFilter","header","options","Select","getComponent","columnFilterValue","uniqValues","useUniqValues","opts","listOptions","jsx","Fragment","_","value","registerComponent"],"mappings":";;;AAOO,SAASA,EAAyB,EAAE,QAAAC,GAAQ,SAAAC,KAAmD;AACpG,QAAMC,IAASC,EAAmC,QAAQ,GACpDC,IAAoBJ,EAAO,OAAO,eAAA,GAClCK,IAAaC,EAAoB,EAAE,QAAAN,GAAQ,GAE3CO,IACJN,EAAQ,WAAW,cACf;AAAA,IACE,aAAa;AAAA,EAAA,IAEf;AAAA,IACE,aAAa,aAAaD,EAAO,OAAO,UAAU,MAAM;AAAA,EAAA,GAG1DQ,IACJ;AAAA,IACE;AAAA,MACE,OAAO,aAAaR,EAAO,OAAO,UAAU,MAAM;AAAA,MAClD,OAAO;AAAA,IAAA;AAAA,EACT,EAEF,OAAOC,EAAQ,WAAWI,CAAU;AAEtC,SACE,gBAAAI,EAAAC,GAAA,EACE,UAAA,gBAAAD;AAAA,IAACP;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACJ,GAAID;AAAA,MACJ,GAAGM;AAAA,MACJ,cAAa;AAAA,MACb,SAASC;AAAA,MACT,MAAM,UAAUR,EAAO,OAAO,EAAE;AAAA,MAChC,eAAa,UAAUA,EAAO,OAAO,EAAE;AAAA,MACvC,OAAOI;AAAA,MACP,UAAU,CAACO,GAAGC,MAAUZ,EAAO,OAAO,eAAeY,CAAK;AAAA,IAAA;AAAA,EAAA,GAE9D;AAEJ;AAEAC,EAAkB,iBAAiBd,CAAY;AAC/Cc,EAAkB,kBAAkBd,CAAY;"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { jsxs as
|
|
1
|
+
import { jsxs as r, Fragment as a, jsx as i } from "react/jsx-runtime";
|
|
2
2
|
import { registerComponent as c, getComponent as d } from "../../../registries/components.js";
|
|
3
3
|
import { useUniqValues as p } from "../hooks/useUniqValues.js";
|
|
4
|
-
function
|
|
5
|
-
const o = d("InputText"), m = t.column.getFilterValue(),
|
|
6
|
-
return /* @__PURE__ */ a
|
|
7
|
-
!e.disableDatalist && /* @__PURE__ */ i("datalist", { id: n, children:
|
|
4
|
+
function F({ header: t, options: e }) {
|
|
5
|
+
const o = d("InputText"), m = t.column.getFilterValue(), s = p({ header: t }), n = `data_list_${t.column.id}`;
|
|
6
|
+
return /* @__PURE__ */ r(a, { children: [
|
|
7
|
+
!e.disableDatalist && /* @__PURE__ */ i("datalist", { id: n, children: s.map((l) => /* @__PURE__ */ i("option", { value: l }, l)) }),
|
|
8
8
|
/* @__PURE__ */ i(
|
|
9
9
|
o,
|
|
10
10
|
{
|
|
@@ -15,13 +15,13 @@ function f({ header: t, options: e }) {
|
|
|
15
15
|
"data-testid": `filter_${t.column.id}`,
|
|
16
16
|
value: m ?? "",
|
|
17
17
|
list: n,
|
|
18
|
-
onChange: (l,
|
|
18
|
+
onChange: (l, u) => t.column.setFilterValue(u)
|
|
19
19
|
}
|
|
20
20
|
)
|
|
21
21
|
] });
|
|
22
22
|
}
|
|
23
|
-
c("Filter.text",
|
|
23
|
+
c("Filter.text", F);
|
|
24
24
|
export {
|
|
25
|
-
|
|
25
|
+
F as TextFieldFilter
|
|
26
26
|
};
|
|
27
27
|
//# sourceMappingURL=TextFieldFilter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TextFieldFilter.js","sources":["../../../../src/molecules/table/filters/TextFieldFilter.tsx"],"sourcesContent":["import { getComponent, registerComponent } from \"../../../registries/components\";\nimport type { InputText as DefaultInputText } from \"../../forms/input-text/InputText\";\nimport type { FilterProps } from \"../components/DefaultFilter\";\nimport { useUniqValues } from \"../hooks/useUniqValues\";\nimport { FilterTextOptions } from \"./Filters\";\n\nexport function TextFieldFilter<Data = any>({ header, options }: FilterProps<Data, FilterTextOptions>) {\n const InputText = getComponent<typeof DefaultInputText>(\"InputText\");\n const columnFilterValue = header.column.getFilterValue();\n const uniqValues = useUniqValues<Data>({ header
|
|
1
|
+
{"version":3,"file":"TextFieldFilter.js","sources":["../../../../src/molecules/table/filters/TextFieldFilter.tsx"],"sourcesContent":["import { getComponent, registerComponent } from \"../../../registries/components\";\nimport type { InputText as DefaultInputText } from \"../../forms/input-text/InputText\";\nimport type { FilterProps } from \"../components/DefaultFilter\";\nimport { useUniqValues } from \"../hooks/useUniqValues\";\nimport { FilterTextOptions } from \"./Filters\";\n\nexport function TextFieldFilter<Data = any>({ header, options }: FilterProps<Data, FilterTextOptions>) {\n const InputText = getComponent<typeof DefaultInputText>(\"InputText\");\n const columnFilterValue = header.column.getFilterValue();\n const uniqValues = useUniqValues<Data>({ header });\n const datalistId = `data_list_${header.column.id}`;\n\n return (\n <>\n {!options.disableDatalist && (\n <datalist id={datalistId}>\n {uniqValues.map((value: any) => (\n <option value={value} key={value} />\n ))}\n </datalist>\n )}\n <InputText<string>\n size='small'\n placeholder={`Filter by ${header.column.columnDef.header}`}\n {...options}\n name={`filter_${header.column.id}`}\n data-testid={`filter_${header.column.id}`}\n value={(columnFilterValue ?? \"\") as string}\n list={datalistId}\n onChange={(_, value) => header.column.setFilterValue(value)}\n />\n </>\n );\n}\n\nregisterComponent(\"Filter.text\", TextFieldFilter);\n"],"names":["TextFieldFilter","header","options","InputText","getComponent","columnFilterValue","uniqValues","useUniqValues","datalistId","jsxs","Fragment","jsx","value","_","registerComponent"],"mappings":";;;AAMO,SAASA,EAA4B,EAAE,QAAAC,GAAQ,SAAAC,KAAiD;AACrG,QAAMC,IAAYC,EAAsC,WAAW,GAC7DC,IAAoBJ,EAAO,OAAO,eAAA,GAClCK,IAAaC,EAAoB,EAAE,QAAAN,GAAQ,GAC3CO,IAAa,aAAaP,EAAO,OAAO,EAAE;AAEhD,SACE,gBAAAQ,EAAAC,GAAA,EACG,UAAA;AAAA,IAAA,CAACR,EAAQ,mBACR,gBAAAS,EAAC,YAAA,EAAS,IAAIH,GACX,UAAAF,EAAW,IAAI,CAACM,MACf,gBAAAD,EAAC,UAAA,EAAO,OAAAC,KAAmBA,CAAO,CACnC,GACH;AAAA,IAEF,gBAAAD;AAAA,MAACR;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,aAAa,aAAaF,EAAO,OAAO,UAAU,MAAM;AAAA,QACvD,GAAGC;AAAA,QACJ,MAAM,UAAUD,EAAO,OAAO,EAAE;AAAA,QAChC,eAAa,UAAUA,EAAO,OAAO,EAAE;AAAA,QACvC,OAAQI,KAAqB;AAAA,QAC7B,MAAMG;AAAA,QACN,UAAU,CAACK,GAAGD,MAAUX,EAAO,OAAO,eAAeW,CAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAC5D,GACF;AAEJ;AAEAE,EAAkB,eAAed,CAAe;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Header } from '@tanstack/react-table';
|
|
2
|
-
|
|
2
|
+
import { SelectOptionProps } from '../../../molecules/forms/select/Select.interface';
|
|
3
|
+
export declare function useUniqValues<Data = any>({ header }: {
|
|
3
4
|
header: Header<Data, unknown>;
|
|
4
|
-
|
|
5
|
-
}): any[];
|
|
5
|
+
}): SelectOptionProps[];
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { useMemo as u } from "react";
|
|
2
|
-
function
|
|
3
|
-
return u(
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
function a({ header: l }) {
|
|
3
|
+
return u(() => {
|
|
4
|
+
switch (l.column.columnDef.meta?.filter?.variant) {
|
|
5
|
+
case "boolean":
|
|
6
|
+
return [
|
|
7
|
+
{ label: l.column.columnDef.meta?.labels?.yes || "Yes", value: !0 },
|
|
8
|
+
{ label: l.column.columnDef.meta?.labels?.no || l.column.columnDef.meta?.labels?.No || "No", value: !1 }
|
|
9
|
+
];
|
|
10
|
+
default:
|
|
11
|
+
return Array.from(l.column.getFacetedUniqueValues().keys()).flat().sort().slice(0, 5e3).map((e) => ({
|
|
12
|
+
label: e,
|
|
13
|
+
value: e
|
|
14
|
+
}));
|
|
15
|
+
}
|
|
16
|
+
}, [l.column]);
|
|
7
17
|
}
|
|
8
18
|
export {
|
|
9
|
-
|
|
19
|
+
a as useUniqValues
|
|
10
20
|
};
|
|
11
21
|
//# sourceMappingURL=useUniqValues.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUniqValues.js","sources":["../../../../src/molecules/table/hooks/useUniqValues.tsx"],"sourcesContent":["import type { Header } from \"@tanstack/react-table\";\nimport { useMemo } from \"react\";\n\nexport function useUniqValues<Data = any>({ header
|
|
1
|
+
{"version":3,"file":"useUniqValues.js","sources":["../../../../src/molecules/table/hooks/useUniqValues.tsx"],"sourcesContent":["import type { Header } from \"@tanstack/react-table\";\nimport { useMemo } from \"react\";\n\nimport { SelectOptionProps } from \"../../../molecules/forms/select/Select.interface\";\n\nexport function useUniqValues<Data = any>({ header }: { header: Header<Data, unknown> }): SelectOptionProps[] {\n return useMemo(() => {\n switch (header.column.columnDef.meta?.filter?.variant) {\n case \"boolean\":\n return [\n { label: header.column.columnDef.meta?.labels?.[\"yes\"] || \"Yes\", value: true },\n { label: header.column.columnDef.meta?.labels?.[\"no\"] || header.column.columnDef.meta?.labels?.[\"No\"] || \"No\", value: false }\n ];\n\n default:\n return Array.from(header.column.getFacetedUniqueValues().keys())\n .flat()\n .sort()\n .slice(0, 5000)\n .map((i) => ({\n label: i,\n value: i\n }));\n }\n }, [header.column]);\n}\n"],"names":["useUniqValues","header","useMemo","i"],"mappings":";AAKO,SAASA,EAA0B,EAAE,QAAAC,KAAkE;AAC5G,SAAOC,EAAQ,MAAM;AACnB,YAAQD,EAAO,OAAO,UAAU,MAAM,QAAQ,SAAA;AAAA,MAC5C,KAAK;AACH,eAAO;AAAA,UACL,EAAE,OAAOA,EAAO,OAAO,UAAU,MAAM,QAAS,OAAU,OAAO,OAAO,GAAA;AAAA,UACxE,EAAE,OAAOA,EAAO,OAAO,UAAU,MAAM,QAAS,MAASA,EAAO,OAAO,UAAU,MAAM,QAAS,MAAS,MAAM,OAAO,GAAA;AAAA,QAAM;AAAA,MAGhI;AACE,eAAO,MAAM,KAAKA,EAAO,OAAO,uBAAA,EAAyB,MAAM,EAC5D,OACA,KAAA,EACA,MAAM,GAAG,GAAI,EACb,IAAI,CAACE,OAAO;AAAA,UACX,OAAOA;AAAA,UACP,OAAOA;AAAA,QAAA,EACP;AAAA,IAAA;AAAA,EAEV,GAAG,CAACF,EAAO,MAAM,CAAC;AACpB;"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { ColumnDef, ColumnDefResolved } from '@tanstack/react-table';
|
|
2
2
|
import { FormType } from '../../../interfaces';
|
|
3
|
-
export declare function mapFormToColumns<Data = any>(form
|
|
3
|
+
export declare function mapFormToColumns<Data = any>({ form, columns, prefix }: {
|
|
4
|
+
form: FormType;
|
|
5
|
+
columns?: ColumnDefResolved<Data, any>[];
|
|
6
|
+
prefix?: string;
|
|
7
|
+
}): ColumnDef<Data, any>[];
|
|
@@ -1,50 +1,66 @@
|
|
|
1
|
-
import { createColumnHelper as
|
|
2
|
-
import { c as
|
|
3
|
-
import { g as
|
|
4
|
-
import { r as
|
|
5
|
-
import { getComponent as
|
|
6
|
-
var
|
|
7
|
-
const
|
|
1
|
+
import { createColumnHelper as f } from "@tanstack/react-table";
|
|
2
|
+
import { c as y } from "../../../chunks/cloneDeep.js";
|
|
3
|
+
import { g as C } from "../../../chunks/_commonjsHelpers.js";
|
|
4
|
+
import { r as g } from "../../../chunks/get.js";
|
|
5
|
+
import { getComponent as b } from "../../../registries/components.js";
|
|
6
|
+
var x = g();
|
|
7
|
+
const h = /* @__PURE__ */ C(x), K = {
|
|
8
8
|
number: "range",
|
|
9
9
|
currency: "range",
|
|
10
10
|
checkbox: "boolean"
|
|
11
|
-
},
|
|
11
|
+
}, k = {
|
|
12
12
|
date: "date",
|
|
13
13
|
datetime: "date",
|
|
14
14
|
number: "number",
|
|
15
15
|
currency: "currency",
|
|
16
16
|
checkbox: "boolean"
|
|
17
17
|
};
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
function m(r) {
|
|
19
|
+
if ("id" in r && typeof r.id == "string")
|
|
20
|
+
return r.id;
|
|
21
|
+
if ("accessorKey" in r && typeof r.accessorKey == "string")
|
|
22
|
+
return r.accessorKey;
|
|
23
|
+
}
|
|
24
|
+
function S({
|
|
25
|
+
form: r,
|
|
26
|
+
columns: p = [],
|
|
27
|
+
prefix: l = "data."
|
|
28
|
+
}) {
|
|
29
|
+
const d = f(), n = y(p);
|
|
30
|
+
return [...r.components.flatMap((e) => e.type === "tabs" ? e.components?.flatMap((t) => t.components) : [e]).filter((e) => e?.tableView).map((e) => {
|
|
31
|
+
const t = e, o = `${l}${t.key}`, a = /* @__PURE__ */ new Set([t.key, o]), i = n.findIndex((u) => {
|
|
32
|
+
const c = m(u);
|
|
33
|
+
return c ? a.has(c) : !1;
|
|
34
|
+
});
|
|
35
|
+
let s = n[i];
|
|
36
|
+
return s && n.splice(i, 1), d.accessor(o, {
|
|
24
37
|
header: (t.label || t.title || t.key)?.replace(/:/, ""),
|
|
25
38
|
meta: {
|
|
26
|
-
type:
|
|
39
|
+
type: k[t.type] || t.type,
|
|
27
40
|
filter: {
|
|
28
|
-
...
|
|
29
|
-
variant:
|
|
41
|
+
...s?.meta?.filter,
|
|
42
|
+
variant: K[t.type] || "text"
|
|
30
43
|
},
|
|
31
|
-
...
|
|
44
|
+
...s?.meta || {}
|
|
32
45
|
},
|
|
33
|
-
...
|
|
46
|
+
...s || {}
|
|
34
47
|
});
|
|
35
|
-
}).
|
|
36
|
-
const o =
|
|
48
|
+
}), ...n].reduce((e, t) => {
|
|
49
|
+
const o = m(t);
|
|
50
|
+
return o && e.some((a) => m(a) === o) || e.push(t), e;
|
|
51
|
+
}, []).map((e, t) => {
|
|
52
|
+
const o = b([`Cell.${e.id}`, `Cell.${e.meta?.type}`, "Cell"]);
|
|
37
53
|
return {
|
|
38
54
|
...e,
|
|
39
55
|
meta: {
|
|
40
56
|
...e?.meta,
|
|
41
|
-
order:
|
|
57
|
+
order: h(e, "meta.order", t * 10)
|
|
42
58
|
},
|
|
43
59
|
cell: e.cell || o
|
|
44
60
|
};
|
|
45
61
|
}).sort((e, t) => e.meta.order > t.meta.order ? 1 : -1);
|
|
46
62
|
}
|
|
47
63
|
export {
|
|
48
|
-
|
|
64
|
+
S as mapFormToColumns
|
|
49
65
|
};
|
|
50
66
|
//# sourceMappingURL=mapFormToColumns.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapFormToColumns.js","sources":["../../../../src/molecules/table/utils/mapFormToColumns.tsx"],"sourcesContent":["import \"../interfaces/extends\";\n\nimport { ColumnDef, ColumnDefResolved, createColumnHelper } from \"@tanstack/react-table\";\nimport cloneDeep from \"lodash/cloneDeep\";\nimport get from \"lodash/get\";\n\nimport type { ComponentType, FormType } from \"../../../interfaces\";\nimport { getComponent } from \"../../../registries/components\";\nimport type { DefaultCell } from \"../components/DefaultCell\";\nimport type { FilterVariants } from \"../filters/Filters.js\";\n\nconst MAP_FILTER_TYPES: Record<string, FilterVariants> = {\n number: \"range\",\n currency: \"range\",\n checkbox: \"boolean\"\n} as const;\n\nconst MAP_TYPES = {\n date: \"date\",\n datetime: \"date\",\n number: \"number\",\n currency: \"currency\",\n checkbox: \"boolean\"\n} as const;\n\nexport function mapFormToColumns<Data = any>(form: FormType
|
|
1
|
+
{"version":3,"file":"mapFormToColumns.js","sources":["../../../../src/molecules/table/utils/mapFormToColumns.tsx"],"sourcesContent":["import \"../interfaces/extends\";\n\nimport { ColumnDef, ColumnDefResolved, createColumnHelper } from \"@tanstack/react-table\";\nimport cloneDeep from \"lodash/cloneDeep\";\nimport get from \"lodash/get\";\n\nimport type { ComponentType, FormType } from \"../../../interfaces\";\nimport { getComponent } from \"../../../registries/components\";\nimport type { DefaultCell } from \"../components/DefaultCell\";\nimport type { FilterVariants } from \"../filters/Filters.js\";\n\nconst MAP_FILTER_TYPES: Record<string, FilterVariants> = {\n number: \"range\",\n currency: \"range\",\n checkbox: \"boolean\"\n} as const;\n\nconst MAP_TYPES = {\n date: \"date\",\n datetime: \"date\",\n number: \"number\",\n currency: \"currency\",\n checkbox: \"boolean\"\n} as const;\n\nfunction getColumnIdentity<Data>(column: ColumnDef<Data, any> | ColumnDefResolved<Data, any>) {\n if (\"id\" in column && typeof column.id === \"string\") {\n return column.id;\n }\n\n if (\"accessorKey\" in column && typeof column.accessorKey === \"string\") {\n return column.accessorKey;\n }\n\n return undefined;\n}\n\nexport function mapFormToColumns<Data = any>({\n form,\n columns = [],\n prefix = \"data.\"\n}: {\n form: FormType;\n columns?: ColumnDefResolved<Data, any>[];\n prefix?: string;\n}): ColumnDef<Data, any>[] {\n const columnHelper = createColumnHelper<Data>();\n const columnsToKeep = cloneDeep(columns);\n\n const columnsFromComponents = form.components\n .flatMap((component) => {\n if (component.type === \"tabs\") {\n return component.components?.flatMap((subComponent: ComponentType) => subComponent.components);\n }\n\n return [component];\n })\n .filter((component) => component?.tableView)\n .map((c) => {\n const component = c as ComponentType;\n const componentColumnKey = `${prefix}${component.key}`;\n const matchingKeys = new Set([component.key, componentColumnKey]);\n\n const columnIndex = columnsToKeep.findIndex((column) => {\n const identity = getColumnIdentity(column);\n\n return identity ? matchingKeys.has(identity) : false;\n });\n\n let column = columnsToKeep[columnIndex];\n\n if (column) {\n columnsToKeep.splice(columnIndex, 1);\n }\n\n return columnHelper.accessor(componentColumnKey as any, {\n header: (component.label || component.title || component.key)?.replace(/:/, \"\"),\n meta: {\n type: (MAP_TYPES[component.type as keyof typeof MAP_TYPES] || component.type) as any,\n filter: {\n ...column?.meta?.filter,\n variant: MAP_FILTER_TYPES[component.type as keyof typeof MAP_FILTER_TYPES] || \"text\"\n },\n ...(column?.meta || {})\n },\n ...(column || {})\n });\n });\n\n const dedupedColumns = [...columnsFromComponents, ...(columnsToKeep as any[])].reduce<ColumnDef<Data, any>[]>((acc, column) => {\n const identity = getColumnIdentity(column);\n\n if (identity && acc.some((existingColumn) => getColumnIdentity(existingColumn) === identity)) {\n return acc;\n }\n\n acc.push(column);\n return acc;\n }, []);\n\n const mergedColumns = dedupedColumns.map((column, index) => {\n const Cell = getComponent<typeof DefaultCell>([`Cell.${column.id}`, `Cell.${column.meta?.type}`, \"Cell\"]);\n\n return {\n ...column,\n meta: {\n ...column?.meta,\n order: get(column, \"meta.order\", index * 10)\n },\n cell: column.cell || Cell\n };\n });\n\n return mergedColumns.sort((a, b) => (a.meta.order > b.meta.order ? 1 : -1)) as ColumnDef<Data, any>[];\n}\n"],"names":["MAP_FILTER_TYPES","MAP_TYPES","getColumnIdentity","column","mapFormToColumns","form","columns","prefix","columnHelper","createColumnHelper","columnsToKeep","cloneDeep","component","subComponent","c","componentColumnKey","matchingKeys","columnIndex","identity","acc","existingColumn","index","Cell","getComponent","get","a","b"],"mappings":";;;;;;gCAWMA,IAAmD;AAAA,EACvD,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AACZ,GAEMC,IAAY;AAAA,EAChB,MAAM;AAAA,EACN,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AACZ;AAEA,SAASC,EAAwBC,GAA6D;AAC5F,MAAI,QAAQA,KAAU,OAAOA,EAAO,MAAO;AACzC,WAAOA,EAAO;AAGhB,MAAI,iBAAiBA,KAAU,OAAOA,EAAO,eAAgB;AAC3D,WAAOA,EAAO;AAIlB;AAEO,SAASC,EAA6B;AAAA,EAC3C,MAAAC;AAAA,EACA,SAAAC,IAAU,CAAA;AAAA,EACV,QAAAC,IAAS;AACX,GAI2B;AACzB,QAAMC,IAAeC,EAAA,GACfC,IAAgBC,EAAUL,CAAO;AAkEvC,SAxBuB,CAAC,GAxCMD,EAAK,WAChC,QAAQ,CAACO,MACJA,EAAU,SAAS,SACdA,EAAU,YAAY,QAAQ,CAACC,MAAgCA,EAAa,UAAU,IAGxF,CAACD,CAAS,CAClB,EACA,OAAO,CAACA,MAAcA,GAAW,SAAS,EAC1C,IAAI,CAACE,MAAM;AACV,UAAMF,IAAYE,GACZC,IAAqB,GAAGR,CAAM,GAAGK,EAAU,GAAG,IAC9CI,IAAe,oBAAI,IAAI,CAACJ,EAAU,KAAKG,CAAkB,CAAC,GAE1DE,IAAcP,EAAc,UAAU,CAACP,MAAW;AACtD,YAAMe,IAAWhB,EAAkBC,CAAM;AAEzC,aAAOe,IAAWF,EAAa,IAAIE,CAAQ,IAAI;AAAA,IACjD,CAAC;AAED,QAAIf,IAASO,EAAcO,CAAW;AAEtC,WAAId,KACFO,EAAc,OAAOO,GAAa,CAAC,GAG9BT,EAAa,SAASO,GAA2B;AAAA,MACtD,SAASH,EAAU,SAASA,EAAU,SAASA,EAAU,MAAM,QAAQ,KAAK,EAAE;AAAA,MAC9E,MAAM;AAAA,QACJ,MAAOX,EAAUW,EAAU,IAA8B,KAAKA,EAAU;AAAA,QACxE,QAAQ;AAAA,UACN,GAAGT,GAAQ,MAAM;AAAA,UACjB,SAASH,EAAiBY,EAAU,IAAqC,KAAK;AAAA,QAAA;AAAA,QAEhF,GAAIT,GAAQ,QAAQ,CAAA;AAAA,MAAC;AAAA,MAEvB,GAAIA,KAAU,CAAA;AAAA,IAAC,CAChB;AAAA,EACH,CAAC,GAE+C,GAAIO,CAAuB,EAAE,OAA+B,CAACS,GAAKhB,MAAW;AAC7H,UAAMe,IAAWhB,EAAkBC,CAAM;AAEzC,WAAIe,KAAYC,EAAI,KAAK,CAACC,MAAmBlB,EAAkBkB,CAAc,MAAMF,CAAQ,KAI3FC,EAAI,KAAKhB,CAAM,GACRgB;AAAA,EACT,GAAG,CAAA,CAAE,EAEgC,IAAI,CAAChB,GAAQkB,MAAU;AAC1D,UAAMC,IAAOC,EAAiC,CAAC,QAAQpB,EAAO,EAAE,IAAI,QAAQA,EAAO,MAAM,IAAI,IAAI,MAAM,CAAC;AAExG,WAAO;AAAA,MACL,GAAGA;AAAA,MACH,MAAM;AAAA,QACJ,GAAGA,GAAQ;AAAA,QACX,OAAOqB,EAAIrB,GAAQ,cAAckB,IAAQ,EAAE;AAAA,MAAA;AAAA,MAE7C,MAAMlB,EAAO,QAAQmB;AAAA,IAAA;AAAA,EAEzB,CAAC,EAEoB,KAAK,CAACG,GAAGC,MAAOD,EAAE,KAAK,QAAQC,EAAE,KAAK,QAAQ,IAAI,EAAG;AAC5E;"}
|
|
@@ -2,7 +2,7 @@ import { jsx as n } from "react/jsx-runtime";
|
|
|
2
2
|
import { Table as s } from "../../../molecules/table/Table.js";
|
|
3
3
|
import { mapFormToColumns as t } from "../../../molecules/table/utils/mapFormToColumns.js";
|
|
4
4
|
function e({ form: o, ...m }) {
|
|
5
|
-
const r = o && t(o);
|
|
5
|
+
const r = o && t({ form: o });
|
|
6
6
|
return /* @__PURE__ */ n(s, { ...m, columns: r });
|
|
7
7
|
}
|
|
8
8
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubmissionsTable.js","sources":["../../../../src/organisms/table/submissions/SubmissionsTable.tsx"],"sourcesContent":["import type { FormType, SubmissionType } from \"../../../interfaces\";\nimport type { JSONRecord } from \"../../../interfaces/JSONRecord\";\nimport { Table, type TableProps } from \"../../../molecules/table/Table\";\nimport { mapFormToColumns } from \"../../../molecules/table/utils/mapFormToColumns.js\";\n\nexport type SubmissionsTableProps<Data extends object = JSONRecord> = Omit<TableProps<SubmissionType<Data>>, \"columns\"> & {\n form?: FormType;\n};\n\nexport function SubmissionsTable<Data extends object = JSONRecord>({ form, ...props }: SubmissionsTableProps<Data>) {\n const columns: any[] | undefined = form && mapFormToColumns(form);\n\n return <Table {...(props as any)} columns={columns!} />;\n}\n"],"names":["SubmissionsTable","form","props","columns","mapFormToColumns","jsx","Table"],"mappings":";;;AASO,SAASA,EAAmD,EAAE,MAAAC,GAAM,GAAGC,KAAsC;AAClH,QAAMC,IAA6BF,KAAQG,
|
|
1
|
+
{"version":3,"file":"SubmissionsTable.js","sources":["../../../../src/organisms/table/submissions/SubmissionsTable.tsx"],"sourcesContent":["import type { FormType, SubmissionType } from \"../../../interfaces\";\nimport type { JSONRecord } from \"../../../interfaces/JSONRecord\";\nimport { Table, type TableProps } from \"../../../molecules/table/Table\";\nimport { mapFormToColumns } from \"../../../molecules/table/utils/mapFormToColumns.js\";\n\nexport type SubmissionsTableProps<Data extends object = JSONRecord> = Omit<TableProps<SubmissionType<Data>>, \"columns\"> & {\n form?: FormType;\n};\n\nexport function SubmissionsTable<Data extends object = JSONRecord>({ form, ...props }: SubmissionsTableProps<Data>) {\n const columns: any[] | undefined = form && mapFormToColumns({ form: form });\n\n return <Table {...(props as any)} columns={columns!} />;\n}\n"],"names":["SubmissionsTable","form","props","columns","mapFormToColumns","jsx","Table"],"mappings":";;;AASO,SAASA,EAAmD,EAAE,MAAAC,GAAM,GAAGC,KAAsC;AAClH,QAAMC,IAA6BF,KAAQG,EAAiB,EAAE,MAAAH,GAAY;AAE1E,SAAO,gBAAAI,EAACC,GAAA,EAAO,GAAIJ,GAAe,SAAAC,EAAA,CAAmB;AACvD;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsed/react-formio",
|
|
3
|
-
"version": "3.0.0-rc.
|
|
3
|
+
"version": "3.0.0-rc.16",
|
|
4
4
|
"description": "Provide a react formio wrapper. Written in TypeScript.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@tanstack/react-table": ">=8.20.6",
|
|
47
|
-
"@tsed/tailwind-formio": "3.0.0-rc.
|
|
48
|
-
"@tsed/typescript": "3.0.0-rc.
|
|
47
|
+
"@tsed/tailwind-formio": "3.0.0-rc.16",
|
|
48
|
+
"@tsed/typescript": "3.0.0-rc.16",
|
|
49
49
|
"microbundle": "0.13.0",
|
|
50
50
|
"vite": "7.1.5",
|
|
51
51
|
"vitest": "3.2.4"
|
|
@@ -74,7 +74,7 @@ type Story = StoryObj<typeof Table<ProductSubmission>>;
|
|
|
74
74
|
export const Usage: Story = {
|
|
75
75
|
args: {
|
|
76
76
|
data: formSubmissions as unknown as ProductSubmission[],
|
|
77
|
-
columns: mapFormToColumns(FormType as any),
|
|
77
|
+
columns: mapFormToColumns({ form: FormType as any }),
|
|
78
78
|
operations: [
|
|
79
79
|
{
|
|
80
80
|
title: "Edit",
|
|
@@ -183,17 +183,20 @@ export const Usage: Story = {
|
|
|
183
183
|
export const WithFilters: Story = {
|
|
184
184
|
args: {
|
|
185
185
|
data: formSubmissions as unknown as ProductSubmission[],
|
|
186
|
-
columns: mapFormToColumns(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
186
|
+
columns: mapFormToColumns({
|
|
187
|
+
form: FormType as any,
|
|
188
|
+
columns: [
|
|
189
|
+
{
|
|
190
|
+
accessorKey: "data.id",
|
|
191
|
+
meta: {
|
|
192
|
+
filter: {
|
|
193
|
+
variant: "select",
|
|
194
|
+
layout: "react"
|
|
195
|
+
}
|
|
193
196
|
}
|
|
194
197
|
}
|
|
195
|
-
|
|
196
|
-
|
|
198
|
+
]
|
|
199
|
+
}),
|
|
197
200
|
operations: [
|
|
198
201
|
{
|
|
199
202
|
title: "Edit",
|
|
@@ -220,7 +223,7 @@ export const WithFilters: Story = {
|
|
|
220
223
|
export const WithPaginationOptions: Story = {
|
|
221
224
|
args: {
|
|
222
225
|
data: formSubmissions as unknown as ProductSubmission[],
|
|
223
|
-
columns: mapFormToColumns(FormType as any),
|
|
226
|
+
columns: mapFormToColumns({ form: FormType as any }),
|
|
224
227
|
operations: [
|
|
225
228
|
{
|
|
226
229
|
title: "Edit",
|
|
@@ -246,67 +249,70 @@ export const WithPaginationOptions: Story = {
|
|
|
246
249
|
export const WithCustomCell: Story = {
|
|
247
250
|
args: {
|
|
248
251
|
data: formSubmissions as unknown as ProductSubmission[],
|
|
249
|
-
columns: mapFormToColumns<ProductSubmission>(
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
252
|
+
columns: mapFormToColumns<ProductSubmission>({
|
|
253
|
+
form: FormType as any,
|
|
254
|
+
columns: [
|
|
255
|
+
{
|
|
256
|
+
accessorKey: "data.id",
|
|
257
|
+
meta: {
|
|
258
|
+
filter: {
|
|
259
|
+
variant: "select",
|
|
260
|
+
layout: "react"
|
|
261
|
+
},
|
|
262
|
+
cellProps: {
|
|
263
|
+
colSpan: 2
|
|
264
|
+
}
|
|
256
265
|
},
|
|
257
|
-
|
|
258
|
-
|
|
266
|
+
cell: (context) => {
|
|
267
|
+
return (
|
|
268
|
+
<div className='flex space-x-4 align-items-center'>
|
|
269
|
+
<div className='max-w-[80px]'>
|
|
270
|
+
<img className='max-w-[80px] rounded-md' src={context.row.original.data.image} alt={context.row.original.data.label} />
|
|
271
|
+
</div>
|
|
272
|
+
<div>
|
|
273
|
+
<div className='text-lg text-primary'>{context.row.original.data.label}</div>
|
|
274
|
+
<div className='text-xs'>{context.getValue()}</div>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
);
|
|
259
278
|
}
|
|
260
279
|
},
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
<img className='max-w-[80px] rounded-md' src={context.row.original.data.image} alt={context.row.original.data.label} />
|
|
266
|
-
</div>
|
|
267
|
-
<div>
|
|
268
|
-
<div className='text-lg text-primary'>{context.row.original.data.label}</div>
|
|
269
|
-
<div className='text-xs'>{context.getValue()}</div>
|
|
270
|
-
</div>
|
|
271
|
-
</div>
|
|
272
|
-
);
|
|
273
|
-
}
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
accessorKey: "data.label",
|
|
277
|
-
meta: {
|
|
278
|
-
hidden: true
|
|
279
|
-
}
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
accessorKey: "data.description",
|
|
283
|
-
meta: {
|
|
284
|
-
filter: {
|
|
285
|
-
variant: "text",
|
|
286
|
-
disableDatalist: true
|
|
280
|
+
{
|
|
281
|
+
accessorKey: "data.label",
|
|
282
|
+
meta: {
|
|
283
|
+
hidden: true
|
|
287
284
|
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
accessorKey: "data.description",
|
|
288
|
+
meta: {
|
|
289
|
+
filter: {
|
|
290
|
+
variant: "text",
|
|
291
|
+
disableDatalist: true
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
accessorKey: "data.price",
|
|
297
|
+
cell: (context) => {
|
|
298
|
+
const value = context.getValue();
|
|
299
|
+
|
|
300
|
+
if (value === undefined) {
|
|
301
|
+
return "-";
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return (
|
|
305
|
+
<div className='text-right'>
|
|
306
|
+
{Intl.NumberFormat("fr-FR", {
|
|
307
|
+
style: "currency",
|
|
308
|
+
currency: context.row.original.data.currency
|
|
309
|
+
}).format(context.getValue())}
|
|
310
|
+
</div>
|
|
311
|
+
);
|
|
297
312
|
}
|
|
298
|
-
|
|
299
|
-
return (
|
|
300
|
-
<div className='text-right'>
|
|
301
|
-
{Intl.NumberFormat("fr-FR", {
|
|
302
|
-
style: "currency",
|
|
303
|
-
currency: context.row.original.data.currency
|
|
304
|
-
}).format(context.getValue())}
|
|
305
|
-
</div>
|
|
306
|
-
);
|
|
307
313
|
}
|
|
308
|
-
|
|
309
|
-
|
|
314
|
+
]
|
|
315
|
+
}),
|
|
310
316
|
operations: [
|
|
311
317
|
{
|
|
312
318
|
title: "Edit",
|
|
@@ -29,13 +29,13 @@ describe("DefaultCellBoolean", () => {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
it("should render custom labels from column metadata", () => {
|
|
32
|
-
render(<DefaultCellBoolean {...createCellContext(true, { yes: "Enabled",
|
|
32
|
+
render(<DefaultCellBoolean {...createCellContext(true, { yes: "Enabled", no: "Disabled" })} />);
|
|
33
33
|
|
|
34
34
|
expect(screen.getByText("Enabled", { selector: "span" })).toBeInTheDocument();
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
it("should render the custom false label from column metadata", () => {
|
|
38
|
-
render(<DefaultCellBoolean {...createCellContext(false, { yes: "Enabled",
|
|
38
|
+
render(<DefaultCellBoolean {...createCellContext(false, { yes: "Enabled", no: "Disabled" })} />);
|
|
39
39
|
|
|
40
40
|
expect(screen.getByText("Disabled", { selector: "span" })).toBeInTheDocument();
|
|
41
41
|
});
|
|
@@ -4,7 +4,7 @@ import { registerComponent } from "../../../registries/components";
|
|
|
4
4
|
|
|
5
5
|
export function DefaultCellBoolean<Data extends object>({ getValue, column: { columnDef } }: CellContext<Data, boolean>) {
|
|
6
6
|
const value = getValue();
|
|
7
|
-
return <span>{String(value ? columnDef.meta?.labels?.["yes"] || "Yes" : columnDef.meta?.labels?.["
|
|
7
|
+
return <span>{String(value ? columnDef.meta?.labels?.["yes"] || "Yes" : columnDef.meta?.labels?.["no"] || "No")}</span>;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
registerComponent("Cell.boolean", DefaultCellBoolean);
|
|
@@ -8,7 +8,7 @@ import { FilterSelectOptions } from "./Filters";
|
|
|
8
8
|
export function SelectFilter<Data = any>({ header, options }: FilterProps<Data, FilterSelectOptions>) {
|
|
9
9
|
const Select = getComponent<typeof DefaultSelect>("Select");
|
|
10
10
|
const columnFilterValue = header.column.getFilterValue();
|
|
11
|
-
const uniqValues = useUniqValues<Data>({ header
|
|
11
|
+
const uniqValues = useUniqValues<Data>({ header });
|
|
12
12
|
|
|
13
13
|
const opts =
|
|
14
14
|
options.layout === "choicesjs"
|
|
@@ -26,7 +26,7 @@ export function SelectFilter<Data = any>({ header, options }: FilterProps<Data,
|
|
|
26
26
|
value: ""
|
|
27
27
|
}
|
|
28
28
|
] as SelectOptionProps[]
|
|
29
|
-
).concat(options.options || uniqValues
|
|
29
|
+
).concat(options.options || uniqValues);
|
|
30
30
|
|
|
31
31
|
return (
|
|
32
32
|
<>
|
|
@@ -46,3 +46,4 @@ export function SelectFilter<Data = any>({ header, options }: FilterProps<Data,
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
registerComponent("Filter.select", SelectFilter);
|
|
49
|
+
registerComponent("Filter.boolean", SelectFilter);
|
|
@@ -7,7 +7,7 @@ import { FilterTextOptions } from "./Filters";
|
|
|
7
7
|
export function TextFieldFilter<Data = any>({ header, options }: FilterProps<Data, FilterTextOptions>) {
|
|
8
8
|
const InputText = getComponent<typeof DefaultInputText>("InputText");
|
|
9
9
|
const columnFilterValue = header.column.getFilterValue();
|
|
10
|
-
const uniqValues = useUniqValues<Data>({ header
|
|
10
|
+
const uniqValues = useUniqValues<Data>({ header });
|
|
11
11
|
const datalistId = `data_list_${header.column.id}`;
|
|
12
12
|
|
|
13
13
|
return (
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { renderHook } from "@testing-library/react";
|
|
2
|
+
|
|
3
|
+
import { useUniqValues } from "./useUniqValues";
|
|
4
|
+
|
|
5
|
+
function createHeader({ variant, labels, values = [] }: { variant?: string; labels?: Record<string, string>; values?: string[] }) {
|
|
6
|
+
return {
|
|
7
|
+
column: {
|
|
8
|
+
columnDef: {
|
|
9
|
+
meta: {
|
|
10
|
+
filter: {
|
|
11
|
+
variant
|
|
12
|
+
},
|
|
13
|
+
labels
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
getFacetedUniqueValues: () => new Map(values.map((value) => [value, 1]))
|
|
17
|
+
}
|
|
18
|
+
} as any;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe("useUniqValues", () => {
|
|
22
|
+
it("should return boolean options with the custom labels", () => {
|
|
23
|
+
const header = createHeader({
|
|
24
|
+
variant: "boolean",
|
|
25
|
+
labels: {
|
|
26
|
+
yes: "Enabled",
|
|
27
|
+
No: "Disabled"
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const { result } = renderHook(() => useUniqValues({ header }));
|
|
32
|
+
|
|
33
|
+
expect(result.current).toEqual([
|
|
34
|
+
{ label: "Enabled", value: true },
|
|
35
|
+
{ label: "Disabled", value: false }
|
|
36
|
+
]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("should map faceted unique values to select options", () => {
|
|
40
|
+
const header = createHeader({
|
|
41
|
+
values: ["beta", "alpha"]
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const { result } = renderHook(() => useUniqValues({ header }));
|
|
45
|
+
|
|
46
|
+
expect(result.current).toEqual([
|
|
47
|
+
{ label: "alpha", value: "alpha" },
|
|
48
|
+
{ label: "beta", value: "beta" }
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import type { Header } from "@tanstack/react-table";
|
|
2
2
|
import { useMemo } from "react";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
return useMemo(
|
|
6
|
-
() => (filterVariant === "range" ? [] : Array.from(header.column.getFacetedUniqueValues().keys()).flat().sort().slice(0, 5000)),
|
|
4
|
+
import { SelectOptionProps } from "../../../molecules/forms/select/Select.interface";
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
)
|
|
6
|
+
export function useUniqValues<Data = any>({ header }: { header: Header<Data, unknown> }): SelectOptionProps[] {
|
|
7
|
+
return useMemo(() => {
|
|
8
|
+
switch (header.column.columnDef.meta?.filter?.variant) {
|
|
9
|
+
case "boolean":
|
|
10
|
+
return [
|
|
11
|
+
{ label: header.column.columnDef.meta?.labels?.["yes"] || "Yes", value: true },
|
|
12
|
+
{ label: header.column.columnDef.meta?.labels?.["no"] || header.column.columnDef.meta?.labels?.["No"] || "No", value: false }
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
default:
|
|
16
|
+
return Array.from(header.column.getFacetedUniqueValues().keys())
|
|
17
|
+
.flat()
|
|
18
|
+
.sort()
|
|
19
|
+
.slice(0, 5000)
|
|
20
|
+
.map((i) => ({
|
|
21
|
+
label: i,
|
|
22
|
+
value: i
|
|
23
|
+
}));
|
|
24
|
+
}
|
|
25
|
+
}, [header.column]);
|
|
10
26
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { DefaultCellBoolean } from "../components/DefaultBooleanCell";
|
|
1
2
|
import { DefaultCell } from "../components/DefaultCell";
|
|
2
3
|
import { DefaultDateCell } from "../components/DefaultDateCell";
|
|
3
4
|
import { mapFormToColumns } from "./mapFormToColumns";
|
|
4
5
|
|
|
5
6
|
describe("mapFormToColumns", () => {
|
|
6
|
-
it("should use
|
|
7
|
+
it("should use DefaultCellBoolean for mapped checkbox table columns", () => {
|
|
7
8
|
const form = {
|
|
8
9
|
components: [
|
|
9
10
|
{
|
|
@@ -15,12 +16,13 @@ describe("mapFormToColumns", () => {
|
|
|
15
16
|
]
|
|
16
17
|
} as any;
|
|
17
18
|
|
|
18
|
-
const [column] = mapFormToColumns(form) as any[];
|
|
19
|
+
const [column] = mapFormToColumns({ form: form }) as any[];
|
|
19
20
|
|
|
20
21
|
expect(column.accessorKey).toEqual("data.enabled");
|
|
21
22
|
expect(column.header).toEqual("Enabled");
|
|
23
|
+
expect(column.meta.type).toEqual("boolean");
|
|
22
24
|
expect(column.meta.filter.variant).toEqual("boolean");
|
|
23
|
-
expect(column.cell).toBe(
|
|
25
|
+
expect(column.cell).toBe(DefaultCellBoolean);
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
it("should fallback to DefaultCell for kept columns without a cell renderer", () => {
|
|
@@ -28,12 +30,45 @@ describe("mapFormToColumns", () => {
|
|
|
28
30
|
components: []
|
|
29
31
|
} as any;
|
|
30
32
|
|
|
31
|
-
const [column] = mapFormToColumns(form, [{ accessorKey: "data.other", header: "Other" } as any]) as any[];
|
|
33
|
+
const [column] = mapFormToColumns({ form: form, columns: [{ accessorKey: "data.other", header: "Other" } as any] }) as any[];
|
|
32
34
|
|
|
33
35
|
expect(column.accessorKey).toEqual("data.other");
|
|
34
36
|
expect(column.cell).toBe(DefaultCell);
|
|
35
37
|
});
|
|
36
38
|
|
|
39
|
+
it("should merge a kept column matched by component key", () => {
|
|
40
|
+
const form = {
|
|
41
|
+
components: [
|
|
42
|
+
{
|
|
43
|
+
type: "textfield",
|
|
44
|
+
key: "name",
|
|
45
|
+
label: "Name:",
|
|
46
|
+
tableView: true
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
} as any;
|
|
50
|
+
|
|
51
|
+
const [column] = mapFormToColumns({
|
|
52
|
+
form: form,
|
|
53
|
+
columns: [
|
|
54
|
+
{
|
|
55
|
+
id: "name",
|
|
56
|
+
header: "Custom name",
|
|
57
|
+
meta: {
|
|
58
|
+
order: 5,
|
|
59
|
+
filter: {
|
|
60
|
+
variant: "text"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
} as any
|
|
64
|
+
]
|
|
65
|
+
}) as any[];
|
|
66
|
+
|
|
67
|
+
expect(column.accessorKey).toEqual("data.name");
|
|
68
|
+
expect(column.header).toEqual("Custom name");
|
|
69
|
+
expect(column.meta.order).toEqual(5);
|
|
70
|
+
});
|
|
71
|
+
|
|
37
72
|
it("should use DefaultDateCell for mapped datetime columns", () => {
|
|
38
73
|
const form = {
|
|
39
74
|
components: [
|
|
@@ -46,10 +81,36 @@ describe("mapFormToColumns", () => {
|
|
|
46
81
|
]
|
|
47
82
|
} as any;
|
|
48
83
|
|
|
49
|
-
const [column] = mapFormToColumns(form) as any[];
|
|
84
|
+
const [column] = mapFormToColumns({ form: form }) as any[];
|
|
50
85
|
|
|
51
86
|
expect(column.accessorKey).toEqual("data.createdAt");
|
|
52
87
|
expect(column.meta.type).toEqual("date");
|
|
53
88
|
expect(column.cell).toBe(DefaultDateCell);
|
|
54
89
|
});
|
|
90
|
+
|
|
91
|
+
it("should dedupe columns when a kept column matches a mapped accessor key", () => {
|
|
92
|
+
const form = {
|
|
93
|
+
components: [
|
|
94
|
+
{
|
|
95
|
+
type: "textfield",
|
|
96
|
+
key: "email",
|
|
97
|
+
label: "Email:",
|
|
98
|
+
tableView: true
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
} as any;
|
|
102
|
+
|
|
103
|
+
const columns = mapFormToColumns({
|
|
104
|
+
form: form,
|
|
105
|
+
columns: [
|
|
106
|
+
{
|
|
107
|
+
accessorKey: "data.email",
|
|
108
|
+
header: "Email"
|
|
109
|
+
} as any
|
|
110
|
+
]
|
|
111
|
+
}) as any[];
|
|
112
|
+
|
|
113
|
+
expect(columns).toHaveLength(1);
|
|
114
|
+
expect(columns[0].accessorKey).toEqual("data.email");
|
|
115
|
+
});
|
|
55
116
|
});
|
|
@@ -23,7 +23,27 @@ const MAP_TYPES = {
|
|
|
23
23
|
checkbox: "boolean"
|
|
24
24
|
} as const;
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
function getColumnIdentity<Data>(column: ColumnDef<Data, any> | ColumnDefResolved<Data, any>) {
|
|
27
|
+
if ("id" in column && typeof column.id === "string") {
|
|
28
|
+
return column.id;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if ("accessorKey" in column && typeof column.accessorKey === "string") {
|
|
32
|
+
return column.accessorKey;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function mapFormToColumns<Data = any>({
|
|
39
|
+
form,
|
|
40
|
+
columns = [],
|
|
41
|
+
prefix = "data."
|
|
42
|
+
}: {
|
|
43
|
+
form: FormType;
|
|
44
|
+
columns?: ColumnDefResolved<Data, any>[];
|
|
45
|
+
prefix?: string;
|
|
46
|
+
}): ColumnDef<Data, any>[] {
|
|
27
47
|
const columnHelper = createColumnHelper<Data>();
|
|
28
48
|
const columnsToKeep = cloneDeep(columns);
|
|
29
49
|
|
|
@@ -38,9 +58,13 @@ export function mapFormToColumns<Data = any>(form: FormType, columns: ColumnDefR
|
|
|
38
58
|
.filter((component) => component?.tableView)
|
|
39
59
|
.map((c) => {
|
|
40
60
|
const component = c as ComponentType;
|
|
61
|
+
const componentColumnKey = `${prefix}${component.key}`;
|
|
62
|
+
const matchingKeys = new Set([component.key, componentColumnKey]);
|
|
41
63
|
|
|
42
|
-
const columnIndex = columnsToKeep.findIndex((
|
|
43
|
-
|
|
64
|
+
const columnIndex = columnsToKeep.findIndex((column) => {
|
|
65
|
+
const identity = getColumnIdentity(column);
|
|
66
|
+
|
|
67
|
+
return identity ? matchingKeys.has(identity) : false;
|
|
44
68
|
});
|
|
45
69
|
|
|
46
70
|
let column = columnsToKeep[columnIndex];
|
|
@@ -49,13 +73,13 @@ export function mapFormToColumns<Data = any>(form: FormType, columns: ColumnDefR
|
|
|
49
73
|
columnsToKeep.splice(columnIndex, 1);
|
|
50
74
|
}
|
|
51
75
|
|
|
52
|
-
return columnHelper.accessor(
|
|
76
|
+
return columnHelper.accessor(componentColumnKey as any, {
|
|
53
77
|
header: (component.label || component.title || component.key)?.replace(/:/, ""),
|
|
54
78
|
meta: {
|
|
55
|
-
type: MAP_TYPES[component.type as keyof typeof MAP_TYPES] || component.type,
|
|
79
|
+
type: (MAP_TYPES[component.type as keyof typeof MAP_TYPES] || component.type) as any,
|
|
56
80
|
filter: {
|
|
57
81
|
...column?.meta?.filter,
|
|
58
|
-
variant: MAP_FILTER_TYPES[component.type
|
|
82
|
+
variant: MAP_FILTER_TYPES[component.type as keyof typeof MAP_FILTER_TYPES] || "text"
|
|
59
83
|
},
|
|
60
84
|
...(column?.meta || {})
|
|
61
85
|
},
|
|
@@ -63,7 +87,18 @@ export function mapFormToColumns<Data = any>(form: FormType, columns: ColumnDefR
|
|
|
63
87
|
});
|
|
64
88
|
});
|
|
65
89
|
|
|
66
|
-
const
|
|
90
|
+
const dedupedColumns = [...columnsFromComponents, ...(columnsToKeep as any[])].reduce<ColumnDef<Data, any>[]>((acc, column) => {
|
|
91
|
+
const identity = getColumnIdentity(column);
|
|
92
|
+
|
|
93
|
+
if (identity && acc.some((existingColumn) => getColumnIdentity(existingColumn) === identity)) {
|
|
94
|
+
return acc;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
acc.push(column);
|
|
98
|
+
return acc;
|
|
99
|
+
}, []);
|
|
100
|
+
|
|
101
|
+
const mergedColumns = dedupedColumns.map((column, index) => {
|
|
67
102
|
const Cell = getComponent<typeof DefaultCell>([`Cell.${column.id}`, `Cell.${column.meta?.type}`, "Cell"]);
|
|
68
103
|
|
|
69
104
|
return {
|
|
@@ -8,7 +8,7 @@ export type SubmissionsTableProps<Data extends object = JSONRecord> = Omit<Table
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
export function SubmissionsTable<Data extends object = JSONRecord>({ form, ...props }: SubmissionsTableProps<Data>) {
|
|
11
|
-
const columns: any[] | undefined = form && mapFormToColumns(form);
|
|
11
|
+
const columns: any[] | undefined = form && mapFormToColumns({ form: form });
|
|
12
12
|
|
|
13
13
|
return <Table {...(props as any)} columns={columns!} />;
|
|
14
14
|
}
|