@fastkit/vui 1.2.0 → 1.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastkit/vui",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "A simple, extensible UI kit for Vue applications.",
5
5
  "keywords": [
6
6
  "fastkit",
@@ -44,32 +44,32 @@
44
44
  "src"
45
45
  ],
46
46
  "dependencies": {
47
+ "@fastkit/color-scheme-gen": "^1.1.0",
47
48
  "@fastkit/color-scheme": "^2.1.0",
48
- "@fastkit/helpers": "^0.15.0",
49
49
  "@fastkit/icon-font": "^2.1.0",
50
- "@fastkit/color-scheme-gen": "^1.1.0",
51
50
  "@fastkit/media-match": "^2.1.0",
51
+ "@fastkit/helpers": "^0.15.0",
52
52
  "@fastkit/dom": "^0.3.0",
53
- "@fastkit/vue-app-layout": "^0.18.0",
53
+ "@fastkit/rules": "^0.15.0",
54
+ "@fastkit/stylebase": "^0.13.1",
54
55
  "@fastkit/tiny-logger": "^0.15.0",
55
56
  "@fastkit/vue-action": "^0.5.0",
56
- "@fastkit/vue-disabled-reason": "^0.2.0",
57
+ "@fastkit/media-match-gen": "^1.1.0",
57
58
  "@fastkit/vue-body-scroll-lock": "^0.4.0",
58
- "@fastkit/vue-click-outside": "^0.4.0",
59
+ "@fastkit/vue-app-layout": "^0.18.0",
60
+ "@fastkit/vue-disabled-reason": "^0.2.0",
59
61
  "@fastkit/vue-color-scheme": "^0.17.0",
62
+ "@fastkit/vue-form-control": "^0.24.0",
63
+ "@fastkit/vue-click-outside": "^0.4.0",
60
64
  "@fastkit/vue-keyboard": "^0.4.0",
61
65
  "@fastkit/vue-location": "^0.6.0",
62
66
  "@fastkit/vue-loading": "^0.17.0",
63
67
  "@fastkit/vue-resize": "^0.4.0",
64
- "@fastkit/vue-stack": "^0.19.0",
65
- "@fastkit/vue-form-control": "^0.23.0",
66
68
  "@fastkit/vue-media-match": "^0.16.0",
69
+ "@fastkit/vue-utils": "^0.17.0",
67
70
  "@fastkit/vue-scroller": "^0.17.0",
68
- "@fastkit/media-match-gen": "^1.1.0",
69
- "@fastkit/rules": "^0.15.0",
70
- "@fastkit/stylebase": "^0.13.1",
71
71
  "@fastkit/vue-transitions": "^0.4.0",
72
- "@fastkit/vue-utils": "^0.17.0"
72
+ "@fastkit/vue-stack": "^0.19.2"
73
73
  },
