@turinhub/atomix-common-ui 0.4.0 → 0.6.0

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.
Files changed (104) hide show
  1. package/README.md +20 -2
  2. package/dist/AuthPanel-CTKx618F.cjs +2 -0
  3. package/dist/AuthPanel-CTKx618F.cjs.map +1 -0
  4. package/dist/AuthPanel-Cn_WwmjX.js +703 -0
  5. package/dist/AuthPanel-Cn_WwmjX.js.map +1 -0
  6. package/dist/PDFSidebar-4DtXqqzN.cjs +2 -0
  7. package/dist/PDFSidebar-4DtXqqzN.cjs.map +1 -0
  8. package/dist/PDFSidebar-ClnrF4Br.js +239 -0
  9. package/dist/PDFSidebar-ClnrF4Br.js.map +1 -0
  10. package/dist/auth.cjs +2 -0
  11. package/dist/auth.cjs.map +1 -0
  12. package/dist/auth.d.ts +11 -0
  13. package/dist/auth.d.ts.map +1 -0
  14. package/dist/auth.js +9 -0
  15. package/dist/auth.js.map +1 -0
  16. package/dist/components/AuthLoginPanel.d.ts +55 -0
  17. package/dist/components/AuthLoginPanel.d.ts.map +1 -0
  18. package/dist/components/AuthPageShell.d.ts +11 -0
  19. package/dist/components/AuthPageShell.d.ts.map +1 -0
  20. package/dist/components/AuthPanel.d.ts +20 -0
  21. package/dist/components/AuthPanel.d.ts.map +1 -0
  22. package/dist/components/AuthRegisterPanel.d.ts +34 -0
  23. package/dist/components/AuthRegisterPanel.d.ts.map +1 -0
  24. package/dist/components/AuthVisualCarousel.d.ts +22 -0
  25. package/dist/components/AuthVisualCarousel.d.ts.map +1 -0
  26. package/dist/components/DataTable.d.ts +2 -2
  27. package/dist/components/DataTable.d.ts.map +1 -1
  28. package/dist/components/ImageReader.d.ts +44 -0
  29. package/dist/components/ImageReader.d.ts.map +1 -0
  30. package/dist/components/MarkdownReader.d.ts.map +1 -1
  31. package/dist/components/PDFReader.d.ts.map +1 -1
  32. package/dist/components/PDFSidebar.d.ts.map +1 -1
  33. package/dist/components/SimplePDFReader.d.ts.map +1 -1
  34. package/dist/components/TableHeader.d.ts.map +1 -1
  35. package/dist/components/TablePagination.d.ts +2 -1
  36. package/dist/components/TablePagination.d.ts.map +1 -1
  37. package/dist/components/VideoReader.d.ts +39 -0
  38. package/dist/components/VideoReader.d.ts.map +1 -0
  39. package/dist/components/media-utils.d.ts +9 -0
  40. package/dist/components/media-utils.d.ts.map +1 -0
  41. package/dist/components/ui/switch.d.ts +5 -0
  42. package/dist/components/ui/switch.d.ts.map +1 -0
  43. package/dist/data-table.cjs +1 -1
  44. package/dist/data-table.cjs.map +1 -1
  45. package/dist/data-table.js +83 -73
  46. package/dist/data-table.js.map +1 -1
  47. package/dist/file-upload.cjs +1 -1
  48. package/dist/file-upload.cjs.map +1 -1
  49. package/dist/file-upload.js +36 -36
  50. package/dist/file-upload.js.map +1 -1
  51. package/dist/image-reader.cjs +2 -0
  52. package/dist/image-reader.cjs.map +1 -0
  53. package/dist/image-reader.d.ts +3 -0
  54. package/dist/image-reader.d.ts.map +1 -0
  55. package/dist/image-reader.js +215 -0
  56. package/dist/image-reader.js.map +1 -0
  57. package/dist/index.cjs +1 -1
  58. package/dist/index.d.ts +10 -0
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +8 -2
  61. package/dist/index.js.map +1 -1
  62. package/dist/markdown-reader.cjs +1 -1
  63. package/dist/markdown-reader.cjs.map +1 -1
  64. package/dist/markdown-reader.js +28 -24
  65. package/dist/markdown-reader.js.map +1 -1
  66. package/dist/media-utils-5UPuocc1.js +23 -0
  67. package/dist/media-utils-5UPuocc1.js.map +1 -0
  68. package/dist/media-utils-X1dDYP9W.cjs +2 -0
  69. package/dist/media-utils-X1dDYP9W.cjs.map +1 -0
  70. package/dist/pdf-reader.cjs +1 -1
  71. package/dist/pdf-reader.cjs.map +1 -1
  72. package/dist/pdf-reader.js +170 -121
  73. package/dist/pdf-reader.js.map +1 -1
  74. package/dist/pdf-sidebar.cjs +1 -1
  75. package/dist/pdf-sidebar.js +1 -1
  76. package/dist/simple-pdf-reader.cjs +1 -1
  77. package/dist/simple-pdf-reader.cjs.map +1 -1
  78. package/dist/simple-pdf-reader.js +138 -105
  79. package/dist/simple-pdf-reader.js.map +1 -1
  80. package/dist/table-header.cjs +1 -1
  81. package/dist/table-header.cjs.map +1 -1
  82. package/dist/table-header.js +42 -34
  83. package/dist/table-header.js.map +1 -1
  84. package/dist/table-pagination.cjs +1 -1
  85. package/dist/table-pagination.cjs.map +1 -1
  86. package/dist/table-pagination.js +49 -43
  87. package/dist/table-pagination.js.map +1 -1
  88. package/dist/types/component-types.d.ts +2 -0
  89. package/dist/types/component-types.d.ts.map +1 -1
  90. package/dist/video-reader.cjs +2 -0
  91. package/dist/video-reader.cjs.map +1 -0
  92. package/dist/video-reader.d.ts +3 -0
  93. package/dist/video-reader.d.ts.map +1 -0
  94. package/dist/video-reader.js +158 -0
  95. package/dist/video-reader.js.map +1 -0
  96. package/package.json +32 -1
  97. package/dist/PDFSidebar-BBtucLK6.js +0 -232
  98. package/dist/PDFSidebar-BBtucLK6.js.map +0 -1
  99. package/dist/PDFSidebar-Di0D-yPS.cjs +0 -2
  100. package/dist/PDFSidebar-Di0D-yPS.cjs.map +0 -1
  101. package/dist/index-BiA_tnaq.cjs +0 -13
  102. package/dist/index-BiA_tnaq.cjs.map +0 -1
  103. package/dist/index-BypbGNpR.js +0 -18821
  104. package/dist/index-BypbGNpR.js.map +0 -1
@@ -1,54 +1,62 @@
1
1
  import { j as e } from "./jsx-runtime-B4hRZ52C.js";
