module-package-comp 1.4.7 → 1.4.8

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.
@@ -16,7 +16,7 @@ const MultiSelect = ({ options, selectedOptions, onChange, disabled, }) => {
16
16
  setFilter(e.target.value);
17
17
  };
18
18
  const filteredOptions = options.filter((option) => option.toLowerCase().includes(filter.toLowerCase()));
19
- return (_jsxs("div", { className: "relative inline-block w-full", children: [_jsx("div", { className: "py-2 px-3 bg-white block w-full border-2 border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none", onClick: toggleDropdown, children: Array.isArray(selectedOptions) && selectedOptions.length > 0 ? (selectedOptions.map((option) => (_jsx("span", { className: "mr-1 inline-block rounded-full bg-secondary-blue px-2 py-1 text-sm", children: option }, option)))) : (_jsx("span", { className: "text-placeholder-gray", children: "Select options" })) }), isOpen && (_jsxs("div", { className: "absolute left-0 right-0 z-10 mt-2 rounded-md border border-secondary-gray bg-white", children: [_jsx("input", { type: "text", className: "w-full border-b border-secondary-gray p-2", placeholder: "Filter options...", value: filter, onChange: handleFilterChange }), _jsx("div", { className: "max-h-60 overflow-y-auto", children: filteredOptions.map((option) => (_jsxs("div", { className: "cursor-pointer p-2 hover:bg-primary-gray", onClick: () => {
19
+ return (_jsxs("div", { className: "relative inline-block w-full", children: [_jsx("div", { className: "py-2 px-3 bg-white block w-full border-2 border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none", onClick: toggleDropdown, children: Array.isArray(selectedOptions) && selectedOptions.length > 0 ? (selectedOptions.map((option) => (_jsx("span", { className: "mr-1 inline-block rounded-full bg-[#0096DC] px-2 py-1 text-sm", children: option }, option)))) : (_jsx("span", { className: "text-placeholder-gray", children: "Select options" })) }), isOpen && (_jsxs("div", { className: "absolute left-0 right-0 z-10 mt-2 rounded-md border border-secondary-gray bg-white", children: [_jsx("input", { type: "text", className: "w-full border-b border-secondary-gray p-2", placeholder: "Filter options...", value: filter, onChange: handleFilterChange }), _jsx("div", { className: "max-h-60 overflow-y-auto", children: filteredOptions.map((option) => (_jsxs("div", { className: "cursor-pointer p-2 hover:bg-primary-gray", onClick: () => {
20
20
  if (!disabled)
21
21
  handleOptionClick(option);
22
22
  }, children: [_jsx("input", { type: "checkbox", checked: selectedOptions.includes(option), readOnly: true, className: "mr-2" }), _jsx("span", { className: "ml-2", children: option })] }, option))) })] }))] }));
@@ -1 +1 @@
1
- {"version":3,"file":"MultiSelect.js","sourceRoot":"","sources":["../../../src/component/inputs/MultiSelect.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AASxC,MAAM,WAAW,GAA+B,CAAC,EAC/C,OAAO,EACP,eAAe,EACf,QAAQ,EACR,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEzC,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IAEhD,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAE,EAAE;QAC3C,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,CAAC,GAAG,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC;IACF,MAAM,kBAAkB,GAAG,CAAC,CAAsC,EAAE,EAAE;QACpE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAChD,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CACpD,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,8BAA8B,aAC3C,cACE,SAAS,EAAC,wKAAwK,EAClL,OAAO,EAAE,cAAc,YAEtB,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAC9D,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC9B,eAEE,SAAS,EAAC,oEAAoE,YAE7E,MAAM,IAHF,MAAM,CAIN,CACR,CAAC,CACH,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,uBAAuB,+BAAsB,CAC9D,GACG,EACL,MAAM,IAAI,CACT,eAAK,SAAS,EAAC,oFAAoF,aACjG,gBACE,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,2CAA2C,EACrD,WAAW,EAAC,mBAAmB,EAC/B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,kBAAkB,GAC5B,EACF,cAAK,SAAS,EAAC,0BAA0B,YACtC,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC/B,eAEE,SAAS,EAAC,0CAA0C,EACpD,OAAO,EAAE,GAAG,EAAE;gCACZ,IAAI,CAAC,QAAQ;oCAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;4BAC3C,CAAC,aAED,gBACE,IAAI,EAAC,UAAU,EACf,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,EACzC,QAAQ,QACR,SAAS,EAAC,MAAM,GAChB,EACF,eAAM,SAAS,EAAC,MAAM,YAAE,MAAM,GAAQ,KAZjC,MAAM,CAaP,CACP,CAAC,GACE,IACF,CACP,IACG,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"}
1
+ {"version":3,"file":"MultiSelect.js","sourceRoot":"","sources":["../../../src/component/inputs/MultiSelect.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AASxC,MAAM,WAAW,GAA+B,CAAC,EAC/C,OAAO,EACP,eAAe,EACf,QAAQ,EACR,QAAQ,GACT,EAAE,EAAE;IACH,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEzC,MAAM,cAAc,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;IAEhD,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAE,EAAE;QAC3C,IAAI,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACrC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,CAAC,GAAG,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC;IACF,MAAM,kBAAkB,GAAG,CAAC,CAAsC,EAAE,EAAE;QACpE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAChD,MAAM,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CACpD,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,8BAA8B,aAC3C,cACE,SAAS,EAAC,wKAAwK,EAClL,OAAO,EAAE,cAAc,YAEtB,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAC9D,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC9B,eAEE,SAAS,EAAC,+DAA+D,YAExE,MAAM,IAHF,MAAM,CAIN,CACR,CAAC,CACH,CAAC,CAAC,CAAC,CACF,eAAM,SAAS,EAAC,uBAAuB,+BAAsB,CAC9D,GACG,EACL,MAAM,IAAI,CACT,eAAK,SAAS,EAAC,oFAAoF,aACjG,gBACE,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,2CAA2C,EACrD,WAAW,EAAC,mBAAmB,EAC/B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,kBAAkB,GAC5B,EACF,cAAK,SAAS,EAAC,0BAA0B,YACtC,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAC/B,eAEE,SAAS,EAAC,0CAA0C,EACpD,OAAO,EAAE,GAAG,EAAE;gCACZ,IAAI,CAAC,QAAQ;oCAAE,iBAAiB,CAAC,MAAM,CAAC,CAAC;4BAC3C,CAAC,aAED,gBACE,IAAI,EAAC,UAAU,EACf,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,EACzC,QAAQ,QACR,SAAS,EAAC,MAAM,GAChB,EACF,eAAM,SAAS,EAAC,MAAM,YAAE,MAAM,GAAQ,KAZjC,MAAM,CAaP,CACP,CAAC,GACE,IACF,CACP,IACG,CACP,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,WAAW,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "module-package-comp",
3
- "version": "1.4.7",
3
+ "version": "1.4.8",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,140 +0,0 @@
1
- import { useState } from "react";
2
- import { Attribute, Component, Condition, DataJSON } from "../util/type";
3
- import { ShowAttr } from "./ShowAttr";
4
- import PrimaryBtn from "./PrimaryBtn";
5
- import ShowErrors from "./ShowErrors";
6
-
7
- type ComponentDisplayerProps = {
8
- component: Component;
9
- data: DataJSON;
10
- setData: (data: DataJSON) => void;
11
- onSubmit?: () => void;
12
- disabled?: boolean;
13
- };
14
-
15
- export function ComponentDisplayer({
16
- component,
17
- data,
18
- setData,
19
- onSubmit,
20
- disabled,
21
- }: ComponentDisplayerProps) {
22
- const [errors, setErrors] = useState<string[]>([]);
23
- return (
24
- <form
25
- onSubmit={(e) => {
26
- e.preventDefault();
27
- const errs = checkRequired(component.attributes, data);
28
- if (errs.length === 0 && onSubmit) {
29
- onSubmit();
30
- } else {
31
- setErrors(errs);
32
- }
33
- }}
34
- className="min-w-72"
35
- >
36
- <h1 className="font-bold text-center text-blue-800 text-4xl mb-8">
37
- {component.label}
38
- </h1>
39
- <div className="space-y-3">
40
- {component.attributes.map((attr) => {
41
- if (canShow(attr, data, component.conditions || [])) {
42
- return (
43
- <ShowAttr
44
- key={attr.name}
45
- attribute={attr}
46
- value={data[attr.name] ? String(data[attr.name]) : ""}
47
- setValue={(s) => {
48
- const temp = { ...data };
49
- temp[attr.name] = s;
50
- setData(temp);
51
- }}
52
- data={data}
53
- disabled={disabled}
54
- />
55
- );
56
- } else {
57
- if (data[attr.name]) {
58
- const temp = { ...data };
59
- temp[attr.name] = "";
60
- setData(temp);
61
- }
62
- }
63
- })}
64
- </div>
65
- {errors.length !== 0 && (
66
- <div className="my-6">
67
- <ShowErrors errors={errors} />
68
- </div>
69
- )}
70
- {onSubmit && (
71
- <div className="flex justify-center my-8">
72
- <PrimaryBtn text="Submit" />
73
- </div>
74
- )}
75
- </form>
76
- );
77
- }
78
-
79
- // check the required attributes and return array string of errors
80
- function checkRequired(attributes: Attribute[], data: DataJSON): string[] {
81
- const requiredAttributes = attributes.filter(
82
- (attr) => attr.settings?.required,
83
- );
84
- const errors: string[] = [];
85
- requiredAttributes.forEach((attr) => {
86
- if (!data[attr.name]) {
87
- errors.push(`${attr.label} is required`);
88
- }
89
- });
90
- return errors;
91
- }
92
-
93
- function canShow(
94
- attr: Attribute,
95
- data: DataJSON,
96
- conds: Condition[][],
97
- ): boolean {
98
- const conditions = conds.filter(
99
- (c) => c[c.length - 1].delimiter === attr.name,
100
- );
101
-
102
- if (!conditions || conditions.length === 0) {
103
- return true;
104
- }
105
- return conditions.some((conditionSet) => {
106
- for (let i = 0; i < conditionSet.length; i++) {
107
- const currentCond = conditionSet[i];
108
- const result = evaluateCondition(currentCond, data);
109
- if (currentCond.delimiter === "ou") {
110
- if (result) {
111
- return true;
112
- }
113
- } else if (currentCond.delimiter === "et") {
114
- if (!result) {
115
- return false;
116
- }
117
- } else {
118
- return result;
119
- }
120
- }
121
- });
122
- }
123
-
124
- function evaluateCondition(condition: Condition, data: DataJSON): boolean {
125
- const { attribute, cond, value } = condition;
126
- const dataValue = data[attribute];
127
-
128
- switch (cond) {
129
- case "EQ":
130
- return value === dataValue;
131
- case "INF":
132
- return value < dataValue;
133
- case "SUP":
134
- return value > dataValue;
135
- case "CONTAIN":
136
- return String(dataValue).includes(value);
137
- default:
138
- return false;
139
- }
140
- }
@@ -1,22 +0,0 @@
1
- import { useRef } from "react";
2
-
3
- type props = {
4
- text: string;
5
- disabled?: boolean;
6
- };
7
-
8
- export default function PrimaryBtn({ text, disabled }: props) {
9
- const btn = useRef<HTMLButtonElement>(null);
10
- return (
11
- <button
12
- type="submit"
13
- ref={btn}
14
- className={
15
- "rounded-2xl bg-[#0096DC] bg-opacity-85 px-8 py-2 font-bold text-white hover:bg-opacity-100"
16
- }
17
- disabled={disabled}
18
- >
19
- {text}
20
- </button>
21
- );
22
- }
@@ -1,177 +0,0 @@
1
- import { Attribute, AttributeTypeEnum, Content, DataJSON } from "../util/type";
2
- import LabeledSelect from "./inputs/LableledSelect";
3
- import LabeledInput from "./inputs/LableledInput";
4
- import LabeledMutliSelect from "./inputs/LabeledMutliSelect";
5
- import { useEffect, useMemo, useState } from "react";
6
- import { Parser } from "expr-eval";
7
- import LabeledFileInput from "./inputs/LableledFileInput";
8
-
9
- type ShowAttrProps = {
10
- attribute: Attribute;
11
- value: string;
12
- setValue: (s: string) => void;
13
- data: DataJSON;
14
- showLabel?: boolean;
15
- disabled?: boolean;
16
- };
17
-
18
- export function ShowAttr({
19
- attribute,
20
- value,
21
- setValue,
22
- showLabel = true,
23
- data,
24
- disabled,
25
- }: ShowAttrProps) {
26
- const label = useMemo(
27
- () => (showLabel ? attribute.label || "" : ""),
28
- [attribute.label]
29
- );
30
- const type = useMemo(() => {
31
- if (attribute.type) return AttributeTypeEnum[attribute.type];
32
- }, [attribute.type]);
33
- switch (type) {
34
- case AttributeTypeEnum.NUMBER:
35
- return (
36
- <LabeledInput
37
- label={label}
38
- value={value}
39
- setValue={setValue}
40
- type="number"
41
- max={
42
- attribute.settings?.max ? Number(attribute.settings.max) : undefined
43
- }
44
- min={
45
- attribute.settings?.min ? Number(attribute.settings.min) : undefined
46
- }
47
- disabled={disabled}
48
- />
49
- );
50
- case AttributeTypeEnum.TEXT:
51
- return (
52
- <LabeledInput
53
- label={label}
54
- value={value}
55
- setValue={setValue}
56
- type="text"
57
- maxLength={attribute.settings?.max}
58
- minLength={attribute.settings?.min}
59
- disabled={disabled}
60
- />
61
- );
62
- case AttributeTypeEnum.LIST:
63
- return (
64
- <LabeledSelect
65
- label={label}
66
- selected={value}
67
- setSelected={setValue}
68
- options={(attribute.content as string[]) || []}
69
- disabled={disabled}
70
- />
71
- );
72
- case AttributeTypeEnum.BOOLEAN:
73
- return (
74
- <LabeledInput
75
- type="checkbox"
76
- label={label}
77
- checked={value === "true"}
78
- setValue={(s) => setValue(s)}
79
- disabled={disabled}
80
- />
81
- );
82
- case AttributeTypeEnum.DATE:
83
- return (
84
- <LabeledInput
85
- type="date"
86
- label={label}
87
- value={value}
88
- setValue={(date) => setValue(date)}
89
- disabled={disabled}
90
- />
91
- );
92
- case AttributeTypeEnum.LINK:
93
- return (
94
- <div className="w-full">
95
- <label className="block text-sm font-bold mb-1">{label}</label>
96
- <a href={attribute.content as string} target="_blank">
97
- {attribute.content}
98
- </a>
99
- </div>
100
- );
101
- case AttributeTypeEnum.MULTIPLE:
102
- return (
103
- <LabeledMutliSelect
104
- label={label}
105
- selectedOptions={value !== "" ? value.split(",") : []}
106
- onChange={(selected) => setValue(selected.join(","))}
107
- options={(attribute.content as string[]) || []}
108
- disabled={disabled}
109
- />
110
- );
111
- case AttributeTypeEnum.FILE:
112
- case AttributeTypeEnum.IMAGE:
113
- return (
114
- <LabeledFileInput
115
- label={label}
116
- fileUrl={value.includes("http") ? value : undefined}
117
- setFileData={setValue}
118
- disabled={disabled}
119
- />
120
- );
121
- case AttributeTypeEnum.IMAGE_OUTPUT:
122
- return (
123
- <div className="w-full">
124
- <label className="block text-sm font-bold mb-1">{label}</label>
125
- <img className="w-64" src={attribute.content as string} />
126
- </div>
127
- );
128
- case AttributeTypeEnum.VIDEO_OUTPUT:
129
- return <ShowVideo url={attribute.content as string} />;
130
- case AttributeTypeEnum.TEXT_OUTPUT:
131
- return (
132
- <div className="w-full">
133
- <label className="block text-sm font-bold mb-1">{label}</label>
134
- <textarea className="w-full bg-white" disabled>
135
- {attribute.content as string}
136
- </textarea>
137
- </div>
138
- );
139
- case AttributeTypeEnum.TITRE:
140
- return (
141
- <div className="w-full">
142
- <h2 className="text-3xl font-semibold">{attribute.label}</h2>
143
- </div>
144
- );
145
- case AttributeTypeEnum.AUTOGEN:
146
- let result = 0;
147
- if (attribute.content && typeof attribute.content === "string") {
148
- result = calculateContent(attribute.content, data);
149
- return <p>{result}</p>;
150
- }
151
- }
152
- }
153
-
154
- function calculateContent(content: string, data: DataJSON): number {
155
- const parser = new Parser();
156
- const expr = parser.parse(content);
157
- const vars = expr.variables();
158
- if (vars.every((v) => !!data[v])) {
159
- return expr.evaluate(data as { [propertyName: string]: string }) as number;
160
- } else {
161
- return 0;
162
- }
163
- }
164
-
165
- function ShowVideo({ url }: { url: string }) {
166
- return (
167
- <div>
168
- <iframe
169
- width="560"
170
- height="315"
171
- src={"https://www.youtube.com/embed/" + url}
172
- title="YouTube video player"
173
- allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
174
- ></iframe>
175
- </div>
176
- );
177
- }
@@ -1,20 +0,0 @@
1
- import WrongIcon from "./icons/WrongIcon";
2
-
3
- export default function ShowErrors({ errors }: { errors: string[] }) {
4
- return (
5
- <div
6
- className="bg-red-50 border border-red-300 text-red-600 px-3 py-2 rounded-xl relative"
7
- role="alert"
8
- >
9
- <div className="flex items-center gap-2">
10
- <WrongIcon />
11
- <span className="font-semibold">{errors.length} error found.</span>
12
- </div>
13
- <ul className="mt-2 ml-7 list-disc list-inside">
14
- {errors.map((error) => (
15
- <li>{error}</li>
16
- ))}
17
- </ul>
18
- </div>
19
- );
20
- }
@@ -1,30 +0,0 @@
1
- export default function WrongIcon() {
2
- return (
3
- <svg
4
- fill="#c01c28"
5
- width="22px"
6
- height="22px"
7
- viewBox="0 0 200 200"
8
- data-name="Layer 1"
9
- id="Layer_1"
10
- xmlns="http://www.w3.org/2000/svg"
11
- stroke="#c01c28"
12
- >
13
- <g id="SVGRepo_bgCarrier" stroke-width="0" />
14
-
15
- <g
16
- id="SVGRepo_tracerCarrier"
17
- stroke-linecap="round"
18
- stroke-linejoin="round"
19
- />
20
-
21
- <g id="SVGRepo_iconCarrier">
22
- <title />
23
-
24
- <path d="M100,15a85,85,0,1,0,85,85A84.93,84.93,0,0,0,100,15Zm0,150a65,65,0,1,1,65-65A64.87,64.87,0,0,1,100,165Z" />
25
-
26
- <path d="M128.5,74a9.67,9.67,0,0,0-14,0L100,88.5l-14-14a9.9,9.9,0,0,0-14,14l14,14-14,14a9.9,9.9,0,0,0,14,14l14-14,14,14a9.9,9.9,0,0,0,14-14l-14-14,14-14A10.77,10.77,0,0,0,128.5,74Z" />
27
- </g>
28
- </svg>
29
- );
30
- }
@@ -1,37 +0,0 @@
1
- import { ChangeEvent } from "react";
2
-
3
- export type FileInputProps = {
4
- fileUrl?: string;
5
- setFileData?: (fileData: string) => void;
6
- disabled?: boolean;
7
- };
8
-
9
- export default function FileInput({
10
- fileUrl,
11
- setFileData,
12
- disabled,
13
- }: FileInputProps) {
14
- function handleChange(event: ChangeEvent<HTMLInputElement>) {
15
- if (event.target.files && event.target.files[0] && setFileData) {
16
- const reader = new FileReader();
17
- reader.onloadend = () => {
18
- setFileData(
19
- `${event.target.files![0].name}&&${reader.result as string}`,
20
- );
21
- };
22
- reader.readAsDataURL(event.target.files[0]);
23
- }
24
- }
25
- return (
26
- <div>
27
- {fileUrl && (
28
- <a href={fileUrl} target="_blank" className="text-blue-500 block">
29
- {fileUrl.substring(fileUrl.lastIndexOf("/") + 1)}
30
- </a>
31
- )}
32
- {setFileData && !disabled && (
33
- <input type="file" onChange={handleChange} />
34
- )}
35
- </div>
36
- );
37
- }
@@ -1,54 +0,0 @@
1
- import { HTMLInputTypeAttribute } from "react";
2
-
3
- export type InputProps = {
4
- value?: string;
5
- setValue: (s: string) => void;
6
- type: HTMLInputTypeAttribute;
7
- onBlur?: () => void;
8
- maxLength?: string;
9
- minLength?: string;
10
- max?: number;
11
- min?: number;
12
- placeholder?: string;
13
- disabled?: boolean;
14
- checked?: boolean;
15
- };
16
-
17
- export default function Input({
18
- value,
19
- setValue,
20
- type,
21
- onBlur,
22
- maxLength,
23
- minLength,
24
- max,
25
- min,
26
- placeholder,
27
- disabled,
28
- checked,
29
- }: InputProps) {
30
- return (
31
- <input
32
- type={type}
33
- className={`py-1.5 px-3 ${type === "checkbox" ? "size-5" : "w-full"} border-2 border-gray-300 rounded-xl text-base focus:border-blue-500 focus:ring-blue-500 disabled:bg-gray-400 disabled:opacity-50 disabled:pointer-events-none`}
34
- value={value}
35
- onChange={(e) =>
36
- type === "checkbox"
37
- ? setValue(String(e.target.checked))
38
- : setValue(e.target.value)
39
- }
40
- disabled={disabled}
41
- onBlur={onBlur}
42
- maxLength={
43
- maxLength && !isNaN(Number(maxLength)) ? Number(maxLength) : undefined
44
- }
45
- minLength={
46
- minLength && !isNaN(Number(minLength)) ? Number(minLength) : undefined
47
- }
48
- max={max}
49
- min={min}
50
- placeholder={placeholder}
51
- checked={checked}
52
- />
53
- );
54
- }
@@ -1,15 +0,0 @@
1
- import Input, { InputProps } from "./Input";
2
- import MultiSelect, { MultiSelectProps } from "./MultiSelect";
3
-
4
- type Props = {
5
- label: string;
6
- } & MultiSelectProps;
7
-
8
- export default function LabeledMutliSelect({ label, ...inputprops }: Props) {
9
- return (
10
- <div className="w-full">
11
- <label className="block text-sm font-bold mb-1">{label}</label>
12
- <MultiSelect {...inputprops} />
13
- </div>
14
- );
15
- }
@@ -1,14 +0,0 @@
1
- import FileInput, { FileInputProps } from "./FileInput";
2
-
3
- type Props = {
4
- label: string;
5
- } & FileInputProps;
6
-
7
- export default function LabeledFileInput({ label, ...inputProps }: Props) {
8
- return (
9
- <div className="w-full flex gap-2 items-center">
10
- <label className="block text-base font-bold mb-1">{label}</label>
11
- <FileInput {...inputProps} />
12
- </div>
13
- );
14
- }
@@ -1,14 +0,0 @@
1
- import Input, { InputProps } from "./Input";
2
-
3
- type Props = {
4
- label: string;
5
- } & InputProps;
6
-
7
- export default function LabeledInput({ label, ...inputProps }: Props) {
8
- return (
9
- <div className="w-full flex gap-2 items-center">
10
- <label className="block text-base font-bold mb-1">{label}</label>
11
- <Input {...inputProps} />
12
- </div>
13
- );
14
- }
@@ -1,14 +0,0 @@
1
- import Select, { SelectProps } from "./Select";
2
-
3
- type Props = {
4
- label: string;
5
- } & SelectProps;
6
-
7
- export default function LabeledSelect({ label, ...inputProps }: Props) {
8
- return (
9
- <div className="w-full">
10
- <label className="block text-sm font-bold mb-1">{label}</label>
11
- <Select {...inputProps} />
12
- </div>
13
- );
14
- }
@@ -1,89 +0,0 @@
1
- import React, { useState } from "react";
2
-
3
- export type MultiSelectProps = {
4
- options: string[];
5
- selectedOptions: string[];
6
- onChange: (selected: string[]) => void;
7
- disabled?: boolean;
8
- };
9
-
10
- const MultiSelect: React.FC<MultiSelectProps> = ({
11
- options,
12
- selectedOptions,
13
- onChange,
14
- disabled,
15
- }) => {
16
- const [isOpen, setIsOpen] = useState(false);
17
- const [filter, setFilter] = useState("");
18
-
19
- const toggleDropdown = () => setIsOpen(!isOpen);
20
-
21
- const handleOptionClick = (option: string) => {
22
- if (selectedOptions.includes(option)) {
23
- onChange(selectedOptions.filter((selected) => selected !== option));
24
- } else {
25
- onChange([...selectedOptions, option]);
26
- }
27
- };
28
- const handleFilterChange = (e: React.ChangeEvent<HTMLInputElement>) => {
29
- setFilter(e.target.value);
30
- };
31
-
32
- const filteredOptions = options.filter((option) =>
33
- option.toLowerCase().includes(filter.toLowerCase()),
34
- );
35
-
36
- return (
37
- <div className="relative inline-block w-full">
38
- <div
39
- className="py-2 px-3 bg-white block w-full border-2 border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none"
40
- onClick={toggleDropdown}
41
- >
42
- {Array.isArray(selectedOptions) && selectedOptions.length > 0 ? (
43
- selectedOptions.map((option) => (
44
- <span
45
- key={option}
46
- className="mr-1 inline-block rounded-full bg-secondary-blue px-2 py-1 text-sm"
47
- >
48
- {option}
49
- </span>
50
- ))
51
- ) : (
52
- <span className="text-placeholder-gray">Select options</span>
53
- )}
54
- </div>
55
- {isOpen && (
56
- <div className="absolute left-0 right-0 z-10 mt-2 rounded-md border border-secondary-gray bg-white">
57
- <input
58
- type="text"
59
- className="w-full border-b border-secondary-gray p-2"
60
- placeholder="Filter options..."
61
- value={filter}
62
- onChange={handleFilterChange}
63
- />
64
- <div className="max-h-60 overflow-y-auto">
65
- {filteredOptions.map((option) => (
66
- <div
67
- key={option}
68
- className="cursor-pointer p-2 hover:bg-primary-gray"
69
- onClick={() => {
70
- if (!disabled) handleOptionClick(option);
71
- }}
72
- >
73
- <input
74
- type="checkbox"
75
- checked={selectedOptions.includes(option)}
76
- readOnly
77
- className="mr-2"
78
- />
79
- <span className="ml-2">{option}</span>
80
- </div>
81
- ))}
82
- </div>
83
- </div>
84
- )}
85
- </div>
86
- );
87
- };
88
-
89
- export default MultiSelect;
@@ -1,33 +0,0 @@
1
- export type SelectProps = {
2
- options: string[];
3
- selected: string;
4
- setSelected: (s: string) => void;
5
- canDefault?: boolean;
6
- disabled?: boolean;
7
- };
8
-
9
- export default function Select({
10
- options,
11
- selected,
12
- setSelected,
13
- canDefault,
14
- disabled,
15
- }: SelectProps) {
16
- return (
17
- <select
18
- value={selected || ""}
19
- onChange={(e) => setSelected(e.target.value)}
20
- className="py-2 px-3 bg-white block w-full border-2 border-gray-200 rounded-lg text-sm focus:border-blue-500 focus:ring-blue-500 disabled:opacity-50 disabled:pointer-events-none"
21
- disabled={disabled}
22
- >
23
- <option value="" disabled={!canDefault} hidden={!canDefault}>
24
- selection
25
- </option>
26
- {options.map((opt, i) => (
27
- <option key={i} value={opt}>
28
- {opt}
29
- </option>
30
- ))}
31
- </select>
32
- );
33
- }
package/src/index.css DELETED
@@ -1,3 +0,0 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
package/src/index.tsx DELETED
@@ -1,6 +0,0 @@
1
- import "./index.css";
2
-
3
- export * from "./component/ComponentDisplayer";
4
- export * from "./component/ShowAttr";
5
-
6
- export * from "./util/type";
package/src/util/type.ts DELETED
@@ -1,124 +0,0 @@
1
- // Scalars
2
- export type DataJSON = Record<string, string | object>;
3
- export type DateTime = string;
4
-
5
- // Enums
6
- export enum ConditionEnum {
7
- EQ = "equal",
8
- SUP = "superior",
9
- INF = "inferior",
10
- CONTAIN = "contain",
11
- }
12
-
13
- export enum AttributeTypeEnum {
14
- TEXT = "text",
15
- LIST = "list",
16
- NUMBER = "number",
17
- BOOLEAN = "boolean",
18
- DATE = "date",
19
- NOTE = "note",
20
- IMAGE = "image",
21
- LINK = "link",
22
- MULTIPLE = "multiple",
23
- AUTOGEN = "autogen",
24
- FILE = "file",
25
- TITRE = "titre",
26
- TEXT_OUTPUT = "text_output",
27
- IMAGE_OUTPUT = "image_output",
28
- VIDEO_OUTPUT = "video_output",
29
- }
30
-
31
- export enum ComponentType {
32
- GENERAL = "general",
33
- ACCESS = "access",
34
- PEC = "PEC",
35
- DOSSIER = "dossier",
36
- PATIENT = "patient",
37
- PRESCRIPTION = "prescription",
38
- WORKFLOW = "workflow",
39
- FOLDER = "folder",
40
- CONSULTATION = "consultation",
41
- TREE = "tree",
42
- }
43
-
44
- // Types
45
- export interface Condition {
46
- attribute: string;
47
- cond: keyof typeof ConditionEnum;
48
- value: string;
49
- delimiter: string;
50
- }
51
-
52
- export interface ISettingsAttribute {
53
- max?: string;
54
- min?: string;
55
- color?: string;
56
- required?: boolean;
57
- newValue?: boolean;
58
- }
59
-
60
- export interface Attribute {
61
- name: string;
62
- label?: string;
63
- type?: keyof typeof AttributeTypeEnum;
64
- content?: Content;
65
- settings?: ISettingsAttribute;
66
- }
67
-
68
- export type Content = string | string[];
69
-
70
- export interface SettingsComponent {
71
- required?: boolean;
72
- }
73
-
74
- export interface Component {
75
- _id: string;
76
- name: string;
77
- label: string;
78
- type: keyof typeof ComponentType;
79
- attributes: Attribute[];
80
- conditions: Condition[][];
81
- settings?: SettingsComponent;
82
- filter?: PrescriptionFilterType;
83
- createdAt?: DateTime;
84
- updatedAt?: DateTime;
85
- }
86
-
87
- export interface ComponentResult {
88
- total: number;
89
- page: number;
90
- lastPage: number;
91
- data: Component[];
92
- }
93
-
94
- export interface Data {
95
- _id: string;
96
- proprietor: string;
97
- from: string;
98
- component: Component;
99
- value: DataJSON;
100
- extra: DataJSON;
101
- createdAt: DateTime;
102
- updatedAt: DateTime;
103
- }
104
-
105
- export interface DataResult {
106
- total: number;
107
- page: number;
108
- lastPage: number;
109
- data: Data[];
110
- }
111
-
112
- export type PrescriptionFilterType = {
113
- protocol: string | null;
114
- cure: string | null;
115
- molecule: string | null;
116
- dose: Filter | null;
117
- validation: Filter | null;
118
- info: boolean | null;
119
- };
120
-
121
- export type Filter = {
122
- op: ConditionEnum | "";
123
- value: string;
124
- };