@faasjs/ant-design 8.0.0-beta.28 → 8.0.0-beta.29

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/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  - [Blank](functions/Blank.md)
7
7
  - [cloneUnionFaasItemElement](functions/cloneUnionFaasItemElement.md)
8
8
  - [ConfigProvider](functions/ConfigProvider.md)
9
+ - [createOnErrorHandler](functions/createOnErrorHandler.md)
9
10
  - [Description](functions/Description.md)
10
11
  - [ErrorBoundary](functions/ErrorBoundary.md)
11
12
  - [faas](functions/faas.md)
@@ -17,6 +18,7 @@
17
18
  - [Link](functions/Link.md)
18
19
  - [Loading](functions/Loading.md)
19
20
  - [PageNotFound](functions/PageNotFound.md)
21
+ - [renderDisplayValue](functions/renderDisplayValue.md)
20
22
  - [Routes](functions/Routes.md)
21
23
  - [Table](functions/Table.md)
22
24
  - [Tabs](functions/Tabs.md)
package/dist/index.d.ts CHANGED
@@ -486,6 +486,9 @@ interface AppProps {
486
486
  */
487
487
  faasConfigProviderProps?: Omit<ConfigProviderProps, 'children'> | false;
488
488
  }
489
+ declare function createOnErrorHandler(messageApi: {
490
+ error: (message: string) => void;
491
+ }): (action: string) => (res: any) => Promise<void>;
489
492
  /**
490
493
  * Render the root provider shell for a FaasJS Ant Design application.
491
494
  *
@@ -655,7 +658,7 @@ declare namespace FormItem {
655
658
  };
656
659
  }
657
660
  //#endregion
658
- //#region src/Table/index.d.ts
661
+ //#region src/Table/types.d.ts
659
662
  /**
660
663
  * Column definition used by the FaasJS Ant Design {@link Table} component.
661
664
  *
@@ -739,6 +742,8 @@ type TableFaasDataResponse<T = any> = {
739
742
  total: number;
740
743
  };
741
744
  };
745
+ //#endregion
746
+ //#region src/Table/table.d.ts
742
747
  /**
743
748
  * Render an Ant Design table from FaasJS item metadata.
744
749
  *
@@ -776,6 +781,12 @@ type TableFaasDataResponse<T = any> = {
776
781
  */
777
782
  declare function Table<T extends Record<string, any>, ExtendTypes = any>(props: TableProps<T, ExtendTypes>): _$react_jsx_runtime0.JSX.Element;
778
783
  //#endregion
784
+ //#region src/data/render.d.ts
785
+ declare function renderDisplayValue(type: FaasItemType, value: any, options?: {
786
+ label: string;
787
+ value?: string | number;
788
+ }[]): JSX.Element | string | number | boolean | null;
789
+ //#endregion
779
790
  //#region src/data/index.d.ts
780
791
  /**
781
792
  * Supported built-in field types shared by form, table, and description components.
@@ -1562,4 +1573,4 @@ declare function useApp<NewT extends useAppProps = useAppProps>(this: void): Rea
1562
1573
  */
1563
1574
  declare function useThemeToken(): GlobalToken;
1564
1575
  //#endregion
