From 0342d400822d139851aa18df2ec24ad5f0434a8d Mon Sep 17 00:00:00 2001 From: rizky Date: Mon, 12 Aug 2024 14:49:26 -0700 Subject: [PATCH] adding key value type --- comps/form/field/type/FilePreview.tsx | 4 +- comps/form/field/type/KeyValue.tsx | 216 +++++++++++++++++++++++--- comps/form/field/type/TypeInput.tsx | 14 +- comps/form/typings.ts | 1 + 4 files changed, 213 insertions(+), 22 deletions(-) diff --git a/comps/form/field/type/FilePreview.tsx b/comps/form/field/type/FilePreview.tsx index af168d8..60d1085 100755 --- a/comps/form/field/type/FilePreview.tsx +++ b/comps/form/field/type/FilePreview.tsx @@ -309,7 +309,7 @@ export const ImgThumb = ({ "img-thumb", className, css` - width: ${w}px; + width: ${w}px; height: ${h}px; background-image: linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(135deg, #ccc 25%, transparent 25%), @@ -320,7 +320,7 @@ export const ImgThumb = ({ ` )} > - {!local.error && ( + {!local.error && url && ( { local.error = true; diff --git a/comps/form/field/type/KeyValue.tsx b/comps/form/field/type/KeyValue.tsx index 6168c1b..bc63eb1 100755 --- a/comps/form/field/type/KeyValue.tsx +++ b/comps/form/field/type/KeyValue.tsx @@ -1,26 +1,204 @@ -export const KeyValue = () => { +import { update } from "autosize"; +import { useLocal } from "lib/utils/use-local"; +import { useEffect, useRef } from "react"; + +export const KeyValue = ({ + value, + onChange, +}: { + value: any; + onChange: (val: any) => void; +}) => { + const local = useLocal({ + entries: Object.entries(value), + new: { idx: -1, key: "", value: "" }, + }); + const ref = useRef(null); + + useEffect(() => { + if (local.entries.length > 0) { + Object.entries(value).forEach(([k, v], idx) => { + const found = local.entries.find((e) => { + if (e[0] === k) return true; + return false; + }); + if (found) { + found[0] = k; + found[1] = v; + } else { + local.entries.push([k, v]); + } + }); + } else { + local.entries = Object.entries(value); + } + local.render(); + }, [value]); + + if (typeof value !== "object") return null; + + const reverseEntries = (input: [string, unknown][]) => { + return input + .filter(([k, v]) => { + return true; // some irrelevant conditions here + }) + .reduce((accum: any, [k, v]) => { + accum[k] = v; + return accum; + }, {}); + }; return ( -
- +
+
- - - - - - - - + {local.entries.map((item, idx) => ( + { + local.entries[idx] = [k, v]; + + if (k === "" && v === "") { + local.entries.splice(idx, 1); + } + + local.render(); + }} + onBlur={() => { + onChange(reverseEntries(local.entries)); + }} + /> + ))} + { + local.new.key = k; + local.new.value = v; + local.render(); + }} + onBlur={(field, val) => { + if (field === "key" && val) { + const idx = local.entries.length; + local.entries[idx] = [local.new.key, local.new.value]; + local.new.key = ""; + local.new.value = ""; + local.render(); + onChange(reverseEntries(local.entries)); + setTimeout(() => { + ( + ref?.current?.querySelector( + `.kv-row-${idx} .kv-value input` + ) as HTMLInputElement + )?.focus(); + }, 10); + } + }} + />
- - - -
- - - -
); }; + +const KVRow = ({ + item, + idx, + update, + onBlur, +}: { + item: [string, unknown]; + idx: number; + update: (idx: number, key: string, value: string) => void; + onBlur?: (field: "key" | "value", val: string) => void; +}) => { + const [k, v] = item as any; + const keyref = useRef(null); + const valref = useRef(null); + + return ( + + 0 && + css` + border-top: 1px solid #ececeb; + ` + )} + > + { + update(idx, e.currentTarget.value, v || ""); + }} + onBlur={ + onBlur + ? (e) => { + onBlur("key", e.currentTarget.value); + } + : undefined + } + ref={keyref} + > + + 0 && + css` + border-top: 1px solid #ececeb; + ` + )} + > + { + update(idx, k, e.currentTarget.value || ""); + }} + onKeyDown={(e) => { + if (e.key === "Backspace" && !e.currentTarget.value) { + keyref.current?.focus(); + } + }} + onBlur={ + onBlur + ? (e) => { + onBlur("value", e.currentTarget.value); + } + : undefined + } + ref={valref} + > + + + ); +}; diff --git a/comps/form/field/type/TypeInput.tsx b/comps/form/field/type/TypeInput.tsx index 2eec322..ca77a21 100755 --- a/comps/form/field/type/TypeInput.tsx +++ b/comps/form/field/type/TypeInput.tsx @@ -215,7 +215,19 @@ export const FieldTypeInput: FC<{ ); } case "key-value": - return ; + return ( + { + fm.data[field.name] = val; + fm.render(); + }} + /> + ); case "monthly": { return (