@pixpilot/formily-shadcn 2.1.1 → 2.2.1

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.
@@ -1,12 +1,12 @@
1
- import * as react2 from "react";
1
+ import * as react0 from "react";
2
2
  import { DatePickerProps } from "@pixpilot/shadcn-ui";
3
3
 
4
4
  //#region src/components/date-picker/DatePicker.d.ts
5
5
 
6
- declare const DatePicker: react2.ForwardRefExoticComponent<Partial<{
6
+ declare const DatePicker: react0.ForwardRefExoticComponent<Partial<{
7
7
  value?: Date;
8
8
  onChange?: (date: Date | undefined) => void;
9
9
  placeholder?: string;
10
- } & Omit<DatePickerProps, "onSelect" | "selected" | "mode">> & react2.RefAttributes<unknown>>;
10
+ } & Omit<DatePickerProps, "onSelect" | "selected" | "mode">> & react0.RefAttributes<unknown>>;
11
11
  //#endregion
12
12
  export { DatePicker };
@@ -1,12 +1,12 @@
1
- import * as react2 from "react";
1
+ import * as react0 from "react";
2
2
  import { DatePickerProps } from "@pixpilot/shadcn-ui";
3
3
 
4
4
  //#region src/components/date-picker/DatePicker.d.ts
5
5
 
6
- declare const DatePicker$1: react2.ForwardRefExoticComponent<Partial<{
6
+ declare const DatePicker$1: react0.ForwardRefExoticComponent<Partial<{
7
7
  value?: Date;
8
8
  onChange?: (date: Date | undefined) => void;
9
9
  placeholder?: string;
10
- } & Omit<DatePickerProps, "onSelect" | "selected" | "mode">> & react2.RefAttributes<unknown>>;
10
+ } & Omit<DatePickerProps, "onSelect" | "selected" | "mode">> & react0.RefAttributes<unknown>>;
11
11
  //#endregion
12
12
  export { DatePicker$1 as DatePicker };
@@ -1,5 +1,5 @@
1
1
  import { DialogItemProps } from "./BaseDialogItem.cjs";
2
- import * as react4 from "react";
2
+ import * as react1 from "react";
3
3
 
4
4
  //#region src/components/dialog-item/ConnectedDialogItem.d.ts
5
5
 
@@ -8,8 +8,8 @@ import * as react4 from "react";
8
8
  * Maps field label, description, and validation state onto the decorator the
9
9
  * same way FormItem does.
10
10
  */
11
- declare const DialogItem: react4.ForwardRefExoticComponent<Omit<Partial<DialogItemProps & {
12
- children?: react4.ReactNode | undefined;
13
- }>, "ref"> & react4.RefAttributes<unknown>>;
11
+ declare const DialogItem: react1.ForwardRefExoticComponent<Omit<Partial<DialogItemProps & {
12
+ children?: react1.ReactNode | undefined;
13
+ }>, "ref"> & react1.RefAttributes<unknown>>;
14
14
  //#endregion
15
15
  export { DialogItem };
@@ -1,5 +1,5 @@
1
1
  import { DialogItemProps } from "./BaseDialogItem.js";
2
- import * as react0 from "react";
2
+ import * as react1 from "react";
3
3
 
4
4
  //#region src/components/dialog-item/ConnectedDialogItem.d.ts
5
5
 
@@ -8,8 +8,8 @@ import * as react0 from "react";
8
8
  * Maps field label, description, and validation state onto the decorator the
9
9
  * same way FormItem does.
10
10
  */
11
- declare const DialogItem: react0.ForwardRefExoticComponent<Omit<Partial<DialogItemProps & {
12
- children?: react0.ReactNode | undefined;
13
- }>, "ref"> & react0.RefAttributes<unknown>>;
11
+ declare const DialogItem: react1.ForwardRefExoticComponent<Omit<Partial<DialogItemProps & {
12
+ children?: react1.ReactNode | undefined;
13
+ }>, "ref"> & react1.RefAttributes<unknown>>;
14
14
  //#endregion
