@farmzone/fz-react-ui 0.0.8 → 0.0.10

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/index.d.cts CHANGED
@@ -1181,7 +1181,7 @@ interface DetailContentProps<T, S extends z.ZodTypeAny = z.ZodTypeAny> {
1181
1181
  }) => ReactNode;
1182
1182
  /** Body 전면 교체 — edit 영역 (RHF methods 포함) */
1183
1183
  renderEditBody?: (ctx: DetailEditBodyContext<z.infer<S>, S>) => ReactNode;
1184
- layout?: "compact" | "full";
1184
+ layout?: "compact" | "full" | "none";
1185
1185
  className?: string;
1186
1186
  }
1187
1187
 
@@ -1200,6 +1200,14 @@ interface DetailModalFrameProps<T, S extends z.ZodTypeAny = z.ZodTypeAny> {
1200
1200
  mode?: UseDetailControllerParams["mode"];
1201
1201
  onModeChange?: UseDetailControllerParams["onModeChange"];
1202
1202
  contentClassName?: string;
1203
+ /** ModalBody 내 DetailContent 하단 추가 컨텐츠 (프로필 사진 등) */
1204
+ renderExtraContent?: (ctx: {
1205
+ isEditMode: boolean;
1206
+ }) => ReactNode;
1207
+ /** read 모드 footer 추가 버튼 — 닫기 앞에 삽입 */
1208
+ renderFooterExtra?: ReactNode;
1209
+ /** isDirty 상태 외부 노출 — 라우터 blocker 등에서 활용 */
1210
+ onDirtyChange?: (isDirty: boolean) => void;
1203
1211
  }
1204
1212
  declare function DetailModalFrame<T, S extends z.ZodTypeAny = z.ZodTypeAny>(props: DetailModalFrameProps<T, S>): React$1.JSX.Element;
1205
1213
 
package/dist/index.d.ts CHANGED
@@ -1181,7 +1181,7 @@ interface DetailContentProps<T, S extends z.ZodTypeAny = z.ZodTypeAny> {
1181
1181
  }) => ReactNode;
1182
1182
  /** Body 전면 교체 — edit 영역 (RHF methods 포함) */
1183
1183
  renderEditBody?: (ctx: DetailEditBodyContext<z.infer<S>, S>) => ReactNode;
1184
- layout?: "compact" | "full";
1184
+ layout?: "compact" | "full" | "none";
1185
1185
  className?: string;
1186
1186
  }
1187
1187
 
@@ -1200,6 +1200,14 @@ interface DetailModalFrameProps<T, S extends z.ZodTypeAny = z.ZodTypeAny> {
1200
1200
  mode?: UseDetailControllerParams["mode"];
1201
1201
  onModeChange?: UseDetailControllerParams["onModeChange"];
1202
1202
  contentClassName?: string;
1203
+ /** ModalBody 내 DetailContent 하단 추가 컨텐츠 (프로필 사진 등) */
1204
+ renderExtraContent?: (ctx: {
1205
+ isEditMode: boolean;
1206
+ }) => ReactNode;
1207
+ /** read 모드 footer 추가 버튼 — 닫기 앞에 삽입 */
1208
+ renderFooterExtra?: ReactNode;
1209
+ /** isDirty 상태 외부 노출 — 라우터 blocker 등에서 활용 */
1210
+ onDirtyChange?: (isDirty: boolean) => void;
1203
1211
  }
1204
1212
  declare function DetailModalFrame<T, S extends z.ZodTypeAny = z.ZodTypeAny>(props: DetailModalFrameProps<T, S>): React$1.JSX.Element;
1205
1213
 
package/dist/index.js CHANGED
@@ -8819,11 +8819,7 @@ function DetailContent(props) {
8819
8819
  layout = "compact",
8820
8820
  className
8821
8821
  } = props;
8822
- const containerClass = cn(
8823
- "overflow-y-auto",
8824
- layout === "compact" ? "max-h-[60vh]" : "min-h-0 flex-1",
8825
- className
8826
- );
8822
+ const containerClass = layout === "none" ? cn(className) : cn("overflow-y-auto", layout === "compact" ? "max-h-[60vh]" : "min-h-0 flex-1", className);
8827
8823
  if (!data) {
8828
8824
  return /* @__PURE__ */ jsx("div", { className: cn(containerClass, "flex items-center justify-center p-8"), children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-400", children: "\uB370\uC774\uD130\uB97C \uBD88\uB7EC\uC624\uB294 \uC911..." }) });
8829
8825
  }
@@ -8860,9 +8856,15 @@ function DetailModalFrame(props) {
8860
8856
  renderEditBody,
8861
8857
  mode,
8862
8858
  onModeChange,
8863
- contentClassName
8859
+ contentClassName,
8860
+ renderExtraContent,
8861
+ renderFooterExtra,
8862
+ onDirtyChange
8864
8863
  } = props;
8865
8864
  const controller = useDetailController({ mode, onModeChange });
8865
+ useEffect(() => {
8866
+ onDirtyChange?.(controller.isDirty);
8867
+ }, [controller.isDirty, onDirtyChange]);
8866
8868
  const handleClose = useCallback(async () => {
8867
8869
  if (controller.isDirty) {
8868
8870
  const confirmed = await new Promise((resolve) => {
@@ -8900,24 +8902,30 @@ function DetailModalFrame(props) {
8900
8902
  /* @__PURE__ */ jsx("span", { className: "text-base font-semibold text-gray-900", children: title }),
8901
8903
  !isEditMode && canEdit && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: handleEdit, children: "\uC218\uC815" })
8902
8904
  ] }),
8903
- /* @__PURE__ */ jsx(ModalBody, { className: "p-0", children: /* @__PURE__ */ jsx(
8904
- DetailContent,
8905
- {
8906
- controller,
8907
- data,
8908
- readFields,
8909
- editSchema,
8910
- editFields,
8911
- onSave,
8912
- renderReadBody,
8913
- renderEditBody,
8914
- layout: "compact"
8915
- }
8916
- ) }),
8905
+ /* @__PURE__ */ jsxs(ModalBody, { className: "flex-1 min-h-0 p-0", children: [
8906
+ /* @__PURE__ */ jsx(
8907
+ DetailContent,
8908
+ {
8909
+ controller,
8910
+ data,
8911
+ readFields,
8912
+ editSchema,
8913
+ editFields,
8914
+ onSave,
8915
+ renderReadBody,
8916
+ renderEditBody,
8917
+ layout: "none"
8918
+ }
8919
+ ),
8920
+ renderExtraContent?.({ isEditMode })
8921
+ ] }),
8917
8922
  /* @__PURE__ */ jsx(ModalFooter, { className: "flex justify-end gap-2", children: isEditMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
8918
8923
  /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleCancelEdit, disabled: controller.isSaving, children: "\uCDE8\uC18C" }),
8919
8924
  /* @__PURE__ */ jsx(Button, { type: "submit", form: controller.formId, variant: "save", disabled: controller.isSaving, children: controller.isSaving ? "\uC800\uC7A5 \uC911..." : "\uC800\uC7A5" })
8920
- ] }) : /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, children: "\uB2EB\uAE30" }) })
8925
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
8926
+ renderFooterExtra,
8927
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: handleClose, children: "\uB2EB\uAE30" })
8928
+ ] }) })
8921
8929
  ] });
8922
8930
  }
8923
8931
  function useBlockModalConfirm() {