@wordrhyme/auto-crud 1.11.0 → 1.11.1

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
@@ -673,10 +673,22 @@ table={{
673
673
 
674
674
  ## 🔧 工具栏操作配置
675
675
 
676
- `toolbar` 数组控制页面顶部右侧工具栏的按钮,设计思路完全对齐行操作 `actions`。旧 prop `toolbarActions` 仍兼容读取,但新代码请使用 `toolbar`。
676
+ `toolbar` 数组控制工具栏操作,设计思路完全对齐行操作 `actions`。旧 prop `toolbarActions` 仍兼容读取,但新代码请使用 `toolbar`。
677
677
 
678
678
  内置操作类型:`refresh`(刷新)、`create`(新建)、`import`(导入)、`export`(导出)。
679
679
 
680
+ 刷新固定显示在搜索筛选行右侧,顺序为 `[排序] [刷新] [列设置]`;其 `label`、`onClick`、`component` 和隐藏配置仍由 `toolbar` 控制。其余操作保留在上方工具栏,没有可见操作时不占空行。
681
+
682
+ 直接使用 `AutoTable` 时,可通过 `toolbarExtra` 插入排序与列设置之间的控件:
683
+
684
+ ```tsx
685
+ <AutoTable
686
+ schema={schema}
687
+ data={rows}
688
+ toolbarExtra={<Button onClick={refresh}>刷新</Button>}
689
+ />
690
+ ```
691
+
680
692
  ### 只添加自定义按钮(内置保持默认)
681
693
 
682
694
  只传 `type: "custom"` 项时,所有内置按钮(刷新、导入、导出、新建)保持原样,custom 项按 `position` 插入首部或尾部。
@@ -692,12 +704,13 @@ table={{
692
704
  { type: 'custom', component: <Button variant="outline">批量标签</Button> }, // 默认 position: "end"
693
705
  ]}
694
706
  />
695
- // 渲染顺序: 分类管理 · [刷新] · [导入] · [导出] · [新建] · 批量标签
707
+ // 上方工具栏: 分类管理 · [导入] · [导出] · [新建] · 批量标签
708
+ // 搜索筛选行右侧: [排序] · [刷新] · [列设置]
696
709
  ```
697
710
 
698
711
  ### 调整内置按钮顺序
699
712
 
700
- 数组中只要包含任意内置 `type`,就会**完全接管工具栏** —— 未列出的内置按钮**直接隐藏**,渲染顺序**严格按数组**。
713
+ 数组中只要包含任意内置 `type`,就会**完全接管工具栏** —— 未列出的内置按钮**直接隐藏**。刷新保持在搜索筛选行,其他按钮的渲染顺序**严格按数组**。
701
714
 
702
715
  ```tsx
703
716
  <AutoCrudTable
package/dist/index.cjs CHANGED
@@ -4430,7 +4430,7 @@ const filterModeConfig = {
4430
4430
  tooltip: "Linear-style command filters"
4431
4431
  }
4432
4432
  };
4433
- function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = false, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, exclude, filterOnly, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
4433
+ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = false, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, exclude, filterOnly, actions, pinnedColumns, filterMode, search = false, toolbarExtra, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
4434
4434
  if (expandedRow && !getRowId) throw new Error("AutoTable requires getRowId when expandedRow is provided.");
4435
4435
  const enableExpansion = !!expandedRow;
4436
4436
  const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
@@ -4649,6 +4649,7 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
4649
4649
  table,
4650
4650
  align: "end"
4651
4651
  }),
4652
+ toolbarExtra,
4652
4653
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableViewOptions, {
4653
4654
  table,
4654
4655
  align: "end"
@@ -7766,6 +7767,60 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7766
7767
  rowActionDefaults,
7767
7768
  openComponent
7768
7769
  ]);
