@ederzeel/nuxt-schema-form-nightly 0.1.0-29041090.dfa7689 → 0.1.0-29072953.6ee0e39

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.
@@ -4,6 +4,7 @@ import convertToYup from 'json-schema-yup-transformer'
4
4
  import type { JsonSchema } from 'json-schema-library'
5
5
  import { computed, ref } from 'vue'
6
6
  import type { Config } from 'json-schema-yup-transformer'
7
+ import type { CustomValidation } from '#schema-form-types'
7
8
 
8
9
  const props = defineProps<{
9
10
  schema: JsonSchema
@@ -19,19 +20,21 @@ async function onSubmit(_event: unknown) {
19
20
  emit('submit', value.value)
20
21
  }
21
22
 
22
- const formValidationSchema = computed(() => convertToYup(props.schema, props?.options?.jsonSchemaYupTransfromer ?? {}))
23
-
24
- export type CustomValidation = {
25
- field: string
26
- message: string
27
- validate(state: any): boolean
28
- }
23
+ const formValidationSchema = computed(() => {
24
+ if (props?.options == null) return {}
25
+ return convertToYup(props.schema, props?.options?.jsonSchemaYupTransfromer ?? {})
26
+ })
29
27
 
30
28
  const validateFields = async (fields: string[]) => {
31
29
  let allValid = true
32
30
  for (const field of fields) {
33
- if (!(await formRef.value.validate(field, { silent: true }))) {
34
- allValid = false
31
+ try {
32
+ if (!(await formRef.value.validate({ name: field, silent: true }))) {
33
+ allValid = false
34
+ }
35
+ } catch (err) {
36
+ console.log(err)
37
+ return false
35
38
  }
36
39
  }
37
40
 
@@ -39,7 +42,7 @@ const validateFields = async (fields: string[]) => {
39
42
  for (const { field, message, validate } of props.options.customValidation) {
40
43
  if (!fields.includes(field)) continue
41
44
  if (!validate(value.value)) {
42
- const errors = [{ path: field, message }]
45
+ const errors = [{ field, message }]
43
46
  formRef.value.setErrors(errors, field)
44
47
  allValid = false
45
48
  }
@@ -173,14 +173,14 @@ const options = computed(() => {
173
173
  @click="add"
174
174
  icon="i-heroicons-plus"
175
175
  trailing
176
- color="gray"
176
+ color="neutral"
177
177
  size="xs"
178
178
  />
179
179
  </div>
180
180
  <div class="flex gap-1.5 items-center">
181
- <UDropdown v-if="selectedRows.length > 0" :items="massActions">
182
- <UButton icon="i-heroicons-chevron-down" trailing color="gray" size="xs"> Action </UButton>
183
- </UDropdown>
181
+ <UDropdownMenu v-if="selectedRows.length > 0" :items="massActions">
182
+ <UButton icon="i-heroicons-chevron-down" trailing color="neutral" size="xs"> Action </UButton>
183
+ </UDropdownMenu>
184
184
  </div>
185
185
  </div>
186
186
  <UTable v-bind="options" by="__id" :rows="values" :columns="columns">
@@ -206,13 +206,13 @@ const options = computed(() => {
206
206
  </template>
207
207
 
208
208
  <template #actions-data="{ index }">
209
- <UDropdown :items="actions(index)">
210
- <UButton color="gray" variant="ghost" icon="i-heroicons-ellipsis-horizontal-20-solid" />
211
- </UDropdown>
209
+ <UDropdownMenu :items="actions(index)">
210
+ <UButton color="neutral" variant="ghost" icon="i-heroicons-ellipsis-horizontal-20-solid" />
211
+ </UDropdownMenu>
212
212
  </template>
213
213
  </UTable>
214
214
  </div>
215
- <UModal v-model="model.open">
215
+ <UModal v-model:open="model.open">
216
216
  <UCard>
217
217
  <SComponent
218
218
  :id="id.length <= 0 ? `${model.index}` : `${id}[0].${items.id}`"
@@ -27,7 +27,7 @@ export type SComponentProps = {
27
27
  }
28
28
 
29
29
  const props = withDefaults(defineProps<SComponentProps>(), { id: '', jsonSchemaPath: '' })
30
- const value = defineModel<unknown>({ required: true, default: '' })
30
+ const value = defineModel<unknown>({ required: true })
31
31
  const emit = defineEmits(['submit'])
32
32
 
33
33
  const options = computed(() => ({
@@ -41,15 +41,12 @@ const onSubmit = () => {
41
41
 
42
42
  <template>
43
43
  <div class="s-form-group">
44
- <component
45
- v-if="renderer"
46
- v-bind="options"
47
- v-model="value"
48
- :is="typeof renderer === 'string' ? renderer : undefined"
49
- @submit="onSubmit"
50
- />
44
+ <template v-if="renderer != null && renderer === 'none'">test</template>
45
+ <component v-else-if="renderer" v-bind="options" v-model="value"
46
+ :is="typeof renderer === 'string' ? renderer : undefined" @submit="onSubmit" />
51
47
 
52
48
  <SDate v-else-if="type === 'string' && format === 'full-date'" v-bind="options" v-model="value" />
49
+ <SInputNumber v-else-if="type === 'number' || type === 'integer'" v-bind="options" v-model="value" />
53
50
  <SInputField v-else-if="type === 'string'" v-bind="options" v-model="value" />
54
51
  <SToggle v-else-if="type === 'boolean'" v-bind="options" v-model="value" />
55
52
  <SObject v-else-if="type === 'object'" v-bind="options" v-model="value" @submit="onSubmit" />
@@ -1,7 +1,6 @@
1
1
  <script lang="ts" setup>
2
- import { format } from 'date-fns'
3
2
  import { ref, watch } from 'vue'
4
- import DatePicker from './DatePicker.vue'
3
+ import { CalendarDate, DateFormatter, getLocalTimeZone } from '@internationalized/date'
5
4
 
6
5
  const props = defineProps<{
7
6
  id: string
@@ -11,28 +10,34 @@ const props = defineProps<{
11
10
  isRequired: boolean
12
11
  }>()
13
12
 
13
+ const df = new DateFormatter('nl-NL', { dateStyle: 'medium' })
14
+
14
15
  const value = defineModel<string>({ required: true })
15
- const date = ref(new Date(value.value))
16
+ const date = ref(new CalendarDate(2000, 1, 1))
17
+
16
18
  watch(date, () => {
17
- value.value = date.value.toISOString()
19
+ value.value = date.value.toDate(getLocalTimeZone()).toISOString()
18
20
  })
21
+ const open = ref(false)
19
22
  </script>
20
23
 
21
24
  <template>
22
25
  <div>
23
- <UFormGroup
26
+ <UFormField
24
27
  :label="props.title || id"
25
28
  :hint="!props.isRequired ? 'optional' : undefined"
26
29
  :description="props.description"
27
30
  :name="props.id"
28
31
  >
29
- <UPopover :popper="{ placement: 'bottom-start' }">
30
- <UButton icon="i-heroicons-calendar-days-20-solid" :label="format(date, 'd MMM, yyy')" />
32
+ <UPopover :open="open">
33
+ <UButton color="neutral" variant="subtle" icon="i-lucide-calendar" class="w-full" @click="() => (open = true)">
34
+ {{ value ? df.format(date.toDate(getLocalTimeZone())) : 'Select a date' }}
35
+ </UButton>
31
36
 
32
- <template #panel="{ close }">
33
- <DatePicker v-model="date" is-required @close="close" />
37
+ <template #content>
38
+ <UCalendar v-model="date" class="p-2" @update:modelValue="() => (open = false)" />
34
39
  </template>
35
40
  </UPopover>
36
- </UFormGroup>
41
+ </UFormField>
37
42
  </div>
38
43
  </template>
@@ -7,18 +7,18 @@ const props = defineProps<{
7
7
  isRequired: boolean
8
8
  }>()
9
9
 
10
- const value = defineModel<string | number>({ required: true })
10
+ const value = defineModel<string>({ required: true, default: '' })
11
11
  </script>
12
12
 
13
13
  <template>
14
14
  <div>
15
- <UFormGroup
15
+ <UFormField
16
16
  :label="props.title || id"
17
17
  :hint="!props.isRequired ? 'optional' : undefined"
18
18
  :description="props.description"
19
19
  :name="props.id"
20
20
  >
21
- <UInput v-model="value" :type="props.type" />
22
- </UFormGroup>
21
+ <UInput v-model="value" :type="props.type" class="w-full" />
22
+ </UFormField>
23
23
  </div>
24
24
  </template>
@@ -0,0 +1,23 @@
1
+ <script lang="ts" setup>
2
+ const props = defineProps<{
3
+ id: string
4
+ title?: string
5
+ description?: string
6
+ type: string
7
+ isRequired: boolean
8
+ }>()
9
+
10
+ const value = defineModel<number>({ required: true, default: 0 })
11
+ </script>
12
+
13
+ <template>
14
+ <div>
15
+ <UFormField :label="props.title || id" :hint="!props.isRequired ? 'optional' : undefined"
16
+ :description="props.description" :name="props.id">
17
+ <UInputNumber v-model="value" class="w-full" :step="0.01" orientation="vertical"
18
+ :stepSnapping="props.type === 'number'" :format-options="{
19
+ minimumFractionDigits: 1
20
+ }" />
21
+ </UFormField>
22
+ </div>
23
+ </template>
@@ -10,14 +10,14 @@ const props = defineProps<{
10
10
  isRequired: boolean
11
11
  }>()
12
12
 
13
- const options = computed(() => props.enum.map((x, i) => ({ key: props?.enum_titles?.[i] ?? x, value: x })))
13
+ const options = computed(() => props.enum.map((x, i) => ({ label: props?.enum_titles?.[i] ?? x, value: x })))
14
14
 
15
15
  const value = defineModel<string>({ required: true })
16
16
  </script>
17
17
 
18
18
  <template>
19
19
  <div>
20
- <UFormGroup
20
+ <UFormField
21
21
  :label="props.title || id"
22
22
  :hint="!props.isRequired ? 'optional' : undefined"
23
23
  :description="props.description"
@@ -26,10 +26,11 @@ const value = defineModel<string>({ required: true })
26
26
  <USelect
27
27
  v-model="value"
28
28
  placeholder="select size"
29
- :options="options"
29
+ :items="options"
30
30
  value-attribute="value"
31
31
  option-attribute="key"
32
+ class="w-full"
32
33
  />
33
- </UFormGroup>
34
+ </UFormField>
34
35
  </div>
35
36
  </template>
@@ -11,13 +11,13 @@ const value = defineModel<string | number>({ required: true })
11
11
 
12
12
  <template>
13
13
  <div>
14
- <UFormGroup
14
+ <UFormField
15
15
  :label="props.title || id"
16
16
  :hint="!props.isRequired ? 'optional' : undefined"
17
17
  :description="props.description"
18
18
  :name="props.id"
19
19
  >
20
- <UTextarea v-model="value" />
21
- </UFormGroup>
20
+ <UTextarea v-model="value" class="w-full" />
21
+ </UFormField>
22
22
  </div>
23
23
  </template>
@@ -12,13 +12,13 @@ const value = defineModel<boolean>({ required: true })
12
12
 
13
13
  <template>
14
14
  <div>
15
- <UFormGroup
15
+ <UFormField
16
16
  :label="props.title || id"
17
17
  :hint="!props.isRequired ? 'optional' : undefined"
18
18
  :description="props.description"
19
19
  :name="props.id"
20
20
  >
21
- <UToggle v-model="value" />
22
- </UFormGroup>
21
+ <USwitch v-model="value" />
22
+ </UFormField>
23
23
  </div>
24
24
  </template>
@@ -0,0 +1,5 @@
1
+ export type CustomValidation = {
2
+ field: string;
3
+ message: string;
4
+ validate(state: any): boolean;
5
+ };
File without changes
@@ -0,0 +1,10 @@
1
+ export declare function pick<Data extends object, Keys extends keyof Data>(data: Data, keys: Keys[]): Pick<Data, Keys>;
2
+ export declare function omit<Data extends object, Keys extends keyof Data>(data: Data, keys: Keys[]): Omit<Data, Keys>;
3
+ export declare function get<T>(object: NestedObject | undefined, path: (string | number)[] | string, defaultValue?: T): T | undefined;
4
+ type NestedObject = {
5
+ [key: string]: any;
6
+ };
7
+ export declare function set(object: NestedObject, path: (string | number)[] | string, value: unknown): void;
8
+ export declare function looseToNumber(val: any): any;
9
+ export declare function compare<T>(value?: T, currentValue?: T, comparator?: string | ((a: T, b: T) => boolean)): boolean;
10
+ export {};
@@ -0,0 +1,74 @@
1
+ import { isEqual } from "ohash/utils";
2
+ export function pick(data, keys) {
3
+ const result = {};
4
+ for (const key of keys) {
5
+ result[key] = data[key];
6
+ }
7
+ return result;
8
+ }
9
+ export function omit(data, keys) {
10
+ const result = { ...data };
11
+ for (const key of keys) {
12
+ delete result[key];
13
+ }
14
+ return result;
15
+ }
16
+ export function get(object, path, defaultValue) {
17
+ if (typeof path === "string") {
18
+ path = path.split(".").map((key) => {
19
+ const numKey = Number(key);
20
+ return Number.isNaN(numKey) ? key : numKey;
21
+ });
22
+ }
23
+ let result = object;
24
+ for (const key of path) {
25
+ if (result === void 0 || result === null) {
26
+ return defaultValue;
27
+ }
28
+ if (typeof key === "string" && !(key in result)) {
29
+ return defaultValue;
30
+ }
31
+ result = result[key];
32
+ }
33
+ return result !== void 0 ? result : defaultValue;
34
+ }
35
+ export function set(object, path, value) {
36
+ if (typeof path === "string") {
37
+ path = path.split(".").map((key) => {
38
+ const numKey = Number(key);
39
+ return Number.isNaN(numKey) ? key : numKey;
40
+ });
41
+ }
42
+ const keys = path;
43
+ keys.reduce((acc, key, i) => {
44
+ if (acc[key] === void 0) {
45
+ acc[key] = isLastKey(i, keys) ? value : {};
46
+ } else if (i === keys.length - 1) {
47
+ acc[key] = value;
48
+ }
49
+ return acc[key];
50
+ }, object);
51
+ }
52
+ function isLastKey(index, keys) {
53
+ return index === keys.length - 1;
54
+ }
55
+ export function looseToNumber(val) {
56
+ if (typeof val !== "string") return val;
57
+ const n = Number.parseFloat(val);
58
+ return Number.isNaN(n) ? val : n;
59
+ }
60
+ export function compare(value, currentValue, comparator) {
61
+ if (value === void 0 || currentValue === void 0) {
62
+ return false;
63
+ }
64
+ if (typeof value === "string") {
65
+ return value === currentValue;
66
+ }
67
+ if (typeof comparator === "function") {
68
+ return comparator(value, currentValue);
69
+ }
70
+ if (typeof comparator === "string") {
71
+ return get(value, comparator) === get(currentValue, comparator);
72
+ }
73
+ return isEqual(value, currentValue);
74
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ederzeel/nuxt-schema-form-nightly",
3
- "version": "0.1.0-29041090.dfa7689",
3
+ "version": "0.1.0-29072953.6ee0e39",
4
4
  "description": "A runtime form generator for nuxt",
5
5
  "type": "module",
6
6
  "exports": {
@@ -8,6 +8,10 @@
8
8
  "types": "./dist/module.d.ts",
9
9
  "import": "./dist/module.mjs",
10
10
  "require": "./dist/module.cjs"
11
+ },
12
+ "./utils/*": {
13
+ "types": "./dist/runtime/utils/*.d.ts",
14
+ "import": "./dist/runtime/utils/*.js"
11
15
  }
12
16
  },
13
17
  "main": "./dist/module.mjs",
@@ -20,6 +24,7 @@
20
24
  "dev": "nuxi dev playground",
21
25
  "dev:build": "nuxi build playground",
22
26
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
27
+ "docs:dev": "nuxi dev docs",
23
28
  "test": "vitest test",
24
29
  "lint": "eslint .",
25
30
  "release": "bumpp --commit \"release: v%s\" --push --tag"
@@ -46,7 +51,7 @@
46
51
  "@nuxt/eslint-config": "^1.0.0",
47
52
  "@nuxt/kit": "^3.15.4",
48
53
  "@nuxt/module-builder": "^0.8.4",
49
- "@nuxt/ui": "^2.21.0",
54
+ "@nuxt/ui": "^3.0.0",
50
55
  "@types/eslint": "^9.6.1",
51
56
  "eslint": "^9.19.0",
52
57
  "eslint-config-prettier": "^10.0.1",
@@ -56,8 +61,9 @@
56
61
  "json-schema-yup-transformer": "^1.6.12",
57
62
  "magic-string": "^0.30.17",
58
63
  "mlly": "^1.7.4",
59
- "nuxt": "^3.15.4",
64
+ "nuxt": "^3.16.0",
60
65
  "nuxt-component-meta": "^0.10.0",
66
+ "ohash": "^2.0.11",
61
67
  "pathe": "^2.0.2",
62
68
  "prettier": "^3.4.2",
63
69
  "tinyglobby": "^0.2.10",
@@ -69,8 +75,7 @@
69
75
  "yup": "^1.6.1"
70
76
  },
71
77
  "dependencies": {
72
- "date-fns": "^4.1.0",
73
- "v-calendar": "^3.1.2"
78
+ "@internationalized/date": "^3.7.0"
74
79
  },
75
80
  "resolutions": {
76
81
  "@ederzeel/nuxt-schema-form": "workspace:*"
@@ -1,56 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed, type PropType } from 'vue'
3
- import { DatePicker as VCalendarDatePicker } from 'v-calendar'
4
- // @ts-ignore
5
- import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker'
6
- import 'v-calendar/dist/style.css'
7
-
8
- defineOptions({
9
- inheritAttrs: false
10
- })
11
-
12
- const props = defineProps({
13
- modelValue: {
14
- type: [Date, Object] as PropType<DatePickerDate | DatePickerRangeObject | null>,
15
- default: null
16
- }
17
- })
18
-
19
- const emit = defineEmits(['update:model-value', 'close'])
20
-
21
- const date = computed({
22
- get: () => props.modelValue,
23
- set: value => {
24
- emit('update:model-value', value)
25
- emit('close')
26
- }
27
- })
28
-
29
- const attrs = {
30
- transparent: true,
31
- borderless: true,
32
- color: 'primary',
33
- 'is-dark': { selector: 'html', darkClass: 'dark' },
34
- 'first-day-of-week': 2
35
- }
36
-
37
- function onDayClick(_: any, event: MouseEvent): void {
38
- const target = event.target as HTMLElement
39
- target.blur()
40
- }
41
- </script>
42
-
43
- <template>
44
- <VCalendarDatePicker
45
- v-if="date && (date as DatePickerRangeObject)?.start && (date as DatePickerRangeObject)?.end"
46
- v-model.range="date"
47
- :columns="2"
48
- v-bind="{ ...attrs, ...$attrs }"
49
- @dayclick="onDayClick"
50
- />
51
- <VCalendarDatePicker v-else v-model="date" v-bind="{ ...attrs, ...$attrs }" @dayclick="onDayClick" />
52
- </template>
53
-
54
- <style>
55
- :root{--vc-gray-50:rgb(var(--color-gray-50));--vc-gray-100:rgb(var(--color-gray-100));--vc-gray-200:rgb(var(--color-gray-200));--vc-gray-300:rgb(var(--color-gray-300));--vc-gray-400:rgb(var(--color-gray-400));--vc-gray-500:rgb(var(--color-gray-500));--vc-gray-600:rgb(var(--color-gray-600));--vc-gray-700:rgb(var(--color-gray-700));--vc-gray-800:rgb(var(--color-gray-800));--vc-gray-900:rgb(var(--color-gray-900))}.vc-primary{--vc-accent-50:rgb(var(--color-primary-50));--vc-accent-100:rgb(var(--color-primary-100));--vc-accent-200:rgb(var(--color-primary-200));--vc-accent-300:rgb(var(--color-primary-300));--vc-accent-400:rgb(var(--color-primary-400));--vc-accent-500:rgb(var(--color-primary-500));--vc-accent-600:rgb(var(--color-primary-600));--vc-accent-700:rgb(var(--color-primary-700));--vc-accent-800:rgb(var(--color-primary-800));--vc-accent-900:rgb(var(--color-primary-900))}
56
- </style>