15
15
  export { DialogItem };
@@ -1,5 +1,5 @@
1
1
  import { DrawerItemProps } from "./BaseDrawerItem.cjs";
2
- import * as react7 from "react";
2
+ import * as react4 from "react";
3
3
 
4
4
  //#region src/components/drawer-item/ConnectedDrawerItem.d.ts
5
5
 
@@ -8,8 +8,8 @@ import * as react7 from "react";
8
8
  * Maps field label, description, and validation state onto the decorator the
9
9
  * same way FormItem does.
10
10
  */
11
- declare const DrawerItem: react7.ForwardRefExoticComponent<Omit<Partial<DrawerItemProps & {
12
- children?: react7.ReactNode | undefined;
13
- }>, "ref"> & react7.RefAttributes<unknown>>;
11
+ declare const DrawerItem: react4.ForwardRefExoticComponent<Omit<Partial<DrawerItemProps & {
12
+ children?: react4.ReactNode | undefined;
13
+ }>, "ref"> & react4.RefAttributes<unknown>>;
14
14
  //#endregion
15
15
  export { DrawerItem };
@@ -2,7 +2,7 @@ import { FormContextStates } from "../context/form-context.cjs";
2
2
  import "../context/index.cjs";
3
3
  import React from "react";
4
4
  import { Form } from "@formily/core";
5
- import * as react_jsx_runtime3 from "react/jsx-runtime";
5
+ import * as react_jsx_runtime1 from "react/jsx-runtime";
6
6
 
7
7
  //#region src/components/form/Form.d.ts
8
8
  interface IFormProps extends FormContextStates {
@@ -27,6 +27,6 @@ declare function Form$1({
27
27
  onAutoSubmit,
28
28
  layout,
29
29
  settings
30
- }: IFormProps): react_jsx_runtime3.JSX.Element;
30
+ }: IFormProps): react_jsx_runtime1.JSX.Element;
31
31
  //#endregion
32
32
  export { Form$1 as Form, IFormProps };
@@ -1,7 +1,7 @@
1
1
  import { FormContextStates } from "../context/form-context.js";
2
2
  import "../context/index.js";
3
3
  import React from "react";
4
- import * as react_jsx_runtime1 from "react/jsx-runtime";
4
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
5
5
  import { Form } from "@formily/core";
6
6
 
7
7
  //#region src/components/form/Form.d.ts
@@ -27,6 +27,6 @@ declare function Form$1({
27
27
  onAutoSubmit,
28
28
  layout,
29
29
  settings
30
- }: IFormProps): react_jsx_runtime1.JSX.Element;
30
+ }: IFormProps): react_jsx_runtime0.JSX.Element;
31
31
  //#endregion
32
32
  export { Form$1 as Form, IFormProps };
@@ -14,11 +14,48 @@ const meta = {
14
14
  },
15
15
  layout: "Optional layout configuration passed through the Formily shadcn form context.",
16
16
  onAutoSubmit: "Called with submitted values after the underlying Formily form submit succeeds.",
17
- settings: "Optional form settings passed through the Formily shadcn form context."
17
+ settings: "Optional form-wide settings passed through the Formily shadcn form context. Each key holds default props applied to every instance of that component in the form (field-level x-component-props still override them). Notably `settings.richTextEditor` accepts the full RichTextEditorProps, so you can register TipTap `extensions` (and their toolbar buttons) once for all RichTextEditor fields. See the \"RichTextEditor extensions via form settings\" example."
18
18
  }),