7770
+ const normalizedToolbarActions = resolvedToolbarActions.length > 0 ? resolveOwnerToolbarActions(resolvedToolbarActions) : [];
7771
+ const renderBuiltinButton = (type, overrides) => {
7772
+ if (type === "refresh") {
7773
+ const onRefresh = overrides?.onClick ?? toolbarRefresh;
7774
+ const label = overrides?.label ?? locale.toolbar.refresh;
7775
+ if (!onRefresh) return null;
7776
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Button, {
7777
+ variant: "outline",
7778
+ size: "icon-sm",
7779
+ "aria-label": label,
7780
+ title: label,
7781
+ onClick: onRefresh,
7782
+ disabled: resource.tableData.isFetching,
7783
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.RefreshCw, { className: resource.tableData.isFetching ? "h-4 w-4 animate-spin" : "h-4 w-4" })
7784
+ }, "refresh");
7785
+ }
7786
+ if (type === "import" && canImport) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Button, {
7787
+ variant: "outline",
7788
+ size: "sm",
7789
+ onClick: overrides?.onClick ?? toolbarOpenImport,
7790
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Download, { className: "mr-2 h-4 w-4" }), overrides?.label ?? locale.toolbar.import]
7791
+ }, "import");
7792
+ if (type === "export" && canExport) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Button, {
7793
+ variant: "outline",
7794
+ size: "sm",
7795
+ onClick: overrides?.onClick ?? toolbarExportData,
7796
+ disabled: exporting || selectedCount === 0 && !resource.handlers.export,
7797
+ children: [exporting ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Upload, { className: "mr-2 h-4 w-4" }), overrides?.label ?? (selectedCount > 0 ? locale.toolbar.exportSelected(selectedCount) : locale.toolbar.export)]
7798
+ }, "export");
7799
+ if (type === "create" && can.create) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Button, {
7800
+ onClick: overrides?.onClick ?? toolbarOpenCreate,
7801
+ children: overrides?.label ?? locale.toolbar.create
7802
+ }, "create");
7803
+ return null;
7804
+ };
7805
+ const renderToolbarComponent = (component) => typeof component === "function" ? component(toolbarContext) : component;
7806
+ const renderToolbarAction = (action$1, index$1) => {
7807
+ if (action$1.type === "custom") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderToolbarComponent(action$1.component) }, `custom-${index$1}`);
7808
+ if (!(() => {
7809
+ switch (action$1.type) {
7810
+ case "refresh": return !!(resource.handlers.refresh || action$1.onClick || action$1.component);
7811
+ case "import": return canImport;
7812
+ case "export": return canExport;
7813
+ case "create": return can.create;
7814
+ }
7815
+ })()) return null;
7816
+ if (action$1.component) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderToolbarComponent(action$1.component) }, action$1.type);
7817
+ return renderBuiltinButton(action$1.type, {
7818
+ onClick: action$1.onClick,
7819
+ label: action$1.label
7820
+ });
7821
+ };
7822
+ const toolbarNodes = normalizedToolbarActions.filter((action$1) => action$1.type !== "refresh").map(renderToolbarAction).filter((node) => node !== null);
7823
+ const refreshNodes = normalizedToolbarActions.filter((action$1) => action$1.type === "refresh").map(renderToolbarAction);
7769
7824
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7770
7825
  className: "space-y-4",
7771
7826
  children: [
@@ -7779,80 +7834,12 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7779
7834
  children: description
7780
7835
  })]
7781
7836
  }),
7782
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7837
+ toolbarNodes.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7783
7838
  className: "flex items-center justify-end gap-4",
