pdyform 1.1.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -1
- package/example/README.md +36 -0
- package/example/react-demo/dist/assets/index-BBU9cJqy.css +1 -0
- package/example/react-demo/dist/assets/index-DeJS8UcQ.js +105 -0
- package/example/react-demo/dist/index.html +13 -0
- package/example/react-demo/index.html +12 -0
- package/example/react-demo/node_modules/.bin/browserslist +17 -0
- package/example/react-demo/node_modules/.bin/tsc +17 -0
- package/example/react-demo/node_modules/.bin/tsserver +17 -0
- package/example/react-demo/node_modules/.bin/vite +17 -0
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-checkbox.js +300 -0
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-checkbox.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-label.js +194 -0
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-label.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-radio-group.js +530 -0
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-radio-group.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-select.js +4808 -0
- package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-select.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/_metadata.json +115 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-3D5PZ6F6.js +49 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-3D5PZ6F6.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-5Q2RBQLA.js +127 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-5Q2RBQLA.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-G3PMV62Z.js +36 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-G3PMV62Z.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-GX7YZ5KV.js +370 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-GX7YZ5KV.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-PUFJGYAC.js +928 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-PUFJGYAC.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-SIU35MPB.js +21 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-SIU35MPB.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-TOMGVNQP.js +1906 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-TOMGVNQP.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-YYN6DZAU.js +21628 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-YYN6DZAU.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-ZE5VSJFE.js +144 -0
- package/example/react-demo/node_modules/.vite/deps/chunk-ZE5VSJFE.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/class-variance-authority.js +51 -0
- package/example/react-demo/node_modules/.vite/deps/class-variance-authority.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/clsx.js +10 -0
- package/example/react-demo/node_modules/.vite/deps/clsx.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/lucide-react.js +29725 -0
- package/example/react-demo/node_modules/.vite/deps/lucide-react.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/package.json +3 -0
- package/example/react-demo/node_modules/.vite/deps/react-dom.js +7 -0
- package/example/react-demo/node_modules/.vite/deps/react-dom.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/react-dom_client.js +39 -0
- package/example/react-demo/node_modules/.vite/deps/react-dom_client.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/react.js +6 -0
- package/example/react-demo/node_modules/.vite/deps/react.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/react_jsx-dev-runtime.js +913 -0
- package/example/react-demo/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/react_jsx-runtime.js +7 -0
- package/example/react-demo/node_modules/.vite/deps/react_jsx-runtime.js.map +7 -0
- package/example/react-demo/node_modules/.vite/deps/tailwind-merge.js +2534 -0
- package/example/react-demo/node_modules/.vite/deps/tailwind-merge.js.map +7 -0
- package/example/react-demo/package.json +23 -0
- package/example/react-demo/postcss.config.mjs +6 -0
- package/example/react-demo/src/App.tsx +64 -0
- package/example/react-demo/src/main.tsx +10 -0
- package/example/react-demo/src/styles.css +102 -0
- package/example/react-demo/tailwind.config.mjs +50 -0
- package/example/react-demo/tsconfig.json +16 -0
- package/example/react-demo/vite.config.ts +14 -0
- package/example/shared/defaultSchema.ts +68 -0
- package/example/vue-demo/dist/assets/index-BhWj3D5x.css +1 -0
- package/example/vue-demo/dist/assets/index-Bw3THsrD.js +44 -0
- package/example/vue-demo/dist/index.html +13 -0
- package/example/vue-demo/index.html +12 -0
- package/example/vue-demo/node_modules/.bin/tsc +17 -0
- package/example/vue-demo/node_modules/.bin/tsserver +17 -0
- package/example/vue-demo/node_modules/.bin/vite +17 -0
- package/example/vue-demo/node_modules/.vite/deps/_metadata.json +46 -0
- package/example/vue-demo/node_modules/.vite/deps/chunk-PZ5AY32C.js +10 -0
- package/example/vue-demo/node_modules/.vite/deps/chunk-PZ5AY32C.js.map +7 -0
- package/example/vue-demo/node_modules/.vite/deps/chunk-TCXBSQ4M.js +12877 -0
- package/example/vue-demo/node_modules/.vite/deps/chunk-TCXBSQ4M.js.map +7 -0
- package/example/vue-demo/node_modules/.vite/deps/clsx.js +22 -0
- package/example/vue-demo/node_modules/.vite/deps/clsx.js.map +7 -0
- package/example/vue-demo/node_modules/.vite/deps/lucide-vue-next.js +29720 -0
- package/example/vue-demo/node_modules/.vite/deps/lucide-vue-next.js.map +7 -0
- package/example/vue-demo/node_modules/.vite/deps/package.json +3 -0
- package/example/vue-demo/node_modules/.vite/deps/radix-vue.js +24321 -0
- package/example/vue-demo/node_modules/.vite/deps/radix-vue.js.map +7 -0
- package/example/vue-demo/node_modules/.vite/deps/tailwind-merge.js +2534 -0
- package/example/vue-demo/node_modules/.vite/deps/tailwind-merge.js.map +7 -0
- package/example/vue-demo/node_modules/.vite/deps/vue.js +348 -0
- package/example/vue-demo/node_modules/.vite/deps/vue.js.map +7 -0
- package/example/vue-demo/package.json +20 -0
- package/example/vue-demo/postcss.config.mjs +6 -0
- package/example/vue-demo/src/App.vue +61 -0
- package/example/vue-demo/src/env.d.ts +1 -0
- package/example/vue-demo/src/main.ts +5 -0
- package/example/vue-demo/src/style.css +102 -0
- package/example/vue-demo/tailwind.config.mjs +50 -0
- package/example/vue-demo/tsconfig.json +15 -0
- package/example/vue-demo/vite.config.ts +14 -0
- package/package.json +10 -2
- package/packages/core/dist/{chunk-KQR3LFND.js → chunk-GQASS6PM.js} +20 -0
- package/packages/core/dist/index.cjs +20 -0
- package/packages/core/dist/index.js +1 -1
- package/packages/core/dist/utils.cjs +20 -0
- package/packages/core/dist/utils.js +1 -1
- package/packages/core/node_modules/.bin/jiti +17 -0
- package/packages/core/node_modules/.bin/tsup +2 -2
- package/packages/core/node_modules/.bin/tsup-node +2 -2
- package/packages/core/node_modules/.vite/vitest/results.json +1 -1
- package/packages/core/src/utils.ts +21 -0
- package/packages/core/test/utils.test.ts +99 -0
- package/packages/react/dist/index.cjs +383 -110
- package/packages/react/dist/index.d.cts +80 -4
- package/packages/react/dist/index.d.ts +80 -4
- package/packages/react/dist/index.js +355 -110
- package/packages/react/node_modules/.bin/jiti +17 -0
- package/packages/react/node_modules/.bin/tsup +2 -2
- package/packages/react/node_modules/.bin/tsup-node +2 -2
- package/packages/react/node_modules/.bin/vite +4 -4
- package/packages/react/node_modules/.vite/vitest/results.json +1 -1
- package/packages/react/package.json +7 -2
- package/packages/react/postcss.config.mjs +6 -0
- package/packages/react/src/FormFieldRenderer.tsx +32 -112
- package/packages/react/src/components/Checkbox.tsx +28 -0
- package/packages/react/src/components/CheckboxRenderer.tsx +37 -0
- package/packages/react/src/components/Input.tsx +24 -0
- package/packages/react/src/components/InputRenderer.tsx +29 -0
- package/packages/react/src/components/Label.tsx +24 -0
- package/packages/react/src/components/RadioGroup.tsx +42 -0
- package/packages/react/src/components/RadioRenderer.tsx +29 -0
- package/packages/react/src/components/Select.tsx +93 -0
- package/packages/react/src/components/SelectRenderer.tsx +27 -0
- package/packages/react/src/components/Textarea.tsx +23 -0
- package/packages/react/src/components/TextareaRenderer.tsx +17 -0
- package/packages/react/src/components/index.ts +55 -0
- package/packages/react/src/components/types.ts +17 -0
- package/packages/react/src/index.tsx +1 -0
- package/packages/react/src/utils.ts +7 -0
- package/packages/react/tailwind.config.mjs +10 -0
- package/packages/react/test/FormFieldRenderer.test.tsx +127 -0
- package/packages/vue/dist/index.d.ts +33 -0
- package/packages/vue/dist/index.js +28 -1
- package/packages/vue/dist/index.mjs +6798 -142
- package/packages/vue/node_modules/.bin/tsc +2 -2
- package/packages/vue/node_modules/.bin/tsserver +2 -2
- package/packages/vue/node_modules/.bin/vite +2 -2
- package/packages/vue/node_modules/.bin/vitest +2 -2
- package/packages/vue/node_modules/.bin/vue-tsc +2 -2
- package/packages/vue/node_modules/.vite/vitest/results.json +1 -1
- package/packages/vue/package.json +4 -2
- package/packages/vue/postcss.config.mjs +6 -0
- package/packages/vue/src/FormFieldRenderer.vue +46 -90
- package/packages/vue/src/components/Checkbox.vue +28 -0
- package/packages/vue/src/components/CheckboxRenderer.vue +35 -0
- package/packages/vue/src/components/Input.vue +21 -0
- package/packages/vue/src/components/InputRenderer.vue +28 -0
- package/packages/vue/src/components/Label.vue +21 -0
- package/packages/vue/src/components/RadioGroup.vue +30 -0
- package/packages/vue/src/components/RadioGroupItem.vue +26 -0
- package/packages/vue/src/components/RadioRenderer.vue +24 -0
- package/packages/vue/src/components/Select.vue +40 -0
- package/packages/vue/src/components/SelectContent.vue +38 -0
- package/packages/vue/src/components/SelectItem.vue +43 -0
- package/packages/vue/src/components/SelectRenderer.vue +30 -0
- package/packages/vue/src/components/SelectTrigger.vue +27 -0
- package/packages/vue/src/components/Textarea.vue +19 -0
- package/packages/vue/src/components/TextareaRenderer.vue +18 -0
- package/packages/vue/src/components/index.ts +24 -0
- package/packages/vue/src/fieldComponentMap.ts +34 -0
- package/packages/vue/src/index.ts +2 -0
- package/packages/vue/src/utils.ts +6 -0
- package/packages/vue/tailwind.config.mjs +10 -0
- package/packages/vue/test/FormFieldRenderer.test.ts +133 -0
- package/pnpm-workspace.yaml +1 -1
- package/packages/core/src/index.test.ts +0 -37
- /package/packages/react/{src → test}/DynamicForm.test.tsx +0 -0
- /package/packages/vue/{src → test}/DynamicForm.test.ts +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { cn } from '../utils'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
class?: any
|
|
6
|
+
modelValue?: any
|
|
7
|
+
}>()
|
|
8
|
+
|
|
9
|
+
const emit = defineEmits(['update:modelValue', 'blur'])
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<textarea
|
|
14
|
+
:class="cn('flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', props.class)"
|
|
15
|
+
:value="modelValue"
|
|
16
|
+
@input="emit('update:modelValue', ($event.target as HTMLTextAreaElement).value)"
|
|
17
|
+
@blur="emit('blur', $event)"
|
|
18
|
+
/>
|
|
19
|
+
</template>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { FieldRendererProps } from '../fieldComponentMap';
|
|
3
|
+
import Textarea from '../components/Textarea.vue';
|
|
4
|
+
|
|
5
|
+
const props = defineProps<FieldRendererProps>();
|
|
6
|
+
const emit = defineEmits<{ 'update:modelValue': [value: any] }>();
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<Textarea
|
|
11
|
+
:id="fieldId"
|
|
12
|
+
:placeholder="field.placeholder"
|
|
13
|
+
:disabled="field.disabled"
|
|
14
|
+
:name="field.name"
|
|
15
|
+
:modelValue="modelValue ?? ''"
|
|
16
|
+
@update:modelValue="emit('update:modelValue', $event)"
|
|
17
|
+
/>
|
|
18
|
+
</template>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// ─── Primitive UI components ─────────────────────────────────────────────────
|
|
2
|
+
export { default as Input } from './Input.vue';
|
|
3
|
+
export { default as Textarea } from './Textarea.vue';
|
|
4
|
+
export { default as Checkbox } from './Checkbox.vue';
|
|
5
|
+
export { default as RadioGroup } from './RadioGroup.vue';
|
|
6
|
+
export { default as RadioGroupItem } from './RadioGroupItem.vue';
|
|
7
|
+
export { default as Select } from './Select.vue';
|
|
8
|
+
export { default as SelectTrigger } from './SelectTrigger.vue';
|
|
9
|
+
export { default as SelectContent } from './SelectContent.vue';
|
|
10
|
+
export { default as SelectItem } from './SelectItem.vue';
|
|
11
|
+
export { default as Label } from './Label.vue';
|
|
12
|
+
|
|
13
|
+
// ─── Field renderer components ────────────────────────────────────────────────
|
|
14
|
+
export { default as InputRenderer } from './InputRenderer.vue';
|
|
15
|
+
export { default as TextareaRenderer } from './TextareaRenderer.vue';
|
|
16
|
+
export { default as SelectRenderer } from './SelectRenderer.vue';
|
|
17
|
+
export { default as CheckboxRenderer } from './CheckboxRenderer.vue';
|
|
18
|
+
export { default as RadioRenderer } from './RadioRenderer.vue';
|
|
19
|
+
|
|
20
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
21
|
+
export type { FieldComponentMap, FieldRendererProps } from '../fieldComponentMap';
|
|
22
|
+
|
|
23
|
+
// ─── Default component map ───────────────────────────────────────────────────
|
|
24
|
+
export { defaultComponentMap } from '../fieldComponentMap';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { FormField } from 'pdyform/core';
|
|
2
|
+
import type { Component } from 'vue';
|
|
3
|
+
|
|
4
|
+
import InputRenderer from './components/InputRenderer.vue';
|
|
5
|
+
import TextareaRenderer from './components/TextareaRenderer.vue';
|
|
6
|
+
import SelectRenderer from './components/SelectRenderer.vue';
|
|
7
|
+
import CheckboxRenderer from './components/CheckboxRenderer.vue';
|
|
8
|
+
import RadioRenderer from './components/RadioRenderer.vue';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The props interface that every field renderer component must accept.
|
|
12
|
+
* Custom field renderers must implement this interface.
|
|
13
|
+
*/
|
|
14
|
+
export interface FieldRendererProps {
|
|
15
|
+
field: FormField;
|
|
16
|
+
modelValue: any;
|
|
17
|
+
fieldId: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Map from field type to a Vue component */
|
|
21
|
+
export type FieldComponentMap = Record<string, Component>;
|
|
22
|
+
|
|
23
|
+
/** The default built-in component map */
|
|
24
|
+
export const defaultComponentMap: FieldComponentMap = {
|
|
25
|
+
text: InputRenderer,
|
|
26
|
+
number: InputRenderer,
|
|
27
|
+
password: InputRenderer,
|
|
28
|
+
email: InputRenderer,
|
|
29
|
+
date: InputRenderer,
|
|
30
|
+
textarea: TextareaRenderer,
|
|
31
|
+
select: SelectRenderer,
|
|
32
|
+
checkbox: CheckboxRenderer,
|
|
33
|
+
radio: RadioRenderer,
|
|
34
|
+
};
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as DynamicForm } from './DynamicForm.vue';
|
|
2
2
|
export { default as FormFieldRenderer } from './FormFieldRenderer.vue';
|
|
3
|
+
export { defaultComponentMap } from './fieldComponentMap';
|
|
4
|
+
export type { FieldComponentMap, FieldRendererProps } from './fieldComponentMap';
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { mount } from '@vue/test-utils';
|
|
4
|
+
import FormFieldRenderer from '../src/FormFieldRenderer.vue';
|
|
5
|
+
import type { FormField } from 'pdyform/core';
|
|
6
|
+
|
|
7
|
+
describe('FormFieldRenderer', () => {
|
|
8
|
+
const defaultField: FormField = {
|
|
9
|
+
name: 'testField',
|
|
10
|
+
label: 'Test Label',
|
|
11
|
+
type: 'text',
|
|
12
|
+
id: 'test-field-id',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
it('renders a text input correctly', async () => {
|
|
16
|
+
const wrapper = mount(FormFieldRenderer, {
|
|
17
|
+
props: { field: defaultField, modelValue: 'test value' }
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
expect(wrapper.find('label').text()).toBe('Test Label');
|
|
21
|
+
const input = wrapper.find('input');
|
|
22
|
+
expect((input.element as HTMLInputElement).value).toBe('test value');
|
|
23
|
+
expect((input.element as HTMLInputElement).type).toBe('text');
|
|
24
|
+
|
|
25
|
+
await input.setValue('new value');
|
|
26
|
+
expect(wrapper.emitted('update:modelValue')![0]).toEqual(['new value']);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('emits number for number inputs', async () => {
|
|
30
|
+
const field: FormField = { ...defaultField, type: 'number' };
|
|
31
|
+
const wrapper = mount(FormFieldRenderer, {
|
|
32
|
+
props: { field, modelValue: 22 }
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const input = wrapper.find('input');
|
|
36
|
+
await input.setValue('23');
|
|
37
|
+
expect(wrapper.emitted('update:modelValue')![0]).toEqual([23]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('renders a textarea correctly', async () => {
|
|
41
|
+
const field: FormField = { ...defaultField, type: 'textarea' };
|
|
42
|
+
const wrapper = mount(FormFieldRenderer, {
|
|
43
|
+
props: { field, modelValue: 'text\narea' }
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const textarea = wrapper.find('textarea');
|
|
47
|
+
expect((textarea.element as HTMLTextAreaElement).value).toBe('text\narea');
|
|
48
|
+
|
|
49
|
+
await textarea.setValue('new textarea value');
|
|
50
|
+
expect(wrapper.emitted('update:modelValue')![0]).toEqual(['new textarea value']);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('renders a select correctly', async () => {
|
|
54
|
+
const field: FormField = {
|
|
55
|
+
...defaultField,
|
|
56
|
+
type: 'select',
|
|
57
|
+
options: [
|
|
58
|
+
{ label: 'Option 1', value: 'opt1' },
|
|
59
|
+
{ label: 'Option 2', value: 'opt2' }
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
const wrapper = mount(FormFieldRenderer, {
|
|
63
|
+
props: { field, modelValue: 'opt1' }
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Radix Select renders a combobox trigger
|
|
67
|
+
expect(wrapper.find('[role="combobox"]').exists()).toBe(true);
|
|
68
|
+
|
|
69
|
+
// Simulate the SelectField emitting the new value (Radix portal doesn't fully function in jsdom)
|
|
70
|
+
const selectField = wrapper.findComponent({ name: 'Select' });
|
|
71
|
+
await selectField.vm.$emit('update:modelValue', 'opt2');
|
|
72
|
+
|
|
73
|
+
expect(wrapper.emitted('update:modelValue')![0]).toEqual(['opt2']);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('renders a checkbox correctly', async () => {
|
|
77
|
+
const field: FormField = {
|
|
78
|
+
...defaultField,
|
|
79
|
+
type: 'checkbox',
|
|
80
|
+
options: [
|
|
81
|
+
{ label: 'Check 1', value: 'c1' },
|
|
82
|
+
{ label: 'Check 2', value: 'c2' }
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
const wrapper = mount(FormFieldRenderer, {
|
|
86
|
+
props: { field, modelValue: ['c1'] }
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const checkboxes = wrapper.findAll('[role="checkbox"]');
|
|
90
|
+
expect(checkboxes[0].attributes('data-state')).toBe('checked');
|
|
91
|
+
expect(checkboxes[1].attributes('data-state')).toBe('unchecked');
|
|
92
|
+
|
|
93
|
+
// Emit from the internal CheckboxComponent logic since Radix click simulation can be tricky with simple DOM wrapper
|
|
94
|
+
const checkboxComponents = wrapper.findAllComponents({ name: 'Checkbox' });
|
|
95
|
+
await checkboxComponents[1].vm.$emit('update:checked', true);
|
|
96
|
+
|
|
97
|
+
expect(wrapper.emitted('update:modelValue')![0]).toEqual([['c1', 'c2']]);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('renders a radio correctly', async () => {
|
|
101
|
+
const field: FormField = {
|
|
102
|
+
...defaultField,
|
|
103
|
+
type: 'radio',
|
|
104
|
+
options: [
|
|
105
|
+
{ label: 'Radio 1', value: 'r1' },
|
|
106
|
+
{ label: 'Radio 2', value: 'r2' }
|
|
107
|
+
]
|
|
108
|
+
};
|
|
109
|
+
const wrapper = mount(FormFieldRenderer, {
|
|
110
|
+
props: { field, modelValue: 'r1' }
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const radios = wrapper.findAll('[role="radio"]');
|
|
114
|
+
expect(radios[0].attributes('data-state')).toBe('checked');
|
|
115
|
+
expect(radios[1].attributes('data-state')).toBe('unchecked');
|
|
116
|
+
|
|
117
|
+
// Radix Vue uses a radio group component wrapper for selecting
|
|
118
|
+
const radioGroupComp = wrapper.findComponent({ name: 'RadioGroup' });
|
|
119
|
+
await radioGroupComp.vm.$emit('update:modelValue', 'r2');
|
|
120
|
+
|
|
121
|
+
expect(wrapper.emitted('update:modelValue')![0]).toEqual(['r2']);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('displays description and error', () => {
|
|
125
|
+
const field: FormField = { ...defaultField, description: 'Desc text' };
|
|
126
|
+
const wrapper = mount(FormFieldRenderer, {
|
|
127
|
+
props: { field, modelValue: '', error: 'Error text' }
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(wrapper.text()).toContain('Desc text');
|
|
131
|
+
expect(wrapper.text()).toContain('Error text');
|
|
132
|
+
});
|
|
133
|
+
});
|
package/pnpm-workspace.yaml
CHANGED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { validateField, getDefaultValues } from '../src';
|
|
3
|
-
import { FormField } from '../src/types';
|
|
4
|
-
|
|
5
|
-
describe('core utils', () => {
|
|
6
|
-
it('should validate required fields', () => {
|
|
7
|
-
const field: FormField = {
|
|
8
|
-
name: 'test',
|
|
9
|
-
label: 'Test',
|
|
10
|
-
type: 'text',
|
|
11
|
-
validations: [{ type: 'required', message: 'Required' }]
|
|
12
|
-
};
|
|
13
|
-
expect(validateField('', field)).toBe('Required');
|
|
14
|
-
expect(validateField('val', field)).toBeNull();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('should validate regex', () => {
|
|
18
|
-
const field: FormField = {
|
|
19
|
-
name: 'test',
|
|
20
|
-
label: 'Test',
|
|
21
|
-
type: 'text',
|
|
22
|
-
validations: [{ type: 'pattern', value: '^[0-9]+$', message: 'Only numbers' }]
|
|
23
|
-
};
|
|
24
|
-
expect(validateField('abc', field)).toBe('Only numbers');
|
|
25
|
-
expect(validateField('123', field)).toBeNull();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should get default values', () => {
|
|
29
|
-
const schema = {
|
|
30
|
-
fields: [
|
|
31
|
-
{ name: 'f1', label: 'L1', type: 'text', defaultValue: 'v1' },
|
|
32
|
-
{ name: 'f2', label: 'L2', type: 'text' }
|
|
33
|
-
]
|
|
34
|
-
} as any;
|
|
35
|
-
expect(getDefaultValues(schema.fields)).toEqual({ f1: 'v1', f2: '' });
|
|
36
|
-
});
|
|
37
|
-
});
|
|
File without changes
|
|
File without changes
|