vueless 0.0.514 → 0.0.516
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 +1 -1
- package/types.ts +8 -0
- package/ui.button-link/useAttrs.ts +2 -2
- package/ui.dropdown-badge/UDropdownBadge.vue +70 -167
- package/ui.dropdown-badge/storybook/Docs.mdx +2 -2
- package/ui.dropdown-badge/storybook/{stories.js → stories.ts} +16 -5
- package/ui.dropdown-badge/types.ts +93 -0
- package/ui.dropdown-badge/{useAttrs.js → useAttrs.ts} +13 -2
- package/ui.dropdown-button/UDropdownButton.vue +85 -203
- package/ui.dropdown-button/storybook/Docs.mdx +2 -2
- package/ui.dropdown-button/storybook/{stories.js → stories.ts} +25 -11
- package/ui.dropdown-button/types.ts +108 -0
- package/ui.dropdown-button/{useAttrs.js → useAttrs.ts} +14 -3
- package/ui.dropdown-link/UDropdownLink.vue +84 -194
- package/ui.dropdown-link/storybook/Docs.mdx +2 -2
- package/ui.dropdown-link/storybook/{stories.js → stories.ts} +20 -9
- package/ui.dropdown-link/types.ts +103 -0
- package/ui.dropdown-link/{useAttrs.js → useAttrs.ts} +14 -3
- package/ui.dropdown-list/UDropdownList.vue +112 -177
- package/ui.dropdown-list/storybook/Docs.mdx +2 -2
- package/ui.dropdown-list/storybook/{stories.js → stories.ts} +23 -7
- package/ui.dropdown-list/types.ts +52 -0
- package/ui.dropdown-list/{useAttrs.js → useAttrs.ts} +6 -3
- package/ui.dropdown-list/usePointer.ts +111 -0
- package/ui.text-money/UMoney.vue +1 -1
- package/ui.text-money/config.ts +12 -13
- package/web-types.json +117 -55
- package/ui.dropdown-list/usePointer.js +0 -86
- /package/ui.dropdown-badge/{config.js → config.ts} +0 -0
- /package/ui.dropdown-badge/{constants.js → constants.ts} +0 -0
- /package/ui.dropdown-button/{config.js → config.ts} +0 -0
- /package/ui.dropdown-button/{constants.js → constants.ts} +0 -0
- /package/ui.dropdown-link/{config.js → config.ts} +0 -0
- /package/ui.dropdown-link/{constants.js → constants.ts} +0 -0
- /package/ui.dropdown-list/{config.js → config.ts} +0 -0
- /package/ui.dropdown-list/{constants.js → constants.ts} +0 -0
|
@@ -1,103 +1,4 @@
|
|
|
1
|
-
<
|
|
2
|
-
<div
|
|
3
|
-
ref="wrapperRef"
|
|
4
|
-
tabindex="1"
|
|
5
|
-
:style="{ maxHeight: wrapperHeight }"
|
|
6
|
-
v-bind="wrapperAttrs"
|
|
7
|
-
@keydown.self.down.prevent="pointerForward"
|
|
8
|
-
@keydown.self.up.prevent="pointerBackward"
|
|
9
|
-
@keydown.enter.stop.self="addPointerElement"
|
|
10
|
-
>
|
|
11
|
-
<ul :id="`listbox-${elementId}`" v-bind="listAttrs" role="listbox">
|
|
12
|
-
<li
|
|
13
|
-
v-for="(option, index) of options"
|
|
14
|
-
:id="`${elementId}-${index}`"
|
|
15
|
-
:key="index"
|
|
16
|
-
v-bind="listItemAttrs"
|
|
17
|
-
ref="optionsRef"
|
|
18
|
-
:role="!(option && option.groupLabel) ? 'option' : null"
|
|
19
|
-
:data-group-label="Boolean(option.groupLabel)"
|
|
20
|
-
>
|
|
21
|
-
<!-- option title -->
|
|
22
|
-
<span
|
|
23
|
-
v-if="!(option && (option.groupLabel || option.isSubGroup)) && !option.isHidden"
|
|
24
|
-
v-bind="optionAttrs"
|
|
25
|
-
:class="optionHighlight(index, option)"
|
|
26
|
-
@click="select(option), onClickOption(option)"
|
|
27
|
-
@mouseenter.self="pointerSet(index)"
|
|
28
|
-
>
|
|
29
|
-
<!--
|
|
30
|
-
@slot Use it to add something before the option.
|
|
31
|
-
@binding {object} option
|
|
32
|
-
@binding {number} index
|
|
33
|
-
-->
|
|
34
|
-
<slot name="before-option" :option="option" :index="index" />
|
|
35
|
-
|
|
36
|
-
<!--
|
|
37
|
-
@slot Use it to add something instead of the option.
|
|
38
|
-
@binding {object} option
|
|
39
|
-
@binding {number} index
|
|
40
|
-
-->
|
|
41
|
-
<slot name="option" :option="option" :index="index">
|
|
42
|
-
<span
|
|
43
|
-
:style="getMarginForSubCategory(option.level)"
|
|
44
|
-
v-bind="optionContentAttrs"
|
|
45
|
-
v-text="option[labelKey]"
|
|
46
|
-
/>
|
|
47
|
-
</slot>
|
|
48
|
-
|
|
49
|
-
<!--
|
|
50
|
-
@slot Use it to add something after the option.
|
|
51
|
-
@binding {object} option
|
|
52
|
-
@binding {number} index
|
|
53
|
-
-->
|
|
54
|
-
<slot name="after-option" :option="option" :index="index" />
|
|
55
|
-
</span>
|
|
56
|
-
|
|
57
|
-
<!-- group title -->
|
|
58
|
-
<template v-if="option && (option.groupLabel || option.isSubGroup) && !option.isHidden">
|
|
59
|
-
<div v-if="option.groupLabel" v-bind="groupAttrs" v-text="option.groupLabel" />
|
|
60
|
-
|
|
61
|
-
<div
|
|
62
|
-
v-else-if="option.isSubGroup"
|
|
63
|
-
:style="getMarginForSubCategory(option.level)"
|
|
64
|
-
v-bind="subGroupAttrs"
|
|
65
|
-
v-text="option[labelKey]"
|
|
66
|
-
/>
|
|
67
|
-
</template>
|
|
68
|
-
</li>
|
|
69
|
-
|
|
70
|
-
<div v-if="!options.length" v-bind="optionAttrs">
|
|
71
|
-
<!-- @slot Use it to add something instead of empty state. -->
|
|
72
|
-
<slot name="empty">
|
|
73
|
-
<span v-bind="optionContentAttrs" v-text="currentLocale.noDataToShow" />
|
|
74
|
-
</slot>
|
|
75
|
-
</div>
|
|
76
|
-
|
|
77
|
-
<!-- Add button -->
|
|
78
|
-
<template v-if="addOption">
|
|
79
|
-
<div v-bind="addOptionLabelWrapperAttrs" @click="onClickAddOption">
|
|
80
|
-
<div v-bind="addOptionLabelAttrs">
|
|
81
|
-
{{ currentLocale.add }}
|
|
82
|
-
<span v-bind="addOptionLabelHotkeyAttrs" v-text="addOptionKeyCombination" />
|
|
83
|
-
</div>
|
|
84
|
-
</div>
|
|
85
|
-
|
|
86
|
-
<UButton round square v-bind="addOptionButtonAttrs" @click="onClickAddOption">
|
|
87
|
-
<UIcon
|
|
88
|
-
internal
|
|
89
|
-
color="white"
|
|
90
|
-
size="xs"
|
|
91
|
-
:name="config.defaults.addOptionIcon"
|
|
92
|
-
v-bind="addOptionIconAttrs"
|
|
93
|
-
/>
|
|
94
|
-
</UButton>
|
|
95
|
-
</template>
|
|
96
|
-
</ul>
|
|
97
|
-
</div>
|
|
98
|
-
</template>
|
|
99
|
-
|
|
100
|
-
<script setup>
|
|
1
|
+
<script lang="ts" setup>
|
|
101
2
|
import { computed, ref, useId } from "vue";
|
|
102
3
|
import { merge } from "lodash-es";
|
|
103
4
|
|
|
@@ -108,90 +9,25 @@ import { getDefault } from "../utils/ui.ts";
|
|
|
108
9
|
import { isMac } from "../utils/platform.ts";
|
|
109
10
|
|
|
110
11
|
import usePointer from "./usePointer.js";
|
|
111
|
-
import useAttrs from "./useAttrs.
|
|
12
|
+
import useAttrs from "./useAttrs.ts";
|
|
112
13
|
import { useLocale } from "../composables/useLocale.ts";
|
|
113
14
|
|
|
114
|
-
import defaultConfig from "./config.
|
|
115
|
-
import { UDropdownList } from "./constants.
|
|
15
|
+
import defaultConfig from "./config.ts";
|
|
16
|
+
import { UDropdownList } from "./constants.ts";
|
|
17
|
+
|
|
18
|
+
import type { UDropdownListProps } from "./types.ts";
|
|
116
19
|
|
|
117
20
|
defineOptions({ inheritAttrs: false });
|
|
118
21
|
|
|
119
22
|
// TODO: Use props and regular modal value
|
|
120
23
|
const modelValue = defineModel({ type: [String, Number, Object], default: "" });
|
|
121
24
|
|
|
122
|
-
const props = defineProps({
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
default: () => [],
|
|
129
|
-
},
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Label key in the item object of options.
|
|
133
|
-
*/
|
|
134
|
-
labelKey: {
|
|
135
|
-
type: String,
|
|
136
|
-
default: getDefault(defaultConfig, UDropdownList).valueKey,
|
|
137
|
-
},
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Value key in the item object of options.
|
|
141
|
-
*/
|
|
142
|
-
valueKey: {
|
|
143
|
-
type: String,
|
|
144
|
-
default: getDefault(defaultConfig, UDropdownList).valueKey,
|
|
145
|
-
},
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Show add option button.
|
|
149
|
-
*/
|
|
150
|
-
addOption: {
|
|
151
|
-
type: Boolean,
|
|
152
|
-
default: false,
|
|
153
|
-
},
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Disable the list.
|
|
157
|
-
*/
|
|
158
|
-
disabled: {
|
|
159
|
-
type: Boolean,
|
|
160
|
-
default: getDefault(defaultConfig, UDropdownList).disabled,
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* List size.
|
|
165
|
-
* @values sm, md, lg
|
|
166
|
-
*/
|
|
167
|
-
size: {
|
|
168
|
-
type: String,
|
|
169
|
-
default: getDefault(defaultConfig, UDropdownList).size,
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Number of options to show without a scroll.
|
|
174
|
-
*/
|
|
175
|
-
visibleOptions: {
|
|
176
|
-
type: Number,
|
|
177
|
-
default: getDefault(defaultConfig, UDropdownList).visibleOptions,
|
|
178
|
-
},
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Unique element id.
|
|
182
|
-
*/
|
|
183
|
-
id: {
|
|
184
|
-
type: String,
|
|
185
|
-
default: "",
|
|
186
|
-
},
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Component config object.
|
|
190
|
-
*/
|
|
191
|
-
config: {
|
|
192
|
-
type: Object,
|
|
193
|
-
default: () => ({}),
|
|
194
|
-
},
|
|
25
|
+
const props = withDefaults(defineProps<UDropdownListProps>(), {
|
|
26
|
+
labelKey: getDefault<UDropdownListProps>(defaultConfig, UDropdownList).labelKey,
|
|
27
|
+
valueKey: getDefault<UDropdownListProps>(defaultConfig, UDropdownList).valueKey,
|
|
28
|
+
disabled: getDefault<UDropdownListProps>(defaultConfig, UDropdownList).disabled,
|
|
29
|
+
size: getDefault<UDropdownListProps>(defaultConfig, UDropdownList).size,
|
|
30
|
+
visibleOptions: getDefault<UDropdownListProps>(defaultConfig, UDropdownList).visibleOptions,
|
|
195
31
|
});
|
|
196
32
|
|
|
197
33
|
const emit = defineEmits([
|
|
@@ -232,7 +68,7 @@ const {
|
|
|
232
68
|
const { tm } = useLocale();
|
|
233
69
|
|
|
234
70
|
const i18nGlobal = tm(UDropdownList);
|
|
235
|
-
const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props
|
|
71
|
+
const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props?.config?.i18n));
|
|
236
72
|
|
|
237
73
|
const addOptionKeyCombination = computed(() => {
|
|
238
74
|
return isMac ? "(⌘ + Enter)" : "(Ctrl + Enter)";
|
|
@@ -349,3 +185,102 @@ defineExpose({
|
|
|
349
185
|
wrapperRef,
|
|
350
186
|
});
|
|
351
187
|
</script>
|
|
188
|
+
|
|
189
|
+
<template>
|
|
190
|
+
<div
|
|
191
|
+
ref="wrapperRef"
|
|
192
|
+
tabindex="1"
|
|
193
|
+
:style="{ maxHeight: wrapperHeight }"
|
|
194
|
+
v-bind="wrapperAttrs"
|
|
195
|
+
@keydown.self.down.prevent="pointerForward"
|
|
196
|
+
@keydown.self.up.prevent="pointerBackward"
|
|
197
|
+
@keydown.enter.stop.self="addPointerElement"
|
|
198
|
+
>
|
|
199
|
+
<ul :id="`listbox-${elementId}`" v-bind="listAttrs" role="listbox">
|
|
200
|
+
<li
|
|
201
|
+
v-for="(option, index) of options"
|
|
202
|
+
:id="`${elementId}-${index}`"
|
|
203
|
+
:key="index"
|
|
204
|
+
v-bind="listItemAttrs"
|
|
205
|
+
ref="optionsRef"
|
|
206
|
+
:role="!(option && option.groupLabel) ? 'option' : null"
|
|
207
|
+
:data-group-label="Boolean(option.groupLabel)"
|
|
208
|
+
>
|
|
209
|
+
<!-- option title -->
|
|
210
|
+
<span
|
|
211
|
+
v-if="!(option && (option.groupLabel || option.isSubGroup)) && !option.isHidden"
|
|
212
|
+
v-bind="optionAttrs"
|
|
213
|
+
:class="optionHighlight(index, option)"
|
|
214
|
+
@click="select(option), onClickOption(option)"
|
|
215
|
+
@mouseenter.self="pointerSet(index)"
|
|
216
|
+
>
|
|
217
|
+
<!--
|
|
218
|
+
@slot Use it to add something before the option.
|
|
219
|
+
@binding {object} option
|
|
220
|
+
@binding {number} index
|
|
221
|
+
-->
|
|
222
|
+
<slot name="before-option" :option="option" :index="index" />
|
|
223
|
+
|
|
224
|
+
<!--
|
|
225
|
+
@slot Use it to add something instead of the option.
|
|
226
|
+
@binding {object} option
|
|
227
|
+
@binding {number} index
|
|
228
|
+
-->
|
|
229
|
+
<slot name="option" :option="option" :index="index">
|
|
230
|
+
<span
|
|
231
|
+
:style="getMarginForSubCategory(option.level)"
|
|
232
|
+
v-bind="optionContentAttrs"
|
|
233
|
+
v-text="option[labelKey]"
|
|
234
|
+
/>
|
|
235
|
+
</slot>
|
|
236
|
+
|
|
237
|
+
<!--
|
|
238
|
+
@slot Use it to add something after the option.
|
|
239
|
+
@binding {object} option
|
|
240
|
+
@binding {number} index
|
|
241
|
+
-->
|
|
242
|
+
<slot name="after-option" :option="option" :index="index" />
|
|
243
|
+
</span>
|
|
244
|
+
|
|
245
|
+
<!-- group title -->
|
|
246
|
+
<template v-if="option && (option.groupLabel || option.isSubGroup) && !option.isHidden">
|
|
247
|
+
<div v-if="option.groupLabel" v-bind="groupAttrs" v-text="option.groupLabel" />
|
|
248
|
+
|
|
249
|
+
<div
|
|
250
|
+
v-else-if="option.isSubGroup"
|
|
251
|
+
:style="getMarginForSubCategory(option.level)"
|
|
252
|
+
v-bind="subGroupAttrs"
|
|
253
|
+
v-text="option[labelKey]"
|
|
254
|
+
/>
|
|
255
|
+
</template>
|
|
256
|
+
</li>
|
|
257
|
+
|
|
258
|
+
<div v-if="!options.length" v-bind="optionAttrs">
|
|
259
|
+
<!-- @slot Use it to add something instead of empty state. -->
|
|
260
|
+
<slot name="empty">
|
|
261
|
+
<span v-bind="optionContentAttrs" v-text="currentLocale.noDataToShow" />
|
|
262
|
+
</slot>
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
<!-- Add button -->
|
|
266
|
+
<template v-if="addOption">
|
|
267
|
+
<div v-bind="addOptionLabelWrapperAttrs" @click="onClickAddOption">
|
|
268
|
+
<div v-bind="addOptionLabelAttrs">
|
|
269
|
+
{{ currentLocale.add }}
|
|
270
|
+
<span v-bind="addOptionLabelHotkeyAttrs" v-text="addOptionKeyCombination" />
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
|
|
274
|
+
<UButton round square v-bind="addOptionButtonAttrs" @click="onClickAddOption">
|
|
275
|
+
<UIcon
|
|
276
|
+
internal
|
|
277
|
+
color="white"
|
|
278
|
+
size="xs"
|
|
279
|
+
:name="config.defaults.addOptionIcon"
|
|
280
|
+
v-bind="addOptionIconAttrs"
|
|
281
|
+
/>
|
|
282
|
+
</UButton>
|
|
283
|
+
</template>
|
|
284
|
+
</ul>
|
|
285
|
+
</div>
|
|
286
|
+
</template>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source } from "@storybook/blocks";
|
|
2
2
|
import { getSource } from "../../utils/storybook.ts";
|
|
3
3
|
|
|
4
|
-
import * as stories from "./stories.
|
|
5
|
-
import defaultConfig from "../config.
|
|
4
|
+
import * as stories from "./stories.ts";
|
|
5
|
+
import defaultConfig from "../config.ts?raw"
|
|
6
6
|
|
|
7
7
|
<Meta of={stories} />
|
|
8
8
|
<Title of={stories} />
|
|
@@ -3,6 +3,15 @@ import { getArgTypes, getSlotNames, getSlotsFragment } from "../../utils/storybo
|
|
|
3
3
|
import UDropdownList from "../../ui.dropdown-list/UDropdownList.vue";
|
|
4
4
|
import URow from "../../ui.container-row/URow.vue";
|
|
5
5
|
|
|
6
|
+
import type { Meta, StoryFn } from "@storybook/vue3";
|
|
7
|
+
import type { UDropdownListProps } from "../types.ts";
|
|
8
|
+
|
|
9
|
+
interface UDropdownListArgs extends UDropdownListProps {
|
|
10
|
+
slotTemplate?: string;
|
|
11
|
+
enum: "size";
|
|
12
|
+
maxHeight: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
6
15
|
/**
|
|
7
16
|
* The `UDropdownList` component. | [View on GitHub](https://github.com/vuelessjs/vueless/tree/main/src/ui.dropdown-list)
|
|
8
17
|
*/
|
|
@@ -27,9 +36,9 @@ export default {
|
|
|
27
36
|
},
|
|
28
37
|
},
|
|
29
38
|
},
|
|
30
|
-
};
|
|
39
|
+
} as Meta;
|
|
31
40
|
|
|
32
|
-
const DefaultTemplate = (args) => ({
|
|
41
|
+
const DefaultTemplate: StoryFn<UDropdownListArgs> = (args: UDropdownListArgs) => ({
|
|
33
42
|
components: { UDropdownList },
|
|
34
43
|
setup() {
|
|
35
44
|
const slots = getSlotNames(UDropdownList.__name);
|
|
@@ -38,17 +47,20 @@ const DefaultTemplate = (args) => ({
|
|
|
38
47
|
},
|
|
39
48
|
template: `
|
|
40
49
|
<UDropdownList v-bind="args" class="mx-4 w-[24rem]">
|
|
41
|
-
${args.slotTemplate || getSlotsFragment()}
|
|
50
|
+
${args.slotTemplate || getSlotsFragment("")}
|
|
42
51
|
</UDropdownList>
|
|
43
52
|
`,
|
|
44
53
|
});
|
|
45
54
|
|
|
46
|
-
const EnumVariantTemplate = (
|
|
55
|
+
const EnumVariantTemplate: StoryFn<UDropdownListArgs> = (
|
|
56
|
+
args: UDropdownListArgs,
|
|
57
|
+
{ argTypes },
|
|
58
|
+
) => ({
|
|
47
59
|
components: { UDropdownList, URow },
|
|
48
60
|
setup() {
|
|
49
61
|
return {
|
|
50
62
|
args,
|
|
51
|
-
options: argTypes[args.enum]
|
|
63
|
+
options: argTypes?.[args.enum]?.options,
|
|
52
64
|
};
|
|
53
65
|
},
|
|
54
66
|
template: `
|
|
@@ -82,7 +94,11 @@ OptionSettings.args = {
|
|
|
82
94
|
options: [
|
|
83
95
|
{ label: "option 1", id: "1" },
|
|
84
96
|
{ label: "option 2", id: "2", isHidden: true },
|
|
85
|
-
|
|
86
|
-
{
|
|
97
|
+
|
|
98
|
+
{
|
|
99
|
+
label: "option 3",
|
|
100
|
+
id: "3",
|
|
101
|
+
onClick: (option: object) => alert("onClick option 3 " + JSON.stringify(option)),
|
|
102
|
+
},
|
|
87
103
|
],
|
|
88
104
|
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import defaultConfig from "./config.ts";
|
|
2
|
+
|
|
3
|
+
import type { UnknownObject } from "../types.ts";
|
|
4
|
+
|
|
5
|
+
export type Config = Partial<typeof defaultConfig>;
|
|
6
|
+
|
|
7
|
+
export interface UDropdownListProps {
|
|
8
|
+
/**
|
|
9
|
+
* List of options.
|
|
10
|
+
*/
|
|
11
|
+
options?: UnknownObject[];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Label key in the item object of options.
|
|
15
|
+
*/
|
|
16
|
+
labelKey?: string;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Value key in the item object of options.
|
|
20
|
+
*/
|
|
21
|
+
valueKey?: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Show add option button.
|
|
25
|
+
*/
|
|
26
|
+
addOption?: boolean;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Disable the list.
|
|
30
|
+
*/
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* List size.
|
|
35
|
+
*/
|
|
36
|
+
size?: "sm" | "md" | "lg";
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Number of options to show without a scroll.
|
|
40
|
+
*/
|
|
41
|
+
visibleOptions?: number;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Unique element id.
|
|
45
|
+
*/
|
|
46
|
+
id?: string;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Component config object.
|
|
50
|
+
*/
|
|
51
|
+
config?: Partial<typeof defaultConfig>;
|
|
52
|
+
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
2
|
import useUI from "../composables/useUI.ts";
|
|
3
3
|
|
|
4
|
-
import defaultConfig from "./config.
|
|
4
|
+
import defaultConfig from "./config.ts";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
import type { UseAttrs } from "../types.ts";
|
|
7
|
+
import type { UDropdownListProps, Config } from "./types.ts";
|
|
8
|
+
|
|
9
|
+
export default function useAttrs(props: UDropdownListProps): UseAttrs<Config> {
|
|
10
|
+
const { config, getKeysAttrs, hasSlotContent, getExtendingKeysClasses } = useUI<Config>(
|
|
8
11
|
defaultConfig,
|
|
9
12
|
() => props.config,
|
|
10
13
|
);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { ref, computed, toValue } from "vue";
|
|
2
|
+
import type { Ref } from "vue";
|
|
3
|
+
|
|
4
|
+
interface Option {
|
|
5
|
+
isSubGroup?: boolean;
|
|
6
|
+
groupLabel?: string;
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default function usePointer(
|
|
11
|
+
options: Option[],
|
|
12
|
+
optionElements: Ref<HTMLElement[]>,
|
|
13
|
+
listWrapperElement: Ref<HTMLElement | null>,
|
|
14
|
+
) {
|
|
15
|
+
const pointer = ref<number | null>(null);
|
|
16
|
+
const pointerDirty = ref<boolean>(false);
|
|
17
|
+
|
|
18
|
+
const activeElementHeight = computed<number>(() => {
|
|
19
|
+
if (pointer.value === null) return 0;
|
|
20
|
+
const element = toValue(optionElements)[pointer.value];
|
|
21
|
+
const isGroupLabel = element.dataset.groupLabel;
|
|
22
|
+
const groupIndex = 2;
|
|
23
|
+
|
|
24
|
+
if (isGroupLabel) {
|
|
25
|
+
return toValue(optionElements)[pointer.value - groupIndex].getBoundingClientRect().height;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return element.getBoundingClientRect().height;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const pointerPosition = computed<number>(() => {
|
|
32
|
+
return (pointer.value !== null ? pointer.value : 0) * activeElementHeight.value || 0;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
function scrollWrapperToElement() {
|
|
36
|
+
if (!listWrapperElement.value) return;
|
|
37
|
+
const visibleElements =
|
|
38
|
+
listWrapperElement.value.getBoundingClientRect().height / activeElementHeight.value;
|
|
39
|
+
const currentElement = visibleElements - 1;
|
|
40
|
+
const currentPointerPosition =
|
|
41
|
+
pointerPosition.value - currentElement * activeElementHeight.value;
|
|
42
|
+
|
|
43
|
+
if (listWrapperElement.value.scrollTop <= currentPointerPosition) {
|
|
44
|
+
listWrapperElement.value.scrollTop = currentPointerPosition;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function pointerForward() {
|
|
49
|
+
if (pointer.value === null) pointer.value = 0;
|
|
50
|
+
|
|
51
|
+
if (pointer.value < options.length - 1) {
|
|
52
|
+
pointer.value++;
|
|
53
|
+
|
|
54
|
+
const isGroup = options[pointer.value]?.isSubGroup || options[pointer.value]?.groupLabel;
|
|
55
|
+
|
|
56
|
+
if (listWrapperElement.value) scrollWrapperToElement();
|
|
57
|
+
|
|
58
|
+
if (options[pointer.value] && isGroup) {
|
|
59
|
+
pointerForward();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pointerDirty.value = true;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function pointerBackward() {
|
|
67
|
+
if (pointer.value === null) pointer.value = 0;
|
|
68
|
+
|
|
69
|
+
if (pointer.value > 0) {
|
|
70
|
+
pointer.value--;
|
|
71
|
+
|
|
72
|
+
const isGroup = options[pointer.value]?.isSubGroup || options[pointer.value]?.groupLabel;
|
|
73
|
+
|
|
74
|
+
if (listWrapperElement.value && listWrapperElement.value.scrollTop >= pointerPosition.value) {
|
|
75
|
+
listWrapperElement.value.scrollTop = pointerPosition.value;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (options[pointer.value] && isGroup) {
|
|
79
|
+
pointerBackward();
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
if (options[0]?.groupLabel) {
|
|
83
|
+
pointerForward();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
pointerDirty.value = true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function pointerSet(index: number) {
|
|
91
|
+
pointer.value = index;
|
|
92
|
+
pointerDirty.value = true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function pointerReset() {
|
|
96
|
+
pointer.value = 0;
|
|
97
|
+
|
|
98
|
+
if (listWrapperElement.value) {
|
|
99
|
+
listWrapperElement.value.scrollTop = 0;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
pointer,
|
|
105
|
+
pointerDirty,
|
|
106
|
+
pointerSet,
|
|
107
|
+
pointerReset,
|
|
108
|
+
pointerBackward,
|
|
109
|
+
pointerForward,
|
|
110
|
+
};
|
|
111
|
+
}
|
package/ui.text-money/UMoney.vue
CHANGED
package/ui.text-money/config.ts
CHANGED
|
@@ -17,13 +17,13 @@ export default /*tw*/ {
|
|
|
17
17
|
sum: {
|
|
18
18
|
variants: {
|
|
19
19
|
size: {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"
|
|
26
|
-
"
|
|
20
|
+
xs: "text-xs",
|
|
21
|
+
sm: "text-sm",
|
|
22
|
+
md: "text-base",
|
|
23
|
+
lg: "text-lg",
|
|
24
|
+
xl: "text-xl",
|
|
25
|
+
"2xl": "text-2xl",
|
|
26
|
+
"3xl": "text-3xl",
|
|
27
27
|
},
|
|
28
28
|
planned: {
|
|
29
29
|
true: "opacity-75 before:content-['('] after:content-[')']",
|
|
@@ -38,12 +38,11 @@ export default /*tw*/ {
|
|
|
38
38
|
size: {
|
|
39
39
|
xs: "text-2xs",
|
|
40
40
|
sm: "text-xs",
|
|
41
|
-
md: "text-
|
|
42
|
-
lg: "text-
|
|
43
|
-
xl: "text-
|
|
44
|
-
"2xl": "text-
|
|
45
|
-
"3xl": "text-
|
|
46
|
-
"4xl": "text-2xl",
|
|
41
|
+
md: "text-sm",
|
|
42
|
+
lg: "text-base",
|
|
43
|
+
xl: "text-lg",
|
|
44
|
+
"2xl": "text-xl",
|
|
45
|
+
"3xl": "text-2xl",
|
|
47
46
|
},
|
|
48
47
|
},
|
|
49
48
|
},
|