@gravitee/graphene-core 2.16.0 → 2.17.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 (40) hide show
  1. package/dist/__stories__/fixtures/index.d.ts +1 -1
  2. package/dist/__stories__/fixtures/index.d.ts.map +1 -1
  3. package/dist/__stories__/fixtures/json-schema-form/array.fixture.d.ts +18 -0
  4. package/dist/__stories__/fixtures/json-schema-form/array.fixture.d.ts.map +1 -0
  5. package/dist/__stories__/fixtures/json-schema-form/index.d.ts +1 -0
  6. package/dist/__stories__/fixtures/json-schema-form/index.d.ts.map +1 -1
  7. package/dist/composed/JsonSchemaForm/SchemaField.d.ts.map +1 -1
  8. package/dist/composed/JsonSchemaForm/fields/__test-utils__/setupJsonSchemaForm.d.ts.map +1 -1
  9. package/dist/composed/JsonSchemaForm/fields/array/ArrayField.d.ts +9 -0
  10. package/dist/composed/JsonSchemaForm/fields/array/ArrayField.d.ts.map +1 -0
  11. package/dist/composed/JsonSchemaForm/fields/array/HeadersArrayField.d.ts +8 -0
  12. package/dist/composed/JsonSchemaForm/fields/array/HeadersArrayField.d.ts.map +1 -0
  13. package/dist/composed/JsonSchemaForm/fields/array/buildDefaultForType.d.ts +4 -0
  14. package/dist/composed/JsonSchemaForm/fields/array/buildDefaultForType.d.ts.map +1 -0
  15. package/dist/composed/JsonSchemaForm/fields/array/use-array-field.d.ts +14 -0
  16. package/dist/composed/JsonSchemaForm/fields/array/use-array-field.d.ts.map +1 -0
  17. package/dist/composed/JsonSchemaForm/form-bindings/ajv-messages.d.ts.map +1 -0
  18. package/dist/composed/JsonSchemaForm/form-bindings/composeResolvers.d.ts +4 -0
  19. package/dist/composed/JsonSchemaForm/form-bindings/composeResolvers.d.ts.map +1 -0
  20. package/dist/composed/JsonSchemaForm/form-bindings/extractDefaults.d.ts.map +1 -0
  21. package/dist/composed/JsonSchemaForm/form-bindings/jsonSchemaResolver.d.ts +6 -0
  22. package/dist/composed/JsonSchemaForm/form-bindings/jsonSchemaResolver.d.ts.map +1 -0
  23. package/dist/composed/JsonSchemaForm/index.d.ts +4 -2
  24. package/dist/composed/JsonSchemaForm/index.d.ts.map +1 -1
  25. package/dist/composed/JsonSchemaForm/models/jsonSchemaResolver.types.d.ts +5 -0
  26. package/dist/composed/JsonSchemaForm/models/jsonSchemaResolver.types.d.ts.map +1 -0
  27. package/dist/composed/JsonSchemaForm/utils/liftRequired.d.ts.map +1 -1
  28. package/dist/composed/JsonSchemaForm/utils/schemaShape.d.ts +2 -1
  29. package/dist/composed/JsonSchemaForm/utils/schemaShape.d.ts.map +1 -1
  30. package/dist/index.js +6624 -6025
  31. package/dist/styles/globals.css +1 -1
  32. package/package.json +1 -1
  33. package/snippets/json-schema-form-simple.tsx +53 -0
  34. package/snippets/json-schema-form-with-meta.tsx +97 -0
  35. package/dist/composed/JsonSchemaForm/utils/ajv-messages.d.ts.map +0 -1
  36. package/dist/composed/JsonSchemaForm/utils/extractDefaults.d.ts.map +0 -1
  37. package/dist/composed/JsonSchemaForm/utils/jsonSchemaResolver.d.ts +0 -5
  38. package/dist/composed/JsonSchemaForm/utils/jsonSchemaResolver.d.ts.map +0 -1
  39. /package/dist/composed/JsonSchemaForm/{utils → form-bindings}/ajv-messages.d.ts +0 -0
  40. /package/dist/composed/JsonSchemaForm/{utils → form-bindings}/extractDefaults.d.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravitee/graphene-core",
3
- "version": "2.16.0",
3
+ "version": "2.17.0",
4
4
  "type": "module",
5
5
  "description": "Gravitee's Graphene design system: accessible React components, design tokens, icons, and shared ESLint/TypeScript configs. Built on shadcn/ui and Tailwind.",
