@novi-ui/tactile 0.2.1 → 0.4.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/accordion/accordion.styles.d.mts.map +1 -1
  4. package/dist/accordion/accordion.styles.mjs +41 -29
  5. package/dist/accordion/accordion.styles.mjs.map +1 -1
  6. package/dist/badge/badge.styles.d.mts.map +1 -1
  7. package/dist/badge/badge.styles.mjs +3 -3
  8. package/dist/badge/badge.styles.mjs.map +1 -1
  9. package/dist/breadcrumbs/breadcrumbs.styles.mjs +1 -1
  10. package/dist/breadcrumbs/breadcrumbs.styles.mjs.map +1 -1
  11. package/dist/button/button.styles.d.mts.map +1 -1
  12. package/dist/button/button.styles.mjs +7 -5
  13. package/dist/button/button.styles.mjs.map +1 -1
  14. package/dist/card/card.styles.d.mts.map +1 -1
  15. package/dist/card/card.styles.mjs +8 -3
  16. package/dist/card/card.styles.mjs.map +1 -1
  17. package/dist/checkbox/checkbox.styles.d.mts.map +1 -1
  18. package/dist/checkbox/checkbox.styles.mjs +5 -5
  19. package/dist/checkbox/checkbox.styles.mjs.map +1 -1
  20. package/dist/color-picker/color-picker.styles.d.mts.map +1 -1
  21. package/dist/color-picker/color-picker.styles.mjs +2 -2
  22. package/dist/color-picker/color-picker.styles.mjs.map +1 -1
  23. package/dist/input/input.styles.d.mts.map +1 -1
  24. package/dist/input/input.styles.mjs +4 -4
  25. package/dist/input/input.styles.mjs.map +1 -1
  26. package/dist/menu/menu.styles.d.mts +12 -12
  27. package/dist/menu/menu.styles.d.mts.map +1 -1
  28. package/dist/menu/menu.styles.mjs +8 -4
  29. package/dist/menu/menu.styles.mjs.map +1 -1
  30. package/dist/modal/modal.styles.d.mts.map +1 -1
  31. package/dist/modal/modal.styles.mjs +5 -3
  32. package/dist/modal/modal.styles.mjs.map +1 -1
  33. package/dist/popover/popover.styles.d.mts.map +1 -1
  34. package/dist/popover/popover.styles.mjs +2 -2
  35. package/dist/popover/popover.styles.mjs.map +1 -1
  36. package/dist/progress/progress.mjs +1 -1
  37. package/dist/progress/progress.mjs.map +1 -1
  38. package/dist/radio/radio.styles.d.mts.map +1 -1
  39. package/dist/radio/radio.styles.mjs +5 -5
  40. package/dist/radio/radio.styles.mjs.map +1 -1
  41. package/dist/select/select.styles.d.mts.map +1 -1
  42. package/dist/select/select.styles.mjs +7 -7
  43. package/dist/select/select.styles.mjs.map +1 -1
  44. package/dist/spinner/spinner.styles.mjs +1 -1
  45. package/dist/spinner/spinner.styles.mjs.map +1 -1
  46. package/dist/switch/switch.styles.d.mts.map +1 -1
  47. package/dist/switch/switch.styles.mjs +1 -1
  48. package/dist/switch/switch.styles.mjs.map +1 -1
  49. package/dist/tabs/tabs.styles.d.mts.map +1 -1
  50. package/dist/tabs/tabs.styles.mjs +7 -7
  51. package/dist/tabs/tabs.styles.mjs.map +1 -1
  52. package/dist/tactile.css +16 -0
  53. package/dist/tactile.scoped.css +16 -0
  54. package/dist/textarea/textarea.styles.d.mts.map +1 -1
  55. package/dist/textarea/textarea.styles.mjs +3 -3
  56. package/dist/textarea/textarea.styles.mjs.map +1 -1
  57. package/dist/toast/toast.styles.d.mts.map +1 -1
  58. package/dist/toast/toast.styles.mjs +7 -5
  59. package/dist/toast/toast.styles.mjs.map +1 -1
  60. package/package.json +7 -6
@@ -1 +1 @@
1
- {"version":3,"file":"menu.styles.d.mts","names":[],"sources":["../../src/menu/menu.styles.ts"],"mappings":";;;;;;;cA8Ca,wCAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEX,iBAAiB,kBAAkB"}
1
+ {"version":3,"file":"menu.styles.d.mts","names":[],"sources":["../../src/menu/menu.styles.ts"],"mappings":";;;;;;;cAqDa,wCAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAEX,iBAAiB,kBAAkB"}
@@ -14,10 +14,10 @@ const slots = {
14
14
  "pl-[env(safe-area-inset-left,0px)] pr-[env(safe-area-inset-right,0px)]",
15
15
  "data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]"
16
16
  ].join(" "),