2
- import { Plus as v, Search as o } from "lucide-react";
3
- function b({
2
+ import { Plus as v, Search as w } from "lucide-react";
3
+ import { useId as h } from "react";
4
+ function k({
4
5
  title: c,
5
- searchPlaceholder: n = "搜索...",
6
+ searchPlaceholder: r = "搜索...",
6
7
  searchValue: f = "",
7
- onSearchChange: l,
8
- onSearch: s,
9
- showSearch: j = !0,
10
- action: t,
11
- actionLabel: a,
12
- onActionClick: d,
13
- loading: i = !1,
14
- components: x
8
+ onSearchChange: t,
9
+ onSearch: l,
10
+ showSearch: p = !0,
11
+ action: i,
12
+ actionLabel: n,
13
+ onActionClick: a,
14
+ loading: m = !1,
15
+ components: d
15
16
  }) {
16
- if (!x)
17
+ const o = h();
18
+ if (!d)
17
19
  return /* @__PURE__ */ e.jsx("div", { className: "p-4 text-center text-destructive", children: "错误:请通过 components prop 注入 UI 组件" });
18
- const { Input: p, Button: m } = x, u = (r) => {
19
- r.key === "Enter" && s && s();
20
+ const { Input: u, Button: x } = d, j = (s) => {
21
+ s.nativeEvent.isComposing || s.nativeEvent.isComposing || s.key === "Enter" && l && l();
20
22
  };
21
- return /* @__PURE__ */ e.jsxs("div", { className: "flex flex-col gap-4 p-1", children: [
22
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center justify-between", children: [
23
- /* @__PURE__ */ e.jsx("div", { className: "text-lg font-semibold leading-none tracking-tight", children: c }),
24
- /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2", children: [
25
- t && /* @__PURE__ */ e.jsx("div", { className: "flex items-center gap-2", children: t }),
26
- !t && a && d && /* @__PURE__ */ e.jsxs(m, { onClick: d, disabled: i, size: "sm", children: [
23
+ return /* @__PURE__ */ e.jsxs("div", { className: "flex min-w-0 flex-col gap-4 p-1", children: [
24
+ /* @__PURE__ */ e.jsxs("div", { className: "flex min-w-0 flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
25
+ /* @__PURE__ */ e.jsx("div", { className: "min-w-0 break-words text-lg font-semibold leading-tight text-foreground", children: c }),
26
+ /* @__PURE__ */ e.jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
27
+ i && /* @__PURE__ */ e.jsx("div", { className: "flex min-w-0 items-center gap-2", children: i }),
28
+ !i && n && a && /* @__PURE__ */ e.jsxs(x, { onClick: a, disabled: m, size: "sm", children: [
27
29
  /* @__PURE__ */ e.jsx(v, { className: "mr-2 h-4 w-4" }),
28
- a
30
+ n
29
31
  ] })
30
32
  ] })
31
33
  ] }),
32
- j && /* @__PURE__ */ e.jsxs("div", { className: "flex items-center gap-2", children: [
33
- /* @__PURE__ */ e.jsxs("div", { className: "relative max-w-sm flex-1", children: [
34
- /* @__PURE__ */ e.jsx(o, { className: "absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" }),
34
+ p && /* @__PURE__ */ e.jsxs("div", { className: "flex min-w-0 flex-col gap-2 sm:flex-row sm:items-center", children: [
35
+ /* @__PURE__ */ e.jsxs("div", { className: "relative min-w-0 flex-1 sm:max-w-sm", children: [
36
+ /* @__PURE__ */ e.jsx("label", { htmlFor: o, className: "sr-only", children: r }),
37
+ /* @__PURE__ */ e.jsx(w, { className: "absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" }),
35
38
  /* @__PURE__ */ e.jsx(
36
- p,
39
+ u,
37
40
  {
38
- placeholder: n,
41
+ id: o,
42
+ name: "table-search",
43
+ type: "search",
44
+ placeholder: r,
39
45
  value: f,
40
- onChange: (r) => l == null ? void 0 : l(r.target.value),
41
- onKeyPress: u,
46
+ onChange: (s) => t == null ? void 0 : t(s.target.value),
47
+ onKeyDown: j,
42
48
  className: "h-9 pl-8",
43
- disabled: i
49
+ disabled: m,
50
+ autoComplete: "off",
51
+ spellCheck: !1
44
52
  }
45
53
  )
46
54
  ] }),
47
- s && /* @__PURE__ */ e.jsx(
48
- m,
55
+ l && /* @__PURE__ */ e.jsx(
56
+ x,
49
57
  {
50
- onClick: s,
51
- disabled: i,
58
+ onClick: l,
59
+ disabled: m,
52
60
  variant: "secondary",
53
61
  size: "sm",
54
62
  children: "搜索"
@@ -58,6 +66,6 @@ function b({
58
66
  ] });
59
67
  }
60
68
  export {
61
- b as TableHeader
69
+ k as TableHeader
62
70
  };
63
71
  //# sourceMappingURL=table-header.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"table-header.js","sources":["../src/components/TableHeader.tsx"],"sourcesContent":["import { Plus, Search } from 'lucide-react';\nimport { ReactNode } from 'react';\n\nimport type { InputComponent, ButtonComponent } from '../types/component-types';\n\n/**\n * UI 组件适配器接口\n */\nexport interface HeaderUIComponents {\n Input: InputComponent;\n Button: ButtonComponent;\n}\n\nexport interface TableHeaderProps {\n title: ReactNode;\n searchPlaceholder?: string;\n searchValue?: string;\n onSearchChange?: (value: string) => void;\n onSearch?: () => void;\n showSearch?: boolean;\n action?: ReactNode;\n actionLabel?: string;\n onActionClick?: () => void;\n loading?: boolean;\n\n // UI 组件注入\n components?: HeaderUIComponents;\n}\n\n/**\n * 表格头部组件\n * 支持搜索框和操作按钮\n */\nexport function TableHeader({\n title,\n searchPlaceholder = '搜索...',\n searchValue = '',\n onSearchChange,\n onSearch,\n showSearch = true,\n action,\n actionLabel,\n onActionClick,\n loading = false,\n components,\n}: TableHeaderProps) {\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n const { Input, Button } = components;\n\n const handleKeyPress = (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && onSearch) {\n onSearch();\n }\n };\n\n return (\n <div className=\"flex flex-col gap-4 p-1\">\n <div className=\"flex items-center justify-between\">\n <div className=\"text-lg font-semibold leading-none tracking-tight\">\n {title}\n </div>\n <div className=\"flex items-center gap-2\">\n {action && <div className=\"flex items-center gap-2\">{action}</div>}\n {!action && actionLabel && onActionClick && (\n <Button onClick={onActionClick} disabled={loading} size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" />\n {actionLabel}\n </Button>\n )}\n </div>\n </div>\n {showSearch && (\n <div className=\"flex items-center gap-2\">\n <div className=\"relative max-w-sm flex-1\">\n <Search className=\"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground\" />\n <Input\n placeholder={searchPlaceholder}\n value={searchValue}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n onSearchChange?.(e.target.value)\n }\n onKeyPress={handleKeyPress}\n className=\"h-9 pl-8\"\n disabled={loading}\n />\n </div>\n {onSearch && (\n <Button\n onClick={onSearch}\n disabled={loading}\n variant=\"secondary\"\n size=\"sm\"\n >\n 搜索\n </Button>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"names":["TableHeader","title","searchPlaceholder","searchValue","onSearchChange","onSearch","showSearch","action","actionLabel","onActionClick","loading","components","jsx","Input","Button","handleKeyPress","e","jsxs","Plus","Search"],"mappings":";;AAiCO,SAASA,EAAY;AAAA,EAC1B,OAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,aAAAC,IAAc;AAAA,EACd,gBAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC,IAAa;AAAA,EACb,QAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,YAAAC;AACF,GAAqB;AACnB,MAAI,CAACA;AACH,WACEC,gBAAAA,EAAAA,IAAC,OAAA,EAAI,WAAU,oCAAmC,UAAA,mCAElD;AAIJ,QAAM,EAAE,OAAAC,GAAO,QAAAC,EAAA,IAAWH,GAEpBI,IAAiB,CAACC,MAA2B;AACjD,IAAIA,EAAE,QAAQ,WAAWX,KACvBA,EAAA;AAAA,EAEJ;AAEA,SACEY,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,IAAAA,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,MAAAL,gBAAAA,EAAAA,IAAC,OAAA,EAAI,WAAU,qDACZ,UAAAX,GACH;AAAA,MACAgB,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,QAAAV,KAAUK,gBAAAA,EAAAA,IAAC,OAAA,EAAI,WAAU,2BAA2B,UAAAL,GAAO;AAAA,QAC3D,CAACA,KAAUC,KAAeC,KACzBQ,gBAAAA,EAAAA,KAACH,GAAA,EAAO,SAASL,GAAe,UAAUC,GAAS,MAAK,MACtD,UAAA;AAAA,UAAAE,gBAAAA,EAAAA,IAACM,GAAA,EAAK,WAAU,eAAA,CAAe;AAAA,UAC9BV;AAAA,QAAA,EAAA,CACH;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,GACF;AAAA,IACCF,KACCW,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,MAAAA,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,4BACb,UAAA;AAAA,QAAAL,gBAAAA,EAAAA,IAACO,GAAA,EAAO,WAAU,wDAAA,CAAwD;AAAA,QAC1EP,gBAAAA,EAAAA;AAAAA,UAACC;AAAA,UAAA;AAAA,YACC,aAAaX;AAAA,YACb,OAAOC;AAAA,YACP,UAAU,CAACa,MACTZ,KAAA,gBAAAA,EAAiBY,EAAE,OAAO;AAAA,YAE5B,YAAYD;AAAA,YACZ,WAAU;AAAA,YACV,UAAUL;AAAA,UAAA;AAAA,QAAA;AAAA,MACZ,GACF;AAAA,MACCL,KACCO,gBAAAA,EAAAA;AAAAA,QAACE;AAAA,QAAA;AAAA,UACC,SAAST;AAAA,UACT,UAAUK;AAAA,UACV,SAAQ;AAAA,UACR,MAAK;AAAA,UACN,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CAEJ;AAAA,EAAA,GAEJ;AAEJ;"}
1
+ {"version":3,"file":"table-header.js","sources":["../src/components/TableHeader.tsx"],"sourcesContent":["import { Plus, Search } from 'lucide-react';\nimport { ReactNode, useId } from 'react';\n\nimport type { InputComponent, ButtonComponent } from '../types/component-types';\n\n/**\n * UI 组件适配器接口\n */\nexport interface HeaderUIComponents {\n Input: InputComponent;\n Button: ButtonComponent;\n}\n\nexport interface TableHeaderProps {\n title: ReactNode;\n searchPlaceholder?: string;\n searchValue?: string;\n onSearchChange?: (value: string) => void;\n onSearch?: () => void;\n showSearch?: boolean;\n action?: ReactNode;\n actionLabel?: string;\n onActionClick?: () => void;\n loading?: boolean;\n\n // UI 组件注入\n components?: HeaderUIComponents;\n}\n\n/**\n * 表格头部组件\n * 支持搜索框和操作按钮\n */\nexport function TableHeader({\n title,\n searchPlaceholder = '搜索...',\n searchValue = '',\n onSearchChange,\n onSearch,\n showSearch = true,\n action,\n actionLabel,\n onActionClick,\n loading = false,\n components,\n}: TableHeaderProps) {\n const searchInputId = useId();\n\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n const { Input, Button } = components;\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n const isComposing =\n e.nativeEvent.isComposing ||\n (e.nativeEvent as KeyboardEvent & { isComposing?: boolean }).isComposing;\n if (isComposing) {\n return;\n }\n if (e.key === 'Enter' && onSearch) {\n onSearch();\n }\n };\n\n return (\n <div className=\"flex min-w-0 flex-col gap-4 p-1\">\n <div className=\"flex min-w-0 flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div className=\"min-w-0 break-words text-lg font-semibold leading-tight text-foreground\">\n {title}\n </div>\n <div className=\"flex shrink-0 items-center gap-2\">\n {action && (\n <div className=\"flex min-w-0 items-center gap-2\">{action}</div>\n )}\n {!action && actionLabel && onActionClick && (\n <Button onClick={onActionClick} disabled={loading} size=\"sm\">\n <Plus className=\"mr-2 h-4 w-4\" />\n {actionLabel}\n </Button>\n )}\n </div>\n </div>\n {showSearch && (\n <div className=\"flex min-w-0 flex-col gap-2 sm:flex-row sm:items-center\">\n <div className=\"relative min-w-0 flex-1 sm:max-w-sm\">\n <label htmlFor={searchInputId} className=\"sr-only\">\n {searchPlaceholder}\n </label>\n <Search className=\"absolute left-2 top-2.5 h-4 w-4 text-muted-foreground\" />\n <Input\n id={searchInputId}\n name=\"table-search\"\n type=\"search\"\n placeholder={searchPlaceholder}\n value={searchValue}\n onChange={(e: React.ChangeEvent<HTMLInputElement>) =>\n onSearchChange?.(e.target.value)\n }\n onKeyDown={handleKeyDown}\n className=\"h-9 pl-8\"\n disabled={loading}\n autoComplete=\"off\"\n spellCheck={false}\n />\n </div>\n {onSearch && (\n <Button\n onClick={onSearch}\n disabled={loading}\n variant=\"secondary\"\n size=\"sm\"\n >\n 搜索\n </Button>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"names":["TableHeader","title","searchPlaceholder","searchValue","onSearchChange","onSearch","showSearch","action","actionLabel","onActionClick","loading","components","searchInputId","useId","jsx","Input","Button","handleKeyDown","e","jsxs","Plus","Search"],"mappings":";;;AAiCO,SAASA,EAAY;AAAA,EAC1B,OAAAC;AAAA,EACA,mBAAAC,IAAoB;AAAA,EACpB,aAAAC,IAAc;AAAA,EACd,gBAAAC;AAAA,EACA,UAAAC;AAAA,EACA,YAAAC,IAAa;AAAA,EACb,QAAAC;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,SAAAC,IAAU;AAAA,EACV,YAAAC;AACF,GAAqB;AACnB,QAAMC,IAAgBC,EAAA;AAEtB,MAAI,CAACF;AACH,WACEG,gBAAAA,EAAAA,IAAC,OAAA,EAAI,WAAU,oCAAmC,UAAA,mCAElD;AAIJ,QAAM,EAAE,OAAAC,GAAO,QAAAC,EAAA,IAAWL,GAEpBM,IAAgB,CAACC,MAA2B;AAIhD,IAFEA,EAAE,YAAY,eACbA,EAAE,YAA0D,eAI3DA,EAAE,QAAQ,WAAWb,KACvBA,EAAA;AAAA,EAEJ;AAEA,SACEc,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,IAAAA,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,8EACb,UAAA;AAAA,MAAAL,gBAAAA,EAAAA,IAAC,OAAA,EAAI,WAAU,2EACZ,UAAAb,GACH;AAAA,MACAkB,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,QAAAZ,KACCO,gBAAAA,EAAAA,IAAC,OAAA,EAAI,WAAU,mCAAmC,UAAAP,GAAO;AAAA,QAE1D,CAACA,KAAUC,KAAeC,KACzBU,gBAAAA,EAAAA,KAACH,GAAA,EAAO,SAASP,GAAe,UAAUC,GAAS,MAAK,MACtD,UAAA;AAAA,UAAAI,gBAAAA,EAAAA,IAACM,GAAA,EAAK,WAAU,eAAA,CAAe;AAAA,UAC9BZ;AAAA,QAAA,EAAA,CACH;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,GACF;AAAA,IACCF,KACCa,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,2DACb,UAAA;AAAA,MAAAA,gBAAAA,EAAAA,KAAC,OAAA,EAAI,WAAU,uCACb,UAAA;AAAA,QAAAL,gBAAAA,MAAC,SAAA,EAAM,SAASF,GAAe,WAAU,WACtC,UAAAV,GACH;AAAA,QACAY,gBAAAA,EAAAA,IAACO,GAAA,EAAO,WAAU,wDAAA,CAAwD;AAAA,QAC1EP,gBAAAA,EAAAA;AAAAA,UAACC;AAAA,UAAA;AAAA,YACC,IAAIH;AAAA,YACJ,MAAK;AAAA,YACL,MAAK;AAAA,YACL,aAAaV;AAAA,YACb,OAAOC;AAAA,YACP,UAAU,CAACe,MACTd,KAAA,gBAAAA,EAAiBc,EAAE,OAAO;AAAA,YAE5B,WAAWD;AAAA,YACX,WAAU;AAAA,YACV,UAAUP;AAAA,YACV,cAAa;AAAA,YACb,YAAY;AAAA,UAAA;AAAA,QAAA;AAAA,MACd,GACF;AAAA,MACCL,KACCS,gBAAAA,EAAAA;AAAAA,QAACE;AAAA,QAAA;AAAA,UACC,SAASX;AAAA,UACT,UAAUK;AAAA,UACV,SAAQ;AAAA,UACR,MAAK;AAAA,UACN,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,IAED,EAAA,CAEJ;AAAA,EAAA,GAEJ;AAEJ;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./jsx-runtime-BB_1_6y_.cjs"),b=require("lucide-react"),R=require("react");function O({currentPage:t,pageSize:x,total:l,onPageChange:E,onPageSizeChange:d,pageSizeOptions:v=[10,20,50],showPageSizeSelector:N=!0,showJumpToPage:g=!0,showTotal:p=!0,searchActive:y=!1,components:j}){const[f,h]=R.useState(String(t+1));if(R.useEffect(()=>{h(String(t+1))},[t]),!j)return e.jsxRuntimeExports.jsx("div",{className:"p-4 text-center text-destructive",children:"错误:请通过 components prop 注入 UI 组件"});const{Button:o,Select:S,SelectTrigger:w,SelectContent:I,SelectItem:$,SelectValue:C}=j,M=Math.ceil(l/x),i=Math.max(M,1),T=t*x+1,k=Math.min((t+1)*x,l),q=Array.from(new Set([...v,x])).sort((s,n)=>s-n),A=N&&!!d,u=i>1,c=s=>{const n=Math.max(0,Math.min(s,i-1));n!==t&&E(n)},B=(()=>{if(i<=7)return Array.from({length:i},(r,a)=>a);const s=new Set([0,1,i-2,i-1,t-1,t,t+1]),n=Array.from(s).filter(r=>r>=0&&r<i).sort((r,a)=>r-a),m=[];for(const r of n){const a=m[m.length-1];typeof a=="number"&&r-a>1&&m.push("ellipsis"),m.push(r)}return m})();return l===0?null:e.jsxRuntimeExports.jsxs("div",{className:`flex w-full items-center gap-3 ${p?"justify-between":"justify-end"}`,children:[p&&e.jsxRuntimeExports.jsx("div",{className:"text-sm text-muted-foreground",children:y?`找到 ${l} 条匹配记录`:l>0?`显示 ${T} - ${k} 条,共 ${l} 条记录`:"暂无数据"}),e.jsxRuntimeExports.jsxs("div",{className:"flex flex-wrap items-center justify-end gap-2",children:[A&&e.jsxRuntimeExports.jsxs("div",{className:"mr-2 flex items-center gap-2",children:[e.jsxRuntimeExports.jsx("span",{className:"text-sm text-muted-foreground",children:"每页"}),e.jsxRuntimeExports.jsxs(S,{value:String(x),onValueChange:s=>{const n=Number(s);Number.isNaN(n)||n===x||!d||d(n)},children:[e.jsxRuntimeExports.jsx(w,{className:"h-8 w-[90px]",children:e.jsxRuntimeExports.jsx(C,{})}),e.jsxRuntimeExports.jsx(I,{children:q.map(s=>e.jsxRuntimeExports.jsx($,{value:String(s),children:s},s))})]}),e.jsxRuntimeExports.jsx("span",{className:"text-sm text-muted-foreground",children:"条"})]}),e.jsxRuntimeExports.jsxs("div",{className:"mr-4 text-sm text-muted-foreground",children:["第 ",t+1," 页,共 ",i," 页"]}),e.jsxRuntimeExports.jsx(o,{variant:"outline",size:"icon",onClick:()=>c(t-1),disabled:t===0||!u,"aria-label":"上一页",children:e.jsxRuntimeExports.jsx(b.ChevronLeft,{className:"h-4 w-4"})}),e.jsxRuntimeExports.jsx("div",{className:"flex items-center gap-1",children:B.map((s,n)=>s==="ellipsis"?e.jsxRuntimeExports.jsx("span",{className:"inline-flex h-8 w-8 items-center justify-center text-sm text-muted-foreground",children:"..."},`ellipsis-${n}`):e.jsxRuntimeExports.jsx(o,{variant:s===t?"default":"outline",size:"sm",onClick:()=>c(s),disabled:s===t,"aria-current":s===t?"page":void 0,children:s+1},s))}),e.jsxRuntimeExports.jsx(o,{variant:"outline",size:"icon",onClick:()=>c(t+1),disabled:t>=i-1||!u,"aria-label":"下一页",children:e.jsxRuntimeExports.jsx(b.ChevronRight,{className:"h-4 w-4"})}),g&&e.jsxRuntimeExports.jsxs("form",{className:"ml-1 flex items-center gap-2",onSubmit:s=>{s.preventDefault();const n=Number.parseInt(f,10);Number.isNaN(n)||c(n-1)},children:[e.jsxRuntimeExports.jsx("span",{className:"text-sm text-muted-foreground",children:"跳至"}),e.jsxRuntimeExports.jsx("input",{type:"number",min:1,max:i,value:f,disabled:!u,onChange:s=>h(s.target.value),className:"h-8 w-16 rounded-md border border-input bg-background px-2 text-sm","aria-label":"跳转页码"}),e.jsxRuntimeExports.jsx(o,{type:"submit",variant:"outline",size:"sm",disabled:!u,children:"跳转"})]})]})]})}exports.TablePagination=O;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./jsx-runtime-BB_1_6y_.cjs"),v=require("lucide-react"),R=require("react");function z({currentPage:t,pageSize:l,total:a,onPageChange:E,onPageSizeChange:d,pageSizeOptions:N=[10,20,50],showPageSizeSelector:w=!0,showJumpToPage:y=!0,showTotal:p=!0,searchActive:S=!1,components:j}){const[f,h]=R.useState(String(t+1));if(R.useEffect(()=>{h(String(t+1))},[t]),!j)return e.jsxRuntimeExports.jsx("div",{className:"p-4 text-center text-destructive",children:"错误:请通过 components prop 注入 UI 组件"});const{Button:x,Select:I,SelectGroup:b,SelectTrigger:C,SelectContent:$,SelectItem:M,SelectValue:k}=j,T=Math.ceil(a/l),i=Math.max(T,1),q=t*l+1,A=Math.min((t+1)*l,a),B=Array.from(new Set([...N,l])).sort((s,n)=>s-n),O=w&&!!d,u=i>1,g=B.map(s=>e.jsxRuntimeExports.jsx(M,{value:String(s),children:s},s)),c=s=>{const n=Math.max(0,Math.min(s,i-1));n!==t&&E(n)},V=(()=>{if(i<=7)return Array.from({length:i},(r,m)=>m);const s=new Set([0,1,i-2,i-1,t-1,t,t+1]),n=Array.from(s).filter(r=>r>=0&&r<i).sort((r,m)=>r-m),o=[];for(const r of n){const m=o[o.length-1];typeof m=="number"&&r-m>1&&o.push("ellipsis"),o.push(r)}return o})();return a===0?null:e.jsxRuntimeExports.jsxs("div",{className:`flex w-full min-w-0 flex-col gap-3 md:flex-row md:items-center ${p?"justify-between":"justify-end"}`,children:[p&&e.jsxRuntimeExports.jsx("div",{className:"min-w-0 text-sm text-muted-foreground",children:S?`找到 ${a} 条匹配记录`:a>0?`显示 ${q} - ${A} 条,共 ${a} 条记录`:"暂无数据"}),e.jsxRuntimeExports.jsxs("div",{className:"flex w-full flex-wrap items-center justify-start gap-2 md:w-auto md:justify-end",children:[O&&e.jsxRuntimeExports.jsxs("div",{className:"mr-0 flex items-center gap-2 md:mr-2",children:[e.jsxRuntimeExports.jsx("span",{className:"text-sm text-muted-foreground",children:"每页"}),e.jsxRuntimeExports.jsxs(I,{value:String(l),onValueChange:s=>{const n=Number(s);Number.isNaN(n)||n===l||!d||d(n)},children:[e.jsxRuntimeExports.jsx(C,{className:"h-8 w-[90px]",children:e.jsxRuntimeExports.jsx(k,{})}),e.jsxRuntimeExports.jsx($,{children:b?e.jsxRuntimeExports.jsx(b,{children:g}):g})]}),e.jsxRuntimeExports.jsx("span",{className:"text-sm text-muted-foreground",children:"条"})]}),e.jsxRuntimeExports.jsxs("div",{className:"mr-0 text-sm tabular-nums text-muted-foreground md:mr-4",children:["第 ",t+1," 页,共 ",i," 页"]}),e.jsxRuntimeExports.jsx(x,{variant:"outline",size:"icon",onClick:()=>c(t-1),disabled:t===0||!u,"aria-label":"上一页",children:e.jsxRuntimeExports.jsx(v.ChevronLeft,{className:"h-4 w-4"})}),e.jsxRuntimeExports.jsx("div",{className:"flex items-center gap-1",children:V.map((s,n)=>s==="ellipsis"?e.jsxRuntimeExports.jsx("span",{className:"inline-flex h-8 w-8 items-center justify-center text-sm text-muted-foreground","aria-hidden":"true",children:""},`ellipsis-${n}`):e.jsxRuntimeExports.jsx(x,{variant:s===t?"default":"outline",size:"sm",onClick:()=>c(s),disabled:s===t,"aria-current":s===t?"page":void 0,className:"min-w-8 tabular-nums",children:s+1},s))}),e.jsxRuntimeExports.jsx(x,{variant:"outline",size:"icon",onClick:()=>c(t+1),disabled:t>=i-1||!u,"aria-label":"下一页",children:e.jsxRuntimeExports.jsx(v.ChevronRight,{className:"h-4 w-4"})}),y&&e.jsxRuntimeExports.jsxs("form",{className:"ml-1 flex items-center gap-2",onSubmit:s=>{s.preventDefault();const n=Number.parseInt(f,10);Number.isNaN(n)||c(n-1)},children:[e.jsxRuntimeExports.jsx("span",{className:"text-sm text-muted-foreground",children:"跳至"}),e.jsxRuntimeExports.jsx("input",{type:"number",name:"jumpPage",min:1,max:i,value:f,disabled:!u,onChange:s=>h(s.target.value),className:"h-8 w-16 rounded-md border border-input bg-background px-2 text-sm tabular-nums shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50","aria-label":"跳转页码",inputMode:"numeric",autoComplete:"off"}),e.jsxRuntimeExports.jsx(x,{type:"submit",variant:"outline",size:"sm",disabled:!u,children:"跳转"})]})]})]})}exports.TablePagination=z;
2
2
  //# sourceMappingURL=table-pagination.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"table-pagination.cjs","sources":["../src/components/TablePagination.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\nimport type {\n ButtonComponent,\n SelectComponent,\n SelectTriggerComponent,\n SelectContentComponent,\n SelectItemComponent,\n SelectValueComponent,\n} from '../types/component-types';\n\n/**\n * UI 组件适配器接口\n */\nexport interface PaginationUIComponents {\n Button: ButtonComponent;\n Select: SelectComponent;\n SelectTrigger: SelectTriggerComponent;\n SelectContent: SelectContentComponent;\n SelectItem: SelectItemComponent;\n SelectValue: SelectValueComponent;\n}\n\nexport interface TablePaginationProps {\n currentPage: number;\n pageSize: number;\n total: number;\n onPageChange: (page: number) => void;\n onPageSizeChange?: (pageSize: number) => void;\n pageSizeOptions?: number[];\n showPageSizeSelector?: boolean;\n showJumpToPage?: boolean;\n showTotal?: boolean;\n searchActive?: boolean;\n\n // UI 组件注入\n components?: PaginationUIComponents;\n}\n\n/**\n * 表格分页组件\n * 支持页码切换和每页条数选择\n */\nexport function TablePagination({\n currentPage,\n pageSize,\n total,\n onPageChange,\n onPageSizeChange,\n pageSizeOptions = [10, 20, 50],\n showPageSizeSelector = true,\n showJumpToPage = true,\n showTotal = true,\n searchActive = false,\n components,\n}: TablePaginationProps) {\n const [jumpPageInput, setJumpPageInput] = useState(String(currentPage + 1));\n\n useEffect(() => {\n setJumpPageInput(String(currentPage + 1));\n }, [currentPage]);\n\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n const {\n Button,\n Select,\n SelectTrigger,\n SelectContent,\n SelectItem,\n SelectValue,\n } = components;\n\n const totalPages = Math.ceil(total / pageSize);\n const safeTotalPages = Math.max(totalPages, 1);\n const startItem = currentPage * pageSize + 1;\n const endItem = Math.min((currentPage + 1) * pageSize, total);\n const availablePageSizeOptions = Array.from(\n new Set([...pageSizeOptions, pageSize])\n ).sort((a, b) => a - b);\n const canChangePageSize = showPageSizeSelector && Boolean(onPageSizeChange);\n const canSwitchPage = safeTotalPages > 1;\n\n const goToPage = (page: number) => {\n const nextPage = Math.max(0, Math.min(page, safeTotalPages - 1));\n if (nextPage === currentPage) {\n return;\n }\n onPageChange(nextPage);\n };\n\n const pageIndicators = (() => {\n if (safeTotalPages <= 7) {\n return Array.from({ length: safeTotalPages }, (_, index) => index);\n }\n\n const pages = new Set<number>([\n 0,\n 1,\n safeTotalPages - 2,\n safeTotalPages - 1,\n currentPage - 1,\n currentPage,\n currentPage + 1,\n ]);\n\n const visiblePages = Array.from(pages)\n .filter((page) => page >= 0 && page < safeTotalPages)\n .sort((a, b) => a - b);\n const indicators: Array<number | 'ellipsis'> = [];\n\n for (const page of visiblePages) {\n const previous = indicators[indicators.length - 1];\n if (typeof previous === 'number' && page - previous > 1) {\n indicators.push('ellipsis');\n }\n indicators.push(page);\n }\n\n return indicators;\n })();\n\n // 如果没有数据,不显示分页\n if (total === 0) return null;\n\n return (\n <div\n className={`flex w-full items-center gap-3 ${\n showTotal ? 'justify-between' : 'justify-end'\n }`}\n >\n {showTotal && (\n <div className=\"text-sm text-muted-foreground\">\n {searchActive\n ? `找到 ${total} 条匹配记录`\n : total > 0\n ? `显示 ${startItem} - ${endItem} 条,共 ${total} 条记录`\n : '暂无数据'}\n </div>\n )}\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {canChangePageSize && (\n <div className=\"mr-2 flex items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">每页</span>\n <Select\n value={String(pageSize)}\n onValueChange={(value: string) => {\n const nextPageSize = Number(value);\n if (\n Number.isNaN(nextPageSize) ||\n nextPageSize === pageSize ||\n !onPageSizeChange\n ) {\n return;\n }\n onPageSizeChange(nextPageSize);\n }}\n >\n <SelectTrigger className=\"h-8 w-[90px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {availablePageSizeOptions.map((option) => (\n <SelectItem key={option} value={String(option)}>\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <span className=\"text-sm text-muted-foreground\">条</span>\n </div>\n )}\n <div className=\"mr-4 text-sm text-muted-foreground\">\n 第 {currentPage + 1} 页,共 {safeTotalPages} 页\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage - 1)}\n disabled={currentPage === 0 || !canSwitchPage}\n aria-label=\"上一页\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n <div className=\"flex items-center gap-1\">\n {pageIndicators.map((indicator, index) =>\n indicator === 'ellipsis' ? (\n <span\n key={`ellipsis-${index}`}\n className=\"inline-flex h-8 w-8 items-center justify-center text-sm text-muted-foreground\"\n >\n ...\n </span>\n ) : (\n <Button\n key={indicator}\n variant={indicator === currentPage ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => goToPage(indicator)}\n disabled={indicator === currentPage}\n aria-current={indicator === currentPage ? 'page' : undefined}\n >\n {indicator + 1}\n </Button>\n )\n )}\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage + 1)}\n disabled={currentPage >= safeTotalPages - 1 || !canSwitchPage}\n aria-label=\"下一页\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n {showJumpToPage && (\n <form\n className=\"ml-1 flex items-center gap-2\"\n onSubmit={(event) => {\n event.preventDefault();\n const nextPage = Number.parseInt(jumpPageInput, 10);\n if (Number.isNaN(nextPage)) {\n return;\n }\n goToPage(nextPage - 1);\n }}\n >\n <span className=\"text-sm text-muted-foreground\">跳至</span>\n <input\n type=\"number\"\n min={1}\n max={safeTotalPages}\n value={jumpPageInput}\n disabled={!canSwitchPage}\n onChange={(event) => setJumpPageInput(event.target.value)}\n className=\"h-8 w-16 rounded-md border border-input bg-background px-2 text-sm\"\n aria-label=\"跳转页码\"\n />\n <Button\n type=\"submit\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!canSwitchPage}\n >\n 跳转\n </Button>\n </form>\n )}\n </div>\n </div>\n );\n}\n"],"names":["TablePagination","currentPage","pageSize","total","onPageChange","onPageSizeChange","pageSizeOptions","showPageSizeSelector","showJumpToPage","showTotal","searchActive","components","jumpPageInput","setJumpPageInput","useState","useEffect","jsx","Button","Select","SelectTrigger","SelectContent","SelectItem","SelectValue","totalPages","safeTotalPages","startItem","endItem","availablePageSizeOptions","a","b","canChangePageSize","canSwitchPage","goToPage","page","nextPage","pageIndicators","_","index","pages","visiblePages","indicators","previous","jsxs","value","nextPageSize","option","ChevronLeft","indicator","ChevronRight","event"],"mappings":"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"}
1
+ {"version":3,"file":"table-pagination.cjs","sources":["../src/components/TablePagination.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\nimport type {\n ButtonComponent,\n SelectComponent,\n SelectGroupComponent,\n SelectTriggerComponent,\n SelectContentComponent,\n SelectItemComponent,\n SelectValueComponent,\n} from '../types/component-types';\n\n/**\n * UI 组件适配器接口\n */\nexport interface PaginationUIComponents {\n Button: ButtonComponent;\n Select: SelectComponent;\n SelectGroup?: SelectGroupComponent;\n SelectTrigger: SelectTriggerComponent;\n SelectContent: SelectContentComponent;\n SelectItem: SelectItemComponent;\n SelectValue: SelectValueComponent;\n}\n\nexport interface TablePaginationProps {\n currentPage: number;\n pageSize: number;\n total: number;\n onPageChange: (page: number) => void;\n onPageSizeChange?: (pageSize: number) => void;\n pageSizeOptions?: number[];\n showPageSizeSelector?: boolean;\n showJumpToPage?: boolean;\n showTotal?: boolean;\n searchActive?: boolean;\n\n // UI 组件注入\n components?: PaginationUIComponents;\n}\n\n/**\n * 表格分页组件\n * 支持页码切换和每页条数选择\n */\nexport function TablePagination({\n currentPage,\n pageSize,\n total,\n onPageChange,\n onPageSizeChange,\n pageSizeOptions = [10, 20, 50],\n showPageSizeSelector = true,\n showJumpToPage = true,\n showTotal = true,\n searchActive = false,\n components,\n}: TablePaginationProps) {\n const [jumpPageInput, setJumpPageInput] = useState(String(currentPage + 1));\n\n useEffect(() => {\n setJumpPageInput(String(currentPage + 1));\n }, [currentPage]);\n\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n const {\n Button,\n Select,\n SelectGroup,\n SelectTrigger,\n SelectContent,\n SelectItem,\n SelectValue,\n } = components;\n\n const totalPages = Math.ceil(total / pageSize);\n const safeTotalPages = Math.max(totalPages, 1);\n const startItem = currentPage * pageSize + 1;\n const endItem = Math.min((currentPage + 1) * pageSize, total);\n const availablePageSizeOptions = Array.from(\n new Set([...pageSizeOptions, pageSize])\n ).sort((a, b) => a - b);\n const canChangePageSize = showPageSizeSelector && Boolean(onPageSizeChange);\n const canSwitchPage = safeTotalPages > 1;\n const pageSizeItems = availablePageSizeOptions.map((option) => (\n <SelectItem key={option} value={String(option)}>\n {option}\n </SelectItem>\n ));\n\n const goToPage = (page: number) => {\n const nextPage = Math.max(0, Math.min(page, safeTotalPages - 1));\n if (nextPage === currentPage) {\n return;\n }\n onPageChange(nextPage);\n };\n\n const pageIndicators = (() => {\n if (safeTotalPages <= 7) {\n return Array.from({ length: safeTotalPages }, (_, index) => index);\n }\n\n const pages = new Set<number>([\n 0,\n 1,\n safeTotalPages - 2,\n safeTotalPages - 1,\n currentPage - 1,\n currentPage,\n currentPage + 1,\n ]);\n\n const visiblePages = Array.from(pages)\n .filter((page) => page >= 0 && page < safeTotalPages)\n .sort((a, b) => a - b);\n const indicators: Array<number | 'ellipsis'> = [];\n\n for (const page of visiblePages) {\n const previous = indicators[indicators.length - 1];\n if (typeof previous === 'number' && page - previous > 1) {\n indicators.push('ellipsis');\n }\n indicators.push(page);\n }\n\n return indicators;\n })();\n\n // 如果没有数据,不显示分页\n if (total === 0) return null;\n\n return (\n <div\n className={`flex w-full min-w-0 flex-col gap-3 md:flex-row md:items-center ${\n showTotal ? 'justify-between' : 'justify-end'\n }`}\n >\n {showTotal && (\n <div className=\"min-w-0 text-sm text-muted-foreground\">\n {searchActive\n ? `找到 ${total} 条匹配记录`\n : total > 0\n ? `显示 ${startItem} - ${endItem} 条,共 ${total} 条记录`\n : '暂无数据'}\n </div>\n )}\n <div className=\"flex w-full flex-wrap items-center justify-start gap-2 md:w-auto md:justify-end\">\n {canChangePageSize && (\n <div className=\"mr-0 flex items-center gap-2 md:mr-2\">\n <span className=\"text-sm text-muted-foreground\">每页</span>\n <Select\n value={String(pageSize)}\n onValueChange={(value: string) => {\n const nextPageSize = Number(value);\n if (\n Number.isNaN(nextPageSize) ||\n nextPageSize === pageSize ||\n !onPageSizeChange\n ) {\n return;\n }\n onPageSizeChange(nextPageSize);\n }}\n >\n <SelectTrigger className=\"h-8 w-[90px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SelectGroup ? (\n <SelectGroup>{pageSizeItems}</SelectGroup>\n ) : (\n pageSizeItems\n )}\n </SelectContent>\n </Select>\n <span className=\"text-sm text-muted-foreground\">条</span>\n </div>\n )}\n <div className=\"mr-0 text-sm tabular-nums text-muted-foreground md:mr-4\">\n 第 {currentPage + 1} 页,共 {safeTotalPages} 页\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage - 1)}\n disabled={currentPage === 0 || !canSwitchPage}\n aria-label=\"上一页\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n <div className=\"flex items-center gap-1\">\n {pageIndicators.map((indicator, index) =>\n indicator === 'ellipsis' ? (\n <span\n key={`ellipsis-${index}`}\n className=\"inline-flex h-8 w-8 items-center justify-center text-sm text-muted-foreground\"\n aria-hidden=\"true\"\n >\n …\n </span>\n ) : (\n <Button\n key={indicator}\n variant={indicator === currentPage ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => goToPage(indicator)}\n disabled={indicator === currentPage}\n aria-current={indicator === currentPage ? 'page' : undefined}\n className=\"min-w-8 tabular-nums\"\n >\n {indicator + 1}\n </Button>\n )\n )}\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage + 1)}\n disabled={currentPage >= safeTotalPages - 1 || !canSwitchPage}\n aria-label=\"下一页\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n {showJumpToPage && (\n <form\n className=\"ml-1 flex items-center gap-2\"\n onSubmit={(event) => {\n event.preventDefault();\n const nextPage = Number.parseInt(jumpPageInput, 10);\n if (Number.isNaN(nextPage)) {\n return;\n }\n goToPage(nextPage - 1);\n }}\n >\n <span className=\"text-sm text-muted-foreground\">跳至</span>\n <input\n type=\"number\"\n name=\"jumpPage\"\n min={1}\n max={safeTotalPages}\n value={jumpPageInput}\n disabled={!canSwitchPage}\n onChange={(event) => setJumpPageInput(event.target.value)}\n className=\"h-8 w-16 rounded-md border border-input bg-background px-2 text-sm tabular-nums shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50\"\n aria-label=\"跳转页码\"\n inputMode=\"numeric\"\n autoComplete=\"off\"\n />\n <Button\n type=\"submit\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!canSwitchPage}\n >\n 跳转\n </Button>\n </form>\n )}\n </div>\n </div>\n );\n}\n"],"names":["TablePagination","currentPage","pageSize","total","onPageChange","onPageSizeChange","pageSizeOptions","showPageSizeSelector","showJumpToPage","showTotal","searchActive","components","jumpPageInput","setJumpPageInput","useState","useEffect","jsx","Button","Select","SelectGroup","SelectTrigger","SelectContent","SelectItem","SelectValue","totalPages","safeTotalPages","startItem","endItem","availablePageSizeOptions","a","b","canChangePageSize","canSwitchPage","pageSizeItems","option","goToPage","page","nextPage","pageIndicators","_","index","pages","visiblePages","indicators","previous","jsxs","value","nextPageSize","ChevronLeft","indicator","ChevronRight","event"],"mappings":"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"}
@@ -1,37 +1,38 @@
1
1
  import { j as e } from "./jsx-runtime-B4hRZ52C.js";
2
- import { ChevronLeft as R, ChevronRight as V } from "lucide-react";
3
- import { useState as D, useEffect as J } from "react";
2
+ import { ChevronLeft as z, ChevronRight as D } from "lucide-react";
3
+ import { useState as G, useEffect as J } from "react";
4
4
  function _({
5
5
  currentPage: t,
6
6
  pageSize: a,
7
7
  total: r,
8
- onPageChange: b,
9
- onPageSizeChange: u,
8
+ onPageChange: g,
9
+ onPageSizeChange: x,
10
10
  pageSizeOptions: N = [10, 20, 50],
11
- showPageSizeSelector: v = !0,
12
- showJumpToPage: g = !0,
11
+ showPageSizeSelector: w = !0,
12
+ showJumpToPage: y = !0,
13
13
  showTotal: f = !0,
14
- searchActive: w = !1,
15
- components: h
14
+ searchActive: S = !1,
15
+ components: p
16
16
  }) {
17
- const [p, j] = D(String(t + 1));
17
+ const [h, b] = G(String(t + 1));
18
18
  if (J(() => {
19
- j(String(t + 1));
20
- }, [t]), !h)
19
+ b(String(t + 1));
20
+ }, [t]), !p)
21
21
  return /* @__PURE__ */ e.jsx("div", { className: "p-4 text-center text-destructive", children: "错误:请通过 components prop 注入 UI 组件" });
22
22
  const {
23
23
  Button: c,
24
- Select: y,
25
- SelectTrigger: S,
26
- SelectContent: I,
27
- SelectItem: C,
28
- SelectValue: $
29
- } = h, M = Math.ceil(r / a), i = Math.max(M, 1), k = t * a + 1, A = Math.min((t + 1) * a, r), T = Array.from(
24
+ Select: I,
25
+ SelectGroup: j,
26
+ SelectTrigger: C,
27
+ SelectContent: M,
28
+ SelectItem: $,
29
+ SelectValue: k
30
+ } = p, A = Math.ceil(r / a), i = Math.max(A, 1), T = t * a + 1, B = Math.min((t + 1) * a, r), E = Array.from(
30
31
  /* @__PURE__ */ new Set([...N, a])
31
- ).sort((s, n) => s - n), B = v && !!u, d = i > 1, x = (s) => {
32
+ ).sort((s, n) => s - n), R = w && !!x, d = i > 1, v = E.map((s) => /* @__PURE__ */ e.jsx($, { value: String(s), children: s }, s)), u = (s) => {
32
33
  const n = Math.max(0, Math.min(s, i - 1));
33
- n !== t && b(n);
34
- }, E = (() => {
34
+ n !== t && g(n);
35
+ }, V = (() => {
35
36
  if (i <= 7)
36
37
  return Array.from({ length: i }, (l, m) => m);
37
38
  const s = /* @__PURE__ */ new Set([
@@ -52,29 +53,29 @@ function _({
52
53
  return r === 0 ? null : /* @__PURE__ */ e.jsxs(
53
54
  "div",
54
55
  {
55
- className: `flex w-full items-center gap-3 ${f ? "justify-between" : "justify-end"}`,
56
+ className: `flex w-full min-w-0 flex-col gap-3 md:flex-row md:items-center ${f ? "justify-between" : "justify-end"}`,
56
57
  children: [
57
- f && /* @__PURE__ */ e.jsx("div", { className: "text-sm text-muted-foreground", children: w ? `找到 ${r} 条匹配记录` : r > 0 ? `显示 ${k} - ${A} 条,共 ${r} 条记录` : "暂无数据" }),
58
- /* @__PURE__ */ e.jsxs("div", { className: "flex flex-wrap items-center justify-end gap-2", children: [
59
- B && /* @__PURE__ */ e.jsxs("div", { className: "mr-2 flex items-center gap-2", children: [
58
+ f && /* @__PURE__ */ e.jsx("div", { className: "min-w-0 text-sm text-muted-foreground", children: S ? `找到 ${r} 条匹配记录` : r > 0 ? `显示 ${T} - ${B} 条,共 ${r} 条记录` : "暂无数据" }),
59
+ /* @__PURE__ */ e.jsxs("div", { className: "flex w-full flex-wrap items-center justify-start gap-2 md:w-auto md:justify-end", children: [
60
+ R && /* @__PURE__ */ e.jsxs("div", { className: "mr-0 flex items-center gap-2 md:mr-2", children: [
60
61
  /* @__PURE__ */ e.jsx("span", { className: "text-sm text-muted-foreground", children: "每页" }),
61
62
  /* @__PURE__ */ e.jsxs(
62
- y,
63
+ I,
63
64
  {
64
65
  value: String(a),
65
66
  onValueChange: (s) => {
66
67
  const n = Number(s);
67
- Number.isNaN(n) || n === a || !u || u(n);
68
+ Number.isNaN(n) || n === a || !x || x(n);
68
69
  },
69
70
  children: [
70
- /* @__PURE__ */ e.jsx(S, { className: "h-8 w-[90px]", children: /* @__PURE__ */ e.jsx($, {}) }),
71
- /* @__PURE__ */ e.jsx(I, { children: T.map((s) => /* @__PURE__ */ e.jsx(C, { value: String(s), children: s }, s)) })
71
+ /* @__PURE__ */ e.jsx(C, { className: "h-8 w-[90px]", children: /* @__PURE__ */ e.jsx(k, {}) }),
72
+ /* @__PURE__ */ e.jsx(M, { children: j ? /* @__PURE__ */ e.jsx(j, { children: v }) : v })
72
73
  ]
73
74
  }
74
75
  ),
75
76
  /* @__PURE__ */ e.jsx("span", { className: "text-sm text-muted-foreground", children: "条" })
76
77
  ] }),
77
- /* @__PURE__ */ e.jsxs("div", { className: "mr-4 text-sm text-muted-foreground", children: [
78
+ /* @__PURE__ */ e.jsxs("div", { className: "mr-0 text-sm tabular-nums text-muted-foreground md:mr-4", children: [
78
79
  "第 ",
79
80
  t + 1,
80
81
  " 页,共 ",
@@ -86,18 +87,19 @@ function _({
86
87
  {
87
88
  variant: "outline",
88
89
  size: "icon",
89
- onClick: () => x(t - 1),
90
+ onClick: () => u(t - 1),
90
91
  disabled: t === 0 || !d,
91
92
  "aria-label": "上一页",
92
- children: /* @__PURE__ */ e.jsx(R, { className: "h-4 w-4" })
93
+ children: /* @__PURE__ */ e.jsx(z, { className: "h-4 w-4" })
93
94
  }
94
95
  ),
95
- /* @__PURE__ */ e.jsx("div", { className: "flex items-center gap-1", children: E.map(
96
+ /* @__PURE__ */ e.jsx("div", { className: "flex items-center gap-1", children: V.map(
96
97
  (s, n) => s === "ellipsis" ? /* @__PURE__ */ e.jsx(
97
98
  "span",
98
99
  {
99
100
  className: "inline-flex h-8 w-8 items-center justify-center text-sm text-muted-foreground",
100
- children: "..."
101
+ "aria-hidden": "true",
102
+ children: "…"
101
103
  },
102
104
  `ellipsis-${n}`
103
105
  ) : /* @__PURE__ */ e.jsx(
@@ -105,9 +107,10 @@ function _({
105
107
  {
106
108
  variant: s === t ? "default" : "outline",
107
109
  size: "sm",
108
- onClick: () => x(s),
110
+ onClick: () => u(s),
109
111
  disabled: s === t,
110
112
  "aria-current": s === t ? "page" : void 0,
113
+ className: "min-w-8 tabular-nums",
111
114
  children: s + 1
112
115
  },
113
116
  s
@@ -118,20 +121,20 @@ function _({
118
121
  {
119
122
  variant: "outline",
120
123
  size: "icon",
121
- onClick: () => x(t + 1),
124
+ onClick: () => u(t + 1),
122
125
  disabled: t >= i - 1 || !d,
123
126
  "aria-label": "下一页",
124
- children: /* @__PURE__ */ e.jsx(V, { className: "h-4 w-4" })
127
+ children: /* @__PURE__ */ e.jsx(D, { className: "h-4 w-4" })
125
128
  }
126
129
  ),
127
- g && /* @__PURE__ */ e.jsxs(
130
+ y && /* @__PURE__ */ e.jsxs(
128
131
  "form",
129
132
  {
130
133
  className: "ml-1 flex items-center gap-2",
131
134
  onSubmit: (s) => {
132
135
  s.preventDefault();
133
- const n = Number.parseInt(p, 10);
134
- Number.isNaN(n) || x(n - 1);
136
+ const n = Number.parseInt(h, 10);
137
+ Number.isNaN(n) || u(n - 1);
135
138
  },
136
139
  children: [
137
140
  /* @__PURE__ */ e.jsx("span", { className: "text-sm text-muted-foreground", children: "跳至" }),
@@ -139,13 +142,16 @@ function _({
139
142
  "input",
140
143
  {
141
144
  type: "number",
145
+ name: "jumpPage",
142
146
  min: 1,
143
147
  max: i,
144
- value: p,
148
+ value: h,
145
149
  disabled: !d,
146
- onChange: (s) => j(s.target.value),
147
- className: "h-8 w-16 rounded-md border border-input bg-background px-2 text-sm",
148
- "aria-label": "跳转页码"
150
+ onChange: (s) => b(s.target.value),
151
+ className: "h-8 w-16 rounded-md border border-input bg-background px-2 text-sm tabular-nums shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
152
+ "aria-label": "跳转页码",
153
+ inputMode: "numeric",
154
+ autoComplete: "off"
149
155
  }
150
156
  ),
151
157
  /* @__PURE__ */ e.jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"table-pagination.js","sources":["../src/components/TablePagination.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\nimport type {\n ButtonComponent,\n SelectComponent,\n SelectTriggerComponent,\n SelectContentComponent,\n SelectItemComponent,\n SelectValueComponent,\n} from '../types/component-types';\n\n/**\n * UI 组件适配器接口\n */\nexport interface PaginationUIComponents {\n Button: ButtonComponent;\n Select: SelectComponent;\n SelectTrigger: SelectTriggerComponent;\n SelectContent: SelectContentComponent;\n SelectItem: SelectItemComponent;\n SelectValue: SelectValueComponent;\n}\n\nexport interface TablePaginationProps {\n currentPage: number;\n pageSize: number;\n total: number;\n onPageChange: (page: number) => void;\n onPageSizeChange?: (pageSize: number) => void;\n pageSizeOptions?: number[];\n showPageSizeSelector?: boolean;\n showJumpToPage?: boolean;\n showTotal?: boolean;\n searchActive?: boolean;\n\n // UI 组件注入\n components?: PaginationUIComponents;\n}\n\n/**\n * 表格分页组件\n * 支持页码切换和每页条数选择\n */\nexport function TablePagination({\n currentPage,\n pageSize,\n total,\n onPageChange,\n onPageSizeChange,\n pageSizeOptions = [10, 20, 50],\n showPageSizeSelector = true,\n showJumpToPage = true,\n showTotal = true,\n searchActive = false,\n components,\n}: TablePaginationProps) {\n const [jumpPageInput, setJumpPageInput] = useState(String(currentPage + 1));\n\n useEffect(() => {\n setJumpPageInput(String(currentPage + 1));\n }, [currentPage]);\n\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n const {\n Button,\n Select,\n SelectTrigger,\n SelectContent,\n SelectItem,\n SelectValue,\n } = components;\n\n const totalPages = Math.ceil(total / pageSize);\n const safeTotalPages = Math.max(totalPages, 1);\n const startItem = currentPage * pageSize + 1;\n const endItem = Math.min((currentPage + 1) * pageSize, total);\n const availablePageSizeOptions = Array.from(\n new Set([...pageSizeOptions, pageSize])\n ).sort((a, b) => a - b);\n const canChangePageSize = showPageSizeSelector && Boolean(onPageSizeChange);\n const canSwitchPage = safeTotalPages > 1;\n\n const goToPage = (page: number) => {\n const nextPage = Math.max(0, Math.min(page, safeTotalPages - 1));\n if (nextPage === currentPage) {\n return;\n }\n onPageChange(nextPage);\n };\n\n const pageIndicators = (() => {\n if (safeTotalPages <= 7) {\n return Array.from({ length: safeTotalPages }, (_, index) => index);\n }\n\n const pages = new Set<number>([\n 0,\n 1,\n safeTotalPages - 2,\n safeTotalPages - 1,\n currentPage - 1,\n currentPage,\n currentPage + 1,\n ]);\n\n const visiblePages = Array.from(pages)\n .filter((page) => page >= 0 && page < safeTotalPages)\n .sort((a, b) => a - b);\n const indicators: Array<number | 'ellipsis'> = [];\n\n for (const page of visiblePages) {\n const previous = indicators[indicators.length - 1];\n if (typeof previous === 'number' && page - previous > 1) {\n indicators.push('ellipsis');\n }\n indicators.push(page);\n }\n\n return indicators;\n })();\n\n // 如果没有数据,不显示分页\n if (total === 0) return null;\n\n return (\n <div\n className={`flex w-full items-center gap-3 ${\n showTotal ? 'justify-between' : 'justify-end'\n }`}\n >\n {showTotal && (\n <div className=\"text-sm text-muted-foreground\">\n {searchActive\n ? `找到 ${total} 条匹配记录`\n : total > 0\n ? `显示 ${startItem} - ${endItem} 条,共 ${total} 条记录`\n : '暂无数据'}\n </div>\n )}\n <div className=\"flex flex-wrap items-center justify-end gap-2\">\n {canChangePageSize && (\n <div className=\"mr-2 flex items-center gap-2\">\n <span className=\"text-sm text-muted-foreground\">每页</span>\n <Select\n value={String(pageSize)}\n onValueChange={(value: string) => {\n const nextPageSize = Number(value);\n if (\n Number.isNaN(nextPageSize) ||\n nextPageSize === pageSize ||\n !onPageSizeChange\n ) {\n return;\n }\n onPageSizeChange(nextPageSize);\n }}\n >\n <SelectTrigger className=\"h-8 w-[90px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {availablePageSizeOptions.map((option) => (\n <SelectItem key={option} value={String(option)}>\n {option}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <span className=\"text-sm text-muted-foreground\">条</span>\n </div>\n )}\n <div className=\"mr-4 text-sm text-muted-foreground\">\n 第 {currentPage + 1} 页,共 {safeTotalPages} 页\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage - 1)}\n disabled={currentPage === 0 || !canSwitchPage}\n aria-label=\"上一页\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n <div className=\"flex items-center gap-1\">\n {pageIndicators.map((indicator, index) =>\n indicator === 'ellipsis' ? (\n <span\n key={`ellipsis-${index}`}\n className=\"inline-flex h-8 w-8 items-center justify-center text-sm text-muted-foreground\"\n >\n ...\n </span>\n ) : (\n <Button\n key={indicator}\n variant={indicator === currentPage ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => goToPage(indicator)}\n disabled={indicator === currentPage}\n aria-current={indicator === currentPage ? 'page' : undefined}\n >\n {indicator + 1}\n </Button>\n )\n )}\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage + 1)}\n disabled={currentPage >= safeTotalPages - 1 || !canSwitchPage}\n aria-label=\"下一页\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n {showJumpToPage && (\n <form\n className=\"ml-1 flex items-center gap-2\"\n onSubmit={(event) => {\n event.preventDefault();\n const nextPage = Number.parseInt(jumpPageInput, 10);\n if (Number.isNaN(nextPage)) {\n return;\n }\n goToPage(nextPage - 1);\n }}\n >\n <span className=\"text-sm text-muted-foreground\">跳至</span>\n <input\n type=\"number\"\n min={1}\n max={safeTotalPages}\n value={jumpPageInput}\n disabled={!canSwitchPage}\n onChange={(event) => setJumpPageInput(event.target.value)}\n className=\"h-8 w-16 rounded-md border border-input bg-background px-2 text-sm\"\n aria-label=\"跳转页码\"\n />\n <Button\n type=\"submit\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!canSwitchPage}\n >\n 跳转\n </Button>\n </form>\n )}\n </div>\n </div>\n );\n}\n"],"names":["TablePagination","currentPage","pageSize","total","onPageChange","onPageSizeChange","pageSizeOptions","showPageSizeSelector","showJumpToPage","showTotal","searchActive","components","jumpPageInput","setJumpPageInput","useState","useEffect","jsx","Button","Select","SelectTrigger","SelectContent","SelectItem","SelectValue","totalPages","safeTotalPages","startItem","endItem","availablePageSizeOptions","a","b","canChangePageSize","canSwitchPage","goToPage","page","nextPage","pageIndicators","_","index","pages","visiblePages","indicators","previous","jsxs","value","nextPageSize","option","ChevronLeft","indicator","ChevronRight","event"],"mappings":"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"}
1
+ {"version":3,"file":"table-pagination.js","sources":["../src/components/TablePagination.tsx"],"sourcesContent":["import { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { useEffect, useState } from 'react';\n\nimport type {\n ButtonComponent,\n SelectComponent,\n SelectGroupComponent,\n SelectTriggerComponent,\n SelectContentComponent,\n SelectItemComponent,\n SelectValueComponent,\n} from '../types/component-types';\n\n/**\n * UI 组件适配器接口\n */\nexport interface PaginationUIComponents {\n Button: ButtonComponent;\n Select: SelectComponent;\n SelectGroup?: SelectGroupComponent;\n SelectTrigger: SelectTriggerComponent;\n SelectContent: SelectContentComponent;\n SelectItem: SelectItemComponent;\n SelectValue: SelectValueComponent;\n}\n\nexport interface TablePaginationProps {\n currentPage: number;\n pageSize: number;\n total: number;\n onPageChange: (page: number) => void;\n onPageSizeChange?: (pageSize: number) => void;\n pageSizeOptions?: number[];\n showPageSizeSelector?: boolean;\n showJumpToPage?: boolean;\n showTotal?: boolean;\n searchActive?: boolean;\n\n // UI 组件注入\n components?: PaginationUIComponents;\n}\n\n/**\n * 表格分页组件\n * 支持页码切换和每页条数选择\n */\nexport function TablePagination({\n currentPage,\n pageSize,\n total,\n onPageChange,\n onPageSizeChange,\n pageSizeOptions = [10, 20, 50],\n showPageSizeSelector = true,\n showJumpToPage = true,\n showTotal = true,\n searchActive = false,\n components,\n}: TablePaginationProps) {\n const [jumpPageInput, setJumpPageInput] = useState(String(currentPage + 1));\n\n useEffect(() => {\n setJumpPageInput(String(currentPage + 1));\n }, [currentPage]);\n\n if (!components) {\n return (\n <div className=\"p-4 text-center text-destructive\">\n 错误:请通过 components prop 注入 UI 组件\n </div>\n );\n }\n\n const {\n Button,\n Select,\n SelectGroup,\n SelectTrigger,\n SelectContent,\n SelectItem,\n SelectValue,\n } = components;\n\n const totalPages = Math.ceil(total / pageSize);\n const safeTotalPages = Math.max(totalPages, 1);\n const startItem = currentPage * pageSize + 1;\n const endItem = Math.min((currentPage + 1) * pageSize, total);\n const availablePageSizeOptions = Array.from(\n new Set([...pageSizeOptions, pageSize])\n ).sort((a, b) => a - b);\n const canChangePageSize = showPageSizeSelector && Boolean(onPageSizeChange);\n const canSwitchPage = safeTotalPages > 1;\n const pageSizeItems = availablePageSizeOptions.map((option) => (\n <SelectItem key={option} value={String(option)}>\n {option}\n </SelectItem>\n ));\n\n const goToPage = (page: number) => {\n const nextPage = Math.max(0, Math.min(page, safeTotalPages - 1));\n if (nextPage === currentPage) {\n return;\n }\n onPageChange(nextPage);\n };\n\n const pageIndicators = (() => {\n if (safeTotalPages <= 7) {\n return Array.from({ length: safeTotalPages }, (_, index) => index);\n }\n\n const pages = new Set<number>([\n 0,\n 1,\n safeTotalPages - 2,\n safeTotalPages - 1,\n currentPage - 1,\n currentPage,\n currentPage + 1,\n ]);\n\n const visiblePages = Array.from(pages)\n .filter((page) => page >= 0 && page < safeTotalPages)\n .sort((a, b) => a - b);\n const indicators: Array<number | 'ellipsis'> = [];\n\n for (const page of visiblePages) {\n const previous = indicators[indicators.length - 1];\n if (typeof previous === 'number' && page - previous > 1) {\n indicators.push('ellipsis');\n }\n indicators.push(page);\n }\n\n return indicators;\n })();\n\n // 如果没有数据,不显示分页\n if (total === 0) return null;\n\n return (\n <div\n className={`flex w-full min-w-0 flex-col gap-3 md:flex-row md:items-center ${\n showTotal ? 'justify-between' : 'justify-end'\n }`}\n >\n {showTotal && (\n <div className=\"min-w-0 text-sm text-muted-foreground\">\n {searchActive\n ? `找到 ${total} 条匹配记录`\n : total > 0\n ? `显示 ${startItem} - ${endItem} 条,共 ${total} 条记录`\n : '暂无数据'}\n </div>\n )}\n <div className=\"flex w-full flex-wrap items-center justify-start gap-2 md:w-auto md:justify-end\">\n {canChangePageSize && (\n <div className=\"mr-0 flex items-center gap-2 md:mr-2\">\n <span className=\"text-sm text-muted-foreground\">每页</span>\n <Select\n value={String(pageSize)}\n onValueChange={(value: string) => {\n const nextPageSize = Number(value);\n if (\n Number.isNaN(nextPageSize) ||\n nextPageSize === pageSize ||\n !onPageSizeChange\n ) {\n return;\n }\n onPageSizeChange(nextPageSize);\n }}\n >\n <SelectTrigger className=\"h-8 w-[90px]\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SelectGroup ? (\n <SelectGroup>{pageSizeItems}</SelectGroup>\n ) : (\n pageSizeItems\n )}\n </SelectContent>\n </Select>\n <span className=\"text-sm text-muted-foreground\">条</span>\n </div>\n )}\n <div className=\"mr-0 text-sm tabular-nums text-muted-foreground md:mr-4\">\n 第 {currentPage + 1} 页,共 {safeTotalPages} 页\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage - 1)}\n disabled={currentPage === 0 || !canSwitchPage}\n aria-label=\"上一页\"\n >\n <ChevronLeft className=\"h-4 w-4\" />\n </Button>\n <div className=\"flex items-center gap-1\">\n {pageIndicators.map((indicator, index) =>\n indicator === 'ellipsis' ? (\n <span\n key={`ellipsis-${index}`}\n className=\"inline-flex h-8 w-8 items-center justify-center text-sm text-muted-foreground\"\n aria-hidden=\"true\"\n >\n …\n </span>\n ) : (\n <Button\n key={indicator}\n variant={indicator === currentPage ? 'default' : 'outline'}\n size=\"sm\"\n onClick={() => goToPage(indicator)}\n disabled={indicator === currentPage}\n aria-current={indicator === currentPage ? 'page' : undefined}\n className=\"min-w-8 tabular-nums\"\n >\n {indicator + 1}\n </Button>\n )\n )}\n </div>\n <Button\n variant=\"outline\"\n size=\"icon\"\n onClick={() => goToPage(currentPage + 1)}\n disabled={currentPage >= safeTotalPages - 1 || !canSwitchPage}\n aria-label=\"下一页\"\n >\n <ChevronRight className=\"h-4 w-4\" />\n </Button>\n {showJumpToPage && (\n <form\n className=\"ml-1 flex items-center gap-2\"\n onSubmit={(event) => {\n event.preventDefault();\n const nextPage = Number.parseInt(jumpPageInput, 10);\n if (Number.isNaN(nextPage)) {\n return;\n }\n goToPage(nextPage - 1);\n }}\n >\n <span className=\"text-sm text-muted-foreground\">跳至</span>\n <input\n type=\"number\"\n name=\"jumpPage\"\n min={1}\n max={safeTotalPages}\n value={jumpPageInput}\n disabled={!canSwitchPage}\n onChange={(event) => setJumpPageInput(event.target.value)}\n className=\"h-8 w-16 rounded-md border border-input bg-background px-2 text-sm tabular-nums shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50\"\n aria-label=\"跳转页码\"\n inputMode=\"numeric\"\n autoComplete=\"off\"\n />\n <Button\n type=\"submit\"\n variant=\"outline\"\n size=\"sm\"\n disabled={!canSwitchPage}\n >\n 跳转\n </Button>\n </form>\n )}\n </div>\n </div>\n );\n}\n"],"names":["TablePagination","currentPage","pageSize","total","onPageChange","onPageSizeChange","pageSizeOptions","showPageSizeSelector","showJumpToPage","showTotal","searchActive","components","jumpPageInput","setJumpPageInput","useState","useEffect","jsx","Button","Select","SelectGroup","SelectTrigger","SelectContent","SelectItem","SelectValue","totalPages","safeTotalPages","startItem","endItem","availablePageSizeOptions","a","b","canChangePageSize","canSwitchPage","pageSizeItems","option","goToPage","page","nextPage","pageIndicators","_","index","pages","visiblePages","indicators","previous","jsxs","value","nextPageSize","ChevronLeft","indicator","ChevronRight","event"],"mappings":"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"}
@@ -45,6 +45,7 @@ export interface SelectComponentProps extends UIComponentProps {
45
45
  children?: React.ReactNode;
46
46
  }
47
47
  export type SelectComponent = UIComponent<SelectComponentProps>;
48
+ export type SelectGroupComponent = UIComponent<HTMLAttributes<HTMLDivElement>>;
48
49
  export type SelectTriggerComponent = UIComponent<ButtonHTMLAttributes<HTMLButtonElement> & {
49
50
  asChild?: boolean;
50
51
  }>;
@@ -110,6 +111,7 @@ export type TabsComponent = UIComponent<{
110
111
  onValueChange?: (value: string) => void;
111
112
  children?: React.ReactNode;
112
113
  defaultValue?: string;
114
+ className?: string;
113
115
  }>;
114
116
  export type TabsListComponent = UIComponent<HTMLAttributes<HTMLDivElement>>;
115
117
  export type TabsTriggerComponent = UIComponent<HTMLAttributes<HTMLButtonElement> & {
@@ -1 +1 @@
1
- {"version":3,"file":"component-types.d.ts","sourceRoot":"","sources":["../../src/types/component-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component-types.d.ts","sourceRoot":"","sources":["../../src/types/component-types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./jsx-runtime-BB_1_6y_.cjs"),r=require("react"),W=require("lucide-react"),p=require("./utils-IjLH3w2e.cjs"),O=require("./media-utils-X1dDYP9W.cjs"),P=["mp4","webm","ogg","ogv","mov","m4v"],_=["video/mp4","video/webm","video/ogg","video/quicktime","video/x-m4v"],Z=s=>s?s instanceof Error?s:new Error(s):null;function ee({src:s,fileName:o,mimeType:i,title:j,components:y,tracks:u,loading:I=!1,error:V,className:E,containerClassName:M,videoClassName:q,toolbarClassName:U,loadingText:D="正在加载视频...",errorText:f="视频加载失败",unsupportedText:T="暂不支持该视频格式",showToolbar:C=!0,showOpenInNewTab:$=!0,allowUnsupportedFormat:k=!1,supportedExtensions:L=P,supportedMimeTypes:z=_,controls:B=!0,preload:F="metadata",playsInline:X=!0,onLoadedData:l,onError:x,...Y}){const{Card:R,CardContent:g,Button:h,Skeleton:a}=y||{},[A,d]=r.useState(!0),[G,c]=r.useState(null),n=Z(V)||G,v=k||O.isSupportedMediaSource({src:s,fileName:o,mimeType:i,supportedExtensions:L,supportedMimeTypes:z}),b=I||A&&!n,H=r.useMemo(()=>{const t=O.getMediaExtension(s,o);return t?t.toUpperCase():i||"视频"},[o,i,s]);r.useEffect(()=>{d(!0),c(null)},[s]);const J=(t,S,N)=>{const Q="inline-flex h-8 w-8 items-center justify-center rounded-md border border-input bg-background text-foreground shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground";return h?e.jsxRuntimeExports.jsx(h,{"aria-label":t,className:"h-8 w-8",onClick:N,size:"icon",title:t,type:"button",variant:"outline",children:S}):e.jsxRuntimeExports.jsx("button",{"aria-label":t,className:Q,onClick:N,title:t,type:"button",children:S})},K=()=>e.jsxRuntimeExports.jsx("div",{className:"w-full space-y-3 p-4",role:"status","aria-live":"polite",children:a?e.jsxRuntimeExports.jsxs(e.jsxRuntimeExports.Fragment,{children:[e.jsxRuntimeExports.jsx(a,{className:"h-4 w-32"}),e.jsxRuntimeExports.jsx(a,{className:"aspect-video w-full"})]}):e.jsxRuntimeExports.jsx("p",{className:"text-sm text-muted-foreground",children:D})}),w=t=>e.jsxRuntimeExports.jsxs("div",{className:"p-4 text-center text-sm text-destructive",role:"alert",children:[e.jsxRuntimeExports.jsx("p",{className:"font-medium",children:t||f}),n!=null&&n.message?e.jsxRuntimeExports.jsx("p",{className:"mt-1 opacity-80",children:n.message}):null]}),m=e.jsxRuntimeExports.jsxs("div",{className:p.cn("flex h-full min-h-[360px] flex-col overflow-hidden rounded-md border bg-background",M),children:[C?e.jsxRuntimeExports.jsxs("div",{className:p.cn("flex flex-wrap items-center justify-between gap-2 border-b px-3 py-2",U),children:[e.jsxRuntimeExports.jsx("span",{className:"text-xs font-medium text-muted-foreground",children:j||H}),$?J("新窗口打开",e.jsxRuntimeExports.jsx(W.ExternalLink,{className:"h-4 w-4"}),()=>window.open(s,"_blank","noreferrer")):null]}):null,e.jsxRuntimeExports.jsxs("div",{className:"relative flex min-h-0 flex-1 items-center justify-center bg-muted/20 p-4",children:[v?n?w():null:w(T),v&&!n?e.jsxRuntimeExports.jsxs(e.jsxRuntimeExports.Fragment,{children:[b?K():null,r.createElement("video",{...Y,key:s,className:p.cn("max-h-full w-full max-w-full bg-black",b?"invisible absolute":"visible",q),controls:B,onError:()=>{const t=new Error(f);d(!1),c(t),x==null||x(t)},onLoadedData:()=>{d(!1),c(null),l==null||l()},playsInline:X,preload:F,title:j},e.jsxRuntimeExports.jsx("source",{src:s,type:i}),u==null?void 0:u.map(t=>e.jsxRuntimeExports.jsx("track",{...t},`${t.src}-${t.kind||""}`)))]}):null]})]});return R?e.jsxRuntimeExports.jsx(R,{className:E,children:g?e.jsxRuntimeExports.jsx(g,{children:m}):m}):e.jsxRuntimeExports.jsx("div",{className:E,children:m})}exports.SUPPORTED_VIDEO_EXTENSIONS=P;exports.SUPPORTED_VIDEO_MIME_TYPES=_;exports.VideoReader=ee;
2
+ //# sourceMappingURL=video-reader.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-reader.cjs","sources":["../src/components/VideoReader.tsx"],"sourcesContent":["import { ExternalLink as ExternalLinkIcon } from 'lucide-react';\nimport { useEffect, useMemo, useState } from 'react';\nimport type {\n HTMLAttributes,\n ReactNode,\n TrackHTMLAttributes,\n VideoHTMLAttributes,\n} from 'react';\n\nimport { cn } from '../lib/utils';\nimport type {\n ButtonComponent,\n CardComponent,\n SkeletonComponent,\n UIComponent,\n} from '../types/component-types';\n\nimport { getMediaExtension, isSupportedMediaSource } from './media-utils';\n\nexport const SUPPORTED_VIDEO_EXTENSIONS = [\n 'mp4',\n 'webm',\n 'ogg',\n 'ogv',\n 'mov',\n 'm4v',\n] as const;\n\nexport const SUPPORTED_VIDEO_MIME_TYPES = [\n 'video/mp4',\n 'video/webm',\n 'video/ogg',\n 'video/quicktime',\n 'video/x-m4v',\n] as const;\n\nexport interface VideoReaderUIComponents {\n Card?: CardComponent;\n CardContent?: UIComponent<HTMLAttributes<HTMLDivElement>>;\n Button?: ButtonComponent;\n Skeleton?: SkeletonComponent;\n}\n\nexport interface VideoReaderTrack extends Omit<\n TrackHTMLAttributes<HTMLTrackElement>,\n 'children'\n> {\n src: string;\n}\n\nexport interface VideoReaderProps extends Omit<\n VideoHTMLAttributes<HTMLVideoElement>,\n 'children' | 'className' | 'onError' | 'onLoadedData' | 'src'\n> {\n src: string;\n fileName?: string;\n mimeType?: string;\n title?: string;\n components?: VideoReaderUIComponents;\n tracks?: VideoReaderTrack[];\n loading?: boolean;\n error?: Error | string | null;\n className?: string;\n containerClassName?: string;\n videoClassName?: string;\n toolbarClassName?: string;\n loadingText?: string;\n errorText?: string;\n unsupportedText?: string;\n showToolbar?: boolean;\n showOpenInNewTab?: boolean;\n allowUnsupportedFormat?: boolean;\n supportedExtensions?: readonly string[];\n supportedMimeTypes?: readonly string[];\n onLoadedData?: () => void;\n onError?: (error: Error) => void;\n}\n\nconst normalizeError = (error: Error | string | null | undefined) => {\n if (!error) return null;\n return error instanceof Error ? error : new Error(error);\n};\n\nexport function VideoReader({\n src,\n fileName,\n mimeType,\n title,\n components,\n tracks,\n loading = false,\n error,\n className,\n containerClassName,\n videoClassName,\n toolbarClassName,\n loadingText = '正在加载视频...',\n errorText = '视频加载失败',\n unsupportedText = '暂不支持该视频格式',\n showToolbar = true,\n showOpenInNewTab = true,\n allowUnsupportedFormat = false,\n supportedExtensions = SUPPORTED_VIDEO_EXTENSIONS,\n supportedMimeTypes = SUPPORTED_VIDEO_MIME_TYPES,\n controls = true,\n preload = 'metadata',\n playsInline = true,\n onLoadedData,\n onError,\n ...videoProps\n}: VideoReaderProps) {\n const { Card, CardContent, Button, Skeleton } = components || {};\n const [isVideoLoading, setIsVideoLoading] = useState(true);\n const [videoError, setVideoError] = useState<Error | null>(null);\n\n const displayedError = normalizeError(error) || videoError;\n const isSupported =\n allowUnsupportedFormat ||\n isSupportedMediaSource({\n src,\n fileName,\n mimeType,\n supportedExtensions,\n supportedMimeTypes,\n });\n const isLoading = loading || (isVideoLoading && !displayedError);\n\n const formatLabel = useMemo(() => {\n const extension = getMediaExtension(src, fileName);\n return extension ? extension.toUpperCase() : mimeType || '视频';\n }, [fileName, mimeType, src]);\n\n useEffect(() => {\n setIsVideoLoading(true);\n setVideoError(null);\n }, [src]);\n\n const renderButton = (\n label: string,\n icon: ReactNode,\n onClick: () => void\n ) => {\n const buttonClassName =\n 'inline-flex h-8 w-8 items-center justify-center rounded-md border border-input bg-background text-foreground shadow-sm transition-colors hover:bg-accent hover:text-accent-foreground';\n\n if (Button) {\n return (\n <Button\n aria-label={label}\n className=\"h-8 w-8\"\n onClick={onClick}\n size=\"icon\"\n title={label}\n type=\"button\"\n variant=\"outline\"\n >\n {icon}\n </Button>\n );\n }\n\n return (\n <button\n aria-label={label}\n className={buttonClassName}\n onClick={onClick}\n title={label}\n type=\"button\"\n >\n {icon}\n </button>\n );\n };\n\n const renderLoading = () => (\n <div className=\"w-full space-y-3 p-4\" role=\"status\" aria-live=\"polite\">\n {Skeleton ? (\n <>\n <Skeleton className=\"h-4 w-32\" />\n <Skeleton className=\"aspect-video w-full\" />\n </>\n ) : (\n <p className=\"text-sm text-muted-foreground\">{loadingText}</p>\n )}\n </div>\n );\n\n const renderError = (message?: string) => (\n <div className=\"p-4 text-center text-sm text-destructive\" role=\"alert\">\n <p className=\"font-medium\">{message || errorText}</p>\n {displayedError?.message ? (\n <p className=\"mt-1 opacity-80\">{displayedError.message}</p>\n ) : null}\n </div>\n );\n\n const body = (\n <div\n className={cn(\n 'flex h-full min-h-[360px] flex-col overflow-hidden rounded-md border bg-background',\n containerClassName\n )}\n >\n {showToolbar ? (\n <div\n className={cn(\n 'flex flex-wrap items-center justify-between gap-2 border-b px-3 py-2',\n toolbarClassName\n )}\n >\n <span className=\"text-xs font-medium text-muted-foreground\">\n {title || formatLabel}\n </span>\n {showOpenInNewTab\n ? renderButton(\n '新窗口打开',\n <ExternalLinkIcon className=\"h-4 w-4\" />,\n () => window.open(src, '_blank', 'noreferrer')\n )\n : null}\n </div>\n ) : null}\n <div className=\"relative flex min-h-0 flex-1 items-center justify-center bg-muted/20 p-4\">\n {!isSupported\n ? renderError(unsupportedText)\n : displayedError\n ? renderError()\n : null}\n {isSupported && !displayedError ? (\n <>\n {isLoading ? renderLoading() : null}\n <video\n {...videoProps}\n key={src}\n className={cn(\n 'max-h-full w-full max-w-full bg-black',\n isLoading ? 'invisible absolute' : 'visible',\n videoClassName\n )}\n controls={controls}\n onError={() => {\n const nextError = new Error(errorText);\n setIsVideoLoading(false);\n setVideoError(nextError);\n onError?.(nextError);\n }}\n onLoadedData={() => {\n setIsVideoLoading(false);\n setVideoError(null);\n onLoadedData?.();\n }}\n playsInline={playsInline}\n preload={preload}\n title={title}\n >\n <source src={src} type={mimeType} />\n {tracks?.map((track) => (\n <track key={`${track.src}-${track.kind || ''}`} {...track} />\n ))}\n </video>\n </>\n ) : null}\n </div>\n </div>\n );\n\n if (Card) {\n return (\n <Card className={className}>\n {CardContent ? <CardContent>{body}</CardContent> : body}\n </Card>\n );\n }\n\n return <div className={className}>{body}</div>;\n}\n"],"names":["SUPPORTED_VIDEO_EXTENSIONS","SUPPORTED_VIDEO_MIME_TYPES","normalizeError","error","VideoReader","src","fileName","mimeType","title","components","tracks","loading","className","containerClassName","videoClassName","toolbarClassName","loadingText","errorText","unsupportedText","showToolbar","showOpenInNewTab","allowUnsupportedFormat","supportedExtensions","supportedMimeTypes","controls","preload","playsInline","onLoadedData","onError","videoProps","Card","CardContent","Button","Skeleton","isVideoLoading","setIsVideoLoading","useState","videoError","setVideoError","displayedError","isSupported","isSupportedMediaSource","isLoading","formatLabel","useMemo","extension","getMediaExtension","useEffect","renderButton","label","icon","onClick","buttonClassName","jsx","renderLoading","jsxs","Fragment","renderError","message","body","cn","ExternalLinkIcon","createElement","nextError","track"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { VideoReader, SUPPORTED_VIDEO_EXTENSIONS, SUPPORTED_VIDEO_MIME_TYPES, } from './components/VideoReader';
2
+ export type { VideoReaderProps, VideoReaderTrack, VideoReaderUIComponents, } from './components/VideoReader';
3
+ //# sourceMappingURL=video-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-reader.d.ts","sourceRoot":"","sources":["../src/video-reader.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC"}