@soave/ui 0.2.2 → 0.3.1
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/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 +48 -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 +55 -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/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/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 +33 -5
- package/dist/types/file-input.d.ts +15 -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 +18 -7
- 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 -41
- 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
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { default as Button } from "./Button.vue";
|
|
2
|
+
export { default as Input } from "./Input.vue";
|
|
3
|
+
export { default as Textarea } from "./Textarea.vue";
|
|
4
|
+
export { default as Card } from "./Card.vue";
|
|
5
|
+
export { default as Checkbox } from "./Checkbox.vue";
|
|
6
|
+
export { default as Switch } from "./Switch.vue";
|
|
7
|
+
export { default as Dialog } from "./Dialog.vue";
|
|
8
|
+
export { default as Select } from "./Select.vue";
|
|
9
|
+
export { default as SelectTrigger } from "./SelectTrigger.vue";
|
|
10
|
+
export { default as SelectContent } from "./SelectContent.vue";
|
|
11
|
+
export { default as SelectItem } from "./SelectItem.vue";
|
|
12
|
+
export { default as RadioGroup } from "./RadioGroup.vue";
|
|
13
|
+
export { default as RadioItem } from "./RadioItem.vue";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { default as Button } from "./Button.vue";
|
|
2
|
+
export { default as Input } from "./Input.vue";
|
|
3
|
+
export { default as Textarea } from "./Textarea.vue";
|
|
4
|
+
export { default as Card } from "./Card.vue";
|
|
5
|
+
export { default as Checkbox } from "./Checkbox.vue";
|
|
6
|
+
export { default as Switch } from "./Switch.vue";
|
|
7
|
+
export { default as Dialog } from "./Dialog.vue";
|
|
8
|
+
export { default as Select } from "./Select.vue";
|
|
9
|
+
export { default as SelectTrigger } from "./SelectTrigger.vue";
|
|
10
|
+
export { default as SelectContent } from "./SelectContent.vue";
|
|
11
|
+
export { default as SelectItem } from "./SelectItem.vue";
|
|
12
|
+
export { default as RadioGroup } from "./RadioGroup.vue";
|
|
13
|
+
export { default as RadioItem } from "./RadioItem.vue";
|
|
@@ -2,7 +2,7 @@ import { type Ref } from "vue";
|
|
|
2
2
|
import type { ButtonProps, ButtonReturn } from "../types/button";
|
|
3
3
|
/**
|
|
4
4
|
* Buttonコンポーネントのロジックを提供するComposable
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* 状態とARIA属性のみを返す(スタイル情報なし)
|
|
6
|
+
* スタイルは StyleAdapter または外部のスタイルパッケージが担当
|
|
7
7
|
*/
|
|
8
8
|
export declare const useButton: (props: Ref<ButtonProps>) => ButtonReturn;
|
|
@@ -1,49 +1,22 @@
|
|
|
1
|
-
import { computed } from "vue";
|
|
2
|
-
import { cn } from "../utils/cn.mjs";
|
|
1
|
+
import { computed, readonly } from "vue";
|
|
3
2
|
import { useUI } from "./useUIConfig.mjs";
|
|
4
3
|
export const useButton = (props) => {
|
|
5
4
|
const ui_config = useUI("button");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
14
|
-
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
15
|
-
};
|
|
16
|
-
return variant_map[props.value.variant ?? ui_config.default_variant];
|
|
17
|
-
});
|
|
18
|
-
const size_classes = computed(() => {
|
|
19
|
-
const size_map = {
|
|
20
|
-
sm: "h-9 px-3 text-sm",
|
|
21
|
-
md: "h-10 px-4 py-2",
|
|
22
|
-
lg: "h-11 px-8"
|
|
23
|
-
};
|
|
24
|
-
return size_map[props.value.size ?? ui_config.default_size];
|
|
25
|
-
});
|
|
26
|
-
const base_classes = computed(
|
|
27
|
-
() => cn(
|
|
28
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium",
|
|
29
|
-
"ring-offset-background transition-colors",
|
|
30
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
31
|
-
"disabled:pointer-events-none disabled:opacity-50",
|
|
32
|
-
variant_classes.value,
|
|
33
|
-
size_classes.value,
|
|
34
|
-
is_disabled.value && "opacity-50 cursor-not-allowed",
|
|
35
|
-
is_loading.value && "cursor-wait"
|
|
36
|
-
)
|
|
37
|
-
);
|
|
5
|
+
const state = computed(() => ({
|
|
6
|
+
variant: props.value.variant ?? ui_config.default_variant,
|
|
7
|
+
size: props.value.size ?? ui_config.default_size,
|
|
8
|
+
disabled: props.value.disabled ?? false,
|
|
9
|
+
loading: props.value.loading ?? false,
|
|
10
|
+
type: props.value.type ?? "button"
|
|
11
|
+
}));
|
|
38
12
|
const aria_attributes = computed(() => ({
|
|
39
|
-
"aria-disabled":
|
|
40
|
-
"aria-busy":
|
|
41
|
-
role: "button"
|
|
13
|
+
"aria-disabled": state.value.disabled || void 0,
|
|
14
|
+
"aria-busy": state.value.loading || void 0,
|
|
15
|
+
role: "button",
|
|
16
|
+
type: state.value.type
|
|
42
17
|
}));
|
|
43
18
|
return {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
is_loading,
|
|
47
|
-
aria_attributes
|
|
19
|
+
state: readonly(state),
|
|
20
|
+
aria_attributes: readonly(aria_attributes)
|
|
48
21
|
};
|
|
49
22
|
};
|
|
@@ -2,7 +2,7 @@ import { type Ref } from "vue";
|
|
|
2
2
|
import type { CardProps, CardReturn } from "../types/card";
|
|
3
3
|
/**
|
|
4
4
|
* Cardコンポーネントのロジックを提供するComposable
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* 状態のみを返す(スタイル情報なし)
|
|
6
|
+
* スタイルは StyleAdapter または外部のスタイルパッケージが担当
|
|
7
7
|
*/
|
|
8
8
|
export declare const useCard: (props: Ref<CardProps>) => CardReturn;
|
|
@@ -1,24 +1,11 @@
|
|
|
1
|
-
import { computed } from "vue";
|
|
2
|
-
import { cn } from "../utils/cn.mjs";
|
|
1
|
+
import { computed, readonly } from "vue";
|
|
3
2
|
import { useUI } from "./useUIConfig.mjs";
|
|
4
3
|
export const useCard = (props) => {
|
|
5
4
|
const ui_config = useUI("card");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
sm: "p-4",
|
|
10
|
-
md: "p-6",
|
|
11
|
-
lg: "p-8"
|
|
12
|
-
};
|
|
13
|
-
return padding_map[props.value.padding ?? ui_config.default_padding];
|
|
14
|
-
});
|
|
15
|
-
const base_classes = computed(
|
|
16
|
-
() => cn(
|
|
17
|
-
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
|
18
|
-
padding_classes.value
|
|
19
|
-
)
|
|
20
|
-
);
|
|
5
|
+
const state = computed(() => ({
|
|
6
|
+
padding: props.value.padding ?? ui_config.default_padding
|
|
7
|
+
}));
|
|
21
8
|
return {
|
|
22
|
-
|
|
9
|
+
state: readonly(state)
|
|
23
10
|
};
|
|
24
11
|
};
|
|
@@ -2,6 +2,7 @@ import { type Ref } from "vue";
|
|
|
2
2
|
import type { CheckboxProps, CheckboxReturn } from "../types/checkbox";
|
|
3
3
|
/**
|
|
4
4
|
* Checkboxコンポーネントのロジックを提供するComposable
|
|
5
|
-
*
|
|
5
|
+
* 状態とARIA属性のみを返す(スタイル情報なし)
|
|
6
|
+
* スタイルは StyleAdapter または外部のスタイルパッケージが担当
|
|
6
7
|
*/
|
|
7
8
|
export declare const useCheckbox: (props: Ref<CheckboxProps>, checked: Ref<boolean>) => CheckboxReturn;
|
|
@@ -1,51 +1,18 @@
|
|
|
1
|
-
import { computed } from "vue";
|
|
2
|
-
import { cn } from "../utils/cn.mjs";
|
|
1
|
+
import { computed, readonly } from "vue";
|
|
3
2
|
export const useCheckbox = (props, checked) => {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
lg: "h-6 w-6"
|
|
11
|
-
};
|
|
12
|
-
return size_map[props.value.size ?? "md"];
|
|
13
|
-
});
|
|
14
|
-
const base_classes = computed(
|
|
15
|
-
() => cn(
|
|
16
|
-
"peer shrink-0 rounded-sm border border-primary",
|
|
17
|
-
"ring-offset-background",
|
|
18
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
19
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
20
|
-
"data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
|
21
|
-
"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground",
|
|
22
|
-
size_classes.value
|
|
23
|
-
)
|
|
24
|
-
);
|
|
25
|
-
const indicator_size_classes = computed(() => {
|
|
26
|
-
const size_map = {
|
|
27
|
-
sm: "h-3 w-3",
|
|
28
|
-
md: "h-4 w-4",
|
|
29
|
-
lg: "h-5 w-5"
|
|
30
|
-
};
|
|
31
|
-
return size_map[props.value.size ?? "md"];
|
|
32
|
-
});
|
|
33
|
-
const indicator_classes = computed(
|
|
34
|
-
() => cn(
|
|
35
|
-
"flex items-center justify-center text-current",
|
|
36
|
-
indicator_size_classes.value
|
|
37
|
-
)
|
|
38
|
-
);
|
|
3
|
+
const state = computed(() => ({
|
|
4
|
+
size: props.value.size ?? "md",
|
|
5
|
+
disabled: props.value.disabled ?? false,
|
|
6
|
+
indeterminate: props.value.indeterminate ?? false,
|
|
7
|
+
checked: checked.value
|
|
8
|
+
}));
|
|
39
9
|
const aria_attributes = computed(() => ({
|
|
40
10
|
role: "checkbox",
|
|
41
|
-
"aria-checked":
|
|
42
|
-
"aria-disabled":
|
|
11
|
+
"aria-checked": state.value.indeterminate ? "mixed" : state.value.checked,
|
|
12
|
+
"aria-disabled": state.value.disabled || void 0
|
|
43
13
|
}));
|
|
44
14
|
return {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
is_disabled,
|
|
48
|
-
is_indeterminate,
|
|
49
|
-
aria_attributes
|
|
15
|
+
state: readonly(state),
|
|
16
|
+
aria_attributes: readonly(aria_attributes)
|
|
50
17
|
};
|
|
51
18
|
};
|
|
@@ -2,5 +2,7 @@ import { type Ref } from "vue";
|
|
|
2
2
|
import type { FileInputProps, FileInputReturn } from "../types/file-input";
|
|
3
3
|
/**
|
|
4
4
|
* FileInputコンポーネントのロジックを提供するComposable
|
|
5
|
+
* 状態とARIA属性のみを返す(スタイル情報なし)
|
|
6
|
+
* スタイルは StyleAdapter または外部のスタイルパッケージが担当
|
|
5
7
|
*/
|
|
6
8
|
export declare const useFileInput: (props: Ref<FileInputProps>, input_ref: Ref<HTMLInputElement | null>) => FileInputReturn;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { computed, ref } from "vue";
|
|
2
|
-
import { cn } from "../utils/cn.mjs";
|
|
1
|
+
import { computed, ref, readonly } from "vue";
|
|
3
2
|
const FILE_ERRORS = {
|
|
4
3
|
MAX_SIZE_EXCEEDED: (max) => `\u30D5\u30A1\u30A4\u30EB\u30B5\u30A4\u30BA\u304C${formatFileSize(max)}\u3092\u8D85\u3048\u3066\u3044\u307E\u3059`,
|
|
5
4
|
MAX_FILES_EXCEEDED: (max) => `\u6700\u5927${max}\u30D5\u30A1\u30A4\u30EB\u307E\u3067\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9\u3067\u304D\u307E\u3059`,
|
|
@@ -17,30 +16,18 @@ const createPreviewUrl = (file) => {
|
|
|
17
16
|
return null;
|
|
18
17
|
};
|
|
19
18
|
export const useFileInput = (props, input_ref) => {
|
|
20
|
-
const is_disabled = computed(() => props.value.disabled ?? false);
|
|
21
19
|
const is_dragging = ref(false);
|
|
22
20
|
const files = ref([]);
|
|
23
21
|
const error = ref(null);
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
);
|
|
30
|
-
const dropzone_classes = computed(
|
|
31
|
-
() => cn(
|
|
32
|
-
"flex flex-col items-center justify-center w-full p-6",
|
|
33
|
-
"border-2 border-dashed rounded-lg",
|
|
34
|
-
"transition-colors cursor-pointer",
|
|
35
|
-
"hover:border-primary hover:bg-primary/5",
|
|
36
|
-
is_dragging.value && "border-primary bg-primary/10",
|
|
37
|
-
error.value && "border-destructive",
|
|
38
|
-
is_disabled.value && "pointer-events-none"
|
|
39
|
-
)
|
|
40
|
-
);
|
|
22
|
+
const state = computed(() => ({
|
|
23
|
+
disabled: props.value.disabled ?? false,
|
|
24
|
+
is_dragging: is_dragging.value,
|
|
25
|
+
has_error: !!error.value,
|
|
26
|
+
has_files: files.value.length > 0
|
|
27
|
+
}));
|
|
41
28
|
const aria_attributes = computed(() => ({
|
|
42
|
-
"aria-disabled":
|
|
43
|
-
"aria-invalid":
|
|
29
|
+
"aria-disabled": state.value.disabled || void 0,
|
|
30
|
+
"aria-invalid": state.value.has_error || void 0
|
|
44
31
|
}));
|
|
45
32
|
const validateFile = (file) => {
|
|
46
33
|
const { accept, max_size } = props.value;
|
|
@@ -65,7 +52,7 @@ export const useFileInput = (props, input_ref) => {
|
|
|
65
52
|
return null;
|
|
66
53
|
};
|
|
67
54
|
const handleFiles = (file_list) => {
|
|
68
|
-
if (!file_list ||
|
|
55
|
+
if (!file_list || state.value.disabled) return;
|
|
69
56
|
error.value = null;
|
|
70
57
|
const { multiple, max_files } = props.value;
|
|
71
58
|
const new_files = [];
|
|
@@ -100,7 +87,7 @@ export const useFileInput = (props, input_ref) => {
|
|
|
100
87
|
};
|
|
101
88
|
const handleDragEnter = (event) => {
|
|
102
89
|
event.preventDefault();
|
|
103
|
-
if (!
|
|
90
|
+
if (!state.value.disabled) {
|
|
104
91
|
is_dragging.value = true;
|
|
105
92
|
}
|
|
106
93
|
};
|
|
@@ -111,7 +98,7 @@ export const useFileInput = (props, input_ref) => {
|
|
|
111
98
|
const handleDrop = (event) => {
|
|
112
99
|
event.preventDefault();
|
|
113
100
|
is_dragging.value = false;
|
|
114
|
-
if (!
|
|
101
|
+
if (!state.value.disabled) {
|
|
115
102
|
handleFiles(event.dataTransfer?.files ?? null);
|
|
116
103
|
}
|
|
117
104
|
};
|
|
@@ -129,18 +116,16 @@ export const useFileInput = (props, input_ref) => {
|
|
|
129
116
|
error.value = null;
|
|
130
117
|
};
|
|
131
118
|
const openFilePicker = () => {
|
|
132
|
-
if (!
|
|
119
|
+
if (!state.value.disabled && input_ref.value) {
|
|
133
120
|
input_ref.value.click();
|
|
134
121
|
}
|
|
135
122
|
};
|
|
136
123
|
return {
|
|
137
|
-
|
|
138
|
-
dropzone_classes,
|
|
139
|
-
is_disabled,
|
|
124
|
+
state: readonly(state),
|
|
140
125
|
is_dragging,
|
|
141
126
|
files,
|
|
142
127
|
error,
|
|
143
|
-
aria_attributes,
|
|
128
|
+
aria_attributes: readonly(aria_attributes),
|
|
144
129
|
handleFiles,
|
|
145
130
|
handleDragEnter,
|
|
146
131
|
handleDragLeave,
|
|
@@ -2,7 +2,7 @@ import { type Ref } from "vue";
|
|
|
2
2
|
import type { InputProps, InputReturn } from "../types/input";
|
|
3
3
|
/**
|
|
4
4
|
* Inputコンポーネントのロジックを提供するComposable
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* 状態とARIA属性のみを返す(スタイル情報なし)
|
|
6
|
+
* スタイルは StyleAdapter または外部のスタイルパッケージが担当
|
|
7
7
|
*/
|
|
8
8
|
export declare const useInput: (props: Ref<InputProps>) => InputReturn;
|
|
@@ -1,37 +1,19 @@
|
|
|
1
|
-
import { computed, ref } from "vue";
|
|
2
|
-
import { cn } from "../utils/cn.mjs";
|
|
1
|
+
import { computed, ref, readonly } from "vue";
|
|
3
2
|
import { useUI } from "./useUIConfig.mjs";
|
|
4
3
|
export const useInput = (props) => {
|
|
5
4
|
const ui_config = useUI("input");
|
|
6
5
|
const is_focused = ref(false);
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
lg: "h-11 text-lg"
|
|
15
|
-
};
|
|
16
|
-
return size_map[props.value.size ?? ui_config.default_size];
|
|
17
|
-
});
|
|
18
|
-
const base_classes = computed(
|
|
19
|
-
() => cn(
|
|
20
|
-
"flex w-full rounded-md border border-input bg-background px-3 py-2",
|
|
21
|
-
"text-sm ring-offset-background",
|
|
22
|
-
"file:border-0 file:bg-transparent file:text-sm file:font-medium",
|
|
23
|
-
"placeholder:text-muted-foreground",
|
|
24
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
25
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
26
|
-
size_classes.value,
|
|
27
|
-
has_error.value && "border-destructive focus-visible:ring-destructive",
|
|
28
|
-
is_readonly.value && "bg-muted"
|
|
29
|
-
)
|
|
30
|
-
);
|
|
6
|
+
const state = computed(() => ({
|
|
7
|
+
type: props.value.type ?? "text",
|
|
8
|
+
size: props.value.size ?? ui_config.default_size,
|
|
9
|
+
disabled: props.value.disabled ?? false,
|
|
10
|
+
readonly: props.value.readonly ?? false,
|
|
11
|
+
has_error: !!props.value.error
|
|
12
|
+
}));
|
|
31
13
|
const aria_attributes = computed(() => ({
|
|
32
|
-
"aria-invalid":
|
|
14
|
+
"aria-invalid": state.value.has_error || void 0,
|
|
33
15
|
"aria-describedby": props.value.error_id,
|
|
34
|
-
"aria-readonly":
|
|
16
|
+
"aria-readonly": state.value.readonly || void 0
|
|
35
17
|
}));
|
|
36
18
|
const handleFocus = () => {
|
|
37
19
|
is_focused.value = true;
|
|
@@ -40,12 +22,9 @@ export const useInput = (props) => {
|
|
|
40
22
|
is_focused.value = false;
|
|
41
23
|
};
|
|
42
24
|
return {
|
|
43
|
-
|
|
25
|
+
state: readonly(state),
|
|
44
26
|
is_focused,
|
|
45
|
-
|
|
46
|
-
is_disabled,
|
|
47
|
-
is_readonly,
|
|
48
|
-
aria_attributes,
|
|
27
|
+
aria_attributes: readonly(aria_attributes),
|
|
49
28
|
handleFocus,
|
|
50
29
|
handleBlur
|
|
51
30
|
};
|
|
@@ -2,6 +2,7 @@ import { type Ref } from "vue";
|
|
|
2
2
|
import type { RadioItemProps, RadioItemReturn } from "../types/radio";
|
|
3
3
|
/**
|
|
4
4
|
* RadioItemコンポーネントのロジックを提供するComposable
|
|
5
|
-
*
|
|
5
|
+
* 状態とARIA属性のみを返す(スタイル情報なし)
|
|
6
|
+
* スタイルは StyleAdapter または外部のスタイルパッケージが担当
|
|
6
7
|
*/
|
|
7
8
|
export declare const useRadioItem: (props: Ref<RadioItemProps>) => RadioItemReturn;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { computed, inject } from "vue";
|
|
2
|
-
import { cn } from "../utils/cn.mjs";
|
|
1
|
+
import { computed, inject, readonly } from "vue";
|
|
3
2
|
import { RADIO_GROUP_KEY } from "../types/radio.mjs";
|
|
4
3
|
import { COMPONENT_ERRORS } from "../constants/errors.mjs";
|
|
5
4
|
export const useRadioItem = (props) => {
|
|
@@ -7,49 +6,18 @@ export const useRadioItem = (props) => {
|
|
|
7
6
|
if (!context) {
|
|
8
7
|
throw new Error(COMPONENT_ERRORS.PROVIDER_NOT_FOUND);
|
|
9
8
|
}
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
md: "h-5 w-5",
|
|
16
|
-
lg: "h-6 w-6"
|
|
17
|
-
};
|
|
18
|
-
return size_map[props.value.size ?? "md"];
|
|
19
|
-
});
|
|
20
|
-
const base_classes = computed(
|
|
21
|
-
() => cn(
|
|
22
|
-
"aspect-square rounded-full border border-primary text-primary",
|
|
23
|
-
"ring-offset-background",
|
|
24
|
-
"focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
25
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
26
|
-
size_classes.value
|
|
27
|
-
)
|
|
28
|
-
);
|
|
29
|
-
const indicator_size_classes = computed(() => {
|
|
30
|
-
const size_map = {
|
|
31
|
-
sm: "h-2 w-2",
|
|
32
|
-
md: "h-2.5 w-2.5",
|
|
33
|
-
lg: "h-3 w-3"
|
|
34
|
-
};
|
|
35
|
-
return size_map[props.value.size ?? "md"];
|
|
36
|
-
});
|
|
37
|
-
const indicator_classes = computed(
|
|
38
|
-
() => cn(
|
|
39
|
-
"flex items-center justify-center",
|
|
40
|
-
indicator_size_classes.value
|
|
41
|
-
)
|
|
42
|
-
);
|
|
9
|
+
const state = computed(() => ({
|
|
10
|
+
size: props.value.size ?? "md",
|
|
11
|
+
disabled: props.value.disabled ?? context.disabled.value,
|
|
12
|
+
checked: context.model_value.value === props.value.value
|
|
13
|
+
}));
|
|
43
14
|
const aria_attributes = computed(() => ({
|
|
44
15
|
role: "radio",
|
|
45
|
-
"aria-checked":
|
|
46
|
-
"aria-disabled":
|
|
16
|
+
"aria-checked": state.value.checked,
|
|
17
|
+
"aria-disabled": state.value.disabled || void 0
|
|
47
18
|
}));
|
|
48
19
|
return {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
is_checked,
|
|
52
|
-
is_disabled,
|
|
53
|
-
aria_attributes
|
|
20
|
+
state: readonly(state),
|
|
21
|
+
aria_attributes: readonly(aria_attributes)
|
|
54
22
|
};
|
|
55
23
|
};
|
|
@@ -2,14 +2,17 @@ import { type Ref } from "vue";
|
|
|
2
2
|
import type { SelectTriggerReturn, SelectContentReturn, SelectItemReturn } from "../types/select";
|
|
3
3
|
/**
|
|
4
4
|
* SelectTriggerコンポーネントのロジックを提供するComposable
|
|
5
|
+
* 状態のみを返す(スタイル情報なし)
|
|
5
6
|
*/
|
|
6
7
|
export declare const useSelectTrigger: () => SelectTriggerReturn;
|
|
7
8
|
/**
|
|
8
9
|
* SelectContentコンポーネントのロジックを提供するComposable
|
|
10
|
+
* 状態のみを返す(スタイル情報なし)
|
|
9
11
|
*/
|
|
10
12
|
export declare const useSelectContent: () => SelectContentReturn;
|
|
11
13
|
/**
|
|
12
14
|
* SelectItemコンポーネントのロジックを提供するComposable
|
|
15
|
+
* 状態のみを返す(スタイル情報なし)
|
|
13
16
|
*/
|
|
14
17
|
export declare const useSelectItem: (props: Ref<{
|
|
15
18
|
value: string;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { computed, inject } from "vue";
|
|
2
|
-
import { cn } from "../utils/cn.mjs";
|
|
1
|
+
import { computed, inject, readonly } from "vue";
|
|
3
2
|
import { SELECT_KEY } from "../types/select.mjs";
|
|
4
3
|
import { COMPONENT_ERRORS } from "../constants/errors.mjs";
|
|
5
4
|
export const useSelectTrigger = () => {
|
|
@@ -7,44 +6,25 @@ export const useSelectTrigger = () => {
|
|
|
7
6
|
if (!context) {
|
|
8
7
|
throw new Error(COMPONENT_ERRORS.PROVIDER_NOT_FOUND);
|
|
9
8
|
}
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
lg: "h-11 text-lg"
|
|
16
|
-
};
|
|
17
|
-
return size_map[context.size.value];
|
|
18
|
-
});
|
|
19
|
-
const base_classes = computed(
|
|
20
|
-
() => cn(
|
|
21
|
-
"flex w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2",
|
|
22
|
-
"text-sm ring-offset-background",
|
|
23
|
-
"placeholder:text-muted-foreground",
|
|
24
|
-
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
25
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
26
|
-
"[&>span]:line-clamp-1",
|
|
27
|
-
size_classes.value
|
|
28
|
-
)
|
|
29
|
-
);
|
|
9
|
+
const state = computed(() => ({
|
|
10
|
+
size: context.size.value,
|
|
11
|
+
disabled: context.disabled.value,
|
|
12
|
+
is_open: context.is_open.value
|
|
13
|
+
}));
|
|
30
14
|
return {
|
|
31
|
-
|
|
32
|
-
is_disabled
|
|
15
|
+
state: readonly(state)
|
|
33
16
|
};
|
|
34
17
|
};
|
|
35
18
|
export const useSelectContent = () => {
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2"
|
|
44
|
-
)
|
|
45
|
-
);
|
|
19
|
+
const context = inject(SELECT_KEY, null);
|
|
20
|
+
if (!context) {
|
|
21
|
+
throw new Error(COMPONENT_ERRORS.PROVIDER_NOT_FOUND);
|
|
22
|
+
}
|
|
23
|
+
const state = computed(() => ({
|
|
24
|
+
is_open: context.is_open.value
|
|
25
|
+
}));
|
|
46
26
|
return {
|
|
47
|
-
|
|
27
|
+
state: readonly(state)
|
|
48
28
|
};
|
|
49
29
|
};
|
|
50
30
|
export const useSelectItem = (props) => {
|
|
@@ -52,20 +32,11 @@ export const useSelectItem = (props) => {
|
|
|
52
32
|
if (!context) {
|
|
53
33
|
throw new Error(COMPONENT_ERRORS.PROVIDER_NOT_FOUND);
|
|
54
34
|
}
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2",
|
|
60
|
-
"text-sm outline-none",
|
|
61
|
-
"focus:bg-accent focus:text-accent-foreground",
|
|
62
|
-
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
63
|
-
is_selected.value && "bg-accent text-accent-foreground"
|
|
64
|
-
)
|
|
65
|
-
);
|
|
35
|
+
const state = computed(() => ({
|
|
36
|
+
selected: context.model_value.value === props.value.value,
|
|
37
|
+
disabled: props.value.disabled ?? false
|
|
38
|
+
}));
|
|
66
39
|
return {
|
|
67
|
-
|
|
68
|
-
is_selected,
|
|
69
|
-
is_disabled
|
|
40
|
+
state: readonly(state)
|
|
70
41
|
};
|
|
71
42
|
};
|
|
@@ -2,6 +2,7 @@ import { type Ref } from "vue";
|
|
|
2
2
|
import type { SwitchProps, SwitchReturn } from "../types/switch";
|
|
3
3
|
/**
|
|
4
4
|
* Switchコンポーネントのロジックを提供するComposable
|
|
5
|
-
*
|
|
5
|
+
* 状態とARIA属性のみを返す(スタイル情報なし)
|
|
6
|
+
* スタイルは StyleAdapter または外部のスタイルパッケージが担当
|
|
6
7
|
*/
|
|
7
8
|
export declare const useSwitch: (props: Ref<SwitchProps>, checked: Ref<boolean>) => SwitchReturn;
|
|
@@ -1,50 +1,17 @@
|
|
|
1
|
-
import { computed } from "vue";
|
|
2
|
-
import { cn } from "../utils/cn.mjs";
|
|
1
|
+
import { computed, readonly } from "vue";
|
|
3
2
|
export const useSwitch = (props, checked) => {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
lg: "h-7 w-14"
|
|
10
|
-
};
|
|
11
|
-
return size_map[props.value.size ?? "md"];
|
|
12
|
-
});
|
|
13
|
-
const track_classes = computed(
|
|
14
|
-
() => cn(
|
|
15
|
-
"peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent",
|
|
16
|
-
"transition-colors",
|
|
17
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
18
|
-
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
19
|
-
"data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
|
20
|
-
track_size_classes.value
|
|
21
|
-
)
|
|
22
|
-
);
|
|
23
|
-
const thumb_size_classes = computed(() => {
|
|
24
|
-
const size_map = {
|
|
25
|
-
sm: "h-4 w-4 data-[state=checked]:translate-x-4",
|
|
26
|
-
md: "h-5 w-5 data-[state=checked]:translate-x-5",
|
|
27
|
-
lg: "h-6 w-6 data-[state=checked]:translate-x-7"
|
|
28
|
-
};
|
|
29
|
-
return size_map[props.value.size ?? "md"];
|
|
30
|
-
});
|
|
31
|
-
const thumb_classes = computed(
|
|
32
|
-
() => cn(
|
|
33
|
-
"pointer-events-none block rounded-full bg-background shadow-lg ring-0",
|
|
34
|
-
"transition-transform",
|
|
35
|
-
"data-[state=unchecked]:translate-x-0",
|
|
36
|
-
thumb_size_classes.value
|
|
37
|
-
)
|
|
38
|
-
);
|
|
3
|
+
const state = computed(() => ({
|
|
4
|
+
size: props.value.size ?? "md",
|
|
5
|
+
disabled: props.value.disabled ?? false,
|
|
6
|
+
checked: checked.value
|
|
7
|
+
}));
|
|
39
8
|
const aria_attributes = computed(() => ({
|
|
40
9
|
role: "switch",
|
|
41
|
-
"aria-checked":
|
|
42
|
-
"aria-disabled":
|
|
10
|
+
"aria-checked": state.value.checked,
|
|
11
|
+
"aria-disabled": state.value.disabled || void 0
|
|
43
12
|
}));
|
|
44
13
|
return {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
is_disabled,
|
|
48
|
-
aria_attributes
|
|
14
|
+
state: readonly(state),
|
|
15
|
+
aria_attributes: readonly(aria_attributes)
|
|
49
16
|
};
|
|
50
17
|
};
|