Skip to content

Commit f6535bf

Browse files
authored
feat(packages): ui: add tags-input (#57)
1 parent c02034a commit f6535bf

File tree

13 files changed

+345
-0
lines changed

13 files changed

+345
-0
lines changed

packages/ui/src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export * from './skeleton';
3838
export * from './slider';
3939
export * from './switch';
4040
export * from './tabs';
41+
export * from './tags-input';
4142
export * from './textarea';
4243
export * from './toast';
4344
export * from './toggle';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import STagsInputRoot from './tags-input-root.vue';
2+
import STagsInputInput from './tags-input-input.vue';
3+
import STagsInputItem from './tags-input-item.vue';
4+
import STagsInputItemText from './tags-input-item-text.vue';
5+
import STagsInputItemDelete from './tags-input-item-delete.vue';
6+
import STagsInput from './tags-input.vue';
7+
8+
export { STagsInputRoot, STagsInputInput, STagsInputItem, STagsInputItemText, STagsInputItemDelete, STagsInput };
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue';
3+
import { TagsInputInput } from '@soybean-ui/primitives';
4+
import { cn, tagsInputVariants } from '@soybean-ui/variants';
5+
import type { TagsInputInputProps } from './types';
6+
7+
defineOptions({
8+
name: 'STagsInputInput'
9+
});
10+
11+
const { class: cls, size, ...delegatedProps } = defineProps<TagsInputInputProps>();
12+
13+
const mergedCls = computed(() => {
14+
const { input } = tagsInputVariants({ size });
15+
16+
return cn(input(), cls);
17+
});
18+
</script>
19+
20+
<template>
21+
<TagsInputInput v-bind="delegatedProps" :class="mergedCls">
22+
<slot />
23+
</TagsInputInput>
24+
</template>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue';
3+
import { Slot, TagsInputItemDelete } from '@soybean-ui/primitives';
4+
import { cn, tagsInputVariants } from '@soybean-ui/variants';
5+
import { X } from 'lucide-vue-next';
6+
import type { TagsInputItemDeleteProps } from './types';
7+
8+
defineOptions({
9+
name: 'STagsInputItemDelete'
10+
});
11+
12+
const { class: cls, size, iconClass } = defineProps<TagsInputItemDeleteProps>();
13+
14+
const mergedCls = computed(() => {
15+
const { itemDelete, itemDeleteIcon } = tagsInputVariants({ size });
16+
17+
return {
18+
cls: cn(itemDelete(), cls),
19+
icon: cn(itemDeleteIcon(), iconClass)
20+
};
21+
});
22+
</script>
23+
24+
<template>
25+
<TagsInputItemDelete :class="mergedCls.cls">
26+
<Slot :class="mergedCls.icon">
27+
<slot>
28+
<X />
29+
</slot>
30+
</Slot>
31+
</TagsInputItemDelete>
32+
</template>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue';
3+
import { TagsInputItemText } from '@soybean-ui/primitives';
4+
import { cn, tagsInputVariants } from '@soybean-ui/variants';
5+
import type { TagsInputItemTextProps } from './types';
6+
7+
defineOptions({
8+
name: 'STagsInputItemText'
9+
});
10+
11+
const { class: cls, size } = defineProps<TagsInputItemTextProps>();
12+
13+
const mergedCls = computed(() => {
14+
const { itemText } = tagsInputVariants({ size });
15+
16+
return cn(itemText(), cls);
17+
});
18+
</script>
19+
20+
<template>
21+
<TagsInputItemText :class="mergedCls">
22+
<slot />
23+
</TagsInputItemText>
24+
</template>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script setup lang="ts">
2+
import { computed } from 'vue';
3+
import { TagsInputItem } from '@soybean-ui/primitives';
4+
import { cn, tagsInputVariants } from '@soybean-ui/variants';
5+
import type { TagsInputItemProps } from './types';
6+
7+
defineOptions({
8+
name: 'STagsInputItem'
9+
});
10+
11+
const { class: cls, size, ...delegatedProps } = defineProps<TagsInputItemProps>();
12+
13+
const mergedCls = computed(() => {
14+
const { item } = tagsInputVariants({ size });
15+
16+
return cn(item(), cls);
17+
});
18+
</script>
19+
20+
<template>
21+
<TagsInputItem v-bind="delegatedProps" :class="mergedCls">
22+
<slot />
23+
</TagsInputItem>
24+
</template>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<script setup lang="ts" generic="T extends AcceptableInputValue = AcceptableInputValue">
2+
import { computed } from 'vue';
3+
import { TagsInputRoot, useForwardPropsEmits } from '@soybean-ui/primitives';
4+
import type { AcceptableInputValue } from '@soybean-ui/primitives';
5+
import { cn, tagsInputVariants } from '@soybean-ui/variants';
6+
import type { TagsInputRootEmits, TagsInputRootProps } from './types';
7+
8+
defineOptions({
9+
name: 'STagsInputRoot'
10+
});
11+
12+
const { class: cls, size, ...delegatedProps } = defineProps<TagsInputRootProps<T>>();
13+
14+
const emit = defineEmits<TagsInputRootEmits<T>>();
15+
16+
const mergedCls = computed(() => {
17+
const { root } = tagsInputVariants({ size });
18+
19+
return cn(root(), cls);
20+
});
21+
22+
const forwarded = useForwardPropsEmits(delegatedProps, emit);
23+
</script>
24+
25+
<template>
26+
<TagsInputRoot v-bind="forwarded" :class="mergedCls">
27+
<slot />
28+
</TagsInputRoot>
29+
</template>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<script setup lang="ts" generic="T extends AcceptableInputValue = AcceptableInputValue">
2+
import { useForwardPropsEmits } from '@soybean-ui/primitives';
3+
import type { AcceptableInputValue } from '@soybean-ui/primitives';
4+
import STagsInputRoot from './tags-input-root.vue';
5+
import STagsInputInput from './tags-input-input.vue';
6+
import STagsInputItem from './tags-input-item.vue';
7+
import STagsInputItemText from './tags-input-item-text.vue';
8+
import STagsInputItemDelete from './tags-input-item-delete.vue';
9+
import type { TagsInputEmits, TagsInputProps } from './types';
10+
11+
defineOptions({
12+
name: 'STagsInput'
13+
});
14+
15+
const {
16+
class: cls,
17+
ui,
18+
disabledValue,
19+
placeholder,
20+
autoFocus,
21+
maxLength,
22+
...delegatedProps
23+
} = defineProps<TagsInputProps<T>>();
24+
25+
const emit = defineEmits<TagsInputEmits<T>>();
26+
27+
const forwarded = useForwardPropsEmits(delegatedProps, emit);
28+
</script>
29+
30+
<template>
31+
<STagsInputRoot v-bind="forwarded" :class="cls || ui?.root">
32+
<template v-for="item in modelValue" :key="item">
33+
<slot name="item" :value="item">
34+
<STagsInputItem
35+
:class="ui?.item"
36+
:size="size"
37+
:value="item"
38+
:disabled="disabled || disabledValue?.includes(item)"
39+
>
40+
<STagsInputItemText :class="ui?.itemText" :size="size" />
41+
<STagsInputItemDelete :class="ui?.itemDelete" :icon-class="ui?.itemDeleteIcon" :size="size">
42+
<slot name="item-delete-icon" :value="item" />
43+
</STagsInputItemDelete>
44+
</STagsInputItem>
45+
</slot>
46+
</template>
47+
<STagsInputInput
48+
:class="ui?.input"
49+
:placeholder="placeholder"
50+
:auto-focus="autoFocus"
51+
:max-length="maxLength"
52+
:size="size"
53+
/>
54+
</STagsInputRoot>
55+
</template>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import type {
2+
AcceptableInputValue,
3+
ClassValue,
4+
TagsInputRootEmits,
5+
TagsInputInputProps as _TagsInputInputProps,
6+
TagsInputItemDeleteProps as _TagsInputItemDeleteProps,
7+
TagsInputItemProps as _TagsInputItemProps,
8+
TagsInputItemTextProps as _TagsInputItemTextProps,
9+
TagsInputRootProps as _TagsInputRootProps
10+
} from '@soybean-ui/primitives';
11+
import type { TagsInputSlots, ThemeSize } from '@soybean-ui/variants';
12+
13+
export interface TagsInputRootProps<T extends AcceptableInputValue> extends _TagsInputRootProps<T> {
14+
size?: ThemeSize;
15+
}
16+
17+
export interface TagsInputInputProps extends _TagsInputInputProps {
18+
size?: ThemeSize;
19+
}
20+
21+
export interface TagsInputItemProps extends _TagsInputItemProps {
22+
size?: ThemeSize;
23+
}
24+
25+
export interface TagsInputItemTextProps extends _TagsInputItemTextProps {
26+
size?: ThemeSize;
27+
}
28+
29+
export interface TagsInputItemDeleteProps extends _TagsInputItemDeleteProps {
30+
size?: ThemeSize;
31+
iconClass?: ClassValue;
32+
}
33+
34+
export type TagsInputUi = Partial<Record<TagsInputSlots, ClassValue>>;
35+
36+
export interface TagsInputProps<T extends AcceptableInputValue> extends TagsInputRootProps<T>, TagsInputInputProps {
37+
disabledValue?: T[];
38+
ui?: TagsInputUi;
39+
}
40+
41+
export type TagsInputEmits<T extends AcceptableInputValue> = TagsInputRootEmits<T>;
42+
43+
export type { TagsInputRootEmits };

packages/variants/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export * from './variants/skeleton';
3636
export * from './variants/slider';
3737
export * from './variants/switch';
3838
export * from './variants/tabs';
39+
export * from './variants/tags-input';
3940
export * from './variants/textarea';
4041
export * from './variants/toast';
4142
export * from './variants/toggle';

0 commit comments

Comments
 (0)