pdyform 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/package.json +9 -3
  2. package/packages/core/dist/chunk-TP3IHKWV.js +69 -0
  3. package/packages/core/dist/{chunk-GQASS6PM.js → chunk-WEDHXOHH.js} +22 -0
  4. package/packages/core/dist/formState.cjs +187 -0
  5. package/packages/core/dist/formState.d.cts +17 -0
  6. package/packages/core/dist/formState.d.ts +17 -0
  7. package/packages/core/dist/formState.js +15 -0
  8. package/packages/core/dist/index.cjs +92 -2
  9. package/packages/core/dist/index.d.cts +2 -1
  10. package/packages/core/dist/index.d.ts +2 -1
  11. package/packages/core/dist/index.js +21 -3
  12. package/packages/core/dist/utils.cjs +27 -2
  13. package/packages/core/dist/utils.d.cts +4 -1
  14. package/packages/core/dist/utils.d.ts +4 -1
  15. package/packages/core/dist/utils.js +9 -3
  16. package/packages/react/dist/index.cjs +14 -43
  17. package/packages/react/dist/index.js +20 -43
  18. package/packages/vue/dist/index.d.ts +2 -36
  19. package/packages/vue/dist/index.js +1 -28
  20. package/packages/vue/dist/index.mjs +267 -6530
  21. package/eslint.config.mjs +0 -53
  22. package/example/README.md +0 -36
  23. package/example/react-demo/index.html +0 -12
  24. package/example/react-demo/node_modules/.bin/browserslist +0 -17
  25. package/example/react-demo/node_modules/.bin/tsc +0 -17
  26. package/example/react-demo/node_modules/.bin/tsserver +0 -17
  27. package/example/react-demo/node_modules/.bin/vite +0 -17
  28. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-checkbox.js +0 -300
  29. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-checkbox.js.map +0 -7
  30. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-label.js +0 -194
  31. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-label.js.map +0 -7
  32. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-radio-group.js +0 -530
  33. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-radio-group.js.map +0 -7
  34. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-select.js +0 -4808
  35. package/example/react-demo/node_modules/.vite/deps/@radix-ui_react-select.js.map +0 -7
  36. package/example/react-demo/node_modules/.vite/deps/_metadata.json +0 -115
  37. package/example/react-demo/node_modules/.vite/deps/chunk-3D5PZ6F6.js +0 -49
  38. package/example/react-demo/node_modules/.vite/deps/chunk-3D5PZ6F6.js.map +0 -7
  39. package/example/react-demo/node_modules/.vite/deps/chunk-5Q2RBQLA.js +0 -127
  40. package/example/react-demo/node_modules/.vite/deps/chunk-5Q2RBQLA.js.map +0 -7
  41. package/example/react-demo/node_modules/.vite/deps/chunk-G3PMV62Z.js +0 -36
  42. package/example/react-demo/node_modules/.vite/deps/chunk-G3PMV62Z.js.map +0 -7
  43. package/example/react-demo/node_modules/.vite/deps/chunk-GX7YZ5KV.js +0 -370
  44. package/example/react-demo/node_modules/.vite/deps/chunk-GX7YZ5KV.js.map +0 -7
  45. package/example/react-demo/node_modules/.vite/deps/chunk-PUFJGYAC.js +0 -928
  46. package/example/react-demo/node_modules/.vite/deps/chunk-PUFJGYAC.js.map +0 -7
  47. package/example/react-demo/node_modules/.vite/deps/chunk-SIU35MPB.js +0 -21
  48. package/example/react-demo/node_modules/.vite/deps/chunk-SIU35MPB.js.map +0 -7
  49. package/example/react-demo/node_modules/.vite/deps/chunk-TOMGVNQP.js +0 -1906
  50. package/example/react-demo/node_modules/.vite/deps/chunk-TOMGVNQP.js.map +0 -7
  51. package/example/react-demo/node_modules/.vite/deps/chunk-YYN6DZAU.js +0 -21628
  52. package/example/react-demo/node_modules/.vite/deps/chunk-YYN6DZAU.js.map +0 -7
  53. package/example/react-demo/node_modules/.vite/deps/chunk-ZE5VSJFE.js +0 -144
  54. package/example/react-demo/node_modules/.vite/deps/chunk-ZE5VSJFE.js.map +0 -7
  55. package/example/react-demo/node_modules/.vite/deps/class-variance-authority.js +0 -51
  56. package/example/react-demo/node_modules/.vite/deps/class-variance-authority.js.map +0 -7
  57. package/example/react-demo/node_modules/.vite/deps/clsx.js +0 -10
  58. package/example/react-demo/node_modules/.vite/deps/clsx.js.map +0 -7
  59. package/example/react-demo/node_modules/.vite/deps/lucide-react.js +0 -29725
  60. package/example/react-demo/node_modules/.vite/deps/lucide-react.js.map +0 -7
  61. package/example/react-demo/node_modules/.vite/deps/package.json +0 -3
  62. package/example/react-demo/node_modules/.vite/deps/react-dom.js +0 -7
  63. package/example/react-demo/node_modules/.vite/deps/react-dom.js.map +0 -7
  64. package/example/react-demo/node_modules/.vite/deps/react-dom_client.js +0 -39
  65. package/example/react-demo/node_modules/.vite/deps/react-dom_client.js.map +0 -7
  66. package/example/react-demo/node_modules/.vite/deps/react.js +0 -6
  67. package/example/react-demo/node_modules/.vite/deps/react.js.map +0 -7
  68. package/example/react-demo/node_modules/.vite/deps/react_jsx-dev-runtime.js +0 -913
  69. package/example/react-demo/node_modules/.vite/deps/react_jsx-dev-runtime.js.map +0 -7
  70. package/example/react-demo/node_modules/.vite/deps/react_jsx-runtime.js +0 -7
  71. package/example/react-demo/node_modules/.vite/deps/react_jsx-runtime.js.map +0 -7
  72. package/example/react-demo/node_modules/.vite/deps/tailwind-merge.js +0 -2534
  73. package/example/react-demo/node_modules/.vite/deps/tailwind-merge.js.map +0 -7
  74. package/example/react-demo/package.json +0 -23
  75. package/example/react-demo/postcss.config.mjs +0 -6
  76. package/example/react-demo/src/App.tsx +0 -64
  77. package/example/react-demo/src/main.tsx +0 -10
  78. package/example/react-demo/src/styles.css +0 -102
  79. package/example/react-demo/tailwind.config.mjs +0 -50
  80. package/example/react-demo/tsconfig.json +0 -16
  81. package/example/react-demo/vite.config.ts +0 -14
  82. package/example/shared/defaultSchema.ts +0 -68
  83. package/example/vue-demo/index.html +0 -12
  84. package/example/vue-demo/node_modules/.bin/tsc +0 -17
  85. package/example/vue-demo/node_modules/.bin/tsserver +0 -17
  86. package/example/vue-demo/node_modules/.bin/vite +0 -17
  87. package/example/vue-demo/node_modules/.vite/deps/_metadata.json +0 -46
  88. package/example/vue-demo/node_modules/.vite/deps/chunk-PZ5AY32C.js +0 -10
  89. package/example/vue-demo/node_modules/.vite/deps/chunk-PZ5AY32C.js.map +0 -7
  90. package/example/vue-demo/node_modules/.vite/deps/chunk-TCXBSQ4M.js +0 -12877
  91. package/example/vue-demo/node_modules/.vite/deps/chunk-TCXBSQ4M.js.map +0 -7
  92. package/example/vue-demo/node_modules/.vite/deps/clsx.js +0 -22
  93. package/example/vue-demo/node_modules/.vite/deps/clsx.js.map +0 -7
  94. package/example/vue-demo/node_modules/.vite/deps/lucide-vue-next.js +0 -29720
  95. package/example/vue-demo/node_modules/.vite/deps/lucide-vue-next.js.map +0 -7
  96. package/example/vue-demo/node_modules/.vite/deps/package.json +0 -3
  97. package/example/vue-demo/node_modules/.vite/deps/radix-vue.js +0 -24321
  98. package/example/vue-demo/node_modules/.vite/deps/radix-vue.js.map +0 -7
  99. package/example/vue-demo/node_modules/.vite/deps/tailwind-merge.js +0 -2534
  100. package/example/vue-demo/node_modules/.vite/deps/tailwind-merge.js.map +0 -7
  101. package/example/vue-demo/node_modules/.vite/deps/vue.js +0 -348
  102. package/example/vue-demo/node_modules/.vite/deps/vue.js.map +0 -7
  103. package/example/vue-demo/package.json +0 -20
  104. package/example/vue-demo/postcss.config.mjs +0 -6
  105. package/example/vue-demo/src/App.vue +0 -61
  106. package/example/vue-demo/src/env.d.ts +0 -1
  107. package/example/vue-demo/src/main.ts +0 -5
  108. package/example/vue-demo/src/style.css +0 -102
  109. package/example/vue-demo/tailwind.config.mjs +0 -50
  110. package/example/vue-demo/tsconfig.json +0 -15
  111. package/example/vue-demo/vite.config.ts +0 -14
  112. package/packages/core/dist/parser.cjs +0 -1
  113. package/packages/core/dist/parser.d.cts +0 -2
  114. package/packages/core/dist/parser.d.ts +0 -2
  115. package/packages/core/dist/parser.js +0 -0
  116. package/packages/core/node_modules/.bin/api-extractor +0 -17
  117. package/packages/core/node_modules/.bin/esbuild +0 -14
  118. package/packages/core/node_modules/.bin/jiti +0 -17
  119. package/packages/core/node_modules/.bin/tsc +0 -17
  120. package/packages/core/node_modules/.bin/tsserver +0 -17
  121. package/packages/core/node_modules/.bin/tsup +0 -17
  122. package/packages/core/node_modules/.bin/tsup-node +0 -17
  123. package/packages/core/node_modules/.bin/vitest +0 -17
  124. package/packages/core/node_modules/.vite/vitest/results.json +0 -1
  125. package/packages/core/package.json +0 -37
  126. package/packages/core/src/index.ts +0 -2
  127. package/packages/core/src/parser.ts +0 -0
  128. package/packages/core/src/types.ts +0 -42
  129. package/packages/core/src/utils.ts +0 -80
  130. package/packages/core/test/utils.test.ts +0 -99
  131. package/packages/core/tsconfig.json +0 -15
  132. package/packages/core/tsup.config.ts +0 -9
  133. package/packages/react/node_modules/.bin/api-extractor +0 -17
  134. package/packages/react/node_modules/.bin/browserslist +0 -17
  135. package/packages/react/node_modules/.bin/esbuild +0 -14
  136. package/packages/react/node_modules/.bin/jiti +0 -17
  137. package/packages/react/node_modules/.bin/tsc +0 -17
  138. package/packages/react/node_modules/.bin/tsserver +0 -17
  139. package/packages/react/node_modules/.bin/tsup +0 -17
  140. package/packages/react/node_modules/.bin/tsup-node +0 -17
  141. package/packages/react/node_modules/.bin/vite +0 -17
  142. package/packages/react/node_modules/.bin/vitest +0 -17
  143. package/packages/react/node_modules/.vite/vitest/results.json +0 -1
  144. package/packages/react/package.json +0 -57
  145. package/packages/react/postcss.config.mjs +0 -6
  146. package/packages/react/src/DynamicForm.tsx +0 -93
  147. package/packages/react/src/FormFieldRenderer.tsx +0 -50
  148. package/packages/react/src/components/Checkbox.tsx +0 -28
  149. package/packages/react/src/components/CheckboxRenderer.tsx +0 -37
  150. package/packages/react/src/components/Input.tsx +0 -24
  151. package/packages/react/src/components/InputRenderer.tsx +0 -29
  152. package/packages/react/src/components/Label.tsx +0 -24
  153. package/packages/react/src/components/RadioGroup.tsx +0 -42
  154. package/packages/react/src/components/RadioRenderer.tsx +0 -29
  155. package/packages/react/src/components/Select.tsx +0 -93
  156. package/packages/react/src/components/SelectRenderer.tsx +0 -27
  157. package/packages/react/src/components/Textarea.tsx +0 -23
  158. package/packages/react/src/components/TextareaRenderer.tsx +0 -17
  159. package/packages/react/src/components/index.ts +0 -55
  160. package/packages/react/src/components/types.ts +0 -17
  161. package/packages/react/src/index.tsx +0 -3
  162. package/packages/react/src/utils.ts +0 -7
  163. package/packages/react/tailwind.config.mjs +0 -10
  164. package/packages/react/test/DynamicForm.test.tsx +0 -25
  165. package/packages/react/test/FormFieldRenderer.test.tsx +0 -127
  166. package/packages/react/tsconfig.json +0 -15
  167. package/packages/react/vitest.config.ts +0 -16
  168. package/packages/vue/node_modules/.bin/rollup +0 -17
  169. package/packages/vue/node_modules/.bin/tsc +0 -17
  170. package/packages/vue/node_modules/.bin/tsserver +0 -17
  171. package/packages/vue/node_modules/.bin/vite +0 -17
  172. package/packages/vue/node_modules/.bin/vitest +0 -17
  173. package/packages/vue/node_modules/.bin/vue-tsc +0 -17
  174. package/packages/vue/node_modules/.vite/vitest/results.json +0 -1
  175. package/packages/vue/node_modules/.vue-global-types/vue_3.5_0_0_0.d.ts +0 -118
  176. package/packages/vue/node_modules/.vue-global-types/vue_3.5_false.d.ts +0 -128
  177. package/packages/vue/package.json +0 -53
  178. package/packages/vue/postcss.config.mjs +0 -6
  179. package/packages/vue/src/DynamicForm.vue +0 -81
  180. package/packages/vue/src/FormFieldRenderer.vue +0 -70
  181. package/packages/vue/src/components/Checkbox.vue +0 -28
  182. package/packages/vue/src/components/CheckboxRenderer.vue +0 -35
  183. package/packages/vue/src/components/Input.vue +0 -21
  184. package/packages/vue/src/components/InputRenderer.vue +0 -28
  185. package/packages/vue/src/components/Label.vue +0 -21
  186. package/packages/vue/src/components/RadioGroup.vue +0 -30
  187. package/packages/vue/src/components/RadioGroupItem.vue +0 -26
  188. package/packages/vue/src/components/RadioRenderer.vue +0 -24
  189. package/packages/vue/src/components/Select.vue +0 -40
  190. package/packages/vue/src/components/SelectContent.vue +0 -38
  191. package/packages/vue/src/components/SelectItem.vue +0 -43
  192. package/packages/vue/src/components/SelectRenderer.vue +0 -30
  193. package/packages/vue/src/components/SelectTrigger.vue +0 -27
  194. package/packages/vue/src/components/Textarea.vue +0 -19
  195. package/packages/vue/src/components/TextareaRenderer.vue +0 -18
  196. package/packages/vue/src/components/index.ts +0 -24
  197. package/packages/vue/src/env.d.ts +0 -7
  198. package/packages/vue/src/fieldComponentMap.ts +0 -34
  199. package/packages/vue/src/index.ts +0 -4
  200. package/packages/vue/src/utils.ts +0 -6
  201. package/packages/vue/tailwind.config.mjs +0 -10
  202. package/packages/vue/test/DynamicForm.test.ts +0 -19
  203. package/packages/vue/test/FormFieldRenderer.test.ts +0 -133
  204. package/packages/vue/tsconfig.json +0 -16
  205. package/packages/vue/vite.config.ts +0 -29
  206. package/packages/vue/vitest.config.ts +0 -16
  207. package/pnpm-workspace.yaml +0 -4
  208. package/tsconfig.json +0 -21
  209. package/turbo.json +0 -25
