@soft-stech/bootsman-ui-shadcn 1.5.5 → 1.5.7
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/dist/BuiCommandNewItem.vue_vue_type_script_setup_true_lang-1gIGF9Wo.js +34 -0
- package/dist/components/ui/command/BuiCommandNewItem.js +4 -0
- package/dist/components/ui/command/BuiCommandNewItem.vue.d.ts +20 -0
- package/dist/components/ui/command/index.d.ts +1 -0
- package/dist/components/ui/command/index.js +4 -2
- package/dist/components/ui/tabs/index.js +17 -17
- package/dist/index.js +312 -310
- package/dist/style.css +1 -1
- package/dist/tailwind-preset.js +3 -1
- package/package.json +1 -1
- package/src/assets/variables.css +5 -1
- package/src/components/stories/BuiCombobox.story.vue +121 -4
- package/src/components/stories/BuiTabs.story.vue +13 -5
- package/src/components/ui/command/BuiCommandNewItem.vue +32 -0
- package/src/components/ui/command/index.ts +1 -0
- package/src/components/ui/tabs/BuiTabsTrigger.vue +1 -1
- package/src/components/ui/tabs/index.ts +6 -5
- package/src/tailwind-preset.ts +3 -1
@@ -1,7 +1,6 @@
|
|
1
1
|
<script setup lang="ts">
|
2
2
|
import { ref } from 'vue'
|
3
3
|
import { z } from 'zod'
|
4
|
-
|
5
4
|
import { cn } from '@/lib/utils'
|
6
5
|
import { BuiButton } from '@/components/ui/button'
|
7
6
|
import {
|
@@ -10,10 +9,11 @@ import {
|
|
10
9
|
BuiCommandGroup,
|
11
10
|
BuiCommandInput,
|
12
11
|
BuiCommandItem,
|
13
|
-
BuiCommandList
|
12
|
+
BuiCommandList,
|
13
|
+
BuiCommandNewItem
|
14
14
|
} from '@/components/ui/command'
|
15
15
|
import { BuiPopover, BuiPopoverContent, BuiPopoverTrigger } from '@/components/ui/popover'
|
16
|
-
import { CheckIcon, ChevronsUpDownIcon, ChevronDown } from 'lucide-vue-next'
|
16
|
+
import { CheckIcon, ChevronsUpDownIcon, ChevronDown, CirclePlusIcon } from 'lucide-vue-next'
|
17
17
|
import {
|
18
18
|
BuiForm,
|
19
19
|
BuiFormField,
|
@@ -34,14 +34,18 @@ const frameworks = [
|
|
34
34
|
|
35
35
|
const open = ref(false)
|
36
36
|
const value = ref<string>('')
|
37
|
+
const search = ref<string>('')
|
37
38
|
|
38
39
|
const formSchema = toTypedSchema(
|
39
40
|
z.object({
|
40
|
-
namespace: z.string().min(2)
|
41
|
+
namespace: z.string().min(2),
|
42
|
+
groups: z.array(z.string())
|
41
43
|
})
|
42
44
|
)
|
43
45
|
const isNamespacesPopoverOpen = ref(false)
|
46
|
+
const isGroupsPopoverOpen = ref(false)
|
44
47
|
const namespaces = ['default', 'local', 'my-namespace']
|
48
|
+
const existingGroups = ref(['group-1', 'group-2', 'group-3'])
|
45
49
|
|
46
50
|
// const filterFunction = (list: typeof frameworks, search: string) => list.filter(i => i.value.toLowerCase().includes(search.toLowerCase()))
|
47
51
|
</script>
|
@@ -178,5 +182,118 @@ const namespaces = ['default', 'local', 'my-namespace']
|
|
178
182
|
</BuiForm>
|
179
183
|
</div>
|
180
184
|
</Variant>
|
185
|
+
|
186
|
+
<Variant key="multi-with-create" title="Multiselect + create">
|
187
|
+
<div class="p-4">
|
188
|
+
<BuiForm :validation-schema="formSchema" :initial-values="{ groups: ['group-1'] }">
|
189
|
+
<BuiFormField name="groups" v-slot="{ meta, validate, value, setValue }">
|
190
|
+
<BuiFormItem class="w-full">
|
191
|
+
<BuiLabel :for="`groups`" class="flex gap-2">
|
192
|
+
<div class="flex">Groups</div>
|
193
|
+
</BuiLabel>
|
194
|
+
|
195
|
+
<BuiPopover
|
196
|
+
v-model:open="isGroupsPopoverOpen"
|
197
|
+
@update:open="
|
198
|
+
(isOpen) => {
|
199
|
+
if (!isOpen) {
|
200
|
+
validate()
|
201
|
+
}
|
202
|
+
}
|
203
|
+
"
|
204
|
+
>
|
205
|
+
<BuiPopoverTrigger as-child :id="`groups`">
|
206
|
+
<BuiButton
|
207
|
+
variant="outline"
|
208
|
+
size="lg"
|
209
|
+
role="combobox"
|
210
|
+
:aria-expanded="isGroupsPopoverOpen"
|
211
|
+
class="flex h-10 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-background px-3 py-2 text-sm text-inherit ring-offset-background placeholder:text-muted-foreground hover:bg-transparent focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 active:bg-transparent active:outline-none active:ring-0 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:min-w-0 [&>span]:truncate"
|
212
|
+
:class="!meta.valid && meta.validated ? '!border-destructive-foreground' : ''"
|
213
|
+
>
|
214
|
+
<span>
|
215
|
+
{{ value.length ? value.join(', ') : 'Select multiple or add' }}
|
216
|
+
</span>
|
217
|
+
<ChevronDown class="h-4 w-4 flex-shrink-0 opacity-50" />
|
218
|
+
</BuiButton>
|
219
|
+
</BuiPopoverTrigger>
|
220
|
+
|
221
|
+
<BuiPopoverContent class="w-[var(--radix-popper-anchor-width)] p-0">
|
222
|
+
<BuiCommand class="p-0">
|
223
|
+
<BuiCommandInput
|
224
|
+
class="h-9"
|
225
|
+
placeholder="Search or create new"
|
226
|
+
v-model="search"
|
227
|
+
@input="(event: Event) => (search = (event.target as HTMLInputElement).value)"
|
228
|
+
/>
|
229
|
+
<BuiCommandEmpty class="flex w-full py-1 pl-1">
|
230
|
+
<BuiCommandNewItem
|
231
|
+
v-if="search"
|
232
|
+
@create="
|
233
|
+
() => {
|
234
|
+
setValue([...value, search])
|
235
|
+
existingGroups = [...existingGroups, search]
|
236
|
+
search = ''
|
237
|
+
isGroupsPopoverOpen = false
|
238
|
+
}
|
239
|
+
"
|
240
|
+
>
|
241
|
+
<CirclePlusIcon class="mr-2 h-4 w-4" />
|
242
|
+
<span>Create "{{ search }}"</span>
|
243
|
+
</BuiCommandNewItem>
|
244
|
+
</BuiCommandEmpty>
|
245
|
+
<BuiFormControl>
|
246
|
+
<BuiCommandList>
|
247
|
+
<BuiCommandGroup>
|
248
|
+
<BuiCommandNewItem
|
249
|
+
v-if="search"
|
250
|
+
@create="
|
251
|
+
() => {
|
252
|
+
setValue([...value, search])
|
253
|
+
existingGroups = [...existingGroups, search]
|
254
|
+
search = ''
|
255
|
+
isGroupsPopoverOpen = false
|
256
|
+
}
|
257
|
+
"
|
258
|
+
>
|
259
|
+
<CirclePlusIcon class="mr-2 h-4 w-4" />
|
260
|
+
<span>Create "{{ search }}"</span>
|
261
|
+
</BuiCommandNewItem>
|
262
|
+
|
263
|
+
<BuiCommandItem
|
264
|
+
v-for="element in existingGroups"
|
265
|
+
:value="element"
|
266
|
+
:key="element"
|
267
|
+
@select="
|
268
|
+
() => {
|
269
|
+
if (value.includes(element)) {
|
270
|
+
setValue(value.filter((item: string) => item !== element))
|
271
|
+
} else {
|
272
|
+
setValue([...value, element])
|
273
|
+
}
|
274
|
+
|
275
|
+
isGroupsPopoverOpen = false
|
276
|
+
}
|
277
|
+
"
|
278
|
+
>
|
279
|
+
<CheckIcon
|
280
|
+
class="mr-2 h-4 w-4"
|
281
|
+
:class="value.includes(element) ? 'opacity-100' : 'opacity-0'"
|
282
|
+
/>
|
283
|
+
{{ element }}
|
284
|
+
</BuiCommandItem>
|
285
|
+
</BuiCommandGroup>
|
286
|
+
</BuiCommandList>
|
287
|
+
</BuiFormControl>
|
288
|
+
</BuiCommand>
|
289
|
+
</BuiPopoverContent>
|
290
|
+
|
291
|
+
<BuiFormMessage />
|
292
|
+
</BuiPopover>
|
293
|
+
</BuiFormItem>
|
294
|
+
</BuiFormField>
|
295
|
+
</BuiForm>
|
296
|
+
</div>
|
297
|
+
</Variant>
|
181
298
|
</Story>
|
182
299
|
</template>
|
@@ -80,14 +80,22 @@ const variantOptions = ['default', 'ghost'] as const
|
|
80
80
|
|
81
81
|
<Variant title="vertical">
|
82
82
|
<BuiTabs default-value="general" class="flex" orientation="vertical">
|
83
|
-
<BuiTabsList
|
83
|
+
<BuiTabsList variant="vertical">
|
84
84
|
<BuiTabsTrigger value="general" variant="vertical">General</BuiTabsTrigger>
|
85
85
|
<BuiTabsTrigger value="health" variant="vertical">Health check</BuiTabsTrigger>
|
86
|
-
<BuiTabsTrigger value="resources" variant="vertical">
|
86
|
+
<BuiTabsTrigger value="resources" variant="vertical">
|
87
|
+
A Very Very Veeeeeery Long Label For Resources
|
88
|
+
</BuiTabsTrigger>
|
87
89
|
</BuiTabsList>
|
88
|
-
<BuiTabsContent value="general" class="mt-0 flex-grow
|
89
|
-
|
90
|
-
|
90
|
+
<BuiTabsContent value="general" class="mt-0 flex-grow bg-background p-2">
|
91
|
+
General content
|
92
|
+
</BuiTabsContent>
|
93
|
+
<BuiTabsContent value="health" class="mt-0 bg-background p-2">
|
94
|
+
Health check content
|
95
|
+
</BuiTabsContent>
|
96
|
+
<BuiTabsContent value="resources" class="mt-0 bg-background p-2">
|
97
|
+
Resources content
|
98
|
+
</BuiTabsContent>
|
91
99
|
</BuiTabs>
|
92
100
|
</Variant>
|
93
101
|
</Story>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<script setup lang="ts">
|
2
|
+
import BuiButton from '@/components/ui/button/BuiButton.vue'
|
3
|
+
import { cn } from '@/lib/utils'
|
4
|
+
|
5
|
+
const emit = defineEmits(['create'])
|
6
|
+
|
7
|
+
function handleClick() {
|
8
|
+
emit('create')
|
9
|
+
}
|
10
|
+
|
11
|
+
function handleKeydown(event: KeyboardEvent) {
|
12
|
+
if (event.key === 'Enter') {
|
13
|
+
emit('create')
|
14
|
+
}
|
15
|
+
}
|
16
|
+
</script>
|
17
|
+
|
18
|
+
<template>
|
19
|
+
<BuiButton
|
20
|
+
variant="none"
|
21
|
+
@click="handleClick"
|
22
|
+
@keydown="handleKeydown"
|
23
|
+
:class="
|
24
|
+
cn(
|
25
|
+
'w-full justify-start px-2 py-1.5 text-left text-primary focus:outline-none',
|
26
|
+
'hover:bg-accent/[0.08] focus:!bg-accent/[0.08]'
|
27
|
+
)
|
28
|
+
"
|
29
|
+
>
|
30
|
+
<slot />
|
31
|
+
</BuiButton>
|
32
|
+
</template>
|
@@ -7,3 +7,4 @@ export { default as BuiCommandItem } from './BuiCommandItem.vue'
|
|
7
7
|
export { default as BuiCommandList } from './BuiCommandList.vue'
|
8
8
|
export { default as BuiCommandSeparator } from './BuiCommandSeparator.vue'
|
9
9
|
export { default as BuiCommandShortcut } from './BuiCommandShortcut.vue'
|
10
|
+
export { default as BuiCommandNewItem } from './BuiCommandNewItem.vue'
|
@@ -13,7 +13,7 @@ const props = defineProps<Props>()
|
|
13
13
|
|
14
14
|
<template>
|
15
15
|
<TabsTrigger v-bind="props" :class="cn(tabsTriggerVariants({ variant }), props.class ?? '')">
|
16
|
-
<div class="flex items-center">
|
16
|
+
<div class="flex items-center text-left">
|
17
17
|
<slot />
|
18
18
|
</div>
|
19
19
|
</TabsTrigger>
|
@@ -10,7 +10,8 @@ export const tabsListVariants = cva('inline-flex items-center justify-center rou
|
|
10
10
|
variant: {
|
11
11
|
default: 'bg-muted text-muted-foreground p-0',
|
12
12
|
ghost: 'bg-background bg-text-foreground',
|
13
|
-
vertical:
|
13
|
+
vertical:
|
14
|
+
'w-[17.5rem] shrink-0 bg-tabs-sidebar text-muted-foreground p-0 flex flex-col justify-start rounded-none shadow-tab-sidebar-shadow'
|
14
15
|
}
|
15
16
|
},
|
16
17
|
defaultVariants: {
|
@@ -19,16 +20,16 @@ export const tabsListVariants = cva('inline-flex items-center justify-center rou
|
|
19
20
|
})
|
20
21
|
|
21
22
|
export const tabsTriggerVariants = cva(
|
22
|
-
'inline-flex items-center justify-center
|
23
|
+
'inline-flex items-center justify-center px-3 py-1 text-sm font-semibold ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-foreground',
|
23
24
|
{
|
24
25
|
variants: {
|
25
26
|
variant: {
|
26
27
|
default:
|
27
|
-
'rounded-sm text-foreground opacity-[0.56] hover:opacity-100 data-[state=active]:opacity-100 data-[state=active]:bg-background my-1 [&:first-child]:ml-1 [&:last-child]:mr-1 data-[state=active]:shadow-tab-shadow',
|
28
|
+
'whitespace-nowrap rounded-sm text-foreground opacity-[0.56] hover:opacity-100 data-[state=active]:opacity-100 data-[state=active]:bg-background my-1 [&:first-child]:ml-1 [&:last-child]:mr-1 data-[state=active]:shadow-tab-shadow',
|
28
29
|
ghost:
|
29
|
-
'border-transparent text-muted-foreground pb-0 [&_div]:pb-0.5 [&_div]:data-[state=active]:border-b-2 [&_div]:data-[state=active]:border-primary',
|
30
|
+
'whitespace-nowrap border-transparent text-muted-foreground pb-0 [&_div]:pb-0.5 [&_div]:data-[state=active]:border-b-2 [&_div]:data-[state=active]:border-primary',
|
30
31
|
vertical:
|
31
|
-
'border-transparent text-primary data-[state=active]:border-primary data-[state=active]:bg-background border-l-2 border-b-0 w-full h-
|
32
|
+
'border-transparent text-primary data-[state=active]:border-primary data-[state=active]:bg-background data-[state=active]:shadow-tab-sidebar-shadow border-l-2 border-b-0 w-full h-fit justify-start pl-6'
|
32
33
|
}
|
33
34
|
},
|
34
35
|
defaultVariants: {
|
package/src/tailwind-preset.ts
CHANGED
@@ -30,6 +30,7 @@ export default {
|
|
30
30
|
background: 'hsl(var(--background))',
|
31
31
|
foreground: 'hsl(var(--foreground))',
|
32
32
|
sidebar: 'hsl(var(--side-bar))',
|
33
|
+
'tabs-sidebar': 'hsl(var(--tabs-sidebar))',
|
33
34
|
primary: {
|
34
35
|
DEFAULT: 'hsl(var(--primary) / <alpha-value>)',
|
35
36
|
foreground: 'hsl(var(--primary-foreground) / <alpha-value>)'
|
@@ -92,7 +93,8 @@ export default {
|
|
92
93
|
level2:
|
93
94
|
'0px 32px 16px 0px hsl(var(--tab-shadow)), 0px 16px 16px 0px hsl(var(--tab-shadow)), 0px 16px 16px 0px hsl(var(--tab-shadow))',
|
94
95
|
level3:
|
95
|
-
'0px 56px 24px 0px hsl(var(--tab-shadow)), 0px 32px 24px 0px hsl(var(--tab-shadow)), 0px 32px 24px 0px hsl(var(--tab-shadow))'
|
96
|
+
'0px 56px 24px 0px hsl(var(--tab-shadow)), 0px 32px 24px 0px hsl(var(--tab-shadow)), 0px 32px 24px 0px hsl(var(--tab-shadow))',
|
97
|
+
'tab-sidebar-shadow': 'inset -8px 0px 16px 0px hsl(var(--tabs-sidebar-shadow))'
|
96
98
|
},
|
97
99
|
keyframes: {
|
98
100
|
'accordion-down': {
|