7784
- children: (() => {
7785
- const renderBuiltinButton = (type, overrides) => {
7786
- if (type === "refresh") {
7787
- const onRefresh = overrides?.onClick ?? toolbarRefresh;
7788
- const label = overrides?.label ?? locale.toolbar.refresh;
7789
- if (!onRefresh) return null;
7790
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Button, {
7791
- variant: "outline",
7792
- size: "icon-sm",
7793
- "aria-label": label,
7794
- title: label,
7795
- onClick: onRefresh,
7796
- disabled: resource.tableData.isFetching,
7797
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.RefreshCw, { className: resource.tableData.isFetching ? "h-4 w-4 animate-spin" : "h-4 w-4" })
7798
- }, "refresh");
7799
- }
7800
- if (type === "import" && canImport) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Button, {
7801
- variant: "outline",
7802
- size: "sm",
7803
- onClick: overrides?.onClick ?? toolbarOpenImport,
7804
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Download, { className: "mr-2 h-4 w-4" }), overrides?.label ?? locale.toolbar.import]
7805
- }, "import");
7806
- if (type === "export" && canExport) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__wordrhyme_shadcn.Button, {
7807
- variant: "outline",
7808
- size: "sm",
7809
- onClick: overrides?.onClick ?? toolbarExportData,
7810
- disabled: exporting || selectedCount === 0 && !resource.handlers.export,
7811
- children: [exporting ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Upload, { className: "mr-2 h-4 w-4" }), overrides?.label ?? (selectedCount > 0 ? locale.toolbar.exportSelected(selectedCount) : locale.toolbar.export)]
7812
- }, "export");
7813
- if (type === "create" && can.create) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__wordrhyme_shadcn.Button, {
7814
- onClick: overrides?.onClick ?? toolbarOpenCreate,
7815
- children: overrides?.label ?? locale.toolbar.create
7816
- }, "create");
7817
- return null;
7818
- };
7819
- const renderToolbarComponent = (component) => typeof component === "function" ? component(toolbarContext) : component;
7820
- if (!resolvedToolbarActions || resolvedToolbarActions.length === 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "flex items-center gap-2" });
7821
- if (!resolvedToolbarActions.some((i) => i.type !== "custom")) {
7822
- const startNodes = resolvedToolbarActions.filter((i) => i.type === "custom" && i.position === "start").map((a, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderToolbarComponent(a.component) }, `start-${i}`));
7823
- const endNodes = resolvedToolbarActions.filter((i) => i.type === "custom" && i.position !== "start").map((a, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderToolbarComponent(a.component) }, `end-${i}`));
7824
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
7825
- className: "flex items-center gap-2",
7826
- children: [
7827
- startNodes,
7828
- renderBuiltinButton("refresh"),
7829
- renderBuiltinButton("import"),
7830
- renderBuiltinButton("export"),
7831
- renderBuiltinButton("create"),
7832
- endNodes
7833
- ]
7834
- });
7835
- }
7836
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7837
- className: "flex items-center gap-2",
7838
- children: resolvedToolbarActions.map((action$1, index$1) => {
7839
- if (action$1.type === "custom") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderToolbarComponent(action$1.component) }, `custom-${index$1}`);
7840
- if (!(() => {
7841
- switch (action$1.type) {
7842
- case "refresh": return !!(resource.handlers.refresh || action$1.onClick || action$1.component);
7843
- case "import": return canImport;
7844
- case "export": return canExport;
7845
- case "create": return can.create;
7846
- }
7847
- })()) return null;
7848
- if (action$1.component) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: renderToolbarComponent(action$1.component) }, action$1.type);
7849
- return renderBuiltinButton(action$1.type, {
7850
- onClick: action$1.onClick,
7851
- label: action$1.label
7852
- });
7853
- })
7854
- });
7855
- })()
7839
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7840
+ className: "flex items-center gap-2",
7841
+ children: toolbarNodes
7842
+ })
7856
7843
  }),