@@ -1,81 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, onMounted } from 'vue';
3
- import type { FormSchema } from 'pdyform/core';
4
- import { validateField, getDefaultValues } from 'pdyform/core';
5
- import FormFieldRenderer from './FormFieldRenderer.vue';
6
-
7
- const props = defineProps<{
8
- schema: FormSchema;
9
- className?: string;
10
- }>();
11
-
12
- const emit = defineEmits(['submit']);
13
-
14
- const values = ref<Record<string, any>>({});
15
- const errors = ref<Record<string, string>>({});
16
- const isSubmitting = ref(false);
17
-
18
- onMounted(() => {
19
- values.value = getDefaultValues(props.schema.fields);
20
- });
21
-
22
- const handleFieldChange = (name: string, value: any) => {
23
- values.value[name] = value;
24
-
25
- const field = props.schema.fields.find(f => f.name === name);
26
- if (field) {
27
- const error = validateField(value, field);
28
- errors.value[name] = error || '';
29
- }
30
- };
31
-
32
- const handleSubmit = () => {
33
- isSubmitting.value = true;
34
- const newErrors: Record<string, string> = {};
35
- let hasError = false;
36
-
37
- props.schema.fields.forEach((field) => {
38
- const error = validateField(values.value[field.name], field);
39
- if (error) {
40
- newErrors[field.name] = error;
41
- hasError = true;
42
- }
43
- });
44
-
45
- errors.value = newErrors;
46
-
47
- if (!hasError) {
48
- emit('submit', { ...values.value });
49
- }
50
- isSubmitting.value = false;
51
- };
52
- </script>
53
-
54
- <template>
55
- <form :class="['space-y-6', className]" @submit.prevent="handleSubmit">
56
- <div v-if="schema.title || schema.description" class="space-y-1">
57
- <h2 v-if="schema.title" class="text-2xl font-bold tracking-tight">{{ schema.title }}</h2>
58
- <p v-if="schema.description" class="text-muted-foreground">{{ schema.description }}</p>
59
- </div>
60
-
61
- <div class="space-y-4">
62
- <template v-for="field in schema.fields" :key="field.id">
63
- <FormFieldRenderer
64
- v-if="!field.hidden"
65
- :field="field"
66
- :model-value="values[field.name]"
67
- :error="errors[field.name]"
68
- @update:model-value="(val: any) => handleFieldChange(field.name, val)"
69
- />
70
- </template>
71
- </div>
72
-
73
- <button
74
- type="submit"
75
- :disabled="isSubmitting"
76
- class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-primary text-primary-foreground hover:bg-primary/90 h-10 px-4 py-2 w-full"
77
- >
78
- {{ isSubmitting ? 'Submitting...' : (schema.submitButtonText || 'Submit') }}
79
- </button>
80
- </form>
81
- </template>
@@ -1,70 +0,0 @@
1
- <script setup lang="ts">
2
- import type { FormField } from 'pdyform/core';
3
- import type { Component } from 'vue';
4
- import { computed } from 'vue';
5
- import { defaultComponentMap, type FieldComponentMap } from './fieldComponentMap';
6
- import Label from './components/Label.vue';
7
- import InputRenderer from './components/InputRenderer.vue';
8
-
9
- const props = defineProps<{
10
- field: FormField;
11
- modelValue: any;
12
- error?: string;
13
- /**
14
- * Custom component map.
15
- * Entries here are merged with the default map, so you can override
16
- * specific types or add entirely new ones.
17
- *
18
- * @example
19
- * ```ts
20
- * import { defaultComponentMap } from 'pdyform-vue';
21
- * const myMap = {
22
- * ...defaultComponentMap,
23
- * text: MyCustomInput, // overrides built-in text input
24
- * rating: StarRatingField, // adds a new field type
25
- * };
26
- * ```
27
- */
28
- componentMap?: FieldComponentMap;
29
- }>();
30
-
31
- const emit = defineEmits(['update:modelValue']);
32
-
33
- const fieldId = computed(() => `field-${props.field.name}`);
34
-
35
- // Merge external map over defaults — external wins
36
- const resolvedMap = computed<FieldComponentMap>(() =>
37
- props.componentMap
38
- ? { ...defaultComponentMap, ...props.componentMap }
39
- : defaultComponentMap
40
- );
41
-
42
- // Resolve a component or fall back to InputRenderer
43
- const ResolvedFieldComponent = computed<Component>(
44
- () => resolvedMap.value[props.field.type] ?? InputRenderer
45
- );
46
- </script>
47
-
48
- <template>
49
- <div :class="['space-y-2', field.className]">
50
- <Label v-if="field.label" :for="fieldId">
51
- {{ field.label }}
52
- </Label>
53
-
54
- <!-- All field rendering is delegated to the resolved component -->
55
- <component
56
- :is="ResolvedFieldComponent"
57
- :field="field"
58
- :fieldId="fieldId"
59
- :modelValue="modelValue"
60
- @update:modelValue="emit('update:modelValue', $event)"
61
- />
62
-
63
- <p v-if="field.description" class="text-[0.8rem] text-muted-foreground">
64
- {{ field.description }}
65
- </p>
66
- <p v-if="error" class="text-[0.8rem] font-medium text-destructive">
67
- {{ error }}
68
- </p>
69
- </div>
70
- </template>
@@ -1,28 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import { CheckboxIndicator, CheckboxRoot, type CheckboxRootEmits, type CheckboxRootProps, useForwardPropsEmits } from 'radix-vue'
4
- import { Check } from 'lucide-vue-next'
5
- import { cn } from '../utils'
6
-
7
- const props = defineProps<CheckboxRootProps & { class?: any }>()
8
- const emits = defineEmits<CheckboxRootEmits & { blur: [] }>()
9
-
10
- const delegatedProps = computed(() => {
11
- const { class: _, ...delegated } = props
12
- return delegated
13
- })
14
-
15
- const forwarded = useForwardPropsEmits(delegatedProps, emits)
16
- </script>
17
-
18
- <template>
19
- <CheckboxRoot
20
- v-bind="forwarded"
21
- :class="cn('peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground', props.class)"
22
- @blur="emits('blur')"
23
- >
24
- <CheckboxIndicator class="flex h-full w-full items-center justify-center text-current">
25
- <Check class="h-4 w-4" />
26
- </CheckboxIndicator>
27
- </CheckboxRoot>
28
- </template>
@@ -1,35 +0,0 @@
1
- <script setup lang="ts">
2
- import type { FieldRendererProps } from '../fieldComponentMap';
3
- import Checkbox from '../components/Checkbox.vue';
4
- import Label from '../components/Label.vue';
5
-
6
- const props = defineProps<FieldRendererProps>();
7
- const emit = defineEmits<{ 'update:modelValue': [value: any] }>();
8
-
9
- const handleChange = (optValue: any, checked: boolean) => {
10
- const current = Array.isArray(props.modelValue) ? [...props.modelValue] : [];
11
- if (checked) {
12
- current.push(optValue);
13
- } else {
14
- const idx = current.indexOf(optValue);
15
- if (idx > -1) current.splice(idx, 1);
16
- }
17
- emit('update:modelValue', current);
18
- };
19
- </script>
20
-
21
- <template>
22
- <div class="flex flex-wrap gap-4">
23
- <div v-for="opt in field.options" :key="opt.value" class="flex items-center space-x-2">
24
- <Checkbox
25
- :id="`checkbox-${field.name}-${opt.value}`"
26
- :disabled="field.disabled"
27
- :checked="Array.isArray(modelValue) && modelValue.includes(opt.value)"
28
- @update:checked="(checked) => handleChange(opt.value, !!checked)"
29
- />
30
- <Label :for="`checkbox-${field.name}-${opt.value}`" class="font-normal">
31
- {{ opt.label }}
32
- </Label>
33
- </div>
34
- </div>
35
- </template>
@@ -1,21 +0,0 @@
1
- <script setup lang="ts">
2
- import { cn } from '../utils'
3
-
4
- const props = defineProps<{
5
- class?: any
6
- type?: string
7
- modelValue?: any
8
- }>()
9
-
10
- const emit = defineEmits(['update:modelValue', 'blur'])
11
- </script>
12
-
13
- <template>
14
- <input
15
- :type="type"
16
- :class="cn('flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium 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)"
17
- :value="modelValue"
18
- @input="emit('update:modelValue', ($event.target as HTMLInputElement).value)"
19
- @blur="emit('blur', $event)"
20
- />
21
- </template>
@@ -1,28 +0,0 @@
1
- <script setup lang="ts">
2
- import type { FieldRendererProps } from '../fieldComponentMap';
3
- import Input from '../components/Input.vue';
4
-
5
- const props = defineProps<FieldRendererProps>();
6
- const emit = defineEmits<{ 'update:modelValue': [value: any] }>();
7
-
8
- const handleInput = (nextValue: any) => {
9
- if (props.field.type !== 'number') {
10
- emit('update:modelValue', nextValue);
11
- return;
12
- }
13
-
14
- emit('update:modelValue', nextValue === '' ? '' : Number(nextValue));
15
- };
16
- </script>
17
-
18
- <template>
19
- <Input
20
- :id="fieldId"
21
- :type="field.type"
22
- :placeholder="field.placeholder"
23
- :disabled="field.disabled"
24
- :name="field.name"
25
- :modelValue="modelValue ?? ''"
26
- @update:modelValue="handleInput"
27
- />
28
- </template>
@@ -1,21 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import { Label, type LabelProps } from 'radix-vue'
4
- import { cn } from '../utils'
5
-
6
- const props = defineProps<LabelProps & { class?: any }>()
7
-
8
- const delegatedProps = computed(() => {
9
- const { class: _, ...delegated } = props
10
- return delegated
11
- })
12
- </script>
13
-
14
- <template>
15
- <Label
16
- v-bind="delegatedProps"
17
- :class="cn('text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70', props.class)"
18
- >
19
- <slot />
20
- </Label>
21
- </template>
@@ -1,30 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import { RadioGroupItem, type RadioGroupItemProps, RadioGroupRoot, type RadioGroupRootEmits, type RadioGroupRootProps, useForwardPropsEmits } from 'radix-vue'
4
- import { Circle } from 'lucide-vue-next'
5
- import { cn } from '../utils'
6
-
7
- // Root
8
- const props = defineProps<RadioGroupRootProps & { class?: any }>()
9
- const emits = defineEmits<RadioGroupRootEmits>()
10
-
11
- const delegatedProps = computed(() => {
12
- const { class: _, ...delegated } = props
13
- return delegated
14
- })
15
-
16
- const forwarded = useForwardPropsEmits(delegatedProps, emits)
17
- </script>
18
-
19
- <script lang="ts">
20
- export { default as RadioGroupItem } from './RadioGroupItem.vue'
21
- </script>
22
-
23
- <template>
24
- <RadioGroupRoot
25
- v-bind="forwarded"
26
- :class="cn('grid gap-2', props.class)"
27
- >
28
- <slot />
29
- </RadioGroupRoot>
30
- </template>
@@ -1,26 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import { RadioGroupIndicator, RadioGroupItem, type RadioGroupItemProps, useForwardProps } from 'radix-vue'
4
- import { Circle } from 'lucide-vue-next'
5
- import { cn } from '../utils'
6
-
7
- const props = defineProps<RadioGroupItemProps & { class?: any }>()
8
-
9
- const delegatedProps = computed(() => {
10
- const { class: _, ...delegated } = props
11
- return delegated
12
- })
13
-
14
- const forwardedProps = useForwardProps(delegatedProps)
15
- </script>
16
-
17
- <template>
18
- <RadioGroupItem
19
- v-bind="forwardedProps"
20
- :class="cn('aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', props.class)"
21
- >
22
- <RadioGroupIndicator class="flex items-center justify-center">
23
- <Circle class="h-2.5 w-2.5 fill-current text-current" />
24
- </RadioGroupIndicator>
25
- </RadioGroupItem>
26
- </template>
@@ -1,24 +0,0 @@
1
- <script setup lang="ts">
2
- import type { FieldRendererProps } from '../fieldComponentMap';
3
- import RadioGroup from '../components/RadioGroup.vue';
4
- import RadioGroupItem from '../components/RadioGroupItem.vue';
5
- import Label from '../components/Label.vue';
6
-
7
- const props = defineProps<FieldRendererProps>();
8
- const emit = defineEmits<{ 'update:modelValue': [value: any] }>();
9
- </script>
10
-
11
- <template>
12
- <RadioGroup
13
- class="flex flex-wrap gap-4"
14
- :disabled="field.disabled"
15
- :name="field.name"
16
- :modelValue="modelValue != null ? String(modelValue) : ''"
17
- @update:modelValue="emit('update:modelValue', $event)"
18
- >
19
- <div v-for="opt in field.options" :key="opt.value" class="flex items-center space-x-2">
20
- <RadioGroupItem :id="`radio-${field.name}-${opt.value}`" :value="String(opt.value)" />
21
- <Label :for="`radio-${field.name}-${opt.value}`" class="font-normal">{{ opt.label }}</Label>
22
- </div>
23
- </RadioGroup>
24
- </template>
@@ -1,40 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import {
4
- SelectContent,
5
- SelectGroup,
6
- SelectItem,
7
- SelectItemIndicator,
8
- SelectItemText,
9
- SelectPortal,
10
- SelectRoot,
11
- type SelectRootEmits,
12
- type SelectRootProps,
13
- SelectScrollDownButton,
14
- SelectScrollUpButton,
15
- SelectTrigger,
16
- SelectValue,
17
- SelectViewport,
18
- useForwardPropsEmits,
19
- } from 'radix-vue'
20
- import { Check, ChevronDown, ChevronUp } from 'lucide-vue-next'
21
- import { cn } from '../utils'
22
-
23
- const props = defineProps<SelectRootProps>()
24
- const emits = defineEmits<SelectRootEmits>()
25
-
26
- const forwarded = useForwardPropsEmits(props, emits)
27
- </script>
28
-
29
- <script lang="ts">
30
- export { default as SelectTrigger } from './SelectTrigger.vue'
31
- export { default as SelectContent } from './SelectContent.vue'
32
- export { default as SelectItem } from './SelectItem.vue'
33
- export { SelectValue, SelectGroup } from 'radix-vue'
34
- </script>
35
-
36
- <template>
37
- <SelectRoot v-bind="forwarded">
38
- <slot />
39
- </SelectRoot>
40
- </template>
@@ -1,38 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import {
4
- SelectContent,
5
- type SelectContentProps,
6
- SelectPortal,
7
- SelectViewport,
8
- useForwardProps,
9
- } from 'radix-vue'
10
- import { cn } from '../utils'
11
-
12
- const props = withDefaults(
13
- defineProps<SelectContentProps & { class?: any }>(),
14
- {
15
- position: 'popper',
16
- },
17
- )
18
-
19
- const delegatedProps = computed(() => {
20
- const { class: _, ...delegated } = props
21
- return delegated
22
- })
23
-
24
- const forwardedProps = useForwardProps(delegatedProps)
25
- </script>
26
-
27
- <template>
28
- <SelectPortal>
29
- <SelectContent
30
- v-bind="forwardedProps"
31
- :class="cn('relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', position === 'popper' && 'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1', props.class)"
32
- >
33
- <SelectViewport :class="cn('p-1', position === 'popper' && 'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]')">
34
- <slot />
35
- </SelectViewport>
36
- </SelectContent>
37
- </SelectPortal>
38
- </template>
@@ -1,43 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed } from 'vue'
3
- import {
4
- SelectItem,
5
- SelectItemIndicator,
6
- type SelectItemProps,
7
- SelectItemText,
8
- useForwardProps,
9
- } from 'radix-vue'
10
- import { Check } from 'lucide-vue-next'
11
- import { cn } from '../utils'
12
-
13
- const props = defineProps<SelectItemProps & { class?: any }>()
14
-
15
- const delegatedProps = computed(() => {
16
- const { class: _, ...delegated } = props
17
- return delegated
18
- })
19
-
20
- const forwardedProps = useForwardProps(delegatedProps)
21
- </script>
22
-
23
- <template>
24
- <SelectItem
25
- v-bind="forwardedProps"
26
- :class="
27
- cn(
28
- 'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
29
- props.class,
30
- )
31
- "
32
- >
33
- <span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
34
- <SelectItemIndicator>
35
- <Check class="h-4 w-4" />
36
- </SelectItemIndicator>
37
- </span>
38
-
39
- <SelectItemText>
40
- <slot />
41
- </SelectItemText>
42
- </SelectItem>
43
- </template>
@@ -1,30 +0,0 @@
1
- <script setup lang="ts">
2
- import type { FieldRendererProps } from '../fieldComponentMap';
3
- import Select from '../components/Select.vue';
4
- import SelectTrigger from '../components/SelectTrigger.vue';
5
- import SelectContent from '../components/SelectContent.vue';
6
- import SelectItem from '../components/SelectItem.vue';
7
- import { SelectValue } from 'radix-vue';
8
-
9
-
10
- const props = defineProps<FieldRendererProps>();
11
- const emit = defineEmits<{ 'update:modelValue': [value: any] }>();
12
- </script>
13
-
14
- <template>
15
- <Select
16
- :disabled="field.disabled"
17
- :name="field.name"
18
- :modelValue="modelValue != null ? String(modelValue) : ''"
19
- @update:modelValue="emit('update:modelValue', $event)"
20
- >
21
- <SelectTrigger :id="fieldId">
22
- <SelectValue :placeholder="field.placeholder || 'Select an option'" />
23
- </SelectTrigger>
24
- <SelectContent>
25
- <SelectItem v-for="opt in field.options" :key="opt.value" :value="String(opt.value)">
26
- {{ opt.label }}
27
- </SelectItem>
28
- </SelectContent>
29
- </Select>
30
- </template>
@@ -1,27 +0,0 @@
1
- <script setup lang="ts">
2
- import { SelectIcon, SelectTrigger, type SelectTriggerProps, useForwardProps } from 'radix-vue'
3
- import { ChevronDown } from 'lucide-vue-next'
4
- import { computed } from 'vue'
5
- import { cn } from '../utils'
6
-
7
- const props = defineProps<SelectTriggerProps & { class?: any }>()
8
-
9
- const delegatedProps = computed(() => {
10
- const { class: _, ...delegated } = props
11
- return delegated
12
- })
13
-
14
- const forwardedProps = useForwardProps(delegatedProps)
15
- </script>
16
-
17
- <template>
18
- <SelectTrigger
19
- v-bind="forwardedProps"
20
- :class="cn('flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', props.class)"
21
- >
22
- <slot />
23
- <SelectIcon as-child>
24
- <ChevronDown class="h-4 w-4 opacity-50" />
25
- </SelectIcon>
26
- </SelectTrigger>
27
- </template>
@@ -1,19 +0,0 @@
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>
@@ -1,18 +0,0 @@
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>
@@ -1,24 +0,0 @@
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';
@@ -1,7 +0,0 @@
1
- /// <reference types="vite/client" />
2
-
3
- declare module '*.vue' {
4
- import type { DefineComponent } from 'vue'
5
- const component: DefineComponent<object, object, any>
6
- export default component
7
- }
@@ -1,34 +0,0 @@
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
- };