@turinhub/atomix-common-ui 0.2.2 → 0.4.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 (116) hide show
  1. package/README.md +34 -15
  2. package/dist/PDFSidebar-BBtucLK6.js +232 -0
  3. package/dist/PDFSidebar-BBtucLK6.js.map +1 -0
  4. package/dist/PDFSidebar-Di0D-yPS.cjs +2 -0
  5. package/dist/PDFSidebar-Di0D-yPS.cjs.map +1 -0
  6. package/dist/component-types.cjs +2 -0
  7. package/dist/component-types.cjs.map +1 -0
  8. package/dist/component-types.d.ts +2 -0
  9. package/dist/component-types.d.ts.map +1 -0
  10. package/dist/component-types.js +2 -0
  11. package/dist/component-types.js.map +1 -0
  12. package/dist/components/FileUpload.d.ts +61 -0
  13. package/dist/components/FileUpload.d.ts.map +1 -0
  14. package/dist/components/MarkdownReader.d.ts +26 -0
  15. package/dist/components/MarkdownReader.d.ts.map +1 -0
  16. package/dist/components/PDFReader.d.ts +2 -2
  17. package/dist/components/PDFReader.d.ts.map +1 -1
  18. package/dist/components/PDFSidebar.d.ts +1 -1
  19. package/dist/components/PDFSidebar.d.ts.map +1 -1
  20. package/dist/components/SimplePDFReader.d.ts +1 -1
  21. package/dist/data-table.cjs +2 -0
  22. package/dist/data-table.cjs.map +1 -0
  23. package/dist/data-table.d.ts +3 -0
  24. package/dist/data-table.d.ts.map +1 -0
  25. package/dist/data-table.js +159 -0
  26. package/dist/data-table.js.map +1 -0
  27. package/dist/delete-confirm-dialog.cjs +2 -0
  28. package/dist/delete-confirm-dialog.cjs.map +1 -0
  29. package/dist/delete-confirm-dialog.d.ts +3 -0
  30. package/dist/delete-confirm-dialog.d.ts.map +1 -0
  31. package/dist/delete-confirm-dialog.js +109 -0
  32. package/dist/delete-confirm-dialog.js.map +1 -0
  33. package/dist/file-upload.cjs +2 -0
  34. package/dist/file-upload.cjs.map +1 -0
  35. package/dist/file-upload.d.ts +3 -0
  36. package/dist/file-upload.d.ts.map +1 -0
  37. package/dist/file-upload.js +354 -0
  38. package/dist/file-upload.js.map +1 -0
  39. package/dist/{index-CN76z2bu.cjs → index-BiA_tnaq.cjs} +3 -3
  40. package/dist/{index-CN76z2bu.cjs.map → index-BiA_tnaq.cjs.map} +1 -1
  41. package/dist/{index-Ba1twkJn.js → index-BypbGNpR.js} +2 -2
  42. package/dist/{index-Ba1twkJn.js.map → index-BypbGNpR.js.map} +1 -1
  43. package/dist/index.cjs +2 -0
  44. package/dist/index.cjs.map +1 -0
  45. package/dist/index.d.ts +0 -18
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +2 -11
  48. package/dist/jsx-runtime-B4hRZ52C.js +283 -0
  49. package/dist/jsx-runtime-B4hRZ52C.js.map +1 -0
  50. package/dist/jsx-runtime-BB_1_6y_.cjs +23 -0
  51. package/dist/jsx-runtime-BB_1_6y_.cjs.map +1 -0
  52. package/dist/markdown-reader.cjs +2 -0
  53. package/dist/markdown-reader.cjs.map +1 -0
  54. package/dist/markdown-reader.d.ts +3 -0
  55. package/dist/markdown-reader.d.ts.map +1 -0
  56. package/dist/markdown-reader.js +145 -0
  57. package/dist/markdown-reader.js.map +1 -0
  58. package/dist/pdf-reader.cjs +2 -0
  59. package/dist/pdf-reader.cjs.map +1 -0
  60. package/dist/pdf-reader.d.ts +3 -0
  61. package/dist/pdf-reader.d.ts.map +1 -0
  62. package/dist/pdf-reader.js +427 -0
  63. package/dist/pdf-reader.js.map +1 -0
  64. package/dist/pdf-sidebar.cjs +2 -0
  65. package/dist/pdf-sidebar.cjs.map +1 -0
  66. package/dist/pdf-sidebar.d.ts +3 -0
  67. package/dist/pdf-sidebar.d.ts.map +1 -0
  68. package/dist/pdf-sidebar.js +5 -0
  69. package/dist/pdf-sidebar.js.map +1 -0
  70. package/dist/simple-pdf-reader.cjs +2 -0
  71. package/dist/simple-pdf-reader.cjs.map +1 -0
  72. package/dist/simple-pdf-reader.d.ts +3 -0
  73. package/dist/simple-pdf-reader.d.ts.map +1 -0
  74. package/dist/simple-pdf-reader.js +268 -0
  75. package/dist/simple-pdf-reader.js.map +1 -0
  76. package/dist/table-header.cjs +2 -0
  77. package/dist/table-header.cjs.map +1 -0
  78. package/dist/table-header.d.ts +3 -0
  79. package/dist/table-header.d.ts.map +1 -0
  80. package/dist/table-header.js +63 -0
  81. package/dist/table-header.js.map +1 -0
  82. package/dist/table-pagination.cjs +2 -0
  83. package/dist/table-pagination.cjs.map +1 -0
  84. package/dist/table-pagination.d.ts +3 -0
  85. package/dist/table-pagination.d.ts.map +1 -0
  86. package/dist/table-pagination.js +172 -0
  87. package/dist/table-pagination.js.map +1 -0
  88. package/dist/theme-switcher-content.cjs +2 -0
  89. package/dist/theme-switcher-content.cjs.map +1 -0
  90. package/dist/theme-switcher-content.d.ts +3 -0
  91. package/dist/theme-switcher-content.d.ts.map +1 -0
  92. package/dist/theme-switcher-content.js +103 -0
  93. package/dist/theme-switcher-content.js.map +1 -0
  94. package/dist/theme-switcher.cjs +2 -0
  95. package/dist/theme-switcher.cjs.map +1 -0
  96. package/dist/theme-switcher.d.ts +3 -0
  97. package/dist/theme-switcher.d.ts.map +1 -0
  98. package/dist/theme-switcher.js +140 -0
  99. package/dist/theme-switcher.js.map +1 -0
  100. package/dist/utils-B6yFEsav.js +9 -0
  101. package/dist/utils-B6yFEsav.js.map +1 -0
  102. package/dist/utils-IjLH3w2e.cjs +2 -0
  103. package/dist/utils-IjLH3w2e.cjs.map +1 -0
  104. package/dist/utils.cjs +2 -0
  105. package/dist/utils.cjs.map +1 -0
  106. package/dist/utils.d.ts +2 -0
  107. package/dist/utils.d.ts.map +1 -0
  108. package/dist/utils.js +5 -0
  109. package/dist/utils.js.map +1 -0
  110. package/package.json +161 -3
  111. package/dist/index-6lJCWESg.js +0 -1793
  112. package/dist/index-6lJCWESg.js.map +0 -1
  113. package/dist/index-C94iJmKE.cjs +0 -23
  114. package/dist/index-C94iJmKE.cjs.map +0 -1
  115. package/dist/index.c.js +0 -2
  116. package/dist/index.c.js.map +0 -1
