@addsign/moje-agenda-shared-lib 2.0.72 → 2.0.74
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/Dialog-BmQoVu5C.js.map +1 -1
- package/dist/assets/style.css +1771 -1760
- package/dist/components/Attachments.js +2 -2
- package/dist/components/datatable/DataTable.js +3 -3
- package/dist/components/datatable/DataTableServer.js +3 -3
- package/dist/components/form/AutocompleteSearchBar.js +2 -2
- package/dist/components/form/AutocompleteSearchBarServer.js +2 -2
- package/dist/components/form/FileInput.js +3 -3
- package/dist/components/form/FileInputForm.d.ts +1 -0
- package/dist/components/form/FileInputForm.js +201 -93
- package/dist/components/form/FileInputForm.js.map +1 -1
- package/dist/components/form/FileInputFormMultiple.d.ts +1 -0
- package/dist/components/form/FileInputFormMultiple.js +203 -82
- package/dist/components/form/FileInputFormMultiple.js.map +1 -1
- package/dist/components/form/FileInputMultiple.js +3 -3
- package/dist/components/form/FormField.js +2 -2
- package/dist/components/form/PositionsSelectorSingle.js +3 -3
- package/dist/components/form/SelectField.js +2 -2
- package/dist/components/layout/Neoptimizovano.js +2 -2
- package/dist/components/profiles/ProfileOverview.js +2 -2
- package/dist/components/ui/Combobox.js +4 -4
- package/dist/components/ui/Combobox.js.map +1 -1
- package/dist/components/ui/DatePicker.js +2 -2
- package/dist/components/ui/DateTimePicker.js +2 -2
- package/dist/components/ui/Dialog.js +1 -1
- package/dist/components/ui/ScrollArea.js +2 -2
- package/dist/components/ui/checkbox.js +4 -4
- package/dist/components/ui/command.d.ts +6 -6
- package/dist/components/ui/command.js +2 -2
- package/dist/components/ui/input.js +8 -107
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/multi-select.js +1 -1
- package/dist/components/ui/popover.js +1 -1
- package/dist/components/ui/radioGroup.js +5 -5
- package/dist/components/ui/select.js +7 -7
- package/dist/components/ui/toast.js +5 -5
- package/dist/components/ui/tooltip.js +6 -6
- package/dist/input-Cm_FjJOF.js +111 -0
- package/dist/input-Cm_FjJOF.js.map +1 -0
- package/dist/main.js +3 -3
- package/dist/popover-DpJhfyvx.js.map +1 -1
- package/lib/components/form/FileInputForm.tsx +245 -99
- package/lib/components/form/FileInputFormMultiple.tsx +233 -65
- package/lib/components/ui/Combobox.tsx +3 -3
- package/lib/css/tailwind.css +9 -9
- package/package.json +1 -1
- package/tailwind.config.js +97 -97
|
@@ -2,10 +2,20 @@ import React, { useState, useCallback, useEffect } from "react";
|
|
|
2
2
|
import { useDropzone } from "react-dropzone";
|
|
3
3
|
import { MdDeleteOutline, MdInsertDriveFile } from "react-icons/md";
|
|
4
4
|
import { AxiosError } from "axios";
|
|
5
|
+
import { LoaderCircleIcon } from "lucide-react";
|
|
5
6
|
import { cn } from "../../utils/utils";
|
|
6
7
|
import { handleErrors } from "@addsign/moje-agenda-shared-lib";
|
|
7
8
|
import { IAttachment } from "../../types";
|
|
8
9
|
import { useFederationContext, useFormField } from "../../main";
|
|
10
|
+
import {
|
|
11
|
+
Dialog,
|
|
12
|
+
DialogContent,
|
|
13
|
+
DialogHeader,
|
|
14
|
+
DialogTitle,
|
|
15
|
+
DialogFooter,
|
|
16
|
+
} from "../ui/Dialog";
|
|
17
|
+
import { Input } from "../ui/input";
|
|
18
|
+
import { Button } from "../ui/button";
|
|
9
19
|
|
|
10
20
|
interface FileInputFormMultipleProps {
|
|
11
21
|
name: string;
|
|
@@ -17,6 +27,7 @@ interface FileInputFormMultipleProps {
|
|
|
17
27
|
initialFileIds?: number[];
|
|
18
28
|
attachmentName?: string;
|
|
19
29
|
attachmentType?: string;
|
|
30
|
+
askForAttachmentName?: boolean;
|
|
20
31
|
}
|
|
21
32
|
|
|
22
33
|
interface IAttachmentReadOnly extends IAttachment {
|
|
@@ -35,6 +46,7 @@ const FileInputFormMultiple: React.FC<FileInputFormMultipleProps> = ({
|
|
|
35
46
|
initialFileIds,
|
|
36
47
|
attachmentName,
|
|
37
48
|
attachmentType,
|
|
49
|
+
askForAttachmentName = false,
|
|
38
50
|
}) => {
|
|
39
51
|
const [fileDataList, setFileDataList] = useState<IAttachmentReadOnly[]>(
|
|
40
52
|
value?.map((file) => ({
|
|
@@ -43,6 +55,11 @@ const FileInputFormMultiple: React.FC<FileInputFormMultipleProps> = ({
|
|
|
43
55
|
})) || []
|
|
44
56
|
);
|
|
45
57
|
|
|
58
|
+
const [pendingFiles, setPendingFiles] = useState<File[]>([]);
|
|
59
|
+
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
60
|
+
const [fileNames, setFileNames] = useState<Record<string, string>>({});
|
|
61
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
62
|
+
|
|
46
63
|
const federationContext = useFederationContext();
|
|
47
64
|
|
|
48
65
|
const { error } = useFormField();
|
|
@@ -61,10 +78,11 @@ const FileInputFormMultiple: React.FC<FileInputFormMultipleProps> = ({
|
|
|
61
78
|
);
|
|
62
79
|
}, [value, initialFilesReadOnly, initialFileIds]);
|
|
63
80
|
|
|
64
|
-
const
|
|
65
|
-
async (
|
|
81
|
+
const uploadFiles = useCallback(
|
|
82
|
+
async (files: File[], customNames?: Record<string, string>) => {
|
|
83
|
+
setIsUploading(true);
|
|
66
84
|
const uploadedFiles = await Promise.all(
|
|
67
|
-
|
|
85
|
+
files.map(async (file) => {
|
|
68
86
|
if (file.size > MAX_FILE_SIZE) {
|
|
69
87
|
// Handle the case when the file size is exceeded
|
|
70
88
|
federationContext.emitter.emit("message", {
|
|
@@ -82,7 +100,9 @@ const FileInputFormMultiple: React.FC<FileInputFormMultipleProps> = ({
|
|
|
82
100
|
|
|
83
101
|
// Add the JSON data object
|
|
84
102
|
const dataObject = {
|
|
85
|
-
...(
|
|
103
|
+
...(customNames?.[file.name]
|
|
104
|
+
? { attachmentName: customNames[file.name] }
|
|
105
|
+
: attachmentName && { attachmentName }),
|
|
86
106
|
...(attachmentType && { attachmentType }),
|
|
87
107
|
};
|
|
88
108
|
|
|
@@ -118,6 +138,7 @@ const FileInputFormMultiple: React.FC<FileInputFormMultipleProps> = ({
|
|
|
118
138
|
const updatedFileDataList = [...fileDataList, ...validFiles];
|
|
119
139
|
setFileDataList(updatedFileDataList);
|
|
120
140
|
onFilesChanged(updatedFileDataList);
|
|
141
|
+
setIsUploading(false);
|
|
121
142
|
},
|
|
122
143
|
[
|
|
123
144
|
federationContext,
|
|
@@ -128,9 +149,67 @@ const FileInputFormMultiple: React.FC<FileInputFormMultipleProps> = ({
|
|
|
128
149
|
]
|
|
129
150
|
);
|
|
130
151
|
|
|
152
|
+
const onDrop = useCallback(
|
|
153
|
+
async (acceptedFiles: File[]) => {
|
|
154
|
+
// Filter out files that exceed size limit
|
|
155
|
+
const validFiles = acceptedFiles.filter((file) => {
|
|
156
|
+
if (file.size > MAX_FILE_SIZE) {
|
|
157
|
+
federationContext.emitter.emit("message", {
|
|
158
|
+
title: "Velikost souboru byla překročena",
|
|
159
|
+
message: `Maximální povolená velikost je ${MAX_FILE_SIZE / (1024 * 1024)} MB.`,
|
|
160
|
+
classes: "bg-danger ",
|
|
161
|
+
timeout: 0,
|
|
162
|
+
type: "error",
|
|
163
|
+
});
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
if (validFiles.length === 0) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (askForAttachmentName) {
|
|
174
|
+
// Initialize file names with original file names
|
|
175
|
+
const initialNames: Record<string, string> = {};
|
|
176
|
+
validFiles.forEach((file) => {
|
|
177
|
+
initialNames[file.name] = file.name;
|
|
178
|
+
});
|
|
179
|
+
setFileNames(initialNames);
|
|
180
|
+
setPendingFiles(validFiles);
|
|
181
|
+
setIsDialogOpen(true);
|
|
182
|
+
} else {
|
|
183
|
+
await uploadFiles(validFiles);
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
[askForAttachmentName, uploadFiles, federationContext]
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
const handleDialogSubmit = async () => {
|
|
190
|
+
setIsDialogOpen(false);
|
|
191
|
+
await uploadFiles(pendingFiles, fileNames);
|
|
192
|
+
setPendingFiles([]);
|
|
193
|
+
setFileNames({});
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const handleDialogCancel = () => {
|
|
197
|
+
setIsDialogOpen(false);
|
|
198
|
+
setPendingFiles([]);
|
|
199
|
+
setFileNames({});
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const formatFileSize = (bytes: number): string => {
|
|
203
|
+
if (bytes === 0) return "0 Bytes";
|
|
204
|
+
const k = 1024;
|
|
205
|
+
const sizes = ["Bytes", "KB", "MB", "GB"];
|
|
206
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
207
|
+
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + " " + sizes[i];
|
|
208
|
+
};
|
|
209
|
+
|
|
131
210
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
|
132
211
|
onDrop,
|
|
133
|
-
disabled,
|
|
212
|
+
disabled: disabled || isUploading,
|
|
134
213
|
});
|
|
135
214
|
|
|
136
215
|
const handleRemove = (fileId: number) => {
|
|
@@ -146,74 +225,163 @@ const FileInputFormMultiple: React.FC<FileInputFormMultipleProps> = ({
|
|
|
146
225
|
}
|
|
147
226
|
|
|
148
227
|
return (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
<div
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
228
|
+
<>
|
|
229
|
+
<div
|
|
230
|
+
className="w-full min-h-30 flex-col justify-start items-start gap-1.5 inline-flex sharedLibrary"
|
|
231
|
+
data-cy={"file-input-form-multiple-" + name}
|
|
232
|
+
>
|
|
233
|
+
<div className="self-stretch flex-col justify-start items-start gap-1.5 flex">
|
|
234
|
+
<div
|
|
235
|
+
className={cn(
|
|
236
|
+
`self-stretch px-3 py-2 rounded-lg justify-start items-center gap-2 outline-none border bg-transparent relative`,
|
|
237
|
+
hasError &&
|
|
158
238
|
"outline-4 outline-red-200 outline-offset-0 border-none ",
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
{isDragActive
|
|
172
|
-
? "Sem přetáhněte soubory"
|
|
173
|
-
: "Klikněte pro nahrání, nebo nahrajte přetažením souborů"}
|
|
174
|
-
</p>
|
|
175
|
-
</div>
|
|
176
|
-
)}
|
|
177
|
-
<div className="w-full">
|
|
178
|
-
{fileDataList.map((file) => (
|
|
239
|
+
disabled ? "bg-gray-100" : "bg-transparent"
|
|
240
|
+
)}
|
|
241
|
+
>
|
|
242
|
+
{isUploading && (
|
|
243
|
+
<div className="absolute inset-0 bg-white/80 backdrop-blur-sm rounded-lg z-10 flex items-center justify-center">
|
|
244
|
+
<div className="flex flex-col items-center gap-2">
|
|
245
|
+
<LoaderCircleIcon className="h-8 w-8 animate-spin text-primary" />
|
|
246
|
+
<p className="text-sm text-gray-600">Nahrávání...</p>
|
|
247
|
+
</div>
|
|
248
|
+
</div>
|
|
249
|
+
)}
|
|
250
|
+
{!disabled && (
|
|
179
251
|
<div
|
|
180
|
-
|
|
181
|
-
className=
|
|
252
|
+
{...getRootProps()}
|
|
253
|
+
className={cn(
|
|
254
|
+
`w-full p-4 border-dashed border-2 rounded-lg text-center`,
|
|
255
|
+
isUploading
|
|
256
|
+
? "cursor-not-allowed opacity-50"
|
|
257
|
+
: "cursor-pointer hover:bg-gray-100",
|
|
258
|
+
isDragActive ? "border-indigo-300 bg-indigo-50" : "border-gray-300"
|
|
259
|
+
)}
|
|
182
260
|
>
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
261
|
+
<input {...getInputProps()} id={name} />
|
|
262
|
+
<p className="text-gray-500">
|
|
263
|
+
{isDragActive
|
|
264
|
+
? "Sem přetáhněte soubory"
|
|
265
|
+
: "Klikněte pro nahrání, nebo nahrajte přetažením souborů"}
|
|
266
|
+
</p>
|
|
267
|
+
</div>
|
|
268
|
+
)}
|
|
269
|
+
<div className="w-full">
|
|
270
|
+
{fileDataList.map((file) => (
|
|
271
|
+
<div
|
|
272
|
+
key={file.id}
|
|
273
|
+
className="w-full flex items-center justify-between py-2 border-b "
|
|
274
|
+
>
|
|
275
|
+
<div className="flex flex-col flex-1">
|
|
276
|
+
<div className="flex items-center content-center gap-2">
|
|
277
|
+
<MdInsertDriveFile style={{ fontSize: "2rem" }} />
|
|
278
|
+
|
|
279
|
+
<div className="flex flex-col flex-1">
|
|
280
|
+
<a
|
|
281
|
+
href={`/api/files/download/${file.id}`}
|
|
282
|
+
className="text-left underline text-primary text-sm"
|
|
283
|
+
target="_blank"
|
|
284
|
+
>
|
|
285
|
+
{file.filename}
|
|
286
|
+
</a>
|
|
287
|
+
{file.attachmentName && (
|
|
288
|
+
<div className="text-sm text-gray-600">
|
|
289
|
+
{file.attachmentName}
|
|
290
|
+
</div>
|
|
291
|
+
)}
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
|
|
295
|
+
</div>
|
|
296
|
+
{!disabled && file.readonly !== true && !isUploading && (
|
|
297
|
+
<div
|
|
298
|
+
onClick={() => handleRemove(file.id)}
|
|
299
|
+
className="text-gray-600 cursor-pointer hover:text-primary hover:bg-gray-200 rounded-full ml-4"
|
|
300
|
+
>
|
|
301
|
+
<MdDeleteOutline
|
|
302
|
+
style={{ fontSize: "1.5rem", margin: "10px" }}
|
|
303
|
+
/>
|
|
304
|
+
</div>
|
|
305
|
+
)}
|
|
192
306
|
</div>
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
307
|
+
))}
|
|
308
|
+
</div>
|
|
309
|
+
</div>
|
|
310
|
+
</div>
|
|
311
|
+
{description && (
|
|
312
|
+
<div
|
|
313
|
+
className="HintText self-stretch text-slate-600 text-sm font-normal leading-tight"
|
|
314
|
+
id={name + ":description"}
|
|
315
|
+
>
|
|
316
|
+
{description}
|
|
317
|
+
</div>
|
|
318
|
+
)}
|
|
319
|
+
</div>
|
|
320
|
+
|
|
321
|
+
<Dialog
|
|
322
|
+
open={isDialogOpen}
|
|
323
|
+
onOpenChange={(open) => {
|
|
324
|
+
setIsDialogOpen(open);
|
|
325
|
+
if (!open) {
|
|
326
|
+
handleDialogCancel();
|
|
327
|
+
}
|
|
328
|
+
}}
|
|
329
|
+
>
|
|
330
|
+
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
|
331
|
+
<DialogHeader>
|
|
332
|
+
<DialogTitle>Zadejte popisy příloh</DialogTitle>
|
|
333
|
+
</DialogHeader>
|
|
334
|
+
<div className="space-y-4 py-4">
|
|
335
|
+
{pendingFiles.map((file) => (
|
|
336
|
+
<div
|
|
337
|
+
key={file.name}
|
|
338
|
+
className="flex flex-col gap-2 p-4 border rounded-lg"
|
|
339
|
+
>
|
|
340
|
+
<div className="flex items-center gap-2">
|
|
341
|
+
<MdInsertDriveFile style={{ fontSize: "1.5rem" }} />
|
|
342
|
+
<div className="flex-1">
|
|
343
|
+
<div className="font-medium text-sm">{file.name}</div>
|
|
344
|
+
<div className="text-xs text-gray-500">
|
|
345
|
+
{formatFileSize(file.size)}
|
|
346
|
+
</div>
|
|
201
347
|
</div>
|
|
202
|
-
|
|
348
|
+
</div>
|
|
349
|
+
<div className="mt-2">
|
|
350
|
+
<label className="text-sm font-medium mb-1 block">
|
|
351
|
+
Popis přílohy:
|
|
352
|
+
</label>
|
|
353
|
+
<Input
|
|
354
|
+
value={fileNames[file.name] || file.name}
|
|
355
|
+
onChange={(e) =>
|
|
356
|
+
setFileNames({
|
|
357
|
+
...fileNames,
|
|
358
|
+
[file.name]: e.target.value,
|
|
359
|
+
})
|
|
360
|
+
}
|
|
361
|
+
placeholder="Zadejte popis přílohy"
|
|
362
|
+
/>
|
|
363
|
+
</div>
|
|
203
364
|
</div>
|
|
204
365
|
))}
|
|
205
366
|
</div>
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
367
|
+
<DialogFooter>
|
|
368
|
+
<Button variant="outline" onClick={handleDialogCancel} disabled={isUploading}>
|
|
369
|
+
Zrušit
|
|
370
|
+
</Button>
|
|
371
|
+
<Button onClick={handleDialogSubmit} disabled={isUploading}>
|
|
372
|
+
{isUploading ? (
|
|
373
|
+
<>
|
|
374
|
+
<LoaderCircleIcon className="h-4 w-4 animate-spin mr-2" />
|
|
375
|
+
Nahrávání...
|
|
376
|
+
</>
|
|
377
|
+
) : (
|
|
378
|
+
"Nahrát"
|
|
379
|
+
)}
|
|
380
|
+
</Button>
|
|
381
|
+
</DialogFooter>
|
|
382
|
+
</DialogContent>
|
|
383
|
+
</Dialog>
|
|
384
|
+
</>
|
|
217
385
|
);
|
|
218
386
|
};
|
|
219
387
|
|
|
@@ -98,7 +98,7 @@ const Combobox = React.forwardRef<HTMLButtonElement, ComboboxProps>(
|
|
|
98
98
|
role="combobox"
|
|
99
99
|
aria-expanded={open}
|
|
100
100
|
disabled={disabled}
|
|
101
|
-
className={cn("w-full justify-between", className)}
|
|
101
|
+
className={cn("w-full justify-between gap-2", className)}
|
|
102
102
|
title={
|
|
103
103
|
value
|
|
104
104
|
? frameworks.find((framework) => framework.value === value)
|
|
@@ -106,7 +106,7 @@ const Combobox = React.forwardRef<HTMLButtonElement, ComboboxProps>(
|
|
|
106
106
|
: placeholder
|
|
107
107
|
}
|
|
108
108
|
>
|
|
109
|
-
<span className="flex-1 text-left truncate
|
|
109
|
+
<span className="flex-1 text-left truncate font-normal">
|
|
110
110
|
{value ? (
|
|
111
111
|
frameworks.find((framework) => framework.value === value)
|
|
112
112
|
?.label
|
|
@@ -117,7 +117,7 @@ const Combobox = React.forwardRef<HTMLButtonElement, ComboboxProps>(
|
|
|
117
117
|
)}
|
|
118
118
|
</span>
|
|
119
119
|
|
|
120
|
-
<ChevronsUpDown className="h-4 w-4 shrink-0 opacity-50
|
|
120
|
+
<ChevronsUpDown className="h-4 w-4 shrink-0 opacity-50" />
|
|
121
121
|
</Button>
|
|
122
122
|
</PopoverTrigger>
|
|
123
123
|
{clearable && !disabled && value && (
|
package/lib/css/tailwind.css
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
@tailwind base;
|
|
2
|
-
@tailwind components;
|
|
3
|
-
@tailwind utilities;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
:root {
|
|
8
|
-
/* --color-primary: green;
|
|
9
|
-
Example color */
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
:root {
|
|
8
|
+
/* --color-primary: green;
|
|
9
|
+
Example color */
|
|
10
10
|
}
|
package/package.json
CHANGED
package/tailwind.config.js
CHANGED
|
@@ -1,97 +1,97 @@
|
|
|
1
|
-
|
|
2
|
-
/** @type {import('tailwindcss').Config.theme.extend} */
|
|
3
|
-
export const TAILWIND_THEME_EXTEND = {
|
|
4
|
-
colors: {
|
|
5
|
-
border: "var(--border)",
|
|
6
|
-
input: "var(--input)",
|
|
7
|
-
ring: "var(--ring)",
|
|
8
|
-
background: "var(--background)",
|
|
9
|
-
foreground: "var(--foreground)",
|
|
10
|
-
|
|
11
|
-
// Using modern `rgb`
|
|
12
|
-
primary: {
|
|
13
|
-
DEFAULT: "var(--color-primary)",
|
|
14
|
-
hover: "var(--color-primary-hover)",
|
|
15
|
-
text: "var(--color-primary-text)",
|
|
16
|
-
foreground: "var(--color-primary-text)",
|
|
17
|
-
border: "var(--color-primary-border)",
|
|
18
|
-
},
|
|
19
|
-
secondary: {
|
|
20
|
-
DEFAULT: "var(--color-secondary)",
|
|
21
|
-
hover: "var(--color-secondary-hover)",
|
|
22
|
-
text: "var(--color-secondary-text)",
|
|
23
|
-
foreground: "var(--secondary-foreground)",
|
|
24
|
-
border: "var(--color-secondary-border)",
|
|
25
|
-
},
|
|
26
|
-
danger: {
|
|
27
|
-
DEFAULT: "var(--color-danger)",
|
|
28
|
-
hover: "var(--color-danger-hover)",
|
|
29
|
-
text: "var(--color-danger-text)",
|
|
30
|
-
border: "var(--color-danger-border)",
|
|
31
|
-
},
|
|
32
|
-
destructive: {
|
|
33
|
-
DEFAULT: "var(--destructive)",
|
|
34
|
-
foreground: "var(--destructive-foreground)",
|
|
35
|
-
},
|
|
36
|
-
warning: {
|
|
37
|
-
DEFAULT: "var(--color-warning)",
|
|
38
|
-
hover: "var(--color-warning-hover)",
|
|
39
|
-
text: "var(--color-warning-text)",
|
|
40
|
-
border: "var(--color-warning-border)",
|
|
41
|
-
},
|
|
42
|
-
success: {
|
|
43
|
-
DEFAULT: "var(--color-success)",
|
|
44
|
-
hover: "var(--color-success-hover)",
|
|
45
|
-
text: "var(--color-success-text)",
|
|
46
|
-
border: "var(--color-success-border)",
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
gray: {
|
|
50
|
-
150: "rgb(238, 240, 243)",
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
muted: {
|
|
54
|
-
DEFAULT: "var(--muted)",
|
|
55
|
-
foreground: "var(--muted-foreground)",
|
|
56
|
-
},
|
|
57
|
-
accent: {
|
|
58
|
-
DEFAULT: "var(--accent)",
|
|
59
|
-
foreground: "var(--accent-foreground)",
|
|
60
|
-
},
|
|
61
|
-
popover: {
|
|
62
|
-
DEFAULT: "var(--popover)",
|
|
63
|
-
foreground: "var(--popover-foreground)",
|
|
64
|
-
},
|
|
65
|
-
card: {
|
|
66
|
-
DEFAULT: "var(--card)",
|
|
67
|
-
foreground: "var(--card-foreground)",
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
|
|
71
|
-
animation: {
|
|
72
|
-
spin: 'spin 2s linear infinite',
|
|
73
|
-
},
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/** @type {import('tailwindcss').Config} */
|
|
77
|
-
export default {
|
|
78
|
-
darkMode: "class",
|
|
79
|
-
important: false, // Ensures all classes use !important
|
|
80
|
-
|
|
81
|
-
content: [
|
|
82
|
-
"./lib/**/*.{js,ts,jsx,tsx}",
|
|
83
|
-
"./lib/**/*.{ts,tsx}",
|
|
84
|
-
"./lib/components/**/*.{ts,tsx}",
|
|
85
|
-
"./node_modules/react-tailwindcss-datepicker/dist/index.esm.js",
|
|
86
|
-
],
|
|
87
|
-
theme: {
|
|
88
|
-
extend: TAILWIND_THEME_EXTEND,
|
|
89
|
-
},
|
|
90
|
-
plugins: [],
|
|
91
|
-
safelist: [
|
|
92
|
-
"bg-danger", // Add any other dynamic classes here
|
|
93
|
-
"lg:grid-cols-3",
|
|
94
|
-
"lg:grid-cols-2",
|
|
95
|
-
"lg:grid-cols-4",
|
|
96
|
-
],
|
|
97
|
-
};
|
|
1
|
+
|
|
2
|
+
/** @type {import('tailwindcss').Config.theme.extend} */
|
|
3
|
+
export const TAILWIND_THEME_EXTEND = {
|
|
4
|
+
colors: {
|
|
5
|
+
border: "var(--border)",
|
|
6
|
+
input: "var(--input)",
|
|
7
|
+
ring: "var(--ring)",
|
|
8
|
+
background: "var(--background)",
|
|
9
|
+
foreground: "var(--foreground)",
|
|
10
|
+
|
|
11
|
+
// Using modern `rgb`
|
|
12
|
+
primary: {
|
|
13
|
+
DEFAULT: "var(--color-primary)",
|
|
14
|
+
hover: "var(--color-primary-hover)",
|
|
15
|
+
text: "var(--color-primary-text)",
|
|
16
|
+
foreground: "var(--color-primary-text)",
|
|
17
|
+
border: "var(--color-primary-border)",
|
|
18
|
+
},
|
|
19
|
+
secondary: {
|
|
20
|
+
DEFAULT: "var(--color-secondary)",
|
|
21
|
+
hover: "var(--color-secondary-hover)",
|
|
22
|
+
text: "var(--color-secondary-text)",
|
|
23
|
+
foreground: "var(--secondary-foreground)",
|
|
24
|
+
border: "var(--color-secondary-border)",
|
|
25
|
+
},
|
|
26
|
+
danger: {
|
|
27
|
+
DEFAULT: "var(--color-danger)",
|
|
28
|
+
hover: "var(--color-danger-hover)",
|
|
29
|
+
text: "var(--color-danger-text)",
|
|
30
|
+
border: "var(--color-danger-border)",
|
|
31
|
+
},
|
|
32
|
+
destructive: {
|
|
33
|
+
DEFAULT: "var(--destructive)",
|
|
34
|
+
foreground: "var(--destructive-foreground)",
|
|
35
|
+
},
|
|
36
|
+
warning: {
|
|
37
|
+
DEFAULT: "var(--color-warning)",
|
|
38
|
+
hover: "var(--color-warning-hover)",
|
|
39
|
+
text: "var(--color-warning-text)",
|
|
40
|
+
border: "var(--color-warning-border)",
|
|
41
|
+
},
|
|
42
|
+
success: {
|
|
43
|
+
DEFAULT: "var(--color-success)",
|
|
44
|
+
hover: "var(--color-success-hover)",
|
|
45
|
+
text: "var(--color-success-text)",
|
|
46
|
+
border: "var(--color-success-border)",
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
gray: {
|
|
50
|
+
150: "rgb(238, 240, 243)",
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
muted: {
|
|
54
|
+
DEFAULT: "var(--muted)",
|
|
55
|
+
foreground: "var(--muted-foreground)",
|
|
56
|
+
},
|
|
57
|
+
accent: {
|
|
58
|
+
DEFAULT: "var(--accent)",
|
|
59
|
+
foreground: "var(--accent-foreground)",
|
|
60
|
+
},
|
|
61
|
+
popover: {
|
|
62
|
+
DEFAULT: "var(--popover)",
|
|
63
|
+
foreground: "var(--popover-foreground)",
|
|
64
|
+
},
|
|
65
|
+
card: {
|
|
66
|
+
DEFAULT: "var(--card)",
|
|
67
|
+
foreground: "var(--card-foreground)",
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
animation: {
|
|
72
|
+
spin: 'spin 2s linear infinite',
|
|
73
|
+
},
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** @type {import('tailwindcss').Config} */
|
|
77
|
+
export default {
|
|
78
|
+
darkMode: "class",
|
|
79
|
+
important: false, // Ensures all classes use !important
|
|
80
|
+
|
|
81
|
+
content: [
|
|
82
|
+
"./lib/**/*.{js,ts,jsx,tsx}",
|
|
83
|
+
"./lib/**/*.{ts,tsx}",
|
|
84
|
+
"./lib/components/**/*.{ts,tsx}",
|
|
85
|
+
"./node_modules/react-tailwindcss-datepicker/dist/index.esm.js",
|
|
86
|
+
],
|
|
87
|
+
theme: {
|
|
88
|
+
extend: TAILWIND_THEME_EXTEND,
|
|
89
|
+
},
|
|
90
|
+
plugins: [],
|
|
91
|
+
safelist: [
|
|
92
|
+
"bg-danger", // Add any other dynamic classes here
|
|
93
|
+
"lg:grid-cols-3",
|
|
94
|
+
"lg:grid-cols-2",
|
|
95
|
+
"lg:grid-cols-4",
|
|
96
|
+
],
|
|
97
|
+
};
|