@cynnie/ui-shadcn 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/{ProTable-CP1Mc52q.js → ProTable-Drtee73G.js} +4 -4
- package/dist/{ProTable-CP1Mc52q.js.map → ProTable-Drtee73G.js.map} +1 -1
- package/dist/components/ProTable/index.js +1 -1
- package/dist/index.js +2 -2
- package/dist/{openDialog-CVp3qAfm.js → openDialog-CqfhNoV7.js} +2 -2
- package/dist/{openDialog-CVp3qAfm.js.map → openDialog-CqfhNoV7.js.map} +1 -1
- package/dist/utils/openDialog.js +1 -1
- package/package.json +4 -3
- package/src/style.css +1 -1
- package/src/tailwind.preset.css +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @cynnie/ui-shadcn
|
|
2
2
|
|
|
3
|
-
基于 [shadcn-vue](https://www.shadcn-vue.com/)(reka-ui + Tailwind CSS v4)的
|
|
3
|
+
基于 [shadcn-vue](https://www.shadcn-vue.com/)(reka-ui + Tailwind CSS v4)的 cynnie-ui 二次封装组件库:
|
|
4
|
+
|
|
5
|
+
**[在线文档 & 演示](https://ui-playground-puce.vercel.app/?ui=shadcn)**
|
|
4
6
|
|
|
5
7
|
- **ProTable** — 搜索表单 + 表格 + 分页一体化
|
|
6
8
|
- **ProFormBuilder** — JSON 配置化表单
|
|
@@ -42,7 +44,7 @@ import { ProTable } from "@cynnie/ui-shadcn";
|
|
|
42
44
|
</script>
|
|
43
45
|
```
|
|
44
46
|
|
|
45
|
-
同系列还有 [@cynnie/ui-antd](https://www.npmjs.com/package/@cynnie/ui-antd)(ant-design-vue 版)与 [@cynnie/ui-element](https://www.npmjs.com/package/@cynnie/ui-element)(element-plus
|
|
47
|
+
同系列还有 [@cynnie/ui-antd](https://www.npmjs.com/package/@cynnie/ui-antd)(ant-design-vue 版)与 [@cynnie/ui-element](https://www.npmjs.com/package/@cynnie/ui-element)(element-plus 版),可按 UI 库选用。
|
|
46
48
|
|
|
47
49
|
## License
|
|
48
50
|
|
|
@@ -5,7 +5,7 @@ import { t as ProFormBuilder_default } from "./ProFormBuilder-CsNShZ0y.js";
|
|
|
5
5
|
import { t as Checkbox_default } from "./Checkbox-DswwIgpU.js";
|
|
6
6
|
import { t as ProConfirmButton_default } from "./ProConfirmButton-zcvp7NcN.js";
|
|
7
7
|
import { t as Loader_default } from "./Loader-DZyMmrI8.js";
|
|
8
|
-
import { t as openDialog } from "./openDialog-
|
|
8
|
+
import { t as openDialog } from "./openDialog-CqfhNoV7.js";
|
|
9
9
|
import { Fragment, computed, createApp, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, h, mergeModels, normalizeClass, openBlock, ref, renderList, renderSlot, shallowRef, toDisplayString, unref, useModel, useTemplateRef, withCtx, withKeys, withModifiers } from "vue";
|
|
10
10
|
import { Toaster, toast } from "vue-sonner";
|
|
11
11
|
var _hoisted_1$1 = {
|
|
@@ -94,9 +94,9 @@ var toasterMounted = false;
|
|
|
94
94
|
function ensureToaster() {
|
|
95
95
|
if (toasterMounted || typeof document === "undefined") return;
|
|
96
96
|
toasterMounted = true;
|
|
97
|
-
if (document.querySelector("[data-
|
|
97
|
+
if (document.querySelector("[data-cynnie-sonner-toaster]")) return;
|
|
98
98
|
const container = document.createElement("div");
|
|
99
|
-
container.setAttribute("data-
|
|
99
|
+
container.setAttribute("data-cynnie-sonner-toaster", "");
|
|
100
100
|
document.body.appendChild(container);
|
|
101
101
|
createApp({ render: () => h(Toaster, {
|
|
102
102
|
position: "top-center",
|
|
@@ -346,4 +346,4 @@ var ProTable_default = /* @__PURE__ */ defineComponent({
|
|
|
346
346
|
});
|
|
347
347
|
export { uiMessage as i, ProTableForm_default as n, Toaster as r, ProTable_default as t };
|
|
348
348
|
|
|
349
|
-
//# sourceMappingURL=ProTable-
|
|
349
|
+
//# sourceMappingURL=ProTable-Drtee73G.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProTable-CP1Mc52q.js","names":["formItems","rules","columns"],"sources":["../src/components/ui/table/Table.vue","../src/components/ui/table/Table.vue","../src/components/ui/table/TableBody.vue","../src/components/ui/table/TableBody.vue","../src/components/ui/table/TableCell.vue","../src/components/ui/table/TableCell.vue","../src/components/ui/table/TableHead.vue","../src/components/ui/table/TableHead.vue","../src/components/ui/table/TableHeader.vue","../src/components/ui/table/TableHeader.vue","../src/components/ui/table/TableRow.vue","../src/components/ui/table/TableRow.vue","../src/utils/uiMessage.ts","../src/components/ProTable/ProTableForm.vue","../src/components/ProTable/ProTableForm.vue","../src/components/ProTable/index.vue","../src/components/ProTable/index.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <div data-slot=\"table-container\" class=\"relative w-full overflow-x-auto\">\n <table data-slot=\"table\" :class=\"cn('w-full caption-bottom text-sm', props.class)\">\n <slot />\n </table>\n </div>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <div data-slot=\"table-container\" class=\"relative w-full overflow-x-auto\">\n <table data-slot=\"table\" :class=\"cn('w-full caption-bottom text-sm', props.class)\">\n <slot />\n </table>\n </div>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <tbody data-slot=\"table-body\" :class=\"cn('[&_tr:last-child]:border-0', props.class)\">\n <slot />\n </tbody>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <tbody data-slot=\"table-body\" :class=\"cn('[&_tr:last-child]:border-0', props.class)\">\n <slot />\n </tbody>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <td data-slot=\"table-cell\" :class=\"cn('p-3 align-middle whitespace-nowrap', props.class)\">\n <slot />\n </td>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <td data-slot=\"table-cell\" :class=\"cn('p-3 align-middle whitespace-nowrap', props.class)\">\n <slot />\n </td>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <th\n data-slot=\"table-head\"\n :class=\"cn('text-foreground h-10 px-3 text-left align-middle font-medium whitespace-nowrap', props.class)\"\n >\n <slot />\n </th>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <th\n data-slot=\"table-head\"\n :class=\"cn('text-foreground h-10 px-3 text-left align-middle font-medium whitespace-nowrap', props.class)\"\n >\n <slot />\n </th>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <thead data-slot=\"table-header\" :class=\"cn('[&_tr]:border-b', props.class)\">\n <slot />\n </thead>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <thead data-slot=\"table-header\" :class=\"cn('[&_tr]:border-b', props.class)\">\n <slot />\n </thead>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <tr\n data-slot=\"table-row\"\n :class=\"cn('hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors', props.class)\"\n >\n <slot />\n </tr>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <tr\n data-slot=\"table-row\"\n :class=\"cn('hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors', props.class)\"\n >\n <slot />\n </tr>\n</template>\n","import { createApp, h } from \"vue\";\nimport { Toaster, toast } from \"vue-sonner\";\n\n/**\n * 全局提示的统一抽象:与 ui-antd / ui-element 导出同名方法,调用方无需关心底层 UI 库。\n * shadcn 版基于 vue-sonner(shadcn 官方 toast 方案)。\n *\n * vue-sonner 的 toast 需要页面里存在 <Toaster />;为保证开箱即用,\n * 首次调用时自动在 body 上挂一个(与 antd 的 message 全局可用行为对齐)。\n */\nlet toasterMounted = false;\n\nfunction ensureToaster() {\n if (toasterMounted || typeof document === \"undefined\") return;\n toasterMounted = true;\n if (document.querySelector(\"[data-snowui-sonner-toaster]\")) return;\n const container = document.createElement(\"div\");\n container.setAttribute(\"data-snowui-sonner-toaster\", \"\");\n document.body.appendChild(container);\n const app = createApp({ render: () => h(Toaster, { position: \"top-center\", richColors: true }) });\n app.mount(container);\n}\n\nfunction withToaster<T extends any[]>(call: (...args: T) => any) {\n return (...args: T) => {\n ensureToaster();\n return call(...args);\n };\n}\n\nexport const uiMessage = {\n success: withToaster((content: string) => toast.success(content)),\n info: withToaster((content: string) => toast.info(content)),\n error: withToaster((content: string) => toast.error(content)),\n warning: withToaster((content: string) => toast.warning(content)),\n};\n\nexport { Toaster, toast };\n","<script setup lang=\"ts\">\nimport { ref, useTemplateRef } from \"vue\";\nimport ProFormBuilder from \"../ProFormBuilder/index.vue\";\n\ndefineOptions({\n name: \"ProTableForm\",\n});\n\nconst props = defineProps<{\n formItems: any[];\n rules?: any;\n formData: Record<string, any>;\n requestApi: (data: Record<string, any>) => Promise<any>;\n}>();\n\nconst data = ref<Record<string, any>>({ ...props.formData });\nconst formRef = useTemplateRef<any>(\"formRef\");\n\ndefineExpose({\n async submit() {\n await formRef.value?.validate();\n return props.requestApi({\n ...data.value,\n });\n },\n});\n</script>\n\n<template>\n <ProFormBuilder ref=\"formRef\" :modelValue=\"data\" :form-items=\"formItems\" :rules=\"rules\" />\n</template>\n","<script setup lang=\"ts\">\nimport { ref, useTemplateRef } from \"vue\";\nimport ProFormBuilder from \"../ProFormBuilder/index.vue\";\n\ndefineOptions({\n name: \"ProTableForm\",\n});\n\nconst props = defineProps<{\n formItems: any[];\n rules?: any;\n formData: Record<string, any>;\n requestApi: (data: Record<string, any>) => Promise<any>;\n}>();\n\nconst data = ref<Record<string, any>>({ ...props.formData });\nconst formRef = useTemplateRef<any>(\"formRef\");\n\ndefineExpose({\n async submit() {\n await formRef.value?.validate();\n return props.requestApi({\n ...data.value,\n });\n },\n});\n</script>\n\n<template>\n <ProFormBuilder ref=\"formRef\" :modelValue=\"data\" :form-items=\"formItems\" :rules=\"rules\" />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, shallowRef } from \"vue\";\nimport { openDialog } from \"../../utils/openDialog\";\nimport ProTableForm from \"./ProTableForm.vue\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"../ui/table\";\nimport { Checkbox } from \"../ui/checkbox\";\nimport { Loader } from \"../ui/loader\";\nimport ProConfirmButton from \"../ProConfirmButton/index.vue\";\nimport { uiMessage } from \"../../utils/uiMessage\";\nimport type { PageApis, TableColumn, FormItem, FormRules } from \"@cynnie/ui-core\";\n\ndefineOptions({\n name: \"ProTable\",\n});\n\nconst props = defineProps<{\n apis: PageApis;\n rowKey?: string;\n beforeCreate?: () => Promise<Record<string, any>>;\n columns: TableColumn[];\n formItems: FormItem[];\n rules?: FormRules;\n}>();\n\nconst key = props.rowKey || \"id\";\n\nconst queryParams = defineModel<any>(\"queryParams\", { default: () => ({}) });\n\nconst { get, create, update, remove } = props.apis;\nconst dataSource = ref<any[]>([]);\nconst isLoading = ref(false);\nfunction loadData() {\n isLoading.value = true;\n get(queryParams.value)\n .then((res) => {\n dataSource.value = res.data;\n })\n .finally(() => {\n isLoading.value = false;\n });\n}\n\nconst selectedRowKeys = ref<any[]>([]);\n\nconst selectedRow = shallowRef<Record<string, any>>();\n\nconst allSelected = computed(\n () => dataSource.value.length > 0 && dataSource.value.every((row) => selectedRowKeys.value.includes(row[key])),\n);\n\nfunction onSelectAll(checked: boolean | \"indeterminate\") {\n if (checked === true) {\n selectedRowKeys.value = dataSource.value.map((row) => row[key]);\n } else {\n selectedRowKeys.value = [];\n }\n}\n\nfunction onSelectRow(row: Record<string, any>, checked: boolean | \"indeterminate\") {\n if (checked === true) {\n selectedRowKeys.value = [...selectedRowKeys.value, row[key]];\n } else {\n selectedRowKeys.value = selectedRowKeys.value.filter((k) => k !== row[key]);\n }\n // 与 antd / element 版对齐:selection 变化即更新 selectedRow\n selectedRow.value = dataSource.value.find((row) => row[key] === selectedRowKeys.value[0]);\n}\n\nfunction onSelectChange(row: Record<string, any>) {\n const rowKey = row[key];\n const checked = !selectedRowKeys.value.includes(rowKey);\n onSelectRow(row, checked);\n}\n\nloadData();\n\nfunction openForm(data: Record<string, any>) {\n openDialog(\n ProTableForm,\n {\n requestApi: data[key] ? update : create,\n formItems: props.formItems,\n rules: props.rules,\n formData: data,\n },\n {\n title: data[key] ? \"修改\" : \"新增\",\n onOk: () => {\n loadData();\n },\n },\n );\n}\n\nasync function handleCreate() {\n openForm({});\n}\nfunction handleUpdate() {\n openForm(selectedRow.value);\n}\nfunction handleRemove() {\n remove(selectedRowKeys.value)\n .then(loadData)\n .catch(() => {\n uiMessage.error(\"删除失败\");\n });\n}\n\ndefineExpose({\n refresh: loadData,\n});\n</script>\n\n<template>\n <div>\n <div class=\"flex flex-wrap items-center gap-3 mb-5\">\n <Button variant=\"default\" @click=\"handleCreate\">新增</Button>\n <Button variant=\"default\" :disabled=\"!selectedRowKeys.length || undefined\" @click=\"handleUpdate\">修改</Button>\n <ProConfirmButton danger title=\"确定删除吗?\" :disabled=\"!selectedRowKeys.length\" :on-confirm=\"handleRemove\">\n 删除\n </ProConfirmButton>\n <slot name=\"search\"></slot>\n <div class=\"flex items-center gap-2 flex-1 max-w-70\">\n <Input\n v-model=\"queryParams.keyword\"\n placeholder=\"搜索关键词\"\n @keydown.enter=\"loadData\"\n />\n <Button variant=\"outline\" @click=\"loadData\">搜索</Button>\n </div>\n </div>\n\n <div class=\"rounded-md border\">\n <Table>\n <TableHeader>\n <TableRow class=\"hover:bg-transparent\">\n <TableCell class=\"w-10\">\n <Checkbox :model-value=\"allSelected\" @update:model-value=\"onSelectAll\" aria-label=\"全选\" />\n </TableCell>\n <TableHead v-for=\"col in columns\" :key=\"col.dataIndex\">{{ col.title }}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <template v-if=\"!isLoading\">\n <TableRow\n v-for=\"row in dataSource\"\n :key=\"row[key]\"\n :class=\"{ 'bg-muted/50': selectedRowKeys.includes(row[key]) }\"\n class=\"cursor-pointer\"\n @click=\"onSelectChange(row)\"\n >\n <TableCell @click.stop>\n <Checkbox\n :model-value=\"selectedRowKeys.includes(row[key])\"\n @update:model-value=\"(v: any) => onSelectRow(row, v)\"\n :aria-label=\"`选择 ${row[key]}`\"\n />\n </TableCell>\n <TableCell v-for=\"col in columns\" :key=\"col.dataIndex\">{{ row[col.dataIndex] }}</TableCell>\n </TableRow>\n <TableRow v-if=\"!dataSource.length\" class=\"hover:bg-transparent\">\n <TableCell class=\"h-24 text-center text-muted-foreground\" :colspan=\"columns.length + 1\">\n 暂无数据\n </TableCell>\n </TableRow>\n </template>\n <TableRow v-else class=\"hover:bg-transparent\">\n <TableCell class=\"h-24\" :colspan=\"columns.length + 1\">\n <div class=\"flex items-center justify-center gap-2 text-muted-foreground\">\n <Loader />\n 加载中...\n </div>\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, shallowRef } from \"vue\";\nimport { openDialog } from \"../../utils/openDialog\";\nimport ProTableForm from \"./ProTableForm.vue\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"../ui/table\";\nimport { Checkbox } from \"../ui/checkbox\";\nimport { Loader } from \"../ui/loader\";\nimport ProConfirmButton from \"../ProConfirmButton/index.vue\";\nimport { uiMessage } from \"../../utils/uiMessage\";\nimport type { PageApis, TableColumn, FormItem, FormRules } from \"@cynnie/ui-core\";\n\ndefineOptions({\n name: \"ProTable\",\n});\n\nconst props = defineProps<{\n apis: PageApis;\n rowKey?: string;\n beforeCreate?: () => Promise<Record<string, any>>;\n columns: TableColumn[];\n formItems: FormItem[];\n rules?: FormRules;\n}>();\n\nconst key = props.rowKey || \"id\";\n\nconst queryParams = defineModel<any>(\"queryParams\", { default: () => ({}) });\n\nconst { get, create, update, remove } = props.apis;\nconst dataSource = ref<any[]>([]);\nconst isLoading = ref(false);\nfunction loadData() {\n isLoading.value = true;\n get(queryParams.value)\n .then((res) => {\n dataSource.value = res.data;\n })\n .finally(() => {\n isLoading.value = false;\n });\n}\n\nconst selectedRowKeys = ref<any[]>([]);\n\nconst selectedRow = shallowRef<Record<string, any>>();\n\nconst allSelected = computed(\n () => dataSource.value.length > 0 && dataSource.value.every((row) => selectedRowKeys.value.includes(row[key])),\n);\n\nfunction onSelectAll(checked: boolean | \"indeterminate\") {\n if (checked === true) {\n selectedRowKeys.value = dataSource.value.map((row) => row[key]);\n } else {\n selectedRowKeys.value = [];\n }\n}\n\nfunction onSelectRow(row: Record<string, any>, checked: boolean | \"indeterminate\") {\n if (checked === true) {\n selectedRowKeys.value = [...selectedRowKeys.value, row[key]];\n } else {\n selectedRowKeys.value = selectedRowKeys.value.filter((k) => k !== row[key]);\n }\n // 与 antd / element 版对齐:selection 变化即更新 selectedRow\n selectedRow.value = dataSource.value.find((row) => row[key] === selectedRowKeys.value[0]);\n}\n\nfunction onSelectChange(row: Record<string, any>) {\n const rowKey = row[key];\n const checked = !selectedRowKeys.value.includes(rowKey);\n onSelectRow(row, checked);\n}\n\nloadData();\n\nfunction openForm(data: Record<string, any>) {\n openDialog(\n ProTableForm,\n {\n requestApi: data[key] ? update : create,\n formItems: props.formItems,\n rules: props.rules,\n formData: data,\n },\n {\n title: data[key] ? \"修改\" : \"新增\",\n onOk: () => {\n loadData();\n },\n },\n );\n}\n\nasync function handleCreate() {\n openForm({});\n}\nfunction handleUpdate() {\n openForm(selectedRow.value);\n}\nfunction handleRemove() {\n remove(selectedRowKeys.value)\n .then(loadData)\n .catch(() => {\n uiMessage.error(\"删除失败\");\n });\n}\n\ndefineExpose({\n refresh: loadData,\n});\n</script>\n\n<template>\n <div>\n <div class=\"flex flex-wrap items-center gap-3 mb-5\">\n <Button variant=\"default\" @click=\"handleCreate\">新增</Button>\n <Button variant=\"default\" :disabled=\"!selectedRowKeys.length || undefined\" @click=\"handleUpdate\">修改</Button>\n <ProConfirmButton danger title=\"确定删除吗?\" :disabled=\"!selectedRowKeys.length\" :on-confirm=\"handleRemove\">\n 删除\n </ProConfirmButton>\n <slot name=\"search\"></slot>\n <div class=\"flex items-center gap-2 flex-1 max-w-70\">\n <Input\n v-model=\"queryParams.keyword\"\n placeholder=\"搜索关键词\"\n @keydown.enter=\"loadData\"\n />\n <Button variant=\"outline\" @click=\"loadData\">搜索</Button>\n </div>\n </div>\n\n <div class=\"rounded-md border\">\n <Table>\n <TableHeader>\n <TableRow class=\"hover:bg-transparent\">\n <TableCell class=\"w-10\">\n <Checkbox :model-value=\"allSelected\" @update:model-value=\"onSelectAll\" aria-label=\"全选\" />\n </TableCell>\n <TableHead v-for=\"col in columns\" :key=\"col.dataIndex\">{{ col.title }}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <template v-if=\"!isLoading\">\n <TableRow\n v-for=\"row in dataSource\"\n :key=\"row[key]\"\n :class=\"{ 'bg-muted/50': selectedRowKeys.includes(row[key]) }\"\n class=\"cursor-pointer\"\n @click=\"onSelectChange(row)\"\n >\n <TableCell @click.stop>\n <Checkbox\n :model-value=\"selectedRowKeys.includes(row[key])\"\n @update:model-value=\"(v: any) => onSelectRow(row, v)\"\n :aria-label=\"`选择 ${row[key]}`\"\n />\n </TableCell>\n <TableCell v-for=\"col in columns\" :key=\"col.dataIndex\">{{ row[col.dataIndex] }}</TableCell>\n </TableRow>\n <TableRow v-if=\"!dataSource.length\" class=\"hover:bg-transparent\">\n <TableCell class=\"h-24 text-center text-muted-foreground\" :colspan=\"columns.length + 1\">\n 暂无数据\n </TableCell>\n </TableRow>\n </template>\n <TableRow v-else class=\"hover:bg-transparent\">\n <TableCell class=\"h-24\" :colspan=\"columns.length + 1\">\n <div class=\"flex items-center justify-center gap-2 text-muted-foreground\">\n <Loader />\n 加载中...\n </div>\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ProTable-Drtee73G.js","names":["formItems","rules","columns"],"sources":["../src/components/ui/table/Table.vue","../src/components/ui/table/Table.vue","../src/components/ui/table/TableBody.vue","../src/components/ui/table/TableBody.vue","../src/components/ui/table/TableCell.vue","../src/components/ui/table/TableCell.vue","../src/components/ui/table/TableHead.vue","../src/components/ui/table/TableHead.vue","../src/components/ui/table/TableHeader.vue","../src/components/ui/table/TableHeader.vue","../src/components/ui/table/TableRow.vue","../src/components/ui/table/TableRow.vue","../src/utils/uiMessage.ts","../src/components/ProTable/ProTableForm.vue","../src/components/ProTable/ProTableForm.vue","../src/components/ProTable/index.vue","../src/components/ProTable/index.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <div data-slot=\"table-container\" class=\"relative w-full overflow-x-auto\">\n <table data-slot=\"table\" :class=\"cn('w-full caption-bottom text-sm', props.class)\">\n <slot />\n </table>\n </div>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <div data-slot=\"table-container\" class=\"relative w-full overflow-x-auto\">\n <table data-slot=\"table\" :class=\"cn('w-full caption-bottom text-sm', props.class)\">\n <slot />\n </table>\n </div>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <tbody data-slot=\"table-body\" :class=\"cn('[&_tr:last-child]:border-0', props.class)\">\n <slot />\n </tbody>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <tbody data-slot=\"table-body\" :class=\"cn('[&_tr:last-child]:border-0', props.class)\">\n <slot />\n </tbody>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <td data-slot=\"table-cell\" :class=\"cn('p-3 align-middle whitespace-nowrap', props.class)\">\n <slot />\n </td>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <td data-slot=\"table-cell\" :class=\"cn('p-3 align-middle whitespace-nowrap', props.class)\">\n <slot />\n </td>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <th\n data-slot=\"table-head\"\n :class=\"cn('text-foreground h-10 px-3 text-left align-middle font-medium whitespace-nowrap', props.class)\"\n >\n <slot />\n </th>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <th\n data-slot=\"table-head\"\n :class=\"cn('text-foreground h-10 px-3 text-left align-middle font-medium whitespace-nowrap', props.class)\"\n >\n <slot />\n </th>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <thead data-slot=\"table-header\" :class=\"cn('[&_tr]:border-b', props.class)\">\n <slot />\n </thead>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <thead data-slot=\"table-header\" :class=\"cn('[&_tr]:border-b', props.class)\">\n <slot />\n </thead>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <tr\n data-slot=\"table-row\"\n :class=\"cn('hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors', props.class)\"\n >\n <slot />\n </tr>\n</template>\n","<script lang=\"ts\" setup>\nimport type { HTMLAttributes } from \"vue\";\nimport { cn } from \"../../../lib/utils\";\n\nconst props = defineProps<{\n class?: HTMLAttributes[\"class\"];\n}>();\n</script>\n\n<template>\n <tr\n data-slot=\"table-row\"\n :class=\"cn('hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors', props.class)\"\n >\n <slot />\n </tr>\n</template>\n","import { createApp, h } from \"vue\";\nimport { Toaster, toast } from \"vue-sonner\";\n\n/**\n * 全局提示的统一抽象:与 ui-antd / ui-element 导出同名方法,调用方无需关心底层 UI 库。\n * shadcn 版基于 vue-sonner(shadcn 官方 toast 方案)。\n *\n * vue-sonner 的 toast 需要页面里存在 <Toaster />;为保证开箱即用,\n * 首次调用时自动在 body 上挂一个(与 antd 的 message 全局可用行为对齐)。\n */\nlet toasterMounted = false;\n\nfunction ensureToaster() {\n if (toasterMounted || typeof document === \"undefined\") return;\n toasterMounted = true;\n if (document.querySelector(\"[data-cynnie-sonner-toaster]\")) return;\n const container = document.createElement(\"div\");\n container.setAttribute(\"data-cynnie-sonner-toaster\", \"\");\n document.body.appendChild(container);\n const app = createApp({ render: () => h(Toaster, { position: \"top-center\", richColors: true }) });\n app.mount(container);\n}\n\nfunction withToaster<T extends any[]>(call: (...args: T) => any) {\n return (...args: T) => {\n ensureToaster();\n return call(...args);\n };\n}\n\nexport const uiMessage = {\n success: withToaster((content: string) => toast.success(content)),\n info: withToaster((content: string) => toast.info(content)),\n error: withToaster((content: string) => toast.error(content)),\n warning: withToaster((content: string) => toast.warning(content)),\n};\n\nexport { Toaster, toast };\n","<script setup lang=\"ts\">\nimport { ref, useTemplateRef } from \"vue\";\nimport ProFormBuilder from \"../ProFormBuilder/index.vue\";\n\ndefineOptions({\n name: \"ProTableForm\",\n});\n\nconst props = defineProps<{\n formItems: any[];\n rules?: any;\n formData: Record<string, any>;\n requestApi: (data: Record<string, any>) => Promise<any>;\n}>();\n\nconst data = ref<Record<string, any>>({ ...props.formData });\nconst formRef = useTemplateRef<any>(\"formRef\");\n\ndefineExpose({\n async submit() {\n await formRef.value?.validate();\n return props.requestApi({\n ...data.value,\n });\n },\n});\n</script>\n\n<template>\n <ProFormBuilder ref=\"formRef\" :modelValue=\"data\" :form-items=\"formItems\" :rules=\"rules\" />\n</template>\n","<script setup lang=\"ts\">\nimport { ref, useTemplateRef } from \"vue\";\nimport ProFormBuilder from \"../ProFormBuilder/index.vue\";\n\ndefineOptions({\n name: \"ProTableForm\",\n});\n\nconst props = defineProps<{\n formItems: any[];\n rules?: any;\n formData: Record<string, any>;\n requestApi: (data: Record<string, any>) => Promise<any>;\n}>();\n\nconst data = ref<Record<string, any>>({ ...props.formData });\nconst formRef = useTemplateRef<any>(\"formRef\");\n\ndefineExpose({\n async submit() {\n await formRef.value?.validate();\n return props.requestApi({\n ...data.value,\n });\n },\n});\n</script>\n\n<template>\n <ProFormBuilder ref=\"formRef\" :modelValue=\"data\" :form-items=\"formItems\" :rules=\"rules\" />\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, shallowRef } from \"vue\";\nimport { openDialog } from \"../../utils/openDialog\";\nimport ProTableForm from \"./ProTableForm.vue\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"../ui/table\";\nimport { Checkbox } from \"../ui/checkbox\";\nimport { Loader } from \"../ui/loader\";\nimport ProConfirmButton from \"../ProConfirmButton/index.vue\";\nimport { uiMessage } from \"../../utils/uiMessage\";\nimport type { PageApis, TableColumn, FormItem, FormRules } from \"@cynnie/ui-core\";\n\ndefineOptions({\n name: \"ProTable\",\n});\n\nconst props = defineProps<{\n apis: PageApis;\n rowKey?: string;\n beforeCreate?: () => Promise<Record<string, any>>;\n columns: TableColumn[];\n formItems: FormItem[];\n rules?: FormRules;\n}>();\n\nconst key = props.rowKey || \"id\";\n\nconst queryParams = defineModel<any>(\"queryParams\", { default: () => ({}) });\n\nconst { get, create, update, remove } = props.apis;\nconst dataSource = ref<any[]>([]);\nconst isLoading = ref(false);\nfunction loadData() {\n isLoading.value = true;\n get(queryParams.value)\n .then((res) => {\n dataSource.value = res.data;\n })\n .finally(() => {\n isLoading.value = false;\n });\n}\n\nconst selectedRowKeys = ref<any[]>([]);\n\nconst selectedRow = shallowRef<Record<string, any>>();\n\nconst allSelected = computed(\n () => dataSource.value.length > 0 && dataSource.value.every((row) => selectedRowKeys.value.includes(row[key])),\n);\n\nfunction onSelectAll(checked: boolean | \"indeterminate\") {\n if (checked === true) {\n selectedRowKeys.value = dataSource.value.map((row) => row[key]);\n } else {\n selectedRowKeys.value = [];\n }\n}\n\nfunction onSelectRow(row: Record<string, any>, checked: boolean | \"indeterminate\") {\n if (checked === true) {\n selectedRowKeys.value = [...selectedRowKeys.value, row[key]];\n } else {\n selectedRowKeys.value = selectedRowKeys.value.filter((k) => k !== row[key]);\n }\n // 与 antd / element 版对齐:selection 变化即更新 selectedRow\n selectedRow.value = dataSource.value.find((row) => row[key] === selectedRowKeys.value[0]);\n}\n\nfunction onSelectChange(row: Record<string, any>) {\n const rowKey = row[key];\n const checked = !selectedRowKeys.value.includes(rowKey);\n onSelectRow(row, checked);\n}\n\nloadData();\n\nfunction openForm(data: Record<string, any>) {\n openDialog(\n ProTableForm,\n {\n requestApi: data[key] ? update : create,\n formItems: props.formItems,\n rules: props.rules,\n formData: data,\n },\n {\n title: data[key] ? \"修改\" : \"新增\",\n onOk: () => {\n loadData();\n },\n },\n );\n}\n\nasync function handleCreate() {\n openForm({});\n}\nfunction handleUpdate() {\n openForm(selectedRow.value);\n}\nfunction handleRemove() {\n remove(selectedRowKeys.value)\n .then(loadData)\n .catch(() => {\n uiMessage.error(\"删除失败\");\n });\n}\n\ndefineExpose({\n refresh: loadData,\n});\n</script>\n\n<template>\n <div>\n <div class=\"flex flex-wrap items-center gap-3 mb-5\">\n <Button variant=\"default\" @click=\"handleCreate\">新增</Button>\n <Button variant=\"default\" :disabled=\"!selectedRowKeys.length || undefined\" @click=\"handleUpdate\">修改</Button>\n <ProConfirmButton danger title=\"确定删除吗?\" :disabled=\"!selectedRowKeys.length\" :on-confirm=\"handleRemove\">\n 删除\n </ProConfirmButton>\n <slot name=\"search\"></slot>\n <div class=\"flex items-center gap-2 flex-1 max-w-70\">\n <Input\n v-model=\"queryParams.keyword\"\n placeholder=\"搜索关键词\"\n @keydown.enter=\"loadData\"\n />\n <Button variant=\"outline\" @click=\"loadData\">搜索</Button>\n </div>\n </div>\n\n <div class=\"rounded-md border\">\n <Table>\n <TableHeader>\n <TableRow class=\"hover:bg-transparent\">\n <TableCell class=\"w-10\">\n <Checkbox :model-value=\"allSelected\" @update:model-value=\"onSelectAll\" aria-label=\"全选\" />\n </TableCell>\n <TableHead v-for=\"col in columns\" :key=\"col.dataIndex\">{{ col.title }}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <template v-if=\"!isLoading\">\n <TableRow\n v-for=\"row in dataSource\"\n :key=\"row[key]\"\n :class=\"{ 'bg-muted/50': selectedRowKeys.includes(row[key]) }\"\n class=\"cursor-pointer\"\n @click=\"onSelectChange(row)\"\n >\n <TableCell @click.stop>\n <Checkbox\n :model-value=\"selectedRowKeys.includes(row[key])\"\n @update:model-value=\"(v: any) => onSelectRow(row, v)\"\n :aria-label=\"`选择 ${row[key]}`\"\n />\n </TableCell>\n <TableCell v-for=\"col in columns\" :key=\"col.dataIndex\">{{ row[col.dataIndex] }}</TableCell>\n </TableRow>\n <TableRow v-if=\"!dataSource.length\" class=\"hover:bg-transparent\">\n <TableCell class=\"h-24 text-center text-muted-foreground\" :colspan=\"columns.length + 1\">\n 暂无数据\n </TableCell>\n </TableRow>\n </template>\n <TableRow v-else class=\"hover:bg-transparent\">\n <TableCell class=\"h-24\" :colspan=\"columns.length + 1\">\n <div class=\"flex items-center justify-center gap-2 text-muted-foreground\">\n <Loader />\n 加载中...\n </div>\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, shallowRef } from \"vue\";\nimport { openDialog } from \"../../utils/openDialog\";\nimport ProTableForm from \"./ProTableForm.vue\";\nimport { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"../ui/table\";\nimport { Checkbox } from \"../ui/checkbox\";\nimport { Loader } from \"../ui/loader\";\nimport ProConfirmButton from \"../ProConfirmButton/index.vue\";\nimport { uiMessage } from \"../../utils/uiMessage\";\nimport type { PageApis, TableColumn, FormItem, FormRules } from \"@cynnie/ui-core\";\n\ndefineOptions({\n name: \"ProTable\",\n});\n\nconst props = defineProps<{\n apis: PageApis;\n rowKey?: string;\n beforeCreate?: () => Promise<Record<string, any>>;\n columns: TableColumn[];\n formItems: FormItem[];\n rules?: FormRules;\n}>();\n\nconst key = props.rowKey || \"id\";\n\nconst queryParams = defineModel<any>(\"queryParams\", { default: () => ({}) });\n\nconst { get, create, update, remove } = props.apis;\nconst dataSource = ref<any[]>([]);\nconst isLoading = ref(false);\nfunction loadData() {\n isLoading.value = true;\n get(queryParams.value)\n .then((res) => {\n dataSource.value = res.data;\n })\n .finally(() => {\n isLoading.value = false;\n });\n}\n\nconst selectedRowKeys = ref<any[]>([]);\n\nconst selectedRow = shallowRef<Record<string, any>>();\n\nconst allSelected = computed(\n () => dataSource.value.length > 0 && dataSource.value.every((row) => selectedRowKeys.value.includes(row[key])),\n);\n\nfunction onSelectAll(checked: boolean | \"indeterminate\") {\n if (checked === true) {\n selectedRowKeys.value = dataSource.value.map((row) => row[key]);\n } else {\n selectedRowKeys.value = [];\n }\n}\n\nfunction onSelectRow(row: Record<string, any>, checked: boolean | \"indeterminate\") {\n if (checked === true) {\n selectedRowKeys.value = [...selectedRowKeys.value, row[key]];\n } else {\n selectedRowKeys.value = selectedRowKeys.value.filter((k) => k !== row[key]);\n }\n // 与 antd / element 版对齐:selection 变化即更新 selectedRow\n selectedRow.value = dataSource.value.find((row) => row[key] === selectedRowKeys.value[0]);\n}\n\nfunction onSelectChange(row: Record<string, any>) {\n const rowKey = row[key];\n const checked = !selectedRowKeys.value.includes(rowKey);\n onSelectRow(row, checked);\n}\n\nloadData();\n\nfunction openForm(data: Record<string, any>) {\n openDialog(\n ProTableForm,\n {\n requestApi: data[key] ? update : create,\n formItems: props.formItems,\n rules: props.rules,\n formData: data,\n },\n {\n title: data[key] ? \"修改\" : \"新增\",\n onOk: () => {\n loadData();\n },\n },\n );\n}\n\nasync function handleCreate() {\n openForm({});\n}\nfunction handleUpdate() {\n openForm(selectedRow.value);\n}\nfunction handleRemove() {\n remove(selectedRowKeys.value)\n .then(loadData)\n .catch(() => {\n uiMessage.error(\"删除失败\");\n });\n}\n\ndefineExpose({\n refresh: loadData,\n});\n</script>\n\n<template>\n <div>\n <div class=\"flex flex-wrap items-center gap-3 mb-5\">\n <Button variant=\"default\" @click=\"handleCreate\">新增</Button>\n <Button variant=\"default\" :disabled=\"!selectedRowKeys.length || undefined\" @click=\"handleUpdate\">修改</Button>\n <ProConfirmButton danger title=\"确定删除吗?\" :disabled=\"!selectedRowKeys.length\" :on-confirm=\"handleRemove\">\n 删除\n </ProConfirmButton>\n <slot name=\"search\"></slot>\n <div class=\"flex items-center gap-2 flex-1 max-w-70\">\n <Input\n v-model=\"queryParams.keyword\"\n placeholder=\"搜索关键词\"\n @keydown.enter=\"loadData\"\n />\n <Button variant=\"outline\" @click=\"loadData\">搜索</Button>\n </div>\n </div>\n\n <div class=\"rounded-md border\">\n <Table>\n <TableHeader>\n <TableRow class=\"hover:bg-transparent\">\n <TableCell class=\"w-10\">\n <Checkbox :model-value=\"allSelected\" @update:model-value=\"onSelectAll\" aria-label=\"全选\" />\n </TableCell>\n <TableHead v-for=\"col in columns\" :key=\"col.dataIndex\">{{ col.title }}</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n <template v-if=\"!isLoading\">\n <TableRow\n v-for=\"row in dataSource\"\n :key=\"row[key]\"\n :class=\"{ 'bg-muted/50': selectedRowKeys.includes(row[key]) }\"\n class=\"cursor-pointer\"\n @click=\"onSelectChange(row)\"\n >\n <TableCell @click.stop>\n <Checkbox\n :model-value=\"selectedRowKeys.includes(row[key])\"\n @update:model-value=\"(v: any) => onSelectRow(row, v)\"\n :aria-label=\"`选择 ${row[key]}`\"\n />\n </TableCell>\n <TableCell v-for=\"col in columns\" :key=\"col.dataIndex\">{{ row[col.dataIndex] }}</TableCell>\n </TableRow>\n <TableRow v-if=\"!dataSource.length\" class=\"hover:bg-transparent\">\n <TableCell class=\"h-24 text-center text-muted-foreground\" :colspan=\"columns.length + 1\">\n 暂无数据\n </TableCell>\n </TableRow>\n </template>\n <TableRow v-else class=\"hover:bg-transparent\">\n <TableCell class=\"h-24\" :colspan=\"columns.length + 1\">\n <div class=\"flex items-center justify-center gap-2 text-muted-foreground\">\n <Loader />\n 加载中...\n </div>\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as ProTable_default } from "../../ProTable-
|
|
1
|
+
import { t as ProTable_default } from "../../ProTable-Drtee73G.js";
|
|
2
2
|
export { ProTable_default as default };
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,8 @@ import { t as Button_default } from "./button-BQVT6mY3.js";
|
|
|
2
2
|
import { t as ProFormBuilder_default } from "./ProFormBuilder-CsNShZ0y.js";
|
|
3
3
|
import { t as ProRadioGroup_default } from "./ProRadioGroup-CTxqLQjw.js";
|
|
4
4
|
import { t as ProConfirmButton_default } from "./ProConfirmButton-zcvp7NcN.js";
|
|
5
|
-
import { i as uiMessage, n as ProTableForm_default, r as Toaster, t as ProTable_default } from "./ProTable-
|
|
6
|
-
import { n as renderDialogForm, t as openDialog } from "./openDialog-
|
|
5
|
+
import { i as uiMessage, n as ProTableForm_default, r as Toaster, t as ProTable_default } from "./ProTable-Drtee73G.js";
|
|
6
|
+
import { n as renderDialogForm, t as openDialog } from "./openDialog-CqfhNoV7.js";
|
|
7
7
|
import { t as ProButton_default } from "./ProButton-BQWpTTCy.js";
|
|
8
8
|
import { t as ProInput_default } from "./ProInput-D20F1Xx-.js";
|
|
9
9
|
import { t as ProSelect_default } from "./ProSelect-DT0zjDjT.js";
|
|
@@ -9,7 +9,7 @@ function openDialog(component, props = EMPTY_OBJ, modelProps = EMPTY_OBJ) {
|
|
|
9
9
|
const open = ref(true);
|
|
10
10
|
const instance = ref();
|
|
11
11
|
const container = document.createElement("div");
|
|
12
|
-
container.setAttribute("data-
|
|
12
|
+
container.setAttribute("data-cynnie-dialog-container", "");
|
|
13
13
|
const loading = ref(false);
|
|
14
14
|
document.body.appendChild(container);
|
|
15
15
|
const reactiveModelProps = reactive(modelProps);
|
|
@@ -92,4 +92,4 @@ function renderDialogForm(formProps, modelProps = EMPTY_OBJ) {
|
|
|
92
92
|
}
|
|
93
93
|
export { renderDialogForm as n, openDialog as t };
|
|
94
94
|
|
|
95
|
-
//# sourceMappingURL=openDialog-
|
|
95
|
+
//# sourceMappingURL=openDialog-CqfhNoV7.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openDialog-
|
|
1
|
+
{"version":3,"file":"openDialog-CqfhNoV7.js","names":["result: any"],"sources":["../src/utils/openDialog.ts"],"sourcesContent":["import { type Component, h, createApp, reactive, ref, defineComponent } from \"vue\";\nimport { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button, Loader } from \"../components/ui/index.js\";\nimport ProFormBuilder from \"../components/ProFormBuilder/index.vue\";\nimport type { DialogHandle } from \"@cynnie/ui-core\";\n\n// 避免每次调用都创建新空对象\nconst EMPTY_OBJ = Object.freeze({});\n\n/** openDialog 的弹窗配置:与 antd / element 版的公共字段对齐(title / width / onOk / onCancel 等) */\ninterface ShadcnDialogProps extends Record<string, any> {\n title?: any;\n width?: string | number;\n onOk?: (result?: any) => any;\n onCancel?: (e?: any) => any;\n}\n\nexport function openDialog(\n component: Component,\n props: Record<string, any> = EMPTY_OBJ,\n modelProps: ShadcnDialogProps = EMPTY_OBJ,\n): DialogHandle {\n // 调用方可通过 props 传 methodKey / onSubmit 自定义确定按钮的行为:\n // - methodKey:内容组件暴露的方法名,默认 'submit'\n // - onSubmit:直接传函数(拿到内容组件实例),优先级高于 methodKey\n const { methodKey = \"submit\", onSubmit, ...restProps } = props;\n const open = ref(true);\n const instance = ref<Record<string, any>>();\n const container = document.createElement(\"div\");\n container.setAttribute(\"data-cynnie-dialog-container\", \"\");\n const loading = ref(false);\n document.body.appendChild(container);\n\n // reactive 包一层:外部传 ref 的 title 等配置可动态响应\n const reactiveModelProps = reactive(modelProps);\n\n async function handleOk() {\n loading.value = true;\n try {\n let result: any;\n if (onSubmit) {\n result = await onSubmit(instance.value);\n } else if (instance.value?.[methodKey]) {\n result = await instance.value[methodKey]();\n }\n open.value = false;\n // 内容组件提交方法(或 onSubmit)的返回值交给 onOk\n reactiveModelProps.onOk?.(result);\n } catch {\n // 提交失败(校验不通过 / 请求报错)保持弹窗打开\n } finally {\n loading.value = false;\n }\n }\n\n function unmount() {\n app.unmount();\n document.body.removeChild(container);\n }\n\n // 关闭动画结束后再卸载\n function watchClose() {\n const stop = setInterval(() => {\n if (!open.value) {\n clearInterval(stop);\n setTimeout(unmount, 250);\n }\n }, 100);\n }\n\n const DialogWithFooter = defineComponent({\n setup() {\n return () => {\n const title =\n typeof reactiveModelProps.title === \"function\"\n ? (reactiveModelProps.title as any)()\n : reactiveModelProps.title;\n const widthStyle =\n reactiveModelProps.width != null\n ? {\n width:\n typeof reactiveModelProps.width === \"number\"\n ? `${reactiveModelProps.width}px`\n : reactiveModelProps.width,\n maxWidth: \"calc(100% - 2rem)\",\n }\n : undefined;\n return h(\n Dialog,\n { open: open.value, \"onUpdate:open\": (value: boolean) => (open.value = value) },\n {\n default: () =>\n h(\n DialogContent,\n {\n style: widthStyle,\n onEscapeKeyDown: (event: any) => {\n // ESC / 点遮罩关闭都走 onCancel,与 antd / element 版对齐\n reactiveModelProps.onCancel?.(event);\n },\n onInteractOutside: (event: any) => {\n reactiveModelProps.onCancel?.(event);\n },\n },\n {\n default: () => [\n h(DialogHeader, {}, () => h(DialogTitle, {}, { default: () => title })),\n h(\"div\", { class: \"py-1\" }, [h(component, { ...restProps, ref: instance })]),\n h(\n DialogFooter,\n { class: \"gap-2\" },\n () => [\n h(Button, { variant: \"outline\", onClick: () => (open.value = false) }, () => \"取 消\"),\n loading.value\n ? h(Button, { disabled: true }, () => [h(Loader, { class: \"text-current\" }), \"确 定\"])\n : h(Button, { onClick: handleOk }, () => \"确 定\"),\n ],\n ),\n ],\n },\n ),\n },\n );\n };\n },\n });\n\n const app = createApp(DialogWithFooter);\n app.mount(container);\n watchClose();\n\n // 返回 close 方法,调用方可编程式关闭弹窗\n function close() {\n open.value = false;\n }\n return { close };\n}\n\n/**\n * 命令式弹窗表单:一行代码弹出一个「确定时自动校验」的表单弹窗。\n *\n * @param formProps ProFormBuilder 的配置:formItems / rules / modelValue 等\n * @param modelProps 弹窗的配置(title / width / onOk 等)\n * @returns { close } 关闭弹窗\n *\n * @example\n * const { close } = renderDialogForm(\n * { formItems: [{ label: '姓名', key: 'name' }], rules: { name: [{ required: true }] } },\n * { title: '新增用户', onOk: (data) => console.log('提交', data) },\n * );\n */\nexport function renderDialogForm(formProps: Record<string, any>, modelProps: ShadcnDialogProps = EMPTY_OBJ): DialogHandle {\n const reactiveFormProps = reactive(formProps);\n return openDialog(\n {\n setup(_: any, { expose }: any) {\n const formInstance = ref();\n expose({\n // 点确定时先跑表单校验,通过后把表单数据交给 onOk\n async submit() {\n await formInstance.value?.validate?.();\n return reactiveFormProps.modelValue;\n },\n });\n // formProps 是运行时动态对象,断言绕开 h() 对 .vue 组件的严格 props 推断\n const FormComp = ProFormBuilder as unknown as Component;\n return () => h(FormComp, { ...reactiveFormProps, ref: formInstance });\n },\n },\n {},\n modelProps,\n );\n}\n"],"mappings":";;;;;AAMA,IAAM,YAAY,OAAO,OAAO,EAAE,CAAC;AAUnC,SAAgB,WACd,WACA,QAA6B,WAC7B,aAAgC,WAClB;CAId,MAAM,EAAE,YAAY,UAAU,UAAU,GAAG,cAAc;CACzD,MAAM,OAAO,IAAI,KAAK;CACtB,MAAM,WAAW,KAA0B;CAC3C,MAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,WAAU,aAAa,gCAAgC,GAAG;CAC1D,MAAM,UAAU,IAAI,MAAM;AAC1B,UAAS,KAAK,YAAY,UAAU;CAGpC,MAAM,qBAAqB,SAAS,WAAW;CAE/C,eAAe,WAAW;AACxB,UAAQ,QAAQ;AAChB,MAAI;GACF,IAAIA;AACJ,OAAI,SACF,UAAS,MAAM,SAAS,SAAS,MAAM;YAC9B,SAAS,QAAQ,WAC1B,UAAS,MAAM,SAAS,MAAM,YAAY;AAE5C,QAAK,QAAQ;AAEb,sBAAmB,OAAO,OAAO;UAC3B,WAEE;AACR,WAAQ,QAAQ;;;CAIpB,SAAS,UAAU;AACjB,MAAI,SAAS;AACb,WAAS,KAAK,YAAY,UAAU;;CAItC,SAAS,aAAa;EACpB,MAAM,OAAO,kBAAkB;AAC7B,OAAI,CAAC,KAAK,OAAO;AACf,kBAAc,KAAK;AACnB,eAAW,SAAS,IAAI;;KAEzB,IAAI;;CA4DT,MAAM,MAAM,UAzDa,gBAAgB,EACvC,QAAQ;AACN,eAAa;GACX,MAAM,QACJ,OAAO,mBAAmB,UAAU,aAC/B,mBAAmB,OAAe,GACnC,mBAAmB;GACzB,MAAM,aACJ,mBAAmB,SAAS,OACxB;IACE,OACE,OAAO,mBAAmB,UAAU,WAChC,GAAG,mBAAmB,MAAM,MAC5B,mBAAmB;IACzB,UAAU;IACX,GACD,KAAA;AACN,UAAO,EACL,gBACA;IAAE,MAAM,KAAK;IAAO,kBAAkB,UAAoB,KAAK,QAAQ;IAAQ,EAC/E,EACE,eACE,EACE,uBACA;IACE,OAAO;IACP,kBAAkB,UAAe;AAE/B,wBAAmB,WAAW,MAAM;;IAEtC,oBAAoB,UAAe;AACjC,wBAAmB,WAAW,MAAM;;IAEvC,EACD,EACE,eAAe;IACb,EAAE,sBAAc,EAAE,QAAQ,EAAE,qBAAa,EAAE,EAAE,EAAE,eAAe,OAAO,CAAC,CAAC;IACvE,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,CAAC,EAAE,WAAW;KAAE,GAAG;KAAW,KAAK;KAAU,CAAC,CAAC,CAAC;IAC5E,EACE,sBACA,EAAE,OAAO,SAAS,QACZ,CACJ,EAAE,gBAAQ;KAAE,SAAS;KAAW,eAAgB,KAAK,QAAQ;KAAQ,QAAQ,MAAM,EACnF,QAAQ,QACJ,EAAE,gBAAQ,EAAE,UAAU,MAAM,QAAQ,CAAC,EAAE,gBAAQ,EAAE,OAAO,gBAAgB,CAAC,EAAE,MAAM,CAAC,GAClF,EAAE,gBAAQ,EAAE,SAAS,UAAU,QAAQ,MAAM,CAClD,CACF;IACF,EACF,CACF,EACJ,CACF;;IAGN,CAAC,CAEqC;AACvC,KAAI,MAAM,UAAU;AACpB,aAAY;CAGZ,SAAS,QAAQ;AACf,OAAK,QAAQ;;AAEf,QAAO,EAAE,OAAO;;AAgBlB,SAAgB,iBAAiB,WAAgC,aAAgC,WAAyB;CACxH,MAAM,oBAAoB,SAAS,UAAU;AAC7C,QAAO,WACL,EACE,MAAM,GAAQ,EAAE,UAAe;EAC7B,MAAM,eAAe,KAAK;AAC1B,SAAO,EAEL,MAAM,SAAS;AACb,SAAM,aAAa,OAAO,YAAY;AACtC,UAAO,kBAAkB;KAE5B,CAAC;EAEF,MAAM,WAAW;AACjB,eAAa,EAAE,UAAU;GAAE,GAAG;GAAmB,KAAK;GAAc,CAAC;IAExE,EACD,EAAE,EACF,WACD"}
|
package/dist/utils/openDialog.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as renderDialogForm, t as openDialog } from "../openDialog-
|
|
1
|
+
import { n as renderDialogForm, t as openDialog } from "../openDialog-CqfhNoV7.js";
|
|
2
2
|
export { openDialog, renderDialogForm };
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cynnie/ui-shadcn",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "基于 shadcn-vue(reka-ui + Tailwind CSS v4)的
|
|
5
|
+
"description": "基于 shadcn-vue(reka-ui + Tailwind CSS v4)的 cynnie-ui 二次封装组件库:ProTable / ProFormBuilder / 命令式弹窗等",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"reka-ui": "^2.10.4",
|
|
87
87
|
"tailwind-merge": "^3.3.1",
|
|
88
88
|
"vue-sonner": "^2.0.9",
|
|
89
|
-
"@cynnie/ui-core": "^0.1.
|
|
89
|
+
"@cynnie/ui-core": "^0.1.1"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
92
|
"@types/lodash-es": "^4.17.12",
|
|
@@ -100,6 +100,7 @@
|
|
|
100
100
|
"vue": "^3.5.17",
|
|
101
101
|
"vue-tsc": "^2.2.10"
|
|
102
102
|
},
|
|
103
|
+
"homepage": "https://ui-playground-puce.vercel.app/?ui=shadcn",
|
|
103
104
|
"scripts": {
|
|
104
105
|
"build": "vite build",
|
|
105
106
|
"format": "prettier --write src/",
|
package/src/style.css
CHANGED
package/src/tailwind.preset.css
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* cynnie-ui shadcn 版的设计令牌与主题映射(不含 @import "tailwindcss"):
|
|
3
3
|
* - shadcn 设计令牌(CSS variables,语义色 primary / destructive / muted ...)
|
|
4
4
|
* - @theme inline 把 CSS variables 映射成 Tailwind 语义色工具类
|
|
5
5
|
* - @layer base 的全局 reset
|
|
6
6
|
*
|
|
7
7
|
* 使用方二选一:
|
|
8
|
-
* 1. 已有自己的 Tailwind 入口,只要
|
|
8
|
+
* 1. 已有自己的 Tailwind 入口,只要 cynnie-ui 令牌:
|
|
9
9
|
* `@import "@cynnie/ui-shadcn/tailwind.preset.css";`
|
|
10
10
|
* 2. 想要开箱即用的完整样式:`import "@cynnie/ui-shadcn/style.css"`。
|
|
11
11
|
* 与 antd / element 的 reset 样式互斥,切换 UI 模式时由使用方动态加载其一。
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
/* 独立 createApp 挂载的命令式弹窗容器:避免挂在文档流里产生滚动条位移 */
|
|
132
|
-
[data-
|
|
132
|
+
[data-cynnie-dialog-container] {
|
|
133
133
|
position: fixed;
|
|
134
134
|
top: 0;
|
|
135
135
|
left: 0;
|