1565
- export { App, AppContext, AppProps, BaseItemProps, BaseOption, Blank, BlankProps, ConfigContext, ConfigProvider, ConfigProviderProps, Description, DescriptionItemContentProps, DescriptionItemProps, DescriptionProps, Drawer, DrawerProps, ErrorBoundary, type ErrorBoundaryProps, ExtendDescriptionItemProps, ExtendDescriptionTypeProps, type ExtendFormItemProps, type ExtendFormTypeProps, ExtendTableItemProps, ExtendTableTypeProps, ExtendTypes, FaasDataInjection, FaasDataWrapper, FaasDataWrapperProps, type FaasDataWrapperRef, FaasItemProps, FaasItemType, FaasItemTypeValue, FaasReactClient, type FaasReactClientOptions, Form, FormFaasProps, FormItem, FormItemProps, FormProps, FormSubmitProps, Link, LinkProps, Loading, LoadingProps, Modal, ModalProps, PageNotFound, ResolvedTheme, Routes, RoutesProps, TabProps, Table, TableFaasDataParams, TableFaasDataResponse, TableItemProps, TableProps, Tabs, TabsProps, Title, TitleProps, UnionFaasItemElement, UnionFaasItemInjection, UnionFaasItemProps, UnionFaasItemRender, UnionScene, cloneUnionFaasItemElement, faas, idToTitle, lazy, setDrawerProps, setModalProps, transferOptions, transferValue, useApp, useAppProps, useConfigContext, useDrawer, useFaas, useModal, useThemeToken, withFaasData };
1576
+ export { App, AppContext, AppProps, BaseItemProps, BaseOption, Blank, BlankProps, ConfigContext, ConfigProvider, ConfigProviderProps, Description, DescriptionItemContentProps, DescriptionItemProps, DescriptionProps, Drawer, DrawerProps, ErrorBoundary, type ErrorBoundaryProps, ExtendDescriptionItemProps, ExtendDescriptionTypeProps, type ExtendFormItemProps, type ExtendFormTypeProps, type ExtendTableItemProps, type ExtendTableTypeProps, ExtendTypes, FaasDataInjection, FaasDataWrapper, FaasDataWrapperProps, type FaasDataWrapperRef, FaasItemProps, FaasItemType, FaasItemTypeValue, FaasReactClient, type FaasReactClientOptions, Form, FormFaasProps, FormItem, FormItemProps, FormProps, FormSubmitProps, Link, LinkProps, Loading, LoadingProps, Modal, ModalProps, PageNotFound, ResolvedTheme, Routes, RoutesProps, TabProps, Table, type TableFaasDataParams, type TableFaasDataResponse, type TableItemProps, type TableProps, Tabs, TabsProps, Title, TitleProps, UnionFaasItemElement, UnionFaasItemInjection, UnionFaasItemProps, UnionFaasItemRender, UnionScene, cloneUnionFaasItemElement, createOnErrorHandler, faas, idToTitle, lazy, renderDisplayValue, setDrawerProps, setModalProps, transferOptions, transferValue, useApp, useAppProps, useConfigContext, useDrawer, useFaas, useModal, useThemeToken, withFaasData };
package/dist/index.mjs CHANGED
@@ -4,8 +4,8 @@ import { BrowserRouter, Route, Routes as Routes$1, useLocation, useNavigate } fr
4
4
  import { cloneDeep, defaultsDeep, isNil, uniqBy } from "lodash-es";
5
5
  import { Suspense, cloneElement, createContext, createElement, isValidElement, lazy, useContext, useState } from "react";
