@pixpilot/formily-shadcn 1.16.0 → 1.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 (76) hide show
  1. package/dist/components/date-picker/DatePicker.d.cts +3 -3
  2. package/dist/components/date-picker/DatePicker.d.ts +3 -3
  3. package/dist/components/dialog-item/BaseDialogItem.cjs +114 -0
  4. package/dist/components/dialog-item/BaseDialogItem.d.cts +56 -0
  5. package/dist/components/dialog-item/BaseDialogItem.d.ts +56 -0
  6. package/dist/components/dialog-item/BaseDialogItem.js +109 -0
  7. package/dist/components/dialog-item/ConnectedDialogItem.cjs +16 -0
  8. package/dist/components/dialog-item/ConnectedDialogItem.d.cts +15 -0
  9. package/dist/components/dialog-item/ConnectedDialogItem.d.ts +15 -0
  10. package/dist/components/dialog-item/ConnectedDialogItem.js +14 -0
  11. package/dist/components/dialog-item/index.cjs +2 -0
  12. package/dist/components/dialog-item/index.d.cts +2 -0
  13. package/dist/components/dialog-item/index.d.ts +2 -0
  14. package/dist/components/dialog-item/index.js +2 -0
  15. package/dist/components/dialog-item/mcp.js +127 -0
  16. package/dist/components/form/Form.d.cts +2 -2
  17. package/dist/components/form/Form.d.ts +2 -2
  18. package/dist/components/form-grid/FormGrid.d.cts +2 -2
  19. package/dist/components/form-grid/FormGrid.d.ts +2 -2
  20. package/dist/components/form-item/ConnectedFormItem.cjs +2 -34
  21. package/dist/components/form-item/ConnectedFormItem.d.cts +4 -4
  22. package/dist/components/form-item/ConnectedFormItem.d.ts +4 -4
  23. package/dist/components/form-item/ConnectedFormItem.js +3 -34
  24. package/dist/components/form-item/map-form-item-props.cjs +50 -0
  25. package/dist/components/form-item/map-form-item-props.js +47 -0
  26. package/dist/components/overlay-common/OverlayFields.cjs +26 -0
  27. package/dist/components/overlay-common/OverlayFields.d.cts +1 -0
  28. package/dist/components/overlay-common/OverlayFields.d.ts +1 -0
  29. package/dist/components/overlay-common/OverlayFields.js +24 -0
  30. package/dist/components/overlay-common/OverlayTrigger.cjs +27 -0
  31. package/dist/components/overlay-common/OverlayTrigger.d.cts +15 -0
  32. package/dist/components/overlay-common/OverlayTrigger.d.ts +15 -0
  33. package/dist/components/overlay-common/OverlayTrigger.js +23 -0
  34. package/dist/components/overlay-common/constants.cjs +10 -0
  35. package/dist/components/overlay-common/constants.js +9 -0
  36. package/dist/components/overlay-common/index.cjs +5 -0
  37. package/dist/components/overlay-common/index.d.cts +4 -0
  38. package/dist/components/overlay-common/index.d.ts +4 -0
  39. package/dist/components/overlay-common/index.js +5 -0
  40. package/dist/components/overlay-common/is-empty-field-value.cjs +23 -0
  41. package/dist/components/overlay-common/is-empty-field-value.js +22 -0
  42. package/dist/components/overlay-common/overlay-types.d.cts +27 -0
  43. package/dist/components/overlay-common/overlay-types.d.ts +27 -0
  44. package/dist/components/overlay-common/use-overlay.cjs +110 -0
  45. package/dist/components/overlay-common/use-overlay.d.cts +1 -0
  46. package/dist/components/overlay-common/use-overlay.d.ts +1 -0
  47. package/dist/components/overlay-common/use-overlay.js +107 -0
  48. package/dist/components/popover-item/BasePopoverItem.cjs +108 -0
  49. package/dist/components/popover-item/BasePopoverItem.d.cts +57 -0
  50. package/dist/components/popover-item/BasePopoverItem.d.ts +57 -0
  51. package/dist/components/popover-item/BasePopoverItem.js +104 -0
  52. package/dist/components/popover-item/ConnectedPopoverItem.cjs +16 -0
  53. package/dist/components/popover-item/ConnectedPopoverItem.d.cts +15 -0
  54. package/dist/components/popover-item/ConnectedPopoverItem.d.ts +15 -0
  55. package/dist/components/popover-item/ConnectedPopoverItem.js +14 -0
  56. package/dist/components/popover-item/index.cjs +2 -0
  57. package/dist/components/popover-item/index.d.cts +2 -0
  58. package/dist/components/popover-item/index.d.ts +2 -0
  59. package/dist/components/popover-item/index.js +2 -0
  60. package/dist/components/popover-item/mcp.js +127 -0
  61. package/dist/components/radio/Radio.d.ts +2 -2
  62. package/dist/components/row/Row.d.ts +2 -2
  63. package/dist/components/schema-field/schema-field-basics.cjs +8 -2
  64. package/dist/components/schema-field/schema-field-basics.d.cts +344 -270
  65. package/dist/components/schema-field/schema-field-basics.d.ts +337 -263
  66. package/dist/components/schema-field/schema-field-basics.js +8 -2
  67. package/dist/components/schema-field/schema-field-extended.d.cts +498 -424
  68. package/dist/components/schema-field/schema-field-extended.d.ts +480 -406
  69. package/dist/components/schema-field/schema-field.d.cts +425 -351
  70. package/dist/components/schema-field/schema-field.d.ts +425 -351
  71. package/dist/generated/mcp-registry.js +56 -52
  72. package/dist/index.cjs +12 -2
  73. package/dist/index.d.cts +7 -1
  74. package/dist/index.d.ts +7 -1
  75. package/dist/index.js +9 -3
  76. package/package.json +2 -2
