@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.
- package/dist/components/date-picker/DatePicker.d.cts +3 -3
- package/dist/components/date-picker/DatePicker.d.ts +3 -3
- package/dist/components/dialog-item/BaseDialogItem.cjs +114 -0
- package/dist/components/dialog-item/BaseDialogItem.d.cts +56 -0
- package/dist/components/dialog-item/BaseDialogItem.d.ts +56 -0
- package/dist/components/dialog-item/BaseDialogItem.js +109 -0
- package/dist/components/dialog-item/ConnectedDialogItem.cjs +16 -0
- package/dist/components/dialog-item/ConnectedDialogItem.d.cts +15 -0
- package/dist/components/dialog-item/ConnectedDialogItem.d.ts +15 -0
- package/dist/components/dialog-item/ConnectedDialogItem.js +14 -0
- package/dist/components/dialog-item/index.cjs +2 -0
- package/dist/components/dialog-item/index.d.cts +2 -0
- package/dist/components/dialog-item/index.d.ts +2 -0
- package/dist/components/dialog-item/index.js +2 -0
- package/dist/components/dialog-item/mcp.js +127 -0
- package/dist/components/form/Form.d.cts +2 -2
- package/dist/components/form/Form.d.ts +2 -2
- package/dist/components/form-grid/FormGrid.d.cts +2 -2
- package/dist/components/form-grid/FormGrid.d.ts +2 -2
- package/dist/components/form-item/ConnectedFormItem.cjs +2 -34
- package/dist/components/form-item/ConnectedFormItem.d.cts +4 -4
- package/dist/components/form-item/ConnectedFormItem.d.ts +4 -4
- package/dist/components/form-item/ConnectedFormItem.js +3 -34
- package/dist/components/form-item/map-form-item-props.cjs +50 -0
- package/dist/components/form-item/map-form-item-props.js +47 -0
- package/dist/components/overlay-common/OverlayFields.cjs +26 -0
- package/dist/components/overlay-common/OverlayFields.d.cts +1 -0
- package/dist/components/overlay-common/OverlayFields.d.ts +1 -0
- package/dist/components/overlay-common/OverlayFields.js +24 -0
- package/dist/components/overlay-common/OverlayTrigger.cjs +27 -0
- package/dist/components/overlay-common/OverlayTrigger.d.cts +15 -0
- package/dist/components/overlay-common/OverlayTrigger.d.ts +15 -0
- package/dist/components/overlay-common/OverlayTrigger.js +23 -0
- package/dist/components/overlay-common/constants.cjs +10 -0
- package/dist/components/overlay-common/constants.js +9 -0
- package/dist/components/overlay-common/index.cjs +5 -0
- package/dist/components/overlay-common/index.d.cts +4 -0
- package/dist/components/overlay-common/index.d.ts +4 -0
- package/dist/components/overlay-common/index.js +5 -0
- package/dist/components/overlay-common/is-empty-field-value.cjs +23 -0
- package/dist/components/overlay-common/is-empty-field-value.js +22 -0
- package/dist/components/overlay-common/overlay-types.d.cts +27 -0
- package/dist/components/overlay-common/overlay-types.d.ts +27 -0
- package/dist/components/overlay-common/use-overlay.cjs +110 -0
- package/dist/components/overlay-common/use-overlay.d.cts +1 -0
- package/dist/components/overlay-common/use-overlay.d.ts +1 -0
- package/dist/components/overlay-common/use-overlay.js +107 -0
- package/dist/components/popover-item/BasePopoverItem.cjs +108 -0
- package/dist/components/popover-item/BasePopoverItem.d.cts +57 -0
- package/dist/components/popover-item/BasePopoverItem.d.ts +57 -0
- package/dist/components/popover-item/BasePopoverItem.js +104 -0
- package/dist/components/popover-item/ConnectedPopoverItem.cjs +16 -0
- package/dist/components/popover-item/ConnectedPopoverItem.d.cts +15 -0
- package/dist/components/popover-item/ConnectedPopoverItem.d.ts +15 -0
- package/dist/components/popover-item/ConnectedPopoverItem.js +14 -0
- package/dist/components/popover-item/index.cjs +2 -0
- package/dist/components/popover-item/index.d.cts +2 -0
- package/dist/components/popover-item/index.d.ts +2 -0
- package/dist/components/popover-item/index.js +2 -0
- package/dist/components/popover-item/mcp.js +127 -0
- package/dist/components/radio/Radio.d.ts +2 -2
- package/dist/components/row/Row.d.ts +2 -2
- package/dist/components/schema-field/schema-field-basics.cjs +8 -2
- package/dist/components/schema-field/schema-field-basics.d.cts +344 -270
- package/dist/components/schema-field/schema-field-basics.d.ts +337 -263
- package/dist/components/schema-field/schema-field-basics.js +8 -2
- package/dist/components/schema-field/schema-field-extended.d.cts +498 -424
- package/dist/components/schema-field/schema-field-extended.d.ts +480 -406
- package/dist/components/schema-field/schema-field.d.cts +425 -351
- package/dist/components/schema-field/schema-field.d.ts +425 -351
- package/dist/generated/mcp-registry.js +56 -52
- package/dist/index.cjs +12 -2
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +9 -3
- package/package.json +2 -2
|
@@ -1,47 +1,15 @@
|
|
|
1
1
|
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
2
|
const require_BaseFormItem = require('./BaseFormItem.cjs');
|
|
3
|
+
const require_map_form_item_props = require('./map-form-item-props.cjs');
|
|
3
4
|
let __formily_react = require("@formily/react");
|
|
4
5
|
__formily_react = require_rolldown_runtime.__toESM(__formily_react);
|
|
5
|
-
let __formily_core = require("@formily/core");
|
|
6
|
-
__formily_core = require_rolldown_runtime.__toESM(__formily_core);
|
|
7
6
|
|
|
8
7
|
//#region src/components/form-item/ConnectedFormItem.tsx
|
|
9
8
|
/**
|
|
10
9
|
* FormItem component connected to Formily field state.
|
|
11
10
|
* Automatically maps field validation state to component props.
|
|
12
11
|
*/
|
|
13
|
-
const FormItem = (0, __formily_react.connect)(require_BaseFormItem.BaseFormItem, (0, __formily_react.mapProps)(
|
|
14
|
-
const schema = (0, __formily_react.useFieldSchema)();
|
|
15
|
-
if ((0, __formily_core.isVoidField)(field)) return {
|
|
16
|
-
label: field.title ?? props.label,
|
|
17
|
-
description: props.description ?? field.description,
|
|
18
|
-
requiredMark: props.requiredMark !== void 0 ? props.requiredMark : props.asterisk
|
|
19
|
-
};
|
|
20
|
-
const takeFeedbackStatus = () => {
|
|
21
|
-
if (field.validating) return void 0;
|
|
22
|
-
if (field.selfErrors?.length) return "error";
|
|
23
|
-
if (field.selfWarnings?.length) return "warning";
|
|
24
|
-
if (field.selfSuccesses?.length) return "success";
|
|
25
|
-
};
|
|
26
|
-
const takeFeedbackText = () => {
|
|
27
|
-
if (field.validating) return void 0;
|
|
28
|
-
if (props.feedbackText != null) return props.feedbackText;
|
|
29
|
-
if (field.selfErrors?.length) return field.selfErrors.join(", ");
|
|
30
|
-
if (field.selfWarnings?.length) return field.selfWarnings.join(", ");
|
|
31
|
-
if (field.selfSuccesses?.length) return field.selfSuccesses.join(", ");
|
|
32
|
-
};
|
|
33
|
-
let resolvedRequiredMark = props.requiredMark;
|
|
34
|
-
if (resolvedRequiredMark === void 0) if (props.asterisk !== void 0) resolvedRequiredMark = Boolean(props.asterisk);
|
|
35
|
-
else if (schema.parent && Array.isArray(schema.parent.required) && schema.parent.required.includes(schema.name)) resolvedRequiredMark = true;
|
|
36
|
-
else resolvedRequiredMark = field.required && field.pattern !== "readPretty";
|
|
37
|
-
return {
|
|
38
|
-
label: props.label ?? field.title,
|
|
39
|
-
description: props.description ?? field.description,
|
|
40
|
-
feedbackStatus: takeFeedbackStatus(),
|
|
41
|
-
feedbackText: takeFeedbackText(),
|
|
42
|
-
requiredMark: resolvedRequiredMark
|
|
43
|
-
};
|
|
44
|
-
}));
|
|
12
|
+
const FormItem = (0, __formily_react.connect)(require_BaseFormItem.BaseFormItem, (0, __formily_react.mapProps)(require_map_form_item_props.mapFormItemProps));
|
|
45
13
|
|
|
46
14
|
//#endregion
|
|
47
15
|
exports.FormItem = FormItem;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { FormItemProps } from "./form-item-types.cjs";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react1450 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:
|
|
10
|
-
children?:
|
|
11
|
-
}>, "ref"> &
|
|
9
|
+
declare const FormItem: react1450.ForwardRefExoticComponent<Omit<Partial<FormItemProps & {
|
|
10
|
+
children?: react1450.ReactNode | undefined;
|
|
11
|
+
}>, "ref"> & react1450.RefAttributes<unknown>>;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { FormItem };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { FormItemProps } from "./form-item-types.js";
|
|
2
|
-
import * as
|
|
2
|
+
import * as react1450 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:
|
|
10
|
-
children?:
|
|
11
|
-
}>, "ref"> &
|
|
9
|
+
declare const FormItem: react1450.ForwardRefExoticComponent<Omit<Partial<FormItemProps & {
|
|
10
|
+
children?: react1450.ReactNode | undefined;
|
|
11
|
+
}>, "ref"> & react1450.RefAttributes<unknown>>;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { FormItem };
|
|
@@ -1,44 +1,13 @@
|
|
|
1
1
|
import { BaseFormItem } from "./BaseFormItem.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { mapFormItemProps } from "./map-form-item-props.js";
|
|
3
|
+
import { connect, mapProps } from "@formily/react";
|
|
4
4
|
|
|
5
5
|
//#region src/components/form-item/ConnectedFormItem.tsx
|
|
6
6
|
/**
|
|
7
7
|
* FormItem component connected to Formily field state.
|
|
8
8
|
* Automatically maps field validation state to component props.
|
|
9
9
|
*/
|
|
10
|
-
const FormItem = connect(BaseFormItem, mapProps(
|
|
11
|
-
const schema = useFieldSchema();
|
|
12
|
-
if (isVoidField(field)) return {
|
|
13
|
-
label: field.title ?? props.label,
|
|
14
|
-
description: props.description ?? field.description,
|
|
15
|
-
requiredMark: props.requiredMark !== void 0 ? props.requiredMark : props.asterisk
|
|
16
|
-
};
|
|
17
|
-
const takeFeedbackStatus = () => {
|
|
18
|
-
if (field.validating) return void 0;
|
|
19
|
-
if (field.selfErrors?.length) return "error";
|
|
20
|
-
if (field.selfWarnings?.length) return "warning";
|
|
21
|
-
if (field.selfSuccesses?.length) return "success";
|
|
22
|
-
};
|
|
23
|
-
const takeFeedbackText = () => {
|
|
24
|
-
if (field.validating) return void 0;
|
|
25
|
-
if (props.feedbackText != null) return props.feedbackText;
|
|
26
|
-
if (field.selfErrors?.length) return field.selfErrors.join(", ");
|
|
27
|
-
if (field.selfWarnings?.length) return field.selfWarnings.join(", ");
|
|
28
|
-
if (field.selfSuccesses?.length) return field.selfSuccesses.join(", ");
|
|
29
|
-
};
|
|
30
|
-
let resolvedRequiredMark = props.requiredMark;
|
|
31
|
-
if (resolvedRequiredMark === void 0) if (props.asterisk !== void 0) resolvedRequiredMark = Boolean(props.asterisk);
|
|
32
|
-
else if (schema.parent && Array.isArray(schema.parent.required) && schema.parent.required.includes(schema.name)) resolvedRequiredMark = true;
|
|
33
|
-
else resolvedRequiredMark = field.required && field.pattern !== "readPretty";
|
|
34
|
-
return {
|
|
35
|
-
label: props.label ?? field.title,
|
|
36
|
-
description: props.description ?? field.description,
|
|
37
|
-
feedbackStatus: takeFeedbackStatus(),
|
|
38
|
-
feedbackText: takeFeedbackText(),
|
|
39
|
-
requiredMark: resolvedRequiredMark
|
|
40
|
-
};
|
|
41
|
-
}));
|
|
10
|
+
const FormItem = connect(BaseFormItem, mapProps(mapFormItemProps));
|
|
42
11
|
|
|
43
12
|
//#endregion
|
|
44
13
|
export { FormItem };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let __formily_react = require("@formily/react");
|
|
3
|
+
__formily_react = require_rolldown_runtime.__toESM(__formily_react);
|
|
4
|
+
let __formily_core = require("@formily/core");
|
|
5
|
+
__formily_core = require_rolldown_runtime.__toESM(__formily_core);
|
|
6
|
+
|
|
7
|
+
//#region src/components/form-item/map-form-item-props.ts
|
|
8
|
+
/**
|
|
9
|
+
* Maps Formily field state onto FormItem props (label, description, validation
|
|
10
|
+
* feedback, required mark).
|
|
11
|
+
*
|
|
12
|
+
* Shared by every decorator that presents a field the way FormItem does —
|
|
13
|
+
* FormItem itself plus the overlay decorators — so they stay in step.
|
|
14
|
+
* Runs inside `mapProps`, which is why calling hooks here is allowed.
|
|
15
|
+
*/
|
|
16
|
+
function mapFormItemProps(props, field) {
|
|
17
|
+
const schema = (0, __formily_react.useFieldSchema)();
|
|
18
|
+
if ((0, __formily_core.isVoidField)(field)) return {
|
|
19
|
+
label: field.title ?? props.label,
|
|
20
|
+
description: props.description ?? field.description,
|
|
21
|
+
requiredMark: props.requiredMark !== void 0 ? props.requiredMark : props.asterisk
|
|
22
|
+
};
|
|
23
|
+
const takeFeedbackStatus = () => {
|
|
24
|
+
if (field.validating) return void 0;
|
|
25
|
+
if (field.selfErrors?.length) return "error";
|
|
26
|
+
if (field.selfWarnings?.length) return "warning";
|
|
27
|
+
if (field.selfSuccesses?.length) return "success";
|
|
28
|
+
};
|
|
29
|
+
const takeFeedbackText = () => {
|
|
30
|
+
if (field.validating) return void 0;
|
|
31
|
+
if (props.feedbackText != null) return props.feedbackText;
|
|
32
|
+
if (field.selfErrors?.length) return field.selfErrors.join(", ");
|
|
33
|
+
if (field.selfWarnings?.length) return field.selfWarnings.join(", ");
|
|
34
|
+
if (field.selfSuccesses?.length) return field.selfSuccesses.join(", ");
|
|
35
|
+
};
|
|
36
|
+
let resolvedRequiredMark = props.requiredMark;
|
|
37
|
+
if (resolvedRequiredMark === void 0) if (props.asterisk !== void 0) resolvedRequiredMark = Boolean(props.asterisk);
|
|
38
|
+
else if (schema.parent && Array.isArray(schema.parent.required) && schema.parent.required.includes(schema.name)) resolvedRequiredMark = true;
|
|
39
|
+
else resolvedRequiredMark = field.required && field.pattern !== "readPretty";
|
|
40
|
+
return {
|
|
41
|
+
label: props.label ?? field.title,
|
|
42
|
+
description: props.description ?? field.description,
|
|
43
|
+
feedbackStatus: takeFeedbackStatus(),
|
|
44
|
+
feedbackText: takeFeedbackText(),
|
|
45
|
+
requiredMark: resolvedRequiredMark
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
exports.mapFormItemProps = mapFormItemProps;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useFieldSchema } from "@formily/react";
|
|
2
|
+
import { isVoidField } from "@formily/core";
|
|
3
|
+
|
|
4
|
+
//#region src/components/form-item/map-form-item-props.ts
|
|
5
|
+
/**
|
|
6
|
+
* Maps Formily field state onto FormItem props (label, description, validation
|
|
7
|
+
* feedback, required mark).
|
|
8
|
+
*
|
|
9
|
+
* Shared by every decorator that presents a field the way FormItem does —
|
|
10
|
+
* FormItem itself plus the overlay decorators — so they stay in step.
|
|
11
|
+
* Runs inside `mapProps`, which is why calling hooks here is allowed.
|
|
12
|
+
*/
|
|
13
|
+
function mapFormItemProps(props, field) {
|
|
14
|
+
const schema = useFieldSchema();
|
|
15
|
+
if (isVoidField(field)) return {
|
|
16
|
+
label: field.title ?? props.label,
|
|
17
|
+
description: props.description ?? field.description,
|
|
18
|
+
requiredMark: props.requiredMark !== void 0 ? props.requiredMark : props.asterisk
|
|
19
|
+
};
|
|
20
|
+
const takeFeedbackStatus = () => {
|
|
21
|
+
if (field.validating) return void 0;
|
|
22
|
+
if (field.selfErrors?.length) return "error";
|
|
23
|
+
if (field.selfWarnings?.length) return "warning";
|
|
24
|
+
if (field.selfSuccesses?.length) return "success";
|
|
25
|
+
};
|
|
26
|
+
const takeFeedbackText = () => {
|
|
27
|
+
if (field.validating) return void 0;
|
|
28
|
+
if (props.feedbackText != null) return props.feedbackText;
|
|
29
|
+
if (field.selfErrors?.length) return field.selfErrors.join(", ");
|
|
30
|
+
if (field.selfWarnings?.length) return field.selfWarnings.join(", ");
|
|
31
|
+
if (field.selfSuccesses?.length) return field.selfSuccesses.join(", ");
|
|
32
|
+
};
|
|
33
|
+
let resolvedRequiredMark = props.requiredMark;
|
|
34
|
+
if (resolvedRequiredMark === void 0) if (props.asterisk !== void 0) resolvedRequiredMark = Boolean(props.asterisk);
|
|
35
|
+
else if (schema.parent && Array.isArray(schema.parent.required) && schema.parent.required.includes(schema.name)) resolvedRequiredMark = true;
|
|
36
|
+
else resolvedRequiredMark = field.required && field.pattern !== "readPretty";
|
|
37
|
+
return {
|
|
38
|
+
label: props.label ?? field.title,
|
|
39
|
+
description: props.description ?? field.description,
|
|
40
|
+
feedbackStatus: takeFeedbackStatus(),
|
|
41
|
+
feedbackText: takeFeedbackText(),
|
|
42
|
+
requiredMark: resolvedRequiredMark
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
export { mapFormItemProps };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
3
|
+
react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
|
|
4
|
+
|
|
5
|
+
//#region src/components/overlay-common/OverlayFields.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Keeps an object's fields mounted while its overlay (dialog/popover) is closed.
|
|
8
|
+
*
|
|
9
|
+
* Formily destroys a field instance when its component unmounts, and the fields
|
|
10
|
+
* inside a closed overlay are unmounted. Without this, `form.submit()` would
|
|
11
|
+
* skip them entirely — a required field the user never opened would pass
|
|
12
|
+
* validation. Rendering them in a hidden container keeps the field instances
|
|
13
|
+
* alive so form-level validation still covers them.
|
|
14
|
+
*
|
|
15
|
+
* `hidden` (rather than unmounting) is the same approach ListItem uses to keep
|
|
16
|
+
* array item fields attached while a row is collapsed.
|
|
17
|
+
*/
|
|
18
|
+
const OverlayFields = ({ children }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
19
|
+
hidden: true,
|
|
20
|
+
"aria-hidden": "true",
|
|
21
|
+
children
|
|
22
|
+
});
|
|
23
|
+
OverlayFields.displayName = "OverlayFields";
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
exports.OverlayFields = OverlayFields;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React from "react";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import React from "react";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
|
|
3
|
+
//#region src/components/overlay-common/OverlayFields.tsx
|
|
4
|
+
/**
|
|
5
|
+
* Keeps an object's fields mounted while its overlay (dialog/popover) is closed.
|
|
6
|
+
*
|
|
7
|
+
* Formily destroys a field instance when its component unmounts, and the fields
|
|
8
|
+
* inside a closed overlay are unmounted. Without this, `form.submit()` would
|
|
9
|
+
* skip them entirely — a required field the user never opened would pass
|
|
10
|
+
* validation. Rendering them in a hidden container keeps the field instances
|
|
11
|
+
* alive so form-level validation still covers them.
|
|
12
|
+
*
|
|
13
|
+
* `hidden` (rather than unmounting) is the same approach ListItem uses to keep
|
|
14
|
+
* array item fields attached while a row is collapsed.
|
|
15
|
+
*/
|
|
16
|
+
const OverlayFields = ({ children }) => /* @__PURE__ */ jsx("div", {
|
|
17
|
+
hidden: true,
|
|
18
|
+
"aria-hidden": "true",
|
|
19
|
+
children
|
|
20
|
+
});
|
|
21
|
+
OverlayFields.displayName = "OverlayFields";
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
export { OverlayFields };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
let lucide_react = require("lucide-react");
|
|
3
|
+
lucide_react = require_rolldown_runtime.__toESM(lucide_react);
|
|
4
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
+
react_jsx_runtime = require_rolldown_runtime.__toESM(react_jsx_runtime);
|
|
6
|
+
let __pixpilot_shadcn = require("@pixpilot/shadcn");
|
|
7
|
+
__pixpilot_shadcn = require_rolldown_runtime.__toESM(__pixpilot_shadcn);
|
|
8
|
+
|
|
9
|
+
//#region src/components/overlay-common/OverlayTrigger.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Button that opens an object overlay (dialog or popover).
|
|
12
|
+
*/
|
|
13
|
+
const OverlayTrigger = ({ label, icon, invalid, className,...rest }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(__pixpilot_shadcn.Button, {
|
|
14
|
+
type: "button",
|
|
15
|
+
variant: "outline",
|
|
16
|
+
"aria-invalid": invalid === true ? true : void 0,
|
|
17
|
+
...rest,
|
|
18
|
+
className: (0, __pixpilot_shadcn.cn)("form-object-trigger w-full justify-between gap-4 font-normal", invalid === true && "border-destructive text-destructive", className),
|
|
19
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
20
|
+
className: "min-w-0 truncate text-left",
|
|
21
|
+
children: label
|
|
22
|
+
}), icon ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRightIcon, { className: "size-4 shrink-0 opacity-50" })]
|
|
23
|
+
});
|
|
24
|
+
OverlayTrigger.displayName = "OverlayTrigger";
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
exports.OverlayTrigger = OverlayTrigger;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SyncReactNode } from "../../types/react.cjs";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Button } from "@pixpilot/shadcn";
|
|
4
|
+
|
|
5
|
+
//#region src/components/overlay-common/OverlayTrigger.d.ts
|
|
6
|
+
interface OverlayTriggerProps extends Omit<React.ComponentProps<typeof Button>, 'children'> {
|
|
7
|
+
/** Text of the trigger button. */
|
|
8
|
+
label?: SyncReactNode;
|
|
9
|
+
/** Icon rendered at the trailing edge. Defaults to a chevron. */
|
|
10
|
+
icon?: React.ReactNode;
|
|
11
|
+
/** Renders the trigger in an error state. */
|
|
12
|
+
invalid?: boolean;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { OverlayTriggerProps };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SyncReactNode } from "../../types/react.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { Button } from "@pixpilot/shadcn";
|
|
4
|
+
|
|
5
|
+
//#region src/components/overlay-common/OverlayTrigger.d.ts
|
|
6
|
+
interface OverlayTriggerProps extends Omit<React.ComponentProps<typeof Button>, 'children'> {
|
|
7
|
+
/** Text of the trigger button. */
|
|
8
|
+
label?: SyncReactNode;
|
|
9
|
+
/** Icon rendered at the trailing edge. Defaults to a chevron. */
|
|
10
|
+
icon?: React.ReactNode;
|
|
11
|
+
/** Renders the trigger in an error state. */
|
|
12
|
+
invalid?: boolean;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { OverlayTriggerProps };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ChevronRightIcon } from "lucide-react";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Button, cn } from "@pixpilot/shadcn";
|
|
4
|
+
|
|
5
|
+
//#region src/components/overlay-common/OverlayTrigger.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Button that opens an object overlay (dialog or popover).
|
|
8
|
+
*/
|
|
9
|
+
const OverlayTrigger = ({ label, icon, invalid, className,...rest }) => /* @__PURE__ */ jsxs(Button, {
|
|
10
|
+
type: "button",
|
|
11
|
+
variant: "outline",
|
|
12
|
+
"aria-invalid": invalid === true ? true : void 0,
|
|
13
|
+
...rest,
|
|
14
|
+
className: cn("form-object-trigger w-full justify-between gap-4 font-normal", invalid === true && "border-destructive text-destructive", className),
|
|
15
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
16
|
+
className: "min-w-0 truncate text-left",
|
|
17
|
+
children: label
|
|
18
|
+
}), icon ?? /* @__PURE__ */ jsx(ChevronRightIcon, { className: "size-4 shrink-0 opacity-50" })]
|
|
19
|
+
});
|
|
20
|
+
OverlayTrigger.displayName = "OverlayTrigger";
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { OverlayTrigger };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/components/overlay-common/constants.ts
|
|
3
|
+
/**
|
|
4
|
+
* Fallback noun for the DialogItem / PopoverItem trigger when the field has
|
|
5
|
+
* no title — e.g. "Add item" / "Edit item".
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_TRIGGER_NOUN = "item";
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
exports.DEFAULT_TRIGGER_NOUN = DEFAULT_TRIGGER_NOUN;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//#region src/components/overlay-common/constants.ts
|
|
2
|
+
/**
|
|
3
|
+
* Fallback noun for the DialogItem / PopoverItem trigger when the field has
|
|
4
|
+
* no title — e.g. "Add item" / "Edit item".
|
|
5
|
+
*/
|
|
6
|
+
const DEFAULT_TRIGGER_NOUN = "item";
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
export { DEFAULT_TRIGGER_NOUN };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
const require_constants = require('./constants.cjs');
|
|
2
|
+
const require_is_empty_field_value = require('./is-empty-field-value.cjs');
|
|
3
|
+
const require_OverlayFields = require('./OverlayFields.cjs');
|
|
4
|
+
const require_OverlayTrigger = require('./OverlayTrigger.cjs');
|
|
5
|
+
const require_use_overlay = require('./use-overlay.cjs');
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DEFAULT_TRIGGER_NOUN } from "./constants.js";
|
|
2
|
+
import { isEmptyFieldValue } from "./is-empty-field-value.js";
|
|
3
|
+
import { OverlayFields } from "./OverlayFields.js";
|
|
4
|
+
import { OverlayTrigger } from "./OverlayTrigger.js";
|
|
5
|
+
import { useOverlay } from "./use-overlay.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/components/overlay-common/is-empty-field-value.ts
|
|
3
|
+
/**
|
|
4
|
+
* Whether a field value holds nothing the user would consider data.
|
|
5
|
+
*
|
|
6
|
+
* Used to pick the trigger verb: an object with no data reads "Add <title>",
|
|
7
|
+
* one with data reads "Edit <title>".
|
|
8
|
+
*
|
|
9
|
+
* Comparing `value` against `initialValue` does not work here: Formily gives an
|
|
10
|
+
* object field an initial value of `{}` while its `initialValue` stays
|
|
11
|
+
* undefined, so an untouched object would always look changed. Empty strings
|
|
12
|
+
* count as empty because clearing an input leaves `''` behind, but `false` and
|
|
13
|
+
* `0` are real values.
|
|
14
|
+
*/
|
|
15
|
+
function isEmptyFieldValue(value) {
|
|
16
|
+
if (value == null || value === "") return true;
|
|
17
|
+
if (Array.isArray(value)) return value.every(isEmptyFieldValue);
|
|
18
|
+
if (typeof value === "object") return Object.values(value).every(isEmptyFieldValue);
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.isEmptyFieldValue = isEmptyFieldValue;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
//#region src/components/overlay-common/is-empty-field-value.ts
|
|
2
|
+
/**
|
|
3
|
+
* Whether a field value holds nothing the user would consider data.
|
|
4
|
+
*
|
|
5
|
+
* Used to pick the trigger verb: an object with no data reads "Add <title>",
|
|
6
|
+
* one with data reads "Edit <title>".
|
|
7
|
+
*
|
|
8
|
+
* Comparing `value` against `initialValue` does not work here: Formily gives an
|
|
9
|
+
* object field an initial value of `{}` while its `initialValue` stays
|
|
10
|
+
* undefined, so an untouched object would always look changed. Empty strings
|
|
11
|
+
* count as empty because clearing an input leaves `''` behind, but `false` and
|
|
12
|
+
* `0` are real values.
|
|
13
|
+
*/
|
|
14
|
+
function isEmptyFieldValue(value) {
|
|
15
|
+
if (value == null || value === "") return true;
|
|
16
|
+
if (Array.isArray(value)) return value.every(isEmptyFieldValue);
|
|
17
|
+
if (typeof value === "object") return Object.values(value).every(isEmptyFieldValue);
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { isEmptyFieldValue };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SyncReactNode } from "../../types/react.cjs";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/components/overlay-common/overlay-types.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The overlay itself — the `dialog` prop on DialogItem and the `popover` prop
|
|
8
|
+
* on PopoverItem.
|
|
9
|
+
*
|
|
10
|
+
* `TSlots` differs per overlay (only a dialog has a footer), so each component
|
|
11
|
+
* supplies its own slot map.
|
|
12
|
+
*/
|
|
13
|
+
interface OverlayProps<TSlots> {
|
|
14
|
+
/** Heading inside the overlay. Defaults to the field label. */
|
|
15
|
+
title?: SyncReactNode;
|
|
16
|
+
/** Description inside the overlay. Defaults to the field description. */
|
|
17
|
+
description?: SyncReactNode;
|
|
18
|
+
/** Props for the overlay's internal parts. */
|
|
19
|
+
slots?: TSlots;
|
|
20
|
+
}
|
|
21
|
+
/** Slots every overlay has, whatever kind it is. */
|
|
22
|
+
interface OverlayBaseSlots {
|
|
23
|
+
header?: React.ComponentProps<'div'>;
|
|
24
|
+
body?: React.ComponentProps<'div'>;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { OverlayBaseSlots, OverlayProps };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SyncReactNode } from "../../types/react.js";
|
|
2
|
+
import React from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/components/overlay-common/overlay-types.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The overlay itself — the `dialog` prop on DialogItem and the `popover` prop
|
|
8
|
+
* on PopoverItem.
|
|
9
|
+
*
|
|
10
|
+
* `TSlots` differs per overlay (only a dialog has a footer), so each component
|
|
11
|
+
* supplies its own slot map.
|
|
12
|
+
*/
|
|
13
|
+
interface OverlayProps<TSlots> {
|
|
14
|
+
/** Heading inside the overlay. Defaults to the field label. */
|
|
15
|
+
title?: SyncReactNode;
|
|
16
|
+
/** Description inside the overlay. Defaults to the field description. */
|
|
17
|
+
description?: SyncReactNode;
|
|
18
|
+
/** Props for the overlay's internal parts. */
|
|
19
|
+
slots?: TSlots;
|
|
20
|
+
}
|
|
21
|
+
/** Slots every overlay has, whatever kind it is. */
|
|
22
|
+
interface OverlayBaseSlots {
|
|
23
|
+
header?: React.ComponentProps<'div'>;
|
|
24
|
+
body?: React.ComponentProps<'div'>;
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { OverlayBaseSlots, OverlayProps };
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_resolve_responsive_space = require('../../utils/resolve-responsive-space.cjs');
|
|
3
|
+
const require_use_description = require('../../hooks/use-description.cjs');
|
|
4
|
+
const require_use_form_context = require('../../hooks/use-form-context.cjs');
|
|
5
|
+
const require_use_label = require('../../hooks/use-label.cjs');
|
|
6
|
+
require('../../hooks/index.cjs');
|
|
7
|
+
const require_use_shake_animation = require('../array-common/use-shake-animation.cjs');
|
|
8
|
+
require('../array-common/index.cjs');
|
|
9
|
+
const require_constants = require('./constants.cjs');
|
|
10
|
+
const require_is_empty_field_value = require('./is-empty-field-value.cjs');
|
|
11
|
+
let __formily_react = require("@formily/react");
|
|
12
|
+
__formily_react = require_rolldown_runtime.__toESM(__formily_react);
|
|
13
|
+
let react = require("react");
|
|
14
|
+
react = require_rolldown_runtime.__toESM(react);
|
|
15
|
+
|
|
16
|
+
//#region src/components/overlay-common/use-overlay.ts
|
|
17
|
+
/**
|
|
18
|
+
* Formily glob matching the field itself and every descendant, and nothing
|
|
19
|
+
* else — `*(a,a.*)` matches `a`, `a.b`, and `a.b.c`, but not the sibling `ab`.
|
|
20
|
+
* One pattern covers both shapes an overlay can hold: a single input (validate
|
|
21
|
+
* the field) and an object's form (validate its fields), at any depth.
|
|
22
|
+
*/
|
|
23
|
+
function buildValidationPattern(address) {
|
|
24
|
+
return `*(${address},${address}.*)`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Shared state for fields that render their input(s) inside an overlay
|
|
28
|
+
* (dialog or popover) opened from a trigger button.
|
|
29
|
+
*
|
|
30
|
+
* Fields render in the parent form (no draft copy), so edits commit as the
|
|
31
|
+
* user types. This mirrors the autoSave mode of ArrayDialog/ArrayPopover:
|
|
32
|
+
* validation on close is scoped to the overlay's own fields so unrelated
|
|
33
|
+
* fields elsewhere in the form are not validated.
|
|
34
|
+
*/
|
|
35
|
+
function useOverlay(options = {}) {
|
|
36
|
+
const { label, description, trigger, open, defaultOpen, onOpenChange, validateOnClose = true } = options;
|
|
37
|
+
const effectiveLabel = require_use_label.useLabel(label);
|
|
38
|
+
const effectiveDescription = require_use_description.useDescription(description);
|
|
39
|
+
const [uncontrolledOpen, setUncontrolledOpen] = react.default.useState(defaultOpen ?? false);
|
|
40
|
+
const isControlled = open !== void 0;
|
|
41
|
+
const isOpen = isControlled ? open : uncontrolledOpen;
|
|
42
|
+
const setOpen = react.default.useCallback((next) => {
|
|
43
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
44
|
+
onOpenChange?.(next);
|
|
45
|
+
}, [isControlled, onOpenChange]);
|
|
46
|
+
const { layout } = require_use_form_context.useFormContext();
|
|
47
|
+
const gapClass = require_resolve_responsive_space.resolveResponsiveGapClass({ density: layout?.density });
|
|
48
|
+
const field = (0, __formily_react.useField)();
|
|
49
|
+
const hasError = field.errors.length > 0;
|
|
50
|
+
const validationPath = buildValidationPattern(field.address.toString());
|
|
51
|
+
const noun = (0, __formily_react.useFieldSchema)().title ?? require_constants.DEFAULT_TRIGGER_NOUN;
|
|
52
|
+
const isEmpty = require_is_empty_field_value.isEmptyFieldValue(field.value);
|
|
53
|
+
const resolvedTrigger = {
|
|
54
|
+
...trigger,
|
|
55
|
+
label: trigger?.label ?? (isEmpty ? `Add ${noun}` : `Edit ${noun}`)
|
|
56
|
+
};
|
|
57
|
+
const { shouldShake, triggerShake } = require_use_shake_animation.useShakeAnimation();
|
|
58
|
+
const revalidateOnOpenRef = react.default.useRef(false);
|
|
59
|
+
react.default.useEffect(() => {
|
|
60
|
+
if (!isOpen || !revalidateOnOpenRef.current) return;
|
|
61
|
+
revalidateOnOpenRef.current = false;
|
|
62
|
+
Promise.resolve(field.form.validate(validationPath)).catch(() => void 0);
|
|
63
|
+
}, [
|
|
64
|
+
field.form,
|
|
65
|
+
isOpen,
|
|
66
|
+
validationPath
|
|
67
|
+
]);
|
|
68
|
+
const requestClose = react.default.useCallback(() => {
|
|
69
|
+
if (!validateOnClose) {
|
|
70
|
+
setOpen(false);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
Promise.resolve(field.form.validate(validationPath)).then(() => {
|
|
74
|
+
setOpen(false);
|
|
75
|
+
}).catch(() => {
|
|
76
|
+
triggerShake();
|
|
77
|
+
});
|
|
78
|
+
}, [
|
|
79
|
+
field.form,
|
|
80
|
+
setOpen,
|
|
81
|
+
triggerShake,
|
|
82
|
+
validateOnClose,
|
|
83
|
+
validationPath
|
|
84
|
+
]);
|
|
85
|
+
return {
|
|
86
|
+
label: effectiveLabel,
|
|
87
|
+
description: effectiveDescription,
|
|
88
|
+
trigger: resolvedTrigger,
|
|
89
|
+
open: isOpen,
|
|
90
|
+
gapClass,
|
|
91
|
+
hasError,
|
|
92
|
+
shouldShake,
|
|
93
|
+
handleOpenChange: react.default.useCallback((next) => {
|
|
94
|
+
if (next) {
|
|
95
|
+
revalidateOnOpenRef.current = hasError;
|
|
96
|
+
setOpen(true);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
requestClose();
|
|
100
|
+
}, [
|
|
101
|
+
hasError,
|
|
102
|
+
requestClose,
|
|
103
|
+
setOpen
|
|
104
|
+
]),
|
|
105
|
+
requestClose
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
//#endregion
|
|
110
|
+
exports.useOverlay = useOverlay;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./OverlayTrigger.cjs";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "./OverlayTrigger.js";
|