@naptics/vue-collection 0.0.1

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.
Files changed (105) hide show
  1. package/README.md +27 -0
  2. package/lib/components/NAlert.d.ts +72 -0
  3. package/lib/components/NAlert.jsx +69 -0
  4. package/lib/components/NBadge.d.ts +174 -0
  5. package/lib/components/NBadge.jsx +58 -0
  6. package/lib/components/NBreadcrub.d.ts +161 -0
  7. package/lib/components/NBreadcrub.jsx +64 -0
  8. package/lib/components/NButton.d.ts +149 -0
  9. package/lib/components/NButton.jsx +58 -0
  10. package/lib/components/NCheckbox.d.ts +51 -0
  11. package/lib/components/NCheckbox.jsx +38 -0
  12. package/lib/components/NCheckboxLabel.d.ts +70 -0
  13. package/lib/components/NCheckboxLabel.jsx +42 -0
  14. package/lib/components/NCrudModal.d.ts +301 -0
  15. package/lib/components/NCrudModal.jsx +89 -0
  16. package/lib/components/NDialog.d.ts +190 -0
  17. package/lib/components/NDialog.jsx +144 -0
  18. package/lib/components/NDropdown.d.ts +116 -0
  19. package/lib/components/NDropdown.jsx +92 -0
  20. package/lib/components/NDropzone.d.ts +162 -0
  21. package/lib/components/NDropzone.jsx +211 -0
  22. package/lib/components/NForm.d.ts +43 -0
  23. package/lib/components/NForm.jsx +26 -0
  24. package/lib/components/NFormModal.d.ts +190 -0
  25. package/lib/components/NFormModal.jsx +48 -0
  26. package/lib/components/NIconButton.d.ts +202 -0
  27. package/lib/components/NIconButton.jsx +71 -0
  28. package/lib/components/NIconCircle.d.ts +135 -0
  29. package/lib/components/NIconCircle.jsx +67 -0
  30. package/lib/components/NInput.css +11 -0
  31. package/lib/components/NInput.d.ts +232 -0
  32. package/lib/components/NInput.jsx +97 -0
  33. package/lib/components/NInputPhone.d.ts +150 -0
  34. package/lib/components/NInputPhone.jsx +31 -0
  35. package/lib/components/NInputSelect.d.ts +271 -0
  36. package/lib/components/NInputSelect.jsx +89 -0
  37. package/lib/components/NInputSuggestion.d.ts +212 -0
  38. package/lib/components/NInputSuggestion.jsx +48 -0
  39. package/lib/components/NLink.d.ts +111 -0
  40. package/lib/components/NLink.jsx +58 -0
  41. package/lib/components/NList.d.ts +43 -0
  42. package/lib/components/NList.jsx +24 -0
  43. package/lib/components/NLoadingIndicator.css +46 -0
  44. package/lib/components/NLoadingIndicator.d.ts +77 -0
  45. package/lib/components/NLoadingIndicator.jsx +42 -0
  46. package/lib/components/NModal.d.ts +333 -0
  47. package/lib/components/NModal.jsx +170 -0
  48. package/lib/components/NPagination.css +15 -0
  49. package/lib/components/NPagination.d.ts +99 -0
  50. package/lib/components/NPagination.jsx +104 -0
  51. package/lib/components/NSearchbar.d.ts +94 -0
  52. package/lib/components/NSearchbar.jsx +58 -0
  53. package/lib/components/NSearchbarList.d.ts +90 -0
  54. package/lib/components/NSearchbarList.jsx +20 -0
  55. package/lib/components/NSelect.d.ts +159 -0
  56. package/lib/components/NSelect.jsx +81 -0
  57. package/lib/components/NSuggestionList.d.ts +275 -0
  58. package/lib/components/NSuggestionList.jsx +157 -0
  59. package/lib/components/NTable.css +3 -0
  60. package/lib/components/NTable.d.ts +187 -0
  61. package/lib/components/NTable.jsx +146 -0
  62. package/lib/components/NTableAction.d.ts +74 -0
  63. package/lib/components/NTableAction.jsx +35 -0
  64. package/lib/components/NTextArea.d.ts +252 -0
  65. package/lib/components/NTextArea.jsx +108 -0
  66. package/lib/components/NTooltip.css +37 -0
  67. package/lib/components/NTooltip.d.ts +186 -0
  68. package/lib/components/NTooltip.jsx +161 -0
  69. package/lib/components/NValInput.d.ts +297 -0
  70. package/lib/components/NValInput.jsx +101 -0
  71. package/lib/components/ValidatedForm.d.ts +34 -0
  72. package/lib/components/ValidatedForm.js +25 -0
  73. package/lib/i18n/de/template.json +10 -0
  74. package/lib/i18n/de/vue-collection.json +58 -0
  75. package/lib/i18n/de.d.ts +61 -0
  76. package/lib/i18n/de.js +5 -0
  77. package/lib/i18n/en/template.json +10 -0
  78. package/lib/i18n/en/vue-collection.json +58 -0
  79. package/lib/i18n/en.d.ts +61 -0
  80. package/lib/i18n/en.js +5 -0
  81. package/lib/i18n/index.d.ts +17 -0
  82. package/lib/i18n/index.js +34 -0
  83. package/lib/index.d.ts +64 -0
  84. package/lib/index.js +65 -0
  85. package/lib/utils/breakpoints.d.ts +15 -0
  86. package/lib/utils/breakpoints.js +37 -0
  87. package/lib/utils/component.d.ts +50 -0
  88. package/lib/utils/component.js +51 -0
  89. package/lib/utils/deferred.d.ts +13 -0
  90. package/lib/utils/deferred.js +17 -0
  91. package/lib/utils/identifiable.d.ts +57 -0
  92. package/lib/utils/identifiable.js +78 -0
  93. package/lib/utils/stringMaxLength.d.ts +14 -0
  94. package/lib/utils/stringMaxLength.js +28 -0
  95. package/lib/utils/tailwind.d.ts +2 -0
  96. package/lib/utils/tailwind.js +1 -0
  97. package/lib/utils/utils.d.ts +27 -0
  98. package/lib/utils/utils.js +26 -0
  99. package/lib/utils/vModel.d.ts +182 -0
  100. package/lib/utils/vModel.js +215 -0
  101. package/lib/utils/validation.d.ts +84 -0
  102. package/lib/utils/validation.js +163 -0
  103. package/lib/utils/vue.d.ts +13 -0
  104. package/lib/utils/vue.js +19 -0
  105. package/package.json +56 -0