6
6
  "keywords": [
@@ -0,0 +1,53 @@
1
+ // Snippet: Render a plugin JSON Schema in a single useForm
2
+ //
3
+ // Use when a host module receives a JSON Schema (from a Gravitee plugin or
4
+ // API definition) and the form has **no fields besides those declared in the
5
+ // schema**. One useForm, one resolver, one submit handler.
6
+ // Do NOT use for hand-coded forms — write the fields directly with Graphene
7
+ // primitives (Field, Input, Select…) instead.
8
+ // Do NOT use when the form has host-owned meta fields (name, description,
9
+ // etc.) alongside the schema — see snippets/json-schema-form-with-meta.tsx.
10
+ //
11
+ // Replace {PLACEHOLDERS} with your actual values.
12
+ // See Storybook "Composed/JsonSchemaForm → Playground" for an interactive demo.
13
+
14
+ import { useMemo } from 'react';
15
+ import { useForm } from 'react-hook-form';
16
+ import { Button, extractDefaults, JsonSchemaForm, jsonSchemaResolver } from '@gravitee/graphene-core';
17
+ import type { JsonSchema } from '@gravitee/graphene-core';
18
+
19
+ interface PluginConfigPageProps {
20
+ // Immutable: passing a new reference re-builds the form and recompiles ajv.
21
+ readonly pluginSchema: JsonSchema;
22
+
23
+ // Pass a stable reference (e.g. from a TanStack Query / SWR cache, or wrap with `useMemo`
24
+ // at the call site). A fresh object on every parent render defeats the `defaultValues`
25
+ // memo and re-seeds the form, wiping in-progress user edits.
26
+ readonly initialValue?: Record<string, unknown>;
27
+ readonly onSave: (data: Record<string, unknown>) => void;
28
+ }
29
+
30
+ export function PluginConfigPage({ pluginSchema, initialValue, onSave }: PluginConfigPageProps) {
31
+ // Memoize so `jsonSchemaResolver` does not recompile ajv on every parent render.
32
+ const resolver = useMemo(() => jsonSchemaResolver(pluginSchema), [pluginSchema]);
33
+ const defaultValues = useMemo(
34
+ () => initialValue ?? (extractDefaults(pluginSchema) as Record<string, unknown>) ?? {},
35
+ [pluginSchema, initialValue],
36
+ );
37
+
38
+ const form = useForm({
39
+ resolver,
40
+ defaultValues,
41
+ criteriaMode: 'all', // surface every failing ajv keyword per field (FieldError renders them as a list)
42
+ mode: 'onTouched', // validate on first blur, then on every change
43
+ });
44
+
45
+ // `noValidate` disables the browser's HTML5 validation popups so the resolver +
46
+ // <FieldError> remain the single source of validation messages.
47
+ return (
48
+ <form noValidate onSubmit={form.handleSubmit(onSave)} className="flex flex-1 flex-col gap-4 p-8">
49
+ <JsonSchemaForm schema={pluginSchema} control={form.control} name="" />
50
+ <Button type="submit">Save</Button>
51
+ </form>
52
+ );
53
+ }
@@ -0,0 +1,97 @@
1
+ // Snippet: Mix host-owned meta fields with a plugin JSON Schema
2
+ //
3
+ // Use when a host module renders a plugin config (immutable JSON Schema from
4
+ // the backend) alongside host-owned meta fields (name, description, or any
5
+ // extra logic validated by your favourite schema lib).
6
+ // One useForm shared across both — `composeResolvers` merges Zod + ajv
7
+ // errors so RHF surfaces them on the right inputs.
8
+ // Do NOT use for the simple case (no meta) — see snippets/json-schema-form-simple.tsx.
9
+ // Do NOT install Zod just for this — any RHF-compatible resolver works:
10
+ // `yupResolver`, `joiResolver`, `valibotResolver`, or a hand-written
11
+ // `Resolver<T>`. Only the first argument to `composeResolvers` changes.
12
+ //
13
+ // Replace {PLACEHOLDERS} with your actual values.
14
+ // See Storybook "Composed/JsonSchemaForm → With external (hand-coded) fields".
15
+
16
+ import { zodResolver } from '@hookform/resolvers/zod';
17
+ import { useMemo } from 'react';
18
+ import { type Control, type Resolver, useForm } from 'react-hook-form';
19
+ import { z } from 'zod';
20
+ import type { JsonSchema } from '@gravitee/graphene-core';
21
+ import {
22
+ Button,
23
+ composeResolvers,
24
+ extractDefaults,
25
+ Field,
26
+ FieldError,
27
+ FieldLabel,
28
+ Input,
29
+ JsonSchemaForm,
30
+ jsonSchemaResolver,
31
+ } from '@gravitee/graphene-core';
32
+
33
+ // Host-owned meta — extend with z.union / z.refine / async checks as needed.
34
+ const metaSchema = z.object({
35
+ name: z.string().min(1, 'Name is required'),
36
+ });
37
+
38
+ type FormValues = z.infer<typeof metaSchema> & { config: Record<string, unknown> };
39
+
40
+ interface PluginConfigPageProps {
41
+ readonly pluginSchema: JsonSchema;
42
+ readonly initialValue?: Partial<FormValues>;
43
+ readonly onSave: (data: FormValues) => void;
44
+ }
45
+
46
+ export function PluginConfigPage({ pluginSchema, initialValue, onSave }: PluginConfigPageProps) {
47
+ // `basePath: 'config'` must match the `name` prop on <JsonSchemaForm> below.
48
+ // Cast widens zodResolver to the composite values shape — each inner resolver reads
49
+ // only its own slice of `values` at runtime, so the cast is sound.
50
+ const resolver = useMemo(
51
+ () =>
52
+ composeResolvers<FormValues>(
53
+ zodResolver(metaSchema) as unknown as Resolver<FormValues>,
54
+ jsonSchemaResolver<FormValues>(pluginSchema, { basePath: 'config' }),
55
+ ),
56
+ [pluginSchema],
57
+ );
58
+
59
+ // Defaults: schema defaults seed `config`, then saved values override per key. Spread
60
+ // `initialValue` at the top level for meta; explicit merge on `config` so saved-but-partial
61
+ // configs do NOT wipe schema defaults for fields the user never touched (or that the schema
62
+ // added in a newer plugin version). For deeply nested schemas, swap `Object.assign` for a
63
+ // recursive merge (e.g. lodash.merge).
64
+ const schemaDefaults = useMemo(
65
+ () => (extractDefaults(pluginSchema) as Record<string, unknown>) ?? {},
66
+ [pluginSchema],
67
+ );
68
+
69
+ const form = useForm<FormValues>({
70
+ resolver,
71
+ mode: 'onTouched',
72
+ criteriaMode: 'all',
73
+ defaultValues: {
74
+ name: '',
75
+ ...initialValue,
76
+ config: { ...schemaDefaults, ...(initialValue?.config ?? {}) },
77
+ },
78
+ });
79
+ const { name: nameError } = form.formState.errors;
80
+
81
+ return (
82
+ <form noValidate onSubmit={form.handleSubmit(onSave)} className="flex flex-1 flex-col gap-4 p-8">
83
+ {/* Host meta — validated by Zod. Duplicate this block for `description`, etc. */}
84
+ <Field data-invalid={!!nameError}>
85
+ <FieldLabel htmlFor="name">Name</FieldLabel>
86
+ <Input id="name" {...form.register('name')} aria-invalid={!!nameError} />
87
+ {nameError && <FieldError errors={[nameError]} />}
88
+ </Field>
89
+
90
+ {/* Plugin sub-tree — fields registered under `values.config.*`. JsonSchemaForm is typed
91
+ against the generic RHF FieldValues; cast widens the narrow composite control. */}
92
+ <JsonSchemaForm schema={pluginSchema} control={form.control as unknown as Control} name="config" />
93
+
94
+ <Button type="submit">Save</Button>
95
+ </form>
96
+ );
97
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"ajv-messages.d.ts","sourceRoot":"","sources":["../../../../src/composed/JsonSchemaForm/utils/ajv-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAyBvC,iBAAS,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG9D;AAOD,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"extractDefaults.d.ts","sourceRoot":"","sources":["../../../../src/composed/JsonSchemaForm/utils/extractDefaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAG9D,iBAAS,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAWpD;AA2BD,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -1,5 +0,0 @@
1
- import { Resolver } from 'react-hook-form';
2
- import { JsonSchema } from '../models/json-schema.types';
3
- declare function jsonSchemaResolver<TFieldValues extends Record<string, unknown> = Record<string, unknown>>(schema: JsonSchema): Resolver<TFieldValues>;
4
- export { jsonSchemaResolver };
5
- //# sourceMappingURL=jsonSchemaResolver.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jsonSchemaResolver.d.ts","sourceRoot":"","sources":["../../../../src/composed/JsonSchemaForm/utils/jsonSchemaResolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA2B,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAO9D,iBAAS,kBAAkB,CAAC,YAAY,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChG,MAAM,EAAE,UAAU,GACjB,QAAQ,CAAC,YAAY,CAAC,CA4BxB;AA6GD,OAAO,EAAE,kBAAkB,EAAE,CAAC"}