@@ -0,0 +1,107 @@
1
+ import { resolveResponsiveGapClass } from "../../utils/resolve-responsive-space.js";
2
+ import { useDescription } from "../../hooks/use-description.js";
3
+ import { useFormContext } from "../../hooks/use-form-context.js";
4
+ import { useLabel } from "../../hooks/use-label.js";
5
+ import "../../hooks/index.js";
6
+ import { useShakeAnimation } from "../array-common/use-shake-animation.js";
7
+ import "../array-common/index.js";
8
+ import { DEFAULT_TRIGGER_NOUN } from "./constants.js";
9
+ import { isEmptyFieldValue } from "./is-empty-field-value.js";
10
+ import { useField, useFieldSchema } from "@formily/react";
11
+ import React from "react";
12
+
13
+ //#region src/components/overlay-common/use-overlay.ts
14
+ /**
15
+ * Formily glob matching the field itself and every descendant, and nothing
16
+ * else — `*(a,a.*)` matches `a`, `a.b`, and `a.b.c`, but not the sibling `ab`.
17
+ * One pattern covers both shapes an overlay can hold: a single input (validate
18
+ * the field) and an object's form (validate its fields), at any depth.
19
+ */
20
+ function buildValidationPattern(address) {
21
+ return `*(${address},${address}.*)`;
22
+ }
23
+ /**
24
+ * Shared state for fields that render their input(s) inside an overlay
25
+ * (dialog or popover) opened from a trigger button.
26
+ *
27
+ * Fields render in the parent form (no draft copy), so edits commit as the
28
+ * user types. This mirrors the autoSave mode of ArrayDialog/ArrayPopover:
29
+ * validation on close is scoped to the overlay's own fields so unrelated
30
+ * fields elsewhere in the form are not validated.
31
+ */
32
+ function useOverlay(options = {}) {
33
+ const { label, description, trigger, open, defaultOpen, onOpenChange, validateOnClose = true } = options;
34
+ const effectiveLabel = useLabel(label);
35
+ const effectiveDescription = useDescription(description);
36
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen ?? false);
37
+ const isControlled = open !== void 0;
38
+ const isOpen = isControlled ? open : uncontrolledOpen;
39
+ const setOpen = React.useCallback((next) => {
40
+ if (!isControlled) setUncontrolledOpen(next);
41
+ onOpenChange?.(next);
42
+ }, [isControlled, onOpenChange]);
43
+ const { layout } = useFormContext();
44
+ const gapClass = resolveResponsiveGapClass({ density: layout?.density });
45
+ const field = useField();
46
+ const hasError = field.errors.length > 0;
47
+ const validationPath = buildValidationPattern(field.address.toString());
48
+ const noun = useFieldSchema().title ?? DEFAULT_TRIGGER_NOUN;
49
+ const isEmpty = isEmptyFieldValue(field.value);
50
+ const resolvedTrigger = {
51
+ ...trigger,
52
+ label: trigger?.label ?? (isEmpty ? `Add ${noun}` : `Edit ${noun}`)
53
+ };
54
+ const { shouldShake, triggerShake } = useShakeAnimation();
55
+ const revalidateOnOpenRef = React.useRef(false);
56
+ React.useEffect(() => {
57
+ if (!isOpen || !revalidateOnOpenRef.current) return;
58
+ revalidateOnOpenRef.current = false;
59
+ Promise.resolve(field.form.validate(validationPath)).catch(() => void 0);
60
+ }, [
61
+ field.form,
62
+ isOpen,
63
+ validationPath
64
+ ]);
65
+ const requestClose = React.useCallback(() => {
66
+ if (!validateOnClose) {
67
+ setOpen(false);
68
+ return;
69
+ }
70
+ Promise.resolve(field.form.validate(validationPath)).then(() => {
71
+ setOpen(false);
72
+ }).catch(() => {
73
+ triggerShake();
74
+ });
75
+ }, [
76
+ field.form,
77
+ setOpen,
78
+ triggerShake,
79
+ validateOnClose,
80
+ validationPath
81
+ ]);
82
+ return {
83
+ label: effectiveLabel,
84
+ description: effectiveDescription,
85
+ trigger: resolvedTrigger,
86
+ open: isOpen,
87
+ gapClass,
88
+ hasError,
89
+ shouldShake,
90
+ handleOpenChange: React.useCallback((next) => {
91
+ if (next) {
92
+ revalidateOnOpenRef.current = hasError;
93
+ setOpen(true);
94
+ return;
95
+ }
96
+ requestClose();
97
+ }, [
98
+ hasError,
99
+ requestClose,
100
+ setOpen
101
+ ]),
102
+ requestClose
103
+ };
104
+ }
105
+
106
+ //#endregion
107
+ export { useOverlay };
@@ -0,0 +1,108 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ const require_ShakeStyles = require('../array-common/ShakeStyles.cjs');
3
+ require('../array-common/index.cjs');
4
+ const require_BaseFormItem = require('../form-item/BaseFormItem.cjs');
5
+ require('../form-item/index.cjs');
6
+ const require_OverlayFields = require('../overlay-common/OverlayFields.cjs');
7
+ const require_OverlayTrigger = require('../overlay-common/OverlayTrigger.cjs');
8
+ const require_use_overlay = require('../overlay-common/use-overlay.cjs');
9
+ require('../overlay-common/index.cjs');
10
+ let react = require("react");
11
+ react = require_rolldown_runtime.__toESM(react);
12
+ let react_jsx_runtime = require("react/jsx-runtime");
13
+ react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
14
+ let __pixpilot_shadcn = require("@pixpilot/shadcn");
15
+ __pixpilot_shadcn = require_rolldown_runtime.__toESM(__pixpilot_shadcn);
16
+
17
+ //#region src/components/popover-item/BasePopoverItem.tsx
18
+ /**
19
+ * Formily decorator that edits a single field inside a popover.
20
+ *
21
+ * Used in place of FormItem (`x-decorator: 'PopoverItem'`), it renders the
22
+ * field's label, description, and validation feedback exactly as FormItem
23
+ * does, but puts a trigger button where the input would sit and moves the
24
+ * input itself into a popover. The field keeps its own component, so
25
+ * validation and x-reactions behave as they do under FormItem.
26
+ */
27
+ const BasePopoverItem = ({ children, label, description, trigger: triggerProp, open: openProp, defaultOpen, onOpenChange, validateOnClose, modal = false, popover, feedbackStatus, feedbackText,...formItemProps }) => {
28
+ const { label: effectiveLabel, description: desc, trigger, open, gapClass, hasError, shouldShake, handleOpenChange, requestClose } = require_use_overlay.useOverlay({
29
+ label,
30
+ description,
31
+ trigger: triggerProp,
32
+ open: openProp,
33
+ defaultOpen,
34
+ onOpenChange,
35
+ validateOnClose
36
+ });
37
+ const title = popover?.title ?? effectiveLabel;
38
+ const overlayDescription = popover?.description ?? desc;
39
+ const slots = popover?.slots;
40
+ const hasHeader = title != null || overlayDescription != null;
41
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Popover, {
42
+ open,
43
+ onOpenChange: handleOpenChange,
44
+ modal,
45
+ children: [
46
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_BaseFormItem.BaseFormItem, {
47
+ ...formItemProps,
48
+ label,
49
+ description,
50
+ feedbackStatus,
51
+ feedbackText,
52
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(__pixpilot_shadcn.PopoverTrigger, {
53
+ asChild: true,
54
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_OverlayTrigger.OverlayTrigger, {
55
+ invalid: hasError,
56
+ ...trigger
57
+ })
58
+ })
59
+ }),
60
+ !open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_OverlayFields.OverlayFields, { children }),
61
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.PopoverContent, {
62
+ align: "start",
63
+ ...slots?.content,
64
+ className: (0, __pixpilot_shadcn.cn)("w-(--radix-popover-trigger-width) min-w-72", shouldShake && "pp-shake", slots?.content?.className),
65
+ onInteractOutside: (event) => {
66
+ slots?.content?.onInteractOutside?.(event);
67
+ if (event.defaultPrevented) return;
68
+ event.preventDefault();
69
+ requestClose();
70
+ },
71
+ onEscapeKeyDown: (event) => {
72
+ slots?.content?.onEscapeKeyDown?.(event);
73
+ if (event.defaultPrevented) return;
74
+ event.preventDefault();
75
+ requestClose();
76
+ },
77
+ children: [
78
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_ShakeStyles.ShakeStyles, {}),
79
+ hasHeader && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
80
+ ...slots?.header,
81
+ className: (0, __pixpilot_shadcn.cn)("space-y-1 pb-3", slots?.header?.className),
82
+ children: [title != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h4", {
83
+ ...slots?.title,
84
+ className: (0, __pixpilot_shadcn.cn)("font-medium leading-none", slots?.title?.className),
85
+ children: title
86
+ }), overlayDescription != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
87
+ ...slots?.description,
88
+ className: (0, __pixpilot_shadcn.cn)("text-muted-foreground text-sm", slots?.description?.className),
89
+ children: overlayDescription
90
+ })]
91
+ }),
92
+ open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
93
+ ...slots?.body,
94
+ className: (0, __pixpilot_shadcn.cn)("grid", gapClass, slots?.body?.className),
95
+ children: [children, feedbackText != null && feedbackText !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
96
+ className: (0, __pixpilot_shadcn.cn)("text-[0.8rem]", feedbackStatus === "error" && "text-destructive font-medium", feedbackStatus === "warning" && "text-amber-600", feedbackStatus === "success" && "text-green-600"),
97
+ children: feedbackText
98
+ })]
99
+ })
100
+ ]
101
+ })
102
+ ]
103
+ });
104
+ };
105
+ BasePopoverItem.displayName = "BasePopoverItem";
106
+
107
+ //#endregion
108
+ exports.BasePopoverItem = BasePopoverItem;
@@ -0,0 +1,57 @@
1
+ import { FormItemProps } from "../form-item/form-item-types.cjs";
2
+ import "../form-item/index.cjs";
3
+ import { OverlayBaseSlots, OverlayProps } from "../overlay-common/overlay-types.cjs";
4
+ import { OverlayTriggerProps } from "../overlay-common/OverlayTrigger.cjs";
5
+ import "../overlay-common/index.cjs";
6
+ import React from "react";
7
+ import { PopoverContent } from "@pixpilot/shadcn";
8
+
9
+ //#region src/components/popover-item/BasePopoverItem.d.ts
10
+ interface PopoverItemProps extends Omit<FormItemProps, 'popover'> {
11
+ /**
12
+ * Props for the trigger button, e.g. `{ label: 'Write a bio' }`. Without a
13
+ * label it reads `Add <title>` when the field is empty and `Edit <title>`
14
+ * once it holds a value. Settable from an x-reaction via
15
+ * `decoratorProps.trigger`.
16
+ */
17
+ trigger?: OverlayTriggerProps;
18
+ /** Controlled open state of the popover. */
19
+ open?: boolean;
20
+ /** Initial open state when uncontrolled. */
21
+ defaultOpen?: boolean;
22
+ onOpenChange?: (open: boolean) => void;
23
+ /**
24
+ * When false, the popover closes without validating the field first.
25
+ * Default is true.
26
+ */
27
+ validateOnClose?: boolean;
28
+ /**
29
+ * If true, interaction outside the popover is blocked while it is open.
30
+ * Default is false.
31
+ */
32
+ modal?: boolean;
33
+ /**
34
+ * The popover itself — its `title`, `description`, and `slots`, e.g.
35
+ * `{ title: 'Notes', slots: { content: { className: 'w-96' } } }`. Title and
36
+ * description default to the field's label and description.
37
+ */
38
+ popover?: PopoverItemPopoverProps;
39
+ }
40
+ interface PopoverItemPopoverSlots extends OverlayBaseSlots {
41
+ content?: React.ComponentProps<typeof PopoverContent>;
42
+ title?: React.ComponentProps<'h4'>;
43
+ description?: React.ComponentProps<'p'>;
44
+ }
45
+ type PopoverItemPopoverProps = OverlayProps<PopoverItemPopoverSlots>;
46
+ /**
47
+ * Formily decorator that edits a single field inside a popover.
48
+ *
49
+ * Used in place of FormItem (`x-decorator: 'PopoverItem'`), it renders the
50
+ * field's label, description, and validation feedback exactly as FormItem
51
+ * does, but puts a trigger button where the input would sit and moves the
52
+ * input itself into a popover. The field keeps its own component, so
53
+ * validation and x-reactions behave as they do under FormItem.
54
+ */
55
+ declare const BasePopoverItem: React.FC<React.PropsWithChildren<PopoverItemProps>>;
56
+ //#endregion
57
+ export { BasePopoverItem, PopoverItemProps };
@@ -0,0 +1,57 @@
1
+ import { FormItemProps } from "../form-item/form-item-types.js";
2
+ import "../form-item/index.js";
3
+ import { OverlayBaseSlots, OverlayProps } from "../overlay-common/overlay-types.js";
4
+ import { OverlayTriggerProps } from "../overlay-common/OverlayTrigger.js";
5
+ import "../overlay-common/index.js";
6
+ import React from "react";
7
+ import { PopoverContent } from "@pixpilot/shadcn";
8
+
9
+ //#region src/components/popover-item/BasePopoverItem.d.ts
10
+ interface PopoverItemProps extends Omit<FormItemProps, 'popover'> {
11
+ /**
12
+ * Props for the trigger button, e.g. `{ label: 'Write a bio' }`. Without a
13
+ * label it reads `Add <title>` when the field is empty and `Edit <title>`
14
+ * once it holds a value. Settable from an x-reaction via
15
+ * `decoratorProps.trigger`.
16
+ */
17
+ trigger?: OverlayTriggerProps;
18
+ /** Controlled open state of the popover. */
19
+ open?: boolean;
20
+ /** Initial open state when uncontrolled. */
21
+ defaultOpen?: boolean;
22
+ onOpenChange?: (open: boolean) => void;
23
+ /**
24
+ * When false, the popover closes without validating the field first.
25
+ * Default is true.
26
+ */
27
+ validateOnClose?: boolean;
28
+ /**
29
+ * If true, interaction outside the popover is blocked while it is open.
30
+ * Default is false.
31
+ */
32
+ modal?: boolean;
33
+ /**
34
+ * The popover itself — its `title`, `description`, and `slots`, e.g.
35
+ * `{ title: 'Notes', slots: { content: { className: 'w-96' } } }`. Title and
36
+ * description default to the field's label and description.
37
+ */
38
+ popover?: PopoverItemPopoverProps;
39
+ }
40
+ interface PopoverItemPopoverSlots extends OverlayBaseSlots {
41
+ content?: React.ComponentProps<typeof PopoverContent>;
42
+ title?: React.ComponentProps<'h4'>;
43
+ description?: React.ComponentProps<'p'>;
44
+ }
45
+ type PopoverItemPopoverProps = OverlayProps<PopoverItemPopoverSlots>;
46
+ /**
47
+ * Formily decorator that edits a single field inside a popover.
48
+ *
49
+ * Used in place of FormItem (`x-decorator: 'PopoverItem'`), it renders the
50
+ * field's label, description, and validation feedback exactly as FormItem
51
+ * does, but puts a trigger button where the input would sit and moves the
52
+ * input itself into a popover. The field keeps its own component, so
53
+ * validation and x-reactions behave as they do under FormItem.
54
+ */
55
+ declare const BasePopoverItem: React.FC<React.PropsWithChildren<PopoverItemProps>>;
56
+ //#endregion
57
+ export { BasePopoverItem, PopoverItemProps };
@@ -0,0 +1,104 @@
1
+ import { ShakeStyles } from "../array-common/ShakeStyles.js";
2
+ import "../array-common/index.js";
3
+ import { BaseFormItem } from "../form-item/BaseFormItem.js";
4
+ import "../form-item/index.js";
5
+ import { OverlayFields } from "../overlay-common/OverlayFields.js";
6
+ import { OverlayTrigger } from "../overlay-common/OverlayTrigger.js";
7
+ import { useOverlay } from "../overlay-common/use-overlay.js";
8
+ import "../overlay-common/index.js";
9
+ import React from "react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ import { Popover, PopoverContent, PopoverTrigger, cn } from "@pixpilot/shadcn";
12
+
13
+ //#region src/components/popover-item/BasePopoverItem.tsx
14
+ /**
15
+ * Formily decorator that edits a single field inside a popover.
16
+ *
17
+ * Used in place of FormItem (`x-decorator: 'PopoverItem'`), it renders the
18
+ * field's label, description, and validation feedback exactly as FormItem
19
+ * does, but puts a trigger button where the input would sit and moves the
20
+ * input itself into a popover. The field keeps its own component, so
21
+ * validation and x-reactions behave as they do under FormItem.
22
+ */
23
+ const BasePopoverItem = ({ children, label, description, trigger: triggerProp, open: openProp, defaultOpen, onOpenChange, validateOnClose, modal = false, popover, feedbackStatus, feedbackText,...formItemProps }) => {
24
+ const { label: effectiveLabel, description: desc, trigger, open, gapClass, hasError, shouldShake, handleOpenChange, requestClose } = useOverlay({
25
+ label,
26
+ description,
27
+ trigger: triggerProp,
28
+ open: openProp,
29
+ defaultOpen,
30
+ onOpenChange,
31
+ validateOnClose
32
+ });
33
+ const title = popover?.title ?? effectiveLabel;
34
+ const overlayDescription = popover?.description ?? desc;
35
+ const slots = popover?.slots;
36
+ const hasHeader = title != null || overlayDescription != null;
37
+ return /* @__PURE__ */ jsxs(Popover, {
38
+ open,
39
+ onOpenChange: handleOpenChange,
40
+ modal,
41
+ children: [
42
+ /* @__PURE__ */ jsx(BaseFormItem, {
43
+ ...formItemProps,
44
+ label,
45
+ description,
46
+ feedbackStatus,
47
+ feedbackText,
48
+ children: /* @__PURE__ */ jsx(PopoverTrigger, {
49
+ asChild: true,
50
+ children: /* @__PURE__ */ jsx(OverlayTrigger, {
51
+ invalid: hasError,
52
+ ...trigger
53
+ })
54
+ })
55
+ }),
56
+ !open && /* @__PURE__ */ jsx(OverlayFields, { children }),
57
+ /* @__PURE__ */ jsxs(PopoverContent, {
58
+ align: "start",
59
+ ...slots?.content,
60
+ className: cn("w-(--radix-popover-trigger-width) min-w-72", shouldShake && "pp-shake", slots?.content?.className),
61
+ onInteractOutside: (event) => {
62
+ slots?.content?.onInteractOutside?.(event);
63
+ if (event.defaultPrevented) return;
64
+ event.preventDefault();
65
+ requestClose();
66
+ },
67
+ onEscapeKeyDown: (event) => {
68
+ slots?.content?.onEscapeKeyDown?.(event);
69
+ if (event.defaultPrevented) return;
70
+ event.preventDefault();
71
+ requestClose();
72
+ },
73
+ children: [
74
+ /* @__PURE__ */ jsx(ShakeStyles, {}),
75
+ hasHeader && /* @__PURE__ */ jsxs("div", {
76
+ ...slots?.header,
77
+ className: cn("space-y-1 pb-3", slots?.header?.className),
78
+ children: [title != null && /* @__PURE__ */ jsx("h4", {
79
+ ...slots?.title,
80
+ className: cn("font-medium leading-none", slots?.title?.className),
81
+ children: title
82
+ }), overlayDescription != null && /* @__PURE__ */ jsx("p", {
83
+ ...slots?.description,
84
+ className: cn("text-muted-foreground text-sm", slots?.description?.className),
85
+ children: overlayDescription
86
+ })]
87
+ }),
88
+ open && /* @__PURE__ */ jsxs("div", {
89
+ ...slots?.body,
90
+ className: cn("grid", gapClass, slots?.body?.className),
91
+ children: [children, feedbackText != null && feedbackText !== "" && /* @__PURE__ */ jsx("p", {
92
+ className: cn("text-[0.8rem]", feedbackStatus === "error" && "text-destructive font-medium", feedbackStatus === "warning" && "text-amber-600", feedbackStatus === "success" && "text-green-600"),
93
+ children: feedbackText
94
+ })]
95
+ })
96
+ ]
97
+ })
98
+ ]
99
+ });
100
+ };
101
+ BasePopoverItem.displayName = "BasePopoverItem";
102
+
103
+ //#endregion
104
+ export { BasePopoverItem };
@@ -0,0 +1,16 @@
1
+ const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
2
+ const require_map_form_item_props = require('../form-item/map-form-item-props.cjs');
3
+ const require_BasePopoverItem = require('./BasePopoverItem.cjs');
4
+ let __formily_react = require("@formily/react");
5
+ __formily_react = require_rolldown_runtime.__toESM(__formily_react);
6
+
7
+ //#region src/components/popover-item/ConnectedPopoverItem.tsx
8
+ /**
9
+ * PopoverItem decorator connected to Formily field state.
10
+ * Maps field label, description, and validation state onto the decorator the
11
+ * same way FormItem does.
12
+ */
13
+ const PopoverItem = (0, __formily_react.connect)(require_BasePopoverItem.BasePopoverItem, (0, __formily_react.mapProps)(require_map_form_item_props.mapFormItemProps));
14
+
15
+ //#endregion
16
+ exports.PopoverItem = PopoverItem;
@@ -0,0 +1,15 @@
1
+ import { PopoverItemProps } from "./BasePopoverItem.cjs";
2
+ import * as react4 from "react";
3
+
4
+ //#region src/components/popover-item/ConnectedPopoverItem.d.ts
5
+
6
+ /**
7
+ * PopoverItem decorator connected to Formily field state.
8
+ * Maps field label, description, and validation state onto the decorator the
9
+ * same way FormItem does.
10
+ */
11
+ declare const PopoverItem: react4.ForwardRefExoticComponent<Omit<Partial<PopoverItemProps & {
12
+ children?: react4.ReactNode | undefined;
13
+ }>, "ref"> & react4.RefAttributes<unknown>>;
14
+ //#endregion
15
+ export { PopoverItem };
@@ -0,0 +1,15 @@
1
+ import { PopoverItemProps } from "./BasePopoverItem.js";
2
+ import * as react0 from "react";
3
+
4
+ //#region src/components/popover-item/ConnectedPopoverItem.d.ts
5
+
6
+ /**
7
+ * PopoverItem decorator connected to Formily field state.
8
+ * Maps field label, description, and validation state onto the decorator the
9
+ * same way FormItem does.
10
+ */
11
+ declare const PopoverItem: react0.ForwardRefExoticComponent<Omit<Partial<PopoverItemProps & {
12
+ children?: react0.ReactNode | undefined;
13
+ }>, "ref"> & react0.RefAttributes<unknown>>;
14
+ //#endregion
15
+ export { PopoverItem };
@@ -0,0 +1,14 @@
1
+ import { mapFormItemProps } from "../form-item/map-form-item-props.js";
2
+ import { BasePopoverItem } from "./BasePopoverItem.js";
3
+ import { connect, mapProps } from "@formily/react";
4
+
5
+ //#region src/components/popover-item/ConnectedPopoverItem.tsx
6
+ /**
7
+ * PopoverItem decorator connected to Formily field state.
8
+ * Maps field label, description, and validation state onto the decorator the
9
+ * same way FormItem does.
10
+ */
11
+ const PopoverItem = connect(BasePopoverItem, mapProps(mapFormItemProps));
12
+
13
+ //#endregion
14
+ export { PopoverItem };
@@ -0,0 +1,2 @@
1
+ const require_BasePopoverItem = require('./BasePopoverItem.cjs');
2
+ const require_ConnectedPopoverItem = require('./ConnectedPopoverItem.cjs');
@@ -0,0 +1,2 @@
1
+ import { BasePopoverItem, PopoverItemProps } from "./BasePopoverItem.cjs";
2
+ import { PopoverItem } from "./ConnectedPopoverItem.cjs";
@@ -0,0 +1,2 @@
1
+ import { BasePopoverItem, PopoverItemProps } from "./BasePopoverItem.js";
2
+ import { PopoverItem } from "./ConnectedPopoverItem.js";
@@ -0,0 +1,2 @@
1
+ import { BasePopoverItem } from "./BasePopoverItem.js";
2
+ import { PopoverItem } from "./ConnectedPopoverItem.js";
@@ -0,0 +1,127 @@
1
+ import { defineProps } from "../../mcp/src/utils.js";
2
+
3
+ //#region src/components/popover-item/mcp.ts
4
+ const meta = {
5
+ name: "PopoverItem",
6
+ category: "Formily",
7
+ description: "A Formily decorator used in place of FormItem (`x-decorator: 'PopoverItem'`). It renders the field's label, description, and validation feedback like FormItem, but puts a trigger button where the input would sit and moves the field's own component into a popover anchored to the button.",
8
+ htmlElement: "div",
9
+ props: defineProps({
10
+ label: "Label content or accessible label for the component.",
11
+ description: "Description content rendered with the component.",
12
+ trigger: {
13
+ description: "Props for the trigger button, e.g. `{ label: 'Write a bio' }`. Without a label it reads `Add <title>` while the field is empty and `Edit <title>` once it holds a value (`item` when the field has no title). Accepts the button's other props too (`icon`, `className`, …). An x-reaction can set this via `decoratorProps.trigger`.",
14
+ defaultValue: "`Add <title>` / `Edit <title>`"
15
+ },
16
+ open: {
17
+ description: "Controlled open state of the popover.",
18
+ type: "boolean"
19
+ },
20
+ defaultOpen: {
21
+ description: "Initial open state when uncontrolled.",
22
+ type: "boolean",
23
+ defaultValue: "false"
24
+ },
25
+ onOpenChange: "Called when the popover open state changes.",
26
+ validateOnClose: {
27
+ description: "When true (default), closing validates the field and keeps the popover open (with a shake) while it is invalid. Set false to always close.",
28
+ type: "boolean",
29
+ defaultValue: "true"
30
+ },
31
+ modal: {
32
+ description: "When true, interaction outside the popover is blocked while it is open.",
33
+ type: "boolean",
34
+ defaultValue: "false"
35
+ },
36
+ popover: "The popover itself: `{ title, description, slots }`, e.g. `{ title: 'Notes', slots: { content: { className: 'w-96' } } }`. Title and description default to the field's label and description; `slots` takes props for `content`, `header`, `title`, `description`, and `body`.",
37
+ slots: "Slot props forwarded to the FormItem parts (label, description, error).",
38
+ descriptionPlacement: "Forwarded to the underlying FormItem.",
39
+ requiredMark: "Forwarded to the underlying FormItem.",
40
+ asterisk: "Forwarded to the underlying FormItem.",
41
+ feedbackStatus: "Forwarded to the underlying FormItem.",
42
+ feedbackText: "Forwarded to the underlying FormItem."
43
+ }),
44
+ examples: [
45
+ {
46
+ title: "Edit a single field in a popover",
47
+ code: `{
48
+ type: 'object',
49
+ properties: {
50
+ age: {
51
+ type: 'number',
52
+ title: 'Age',
53
+ description: 'Enter your age in years.',
54
+ default: 25,
55
+ 'x-decorator': 'PopoverItem',
56
+ 'x-component': 'NumberInput',
57
+ },
58
+ },
59
+ }`
60
+ },
61
+ {
62
+ title: "Declarative schema field",
63
+ code: `<SchemaField.String name="bio" title="Bio" x-decorator="PopoverItem" x-component="Textarea" />`
64
+ },
65
+ {
66
+ title: "Trigger label driven by an x-reaction",
67
+ code: `{
68
+ type: 'string',
69
+ title: 'Bio',
70
+ 'x-decorator': 'PopoverItem',
71
+ 'x-component': 'Textarea',
72
+ // Decorator props come from decoratorProps, not componentProps.
73
+ 'x-reactions': {
74
+ fulfill: {
75
+ state: {
76
+ decoratorProps: {
77
+ trigger: {
78
+ label: "{{$self.value ? 'Edit bio' : 'Write a bio'}}",
79
+ },
80
+ },
81
+ },
82
+ },
83
+ },
84
+ }`
85
+ },
86
+ {
87
+ title: "A whole object edited in one popover",
88
+ code: `{
89
+ type: 'object',
90
+ title: 'Profile',
91
+ 'x-decorator': 'PopoverItem',
92
+ // type: 'object' resolves to ObjectContainer. Turn off its own label and
93
+ // description — the popover header already shows them — and use the flat
94
+ // variant so the card chrome does not double up inside the popover.
95
+ 'x-component-props': { variant: 'flat', label: false, description: false },
96
+ properties: {
97
+ firstName: { type: 'string', title: 'First Name' },
98
+ lastName: { type: 'string', title: 'Last Name', required: true },
99
+ },
100
+ }`
101
+ }
102
+ ],
103
+ notes: [
104
+ "Works on an object too: decorating a `type: object` field puts its whole form in the popover, and closing validates every field inside it, at any depth.",
105
+ "Swap in for FormItem on any field — the field keeps its own `x-component`, so validation, x-reactions, and component props behave exactly as under FormItem.",
106
+ "Edits commit to the form as the user types; there is no draft/Save step.",
107
+ "Closing (Escape or an outside click) validates the field first. An invalid field keeps the popover open and shakes it.",
108
+ "While the popover is closed the input stays mounted in a hidden container, so component state and reactions behave as if it were always rendered.",
109
+ "The trigger renders in an error state, and the label turns red, while the field has a validation error — the message appears under the trigger and inside the popover.",
110
+ "The popover content matches the trigger width by default; override with `popover.slots.content.className`."
111
+ ],
112
+ keywords: [
113
+ "formily",
114
+ "decorator",
115
+ "popover",
116
+ "field",
117
+ "form-item"
118
+ ],
119
+ related: [
120
+ "FormItem",
121
+ "DialogItem",
122
+ "ObjectContainer"
123
+ ]
124
+ };
125
+
126
+ //#endregion
127
+ export { meta };
@@ -1,5 +1,5 @@
1
1
  import { ComponentProps, FC } from "react";
2
- import * as react_jsx_runtime2 from "react/jsx-runtime";
2
+ import * as react_jsx_runtime0 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_runtime2.JSX.Element;
18
+ declare function Radio(props: RadioProps): react_jsx_runtime0.JSX.Element;
19
19
  declare namespace Radio {
20
20
  var displayName: string;
21
21
  }