@rkosafo/cai.components 0.0.78 → 0.0.80
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/README.md +8 -8
- package/dist/baseEditor/index.svelte +32 -32
- package/dist/builders/filters/FilterBuilder.svelte +641 -641
- package/dist/forms/FormCheckbox/FormCheckbox.svelte +53 -53
- package/dist/forms/FormClEditor/ClEdito.svelte +68 -68
- package/dist/forms/FormDatepicker/FormDatepicker.svelte +159 -159
- package/dist/forms/FormFileUpload/FormFileUplad.svelte +134 -134
- package/dist/forms/FormInput/FormInput.svelte +87 -87
- package/dist/forms/FormRadio/FormRadio.svelte +53 -53
- package/dist/forms/FormSelect/FormSelect.svelte +88 -88
- package/dist/forms/FormTextarea/FormTextarea.svelte +78 -78
- package/dist/forms/button-toggle/ButtonToggle.svelte +119 -119
- package/dist/forms/button-toggle/CheckIcon.svelte +28 -28
- package/dist/forms/checkbox/Checkbox.svelte +82 -82
- package/dist/forms/checkbox/CheckboxButton.svelte +92 -92
- package/dist/forms/datepicker/Datepicker.svelte +707 -707
- package/dist/forms/form/Form.svelte +69 -69
- package/dist/forms/input/Input.svelte +363 -363
- package/dist/forms/label/Label.svelte +38 -38
- package/dist/forms/radio/Radio.svelte +48 -48
- package/dist/forms/radio/RadioButton.svelte +22 -22
- package/dist/forms/select/Select.svelte +56 -56
- package/dist/forms/textarea/Textarea.svelte +165 -165
- package/dist/forms/toggle/Toggle.svelte +70 -70
- package/dist/layout/Chat/CategorySelector.svelte +52 -52
- package/dist/layout/Chat/ChatEntry.svelte +246 -246
- package/dist/layout/Chat/ChatEntrySkeleton.svelte +81 -81
- package/dist/layout/Chat/ChatHeader.svelte +172 -172
- package/dist/layout/Chat/ChatInput.svelte +207 -207
- package/dist/layout/Chat/DraggableWindow.svelte +230 -230
- package/dist/layout/Chat/PreviewPage.svelte +182 -182
- package/dist/layout/Chat/RichText.svelte +216 -216
- package/dist/layout/ComponentCanvas/Canvas.svelte +40 -40
- package/dist/layout/ComponentCanvas/ComponentRenderer.svelte +85 -85
- package/dist/layout/TF/Content/Content.svelte +21 -21
- package/dist/layout/TF/Header/Header.svelte +166 -166
- package/dist/layout/TF/Sidebar/Sidebar.svelte +148 -148
- package/dist/layout/TF/Wrapper/Wrapper.svelte +17 -17
- package/dist/layout/mailing/MailPaginator.svelte +36 -36
- package/dist/layout/mailing/MailSidebar.svelte +39 -39
- package/dist/layout/mailing/MailToolBar.svelte +174 -174
- package/dist/layout/mailing/MailingContent.svelte +10 -10
- package/dist/layout/mailing/MailingHeader.svelte +55 -55
- package/dist/layout/mailing/MailingMessageCard.svelte +112 -112
- package/dist/layout/mailing/MailingMessageViewer.svelte +87 -87
- package/dist/layout/mailing/MailingModule.svelte +448 -448
- package/dist/styles/docs.css +615 -615
- package/dist/styles/tf-layout.css +185 -185
- package/dist/themes/ThemeProvider.svelte +20 -20
- package/dist/types/index.d.ts +2 -0
- package/dist/typography/heading/Heading.svelte +35 -35
- package/dist/ui/accordion/Accordion.svelte +49 -49
- package/dist/ui/accordion/AccordionItem.svelte +173 -173
- package/dist/ui/alert/Alert.svelte +83 -83
- package/dist/ui/alertDialog/AlertDialog.svelte +40 -40
- package/dist/ui/avatar/Avatar.svelte +77 -77
- package/dist/ui/box/Box.svelte +28 -28
- package/dist/ui/breadcrumb/Breadcrumb.svelte +39 -39
- package/dist/ui/buttons/ActionButton.svelte +234 -234
- package/dist/ui/buttons/Button.svelte +102 -102
- package/dist/ui/buttons/GradientButton.svelte +59 -59
- package/dist/ui/datatable/Datatable.svelte +525 -525
- package/dist/ui/drawer/Drawer.svelte +300 -300
- package/dist/ui/dropdown/Dropdown.svelte +36 -36
- package/dist/ui/dropdown/DropdownDivider.svelte +11 -11
- package/dist/ui/dropdown/DropdownGroup.svelte +14 -14
- package/dist/ui/dropdown/DropdownHeader.svelte +14 -14
- package/dist/ui/dropdown/DropdownItem.svelte +52 -52
- package/dist/ui/footer/Footer.svelte +15 -15
- package/dist/ui/footer/FooterBrand.svelte +37 -37
- package/dist/ui/footer/FooterCopyright.svelte +45 -45
- package/dist/ui/footer/FooterIcon.svelte +22 -22
- package/dist/ui/footer/FooterLink.svelte +33 -33
- package/dist/ui/footer/FooterLinkGroup.svelte +13 -13
- package/dist/ui/icons/IconifyIcon.svelte +7 -7
- package/dist/ui/indicator/Indicator.svelte +42 -42
- package/dist/ui/modal/Modal.svelte +265 -265
- package/dist/ui/notificationList/NotificationList.svelte +123 -123
- package/dist/ui/pageLoader/PageLoader.svelte +14 -14
- package/dist/ui/pageLoader/PageLoader2.svelte +99 -0
- package/dist/ui/pageLoader/PageLoader2.svelte.d.ts +24 -0
- package/dist/ui/pageLoader/index.d.ts +2 -1
- package/dist/ui/pageLoader/index.js +2 -1
- package/dist/ui/paginate/Paginate.svelte +96 -96
- package/dist/ui/speedDial/SpeedDial.svelte +77 -77
- package/dist/ui/speedDial/SpeedDialButton.svelte +75 -75
- package/dist/ui/speedDial/SpeedDialTrigger.svelte +79 -79
- package/dist/ui/tab/Tab.svelte +93 -67
- package/dist/ui/table/Table.svelte +396 -396
- package/dist/ui/tableLoader/TableLoader.svelte +24 -24
- package/dist/ui/toast/Toast.svelte +337 -337
- package/dist/ui/toast/Toast.svelte.d.ts +10 -10
- package/dist/ui/toolbar/Toolbar.svelte +59 -59
- package/dist/ui/toolbar/ToolbarButton.svelte +56 -56
- package/dist/ui/toolbar/ToolbarGroup.svelte +43 -43
- package/dist/ui/tooltip/Tooltip.svelte +51 -51
- package/dist/utils/Popper.svelte +257 -257
- package/dist/utils/closeButton/CloseButton.svelte +88 -88
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +3 -3
- package/dist/utils/singleSelection.svelte.js +48 -48
- package/dist/youtube/index.svelte +12 -12
- package/package.json +1 -1
|
@@ -1,134 +1,134 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import { registerPlugin, supported } from 'svelte-filepond';
|
|
3
|
-
import FilePondPluginImageExifOrientation from 'filepond-plugin-image-exif-orientation';
|
|
4
|
-
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
|
|
5
|
-
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
|
|
6
|
-
registerPlugin(
|
|
7
|
-
FilePondPluginImageExifOrientation,
|
|
8
|
-
FilePondPluginImagePreview,
|
|
9
|
-
FilePondPluginFileValidateType
|
|
10
|
-
);
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<script lang="ts">
|
|
14
|
-
import { key, Label } from '../../index.js';
|
|
15
|
-
import type { FormFileUploadProps } from '../../types/index.js';
|
|
16
|
-
import { nanoid } from 'nanoid';
|
|
17
|
-
import { getContext } from 'svelte';
|
|
18
|
-
import FilePond from 'svelte-filepond';
|
|
19
|
-
|
|
20
|
-
let {
|
|
21
|
-
title = 'Click Browse or drop the file to upload',
|
|
22
|
-
subTitle = '',
|
|
23
|
-
url = '',
|
|
24
|
-
name = 'file',
|
|
25
|
-
allowMultiple = false,
|
|
26
|
-
acceptedFileTypes = [
|
|
27
|
-
'image/png',
|
|
28
|
-
'image/jpeg',
|
|
29
|
-
'application/pdf',
|
|
30
|
-
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
31
|
-
],
|
|
32
|
-
files = [],
|
|
33
|
-
label = '',
|
|
34
|
-
required = false,
|
|
35
|
-
showError = false,
|
|
36
|
-
imageOnly = false,
|
|
37
|
-
contextKey = null,
|
|
38
|
-
onChange
|
|
39
|
-
}: FormFileUploadProps = $props();
|
|
40
|
-
|
|
41
|
-
// State
|
|
42
|
-
let pond = $state<any>();
|
|
43
|
-
|
|
44
|
-
// Context
|
|
45
|
-
const { touched, errors, data, setData }: any = getContext(contextKey || key);
|
|
46
|
-
|
|
47
|
-
// Derived state
|
|
48
|
-
let id = nanoid();
|
|
49
|
-
let hasError = $derived($touched[name] && $errors[name]?.length);
|
|
50
|
-
let error = $derived($errors[name]?.join(', '));
|
|
51
|
-
|
|
52
|
-
// Constants
|
|
53
|
-
const uploadServerConfig = {};
|
|
54
|
-
|
|
55
|
-
// Effects
|
|
56
|
-
$effect(() => {
|
|
57
|
-
if (imageOnly && acceptedFileTypes?.length === 3) {
|
|
58
|
-
acceptedFileTypes = ['image/png', 'image/jpeg'];
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
function checkFiles(files: any) {
|
|
63
|
-
if (files.length > 1) {
|
|
64
|
-
const newFiles = files.map((x: any) => x.file);
|
|
65
|
-
setData({ ...$data, [name]: newFiles });
|
|
66
|
-
onChange?.({ name, value: newFiles });
|
|
67
|
-
} else if (files.length === 1) {
|
|
68
|
-
const { file } = files[0];
|
|
69
|
-
setData({ ...$data, [name]: file });
|
|
70
|
-
onChange?.({ name, value: file });
|
|
71
|
-
} else if (files.length == 0) {
|
|
72
|
-
onChange?.(null);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function customFileTypeDetection(source: File, type: string) {
|
|
77
|
-
return new Promise((resolve, reject) => {
|
|
78
|
-
const fileName = source.name;
|
|
79
|
-
if (fileName.endsWith('.frx')) {
|
|
80
|
-
resolve('.frx');
|
|
81
|
-
} else {
|
|
82
|
-
resolve(type);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
</script>
|
|
87
|
-
|
|
88
|
-
<div class="relative my-2 flex flex-grow flex-col">
|
|
89
|
-
<Label
|
|
90
|
-
>{label}
|
|
91
|
-
{#if required}
|
|
92
|
-
<span class="pl-1 text-red-500">*</span>
|
|
93
|
-
{/if}
|
|
94
|
-
</Label>
|
|
95
|
-
|
|
96
|
-
<FilePond
|
|
97
|
-
{name}
|
|
98
|
-
required={true}
|
|
99
|
-
allowReplace={true}
|
|
100
|
-
instantUpload={false}
|
|
101
|
-
server={uploadServerConfig}
|
|
102
|
-
{allowMultiple}
|
|
103
|
-
allowRevert={true}
|
|
104
|
-
allowImagePreview={true}
|
|
105
|
-
allowImageResize={true}
|
|
106
|
-
bind:this={pond}
|
|
107
|
-
onupdatefiles={checkFiles}
|
|
108
|
-
{files}
|
|
109
|
-
{acceptedFileTypes}
|
|
110
|
-
fileValidateTypeDetectType={customFileTypeDetection}
|
|
111
|
-
credits={false}
|
|
112
|
-
/>
|
|
113
|
-
|
|
114
|
-
{#if hasError}
|
|
115
|
-
<Label
|
|
116
|
-
class="v-error-container absolute top-9 right-2 flex items-center gap-1 text-sm {hasError &&
|
|
117
|
-
'text-red-600'}"
|
|
118
|
-
>
|
|
119
|
-
<span class="v-error-message hidden backdrop-blur-sm">
|
|
120
|
-
{error}
|
|
121
|
-
</span>
|
|
122
|
-
<iconify-icon
|
|
123
|
-
icon="solar:danger-circle-bold-duotone"
|
|
124
|
-
class="v-error-svg ml-auto cursor-pointer text-red-500 select-none hover:text-red-600"
|
|
125
|
-
style="font-size: 18px;"
|
|
126
|
-
></iconify-icon>
|
|
127
|
-
</Label>
|
|
128
|
-
{/if}
|
|
129
|
-
</div>
|
|
130
|
-
|
|
131
|
-
<style>
|
|
132
|
-
@import 'filepond/dist/filepond.css';
|
|
133
|
-
@import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css';
|
|
134
|
-
</style>
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import { registerPlugin, supported } from 'svelte-filepond';
|
|
3
|
+
import FilePondPluginImageExifOrientation from 'filepond-plugin-image-exif-orientation';
|
|
4
|
+
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
|
|
5
|
+
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
|
|
6
|
+
registerPlugin(
|
|
7
|
+
FilePondPluginImageExifOrientation,
|
|
8
|
+
FilePondPluginImagePreview,
|
|
9
|
+
FilePondPluginFileValidateType
|
|
10
|
+
);
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
import { key, Label } from '../../index.js';
|
|
15
|
+
import type { FormFileUploadProps } from '../../types/index.js';
|
|
16
|
+
import { nanoid } from 'nanoid';
|
|
17
|
+
import { getContext } from 'svelte';
|
|
18
|
+
import FilePond from 'svelte-filepond';
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
title = 'Click Browse or drop the file to upload',
|
|
22
|
+
subTitle = '',
|
|
23
|
+
url = '',
|
|
24
|
+
name = 'file',
|
|
25
|
+
allowMultiple = false,
|
|
26
|
+
acceptedFileTypes = [
|
|
27
|
+
'image/png',
|
|
28
|
+
'image/jpeg',
|
|
29
|
+
'application/pdf',
|
|
30
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
31
|
+
],
|
|
32
|
+
files = [],
|
|
33
|
+
label = '',
|
|
34
|
+
required = false,
|
|
35
|
+
showError = false,
|
|
36
|
+
imageOnly = false,
|
|
37
|
+
contextKey = null,
|
|
38
|
+
onChange
|
|
39
|
+
}: FormFileUploadProps = $props();
|
|
40
|
+
|
|
41
|
+
// State
|
|
42
|
+
let pond = $state<any>();
|
|
43
|
+
|
|
44
|
+
// Context
|
|
45
|
+
const { touched, errors, data, setData }: any = getContext(contextKey || key);
|
|
46
|
+
|
|
47
|
+
// Derived state
|
|
48
|
+
let id = nanoid();
|
|
49
|
+
let hasError = $derived($touched[name] && $errors[name]?.length);
|
|
50
|
+
let error = $derived($errors[name]?.join(', '));
|
|
51
|
+
|
|
52
|
+
// Constants
|
|
53
|
+
const uploadServerConfig = {};
|
|
54
|
+
|
|
55
|
+
// Effects
|
|
56
|
+
$effect(() => {
|
|
57
|
+
if (imageOnly && acceptedFileTypes?.length === 3) {
|
|
58
|
+
acceptedFileTypes = ['image/png', 'image/jpeg'];
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
function checkFiles(files: any) {
|
|
63
|
+
if (files.length > 1) {
|
|
64
|
+
const newFiles = files.map((x: any) => x.file);
|
|
65
|
+
setData({ ...$data, [name]: newFiles });
|
|
66
|
+
onChange?.({ name, value: newFiles });
|
|
67
|
+
} else if (files.length === 1) {
|
|
68
|
+
const { file } = files[0];
|
|
69
|
+
setData({ ...$data, [name]: file });
|
|
70
|
+
onChange?.({ name, value: file });
|
|
71
|
+
} else if (files.length == 0) {
|
|
72
|
+
onChange?.(null);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function customFileTypeDetection(source: File, type: string) {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
const fileName = source.name;
|
|
79
|
+
if (fileName.endsWith('.frx')) {
|
|
80
|
+
resolve('.frx');
|
|
81
|
+
} else {
|
|
82
|
+
resolve(type);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<div class="relative my-2 flex flex-grow flex-col">
|
|
89
|
+
<Label
|
|
90
|
+
>{label}
|
|
91
|
+
{#if required}
|
|
92
|
+
<span class="pl-1 text-red-500">*</span>
|
|
93
|
+
{/if}
|
|
94
|
+
</Label>
|
|
95
|
+
|
|
96
|
+
<FilePond
|
|
97
|
+
{name}
|
|
98
|
+
required={true}
|
|
99
|
+
allowReplace={true}
|
|
100
|
+
instantUpload={false}
|
|
101
|
+
server={uploadServerConfig}
|
|
102
|
+
{allowMultiple}
|
|
103
|
+
allowRevert={true}
|
|
104
|
+
allowImagePreview={true}
|
|
105
|
+
allowImageResize={true}
|
|
106
|
+
bind:this={pond}
|
|
107
|
+
onupdatefiles={checkFiles}
|
|
108
|
+
{files}
|
|
109
|
+
{acceptedFileTypes}
|
|
110
|
+
fileValidateTypeDetectType={customFileTypeDetection}
|
|
111
|
+
credits={false}
|
|
112
|
+
/>
|
|
113
|
+
|
|
114
|
+
{#if hasError}
|
|
115
|
+
<Label
|
|
116
|
+
class="v-error-container absolute top-9 right-2 flex items-center gap-1 text-sm {hasError &&
|
|
117
|
+
'text-red-600'}"
|
|
118
|
+
>
|
|
119
|
+
<span class="v-error-message hidden backdrop-blur-sm">
|
|
120
|
+
{error}
|
|
121
|
+
</span>
|
|
122
|
+
<iconify-icon
|
|
123
|
+
icon="solar:danger-circle-bold-duotone"
|
|
124
|
+
class="v-error-svg ml-auto cursor-pointer text-red-500 select-none hover:text-red-600"
|
|
125
|
+
style="font-size: 18px;"
|
|
126
|
+
></iconify-icon>
|
|
127
|
+
</Label>
|
|
128
|
+
{/if}
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
<style>
|
|
132
|
+
@import 'filepond/dist/filepond.css';
|
|
133
|
+
@import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css';
|
|
134
|
+
</style>
|
|
@@ -1,87 +1,87 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
function formatInput(value: string, type: string | null, pattern: string | null) {
|
|
3
|
-
if (!value) return '';
|
|
4
|
-
if (!type) return value;
|
|
5
|
-
switch (type) {
|
|
6
|
-
case 'number':
|
|
7
|
-
const v = +value;
|
|
8
|
-
if (isNaN(v)) return '';
|
|
9
|
-
return v.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
10
|
-
default:
|
|
11
|
-
return value;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function getNestedValue<T extends Record<string, any>>(obj: T, path: string): any {
|
|
16
|
-
return path
|
|
17
|
-
.split('.')
|
|
18
|
-
.reduce((acc, key) => (acc && acc[key] !== undefined ? acc[key] : null), obj);
|
|
19
|
-
}
|
|
20
|
-
</script>
|
|
21
|
-
|
|
22
|
-
<script lang="ts">
|
|
23
|
-
import { key, type FormInputProps } from '../../index.js';
|
|
24
|
-
import { getContext } from 'svelte';
|
|
25
|
-
import Input from '../input/Input.svelte';
|
|
26
|
-
import { nanoid } from 'nanoid';
|
|
27
|
-
import Label from '../label/Label.svelte';
|
|
28
|
-
|
|
29
|
-
let {
|
|
30
|
-
name = '',
|
|
31
|
-
label = '',
|
|
32
|
-
required,
|
|
33
|
-
readonly,
|
|
34
|
-
contextKey = null,
|
|
35
|
-
type = 'text',
|
|
36
|
-
pattern = null,
|
|
37
|
-
placeholder,
|
|
38
|
-
...otherProps
|
|
39
|
-
}: FormInputProps = $props();
|
|
40
|
-
const { touched, errors, data, setData }: any = getContext(contextKey || key);
|
|
41
|
-
|
|
42
|
-
const hasError = $derived($touched[name] && $errors[name]?.length);
|
|
43
|
-
const error = $derived($errors[name]?.join(', '));
|
|
44
|
-
const isSuccess = $derived(!readonly && !hasError && $touched[name]);
|
|
45
|
-
let id = nanoid();
|
|
46
|
-
</script>
|
|
47
|
-
|
|
48
|
-
<div class="relative space-y-1">
|
|
49
|
-
<Label
|
|
50
|
-
>{label}
|
|
51
|
-
{#if required}
|
|
52
|
-
<span class="pl-1 text-red-500">*</span>
|
|
53
|
-
{/if}
|
|
54
|
-
</Label>
|
|
55
|
-
{#if readonly}
|
|
56
|
-
<div class="min-h-[42px] rounded-md border border-gray-300 bg-gray-100 p-2">
|
|
57
|
-
<span>{formatInput(getNestedValue($data, name) || '', type, pattern)}</span>
|
|
58
|
-
</div>
|
|
59
|
-
{:else}
|
|
60
|
-
<Input
|
|
61
|
-
{name}
|
|
62
|
-
{type}
|
|
63
|
-
{id}
|
|
64
|
-
{placeholder}
|
|
65
|
-
{readonly}
|
|
66
|
-
color={readonly ? 'gray' : hasError ? 'red' : isSuccess ? 'green' : 'default'}
|
|
67
|
-
value={getNestedValue($data, name) || ''}
|
|
68
|
-
{...otherProps}
|
|
69
|
-
/>
|
|
70
|
-
{/if}
|
|
71
|
-
|
|
72
|
-
{#if hasError}
|
|
73
|
-
<Label
|
|
74
|
-
class="v-error-container absolute top-9 right-2 flex items-center gap-1 text-sm {hasError &&
|
|
75
|
-
'text-red-600'}"
|
|
76
|
-
>
|
|
77
|
-
<span class="v-error-message hidden backdrop-blur-sm">
|
|
78
|
-
{error}
|
|
79
|
-
</span>
|
|
80
|
-
<iconify-icon
|
|
81
|
-
icon="solar:danger-circle-bold-duotone"
|
|
82
|
-
class="v-error-svg ml-auto cursor-pointer text-red-500 select-none hover:text-red-600"
|
|
83
|
-
style="font-size: 18px;"
|
|
84
|
-
></iconify-icon>
|
|
85
|
-
</Label>
|
|
86
|
-
{/if}
|
|
87
|
-
</div>
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
function formatInput(value: string, type: string | null, pattern: string | null) {
|
|
3
|
+
if (!value) return '';
|
|
4
|
+
if (!type) return value;
|
|
5
|
+
switch (type) {
|
|
6
|
+
case 'number':
|
|
7
|
+
const v = +value;
|
|
8
|
+
if (isNaN(v)) return '';
|
|
9
|
+
return v.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
10
|
+
default:
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function getNestedValue<T extends Record<string, any>>(obj: T, path: string): any {
|
|
16
|
+
return path
|
|
17
|
+
.split('.')
|
|
18
|
+
.reduce((acc, key) => (acc && acc[key] !== undefined ? acc[key] : null), obj);
|
|
19
|
+
}
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<script lang="ts">
|
|
23
|
+
import { key, type FormInputProps } from '../../index.js';
|
|
24
|
+
import { getContext } from 'svelte';
|
|
25
|
+
import Input from '../input/Input.svelte';
|
|
26
|
+
import { nanoid } from 'nanoid';
|
|
27
|
+
import Label from '../label/Label.svelte';
|
|
28
|
+
|
|
29
|
+
let {
|
|
30
|
+
name = '',
|
|
31
|
+
label = '',
|
|
32
|
+
required,
|
|
33
|
+
readonly,
|
|
34
|
+
contextKey = null,
|
|
35
|
+
type = 'text',
|
|
36
|
+
pattern = null,
|
|
37
|
+
placeholder,
|
|
38
|
+
...otherProps
|
|
39
|
+
}: FormInputProps = $props();
|
|
40
|
+
const { touched, errors, data, setData }: any = getContext(contextKey || key);
|
|
41
|
+
|
|
42
|
+
const hasError = $derived($touched[name] && $errors[name]?.length);
|
|
43
|
+
const error = $derived($errors[name]?.join(', '));
|
|
44
|
+
const isSuccess = $derived(!readonly && !hasError && $touched[name]);
|
|
45
|
+
let id = nanoid();
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<div class="relative space-y-1">
|
|
49
|
+
<Label
|
|
50
|
+
>{label}
|
|
51
|
+
{#if required}
|
|
52
|
+
<span class="pl-1 text-red-500">*</span>
|
|
53
|
+
{/if}
|
|
54
|
+
</Label>
|
|
55
|
+
{#if readonly}
|
|
56
|
+
<div class="min-h-[42px] rounded-md border border-gray-300 bg-gray-100 p-2">
|
|
57
|
+
<span>{formatInput(getNestedValue($data, name) || '', type, pattern)}</span>
|
|
58
|
+
</div>
|
|
59
|
+
{:else}
|
|
60
|
+
<Input
|
|
61
|
+
{name}
|
|
62
|
+
{type}
|
|
63
|
+
{id}
|
|
64
|
+
{placeholder}
|
|
65
|
+
{readonly}
|
|
66
|
+
color={readonly ? 'gray' : hasError ? 'red' : isSuccess ? 'green' : 'default'}
|
|
67
|
+
value={getNestedValue($data, name) || ''}
|
|
68
|
+
{...otherProps}
|
|
69
|
+
/>
|
|
70
|
+
{/if}
|
|
71
|
+
|
|
72
|
+
{#if hasError}
|
|
73
|
+
<Label
|
|
74
|
+
class="v-error-container absolute top-9 right-2 flex items-center gap-1 text-sm {hasError &&
|
|
75
|
+
'text-red-600'}"
|
|
76
|
+
>
|
|
77
|
+
<span class="v-error-message hidden backdrop-blur-sm">
|
|
78
|
+
{error}
|
|
79
|
+
</span>
|
|
80
|
+
<iconify-icon
|
|
81
|
+
icon="solar:danger-circle-bold-duotone"
|
|
82
|
+
class="v-error-svg ml-auto cursor-pointer text-red-500 select-none hover:text-red-600"
|
|
83
|
+
style="font-size: 18px;"
|
|
84
|
+
></iconify-icon>
|
|
85
|
+
</Label>
|
|
86
|
+
{/if}
|
|
87
|
+
</div>
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { Checkbox, key, Label } from '../../index.js';
|
|
3
|
-
import type { FormCheckboxProps, FormRadioProps, FormSelectProps } from '../../types/index.js';
|
|
4
|
-
import { getContext } from 'svelte';
|
|
5
|
-
import Radio from '../radio/Radio.svelte';
|
|
6
|
-
|
|
7
|
-
let {
|
|
8
|
-
label = '',
|
|
9
|
-
required,
|
|
10
|
-
name,
|
|
11
|
-
disabled,
|
|
12
|
-
contextKey = null,
|
|
13
|
-
placeholder,
|
|
14
|
-
multiple = false,
|
|
15
|
-
onchange,
|
|
16
|
-
...otherProps
|
|
17
|
-
}: FormRadioProps<any> = $props();
|
|
18
|
-
const { touched, errors, data, setData }: any = getContext(contextKey || key);
|
|
19
|
-
|
|
20
|
-
const hasError = $derived($touched[name] && $errors[name]?.length);
|
|
21
|
-
const error = $derived($errors[name]?.join(', '));
|
|
22
|
-
const value = $derived($data[name]);
|
|
23
|
-
|
|
24
|
-
function handleChange(e: Event) {
|
|
25
|
-
const value = (e.target as HTMLInputElement).value;
|
|
26
|
-
setData({ ...$data, [name]: value });
|
|
27
|
-
if (onchange) onchange(e as any);
|
|
28
|
-
}
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
<div class="relative space-y-1">
|
|
32
|
-
<Radio {disabled} onchange={handleChange} {...otherProps} group={value}
|
|
33
|
-
>{label}
|
|
34
|
-
{#if required}
|
|
35
|
-
<span class="pt-1 pl-1 text-red-500">*</span>
|
|
36
|
-
{/if}
|
|
37
|
-
{#if hasError}
|
|
38
|
-
<Label
|
|
39
|
-
class="v-error-container absolute top-0 right-2 flex items-center gap-1 text-sm {hasError &&
|
|
40
|
-
'text-red-600'}"
|
|
41
|
-
>
|
|
42
|
-
<span class="v-error-message hidden backdrop-blur-sm">
|
|
43
|
-
{error}
|
|
44
|
-
</span>
|
|
45
|
-
<iconify-icon
|
|
46
|
-
icon="solar:danger-circle-bold-duotone"
|
|
47
|
-
class="v-error-svg ml-auto cursor-pointer text-red-500 select-none hover:text-red-600"
|
|
48
|
-
style="font-size: 18px;"
|
|
49
|
-
></iconify-icon>
|
|
50
|
-
</Label>
|
|
51
|
-
{/if}
|
|
52
|
-
</Radio>
|
|
53
|
-
</div>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { Checkbox, key, Label } from '../../index.js';
|
|
3
|
+
import type { FormCheckboxProps, FormRadioProps, FormSelectProps } from '../../types/index.js';
|
|
4
|
+
import { getContext } from 'svelte';
|
|
5
|
+
import Radio from '../radio/Radio.svelte';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
label = '',
|
|
9
|
+
required,
|
|
10
|
+
name,
|
|
11
|
+
disabled,
|
|
12
|
+
contextKey = null,
|
|
13
|
+
placeholder,
|
|
14
|
+
multiple = false,
|
|
15
|
+
onchange,
|
|
16
|
+
...otherProps
|
|
17
|
+
}: FormRadioProps<any> = $props();
|
|
18
|
+
const { touched, errors, data, setData }: any = getContext(contextKey || key);
|
|
19
|
+
|
|
20
|
+
const hasError = $derived($touched[name] && $errors[name]?.length);
|
|
21
|
+
const error = $derived($errors[name]?.join(', '));
|
|
22
|
+
const value = $derived($data[name]);
|
|
23
|
+
|
|
24
|
+
function handleChange(e: Event) {
|
|
25
|
+
const value = (e.target as HTMLInputElement).value;
|
|
26
|
+
setData({ ...$data, [name]: value });
|
|
27
|
+
if (onchange) onchange(e as any);
|
|
28
|
+
}
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<div class="relative space-y-1">
|
|
32
|
+
<Radio {disabled} onchange={handleChange} {...otherProps} group={value}
|
|
33
|
+
>{label}
|
|
34
|
+
{#if required}
|
|
35
|
+
<span class="pt-1 pl-1 text-red-500">*</span>
|
|
36
|
+
{/if}
|
|
37
|
+
{#if hasError}
|
|
38
|
+
<Label
|
|
39
|
+
class="v-error-container absolute top-0 right-2 flex items-center gap-1 text-sm {hasError &&
|
|
40
|
+
'text-red-600'}"
|
|
41
|
+
>
|
|
42
|
+
<span class="v-error-message hidden backdrop-blur-sm">
|
|
43
|
+
{error}
|
|
44
|
+
</span>
|
|
45
|
+
<iconify-icon
|
|
46
|
+
icon="solar:danger-circle-bold-duotone"
|
|
47
|
+
class="v-error-svg ml-auto cursor-pointer text-red-500 select-none hover:text-red-600"
|
|
48
|
+
style="font-size: 18px;"
|
|
49
|
+
></iconify-icon>
|
|
50
|
+
</Label>
|
|
51
|
+
{/if}
|
|
52
|
+
</Radio>
|
|
53
|
+
</div>
|