@novi-ui/raster 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.
Files changed (188) hide show
  1. package/README.md +129 -0
  2. package/dist/accordion/accordion.d.mts +31 -0
  3. package/dist/accordion/accordion.d.mts.map +1 -0
  4. package/dist/accordion/accordion.mjs +88 -0
  5. package/dist/accordion/accordion.mjs.map +1 -0
  6. package/dist/accordion/accordion.styles.d.mts +61 -0
  7. package/dist/accordion/accordion.styles.d.mts.map +1 -0
  8. package/dist/accordion/accordion.styles.mjs +78 -0
  9. package/dist/accordion/accordion.styles.mjs.map +1 -0
  10. package/dist/accordion/index.d.mts +3 -0
  11. package/dist/avatar/avatar.d.mts +19 -0
  12. package/dist/avatar/avatar.d.mts.map +1 -0
  13. package/dist/avatar/avatar.mjs +57 -0
  14. package/dist/avatar/avatar.mjs.map +1 -0
  15. package/dist/avatar/avatar.styles.d.mts +49 -0
  16. package/dist/avatar/avatar.styles.d.mts.map +1 -0
  17. package/dist/avatar/avatar.styles.mjs +45 -0
  18. package/dist/avatar/avatar.styles.mjs.map +1 -0
  19. package/dist/avatar/index.d.mts +3 -0
  20. package/dist/badge/badge.d.mts +15 -0
  21. package/dist/badge/badge.d.mts.map +1 -0
  22. package/dist/badge/badge.mjs +39 -0
  23. package/dist/badge/badge.mjs.map +1 -0
  24. package/dist/badge/badge.styles.d.mts +67 -0
  25. package/dist/badge/badge.styles.d.mts.map +1 -0
  26. package/dist/badge/badge.styles.mjs +99 -0
  27. package/dist/badge/badge.styles.mjs.map +1 -0
  28. package/dist/badge/index.d.mts +3 -0
  29. package/dist/breadcrumbs/breadcrumbs.d.mts +33 -0
  30. package/dist/breadcrumbs/breadcrumbs.d.mts.map +1 -0
  31. package/dist/breadcrumbs/breadcrumbs.mjs +79 -0
  32. package/dist/breadcrumbs/breadcrumbs.mjs.map +1 -0
  33. package/dist/breadcrumbs/breadcrumbs.styles.d.mts +46 -0
  34. package/dist/breadcrumbs/breadcrumbs.styles.d.mts.map +1 -0
  35. package/dist/breadcrumbs/breadcrumbs.styles.mjs +35 -0
  36. package/dist/breadcrumbs/breadcrumbs.styles.mjs.map +1 -0
  37. package/dist/breadcrumbs/index.d.mts +3 -0
  38. package/dist/button/button.d.mts +14 -0
  39. package/dist/button/button.d.mts.map +1 -0
  40. package/dist/button/button.mjs +75 -0
  41. package/dist/button/button.mjs.map +1 -0
  42. package/dist/button/button.styles.d.mts +82 -0
  43. package/dist/button/button.styles.d.mts.map +1 -0
  44. package/dist/button/button.styles.mjs +118 -0
  45. package/dist/button/button.styles.mjs.map +1 -0
  46. package/dist/button/index.d.mts +3 -0
  47. package/dist/card/card.d.mts +51 -0
  48. package/dist/card/card.d.mts.map +1 -0
  49. package/dist/card/card.mjs +96 -0
  50. package/dist/card/card.mjs.map +1 -0
  51. package/dist/card/card.styles.d.mts +70 -0
  52. package/dist/card/card.styles.d.mts.map +1 -0
  53. package/dist/card/card.styles.mjs +62 -0
  54. package/dist/card/card.styles.mjs.map +1 -0
  55. package/dist/card/index.d.mts +3 -0
  56. package/dist/checkbox/checkbox.d.mts +24 -0
  57. package/dist/checkbox/checkbox.d.mts.map +1 -0
  58. package/dist/checkbox/checkbox.mjs +124 -0
  59. package/dist/checkbox/checkbox.mjs.map +1 -0
  60. package/dist/checkbox/checkbox.styles.d.mts +111 -0
  61. package/dist/checkbox/checkbox.styles.d.mts.map +1 -0
  62. package/dist/checkbox/checkbox.styles.mjs +89 -0
  63. package/dist/checkbox/checkbox.styles.mjs.map +1 -0
  64. package/dist/checkbox/index.d.mts +3 -0
  65. package/dist/index.d.mts +61 -0
  66. package/dist/index.mjs +42 -0
  67. package/dist/input/index.d.mts +3 -0
  68. package/dist/input/input.d.mts +20 -0
  69. package/dist/input/input.d.mts.map +1 -0
  70. package/dist/input/input.mjs +86 -0
  71. package/dist/input/input.mjs.map +1 -0
  72. package/dist/input/input.styles.d.mts +81 -0
  73. package/dist/input/input.styles.d.mts.map +1 -0
  74. package/dist/input/input.styles.mjs +83 -0
  75. package/dist/input/input.styles.mjs.map +1 -0
  76. package/dist/menu/index.d.mts +3 -0
  77. package/dist/menu/menu.d.mts +62 -0
  78. package/dist/menu/menu.d.mts.map +1 -0
  79. package/dist/menu/menu.mjs +115 -0
  80. package/dist/menu/menu.mjs.map +1 -0
  81. package/dist/menu/menu.styles.d.mts +90 -0
  82. package/dist/menu/menu.styles.d.mts.map +1 -0
  83. package/dist/menu/menu.styles.mjs +40 -0
  84. package/dist/menu/menu.styles.mjs.map +1 -0
  85. package/dist/modal/index.d.mts +3 -0
  86. package/dist/modal/modal.d.mts +47 -0
  87. package/dist/modal/modal.d.mts.map +1 -0
  88. package/dist/modal/modal.mjs +110 -0
  89. package/dist/modal/modal.mjs.map +1 -0
  90. package/dist/modal/modal.styles.d.mts +58 -0
  91. package/dist/modal/modal.styles.d.mts.map +1 -0
  92. package/dist/modal/modal.styles.mjs +69 -0
  93. package/dist/modal/modal.styles.mjs.map +1 -0
  94. package/dist/popover/index.d.mts +3 -0
  95. package/dist/popover/popover.d.mts +40 -0
  96. package/dist/popover/popover.d.mts.map +1 -0
  97. package/dist/popover/popover.mjs +86 -0
  98. package/dist/popover/popover.mjs.map +1 -0
  99. package/dist/popover/popover.styles.d.mts +81 -0
  100. package/dist/popover/popover.styles.d.mts.map +1 -0
  101. package/dist/popover/popover.styles.mjs +53 -0
  102. package/dist/popover/popover.styles.mjs.map +1 -0
  103. package/dist/progress/index.d.mts +3 -0
  104. package/dist/progress/progress.d.mts +14 -0
  105. package/dist/progress/progress.d.mts.map +1 -0
  106. package/dist/progress/progress.mjs +54 -0
  107. package/dist/progress/progress.mjs.map +1 -0
  108. package/dist/progress/progress.styles.d.mts +70 -0
  109. package/dist/progress/progress.styles.d.mts.map +1 -0
  110. package/dist/progress/progress.styles.mjs +54 -0
  111. package/dist/progress/progress.styles.mjs.map +1 -0
  112. package/dist/radio/index.d.mts +3 -0
  113. package/dist/radio/radio.d.mts +22 -0
  114. package/dist/radio/radio.d.mts.map +1 -0
  115. package/dist/radio/radio.mjs +95 -0
  116. package/dist/radio/radio.mjs.map +1 -0
  117. package/dist/radio/radio.styles.d.mts +111 -0
  118. package/dist/radio/radio.styles.d.mts.map +1 -0
  119. package/dist/radio/radio.styles.mjs +88 -0
  120. package/dist/radio/radio.styles.mjs.map +1 -0
  121. package/dist/raster.css +92 -0
  122. package/dist/raster.scoped.css +92 -0
  123. package/dist/select/index.d.mts +3 -0
  124. package/dist/select/select.d.mts +33 -0
  125. package/dist/select/select.d.mts.map +1 -0
  126. package/dist/select/select.mjs +114 -0
  127. package/dist/select/select.mjs.map +1 -0
  128. package/dist/select/select.styles.d.mts +82 -0
  129. package/dist/select/select.styles.d.mts.map +1 -0
  130. package/dist/select/select.styles.mjs +93 -0
  131. package/dist/select/select.styles.mjs.map +1 -0
  132. package/dist/skeleton/index.d.mts +3 -0
  133. package/dist/skeleton/skeleton.d.mts +15 -0
  134. package/dist/skeleton/skeleton.d.mts.map +1 -0
  135. package/dist/skeleton/skeleton.mjs +26 -0
  136. package/dist/skeleton/skeleton.mjs.map +1 -0
  137. package/dist/skeleton/skeleton.styles.d.mts +31 -0
  138. package/dist/skeleton/skeleton.styles.d.mts.map +1 -0
  139. package/dist/skeleton/skeleton.styles.mjs +22 -0
  140. package/dist/skeleton/skeleton.styles.mjs.map +1 -0
  141. package/dist/spinner/index.d.mts +3 -0
  142. package/dist/spinner/spinner.d.mts +15 -0
  143. package/dist/spinner/spinner.d.mts.map +1 -0
  144. package/dist/spinner/spinner.mjs +55 -0
  145. package/dist/spinner/spinner.mjs.map +1 -0
  146. package/dist/spinner/spinner.styles.d.mts +46 -0
  147. package/dist/spinner/spinner.styles.d.mts.map +1 -0
  148. package/dist/spinner/spinner.styles.mjs +37 -0
  149. package/dist/spinner/spinner.styles.mjs.map +1 -0
  150. package/dist/styles/focus-ring.mjs +23 -0
  151. package/dist/styles/focus-ring.mjs.map +1 -0
  152. package/dist/switch/index.d.mts +3 -0
  153. package/dist/switch/switch.d.mts +17 -0
  154. package/dist/switch/switch.d.mts.map +1 -0
  155. package/dist/switch/switch.mjs +57 -0
  156. package/dist/switch/switch.mjs.map +1 -0
  157. package/dist/switch/switch.styles.d.mts +58 -0
  158. package/dist/switch/switch.styles.d.mts.map +1 -0
  159. package/dist/switch/switch.styles.mjs +80 -0
  160. package/dist/switch/switch.styles.mjs.map +1 -0
  161. package/dist/tabs/index.d.mts +3 -0
  162. package/dist/tabs/tabs.d.mts +55 -0
  163. package/dist/tabs/tabs.d.mts.map +1 -0
  164. package/dist/tabs/tabs.mjs +84 -0
  165. package/dist/tabs/tabs.mjs.map +1 -0
  166. package/dist/tabs/tabs.styles.d.mts +55 -0
  167. package/dist/tabs/tabs.styles.d.mts.map +1 -0
  168. package/dist/tabs/tabs.styles.mjs +73 -0
  169. package/dist/tabs/tabs.styles.mjs.map +1 -0
  170. package/dist/textarea/index.d.mts +3 -0
  171. package/dist/textarea/textarea.d.mts +15 -0
  172. package/dist/textarea/textarea.d.mts.map +1 -0
  173. package/dist/textarea/textarea.mjs +70 -0
  174. package/dist/textarea/textarea.mjs.map +1 -0
  175. package/dist/textarea/textarea.styles.d.mts +73 -0
  176. package/dist/textarea/textarea.styles.d.mts.map +1 -0
  177. package/dist/textarea/textarea.styles.mjs +81 -0
  178. package/dist/textarea/textarea.styles.mjs.map +1 -0
  179. package/dist/toast/index.d.mts +3 -0
  180. package/dist/toast/toast.d.mts +38 -0
  181. package/dist/toast/toast.d.mts.map +1 -0
  182. package/dist/toast/toast.mjs +86 -0
  183. package/dist/toast/toast.mjs.map +1 -0
  184. package/dist/toast/toast.styles.d.mts +61 -0
  185. package/dist/toast/toast.styles.d.mts.map +1 -0
  186. package/dist/toast/toast.styles.mjs +59 -0
  187. package/dist/toast/toast.styles.mjs.map +1 -0
  188. package/package.json +59 -0
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # @novi-ui/raster
2
+
3
+ Novi UI のテーマ1。**ミニマル / スイス系。**
4
+
5
+ 角を立て、影を使わず、線は 1px だけ。余白と整列で階層を作る。
6
+ ごまかしが効かないぶん、実装の精度がそのまま出る。
7
+
8
+ ```bash
9
+ pnpm add @novi-ui/raster @novi-ui/core react-aria-components
10
+ ```
11
+
12
+ ```tsx
13
+ import '@novi-ui/core/base.css'
14
+ import '@novi-ui/raster/raster.css'
15
+ import { Button, Input } from '@novi-ui/raster'
16
+
17
+ export function Example() {
18
+ return (
19
+ <form>
20
+ <Input label="メールアドレス" type="email" isRequired />
21
+ <Button type="submit" color="primary">送信</Button>
22
+ </form>
23
+ )
24
+ }
25
+ ```
26
+
27
+ Provider は要りません。テーマは CSS 変数だけで効きます。
28
+
29
+ ## デザイン言語(数値定義)
30
+
31
+ 「ミニマル」を主観で運用すると必ずブレるので、すべて数値で固定しています。
32
+ 違反は CI(`scripts/check-design-rules.mjs`)が検出します。
33
+
34
+ | 項目 | 規則 |
35
+ |---|---|
36
+ | ベースグリッド | 垂直リズムは 4px、ブロック間余白は 8px の倍数 |
37
+ | コンポーネント高さ | `sm` 32px / `md` 40px / `lg` 48px |
38
+ | タイポスケール | 比率 1.2。12 / 14 / 16 / 20 / 24 / 30 / 36px |
39
+ | 境界線 | **1px のみ。** 2px 以上は使わない |
40
+ | 影 | **使わない。** 階層は境界線と背景色の差で表す |
41
+ | 角丸 | 既定 0。**最大でも 2px** |
42
+ | 彩度 | 中立色は chroma 0。意味を持つ色のみ有彩(上限 0.19) |
43
+ | モーション | `--novi-duration-fast`(120ms) のみ。`opacity` と `translate` だけ |
44
+
45
+ ## 知っておくべき仕様
46
+
47
+ ### `radius` は効きません(意図的)
48
+
49
+ API としては `radius="lg"` を受け付けますが、Raster では **`md` も `lg` も 2px に潰れます**。
50
+ 角を立てるのが Raster の思想だからです。不具合ではありません。
51
+
52
+ 語彙は core が共通で固定し、解釈はテーマの自由、という設計です。
53
+ おかげでドキュメントのコード例がテーマを跨いでそのまま動きます。
54
+
55
+ ### Switch は矩形です
56
+
57
+ 一般的なピル型トグルは「角を立てる」原則と衝突するため、
58
+ トラックもサムも角丸 0 の矩形にしています。
59
+ 形が見慣れないぶん状態が読み取りにくいので、**ラベルの併記を強く推奨**します。
60
+
61
+ ```tsx
62
+ <Switch isSelected={enabled} onChange={setEnabled}>
63
+ メール通知を受け取る
64
+ </Switch>
65
+ ```
66
+
67
+ ### Tabs は背景を変えません
68
+
69
+ 選択中は**下線 1px と文字色**だけで示します。背景の塗り分けは面を増やすため使いません。
70
+
71
+ ### Spinner だけ回転します
72
+
73
+ 「動きで飾らない」原則の唯一の例外です。
74
+ 代替のローディング表現(点滅・バーの往復)は視認性か情報量で劣るため、ここだけ許可しています。
75
+ `prefers-reduced-motion` が有効なときは止まります。
76
+
77
+ ## スタイルの拡張
78
+
79
+ 全コンポーネントの `tv()` 定義を named export しています。
80
+
81
+ ```ts
82
+ import { buttonStyles } from '@novi-ui/raster'
83
+ import { tv } from 'tailwind-variants'
84
+
85
+ // slot ベースの定義なので `slots` で足す。`base` は効かない
86
+ const myButton = tv({
87
+ extend: buttonStyles,
88
+ slots: { root: 'uppercase tracking-widest' },
89
+ })
90
+ ```
91
+
92
+ **variant のクラスを上書きしたい場合は `classNames` を使います。**
93
+ `extend` の `slots` は base に足されるため、後から適用される variant に負けます。
94
+
95
+ ```tsx
96
+ // ✗ size variant の w-9 に負ける
97
+ tv({ extend: switchStyles, slots: { track: 'w-14' } })
98
+
99
+ // ✓ 呼び出し時に渡せば勝つ
100
+ <Switch classNames={{ track: 'w-14' }} />
101
+ ```
102
+
103
+ ブランド色を変えるだけなら CSS 変数の上書きで足ります。
104
+
105
+ ```css
106
+ :root {
107
+ --novi-color-primary: oklch(50% 0.18 20);
108
+ }
109
+ ```
110
+
111
+ ## slot
112
+
113
+ 全コンポーネントは構成部位に `data-slot="<名前>"` を出力します。
114
+ テスト・CSS の上書き・視覚回帰がすべてこれに乗ります。
115
+
116
+ ```css
117
+ [data-slot='panel'] { max-width: 40rem; }
118
+ ```
119
+
120
+ slot 名の一覧は `@novi-ui/core` の `NOVI_CONTRACTS` から取得できます。
121
+
122
+ ## 日本語入力
123
+
124
+ `Input` と `TextArea` の `onKeyDown` は、**IME 変換中のキーを受け取りません**。
125
+ 変換確定の Enter でフォーム送信が暴発する事故を、利用側が意識せずに防げます。
126
+
127
+ ## ライセンス
128
+
129
+ MIT
@@ -0,0 +1,31 @@
1
+ import { ReactNode } from "react";
2
+ import { AccordionProps } from "@novi-ui/core";
3
+ //#region src/accordion/accordion.d.ts
4
+ interface AccordionItemProps {
5
+ id: string;
6
+ title: ReactNode;
7
+ isDisabled?: boolean;
8
+ children?: ReactNode;
9
+ className?: string;
10
+ }
11
+ /**
12
+ * Accordion の項目。
13
+ *
14
+ * @example
15
+ * <AccordionItem id="shipping" title="配送について">…</AccordionItem>
16
+ */
17
+ declare function AccordionItem({ id, title, isDisabled, children, className }: AccordionItemProps): import("react").JSX.Element;
18
+ /**
19
+ * 折りたたみできる項目の集合。
20
+ *
21
+ * 開閉の記号は `+` / `−` の線で示す。三角矢印の回転は使わない。
22
+ *
23
+ * @example
24
+ * <Accordion allowsMultipleExpanded>
25
+ * <AccordionItem id="shipping" title="配送について">…</AccordionItem>
26
+ * </Accordion>
27
+ */
28
+ declare function Accordion({ variant, size, allowsMultipleExpanded, expandedKeys, defaultExpandedKeys, onExpandedChange, isDisabled, children, className, classNames, id }: AccordionProps): import("react").JSX.Element;
29
+ //#endregion
30
+ export { Accordion, AccordionItem, AccordionItemProps };
31
+ //# sourceMappingURL=accordion.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.d.mts","names":[],"sources":["../../src/accordion/accordion.tsx"],"mappings":";;;UAuBiB;EACf;EACA,OAAO;EACP;EACA,WAAW;EACX;;;;;;;;iBASc,gBAAgB,IAAI,OAAO,YAAY,UAAU,aAAa,qCAAkB,IAAA;;;;;;;;;;;iBAuChF,YACd,SACA,MACA,wBACA,cACA,qBACA,kBACA,YACA,UACA,WACA,YACA,MACC,iCAAc,IAAA"}
@@ -0,0 +1,88 @@
1
+ "use client";
2
+ import { accordionStyles } from "./accordion.styles.mjs";
3
+ import { Button, Disclosure, DisclosureGroup, DisclosurePanel, Heading } from "react-aria-components";
4
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
+ //#region src/accordion/accordion.tsx
6
+ /** 開閉を示す記号。回転させず `+` と `−` の線で描く。 */
7
+ function Indicator({ isExpanded }) {
8
+ return /* @__PURE__ */ jsxs("svg", {
9
+ viewBox: "0 0 16 16",
10
+ width: "0.875em",
11
+ height: "0.875em",
12
+ fill: "none",
13
+ "aria-hidden": "true",
14
+ children: [/* @__PURE__ */ jsx("path", {
15
+ d: "M3 8h10",
16
+ stroke: "currentColor",
17
+ strokeWidth: "1.5"
18
+ }), !isExpanded && /* @__PURE__ */ jsx("path", {
19
+ d: "M8 3v10",
20
+ stroke: "currentColor",
21
+ strokeWidth: "1.5"
22
+ })]
23
+ });
24
+ }
25
+ /**
26
+ * Accordion の項目。
27
+ *
28
+ * @example
29
+ * <AccordionItem id="shipping" title="配送について">…</AccordionItem>
30
+ */
31
+ function AccordionItem({ id, title, isDisabled, children, className }) {
32
+ const s = accordionStyles();
33
+ return /* @__PURE__ */ jsx(Disclosure, {
34
+ id,
35
+ isDisabled,
36
+ "data-slot": "item",
37
+ className: s.item({ class: className }),
38
+ children: ({ isExpanded }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Heading, {
39
+ "data-slot": "heading",
40
+ className: s.heading(),
41
+ children: /* @__PURE__ */ jsxs(Button, {
42
+ slot: "trigger",
43
+ "data-slot": "trigger",
44
+ className: s.trigger(),
45
+ children: [/* @__PURE__ */ jsx("span", { children: title }), /* @__PURE__ */ jsx("span", {
46
+ "data-slot": "indicator",
47
+ className: s.indicator(),
48
+ children: /* @__PURE__ */ jsx(Indicator, { isExpanded })
49
+ })]
50
+ })
51
+ }), /* @__PURE__ */ jsx(DisclosurePanel, {
52
+ "data-slot": "panel",
53
+ className: s.panel(),
54
+ children
55
+ })] })
56
+ });
57
+ }
58
+ /**
59
+ * 折りたたみできる項目の集合。
60
+ *
61
+ * 開閉の記号は `+` / `−` の線で示す。三角矢印の回転は使わない。
62
+ *
63
+ * @example
64
+ * <Accordion allowsMultipleExpanded>
65
+ * <AccordionItem id="shipping" title="配送について">…</AccordionItem>
66
+ * </Accordion>
67
+ */
68
+ function Accordion({ variant, size, allowsMultipleExpanded, expandedKeys, defaultExpandedKeys, onExpandedChange, isDisabled, children, className, classNames, id }) {
69
+ const s = accordionStyles({
70
+ variant,
71
+ size
72
+ });
73
+ return /* @__PURE__ */ jsx(DisclosureGroup, {
74
+ id,
75
+ allowsMultipleExpanded,
76
+ expandedKeys,
77
+ defaultExpandedKeys,
78
+ onExpandedChange: (keys) => onExpandedChange?.([...keys].map(String)),
79
+ isDisabled,
80
+ "data-slot": "root",
81
+ className: s.root({ class: [className, classNames?.root] }),
82
+ children
83
+ });
84
+ }
85
+ //#endregion
86
+ export { Accordion, AccordionItem };
87
+
88
+ //# sourceMappingURL=accordion.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.mjs","names":[],"sources":["../../src/accordion/accordion.tsx"],"sourcesContent":["'use client'\n\nimport type { AccordionProps } from '@novi-ui/core'\nimport type { ReactNode } from 'react'\nimport {\n Button,\n Disclosure,\n DisclosureGroup,\n DisclosurePanel,\n Heading,\n} from 'react-aria-components'\nimport { accordionStyles } from './accordion.styles'\n\n/** 開閉を示す記号。回転させず `+` と `−` の線で描く。 */\nfunction Indicator({ isExpanded }: { isExpanded: boolean }) {\n return (\n <svg viewBox=\"0 0 16 16\" width=\"0.875em\" height=\"0.875em\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M3 8h10\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n {!isExpanded && <path d=\"M8 3v10\" stroke=\"currentColor\" strokeWidth=\"1.5\" />}\n </svg>\n )\n}\n\nexport interface AccordionItemProps {\n id: string\n title: ReactNode\n isDisabled?: boolean\n children?: ReactNode\n className?: string\n}\n\n/**\n * Accordion の項目。\n *\n * @example\n * <AccordionItem id=\"shipping\" title=\"配送について\">…</AccordionItem>\n */\nexport function AccordionItem({ id, title, isDisabled, children, className }: AccordionItemProps) {\n const s = accordionStyles()\n\n return (\n <Disclosure\n id={id}\n isDisabled={isDisabled}\n data-slot=\"item\"\n className={s.item({ class: className })}\n >\n {({ isExpanded }) => (\n <>\n <Heading data-slot=\"heading\" className={s.heading()}>\n <Button slot=\"trigger\" data-slot=\"trigger\" className={s.trigger()}>\n <span>{title}</span>\n <span data-slot=\"indicator\" className={s.indicator()}>\n <Indicator isExpanded={isExpanded} />\n </span>\n </Button>\n </Heading>\n <DisclosurePanel data-slot=\"panel\" className={s.panel()}>\n {children}\n </DisclosurePanel>\n </>\n )}\n </Disclosure>\n )\n}\n\n/**\n * 折りたたみできる項目の集合。\n *\n * 開閉の記号は `+` / `−` の線で示す。三角矢印の回転は使わない。\n *\n * @example\n * <Accordion allowsMultipleExpanded>\n * <AccordionItem id=\"shipping\" title=\"配送について\">…</AccordionItem>\n * </Accordion>\n */\nexport function Accordion({\n variant,\n size,\n allowsMultipleExpanded,\n expandedKeys,\n defaultExpandedKeys,\n onExpandedChange,\n isDisabled,\n children,\n className,\n classNames,\n id,\n}: AccordionProps) {\n const s = accordionStyles({ variant, size })\n\n return (\n <DisclosureGroup\n id={id}\n allowsMultipleExpanded={allowsMultipleExpanded}\n expandedKeys={expandedKeys}\n defaultExpandedKeys={defaultExpandedKeys}\n onExpandedChange={(keys) => onExpandedChange?.([...keys].map(String))}\n isDisabled={isDisabled}\n data-slot=\"root\"\n className={s.root({ class: [className, classNames?.root] })}\n >\n {children}\n </DisclosureGroup>\n )\n}\n"],"mappings":";;;;;;AAcA,SAAS,UAAU,EAAE,cAAuC;CAC1D,OACE,qBAAC,OAAD;EAAK,SAAQ;EAAY,OAAM;EAAU,QAAO;EAAU,MAAK;EAAO,eAAY;EAAlF,UAAA,CACE,oBAAC,QAAD;GAAM,GAAE;GAAU,QAAO;GAAe,aAAY;EAAO,CAAA,GAC1D,CAAC,cAAc,oBAAC,QAAD;GAAM,GAAE;GAAU,QAAO;GAAe,aAAY;EAAO,CAAA,CACxE;;AAET;;;;;;;AAgBA,SAAgB,cAAc,EAAE,IAAI,OAAO,YAAY,UAAU,aAAiC;CAChG,MAAM,IAAI,gBAAgB;CAE1B,OACE,oBAAC,YAAD;EACM;EACQ;EACZ,aAAU;EACV,WAAW,EAAE,KAAK,EAAE,OAAO,UAAU,CAAC;EAEpC,WAAA,EAAE,iBACF,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,SAAD;GAAS,aAAU;GAAU,WAAW,EAAE,QAAQ;GAChD,UAAA,qBAAC,QAAD;IAAQ,MAAK;IAAU,aAAU;IAAU,WAAW,EAAE,QAAQ;IAAhE,UAAA,CACE,oBAAC,QAAD,EAAA,UAAO,MAAY,CAAA,GACnB,oBAAC,QAAD;KAAM,aAAU;KAAY,WAAW,EAAE,UAAU;KACjD,UAAA,oBAAC,WAAD,EAAuB,WAAa,CAAA;IAChC,CAAA,CACA;;EACD,CAAA,GACT,oBAAC,iBAAD;GAAiB,aAAU;GAAQ,WAAW,EAAE,MAAM;GACnD;EACc,CAAA,CACjB,EAAA,CAAA;CAEM,CAAA;AAEhB;;;;;;;;;;;AAYA,SAAgB,UAAU,EACxB,SACA,MACA,wBACA,cACA,qBACA,kBACA,YACA,UACA,WACA,YACA,MACiB;CACjB,MAAM,IAAI,gBAAgB;EAAE;EAAS;CAAK,CAAC;CAE3C,OACE,oBAAC,iBAAD;EACM;EACoB;EACV;EACO;EACrB,mBAAmB,SAAS,mBAAmB,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC;EACxD;EACZ,aAAU;EACV,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,YAAY,IAAI,EAAE,CAAC;EAEzD;CACc,CAAA;AAErB"}
@@ -0,0 +1,61 @@
1
+ import { VariantMap } from "@novi-ui/core";
2
+ //#region src/accordion/accordion.styles.d.ts
3
+ /**
4
+ * Accordion のスタイル定義。
5
+ *
6
+ * @example
7
+ * const myAccordion = tv({ extend: accordionStyles, slots: { panel: 'pt-2' } })
8
+ */
9
+ declare const accordionStyles: import("tailwind-variants").TVReturnType<{
10
+ size: VariantMap<"sm" | "md" | "lg", {
11
+ trigger: string;
12
+ panel: string;
13
+ }>;
14
+ variant: VariantMap<"solid" | "outline" | "soft" | "ghost" | "plain", {
15
+ root: string;
16
+ item: string;
17
+ }>;
18
+ }, {
19
+ root: string;
20
+ item: string;
21
+ heading: string;
22
+ trigger: string;
23
+ indicator: string;
24
+ panel: string;
25
+ }, undefined, {
26
+ size: VariantMap<"sm" | "md" | "lg", {
27
+ trigger: string;
28
+ panel: string;
29
+ }>;
30
+ variant: VariantMap<"solid" | "outline" | "soft" | "ghost" | "plain", {
31
+ root: string;
32
+ item: string;
33
+ }>;
34
+ }, {
35
+ root: string;
36
+ item: string;
37
+ heading: string;
38
+ trigger: string;
39
+ indicator: string;
40
+ panel: string;
41
+ }, import("tailwind-variants").TVReturnTypeLike<{
42
+ size: VariantMap<"sm" | "md" | "lg", {
43
+ trigger: string;
44
+ panel: string;
45
+ }>;
46
+ variant: VariantMap<"solid" | "outline" | "soft" | "ghost" | "plain", {
47
+ root: string;
48
+ item: string;
49
+ }>;
50
+ }, {
51
+ root: string;
52
+ item: string;
53
+ heading: string;
54
+ trigger: string;
55
+ indicator: string;
56
+ panel: string;
57
+ }>>;
58
+ type AccordionStyleProps = Parameters<typeof accordionStyles>[0];
59
+ //#endregion
60
+ export { AccordionStyleProps, accordionStyles };
61
+ //# sourceMappingURL=accordion.styles.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.styles.d.mts","names":[],"sources":["../../src/accordion/accordion.styles.ts"],"mappings":";;;;;;;;cAqDa,6CAAe;;IAZgB;IAAe;;;IARZ;IAAc;;;;;;;;;;;IAQjB;IAAe;;;IARZ;IAAc;;;;;;;;;;;IAQjB;IAAe;;;IARZ;IAAc;;;;;;;;;;KA0BjD,sBAAsB,kBAAkB"}
@@ -0,0 +1,78 @@
1
+ import { focusRing } from "../styles/focus-ring.mjs";
2
+ import { tv } from "tailwind-variants";
3
+ //#region src/accordion/accordion.styles.ts
4
+ /**
5
+ * インジケータは `+` と `−` の線で示す。
6
+ * 三角矢印を回転させる表現は Raster の「動きで飾らない」原則に反するため使わない。
7
+ */
8
+ const slots = {
9
+ root: "flex flex-col border-t border-[var(--novi-color-border)]",
10
+ item: "border-b border-[var(--novi-color-border)]",
11
+ heading: "m-0",
12
+ trigger: [
13
+ "flex items-center justify-between gap-4 w-full text-left",
14
+ "cursor-pointer outline-none",
15
+ "text-[var(--novi-color-fg)]",
16
+ "transition-colors duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]",
17
+ "hover:bg-[var(--novi-color-subtle)]",
18
+ "data-[disabled]:opacity-40 data-[disabled]:cursor-default",
19
+ focusRing
20
+ ].join(" "),
21
+ indicator: "shrink-0 text-[var(--novi-color-muted)]",
22
+ panel: "text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]"
23
+ };
24
+ /**
25
+ * Accordion のスタイル定義。
26
+ *
27
+ * @example
28
+ * const myAccordion = tv({ extend: accordionStyles, slots: { panel: 'pt-2' } })
29
+ */
30
+ const accordionStyles = tv({
31
+ slots,
32
+ variants: {
33
+ size: {
34
+ sm: {
35
+ trigger: "px-3 py-2.5 text-[length:var(--novi-text-sm)]",
36
+ panel: "px-3 pb-2.5"
37
+ },
38
+ md: {
39
+ trigger: "px-4 py-3 text-[length:var(--novi-text-base)]",
40
+ panel: "px-4 pb-3"
41
+ },
42
+ lg: {
43
+ trigger: "px-5 py-4 text-[length:var(--novi-text-base)]",
44
+ panel: "px-5 pb-4"
45
+ }
46
+ },
47
+ variant: {
48
+ solid: {
49
+ root: "border-t-0 gap-1",
50
+ item: "bg-[var(--novi-color-subtle)] border-b-0"
51
+ },
52
+ outline: {
53
+ root: "border-t border-[var(--novi-color-border)]",
54
+ item: "border-b"
55
+ },
56
+ soft: {
57
+ root: "border-t-0 gap-1",
58
+ item: "bg-[var(--novi-color-subtle)] border-b-0"
59
+ },
60
+ ghost: {
61
+ root: "border-t-0",
62
+ item: "border-b border-[var(--novi-color-border)]"
63
+ },
64
+ plain: {
65
+ root: "border-t-0 gap-2",
66
+ item: "border-b-0"
67
+ }
68
+ }
69
+ },
70
+ defaultVariants: {
71
+ variant: "outline",
72
+ size: "md"
73
+ }
74
+ });
75
+ //#endregion
76
+ export { accordionStyles };
77
+
78
+ //# sourceMappingURL=accordion.styles.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.styles.mjs","names":[],"sources":["../../src/accordion/accordion.styles.ts"],"sourcesContent":["import type {\n accordionRequiredSlots,\n accordionSlots,\n NoviSize,\n NoviVariant,\n SlotMap,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { focusRing } from '../styles/focus-ring'\n\n/**\n * インジケータは `+` と `−` の線で示す。\n * 三角矢印を回転させる表現は Raster の「動きで飾らない」原則に反するため使わない。\n */\nconst slots = {\n root: 'flex flex-col border-t border-[var(--novi-color-border)]',\n item: 'border-b border-[var(--novi-color-border)]',\n // 見出し要素とその中のボタンを分ける。支援技術のために必要\n heading: 'm-0',\n trigger: [\n 'flex items-center justify-between gap-4 w-full text-left',\n 'cursor-pointer outline-none',\n 'text-[var(--novi-color-fg)]',\n 'transition-colors duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'hover:bg-[var(--novi-color-subtle)]',\n 'data-[disabled]:opacity-40 data-[disabled]:cursor-default',\n focusRing,\n ].join(' '),\n indicator: 'shrink-0 text-[var(--novi-color-muted)]',\n panel: 'text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n} satisfies SlotMap<typeof accordionSlots, (typeof accordionRequiredSlots)[number]>\n\nconst variant: VariantMap<NoviVariant, { root: string; item: string }> = {\n solid: { root: 'border-t-0 gap-1', item: 'bg-[var(--novi-color-subtle)] border-b-0' },\n outline: { root: 'border-t border-[var(--novi-color-border)]', item: 'border-b' },\n soft: { root: 'border-t-0 gap-1', item: 'bg-[var(--novi-color-subtle)] border-b-0' },\n ghost: { root: 'border-t-0', item: 'border-b border-[var(--novi-color-border)]' },\n plain: { root: 'border-t-0 gap-2', item: 'border-b-0' },\n}\n\nconst size: VariantMap<NoviSize, { trigger: string; panel: string }> = {\n sm: { trigger: 'px-3 py-2.5 text-[length:var(--novi-text-sm)]', panel: 'px-3 pb-2.5' },\n md: { trigger: 'px-4 py-3 text-[length:var(--novi-text-base)]', panel: 'px-4 pb-3' },\n lg: { trigger: 'px-5 py-4 text-[length:var(--novi-text-base)]', panel: 'px-5 pb-4' },\n}\n\n/**\n * Accordion のスタイル定義。\n *\n * @example\n * const myAccordion = tv({ extend: accordionStyles, slots: { panel: 'pt-2' } })\n */\nexport const accordionStyles = tv({\n slots,\n variants: { size, variant },\n defaultVariants: { variant: 'outline', size: 'md' },\n})\n\nexport type AccordionStyleProps = Parameters<typeof accordionStyles>[0]\n"],"mappings":";;;;;;;AAeA,MAAM,QAAQ;CACZ,MAAM;CACN,MAAM;CAEN,SAAS;CACT,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,WAAW;CACX,OAAO;AACT;;;;;;;AAsBA,MAAa,kBAAkB,GAAG;CAChC;CACA,UAAU;EAAE;GAbZ,IAAI;IAAE,SAAS;IAAiD,OAAO;GAAc;GACrF,IAAI;IAAE,SAAS;IAAiD,OAAO;GAAY;GACnF,IAAI;IAAE,SAAS;IAAiD,OAAO;GAAY;EAWvE;EAAM;GArBlB,OAAO;IAAE,MAAM;IAAoB,MAAM;GAA2C;GACpF,SAAS;IAAE,MAAM;IAA8C,MAAM;GAAW;GAChF,MAAM;IAAE,MAAM;IAAoB,MAAM;GAA2C;GACnF,OAAO;IAAE,MAAM;IAAc,MAAM;GAA6C;GAChF,OAAO;IAAE,MAAM;IAAoB,MAAM;GAAa;EAiBpC;CAAQ;CAC1B,iBAAiB;EAAE,SAAS;EAAW,MAAM;CAAK;AACpD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Accordion, AccordionItem, AccordionItemProps } from "./accordion.mjs";
2
+ import { AccordionStyleProps, accordionStyles } from "./accordion.styles.mjs";
3
+ export { Accordion, AccordionItem, type AccordionItemProps, type AccordionStyleProps, accordionStyles };
@@ -0,0 +1,19 @@
1
+ import { AvatarProps } from "@novi-ui/core";
2
+ //#region src/avatar/avatar.d.ts
3
+ /**
4
+ * 表示名からイニシャルを作る。
5
+ *
6
+ * 日本語の氏名は空白で区切られないことが多いので、
7
+ * 空白があれば各語の先頭、なければ先頭1文字を使う。
8
+ */
9
+ declare function initialsOf(name: string): string;
10
+ /**
11
+ * 人や組織を表す画像。読み込みに失敗したら fallback を表示する。
12
+ *
13
+ * @example
14
+ * <Avatar src="/me.jpg" name="小島 佑翔" />
15
+ */
16
+ declare function Avatar({ size, radius, src, name, fallback, badge, className, classNames, id }: AvatarProps): import("react").JSX.Element;
17
+ //#endregion
18
+ export { Avatar, initialsOf };
19
+ //# sourceMappingURL=avatar.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar.d.mts","names":[],"sources":["../../src/avatar/avatar.tsx"],"mappings":";;;;;;;;iBAYgB,WAAW;;;;;;;iBAgBX,SACd,MACA,QACA,KACA,MACA,UACA,OACA,WACA,YACA,MACC,8BAAW,IAAA"}
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ import { avatarStyles } from "./avatar.styles.mjs";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useState } from "react";
5
+ //#region src/avatar/avatar.tsx
6
+ /**
7
+ * 表示名からイニシャルを作る。
8
+ *
9
+ * 日本語の氏名は空白で区切られないことが多いので、
10
+ * 空白があれば各語の先頭、なければ先頭1文字を使う。
11
+ */
12
+ function initialsOf(name) {
13
+ const parts = name.trim().split(/\s+/).filter(Boolean);
14
+ if (parts.length === 0) return "";
15
+ if (parts.length === 1) return [...parts[0]][0] ?? "";
16
+ return parts.slice(0, 2).map((part) => [...part][0] ?? "").join("");
17
+ }
18
+ /**
19
+ * 人や組織を表す画像。読み込みに失敗したら fallback を表示する。
20
+ *
21
+ * @example
22
+ * <Avatar src="/me.jpg" name="小島 佑翔" />
23
+ */
24
+ function Avatar({ size, radius, src, name, fallback, badge, className, classNames, id }) {
25
+ const s = avatarStyles({
26
+ size,
27
+ radius
28
+ });
29
+ const [failed, setFailed] = useState(false);
30
+ const showImage = src !== void 0 && src !== "" && !failed;
31
+ return /* @__PURE__ */ jsxs("span", {
32
+ id,
33
+ "data-slot": "root",
34
+ className: s.root({ class: [className, classNames?.root] }),
35
+ children: [showImage ? /* @__PURE__ */ jsx("img", {
36
+ "data-slot": "image",
37
+ className: s.image({ class: classNames?.image }),
38
+ src,
39
+ alt: name ?? "",
40
+ onError: () => setFailed(true)
41
+ }) : /* @__PURE__ */ jsx("span", {
42
+ "data-slot": "fallback",
43
+ className: s.fallback({ class: classNames?.fallback }),
44
+ role: "img",
45
+ "aria-label": name,
46
+ children: fallback ?? (name !== void 0 ? initialsOf(name) : null)
47
+ }), badge !== void 0 && /* @__PURE__ */ jsx("span", {
48
+ "data-slot": "badge",
49
+ className: s.badge({ class: classNames?.badge }),
50
+ children: badge
51
+ })]
52
+ });
53
+ }
54
+ //#endregion
55
+ export { Avatar, initialsOf };
56
+
57
+ //# sourceMappingURL=avatar.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar.mjs","names":[],"sources":["../../src/avatar/avatar.tsx"],"sourcesContent":["'use client'\n\nimport type { AvatarProps } from '@novi-ui/core'\nimport { useState } from 'react'\nimport { avatarStyles } from './avatar.styles'\n\n/**\n * 表示名からイニシャルを作る。\n *\n * 日本語の氏名は空白で区切られないことが多いので、\n * 空白があれば各語の先頭、なければ先頭1文字を使う。\n */\nexport function initialsOf(name: string): string {\n const parts = name.trim().split(/\\s+/).filter(Boolean)\n if (parts.length === 0) return ''\n if (parts.length === 1) return [...(parts[0] as string)][0] ?? ''\n return parts\n .slice(0, 2)\n .map((part) => [...part][0] ?? '')\n .join('')\n}\n\n/**\n * 人や組織を表す画像。読み込みに失敗したら fallback を表示する。\n *\n * @example\n * <Avatar src=\"/me.jpg\" name=\"小島 佑翔\" />\n */\nexport function Avatar({\n size,\n radius,\n src,\n name,\n fallback,\n badge,\n className,\n classNames,\n id,\n}: AvatarProps) {\n const s = avatarStyles({ size, radius })\n const [failed, setFailed] = useState(false)\n const showImage = src !== undefined && src !== '' && !failed\n\n return (\n <span id={id} data-slot=\"root\" className={s.root({ class: [className, classNames?.root] })}>\n {showImage ? (\n <img\n data-slot=\"image\"\n className={s.image({ class: classNames?.image })}\n src={src}\n alt={name ?? ''}\n onError={() => setFailed(true)}\n />\n ) : (\n // 画像の代わりなので role=\"img\" を与える。\n // これがないと aria-label が効かず、読み上げが「小佑」のような\n // イニシャルだけになって氏名が伝わらない\n <span\n data-slot=\"fallback\"\n className={s.fallback({ class: classNames?.fallback })}\n role=\"img\"\n aria-label={name}\n >\n {fallback ?? (name !== undefined ? initialsOf(name) : null)}\n </span>\n )}\n\n {badge !== undefined && (\n <span data-slot=\"badge\" className={s.badge({ class: classNames?.badge })}>\n {badge}\n </span>\n )}\n </span>\n )\n}\n"],"mappings":";;;;;;;;;;;AAYA,SAAgB,WAAW,MAAsB;CAC/C,MAAM,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,OAAO;CACrD,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,IAAI,MAAM,WAAW,GAAG,OAAO,CAAC,GAAI,MAAM,EAAa,CAAC,CAAC,MAAM;CAC/D,OAAO,MACJ,MAAM,GAAG,CAAC,CAAC,CACX,KAAK,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CACjC,KAAK,EAAE;AACZ;;;;;;;AAQA,SAAgB,OAAO,EACrB,MACA,QACA,KACA,MACA,UACA,OACA,WACA,YACA,MACc;CACd,MAAM,IAAI,aAAa;EAAE;EAAM;CAAO,CAAC;CACvC,MAAM,CAAC,QAAQ,aAAa,SAAS,KAAK;CAC1C,MAAM,YAAY,QAAQ,KAAA,KAAa,QAAQ,MAAM,CAAC;CAEtD,OACE,qBAAC,QAAD;EAAU;EAAI,aAAU;EAAO,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,YAAY,IAAI,EAAE,CAAC;EAAzF,UAAA,CACG,YACC,oBAAC,OAAD;GACE,aAAU;GACV,WAAW,EAAE,MAAM,EAAE,OAAO,YAAY,MAAM,CAAC;GAC1C;GACL,KAAK,QAAQ;GACb,eAAe,UAAU,IAAI;EAC9B,CAAA,IAKD,oBAAC,QAAD;GACE,aAAU;GACV,WAAW,EAAE,SAAS,EAAE,OAAO,YAAY,SAAS,CAAC;GACrD,MAAK;GACL,cAAY;GAEX,UAAA,aAAa,SAAS,KAAA,IAAY,WAAW,IAAI,IAAI;EAClD,CAAA,GAGP,UAAU,KAAA,KACT,oBAAC,QAAD;GAAM,aAAU;GAAQ,WAAW,EAAE,MAAM,EAAE,OAAO,YAAY,MAAM,CAAC;GACpE,UAAA;EACG,CAAA,CAEJ;;AAEV"}
@@ -0,0 +1,49 @@
1
+ import { VariantMap } from "@novi-ui/core";
2
+ //#region src/avatar/avatar.styles.d.ts
3
+ /**
4
+ * Avatar のスタイル定義。
5
+ *
6
+ * @example
7
+ * const myAvatar = tv({ extend: avatarStyles, slots: { root: 'border-2' } })
8
+ */
9
+ declare const avatarStyles: import("tailwind-variants").TVReturnType<{
10
+ size: VariantMap<"sm" | "md" | "lg", {
11
+ root: string;
12
+ }>;
13
+ radius: VariantMap<"sm" | "md" | "lg" | "none" | "full", {
14
+ root: string;
15
+ }>;
16
+ }, {
17
+ root: string;
18
+ image: string;
19
+ fallback: string;
20
+ badge: string;
21
+ }, undefined, {
22
+ size: VariantMap<"sm" | "md" | "lg", {
23
+ root: string;
24
+ }>;
25
+ radius: VariantMap<"sm" | "md" | "lg" | "none" | "full", {
26
+ root: string;
27
+ }>;
28
+ }, {
29
+ root: string;
30
+ image: string;
31
+ fallback: string;
32
+ badge: string;
33
+ }, import("tailwind-variants").TVReturnTypeLike<{
34
+ size: VariantMap<"sm" | "md" | "lg", {
35
+ root: string;
36
+ }>;
37
+ radius: VariantMap<"sm" | "md" | "lg" | "none" | "full", {
38
+ root: string;
39
+ }>;
40
+ }, {
41
+ root: string;
42
+ image: string;
43
+ fallback: string;
44
+ badge: string;
45
+ }>>;
46
+ type AvatarStyleProps = Parameters<typeof avatarStyles>[0];
47
+ //#endregion
48
+ export { AvatarStyleProps, avatarStyles };
49
+ //# sourceMappingURL=avatar.styles.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar.styles.d.mts","names":[],"sources":["../../src/avatar/avatar.styles.ts"],"mappings":";;;;;;;;cA6Ca,0CAAY;;IArBgB;;;IAOI;;;;;;;;;IAPJ;;;IAOI;;;;;;;;;IAPJ;;;IAOI;;;;;;;;KAoBjC,mBAAmB,kBAAkB"}
@@ -0,0 +1,45 @@
1
+ import { tv } from "tailwind-variants";
2
+ //#region src/avatar/avatar.styles.ts
3
+ const slots = {
4
+ root: [
5
+ "relative inline-grid place-items-center shrink-0",
6
+ "bg-[var(--novi-color-subtle)]",
7
+ "border border-[var(--novi-color-border)]",
8
+ "overflow-hidden select-none",
9
+ "text-[var(--novi-color-muted)] font-medium"
10
+ ].join(" "),
11
+ image: "size-full object-cover",
12
+ fallback: "uppercase tracking-wide",
13
+ badge: "absolute -bottom-0.5 -right-0.5 ring-2 ring-[var(--novi-color-bg)]"
14
+ };
15
+ /**
16
+ * Avatar のスタイル定義。
17
+ *
18
+ * @example
19
+ * const myAvatar = tv({ extend: avatarStyles, slots: { root: 'border-2' } })
20
+ */
21
+ const avatarStyles = tv({
22
+ slots,
23
+ variants: {
24
+ size: {
25
+ sm: { root: "size-8 text-[length:var(--novi-text-xs)]" },
26
+ md: { root: "size-10 text-[length:var(--novi-text-sm)]" },
27
+ lg: { root: "size-12 text-[length:var(--novi-text-base)]" }
28
+ },
29
+ radius: {
30
+ none: { root: "rounded-[var(--novi-radius-none)]" },
31
+ sm: { root: "rounded-[var(--novi-radius-sm)]" },
32
+ md: { root: "rounded-[var(--novi-radius-md)]" },
33
+ lg: { root: "rounded-[var(--novi-radius-lg)]" },
34
+ full: { root: "rounded-[var(--novi-radius-full)]" }
35
+ }
36
+ },
37
+ defaultVariants: {
38
+ size: "md",
39
+ radius: "full"
40
+ }
41
+ });
42
+ //#endregion
43
+ export { avatarStyles };
44
+
45
+ //# sourceMappingURL=avatar.styles.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avatar.styles.mjs","names":[],"sources":["../../src/avatar/avatar.styles.ts"],"sourcesContent":["import type {\n avatarRequiredSlots,\n avatarSlots,\n NoviRadius,\n NoviSize,\n SlotMap,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\n\nconst slots = {\n root: [\n 'relative inline-grid place-items-center shrink-0',\n 'bg-[var(--novi-color-subtle)]',\n 'border border-[var(--novi-color-border)]',\n 'overflow-hidden select-none',\n 'text-[var(--novi-color-muted)] font-medium',\n ].join(' '),\n image: 'size-full object-cover',\n fallback: 'uppercase tracking-wide',\n // 右下に重ねる。地色で縁取りして境目を作る(影を使わない)\n badge: 'absolute -bottom-0.5 -right-0.5 ring-2 ring-[var(--novi-color-bg)]',\n} satisfies SlotMap<typeof avatarSlots, (typeof avatarRequiredSlots)[number]>\n\nconst size: VariantMap<NoviSize, { root: string }> = {\n sm: { root: 'size-8 text-[length:var(--novi-text-xs)]' },\n md: { root: 'size-10 text-[length:var(--novi-text-sm)]' },\n lg: { root: 'size-12 text-[length:var(--novi-text-base)]' },\n}\n\n/** Avatar は `full` を既定にする唯一のコンポーネント。人を表すものは丸で示す慣習に従う。 */\nconst radius: VariantMap<NoviRadius, { root: string }> = {\n none: { root: 'rounded-[var(--novi-radius-none)]' },\n sm: { root: 'rounded-[var(--novi-radius-sm)]' },\n md: { root: 'rounded-[var(--novi-radius-md)]' },\n lg: { root: 'rounded-[var(--novi-radius-lg)]' },\n full: { root: 'rounded-[var(--novi-radius-full)]' },\n}\n\n/**\n * Avatar のスタイル定義。\n *\n * @example\n * const myAvatar = tv({ extend: avatarStyles, slots: { root: 'border-2' } })\n */\nexport const avatarStyles = tv({\n slots,\n variants: { size, radius },\n defaultVariants: { size: 'md', radius: 'full' },\n})\n\nexport type AvatarStyleProps = Parameters<typeof avatarStyles>[0]\n"],"mappings":";;AAUA,MAAM,QAAQ;CACZ,MAAM;EACJ;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;CACP,UAAU;CAEV,OAAO;AACT;;;;;;;AAuBA,MAAa,eAAe,GAAG;CAC7B;CACA,UAAU;EAAE;GAtBZ,IAAI,EAAE,MAAM,2CAA2C;GACvD,IAAI,EAAE,MAAM,4CAA4C;GACxD,IAAI,EAAE,MAAM,8CAA8C;EAoB9C;EAAM;GAflB,MAAM,EAAE,MAAM,oCAAoC;GAClD,IAAI,EAAE,MAAM,kCAAkC;GAC9C,IAAI,EAAE,MAAM,kCAAkC;GAC9C,IAAI,EAAE,MAAM,kCAAkC;GAC9C,MAAM,EAAE,MAAM,oCAAoC;EAWhC;CAAO;CACzB,iBAAiB;EAAE,MAAM;EAAM,QAAQ;CAAO;AAChD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Avatar, initialsOf } from "./avatar.mjs";
2
+ import { AvatarStyleProps, avatarStyles } from "./avatar.styles.mjs";
3
+ export { Avatar, type AvatarStyleProps, avatarStyles, initialsOf };
@@ -0,0 +1,15 @@
1
+ import { BadgeProps } from "@novi-ui/core";
2
+ //#region src/badge/badge.d.ts
3
+ /**
4
+ * 短いラベルで状態や分類を示す。
5
+ *
6
+ * 色だけで意味を伝えないこと。`success` と `danger` は色相が違うが、
7
+ * 色覚特性によっては区別できない。必ず文言を伴わせる(WCAG 1.4.1)。
8
+ *
9
+ * @example
10
+ * <Badge color="success" variant="soft">公開中</Badge>
11
+ */
12
+ declare function Badge({ variant, size, color, radius, withDot, children, className, classNames, id }: BadgeProps): import("react").JSX.Element;
13
+ //#endregion
14
+ export { Badge };
15
+ //# sourceMappingURL=badge.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.d.mts","names":[],"sources":["../../src/badge/badge.tsx"],"mappings":";;;;;;;;;;;iBAcgB,QACd,SACA,MACA,OACA,QACA,SACA,UACA,WACA,YACA,MACC,6BAAU,IAAA"}