7857
7844
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoTable, {
7858
7845
  data: resource.tableData.data,
@@ -7872,6 +7859,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7872
7859
  filterOnly,
7873
7860
  filterMode: tableConfig?.filterModes,
7874
7861
  search: searchConfig,
7862
+ toolbarExtra: refreshNodes,
7875
7863
  actions: tableRowActions,
7876
7864
  onDeleteSelected: can.delete ? resource.handlers.deleteMany : void 0,
7877
7865
  onUpdateSelected: can.update ? resource.handlers.updateMany : void 0,
package/dist/index.d.cts CHANGED
@@ -902,6 +902,8 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> extends Pick<Data
902
902
  search?: boolean | {
903
903
  placeholder?: string;
904
904
  };
905
+ /** Extra table controls rendered between sorting and column visibility. */
906
+ toolbarExtra?: React.ReactNode;
905
907
  /** 批量删除回调 */
906
908
  onDeleteSelected?: (rows: z.infer<T>[]) => void;
907
909
  /** 批量更新回调 */
@@ -945,6 +947,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
945
947
  pinnedColumns,
946
948
  filterMode,
947
949
  search,
950
+ toolbarExtra,
948
951
  onDeleteSelected,
949
952
  onUpdateSelected,
950
953
  batchUpdateFields,
package/dist/index.d.ts CHANGED
@@ -902,6 +902,8 @@ interface AutoTableProps<T extends z.ZodObject<z.ZodRawShape>> extends Pick<Data
902
902
  search?: boolean | {
903
903
  placeholder?: string;
904
904
  };
905
+ /** Extra table controls rendered between sorting and column visibility. */
906
+ toolbarExtra?: React.ReactNode;
905
907
  /** 批量删除回调 */
906
908
  onDeleteSelected?: (rows: z.infer<T>[]) => void;
907
909
  /** 批量更新回调 */
@@ -945,6 +947,7 @@ declare function AutoTable<T extends z.ZodObject<z.ZodRawShape>>({
945
947
  pinnedColumns,
946
948
  filterMode,
947
949
  search,
950
+ toolbarExtra,
948
951
  onDeleteSelected,
949
952
  onUpdateSelected,
950
953
  batchUpdateFields,
package/dist/index.js CHANGED
@@ -4415,7 +4415,7 @@ const filterModeConfig = {
4415
4415
  tooltip: "Linear-style command filters"
4416
4416
  }
4417
4417
  };
4418
- function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = false, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, exclude, filterOnly, actions, pinnedColumns, filterMode, search = false, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
4418
+ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = false, pageCount = 1, pagination, total, overrides, classNames, enableRowSelection = true, exclude, filterOnly, actions, pinnedColumns, filterMode, search = false, toolbarExtra, onDeleteSelected, onUpdateSelected, batchUpdateFields, actionBarExtra, actionBarActions, deleteConfirmation, initialSorting, enableExport = true, showDefaultExport = true, onSelectedCountChange, onSelectedRowsChange, getSelectedRows }) {
4419
4419
  if (expandedRow && !getRowId) throw new Error("AutoTable requires getRowId when expandedRow is provided.");
4420
4420
  const enableExpansion = !!expandedRow;
4421
4421
  const modes = filterMode ? Array.isArray(filterMode) ? filterMode : [filterMode] : DEFAULT_MODES;
@@ -4634,6 +4634,7 @@ function AutoTable({ schema, data, getRowId, expandedRow, defaultExpanded = fals
4634
4634
  table,
4635
4635
  align: "end"
4636
4636
  }),
4637
+ toolbarExtra,
4637
4638
  /* @__PURE__ */ jsx(DataTableViewOptions, {
4638
4639
  table,
4639
4640
  align: "end"
@@ -7751,6 +7752,60 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7751
7752
  rowActionDefaults,
7752
7753
  openComponent
7753
7754
  ]);
7755
+ const normalizedToolbarActions = resolvedToolbarActions.length > 0 ? resolveOwnerToolbarActions(resolvedToolbarActions) : [];
7756
+ const renderBuiltinButton = (type, overrides) => {
7757
+ if (type === "refresh") {
7758
+ const onRefresh = overrides?.onClick ?? toolbarRefresh;
7759
+ const label = overrides?.label ?? locale.toolbar.refresh;
7760
+ if (!onRefresh) return null;
7761
+ return /* @__PURE__ */ jsx(Button, {
7762
+ variant: "outline",
7763
+ size: "icon-sm",
7764
+ "aria-label": label,
7765
+ title: label,
7766
+ onClick: onRefresh,
7767
+ disabled: resource.tableData.isFetching,
7768
+ children: /* @__PURE__ */ jsx(RefreshCw, { className: resource.tableData.isFetching ? "h-4 w-4 animate-spin" : "h-4 w-4" })
7769
+ }, "refresh");
7770
+ }
7771
+ if (type === "import" && canImport) return /* @__PURE__ */ jsxs(Button, {
7772
+ variant: "outline",
7773
+ size: "sm",
7774
+ onClick: overrides?.onClick ?? toolbarOpenImport,
7775
+ children: [/* @__PURE__ */ jsx(Download, { className: "mr-2 h-4 w-4" }), overrides?.label ?? locale.toolbar.import]
7776
+ }, "import");
7777
+ if (type === "export" && canExport) return /* @__PURE__ */ jsxs(Button, {
7778
+ variant: "outline",
7779
+ size: "sm",
7780
+ onClick: overrides?.onClick ?? toolbarExportData,
7781
+ disabled: exporting || selectedCount === 0 && !resource.handlers.export,
7782
+ children: [exporting ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Upload, { className: "mr-2 h-4 w-4" }), overrides?.label ?? (selectedCount > 0 ? locale.toolbar.exportSelected(selectedCount) : locale.toolbar.export)]
7783
+ }, "export");
7784
+ if (type === "create" && can.create) return /* @__PURE__ */ jsx(Button, {
7785
+ onClick: overrides?.onClick ?? toolbarOpenCreate,
7786
+ children: overrides?.label ?? locale.toolbar.create
7787
+ }, "create");
7788
+ return null;
7789
+ };
7790
+ const renderToolbarComponent = (component) => typeof component === "function" ? component(toolbarContext) : component;
7791
+ const renderToolbarAction = (action$1, index$1) => {
7792
+ if (action$1.type === "custom") return /* @__PURE__ */ jsx(React.Fragment, { children: renderToolbarComponent(action$1.component) }, `custom-${index$1}`);
7793
+ if (!(() => {
7794
+ switch (action$1.type) {
7795
+ case "refresh": return !!(resource.handlers.refresh || action$1.onClick || action$1.component);
7796
+ case "import": return canImport;
7797
+ case "export": return canExport;
7798
+ case "create": return can.create;
7799
+ }
7800
+ })()) return null;
7801
+ if (action$1.component) return /* @__PURE__ */ jsx(React.Fragment, { children: renderToolbarComponent(action$1.component) }, action$1.type);
7802
+ return renderBuiltinButton(action$1.type, {
7803
+ onClick: action$1.onClick,
7804
+ label: action$1.label
7805
+ });
7806
+ };
7807
+ const toolbarNodes = normalizedToolbarActions.filter((action$1) => action$1.type !== "refresh").map(renderToolbarAction).filter((node) => node !== null);
7808
+ const refreshNodes = normalizedToolbarActions.filter((action$1) => action$1.type === "refresh").map(renderToolbarAction);
7754
7809
  return /* @__PURE__ */ jsxs("div", {
7755
7810
  className: "space-y-4",
7756
7811
  children: [
@@ -7764,80 +7819,12 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7764
7819
  children: description
7765
7820
  })]
