From fdbe623e1060efc4b074d213a96e8f5a2ab7498b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 20 Sep 2023 15:16:28 -0300 Subject: more ui stuff, moved forms to util --- .../web-util/src/forms/InputSelectMultiple.tsx | 151 +++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 packages/web-util/src/forms/InputSelectMultiple.tsx (limited to 'packages/web-util/src/forms/InputSelectMultiple.tsx') diff --git a/packages/web-util/src/forms/InputSelectMultiple.tsx b/packages/web-util/src/forms/InputSelectMultiple.tsx new file mode 100644 index 000000000..8116bdc03 --- /dev/null +++ b/packages/web-util/src/forms/InputSelectMultiple.tsx @@ -0,0 +1,151 @@ +import { Fragment, VNode, h } from "preact"; +import { useState } from "preact/hooks"; +import { Choice } from "./InputChoiceStacked.js"; +import { LabelWithTooltipMaybeRequired, UIFormProps } from "./InputLine.js"; +import { useField } from "./useField.js"; + +export function InputSelectMultiple( + props: { + choices: Choice[]; + unique?: boolean; + max?: number; + } & UIFormProps, +): VNode { + const { name, label, choices, placeholder, tooltip, required, unique, max } = + props; + const { value, onChange } = useField(name); + + const [filter, setFilter] = useState(undefined); + const regex = new RegExp(`.*${filter}.*`, "i"); + const choiceMap = choices.reduce((prev, curr) => { + return { ...prev, [curr.value as string]: curr.label }; + }, {} as Record); + + const list = (value ?? []) as string[]; + const filteredChoices = + filter === undefined + ? undefined + : choices.filter((v) => { + return regex.test(v.label); + }); + return ( +
+ + {list.map((v, idx) => { + return ( + + {choiceMap[v]} + + + ); + })} + +
+ { + setFilter(e.currentTarget.value); + }} + placeholder={placeholder} + class="w-full rounded-md border-0 bg-white py-1.5 pl-3 pr-12 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" + role="combobox" + aria-controls="options" + aria-expanded="false" + /> + + + {filteredChoices !== undefined && ( +
    + {filteredChoices.map((v, idx) => { + return ( +
  • { + setFilter(undefined); + if (unique && list.indexOf(v.value as string) !== -1) { + return; + } + if (max !== undefined && list.length >= max) { + return; + } + const newValue = [...list]; + newValue.splice(0, 0, v.value as string); + onChange(newValue as T[K]); + }} + + // tabindex="-1" + > + {/* */} + {v.label} + + {/* */} +
  • + ); + })} + + {/* */} + + {/* */} +
+ )} +
+
+ ); +} -- cgit v1.2.3