74
74
  "devDependencies": {
75
75
  "vue": "^3.5.22",
@@ -6,6 +6,7 @@
6
6
  width: 100%;
7
7
  min-width: 0;
8
8
  height: var(--control-field-height);
9
+ min-height: var(--control-field-height);
9
10
  padding: 0 8px;
10
11
  font-size: var(--control-field-font-size);
11
12
  line-height: var(--control-field-line-height);
@@ -0,0 +1,42 @@
1
+ @use '../../styles/core';
2
+
3
+ @layer vui {
4
+ .v-file-input {
5
+ &__inner {
6
+ display: flex;
7
+ align-items: stretch;
8
+ }
9
+
10
+ &__button {
11
+ flex: 0 0 auto;
12
+ height: auto;
13
+ margin: 0;
14
+ margin-bottom: 1px;
15
+ border-top-right-radius: 0;
16
+ border-bottom-right-radius: 0;
17
+ }
18
+
19
+ &__selections {
20
+ display: flex;
21
+ flex-wrap: wrap;
22
+ align-items: center;
23
+ align-self: stretch;
24
+ padding: 4px 6px;
25
+ }
26
+
27
+ &__placeholder {
28
+ color: var(--control-disabled-color);
29
+ }
30
+
31
+ &__input {
32
+ flex: 1 1 100%;
33
+ cursor: text;
34
+ border-top-left-radius: 0;
35
+ border-bottom-left-radius: 0;
36
+
37
+ &__element {
38
+ @include core.hidden-input-element;
39
+ }
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,178 @@
1
+ import './VFileInput.scss';
2
+ import { defineComponent, computed } from 'vue';
3
+ import {
4
+ createFileInputNodeSettings,
5
+ useFileInputNodeControl,
6
+ createFormNodeWrapperProps,
7
+ FormNodeWrapperSlots,
8
+ FileInputNodeEmits,
9
+ type FileInputNodeControl,
10
+ } from '@fastkit/vue-form-control';
11
+ import { defineSlots, ExtractPropInput, withCtx } from '@fastkit/vue-utils';
12
+ import { VFormControl } from '../VFormControl';
13
+ import {
14
+ VControlField,
15
+ createControlFieldProps,
16
+ InputBoxSlots,
17
+ } from '../VControlField';
18
+ import {
19
+ createControlProps,
20
+ useControl,
21
+ createControlFieldProviderProps,
22
+ useControlField,
23
+ } from '../../composables';
24
+ import { colorSchemeProps } from '@fastkit/vue-color-scheme';
25
+ import { VUI_FILE_INPUT_SYMBOL, useVui } from '../../injections';
26
+ import { VButton } from '../VButton';
27
+
28
+ const { props, emits } = createFileInputNodeSettings();
29
+
30
+ const slots = defineSlots<
31
+ FormNodeWrapperSlots &
32
+ InputBoxSlots & {
33
+ selections?: (control: FileInputNodeControl) => any;
34
+ }
35
+ >();
36
+
37
+ function createFileInputProps() {
38
+ return {
39
+ ...props,
40
+ ...colorSchemeProps(),
41
+ ...createFormNodeWrapperProps(),
42
+ ...createControlFieldProps(),
43
+ ...createControlFieldProviderProps(),
44
+ ...createControlProps(),
45
+ ...slots(),
46
+ buttonText: {
47
+ type: String,
48
+ default: 'Choose File',
49
+ },
50
+ truncateLength: {
51
+ type: [Number, String],
52
+ default: 22,
53
+ },
54
+ };
55
+ }
56
+
57
+ export type FileInputPropsOptions = ReturnType<typeof createFileInputProps>;
58
+
59
+ export type FileInputEmits = FileInputNodeEmits;
60
+
61
+ export type FileInputInput = ExtractPropInput<
62
+ ReturnType<typeof createFileInputProps>
63
+ >;
64
+
65
+ export const VFileInput = defineComponent({
66
+ name: 'VFileInput',
67
+ props: createFileInputProps(),
68
+ emits,
69
+ slots,
70
+ setup(props, ctx) {
71
+ const vui = useVui();
72
+ const inputControl = useFileInputNodeControl(props, ctx, {
73
+ nodeType: VUI_FILE_INPUT_SYMBOL,
74
+ });
75
+ const control = useControl(props);
76
+ useControlField(props);
77
+
78
+ const classes = computed(() => ['v-file-input', control.classes.value]);
79
+
80
+ const handleClickLabel = (ev: PointerEvent) => {
81
+ inputControl.focus();
82
+ };
83
+
84
+ const endAdornmentSlot = () => {
85
+ // }
86
+ if (props.clearable && inputControl.value.length) {
87
+ return (
88
+ <VButton
89
+ key="clear"
90
+ icon={vui.icon('clear')}
91
+ rounded
92
+ onClick={(ev) => {
93
+ ev.stopPropagation();
94
+ inputControl.clear();
95
+ }}
96
+ />
97
+ );
98
+ }
99
+ };
100
+
101
+ const showDialog = () => {
102
+ if (inputControl.canOperation) {
103
+ inputControl.inputElement?.click();
104
+ }
105
+ };
106
+
107
+ const renderSelections = () => {
108
+ if (ctx.slots.selections) {
109
+ return ctx.slots.selections(inputControl);
110
+ }
111
+
112
+ const { files } = inputControl.selectionContext;
113
+ if (!files.length)
114
+ return (
115
+ <span class="v-file-input__placeholder">
116
+ {inputControl.placeholder || 'No file chosen'}
117
+ </span>
118
+ );
119
+ return files.map((file) => file.truncatedName).join(', ');
120
+ };
121
+
122
+ const defaultSlot = () => (
123
+ <div class="v-file-input__inner">
124
+ <VButton
125
+ key="open"
126
+ class="v-file-input__button"
127
+ color={'base' as any}
128
+ size={props.size}
129
+ startIcon={vui.icon('fileUpload')}
130
+ variant={vui.setting('containedVariant')}
131
+ onClick={showDialog}>
132
+ {props.buttonText}
133
+ </VButton>
134
+ <VControlField
135
+ class="v-file-input__input"
136
+ startAdornment={props.startAdornment}
137
+ endAdornment={props.endAdornment}
138
+ size={control.size.value}
139
+ onClick={showDialog}
140
+ autoHeight
141
+ v-slots={{
142
+ ...ctx.slots,
143
+ default: withCtx(() => [
144
+ inputControl.createInputElement({
145
+ class: 'v-file-input__input__element',
146
+ }),
147
+ <div class="v-file-input__selections">{renderSelections()}</div>,
148
+ ]),
149
+ endAdornment: withCtx(endAdornmentSlot),
150
+ }}
151
+ />
152
+ </div>
153
+ );
154
+
155
+ ctx.expose({
156
+ control: inputControl,
157
+ });
158
+
159
+ return () => (
160
+ <VFormControl
161
+ nodeControl={inputControl}
162
+ // focused={inputControl.focused}
163
+ hiddenInfo={props.hiddenInfo}
164
+ class={classes.value}
165
+ label={props.label}
166
+ hint={props.hint}
167
+ hinttip={props.hinttip}
168
+ requiredChip={props.requiredChip}
169
+ onClickLabel={handleClickLabel}
170
+ v-slots={{
171
+ ...ctx.slots,
172
+ default: withCtx(defaultSlot),
173
+ // infoAppends: withCtx(infoAppendsSlot),
174
+ }}
175
+ />
176
+ );
177
+ },
178
+ });
@@ -0,0 +1 @@
1
+ export * from './VFileInput';
@@ -35,6 +35,7 @@ export * from './VSelect';
35
35
  export * from './VTextField';
36
36
  export * from './VNumberField';
37
37
  export * from './VTextarea';
38
+ export * from './VFileInput';
38
39
  // export * from './VWysiwygEditor';
39
40
  export * from './VFormGroup';
40
41
  export * from './VForm';
package/src/injections.ts CHANGED
@@ -27,6 +27,7 @@ export const VUI_RADIO_GROUP_SYMBOL = 'vui-radio-group';
27
27
  export const VUI_RADIO_SYMBOL = 'vui-radio';
28
28
  export const VUI_SWITCH_GROUP_SYMBOL = 'vui-switch-group';
29
29
  export const VUI_SWITCH_SYMBOL = 'vui-switch';
30
+ export const VUI_FILE_INPUT_SYMBOL = 'vui-file-input';
30
31
  export const VUI_FORM_GROUP_SYMBOL = 'vui-form-group';
31
32
  export const VUI_FORM_SYMBOL = 'vui-form';
32
33
 
package/src/service.tsx CHANGED
@@ -132,6 +132,7 @@ export interface VuiServiceIconSettings {
132
132
  hinttip: IconName;
133
133
  clear: IconName;
134
134
  reload: IconName;
135
+ fileUpload: IconName;
135
136
  }
136
137
 
137
138
  export type RawVuiServiceIconSettings = Partial<VuiServiceIconSettings>;