@byyuurin/ui 0.3.0 → 0.4.0

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 (82) hide show
  1. package/LICENSE +20 -20
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +2 -2
  4. package/dist/runtime/components/Accordion.vue +43 -43
  5. package/dist/runtime/components/Alert.vue +65 -64
  6. package/dist/runtime/components/App.vue +10 -10
  7. package/dist/runtime/components/Avatar.vue +31 -30
  8. package/dist/runtime/components/AvatarGroup.vue +6 -5
  9. package/dist/runtime/components/Badge.vue +36 -35
  10. package/dist/runtime/components/Breadcrumb.vue +51 -51
  11. package/dist/runtime/components/Button.vue +54 -55
  12. package/dist/runtime/components/Calendar.vue +76 -75
  13. package/dist/runtime/components/Card.vue +43 -42
  14. package/dist/runtime/components/Carousel.vue +68 -67
  15. package/dist/runtime/components/Checkbox.vue +50 -48
  16. package/dist/runtime/components/CheckboxGroup.vue +33 -32
  17. package/dist/runtime/components/Chip.vue +20 -16
  18. package/dist/runtime/components/Collapsible.vue +16 -15
  19. package/dist/runtime/components/Drawer.vue +78 -77
  20. package/dist/runtime/components/DropdownMenu.vue +29 -29
  21. package/dist/runtime/components/DropdownMenuContent.vue +152 -152
  22. package/dist/runtime/components/FieldGroup.vue +5 -4
  23. package/dist/runtime/components/FileUpload.vue +267 -0
  24. package/dist/runtime/components/FileUpload.vue.d.ts +178 -0
  25. package/dist/runtime/components/Form.vue +11 -10
  26. package/dist/runtime/components/FormField.vue +39 -38
  27. package/dist/runtime/components/Icon.vue +2 -2
  28. package/dist/runtime/components/Input.vue +52 -52
  29. package/dist/runtime/components/InputNumber.vue +50 -49
  30. package/dist/runtime/components/InputTags.vue +55 -55
  31. package/dist/runtime/components/Kbd.vue +5 -4
  32. package/dist/runtime/components/Link.vue +25 -24
  33. package/dist/runtime/components/LinkBase.vue +3 -3
  34. package/dist/runtime/components/Marquee.vue +7 -6
  35. package/dist/runtime/components/Modal.vue +76 -75
  36. package/dist/runtime/components/NavigationMenu.vue +230 -230
  37. package/dist/runtime/components/OverlayProvider.vue +9 -9
  38. package/dist/runtime/components/Pagination.vue +49 -48
  39. package/dist/runtime/components/PinInput.vue +25 -25
  40. package/dist/runtime/components/Popover.vue +23 -23
  41. package/dist/runtime/components/Progress.vue +27 -26
  42. package/dist/runtime/components/RadioGroup.vue +53 -53
  43. package/dist/runtime/components/ScrollArea.vue +34 -33
  44. package/dist/runtime/components/Select.vue +203 -203
  45. package/dist/runtime/components/Separator.vue +32 -31
  46. package/dist/runtime/components/Skeleton.vue +13 -12
  47. package/dist/runtime/components/Slider.vue +27 -26
  48. package/dist/runtime/components/Stepper.vue +53 -52
  49. package/dist/runtime/components/Stepper.vue.d.ts +2 -2
  50. package/dist/runtime/components/Switch.vue +33 -34
  51. package/dist/runtime/components/Table.vue +139 -138
  52. package/dist/runtime/components/Tabs.vue +76 -76
  53. package/dist/runtime/components/Textarea.vue +50 -50
  54. package/dist/runtime/components/Timeline.vue +49 -48
  55. package/dist/runtime/components/Toast.vue +95 -94
  56. package/dist/runtime/components/ToastProvider.vue +31 -31
  57. package/dist/runtime/components/Tooltip.vue +26 -25
  58. package/dist/runtime/components/Tree.vue +133 -133
  59. package/dist/runtime/composables/useFileUpload.d.ts +19 -0
  60. package/dist/runtime/composables/useFileUpload.js +79 -0
  61. package/dist/runtime/composables/useLocale.d.ts +6 -0
  62. package/dist/runtime/locale/en.d.ts +3 -0
  63. package/dist/runtime/locale/en.js +3 -0
  64. package/dist/runtime/locale/zh_tw.d.ts +3 -0
  65. package/dist/runtime/locale/zh_tw.js +3 -0
  66. package/dist/runtime/types/index.d.ts +1 -0
  67. package/dist/runtime/types/index.js +1 -0
  68. package/dist/runtime/types/locale.d.ts +3 -0
  69. package/dist/runtime/types/unocss.d.ts +4 -4
  70. package/dist/runtime/types/utils.d.ts +1 -1
  71. package/dist/runtime/vue/components/Icon.vue +2 -2
  72. package/dist/setup.d.mts +1 -1
  73. package/dist/shared/{ui.D8Bg1HWt.d.mts → ui.CGCKYv7g.d.mts} +4 -2
  74. package/dist/shared/{ui.9kQouwss.mjs → ui.DYMXCXO6.mjs} +4 -2
  75. package/dist/shared/{ui.DpkP12cX.mjs → ui.DcEKQd0n.mjs} +230 -5
  76. package/dist/unocss.mjs +1 -1
  77. package/dist/unplugin.d.mts +1 -1
  78. package/dist/unplugin.mjs +2 -2
  79. package/dist/vite.d.mts +1 -1
  80. package/dist/vite.mjs +2 -2
  81. package/package.json +10 -10
  82. package/vue-plugin.d.ts +5 -5