19
19
  examples: [{
20
20
  title: "Basic Formily form",
21
21
  code: "<Form form={form} onSubmit={(values) => save(values)}><SchemaField schema={schema} /></Form>"
22
+ }, {
23
+ title: "RichTextEditor extensions via form settings",
24
+ code: `import { Mark, mergeAttributes } from '@tiptap/core';
25
+
26
+ // Register a custom TipTap extension (or an official package like
27
+ // @tiptap/extension-highlight) once for every RichTextEditor field in the form.
28
+ const Highlight = Mark.create({
29
+ name: 'highlight',
30
+ parseHTML() {
31
+ return [{ tag: 'mark' }];
32
+ },
33
+ renderHTML({ HTMLAttributes }) {
34
+ return ['mark', mergeAttributes(HTMLAttributes), 0];
35
+ },
36
+ });
37
+
38
+ <Form
39
+ form={form}
40
+ settings={{
41
+ richTextEditor: {
42
+ extensions: [Highlight],
43
+ toolbarItems: [
44
+ 'bold',
45
+ 'italic',
46
+ '|',
47
+ {
48
+ icon: '🖍️',
49
+ tooltip: 'Highlight',
50
+ onClick: (editor) => editor.chain().focus().toggleMark('highlight').run(),
51
+ isActive: (editor) => editor.isActive('highlight'),
52
+ },
53
+ ],
54
+ },
55
+ }}
56
+ >
57
+ <SchemaField schema={schema} />
58
+ </Form>`
22
59
  }],
23
60
  keywords: [
24
61
  "formily",
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import * as react_jsx_runtime4 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/form-grid/FormGrid.d.ts
5
5
  interface IFormGridProps extends React.HTMLAttributes<HTMLDivElement> {}
@@ -7,6 +7,6 @@ declare function FormGrid({
7
7
  className,
8
8
  children,
9
9
  ...rest
10
- }: IFormGridProps): react_jsx_runtime4.JSX.Element;
10
+ }: IFormGridProps): react_jsx_runtime0.JSX.Element;
11
11
  //#endregion
12
12
  export { FormGrid, IFormGridProps };
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime1 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/form-grid/FormGrid.d.ts
5
5
  interface IFormGridProps extends React.HTMLAttributes<HTMLDivElement> {}
@@ -7,6 +7,6 @@ declare function FormGrid({
7
7
  className,
8
8
  children,
9
9
  ...rest
10
- }: IFormGridProps): react_jsx_runtime0.JSX.Element;
10
+ }: IFormGridProps): react_jsx_runtime1.JSX.Element;
11
11
  //#endregion
12
12
  export { FormGrid, IFormGridProps };
@@ -1,13 +1,13 @@
1
1
  import { FormItemProps } from "./form-item-types.cjs";
2
- import * as react1585 from "react";
2
+ import * as react1583 from "react";
3
3
 
4
4
  //#region src/components/form-item/ConnectedFormItem.d.ts
5
5
  /**
6
6
  * FormItem component connected to Formily field state.
7
7
  * Automatically maps field validation state to component props.
8
8
  */
9
- declare const FormItem: react1585.ForwardRefExoticComponent<Omit<Partial<FormItemProps & {
10
- children?: react1585.ReactNode | undefined;
11
- }>, "ref"> & react1585.RefAttributes<unknown>>;
9
+ declare const FormItem: react1583.ForwardRefExoticComponent<Omit<Partial<FormItemProps & {
10
+ children?: react1583.ReactNode | undefined;
11
+ }>, "ref"> & react1583.RefAttributes<unknown>>;
12
12
  //#endregion
13
13
  export { FormItem };
@@ -1,5 +1,5 @@
1
1
  import { PopoverItemProps } from "./BasePopoverItem.cjs";
2
- import * as react0 from "react";
2
+ import * as react7 from "react";
3
3
 
4
4
  //#region src/components/popover-item/ConnectedPopoverItem.d.ts
5
5
 
@@ -8,8 +8,8 @@ import * as react0 from "react";
8
8
  * Maps field label, description, and validation state onto the decorator the
9
9
  * same way FormItem does.
10
10
  */
