v-nuxt-ui 0.1.28 → 0.1.30

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/dist/module.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "dependencies": [
8
8
  "@nuxt/ui"
9
9
  ],
10
- "version": "0.1.28",
10
+ "version": "0.1.30",
11
11
  "builder": {
12
12
  "@nuxt/module-builder": "1.0.2",
13
13
  "unbuild": "3.6.1"
@@ -133,7 +133,7 @@ defineExpose({
133
133
  }
134
134
  }"
135
135
  >
136
- <UFieldGroup>
136
+ <UFieldGroup v-if="peerButtons && peerButtons.length > 0">
137
137
  <UButton
138
138
  color="neutral"
139
139
  variant="outline"
@@ -148,6 +148,20 @@ defineExpose({
148
148
  </UButton>
149
149
  <UButton v-for="(btnProps, idx) in peerButtons" :key="idx" v-bind="btnProps" />
150
150
  </UFieldGroup>
151
+ <!-- TODO: vueuse -->
152
+ <UButton
153
+ v-else
154
+ color="neutral"
155
+ variant="outline"
156
+ :leading-icon="leadingIcon ?? 'i-lucide-calendar'"
157
+ trailing-icon="i-lucide-chevron-down"
158
+ :loading="loading"
159
+ :size="size"
160
+ >
161
+ <div class="flex items-center gap-1">
162
+ <span>{{ displayValue }}</span>
163
+ </div>
164
+ </UButton>
151
165
 
152
166
  <template #content>
153
167
  <div class="p-3 flex flex-col gap-2">
@@ -15,7 +15,10 @@ const props = defineProps({
15
15
  disableOprSelector: { type: Boolean, required: false },
16
16
  multiple: { type: Boolean, required: false },
17
17
  placeholder: { type: String, required: false },
18
- size: { type: null, required: false }
18
+ size: { type: null, required: false },
19
+ canCreate: { type: Boolean, required: false },
20
+ createModalComponent: { type: null, required: false },
21
+ createModalOpenProps: { type: Object, required: false }
19
22
  });
20
23
  const modelValue = defineModel("modelValue", { type: null, ...{ required: true } });
21
24
  const initModelValue = ref(modelValue.value);
@@ -1,8 +1,12 @@
1
+ import type { Component } from 'vue';
1
2
  import type { VFormFieldAsyncSelectProps } from '#v/types';
2
3
  declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
4
  props: import("vue").PublicProps & __VLS_PrettifyLocal<(VFormFieldAsyncSelectProps<T> & {
4
5
  icon?: string;
5
6
  disabled?: boolean;
7
+ canCreate?: boolean;
8
+ createModalComponent?: Component;
9
+ createModalOpenProps?: Record<string, any>;
6
10
  } & {
7
11
  modelValue: string[] | number[] | number | string | null | undefined;
8
12
  }) & {
@@ -25,6 +25,9 @@ const props = defineProps({
25
25
  multiple: { type: Boolean, required: false },
26
26
  placeholder: { type: String, required: false },
27
27
  size: { type: null, required: false },
28
+ canCreate: { type: Boolean, required: false },
29
+ createModalComponent: { type: void 0, required: false },
30
+ createModalOpenProps: { type: Object, required: false },
28
31
  icon: { type: String, required: false },
29
32
  disabled: { type: Boolean, required: false }
30
33
  });
@@ -1,8 +1,12 @@
1
+ import type { Component } from 'vue';
1
2
  import type { VFormFieldAsyncSelectProps } from '#v/types';
2
3
  declare const __VLS_export: <T>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
4
  props: import("vue").PublicProps & __VLS_PrettifyLocal<(VFormFieldAsyncSelectProps<T> & {
4
5
  icon?: string;
5
6
  disabled?: boolean;
7
+ canCreate?: boolean;
8
+ createModalComponent?: Component;
9
+ createModalOpenProps?: Record<string, any>;
6
10
  } & {
7
11
  modelValue: string[] | number[] | number | string | null | undefined;
8
12
  }) & {
@@ -23,6 +23,9 @@ const props = defineProps({
23
23
  multiple: { type: Boolean, required: false },
24
24
  placeholder: { type: String, required: false },
25
25
  size: { type: null, required: false },
26
+ canCreate: { type: Boolean, required: false },
27
+ createModalComponent: { type: null, required: false },
28
+ createModalOpenProps: { type: Object, required: false },
26
29
  icon: { type: String, required: false },
27
30
  disabled: { type: Boolean, required: false }
28
31
  });
@@ -68,8 +68,7 @@ function handleUpdateModelValue(selectedItems) {
68
68
  :model-value="indeterminate ? 'indeterminate' : selected"
69
69
  tabindex="-1"
70
70
  size="sm"
71
- @change="handleSelect"
72
- @click.stop
71
+ @click.stop="handleSelect"
73
72
  />
74
73
  </template>
75
74
  </UTree>
@@ -147,6 +147,9 @@ const fieldModelValue = computed({
147
147
  :disabled="field.disabled"
148
148
  :enable-empty-option="field.enableEmptyOption"
149
149
  :extra-search-field-fn="field.extraSearchFieldFn"
150
+ :can-create="field.canCreate"
151
+ :create-modal-component="field.createModalComponent"
152
+ :create-modal-open-props="field.createModalOpenProps"
150
153
  @update-init-model-values="field.onUpdateInitModelValues"
151
154
  />
152
155
  <FormFieldAsyncObjectSelect
@@ -53,11 +53,16 @@ const columns = [
53
53
  { label: "\u662F", value: true, color: "primary" },
54
54
  { label: "\u5426", value: false, color: "neutral" }
55
55
  ],
56
+ empty: {
57
+ label: "\u5426",
58
+ color: "neutral",
59
+ variant: "outline"
60
+ },
56
61
  initHide: false
57
62
  }
58
63
  },
59
64
  { accessorKey: "name", header: "\u83DC\u5355\u540D\u79F0", filterOption: { type: "input" }, sortOption: true },
60
- { accessorKey: "staticRouteKeys", header: "\u9759\u6001\u8DEF\u7531\u952E\u503C", filterOption: { type: "input" }, sortOption: true },
65
+ { accessorKey: "staticRouteKeys", header: "\u9759\u6001\u8DEF\u7531\u952E\u503C", filterOption: { type: "input", defaultOpr: "text_arr_str_like" }, sortOption: true },
61
66
  {
62
67
  accessorKey: "disabled",
63
68
  header: "\u662F\u5426\u7981\u7528",
@@ -39,9 +39,8 @@ const sourceTreeItems = computed(() => treeifyOptions(
39
39
  ));
40
40
  const targetTreeItems = computed({
41
41
  get() {
42
- const sortedMenus = (newValues.value.menus || []).sort((a, b) => a.order?.localeCompare(b.order || "") || 0);
43
42
  return treeifyOptions(
44
- sortedMenus,
43
+ (newValues.value.menus || []).sort((a, b) => a.order?.localeCompare(b.order || "") || 0),
45
44
  () => {
46
45
  },
47
46
  "name",
@@ -54,6 +53,28 @@ const targetTreeItems = computed({
54
53
  newValues.value.menus = menus.value.filter((menu) => newMenuIds.includes(menu.id));
55
54
  }
56
55
  });
56
+ function updateTargetTreeItems(newVal) {
57
+ targetTreeItems.value = newVal;
58
+ }
59
+ const fields = computed(() => [
60
+ { name: "name", type: "input", label: "\u89D2\u8272\u540D\u79F0", colSpan: "12", zodType: z.string().min(2, "\u540D\u79F0\u5B57\u6570\u4E0D\u8DB3") },
61
+ { name: "isAdmin", type: "button-switch", label: "\u662F\u5426\u662F\u7CFB\u7EDF\u89D2\u8272", colSpan: "12", zodType: z.boolean() },
62
+ {
63
+ name: "menus",
64
+ label: "\u83DC\u5355\u6743\u9650",
65
+ colSpan: "24",
66
+ zodType: z.array(z.object({ id: z.number() })),
67
+ type: "tree-select-transfer",
68
+ sourceTreeItems: sourceTreeItems.value,
69
+ targetTreeItems: targetTreeItems.value,
70
+ onUpdateTargetTreeItems: updateTargetTreeItems
71
+ },
72
+ { name: "disabled", type: "button-switch", label: "\u662F\u5426\u7981\u7528", colSpan: "12", zodType: z.boolean() },
73
+ { name: "remark", type: "input", label: "\u5907\u6CE8", colSpan: "24", zodType: z.string().optional().nullable() }
74
+ ]);
75
+ function updateModelValue(newVal) {
76
+ newValues.value = { id: 0, ...newVal };
77
+ }
57
78
  onMounted(async () => {
58
79
  await onFetchMenus();
59
80
  });
@@ -63,24 +84,9 @@ onMounted(async () => {
63
84
  <FormCreateModalTemplate
64
85
  title="角色信息"
65
86
  :on-close="(ok) => emit('close', ok)"
66
- :fields="[
67
- { name: 'name', type: 'input', label: '\u89D2\u8272\u540D\u79F0', colSpan: '12', zodType: z.string().min(2, '\u540D\u79F0\u5B57\u6570\u4E0D\u8DB3') },
68
- { name: 'isAdmin', type: 'button-switch', label: '\u662F\u5426\u662F\u7CFB\u7EDF\u89D2\u8272', colSpan: '12', zodType: z.boolean() },
69
- {
70
- name: 'menus',
71
- label: '\u83DC\u5355\u6743\u9650',
72
- colSpan: '24',
73
- zodType: z.array(z.object({ id: z.number() })),
74
- type: 'tree-select-transfer',
75
- sourceTreeItems,
76
- targetTreeItems,
77
- onUpdateTargetTreeItems: (newVal) => targetTreeItems = newVal
78
- },
79
- { name: 'disabled', type: 'button-switch', label: '\u662F\u5426\u7981\u7528', colSpan: '12', zodType: z.boolean() },
80
- { name: 'remark', type: 'input', label: '\u5907\u6CE8', colSpan: '24', zodType: z.string().optional().nullable() }
81
- ]"
87
+ :fields="fields"
82
88
  :model-value="newValues"
83
- @update-model-value="(newVal) => newValues = { id: 0, ...newVal }"
89
+ @update-model-value="updateModelValue"
84
90
  @submit="onSubmit"
85
91
  />
86
92
  </template>
@@ -2,7 +2,7 @@
2
2
  import { useOverlay } from "@nuxt/ui/composables";
3
3
  import { useRoleApi } from "#v/composables";
4
4
  import SysRolesCreateModal from "./CreateModal.vue";
5
- import { getOprColumns } from "#v/constants";
5
+ import { booleanOptions, getOprColumns } from "#v/constants";
6
6
  import UBadge from "@nuxt/ui/components/Badge.vue";
7
7
  import TablePage from "#v/components/table/Page.vue";
8
8
  import { h } from "vue";
@@ -23,8 +23,8 @@ const columns = [
23
23
  header: "\u662F\u5426\u662F\u7CFB\u7EDF\u89D2\u8272",
24
24
  sortOption: true,
25
25
  filterOption: {
26
- type: "input",
27
- initHide: false
26
+ type: "select",
27
+ items: booleanOptions
28
28
  },
29
29
  cell: ({ row }) => h(
30
30
  UBadge,
@@ -51,6 +51,9 @@ const roleTargetTreeItems = computed({
51
51
  newValues.value.roles = roles.value.filter((role) => newRoleIds.includes(role.id));
52
52
  }
53
53
  });
54
+ function updateRoleTargetTreeItems(newVal) {
55
+ roleTargetTreeItems.value = newVal;
56
+ }
54
57
  const menus = ref([]);
55
58
  const onFetchMenus = async () => {
56
59
  const { data } = await useMenuApi().list({
@@ -97,85 +100,98 @@ const menuTargetTreeItems = computed({
97
100
  newValues.value.menus = menus.value.filter((menu) => !menuIdsFromRoles.value.includes(menu.id)).filter((menu) => newMenuIds.includes(menu.id));
98
101
  }
99
102
  });
100
- onMounted(async () => {
101
- await onFetchRoles();
102
- await onFetchMenus();
103
- });
104
- </script>
105
-
106
- <template>
107
- <FormCreateModalTemplate
108
- title="用户信息"
109
- :on-close="(ok) => emit('close', ok)"
110
- :fields="[
111
- { name: 'nickname', type: 'input', label: '\u540D\u79F0', colSpan: '12', zodType: z.string().min(2, '\u540D\u79F0\u5B57\u6570\u4E0D\u8DB3') },
103
+ function updateMenuTargetTreeItems(newVal) {
104
+ menuTargetTreeItems.value = newVal;
105
+ }
106
+ function updateDepartment(newInitModelValues) {
107
+ newValues.value.department = newInitModelValues;
108
+ }
109
+ function updateSupervisor(newInitModelValues) {
110
+ newValues.value.supervisor = newInitModelValues;
111
+ }
112
+ const fields = computed(() => [
113
+ { name: "nickname", type: "input", label: "\u540D\u79F0", colSpan: "12", zodType: z.string().min(2, "\u540D\u79F0\u5B57\u6570\u4E0D\u8DB3") },
112
114
  {
113
- name: 'gender',
114
- icon: 'i-lucide-venus-and-mars',
115
- type: 'select',
116
- label: '\u6027\u522B',
115
+ name: "gender",
116
+ icon: "i-lucide-venus-and-mars",
117
+ type: "select",
118
+ label: "\u6027\u522B",
117
119
  items: genderOptions,
118
- colSpan: '12',
120
+ colSpan: "12",
119
121
  zodType: z.enum(Gender)
120
122
  },
121
- { name: 'username', type: 'input', label: '\u7528\u6237\u540D', colSpan: '12', zodType: z.string().nullable().optional() },
122
- { name: 'loginType', type: 'multiple-select-string', items: loginTypeOptions, label: '\u767B\u5F55\u65B9\u5F0F', colSpan: '12', zodType: z.string() },
123
+ { name: "username", type: "input", label: "\u7528\u6237\u540D", colSpan: "12", zodType: z.string().nullable().optional() },
124
+ { name: "loginType", type: "multiple-select-string", items: loginTypeOptions, label: "\u767B\u5F55\u65B9\u5F0F", colSpan: "12", zodType: z.string() },
123
125
  {
124
- name: 'departmentId',
125
- label: '\u90E8\u95E8',
126
- colSpan: '12',
127
- type: 'async-tree-select',
128
- labelField: 'name',
129
- valueField: 'id',
130
- searchFields: ['name'],
126
+ name: "departmentId",
127
+ label: "\u90E8\u95E8",
128
+ colSpan: "12",
129
+ type: "async-tree-select",
130
+ labelField: "name",
131
+ valueField: "id",
132
+ searchFields: ["name"],
131
133
  listApi: useDepartmentApi().list,
132
134
  fetchAll: true,
133
- initModelValues: newValues.department,
134
- onUpdateInitModelValues: (newInitModelValues) => newValues.department = newInitModelValues,
135
+ initModelValues: newValues.value.department,
136
+ onUpdateInitModelValues: updateDepartment,
135
137
  zodType: z.number().min(0)
136
138
  },
137
139
  {
138
- name: 'supervisorId',
139
- label: '\u76F4\u5C5E\u9886\u5BFC',
140
- colSpan: '12',
141
- type: 'async-select',
142
- labelField: 'nickname',
143
- valueField: 'id',
144
- searchFields: ['nickname'],
140
+ name: "supervisorId",
141
+ label: "\u76F4\u5C5E\u9886\u5BFC",
142
+ colSpan: "12",
143
+ type: "async-select",
144
+ labelField: "nickname",
145
+ valueField: "id",
146
+ searchFields: ["nickname"],
145
147
  listApi: useUserApi().list,
146
- initModelValues: newValues.supervisor,
147
- onUpdateInitModelValues: (newInitModelValues) => newValues.supervisor = newInitModelValues,
148
+ initModelValues: newValues.value.supervisor,
149
+ onUpdateInitModelValues: updateSupervisor,
148
150
  enableEmptyOption: true,
149
151
  zodType: z.number().min(0).optional()
150
152
  },
151
- { name: 'email', type: 'input', label: '\u90AE\u7BB1', colSpan: '24', zodType: z.string().optional().nullable() },
152
- { name: 'entryDate', type: 'date-picker', label: '\u5165\u804C\u65F6\u95F4', colSpan: '12', zodType: z.string().optional().nullable() },
153
- { name: 'resignDate', type: 'date-picker', label: '\u79BB\u804C\u65F6\u95F4', colSpan: '12', zodType: z.string().optional().nullable() },
154
- { name: 'needFillWh', type: 'button-switch', label: '\u662F\u5426\u9700\u8981\u586B\u5199\u5DE5\u65F6', colSpan: '12', zodType: z.boolean() },
155
- { name: 'isAdmin', type: 'button-switch', label: '\u662F\u5426\u662F\u7CFB\u7EDF\u7BA1\u7406\u5458', colSpan: '12', zodType: z.boolean() },
153
+ { name: "email", type: "input", label: "\u90AE\u7BB1", colSpan: "24", zodType: z.string().optional().nullable() },
154
+ { name: "entryDate", type: "date-picker", label: "\u5165\u804C\u65F6\u95F4", colSpan: "12", zodType: z.string().optional().nullable() },
155
+ { name: "resignDate", type: "date-picker", label: "\u79BB\u804C\u65F6\u95F4", colSpan: "12", zodType: z.string().optional().nullable() },
156
+ { name: "needFillWh", type: "button-switch", label: "\u662F\u5426\u9700\u8981\u586B\u5199\u5DE5\u65F6", colSpan: "12", zodType: z.boolean() },
157
+ { name: "isAdmin", type: "button-switch", label: "\u662F\u5426\u662F\u7CFB\u7EDF\u7BA1\u7406\u5458", colSpan: "12", zodType: z.boolean() },
156
158
  {
157
- name: 'roles',
158
- label: '\u89D2\u8272\u6743\u9650',
159
- colSpan: '24',
159
+ name: "roles",
160
+ label: "\u89D2\u8272\u6743\u9650",
161
+ colSpan: "24",
160
162
  zodType: z.array(z.object({ id: z.number() })).optional(),
161
- type: 'tree-select-transfer',
162
- sourceTreeItems: roleSourceTreeItems,
163
- targetTreeItems: roleTargetTreeItems,
164
- onUpdateTargetTreeItems: (newVal) => roleTargetTreeItems = newVal
163
+ type: "tree-select-transfer",
164
+ sourceTreeItems: roleSourceTreeItems.value,
165
+ targetTreeItems: roleTargetTreeItems.value,
166
+ onUpdateTargetTreeItems: updateRoleTargetTreeItems
165
167
  },
166
168
  {
167
- name: 'menus',
168
- label: '\u83DC\u5355\u6743\u9650',
169
- colSpan: '24',
169
+ name: "menus",
170
+ label: "\u83DC\u5355\u6743\u9650",
171
+ colSpan: "24",
170
172
  zodType: z.array(z.object({ id: z.number() })).optional(),
171
- type: 'tree-select-transfer',
172
- sourceTreeItems: menuSourceTreeItems,
173
- targetTreeItems: menuTargetTreeItems,
174
- onUpdateTargetTreeItems: (newVal) => menuTargetTreeItems = newVal
173
+ type: "tree-select-transfer",
174
+ sourceTreeItems: menuSourceTreeItems.value,
175
+ targetTreeItems: menuTargetTreeItems.value,
176
+ onUpdateTargetTreeItems: updateMenuTargetTreeItems
175
177
  }
176
- ]"
178
+ ]);
179
+ function updateModelValue(newVal) {
180
+ newValues.value = { id: 0, ...newVal };
181
+ }
182
+ onMounted(async () => {
183
+ await onFetchRoles();
184
+ await onFetchMenus();
185
+ });
186
+ </script>
187
+
188
+ <template>
189
+ <FormCreateModalTemplate
190
+ title="用户信息"
191
+ :on-close="(ok) => emit('close', ok)"
192
+ :fields="fields"
177
193
  :model-value="newValues"
178
- @update-model-value="(newVal) => newValues = { id: 0, ...newVal }"
194
+ @update-model-value="updateModelValue"
179
195
  @submit="onSubmit"
180
196
  />
181
197
  </template>
@@ -22,7 +22,10 @@ const props = defineProps({
22
22
  disableOprSelector: { type: Boolean, required: false },
23
23
  multiple: { type: Boolean, required: false },
24
24
  placeholder: { type: String, required: false },
25
- size: { type: null, required: false, default: "sm" }
25
+ size: { type: null, required: false, default: "sm" },
26
+ canCreate: { type: Boolean, required: false },
27
+ createModalComponent: { type: null, required: false },
28
+ createModalOpenProps: { type: Object, required: false }
26
29
  });
27
30
  const whereQueryItem = defineModel("whereQueryItem", { type: Object, ...{ required: true } });
28
31
  const { fetching, startFetching, endFetching } = useFetching();
@@ -47,35 +47,47 @@ export function useTableRowActions(props) {
47
47
  }
48
48
  });
49
49
  }
50
- extraRowActions?.forEach((action) => {
51
- actionItems.push({
50
+ const buildActionItem = (action) => {
51
+ const item = {
52
52
  label: action.label,
53
53
  icon: action.icon,
54
54
  type: action.type,
55
- color: action.color,
56
- onClick: async () => {
57
- if (action.fn) {
55
+ color: action.color
56
+ };
57
+ if (action.children && action.children.length > 0) {
58
+ item.children = action.children.map(buildActionItem);
59
+ return item;
60
+ }
61
+ item.onClick = async () => {
62
+ if (action.fn) {
63
+ try {
58
64
  action.fn(row.original);
59
- if (action.refetchAfterFn) {
60
- await fetchList();
61
- }
65
+ } catch (e) {
66
+ console.error("Error in row action fn:", e);
62
67
  }
63
- if (action.asyncFn) {
64
- actionLoadingRowIdxSet.value.add(row.index);
65
- try {
66
- await action.asyncFn(row.original);
67
- } finally {
68
- actionLoadingRowIdxSet.value.delete(row.index);
69
- }
68
+ if (action.refetchAfterFn) {
69
+ await fetchList();
70
70
  }
71
- if (action.fnWithModal) {
72
- const result = await action.fnWithModal(row.original);
73
- if (result) {
74
- await fetchList();
75
- }
71
+ }
72
+ if (action.asyncFn) {
73
+ actionLoadingRowIdxSet.value.add(row.index);
74
+ try {
75
+ await action.asyncFn(row.original);
76
+ } finally {
77
+ actionLoadingRowIdxSet.value.delete(row.index);
76
78
  }
77
79
  }
78
- });
80
+ if (action.fnWithModal) {
81
+ const result = await action.fnWithModal(row.original);
82
+ if (result) {
83
+ await fetchList();
84
+ }
85
+ }
86
+ };
87
+ return item;
88
+ };
89
+ extraRowActions?.forEach((action) => {
90
+ actionItems.push(buildActionItem(action));
79
91
  });
80
92
  if (!disableRowDeletion) {
81
93
  if (actionItems.length > 0) {
@@ -2,12 +2,12 @@ import { ref, computed, watch, onMounted, onUnmounted, nextTick, useTemplateRef
2
2
  import { useTable } from "./useTable.js";
3
3
  const PINNED_SHADOW_CLASSES = {
4
4
  left: {
5
- base: "[&_th[data-pinned=left]]:after:absolute [&_th[data-pinned=left]]:after:top-0 [&_th[data-pinned=left]]:after:right-0 [&_th[data-pinned=left]]:after:bottom-0 [&_th[data-pinned=left]]:after:w-[30px] [&_th[data-pinned=left]]:after:translate-x-full [&_th[data-pinned=left]]:after:transition-opacity [&_th[data-pinned=left]]:after:duration-300 [&_th[data-pinned=left]]:after:pointer-events-none [&_th[data-pinned=left]]:after:shadow-[inset_10px_0_8px_-8px_rgba(0,0,0,0.15)] [&_td[data-pinned=left]]:after:absolute [&_td[data-pinned=left]]:after:top-0 [&_td[data-pinned=left]]:after:right-0 [&_td[data-pinned=left]]:after:bottom-0 [&_td[data-pinned=left]]:after:w-[30px] [&_td[data-pinned=left]]:after:translate-x-full [&_td[data-pinned=left]]:after:transition-opacity [&_td[data-pinned=left]]:after:duration-200 [&_td[data-pinned=left]]:after:pointer-events-none [&_td[data-pinned=left]]:after:shadow-[inset_10px_0_8px_-8px_rgba(0,0,0,0.15)]",
5
+ base: "[--pinned-shadow-color:rgba(0,0,0,0.15)] dark:[--pinned-shadow-color:rgba(0,0,0,0.45)] [&_th[data-pinned=left]]:after:absolute [&_th[data-pinned=left]]:after:top-0 [&_th[data-pinned=left]]:after:right-0 [&_th[data-pinned=left]]:after:bottom-0 [&_th[data-pinned=left]]:after:w-[30px] [&_th[data-pinned=left]]:after:translate-x-full [&_th[data-pinned=left]]:after:transition-opacity [&_th[data-pinned=left]]:after:duration-300 [&_th[data-pinned=left]]:after:pointer-events-none [&_th[data-pinned=left]]:after:shadow-[inset_10px_0_8px_-8px_var(--pinned-shadow-color)] [&_td[data-pinned=left]]:after:absolute [&_td[data-pinned=left]]:after:top-0 [&_td[data-pinned=left]]:after:right-0 [&_td[data-pinned=left]]:after:bottom-0 [&_td[data-pinned=left]]:after:w-[30px] [&_td[data-pinned=left]]:after:translate-x-full [&_td[data-pinned=left]]:after:transition-opacity [&_td[data-pinned=left]]:after:duration-200 [&_td[data-pinned=left]]:after:pointer-events-none [&_td[data-pinned=left]]:after:shadow-[inset_10px_0_8px_-8px_var(--pinned-shadow-color)]",
6
6
  show: "[&_th[data-pinned=left]]:after:opacity-100 [&_td[data-pinned=left]]:after:opacity-100",
7
7
  hide: "[&_th[data-pinned=left]]:after:opacity-0 [&_td[data-pinned=left]]:after:opacity-0"
8
8
  },
9
9
  right: {
10
- base: "[&_th[data-pinned=right]]:before:absolute [&_th[data-pinned=right]]:before:top-0 [&_th[data-pinned=right]]:before:left-0 [&_th[data-pinned=right]]:before:bottom-0 [&_th[data-pinned=right]]:before:w-[30px] [&_th[data-pinned=right]]:before:-translate-x-full [&_th[data-pinned=right]]:before:transition-opacity [&_th[data-pinned=right]]:before:duration-300 [&_th[data-pinned=right]]:before:pointer-events-none [&_th[data-pinned=right]]:before:shadow-[inset_-10px_0_8px_-8px_rgba(0,0,0,0.15)] [&_td[data-pinned=right]]:before:absolute [&_td[data-pinned=right]]:before:top-0 [&_td[data-pinned=right]]:before:left-0 [&_td[data-pinned=right]]:before:bottom-0 [&_td[data-pinned=right]]:before:w-[30px] [&_td[data-pinned=right]]:before:-translate-x-full [&_td[data-pinned=right]]:before:transition-opacity [&_td[data-pinned=right]]:before:duration-200 [&_td[data-pinned=right]]:before:pointer-events-none [&_td[data-pinned=right]]:before:shadow-[inset_-10px_0_8px_-8px_rgba(0,0,0,0.15)]",
10
+ base: "[&_th[data-pinned=right]]:before:absolute [&_th[data-pinned=right]]:before:top-0 [&_th[data-pinned=right]]:before:left-0 [&_th[data-pinned=right]]:before:bottom-0 [&_th[data-pinned=right]]:before:w-[30px] [&_th[data-pinned=right]]:before:-translate-x-full [&_th[data-pinned=right]]:before:transition-opacity [&_th[data-pinned=right]]:before:duration-300 [&_th[data-pinned=right]]:before:pointer-events-none [&_th[data-pinned=right]]:before:shadow-[inset_-10px_0_8px_-8px_var(--pinned-shadow-color)] [&_td[data-pinned=right]]:before:absolute [&_td[data-pinned=right]]:before:top-0 [&_td[data-pinned=right]]:before:left-0 [&_td[data-pinned=right]]:before:bottom-0 [&_td[data-pinned=right]]:before:w-[30px] [&_td[data-pinned=right]]:before:-translate-x-full [&_td[data-pinned=right]]:before:transition-opacity [&_td[data-pinned=right]]:before:duration-200 [&_td[data-pinned=right]]:before:pointer-events-none [&_td[data-pinned=right]]:before:shadow-[inset_-10px_0_8px_-8px_var(--pinned-shadow-color)]",
11
11
  show: "[&_th[data-pinned=right]]:before:opacity-100 [&_td[data-pinned=right]]:before:opacity-100",
12
12
  hide: "[&_th[data-pinned=right]]:before:opacity-0 [&_td[data-pinned=right]]:before:opacity-0"
13
13
  }
@@ -1,10 +1,10 @@
1
1
  export const TIME_ZONE = "Asia/Shanghai";
2
2
  export const timeUnitOptions = [
3
- { label: "Year", value: "year" },
4
- { label: "Quarter", value: "quarter" },
5
- { label: "Month", value: "month" },
6
- { label: "Week", value: "week" },
7
- { label: "Day", value: "day" }
3
+ { label: "\u5E74", value: "year" },
4
+ { label: "\u5B63", value: "quarter" },
5
+ { label: "\u6708", value: "month" },
6
+ { label: "\u5468", value: "week" },
7
+ { label: "\u65E5", value: "day" }
8
8
  ];
9
9
  export const weekEnLabels = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
10
10
  export const weekCnLabels = ["\u5468\u4E00", "\u5468\u4E8C", "\u5468\u4E09", "\u5468\u56DB", "\u5468\u4E94", "\u5468\u516D", "\u5468\u65E5"];
@@ -1,4 +1,4 @@
1
- import type { VNode, Ref } from 'vue';
1
+ import type { VNode, Ref, Component } from 'vue';
2
2
  import type { ButtonProps, FormFieldProps, InputProps, RadioGroupProps, SelectMenuItem, SelectProps, TreeItem } from '@nuxt/ui';
3
3
  import type { ZodType } from 'zod';
4
4
  import type { PageResult, RequestResult } from '../../request.js';
@@ -20,6 +20,9 @@ export type VFormFieldAsyncSelectProps<T> = {
20
20
  multiple?: boolean;
21
21
  placeholder?: string;
22
22
  size?: SelectProps['size'];
23
+ canCreate?: boolean;
24
+ createModalComponent?: Component;
25
+ createModalOpenProps?: Record<string, any>;
23
26
  };
24
27
  export type VFormFieldAsyncTreeSelectProps<T> = {
25
28
  fetchAll?: boolean;
@@ -54,6 +54,7 @@ export type RowActionProps<T> = {
54
54
  refetchAfterFn?: boolean;
55
55
  fnWithModal?: (model: T) => Promise<boolean>;
56
56
  asyncFn?: (model: T) => Promise<void>;
57
+ children?: RowActionProps<T>[];
57
58
  };
58
59
  export type VTableExportExcelProps<T> = {
59
60
  filename: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "v-nuxt-ui",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "description": "Veken UI Component Library - Reusable Nuxt UI components, composables, and utilities for enterprise applications",
5
5
  "type": "module",
6
6
  "style": "./dist/runtime/index.css",