6
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
- import { CheckOutlined, CloseOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
8
7
  import dayjs from "dayjs";
8
+ import { CheckOutlined, CloseOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
9
9
  //#region src/Loading/index.tsx
10
10
  /**
11
11
  * Render an Ant Design loading spinner with an optional content fallback.
@@ -523,6 +523,13 @@ function useApp() {
523
523
  }
524
524
  //#endregion
525
525
  //#region src/App/index.tsx
526
+ function createOnErrorHandler(messageApi) {
527
+ return (action) => async (res) => {
528
+ if ("message" in res && res.toString().includes("AbortError")) return;
529
+ console.error(`[FaasJS][${action}]`, res);
530
+ messageApi.error("message" in res ? res.message : "Unknown error");
531
+ };
532
+ }
526
533
  function RoutesApp(props) {
527
534
  const location = useLocation();
528
535
  const { drawerProps, setDrawerProps, modalProps, setModalProps } = useApp();
@@ -580,11 +587,7 @@ function App(props) {
580
587
  children: /* @__PURE__ */ jsx(ConfigProvider, {
581
588
  ...props.faasConfigProviderProps,
582
589
  faasClientOptions: {
583
- onError: (action) => async (res) => {
584
- if ("message" in res && res.toString().includes("AbortError")) return;
585
- console.error(`[FaasJS][${action}]`, res);
586
- messageApi.error("message" in res ? res.message : "Unknown error");
587
- },
590
+ onError: createOnErrorHandler(messageApi),
588
591
  ...props.faasConfigProviderProps ? props.faasConfigProviderProps.faasClientOptions : {}
589
592
  },
590
593
  children: /* @__PURE__ */ jsx(ErrorBoundary, {
@@ -633,6 +636,44 @@ function Blank(options) {
633
636
  }) : options.value;
634
637
  }
635
638
  //#endregion
639
+ //#region src/data/render.tsx
640
+ function renderBooleanIcon(value) {
641
+ return value ? /* @__PURE__ */ jsx(CheckOutlined, { style: {
642
+ marginTop: "4px",
643
+ color: "#52c41a"
644
+ } }) : /* @__PURE__ */ jsx(CloseOutlined, { style: {
645
+ marginTop: "4px",
646
+ color: "#ff4d4f"
647
+ } });
648
+ }
649
+ function formatDateValue(value, type) {
650
+ return value.format(type === "date" ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm:ss");
651
+ }
652
+ function resolveOptionLabel(value, options) {
653
+ if (!options?.length) return value;
654
+ for (const option of options) if (option.value === value) return option.label ?? value;
655
+ return value;
656
+ }
657
+ function renderDisplayValue(type, value, options) {
658
+ if (value === null || value === void 0 || Array.isArray(value) && value.length === 0) return /* @__PURE__ */ jsx(Blank, {});
659
+ if (options?.length) {
660
+ if (type.endsWith("[]")) return /* @__PURE__ */ jsx(Fragment, { children: value.map((v) => resolveOptionLabel(v, options)).join(", ") });
661
+ if ([
662
+ "string",
663
+ "number",
664
+ "boolean"
665
+ ].includes(type)) return /* @__PURE__ */ jsx(Fragment, { children: resolveOptionLabel(value, options) });
666
+ }
667
+ switch (type) {
668
+ case "string[]":
669
+ case "number[]": return /* @__PURE__ */ jsx(Fragment, { children: value.join(", ") });
670
+ case "boolean": return renderBooleanIcon(value);
671
+ case "time": return /* @__PURE__ */ jsx(Fragment, { children: formatDateValue(value, "time") });
672
+ case "date": return /* @__PURE__ */ jsx(Fragment, { children: formatDateValue(value, "date") });
673
+ default: return value;
674
+ }
675
+ }
676
+ //#endregion
636
677
  //#region src/data/index.ts
637
678
  /**
638
679
  * Convert a snake_case, kebab-case, or spaced identifier into a title-style label.
@@ -749,78 +790,50 @@ function cloneUnionFaasItemElement(element, props) {
749
790
  //#endregion
750
791
  //#region src/Description/index.tsx
751
792
  function DescriptionItemContent(props) {
752
- const [computedProps, setComputedProps] = useState();
753
- useEqualEffect(() => {
754
- const propsCopy = { ...props };
755
- propsCopy.item.title = propsCopy.item.title ?? idToTitle(propsCopy.item.id);
756
- if (!propsCopy.item.type) propsCopy.item.type = "string";
757
- if (propsCopy.item.options?.length) propsCopy.item.options = transferOptions(propsCopy.item.options);
758
- propsCopy.value = transferValue(propsCopy.item.type, propsCopy.value);
759
- if (propsCopy.item.options && propsCopy.value !== null) {
760
- if (propsCopy.item.type.endsWith("[]")) propsCopy.value = propsCopy.value.map((v) => propsCopy.item.options.find((option) => option.value === v)?.label || v);
761
- else if ([
762
- "string",
763
- "number",
764
- "boolean"
765
- ].includes(propsCopy.item.type)) propsCopy.value = props.item.options.find((option) => option.value === props.value)?.label || props.value;
766
- }
767
- setComputedProps(propsCopy);
768
- }, [props]);
769
- if (!computedProps) return null;
770
- const itemType = computedProps.item.type ?? "string";
771
- if (computedProps.item.descriptionChildren === null || computedProps.item.children === null || computedProps.item.descriptionRender === null || computedProps.item.render === null) return null;
772
- const children = computedProps.item.descriptionChildren || computedProps.item.children;
793
+ const { item, value: rawValue, values, extendTypes } = props;
794
+ const type = item.type ?? "string";
795
+ const options = item.options?.length ? transferOptions(item.options) : void 0;
796
+ const value = transferValue(type, rawValue);
797
+ if (item.descriptionChildren === null || item.children === null || item.descriptionRender === null || item.render === null) return null;
798
+ const children = item.descriptionChildren || item.children;
773
799
  if (children) return cloneUnionFaasItemElement(children, {
774
800
  scene: "description",
775
- value: computedProps.value,
776
- values: computedProps.values,
801
+ value,
802
+ values,
777
803
  index: 0
778
804
  });
779
- const render = computedProps.item.descriptionRender || computedProps.item.render;
780
- if (render) return /* @__PURE__ */ jsx(Fragment, { children: render(computedProps.value, computedProps.values, 0, "description") });
781
- if (computedProps.extendTypes?.[itemType]) {
782
- const extendType = computedProps.extendTypes[itemType];
805
+ const render = item.descriptionRender || item.render;
806
+ if (render) return /* @__PURE__ */ jsx(Fragment, { children: render(value, values, 0, "description") });
807
+ if (extendTypes?.[type]) {
808
+ const extendType = extendTypes[type];
783
809
  if (extendType.children) return cloneUnionFaasItemElement(extendType.children, {
784
810
  scene: "description",
785
- value: computedProps.value,
786
- values: computedProps.values
811
+ value,
812
+ values
787
813
  });
788
- if (extendType.render) return /* @__PURE__ */ jsx(Fragment, { children: extendType.render(computedProps.value, computedProps.values, 0, "description") });
789
- throw Error(`${itemType} requires children or render`);
814
+ if (extendType.render) return /* @__PURE__ */ jsx(Fragment, { children: extendType.render(value, values, 0, "description") });
815
+ throw Error(`${type} requires children or render`);
790
816
  }
791
- if (computedProps.value === null || Array.isArray(computedProps.value) && !computedProps.value.length) return /* @__PURE__ */ jsx(Blank, {});
792
- switch (itemType) {
793
- case "string[]": return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.join(", ") });
794
- case "number": return computedProps.value || null;
795
- case "number[]": return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.join(", ") });
796
- case "boolean": return computedProps.value ? /* @__PURE__ */ jsx(CheckOutlined, { style: {
797
- marginTop: "4px",
798
- color: "#52c41a"
799
- } }) : /* @__PURE__ */ jsx(CloseOutlined, { style: {
800
- marginTop: "4px",
801
- color: "#ff4d4f"
802
- } });
803
- case "time": return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.format("YYYY-MM-DD HH:mm:ss") });
804
- case "date": return /* @__PURE__ */ jsx(Fragment, { children: computedProps.value.format("YYYY-MM-DD") });
805
- case "object":
806
- if (!computedProps.value) return /* @__PURE__ */ jsx(Blank, {});
807
- return /* @__PURE__ */ jsx(Description, {
808
- items: computedProps.item.object || [],
809
- dataSource: computedProps.value,
817
+ if (type === "object") {
818
+ if (!value) return /* @__PURE__ */ jsx(Blank, {});
819
+ return /* @__PURE__ */ jsx(Description, {
820
+ items: item.object || [],
821
+ dataSource: value,
822
+ column: 1
823
+ });
824
+ }
825
+ if (type === "object[]") {
826
+ if (!value?.length) return /* @__PURE__ */ jsx(Blank, {});
827
+ return /* @__PURE__ */ jsx(Space, {
828
+ direction: "vertical",
829
+ children: value.map((v, index) => /* @__PURE__ */ jsx(Description, {
830
+ items: item.object || [],
831
+ dataSource: v,
810
832
  column: 1
811
- });
812
- case "object[]":
813
- if (!computedProps.value?.length) return /* @__PURE__ */ jsx(Blank, {});
814
- return /* @__PURE__ */ jsx(Space, {
815
- direction: "vertical",
816
- children: computedProps.value.map((value, index) => /* @__PURE__ */ jsx(Description, {
817
- items: computedProps.item.object || [],
818
- dataSource: value,
819
- column: 1
820
- }, index))
821
- });
822
- default: return computedProps.value || null;
833
+ }, index))
834
+ });
823
835
  }
836
+ return /* @__PURE__ */ jsx(Fragment, { children: renderDisplayValue(type, value, options) });
824
837
  }