@@ -0,0 +1,267 @@
1
+ <script>
2
+ import theme from "#build/ui/file-upload";
3
+ </script>
4
+
5
+ <script setup>
6
+ import { createReusableTemplate } from "@vueuse/core";
7
+ import { Primitive, VisuallyHidden } from "reka-ui";
8
+ import { computed, toRef, watch } from "vue";
9
+ import { useAppConfig } from "#imports";
10
+ import { useFileUpload } from "../composables/useFileUpload";
11
+ import { useFormField } from "../composables/useFormField";
12
+ import { useLocale } from "../composables/useLocale";
13
+ import { pick } from "../utils";
14
+ import { cv, merge } from "../utils/style";
15
+ import Avatar from "./Avatar.vue";
16
+ import Button from "./Button.vue";
17
+ import Icon from "./Icon.vue";
18
+ defineOptions({ inheritAttrs: false });
19
+ const props = defineProps({
20
+ as: { type: null, required: false },
21
+ id: { type: String, required: false },
22
+ name: { type: String, required: false },
23
+ modelValue: { type: null, required: false },
24
+ icon: { type: [String, Object], required: false },
25
+ label: { type: String, required: false },
26
+ description: { type: String, required: false },
27
+ color: { type: null, required: false },
28
+ variant: { type: null, required: false },
29
+ size: { type: null, required: false },
30
+ layout: { type: null, required: false, default: "grid" },
31
+ position: { type: null, required: false, default: "outside" },
32
+ highlight: { type: Boolean, required: false },
33
+ accept: { type: String, required: false, default: "*" },
34
+ multiple: { type: Boolean, required: false, default: false },
35
+ reset: { type: Boolean, required: false, default: false },
36
+ dropzone: { type: Boolean, required: false, default: true },
37
+ interactive: { type: Boolean, required: false, default: true },
38
+ required: { type: Boolean, required: false },
39
+ disabled: { type: Boolean, required: false },
40
+ fileIcon: { type: [String, Object], required: false },
41
+ fileDelete: { type: [Boolean, Object], required: false, default: true },
42
+ fileDeleteIcon: { type: [String, Object], required: false },
43
+ preview: { type: Boolean, required: false, default: true },
44
+ ui: { type: null, required: false },
45
+ class: { type: [Object, String, Number, Boolean, null, Array], required: false, skipCheck: true }
46
+ });
47
+ const emit = defineEmits(["change"]);
48
+ const slots = defineSlots();
49
+ const modelValue = defineModel({ type: null });
50
+ const { t } = useLocale();
51
+ const [DefineFilesTemplate, ReuseFilesTemplate] = createReusableTemplate();
52
+ const { isDragging, open, inputRef, dropzoneRef } = useFileUpload({
53
+ accept: toRef(() => props.accept),
54
+ reset: props.reset,
55
+ multiple: toRef(() => props.multiple),
56
+ dropzone: toRef(() => props.dropzone),
57
+ onUpdate
58
+ });
59
+ const { id, name, disabled, ariaAttrs, emitFormInput, emitFormChange } = useFormField(props);
60
+ const variant = computed(() => props.multiple ? "area" : props.variant);
61
+ const layout = computed(() => props.variant === "button" && !props.multiple ? "grid" : props.layout);
62
+ const position = computed(() => {
63
+ if (layout.value === "grid" && props.multiple)
64
+ return "inside";
65
+ if (variant.value === "button")
66
+ return "outside";
67
+ return props.position;
68
+ });
69
+ const appConfig = useAppConfig();
70
+ const ui = computed(() => {
71
+ const styler = cv(merge(theme, appConfig.ui.fileUpload));
72
+ return styler({
73
+ ...pick(props, ["dropzone", "interactive", "color", "size", "multiple", "highlight"]),
74
+ variant: variant.value,
75
+ layout: layout.value,
76
+ position: position.value,
77
+ disabled: disabled.value
78
+ });
79
+ });
80
+ function createObjectUrl(file) {
81
+ return URL.createObjectURL(file);
82
+ }
83
+ function formatFileSize(bytes) {
84
+ if (bytes === 0)
85
+ return "0B";
86
+ const k = 1024;
87
+ const sizes = ["B", "KB", "MB", "GB"];
88
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
89
+ const size = bytes / k ** i;
90
+ const formattedSize = i === 0 ? size.toString() : size.toFixed(0);
91
+ return `${formattedSize}${sizes[i]}`;
92
+ }
93
+ function onUpdate(files, reset = false) {
94
+ if (props.multiple) {
95
+ if (reset) {
96
+ modelValue.value = files;
97
+ } else {
98
+ const existingFiles = modelValue.value || [];
99
+ modelValue.value = [...existingFiles, ...files || []];
100
+ }
101
+ } else {
102
+ modelValue.value = files?.[0];
103
+ }
104
+ const event = new Event("change", { target: { value: modelValue.value } });
105
+ emit("change", event);
106
+ emitFormChange();
107
+ emitFormInput();
108
+ }
109
+ function removeFile(index) {
110
+ if (!modelValue.value)
111
+ return;
112
+ if (!props.multiple || index === void 0) {
113
+ onUpdate([], true);
114
+ dropzoneRef.value?.focus();
115
+ return;
116
+ }
117
+ const files = [...modelValue.value];
118
+ files.splice(index, 1);
119
+ onUpdate(files, true);
120
+ dropzoneRef.value?.focus();
121
+ }
122
+ watch(modelValue, (newValue) => {
123
+ const hasModelReset = props.multiple ? !newValue?.length : !newValue;
124
+ if (hasModelReset && inputRef.value?.$el)
125
+ inputRef.value.$el.value = "";
126
+ });
127
+ defineExpose({
128
+ inputRef: toRef(() => inputRef.value?.$el),
129
+ dropzoneRef
130
+ });
131
+ </script>
132
+
133
+ <template>
134
+ <DefineFilesTemplate>
135
+ <template v-if="props.preview && modelValue && (Array.isArray(modelValue) ? modelValue.length : true)">
136
+ <slot name="files-top" :files="modelValue" :open="open" :remove-file="removeFile"></slot>
137
+
138
+ <div :class="ui.files({ class: props.ui?.files })" data-part="files">
139
+ <slot name="files" :files="modelValue">
140
+ <div v-for="(file, index) in Array.isArray(modelValue) ? modelValue : [modelValue]" :key="index" :class="ui.file({ class: props.ui?.file })" data-part="file">
141
+ <slot name="file" :file="file" :index="index">
142
+ <slot name="file-leading" :file="file" :index="index" :ui="ui">
143
+ <Avatar
144
+ :as="{ img: 'img' }"
145
+ :src="createObjectUrl(file)"
146
+ :icon="props.fileIcon || appConfig.ui.icons.file"
147
+ :size="props.size"
148
+ :class="ui.fileLeadingAvatar({ class: props.ui?.fileLeadingAvatar })"
149
+ data-part="fileLeadingAvatar"
150
+ />
151
+ </slot>
152
+
153
+ <div :class="ui.fileWrapper({ class: props.ui?.fileWrapper })" data-part="fileWrapper">
154
+ <span :class="ui.fileName({ class: props.ui?.fileName })" data-part="fileName">
155
+ <slot name="file-name" :file="file" :index="index">
156
+ {{ file.name }}
157
+ </slot>
158
+ </span>
159
+
160
+ <span :class="ui.fileSize({ class: props.ui?.fileSize })" data-part="fileSize">
161
+ <slot name="file-size" :file="file" :index="index">
162
+ {{ formatFileSize(file.size) }}
163
+ </slot>
164
+ </span>
165
+ </div>
166
+
167
+ <slot name="file-trailing" :file="file" :index="index" :ui="ui">
168
+ <Button
169
+ v-if="props.fileDelete"
170
+ color="neutral"
171
+ v-bind="{
172
+ ...layout === 'grid' ? { variant: 'solid', size: 'xs' } : { variant: 'link', size: props.size },
173
+ ...typeof props.fileDelete === 'object' ? props.fileDelete : void 0
174
+ }"
175
+ :aria-label="t('fileUpload.removeFile', { filename: file.name })"
176
+ :trailing-icon="props.fileDeleteIcon || appConfig.ui.icons.close"
177
+ :class="ui.fileTrailingButton({ class: props.ui?.fileTrailingButton })"
178
+ data-part="fileTrailingButton"
179
+ @click.stop.prevent="removeFile(index)"
180
+ />
181
+ </slot>
182
+ </slot>
183
+ </div>
184
+ </slot>
185
+ </div>
186
+
187
+ <slot name="files-bottom" :files="modelValue" :open="open" :remove-file="removeFile"></slot>
188
+ </template>
189
+ </DefineFilesTemplate>
190
+
191
+ <Primitive :as="props.as" :class="ui.root({ class: [props.ui?.root, props.class] })" data-part="root">
192
+ <slot :open="open" :remove-file="removeFile" :ui="ui">
193
+ <component
194
+ :is="variant === 'button' ? 'button' : 'div'"
195
+ ref="dropzoneRef"
196
+ :type="variant === 'button' ? 'button' : void 0"
197
+ :role="variant === 'button' ? void 0 : 'button'"
198
+ :tabindex="props.interactive && disabled ? 0 : -1"
199
+ :data-dragging="isDragging"
200
+ :class="ui.base({ class: props.ui?.base })"
201
+ data-part="base"
202
+ @click="props.interactive && !disabled && open()"
203
+ @keydown.space.prevent
204
+ @keyup.enter.space="props.interactive && !disabled && open()"
205
+ >
206
+ <ReuseFilesTemplate v-if="position === 'inside'" />
207
+
208
+ <div
209
+ v-if="props.preview && position === 'inside' ? props.multiple ? !modelValue?.length : !modelValue : true"
210
+ :class="ui.wrapper({ class: props.ui?.wrapper })"
211
+ data-part="wrapper"
212
+ >
213
+ <slot name="leading" :ui="ui">
214
+ <Icon
215
+ v-if="variant === 'button'"
216
+ :name="props.icon || appConfig.ui.icons.upload"
217
+ :class="ui.icon({ class: props.ui?.icon })"
218
+ data-part="icon"
219
+ />
220
+ <Avatar
221
+ v-else
222
+ :icon="props.icon || appConfig.ui.icons.upload"
223
+ :size="props.size"
224
+ :ui="{ icon: props.ui?.icon }"
225
+ :class="ui.avatar({ class: props.ui?.avatar })"
226
+ data-part="avatar"
227
+ />
228
+ </slot>
229
+
230
+ <template v-if="variant !== 'button'">
231
+ <div v-if="props.label || slots.label" :class="ui.label({ class: props.ui?.label })" data-part="label">
232
+ <slot name="label">
233
+ {{ props.label }}
234
+ </slot>
235
+ </div>
236
+
237
+ <div v-if="props.description || slots.description" :class="ui.description({ class: props.ui?.description })">
238
+ <slot name="description">
239
+ {{ props.description }}
240
+ </slot>
241
+ </div>
242
+
243
+ <div v-if="slots.actions">
244
+ <slot name="actions" :files="modelValue || null" :open="open" :remove-file="removeFile"></slot>
245
+ </div>
246
+ </template>
247
+ </div>
248
+ </component>
249
+
250
+ <ReuseFilesTemplate v-if="position === 'outside'" />
251
+ </slot>
252
+
253
+ <VisuallyHidden
254
+ :id="id"
255
+ ref="inputRef"
256
+ as="input"
257
+ type="file"
258
+ feature="fully-hidden"
259
+ :name="name"
260
+ :accept="props.accept"
261
+ :multiple="props.multiple"
262
+ :required="props.required"
263
+ :disabled="disabled"
264
+ v-bind="{ ...$attrs, ...ariaAttrs }"
265
+ />
266
+ </Primitive>
267
+ </template>
@@ -0,0 +1,178 @@
1
+ import type { VariantProps } from '@byyuurin/ui-kit';
2
+ import type { UseFileDialogReturn } from '@vueuse/core';
3
+ import type { PrimitiveProps } from 'reka-ui';
4
+ import theme from '#build/ui/file-upload';
5
+ import type { ButtonProps, ComponentBaseProps, ComponentStyler, ComponentUIProps, IconProps, LinkPropsKeys } from '../types';
6
+ import type { InputHTMLAttributes } from '../types/html';
7
+ import type { MaybeNull, StaticSlot } from '../types/utils';
8
+ type ThemeVariants = VariantProps<typeof theme>;
9
+ export interface FileUploadProps<M extends boolean = false> extends ComponentBaseProps, /** @vue-ignore */ Pick<InputHTMLAttributes, 'form' | 'formaction' | 'formenctype' | 'formmethod' | 'formnovalidate' | 'formtarget'> {
10
+ /**
11
+ * The element or component this component should render as.
12
+ * @default "div"
13
+ */
14
+ as?: PrimitiveProps['as'];
15
+ id?: string;
16
+ name?: string;
17
+ modelValue?: MaybeNull<M extends true ? File[] : File>;
18
+ /**
19
+ * The icon to display.
20
+ * @default app.icons.upload
21
+ */
22
+ icon?: IconProps['name'];
23
+ label?: string;
24
+ description?: string;
25
+ /** @default "primary" */
26
+ color?: ThemeVariants['color'];
27
+ /**
28
+ * The `button` variant is only available when `multiple` is `false`.
29
+ * @default "area"
30
+ */
31
+ variant?: ThemeVariants['variant'];
32
+ /** @default "md" */
33
+ size?: ThemeVariants['size'];
34
+ /**
35
+ * The layout of how files are displayed.
36
+ * Only works when `variant` is `area`.
37
+ * @default "list"
38
+ */
39
+ layout?: ThemeVariants['layout'];
40
+ /**
41
+ * The position of the files.
42
+ * Only works when `variant` is `area` and when `layout` is `list`.
43
+ * @default "outside"
44
+ */
45
+ position?: ThemeVariants['position'];
46
+ /** Highlight the ring color like a focus state. */
47
+ highlight?: boolean;
48
+ /**
49
+ * Specifies the allowed file types for the input. Provide a comma-separated list of MIME types or file extensions (e.g., "image/png,application/pdf,.jpg").
50
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/accept
51
+ * @default "*"
52
+ */
53
+ accept?: string;
54
+ multiple?: M & boolean;
55
+ /**
56
+ * Reset the file input when the dialog is opened.
57
+ * @default false
58
+ */
59
+ reset?: boolean;
60
+ /**
61
+ * Create a zone that allows the user to drop files onto it.
62
+ * @default true
63
+ */
64
+ dropzone?: boolean;
65
+ /**
66
+ * Make the dropzone interactive when the user is clicking on it.
67
+ * @default true
68
+ */
69
+ interactive?: boolean;
70
+ required?: boolean;
71
+ disabled?: boolean;
72
+ /**
73
+ * The icon to display for the file.
74
+ * @default app.icons.file
75
+ */
76
+ fileIcon?: IconProps['name'];
77
+ /**
78
+ * Configure the delete button for the file.
79
+ *
80
+ * When `layout` is `grid`, the default is `{ color: 'neutral', variant: 'solid', size: 'xs' }`
81
+ *
82
+ * When `layout` is `list`, the default is `{ color: 'neutral', variant: 'link' }`
83
+ */
84
+ fileDelete?: boolean | Omit<ButtonProps, LinkPropsKeys>;
85
+ /**
86
+ * The icon displayed to delete a file.
87
+ * @default app.icons.close
88
+ */
89
+ fileDeleteIcon?: IconProps['name'];
90
+ /**
91
+ * Show the file preview/list after upload.
92
+ * @default true
93
+ */
94
+ preview?: boolean;
95
+ ui?: ComponentUIProps<typeof theme>;
96
+ }
97
+ export interface FileUploadEmits {
98
+ change: [event: Event];
99
+ }
100
+ type FileUploadFiles<M> = (M extends true ? File[] : File) | null;
101
+ export interface FileUploadSlots<M extends boolean = false> {
102
+ 'default': StaticSlot<{
103
+ open: UseFileDialogReturn['open'];
104
+ removeFile: (index?: number) => void;
105
+ ui: ComponentStyler<typeof theme>;
106
+ }>;
107
+ 'leading': StaticSlot<{
108
+ ui: ComponentStyler<typeof theme>;
109
+ }>;
110
+ 'label': StaticSlot;
111
+ 'description': StaticSlot;
112
+ 'actions': StaticSlot<{
113
+ files: FileUploadFiles<M>;
114
+ open: UseFileDialogReturn['open'];
115
+ removeFile: (index?: number) => void;
116
+ }>;
117
+ 'files': StaticSlot<{
118
+ files: FileUploadFiles<M>;
119
+ }>;
120
+ 'files-top': StaticSlot<{
121
+ files: FileUploadFiles<M>;
122
+ open: UseFileDialogReturn['open'];
123
+ removeFile: (index?: number) => void;
124
+ }>;
125
+ 'files-bottom': StaticSlot<{
126
+ files: FileUploadFiles<M>;
127
+ open: UseFileDialogReturn['open'];
128
+ removeFile: (index?: number) => void;
129
+ }>;
130
+ 'file': StaticSlot<{
131
+ file: File;
132
+ index: number;
133
+ }>;
134
+ 'file-leading': StaticSlot<{
135
+ file: File;
136
+ index: number;
137
+ ui: ComponentStyler<typeof theme>;
138
+ }>;
139
+ 'file-name': StaticSlot<{
140
+ file: File;
141
+ index: number;
142
+ }>;
143
+ 'file-size': StaticSlot<{
144
+ file: File;
145
+ index: number;
146
+ }>;
147
+ 'file-trailing': StaticSlot<{
148
+ file: File;
149
+ index: number;
150
+ ui: ComponentStyler<typeof theme>;
151
+ }>;
152
+ }
153
+ declare const _default: typeof __VLS_export;
154
+ export default _default;
155
+ declare const __VLS_export: <M extends boolean = false>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
156
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<(FileUploadProps<M> & {
157
+ modelValue?: MaybeNull<(M extends true ? File[] : File)>;
158
+ }) & {
159
+ onChange?: ((event: Event) => any) | undefined;
160
+ "onUpdate:modelValue"?: ((value: MaybeNull<M extends true ? File[] : File> | undefined) => any) | undefined;
161
+ }> & (typeof globalThis extends {
162
+ __VLS_PROPS_FALLBACK: infer P;
163
+ } ? P : {});
164
+ expose: (exposed: import("vue").ShallowUnwrapRef<{
165
+ inputRef: Readonly<import("vue").Ref<HTMLInputElement, HTMLInputElement>>;
166
+ dropzoneRef: import("vue").ShallowRef<HTMLDivElement | undefined, HTMLDivElement | undefined>;
167
+ }>) => void;
168
+ attrs: any;
169
+ slots: FileUploadSlots<M>;
170
+ emit: ((evt: "change", event: Event) => void) & ((evt: "update:modelValue", value: MaybeNull<M extends true ? File[] : File> | undefined) => void);
171
+ }>) => import("vue").VNode & {
172
+ __ctx?: Awaited<typeof __VLS_setup>;
173
+ };
174
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
175
+ [K in keyof T]: T[K];
176
+ } : {
177
+ [K in keyof T as K]: T[K];
178
+ }) & {};
@@ -8,6 +8,7 @@ import { computed, nextTick, onMounted, onUnmounted, reactive, readonly, ref, sh
8
8
  import { useAppConfig } from "#imports";
9
9
  import { injectFormBus, injectFormState, provideFormBus, provideFormErrors, provideFormInputs, provideFormLoading, provideFormOptions, provideFormState } from "../composables/useFormField";
10
10
  import { FormValidationException } from "../types/form";
11
+ import { pick } from "../utils";
11
12
  import { getAtPath, setAtPath, validateSchema } from "../utils/form";
12
13
  import { cv, merge } from "../utils/style";
13
14
  const props = defineProps({
@@ -264,18 +265,18 @@ defineExpose(api);
264
265
  const appConfig = useAppConfig();
265
266
  const ui = computed(() => {
266
267
  const styler = cv(merge(theme, appConfig.ui.form));
267
- return styler(props);
268
+ return styler(pick(props, []));
268
269
  });
269
270
  </script>
270
271
 
271
272
  <template>
272
- <component
273
- :is="parentBus ? 'div' : 'form'"
274
- :id="formId"
275
- :class="ui.base({ class: props.class })"
276
- data-part="base"
277
- @submit.prevent="onSubmitWrapper"
278
- >
279
- <slot :errors="errors" :loading="loading"></slot>
280
- </component>
273
+ <component
274
+ :is="parentBus ? 'div' : 'form'"
275
+ :id="formId"
276
+ :class="ui.base({ class: props.class })"
277
+ data-part="base"
278
+ @submit.prevent="onSubmitWrapper"
279
+ >
280
+ <slot :errors="errors" :loading="loading"></slot>
281
+ </component>
281
282
  </template>
@@ -7,6 +7,7 @@ import { Label, Primitive } from "reka-ui";
7
7
  import { computed, ref, useId, watch } from "vue";
8
8
  import { useAppConfig } from "#imports";
9
9
  import { injectFormErrors, injectFormInputs, provideFormField, provideFormInputId } from "../composables/useFormField";
10
+ import { pick } from "../utils";
10
11
  import { cv, merge } from "../utils/style";
11
12
  const props = defineProps({
12
13
  as: { type: null, required: false },
@@ -64,46 +65,46 @@ provideFormField(computed(() => ({
64
65
  const appConfig = useAppConfig();
65
66
  const ui = computed(() => {
66
67
  const styler = cv(merge(theme, appConfig.ui.formField));
67
- return styler(props);
68
+ return styler(pick(props, ["size", "required", "orientation"]));
68
69
  });
69
70
  </script>
70
71
 
71
72
  <template>
72
- <Primitive :as="props.as" :class="ui.root({ class: [props.ui?.root, props.class] })" :data-orientation="props.orientation" data-part="root">
73
- <div :class="ui.wrapper({ class: props.ui?.wrapper })" data-part="wrapper">
74
- <div v-if="props.label || !!slots.label" :class="ui.labelWrapper({ class: props.ui?.labelWrapper })" data-part="labelWrapper">
75
- <Label :for="id" :class="ui.label({ class: props.ui?.label })" data-part="label">
76
- <slot name="label" :label="props.label">
77
- {{ props.label }}
78
- </slot>
79
- </Label>
80
- <span v-if="props.hint || !!slots.hint" :id="`${ariaId}-hint`" :class="ui.hint({ class: props.ui?.hint })" data-part="hint">
81
- <slot name="hint" :hint="props.hint">
82
- {{ props.hint }}
83
- </slot>
84
- </span>
85
- </div>
86
-
87
- <p v-if="props.description || !!slots.description" :id="`${ariaId}-description`" :class="ui.description({ class: props.ui?.description })" data-part="description">
88
- <slot name="description" :description="props.description">
89
- {{ props.description }}
90
- </slot>
91
- </p>
92
- </div>
93
-
94
- <div :class="(props.label || !!slots.label || props.description || !!slots.description) && ui.container({ class: props.ui?.container })" data-part="container">
95
- <slot :error="error"></slot>
96
-
97
- <div v-if="props.error !== false && (typeof error === 'string' && error || !!slots.error)" :id="`${ariaId}-error`" :class="ui.error({ class: props.ui?.error })" data-part="error">
98
- <slot name="error" :error="error">
99
- {{ error }}
100
- </slot>
101
- </div>
102
- <div v-else-if="props.help || !!slots.help" :class="ui.help({ class: props.ui?.help })" data-part="help">
103
- <slot name="help" :help="props.help">
104
- {{ props.help }}
105
- </slot>
106
- </div>
107
- </div>
108
- </Primitive>
73
+ <Primitive :as="props.as" :class="ui.root({ class: [props.ui?.root, props.class] })" :data-orientation="props.orientation" data-part="root">
74
+ <div :class="ui.wrapper({ class: props.ui?.wrapper })" data-part="wrapper">
75
+ <div v-if="props.label || !!slots.label" :class="ui.labelWrapper({ class: props.ui?.labelWrapper })" data-part="labelWrapper">
76
+ <Label :for="id" :class="ui.label({ class: props.ui?.label })" data-part="label">
77
+ <slot name="label" :label="props.label">
78
+ {{ props.label }}
79
+ </slot>
80
+ </Label>
81
+ <span v-if="props.hint || !!slots.hint" :id="`${ariaId}-hint`" :class="ui.hint({ class: props.ui?.hint })" data-part="hint">
82
+ <slot name="hint" :hint="props.hint">
83
+ {{ props.hint }}
84
+ </slot>
85
+ </span>
86
+ </div>
87
+
88
+ <p v-if="props.description || !!slots.description" :id="`${ariaId}-description`" :class="ui.description({ class: props.ui?.description })" data-part="description">
89
+ <slot name="description" :description="props.description">
90
+ {{ props.description }}
91
+ </slot>
92
+ </p>
93
+ </div>
94
+
95
+ <div :class="(props.label || !!slots.label || props.description || !!slots.description) && ui.container({ class: props.ui?.container })" data-part="container">
96
+ <slot :error="error"></slot>
97
+
98
+ <div v-if="props.error !== false && (typeof error === 'string' && error || !!slots.error)" :id="`${ariaId}-error`" :class="ui.error({ class: props.ui?.error })" data-part="error">
99
+ <slot name="error" :error="error">
100
+ {{ error }}
101
+ </slot>
102
+ </div>
103
+ <div v-else-if="props.help || !!slots.help" :class="ui.help({ class: props.ui?.help })" data-part="help">
104
+ <slot name="help" :help="props.help">
105
+ {{ props.help }}
106
+ </slot>
107
+ </div>
108
+ </div>
109
+ </Primitive>
109
110
  </template>
@@ -15,6 +15,6 @@ const iconProps = useForwardProps(reactivePick(props, "name", "mode", "size", "c
15
15
  </script>
16
16
 
17
17
  <template>
18
- <Icon v-if="typeof props.name === 'string'" v-bind="iconProps" />
19
- <component :is="props.name" v-else />
18
+ <Icon v-if="typeof props.name === 'string'" v-bind="iconProps" />
19
+ <component :is="props.name" v-else />
20
20
  </template>