UI/modules: exclude typescript from dynamic field names and types
This commit is contained in:
@@ -12,7 +12,11 @@ import { Label } from "../base/label";
|
|||||||
import { useFloating } from "../base";
|
import { useFloating } from "../base";
|
||||||
import { autoUpdate, flip, hide, shift, size } from "@floating-ui/dom";
|
import { autoUpdate, flip, hide, shift, size } from "@floating-ui/dom";
|
||||||
|
|
||||||
export type Option = { value: string; label: string };
|
export interface Option {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface SelectInputpProps {
|
interface SelectInputpProps {
|
||||||
value: string[] | string;
|
value: string[] | string;
|
||||||
selectProps: JSX.InputHTMLAttributes<HTMLSelectElement>;
|
selectProps: JSX.InputHTMLAttributes<HTMLSelectElement>;
|
||||||
@@ -81,7 +85,7 @@ export function SelectInput(props: SelectInputpProps) {
|
|||||||
|
|
||||||
const handleClickOption = (opt: Option) => {
|
const handleClickOption = (opt: Option) => {
|
||||||
if (!props.multiple) {
|
if (!props.multiple) {
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
props.selectProps.onInput({
|
props.selectProps.onInput({
|
||||||
currentTarget: {
|
currentTarget: {
|
||||||
value: opt.value,
|
value: opt.value,
|
||||||
@@ -96,7 +100,7 @@ export function SelectInput(props: SelectInputpProps) {
|
|||||||
} else {
|
} else {
|
||||||
currValues.push(opt.value);
|
currValues.push(opt.value);
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
props.selectProps.onInput({
|
props.selectProps.onInput({
|
||||||
currentTarget: {
|
currentTarget: {
|
||||||
options: currValues.map((value) => ({
|
options: currValues.map((value) => ({
|
||||||
@@ -128,17 +132,17 @@ export function SelectInput(props: SelectInputpProps) {
|
|||||||
{props.adornment?.content}
|
{props.adornment?.content}
|
||||||
</Show>
|
</Show>
|
||||||
{props.inlineLabel}
|
{props.inlineLabel}
|
||||||
<div class="flex flex-row gap-2 cursor-default">
|
<div class="flex cursor-default flex-row gap-2">
|
||||||
<For each={getValues()} fallback={"Select"}>
|
<For each={getValues()} fallback={"Select"}>
|
||||||
{(item) => (
|
{(item) => (
|
||||||
<div class="text-sm rounded-xl bg-slate-800 text-white px-4 py-1">
|
<div class="rounded-xl bg-slate-800 px-4 py-1 text-sm text-white">
|
||||||
{item}
|
{item}
|
||||||
<Show when={props.multiple}>
|
<Show when={props.multiple}>
|
||||||
<button
|
<button
|
||||||
class="btn-xs btn-ghost"
|
class="btn-ghost btn-xs"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={(_e) => {
|
onClick={(_e) => {
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
props.selectProps.onInput({
|
props.selectProps.onInput({
|
||||||
currentTarget: {
|
currentTarget: {
|
||||||
options: getValues()
|
options: getValues()
|
||||||
@@ -188,9 +192,9 @@ export function SelectInput(props: SelectInputpProps) {
|
|||||||
top: `${position.y ?? 0}px`,
|
top: `${position.y ?? 0}px`,
|
||||||
left: `${position.x ?? 0}px`,
|
left: `${position.x ?? 0}px`,
|
||||||
}}
|
}}
|
||||||
class="dropdown-content bg-base-100 rounded-b-box z-[1] shadow"
|
class="dropdown-content z-[1] rounded-b-box bg-base-100 shadow"
|
||||||
>
|
>
|
||||||
<ul class="menu flex flex-col gap-1 max-h-96 overflow-y-scroll overflow-x-hidden">
|
<ul class="menu flex max-h-96 flex-col gap-1 overflow-x-hidden overflow-y-scroll">
|
||||||
<For each={props.options}>
|
<For each={props.options}>
|
||||||
{(opt) => (
|
{(opt) => (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import cx from "classnames";
|
|||||||
import { Label } from "../base/label";
|
import { Label } from "../base/label";
|
||||||
import { SelectInput } from "../fields/Select";
|
import { SelectInput } from "../fields/Select";
|
||||||
|
|
||||||
function generateDefaults(schema: JSONSchema7): any {
|
function generateDefaults(schema: JSONSchema7): unknown {
|
||||||
switch (schema.type) {
|
switch (schema.type) {
|
||||||
case "string":
|
case "string":
|
||||||
return ""; // Default value for string
|
return ""; // Default value for string
|
||||||
@@ -51,11 +51,12 @@ function generateDefaults(schema: JSONSchema7): any {
|
|||||||
case "array":
|
case "array":
|
||||||
return []; // Default empty array if no items schema or items is true/false
|
return []; // Default empty array if no items schema or items is true/false
|
||||||
|
|
||||||
case "object":
|
case "object": {
|
||||||
const obj: { [key: string]: any } = {};
|
const obj: Record<string, unknown> = {};
|
||||||
if (schema.properties) {
|
if (schema.properties) {
|
||||||
Object.entries(schema.properties).forEach(([key, propSchema]) => {
|
Object.entries(schema.properties).forEach(([key, propSchema]) => {
|
||||||
if (typeof propSchema === "boolean") {
|
if (typeof propSchema === "boolean") {
|
||||||
|
obj[key] = false;
|
||||||
} else {
|
} else {
|
||||||
// if (schema.required schema.required.includes(key))
|
// if (schema.required schema.required.includes(key))
|
||||||
obj[key] = generateDefaults(propSchema);
|
obj[key] = generateDefaults(propSchema);
|
||||||
@@ -63,6 +64,7 @@ function generateDefaults(schema: JSONSchema7): any {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null; // Default for unknown types or nulls
|
return null; // Default for unknown types or nulls
|
||||||
@@ -359,7 +361,7 @@ export function ListValueDisplay<T extends FieldValues, R extends ResponseData>(
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
remove(
|
remove(
|
||||||
props.formStore,
|
props.formStore,
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
props.listFieldName,
|
props.listFieldName,
|
||||||
{ at: props.idx },
|
{ at: props.idx },
|
||||||
);
|
);
|
||||||
@@ -368,7 +370,7 @@ export function ListValueDisplay<T extends FieldValues, R extends ResponseData>(
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
move(
|
move(
|
||||||
props.formStore,
|
props.formStore,
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
props.listFieldName,
|
props.listFieldName,
|
||||||
{ from: props.idx, to: props.idx + dir },
|
{ from: props.idx, to: props.idx + dir },
|
||||||
);
|
);
|
||||||
@@ -377,10 +379,10 @@ export function ListValueDisplay<T extends FieldValues, R extends ResponseData>(
|
|||||||
const bottomMost = () => props.idx === 0;
|
const bottomMost = () => props.idx === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="border-l-4 border-gray-300 w-full">
|
<div class="w-full border-l-4 border-gray-300">
|
||||||
<div class="flex w-full gap-2 items-end px-4">
|
<div class="flex w-full items-end gap-2 px-4">
|
||||||
{props.children}
|
{props.children}
|
||||||
<div class="pb-4 ml-4 min-w-fit">
|
<div class="ml-4 min-w-fit pb-4">
|
||||||
<button class="btn" onClick={moveItemBy(1)} disabled={topMost()}>
|
<button class="btn" onClick={moveItemBy(1)} disabled={topMost()}>
|
||||||
↓
|
↓
|
||||||
</button>
|
</button>
|
||||||
@@ -396,7 +398,7 @@ export function ListValueDisplay<T extends FieldValues, R extends ResponseData>(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const findDuplicates = (arr: any[]) => {
|
const findDuplicates = (arr: unknown[]) => {
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
const duplicates: number[] = [];
|
const duplicates: number[] = [];
|
||||||
|
|
||||||
@@ -475,20 +477,19 @@ export function ArrayFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
when={itemsSchema().type === "string" && itemsSchema().enum}
|
when={itemsSchema().type === "string" && itemsSchema().enum}
|
||||||
>
|
>
|
||||||
<Field
|
<Field
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
name={listFieldName}
|
name={listFieldName}
|
||||||
// @ts-ignore
|
// @ts-expect-error: type is known due to schema
|
||||||
type="string[]"
|
type="string[]"
|
||||||
validateOn="touched"
|
validateOn="touched"
|
||||||
revalidateOn="touched"
|
revalidateOn="touched"
|
||||||
validate={() => {
|
validate={() => {
|
||||||
let error = "";
|
let error = "";
|
||||||
// @ts-ignore
|
const values: unknown[] = getValues(
|
||||||
const values: any[] = getValues(
|
|
||||||
props.formStore,
|
props.formStore,
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
listFieldName,
|
listFieldName,
|
||||||
// @ts-ignore
|
// @ts-expect-error: assumption based on the behavior of selectInput
|
||||||
)?.strings?.selection;
|
)?.strings?.selection;
|
||||||
console.log("vali", { values });
|
console.log("vali", { values });
|
||||||
if (props.schema.uniqueItems) {
|
if (props.schema.uniqueItems) {
|
||||||
@@ -543,17 +544,17 @@ export function ArrayFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
>
|
>
|
||||||
{/* !Important: Register the parent field to gain access to array items*/}
|
{/* !Important: Register the parent field to gain access to array items*/}
|
||||||
<FieldArray
|
<FieldArray
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
name={listFieldName}
|
name={listFieldName}
|
||||||
of={props.formStore}
|
of={props.formStore}
|
||||||
validateOn="touched"
|
validateOn="touched"
|
||||||
revalidateOn="touched"
|
revalidateOn="touched"
|
||||||
validate={() => {
|
validate={() => {
|
||||||
let error = "";
|
let error = "";
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
const values: any[] = getValues(
|
const values: unknown[] = getValues(
|
||||||
props.formStore,
|
props.formStore,
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
listFieldName,
|
listFieldName,
|
||||||
);
|
);
|
||||||
if (props.schema.uniqueItems) {
|
if (props.schema.uniqueItems) {
|
||||||
@@ -596,7 +597,7 @@ export function ArrayFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
of={fieldArray.items.length}
|
of={fieldArray.items.length}
|
||||||
>
|
>
|
||||||
<Field
|
<Field
|
||||||
// @ts-ignore: field names are not know ahead of time
|
// @ts-expect-error: field names are not know ahead of time
|
||||||
name={`${listFieldName}.${idx()}`}
|
name={`${listFieldName}.${idx()}`}
|
||||||
>
|
>
|
||||||
{(f, fp) => (
|
{(f, fp) => (
|
||||||
@@ -642,25 +643,29 @@ export function ArrayFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
}}
|
}}
|
||||||
// Add the new item to the FieldArray
|
// Add the new item to the FieldArray
|
||||||
handleSubmit={(values, event) => {
|
handleSubmit={(values, event) => {
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
const prev: any[] = getValues(
|
const prev: unknown[] = getValues(
|
||||||
props.formStore,
|
props.formStore,
|
||||||
// @ts-ignore
|
|
||||||
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
listFieldName,
|
listFieldName,
|
||||||
);
|
);
|
||||||
if (itemsSchema().type === "object") {
|
if (itemsSchema().type === "object") {
|
||||||
const newIdx = prev.length;
|
const newIdx = prev.length;
|
||||||
setValue(
|
setValue(
|
||||||
props.formStore,
|
props.formStore,
|
||||||
// @ts-ignore
|
|
||||||
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
`${listFieldName}.${newIdx}`,
|
`${listFieldName}.${newIdx}`,
|
||||||
// @ts-ignore
|
|
||||||
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
values.root,
|
values.root,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// @ts-ignore
|
|
||||||
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
insert(props.formStore, listFieldName, {
|
insert(props.formStore, listFieldName, {
|
||||||
// @ts-ignore
|
// @ts-expect-error: listFieldName is not known ahead of time
|
||||||
value: values.root,
|
value: values.root,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -685,7 +690,7 @@ interface ObjectFieldPropertyLabelProps {
|
|||||||
export function ObjectFieldPropertyLabel(props: ObjectFieldPropertyLabelProps) {
|
export function ObjectFieldPropertyLabel(props: ObjectFieldPropertyLabelProps) {
|
||||||
return (
|
return (
|
||||||
<Switch fallback={props.fallback}>
|
<Switch fallback={props.fallback}>
|
||||||
{/* @ts-ignore */}
|
{/* @ts-expect-error: $exportedModuleInfo should exist since we export it */}
|
||||||
<Match when={props.schema?.$exportedModuleInfo?.path}>
|
<Match when={props.schema?.$exportedModuleInfo?.path}>
|
||||||
{(path) => path()[path().length - 1]}
|
{(path) => path()[path().length - 1]}
|
||||||
</Match>
|
</Match>
|
||||||
@@ -724,6 +729,7 @@ export function ObjectFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
<For each={Object.entries(properties())}>
|
<For each={Object.entries(properties())}>
|
||||||
{([propName, propSchema]) => (
|
{([propName, propSchema]) => (
|
||||||
<div
|
<div
|
||||||
|
// eslint-disable-next-line tailwindcss/no-custom-classname
|
||||||
class={cx(
|
class={cx(
|
||||||
"w-full grid grid-cols-1 gap-4 justify-items-start",
|
"w-full grid grid-cols-1 gap-4 justify-items-start",
|
||||||
`p-${props.path.length * 2}`,
|
`p-${props.path.length * 2}`,
|
||||||
@@ -780,7 +786,7 @@ export function ObjectFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
{(itemSchema) => (
|
{(itemSchema) => (
|
||||||
<Field
|
<Field
|
||||||
// Important!: Register the object field to gain access to the dynamic object properties
|
// Important!: Register the object field to gain access to the dynamic object properties
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
name={fieldName}
|
name={fieldName}
|
||||||
>
|
>
|
||||||
{(objectField, fp) => (
|
{(objectField, fp) => (
|
||||||
@@ -802,11 +808,11 @@ export function ObjectFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
>
|
>
|
||||||
{([key, relatedValue]) => (
|
{([key, relatedValue]) => (
|
||||||
<Field
|
<Field
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
name={`${fieldName}.${key}`}
|
name={`${fieldName}.${key}`}
|
||||||
>
|
>
|
||||||
{(f, fp) => (
|
{(f, fp) => (
|
||||||
<div class="border-l-4 border-gray-300 pl-4 w-full">
|
<div class="w-full border-l-4 border-gray-300 pl-4">
|
||||||
<DynForm
|
<DynForm
|
||||||
formProps={{
|
formProps={{
|
||||||
class: cx("w-full"),
|
class: cx("w-full"),
|
||||||
@@ -820,19 +826,19 @@ export function ObjectFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
{key}
|
{key}
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-warning ml-auto"
|
class="btn btn-warning btn-sm ml-auto"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={(_e) => {
|
onClick={(_e) => {
|
||||||
const copy = {
|
const copy = {
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
...objectField.value,
|
...objectField.value,
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||||
delete copy[key];
|
delete copy[key];
|
||||||
setValue(
|
setValue(
|
||||||
props.formStore,
|
props.formStore,
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
`${fieldName}`,
|
`${fieldName}`,
|
||||||
// @ts-ignore
|
|
||||||
copy,
|
copy,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@@ -862,9 +868,9 @@ export function ObjectFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
handleSubmit={(values, event) => {
|
handleSubmit={(values, event) => {
|
||||||
setValue(
|
setValue(
|
||||||
props.formStore,
|
props.formStore,
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
`${fieldName}`,
|
`${fieldName}`,
|
||||||
// @ts-ignore
|
// @ts-expect-error: fieldName is not known ahead of time
|
||||||
{ ...objectField.value, [values[""]]: {} },
|
{ ...objectField.value, [values[""]]: {} },
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user