7766
7821
  }),
7767
- /* @__PURE__ */ jsx("div", {
7822
+ toolbarNodes.length > 0 && /* @__PURE__ */ jsx("div", {
7768
7823
  className: "flex items-center justify-end gap-4",
7769
- children: (() => {
7770
- const renderBuiltinButton = (type, overrides) => {
7771
- if (type === "refresh") {
7772
- const onRefresh = overrides?.onClick ?? toolbarRefresh;
7773
- const label = overrides?.label ?? locale.toolbar.refresh;
7774
- if (!onRefresh) return null;
7775
- return /* @__PURE__ */ jsx(Button, {
7776
- variant: "outline",
7777
- size: "icon-sm",
7778
- "aria-label": label,
7779
- title: label,
7780
- onClick: onRefresh,
7781
- disabled: resource.tableData.isFetching,
7782
- children: /* @__PURE__ */ jsx(RefreshCw, { className: resource.tableData.isFetching ? "h-4 w-4 animate-spin" : "h-4 w-4" })
7783
- }, "refresh");
7784
- }
7785
- if (type === "import" && canImport) return /* @__PURE__ */ jsxs(Button, {
7786
- variant: "outline",
7787
- size: "sm",
7788
- onClick: overrides?.onClick ?? toolbarOpenImport,
7789
- children: [/* @__PURE__ */ jsx(Download, { className: "mr-2 h-4 w-4" }), overrides?.label ?? locale.toolbar.import]
7790
- }, "import");
7791
- if (type === "export" && canExport) return /* @__PURE__ */ jsxs(Button, {
7792
- variant: "outline",
7793
- size: "sm",
7794
- onClick: overrides?.onClick ?? toolbarExportData,
7795
- disabled: exporting || selectedCount === 0 && !resource.handlers.export,
7796
- children: [exporting ? /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Upload, { className: "mr-2 h-4 w-4" }), overrides?.label ?? (selectedCount > 0 ? locale.toolbar.exportSelected(selectedCount) : locale.toolbar.export)]
7797
- }, "export");
7798
- if (type === "create" && can.create) return /* @__PURE__ */ jsx(Button, {
7799
- onClick: overrides?.onClick ?? toolbarOpenCreate,
7800
- children: overrides?.label ?? locale.toolbar.create
7801
- }, "create");
7802
- return null;
7803
- };
7804
- const renderToolbarComponent = (component) => typeof component === "function" ? component(toolbarContext) : component;
7805
- if (!resolvedToolbarActions || resolvedToolbarActions.length === 0) return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2" });
7806
- if (!resolvedToolbarActions.some((i) => i.type !== "custom")) {
7807
- const startNodes = resolvedToolbarActions.filter((i) => i.type === "custom" && i.position === "start").map((a, i) => /* @__PURE__ */ jsx(React.Fragment, { children: renderToolbarComponent(a.component) }, `start-${i}`));
7808
- const endNodes = resolvedToolbarActions.filter((i) => i.type === "custom" && i.position !== "start").map((a, i) => /* @__PURE__ */ jsx(React.Fragment, { children: renderToolbarComponent(a.component) }, `end-${i}`));
7809
- return /* @__PURE__ */ jsxs("div", {
7810
- className: "flex items-center gap-2",
7811
- children: [
7812
- startNodes,
7813
- renderBuiltinButton("refresh"),
7814
- renderBuiltinButton("import"),
7815
- renderBuiltinButton("export"),
7816
- renderBuiltinButton("create"),
7817
- endNodes
7818
- ]
7819
- });
7820
- }
7821
- return /* @__PURE__ */ jsx("div", {
7822
- className: "flex items-center gap-2",
7823
- children: resolvedToolbarActions.map((action$1, index$1) => {
7824
- if (action$1.type === "custom") return /* @__PURE__ */ jsx(React.Fragment, { children: renderToolbarComponent(action$1.component) }, `custom-${index$1}`);
7825
- if (!(() => {
7826
- switch (action$1.type) {
7827
- case "refresh": return !!(resource.handlers.refresh || action$1.onClick || action$1.component);
7828
- case "import": return canImport;
7829
- case "export": return canExport;
7830
- case "create": return can.create;
7831
- }
7832
- })()) return null;
7833
- if (action$1.component) return /* @__PURE__ */ jsx(React.Fragment, { children: renderToolbarComponent(action$1.component) }, action$1.type);
7834
- return renderBuiltinButton(action$1.type, {
7835
- onClick: action$1.onClick,
7836
- label: action$1.label
7837
- });
7838
- })
7839
- });
7840
- })()
7824
+ children: /* @__PURE__ */ jsx("div", {
7825
+ className: "flex items-center gap-2",
7826
+ children: toolbarNodes
7827
+ })
7841
7828
  }),
7842
7829
  /* @__PURE__ */ jsx(AutoTable, {
7843
7830
  data: resource.tableData.data,
@@ -7857,6 +7844,7 @@ function AutoCrudTable({ id, title, description, schema, resource, fields, table
7857
7844
  filterOnly,
7858
7845
  filterMode: tableConfig?.filterModes,
7859
7846
  search: searchConfig,
7847
+ toolbarExtra: refreshNodes,
7860
7848
  actions: tableRowActions,
7861
7849
  onDeleteSelected: can.delete ? resource.handlers.deleteMany : void 0,
7862
7850
  onUpdateSelected: can.update ? resource.handlers.updateMany : void 0,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@wordrhyme/auto-crud",
3
3
  "type": "module",
4
- "version": "1.11.0",
4
+ "version": "1.11.1",
5
5
  "description": "Schema-first CRUD components with auto-generated tables and forms",
6
6
  "author": "wordrhyme",
7
7
  "license": "MIT",
@@ -70,8 +70,8 @@
70
70
  "nanoid": "^5.1.6",
71
71
  "tailwind-merge": "^3.5.0",
72
72
  "vaul": "^1.1.2",
73
- "@wordrhyme/formily-shadcn": "2.1.1",
74
73
  "@wordrhyme/shadcn": "2.0.1",
74
+ "@wordrhyme/formily-shadcn": "2.1.1",
75
75
  "@wordrhyme/shadcn-ui": "2.1.1"
76
76
  },
77
77
  "devDependencies": {
@@ -94,10 +94,10 @@
94
94
  "typescript": "^5.9.3",
95
95
  "vitest": "^3.2.4",
96
96
  "@internal/eslint-config": "0.3.0",
97
- "@internal/tsconfig": "0.1.0",
98
- "@internal/vitest-config": "0.1.0",
97
+ "@internal/prettier-config": "0.0.1",
99
98
  "@internal/tsdown-config": "0.1.0",
100
- "@internal/prettier-config": "0.0.1"
99
+ "@internal/tsconfig": "0.1.0",
100
+ "@internal/vitest-config": "0.1.0"
101
101
  },
102
102
  "prettier": "@internal/prettier-config",
103
103
  "scripts": {