11
- declare const PopoverItem: react0.ForwardRefExoticComponent<Omit<Partial<PopoverItemProps & {
12
- children?: react0.ReactNode | undefined;
13
- }>, "ref"> & react0.RefAttributes<unknown>>;
11
+ declare const PopoverItem: react7.ForwardRefExoticComponent<Omit<Partial<PopoverItemProps & {
12
+ children?: react7.ReactNode | undefined;
13
+ }>, "ref"> & react7.RefAttributes<unknown>>;
14
14
  //#endregion
15
15
  export { PopoverItem };
@@ -1,5 +1,5 @@
1
1
  import { ComponentProps, FC } from "react";
2
- import * as react_jsx_runtime1 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime2 from "react/jsx-runtime";
3
3
  import { RadioGroup } from "@pixpilot/shadcn";
4
4
 
5
5
  //#region src/components/radio/Radio.d.ts
@@ -15,7 +15,7 @@ type RadioProps = {
15
15
  /**
16
16
  * Radio component with options rendering
17
17
  */
18
- declare function Radio(props: RadioProps): react_jsx_runtime1.JSX.Element;
18
+ declare function Radio(props: RadioProps): react_jsx_runtime2.JSX.Element;
19
19
  declare namespace Radio {
20
20
  var displayName: string;
21
21
  }
@@ -11,7 +11,7 @@ const meta = {
11
11
  editable: "Forwarded to the underlying UI component.",
12
12
  editorProps: "Forwarded to the underlying UI component.",
13
13
  immediatelyRender: "Forwarded to the underlying UI component.",
14
- extensions: "Forwarded to the underlying UI component.",
14
+ extensions: "Additional TipTap extensions forwarded to the underlying UI component, appended to the built-in ones (StarterKit, Link, TextAlign, Placeholder). Accepts any TipTap Extension, Node, or Mark. In schema forms pass them via `x-component-props.extensions`. See the \"Add a custom extension\" example.",
15
15
  slots: "Slot props for customizing internal rendered parts.",
16
16
  showToolbar: "Forwarded to the underlying UI component.",
17
17
  toolbarItems: "Forwarded to the underlying UI component.",
@@ -20,12 +20,14 @@ const meta = {
20
20
  allowLinkTarget: "Forwarded to the underlying UI component.",
21
21
  openOnClick: "Forwarded to the underlying UI component."
22
22
  }),
23
- examples: [{
24
- title: "Declarative schema field",
25
- code: `<SchemaField.String name="richTextEditor" title="RichTextEditor" x-decorator="FormItem" x-component="RichTextEditor" />`
26
- }, {
27
- title: "JSON schema for form renderer",
28
- code: `{
23
+ examples: [
24
+ {
25
+ title: "Declarative schema field",
26
+ code: `<SchemaField.String name="richTextEditor" title="RichTextEditor" x-decorator="FormItem" x-component="RichTextEditor" />`
27
+ },
28
+ {
29
+ title: "JSON schema for form renderer",
30
+ code: `{
29
31
  type: 'object',
30
32
  properties: {
31
33
  richTextEditor: {
@@ -36,7 +38,50 @@ const meta = {
36
38
  },
37
39
  },
38
40
  }`
39
- }],
41
+ },
42
+ {
43
+ title: "Add a custom extension via x-component-props",
44
+ code: `import { Mark, mergeAttributes } from '@tiptap/core';
45
+
46
+ // Any Mark.create / Node.create / Extension.create result (or an official
47
+ // package like @tiptap/extension-highlight) can be passed to \`extensions\`.
48
+ const Highlight = Mark.create({
49
+ name: 'highlight',
50
+ parseHTML() {
51
+ return [{ tag: 'mark' }];
52
+ },
53
+ renderHTML({ HTMLAttributes }) {
54
+ return ['mark', mergeAttributes(HTMLAttributes), 0];
55
+ },
56
+ });
57
+
58
+ const schema = {
59
+ type: 'object',
60
+ properties: {
61
+ richText: {
62
+ type: 'string',
63
+ title: 'Rich Text Editor',
64
+ 'x-decorator': 'FormItem',
65
+ 'x-component': 'RichTextEditor',
66
+ 'x-component-props': {
67
+ extensions: [Highlight],
68
+ toolbarItems: [
69
+ 'bold',
70
+ 'italic',
71
+ '|',
72
+ {
73
+ icon: '🖍️',
74
+ tooltip: 'Highlight',
75
+ onClick: (editor) => editor.chain().focus().toggleMark('highlight').run(),
76
+ isActive: (editor) => editor.isActive('highlight'),
77
+ },
78
+ ],
79
+ },
80
+ },
81
+ },
82
+ };`
83
+ }
84
+ ],
40
85
  keywords: [
41
86
  "formily",
42
87
  "rich text",
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime3 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/components/row/Row.d.ts
5
5
  interface IRowProps {
@@ -36,6 +36,6 @@ interface IRowProps {
36
36
  declare function Row({
37
37
  className,
38
38
  children
39
- }: IRowProps): react_jsx_runtime0.JSX.Element;
39
+ }: IRowProps): react_jsx_runtime3.JSX.Element;
40
40
  //#endregion
41
41
  export { IRowProps, Row };
@@ -26,13 +26,33 @@ const inputSchemaMap = {
26
26
  },
27
27
  object: { "x-component": "ObjectContainer" }
28
28
  };
29
- function transformSchema(schema, fieldsDecorators) {
30
- let normalizedSchema;
31
- try {
32
- normalizedSchema = JSON.parse(JSON.stringify(schema));
33
- } catch {
34
- normalizedSchema = JSON.parse(JSON.stringify(schema));
29
+ /**
30
+ * Deep-clone the plain-object/array structure of a schema while keeping any
31
+ * non-plain values (functions, class instances such as TipTap extensions,
32
+ * Dates, etc.) by reference.
33
+ *
34
+ * A plain `JSON.parse(JSON.stringify(...))` clone silently drops function
35
+ * values, which breaks `x-component-props` that carry callbacks (e.g. custom
36
+ * toolbar `onClick` handlers) or class instances (e.g. TipTap `extensions`,
37
+ * whose `parseHTML`/`renderHTML` methods would be stripped). This clone only
38
+ * copies plain objects and arrays — the parts `transformSchema` actually
39
+ * mutates — and leaves everything else untouched.
40
+ */
41
+ function cloneSchemaPreservingRefs(value) {
42
+ if (Array.isArray(value)) return value.map((item) => cloneSchemaPreservingRefs(item));
43
+ if (value !== null && typeof value === "object") {
44
+ const proto = Object.getPrototypeOf(value);
45
+ if (proto === Object.prototype || proto === null) {
46
+ const source = value;
47
+ const out = {};
48
+ for (const key of Object.keys(source)) out[key] = cloneSchemaPreservingRefs(source[key]);
49
+ return out;
50
+ }
35
51
  }
52
+ return value;
53
+ }
54
+ function transformSchema(schema, fieldsDecorators) {
55
+ const normalizedSchema = cloneSchemaPreservingRefs(schema);
36
56
  (0, json_schema_traverse.default)(normalizedSchema, { allKeys: true }, (currentSchema, _jsonPtr, _rootSchema, _parentJSONPtr, parentKeyword, _parentSchema, _keyIndex) => {
37
57
  const { type } = currentSchema;
38
58
  const xComponent = currentSchema["x-component"];
@@ -24,13 +24,33 @@ const inputSchemaMap = {
24
24
  },
25
25
  object: { "x-component": "ObjectContainer" }
26
26
  };
27
- function transformSchema(schema, fieldsDecorators) {
28
- let normalizedSchema;
29
- try {
30
- normalizedSchema = JSON.parse(JSON.stringify(schema));
31
- } catch {
32
- normalizedSchema = JSON.parse(JSON.stringify(schema));
27
+ /**
28
+ * Deep-clone the plain-object/array structure of a schema while keeping any
29
+ * non-plain values (functions, class instances such as TipTap extensions,
30
+ * Dates, etc.) by reference.
31
+ *
32
+ * A plain `JSON.parse(JSON.stringify(...))` clone silently drops function
33
+ * values, which breaks `x-component-props` that carry callbacks (e.g. custom
34
+ * toolbar `onClick` handlers) or class instances (e.g. TipTap `extensions`,
35
+ * whose `parseHTML`/`renderHTML` methods would be stripped). This clone only
36
+ * copies plain objects and arrays — the parts `transformSchema` actually
37
+ * mutates — and leaves everything else untouched.
38
+ */
39
+ function cloneSchemaPreservingRefs(value) {
40
+ if (Array.isArray(value)) return value.map((item) => cloneSchemaPreservingRefs(item));
41
+ if (value !== null && typeof value === "object") {
42
+ const proto = Object.getPrototypeOf(value);
43
+ if (proto === Object.prototype || proto === null) {
44
+ const source = value;
45
+ const out = {};
46
+ for (const key of Object.keys(source)) out[key] = cloneSchemaPreservingRefs(source[key]);
47
+ return out;
48
+ }
33
49
  }
50
+ return value;
51
+ }
52
+ function transformSchema(schema, fieldsDecorators) {
53
+ const normalizedSchema = cloneSchemaPreservingRefs(schema);
34
54
  traverse(normalizedSchema, { allKeys: true }, (currentSchema, _jsonPtr, _rootSchema, _parentJSONPtr, parentKeyword, _parentSchema, _keyIndex) => {
35
55
  const { type } = currentSchema;
36
56
  const xComponent = currentSchema["x-component"];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pixpilot/formily-shadcn",
3
3
  "type": "module",
4
- "version": "2.1.1",
4
+ "version": "2.2.1",
5
5
  "description": "Formily integration for shadcn/ui components",
6
6
  "author": "m.doaie <m.doaie@hotmail.com>",
7
7
  "license": "MIT",
@@ -48,26 +48,27 @@
48
48
  "@pixpilot/string": "^3.0.1",
49
49
  "json-schema-traverse": "^1.0.0",
50
50
  "lucide-react": "^0.562.0",
51
- "pretty-bytes": "^7.1.0",
51
+ "pretty-bytes": "^7.1.1",
52
52
  "zod": "^4.3.6",
53
53
  "@pixpilot/shadcn": "2.1.0",
54
- "@pixpilot/shadcn-ui": "3.5.1"
54
+ "@pixpilot/shadcn-ui": "3.6.1"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@storybook/react": "^8.6.18",
58
58
  "@testing-library/react": "^16.3.2",
59
+ "@tiptap/core": "^3.22.3",
59
60
  "@types/node": "^22.19.17",
60
61
  "@types/react": "^19.2.14",
61
62
  "@types/react-dom": "^19.2.3",
62
63
  "eslint": "^9.39.4",
63
- "react": "19.2.0",
64
- "react-dom": "19.2.0",
64
+ "react": "19.2.8",
65
+ "react-dom": "19.2.8",
65
66
  "tsdown": "^0.15.12",
66
67
  "tsx": "^4.21.0",
67
68
  "typescript": "^5.9.3",
68
69
  "@internal/eslint-config": "0.3.0",
69
- "@internal/mcp": "0.0.0",
70
70
  "@internal/prettier-config": "0.0.1",
71
+ "@internal/mcp": "0.0.0",
71
72
  "@internal/tsconfig": "0.1.0",
72
73
  "@internal/tsdown-config": "0.1.0",
73
74
  "@internal/vitest-config": "0.1.0"