@@ -0,0 +1,172 @@
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";
4
+ function _({
5
+ currentPage: t,
6
+ pageSize: a,
7
+ total: r,
8
+ onPageChange: b,
9
+ onPageSizeChange: u,
10
+ pageSizeOptions: N = [10, 20, 50],
11
+ showPageSizeSelector: v = !0,
12
+ showJumpToPage: g = !0,
13
+ showTotal: f = !0,
14
+ searchActive: w = !1,
15
+ components: h
16
+ }) {
17
+ const [p, j] = D(String(t + 1));
18
+ if (J(() => {
19
+ j(String(t + 1));
20
+ }, [t]), !h)
21
+ return /* @__PURE__ */ e.jsx("div", { className: "p-4 text-center text-destructive", children: "错误:请通过 components prop 注入 UI 组件" });
22
+ const {
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(
30
+ /* @__PURE__ */ new Set([...N, a])
31
+ ).sort((s, n) => s - n), B = v && !!u, d = i > 1, x = (s) => {
32
+ const n = Math.max(0, Math.min(s, i - 1));
33
+ n !== t && b(n);
34
+ }, E = (() => {
35
+ if (i <= 7)
36
+ return Array.from({ length: i }, (l, m) => m);
37
+ const s = /* @__PURE__ */ new Set([
38
+ 0,
39
+ 1,
40
+ i - 2,
41
+ i - 1,
42
+ t - 1,
43
+ t,
44
+ t + 1
45
+ ]), n = Array.from(s).filter((l) => l >= 0 && l < i).sort((l, m) => l - m), o = [];
46
+ for (const l of n) {
47
+ const m = o[o.length - 1];
48
+ typeof m == "number" && l - m > 1 && o.push("ellipsis"), o.push(l);
49
+ }
50
+ return o;
51
+ })();
52
+ return r === 0 ? null : /* @__PURE__ */ e.jsxs(
53
+ "div",
54
+ {
55
+ className: `flex w-full items-center gap-3 ${f ? "justify-between" : "justify-end"}`,
56
+ 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: [
60
+ /* @__PURE__ */ e.jsx("span", { className: "text-sm text-muted-foreground", children: "每页" }),
61
+ /* @__PURE__ */ e.jsxs(
62
+ y,
63
+ {
64
+ value: String(a),
65
+ onValueChange: (s) => {
66
+ const n = Number(s);
67
+ Number.isNaN(n) || n === a || !u || u(n);
68
+ },
69
+ 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)) })
72
+ ]
73
+ }
74
+ ),
75
+ /* @__PURE__ */ e.jsx("span", { className: "text-sm text-muted-foreground", children: "条" })
76
+ ] }),
77
+ /* @__PURE__ */ e.jsxs("div", { className: "mr-4 text-sm text-muted-foreground", children: [
78
+ "第 ",
79
+ t + 1,
80
+ " 页,共 ",
81
+ i,
82
+ " 页"
83
+ ] }),
84
+ /* @__PURE__ */ e.jsx(
85
+ c,
86
+ {
87
+ variant: "outline",
88
+ size: "icon",
89
+ onClick: () => x(t - 1),
90
+ disabled: t === 0 || !d,
91
+ "aria-label": "上一页",
92
+ children: /* @__PURE__ */ e.jsx(R, { className: "h-4 w-4" })
93
+ }
94
+ ),
95
+ /* @__PURE__ */ e.jsx("div", { className: "flex items-center gap-1", children: E.map(
96
+ (s, n) => s === "ellipsis" ? /* @__PURE__ */ e.jsx(
97
+ "span",
98
+ {
99
+ className: "inline-flex h-8 w-8 items-center justify-center text-sm text-muted-foreground",
100
+ children: "..."
101
+ },
102
+ `ellipsis-${n}`
103
+ ) : /* @__PURE__ */ e.jsx(
104
+ c,
105
+ {
106
+ variant: s === t ? "default" : "outline",
107
+ size: "sm",
108
+ onClick: () => x(s),
109
+ disabled: s === t,
110
+ "aria-current": s === t ? "page" : void 0,
111
+ children: s + 1
112
+ },
113
+ s
114
+ )
115
+ ) }),
116
+ /* @__PURE__ */ e.jsx(
117
+ c,
118
+ {
119
+ variant: "outline",
120
+ size: "icon",
121
+ onClick: () => x(t + 1),
122
+ disabled: t >= i - 1 || !d,
123
+ "aria-label": "下一页",
124
+ children: /* @__PURE__ */ e.jsx(V, { className: "h-4 w-4" })
125
+ }
126
+ ),
127
+ g && /* @__PURE__ */ e.jsxs(
128
+ "form",
129
+ {
130
+ className: "ml-1 flex items-center gap-2",
131
+ onSubmit: (s) => {
132
+ s.preventDefault();
133
+ const n = Number.parseInt(p, 10);
134
+ Number.isNaN(n) || x(n - 1);
135
+ },
136
+ children: [
137
+ /* @__PURE__ */ e.jsx("span", { className: "text-sm text-muted-foreground", children: "跳至" }),
138
+ /* @__PURE__ */ e.jsx(
139
+ "input",
140
+ {
141
+ type: "number",
142
+ min: 1,
143
+ max: i,
144
+ value: p,
145
+ 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": "跳转页码"
149
+ }
150
+ ),
151
+ /* @__PURE__ */ e.jsx(
152
+ c,
153
+ {
154
+ type: "submit",
155
+ variant: "outline",
156
+ size: "sm",
157
+ disabled: !d,
158
+ children: "跳转"
159
+ }
160
+ )
161
+ ]
162
+ }
163
+ )
164
+ ] })
165
+ ]
166
+ }
167
+ );
168
+ }
169
+ export {
170
+ _ as TablePagination
171
+ };
172
+ //# sourceMappingURL=table-pagination.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./jsx-runtime-BB_1_6y_.cjs"),j=[{value:"light",label:"浅色",icon:e.jsxRuntimeExports.jsxs("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[e.jsxRuntimeExports.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",strokeWidth:"2"}),e.jsxRuntimeExports.jsx("path",{className:"opacity-75",d:"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41",strokeWidth:"2",strokeLinecap:"round"})]})},{value:"dark",label:"深色",icon:e.jsxRuntimeExports.jsx("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsxRuntimeExports.jsx("path",{d:"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{value:"system",label:"跟随系统",icon:e.jsxRuntimeExports.jsxs("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[e.jsxRuntimeExports.jsx("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",ry:"2",strokeWidth:"2"}),e.jsxRuntimeExports.jsx("path",{d:"M8 21h8m-4-4v4",strokeWidth:"2",strokeLinecap:"round"})]})}];function h({value:l,onValueChange:x,themes:o=j,iconSize:s=16,components:i,themeIcons:r}){if(!i)return e.jsxRuntimeExports.jsx("div",{className:"p-4 text-center text-destructive",children:"错误:请通过 components prop 注入 UI 组件"});const{DropdownMenuRadioGroup:c,DropdownMenuRadioItem:a}=i,u=t=>{if(r&&r[t])return r[t];const n=o.find(p=>p.value===t);return n==null?void 0:n.icon},d=s?{width:s,height:s}:{};return e.jsxRuntimeExports.jsx(c,{value:l,onValueChange:x,children:o.map(t=>e.jsxRuntimeExports.jsxs(a,{value:t.value,children:[e.jsxRuntimeExports.jsx("span",{className:"mr-2 inline-flex items-center",style:d,children:u(t.value)}),e.jsxRuntimeExports.jsx("span",{children:t.label})]},t.value))})}exports.ThemeSwitcherContent=h;
2
+ //# sourceMappingURL=theme-switcher-content.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-switcher-content.cjs","sources":["../src/components/ThemeSwitcherContent.tsx"],"sourcesContent":["import type {\n DropdownMenuRadioGroupComponent,\n DropdownMenuRadioItemComponent,\n} from '../types/component-types';\n\n/**\n * 主题选项\n */\nexport interface ThemeOption {\n value: string;\n label: string;\n icon: React.ReactNode;\n}\n\nexport interface ThemeSwitcherContentProps {\n value: string;\n onValueChange: (value: string) => void;\n themes?: ThemeOption[];\n iconSize?: number;\n components?: Pick<\n ThemeSwitcherContentUIComponents,\n 'DropdownMenuRadioGroup' | 'DropdownMenuRadioItem'\n >;\n // 自定义主题图标(可选)\n themeIcons?: Partial<Record<string, React.ReactNode>>;\n}\n\n/**\n * UI 组件适配器接口(轻量版)\n */\nexport interface ThemeSwitcherContentUIComponents {\n DropdownMenuRadioGroup: DropdownMenuRadioGroupComponent;\n DropdownMenuRadioItem: DropdownMenuRadioItemComponent;\n}\n\n/**\n * 默认主题配置\n */\nconst defaultThemes: ThemeOption[] = [\n {\n value: 'light',\n label: '浅色',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" strokeWidth=\"2\" />\n <path\n className=\"opacity-75\"\n d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n ),\n },\n {\n value: 'dark',\n label: '深色',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n d=\"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ),\n },\n {\n value: 'system',\n label: '跟随系统',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <rect\n x=\"2\"\n y=\"3\"\n width=\"20\"\n height=\"14\"\n rx=\"2\"\n ry=\"2\"\n strokeWidth=\"2\"\n />\n <path d=\"M8 21h8m-4-4v4\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n ),\n },\n];\n\n/**\n * 主题切换内容组件(轻量版)\n * 可嵌入到其他 DropdownMenu 中使用\n */\nexport function ThemeSwitcherContent({\n value,\n onValueChange,\n themes = defaultThemes,\n iconSize = 16,\n components,\n themeIcons,\n}: ThemeSwitcherContentProps) {\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 { DropdownMenuRadioGroup, DropdownMenuRadioItem } = components;\n\n /**\n * 获取主题图标\n * 优先使用 themeIcons 中的自定义图标,如果没有则使用主题配置中的默认图标\n */\n const getThemeIcon = (themeValue: string): React.ReactNode => {\n if (themeIcons && themeIcons[themeValue]) {\n return themeIcons[themeValue];\n }\n const theme = themes.find((t) => t.value === themeValue);\n return theme?.icon;\n };\n\n const iconStyle = iconSize ? { width: iconSize, height: iconSize } : {};\n\n return (\n <DropdownMenuRadioGroup value={value} onValueChange={onValueChange}>\n {themes.map((theme) => (\n <DropdownMenuRadioItem key={theme.value} value={theme.value}>\n <span className=\"mr-2 inline-flex items-center\" style={iconStyle}>\n {getThemeIcon(theme.value)}\n </span>\n <span>{theme.label}</span>\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n );\n}\n"],"names":["defaultThemes","jsxs","jsx","ThemeSwitcherContent","value","onValueChange","themes","iconSize","components","themeIcons","DropdownMenuRadioGroup","DropdownMenuRadioItem","getThemeIcon","themeValue","theme","t","iconStyle"],"mappings":"8HAsCMA,EAA+B,CACnC,CACE,MAAO,QACP,MAAO,KACP,KACEC,EAAAA,kBAAAA,KAAC,MAAA,CACC,UAAU,UACV,KAAK,OACL,QAAQ,YACR,OAAO,eAEP,SAAA,CAAAC,EAAAA,kBAAAA,IAAC,SAAA,CAAO,UAAU,aAAa,GAAG,KAAK,GAAG,KAAK,EAAE,KAAK,YAAY,GAAA,CAAI,EACtEA,EAAAA,kBAAAA,IAAC,OAAA,CACC,UAAU,aACV,EAAE,qHACF,YAAY,IACZ,cAAc,OAAA,CAAA,CAChB,CAAA,CAAA,CACF,EAGJ,CACE,MAAO,OACP,MAAO,KACP,KACEA,EAAAA,kBAAAA,IAAC,MAAA,CACC,UAAU,UACV,KAAK,OACL,QAAQ,YACR,OAAO,eAEP,SAAAA,EAAAA,kBAAAA,IAAC,OAAA,CACC,EAAE,8CACF,YAAY,IACZ,cAAc,QACd,eAAe,OAAA,CAAA,CACjB,CAAA,CACF,EAGJ,CACE,MAAO,SACP,MAAO,OACP,KACED,EAAAA,kBAAAA,KAAC,MAAA,CACC,UAAU,UACV,KAAK,OACL,QAAQ,YACR,OAAO,eAEP,SAAA,CAAAC,EAAAA,kBAAAA,IAAC,OAAA,CACC,EAAE,IACF,EAAE,IACF,MAAM,KACN,OAAO,KACP,GAAG,IACH,GAAG,IACH,YAAY,GAAA,CAAA,0BAEb,OAAA,CAAK,EAAE,iBAAiB,YAAY,IAAI,cAAc,OAAA,CAAQ,CAAA,CAAA,CAAA,CACjE,CAGN,EAMO,SAASC,EAAqB,CACnC,MAAAC,EACA,cAAAC,EACA,OAAAC,EAASN,EACT,SAAAO,EAAW,GACX,WAAAC,EACA,WAAAC,CACF,EAA8B,CAC5B,GAAI,CAACD,EACH,OACEN,EAAAA,kBAAAA,IAAC,MAAA,CAAI,UAAU,mCAAmC,SAAA,kCAElD,EAIJ,KAAM,CAAE,uBAAAQ,EAAwB,sBAAAC,CAAA,EAA0BH,EAMpDI,EAAgBC,GAAwC,CAC5D,GAAIJ,GAAcA,EAAWI,CAAU,EACrC,OAAOJ,EAAWI,CAAU,EAE9B,MAAMC,EAAQR,EAAO,KAAMS,GAAMA,EAAE,QAAUF,CAAU,EACvD,OAAOC,GAAA,YAAAA,EAAO,IAChB,EAEME,EAAYT,EAAW,CAAE,MAAOA,EAAU,OAAQA,CAAA,EAAa,CAAA,EAErE,OACEL,EAAAA,kBAAAA,IAACQ,EAAA,CAAuB,MAAAN,EAAc,cAAAC,EACnC,SAAAC,EAAO,IAAKQ,GACXb,EAAAA,kBAAAA,KAACU,EAAA,CAAwC,MAAOG,EAAM,MACpD,SAAA,CAAAZ,EAAAA,kBAAAA,IAAC,OAAA,CAAK,UAAU,gCAAgC,MAAOc,EACpD,SAAAJ,EAAaE,EAAM,KAAK,CAAA,CAC3B,EACAZ,EAAAA,kBAAAA,IAAC,OAAA,CAAM,SAAAY,EAAM,KAAA,CAAM,CAAA,CAAA,EAJOA,EAAM,KAKlC,CACD,EACH,CAEJ"}
@@ -0,0 +1,3 @@
1
+ export { ThemeSwitcherContent } from './components/ThemeSwitcherContent';
2
+ export type { ThemeSwitcherContentProps, ThemeSwitcherContentUIComponents, } from './components/ThemeSwitcherContent';
3
+ //# sourceMappingURL=theme-switcher-content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-switcher-content.d.ts","sourceRoot":"","sources":["../src/theme-switcher-content.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,YAAY,EACV,yBAAyB,EACzB,gCAAgC,GACjC,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,103 @@
1
+ import { j as e } from "./jsx-runtime-B4hRZ52C.js";
2
+ const p = [
3
+ {
4
+ value: "light",
5
+ label: "浅色",
6
+ icon: /* @__PURE__ */ e.jsxs(
7
+ "svg",
8
+ {
9
+ className: "h-4 w-4",
10
+ fill: "none",
11
+ viewBox: "0 0 24 24",
12
+ stroke: "currentColor",
13
+ children: [
14
+ /* @__PURE__ */ e.jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", strokeWidth: "2" }),
15
+ /* @__PURE__ */ e.jsx(
16
+ "path",
17
+ {
18
+ className: "opacity-75",
19
+ d: "M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41",
20
+ strokeWidth: "2",
21
+ strokeLinecap: "round"
22
+ }
23
+ )
24
+ ]
25
+ }
26
+ )
27
+ },
28
+ {
29
+ value: "dark",
30
+ label: "深色",
31
+ icon: /* @__PURE__ */ e.jsx(
32
+ "svg",
33
+ {
34
+ className: "h-4 w-4",
35
+ fill: "none",
36
+ viewBox: "0 0 24 24",
37
+ stroke: "currentColor",
38
+ children: /* @__PURE__ */ e.jsx(
39
+ "path",
40
+ {
41
+ d: "M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z",
42
+ strokeWidth: "2",
43
+ strokeLinecap: "round",
44
+ strokeLinejoin: "round"
45
+ }
46
+ )
47
+ }
48
+ )
49
+ },
50
+ {
51
+ value: "system",
52
+ label: "跟随系统",
53
+ icon: /* @__PURE__ */ e.jsxs(
54
+ "svg",
55
+ {
56
+ className: "h-4 w-4",
57
+ fill: "none",
58
+ viewBox: "0 0 24 24",
59
+ stroke: "currentColor",
60
+ children: [
61
+ /* @__PURE__ */ e.jsx(
62
+ "rect",
63
+ {
64
+ x: "2",
65
+ y: "3",
66
+ width: "20",
67
+ height: "14",
68
+ rx: "2",
69
+ ry: "2",
70
+ strokeWidth: "2"
71
+ }
72
+ ),
73
+ /* @__PURE__ */ e.jsx("path", { d: "M8 21h8m-4-4v4", strokeWidth: "2", strokeLinecap: "round" })
74
+ ]
75
+ }
76
+ )
77
+ }
78
+ ];
79
+ function j({
80
+ value: i,
81
+ onValueChange: a,
82
+ themes: o = p,
83
+ iconSize: s = 16,
84
+ components: l,
85
+ themeIcons: t
86
+ }) {
87
+ if (!l)
88
+ return /* @__PURE__ */ e.jsx("div", { className: "p-4 text-center text-destructive", children: "错误:请通过 components prop 注入 UI 组件" });
89
+ const { DropdownMenuRadioGroup: c, DropdownMenuRadioItem: d } = l, x = (r) => {
90
+ if (t && t[r])
91
+ return t[r];
92
+ const n = o.find((u) => u.value === r);
93
+ return n == null ? void 0 : n.icon;
94
+ }, h = s ? { width: s, height: s } : {};
95
+ return /* @__PURE__ */ e.jsx(c, { value: i, onValueChange: a, children: o.map((r) => /* @__PURE__ */ e.jsxs(d, { value: r.value, children: [
96
+ /* @__PURE__ */ e.jsx("span", { className: "mr-2 inline-flex items-center", style: h, children: x(r.value) }),
97
+ /* @__PURE__ */ e.jsx("span", { children: r.label })
98
+ ] }, r.value)) });
99
+ }
100
+ export {
101
+ j as ThemeSwitcherContent
102
+ };
103
+ //# sourceMappingURL=theme-switcher-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-switcher-content.js","sources":["../src/components/ThemeSwitcherContent.tsx"],"sourcesContent":["import type {\n DropdownMenuRadioGroupComponent,\n DropdownMenuRadioItemComponent,\n} from '../types/component-types';\n\n/**\n * 主题选项\n */\nexport interface ThemeOption {\n value: string;\n label: string;\n icon: React.ReactNode;\n}\n\nexport interface ThemeSwitcherContentProps {\n value: string;\n onValueChange: (value: string) => void;\n themes?: ThemeOption[];\n iconSize?: number;\n components?: Pick<\n ThemeSwitcherContentUIComponents,\n 'DropdownMenuRadioGroup' | 'DropdownMenuRadioItem'\n >;\n // 自定义主题图标(可选)\n themeIcons?: Partial<Record<string, React.ReactNode>>;\n}\n\n/**\n * UI 组件适配器接口(轻量版)\n */\nexport interface ThemeSwitcherContentUIComponents {\n DropdownMenuRadioGroup: DropdownMenuRadioGroupComponent;\n DropdownMenuRadioItem: DropdownMenuRadioItemComponent;\n}\n\n/**\n * 默认主题配置\n */\nconst defaultThemes: ThemeOption[] = [\n {\n value: 'light',\n label: '浅色',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" strokeWidth=\"2\" />\n <path\n className=\"opacity-75\"\n d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n ),\n },\n {\n value: 'dark',\n label: '深色',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n d=\"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ),\n },\n {\n value: 'system',\n label: '跟随系统',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <rect\n x=\"2\"\n y=\"3\"\n width=\"20\"\n height=\"14\"\n rx=\"2\"\n ry=\"2\"\n strokeWidth=\"2\"\n />\n <path d=\"M8 21h8m-4-4v4\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n ),\n },\n];\n\n/**\n * 主题切换内容组件(轻量版)\n * 可嵌入到其他 DropdownMenu 中使用\n */\nexport function ThemeSwitcherContent({\n value,\n onValueChange,\n themes = defaultThemes,\n iconSize = 16,\n components,\n themeIcons,\n}: ThemeSwitcherContentProps) {\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 { DropdownMenuRadioGroup, DropdownMenuRadioItem } = components;\n\n /**\n * 获取主题图标\n * 优先使用 themeIcons 中的自定义图标,如果没有则使用主题配置中的默认图标\n */\n const getThemeIcon = (themeValue: string): React.ReactNode => {\n if (themeIcons && themeIcons[themeValue]) {\n return themeIcons[themeValue];\n }\n const theme = themes.find((t) => t.value === themeValue);\n return theme?.icon;\n };\n\n const iconStyle = iconSize ? { width: iconSize, height: iconSize } : {};\n\n return (\n <DropdownMenuRadioGroup value={value} onValueChange={onValueChange}>\n {themes.map((theme) => (\n <DropdownMenuRadioItem key={theme.value} value={theme.value}>\n <span className=\"mr-2 inline-flex items-center\" style={iconStyle}>\n {getThemeIcon(theme.value)}\n </span>\n <span>{theme.label}</span>\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n );\n}\n"],"names":["defaultThemes","jsxs","jsx","ThemeSwitcherContent","value","onValueChange","themes","iconSize","components","themeIcons","DropdownMenuRadioGroup","DropdownMenuRadioItem","getThemeIcon","themeValue","theme","t","iconStyle"],"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"),u=require("react"),C=[{value:"light",label:"浅色",icon:e.jsxRuntimeExports.jsxs("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[e.jsxRuntimeExports.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",strokeWidth:"2"}),e.jsxRuntimeExports.jsx("path",{className:"opacity-75",d:"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41",strokeWidth:"2",strokeLinecap:"round"})]})},{value:"dark",label:"深色",icon:e.jsxRuntimeExports.jsx("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:e.jsxRuntimeExports.jsx("path",{d:"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{value:"system",label:"跟随系统",icon:e.jsxRuntimeExports.jsxs("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:[e.jsxRuntimeExports.jsx("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",ry:"2",strokeWidth:"2"}),e.jsxRuntimeExports.jsx("path",{d:"M8 21h8m-4-4v4",strokeWidth:"2",strokeLinecap:"round"})]})}];function D({value:o,onValueChange:c,themes:i=C,triggerVariant:a="ghost",triggerSize:d="icon",triggerClassName:j,iconSize:s=16,showCurrentIcon:p=!0,enableSSRHandling:m=!0,triggerContent:h,components:l,themeIcons:r}){const[R,v]=u.useState(!1);if(u.useEffect(()=>{v(!0)},[]),m&&!R)return null;if(!l)return e.jsxRuntimeExports.jsx("div",{className:"p-4 text-center text-destructive",children:"错误:请通过 components prop 注入 UI 组件"});const{DropdownMenu:E,DropdownMenuTrigger:f,DropdownMenuContent:w,DropdownMenuRadioGroup:g,DropdownMenuRadioItem:M,Button:k}=l,x=t=>{if(r&&r[t])return r[t];const n=i.find(T=>T.value===t);return n==null?void 0:n.icon},y=x(o),N=p?y:null,b=s?{width:s,height:s}:{};return e.jsxRuntimeExports.jsxs(E,{children:[e.jsxRuntimeExports.jsx(f,{asChild:!0,children:e.jsxRuntimeExports.jsx(k,{variant:a,size:d,className:j,children:h||e.jsxRuntimeExports.jsx("span",{style:b,className:"inline-flex items-center justify-center",children:N})})}),e.jsxRuntimeExports.jsx(w,{children:e.jsxRuntimeExports.jsx(g,{value:o,onValueChange:c,children:i.map(t=>e.jsxRuntimeExports.jsxs(M,{value:t.value,children:[e.jsxRuntimeExports.jsx("span",{className:"mr-2 inline-flex items-center",children:x(t.value)}),e.jsxRuntimeExports.jsx("span",{children:t.label})]},t.value))})})]})}exports.ThemeSwitcher=D;
2
+ //# sourceMappingURL=theme-switcher.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-switcher.cjs","sources":["../src/components/ThemeSwitcher.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\n\nimport type {\n ButtonComponent,\n DropdownMenuComponent,\n DropdownMenuTriggerComponent,\n DropdownMenuContentComponent,\n DropdownMenuRadioGroupComponent,\n DropdownMenuRadioItemComponent,\n} from '../types/component-types';\n\n/**\n * 主题选项\n */\nexport interface ThemeOption {\n value: string;\n label: string;\n icon: React.ReactNode;\n}\n\n/**\n * UI 组件适配器接口\n */\nexport interface ThemeSwitcherUIComponents {\n DropdownMenu: DropdownMenuComponent;\n DropdownMenuTrigger: DropdownMenuTriggerComponent;\n DropdownMenuContent: DropdownMenuContentComponent;\n DropdownMenuRadioGroup: DropdownMenuRadioGroupComponent;\n DropdownMenuRadioItem: DropdownMenuRadioItemComponent;\n Button: ButtonComponent;\n}\n\nexport interface ThemeSwitcherProps {\n value: string;\n onValueChange: (value: string) => void;\n themes?: ThemeOption[];\n triggerVariant?:\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost'\n | 'link';\n triggerSize?: 'default' | 'sm' | 'lg' | 'icon';\n triggerClassName?: string;\n iconSize?: number;\n showCurrentIcon?: boolean;\n enableSSRHandling?: boolean;\n triggerContent?: React.ReactNode;\n components?: ThemeSwitcherUIComponents;\n // 自定义主题图标(可选)\n themeIcons?: Partial<Record<string, React.ReactNode>>;\n}\n\n/**\n * 默认主题配置\n */\nconst defaultThemes: ThemeOption[] = [\n {\n value: 'light',\n label: '浅色',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" strokeWidth=\"2\" />\n <path\n className=\"opacity-75\"\n d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n ),\n },\n {\n value: 'dark',\n label: '深色',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n d=\"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ),\n },\n {\n value: 'system',\n label: '跟随系统',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <rect\n x=\"2\"\n y=\"3\"\n width=\"20\"\n height=\"14\"\n rx=\"2\"\n ry=\"2\"\n strokeWidth=\"2\"\n />\n <path d=\"M8 21h8m-4-4v4\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n ),\n },\n];\n\n/**\n * 主题切换组件\n * 需要通过 components prop 注入 UI 组件\n */\nexport function ThemeSwitcher({\n value,\n onValueChange,\n themes = defaultThemes,\n triggerVariant = 'ghost',\n triggerSize = 'icon',\n triggerClassName,\n iconSize = 16,\n showCurrentIcon = true,\n enableSSRHandling = true,\n triggerContent,\n components,\n themeIcons,\n}: ThemeSwitcherProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (enableSSRHandling && !mounted) {\n return null;\n }\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 DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n Button,\n } = components;\n\n /**\n * 获取主题图标\n * 优先使用 themeIcons 中的自定义图标,如果没有则使用主题配置中的默认图标\n */\n const getThemeIcon = (themeValue: string): React.ReactNode => {\n if (themeIcons && themeIcons[themeValue]) {\n return themeIcons[themeValue];\n }\n const theme = themes.find((t) => t.value === themeValue);\n return theme?.icon;\n };\n\n const currentIcon = getThemeIcon(value);\n\n const triggerIcon = showCurrentIcon ? currentIcon : null;\n const iconStyle = iconSize ? { width: iconSize, height: iconSize } : {};\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant={triggerVariant}\n size={triggerSize}\n className={triggerClassName}\n >\n {triggerContent || (\n <span\n style={iconStyle}\n className=\"inline-flex items-center justify-center\"\n >\n {triggerIcon}\n </span>\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent>\n <DropdownMenuRadioGroup value={value} onValueChange={onValueChange}>\n {themes.map((theme) => (\n <DropdownMenuRadioItem key={theme.value} value={theme.value}>\n <span className=\"mr-2 inline-flex items-center\">\n {getThemeIcon(theme.value)}\n </span>\n <span>{theme.label}</span>\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n"],"names":["defaultThemes","jsxs","jsx","ThemeSwitcher","value","onValueChange","themes","triggerVariant","triggerSize","triggerClassName","iconSize","showCurrentIcon","enableSSRHandling","triggerContent","components","themeIcons","mounted","setMounted","useState","useEffect","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","Button","getThemeIcon","themeValue","theme","t","currentIcon","triggerIcon","iconStyle"],"mappings":"iJAyDMA,EAA+B,CACnC,CACE,MAAO,QACP,MAAO,KACP,KACEC,EAAAA,kBAAAA,KAAC,MAAA,CACC,UAAU,UACV,KAAK,OACL,QAAQ,YACR,OAAO,eAEP,SAAA,CAAAC,EAAAA,kBAAAA,IAAC,SAAA,CAAO,UAAU,aAAa,GAAG,KAAK,GAAG,KAAK,EAAE,KAAK,YAAY,GAAA,CAAI,EACtEA,EAAAA,kBAAAA,IAAC,OAAA,CACC,UAAU,aACV,EAAE,qHACF,YAAY,IACZ,cAAc,OAAA,CAAA,CAChB,CAAA,CAAA,CACF,EAGJ,CACE,MAAO,OACP,MAAO,KACP,KACEA,EAAAA,kBAAAA,IAAC,MAAA,CACC,UAAU,UACV,KAAK,OACL,QAAQ,YACR,OAAO,eAEP,SAAAA,EAAAA,kBAAAA,IAAC,OAAA,CACC,EAAE,8CACF,YAAY,IACZ,cAAc,QACd,eAAe,OAAA,CAAA,CACjB,CAAA,CACF,EAGJ,CACE,MAAO,SACP,MAAO,OACP,KACED,EAAAA,kBAAAA,KAAC,MAAA,CACC,UAAU,UACV,KAAK,OACL,QAAQ,YACR,OAAO,eAEP,SAAA,CAAAC,EAAAA,kBAAAA,IAAC,OAAA,CACC,EAAE,IACF,EAAE,IACF,MAAM,KACN,OAAO,KACP,GAAG,IACH,GAAG,IACH,YAAY,GAAA,CAAA,0BAEb,OAAA,CAAK,EAAE,iBAAiB,YAAY,IAAI,cAAc,OAAA,CAAQ,CAAA,CAAA,CAAA,CACjE,CAGN,EAMO,SAASC,EAAc,CAC5B,MAAAC,EACA,cAAAC,EACA,OAAAC,EAASN,EACT,eAAAO,EAAiB,QACjB,YAAAC,EAAc,OACd,iBAAAC,EACA,SAAAC,EAAW,GACX,gBAAAC,EAAkB,GAClB,kBAAAC,EAAoB,GACpB,eAAAC,EACA,WAAAC,EACA,WAAAC,CACF,EAAuB,CACrB,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAAS,EAAK,EAM5C,GAJAC,EAAAA,UAAU,IAAM,CACdF,EAAW,EAAI,CACjB,EAAG,CAAA,CAAE,EAEDL,GAAqB,CAACI,EACxB,OAAO,KAGT,GAAI,CAACF,EACH,OACEZ,EAAAA,kBAAAA,IAAC,MAAA,CAAI,UAAU,mCAAmC,SAAA,kCAElD,EAIJ,KAAM,CACJ,aAAAkB,EACA,oBAAAC,EACA,oBAAAC,EACA,uBAAAC,EACA,sBAAAC,EACA,OAAAC,CAAA,EACEX,EAMEY,EAAgBC,GAAwC,CAC5D,GAAIZ,GAAcA,EAAWY,CAAU,EACrC,OAAOZ,EAAWY,CAAU,EAE9B,MAAMC,EAAQtB,EAAO,KAAMuB,GAAMA,EAAE,QAAUF,CAAU,EACvD,OAAOC,GAAA,YAAAA,EAAO,IAChB,EAEME,EAAcJ,EAAatB,CAAK,EAEhC2B,EAAcpB,EAAkBmB,EAAc,KAC9CE,EAAYtB,EAAW,CAAE,MAAOA,EAAU,OAAQA,CAAA,EAAa,CAAA,EAErE,gCACGU,EAAA,CACC,SAAA,CAAAlB,EAAAA,kBAAAA,IAACmB,EAAA,CAAoB,QAAO,GAC1B,SAAAnB,EAAAA,kBAAAA,IAACuB,EAAA,CACC,QAASlB,EACT,KAAMC,EACN,UAAWC,EAEV,SAAAI,GACCX,EAAAA,kBAAAA,IAAC,OAAA,CACC,MAAO8B,EACP,UAAU,0CAET,SAAAD,CAAA,CAAA,CACH,CAAA,EAGN,EACA7B,wBAACoB,EAAA,CACC,SAAApB,EAAAA,kBAAAA,IAACqB,EAAA,CAAuB,MAAAnB,EAAc,cAAAC,EACnC,SAAAC,EAAO,IAAKsB,GACX3B,yBAACuB,EAAA,CAAwC,MAAOI,EAAM,MACpD,SAAA,CAAA1B,wBAAC,QAAK,UAAU,gCACb,SAAAwB,EAAaE,EAAM,KAAK,EAC3B,EACA1B,EAAAA,kBAAAA,IAAC,OAAA,CAAM,SAAA0B,EAAM,KAAA,CAAM,CAAA,CAAA,EAJOA,EAAM,KAKlC,CACD,CAAA,CACH,CAAA,CACF,CAAA,EACF,CAEJ"}
@@ -0,0 +1,3 @@
1
+ export { ThemeSwitcher } from './components/ThemeSwitcher';
2
+ export type { ThemeOption, ThemeSwitcherProps, ThemeSwitcherUIComponents, } from './components/ThemeSwitcher';
3
+ //# sourceMappingURL=theme-switcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-switcher.d.ts","sourceRoot":"","sources":["../src/theme-switcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,140 @@
1
+ import { j as e } from "./jsx-runtime-B4hRZ52C.js";
2
+ import { useState as b, useEffect as B } from "react";
3
+ const L = [
4
+ {
5
+ value: "light",
6
+ label: "浅色",
7
+ icon: /* @__PURE__ */ e.jsxs(
8
+ "svg",
9
+ {
10
+ className: "h-4 w-4",
11
+ fill: "none",
12
+ viewBox: "0 0 24 24",
13
+ stroke: "currentColor",
14
+ children: [
15
+ /* @__PURE__ */ e.jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", strokeWidth: "2" }),
16
+ /* @__PURE__ */ e.jsx(
17
+ "path",
18
+ {
19
+ className: "opacity-75",
20
+ d: "M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41",
21
+ strokeWidth: "2",
22
+ strokeLinecap: "round"
23
+ }
24
+ )
25
+ ]
26
+ }
27
+ )
28
+ },
29
+ {
30
+ value: "dark",
31
+ label: "深色",
32
+ icon: /* @__PURE__ */ e.jsx(
33
+ "svg",
34
+ {
35
+ className: "h-4 w-4",
36
+ fill: "none",
37
+ viewBox: "0 0 24 24",
38
+ stroke: "currentColor",
39
+ children: /* @__PURE__ */ e.jsx(
40
+ "path",
41
+ {
42
+ d: "M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z",
43
+ strokeWidth: "2",
44
+ strokeLinecap: "round",
45
+ strokeLinejoin: "round"
46
+ }
47
+ )
48
+ }
49
+ )
50
+ },
51
+ {
52
+ value: "system",
53
+ label: "跟随系统",
54
+ icon: /* @__PURE__ */ e.jsxs(
55
+ "svg",
56
+ {
57
+ className: "h-4 w-4",
58
+ fill: "none",
59
+ viewBox: "0 0 24 24",
60
+ stroke: "currentColor",
61
+ children: [
62
+ /* @__PURE__ */ e.jsx(
63
+ "rect",
64
+ {
65
+ x: "2",
66
+ y: "3",
67
+ width: "20",
68
+ height: "14",
69
+ rx: "2",
70
+ ry: "2",
71
+ strokeWidth: "2"
72
+ }
73
+ ),
74
+ /* @__PURE__ */ e.jsx("path", { d: "M8 21h8m-4-4v4", strokeWidth: "2", strokeLinecap: "round" })
75
+ ]
76
+ }
77
+ )
78
+ }
79
+ ];
80
+ function R({
81
+ value: o,
82
+ onValueChange: a,
83
+ themes: i = L,
84
+ triggerVariant: d = "ghost",
85
+ triggerSize: u = "icon",
86
+ triggerClassName: h,
87
+ iconSize: n = 16,
88
+ showCurrentIcon: x = !0,
89
+ enableSSRHandling: p = !0,
90
+ triggerContent: j,
91
+ components: l,
92
+ themeIcons: s
93
+ }) {
94
+ const [m, v] = b(!1);
95
+ if (B(() => {
96
+ v(!0);
97
+ }, []), p && !m)
98
+ return null;
99
+ if (!l)
100
+ return /* @__PURE__ */ e.jsx("div", { className: "p-4 text-center text-destructive", children: "错误:请通过 components prop 注入 UI 组件" });
101
+ const {
102
+ DropdownMenu: f,
103
+ DropdownMenuTrigger: w,
104
+ DropdownMenuContent: k,
105
+ DropdownMenuRadioGroup: M,
106
+ DropdownMenuRadioItem: g,
107
+ Button: y
108
+ } = l, c = (r) => {
109
+ if (s && s[r])
110
+ return s[r];
111
+ const t = i.find((W) => W.value === r);
112
+ return t == null ? void 0 : t.icon;
113
+ }, N = c(o), C = x ? N : null, D = n ? { width: n, height: n } : {};
114
+ return /* @__PURE__ */ e.jsxs(f, { children: [
115
+ /* @__PURE__ */ e.jsx(w, { asChild: !0, children: /* @__PURE__ */ e.jsx(
116
+ y,
117
+ {
118
+ variant: d,
119
+ size: u,
120
+ className: h,
121
+ children: j || /* @__PURE__ */ e.jsx(
122
+ "span",
123
+ {
124
+ style: D,
125
+ className: "inline-flex items-center justify-center",
126
+ children: C
127
+ }
128
+ )
129
+ }
130
+ ) }),
131
+ /* @__PURE__ */ e.jsx(k, { children: /* @__PURE__ */ e.jsx(M, { value: o, onValueChange: a, children: i.map((r) => /* @__PURE__ */ e.jsxs(g, { value: r.value, children: [
132
+ /* @__PURE__ */ e.jsx("span", { className: "mr-2 inline-flex items-center", children: c(r.value) }),
133
+ /* @__PURE__ */ e.jsx("span", { children: r.label })
134
+ ] }, r.value)) }) })
135
+ ] });
136
+ }
137
+ export {
138
+ R as ThemeSwitcher
139
+ };
140
+ //# sourceMappingURL=theme-switcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-switcher.js","sources":["../src/components/ThemeSwitcher.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\n\nimport type {\n ButtonComponent,\n DropdownMenuComponent,\n DropdownMenuTriggerComponent,\n DropdownMenuContentComponent,\n DropdownMenuRadioGroupComponent,\n DropdownMenuRadioItemComponent,\n} from '../types/component-types';\n\n/**\n * 主题选项\n */\nexport interface ThemeOption {\n value: string;\n label: string;\n icon: React.ReactNode;\n}\n\n/**\n * UI 组件适配器接口\n */\nexport interface ThemeSwitcherUIComponents {\n DropdownMenu: DropdownMenuComponent;\n DropdownMenuTrigger: DropdownMenuTriggerComponent;\n DropdownMenuContent: DropdownMenuContentComponent;\n DropdownMenuRadioGroup: DropdownMenuRadioGroupComponent;\n DropdownMenuRadioItem: DropdownMenuRadioItemComponent;\n Button: ButtonComponent;\n}\n\nexport interface ThemeSwitcherProps {\n value: string;\n onValueChange: (value: string) => void;\n themes?: ThemeOption[];\n triggerVariant?:\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost'\n | 'link';\n triggerSize?: 'default' | 'sm' | 'lg' | 'icon';\n triggerClassName?: string;\n iconSize?: number;\n showCurrentIcon?: boolean;\n enableSSRHandling?: boolean;\n triggerContent?: React.ReactNode;\n components?: ThemeSwitcherUIComponents;\n // 自定义主题图标(可选)\n themeIcons?: Partial<Record<string, React.ReactNode>>;\n}\n\n/**\n * 默认主题配置\n */\nconst defaultThemes: ThemeOption[] = [\n {\n value: 'light',\n label: '浅色',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" strokeWidth=\"2\" />\n <path\n className=\"opacity-75\"\n d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n />\n </svg>\n ),\n },\n {\n value: 'dark',\n label: '深色',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n d=\"M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n ),\n },\n {\n value: 'system',\n label: '跟随系统',\n icon: (\n <svg\n className=\"h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <rect\n x=\"2\"\n y=\"3\"\n width=\"20\"\n height=\"14\"\n rx=\"2\"\n ry=\"2\"\n strokeWidth=\"2\"\n />\n <path d=\"M8 21h8m-4-4v4\" strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n ),\n },\n];\n\n/**\n * 主题切换组件\n * 需要通过 components prop 注入 UI 组件\n */\nexport function ThemeSwitcher({\n value,\n onValueChange,\n themes = defaultThemes,\n triggerVariant = 'ghost',\n triggerSize = 'icon',\n triggerClassName,\n iconSize = 16,\n showCurrentIcon = true,\n enableSSRHandling = true,\n triggerContent,\n components,\n themeIcons,\n}: ThemeSwitcherProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n if (enableSSRHandling && !mounted) {\n return null;\n }\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 DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n Button,\n } = components;\n\n /**\n * 获取主题图标\n * 优先使用 themeIcons 中的自定义图标,如果没有则使用主题配置中的默认图标\n */\n const getThemeIcon = (themeValue: string): React.ReactNode => {\n if (themeIcons && themeIcons[themeValue]) {\n return themeIcons[themeValue];\n }\n const theme = themes.find((t) => t.value === themeValue);\n return theme?.icon;\n };\n\n const currentIcon = getThemeIcon(value);\n\n const triggerIcon = showCurrentIcon ? currentIcon : null;\n const iconStyle = iconSize ? { width: iconSize, height: iconSize } : {};\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n variant={triggerVariant}\n size={triggerSize}\n className={triggerClassName}\n >\n {triggerContent || (\n <span\n style={iconStyle}\n className=\"inline-flex items-center justify-center\"\n >\n {triggerIcon}\n </span>\n )}\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent>\n <DropdownMenuRadioGroup value={value} onValueChange={onValueChange}>\n {themes.map((theme) => (\n <DropdownMenuRadioItem key={theme.value} value={theme.value}>\n <span className=\"mr-2 inline-flex items-center\">\n {getThemeIcon(theme.value)}\n </span>\n <span>{theme.label}</span>\n </DropdownMenuRadioItem>\n ))}\n </DropdownMenuRadioGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n"],"names":["defaultThemes","jsxs","jsx","ThemeSwitcher","value","onValueChange","themes","triggerVariant","triggerSize","triggerClassName","iconSize","showCurrentIcon","enableSSRHandling","triggerContent","components","themeIcons","mounted","setMounted","useState","useEffect","DropdownMenu","DropdownMenuTrigger","DropdownMenuContent","DropdownMenuRadioGroup","DropdownMenuRadioItem","Button","getThemeIcon","themeValue","theme","t","currentIcon","triggerIcon","iconStyle"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { clsx as o } from "clsx";
2
+ import { twMerge as t } from "tailwind-merge";
3
+ function m(...r) {
4
+ return t(o(r));
5
+ }
6
+ export {
7
+ m as c
8
+ };
9
+ //# sourceMappingURL=utils-B6yFEsav.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-B6yFEsav.js","sources":["../src/lib/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"names":["cn","inputs","twMerge","clsx"],"mappings":";;AAGO,SAASA,KAAMC,GAAsB;AAC1C,SAAOC,EAAQC,EAAKF,CAAM,CAAC;AAC7B;"}
@@ -0,0 +1,2 @@
1
+ "use strict";const r=require("clsx"),c=require("tailwind-merge");function n(...e){return c.twMerge(r.clsx(e))}exports.cn=n;
2
+ //# sourceMappingURL=utils-IjLH3w2e.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils-IjLH3w2e.cjs","sources":["../src/lib/utils.ts"],"sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"],"names":["cn","inputs","twMerge","clsx"],"mappings":"iEAGO,SAASA,KAAMC,EAAsB,CAC1C,OAAOC,EAAAA,QAAQC,OAAKF,CAAM,CAAC,CAC7B"}
package/dist/utils.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./utils-IjLH3w2e.cjs");exports.cn=e.cn;
2
+ //# sourceMappingURL=utils.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export { cn } from './lib/utils';
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC"}
package/dist/utils.js ADDED
@@ -0,0 +1,5 @@
1
+ import { c as r } from "./utils-B6yFEsav.js";
2
+ export {
3
+ r as cn
4
+ };
5
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}