17
- list: "outline-none p-2 flex flex-col",
17
+ list: "outline-none p-1.5 flex flex-col",
18
18
  item: [
19
- "flex items-center gap-3 justify-between",
20
- "min-h-12 px-3 cursor-pointer outline-none",
19
+ "flex items-center gap-[var(--novi-gap-inline)] justify-between",
20
+ "min-h-12 px-[var(--novi-pad-control-x-md)] cursor-pointer outline-none",
21
21
  "text-[var(--novi-color-fg)]",
22
22
  "rounded-[var(--novi-radius-md)]",
23
23
  "data-[focused]:bg-[var(--novi-color-subtle)]",
@@ -28,7 +28,11 @@ const slots = {
28
28
  itemShortcut: "shrink-0 text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)] tabular-nums",
29
29
  separator: "my-1 h-px bg-[var(--novi-color-border)]",
30
30
  section: "flex flex-col",
31
- sectionLabel: "px-2 pt-2 pb-1 text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)] tracking-wide"
31
+ sectionLabel: [
32
+ "px-[var(--novi-pad-control-x-md)] pt-[var(--novi-gap-inline)] pb-1",
33
+ "text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)]",
34
+ "tracking-[var(--novi-tracking-normal)]"
35
+ ].join(" ")
32
36
  };
33
37
  /**
34
38
  * Menu のスタイル定義。
@@ -1 +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 // 横向きのノッチは左右に来る。面は全幅のまま、中身だけを内側へ寄せる(FR-13)\n 'pl-[env(safe-area-inset-left,0px)] pr-[env(safe-area-inset-right,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;EAEA;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"}
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 // 横向きのノッチは左右に来る。面は全幅のまま、中身だけを内側へ寄せる(FR-13)\n 'pl-[env(safe-area-inset-left,0px)] pr-[env(safe-area-inset-right,0px)]',\n 'data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]',\n ].join(' '),\n // 行の背景が丸く抜けて見えるための溝。ここは「余白の設計」ではなく行の位置合わせなので\n // 生値のまま置く。シート端から文字までの実距離は溝 + 行の余白 = 26px で、\n // 面の余白(28px)とほぼ揃う\n list: 'outline-none p-1.5 flex flex-col',\n item: [\n 'flex items-center gap-[var(--novi-gap-inline)] justify-between',\n // 一覧は誤タップが最も起きる場所。行高は 48px を下回らせない\n 'min-h-12 px-[var(--novi-pad-control-x-md)] 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 // 行の文字と左端を揃える。ラベルだけ内側にずれると、どの行に掛かる見出しか読めない\n sectionLabel: [\n 'px-[var(--novi-pad-control-x-md)] pt-[var(--novi-gap-inline)] pb-1',\n 'text-[length:var(--novi-text-xs)] text-[var(--novi-color-muted)]',\n 'tracking-[var(--novi-tracking-normal)]',\n ].join(' '),\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;EAEA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAIV,MAAM;CACN,MAAM;EACJ;EAEA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,WAAW;CACX,iBAAiB;CAEjB,cACE;CACF,WAAW;CACX,SAAS;CAET,cAAc;EACZ;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;AACZ;;;;;;;AAQA,MAAa,aAAa,GAAG,EAAE,MAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"modal.styles.d.mts","names":[],"sources":["../../src/modal/modal.styles.ts"],"mappings":";;;;;;;;;;;cA8Fa,yCAAW;;IAzB2B;;;IAQL;;;;;;;;;;;IARK;;;IAQL;;;;;;;;;;;IARK;;;IAQL;;;;;;;;;;KAuBlC,kBAAkB,kBAAkB"}
1
+ {"version":3,"file":"modal.styles.d.mts","names":[],"sources":["../../src/modal/modal.styles.ts"],"mappings":";;;;;;;;;;;cAuGa,yCAAW;;IAzB2B;;;IAQL;;;;;;;;;;;IARK;;;IAQL;;;;;;;;;;;IARK;;;IAQL;;;;;;;;;;KAuBlC,kBAAkB,kBAAkB"}
@@ -27,8 +27,10 @@ const slots = {
27
27
  "data-[entering]:motion-safe:animate-[novi-slide-up_260ms_var(--novi-ease-emphasized)]"
28
28
  ].join(" "),
29
29
  title: [
30
- "px-5 pt-5 pb-2",
30
+ "px-[var(--novi-pad-surface-x)] pt-[var(--novi-pad-surface-y)] pb-[var(--novi-gap-inline)]",
31
31
  "text-[length:var(--novi-text-lg)] font-bold",
32
+ "font-[family-name:var(--novi-font-heading)]",
33
+ "tracking-[var(--novi-tracking-tight)] leading-[var(--novi-leading-heading)]",
32
34
  "text-[var(--novi-color-fg)]"
33
35
  ].join(" "),
34
36
  closeButton: [
@@ -41,8 +43,8 @@ const slots = {
41
43
  "data-[pressed]:scale-[0.97] motion-reduce:data-[pressed]:scale-100",
42
44
  focusRing
43
45
  ].join(" "),
44
- body: ["px-5 pb-5 pt-1", "text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]"].join(" "),
45
- footer: "flex flex-col gap-2 px-5 pb-5"
46
+ body: ["px-[var(--novi-pad-surface-x)] pb-[var(--novi-pad-surface-y)] pt-1", "text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]"].join(" "),
47
+ footer: ["flex flex-col gap-[var(--novi-gap-inline)]", "px-[var(--novi-pad-surface-x)] pb-[var(--novi-pad-surface-y)]"].join(" ")
46
48
  };
47
49
  /**
48
50
  * Modal のスタイル定義。
@@ -1 +1 @@
1
- {"version":3,"file":"modal.styles.mjs","names":[],"sources":["../../src/modal/modal.styles.ts"],"sourcesContent":["import type {\n modalRequiredSlots,\n modalSlots,\n NoviRadius,\n NoviSize,\n SlotMap,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Modal は **下端から出るボトムシート**(architecture.md §5 テーマB)。\n *\n * Raster との構造差:\n * - 中央配置 → 画面下端に張り付く(`items-end`)\n * - ヘッダー行に ✕ → **フッターのフルワイドボタン**(親指の届く位置に出口を置く)\n * - 上下すべて角丸 → **上端だけ角丸**(下から出てきた紙という形)\n * - 影は下向き → **上向き**(下端から来る面には上から光が当たる)\n */\nconst slots = {\n backdrop: [\n // items-end が「下から出る」の全て。Raster は place-items-center\n 'fixed inset-0 z-50 flex items-end justify-center',\n 'bg-[var(--novi-color-overlay)]',\n 'data-[entering]:motion-safe:animate-[novi-fade-in_200ms_ease-out]',\n ].join(' '),\n panel: [\n 'text-[var(--novi-color-fg)]',\n 'w-full outline-none',\n 'bg-[var(--novi-color-surface)]',\n 'shadow-[var(--novi-shadow-lg)]',\n 'overflow-auto',\n // 下端の余白はホームインジケータぶんを足す。env() の第2引数で\n // safe-area の無い環境(デスクトップ)では 0 に落ちる(AC-10-3 / FR-13)\n 'pb-[env(safe-area-inset-bottom,0px)]',\n // 横向きではノッチが左右に来る。面は画面幅いっぱいのまま、中身だけを内側へ寄せる\n 'pl-[env(safe-area-inset-left,0px)] pr-[env(safe-area-inset-right,0px)]',\n // 下から せり上がる。260ms は移動距離に見合う時間(120ms では瞬間移動に見える)\n 'data-[entering]:motion-safe:animate-[novi-slide-up_260ms_var(--novi-ease-emphasized)]',\n ].join(' '),\n // header は描画しない(任意 slot の省略)。title だけが body の上に載る\n title: [\n 'px-5 pt-5 pb-2',\n 'text-[length:var(--novi-text-lg)] font-bold',\n 'text-[var(--novi-color-fg)]',\n ].join(' '),\n closeButton: [\n // フルワイド。指がどこに落ちても当たる\n 'w-full h-14 grid place-items-center',\n 'text-[length:var(--novi-text-base)] font-bold',\n 'text-[var(--novi-color-fg)]',\n 'bg-[var(--novi-color-subtle)]',\n 'rounded-[var(--novi-radius-md)]',\n 'transition-[background-color,scale] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[pressed]:scale-[0.97] motion-reduce:data-[pressed]:scale-100',\n focusRing,\n ].join(' '),\n body: ['px-5 pb-5 pt-1', 'text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]'].join(\n ' ',\n ),\n // 縦積み。横並びだと1つあたりの幅が指に対して狭くなる\n footer: 'flex flex-col gap-2 px-5 pb-5',\n} satisfies SlotMap<typeof modalSlots, (typeof modalRequiredSlots)[number]>\n\n/**\n * 全幅シートに幅の段階は存在しないため、`size` は**最大高**として解釈する(ADR-T3)。\n * 語彙は共通、解釈はテーマの自由(ADR-06)。\n */\nconst size: VariantMap<NoviSize | 'full', { panel: string }> = {\n sm: { panel: 'max-h-[40dvh]' },\n md: { panel: 'max-h-[60dvh]' },\n lg: { panel: 'max-h-[80dvh]' },\n full: { panel: 'max-h-[100dvh] h-[100dvh]' },\n}\n\n/** 下端は画面に接しているので、角丸は上端だけに効く。 */\nconst radius: VariantMap<NoviRadius, { panel: string }> = {\n none: { panel: 'rounded-t-[var(--novi-radius-none)]' },\n sm: { panel: 'rounded-t-[var(--novi-radius-sm)]' },\n md: { panel: 'rounded-t-[var(--novi-radius-md)]' },\n lg: { panel: 'rounded-t-[var(--novi-radius-lg)]' },\n full: { panel: 'rounded-t-[var(--novi-radius-full)]' },\n}\n\n/**\n * Modal のスタイル定義。\n *\n * @example\n * import { modalStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const myModal = tv({ extend: modalStyles, slots: { panel: 'max-h-[50dvh]' } })\n */\nexport const modalStyles = tv({\n slots,\n variants: { size, radius },\n defaultVariants: { size: 'md', radius: 'lg' },\n})\n\nexport type ModalStyleProps = Parameters<typeof modalStyles>[0]\n\n/**\n * シート上端の掴み手。**装飾であり slot ではない**(architecture.md §5 の運用)。\n *\n * ドラッグ開閉は MVP の対象外(NG6)なので、掴めそうに見せすぎない。\n * 細く低コントラストにして「シートの上端」を示す線に留める。\n */\nexport const grabberClass = [\n 'mx-auto mt-2 mb-1 h-1 w-9 shrink-0',\n 'rounded-[var(--novi-radius-full)]',\n 'bg-[var(--novi-color-border)]',\n].join(' ')\n"],"mappings":";;;;;;;;;;;;AAoBA,MAAM,QAAQ;CACZ,UAAU;EAER;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;EACL;EACA;EACA;EACA;EACA;EAGA;EAEA;EAEA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,OAAO;EACL;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,aAAa;EAEX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,MAAM,CAAC,kBAAkB,gEAAgE,CAAC,CAAC,KACzF,GACF;CAEA,QAAQ;AACV;;;;;;;;;;AA+BA,MAAa,cAAc,GAAG;CAC5B;CACA,UAAU;EAAE;GA1BZ,IAAI,EAAE,OAAO,gBAAgB;GAC7B,IAAI,EAAE,OAAO,gBAAgB;GAC7B,IAAI,EAAE,OAAO,gBAAgB;GAC7B,MAAM,EAAE,OAAO,4BAA4B;EAuB/B;EAAM;GAlBlB,MAAM,EAAE,OAAO,sCAAsC;GACrD,IAAI,EAAE,OAAO,oCAAoC;GACjD,IAAI,EAAE,OAAO,oCAAoC;GACjD,IAAI,EAAE,OAAO,oCAAoC;GACjD,MAAM,EAAE,OAAO,sCAAsC;EAcnC;CAAO;CACzB,iBAAiB;EAAE,MAAM;EAAM,QAAQ;CAAK;AAC9C,CAAC;;;;;;;AAUD,MAAa,eAAe;CAC1B;CACA;CACA;AACF,CAAC,CAAC,KAAK,GAAG"}
1
+ {"version":3,"file":"modal.styles.mjs","names":[],"sources":["../../src/modal/modal.styles.ts"],"sourcesContent":["import type {\n modalRequiredSlots,\n modalSlots,\n NoviRadius,\n NoviSize,\n SlotMap,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Modal は **下端から出るボトムシート**(architecture.md §5 テーマB)。\n *\n * Raster との構造差:\n * - 中央配置 → 画面下端に張り付く(`items-end`)\n * - ヘッダー行に ✕ → **フッターのフルワイドボタン**(親指の届く位置に出口を置く)\n * - 上下すべて角丸 → **上端だけ角丸**(下から出てきた紙という形)\n * - 影は下向き → **上向き**(下端から来る面には上から光が当たる)\n */\nconst slots = {\n backdrop: [\n // items-end が「下から出る」の全て。Raster は place-items-center\n 'fixed inset-0 z-50 flex items-end justify-center',\n 'bg-[var(--novi-color-overlay)]',\n 'data-[entering]:motion-safe:animate-[novi-fade-in_200ms_ease-out]',\n ].join(' '),\n panel: [\n 'text-[var(--novi-color-fg)]',\n 'w-full outline-none',\n 'bg-[var(--novi-color-surface)]',\n 'shadow-[var(--novi-shadow-lg)]',\n 'overflow-auto',\n // 下端の余白はホームインジケータぶんを足す。env() の第2引数で\n // safe-area の無い環境(デスクトップ)では 0 に落ちる(AC-10-3 / FR-13)\n 'pb-[env(safe-area-inset-bottom,0px)]',\n // 横向きではノッチが左右に来る。面は画面幅いっぱいのまま、中身だけを内側へ寄せる\n 'pl-[env(safe-area-inset-left,0px)] pr-[env(safe-area-inset-right,0px)]',\n // 下から せり上がる。260ms は移動距離に見合う時間(120ms では瞬間移動に見える)\n 'data-[entering]:motion-safe:animate-[novi-slide-up_260ms_var(--novi-ease-emphasized)]',\n ].join(' '),\n // header は描画しない(任意 slot の省略)。title だけが body の上に載る\n title: [\n // 下だけ gap トークンなのは、この余白が「見出しと本文の距離」そのものだから。\n // 面の余白(surface-y)で開けると、見出しが本文から切り離されて別の区画に見える\n 'px-[var(--novi-pad-surface-x)] pt-[var(--novi-pad-surface-y)] pb-[var(--novi-gap-inline)]',\n 'text-[length:var(--novi-text-lg)] font-bold',\n 'font-[family-name:var(--novi-font-heading)]',\n 'tracking-[var(--novi-tracking-tight)] leading-[var(--novi-leading-heading)]',\n 'text-[var(--novi-color-fg)]',\n ].join(' '),\n closeButton: [\n // フルワイド。指がどこに落ちても当たる\n 'w-full h-14 grid place-items-center',\n 'text-[length:var(--novi-text-base)] font-bold',\n 'text-[var(--novi-color-fg)]',\n 'bg-[var(--novi-color-subtle)]',\n 'rounded-[var(--novi-radius-md)]',\n 'transition-[background-color,scale] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[pressed]:scale-[0.97] motion-reduce:data-[pressed]:scale-100',\n focusRing,\n ].join(' '),\n body: [\n 'px-[var(--novi-pad-surface-x)] pb-[var(--novi-pad-surface-y)] pt-1',\n 'text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n ].join(' '),\n // 縦積み。横並びだと1つあたりの幅が指に対して狭くなる。\n // ボタン列は1つの塊なので gap は inline。stack まで開けると別々の操作に見える\n footer: [\n 'flex flex-col gap-[var(--novi-gap-inline)]',\n 'px-[var(--novi-pad-surface-x)] pb-[var(--novi-pad-surface-y)]',\n ].join(' '),\n} satisfies SlotMap<typeof modalSlots, (typeof modalRequiredSlots)[number]>\n\n/**\n * 全幅シートに幅の段階は存在しないため、`size` は**最大高**として解釈する(ADR-T3)。\n * 語彙は共通、解釈はテーマの自由(ADR-06)。\n */\nconst size: VariantMap<NoviSize | 'full', { panel: string }> = {\n sm: { panel: 'max-h-[40dvh]' },\n md: { panel: 'max-h-[60dvh]' },\n lg: { panel: 'max-h-[80dvh]' },\n full: { panel: 'max-h-[100dvh] h-[100dvh]' },\n}\n\n/** 下端は画面に接しているので、角丸は上端だけに効く。 */\nconst radius: VariantMap<NoviRadius, { panel: string }> = {\n none: { panel: 'rounded-t-[var(--novi-radius-none)]' },\n sm: { panel: 'rounded-t-[var(--novi-radius-sm)]' },\n md: { panel: 'rounded-t-[var(--novi-radius-md)]' },\n lg: { panel: 'rounded-t-[var(--novi-radius-lg)]' },\n full: { panel: 'rounded-t-[var(--novi-radius-full)]' },\n}\n\n/**\n * Modal のスタイル定義。\n *\n * @example\n * import { modalStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const myModal = tv({ extend: modalStyles, slots: { panel: 'max-h-[50dvh]' } })\n */\nexport const modalStyles = tv({\n slots,\n variants: { size, radius },\n defaultVariants: { size: 'md', radius: 'lg' },\n})\n\nexport type ModalStyleProps = Parameters<typeof modalStyles>[0]\n\n/**\n * シート上端の掴み手。**装飾であり slot ではない**(architecture.md §5 の運用)。\n *\n * ドラッグ開閉は MVP の対象外(NG6)なので、掴めそうに見せすぎない。\n * 細く低コントラストにして「シートの上端」を示す線に留める。\n */\nexport const grabberClass = [\n 'mx-auto mt-2 mb-1 h-1 w-9 shrink-0',\n 'rounded-[var(--novi-radius-full)]',\n 'bg-[var(--novi-color-border)]',\n].join(' ')\n"],"mappings":";;;;;;;;;;;;AAoBA,MAAM,QAAQ;CACZ,UAAU;EAER;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;EACL;EACA;EACA;EACA;EACA;EAGA;EAEA;EAEA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,OAAO;EAGL;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,aAAa;EAEX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,MAAM,CACJ,sEACA,gEACF,CAAC,CAAC,KAAK,GAAG;CAGV,QAAQ,CACN,8CACA,+DACF,CAAC,CAAC,KAAK,GAAG;AACZ;;;;;;;;;;AA+BA,MAAa,cAAc,GAAG;CAC5B;CACA,UAAU;EAAE;GA1BZ,IAAI,EAAE,OAAO,gBAAgB;GAC7B,IAAI,EAAE,OAAO,gBAAgB;GAC7B,IAAI,EAAE,OAAO,gBAAgB;GAC7B,MAAM,EAAE,OAAO,4BAA4B;EAuB/B;EAAM;GAlBlB,MAAM,EAAE,OAAO,sCAAsC;GACrD,IAAI,EAAE,OAAO,oCAAoC;GACjD,IAAI,EAAE,OAAO,oCAAoC;GACjD,IAAI,EAAE,OAAO,oCAAoC;GACjD,MAAM,EAAE,OAAO,sCAAsC;EAcnC;CAAO;CACzB,iBAAiB;EAAE,MAAM;EAAM,QAAQ;CAAK;AAC9C,CAAC;;;;;;;AAUD,MAAa,eAAe;CAC1B;CACA;CACA;AACF,CAAC,CAAC,KAAK,GAAG"}
@@ -1 +1 @@
1
- {"version":3,"file":"popover.styles.d.mts","names":[],"sources":["../../src/popover/popover.styles.ts"],"mappings":";;;;;;;;cAuCa,2CAAa;;IAdmB;;;;;;;;IAAA;;;;;;;;IAAA;;;;;;;;;;;;;cA0BhC,2CAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAed,oBAAoB,kBAAkB;KACtC,oBAAoB,kBAAkB"}
1
+ {"version":3,"file":"popover.styles.d.mts","names":[],"sources":["../../src/popover/popover.styles.ts"],"mappings":";;;;;;;;cA0Ca,2CAAa;;IAdmB;;;;;;;;IAAA;;;;;;;;IAAA;;;;;;;;;;;;;cA0BhC,2CAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAoBd,oBAAoB,kBAAkB;KACtC,oBAAoB,kBAAkB"}
@@ -10,7 +10,7 @@ const slots = {
10
10
  "data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]"
11
11
  ].join(" "),
12
12
  arrow: "hidden",
13
- content: "px-4 py-3 text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]"
13
+ content: ["px-[var(--novi-pad-surface-x)] py-[var(--novi-pad-surface-y)]", "text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]"].join(" ")
14
14
  };
15
15
  /**
16
16
  * Popover のスタイル定義。
@@ -45,7 +45,7 @@ const tooltipStyles = tv({ slots: {
45
45
  "data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]"
46
46
  ].join(" "),
47
47
  arrow: "hidden",
48
- content: "px-2 py-1 text-[length:var(--novi-text-xs)] leading-snug"
48
+ content: ["px-[var(--novi-pad-control-x-sm)] py-1.5", "text-[length:var(--novi-text-xs)] leading-snug"].join(" ")
49
49
  } });
50
50
  //#endregion
51
51
  export { popoverStyles, tooltipStyles };
@@ -1 +1 @@
1
- {"version":3,"file":"popover.styles.mjs","names":[],"sources":["../../src/popover/popover.styles.ts"],"sourcesContent":["import type {\n NoviRadius,\n popoverRequiredSlots,\n popoverSlots,\n SlotMap,\n tooltipRequiredSlots,\n tooltipSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\n\nconst slots = {\n root: [\n 'text-[var(--novi-color-fg)]',\n 'outline-none',\n 'bg-[var(--novi-color-bg)]',\n 'ring-1 ring-[var(--novi-color-border)]',\n 'shadow-[var(--novi-shadow-md)]',\n 'data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]',\n ].join(' '),\n // Raster では arrow を描画しない。任意 slot を省略する実例\n arrow: 'hidden',\n content: 'px-4 py-3 text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n} satisfies SlotMap<typeof popoverSlots, (typeof popoverRequiredSlots)[number]>\n\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 * Popover のスタイル定義。\n *\n * @example\n * const myPopover = tv({ extend: popoverStyles, slots: { content: 'p-6' } })\n */\nexport const popoverStyles = tv({\n slots,\n variants: { radius },\n defaultVariants: { radius: 'lg' },\n})\n\n/**\n * Tooltip のスタイル定義。\n *\n * Popover と違い**反転色**(暗い面に明るい文字)で出す。\n * 補足であって操作対象ではない、という区別を色で伝える。\n */\nexport const tooltipStyles = tv({\n slots: {\n root: [\n 'outline-none max-w-xs',\n 'bg-[var(--novi-color-fg)] text-[var(--novi-color-bg)]',\n 'border border-transparent',\n 'rounded-[var(--novi-radius-sm)]',\n 'shadow-[var(--novi-shadow-md)]',\n 'data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]',\n ].join(' '),\n arrow: 'hidden',\n content: 'px-2 py-1 text-[length:var(--novi-text-xs)] leading-snug',\n } satisfies SlotMap<typeof tooltipSlots, (typeof tooltipRequiredSlots)[number]>,\n})\n\nexport type PopoverStyleProps = Parameters<typeof popoverStyles>[0]\nexport type TooltipStyleProps = Parameters<typeof tooltipStyles>[0]\n"],"mappings":";;AAWA,MAAM,QAAQ;CACZ,MAAM;EACJ;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,OAAO;CACP,SAAS;AACX;;;;;;;AAgBA,MAAa,gBAAgB,GAAG;CAC9B;CACA,UAAU,EAAE;EAfZ,MAAM,EAAE,MAAM,oCAAoC;EAClD,IAAI,EAAE,MAAM,kCAAkC;EAC9C,IAAI,EAAE,MAAM,kCAAkC;EAC9C,IAAI,EAAE,MAAM,kCAAkC;EAC9C,MAAM,EAAE,MAAM,oCAAoC;CAWtC,EAAO;CACnB,iBAAiB,EAAE,QAAQ,KAAK;AAClC,CAAC;;;;;;;AAQD,MAAa,gBAAgB,GAAG,EAC9B,OAAO;CACL,MAAM;EACJ;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;CACP,SAAS;AACX,EACF,CAAC"}
1
+ {"version":3,"file":"popover.styles.mjs","names":[],"sources":["../../src/popover/popover.styles.ts"],"sourcesContent":["import type {\n NoviRadius,\n popoverRequiredSlots,\n popoverSlots,\n SlotMap,\n tooltipRequiredSlots,\n tooltipSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\n\nconst slots = {\n root: [\n 'text-[var(--novi-color-fg)]',\n 'outline-none',\n 'bg-[var(--novi-color-bg)]',\n 'ring-1 ring-[var(--novi-color-border)]',\n 'shadow-[var(--novi-shadow-md)]',\n 'data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]',\n ].join(' '),\n // Raster では arrow を描画しない。任意 slot を省略する実例\n arrow: 'hidden',\n content: [\n 'px-[var(--novi-pad-surface-x)] py-[var(--novi-pad-surface-y)]',\n 'text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n ].join(' '),\n} satisfies SlotMap<typeof popoverSlots, (typeof popoverRequiredSlots)[number]>\n\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 * Popover のスタイル定義。\n *\n * @example\n * const myPopover = tv({ extend: popoverStyles, slots: { content: 'p-6' } })\n */\nexport const popoverStyles = tv({\n slots,\n variants: { radius },\n defaultVariants: { radius: 'lg' },\n})\n\n/**\n * Tooltip のスタイル定義。\n *\n * Popover と違い**反転色**(暗い面に明るい文字)で出す。\n * 補足であって操作対象ではない、という区別を色で伝える。\n */\nexport const tooltipStyles = tv({\n slots: {\n root: [\n 'outline-none max-w-xs',\n 'bg-[var(--novi-color-fg)] text-[var(--novi-color-bg)]',\n 'border border-transparent',\n 'rounded-[var(--novi-radius-sm)]',\n 'shadow-[var(--novi-shadow-md)]',\n 'data-[entering]:motion-safe:animate-[novi-fade-in_120ms_ease-out]',\n ].join(' '),\n arrow: 'hidden',\n // 補足の小片であって面ではないので、上下は面の余白を使わない。\n // 横だけコントロール段の余白に揃えると、隣接するボタンと縁が並んで見える\n content: [\n 'px-[var(--novi-pad-control-x-sm)] py-1.5',\n 'text-[length:var(--novi-text-xs)] leading-snug',\n ].join(' '),\n } satisfies SlotMap<typeof tooltipSlots, (typeof tooltipRequiredSlots)[number]>,\n})\n\nexport type PopoverStyleProps = Parameters<typeof popoverStyles>[0]\nexport type TooltipStyleProps = Parameters<typeof tooltipStyles>[0]\n"],"mappings":";;AAWA,MAAM,QAAQ;CACZ,MAAM;EACJ;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,OAAO;CACP,SAAS,CACP,iEACA,gEACF,CAAC,CAAC,KAAK,GAAG;AACZ;;;;;;;AAgBA,MAAa,gBAAgB,GAAG;CAC9B;CACA,UAAU,EAAE;EAfZ,MAAM,EAAE,MAAM,oCAAoC;EAClD,IAAI,EAAE,MAAM,kCAAkC;EAC9C,IAAI,EAAE,MAAM,kCAAkC;EAC9C,IAAI,EAAE,MAAM,kCAAkC;EAC9C,MAAM,EAAE,MAAM,oCAAoC;CAWtC,EAAO;CACnB,iBAAiB,EAAE,QAAQ,KAAK;AAClC,CAAC;;;;;;;AAQD,MAAa,gBAAgB,GAAG,EAC9B,OAAO;CACL,MAAM;EACJ;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;CAGP,SAAS,CACP,4CACA,gDACF,CAAC,CAAC,KAAK,GAAG;AACZ,EACF,CAAC"}
@@ -27,7 +27,7 @@ function Progress({ size, color, label, value, minValue = 0, maxValue = 100, sho
27
27
  "data-slot": "root",
28
28
  className: s.root({ class: [className, classNames?.root] }),
29
29
  children: ({ percentage, valueText }) => /* @__PURE__ */ jsxs(Fragment, { children: [(label !== void 0 || showValueLabel === true) && /* @__PURE__ */ jsxs("span", {
30
- className: "flex items-baseline justify-between gap-2",
30
+ className: "flex items-baseline justify-between gap-[var(--novi-gap-inline)]",
31
31
  children: [label !== void 0 && /* @__PURE__ */ jsx(Label, {
32
32
  "data-slot": "label",
33
33
  className: s.label({ class: classNames?.label }),
@@ -1 +1 @@
1
- {"version":3,"file":"progress.mjs","names":[],"sources":["../../src/progress/progress.tsx"],"sourcesContent":["'use client'\n\nimport type { ProgressProps } from '@novi-ui/core'\nimport { Label, ProgressBar } from 'react-aria-components'\nimport { progressStyles } from './progress.styles'\n\n/**\n * 進捗の表示。`value` を省略すると不確定(indeterminate)表示になる。\n *\n * `prefers-reduced-motion` が有効なときは不確定表示のアニメーションを止める。\n *\n * @example\n * <Progress label=\"アップロード中\" value={62} showValueLabel />\n */\nexport function Progress({\n size,\n color,\n label,\n value,\n minValue = 0,\n maxValue = 100,\n showValueLabel,\n className,\n classNames,\n id,\n}: ProgressProps) {\n const isIndeterminate = value === undefined\n const s = progressStyles({ size, color, isIndeterminate })\n\n return (\n <ProgressBar\n id={id}\n value={value}\n minValue={minValue}\n maxValue={maxValue}\n isIndeterminate={isIndeterminate}\n data-slot=\"root\"\n className={s.root({ class: [className, classNames?.root] })}\n >\n {({ percentage, valueText }) => (\n <>\n {(label !== undefined || showValueLabel === true) && (\n <span className=\"flex items-baseline justify-between gap-2\">\n {label !== undefined && (\n <Label data-slot=\"label\" className={s.label({ class: classNames?.label })}>\n {label}\n </Label>\n )}\n {showValueLabel === true && !isIndeterminate && (\n <span\n data-slot=\"valueLabel\"\n className={s.valueLabel({ class: classNames?.valueLabel })}\n >\n {valueText}\n </span>\n )}\n </span>\n )}\n\n <span data-slot=\"track\" className={s.track({ class: classNames?.track })}>\n <span\n data-slot=\"indicator\"\n className={s.indicator({ class: classNames?.indicator })}\n style={isIndeterminate ? undefined : { width: `${percentage ?? 0}%` }}\n />\n </span>\n </>\n )}\n </ProgressBar>\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,SAAS,EACvB,MACA,OACA,OACA,OACA,WAAW,GACX,WAAW,KACX,gBACA,WACA,YACA,MACgB;CAChB,MAAM,kBAAkB,UAAU,KAAA;CAClC,MAAM,IAAI,eAAe;EAAE;EAAM;EAAO;CAAgB,CAAC;CAEzD,OACE,oBAAC,aAAD;EACM;EACG;EACG;EACA;EACO;EACjB,aAAU;EACV,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,YAAY,IAAI,EAAE,CAAC;EAExD,WAAA,EAAE,YAAY,gBACd,qBAAA,UAAA,EAAA,UAAA,EACI,UAAU,KAAA,KAAa,mBAAmB,SAC1C,qBAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACG,UAAU,KAAA,KACT,oBAAC,OAAD;IAAO,aAAU;IAAQ,WAAW,EAAE,MAAM,EAAE,OAAO,YAAY,MAAM,CAAC;IACrE,UAAA;GACI,CAAA,GAER,mBAAmB,QAAQ,CAAC,mBAC3B,oBAAC,QAAD;IACE,aAAU;IACV,WAAW,EAAE,WAAW,EAAE,OAAO,YAAY,WAAW,CAAC;IAExD,UAAA;GACG,CAAA,CAEJ;EAGR,CAAA,GAAA,oBAAC,QAAD;GAAM,aAAU;GAAQ,WAAW,EAAE,MAAM,EAAE,OAAO,YAAY,MAAM,CAAC;GACrE,UAAA,oBAAC,QAAD;IACE,aAAU;IACV,WAAW,EAAE,UAAU,EAAE,OAAO,YAAY,UAAU,CAAC;IACvD,OAAO,kBAAkB,KAAA,IAAY,EAAE,OAAO,GAAG,cAAc,EAAE,GAAG;GACrE,CAAA;EACG,CAAA,CACN,EAAA,CAAA;CAEO,CAAA;AAEjB"}
1
+ {"version":3,"file":"progress.mjs","names":[],"sources":["../../src/progress/progress.tsx"],"sourcesContent":["'use client'\n\nimport type { ProgressProps } from '@novi-ui/core'\nimport { Label, ProgressBar } from 'react-aria-components'\nimport { progressStyles } from './progress.styles'\n\n/**\n * 進捗の表示。`value` を省略すると不確定(indeterminate)表示になる。\n *\n * `prefers-reduced-motion` が有効なときは不確定表示のアニメーションを止める。\n *\n * @example\n * <Progress label=\"アップロード中\" value={62} showValueLabel />\n */\nexport function Progress({\n size,\n color,\n label,\n value,\n minValue = 0,\n maxValue = 100,\n showValueLabel,\n className,\n classNames,\n id,\n}: ProgressProps) {\n const isIndeterminate = value === undefined\n const s = progressStyles({ size, color, isIndeterminate })\n\n return (\n <ProgressBar\n id={id}\n value={value}\n minValue={minValue}\n maxValue={maxValue}\n isIndeterminate={isIndeterminate}\n data-slot=\"root\"\n className={s.root({ class: [className, classNames?.root] })}\n >\n {({ percentage, valueText }) => (\n <>\n {(label !== undefined || showValueLabel === true) && (\n <span className=\"flex items-baseline justify-between gap-[var(--novi-gap-inline)]\">\n {label !== undefined && (\n <Label data-slot=\"label\" className={s.label({ class: classNames?.label })}>\n {label}\n </Label>\n )}\n {showValueLabel === true && !isIndeterminate && (\n <span\n data-slot=\"valueLabel\"\n className={s.valueLabel({ class: classNames?.valueLabel })}\n >\n {valueText}\n </span>\n )}\n </span>\n )}\n\n <span data-slot=\"track\" className={s.track({ class: classNames?.track })}>\n <span\n data-slot=\"indicator\"\n className={s.indicator({ class: classNames?.indicator })}\n style={isIndeterminate ? undefined : { width: `${percentage ?? 0}%` }}\n />\n </span>\n </>\n )}\n </ProgressBar>\n )\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,SAAS,EACvB,MACA,OACA,OACA,OACA,WAAW,GACX,WAAW,KACX,gBACA,WACA,YACA,MACgB;CAChB,MAAM,kBAAkB,UAAU,KAAA;CAClC,MAAM,IAAI,eAAe;EAAE;EAAM;EAAO;CAAgB,CAAC;CAEzD,OACE,oBAAC,aAAD;EACM;EACG;EACG;EACA;EACO;EACjB,aAAU;EACV,WAAW,EAAE,KAAK,EAAE,OAAO,CAAC,WAAW,YAAY,IAAI,EAAE,CAAC;EAExD,WAAA,EAAE,YAAY,gBACd,qBAAA,UAAA,EAAA,UAAA,EACI,UAAU,KAAA,KAAa,mBAAmB,SAC1C,qBAAC,QAAD;GAAM,WAAU;GAAhB,UAAA,CACG,UAAU,KAAA,KACT,oBAAC,OAAD;IAAO,aAAU;IAAQ,WAAW,EAAE,MAAM,EAAE,OAAO,YAAY,MAAM,CAAC;IACrE,UAAA;GACI,CAAA,GAER,mBAAmB,QAAQ,CAAC,mBAC3B,oBAAC,QAAD;IACE,aAAU;IACV,WAAW,EAAE,WAAW,EAAE,OAAO,YAAY,WAAW,CAAC;IAExD,UAAA;GACG,CAAA,CAEJ;EAGR,CAAA,GAAA,oBAAC,QAAD;GAAM,aAAU;GAAQ,WAAW,EAAE,MAAM,EAAE,OAAO,YAAY,MAAM,CAAC;GACrE,UAAA,oBAAC,QAAD;IACE,aAAU;IACV,WAAW,EAAE,UAAU,EAAE,OAAO,YAAY,UAAU,CAAC;IACvD,OAAO,kBAAkB,KAAA,IAAY,EAAE,OAAO,GAAG,cAAc,EAAE,GAAG;GACrE,CAAA;EACG,CAAA,CACN,EAAA,CAAA;CAEO,CAAA;AAEjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"radio.styles.d.mts","names":[],"sources":["../../src/radio/radio.styles.ts"],"mappings":";;;;;;;;cAmEa,yCAAW;;IAtBmB;;;IAUC;IAAmB;IAAe;;;;;;;;;;IAVnC;;;IAUC;IAAmB;IAAe;;;;;;;;;;IAVnC;;;IAUC;IAAmB;IAAe;;;;;;;;;;;;;;;cAgCjE,8CAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAWjB,kBAAkB,kBAAkB;KACpC,uBAAuB,kBAAkB"}
1
+ {"version":3,"file":"radio.styles.d.mts","names":[],"sources":["../../src/radio/radio.styles.ts"],"mappings":";;;;;;;;cAmEa,yCAAW;;IAtBmB;;;IAUC;IAAmB;IAAe;;;;;;;;;;IAVnC;;;IAUC;IAAmB;IAAe;;;;;;;;;;IAVnC;;;IAUC;IAAmB;IAAe;;;;;;;;;;;;;;;cAiCjE,8CAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAWjB,kBAAkB,kBAAkB;KACpC,uBAAuB,kBAAkB"}
@@ -8,7 +8,7 @@ import { tv } from "tailwind-variants";
8
8
  */
9
9
  const slots = {
10
10
  root: [
11
- "inline-flex items-center gap-3 min-h-12 py-1",
11
+ "inline-flex items-center gap-[var(--novi-gap-inline)] min-h-12 py-1",
12
12
  "cursor-pointer",
13
13
  tapTarget,
14
14
  disabledState
@@ -77,15 +77,15 @@ const radioStyles = tv({
77
77
  */
78
78
  const radioGroupStyles = tv({
79
79
  slots: {
80
- root: "flex flex-col gap-2",
80
+ root: "flex flex-col gap-[var(--novi-gap-inline)]",
81
81
  label: "text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]",
82
- list: "flex flex-col gap-2",
82
+ list: "flex flex-col gap-[var(--novi-gap-stack)]",
83
83
  description: "text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]",
84
84
  errorMessage: "text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]"
85
85
  },
86
86
  variants: { orientation: {
87
- vertical: { list: "flex-col gap-2" },
88
- horizontal: { list: "flex-row gap-4 flex-wrap" }
87
+ vertical: { list: "flex-col gap-[var(--novi-gap-stack)]" },
88
+ horizontal: { list: "flex-row gap-[var(--novi-gap-section)] flex-wrap" }
89
89
  } },
90
90
  defaultVariants: { orientation: "vertical" }
91
91
  });
@@ -1 +1 @@
1
- {"version":3,"file":"radio.styles.mjs","names":[],"sources":["../../src/radio/radio.styles.ts"],"sourcesContent":["import type {\n NoviColor,\n NoviSize,\n radioGroupRequiredSlots,\n radioGroupSlots,\n radioRequiredSlots,\n radioSlots,\n SlotMap,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\nimport { tapTarget } from '../styles/tap-target'\n\n/**\n * Checkbox と同じく、視覚寸法とタップ寸法を分ける(AC-01-5)。\n * 行全体を押せるようにするのは、指がラベルに落ちても切り替わるようにするため。\n */\nconst slots = {\n root: [\n 'inline-flex items-center gap-3 min-h-12 py-1',\n 'cursor-pointer',\n tapTarget,\n disabledState,\n ].join(' '),\n // 円は radius-full を使う数少ない例外。Checkbox(四角)との形の差で\n // 「1つだけ選ぶ」ことを示すため、ここは丸を守る\n control: [\n 'shrink-0 inline-grid place-items-center',\n 'ring-1 ring-[var(--novi-color-border-strong)]',\n 'rounded-[var(--novi-radius-full)]',\n 'bg-[var(--novi-color-surface)]',\n 'transition-[box-shadow,scale]',\n 'duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'group-data-[pressed]:scale-[0.92] motion-reduce:group-data-[pressed]:scale-100',\n 'group-data-[selected]:ring-[var(--c)]',\n 'group-data-[invalid]:ring-[var(--novi-color-danger)]',\n focusRing,\n ].join(' '),\n // 内側のドットで選択を示す。塗りつぶしにしない\n indicator: 'rounded-[var(--novi-radius-full)] bg-[var(--c)]',\n label: 'text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n} satisfies SlotMap<typeof radioSlots, (typeof radioRequiredSlots)[number]>\n\nconst color: VariantMap<NoviColor, { root: string }> = {\n default: { root: '[--c:var(--novi-color-fg)]' },\n primary: { root: '[--c:var(--novi-color-primary)]' },\n secondary: { root: '[--c:var(--novi-color-secondary)]' },\n success: { root: '[--c:var(--novi-color-success)]' },\n warning: { root: '[--c:var(--novi-color-warning)]' },\n danger: { root: '[--c:var(--novi-color-danger)]' },\n}\n\n/** 視覚寸法。当たり判定は root の tapTarget が 44px を保つ。 */\nconst size: VariantMap<NoviSize, { control: string; indicator: string; label: string }> = {\n sm: { control: 'size-5', indicator: 'size-2', label: 'text-[length:var(--novi-text-sm)]' },\n md: { control: 'size-6', indicator: 'size-2.5', label: 'text-[length:var(--novi-text-base)]' },\n lg: { control: 'size-7', indicator: 'size-3', label: 'text-[length:var(--novi-text-base)]' },\n}\n\n/**\n * Radio のスタイル定義。\n *\n * @example\n * const myRadio = tv({ extend: radioStyles, slots: { label: 'font-medium' } })\n */\nexport const radioStyles = tv({\n slots,\n variants: { color, size },\n defaultVariants: { color: 'default', size: 'md' },\n})\n\nconst groupSlots = {\n root: 'flex flex-col gap-2',\n label: 'text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]',\n list: 'flex flex-col gap-2',\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n errorMessage: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]',\n} satisfies SlotMap<typeof radioGroupSlots, (typeof radioGroupRequiredSlots)[number]>\n\n/**\n * RadioGroup のスタイル定義。\n *\n * @example\n * const myGroup = tv({ extend: radioGroupStyles, slots: { list: 'gap-4' } })\n */\nexport const radioGroupStyles = tv({\n slots: groupSlots,\n variants: {\n orientation: {\n vertical: { list: 'flex-col gap-2' },\n horizontal: { list: 'flex-row gap-4 flex-wrap' },\n },\n },\n defaultVariants: { orientation: 'vertical' },\n})\n\nexport type RadioStyleProps = Parameters<typeof radioStyles>[0]\nexport type RadioGroupStyleProps = Parameters<typeof radioGroupStyles>[0]\n"],"mappings":";;;;;;;;AAkBA,MAAM,QAAQ;CACZ,MAAM;EACJ;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAGV,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,WAAW;CACX,OAAO;CACP,aAAa;AACf;;;;;;;AAwBA,MAAa,cAAc,GAAG;CAC5B;CACA,UAAU;EAAE;GAvBZ,SAAS,EAAE,MAAM,6BAA6B;GAC9C,SAAS,EAAE,MAAM,kCAAkC;GACnD,WAAW,EAAE,MAAM,oCAAoC;GACvD,SAAS,EAAE,MAAM,kCAAkC;GACnD,SAAS,EAAE,MAAM,kCAAkC;GACnD,QAAQ,EAAE,MAAM,iCAAiC;EAkBrC;EAAO;GAbnB,IAAI;IAAE,SAAS;IAAU,WAAW;IAAU,OAAO;GAAoC;GACzF,IAAI;IAAE,SAAS;IAAU,WAAW;IAAY,OAAO;GAAsC;GAC7F,IAAI;IAAE,SAAS;IAAU,WAAW;IAAU,OAAO;GAAsC;EAWxE;CAAK;CACxB,iBAAiB;EAAE,OAAO;EAAW,MAAM;CAAK;AAClD,CAAC;;;;;;;AAgBD,MAAa,mBAAmB,GAAG;CACjC,OAAO;EAdP,MAAM;EACN,OAAO;EACP,MAAM;EACN,aAAa;EACb,cAAc;CAUP;CACP,UAAU,EACR,aAAa;EACX,UAAU,EAAE,MAAM,iBAAiB;EACnC,YAAY,EAAE,MAAM,2BAA2B;CACjD,EACF;CACA,iBAAiB,EAAE,aAAa,WAAW;AAC7C,CAAC"}
1
+ {"version":3,"file":"radio.styles.mjs","names":[],"sources":["../../src/radio/radio.styles.ts"],"sourcesContent":["import type {\n NoviColor,\n NoviSize,\n radioGroupRequiredSlots,\n radioGroupSlots,\n radioRequiredSlots,\n radioSlots,\n SlotMap,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\nimport { tapTarget } from '../styles/tap-target'\n\n/**\n * Checkbox と同じく、視覚寸法とタップ寸法を分ける(AC-01-5)。\n * 行全体を押せるようにするのは、指がラベルに落ちても切り替わるようにするため。\n */\nconst slots = {\n root: [\n 'inline-flex items-center gap-[var(--novi-gap-inline)] min-h-12 py-1',\n 'cursor-pointer',\n tapTarget,\n disabledState,\n ].join(' '),\n // 円は radius-full を使う数少ない例外。Checkbox(四角)との形の差で\n // 「1つだけ選ぶ」ことを示すため、ここは丸を守る\n control: [\n 'shrink-0 inline-grid place-items-center',\n 'ring-1 ring-[var(--novi-color-border-strong)]',\n 'rounded-[var(--novi-radius-full)]',\n 'bg-[var(--novi-color-surface)]',\n 'transition-[box-shadow,scale]',\n 'duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'group-data-[pressed]:scale-[0.92] motion-reduce:group-data-[pressed]:scale-100',\n 'group-data-[selected]:ring-[var(--c)]',\n 'group-data-[invalid]:ring-[var(--novi-color-danger)]',\n focusRing,\n ].join(' '),\n // 内側のドットで選択を示す。塗りつぶしにしない\n indicator: 'rounded-[var(--novi-radius-full)] bg-[var(--c)]',\n label: 'text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n} satisfies SlotMap<typeof radioSlots, (typeof radioRequiredSlots)[number]>\n\nconst color: VariantMap<NoviColor, { root: string }> = {\n default: { root: '[--c:var(--novi-color-fg)]' },\n primary: { root: '[--c:var(--novi-color-primary)]' },\n secondary: { root: '[--c:var(--novi-color-secondary)]' },\n success: { root: '[--c:var(--novi-color-success)]' },\n warning: { root: '[--c:var(--novi-color-warning)]' },\n danger: { root: '[--c:var(--novi-color-danger)]' },\n}\n\n/** 視覚寸法。当たり判定は root の tapTarget が 44px を保つ。 */\nconst size: VariantMap<NoviSize, { control: string; indicator: string; label: string }> = {\n sm: { control: 'size-5', indicator: 'size-2', label: 'text-[length:var(--novi-text-sm)]' },\n md: { control: 'size-6', indicator: 'size-2.5', label: 'text-[length:var(--novi-text-base)]' },\n lg: { control: 'size-7', indicator: 'size-3', label: 'text-[length:var(--novi-text-base)]' },\n}\n\n/**\n * Radio のスタイル定義。\n *\n * @example\n * const myRadio = tv({ extend: radioStyles, slots: { label: 'font-medium' } })\n */\nexport const radioStyles = tv({\n slots,\n variants: { color, size },\n defaultVariants: { color: 'default', size: 'md' },\n})\n\nconst groupSlots = {\n // Checkbox と同じ扱い。フィールドの部品どうしは inline、選択肢どうしは stack\n root: 'flex flex-col gap-[var(--novi-gap-inline)]',\n label: 'text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]',\n list: 'flex flex-col gap-[var(--novi-gap-stack)]',\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n errorMessage: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]',\n} satisfies SlotMap<typeof radioGroupSlots, (typeof radioGroupRequiredSlots)[number]>\n\n/**\n * RadioGroup のスタイル定義。\n *\n * @example\n * const myGroup = tv({ extend: radioGroupStyles, slots: { list: 'gap-4' } })\n */\nexport const radioGroupStyles = tv({\n slots: groupSlots,\n variants: {\n orientation: {\n vertical: { list: 'flex-col gap-[var(--novi-gap-stack)]' },\n horizontal: { list: 'flex-row gap-[var(--novi-gap-section)] flex-wrap' },\n },\n },\n defaultVariants: { orientation: 'vertical' },\n})\n\nexport type RadioStyleProps = Parameters<typeof radioStyles>[0]\nexport type RadioGroupStyleProps = Parameters<typeof radioGroupStyles>[0]\n"],"mappings":";;;;;;;;AAkBA,MAAM,QAAQ;CACZ,MAAM;EACJ;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAGV,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,WAAW;CACX,OAAO;CACP,aAAa;AACf;;;;;;;AAwBA,MAAa,cAAc,GAAG;CAC5B;CACA,UAAU;EAAE;GAvBZ,SAAS,EAAE,MAAM,6BAA6B;GAC9C,SAAS,EAAE,MAAM,kCAAkC;GACnD,WAAW,EAAE,MAAM,oCAAoC;GACvD,SAAS,EAAE,MAAM,kCAAkC;GACnD,SAAS,EAAE,MAAM,kCAAkC;GACnD,QAAQ,EAAE,MAAM,iCAAiC;EAkBrC;EAAO;GAbnB,IAAI;IAAE,SAAS;IAAU,WAAW;IAAU,OAAO;GAAoC;GACzF,IAAI;IAAE,SAAS;IAAU,WAAW;IAAY,OAAO;GAAsC;GAC7F,IAAI;IAAE,SAAS;IAAU,WAAW;IAAU,OAAO;GAAsC;EAWxE;CAAK;CACxB,iBAAiB;EAAE,OAAO;EAAW,MAAM;CAAK;AAClD,CAAC;;;;;;;AAiBD,MAAa,mBAAmB,GAAG;CACjC,OAAO;EAdP,MAAM;EACN,OAAO;EACP,MAAM;EACN,aAAa;EACb,cAAc;CAUP;CACP,UAAU,EACR,aAAa;EACX,UAAU,EAAE,MAAM,uCAAuC;EACzD,YAAY,EAAE,MAAM,mDAAmD;CACzE,EACF;CACA,iBAAiB,EAAE,aAAa,WAAW;AAC7C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"select.styles.d.mts","names":[],"sources":["../../src/select/select.styles.ts"],"mappings":";;;;;;;;;;;;;;cA4Ha,0CAAY;;IAhDmB;IAAgB;;;IAeZ;;;IAQE;;;;;;;;;;;;;;;IAvBN;IAAgB;;;IAeZ;;;IAQE;;;;;;;;;;;;;;;IAvBN;IAAgB;;;IAeZ;;;IAQE;;;;;;;;;;;;;;KA+BtC,mBAAmB,kBAAkB"}
1
+ {"version":3,"file":"select.styles.d.mts","names":[],"sources":["../../src/select/select.styles.ts"],"mappings":";;;;;;;;;;;;;;cA6Ha,0CAAY;;IAhDmB;IAAgB;;;IAeZ;;;IAQE;;;;;;;;;;;;;;;IAvBN;IAAgB;;;IAeZ;;;IAQE;;;;;;;;;;;;;;;IAvBN;IAAgB;;;IAeZ;;;IAQE;;;;;;;;;;;;;;KA+BtC,mBAAmB,kBAAkB"}
@@ -15,7 +15,7 @@ const slots = {
15
15
  label: "text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]",
16
16
  trigger: [
17
17
  "text-[var(--novi-color-fg)]",
18
- "flex items-center justify-between gap-2 w-full",
18
+ "flex items-center justify-between gap-[var(--novi-gap-inline)] w-full",
19
19
  "text-left",
20
20
  "bg-[var(--novi-color-surface)]",
21
21
  "shadow-[var(--novi-shadow-sm)]",
@@ -40,10 +40,10 @@ const slots = {
40
40
  "pl-[env(safe-area-inset-left,0px)] pr-[env(safe-area-inset-right,0px)]",
41
41
  "data-[entering]:motion-safe:animate-[novi-slide-up_260ms_var(--novi-ease-emphasized)]"
42
42
  ].join(" "),
43
- listbox: "outline-none p-2 flex flex-col",
43
+ listbox: "outline-none p-1.5 flex flex-col",
44
44
  option: [
45
- "flex items-center justify-between gap-3",
46
- "px-3 cursor-pointer outline-none",
45
+ "flex items-center justify-between gap-[var(--novi-gap-inline)]",
46
+ "px-[var(--novi-pad-control-x-md)] cursor-pointer outline-none",
47
47
  "text-[var(--novi-color-fg)]",
48
48
  "rounded-[var(--novi-radius-md)]",
49
49
  "transition-[background-color] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]",
@@ -71,15 +71,15 @@ const selectStyles = tv({
71
71
  variants: {
72
72
  size: {
73
73
  sm: {
74
- trigger: "h-10 px-3 text-[length:var(--novi-text-sm)]",
74
+ trigger: "h-10 px-[var(--novi-pad-control-x-sm)] text-[length:var(--novi-text-sm)]",
75
75
  option: "h-12 text-[length:var(--novi-text-sm)]"
76
76
  },
77
77
  md: {
78
- trigger: "h-12 px-4 text-[length:var(--novi-text-base)]",
78
+ trigger: "h-12 px-[var(--novi-pad-control-x-md)] text-[length:var(--novi-text-base)]",
79
79
  option: "h-14 text-[length:var(--novi-text-base)]"
80
80
  },
81
81
  lg: {
82
- trigger: "h-14 px-5 text-[length:var(--novi-text-base)]",
82
+ trigger: "h-14 px-[var(--novi-pad-control-x-lg)] text-[length:var(--novi-text-base)]",
83
83
  option: "h-16 text-[length:var(--novi-text-base)]"
84
84
  }
85
85
  },
@@ -1 +1 @@
1
- {"version":3,"file":"select.styles.mjs","names":[],"sources":["../../src/select/select.styles.ts"],"sourcesContent":["import type {\n NoviRadius,\n NoviSize,\n NoviVariant,\n SlotMap,\n selectRequiredSlots,\n selectSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Select は **画面下端から出るシート型ピッカー**(Raster はアンカー型ポップオーバー)。\n *\n * 一覧は誤タップが最も起きる場所なので、行を大きく取り、選択済みをチェックで示す。\n *\n * **`!` 付きのユーティリティは意図的**。RAC の `Popover` はトリガー基準の位置を\n * インラインスタイルで書き込むため、通常のクラスでも `style` prop でも勝てない。\n * スタイルシートの `!important` だけがインラインに勝つ(ADR-T2 / T-13 の実測)。\n */\nconst slots = {\n root: 'flex flex-col gap-1.5',\n label: 'text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]',\n trigger: [\n 'text-[var(--novi-color-fg)]',\n 'flex items-center justify-between gap-2 w-full',\n 'text-left',\n 'bg-[var(--novi-color-surface)]',\n 'shadow-[var(--novi-shadow-sm)]',\n 'rounded-[var(--novi-radius-md)]',\n 'transition-[opacity,scale] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[pressed]:scale-[0.99] motion-reduce:data-[pressed]:scale-100',\n 'group-data-[invalid]:ring-1 group-data-[invalid]:ring-[var(--novi-color-danger)]',\n focusRing,\n disabledState,\n ].join(' '),\n value: [\n 'truncate text-[var(--novi-color-fg)]',\n 'data-[placeholder]:text-[var(--novi-color-muted)]',\n ].join(' '),\n icon: 'shrink-0 text-[var(--novi-color-muted)]',\n popover: [\n // ここが Raster との構造差そのもの。トリガーの隣ではなく画面下端に張り付く\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 'text-[var(--novi-color-fg)]',\n // 下端は画面に接するので上端だけ角丸。下から出てきた紙の形\n 'rounded-t-[var(--novi-radius-lg)]',\n 'shadow-[var(--novi-shadow-lg)]',\n 'overflow-auto',\n 'pb-[env(safe-area-inset-bottom,0px)]',\n // 横向きのノッチは左右に来る。面は全幅のまま、中身だけを内側へ寄せる(FR-13)\n 'pl-[env(safe-area-inset-left,0px)] pr-[env(safe-area-inset-right,0px)]',\n 'data-[entering]:motion-safe:animate-[novi-slide-up_260ms_var(--novi-ease-emphasized)]',\n ].join(' '),\n listbox: 'outline-none p-2 flex flex-col',\n option: [\n 'flex items-center justify-between gap-3',\n 'px-3 cursor-pointer outline-none',\n 'text-[var(--novi-color-fg)]',\n 'rounded-[var(--novi-radius-md)]',\n 'transition-[background-color] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[focused]:bg-[var(--novi-color-subtle)]',\n 'data-[selected]:font-bold',\n disabledState,\n ].join(' '),\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n errorMessage: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]',\n} satisfies SlotMap<typeof selectSlots, (typeof selectRequiredSlots)[number]>\n\n/**\n * `size` はトリガーの寸法と**行の密度**(ADR-T3)。\n * 行はどの段でも 48px を下回らない — 一覧は誤タップが最も起きる場所。\n */\nconst size: VariantMap<NoviSize, { trigger: string; option: string }> = {\n sm: {\n trigger: 'h-10 px-3 text-[length:var(--novi-text-sm)]',\n option: 'h-12 text-[length:var(--novi-text-sm)]',\n },\n md: {\n trigger: 'h-12 px-4 text-[length:var(--novi-text-base)]',\n option: 'h-14 text-[length:var(--novi-text-base)]',\n },\n lg: {\n trigger: 'h-14 px-5 text-[length:var(--novi-text-base)]',\n option: 'h-16 text-[length:var(--novi-text-base)]',\n },\n}\n\nconst radius: VariantMap<NoviRadius, { trigger: string }> = {\n none: { trigger: 'rounded-[var(--novi-radius-none)]' },\n sm: { trigger: 'rounded-[var(--novi-radius-sm)]' },\n md: { trigger: 'rounded-[var(--novi-radius-md)]' },\n lg: { trigger: 'rounded-[var(--novi-radius-lg)]' },\n full: { trigger: 'rounded-[var(--novi-radius-full)]' },\n}\n\nconst variant: VariantMap<NoviVariant, { trigger: string }> = {\n solid: { trigger: 'bg-[var(--novi-color-surface)]' },\n outline: {\n trigger:\n 'bg-transparent shadow-[var(--novi-shadow-none)] ring-1 ring-[var(--novi-color-border-strong)]',\n },\n soft: { trigger: 'bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]' },\n ghost: { trigger: 'bg-transparent shadow-[var(--novi-shadow-none)]' },\n plain: {\n trigger: 'bg-transparent shadow-[var(--novi-shadow-none)] px-0 underline underline-offset-4',\n },\n}\n\n/**\n * Select のスタイル定義。\n *\n * `popover` の `!` 付きクラスを `classNames` で上書きすることはできない\n * (`!important` 同士では後勝ちにならない)。配置を変えたい場合は `tv({ extend })` を使う。\n *\n * @example\n * import { selectStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const mySelect = tv({ extend: selectStyles, slots: { option: 'font-mono' } })\n */\nexport const selectStyles = tv({\n slots,\n variants: { size, radius, variant },\n defaultVariants: { size: 'md', radius: 'md', variant: 'solid' },\n})\n\nexport type SelectStyleProps = Parameters<typeof selectStyles>[0]\n"],"mappings":";;;;;;;;;;;;AAqBA,MAAM,QAAQ;CACZ,MAAM;CACN,OAAO;CACP,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO,CACL,wCACA,mDACF,CAAC,CAAC,KAAK,GAAG;CACV,MAAM;CACN,SAAS;EAEP;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EAEA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,SAAS;CACT,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,aAAa;CACb,cAAc;AAChB;;;;;;;;;;;;;AAsDA,MAAa,eAAe,GAAG;CAC7B;CACA,UAAU;EAAE;GAjDZ,IAAI;IACF,SAAS;IACT,QAAQ;GACV;GACA,IAAI;IACF,SAAS;IACT,QAAQ;GACV;GACA,IAAI;IACF,SAAS;IACT,QAAQ;GACV;EAsCY;EAAM;GAlClB,MAAM,EAAE,SAAS,oCAAoC;GACrD,IAAI,EAAE,SAAS,kCAAkC;GACjD,IAAI,EAAE,SAAS,kCAAkC;GACjD,IAAI,EAAE,SAAS,kCAAkC;GACjD,MAAM,EAAE,SAAS,oCAAoC;EA8BnC;EAAQ;GA1B1B,OAAO,EAAE,SAAS,iCAAiC;GACnD,SAAS,EACP,SACE,gGACJ;GACA,MAAM,EAAE,SAAS,iEAAiE;GAClF,OAAO,EAAE,SAAS,kDAAkD;GACpE,OAAO,EACL,SAAS,oFACX;EAiB0B;CAAQ;CAClC,iBAAiB;EAAE,MAAM;EAAM,QAAQ;EAAM,SAAS;CAAQ;AAChE,CAAC"}
1
+ {"version":3,"file":"select.styles.mjs","names":[],"sources":["../../src/select/select.styles.ts"],"sourcesContent":["import type {\n NoviRadius,\n NoviSize,\n NoviVariant,\n SlotMap,\n selectRequiredSlots,\n selectSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Select は **画面下端から出るシート型ピッカー**(Raster はアンカー型ポップオーバー)。\n *\n * 一覧は誤タップが最も起きる場所なので、行を大きく取り、選択済みをチェックで示す。\n *\n * **`!` 付きのユーティリティは意図的**。RAC の `Popover` はトリガー基準の位置を\n * インラインスタイルで書き込むため、通常のクラスでも `style` prop でも勝てない。\n * スタイルシートの `!important` だけがインラインに勝つ(ADR-T2 / T-13 の実測)。\n */\nconst slots = {\n root: 'flex flex-col gap-1.5',\n label: 'text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]',\n trigger: [\n 'text-[var(--novi-color-fg)]',\n 'flex items-center justify-between gap-[var(--novi-gap-inline)] w-full',\n 'text-left',\n 'bg-[var(--novi-color-surface)]',\n 'shadow-[var(--novi-shadow-sm)]',\n 'rounded-[var(--novi-radius-md)]',\n 'transition-[opacity,scale] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[pressed]:scale-[0.99] motion-reduce:data-[pressed]:scale-100',\n 'group-data-[invalid]:ring-1 group-data-[invalid]:ring-[var(--novi-color-danger)]',\n focusRing,\n disabledState,\n ].join(' '),\n value: [\n 'truncate text-[var(--novi-color-fg)]',\n 'data-[placeholder]:text-[var(--novi-color-muted)]',\n ].join(' '),\n icon: 'shrink-0 text-[var(--novi-color-muted)]',\n popover: [\n // ここが Raster との構造差そのもの。トリガーの隣ではなく画面下端に張り付く\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 'text-[var(--novi-color-fg)]',\n // 下端は画面に接するので上端だけ角丸。下から出てきた紙の形\n 'rounded-t-[var(--novi-radius-lg)]',\n 'shadow-[var(--novi-shadow-lg)]',\n 'overflow-auto',\n 'pb-[env(safe-area-inset-bottom,0px)]',\n // 横向きのノッチは左右に来る。面は全幅のまま、中身だけを内側へ寄せる(FR-13)\n 'pl-[env(safe-area-inset-left,0px)] pr-[env(safe-area-inset-right,0px)]',\n 'data-[entering]:motion-safe:animate-[novi-slide-up_260ms_var(--novi-ease-emphasized)]',\n ].join(' '),\n // Menu と同じ溝。行の背景が丸く抜けて見えるための位置合わせで、余白の設計ではない\n listbox: 'outline-none p-1.5 flex flex-col',\n option: [\n 'flex items-center justify-between gap-[var(--novi-gap-inline)]',\n 'px-[var(--novi-pad-control-x-md)] cursor-pointer outline-none',\n 'text-[var(--novi-color-fg)]',\n 'rounded-[var(--novi-radius-md)]',\n 'transition-[background-color] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[focused]:bg-[var(--novi-color-subtle)]',\n 'data-[selected]:font-bold',\n disabledState,\n ].join(' '),\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n errorMessage: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]',\n} satisfies SlotMap<typeof selectSlots, (typeof selectRequiredSlots)[number]>\n\n/**\n * `size` はトリガーの寸法と**行の密度**(ADR-T3)。\n * 行はどの段でも 48px を下回らない — 一覧は誤タップが最も起きる場所。\n */\nconst size: VariantMap<NoviSize, { trigger: string; option: string }> = {\n sm: {\n trigger: 'h-10 px-[var(--novi-pad-control-x-sm)] text-[length:var(--novi-text-sm)]',\n option: 'h-12 text-[length:var(--novi-text-sm)]',\n },\n md: {\n trigger: 'h-12 px-[var(--novi-pad-control-x-md)] text-[length:var(--novi-text-base)]',\n option: 'h-14 text-[length:var(--novi-text-base)]',\n },\n lg: {\n trigger: 'h-14 px-[var(--novi-pad-control-x-lg)] text-[length:var(--novi-text-base)]',\n option: 'h-16 text-[length:var(--novi-text-base)]',\n },\n}\n\nconst radius: VariantMap<NoviRadius, { trigger: string }> = {\n none: { trigger: 'rounded-[var(--novi-radius-none)]' },\n sm: { trigger: 'rounded-[var(--novi-radius-sm)]' },\n md: { trigger: 'rounded-[var(--novi-radius-md)]' },\n lg: { trigger: 'rounded-[var(--novi-radius-lg)]' },\n full: { trigger: 'rounded-[var(--novi-radius-full)]' },\n}\n\nconst variant: VariantMap<NoviVariant, { trigger: string }> = {\n solid: { trigger: 'bg-[var(--novi-color-surface)]' },\n outline: {\n trigger:\n 'bg-transparent shadow-[var(--novi-shadow-none)] ring-1 ring-[var(--novi-color-border-strong)]',\n },\n soft: { trigger: 'bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]' },\n ghost: { trigger: 'bg-transparent shadow-[var(--novi-shadow-none)]' },\n plain: {\n trigger: 'bg-transparent shadow-[var(--novi-shadow-none)] px-0 underline underline-offset-4',\n },\n}\n\n/**\n * Select のスタイル定義。\n *\n * `popover` の `!` 付きクラスを `classNames` で上書きすることはできない\n * (`!important` 同士では後勝ちにならない)。配置を変えたい場合は `tv({ extend })` を使う。\n *\n * @example\n * import { selectStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const mySelect = tv({ extend: selectStyles, slots: { option: 'font-mono' } })\n */\nexport const selectStyles = tv({\n slots,\n variants: { size, radius, variant },\n defaultVariants: { size: 'md', radius: 'md', variant: 'solid' },\n})\n\nexport type SelectStyleProps = Parameters<typeof selectStyles>[0]\n"],"mappings":";;;;;;;;;;;;AAqBA,MAAM,QAAQ;CACZ,MAAM;CACN,OAAO;CACP,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO,CACL,wCACA,mDACF,CAAC,CAAC,KAAK,GAAG;CACV,MAAM;CACN,SAAS;EAEP;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EAEA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,SAAS;CACT,QAAQ;EACN;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,aAAa;CACb,cAAc;AAChB;;;;;;;;;;;;;AAsDA,MAAa,eAAe,GAAG;CAC7B;CACA,UAAU;EAAE;GAjDZ,IAAI;IACF,SAAS;IACT,QAAQ;GACV;GACA,IAAI;IACF,SAAS;IACT,QAAQ;GACV;GACA,IAAI;IACF,SAAS;IACT,QAAQ;GACV;EAsCY;EAAM;GAlClB,MAAM,EAAE,SAAS,oCAAoC;GACrD,IAAI,EAAE,SAAS,kCAAkC;GACjD,IAAI,EAAE,SAAS,kCAAkC;GACjD,IAAI,EAAE,SAAS,kCAAkC;GACjD,MAAM,EAAE,SAAS,oCAAoC;EA8BnC;EAAQ;GA1B1B,OAAO,EAAE,SAAS,iCAAiC;GACnD,SAAS,EACP,SACE,gGACJ;GACA,MAAM,EAAE,SAAS,iEAAiE;GAClF,OAAO,EAAE,SAAS,kDAAkD;GACpE,OAAO,EACL,SAAS,oFACX;EAiB0B;CAAQ;CAClC,iBAAiB;EAAE,MAAM;EAAM,QAAQ;EAAM,SAAS;CAAQ;AAChE,CAAC"}
@@ -7,7 +7,7 @@ import { tv } from "tailwind-variants";
7
7
  */
8
8
  const spinnerStyles = tv({
9
9
  slots: {
10
- root: "inline-flex items-center gap-2",
10
+ root: "inline-flex items-center gap-[var(--novi-gap-inline)]",
11
11
  circle: "shrink-0 motion-safe:animate-spin text-[var(--c)]",
12
12
  label: "text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]"
13
13
  },
@@ -1 +1 @@
1
- {"version":3,"file":"spinner.styles.mjs","names":[],"sources":["../../src/spinner/spinner.styles.ts"],"sourcesContent":["import type {\n NoviColor,\n NoviSize,\n SlotMap,\n spinnerRequiredSlots,\n spinnerSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\n\n/**\n * Spinner は `rotate` を使う**唯一の例外**(ADR-R2)。\n *\n * 代替のローディング表現(点滅・バーの往復)は視認性か情報量で劣るため、\n * ここだけ回転を許可している。デザイン規律の検査でも例外登録済み。\n * `prefers-reduced-motion` のときは回転を止める。\n */\nconst slots = {\n root: 'inline-flex items-center gap-2',\n circle: 'shrink-0 motion-safe:animate-spin text-[var(--c)]',\n label: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n} satisfies SlotMap<typeof spinnerSlots, (typeof spinnerRequiredSlots)[number]>\n\nconst color: VariantMap<NoviColor, { root: string }> = {\n default: { root: '[--c:var(--novi-color-fg)]' },\n primary: { root: '[--c:var(--novi-color-primary)]' },\n secondary: { root: '[--c:var(--novi-color-secondary)]' },\n success: { root: '[--c:var(--novi-color-success)]' },\n warning: { root: '[--c:var(--novi-color-warning)]' },\n danger: { root: '[--c:var(--novi-color-danger)]' },\n}\n\nconst size: VariantMap<NoviSize, { circle: string }> = {\n sm: { circle: 'size-5' },\n md: { circle: 'size-6' },\n lg: { circle: 'size-7' },\n}\n\n/**\n * Spinner のスタイル定義。\n *\n * @example\n * const mySpinner = tv({ extend: spinnerStyles, slots: { label: 'font-medium' } })\n */\nexport const spinnerStyles = tv({\n slots,\n variants: { color, size },\n defaultVariants: { color: 'default', size: 'md' },\n})\n\nexport type SpinnerStyleProps = Parameters<typeof spinnerStyles>[0]\n"],"mappings":";;;;;;;AA4CA,MAAa,gBAAgB,GAAG;CAC9B;EA3BA,MAAM;EACN,QAAQ;EACR,OAAO;CAyBP;CACA,UAAU;EAAE;GAtBZ,SAAS,EAAE,MAAM,6BAA6B;GAC9C,SAAS,EAAE,MAAM,kCAAkC;GACnD,WAAW,EAAE,MAAM,oCAAoC;GACvD,SAAS,EAAE,MAAM,kCAAkC;GACnD,SAAS,EAAE,MAAM,kCAAkC;GACnD,QAAQ,EAAE,MAAM,iCAAiC;EAiBrC;EAAO;GAbnB,IAAI,EAAE,QAAQ,SAAS;GACvB,IAAI,EAAE,QAAQ,SAAS;GACvB,IAAI,EAAE,QAAQ,SAAS;EAWJ;CAAK;CACxB,iBAAiB;EAAE,OAAO;EAAW,MAAM;CAAK;AAClD,CAAC"}
1
+ {"version":3,"file":"spinner.styles.mjs","names":[],"sources":["../../src/spinner/spinner.styles.ts"],"sourcesContent":["import type {\n NoviColor,\n NoviSize,\n SlotMap,\n spinnerRequiredSlots,\n spinnerSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\n\n/**\n * Spinner は `rotate` を使う**唯一の例外**(ADR-R2)。\n *\n * 代替のローディング表現(点滅・バーの往復)は視認性か情報量で劣るため、\n * ここだけ回転を許可している。デザイン規律の検査でも例外登録済み。\n * `prefers-reduced-motion` のときは回転を止める。\n */\nconst slots = {\n root: 'inline-flex items-center gap-[var(--novi-gap-inline)]',\n circle: 'shrink-0 motion-safe:animate-spin text-[var(--c)]',\n label: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n} satisfies SlotMap<typeof spinnerSlots, (typeof spinnerRequiredSlots)[number]>\n\nconst color: VariantMap<NoviColor, { root: string }> = {\n default: { root: '[--c:var(--novi-color-fg)]' },\n primary: { root: '[--c:var(--novi-color-primary)]' },\n secondary: { root: '[--c:var(--novi-color-secondary)]' },\n success: { root: '[--c:var(--novi-color-success)]' },\n warning: { root: '[--c:var(--novi-color-warning)]' },\n danger: { root: '[--c:var(--novi-color-danger)]' },\n}\n\nconst size: VariantMap<NoviSize, { circle: string }> = {\n sm: { circle: 'size-5' },\n md: { circle: 'size-6' },\n lg: { circle: 'size-7' },\n}\n\n/**\n * Spinner のスタイル定義。\n *\n * @example\n * const mySpinner = tv({ extend: spinnerStyles, slots: { label: 'font-medium' } })\n */\nexport const spinnerStyles = tv({\n slots,\n variants: { color, size },\n defaultVariants: { color: 'default', size: 'md' },\n})\n\nexport type SpinnerStyleProps = Parameters<typeof spinnerStyles>[0]\n"],"mappings":";;;;;;;AA4CA,MAAa,gBAAgB,GAAG;CAC9B;EA3BA,MAAM;EACN,QAAQ;EACR,OAAO;CAyBP;CACA,UAAU;EAAE;GAtBZ,SAAS,EAAE,MAAM,6BAA6B;GAC9C,SAAS,EAAE,MAAM,kCAAkC;GACnD,WAAW,EAAE,MAAM,oCAAoC;GACvD,SAAS,EAAE,MAAM,kCAAkC;GACnD,SAAS,EAAE,MAAM,kCAAkC;GACnD,QAAQ,EAAE,MAAM,iCAAiC;EAiBrC;EAAO;GAbnB,IAAI,EAAE,QAAQ,SAAS;GACvB,IAAI,EAAE,QAAQ,SAAS;GACvB,IAAI,EAAE,QAAQ,SAAS;EAWJ;CAAK;CACxB,iBAAiB;EAAE,OAAO;EAAW,MAAM;CAAK;AAClD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"switch.styles.d.mts","names":[],"sources":["../../src/switch/switch.styles.ts"],"mappings":";;;;;;;;cA8Ea,0CAAY;;IAlCkB;;;IAUD;IAAe;IAAe;;;;;;;;;;IAV7B;;;IAUD;IAAe;IAAe;;;;;;;;;;IAV7B;;;IAUD;IAAe;IAAe;;;;;;;;;KA8B5D,mBAAmB,kBAAkB"}
1
+ {"version":3,"file":"switch.styles.d.mts","names":[],"sources":["../../src/switch/switch.styles.ts"],"mappings":";;;;;;;;cAkFa,0CAAY;;IAlCkB;;;IAUD;IAAe;IAAe;;;;;;;;;;IAV7B;;;IAUD;IAAe;IAAe;;;;;;;;;;IAV7B;;;IAUD;IAAe;IAAe;;;;;;;;;KA8B5D,mBAAmB,kBAAkB"}
@@ -9,7 +9,7 @@ import { tv } from "tailwind-variants";
9
9
  */
10
10
  const slots = {
11
11
  root: [
12
- "inline-flex items-center gap-3 min-h-11",
12
+ "inline-flex items-center gap-[var(--novi-gap-inline)] min-h-11",
13
13
  "cursor-pointer",
14
14
  disabledState
15
15
  ].join(" "),
@@ -1 +1 @@
1
- {"version":3,"file":"switch.styles.mjs","names":[],"sources":["../../src/switch/switch.styles.ts"],"sourcesContent":["import type {\n NoviColor,\n NoviSize,\n SlotMap,\n switchRequiredSlots,\n switchSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Switch は **iOS 相当の 51×31px**。パーツ自体がタップ下限を満たす。\n *\n * 押下フィードバックは `scale` ではなく**サムの横伸長**で出す。\n * トグルは「掴んで動かす」ものなので、沈むより伸びる方が動作の予告になる。\n */\nconst slots = {\n // 行全体が押せる。トラック(31px)だけでは指のタップ下限を割るため、\n // ラベルを含む行に 44px の下限を持たせる(e2e の実測で判明)\n root: ['inline-flex items-center gap-3 min-h-11', 'cursor-pointer', disabledState].join(' '),\n track: [\n 'shrink-0 inline-flex items-center',\n 'rounded-[var(--novi-radius-full)]',\n 'bg-[var(--novi-color-subtle)]',\n 'ring-1 ring-[var(--novi-color-border)]',\n 'transition-[background-color,box-shadow]',\n 'duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'group-data-[selected]:bg-[var(--c)] group-data-[selected]:ring-[var(--c)]',\n focusRing,\n ].join(' '),\n // 押下でサムが横に伸びる。scale を使わないのは、掴んでいる感触は\n // 「縮む」より「引き伸ばされる」方が近いため(ADR-T5 の scale はボタン用)\n thumb: [\n 'rounded-[var(--novi-radius-full)]',\n 'bg-[var(--novi-color-surface)]',\n 'shadow-[var(--novi-shadow-sm)]',\n 'transition-[transform,width]',\n 'duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n ].join(' '),\n label: 'text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n} satisfies SlotMap<typeof switchSlots, (typeof switchRequiredSlots)[number]>\n\nconst color: VariantMap<NoviColor, { root: string }> = {\n default: { root: '[--c:var(--novi-color-fg)]' },\n primary: { root: '[--c:var(--novi-color-primary)]' },\n secondary: { root: '[--c:var(--novi-color-secondary)]' },\n success: { root: '[--c:var(--novi-color-success)]' },\n warning: { root: '[--c:var(--novi-color-warning)]' },\n danger: { root: '[--c:var(--novi-color-danger)]' },\n}\n\n/** md の 51×31px は iOS のスイッチ寸法。パーツ自体が 44px 相当のタップ域を持つ。 */\nconst size: VariantMap<NoviSize, { track: string; thumb: string; label: string }> = {\n sm: {\n track: 'h-7 w-12 p-0.5',\n thumb: 'size-6 group-data-[selected]:translate-x-5',\n label: 'text-[length:var(--novi-text-sm)]',\n },\n md: {\n track: 'h-[31px] w-[51px] p-0.5',\n thumb: 'size-[27px] group-data-[selected]:translate-x-5',\n label: 'text-[length:var(--novi-text-base)]',\n },\n lg: {\n track: 'h-9 w-[60px] p-0.5',\n thumb: 'size-8 group-data-[selected]:translate-x-6',\n label: 'text-[length:var(--novi-text-base)]',\n },\n}\n\n/**\n * Switch のスタイル定義。\n *\n * @example\n * const mySwitch = tv({ extend: switchStyles, slots: { track: 'w-12' } })\n */\nexport const switchStyles = tv({\n slots,\n variants: { color, size },\n defaultVariants: { color: 'default', size: 'md' },\n})\n\nexport type SwitchStyleProps = Parameters<typeof switchStyles>[0]\n"],"mappings":";;;;;;;;;AAiBA,MAAM,QAAQ;CAGZ,MAAM;EAAC;EAA2C;EAAkB;CAAa,CAAC,CAAC,KAAK,GAAG;CAC3F,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAGV,OAAO;EACL;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;CACP,aAAa;AACf;;;;;;;AAoCA,MAAa,eAAe,GAAG;CAC7B;CACA,UAAU;EAAE;GAnCZ,SAAS,EAAE,MAAM,6BAA6B;GAC9C,SAAS,EAAE,MAAM,kCAAkC;GACnD,WAAW,EAAE,MAAM,oCAAoC;GACvD,SAAS,EAAE,MAAM,kCAAkC;GACnD,SAAS,EAAE,MAAM,kCAAkC;GACnD,QAAQ,EAAE,MAAM,iCAAiC;EA8BrC;EAAO;GAzBnB,IAAI;IACF,OAAO;IACP,OAAO;IACP,OAAO;GACT;GACA,IAAI;IACF,OAAO;IACP,OAAO;IACP,OAAO;GACT;GACA,IAAI;IACF,OAAO;IACP,OAAO;IACP,OAAO;GACT;EAWmB;CAAK;CACxB,iBAAiB;EAAE,OAAO;EAAW,MAAM;CAAK;AAClD,CAAC"}
1
+ {"version":3,"file":"switch.styles.mjs","names":[],"sources":["../../src/switch/switch.styles.ts"],"sourcesContent":["import type {\n NoviColor,\n NoviSize,\n SlotMap,\n switchRequiredSlots,\n switchSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Switch は **iOS 相当の 51×31px**。パーツ自体がタップ下限を満たす。\n *\n * 押下フィードバックは `scale` ではなく**サムの横伸長**で出す。\n * トグルは「掴んで動かす」ものなので、沈むより伸びる方が動作の予告になる。\n */\nconst slots = {\n // 行全体が押せる。トラック(31px)だけでは指のタップ下限を割るため、\n // ラベルを含む行に 44px の下限を持たせる(e2e の実測で判明)\n root: [\n 'inline-flex items-center gap-[var(--novi-gap-inline)] min-h-11',\n 'cursor-pointer',\n disabledState,\n ].join(' '),\n track: [\n 'shrink-0 inline-flex items-center',\n 'rounded-[var(--novi-radius-full)]',\n 'bg-[var(--novi-color-subtle)]',\n 'ring-1 ring-[var(--novi-color-border)]',\n 'transition-[background-color,box-shadow]',\n 'duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'group-data-[selected]:bg-[var(--c)] group-data-[selected]:ring-[var(--c)]',\n focusRing,\n ].join(' '),\n // 押下でサムが横に伸びる。scale を使わないのは、掴んでいる感触は\n // 「縮む」より「引き伸ばされる」方が近いため(ADR-T5 の scale はボタン用)\n thumb: [\n 'rounded-[var(--novi-radius-full)]',\n 'bg-[var(--novi-color-surface)]',\n 'shadow-[var(--novi-shadow-sm)]',\n 'transition-[transform,width]',\n 'duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n ].join(' '),\n label: 'text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n} satisfies SlotMap<typeof switchSlots, (typeof switchRequiredSlots)[number]>\n\nconst color: VariantMap<NoviColor, { root: string }> = {\n default: { root: '[--c:var(--novi-color-fg)]' },\n primary: { root: '[--c:var(--novi-color-primary)]' },\n secondary: { root: '[--c:var(--novi-color-secondary)]' },\n success: { root: '[--c:var(--novi-color-success)]' },\n warning: { root: '[--c:var(--novi-color-warning)]' },\n danger: { root: '[--c:var(--novi-color-danger)]' },\n}\n\n/** md の 51×31px は iOS のスイッチ寸法。パーツ自体が 44px 相当のタップ域を持つ。 */\nconst size: VariantMap<NoviSize, { track: string; thumb: string; label: string }> = {\n sm: {\n track: 'h-7 w-12 p-0.5',\n thumb: 'size-6 group-data-[selected]:translate-x-5',\n label: 'text-[length:var(--novi-text-sm)]',\n },\n md: {\n track: 'h-[31px] w-[51px] p-0.5',\n thumb: 'size-[27px] group-data-[selected]:translate-x-5',\n label: 'text-[length:var(--novi-text-base)]',\n },\n lg: {\n track: 'h-9 w-[60px] p-0.5',\n thumb: 'size-8 group-data-[selected]:translate-x-6',\n label: 'text-[length:var(--novi-text-base)]',\n },\n}\n\n/**\n * Switch のスタイル定義。\n *\n * @example\n * const mySwitch = tv({ extend: switchStyles, slots: { track: 'w-12' } })\n */\nexport const switchStyles = tv({\n slots,\n variants: { color, size },\n defaultVariants: { color: 'default', size: 'md' },\n})\n\nexport type SwitchStyleProps = Parameters<typeof switchStyles>[0]\n"],"mappings":";;;;;;;;;AAiBA,MAAM,QAAQ;CAGZ,MAAM;EACJ;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAGV,OAAO;EACL;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;CACP,aAAa;AACf;;;;;;;AAoCA,MAAa,eAAe,GAAG;CAC7B;CACA,UAAU;EAAE;GAnCZ,SAAS,EAAE,MAAM,6BAA6B;GAC9C,SAAS,EAAE,MAAM,kCAAkC;GACnD,WAAW,EAAE,MAAM,oCAAoC;GACvD,SAAS,EAAE,MAAM,kCAAkC;GACnD,SAAS,EAAE,MAAM,kCAAkC;GACnD,QAAQ,EAAE,MAAM,iCAAiC;EA8BrC;EAAO;GAzBnB,IAAI;IACF,OAAO;IACP,OAAO;IACP,OAAO;GACT;GACA,IAAI;IACF,OAAO;IACP,OAAO;IACP,OAAO;GACT;GACA,IAAI;IACF,OAAO;IACP,OAAO;IACP,OAAO;GACT;EAWmB;CAAK;CACxB,iBAAiB;EAAE,OAAO;EAAW,MAAM;CAAK;AAClD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.styles.d.mts","names":[],"sources":["../../src/tabs/tabs.styles.ts"],"mappings":";;;;;;;;;;;cAuFa,wCAAU;;IAfiB;;;IAlBO;IAAmB;;;;;;;;;;IAkB1B;;;IAlBO;IAAmB;;;;;;;;;;IAkB1B;;;IAlBO;IAAmB;;;;;;;;;KAuCtD,iBAAiB,kBAAkB"}
1
+ {"version":3,"file":"tabs.styles.d.mts","names":[],"sources":["../../src/tabs/tabs.styles.ts"],"mappings":";;;;;;;;;;;cAyFa,wCAAU;;IAfiB;;;IAnBO;IAAmB;;;;;;;;;;IAmB1B;;;IAnBO;IAAmB;;;;;;;;;;IAmB1B;;;IAnBO;IAAmB;;;;;;;;;KAwCtD,iBAAiB,kBAAkB"}
@@ -13,7 +13,7 @@ import { tv } from "tailwind-variants";
13
13
  * 下線1本は視線には十分でも、指には「どこまでが自分の区画か」を伝えない。
14
14
  */
15
15
  const slots = {
16
- root: "flex flex-col gap-4",
16
+ root: "flex flex-col gap-[var(--novi-gap-stack)]",
17
17
  list: [
18
18
  "flex gap-1 w-fit",
19
19
  "bg-[var(--novi-color-subtle)]",
@@ -39,7 +39,7 @@ const slots = {
39
39
  "rounded-[var(--novi-radius-sm)]",
40
40
  "shadow-[var(--novi-shadow-sm)]"
41
41
  ].join(" "),
42
- panel: "outline-none text-[var(--novi-color-fg)]"
42
+ panel: "outline-none text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]"
43
43
  };
44
44
  /**
45
45
  * Tabs のスタイル定義。
@@ -54,9 +54,9 @@ const tabsStyles = tv({
54
54
  slots,
55
55
  variants: {
56
56
  size: {
57
- sm: { tab: "h-10 px-4 text-[length:var(--novi-text-sm)]" },
58
- md: { tab: "h-12 px-5 text-[length:var(--novi-text-base)]" },
59
- lg: { tab: "h-14 px-6 text-[length:var(--novi-text-base)]" }
57
+ sm: { tab: "h-10 px-[var(--novi-pad-control-x-sm)] text-[length:var(--novi-text-sm)]" },
58
+ md: { tab: "h-12 px-[var(--novi-pad-control-x-md)] text-[length:var(--novi-text-base)]" },
59
+ lg: { tab: "h-14 px-[var(--novi-pad-control-x-lg)] text-[length:var(--novi-text-base)]" }
60
60
  },
61
61
  variant: {
62
62
  solid: {
@@ -72,11 +72,11 @@ const tabsStyles = tv({
72
72
  indicator: "shadow-[var(--novi-shadow-none)]"
73
73
  },
74
74
  ghost: {
75
- list: "bg-transparent p-0 gap-2",
75
+ list: "bg-transparent p-0 gap-[var(--novi-gap-inline)]",
76
76
  indicator: "bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]"
77
77
  },
78
78
  plain: {
79
- list: "bg-transparent p-0 gap-4",
79
+ list: "bg-transparent p-0 gap-[var(--novi-gap-stack)]",
80
80
  indicator: "bg-transparent shadow-[var(--novi-shadow-none)]"
81
81
  }
82
82
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.styles.mjs","names":[],"sources":["../../src/tabs/tabs.styles.ts"],"sourcesContent":["import type {\n NoviSize,\n NoviVariant,\n SlotMap,\n tabsRequiredSlots,\n tabsSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Tabs は**セグメンテッドコントロール**(Raster は下線1本)。\n *\n * 構造差の要点:\n * - `list` が**塗られたトラック**になる(Raster は下辺の罫線だけ)\n * - `indicator` が**実体を持つ塗り面**として選択中のタブに重なる(Raster は描画しない)\n * - タブは「線の上の文字」ではなく「トラックに沈んだ区画」になる\n *\n * 指で切り替える前提なので、どこが押せる範囲かが面で分かる必要がある。\n * 下線1本は視線には十分でも、指には「どこまでが自分の区画か」を伝えない。\n */\nconst slots = {\n root: 'flex flex-col gap-4',\n list: [\n 'flex gap-1 w-fit',\n 'bg-[var(--novi-color-subtle)]',\n 'rounded-[var(--novi-radius-md)]',\n 'p-1',\n ].join(' '),\n tab: [\n // indicator を内側に置くため、位置の基準を作る\n 'relative isolate cursor-pointer outline-none whitespace-nowrap',\n 'flex items-center justify-center',\n 'text-[var(--novi-color-muted)]',\n 'rounded-[var(--novi-radius-sm)]',\n 'transition-[color,scale] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[pressed]:scale-[0.97] motion-reduce:data-[pressed]:scale-100',\n 'hover:text-[var(--novi-color-fg)]',\n 'data-[selected]:text-[var(--novi-color-fg)]',\n 'data-[selected]:font-bold',\n 'data-[disabled]:opacity-40 data-[disabled]:cursor-default',\n focusRing,\n ].join(' '),\n // 選択中のタブの内側に敷かれる面。トラックから1段持ち上がって見える\n indicator: [\n 'absolute inset-0 -z-10',\n 'bg-[var(--novi-color-surface)]',\n 'rounded-[var(--novi-radius-sm)]',\n 'shadow-[var(--novi-shadow-sm)]',\n ].join(' '),\n panel: 'outline-none text-[var(--novi-color-fg)]',\n} satisfies SlotMap<typeof tabsSlots, (typeof tabsRequiredSlots)[number]>\n\nconst variant: VariantMap<NoviVariant, { list: string; indicator: string }> = {\n solid: { list: 'bg-[var(--novi-color-subtle)]', indicator: '' },\n outline: {\n list: 'bg-transparent ring-1 ring-[var(--novi-color-border)]',\n indicator: 'shadow-[var(--novi-shadow-none)] ring-1 ring-[var(--novi-color-border-strong)]',\n },\n soft: { list: 'bg-[var(--novi-color-subtle)]', indicator: 'shadow-[var(--novi-shadow-none)]' },\n ghost: {\n list: 'bg-transparent p-0 gap-2',\n indicator: 'bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]',\n },\n plain: {\n list: 'bg-transparent p-0 gap-4',\n indicator: 'bg-transparent shadow-[var(--novi-shadow-none)]',\n },\n}\n\n/** どの段でもタップ下限を割らない。トラックの内側なので上下の余白も確保する。 */\nconst size: VariantMap<NoviSize, { tab: string }> = {\n sm: { tab: 'h-10 px-4 text-[length:var(--novi-text-sm)]' },\n md: { tab: 'h-12 px-5 text-[length:var(--novi-text-base)]' },\n lg: { tab: 'h-14 px-6 text-[length:var(--novi-text-base)]' },\n}\n\n/**\n * Tabs のスタイル定義。\n *\n * @example\n * import { tabsStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const myTabs = tv({ extend: tabsStyles, slots: { list: 'w-full' } })\n */\nexport const tabsStyles = tv({\n slots,\n variants: { size, variant },\n defaultVariants: { size: 'md', variant: 'solid' },\n})\n\nexport type TabsStyleProps = Parameters<typeof tabsStyles>[0]\n"],"mappings":";;;;;;;;;;;;;;AAsBA,MAAM,QAAQ;CACZ,MAAM;CACN,MAAM;EACJ;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,KAAK;EAEH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,WAAW;EACT;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;AACT;;;;;;;;;;AAmCA,MAAa,aAAa,GAAG;CAC3B;CACA,UAAU;EAAE;GAhBZ,IAAI,EAAE,KAAK,8CAA8C;GACzD,IAAI,EAAE,KAAK,gDAAgD;GAC3D,IAAI,EAAE,KAAK,gDAAgD;EAc/C;EAAM;GAlClB,OAAO;IAAE,MAAM;IAAiC,WAAW;GAAG;GAC9D,SAAS;IACP,MAAM;IACN,WAAW;GACb;GACA,MAAM;IAAE,MAAM;IAAiC,WAAW;GAAmC;GAC7F,OAAO;IACL,MAAM;IACN,WAAW;GACb;GACA,OAAO;IACL,MAAM;IACN,WAAW;GACb;EAqBkB;CAAQ;CAC1B,iBAAiB;EAAE,MAAM;EAAM,SAAS;CAAQ;AAClD,CAAC"}
1
+ {"version":3,"file":"tabs.styles.mjs","names":[],"sources":["../../src/tabs/tabs.styles.ts"],"sourcesContent":["import type {\n NoviSize,\n NoviVariant,\n SlotMap,\n tabsRequiredSlots,\n tabsSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { focusRing } from '../styles/focus-ring'\n\n/**\n * Tactile の Tabs は**セグメンテッドコントロール**(Raster は下線1本)。\n *\n * 構造差の要点:\n * - `list` が**塗られたトラック**になる(Raster は下辺の罫線だけ)\n * - `indicator` が**実体を持つ塗り面**として選択中のタブに重なる(Raster は描画しない)\n * - タブは「線の上の文字」ではなく「トラックに沈んだ区画」になる\n *\n * 指で切り替える前提なので、どこが押せる範囲かが面で分かる必要がある。\n * 下線1本は視線には十分でも、指には「どこまでが自分の区画か」を伝えない。\n */\nconst slots = {\n // トラックとパネルは別の区画。ここを詰めると、どのタブの中身なのかが読めなくなる\n root: 'flex flex-col gap-[var(--novi-gap-stack)]',\n list: [\n 'flex gap-1 w-fit',\n 'bg-[var(--novi-color-subtle)]',\n 'rounded-[var(--novi-radius-md)]',\n 'p-1',\n ].join(' '),\n tab: [\n // indicator を内側に置くため、位置の基準を作る\n 'relative isolate cursor-pointer outline-none whitespace-nowrap',\n 'flex items-center justify-center',\n 'text-[var(--novi-color-muted)]',\n 'rounded-[var(--novi-radius-sm)]',\n 'transition-[color,scale] duration-[var(--novi-duration-fast)] ease-[var(--novi-ease-standard)]',\n 'data-[pressed]:scale-[0.97] motion-reduce:data-[pressed]:scale-100',\n 'hover:text-[var(--novi-color-fg)]',\n 'data-[selected]:text-[var(--novi-color-fg)]',\n 'data-[selected]:font-bold',\n 'data-[disabled]:opacity-40 data-[disabled]:cursor-default',\n focusRing,\n ].join(' '),\n // 選択中のタブの内側に敷かれる面。トラックから1段持ち上がって見える\n indicator: [\n 'absolute inset-0 -z-10',\n 'bg-[var(--novi-color-surface)]',\n 'rounded-[var(--novi-radius-sm)]',\n 'shadow-[var(--novi-shadow-sm)]',\n ].join(' '),\n panel: 'outline-none text-[var(--novi-color-fg)] leading-[var(--novi-leading-body)]',\n} satisfies SlotMap<typeof tabsSlots, (typeof tabsRequiredSlots)[number]>\n\nconst variant: VariantMap<NoviVariant, { list: string; indicator: string }> = {\n solid: { list: 'bg-[var(--novi-color-subtle)]', indicator: '' },\n outline: {\n list: 'bg-transparent ring-1 ring-[var(--novi-color-border)]',\n indicator: 'shadow-[var(--novi-shadow-none)] ring-1 ring-[var(--novi-color-border-strong)]',\n },\n soft: { list: 'bg-[var(--novi-color-subtle)]', indicator: 'shadow-[var(--novi-shadow-none)]' },\n ghost: {\n list: 'bg-transparent p-0 gap-[var(--novi-gap-inline)]',\n indicator: 'bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]',\n },\n plain: {\n // トラックが無いぶん、区画の境目は距離だけで示す\n list: 'bg-transparent p-0 gap-[var(--novi-gap-stack)]',\n indicator: 'bg-transparent shadow-[var(--novi-shadow-none)]',\n },\n}\n\n/** どの段でもタップ下限を割らない。トラックの内側なので上下の余白も確保する。 */\nconst size: VariantMap<NoviSize, { tab: string }> = {\n sm: { tab: 'h-10 px-[var(--novi-pad-control-x-sm)] text-[length:var(--novi-text-sm)]' },\n md: { tab: 'h-12 px-[var(--novi-pad-control-x-md)] text-[length:var(--novi-text-base)]' },\n lg: { tab: 'h-14 px-[var(--novi-pad-control-x-lg)] text-[length:var(--novi-text-base)]' },\n}\n\n/**\n * Tabs のスタイル定義。\n *\n * @example\n * import { tabsStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const myTabs = tv({ extend: tabsStyles, slots: { list: 'w-full' } })\n */\nexport const tabsStyles = tv({\n slots,\n variants: { size, variant },\n defaultVariants: { size: 'md', variant: 'solid' },\n})\n\nexport type TabsStyleProps = Parameters<typeof tabsStyles>[0]\n"],"mappings":";;;;;;;;;;;;;;AAsBA,MAAM,QAAQ;CAEZ,MAAM;CACN,MAAM;EACJ;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,KAAK;EAEH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,WAAW;EACT;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,OAAO;AACT;;;;;;;;;;AAoCA,MAAa,aAAa,GAAG;CAC3B;CACA,UAAU;EAAE;GAhBZ,IAAI,EAAE,KAAK,2EAA2E;GACtF,IAAI,EAAE,KAAK,6EAA6E;GACxF,IAAI,EAAE,KAAK,6EAA6E;EAc5E;EAAM;GAnClB,OAAO;IAAE,MAAM;IAAiC,WAAW;GAAG;GAC9D,SAAS;IACP,MAAM;IACN,WAAW;GACb;GACA,MAAM;IAAE,MAAM;IAAiC,WAAW;GAAmC;GAC7F,OAAO;IACL,MAAM;IACN,WAAW;GACb;GACA,OAAO;IAEL,MAAM;IACN,WAAW;GACb;EAqBkB;CAAQ;CAC1B,iBAAiB;EAAE,MAAM;EAAM,SAAS;CAAQ;AAClD,CAAC"}
package/dist/tactile.css CHANGED
@@ -28,6 +28,22 @@
28
28
  --novi-text-xl: 26px;
29
29
  --novi-text-2xl: 32px;
30
30
  --novi-text-3xl: 40px;
31
+ --novi-pad-surface-x: 28px;
32
+ --novi-pad-surface-y: 24px;
33
+ --novi-pad-control-x-sm: 16px;
34
+ --novi-pad-control-x-md: 20px;
35
+ --novi-pad-control-x-lg: 24px;
36
+ --novi-gap-inline: 10px;
37
+ --novi-gap-stack: 20px;
38
+ --novi-gap-section: 32px;
39
+ --novi-tracking-tight: -0.006em;
40
+ --novi-tracking-normal: 0.006em;
41
+ --novi-leading-body: 1.75;
42
+ --novi-leading-heading: 1.3;
43
+ --novi-font-sans: system-ui, sans-serif;
44
+ --novi-font-mono: ui-monospace, monospace;
45
+ --novi-font-heading: var(--novi-font-sans);
46
+ --novi-font-numeric: normal;
31
47
  --novi-duration-fast: 120ms;
32
48
  --novi-duration-base: 200ms;
33
49
  --novi-duration-slow: 260ms;
@@ -28,6 +28,22 @@
28
28
  --novi-text-xl: 26px;
29
29
  --novi-text-2xl: 32px;
30
30
  --novi-text-3xl: 40px;
31
+ --novi-pad-surface-x: 28px;
32
+ --novi-pad-surface-y: 24px;
33
+ --novi-pad-control-x-sm: 16px;
34
+ --novi-pad-control-x-md: 20px;
35
+ --novi-pad-control-x-lg: 24px;
36
+ --novi-gap-inline: 10px;
37
+ --novi-gap-stack: 20px;
38
+ --novi-gap-section: 32px;
39
+ --novi-tracking-tight: -0.006em;
40
+ --novi-tracking-normal: 0.006em;
41
+ --novi-leading-body: 1.75;
42
+ --novi-leading-heading: 1.3;
43
+ --novi-font-sans: system-ui, sans-serif;
44
+ --novi-font-mono: ui-monospace, monospace;
45
+ --novi-font-heading: var(--novi-font-sans);
46
+ --novi-font-numeric: normal;
31
47
  --novi-duration-fast: 120ms;
32
48
  --novi-duration-base: 200ms;
33
49
  --novi-duration-slow: 260ms;
@@ -1 +1 @@
1
- {"version":3,"file":"textarea.styles.d.mts","names":[],"sources":["../../src/textarea/textarea.styles.ts"],"mappings":";;;;;;;;;;;;;;cAsFa,4CAAc;;IA3C4B;;;IAgBN;IAAkB;;;IAOd;;;;;;;;;;;IAvBE;;;IAgBN;IAAkB;;;IAOd;;;;;;;;;;;IAvBE;;;IAgBN;IAAkB;;;IAOd;;;;;;;;;;KA0BzC,qBAAqB,kBAAkB"}
1
+ {"version":3,"file":"textarea.styles.d.mts","names":[],"sources":["../../src/textarea/textarea.styles.ts"],"mappings":";;;;;;;;;;;;;;cAoGa,4CAAc;;IAzD4B;;;IAqBN;IAAkB;;;IAgBd;;;;;;;;;;;IArCE;;;IAqBN;IAAkB;;;IAgBd;;;;;;;;;;;IArCE;;;IAqBN;IAAkB;;;IAgBd;;;;;;;;;;KA0BzC,qBAAqB,kBAAkB"}
@@ -51,15 +51,15 @@ const textareaStyles = tv({
51
51
  },
52
52
  size: {
53
53
  sm: {
54
- inputWrapper: "px-3 py-2",
54
+ inputWrapper: "px-[var(--novi-pad-control-x-sm)] py-[var(--novi-pad-surface-y)]",
55
55
  textarea: "text-[length:var(--novi-text-base)]"
56
56
  },
57
57
  md: {
58
- inputWrapper: "px-4 py-3",
58
+ inputWrapper: "px-[var(--novi-pad-control-x-md)] py-[var(--novi-pad-surface-y)]",
59
59
  textarea: "text-[length:var(--novi-text-base)]"
60
60
  },
61
61
  lg: {
62
- inputWrapper: "px-5 py-4",
62
+ inputWrapper: "px-[var(--novi-pad-control-x-lg)] py-[var(--novi-pad-surface-y)]",
63
63
  textarea: "text-[length:var(--novi-text-base)]"
64
64
  }
65
65
  },
@@ -1 +1 @@
1
- {"version":3,"file":"textarea.styles.mjs","names":[],"sources":["../../src/textarea/textarea.styles.ts"],"sourcesContent":["import type {\n NoviRadius,\n NoviSize,\n NoviVariant,\n SlotMap,\n textareaRequiredSlots,\n textareaSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\n\nconst slots = {\n root: 'flex flex-col gap-1.5',\n label: 'text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]',\n inputWrapper: [\n 'text-[var(--novi-color-fg)]',\n 'flex 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 textarea: [\n 'w-full min-w-0 bg-transparent outline-none',\n 'text-[var(--novi-color-fg)]',\n 'placeholder:text-[var(--novi-color-muted)]',\n // 横に伸ばすとレイアウトが崩れるので縦のみ許可する\n 'resize-y',\n // 指で書く前提なので最低でも3行ぶんの高さを確保する\n 'min-h-24',\n 'leading-[var(--novi-leading-body)]',\n ].join(' '),\n // 文字数カウンタもここに置く。専用 slot を増やさない\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n errorMessage: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]',\n} satisfies SlotMap<typeof textareaSlots, (typeof textareaRequiredSlots)[number]>\n\n/** Input と同じ解釈。面の重さで5段を作る(境界線ではなく影と背景で区別する)。 */\nconst variant: VariantMap<NoviVariant, { inputWrapper: string }> = {\n solid: { inputWrapper: 'bg-[var(--novi-color-surface)] shadow-[var(--novi-shadow-sm)]' },\n outline: {\n inputWrapper:\n 'bg-transparent shadow-[var(--novi-shadow-none)] ring-1 ring-[var(--novi-color-border-strong)]',\n },\n soft: { inputWrapper: 'bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]' },\n ghost: { inputWrapper: 'bg-transparent shadow-[var(--novi-shadow-none)]' },\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/** 1行入力と違い高さは固定しない。余白と文字サイズだけを段階で変える。 */\nconst size: VariantMap<NoviSize, { inputWrapper: string; textarea: string }> = {\n // 入力の文字は全段 base(17px)。16px を割ると iOS Safari が自動ズームする\n sm: { inputWrapper: 'px-3 py-2', textarea: 'text-[length:var(--novi-text-base)]' },\n md: { inputWrapper: 'px-4 py-3', textarea: 'text-[length:var(--novi-text-base)]' },\n lg: { inputWrapper: 'px-5 py-4', textarea: '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 * TextArea のスタイル定義。\n *\n * @example\n * import { textareaStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const myTextarea = tv({\n * extend: textareaStyles,\n * slots: { textarea: 'font-mono' },\n * })\n */\nexport const textareaStyles = tv({\n slots,\n variants: { variant, size, radius },\n defaultVariants: { variant: 'outline', size: 'md', radius: 'md' },\n})\n\nexport type TextareaStyleProps = Parameters<typeof textareaStyles>[0]\n"],"mappings":";;;AAYA,MAAM,QAAQ;CACZ,MAAM;CACN,OAAO;CACP,cAAc;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,UAAU;EACR;EACA;EACA;EAEA;EAEA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,aAAa;CACb,cAAc;AAChB;;;;;;;;;;;;;AA8CA,MAAa,iBAAiB,GAAG;CAC/B;CACA,UAAU;EAAE;GA5CZ,OAAO,EAAE,cAAc,gEAAgE;GACvF,SAAS,EACP,cACE,gGACJ;GACA,MAAM,EAAE,cAAc,iEAAiE;GACvF,OAAO,EAAE,cAAc,kDAAkD;GAEzE,OAAO,EACL,cACE,sIACJ;EAiCY;EAAS;GA3BrB,IAAI;IAAE,cAAc;IAAa,UAAU;GAAsC;GACjF,IAAI;IAAE,cAAc;IAAa,UAAU;GAAsC;GACjF,IAAI;IAAE,cAAc;IAAa,UAAU;GAAsC;EAyB5D;EAAM;GArB3B,MAAM,EAAE,cAAc,oCAAoC;GAC1D,IAAI,EAAE,cAAc,kCAAkC;GACtD,IAAI,EAAE,cAAc,kCAAkC;GACtD,IAAI,EAAE,cAAc,kCAAkC;GACtD,MAAM,EAAE,cAAc,oCAAoC;EAiB/B;CAAO;CAClC,iBAAiB;EAAE,SAAS;EAAW,MAAM;EAAM,QAAQ;CAAK;AAClE,CAAC"}
1
+ {"version":3,"file":"textarea.styles.mjs","names":[],"sources":["../../src/textarea/textarea.styles.ts"],"sourcesContent":["import type {\n NoviRadius,\n NoviSize,\n NoviVariant,\n SlotMap,\n textareaRequiredSlots,\n textareaSlots,\n VariantMap,\n} from '@novi-ui/core'\nimport { tv } from 'tailwind-variants'\nimport { disabledState, focusRing } from '../styles/focus-ring'\n\nconst slots = {\n root: 'flex flex-col gap-1.5',\n label: 'text-[length:var(--novi-text-sm)] font-medium text-[var(--novi-color-fg)]',\n inputWrapper: [\n 'text-[var(--novi-color-fg)]',\n 'flex 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 textarea: [\n 'w-full min-w-0 bg-transparent outline-none',\n 'text-[var(--novi-color-fg)]',\n 'placeholder:text-[var(--novi-color-muted)]',\n // 横に伸ばすとレイアウトが崩れるので縦のみ許可する\n 'resize-y',\n // 指で書く前提なので最低でも3行ぶんの高さを確保する\n 'min-h-24',\n 'leading-[var(--novi-leading-body)]',\n ].join(' '),\n // 文字数カウンタもここに置く。専用 slot を増やさない\n description: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-muted)]',\n errorMessage: 'text-[length:var(--novi-text-sm)] text-[var(--novi-color-danger)]',\n} satisfies SlotMap<typeof textareaSlots, (typeof textareaRequiredSlots)[number]>\n\n/** Input と同じ解釈。面の重さで5段を作る(境界線ではなく影と背景で区別する)。 */\nconst variant: VariantMap<NoviVariant, { inputWrapper: string }> = {\n solid: { inputWrapper: 'bg-[var(--novi-color-surface)] shadow-[var(--novi-shadow-sm)]' },\n outline: {\n inputWrapper:\n 'bg-transparent shadow-[var(--novi-shadow-none)] ring-1 ring-[var(--novi-color-border-strong)]',\n },\n soft: { inputWrapper: 'bg-[var(--novi-color-subtle)] shadow-[var(--novi-shadow-none)]' },\n ghost: { inputWrapper: 'bg-transparent shadow-[var(--novi-shadow-none)]' },\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 * 1行入力と違い高さは固定しない。**段が変えるのは左右の余白だけ。**\n *\n * 上下は書く面の余白(surface-y)で一定にする。複数行を書く面で上下だけ詰めると、\n * カーソルが枠の縁に寄って、指を置いたときに親指で最終行が隠れる。\n */\nconst size: VariantMap<NoviSize, { inputWrapper: string; textarea: string }> = {\n // 入力の文字は全段 base(17px)。16px を割ると iOS Safari が自動ズームする\n sm: {\n inputWrapper: 'px-[var(--novi-pad-control-x-sm)] py-[var(--novi-pad-surface-y)]',\n textarea: 'text-[length:var(--novi-text-base)]',\n },\n md: {\n inputWrapper: 'px-[var(--novi-pad-control-x-md)] py-[var(--novi-pad-surface-y)]',\n textarea: 'text-[length:var(--novi-text-base)]',\n },\n lg: {\n inputWrapper: 'px-[var(--novi-pad-control-x-lg)] py-[var(--novi-pad-surface-y)]',\n textarea: 'text-[length:var(--novi-text-base)]',\n },\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 * TextArea のスタイル定義。\n *\n * @example\n * import { textareaStyles } from '@novi-ui/tactile'\n * import { tv } from 'tailwind-variants'\n *\n * const myTextarea = tv({\n * extend: textareaStyles,\n * slots: { textarea: 'font-mono' },\n * })\n */\nexport const textareaStyles = tv({\n slots,\n variants: { variant, size, radius },\n defaultVariants: { variant: 'outline', size: 'md', radius: 'md' },\n})\n\nexport type TextareaStyleProps = Parameters<typeof textareaStyles>[0]\n"],"mappings":";;;AAYA,MAAM,QAAQ;CACZ,MAAM;CACN,OAAO;CACP,cAAc;EACZ;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CACV,UAAU;EACR;EACA;EACA;EAEA;EAEA;EACA;CACF,CAAC,CAAC,KAAK,GAAG;CAEV,aAAa;CACb,cAAc;AAChB;;;;;;;;;;;;;AA4DA,MAAa,iBAAiB,GAAG;CAC/B;CACA,UAAU;EAAE;GA1DZ,OAAO,EAAE,cAAc,gEAAgE;GACvF,SAAS,EACP,cACE,gGACJ;GACA,MAAM,EAAE,cAAc,iEAAiE;GACvF,OAAO,EAAE,cAAc,kDAAkD;GAEzE,OAAO,EACL,cACE,sIACJ;EA+CY;EAAS;GApCrB,IAAI;IACF,cAAc;IACd,UAAU;GACZ;GACA,IAAI;IACF,cAAc;IACd,UAAU;GACZ;GACA,IAAI;IACF,cAAc;IACd,UAAU;GACZ;EAyBqB;EAAM;GArB3B,MAAM,EAAE,cAAc,oCAAoC;GAC1D,IAAI,EAAE,cAAc,kCAAkC;GACtD,IAAI,EAAE,cAAc,kCAAkC;GACtD,IAAI,EAAE,cAAc,kCAAkC;GACtD,MAAM,EAAE,cAAc,oCAAoC;EAiB/B;CAAO;CAClC,iBAAiB;EAAE,SAAS;EAAW,MAAM;EAAM,QAAQ;CAAK;AAClE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"toast.styles.d.mts","names":[],"sources":["../../src/toast/toast.styles.ts"],"mappings":";;;;;;;;cAmEa,yCAAW;;IAvBmB;;;IASE;;;;;;;;;;;;;IATF;;;IASE;;;;;;;;;;;;;IATF;;;IASE;;;;;;;;;;;;KAoBjC,kBAAkB,kBAAkB"}
1
+ {"version":3,"file":"toast.styles.d.mts","names":[],"sources":["../../src/toast/toast.styles.ts"],"mappings":";;;;;;;;cAuEa,yCAAW;;IAvBmB;;;IASE;;;;;;;;;;;;;IATF;;;IASE;;;;;;;;;;;;;IATF;;;IASE;;;;;;;;;;;;KAoBjC,kBAAkB,kBAAkB"}