825
838
  DescriptionItemContent.displayName = "DescriptionItemContent";
826
839
  /**
@@ -1544,22 +1557,10 @@ function Routes(props) {
1544
1557
  }, "*")] });
1545
1558
  }
1546
1559
  //#endregion
1547
- //#region src/Table/index.tsx
1560
+ //#region src/Table/utils.tsx
1548
1561
  function processValue(item, value) {
1549
1562
  const itemType = item.type ?? "string";
1550
- const transferred = transferValue(itemType, value);
1551
- if (transferred === null || Array.isArray(transferred) && transferred.length === 0) return /* @__PURE__ */ jsx(Blank, {});
1552
- if (item.options) {
1553
- if (itemType.endsWith("[]")) return transferred.map((v) => item.options.find((option) => option.value === v)?.label || v).join(", ");
1554
- if ([
1555
- "string",
1556
- "number",
1557
- "boolean"
1558
- ].includes(itemType)) return item.options.find((option) => option.value === transferred)?.label || transferred;
1559
- }
1560
- if (itemType.endsWith("[]")) return transferred.join(", ");
1561
- if (["date", "time"].includes(itemType)) return transferred.format(itemType === "date" ? "YYYY-MM-DD" : "YYYY-MM-DD HH:mm:ss");
1562
- return transferred;
1563
+ return renderDisplayValue(itemType, transferValue(itemType, value), item.options);
1563
1564
  }
