feat: add formkit custom input of repeater (halo-dev/console#692)

#### What type of PR is this?

/kind feature
/milestone 2.0

#### What this PR does / why we need it:

为 FormKit 添加 Repeater 输入类型,用于让用户动态操作一个对象数组。

使用方式可以查阅:https://github.com/ruibaby/halo-console/tree/feat/formkit-repeater/docs/custom-formkit-input#repeater

#### Which issue(s) this PR fixes:

Fixes https://github.com/halo-dev/halo/issues/2529

#### Screenshots:

<img width="635" alt="image" src="https://user-images.githubusercontent.com/21301288/201640327-5eb0489a-2193-445d-9dfe-7405ae75a297.png">

#### Special notes for your reviewer:

/cc @halo-dev/sig-halo-console 

测试方式:

1. 按照 https://github.com/ruibaby/halo-console/tree/feat/formkit-repeater/docs/custom-formkit-input#repeater 文档,在主题或者插件中使用 FormKit Schema 的形式定义设置表单,然后对表单进行保存等设置,检查是否符合预期。
2. 或者使用 https://github.com/halo-sigs/theme-earth/tree/refactor/setting-spec 主题进行测试,这个分支已经对社交媒体和侧边栏进行了适配。可以在主题设置中测试社交媒体和侧边栏配置,检查在主题端的效果。

#### Does this PR introduce a user-facing change?

```release-note
为 FormKit 添加 Repeater 输入类型。
```
pull/3445/head
Ryan Wang 2022-11-15 15:48:17 +08:00 committed by GitHub
parent 949697804d
commit 6d0e13365a
18 changed files with 328 additions and 68 deletions

View File

@ -13,6 +13,7 @@
1. language: 目前支持 `yaml`, `html`, `css`, `javascript`, `json`
2. height: 编辑器高度,如:`100px`
- `attachment`: 附件选择
- `repeater`: 定义一个对象集合,可以让使用者可视化的操作集合。
- `menuCheckbox`:选择一组菜单
- `menuRadio`:选择一个菜单
- `menuItemSelect`:选择菜单项
@ -48,3 +49,68 @@ const postName = ref("")
name: menus
label: 底部菜单组
```
### Repeater
Repeater 是一个集合类型的输入组件,可以让使用者可视化的操作集合。
在 Vue SFC 中以组件形式使用:
```vue
<script lang="ts" setup>
const users = ref([])
</script>
<template>
<FormKit
v-model="users"
type="repeater"
label="Users"
>
<FormKit
type="text"
label="Full Name"
name="full_name"
validation="required"
/>
<FormKit
type="email"
label="Email"
name="email"
validation="required|email"
/>
</FormKit>
</template>
```
在 FormKit Schema 中使用:
```yaml
- $formkit: repeater
name: users
label: Users
items:
- $formkit: text
name: full_name
label: Full Name
validation: required
- $formkit: email
name: email
label: Email
validation: required|email
```
最终得到的数据类似于:
```json
[
{
"full_name": "Jack",
"email": "jack@example.com"
},
{
"full_name": "John",
"email": "john@example.com"
}
]
```

View File

@ -31,6 +31,7 @@
"@formkit/inputs": "^1.0.0-beta.11",
"@formkit/themes": "^1.0.0-beta.11",
"@formkit/vue": "^1.0.0-beta.11",
"@formkit/utils": "^1.0.0-beta.11",
"@halo-dev/api-client": "^0.0.46",
"@halo-dev/components": "workspace:*",
"@halo-dev/console-shared": "workspace:*",

View File

@ -3,6 +3,7 @@
:class="classes"
:disabled="disabled"
class="btn"
type="button"
@click="handleClick"
>
<span v-if="$slots.icon || loading" class="btn-icon">
@ -128,11 +129,11 @@ function handleClick() {
}
.btn-primary {
@apply text-white bg-primary;
@apply text-white bg-primary #{!important};
}
.btn-secondary {
@apply text-white bg-secondary;
@apply text-white bg-secondary #{!important};
}
.btn-danger {

View File

@ -1,61 +1,61 @@
// Vitest Snapshot v1
exports[`Button > should render 1`] = `
"<button class=\\"btn-md btn-default btn\\">
"<button class=\\"btn-md btn-default btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with block prop 1`] = `
"<button class=\\"btn-md btn-default btn-block btn\\">
"<button class=\\"btn-md btn-default btn-block btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with circle prop 1`] = `
"<button class=\\"btn-md btn-default btn-circle btn\\">
"<button class=\\"btn-md btn-default btn-circle btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with disabled prop 1`] = `
"<button class=\\"btn-md btn-default btn\\" disabled=\\"\\">
"<button class=\\"btn-md btn-default btn\\" type=\\"button\\" disabled=\\"\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with size prop 1`] = `
"<button class=\\"btn-lg btn-default btn\\">
"<button class=\\"btn-lg btn-default btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with size prop 2`] = `
"<button class=\\"btn-sm btn-default btn\\">
"<button class=\\"btn-sm btn-default btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with size prop 3`] = `
"<button class=\\"btn-xs btn-default btn\\">
"<button class=\\"btn-xs btn-default btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with type prop 1`] = `
"<button class=\\"btn-md btn-primary btn\\">
"<button class=\\"btn-md btn-primary btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with type prop 2`] = `
"<button class=\\"btn-md btn-secondary btn\\">
"<button class=\\"btn-md btn-secondary btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;
exports[`Button > should work with type prop 3`] = `
"<button class=\\"btn-md btn-danger btn\\">
"<button class=\\"btn-md btn-danger btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\"></span>
</button>"
`;

View File

@ -5,7 +5,7 @@ exports[`Empty > should match snapshot 1`] = `
<div class=\\"empty-image h-32 w-32\\"><img src=\\"/src/components/empty/Empty.svg\\" alt=\\"Empty\\"></div>
<div class=\\"empty-title\\">Not found</div>
<div class=\\"empty-message\\">No posts found</div>
<div class=\\"empty-actions\\"><button class=\\"btn-md btn-primary btn\\">
<div class=\\"empty-actions\\"><button class=\\"btn-md btn-primary btn\\" type=\\"button\\">
<!--v-if--><span class=\\"btn-content\\">New Post</span>
</button></div>
</div>"

View File

@ -54,6 +54,8 @@ import IconRefreshLine from "~icons/ri/refresh-line";
import IconWindowLine from "~icons/ri/window-line";
import IconSendPlaneFill from "~icons/ri/send-plane-fill";
import IconRocketLine from "~icons/ri/rocket-line";
import IconArrowUpCircleLine from "~icons/ri/arrow-up-circle-line";
import IconArrowDownCircleLine from "~icons/ri/arrow-down-circle-line";
export {
IconDashboard,
@ -112,4 +114,6 @@ export {
IconWindowLine,
IconSendPlaneFill,
IconRocketLine,
IconArrowUpCircleLine,
IconArrowDownCircleLine,
};

View File

@ -10,6 +10,7 @@ importers:
'@formkit/i18n': ^1.0.0-beta.11
'@formkit/inputs': ^1.0.0-beta.11
'@formkit/themes': ^1.0.0-beta.11
'@formkit/utils': ^1.0.0-beta.11
'@formkit/vue': ^1.0.0-beta.11
'@halo-dev/api-client': ^0.0.46
'@halo-dev/components': workspace:*
@ -99,11 +100,12 @@ importers:
yaml: ^2.1.3
dependencies:
'@emoji-mart/data': 1.0.6
'@formkit/core': 1.0.0-beta.11
'@formkit/i18n': 1.0.0-beta.11
'@formkit/inputs': 1.0.0-beta.11
'@formkit/themes': 1.0.0-beta.11_tailwindcss@3.2.1
'@formkit/vue': 1.0.0-beta.11_vjnbgdptsk6bkj7ab5a6mk2cwm
'@formkit/core': 1.0.0-beta.12-e579559
'@formkit/i18n': 1.0.0-beta.12-e579559
'@formkit/inputs': 1.0.0-beta.12-e579559
'@formkit/themes': 1.0.0-beta.12-e579559_tailwindcss@3.2.1
'@formkit/utils': 1.0.0-beta.12-e579559
'@formkit/vue': 1.0.0-beta.12-e579559_vjnbgdptsk6bkj7ab5a6mk2cwm
'@halo-dev/api-client': 0.0.46
'@halo-dev/components': link:packages/components
'@halo-dev/console-shared': link:packages/shared
@ -1845,50 +1847,50 @@ packages:
'@floating-ui/core': 0.3.1
dev: false
/@formkit/core/1.0.0-beta.11:
resolution: {integrity: sha512-1yIQUicY1ZVGkeT0AEVp3ahx5FdJg+snyc8yaitsNmQeCSq1Ju5o1nCRcpcZ7j2ezMbGUiL7nTscGGejC15N2Q==}
/@formkit/core/1.0.0-beta.12-e579559:
resolution: {integrity: sha512-y90ubMcFr6WtAjZqUOLgA3p4jm024f6R7iDRVKHsmdwSKm1/GZl4D+Yo2k8DL40xM7NbZhIvK40MiEC0pNZ3ig==}
dependencies:
'@formkit/utils': 1.0.0-beta.11
'@formkit/utils': 1.0.0-beta.12-e579559
dev: false
/@formkit/dev/1.0.0-beta.11:
resolution: {integrity: sha512-YuPfE4ZoIAOQfawKlnCxXdnNOktckGNUhtCirpgsyBuHVu15rX1E5mYRAyEBhDGeEPV8IOFNpooSKA/y9W7dtw==}
/@formkit/dev/1.0.0-beta.12-e579559:
resolution: {integrity: sha512-jH5o9VwQWVuyO8cIr3BiZFXai0BtQe8mL+EUECEoRYtp6vkzgk6ErezejX7jqnu4dW9NS6chMeLIF+OAjh6zIg==}
dependencies:
'@formkit/core': 1.0.0-beta.11
'@formkit/utils': 1.0.0-beta.11
'@formkit/core': 1.0.0-beta.12-e579559
'@formkit/utils': 1.0.0-beta.12-e579559
dev: false
/@formkit/i18n/1.0.0-beta.11:
resolution: {integrity: sha512-ID4y9r5NoKy+rIiv41UGCtrg8iR3Lor30oBEUJlEDPAh34vlwh4g2jorXgysdSVMRCuLnqGyGspLnrPdxgSszw==}
/@formkit/i18n/1.0.0-beta.12-e579559:
resolution: {integrity: sha512-IKfhVR+LWSoIAd60OFHjLbt4y/owd7uQfI1uO8sjXs2iz+7VqmE33R7DcI3cu5+WuC9JE/letRteL9nSSJ6kBA==}
dependencies:
'@formkit/core': 1.0.0-beta.11
'@formkit/utils': 1.0.0-beta.11
'@formkit/validation': 1.0.0-beta.11
'@formkit/core': 1.0.0-beta.12-e579559
'@formkit/utils': 1.0.0-beta.12-e579559
'@formkit/validation': 1.0.0-beta.12-e579559
dev: false
/@formkit/inputs/1.0.0-beta.11:
resolution: {integrity: sha512-DF+olkewjAE/q+alsG1t4GFX7JHzVvTCukOOEuqp8AzT+MGyZFzxikSXd8qA5zX+1BvRCgQwzWZMBaQLUo3IMA==}
/@formkit/inputs/1.0.0-beta.12-e579559:
resolution: {integrity: sha512-igRXzW9edZ4wMHkX7XFricPsVNU99BoMWKwDOzg+erjLKwPw+h4tVKWmZFe2xTUUDSCBoxkLS5TgdsUZ84vMng==}
dependencies:
'@formkit/core': 1.0.0-beta.11
'@formkit/core': 1.0.0-beta.12-e579559
dev: false
/@formkit/observer/1.0.0-beta.11:
resolution: {integrity: sha512-jpOqOJdpydl/2eOL0yXVZjXYdk9tY0EsAf9e5PTxXcWOZpBskSwPdjNMnx8y9ycrpj6lKPcbMfs2bjnQQue8IQ==}
/@formkit/observer/1.0.0-beta.12-e579559:
resolution: {integrity: sha512-6Nki4VmUN3OyU70N6AIttvn/ScZXq5mwv11BIYLgfsfiMI5zoiflmNHrD7yf4KTUVvz16ThJB5nRGIXlnUnH3Q==}
dependencies:
'@formkit/core': 1.0.0-beta.11
'@formkit/utils': 1.0.0-beta.11
'@formkit/core': 1.0.0-beta.12-e579559
'@formkit/utils': 1.0.0-beta.12-e579559
dev: false
/@formkit/rules/1.0.0-beta.11:
resolution: {integrity: sha512-6SQ+fGXTx9MLMUk832x9oR/423U4/7TpDxyx/cjz1xaQjAKzorwNGbjiiRszp4f3cSYcpyi/SZ36n0UktLaCVA==}
/@formkit/rules/1.0.0-beta.12-e579559:
resolution: {integrity: sha512-xu3VRPTob2GWA54MQafekVX+fUWYJbcMrkcDEo8yB4ZgKdlW5Er1C3gYa/bByuMNpY0/lklwdpKP/8aoIKfmxw==}
dependencies:
'@formkit/core': 1.0.0-beta.11
'@formkit/utils': 1.0.0-beta.11
'@formkit/validation': 1.0.0-beta.11
'@formkit/core': 1.0.0-beta.12-e579559
'@formkit/utils': 1.0.0-beta.12-e579559
'@formkit/validation': 1.0.0-beta.12-e579559
dev: false
/@formkit/themes/1.0.0-beta.11_tailwindcss@3.2.1:
resolution: {integrity: sha512-OmefvFoLHZLnmbuT+Mqbqr681rumc62Q08Y1g82ZxG6aXWculwQYVQfZJeJFrqrJPpccsfoSflWeAuAMWiP/Yw==}
/@formkit/themes/1.0.0-beta.12-e579559_tailwindcss@3.2.1:
resolution: {integrity: sha512-ceFbta+xDO87Y96zAGqe3qCvSVyqEgmpsDCjk3BZTghydhIJupmgKSyr6TmmyJ5WT8zpcs8wnc2kF1YbUVt8Yw==}
peerDependencies:
tailwindcss: ^3.0.0
unocss: ^0.31.0
@ -1901,35 +1903,35 @@ packages:
windicss:
optional: true
dependencies:
'@formkit/core': 1.0.0-beta.11
'@formkit/core': 1.0.0-beta.12-e579559
tailwindcss: 3.2.1_postcss@8.4.18
dev: false
/@formkit/utils/1.0.0-beta.11:
resolution: {integrity: sha512-ajeB6A0WJXaErwIgdHGnVZotghvWOZ+JvFKK6fM/rYQza2O4YFiPAVKqJRQjMbW5Jxia4sT7PQhPUFvZQFbuKQ==}
/@formkit/utils/1.0.0-beta.12-e579559:
resolution: {integrity: sha512-4yTz4IRzPX3G08aAO+ZfEuBYfy6OSgk3csx3TBhOcL6NzyIbJkTc2ZsxaUYXgY6FOVclazLGMKM5+jBitMOL5Q==}
dev: false
/@formkit/validation/1.0.0-beta.11:
resolution: {integrity: sha512-7HePIek0Y2MsH45lHDyCekJfENNdIr8ZIkJQx4VwAlfbIyZElZx5VsxInCSLf/03aOu4PhabOxpNUt38AP2hAg==}
/@formkit/validation/1.0.0-beta.12-e579559:
resolution: {integrity: sha512-f/S0LefikeBZRxKkjx1fD7RODXMHglg6+B1NUYEKsEKc3ySjH/V9/XroaPszXfkupAnVBSTjZXG7T9hmn39VVA==}
dependencies:
'@formkit/core': 1.0.0-beta.11
'@formkit/observer': 1.0.0-beta.11
'@formkit/core': 1.0.0-beta.12-e579559
'@formkit/observer': 1.0.0-beta.12-e579559
dev: false
/@formkit/vue/1.0.0-beta.11_vjnbgdptsk6bkj7ab5a6mk2cwm:
resolution: {integrity: sha512-0tVy8JZ/j4QbmYlVPJyFGZOukWgRBTV+DhyGo82FZvvb2+YrRAbDhqJGLIjLyOO0pNTwk7arSgDiiKd/OK8LtA==}
/@formkit/vue/1.0.0-beta.12-e579559_vjnbgdptsk6bkj7ab5a6mk2cwm:
resolution: {integrity: sha512-z281m0+6alG7RyztFBDFvhVB2iYqaVk5o3Flfrro9FkzGDNCFjMyk0LwSTVQd8DhOVYeXPGImtKqp+mFoxrH4Q==}
peerDependencies:
vue: ^3.2.1
dependencies:
'@formkit/core': 1.0.0-beta.11
'@formkit/dev': 1.0.0-beta.11
'@formkit/i18n': 1.0.0-beta.11
'@formkit/inputs': 1.0.0-beta.11
'@formkit/observer': 1.0.0-beta.11
'@formkit/rules': 1.0.0-beta.11
'@formkit/themes': 1.0.0-beta.11_tailwindcss@3.2.1
'@formkit/utils': 1.0.0-beta.11
'@formkit/validation': 1.0.0-beta.11
'@formkit/core': 1.0.0-beta.12-e579559
'@formkit/dev': 1.0.0-beta.12-e579559
'@formkit/i18n': 1.0.0-beta.12-e579559
'@formkit/inputs': 1.0.0-beta.12-e579559
'@formkit/observer': 1.0.0-beta.12-e579559
'@formkit/rules': 1.0.0-beta.12-e579559
'@formkit/themes': 1.0.0-beta.12-e579559_tailwindcss@3.2.1
'@formkit/utils': 1.0.0-beta.12-e579559
'@formkit/validation': 1.0.0-beta.12-e579559
vue: 3.2.41
transitivePeerDependencies:
- tailwindcss

View File

@ -5,6 +5,7 @@ import type { DefaultConfigOptions } from "@formkit/vue";
import { form } from "./inputs/form";
import { attachment } from "./inputs/attachment";
import { code } from "./inputs/code";
import { repeater } from "./inputs/repeater";
import { menuCheckbox } from "./inputs/menu-checkbox";
import { menuRadio } from "./inputs/menu-radio";
import { menuItemSelect } from "./inputs/menu-item-select";
@ -15,14 +16,18 @@ import { tagSelect } from "./inputs/tag-select";
import { categoryCheckbox } from "./inputs/category-checkbox";
import { tagCheckbox } from "./inputs/tag-checkbox";
import radioAlt from "./plugins/radio-alt";
const config: DefaultConfigOptions = {
config: {
classes: generateClasses(theme),
},
plugins: [radioAlt],
inputs: {
form,
attachment,
code,
repeater,
menuCheckbox,
menuRadio,
menuItemSelect,

View File

@ -0,0 +1,117 @@
<script lang="ts" setup>
import {
VButton,
IconAddCircle,
IconCloseCircle,
IconArrowUpCircleLine,
IconArrowDownCircleLine,
} from "@halo-dev/components";
import type { FormKitFrameworkContext } from "@formkit/core";
import type { PropType } from "vue";
import cloneDeep from "lodash.clonedeep";
const props = defineProps({
context: {
type: Object as PropType<FormKitFrameworkContext>,
required: true,
},
});
const handleAppend = (index: number) => {
const value = cloneDeep(props.context._value);
value.splice(index + 1, 0, {});
props.context.node.input(value);
};
const handleRemove = (index: number) => {
const value = cloneDeep(props.context._value);
value.splice(index, 1);
props.context.node.input(value);
};
const handleMoveUp = (index: number) => {
if (index === 0) {
return;
}
const value = cloneDeep(props.context._value);
value.splice(index - 1, 0, value.splice(index, 1)[0]);
props.context.node.input(value);
};
const handleMoveDown = (index: number) => {
if (index === props.context._value.length - 1) {
return;
}
const value = cloneDeep(props.context._value);
value.splice(index + 1, 0, value.splice(index, 1)[0]);
props.context.node.input(value);
};
</script>
<template>
<ul :class="context.classes.items">
<li
v-for="(item, index) in context._value"
:key="index"
:class="context.classes.item"
>
<div :class="context.classes.content">
<FormKit
:id="`${context.node.name}-group-${index}`"
:key="`${context.node.name}-group-${index}`"
:model-value="item"
type="group"
>
<slot />
</FormKit>
</div>
<div :class="context.classes.controls">
<ul class="flex flex-col items-center justify-center gap-1.5 py-2">
<li
class="cursor-pointer text-gray-500 transition-all hover:text-primary"
:class="{
'cursor-not-allowed opacity-50 hover:!text-gray-500': index === 0,
}"
>
<IconArrowUpCircleLine
class="h-5 w-5"
@click="handleMoveUp(index)"
/>
</li>
<li
class="cursor-pointer text-gray-500 transition-all hover:text-primary"
>
<IconCloseCircle class="h-5 w-5" @click="handleRemove(index)" />
</li>
<li
class="cursor-pointer text-gray-500 transition-all hover:text-primary"
>
<IconAddCircle class="h-5 w-5" @click="handleAppend(index)" />
</li>
<li
class="cursor-pointer text-gray-500 transition-all hover:text-primary"
:class="{
'cursor-not-allowed opacity-50 hover:!text-gray-500':
index === context._value.length - 1,
}"
>
<IconArrowDownCircleLine
class="h-5 w-5"
@click="handleMoveDown(index)"
/>
</li>
</ul>
</div>
</li>
</ul>
<div :class="context.classes.add">
<VButton type="secondary" @click="handleAppend(context._value.length)">
<template #icon>
<IconAddCircle class="h-full w-full" />
</template>
添加
</VButton>
</div>
</template>

View File

@ -0,0 +1,29 @@
import type { FormKitTypeDefinition } from "@formkit/core";
import {
fieldset,
help,
inner,
legend,
message,
messages,
outer,
prefix,
suffix,
} from "@formkit/inputs";
import { repeaterItems } from "./sections";
import Repeater from "./Repeater.vue";
export const repeater: FormKitTypeDefinition = {
schema: outer(
fieldset(
legend("$label"),
help("$help"),
inner(prefix(), repeaterItems("$slots.default"), suffix())
),
messages(message("$message.value"))
),
type: "list",
library: {
Repeater: Repeater,
},
};

View File

@ -0,0 +1,8 @@
import { createSection } from "@formkit/inputs";
export const repeaterItems = createSection("repeaterItems", () => ({
$cmp: "Repeater",
props: {
context: "$node.context",
},
}));

View File

@ -0,0 +1,9 @@
import type { FormKitNode } from "@formkit/core";
let i = 0;
export default function radioAlt(node: FormKitNode) {
if (node.props.type === "radio") {
node.props.altName = `radio_${node.name}_${++i}`;
}
}

View File

@ -14,7 +14,7 @@ const boxClassification = {
"group border border-gray-300 rounded-base px-2 py-2 focus-within:border-primary max-w-lg",
wrapper:
"flex items-center mb-1 cursor-pointer group-[.formkit-fieldset]:px-2",
help: "mb-2 mt-0",
help: "mb-2 mt-0 px-2",
input:
"form-check-input h-4 w-4 mr-2 border border-gray-500 rounded-sm bg-white checked:bg-primary focus:outline-none focus:ring-0 transition duration-200",
inner: "flex items-center",
@ -79,6 +79,18 @@ const theme: Record<string, Record<string, string>> = {
input:
textClassification.input.replace("resize-none", "resize-y") + " py-2",
},
repeater: {
label: textClassification.label,
legend: `${textClassification.label} px-2`,
fieldset: boxClassification.fieldset,
wrapper: boxClassification.wrapper,
help: boxClassification.wrapper,
inner: "flex flex-col gap-4",
items: "flex flex-col w-full gap-2",
item: "border rounded-base grid grid-cols-12 focus-within:border-primary transition-all overflow-hidden focus-within:shadow-sm",
content: "flex-1 p-2 col-span-11",
controls: "bg-gray-200 col-span-1 flex items-center justify-center",
},
};
export default theme;

View File

@ -208,7 +208,10 @@ const onVisibleChange = (visible: boolean) => {
name="displayName"
validation="required"
></FormKit>
<FormKitSchema :schema="formSchema" />
<FormKitSchema
:schema="formSchema"
:data="configMapFormData['default']"
/>
</FormKit>
<template #footer>

View File

@ -65,7 +65,7 @@ watch(
type="form"
@submit="handleSaveConfigMap"
>
<FormKitSchema :schema="formSchema" />
<FormKitSchema :schema="formSchema" :data="configMapFormData[group]" />
</FormKit>
</div>
<div v-permission="['system:configmaps:manage']" class="pt-5">

View File

@ -297,7 +297,10 @@ const iframeClasses = computed(() => {
type="form"
@submit="handleSaveThemeConfigMap"
>
<FormKitSchema :schema="formSchema" />
<FormKitSchema
:schema="formSchema"
:data="configMapFormData[tab.id]"
/>
</FormKit>
</div>
<div v-permission="['system:configmaps:manage']" class="pt-5">

View File

@ -74,7 +74,7 @@ await handleFetchPlugin();
type="form"
@submit="handleSaveConfigMap"
>
<FormKitSchema :schema="formSchema" />
<FormKitSchema :schema="formSchema" :data="configMapFormData[group]" />
</FormKit>
</div>
<div v-permission="['system:configmaps:manage']" class="pt-5">

View File

@ -45,7 +45,7 @@ await handleFetchConfigMap();
type="form"
@submit="handleSaveConfigMap"
>
<FormKitSchema :schema="formSchema" />
<FormKitSchema :schema="formSchema" :data="configMapFormData[group]" />
</FormKit>
</div>
<div v-permission="['system:configmaps:manage']" class="pt-5">