@novi-ui/tactile 0.1.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/README.md +195 -0
- package/dist/accordion/accordion.d.mts +31 -0
- package/dist/accordion/accordion.d.mts.map +1 -0
- package/dist/accordion/accordion.mjs +88 -0
- package/dist/accordion/accordion.mjs.map +1 -0
- package/dist/accordion/accordion.styles.d.mts +61 -0
- package/dist/accordion/accordion.styles.d.mts.map +1 -0
- package/dist/accordion/accordion.styles.mjs +83 -0
- package/dist/accordion/accordion.styles.mjs.map +1 -0
- package/dist/accordion/index.d.mts +3 -0
- package/dist/avatar/avatar.d.mts +19 -0
- package/dist/avatar/avatar.d.mts.map +1 -0
- package/dist/avatar/avatar.mjs +57 -0
- package/dist/avatar/avatar.mjs.map +1 -0
- package/dist/avatar/avatar.styles.d.mts +49 -0
- package/dist/avatar/avatar.styles.d.mts.map +1 -0
- package/dist/avatar/avatar.styles.mjs +45 -0
- package/dist/avatar/avatar.styles.mjs.map +1 -0
- package/dist/avatar/index.d.mts +3 -0
- package/dist/badge/badge.d.mts +15 -0
- package/dist/badge/badge.d.mts.map +1 -0
- package/dist/badge/badge.mjs +39 -0
- package/dist/badge/badge.mjs.map +1 -0
- package/dist/badge/badge.styles.d.mts +67 -0
- package/dist/badge/badge.styles.d.mts.map +1 -0
- package/dist/badge/badge.styles.mjs +99 -0
- package/dist/badge/badge.styles.mjs.map +1 -0
- package/dist/badge/index.d.mts +3 -0
- package/dist/breadcrumbs/breadcrumbs.d.mts +33 -0
- package/dist/breadcrumbs/breadcrumbs.d.mts.map +1 -0
- package/dist/breadcrumbs/breadcrumbs.mjs +79 -0
- package/dist/breadcrumbs/breadcrumbs.mjs.map +1 -0
- package/dist/breadcrumbs/breadcrumbs.styles.d.mts +46 -0
- package/dist/breadcrumbs/breadcrumbs.styles.d.mts.map +1 -0
- package/dist/breadcrumbs/breadcrumbs.styles.mjs +38 -0
- package/dist/breadcrumbs/breadcrumbs.styles.mjs.map +1 -0
- package/dist/breadcrumbs/index.d.mts +3 -0
- package/dist/button/button.d.mts +17 -0
- package/dist/button/button.d.mts.map +1 -0
- package/dist/button/button.mjs +78 -0
- package/dist/button/button.mjs.map +1 -0
- package/dist/button/button.styles.d.mts +82 -0
- package/dist/button/button.styles.d.mts.map +1 -0
- package/dist/button/button.styles.mjs +136 -0
- package/dist/button/button.styles.mjs.map +1 -0
- package/dist/button/index.d.mts +3 -0
- package/dist/card/card.d.mts +51 -0
- package/dist/card/card.d.mts.map +1 -0
- package/dist/card/card.mjs +96 -0
- package/dist/card/card.mjs.map +1 -0
- package/dist/card/card.styles.d.mts +70 -0
- package/dist/card/card.styles.d.mts.map +1 -0
- package/dist/card/card.styles.mjs +61 -0
- package/dist/card/card.styles.mjs.map +1 -0
- package/dist/card/index.d.mts +3 -0
- package/dist/checkbox/checkbox.d.mts +24 -0
- package/dist/checkbox/checkbox.d.mts.map +1 -0
- package/dist/checkbox/checkbox.mjs +124 -0
- package/dist/checkbox/checkbox.mjs.map +1 -0
- package/dist/checkbox/checkbox.styles.d.mts +111 -0
- package/dist/checkbox/checkbox.styles.d.mts.map +1 -0
- package/dist/checkbox/checkbox.styles.mjs +99 -0
- package/dist/checkbox/checkbox.styles.mjs.map +1 -0
- package/dist/checkbox/index.d.mts +3 -0
- package/dist/index.d.mts +61 -0
- package/dist/index.mjs +42 -0
- package/dist/input/index.d.mts +3 -0
- package/dist/input/input.d.mts +20 -0
- package/dist/input/input.d.mts.map +1 -0
- package/dist/input/input.mjs +86 -0
- package/dist/input/input.mjs.map +1 -0
- package/dist/input/input.styles.d.mts +81 -0
- package/dist/input/input.styles.d.mts.map +1 -0
- package/dist/input/input.styles.mjs +88 -0
- package/dist/input/input.styles.mjs.map +1 -0
- package/dist/menu/index.d.mts +3 -0
- package/dist/menu/menu.d.mts +62 -0
- package/dist/menu/menu.d.mts.map +1 -0
- package/dist/menu/menu.mjs +115 -0
- package/dist/menu/menu.mjs.map +1 -0
- package/dist/menu/menu.styles.d.mts +90 -0
- package/dist/menu/menu.styles.d.mts.map +1 -0
- package/dist/menu/menu.styles.mjs +42 -0
- package/dist/menu/menu.styles.mjs.map +1 -0
- package/dist/modal/index.d.mts +3 -0
- package/dist/modal/modal.d.mts +55 -0
- package/dist/modal/modal.d.mts.map +1 -0
- package/dist/modal/modal.mjs +122 -0
- package/dist/modal/modal.mjs.map +1 -0
- package/dist/modal/modal.styles.d.mts +58 -0
- package/dist/modal/modal.styles.d.mts.map +1 -0
- package/dist/modal/modal.styles.mjs +91 -0
- package/dist/modal/modal.styles.mjs.map +1 -0
- package/dist/popover/index.d.mts +3 -0
- package/dist/popover/popover.d.mts +40 -0
- package/dist/popover/popover.d.mts.map +1 -0
- package/dist/popover/popover.mjs +86 -0
- package/dist/popover/popover.mjs.map +1 -0
- package/dist/popover/popover.styles.d.mts +81 -0
- package/dist/popover/popover.styles.d.mts.map +1 -0
- package/dist/popover/popover.styles.mjs +53 -0
- package/dist/popover/popover.styles.mjs.map +1 -0
- package/dist/progress/index.d.mts +3 -0
- package/dist/progress/progress.d.mts +14 -0
- package/dist/progress/progress.d.mts.map +1 -0
- package/dist/progress/progress.mjs +54 -0
- package/dist/progress/progress.mjs.map +1 -0
- package/dist/progress/progress.styles.d.mts +70 -0
- package/dist/progress/progress.styles.d.mts.map +1 -0
- package/dist/progress/progress.styles.mjs +54 -0
- package/dist/progress/progress.styles.mjs.map +1 -0
- package/dist/radio/index.d.mts +3 -0
- package/dist/radio/radio.d.mts +22 -0
- package/dist/radio/radio.d.mts.map +1 -0
- package/dist/radio/radio.mjs +95 -0
- package/dist/radio/radio.mjs.map +1 -0
- package/dist/radio/radio.styles.d.mts +111 -0
- package/dist/radio/radio.styles.d.mts.map +1 -0
- package/dist/radio/radio.styles.mjs +95 -0
- package/dist/radio/radio.styles.mjs.map +1 -0
- package/dist/select/index.d.mts +3 -0
- package/dist/select/select.d.mts +34 -0
- package/dist/select/select.d.mts.map +1 -0
- package/dist/select/select.mjs +136 -0
- package/dist/select/select.mjs.map +1 -0
- package/dist/select/select.styles.d.mts +85 -0
- package/dist/select/select.styles.d.mts.map +1 -0
- package/dist/select/select.styles.mjs +109 -0
- package/dist/select/select.styles.mjs.map +1 -0
- package/dist/skeleton/index.d.mts +3 -0
- package/dist/skeleton/skeleton.d.mts +15 -0
- package/dist/skeleton/skeleton.d.mts.map +1 -0
- package/dist/skeleton/skeleton.mjs +26 -0
- package/dist/skeleton/skeleton.mjs.map +1 -0
- package/dist/skeleton/skeleton.styles.d.mts +31 -0
- package/dist/skeleton/skeleton.styles.d.mts.map +1 -0
- package/dist/skeleton/skeleton.styles.mjs +22 -0
- package/dist/skeleton/skeleton.styles.mjs.map +1 -0
- package/dist/spinner/index.d.mts +3 -0
- package/dist/spinner/spinner.d.mts +15 -0
- package/dist/spinner/spinner.d.mts.map +1 -0
- package/dist/spinner/spinner.mjs +55 -0
- package/dist/spinner/spinner.mjs.map +1 -0
- package/dist/spinner/spinner.styles.d.mts +46 -0
- package/dist/spinner/spinner.styles.d.mts.map +1 -0
- package/dist/spinner/spinner.styles.mjs +37 -0
- package/dist/spinner/spinner.styles.mjs.map +1 -0
- package/dist/styles/focus-ring.mjs +23 -0
- package/dist/styles/focus-ring.mjs.map +1 -0
- package/dist/styles/tap-target.mjs +25 -0
- package/dist/styles/tap-target.mjs.map +1 -0
- package/dist/switch/index.d.mts +3 -0
- package/dist/switch/switch.d.mts +17 -0
- package/dist/switch/switch.d.mts.map +1 -0
- package/dist/switch/switch.mjs +57 -0
- package/dist/switch/switch.mjs.map +1 -0
- package/dist/switch/switch.styles.d.mts +58 -0
- package/dist/switch/switch.styles.d.mts.map +1 -0
- package/dist/switch/switch.styles.mjs +79 -0
- package/dist/switch/switch.styles.mjs.map +1 -0
- package/dist/tabs/index.d.mts +3 -0
- package/dist/tabs/tabs.d.mts +57 -0
- package/dist/tabs/tabs.d.mts.map +1 -0
- package/dist/tabs/tabs.mjs +91 -0
- package/dist/tabs/tabs.mjs.map +1 -0
- package/dist/tabs/tabs.styles.d.mts +58 -0
- package/dist/tabs/tabs.styles.d.mts.map +1 -0
- package/dist/tabs/tabs.styles.mjs +92 -0
- package/dist/tabs/tabs.styles.mjs.map +1 -0
- package/dist/tactile.css +528 -0
- package/dist/tactile.scoped.css +528 -0
- package/dist/textarea/index.d.mts +3 -0
- package/dist/textarea/textarea.d.mts +15 -0
- package/dist/textarea/textarea.d.mts.map +1 -0
- package/dist/textarea/textarea.mjs +70 -0
- package/dist/textarea/textarea.mjs.map +1 -0
- package/dist/textarea/textarea.styles.d.mts +73 -0
- package/dist/textarea/textarea.styles.d.mts.map +1 -0
- package/dist/textarea/textarea.styles.mjs +83 -0
- package/dist/textarea/textarea.styles.mjs.map +1 -0
- package/dist/toast/index.d.mts +3 -0
- package/dist/toast/toast.d.mts +38 -0
- package/dist/toast/toast.d.mts.map +1 -0
- package/dist/toast/toast.mjs +86 -0
- package/dist/toast/toast.mjs.map +1 -0
- package/dist/toast/toast.styles.d.mts +61 -0
- package/dist/toast/toast.styles.d.mts.map +1 -0
- package/dist/toast/toast.styles.mjs +59 -0
- package/dist/toast/toast.styles.mjs.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { VariantMap } from "@novi-ui/core";
|
|
2
|
+
//#region src/input/input.styles.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* Input のスタイル定義。
|
|
5
|
+
*
|
|
6
|
+
* 拡張は `base` ではなく `slots` で行う(slot ベースの定義のため)。
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* import { inputStyles } from '@novi-ui/tactile'
|
|
10
|
+
* import { tv } from 'tailwind-variants'
|
|
11
|
+
*
|
|
12
|
+
* const myInput = tv({
|
|
13
|
+
* extend: inputStyles,
|
|
14
|
+
* slots: { inputWrapper: 'font-mono' },
|
|
15
|
+
* })
|
|
16
|
+
*/
|
|
17
|
+
declare const inputStyles: import("tailwind-variants").TVReturnType<{
|
|
18
|
+
variant: VariantMap<"solid" | "outline" | "soft" | "ghost" | "plain", {
|
|
19
|
+
inputWrapper: string;
|
|
20
|
+
}>;
|
|
21
|
+
size: VariantMap<"sm" | "md" | "lg", {
|
|
22
|
+
inputWrapper: string;
|
|
23
|
+
input: string;
|
|
24
|
+
}>;
|
|
25
|
+
radius: VariantMap<"sm" | "md" | "lg" | "none" | "full", {
|
|
26
|
+
inputWrapper: string;
|
|
27
|
+
}>;
|
|
28
|
+
}, {
|
|
29
|
+
root: string;
|
|
30
|
+
label: string;
|
|
31
|
+
inputWrapper: string;
|
|
32
|
+
input: string;
|
|
33
|
+
startContent: string;
|
|
34
|
+
endContent: string;
|
|
35
|
+
description: string;
|
|
36
|
+
errorMessage: string;
|
|
37
|
+
}, undefined, {
|
|
38
|
+
variant: VariantMap<"solid" | "outline" | "soft" | "ghost" | "plain", {
|
|
39
|
+
inputWrapper: string;
|
|
40
|
+
}>;
|
|
41
|
+
size: VariantMap<"sm" | "md" | "lg", {
|
|
42
|
+
inputWrapper: string;
|
|
43
|
+
input: string;
|
|
44
|
+
}>;
|
|
45
|
+
radius: VariantMap<"sm" | "md" | "lg" | "none" | "full", {
|
|
46
|
+
inputWrapper: string;
|
|
47
|
+
}>;
|
|
48
|
+
}, {
|
|
49
|
+
root: string;
|
|
50
|
+
label: string;
|
|
51
|
+
inputWrapper: string;
|
|
52
|
+
input: string;
|
|
53
|
+
startContent: string;
|
|
54
|
+
endContent: string;
|
|
55
|
+
description: string;
|
|
56
|
+
errorMessage: string;
|
|
57
|
+
}, import("tailwind-variants").TVReturnTypeLike<{
|
|
58
|
+
variant: VariantMap<"solid" | "outline" | "soft" | "ghost" | "plain", {
|
|
59
|
+
inputWrapper: string;
|
|
60
|
+
}>;
|
|
61
|
+
size: VariantMap<"sm" | "md" | "lg", {
|
|
62
|
+
inputWrapper: string;
|
|
63
|
+
input: string;
|
|
64
|
+
}>;
|
|
65
|
+
radius: VariantMap<"sm" | "md" | "lg" | "none" | "full", {
|
|
66
|
+
inputWrapper: string;
|
|
67
|
+
}>;
|
|
68
|
+
}, {
|
|
69
|
+
root: string;
|
|
70
|
+
label: string;
|
|
71
|
+
inputWrapper: string;
|
|
72
|
+
input: string;
|
|
73
|
+
startContent: string;
|
|
74
|
+
endContent: string;
|
|
75
|
+
description: string;
|
|
76
|
+
errorMessage: string;
|
|
77
|
+
}>>;
|
|
78
|
+
type InputStyleProps = Parameters<typeof inputStyles>[0];
|
|
79
|
+
//#endregion
|
|
80
|
+
export { InputStyleProps, inputStyles };
|
|
81
|
+
//# sourceMappingURL=input.styles.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.styles.d.mts","names":[],"sources":["../../src/input/input.styles.ts"],"mappings":";;;;;;;;;;;;;;;;cA2Ga,yCAAW;;IAvD+B;;;IA2BN;IAAe;;;IAMX;;;;;;;;;;;;;IAjCE;;;IA2BN;IAAe;;;IAMX;;;;;;;;;;;;;IAjCE;;;IA2BN;IAAe;;;IAMX;;;;;;;;;;;;KA4BzC,kBAAkB,kBAAkB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { disabledState, focusRing } from "../styles/focus-ring.mjs";
|
|
2
|
+
import { tv } from "tailwind-variants";
|
|
3
|
+
//#region src/input/input.styles.ts
|
|
4
|
+
/**
|
|
5
|
+
* Tactile の Input は**指で触る前提の面**。境界線ではなく影で持ち上げ、
|
|
6
|
+
* 入力の文字は 16px を下回らせない(iOS Safari が自動ズームしてレイアウトが飛ぶ)。
|
|
7
|
+
*/
|
|
8
|
+
const slots = {
|
|
9
|
+
root: "flex flex-col gap-1.5",
|
|
10
|
+
label: "text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]",
|
|
11
|
+
inputWrapper: [
|
|
12
|
+
"text-[var(--novi-color-fg)]",
|
|
13
|
+
"flex items-center gap-2 w-full",
|
|
14
|
+
"bg-[var(--novi-color-surface)]",
|
|
15
|
+
"shadow-[var(--novi-shadow-sm)]",
|
|
16
|
+
"rounded-[var(--novi-radius-md)]",
|
|
17
|
+
"transition-[opacity,box-shadow]",
|
|
18
|
+
"duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]",
|
|
19
|
+
"data-[invalid]:ring-1 data-[invalid]:ring-[var(--novi-color-danger)]",
|
|
20
|
+
focusRing,
|
|
21
|
+
disabledState
|
|
22
|
+
].join(" "),
|
|
23
|
+
input: [
|
|
24
|
+
"w-full min-w-0 bg-transparent outline-none",
|
|
25
|
+
"text-[var(--novi-color-fg)]",
|
|
26
|
+
"placeholder:text-[var(--novi-color-muted)]"
|
|
27
|
+
].join(" "),
|
|
28
|
+
startContent: "shrink-0 inline-flex text-[var(--novi-color-muted)]",
|
|
29
|
+
endContent: "shrink-0 inline-flex text-[var(--novi-color-muted)]",
|
|
30
|
+
description: "text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]",
|
|
31
|
+
errorMessage: "text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]"
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Input のスタイル定義。
|
|
35
|
+
*
|
|
36
|
+
* 拡張は `base` ではなく `slots` で行う(slot ベースの定義のため)。
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* import { inputStyles } from '@novi-ui/tactile'
|
|
40
|
+
* import { tv } from 'tailwind-variants'
|
|
41
|
+
*
|
|
42
|
+
* const myInput = tv({
|
|
43
|
+
* extend: inputStyles,
|
|
44
|
+
* slots: { inputWrapper: 'font-mono' },
|
|
45
|
+
* })
|
|
46
|
+
*/
|
|
47
|
+
const inputStyles = tv({
|
|
48
|
+
slots,
|
|
49
|
+
variants: {
|
|
50
|
+
variant: {
|
|
51
|
+
solid: { inputWrapper: "bg-[var(--novi-color-surface)] shadow-[var(--novi-shadow-sm)]" },
|
|
52
|
+
outline: { inputWrapper: "bg-transparent shadow-[var(--novi-shadow-none)] ring-1 ring-[var(--novi-color-border-strong)]" },
|
|
53
|
+
soft: { inputWrapper: "bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]" },
|
|
54
|
+
ghost: { inputWrapper: "bg-transparent shadow-[var(--novi-shadow-none)]" },
|
|
55
|
+
plain: { inputWrapper: "bg-transparent shadow-[var(--novi-shadow-none)] rounded-[var(--novi-radius-none)] border-b border-[var(--novi-color-border-strong)]" }
|
|
56
|
+
},
|
|
57
|
+
size: {
|
|
58
|
+
sm: {
|
|
59
|
+
inputWrapper: "h-10 px-3",
|
|
60
|
+
input: "text-[length:var(--novi-text-base)]"
|
|
61
|
+
},
|
|
62
|
+
md: {
|
|
63
|
+
inputWrapper: "h-12 px-4",
|
|
64
|
+
input: "text-[length:var(--novi-text-base)]"
|
|
65
|
+
},
|
|
66
|
+
lg: {
|
|
67
|
+
inputWrapper: "h-14 px-5",
|
|
68
|
+
input: "text-[length:var(--novi-text-base)]"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
radius: {
|
|
72
|
+
none: { inputWrapper: "rounded-[var(--novi-radius-none)]" },
|
|
73
|
+
sm: { inputWrapper: "rounded-[var(--novi-radius-sm)]" },
|
|
74
|
+
md: { inputWrapper: "rounded-[var(--novi-radius-md)]" },
|
|
75
|
+
lg: { inputWrapper: "rounded-[var(--novi-radius-lg)]" },
|
|
76
|
+
full: { inputWrapper: "rounded-[var(--novi-radius-full)]" }
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
defaultVariants: {
|
|
80
|
+
variant: "outline",
|
|
81
|
+
size: "md",
|
|
82
|
+
radius: "md"
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
//#endregion
|
|
86
|
+
export { inputStyles };
|
|
87
|
+
|
|
88
|
+
//# sourceMappingURL=input.styles.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.styles.mjs","names":[],"sources":["../../src/input/input.styles.ts"],"sourcesContent":["import type {\n inputRequiredSlots,\n inputSlots,\n NoviRadius,\n NoviSize,\n NoviVariant,\n SlotMap,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Input は**指で触る前提の面**。境界線ではなく影で持ち上げ、\n * 入力の文字は 16px を下回らせない(iOS Safari が自動ズームしてレイアウトが飛ぶ)。\n */\n// 型注釈ではなく satisfies(ADR-R5)。任意 slot が呼べなくなるのを防ぐ。\nconst slots = {\n root: 'flex flex-col gap-1.5',\n // ラベルは常に上・左揃え。プレースホルダをラベル代わりにしない\n label: 'text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]',\n // RAC の Group を使う。Group は data-focus-visible / data-invalid を出すので、\n // Button と同じ focusRing 定義がそのまま使える(属性名を書き換える必要がない)。\n inputWrapper: [\n 'text-[var(--novi-color-fg)]',\n 'flex items-center gap-2 w-full',\n 'bg-[var(--novi-color-surface)]',\n 'shadow-[var(--novi-shadow-sm)]',\n 'rounded-[var(--novi-radius-md)]',\n 'transition-[opacity,box-shadow]',\n 'duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[invalid]:ring-1 data-[invalid]:ring-[var(--novi-color-danger)]',\n focusRing,\n disabledState,\n ].join(' '),\n input: [\n 'w-full min-w-0 bg-transparent outline-none',\n 'text-[var(--novi-color-fg)]',\n 'placeholder:text-[var(--novi-color-muted)]',\n ].join(' '),\n startContent: 'shrink-0 inline-flex text-[var(--novi-color-muted)]',\n endContent: 'shrink-0 inline-flex text-[var(--novi-color-muted)]',\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n // 色だけに頼らずテキストを必ず伴う(WCAG 1.4.1)\n errorMessage: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]',\n} satisfies SlotMap<typeof inputSlots, (typeof inputRequiredSlots)[number]>\n\n/**\n * core の語彙定義(solid=塗りつぶしで最も強い / soft=淡い背景で境界線なし)に従って\n * 5つを視覚的に区別する。同じクラスを生む variant があると\n * 「テーマを切り替えても API が同じ」という約束が形だけになる。\n */\nconst variant: VariantMap<NoviVariant, { inputWrapper: string }> = {\n // 持ち上がった面。最も強い\n solid: { inputWrapper: 'bg-[var(--novi-color-surface)] shadow-[var(--novi-shadow-sm)]' },\n // 輪郭のみ。影を持たない\n outline: {\n inputWrapper:\n 'bg-transparent shadow-[var(--novi-shadow-none)] ring-1 ring-[var(--novi-color-border-strong)]',\n },\n // 沈んだ面。輪郭も影も持たない\n soft: { inputWrapper: 'bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]' },\n // 地に溶ける。表を詰めて並べるときに面を増やさない\n ghost: { inputWrapper: 'bg-transparent shadow-[var(--novi-shadow-none)]' },\n // 完全に無装飾。インライン編集などで使う\n // 下線だけ残す。ghost(完全に地へ溶ける)と見分けがつかなくならないようにする\n plain: {\n inputWrapper:\n 'bg-transparent shadow-[var(--novi-shadow-none)] rounded-[var(--novi-radius-none)] border-b border-[var(--novi-color-border-strong)]',\n },\n}\n\n/**\n * 高さは Button と揃える。40 / 48 / 56px。\n *\n * **入力の文字は全段 base(17px)** にする。`sm` でも小さくしないのは、\n * iOS Safari が 16px 未満の入力欄でフォーカス時にページごと拡大するため。\n * 視覚的な軽さは高さと余白で作る(FR-08 / AC-01-3)。\n */\nconst size: VariantMap<NoviSize, { inputWrapper: string; input: string }> = {\n sm: { inputWrapper: 'h-10 px-3', input: 'text-[length:var(--novi-text-base)]' },\n md: { inputWrapper: 'h-12 px-4', input: 'text-[length:var(--novi-text-base)]' },\n lg: { inputWrapper: 'h-14 px-5', input: 'text-[length:var(--novi-text-base)]' },\n}\n\nconst radius: VariantMap<NoviRadius, { inputWrapper: string }> = {\n none: { inputWrapper: 'rounded-[var(--novi-radius-none)]' },\n sm: { inputWrapper: 'rounded-[var(--novi-radius-sm)]' },\n md: { inputWrapper: 'rounded-[var(--novi-radius-md)]' },\n lg: { inputWrapper: 'rounded-[var(--novi-radius-lg)]' },\n full: { inputWrapper: 'rounded-[var(--novi-radius-full)]' },\n}\n\n/**\n * Input のスタイル定義。\n *\n * 拡張は `base` ではなく `slots` で行う(slot ベースの定義のため)。\n *\n * @example\n * import { inputStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const myInput = tv({\n * extend: inputStyles,\n * slots: { inputWrapper: 'font-mono' },\n * })\n */\nexport const inputStyles = tv({\n slots,\n variants: { variant, size, radius },\n defaultVariants: { variant: 'outline', size: 'md', radius: 'md' },\n})\n\nexport type InputStyleProps = Parameters<typeof inputStyles>[0]\n"],"mappings":";;;;;;;AAiBA,MAAM,QAAQ;CACZ,MAAM;CAEN,OAAO;CAGP,cAAc;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;EACL;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,cAAc;CACd,YAAY;CACZ,aAAa;CAEb,cAAc;AAChB;;;;;;;;;;;;;;;AA8DA,MAAa,cAAc,GAAG;CAC5B;CACA,UAAU;EAAE;GAvDZ,OAAO,EAAE,cAAc,gEAAgE;GAEvF,SAAS,EACP,cACE,gGACJ;GAEA,MAAM,EAAE,cAAc,iEAAiE;GAEvF,OAAO,EAAE,cAAc,kDAAkD;GAGzE,OAAO,EACL,cACE,sIACJ;EAwCY;EAAS;GA7BrB,IAAI;IAAE,cAAc;IAAa,OAAO;GAAsC;GAC9E,IAAI;IAAE,cAAc;IAAa,OAAO;GAAsC;GAC9E,IAAI;IAAE,cAAc;IAAa,OAAO;GAAsC;EA2BzD;EAAM;GAvB3B,MAAM,EAAE,cAAc,oCAAoC;GAC1D,IAAI,EAAE,cAAc,kCAAkC;GACtD,IAAI,EAAE,cAAc,kCAAkC;GACtD,IAAI,EAAE,cAAc,kCAAkC;GACtD,MAAM,EAAE,cAAc,oCAAoC;EAmB/B;CAAO;CAClC,iBAAiB;EAAE,SAAS;EAAW,MAAM;EAAM,QAAQ;CAAK;AAClE,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Menu, MenuItemComponent, MenuItemProps, MenuSection, MenuSeparator } from "./menu.mjs";
|
|
2
|
+
import { MenuStyleProps, menuStyles } from "./menu.styles.mjs";
|
|
3
|
+
export { Menu, MenuItemComponent as MenuItem, type MenuItemProps, MenuSection, MenuSeparator, type MenuStyleProps, menuStyles };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { MenuProps } from "@novi-ui/core";
|
|
3
|
+
//#region src/menu/menu.d.ts
|
|
4
|
+
interface MenuItemProps {
|
|
5
|
+
/** 選ばれたときに `onAction` へ渡る値 */
|
|
6
|
+
id: string;
|
|
7
|
+
isDisabled?: boolean;
|
|
8
|
+
/** 補足説明。項目名だけで足りないときに使う */
|
|
9
|
+
description?: ReactNode;
|
|
10
|
+
/** キーボードショートカットの表示。桁が揃うよう等幅数字にしている */
|
|
11
|
+
shortcut?: ReactNode;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Menu の項目。
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* <MenuItem id="rename" shortcut="⌘R">名前を変更</MenuItem>
|
|
20
|
+
*/
|
|
21
|
+
declare function MenuItemComponent({ id, isDisabled, description, shortcut, children, className }: MenuItemProps): import("react").JSX.Element;
|
|
22
|
+
/**
|
|
23
|
+
* Menu の区切り線。
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* <MenuSeparator />
|
|
27
|
+
*/
|
|
28
|
+
declare function MenuSeparator({ className }: {
|
|
29
|
+
className?: string;
|
|
30
|
+
}): import("react").JSX.Element;
|
|
31
|
+
/**
|
|
32
|
+
* Menu の見出し付きグループ。項目が多いときに種類でまとめる。
|
|
33
|
+
*
|
|
34
|
+
* 語彙に `section` / `sectionLabel` があるのに実装がなく、
|
|
35
|
+
* T-41 の slot 語彙レビューで漏れが判明したもの。
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* <MenuSection title="ファイル">
|
|
39
|
+
* <MenuItem id="rename">名前を変更</MenuItem>
|
|
40
|
+
* </MenuSection>
|
|
41
|
+
*/
|
|
42
|
+
declare function MenuSection({ title, children, className }: {
|
|
43
|
+
title: ReactNode;
|
|
44
|
+
children?: ReactNode;
|
|
45
|
+
className?: string;
|
|
46
|
+
}): import("react").JSX.Element;
|
|
47
|
+
/**
|
|
48
|
+
* トリガーから開く操作の一覧。矢印キーで移動、Escape で閉じる。
|
|
49
|
+
*
|
|
50
|
+
* 最初の子要素がトリガーになる。残りが項目として扱われる。
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* <Menu onAction={(key) => run(key)}>
|
|
54
|
+
* <Button>操作</Button>
|
|
55
|
+
* <MenuItem id="rename">名前を変更</MenuItem>
|
|
56
|
+
* <MenuItem id="delete">削除</MenuItem>
|
|
57
|
+
* </Menu>
|
|
58
|
+
*/
|
|
59
|
+
declare function Menu({ placement, offset, isOpen, defaultOpen, onOpenChange, onAction, disabledKeys, children, className, classNames, id }: MenuProps): import("react").JSX.Element;
|
|
60
|
+
//#endregion
|
|
61
|
+
export { Menu, MenuItemComponent, MenuItemProps, MenuSection, MenuSeparator };
|
|
62
|
+
//# sourceMappingURL=menu.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.d.mts","names":[],"sources":["../../src/menu/menu.tsx"],"mappings":";;;UAeiB;;EAEf;EACA;;EAEA,cAAc;;EAEd,WAAW;EACX,WAAW;EACX;;;;;;;;iBASc,oBACd,IACA,YACA,aACA,UACA,UACA,aACC,gCAAa,IAAA;;;;;;;iBAoCA,gBAAgB;EAAe;oBAAoB,IAAA;;;;;;;;;;;;iBAiBnD,cACd,OACA,UACA;EAEA,OAAO;EACP,WAAW;EACX;oBACD,IAAA;;;;;;;;;;;;;iBAyBe,OACd,WACA,QACA,QACA,aACA,cACA,UACA,cACA,UACA,WACA,YACA,MACC,4BAAS,IAAA"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { menuStyles } from "./menu.styles.mjs";
|
|
3
|
+
import { Header, Menu, MenuItem, MenuSection, MenuTrigger, Popover, Separator } from "react-aria-components";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
//#region src/menu/menu.tsx
|
|
6
|
+
/**
|
|
7
|
+
* Menu の項目。
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* <MenuItem id="rename" shortcut="⌘R">名前を変更</MenuItem>
|
|
11
|
+
*/
|
|
12
|
+
function MenuItemComponent({ id, isDisabled, description, shortcut, children, className }) {
|
|
13
|
+
const s = menuStyles();
|
|
14
|
+
return /* @__PURE__ */ jsxs(MenuItem, {
|
|
15
|
+
id,
|
|
16
|
+
isDisabled,
|
|
17
|
+
textValue: typeof children === "string" ? children : void 0,
|
|
18
|
+
"data-slot": "item",
|
|
19
|
+
className: s.item({ class: className }),
|
|
20
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
21
|
+
className: "flex flex-col min-w-0",
|
|
22
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
23
|
+
"data-slot": "itemLabel",
|
|
24
|
+
className: s.itemLabel(),
|
|
25
|
+
children
|
|
26
|
+
}), description !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
27
|
+
"data-slot": "itemDescription",
|
|
28
|
+
className: s.itemDescription(),
|
|
29
|
+
children: description
|
|
30
|
+
})]
|
|
31
|
+
}), shortcut !== void 0 && /* @__PURE__ */ jsx("span", {
|
|
32
|
+
"data-slot": "itemShortcut",
|
|
33
|
+
className: s.itemShortcut(),
|
|
34
|
+
children: shortcut
|
|
35
|
+
})]
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Menu の区切り線。
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* <MenuSeparator />
|
|
43
|
+
*/
|
|
44
|
+
function MenuSeparator({ className }) {
|
|
45
|
+
return /* @__PURE__ */ jsx(Separator, {
|
|
46
|
+
"data-slot": "separator",
|
|
47
|
+
className: menuStyles().separator({ class: className })
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Menu の見出し付きグループ。項目が多いときに種類でまとめる。
|
|
52
|
+
*
|
|
53
|
+
* 語彙に `section` / `sectionLabel` があるのに実装がなく、
|
|
54
|
+
* T-41 の slot 語彙レビューで漏れが判明したもの。
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* <MenuSection title="ファイル">
|
|
58
|
+
* <MenuItem id="rename">名前を変更</MenuItem>
|
|
59
|
+
* </MenuSection>
|
|
60
|
+
*/
|
|
61
|
+
function MenuSection$1({ title, children, className }) {
|
|
62
|
+
const s = menuStyles();
|
|
63
|
+
return /* @__PURE__ */ jsxs(MenuSection, {
|
|
64
|
+
"data-slot": "section",
|
|
65
|
+
className: s.section({ class: className }),
|
|
66
|
+
children: [/* @__PURE__ */ jsx(Header, {
|
|
67
|
+
"data-slot": "sectionLabel",
|
|
68
|
+
className: s.sectionLabel(),
|
|
69
|
+
children: title
|
|
70
|
+
}), children]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* トリガーから開く操作の一覧。矢印キーで移動、Escape で閉じる。
|
|
75
|
+
*
|
|
76
|
+
* 最初の子要素がトリガーになる。残りが項目として扱われる。
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* <Menu onAction={(key) => run(key)}>
|
|
80
|
+
* <Button>操作</Button>
|
|
81
|
+
* <MenuItem id="rename">名前を変更</MenuItem>
|
|
82
|
+
* <MenuItem id="delete">削除</MenuItem>
|
|
83
|
+
* </Menu>
|
|
84
|
+
*/
|
|
85
|
+
function Menu$1({ placement = "bottom", offset = 4, isOpen, defaultOpen, onOpenChange, onAction, disabledKeys, children, className, classNames, id }) {
|
|
86
|
+
const s = menuStyles();
|
|
87
|
+
const [trigger, ...rest] = Array.isArray(children) ? children : [children];
|
|
88
|
+
return /* @__PURE__ */ jsxs(MenuTrigger, {
|
|
89
|
+
isOpen,
|
|
90
|
+
defaultOpen,
|
|
91
|
+
onOpenChange,
|
|
92
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
93
|
+
"data-slot": "trigger",
|
|
94
|
+
className: s.trigger({ class: classNames?.trigger }),
|
|
95
|
+
children: trigger
|
|
96
|
+
}), /* @__PURE__ */ jsx(Popover, {
|
|
97
|
+
placement,
|
|
98
|
+
offset,
|
|
99
|
+
"data-slot": "popover",
|
|
100
|
+
className: s.popover({ class: [className, classNames?.popover] }),
|
|
101
|
+
children: /* @__PURE__ */ jsx(Menu, {
|
|
102
|
+
id,
|
|
103
|
+
"data-slot": "list",
|
|
104
|
+
className: s.list({ class: classNames?.list }),
|
|
105
|
+
onAction: (key) => onAction?.(String(key)),
|
|
106
|
+
disabledKeys,
|
|
107
|
+
children: rest
|
|
108
|
+
})
|
|
109
|
+
})]
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
export { Menu$1 as Menu, MenuItemComponent, MenuSection$1 as MenuSection, MenuSeparator };
|
|
114
|
+
|
|
115
|
+
//# sourceMappingURL=menu.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.mjs","names":["MenuSection","RACMenuSection","Menu","RACMenu"],"sources":["../../src/menu/menu.tsx"],"sourcesContent":["'use client'\n\nimport type { MenuProps } from '@novi-ui/core'\nimport type { ReactNode } from 'react'\nimport {\n Header,\n MenuItem,\n MenuTrigger,\n Popover,\n Menu as RACMenu,\n MenuSection as RACMenuSection,\n Separator,\n} from 'react-aria-components'\nimport { menuStyles } from './menu.styles'\n\nexport interface MenuItemProps {\n /** 選ばれたときに `onAction` へ渡る値 */\n id: string\n isDisabled?: boolean\n /** 補足説明。項目名だけで足りないときに使う */\n description?: ReactNode\n /** キーボードショートカットの表示。桁が揃うよう等幅数字にしている */\n shortcut?: ReactNode\n children?: ReactNode\n className?: string\n}\n\n/**\n * Menu の項目。\n *\n * @example\n * <MenuItem id=\"rename\" shortcut=\"⌘R\">名前を変更</MenuItem>\n */\nexport function MenuItemComponent({\n id,\n isDisabled,\n description,\n shortcut,\n children,\n className,\n}: MenuItemProps) {\n const s = menuStyles()\n\n return (\n <MenuItem\n id={id}\n isDisabled={isDisabled}\n textValue={typeof children === 'string' ? children : undefined}\n data-slot=\"item\"\n className={s.item({ class: className })}\n >\n <span className=\"flex flex-col min-w-0\">\n <span data-slot=\"itemLabel\" className={s.itemLabel()}>\n {children}\n </span>\n {description !== undefined && (\n <span data-slot=\"itemDescription\" className={s.itemDescription()}>\n {description}\n </span>\n )}\n </span>\n {shortcut !== undefined && (\n <span data-slot=\"itemShortcut\" className={s.itemShortcut()}>\n {shortcut}\n </span>\n )}\n </MenuItem>\n )\n}\n\n/**\n * Menu の区切り線。\n *\n * @example\n * <MenuSeparator />\n */\nexport function MenuSeparator({ className }: { className?: string }) {\n return (\n <Separator data-slot=\"separator\" className={menuStyles().separator({ class: className })} />\n )\n}\n\n/**\n * Menu の見出し付きグループ。項目が多いときに種類でまとめる。\n *\n * 語彙に `section` / `sectionLabel` があるのに実装がなく、\n * T-41 の slot 語彙レビューで漏れが判明したもの。\n *\n * @example\n * <MenuSection title=\"ファイル\">\n * <MenuItem id=\"rename\">名前を変更</MenuItem>\n * </MenuSection>\n */\nexport function MenuSection({\n title,\n children,\n className,\n}: {\n title: ReactNode\n children?: ReactNode\n className?: string\n}) {\n const s = menuStyles()\n\n return (\n <RACMenuSection data-slot=\"section\" className={s.section({ class: className })}>\n <Header data-slot=\"sectionLabel\" className={s.sectionLabel()}>\n {title}\n </Header>\n {children}\n </RACMenuSection>\n )\n}\n\n/**\n * トリガーから開く操作の一覧。矢印キーで移動、Escape で閉じる。\n *\n * 最初の子要素がトリガーになる。残りが項目として扱われる。\n *\n * @example\n * <Menu onAction={(key) => run(key)}>\n * <Button>操作</Button>\n * <MenuItem id=\"rename\">名前を変更</MenuItem>\n * <MenuItem id=\"delete\">削除</MenuItem>\n * </Menu>\n */\nexport function Menu({\n placement = 'bottom',\n offset = 4,\n isOpen,\n defaultOpen,\n onOpenChange,\n onAction,\n disabledKeys,\n children,\n className,\n classNames,\n id,\n}: MenuProps) {\n const s = menuStyles()\n const items = Array.isArray(children) ? children : [children]\n const [trigger, ...rest] = items\n\n return (\n <MenuTrigger isOpen={isOpen} defaultOpen={defaultOpen} onOpenChange={onOpenChange}>\n <span data-slot=\"trigger\" className={s.trigger({ class: classNames?.trigger })}>\n {trigger}\n </span>\n <Popover\n placement={placement}\n offset={offset}\n data-slot=\"popover\"\n className={s.popover({ class: [className, classNames?.popover] })}\n >\n {/* RAC の Popover は id を受け取らないため Menu 本体に付ける */}\n <RACMenu\n id={id}\n data-slot=\"list\"\n className={s.list({ class: classNames?.list })}\n onAction={(key) => onAction?.(String(key))}\n disabledKeys={disabledKeys}\n >\n {rest}\n </RACMenu>\n </Popover>\n </MenuTrigger>\n )\n}\n"],"mappings":";;;;;;;;;;;AAiCA,SAAgB,kBAAkB,EAChC,IACA,YACA,aACA,UACA,UACA,aACgB;CAChB,MAAM,IAAI,WAAW;CAErB,OACE,qBAAC,UAAD;EACM;EACQ;EACZ,WAAW,OAAO,aAAa,WAAW,WAAW,KAAA;EACrD,aAAU;EACV,WAAW,EAAE,KAAK,EAAE,OAAO,UAAU,CAAC;EALxC,UAAA,CAOE,qBAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACE,oBAAC,QAAD;IAAM,aAAU;IAAY,WAAW,EAAE,UAAU;IAChD;GACG,CAAA,GACL,gBAAgB,KAAA,KACf,oBAAC,QAAD;IAAM,aAAU;IAAkB,WAAW,EAAE,gBAAgB;IAC5D,UAAA;GACG,CAAA,CAEJ;EACL,CAAA,GAAA,aAAa,KAAA,KACZ,oBAAC,QAAD;GAAM,aAAU;GAAe,WAAW,EAAE,aAAa;GACtD,UAAA;EACG,CAAA,CAEA;;AAEd;;;;;;;AAQA,SAAgB,cAAc,EAAE,aAAqC;CACnE,OACE,oBAAC,WAAD;EAAW,aAAU;EAAY,WAAW,WAAW,CAAC,CAAC,UAAU,EAAE,OAAO,UAAU,CAAC;CAAI,CAAA;AAE/F;;;;;;;;;;;;AAaA,SAAgBA,cAAY,EAC1B,OACA,UACA,aAKC;CACD,MAAM,IAAI,WAAW;CAErB,OACE,qBAACC,aAAD;EAAgB,aAAU;EAAU,WAAW,EAAE,QAAQ,EAAE,OAAO,UAAU,CAAC;EAA7E,UAAA,CACE,oBAAC,QAAD;GAAQ,aAAU;GAAe,WAAW,EAAE,aAAa;GACxD,UAAA;EACK,CAAA,GACP,QACa;;AAEpB;;;;;;;;;;;;;AAcA,SAAgBC,OAAK,EACnB,YAAY,UACZ,SAAS,GACT,QACA,aACA,cACA,UACA,cACA,UACA,WACA,YACA,MACY;CACZ,MAAM,IAAI,WAAW;CAErB,MAAM,CAAC,SAAS,GAAG,QADL,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ;CAG5D,OACE,qBAAC,aAAD;EAAqB;EAAqB;EAA2B;EAArE,UAAA,CACE,oBAAC,QAAD;GAAM,aAAU;GAAU,WAAW,EAAE,QAAQ,EAAE,OAAO,YAAY,QAAQ,CAAC;GAC1E,UAAA;EACG,CAAA,GACN,oBAAC,SAAD;GACa;GACH;GACR,aAAU;GACV,WAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,WAAW,YAAY,OAAO,EAAE,CAAC;GAGhE,UAAA,oBAACC,MAAD;IACM;IACJ,aAAU;IACV,WAAW,EAAE,KAAK,EAAE,OAAO,YAAY,KAAK,CAAC;IAC7C,WAAW,QAAQ,WAAW,OAAO,GAAG,CAAC;IAC3B;IAEb,UAAA;GACM,CAAA;EACF,CAAA,CACE;;AAEjB"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
//#region src/menu/menu.styles.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Menu のスタイル定義。
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const myMenu = tv({ extend: menuStyles, slots: { popover: 'min-w-56' } })
|
|
7
|
+
*/
|
|
8
|
+
declare const menuStyles: import("tailwind-variants").TVReturnType<{
|
|
9
|
+
[key: string]: {
|
|
10
|
+
[key: string]: import("tailwind-variants").ClassValue | {
|
|
11
|
+
item?: import("tailwind-variants").ClassValue;
|
|
12
|
+
trigger?: import("tailwind-variants").ClassValue;
|
|
13
|
+
list?: import("tailwind-variants").ClassValue;
|
|
14
|
+
separator?: import("tailwind-variants").ClassValue;
|
|
15
|
+
popover?: import("tailwind-variants").ClassValue;
|
|
16
|
+
itemLabel?: import("tailwind-variants").ClassValue;
|
|
17
|
+
itemDescription?: import("tailwind-variants").ClassValue;
|
|
18
|
+
itemShortcut?: import("tailwind-variants").ClassValue;
|
|
19
|
+
section?: import("tailwind-variants").ClassValue;
|
|
20
|
+
sectionLabel?: import("tailwind-variants").ClassValue;
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
} | {
|
|
24
|
+
[x: string]: {
|
|
25
|
+
[x: string]: import("tailwind-variants").ClassValue | {
|
|
26
|
+
item?: import("tailwind-variants").ClassValue;
|
|
27
|
+
trigger?: import("tailwind-variants").ClassValue;
|
|
28
|
+
list?: import("tailwind-variants").ClassValue;
|
|
29
|
+
separator?: import("tailwind-variants").ClassValue;
|
|
30
|
+
popover?: import("tailwind-variants").ClassValue;
|
|
31
|
+
itemLabel?: import("tailwind-variants").ClassValue;
|
|
32
|
+
itemDescription?: import("tailwind-variants").ClassValue;
|
|
33
|
+
itemShortcut?: import("tailwind-variants").ClassValue;
|
|
34
|
+
section?: import("tailwind-variants").ClassValue;
|
|
35
|
+
sectionLabel?: import("tailwind-variants").ClassValue;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
} | {}, {
|
|
39
|
+
trigger: string;
|
|
40
|
+
popover: string;
|
|
41
|
+
list: string;
|
|
42
|
+
item: string;
|
|
43
|
+
itemLabel: string;
|
|
44
|
+
itemDescription: string;
|
|
45
|
+
itemShortcut: string;
|
|
46
|
+
separator: string;
|
|
47
|
+
section: string;
|
|
48
|
+
sectionLabel: string;
|
|
49
|
+
}, undefined, {
|
|
50
|
+
[key: string]: {
|
|
51
|
+
[key: string]: import("tailwind-variants").ClassValue | {
|
|
52
|
+
item?: import("tailwind-variants").ClassValue;
|
|
53
|
+
trigger?: import("tailwind-variants").ClassValue;
|
|
54
|
+
list?: import("tailwind-variants").ClassValue;
|
|
55
|
+
separator?: import("tailwind-variants").ClassValue;
|
|
56
|
+
popover?: import("tailwind-variants").ClassValue;
|
|
57
|
+
itemLabel?: import("tailwind-variants").ClassValue;
|
|
58
|
+
itemDescription?: import("tailwind-variants").ClassValue;
|
|
59
|
+
itemShortcut?: import("tailwind-variants").ClassValue;
|
|
60
|
+
section?: import("tailwind-variants").ClassValue;
|
|
61
|
+
sectionLabel?: import("tailwind-variants").ClassValue;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
} | {}, {
|
|
65
|
+
trigger: string;
|
|
66
|
+
popover: string;
|
|
67
|
+
list: string;
|
|
68
|
+
item: string;
|
|
69
|
+
itemLabel: string;
|
|
70
|
+
itemDescription: string;
|
|
71
|
+
itemShortcut: string;
|
|
72
|
+
separator: string;
|
|
73
|
+
section: string;
|
|
74
|
+
sectionLabel: string;
|
|
75
|
+
}, import("tailwind-variants").TVReturnTypeLike<unknown, {
|
|
76
|
+
trigger: string;
|
|
77
|
+
popover: string;
|
|
78
|
+
list: string;
|
|
79
|
+
item: string;
|
|
80
|
+
itemLabel: string;
|
|
81
|
+
itemDescription: string;
|
|
82
|
+
itemShortcut: string;
|
|
83
|
+
separator: string;
|
|
84
|
+
section: string;
|
|
85
|
+
sectionLabel: string;
|
|
86
|
+
}>>;
|
|
87
|
+
type MenuStyleProps = Parameters<typeof menuStyles>[0];
|
|
88
|
+
//#endregion
|
|
89
|
+
export { MenuStyleProps, menuStyles };
|
|
90
|
+
//# sourceMappingURL=menu.styles.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.styles.d.mts","names":[],"sources":["../../src/menu/menu.styles.ts"],"mappings":";;;;;;;cA4Ca,wCAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEX,iBAAiB,kBAAkB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { tv } from "tailwind-variants";
|
|
2
|
+
//#region src/menu/menu.styles.ts
|
|
3
|
+
const slots = {
|
|
4
|
+
trigger: "outline-none",
|
|
5
|
+
popover: [
|
|
6
|
+
"text-[var(--novi-color-fg)]",
|
|
7
|
+
"outline-none",
|
|
8
|
+
"!fixed !top-auto !inset-x-0 !bottom-0 !max-w-none !w-full",
|
|
9
|
+
"!max-h-[70dvh]",
|
|
10
|
+
"bg-[var(--novi-color-surface)]",
|
|
11
|
+
"rounded-t-[var(--novi-radius-lg)]",
|
|
12
|
+
"shadow-[var(--novi-shadow-lg)]",
|
|
13
|
+
"pb-[env(safe-area-inset-bottom,0px)]",
|
|
14
|
+
"data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]"
|
|
15
|
+
].join(" "),
|
|
16
|
+
list: "outline-none p-2 flex flex-col",
|
|
17
|
+
item: [
|
|
18
|
+
"flex items-center gap-3 justify-between",
|
|
19
|
+
"min-h-12 px-3 cursor-pointer outline-none",
|
|
20
|
+
"text-[var(--novi-color-fg)]",
|
|
21
|
+
"rounded-[var(--novi-radius-md)]",
|
|
22
|
+
"data-[focused]:bg-[var(--novi-color-subtle)]",
|
|
23
|
+
"data-[disabled]:opacity-40 data-[disabled]:cursor-default"
|
|
24
|
+
].join(" "),
|
|
25
|
+
itemLabel: "truncate",
|
|
26
|
+
itemDescription: "text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)]",
|
|
27
|
+
itemShortcut: "shrink-0 text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)] tabular-nums",
|
|
28
|
+
separator: "my-1 h-px bg-[var(--novi-color-border)]",
|
|
29
|
+
section: "flex flex-col",
|
|
30
|
+
sectionLabel: "px-2 pt-2 pb-1 text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)] tracking-wide"
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Menu のスタイル定義。
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* const myMenu = tv({ extend: menuStyles, slots: { popover: 'min-w-56' } })
|
|
37
|
+
*/
|
|
38
|
+
const menuStyles = tv({ slots });
|
|
39
|
+
//#endregion
|
|
40
|
+
export { menuStyles };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=menu.styles.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.styles.mjs","names":[],"sources":["../../src/menu/menu.styles.ts"],"sourcesContent":["import type { menuRequiredSlots, menuSlots, SlotMap } from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\n\nconst slots = {\n trigger: 'outline-none',\n // Select と同じ下端シート。RAC の位置決めを奪えるのは !important だけ(ADR-T2)\n popover: [\n 'text-[var(--novi-color-fg)]',\n 'outline-none',\n '!fixed !top-auto !inset-x-0 !bottom-0 !max-w-none !w-full',\n '!max-h-[70dvh]',\n 'bg-[var(--novi-color-surface)]',\n 'rounded-t-[var(--novi-radius-lg)]',\n 'shadow-[var(--novi-shadow-lg)]',\n 'pb-[env(safe-area-inset-bottom,0px)]',\n 'data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]',\n ].join(' '),\n list: 'outline-none p-2 flex flex-col',\n item: [\n 'flex items-center gap-3 justify-between',\n // 一覧は誤タップが最も起きる場所。行高は 48px を下回らせない\n 'min-h-12 px-3 cursor-pointer outline-none',\n 'text-[var(--novi-color-fg)]',\n 'rounded-[var(--novi-radius-md)]',\n 'data-[focused]:bg-[var(--novi-color-subtle)]',\n 'data-[disabled]:opacity-40 data-[disabled]:cursor-default',\n ].join(' '),\n itemLabel: 'truncate',\n itemDescription: 'text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)]',\n // ショートカットは桁を揃える。等幅数字にしないと縦の線が揃わない\n itemShortcut:\n 'shrink-0 text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)] tabular-nums',\n separator: 'my-1 h-px bg-[var(--novi-color-border)]',\n section: 'flex flex-col',\n sectionLabel:\n 'px-2 pt-2 pb-1 text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)] tracking-wide',\n} satisfies SlotMap<typeof menuSlots, (typeof menuRequiredSlots)[number]>\n\n/**\n * Menu のスタイル定義。\n *\n * @example\n * const myMenu = tv({ extend: menuStyles, slots: { popover: 'min-w-56' } })\n */\nexport const menuStyles = tv({ slots })\n\nexport type MenuStyleProps = Parameters<typeof menuStyles>[0]\n"],"mappings":";;AAGA,MAAM,QAAQ;CACZ,SAAS;CAET,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,MAAM;CACN,MAAM;EACJ;EAEA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,WAAW;CACX,iBAAiB;CAEjB,cACE;CACF,WAAW;CACX,SAAS;CACT,cACE;AACJ;;;;;;;AAQA,MAAa,aAAa,GAAG,EAAE,MAAM,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { ModalProps } from "@novi-ui/core";
|
|
3
|
+
//#region src/modal/modal.d.ts
|
|
4
|
+
interface PartProps {
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Modal の見出し。
|
|
10
|
+
*
|
|
11
|
+
* Raster と違い**ヘッダー行を作らない** — 閉じるボタンはフッターにあるので、
|
|
12
|
+
* 横方向に並べる相手がいない。見出しは本文の上に素直に載る。
|
|
13
|
+
* それでも描画するのは、ダイアログにアクセシブルな名前が要るため。
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <ModalTitle>削除しますか</ModalTitle>
|
|
17
|
+
*/
|
|
18
|
+
declare function ModalTitle({ children, className }: PartProps): import("react").JSX.Element;
|
|
19
|
+
/**
|
|
20
|
+
* Modal の本体。
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <ModalBody>この操作は取り消せません。</ModalBody>
|
|
24
|
+
*/
|
|
25
|
+
declare function ModalBody({ children, className }: PartProps): import("react").JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Modal の操作列。**縦積みでフルワイド**になり、末尾に閉じるボタンが入る。
|
|
28
|
+
*
|
|
29
|
+
* 横に並べると1つあたりの幅が指に対して狭くなるため、Tactile では積む。
|
|
30
|
+
* 閉じるを最後に置くのは、親指が最も届く位置が下端だから。
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* <ModalFooter>
|
|
34
|
+
* <Button color="danger">削除</Button>
|
|
35
|
+
* </ModalFooter>
|
|
36
|
+
*/
|
|
37
|
+
declare function ModalFooter({ children, className }: PartProps): import("react").JSX.Element;
|
|
38
|
+
/**
|
|
39
|
+
* 画面下端から出るボトムシート。開いている間フォーカスは内側に閉じ込められ、
|
|
40
|
+
* Escape で閉じる。
|
|
41
|
+
*
|
|
42
|
+
* Raster が中央のダイアログで閉じるを右上に置くのに対し、Tactile は
|
|
43
|
+
* **下から出て、閉じるをフッターのフルワイドボタンにする**。親指の届く位置に
|
|
44
|
+
* 出口を置くため。`size` は幅ではなく**最大高**の意味になる(ADR-T3)。
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* <Modal isOpen={isOpen} onOpenChange={setIsOpen}>
|
|
48
|
+
* <ModalTitle>削除しますか</ModalTitle>
|
|
49
|
+
* <ModalBody>この操作は取り消せません。</ModalBody>
|
|
50
|
+
* </Modal>
|
|
51
|
+
*/
|
|
52
|
+
declare function Modal({ size, radius, isOpen, defaultOpen, onOpenChange, isDismissable, isKeyboardDismissDisabled, children, className, classNames, id }: ModalProps): import("react").JSX.Element;
|
|
53
|
+
//#endregion
|
|
54
|
+
export { Modal, ModalBody, ModalFooter, ModalTitle };
|
|
55
|
+
//# sourceMappingURL=modal.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal.d.mts","names":[],"sources":["../../src/modal/modal.tsx"],"mappings":";;;UAOU;EACR,WAAW;EACX;;;;;;;;;;;;iBAac,aAAa,UAAU,aAAa,4BAAS,IAAA;;;;;;;iBAc7C,YAAY,UAAU,aAAa,4BAAS,IAAA;;;;;;;;;;;;iBAgC5C,cAAc,UAAU,aAAa,4BAAS,IAAA;;;;;;;;;;;;;;;iBA8B9C,QACd,MACA,QACA,QACA,aACA,cACA,eACA,2BACA,UACA,WACA,YACA,MACC,6BAAU,IAAA"}
|