1564
1565
  function toTableFilters(options, includeBlank = false) {
1565
1566
  const filters = options.map((option) => ({
@@ -1620,6 +1621,23 @@ function createTextSearchFilterDropdown(item, search, transformValue) {
1620
1621
  }
1621
1622
  });
1622
1623
  }
1624
+ function applyFaasDataColumnOptions(columns, data) {
1625
+ if (!data?.options) return columns;
1626
+ let updated = false;
1627
+ const nextColumns = columns.map((column) => {
1628
+ if (!data.options?.[column.id]) return column;
1629
+ updated = true;
1630
+ const nextColumn = { ...column };
1631
+ nextColumn.options = transferOptions(data.options[column.id]);
1632
+ nextColumn.filters = toTableFilters(nextColumn.options, true);
1633
+ nextColumn.render = (value) => processValue(nextColumn, value);
1634
+ if (nextColumn.filterDropdown) delete nextColumn.filterDropdown;
1635
+ return nextColumn;
1636
+ });
1637
+ return updated ? nextColumns : columns;
1638
+ }
1639
+ //#endregion
1640
+ //#region src/Table/column-builder.tsx
1623
1641
  function createTableColumns(items, options) {
1624
1642
  const columns = cloneDeep(items).filter((item) => !(item.tableChildren === null || item.children === null || item.tableRender === null || item.render === null));
1625
1643
  for (const item of columns) {
@@ -1714,13 +1732,7 @@ function createTableColumns(items, options) {
1714
1732
  }
1715
1733
  break;
1716
1734
  case "boolean":
1717
- if (!item.render) item.render = (value) => isNil(value) ? /* @__PURE__ */ jsx(Blank, {}) : value ? /* @__PURE__ */ jsx(CheckOutlined, { style: {
1718
- marginTop: "4px",
1719
- color: "#52c41a"
1720
- } }) : /* @__PURE__ */ jsx(CloseOutlined, { style: {
1721
- marginTop: "4px",
1722
- color: "#ff4d4f"
1723
- } });
1735
+ if (!item.render) item.render = (value) => renderDisplayValue("boolean", value);
1724
1736
  if (item.filterDropdown !== false) {
1725
1737
  if (typeof item.filterDropdown === "undefined") item.filterDropdown = ({ setSelectedKeys, selectedKeys, confirm: confirmFilter }) => /* @__PURE__ */ jsxs(Radio.Group, {
1726
1738
  style: { padding: 8 },
@@ -1824,21 +1836,8 @@ function createTableColumns(items, options) {
1824
1836
  }
1825
1837
  return columns;
1826
1838
  }
1827
- function applyFaasDataColumnOptions(columns, data) {
1828
- if (!data?.options) return columns;
1829
- let updated = false;
1830
- const nextColumns = columns.map((column) => {
1831
- if (!data.options?.[column.id]) return column;
1832
- updated = true;
1833
- const nextColumn = { ...column };
1834
- nextColumn.options = transferOptions(data.options[column.id]);
1835
- nextColumn.filters = toTableFilters(nextColumn.options, true);
1836
- nextColumn.render = (value) => processValue(nextColumn, value);
1837
- if (nextColumn.filterDropdown) delete nextColumn.filterDropdown;
1838
- return nextColumn;
1839
- });
1840
- return updated ? nextColumns : columns;
1841
- }
1839
+ //#endregion
1840
+ //#region src/Table/table.tsx
1842
1841
  /**
1843
1842
  * Render an Ant Design table from FaasJS item metadata.
1844
1843
  *
@@ -2052,4 +2051,4 @@ function useThemeToken() {
2052
2051
  return theme.useToken().token;
2053
2052
  }
2054
2053
  //#endregion
2055
- export { App, AppContext, Blank, ConfigContext, ConfigProvider, Description, Drawer, ErrorBoundary, FaasDataWrapper, FaasReactClient, Form, FormItem, Link, Loading, Modal, PageNotFound, Routes, Table, Tabs, Title, cloneUnionFaasItemElement, faas, idToTitle, lazy, transferOptions, transferValue, useApp, useConfigContext, useDrawer, useFaas, useModal, useThemeToken, withFaasData };
2054
+ export { App, AppContext, Blank, ConfigContext, ConfigProvider, Description, Drawer, ErrorBoundary, FaasDataWrapper, FaasReactClient, Form, FormItem, Link, Loading, Modal, PageNotFound, Routes, Table, Tabs, Title, cloneUnionFaasItemElement, createOnErrorHandler, faas, idToTitle, lazy, renderDisplayValue, transferOptions, transferValue, useApp, useConfigContext, useDrawer, useFaas, useModal, useThemeToken, withFaasData };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faasjs/ant-design",
3
- "version": "8.0.0-beta.28",
3
+ "version": "8.0.0-beta.29",
4
4
  "homepage": "https://faasjs.com/doc/ant-design",
5
5
  "bugs": {
6
6
  "url": "https://github.com/faasjs/faasjs/issues"
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "devDependencies": {
29
29
  "@ant-design/icons": "*",
30
- "@faasjs/react": ">=8.0.0-beta.28",
30
+ "@faasjs/react": ">=8.0.0-beta.29",
31
31
  "@types/lodash-es": "*",
32
32
  "@types/react": "^19.0.0",
33
33
  "@types/react-dom": "^19.0.0",
@@ -39,7 +39,7 @@
39
39
  },
40
40
  "peerDependencies": {
41
41
  "@ant-design/icons": "*",
42
- "@faasjs/react": ">=8.0.0-beta.28",
42
+ "@faasjs/react": ">=8.0.0-beta.29",
43
43
  "antd": "^6.0.0",
44
44
  "lodash-es": "*",
45
45
  "react": "^19.0.0",
@@ -47,7 +47,7 @@
47
47
  "react-router-dom": "*"
48
48
  },
49
49
  "engines": {
50
- "node": ">=24.0.0",
50
+ "node": ">=26.0.0",
51
51
  "npm": ">=11.0.0"
52
52
  }
53
53
  }