@@ -0,0 +1,211 @@
1
+ import { trslc } from '../i18n';
2
+ import { createComponent, createProps } from '../utils/component';
3
+ import { maxLengthSplitCenter } from '../utils/stringMaxLength';
4
+ import { notNullish } from '../utils/utils';
5
+ import { XMarkIcon } from '@heroicons/vue/24/solid';
6
+ import { computed, ref } from 'vue';
7
+ import NBadge from './NBadge';
8
+ import NIconButton from './NIconButton';
9
+ import NLink from './NLink';
10
+ import { vModelProps } from '../utils/vModel';
11
+ export const nDropzoneProps = createProps({
12
+ ...vModelProps(Array),
13
+ /**
14
+ * A description which files are allowed for this dropzone.
15
+ * This should include everything the user needs to know about
16
+ * the file type / the extensions and the maximum size of the file.
17
+ * @see {@link nDropzoneProps.accept}
18
+ * @see {@link nDropzoneProps.maxFileSize}
19
+ */
20
+ description: String,
21
+ /**
22
+ * The maximum amount of files which can be added to the dropzone.
23
+ */
24
+ maxFiles: {
25
+ type: Number,
26
+ default: 1,
27
+ },
28
+ /**
29
+ * Specifies which file types are accepted. The same syntax as with inputs of type file is used.
30
+ * Make sure to explain the requirements to the user in the {@link nDropzoneProps.description}.
31
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers
32
+ */
33
+ accept: String,
34
+ /**
35
+ * Specifies the maximum size of an individual file in bytes.
36
+ * Make sure to explain the max size to the user in the {@link nDropzoneProps.description}.
37
+ */
38
+ maxFileSize: {
39
+ type: Number,
40
+ default: 100 * 1024 * 1024,
41
+ },
42
+ /**
43
+ * The maximum length of the file names.
44
+ * Files names longer than the specified amount of characters will be shortened.
45
+ * @see {@link maxLengthSplitCenter}
46
+ */
47
+ maxLengthFileNames: {
48
+ type: Number,
49
+ default: 35,
50
+ },
51
+ /**
52
+ * A tailwind height class, which is applied to the dropzone area.
53
+ * It is recommended to use `min-h-*` classes,
54
+ * so the box is always large enough to display it's text.
55
+ */
56
+ height: {
57
+ type: String,
58
+ default: 'min-h-36',
59
+ },
60
+ });
61
+ /**
62
+ * The `NDropzone` is an area where files can be added by the user by drag & drop.
63
+ * Files can also be selected with a file chooser by clicking on the dropzone.
64
+ */
65
+ export default createComponent('NDropzone', nDropzoneProps, props => {
66
+ const fileError = ref();
67
+ const filterAndUpdateFiles = (files) => {
68
+ // filter for mime type and max size
69
+ const fileTypeFilteredFiles = files.filter(file => !props.accept || testFileWithAcceptString(props.accept, file));
70
+ const filteredFiles = fileTypeFilteredFiles.filter(file => file.size <= props.maxFileSize);
71
+ // filter for already existing files
72
+ const currentFiles = props.value || [];
73
+ filteredFiles.forEach(file => {
74
+ if (currentFiles.filter(currFile => currFile.name == file.name).length == 0)
75
+ currentFiles.push(file);
76
+ });
77
+ // slice down to max amount of files
78
+ const newFiles = currentFiles.slice(0, props.maxFiles);
79
+ // error handling
80
+ const fileTypeFilterDiff = files.length - fileTypeFilteredFiles.length;
81
+ const fileSizeFilterDiff = fileTypeFilteredFiles.length - filteredFiles.length;
82
+ if (newFiles.length < currentFiles.length)
83
+ fileError.value = trslc('vue-collection.error.too-many-files', props.maxFiles, { max: props.maxFiles });
84
+ else if (fileSizeFilterDiff > 0) {
85
+ fileError.value = trslc('vue-collection.error.file-size', fileSizeFilterDiff, { n: fileSizeFilterDiff });
86
+ }
87
+ else if (fileTypeFilterDiff > 0)
88
+ fileError.value = trslc('vue-collection.error.file-type', fileTypeFilterDiff, { n: fileTypeFilterDiff });
89
+ else
90
+ fileError.value = undefined;
91
+ // update new value
92
+ props.onUpdateValue?.(newFiles);
93
+ };
94
+ const files = computed(() => props.value?.map((file, index) => ({
95
+ index,
96
+ name: maxLengthSplitCenter(file.name, props.maxLengthFileNames),
97
+ })) || []);
98
+ const removeFile = (index) => {
99
+ const newFiles = [...(props.value || [])];
100
+ newFiles.splice(index, 1);
101
+ fileError.value = undefined;
102
+ props.onUpdateValue?.(newFiles);
103
+ };
104
+ const clearFiles = () => {
105
+ fileError.value = undefined;
106
+ props.onUpdateValue?.([]);
107
+ };
108
+ const isDragOver = ref(false);
109
+ const onDrop = (event) => {
110
+ event.preventDefault();
111
+ isDragOver.value = false;
112
+ const transfer = event.dataTransfer;
113
+ if (transfer == null)
114
+ return;
115
+ if (transfer.items.length > 0) {
116
+ const items = [...transfer.items];
117
+ const files = items.map(item => (item.kind === 'file' ? item.getAsFile() : null)).filter(notNullish);
118
+ filterAndUpdateFiles(files);
119
+ }
120
+ else {
121
+ filterAndUpdateFiles([...transfer.files]);
122
+ }
123
+ };
124
+ const onDragOver = (event) => {
125
+ event.preventDefault();
126
+ isDragOver.value = true;
127
+ };
128
+ const onDragLeave = () => {
129
+ isDragOver.value = false;
130
+ };
131
+ const onClick = () => {
132
+ fileInput.value?.click();
133
+ };
134
+ const fileInput = ref();
135
+ const onInputFilesChanged = () => {
136
+ const input = fileInput.value;
137
+ if (input != null) {
138
+ if (input.files != null)
139
+ filterAndUpdateFiles([...input.files]);
140
+ input.value = '';
141
+ }
142
+ };
143
+ return () => (<div>
144
+ <button class={[
145
+ 'block w-full rounded-md border-dashed border-2 hover:border-primary-300 hover:bg-primary-50 focus-visible:border-primary-500 focus:outline-none ',
146
+ 'flex flex-col items-center justify-center text-center text-sm select-none hover:text-primary-700 p-4',
147
+ isDragOver.value
148
+ ? 'border-primary-300 bg-primary-50 text-primary-700'
149
+ : 'border-default-300 bg-default-50 text-default-500',
150
+ props.height,
151
+ ]} onDrop={onDrop} onDragover={onDragOver} onDragleave={onDragLeave} onClick={onClick}>
152
+ <input type="file" class="hidden" ref={fileInput} multiple={props.maxFiles > 1} accept={props.accept} onChange={onInputFilesChanged} onClick={event => event.stopPropagation()}/>
153
+
154
+ {/* Counterweight */}
155
+ <div class="flex-grow mb-2"/>
156
+
157
+ <span class="font-medium">
158
+ {trslc('vue-collection.text.drag-n-drop-files', props.maxFiles, { n: props.maxFiles })}
159
+ </span>
160
+ <span>{props.description}</span>
161
+
162
+ <div class="flex-grow mt-2 flex items-end justify-center text-red-500 font-medium">
163
+ <span>{fileError.value}</span>
164
+ </div>
165
+ </button>
166
+
167
+ <div class="mt-2 space-y-1">
168
+ <div class="flex flex-wrap gap-2 ">
169
+ {files.value.map(file => (<NBadge key={file.index} color="default" allCaps={false} textSize="text-xs">
170
+ <div class="flex items-center space-x-2">
171
+ <span>{file.name}</span>
172
+ <NIconButton icon={XMarkIcon} shade={900} size={3} onClick={() => removeFile(file.index)}/>
173
+ </div>
174
+ </NBadge>))}
175
+
176
+ <div class="flex-grow text-sm text-default-500 flex items-end justify-end text-right">
177
+ <span>
178
+ <span>
179
+ {trslc('vue-collection.text.files-selected', files.value.length, {
180
+ n: files.value.length,
181
+ })}
182
+ </span>
183
+ {files.value.length > 0 && (<>
184
+ <span> </span>
185
+ <NLink color="default" onClick={clearFiles}>
186
+ {trslc('vue-collection.action.clear-files', files.value.length)}
187
+ </NLink>
188
+ </>)}
189
+ </span>
190
+ </div>
191
+ </div>
192
+ </div>
193
+ </div>);
194
+ });
195
+ // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#unique_file_type_specifiers
196
+ const MIME_FORMAT = /^(image|audio|application|video|text)\/\*$/;
197
+ const EXTENSION_FORMAT = /^\.\w{2,20}$/;
198
+ function testFileWithAcceptString(accept, file) {
199
+ const splitted = accept.split(',').map(pattern => pattern.trim());
200
+ for (const pattern of splitted) {
201
+ if (MIME_FORMAT.test(pattern)) {
202
+ if (RegExp(`^${pattern.substring(0, pattern.length - 2)}\\/.{2,}$`).test(file.type))
203
+ return true;
204
+ }
205
+ else if (EXTENSION_FORMAT.test(pattern)) {
206
+ if (RegExp(`^.*${pattern}$`).test(file.name))
207
+ return true;
208
+ }
209
+ }
210
+ return false;
211
+ }
@@ -0,0 +1,43 @@
1
+ import type { PropType } from 'vue';
2
+ import type { ValidatedForm } from './ValidatedForm';
3
+ export declare const nFormProps: {
4
+ /**
5
+ * The {@link ValidatedForm} which will be used to validate the inputs.
6
+ * All inputs in this forms hierarchy should be added to the {@link ValidatedForm}.
7
+ */
8
+ form: PropType<ValidatedForm>;
9
+ /**
10
+ * This is called, when a button of type `submit` in the hierarchy of this view is clicked
11
+ * and when the validation of the `form` was successful.
12
+ */
13
+ onSubmit: PropType<() => void>;
14
+ };
15
+ /**
16
+ * The `NForm` should be used to wrap multiple inputs.
17
+ * If it contains a button of type `submit` in it's hierarchy,
18
+ * it catches the submit event and passes it to the {@link ValidatedForm} in its `form` prop.
19
+ */
20
+ declare const _default: import("vue").DefineComponent<{
21
+ /**
22
+ * The {@link ValidatedForm} which will be used to validate the inputs.
23
+ * All inputs in this forms hierarchy should be added to the {@link ValidatedForm}.
24
+ */
25
+ form: PropType<ValidatedForm>;
26
+ /**
27
+ * This is called, when a button of type `submit` in the hierarchy of this view is clicked
28
+ * and when the validation of the `form` was successful.
29
+ */
30
+ onSubmit: PropType<() => void>;
31
+ }, import("vue").RenderFunction, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, never[], never, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
32
+ /**
33
+ * The {@link ValidatedForm} which will be used to validate the inputs.
34
+ * All inputs in this forms hierarchy should be added to the {@link ValidatedForm}.
35
+ */
36
+ form: PropType<ValidatedForm>;
37
+ /**
38
+ * This is called, when a button of type `submit` in the hierarchy of this view is clicked
39
+ * and when the validation of the `form` was successful.
40
+ */
41
+ onSubmit: PropType<() => void>;
42
+ }>> & {}, {}>;
43
+ export default _default;
@@ -0,0 +1,26 @@
1
+ import { createComponent, createProps } from '../utils/component';
2
+ export const nFormProps = createProps({
3
+ /**
4
+ * The {@link ValidatedForm} which will be used to validate the inputs.
5
+ * All inputs in this forms hierarchy should be added to the {@link ValidatedForm}.
6
+ */
7
+ form: Object,
8
+ /**
9
+ * This is called, when a button of type `submit` in the hierarchy of this view is clicked
10
+ * and when the validation of the `form` was successful.
11
+ */
12
+ onSubmit: Function,
13
+ });
14
+ /**
15
+ * The `NForm` should be used to wrap multiple inputs.
16
+ * If it contains a button of type `submit` in it's hierarchy,
17
+ * it catches the submit event and passes it to the {@link ValidatedForm} in its `form` prop.
18
+ */
19
+ export default createComponent('NForm', nFormProps, (props, context) => {
20
+ const onSubmit = (event) => {
21
+ event.preventDefault();
22
+ if (!props.form || props.form.validate().isValid)
23
+ props.onSubmit?.();
24
+ };
25
+ return () => <form onSubmit={onSubmit}>{context.slots.default?.()}</form>;
26
+ });
@@ -0,0 +1,190 @@
1
+ import type { TWMaxWidth } from '../utils/tailwind';
2
+ import { type PropType } from 'vue';
3
+ import type { ValidatedForm } from './ValidatedForm';
4
+ export declare const nFormModalProps: {
5
+ /**
6
+ * The maximum width of the modal. A regular tailwind class.
7
+ */
8
+ maxWidth: {
9
+ type: PropType<TWMaxWidth>;
10
+ default: string;
11
+ };
12
+ /**
13
+ * If set to `true` the modal closes when clicking on the background.
14
+ * Default is `false` as the accidental reseting of the whole form is very annoying.
15
+ */
16
+ closeOnBackground: {
17
+ type: BooleanConstructor;
18
+ default: boolean;
19
+ };
20
+ /**
21
+ * The {@link ValidatedForm} to validate the inputs.
22
+ * All inputs should be added to the form.
23
+ */
24
+ form: PropType<ValidatedForm>;
25
+ hideHeader: BooleanConstructor;
26
+ hideFooter: BooleanConstructor;
27
+ hideX: BooleanConstructor;
28
+ title: StringConstructor;
29
+ okText: {
30
+ type: StringConstructor;
31
+ default: string;
32
+ };
33
+ okColor: {
34
+ type: StringConstructor;
35
+ default: string;
36
+ };
37
+ closeOnOk: {
38
+ type: BooleanConstructor;
39
+ default: boolean;
40
+ };
41
+ hideOk: BooleanConstructor;
42
+ okDisabled: BooleanConstructor;
43
+ cancelText: {
44
+ type: StringConstructor;
45
+ default: string;
46
+ };
47
+ cancelColor: {
48
+ type: StringConstructor;
49
+ default: string;
50
+ };
51
+ hideCancel: BooleanConstructor;
52
+ onOk: PropType<() => void>;
53
+ onCancel: PropType<() => void>;
54
+ modal: PropType<(props: import("./NModal").ModalSlotProps) => JSX.Element>;
55
+ header: PropType<() => JSX.Element>;
56
+ footer: PropType<(props: import("./NModal").ModalSlotProps) => JSX.Element>;
57
+ value: PropType<boolean>;
58
+ onUpdateValue: PropType<(newValue: boolean) => void>;
59
+ };
60
+ /**
61
+ * The `NFormModal` is a {@link NModal} with an integrated form.
62
+ * When submitting a `NFormModal` the form is first validated and
63
+ * only if the validation is succesful the `onOk` event is called.
64
+ */
65
+ declare const _default: import("vue").DefineComponent<{
66
+ /**
67
+ * The maximum width of the modal. A regular tailwind class.
68
+ */
69
+ maxWidth: {
70
+ type: PropType<TWMaxWidth>;
71
+ default: string;
72
+ };
73
+ /**
74
+ * If set to `true` the modal closes when clicking on the background.
75
+ * Default is `false` as the accidental reseting of the whole form is very annoying.
76
+ */
77
+ closeOnBackground: {
78
+ type: BooleanConstructor;
79
+ default: boolean;
80
+ };
81
+ /**
82
+ * The {@link ValidatedForm} to validate the inputs.
83
+ * All inputs should be added to the form.
84
+ */
85
+ form: PropType<ValidatedForm>;
86
+ hideHeader: BooleanConstructor;
87
+ hideFooter: BooleanConstructor;
88
+ hideX: BooleanConstructor;
89
+ title: StringConstructor;
90
+ okText: {
91
+ type: StringConstructor;
92
+ default: string;
93
+ };
94
+ okColor: {
95
+ type: StringConstructor;
96
+ default: string;
97
+ };
98
+ closeOnOk: {
99
+ type: BooleanConstructor;
100
+ default: boolean;
101
+ };
102
+ hideOk: BooleanConstructor;
103
+ okDisabled: BooleanConstructor;
104
+ cancelText: {
105
+ type: StringConstructor;
106
+ default: string;
107
+ };
108
+ cancelColor: {
109
+ type: StringConstructor;
110
+ default: string;
111
+ };
112
+ hideCancel: BooleanConstructor;
113
+ onOk: PropType<() => void>;
114
+ onCancel: PropType<() => void>;
115
+ modal: PropType<(props: import("./NModal").ModalSlotProps) => JSX.Element>;
116
+ header: PropType<() => JSX.Element>;
117
+ footer: PropType<(props: import("./NModal").ModalSlotProps) => JSX.Element>;
118
+ value: PropType<boolean>;
119
+ onUpdateValue: PropType<(newValue: boolean) => void>;
120
+ }, import("vue").RenderFunction, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, never[], never, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<{
121
+ /**
122
+ * The maximum width of the modal. A regular tailwind class.
123
+ */
124
+ maxWidth: {
125
+ type: PropType<TWMaxWidth>;
126
+ default: string;
127
+ };
128
+ /**
129
+ * If set to `true` the modal closes when clicking on the background.
130
+ * Default is `false` as the accidental reseting of the whole form is very annoying.
131
+ */
132
+ closeOnBackground: {
133
+ type: BooleanConstructor;
134
+ default: boolean;
135
+ };
136
+ /**
137
+ * The {@link ValidatedForm} to validate the inputs.
138
+ * All inputs should be added to the form.
139
+ */
140
+ form: PropType<ValidatedForm>;
141
+ hideHeader: BooleanConstructor;
142
+ hideFooter: BooleanConstructor;
143
+ hideX: BooleanConstructor;
144
+ title: StringConstructor;
145
+ okText: {
146
+ type: StringConstructor;
147
+ default: string;
148
+ };
149
+ okColor: {
150
+ type: StringConstructor;
151
+ default: string;
152
+ };
153
+ closeOnOk: {
154
+ type: BooleanConstructor;
155
+ default: boolean;
156
+ };
157
+ hideOk: BooleanConstructor;
158
+ okDisabled: BooleanConstructor;
159
+ cancelText: {
160
+ type: StringConstructor;
161
+ default: string;
162
+ };
163
+ cancelColor: {
164
+ type: StringConstructor;
165
+ default: string;
166
+ };
167
+ hideCancel: BooleanConstructor;
168
+ onOk: PropType<() => void>;
169
+ onCancel: PropType<() => void>;
170
+ modal: PropType<(props: import("./NModal").ModalSlotProps) => JSX.Element>;
171
+ header: PropType<() => JSX.Element>;
172
+ footer: PropType<(props: import("./NModal").ModalSlotProps) => JSX.Element>;
173
+ value: PropType<boolean>;
174
+ onUpdateValue: PropType<(newValue: boolean) => void>;
175
+ }>> & {}, {
176
+ maxWidth: TWMaxWidth;
177
+ hideX: boolean;
178
+ hideHeader: boolean;
179
+ hideFooter: boolean;
180
+ okText: string;
181
+ okColor: string;
182
+ closeOnOk: boolean;
183
+ hideOk: boolean;
184
+ okDisabled: boolean;
185
+ cancelText: string;
186
+ cancelColor: string;
187
+ closeOnBackground: boolean;
188
+ hideCancel: boolean;
189
+ }>;
190
+ export default _default;
@@ -0,0 +1,48 @@
1
+ import { createComponent, createProps } from '../utils/component';
2
+ import { reactive, toRefs } from 'vue';
3
+ import NForm from './NForm';
4
+ import NModal, { nModalProps } from './NModal';
5
+ export const nFormModalProps = createProps({
6
+ ...nModalProps,
7
+ /**
8
+ * The maximum width of the modal. A regular tailwind class.
9
+ */
10
+ maxWidth: {
11
+ type: String,
12
+ default: 'max-w-lg',
13
+ },
14
+ /**
15
+ * If set to `true` the modal closes when clicking on the background.
16
+ * Default is `false` as the accidental reseting of the whole form is very annoying.
17
+ */
18
+ closeOnBackground: {
19
+ type: Boolean,
20
+ default: false,
21
+ },
22
+ /**
23
+ * The {@link ValidatedForm} to validate the inputs.
24
+ * All inputs should be added to the form.
25
+ */
26
+ form: Object,
27
+ });
28
+ /**
29
+ * The `NFormModal` is a {@link NModal} with an integrated form.
30
+ * When submitting a `NFormModal` the form is first validated and
31
+ * only if the validation is succesful the `onOk` event is called.
32
+ */
33
+ export default createComponent('NFormModal', nFormModalProps, (props, { slots }) => {
34
+ const childProps = reactive({
35
+ ...toRefs(props),
36
+ onOk: () => {
37
+ if (!props.form || props.form.validate().isValid) {
38
+ props.onOk?.();
39
+ if (props.closeOnOk)
40
+ props.onUpdateValue?.(false);
41
+ }
42
+ },
43
+ closeOnOk: false,
44
+ });
45
+ return () => (<NModal {...childProps}>
46
+ <NForm form={props.form}>{slots.default?.()}</NForm>
47
+ </NModal>);
48
+ });