@soave/ui 0.2.1 → 0.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/dist/adapters/types.d.ts +1 -1
- package/dist/components/Button.vue +36 -0
- package/dist/components/Card.vue +23 -0
- package/dist/components/Checkbox.vue +44 -0
- package/dist/components/Dialog.vue +99 -0
- package/dist/components/Input.vue +42 -0
- package/dist/components/RadioGroup.vue +35 -0
- package/dist/components/RadioItem.vue +55 -0
- package/dist/components/Select.vue +95 -0
- package/dist/components/SelectContent.vue +40 -0
- package/dist/components/SelectItem.vue +44 -0
- package/dist/components/SelectTrigger.vue +61 -0
- package/dist/components/Switch.vue +43 -0
- package/dist/components/Textarea.vue +49 -0
- package/dist/components/index.d.ts +13 -0
- package/dist/components/index.mjs +13 -0
- package/dist/composables/useButton.d.ts +2 -2
- package/dist/composables/useButton.mjs +14 -41
- package/dist/composables/useCard.d.ts +2 -2
- package/dist/composables/useCard.mjs +5 -18
- package/dist/composables/useCheckbox.d.ts +2 -1
- package/dist/composables/useCheckbox.mjs +11 -44
- package/dist/composables/useFileInput.d.ts +2 -0
- package/dist/composables/useFileInput.mjs +15 -30
- package/dist/composables/useForm.mjs +2 -2
- package/dist/composables/useInput.d.ts +2 -2
- package/dist/composables/useInput.mjs +12 -33
- package/dist/composables/useRadio.d.ts +2 -1
- package/dist/composables/useRadio.mjs +10 -42
- package/dist/composables/useSelect.d.ts +3 -0
- package/dist/composables/useSelect.mjs +20 -49
- package/dist/composables/useSwitch.d.ts +2 -1
- package/dist/composables/useSwitch.mjs +10 -43
- package/dist/composables/useTextarea.d.ts +2 -1
- package/dist/composables/useTextarea.mjs +12 -33
- package/dist/composables/useToast.mjs +1 -1
- package/dist/env.d.ts +11 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/types/button.d.ts +19 -5
- package/dist/types/card.d.ts +11 -2
- package/dist/types/checkbox.d.ts +15 -6
- package/dist/types/composables.d.ts +52 -24
- package/dist/types/config.d.ts +1 -0
- package/dist/types/file-input.d.ts +15 -5
- package/dist/types/form.d.ts +5 -5
- package/dist/types/input.d.ts +17 -6
- package/dist/types/radio.d.ts +14 -6
- package/dist/types/select.d.ts +25 -7
- package/dist/types/switch.d.ts +14 -5
- package/dist/types/textarea.d.ts +20 -7
- package/dist/types/toast.d.ts +2 -2
- package/dist/types/tooltip.d.ts +3 -0
- package/dist/types/tooltip.mjs +1 -0
- package/package.json +1 -9
- package/dist/components/ui/Alert.vue +0 -41
- package/dist/components/ui/AlertDescription.vue +0 -22
- package/dist/components/ui/AlertTitle.vue +0 -22
- package/dist/components/ui/Button.vue +0 -85
- package/dist/components/ui/Card.vue +0 -39
- package/dist/components/ui/CardContent.vue +0 -22
- package/dist/components/ui/CardDescription.vue +0 -22
- package/dist/components/ui/CardFooter.vue +0 -22
- package/dist/components/ui/CardHeader.vue +0 -22
- package/dist/components/ui/CardTitle.vue +0 -22
- package/dist/components/ui/Checkbox.vue +0 -94
- package/dist/components/ui/Dialog.vue +0 -110
- package/dist/components/ui/DialogDescription.vue +0 -22
- package/dist/components/ui/DialogFooter.vue +0 -22
- package/dist/components/ui/DialogHeader.vue +0 -22
- package/dist/components/ui/DialogTitle.vue +0 -22
- package/dist/components/ui/DropdownMenu.vue +0 -32
- package/dist/components/ui/DropdownMenuContent.vue +0 -69
- package/dist/components/ui/DropdownMenuItem.vue +0 -71
- package/dist/components/ui/DropdownMenuLabel.vue +0 -20
- package/dist/components/ui/DropdownMenuSeparator.vue +0 -16
- package/dist/components/ui/DropdownMenuTrigger.vue +0 -38
- package/dist/components/ui/FileInput.vue +0 -153
- package/dist/components/ui/FormError.vue +0 -20
- package/dist/components/ui/FormField.vue +0 -12
- package/dist/components/ui/FormInput.vue +0 -46
- package/dist/components/ui/FormLabel.vue +0 -19
- package/dist/components/ui/FormTextarea.vue +0 -39
- package/dist/components/ui/Input.vue +0 -72
- package/dist/components/ui/Popover.vue +0 -35
- package/dist/components/ui/PopoverContent.vue +0 -66
- package/dist/components/ui/PopoverTrigger.vue +0 -36
- package/dist/components/ui/RadioGroup.vue +0 -47
- package/dist/components/ui/RadioItem.vue +0 -62
- package/dist/components/ui/Select.vue +0 -62
- package/dist/components/ui/SelectContent.vue +0 -55
- package/dist/components/ui/SelectItem.vue +0 -55
- package/dist/components/ui/SelectTrigger.vue +0 -70
- package/dist/components/ui/SelectValue.vue +0 -27
- package/dist/components/ui/Sheet.vue +0 -148
- package/dist/components/ui/SheetDescription.vue +0 -22
- package/dist/components/ui/SheetFooter.vue +0 -22
- package/dist/components/ui/SheetHeader.vue +0 -22
- package/dist/components/ui/SheetTitle.vue +0 -22
- package/dist/components/ui/Switch.vue +0 -63
- package/dist/components/ui/Textarea.vue +0 -73
- package/dist/components/ui/Toast.vue +0 -116
- package/dist/components/ui/Toaster.vue +0 -76
- package/dist/components/ui/Tooltip.vue +0 -42
- package/dist/components/ui/TooltipContent.vue +0 -71
- package/dist/components/ui/TooltipTrigger.vue +0 -39
- package/dist/components/ui/UIProvider.vue +0 -23
- package/dist/components/ui/index.d.ts +0 -52
- package/dist/components/ui/index.mjs +0 -52
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div :class="[computed_classes, props.class]">
|
|
3
|
-
<slot />
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue"
|
|
9
|
-
import { useStyleAdapter } from "../../composables"
|
|
10
|
-
import type { DialogFooterProps } from "../../types/dialog"
|
|
11
|
-
|
|
12
|
-
const props = withDefaults(defineProps<DialogFooterProps>(), {
|
|
13
|
-
unstyled: false
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
const style_adapter = useStyleAdapter()
|
|
17
|
-
|
|
18
|
-
const computed_classes = computed(() => {
|
|
19
|
-
if (props.unstyled) return ""
|
|
20
|
-
return style_adapter.getClasses("dialog-footer", {})
|
|
21
|
-
})
|
|
22
|
-
</script>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div :class="[computed_classes, props.class]">
|
|
3
|
-
<slot />
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue"
|
|
9
|
-
import { useStyleAdapter } from "../../composables"
|
|
10
|
-
import type { DialogHeaderProps } from "../../types/dialog"
|
|
11
|
-
|
|
12
|
-
const props = withDefaults(defineProps<DialogHeaderProps>(), {
|
|
13
|
-
unstyled: false
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
const style_adapter = useStyleAdapter()
|
|
17
|
-
|
|
18
|
-
const computed_classes = computed(() => {
|
|
19
|
-
if (props.unstyled) return ""
|
|
20
|
-
return style_adapter.getClasses("dialog-header", {})
|
|
21
|
-
})
|
|
22
|
-
</script>
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<h2 :class="[computed_classes, props.class]">
|
|
3
|
-
<slot />
|
|
4
|
-
</h2>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { computed } from "vue"
|
|
9
|
-
import { useStyleAdapter } from "../../composables"
|
|
10
|
-
import type { DialogTitleProps } from "../../types/dialog"
|
|
11
|
-
|
|
12
|
-
const props = withDefaults(defineProps<DialogTitleProps>(), {
|
|
13
|
-
unstyled: false
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
const style_adapter = useStyleAdapter()
|
|
17
|
-
|
|
18
|
-
const computed_classes = computed(() => {
|
|
19
|
-
if (props.unstyled) return ""
|
|
20
|
-
return style_adapter.getClasses("dialog-title", {})
|
|
21
|
-
})
|
|
22
|
-
</script>
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="relative inline-block" :class="props.class">
|
|
3
|
-
<slot />
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { provide, ref, type Ref } from "vue"
|
|
9
|
-
import { useDropdown } from "../../composables/useDropdown"
|
|
10
|
-
import type { DropdownSide, DropdownAlign } from "../../types/dropdown"
|
|
11
|
-
import { DROPDOWN_CONTEXT_KEY } from "../../types/dropdown"
|
|
12
|
-
|
|
13
|
-
interface Props {
|
|
14
|
-
side?: DropdownSide
|
|
15
|
-
align?: DropdownAlign
|
|
16
|
-
class?: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
20
|
-
side: "bottom",
|
|
21
|
-
align: "start"
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
const dropdown_props = ref({
|
|
25
|
-
side: props.side,
|
|
26
|
-
align: props.align
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
const dropdown = useDropdown(dropdown_props as Ref<typeof dropdown_props.value>)
|
|
30
|
-
|
|
31
|
-
provide(DROPDOWN_CONTEXT_KEY, dropdown)
|
|
32
|
-
</script>
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Transition name="dropdown">
|
|
3
|
-
<div
|
|
4
|
-
v-if="is_open"
|
|
5
|
-
ref="content_element"
|
|
6
|
-
:id="dropdown_id"
|
|
7
|
-
role="menu"
|
|
8
|
-
:aria-labelledby="`${dropdown_id}-trigger`"
|
|
9
|
-
:style="position_styles"
|
|
10
|
-
:class="[computed_classes, props.class]"
|
|
11
|
-
tabindex="-1"
|
|
12
|
-
@keydown="handleContentKeyDown"
|
|
13
|
-
>
|
|
14
|
-
<slot />
|
|
15
|
-
</div>
|
|
16
|
-
</Transition>
|
|
17
|
-
</template>
|
|
18
|
-
|
|
19
|
-
<script setup lang="ts">
|
|
20
|
-
import { inject, ref, computed, watchEffect, nextTick, watch } from "vue"
|
|
21
|
-
import { useStyleAdapter } from "../../composables"
|
|
22
|
-
import type { DropdownContentProps } from "../../types/dropdown"
|
|
23
|
-
import { DROPDOWN_CONTEXT_KEY } from "../../types/dropdown"
|
|
24
|
-
import type { DropdownState } from "../../types/composables"
|
|
25
|
-
|
|
26
|
-
const props = withDefaults(defineProps<DropdownContentProps>(), {
|
|
27
|
-
unstyled: false
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
const context = inject(DROPDOWN_CONTEXT_KEY)
|
|
31
|
-
|
|
32
|
-
if (!context) {
|
|
33
|
-
throw new Error("DropdownMenuContent must be used within a DropdownMenu component")
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const {
|
|
37
|
-
is_open,
|
|
38
|
-
content_ref,
|
|
39
|
-
dropdown_id,
|
|
40
|
-
position_styles,
|
|
41
|
-
handleContentKeyDown
|
|
42
|
-
} = context
|
|
43
|
-
|
|
44
|
-
const style_adapter = useStyleAdapter()
|
|
45
|
-
const content_element = ref<HTMLElement | null>(null)
|
|
46
|
-
|
|
47
|
-
watchEffect(() => {
|
|
48
|
-
content_ref.value = content_element.value
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
watch(is_open, async (open) => {
|
|
52
|
-
if (open) {
|
|
53
|
-
await nextTick()
|
|
54
|
-
content_element.value?.focus()
|
|
55
|
-
}
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
const computed_classes = computed(() => {
|
|
59
|
-
if (props.unstyled) return ""
|
|
60
|
-
const state: DropdownState = {
|
|
61
|
-
is_open: is_open.value
|
|
62
|
-
}
|
|
63
|
-
return style_adapter.getClasses("dropdown", state)
|
|
64
|
-
})
|
|
65
|
-
</script>
|
|
66
|
-
|
|
67
|
-
<style scoped>
|
|
68
|
-
.dropdown-enter-active,.dropdown-leave-active{transition:opacity .15s ease,transform .15s ease}.dropdown-enter-from,.dropdown-leave-to{opacity:0;transform:scale(.95)}
|
|
69
|
-
</style>
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
role="menuitem"
|
|
4
|
-
:tabindex="disabled ? -1 : 0"
|
|
5
|
-
:class="[computed_classes, props.class]"
|
|
6
|
-
:aria-disabled="disabled"
|
|
7
|
-
:data-highlighted="is_active ? '' : undefined"
|
|
8
|
-
:data-disabled="disabled ? '' : undefined"
|
|
9
|
-
@click="handleClick"
|
|
10
|
-
@mouseenter="handleMouseEnter"
|
|
11
|
-
@keydown.enter="handleClick"
|
|
12
|
-
@keydown.space.prevent="handleClick"
|
|
13
|
-
>
|
|
14
|
-
<slot />
|
|
15
|
-
</div>
|
|
16
|
-
</template>
|
|
17
|
-
|
|
18
|
-
<script setup lang="ts">
|
|
19
|
-
import { inject, computed, onMounted } from "vue"
|
|
20
|
-
import { useStyleAdapter } from "../../composables"
|
|
21
|
-
import type { DropdownItemProps } from "../../types/dropdown"
|
|
22
|
-
import { DROPDOWN_CONTEXT_KEY } from "../../types/dropdown"
|
|
23
|
-
|
|
24
|
-
const props = withDefaults(defineProps<DropdownItemProps>(), {
|
|
25
|
-
disabled: false,
|
|
26
|
-
destructive: false,
|
|
27
|
-
unstyled: false
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
const emit = defineEmits<{
|
|
31
|
-
select: []
|
|
32
|
-
}>()
|
|
33
|
-
|
|
34
|
-
const context = inject(DROPDOWN_CONTEXT_KEY)
|
|
35
|
-
|
|
36
|
-
if (!context) {
|
|
37
|
-
throw new Error("DropdownMenuItem must be used within a DropdownMenu component")
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const { active_item_index, close, registerItem, setActiveItem } = context
|
|
41
|
-
const style_adapter = useStyleAdapter()
|
|
42
|
-
|
|
43
|
-
let item_index = -1
|
|
44
|
-
|
|
45
|
-
onMounted(() => {
|
|
46
|
-
if (!props.disabled) {
|
|
47
|
-
item_index = registerItem()
|
|
48
|
-
}
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const is_active = computed(() => {
|
|
52
|
-
return active_item_index.value === item_index && !props.disabled
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
const handleClick = (): void => {
|
|
56
|
-
if (props.disabled) return
|
|
57
|
-
emit("select")
|
|
58
|
-
close()
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const handleMouseEnter = (): void => {
|
|
62
|
-
if (!props.disabled && item_index >= 0) {
|
|
63
|
-
setActiveItem(item_index)
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const computed_classes = computed(() => {
|
|
68
|
-
if (props.unstyled) return ""
|
|
69
|
-
return style_adapter.getClasses("dropdown-item", {})
|
|
70
|
-
})
|
|
71
|
-
</script>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
:class="cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', props.class)"
|
|
4
|
-
>
|
|
5
|
-
<slot />
|
|
6
|
-
</div>
|
|
7
|
-
</template>
|
|
8
|
-
|
|
9
|
-
<script setup lang="ts">
|
|
10
|
-
import { cn } from "../../utils/cn"
|
|
11
|
-
|
|
12
|
-
export interface Props {
|
|
13
|
-
inset?: boolean
|
|
14
|
-
class?: string
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
18
|
-
inset: false
|
|
19
|
-
})
|
|
20
|
-
</script>
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
role="separator"
|
|
4
|
-
:class="cn('-mx-1 my-1 h-px bg-muted', props.class)"
|
|
5
|
-
/>
|
|
6
|
-
</template>
|
|
7
|
-
|
|
8
|
-
<script setup lang="ts">
|
|
9
|
-
import { cn } from "../../utils/cn"
|
|
10
|
-
|
|
11
|
-
export interface Props {
|
|
12
|
-
class?: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const props = defineProps<Props>()
|
|
16
|
-
</script>
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<button
|
|
3
|
-
ref="trigger_element"
|
|
4
|
-
type="button"
|
|
5
|
-
:aria-expanded="is_open"
|
|
6
|
-
:aria-controls="dropdown_id"
|
|
7
|
-
:aria-haspopup="true"
|
|
8
|
-
@click="handleTriggerClick"
|
|
9
|
-
@keydown="handleTriggerKeyDown"
|
|
10
|
-
>
|
|
11
|
-
<slot />
|
|
12
|
-
</button>
|
|
13
|
-
</template>
|
|
14
|
-
|
|
15
|
-
<script setup lang="ts">
|
|
16
|
-
import { inject, ref, watchEffect } from "vue"
|
|
17
|
-
import { DROPDOWN_CONTEXT_KEY } from "../../types/dropdown"
|
|
18
|
-
|
|
19
|
-
const context = inject(DROPDOWN_CONTEXT_KEY)
|
|
20
|
-
|
|
21
|
-
if (!context) {
|
|
22
|
-
throw new Error("DropdownMenuTrigger must be used within a DropdownMenu component")
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const {
|
|
26
|
-
is_open,
|
|
27
|
-
trigger_ref,
|
|
28
|
-
dropdown_id,
|
|
29
|
-
handleTriggerClick,
|
|
30
|
-
handleTriggerKeyDown
|
|
31
|
-
} = context
|
|
32
|
-
|
|
33
|
-
const trigger_element = ref<HTMLElement | null>(null)
|
|
34
|
-
|
|
35
|
-
watchEffect(() => {
|
|
36
|
-
trigger_ref.value = trigger_element.value
|
|
37
|
-
})
|
|
38
|
-
</script>
|
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div :class="composable.base_classes.value">
|
|
3
|
-
<input
|
|
4
|
-
ref="input_ref"
|
|
5
|
-
type="file"
|
|
6
|
-
:accept="accept"
|
|
7
|
-
:multiple="multiple"
|
|
8
|
-
:disabled="composable.is_disabled.value"
|
|
9
|
-
class="sr-only"
|
|
10
|
-
@change="handleChange"
|
|
11
|
-
/>
|
|
12
|
-
|
|
13
|
-
<div
|
|
14
|
-
:class="composable.dropzone_classes.value"
|
|
15
|
-
v-bind="composable.aria_attributes.value"
|
|
16
|
-
@click="composable.openFilePicker"
|
|
17
|
-
@dragenter="composable.handleDragEnter"
|
|
18
|
-
@dragleave="composable.handleDragLeave"
|
|
19
|
-
@dragover.prevent
|
|
20
|
-
@drop="composable.handleDrop"
|
|
21
|
-
>
|
|
22
|
-
<slot name="dropzone">
|
|
23
|
-
<svg
|
|
24
|
-
class="w-10 h-10 mb-3 text-muted-foreground"
|
|
25
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
26
|
-
viewBox="0 0 24 24"
|
|
27
|
-
fill="none"
|
|
28
|
-
stroke="currentColor"
|
|
29
|
-
stroke-width="1.5"
|
|
30
|
-
stroke-linecap="round"
|
|
31
|
-
stroke-linejoin="round"
|
|
32
|
-
>
|
|
33
|
-
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
|
34
|
-
<polyline points="17 8 12 3 7 8" />
|
|
35
|
-
<line x1="12" y1="3" x2="12" y2="15" />
|
|
36
|
-
</svg>
|
|
37
|
-
<p class="text-sm text-muted-foreground">
|
|
38
|
-
<span class="font-semibold text-primary">クリック</span>
|
|
39
|
-
または ドラッグ&ドロップ
|
|
40
|
-
</p>
|
|
41
|
-
<p v-if="accept" class="mt-1 text-xs text-muted-foreground">
|
|
42
|
-
{{ accept }}
|
|
43
|
-
</p>
|
|
44
|
-
</slot>
|
|
45
|
-
</div>
|
|
46
|
-
|
|
47
|
-
<p
|
|
48
|
-
v-if="composable.error.value"
|
|
49
|
-
class="mt-2 text-sm text-destructive"
|
|
50
|
-
>
|
|
51
|
-
{{ composable.error.value }}
|
|
52
|
-
</p>
|
|
53
|
-
|
|
54
|
-
<ul
|
|
55
|
-
v-if="composable.files.value.length > 0"
|
|
56
|
-
class="mt-4 space-y-2"
|
|
57
|
-
>
|
|
58
|
-
<li
|
|
59
|
-
v-for="(file, index) in composable.files.value"
|
|
60
|
-
:key="file.name + index"
|
|
61
|
-
class="flex items-center gap-3 p-2 rounded-md border bg-muted/50"
|
|
62
|
-
>
|
|
63
|
-
<img
|
|
64
|
-
v-if="file.preview_url"
|
|
65
|
-
:src="file.preview_url"
|
|
66
|
-
:alt="file.name"
|
|
67
|
-
class="w-10 h-10 object-cover rounded"
|
|
68
|
-
/>
|
|
69
|
-
<svg
|
|
70
|
-
v-else
|
|
71
|
-
class="w-10 h-10 text-muted-foreground"
|
|
72
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
73
|
-
viewBox="0 0 24 24"
|
|
74
|
-
fill="none"
|
|
75
|
-
stroke="currentColor"
|
|
76
|
-
stroke-width="1.5"
|
|
77
|
-
>
|
|
78
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
|
79
|
-
<polyline points="14 2 14 8 20 8" />
|
|
80
|
-
</svg>
|
|
81
|
-
<div class="flex-1 min-w-0">
|
|
82
|
-
<p class="text-sm font-medium truncate">{{ file.name }}</p>
|
|
83
|
-
<p class="text-xs text-muted-foreground">
|
|
84
|
-
{{ formatSize(file.size) }}
|
|
85
|
-
</p>
|
|
86
|
-
</div>
|
|
87
|
-
<button
|
|
88
|
-
type="button"
|
|
89
|
-
class="p-1 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive"
|
|
90
|
-
@click.stop="composable.removeFile(index)"
|
|
91
|
-
>
|
|
92
|
-
<svg
|
|
93
|
-
class="w-4 h-4"
|
|
94
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
95
|
-
viewBox="0 0 24 24"
|
|
96
|
-
fill="none"
|
|
97
|
-
stroke="currentColor"
|
|
98
|
-
stroke-width="2"
|
|
99
|
-
>
|
|
100
|
-
<line x1="18" y1="6" x2="6" y2="18" />
|
|
101
|
-
<line x1="6" y1="6" x2="18" y2="18" />
|
|
102
|
-
</svg>
|
|
103
|
-
</button>
|
|
104
|
-
</li>
|
|
105
|
-
</ul>
|
|
106
|
-
</div>
|
|
107
|
-
</template>
|
|
108
|
-
|
|
109
|
-
<script setup lang="ts">
|
|
110
|
-
import { ref, toRef, watch } from "vue"
|
|
111
|
-
import { useFileInput } from "../../composables/useFileInput"
|
|
112
|
-
import type { FileInputProps, FileInfo } from "../../types/file-input"
|
|
113
|
-
|
|
114
|
-
interface Props extends FileInputProps {
|
|
115
|
-
modelValue?: File | File[] | null
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
119
|
-
multiple: false,
|
|
120
|
-
disabled: false
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
const emit = defineEmits<{
|
|
124
|
-
"update:modelValue": [value: File | File[] | null]
|
|
125
|
-
}>()
|
|
126
|
-
|
|
127
|
-
const input_ref = ref<HTMLInputElement | null>(null)
|
|
128
|
-
const composable = useFileInput(toRef(() => props), input_ref)
|
|
129
|
-
|
|
130
|
-
const formatSize = (bytes: number): string => {
|
|
131
|
-
if (bytes < 1024) return `${bytes}B`
|
|
132
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`
|
|
133
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const handleChange = (event: Event) => {
|
|
137
|
-
const target = event.target as HTMLInputElement
|
|
138
|
-
composable.handleFiles(target.files)
|
|
139
|
-
target.value = ""
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
watch(
|
|
143
|
-
() => composable.files.value,
|
|
144
|
-
(new_files: FileInfo[]) => {
|
|
145
|
-
if (props.multiple) {
|
|
146
|
-
emit("update:modelValue", new_files.map(f => f.file))
|
|
147
|
-
} else {
|
|
148
|
-
emit("update:modelValue", new_files[0]?.file ?? null)
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
{ deep: true }
|
|
152
|
-
)
|
|
153
|
-
</script>
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<p
|
|
3
|
-
v-if="$slots.default"
|
|
4
|
-
:id="id"
|
|
5
|
-
:class="cn('text-sm font-medium text-destructive', props.class)"
|
|
6
|
-
>
|
|
7
|
-
<slot />
|
|
8
|
-
</p>
|
|
9
|
-
</template>
|
|
10
|
-
|
|
11
|
-
<script setup lang="ts">
|
|
12
|
-
import { cn } from "../../utils/cn"
|
|
13
|
-
import type { FormErrorProps } from "../../types/form"
|
|
14
|
-
|
|
15
|
-
interface Props extends FormErrorProps {
|
|
16
|
-
id?: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const props = defineProps<Props>()
|
|
20
|
-
</script>
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div :class="cn('space-y-2', props.class)">
|
|
3
|
-
<slot />
|
|
4
|
-
</div>
|
|
5
|
-
</template>
|
|
6
|
-
|
|
7
|
-
<script setup lang="ts">
|
|
8
|
-
import { cn } from "../../utils/cn"
|
|
9
|
-
import type { FormFieldProps } from "../../types/form"
|
|
10
|
-
|
|
11
|
-
const props = defineProps<FormFieldProps>()
|
|
12
|
-
</script>
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Input
|
|
3
|
-
:id="id"
|
|
4
|
-
:type="type"
|
|
5
|
-
:size="size"
|
|
6
|
-
:placeholder="placeholder"
|
|
7
|
-
:disabled="disabled"
|
|
8
|
-
:readonly="readonly"
|
|
9
|
-
:error="error"
|
|
10
|
-
:error_id="error_id"
|
|
11
|
-
:model-value="modelValue"
|
|
12
|
-
:class="props.class"
|
|
13
|
-
@update:model-value="emit('update:modelValue', $event)"
|
|
14
|
-
@blur="emit('blur', $event)"
|
|
15
|
-
/>
|
|
16
|
-
</template>
|
|
17
|
-
|
|
18
|
-
<script setup lang="ts">
|
|
19
|
-
import Input from "./Input.vue"
|
|
20
|
-
import type { InputType, InputSize } from "../../types/input"
|
|
21
|
-
|
|
22
|
-
interface Props {
|
|
23
|
-
id?: string
|
|
24
|
-
type?: InputType
|
|
25
|
-
size?: InputSize
|
|
26
|
-
placeholder?: string
|
|
27
|
-
disabled?: boolean
|
|
28
|
-
readonly?: boolean
|
|
29
|
-
error?: string
|
|
30
|
-
error_id?: string
|
|
31
|
-
modelValue?: string | number
|
|
32
|
-
class?: string
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
36
|
-
type: "text",
|
|
37
|
-
size: "md",
|
|
38
|
-
disabled: false,
|
|
39
|
-
readonly: false
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
const emit = defineEmits<{
|
|
43
|
-
"update:modelValue": [value: string | number]
|
|
44
|
-
blur: [event: FocusEvent]
|
|
45
|
-
}>()
|
|
46
|
-
</script>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<label
|
|
3
|
-
:for="props.for"
|
|
4
|
-
:class="cn(
|
|
5
|
-
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
|
|
6
|
-
props.class
|
|
7
|
-
)"
|
|
8
|
-
>
|
|
9
|
-
<slot />
|
|
10
|
-
<span v-if="props.required" class="text-destructive ml-1">*</span>
|
|
11
|
-
</label>
|
|
12
|
-
</template>
|
|
13
|
-
|
|
14
|
-
<script setup lang="ts">
|
|
15
|
-
import { cn } from "../../utils/cn"
|
|
16
|
-
import type { FormLabelProps } from "../../types/form"
|
|
17
|
-
|
|
18
|
-
const props = defineProps<FormLabelProps>()
|
|
19
|
-
</script>
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<Textarea
|
|
3
|
-
:id="id"
|
|
4
|
-
:placeholder="placeholder"
|
|
5
|
-
:disabled="disabled"
|
|
6
|
-
:readonly="readonly"
|
|
7
|
-
:error="error"
|
|
8
|
-
:error_id="error_id"
|
|
9
|
-
:rows="rows"
|
|
10
|
-
:resize="resize"
|
|
11
|
-
:model-value="modelValue"
|
|
12
|
-
:class="props.class"
|
|
13
|
-
@update:model-value="emit('update:modelValue', $event)"
|
|
14
|
-
@blur="emit('blur', $event)"
|
|
15
|
-
/>
|
|
16
|
-
</template>
|
|
17
|
-
|
|
18
|
-
<script setup lang="ts">
|
|
19
|
-
import Textarea from "./Textarea.vue"
|
|
20
|
-
import type { TextareaProps } from "../../types/textarea"
|
|
21
|
-
|
|
22
|
-
interface Props extends TextareaProps {
|
|
23
|
-
id?: string
|
|
24
|
-
modelValue?: string
|
|
25
|
-
class?: string
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
29
|
-
rows: 3,
|
|
30
|
-
resize: "vertical",
|
|
31
|
-
disabled: false,
|
|
32
|
-
readonly: false
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const emit = defineEmits<{
|
|
36
|
-
"update:modelValue": [value: string]
|
|
37
|
-
blur: [event: FocusEvent]
|
|
38
|
-
}>()
|
|
39
|
-
</script>
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<input
|
|
3
|
-
:id="id"
|
|
4
|
-
:type="type"
|
|
5
|
-
:class="[computed_classes, props.class]"
|
|
6
|
-
:disabled="composable.is_disabled.value"
|
|
7
|
-
:readonly="composable.is_readonly.value"
|
|
8
|
-
:placeholder="placeholder"
|
|
9
|
-
:value="modelValue"
|
|
10
|
-
v-bind="composable.aria_attributes.value"
|
|
11
|
-
@input="handleInput"
|
|
12
|
-
@focus="composable.handleFocus"
|
|
13
|
-
@blur="handleBlur"
|
|
14
|
-
/>
|
|
15
|
-
</template>
|
|
16
|
-
|
|
17
|
-
<script setup lang="ts">
|
|
18
|
-
import { toRef, computed } from "vue"
|
|
19
|
-
import { useInput } from "../../composables/useInput"
|
|
20
|
-
import { useStyleAdapter, useUI } from "../../composables/useUIConfig"
|
|
21
|
-
import type { InputProps, InputType } from "../../types/input"
|
|
22
|
-
import type { InputState } from "../../types/composables"
|
|
23
|
-
|
|
24
|
-
interface Props extends InputProps {
|
|
25
|
-
id?: string
|
|
26
|
-
modelValue?: string | number
|
|
27
|
-
class?: string
|
|
28
|
-
unstyled?: boolean
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
32
|
-
type: "text" as InputType,
|
|
33
|
-
disabled: false,
|
|
34
|
-
readonly: false,
|
|
35
|
-
unstyled: false
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
const emit = defineEmits<{
|
|
39
|
-
"update:modelValue": [value: string | number]
|
|
40
|
-
blur: [event: FocusEvent]
|
|
41
|
-
}>()
|
|
42
|
-
|
|
43
|
-
const ui_config = useUI("input")
|
|
44
|
-
const style_adapter = useStyleAdapter()
|
|
45
|
-
const composable = useInput(toRef(() => props))
|
|
46
|
-
|
|
47
|
-
// StyleAdapterからクラスを取得
|
|
48
|
-
const computed_classes = computed(() => {
|
|
49
|
-
if (props.unstyled) {
|
|
50
|
-
return ""
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const state: InputState = {
|
|
54
|
-
size: props.size ?? ui_config.default_size,
|
|
55
|
-
disabled: composable.is_disabled.value,
|
|
56
|
-
readonly: composable.is_readonly.value,
|
|
57
|
-
error: props.error
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return style_adapter.getClasses("input", state)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
const handleInput = (event: Event) => {
|
|
64
|
-
const target = event.target as HTMLInputElement
|
|
65
|
-
emit("update:modelValue", target.value)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const handleBlur = (event: FocusEvent) => {
|
|
69
|
-
composable.handleBlur()
|
|
70
|
-
emit("blur", event)
|
|
71
|
-
}
|
|
72
|
-
</script>
|