@cakejp/design-system 0.20.0 → 0.21.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 (161) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/CLAUDE.md +5 -3
  3. package/MIGRATION.md +3 -3
  4. package/README.md +31 -11
  5. package/contracts/components.json +424 -62
  6. package/contracts/composition.json +38 -4
  7. package/contracts/rules.json +27 -5
  8. package/contracts/screen-patterns.json +6 -4
  9. package/dist/components/ec/admin-shell.js +62 -60
  10. package/dist/components/ec/anniversary-card.js +13 -12
  11. package/dist/components/ec/coupon-card.js +11 -11
  12. package/dist/components/ec/delivery-calendar.js +51 -45
  13. package/dist/components/ec/mypage-shell.js +80 -69
  14. package/dist/components/ec/product-card.js +93 -76
  15. package/dist/components/ec/product-carousel.js +65 -60
  16. package/dist/components/ec/product-detail-bar.js +13 -11
  17. package/dist/components/ec/product-detail-sidebar.js +60 -58
  18. package/dist/components/ec/product-list-item.js +64 -63
  19. package/dist/components/ec/product-option.js +30 -26
  20. package/dist/components/ec/rating-stars.js +27 -27
  21. package/dist/components/ec/review-card.js +32 -32
  22. package/dist/components/ec/review-form.js +37 -37
  23. package/dist/components/ec/shop-card.js +21 -19
  24. package/dist/components/foundations/accordion.js +33 -31
  25. package/dist/components/foundations/alert-dialog.js +4 -5
  26. package/dist/components/foundations/badge.js +5 -5
  27. package/dist/components/foundations/breadcrumb.js +27 -26
  28. package/dist/components/foundations/button.js +144 -25
  29. package/dist/components/foundations/calendar.js +28 -26
  30. package/dist/components/foundations/checkbox-card.js +71 -47
  31. package/dist/components/foundations/checkbox-group.js +30 -27
  32. package/dist/components/foundations/checkbox.js +69 -52
  33. package/dist/components/foundations/chip-variants.js +13 -0
  34. package/dist/components/foundations/command.js +81 -79
  35. package/dist/components/foundations/confirm-dialog.js +136 -0
  36. package/dist/components/foundations/context-menu.js +43 -38
  37. package/dist/components/foundations/data-table.js +88 -84
  38. package/dist/components/foundations/dialog.js +45 -36
  39. package/dist/components/foundations/dropdown-menu.js +47 -42
  40. package/dist/components/foundations/file-input.js +97 -67
  41. package/dist/components/foundations/hover-card.js +21 -21
  42. package/dist/components/foundations/menubar.js +75 -69
  43. package/dist/components/foundations/navigation-menu.js +31 -26
  44. package/dist/components/foundations/pagination.js +54 -50
  45. package/dist/components/foundations/popover.js +7 -7
  46. package/dist/components/foundations/progress.js +10 -6
  47. package/dist/components/foundations/radio-group.js +6 -3
  48. package/dist/components/foundations/responsive-dialog.js +73 -55
  49. package/dist/components/foundations/scroll-area.js +18 -14
  50. package/dist/components/foundations/select.js +44 -39
  51. package/dist/components/foundations/sheet.js +45 -37
  52. package/dist/components/foundations/skeleton.js +6 -6
  53. package/dist/components/foundations/skip-link.js +10 -8
  54. package/dist/components/foundations/slider.js +73 -48
  55. package/dist/components/foundations/sonner.js +5 -4
  56. package/dist/components/foundations/spinner.js +7 -5
  57. package/dist/components/foundations/switch.js +11 -10
  58. package/dist/components/foundations/tabs.js +54 -39
  59. package/dist/components/foundations/toggle-group.js +29 -21
  60. package/dist/components/foundations/toggle.js +20 -16
  61. package/dist/components/primitives/admin-side-nav.js +65 -62
  62. package/dist/components/primitives/banner-carousel.js +32 -29
  63. package/dist/components/primitives/bottom-tab-bar.js +16 -15
  64. package/dist/components/primitives/category-scroll.js +39 -29
  65. package/dist/components/primitives/category-shortcuts.js +9 -9
  66. package/dist/components/primitives/chat-composer.js +77 -74
  67. package/dist/components/primitives/chip.js +84 -61
  68. package/dist/components/primitives/combobox.js +63 -47
  69. package/dist/components/primitives/container.js +9 -9
  70. package/dist/components/primitives/content-card.js +15 -17
  71. package/dist/components/primitives/content-carousel.js +79 -68
  72. package/dist/components/primitives/date-picker.js +137 -99
  73. package/dist/components/primitives/footer.js +36 -37
  74. package/dist/components/primitives/header.js +175 -168
  75. package/dist/components/primitives/image-carousel.js +107 -87
  76. package/dist/components/primitives/image-gallery.js +32 -27
  77. package/dist/components/primitives/image-uploader.js +43 -22
  78. package/dist/components/primitives/list-item.js +59 -51
  79. package/dist/components/primitives/menu-drawer.js +36 -38
  80. package/dist/components/primitives/multi-select.js +89 -58
  81. package/dist/components/primitives/notification-list.js +10 -9
  82. package/dist/components/primitives/number-input.js +116 -105
  83. package/dist/components/primitives/scroll-row.js +21 -0
  84. package/dist/components/primitives/search-bar.js +31 -28
  85. package/dist/components/primitives/section-header.js +54 -53
  86. package/dist/components/primitives/side-nav.js +57 -56
  87. package/dist/components/primitives/sub-nav.js +13 -14
  88. package/dist/components/primitives/tag.js +4 -2
  89. package/dist/index.css +1 -1
  90. package/dist/index.js +3076 -929
  91. package/dist/lib/field-labelling.js +31 -21
  92. package/dist/lib/focus-ring.js +22 -4
  93. package/dist/lib/high-contrast.js +4 -0
  94. package/dist/lib/image-index.js +8 -0
  95. package/dist/lib/use-prefers-reduced-motion.js +21 -0
  96. package/dist/types/components/ec/admin-shell.d.ts +11 -1
  97. package/dist/types/components/ec/anniversary-card.d.ts +9 -1
  98. package/dist/types/components/ec/mypage-shell.d.ts +12 -1
  99. package/dist/types/components/ec/product-card.d.ts +13 -1
  100. package/dist/types/components/ec/product-carousel.d.ts +13 -1
  101. package/dist/types/components/ec/product-detail-bar.d.ts +12 -1
  102. package/dist/types/components/ec/product-detail-sidebar.d.ts +11 -1
  103. package/dist/types/components/ec/product-list-item.d.ts +9 -1
  104. package/dist/types/components/ec/rating-stars.d.ts +2 -0
  105. package/dist/types/components/ec/review-card.d.ts +1 -1
  106. package/dist/types/components/ec/shop-card.d.ts +8 -1
  107. package/dist/types/components/foundations/badge.d.ts +1 -1
  108. package/dist/types/components/foundations/breadcrumb.d.ts +8 -1
  109. package/dist/types/components/foundations/button.d.ts +38 -3
  110. package/dist/types/components/foundations/checkbox-card.d.ts +7 -1
  111. package/dist/types/components/foundations/checkbox.d.ts +1 -1
  112. package/dist/types/components/foundations/chip-variants.d.ts +2 -2
  113. package/dist/types/components/foundations/confirm-dialog.d.ts +61 -0
  114. package/dist/types/components/foundations/data-table.d.ts +9 -2
  115. package/dist/types/components/foundations/dialog.d.ts +16 -1
  116. package/dist/types/components/foundations/pagination.d.ts +1 -1
  117. package/dist/types/components/foundations/responsive-dialog.d.ts +2 -1
  118. package/dist/types/components/foundations/sheet.d.ts +12 -1
  119. package/dist/types/components/foundations/skeleton.d.ts +6 -0
  120. package/dist/types/components/foundations/slider.d.ts +15 -1
  121. package/dist/types/components/foundations/tabs.d.ts +7 -0
  122. package/dist/types/components/primitives/admin-side-nav.d.ts +22 -2
  123. package/dist/types/components/primitives/banner-carousel.d.ts +9 -1
  124. package/dist/types/components/primitives/bottom-tab-bar.d.ts +13 -2
  125. package/dist/types/components/primitives/category-scroll.d.ts +10 -1
  126. package/dist/types/components/primitives/category-shortcuts.d.ts +11 -2
  127. package/dist/types/components/primitives/chip.d.ts +22 -3
  128. package/dist/types/components/primitives/combobox.d.ts +7 -2
  129. package/dist/types/components/primitives/container.d.ts +3 -0
  130. package/dist/types/components/primitives/content-card.d.ts +1 -1
  131. package/dist/types/components/primitives/content-carousel.d.ts +12 -4
  132. package/dist/types/components/primitives/date-picker.d.ts +10 -3
  133. package/dist/types/components/primitives/footer.d.ts +1 -1
  134. package/dist/types/components/primitives/header.d.ts +14 -2
  135. package/dist/types/components/primitives/image-carousel.d.ts +23 -5
  136. package/dist/types/components/primitives/list-item.d.ts +10 -1
  137. package/dist/types/components/primitives/menu-drawer.d.ts +1 -1
  138. package/dist/types/components/primitives/multi-select.d.ts +7 -2
  139. package/dist/types/components/primitives/notification-list.d.ts +10 -1
  140. package/dist/types/components/primitives/number-input.d.ts +18 -5
  141. package/dist/types/components/primitives/scroll-row.d.ts +43 -0
  142. package/dist/types/components/primitives/section-header.d.ts +9 -2
  143. package/dist/types/components/primitives/side-nav.d.ts +13 -1
  144. package/dist/types/components/primitives/sub-nav.d.ts +1 -1
  145. package/dist/types/components/primitives/tag.d.ts +1 -1
  146. package/dist/types/index.d.ts +7 -1
  147. package/dist/types/lib/field-labelling.d.ts +23 -8
  148. package/dist/types/lib/focus-ring.d.ts +70 -3
  149. package/dist/types/lib/high-contrast.d.ts +25 -0
  150. package/dist/types/lib/image-index.d.ts +2 -0
  151. package/dist/types/lib/link-component.d.ts +26 -21
  152. package/dist/types/lib/use-prefers-reduced-motion.d.ts +9 -0
  153. package/package.json +11 -3
  154. package/src/components/COMPONENT_LOOKUP.md +19 -17
  155. package/src/preset-standalone.css +42 -0
  156. package/src/preset.css +20 -1
  157. package/src/styles/semantic.css +57 -0
  158. package/templates/AGENTS.md +5 -1
  159. package/templates/CLAUDE.md +3 -1
  160. package/tokens.json +49 -0
  161. package/dist/lib/link-component.js +0 -6
@@ -1,157 +1,177 @@
1
1
  "use client";
2
- import { jsxs as y, jsx as t, Fragment as T } from "react/jsx-runtime";
3
- import * as l from "react";
4
- import k from "iconsax-reactjs/dist/esm/ArrowLeft2.js";
5
- import C from "iconsax-reactjs/dist/esm/ArrowRight2.js";
6
- import { cn as o } from "../../lib/utils.js";
7
- function B({
8
- images: c,
9
- aspectRatio: i = "banner",
10
- showDots: N = !0,
11
- showArrows: w = !0,
12
- autoPlay: u = 0,
13
- peek: x = !1,
14
- pcSlidesPerView: d = 1,
15
- centeredSlides: h = !1,
2
+ import { jsxs as C, jsx as t, Fragment as M } from "react/jsx-runtime";
3
+ import * as n from "react";
4
+ import q from "iconsax-reactjs/dist/esm/ArrowLeft2.js";
5
+ import B from "iconsax-reactjs/dist/esm/ArrowRight2.js";
6
+ import { cn as l } from "../../lib/utils.js";
7
+ import { FOCUS_RING_ONLY as G } from "../../lib/focus-ring.js";
8
+ import { usePrefersReducedMotion as _ } from "../../lib/use-prefers-reduced-motion.js";
9
+ function J({
10
+ images: x,
11
+ aspectRatio: v = "banner",
12
+ showDots: E = !0,
13
+ showArrows: z = !0,
14
+ autoPlay: h = 0,
15
+ peek: c = !1,
16
+ pcSlidesPerView: u = 1,
17
+ centeredSlides: d = !1,
18
+ linkComponent: L,
16
19
  className: j,
17
- ...z
20
+ ...A
18
21
  }) {
19
- const p = l.useRef(null), [s, E] = l.useState(0), a = c.length, b = i === "square" ? "aspect-square" : i === "video" ? "aspect-video" : i === "ogp" ? "aspect-[1.91/1]" : "aspect-[311/162.5]";
20
- l.useEffect(() => {
21
- const r = p.current;
22
- if (!r) return;
23
- const e = new IntersectionObserver(
24
- (m) => {
25
- for (const v of m)
26
- if (v.isIntersecting) {
27
- const g = Number(
28
- v.target.dataset.index
29
- );
30
- Number.isNaN(g) || E(g);
31
- }
32
- },
33
- { root: r, threshold: 0.6 }
34
- );
35
- return r.querySelectorAll("[data-slide]").forEach((m) => e.observe(m)), () => e.disconnect();
36
- }, [a]);
37
- function n(r) {
22
+ const O = L ?? "a", p = n.useRef(null), [s, T] = n.useState(0), f = _(), a = x.length, g = v === "square" ? "aspect-square" : v === "video" ? "aspect-video" : v === "ogp" ? "aspect-[1.91/1]" : "aspect-[311/162.5]";
23
+ n.useEffect(() => {
38
24
  const e = p.current;
39
25
  if (!e) return;
40
- const f = e.children[r];
41
- f && e.scrollTo({ left: f.offsetLeft, behavior: "smooth" });
42
- }
43
- l.useEffect(() => {
44
- if (u <= 0 || a <= 1) return;
45
- const r = setInterval(() => {
46
- n((s + 1) % a);
47
- }, u);
48
- return () => clearInterval(r);
49
- }, [u, s, a]);
50
- function I() {
51
- n(s <= 0 ? a - 1 : s - 1);
52
- }
53
- function S() {
54
- n(s >= a - 1 ? 0 : s + 1);
26
+ let r = 0;
27
+ const o = () => {
28
+ cancelAnimationFrame(r), r = requestAnimationFrame(() => {
29
+ const y = Array.from(e.querySelectorAll("[data-slide]")), S = y[0]?.offsetLeft ?? 0;
30
+ let N = 0, w = Number.POSITIVE_INFINITY;
31
+ y.forEach((R, k) => {
32
+ const I = Math.abs(R.offsetLeft - S - e.scrollLeft);
33
+ I < w && (w = I, N = k);
34
+ }), T(N);
35
+ });
36
+ };
37
+ o(), e.addEventListener("scroll", o, { passive: !0 });
38
+ const i = typeof ResizeObserver > "u" ? void 0 : new ResizeObserver(o);
39
+ return i?.observe(e), () => {
40
+ cancelAnimationFrame(r), e.removeEventListener("scroll", o), i?.disconnect();
41
+ };
42
+ }, [a]);
43
+ const m = n.useCallback(
44
+ (e) => {
45
+ const r = p.current;
46
+ if (!r) return;
47
+ const o = r.children[e], i = r.children[0];
48
+ o && i && r.scrollTo({
49
+ left: o.offsetLeft - i.offsetLeft,
50
+ behavior: f ? "auto" : "smooth"
51
+ });
52
+ },
53
+ [f]
54
+ ), b = n.useCallback(() => {
55
+ const e = p.current, r = e ? e.scrollLeft >= e.scrollWidth - e.clientWidth - 1 : !1;
56
+ m(s >= a - 1 || r ? 0 : s + 1);
57
+ }, [s, a, m]);
58
+ n.useEffect(() => {
59
+ if (f || h <= 0 || a <= 1) return;
60
+ const e = setInterval(b, h);
61
+ return () => clearInterval(e);
62
+ }, [h, a, f, b]);
63
+ function F() {
64
+ m(s <= 0 ? a - 1 : s - 1);
55
65
  }
56
- return a === 0 ? null : /* @__PURE__ */ y(
66
+ return a === 0 ? null : /* @__PURE__ */ C(
57
67
  "div",
58
68
  {
59
69
  "data-slot": "image-carousel",
60
- className: o("@container group/carousel relative", j),
61
- ...z,
70
+ className: l("@container group/carousel relative", j),
71
+ ...A,
62
72
  children: [
63
73
  /* @__PURE__ */ t(
64
74
  "div",
65
75
  {
66
76
  ref: p,
67
77
  tabIndex: 0,
68
- className: o(
69
- "flex snap-x snap-mandatory overflow-x-auto scroll-smooth scrollbar-none",
70
- "focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50",
71
- x && "pl-4 @[960px]:pl-0",
78
+ className: l(
79
+ "flex snap-x snap-mandatory overflow-x-auto scroll-smooth motion-reduce:scroll-auto scrollbar-none",
80
+ `focus-visible:outline-none ${G}`,
81
+ // peek: 端の余白 = Container の gutter(外に置いたときは 16px)。Container の中では
82
+ // gutter 分だけ外へはみ出して画面端までスクロールさせる。scroll-padding も同じ幅にして、
83
+ // スナップ後も端の余白が消えないようにする。PC (@[960px]:) では peek しないので外す
84
+ c && "-mx-[var(--Container-Gutter,0px)] gap-3 px-[var(--Container-Gutter,16px)] scroll-px-[var(--Container-Gutter,16px)] @[960px]:mx-0 @[960px]:px-0 @[960px]:scroll-px-0",
85
+ c && u === 1 && "@[960px]:gap-0",
86
+ // peek + centeredSlides: タブレットでは centeredSlides の左右の余白に任せ、はみ出しを外す
87
+ c && d && "@[768px]:mx-0 @[768px]:scroll-px-0",
72
88
  // タブレット centeredSlides: コンテナに px-[22.25%] を付与し
73
89
  // flex item の w-full が自動で ~426px になる(768px の 55.5%)
74
90
  // @[768px]: と @[960px]: は数値指定で CSS 出力順が保証されるため
75
91
  // 960px+ では @[960px]:px-0 が必ず上書きする
76
- h && "@[768px]:px-[22.25%] @[960px]:px-0 @[768px]:gap-4",
92
+ d && "@[768px]:px-[22.25%] @[960px]:px-0 @[768px]:gap-4",
77
93
  // PC 複数枚表示時のスライド間ギャップ(本番 spaceBetween:24 準拠)
78
94
  // cascade: @[960px]:gap-6 > @[768px]:gap-4 at 960px+
79
- d > 1 && "@[960px]:gap-6"
95
+ u > 1 && "@[960px]:gap-6"
80
96
  ),
81
97
  style: { scrollbarWidth: "none", msOverflowStyle: "none" },
82
- children: c.map((r, e) => /* @__PURE__ */ t(
98
+ children: x.map((e, r) => /* @__PURE__ */ t(
83
99
  "div",
84
100
  {
85
101
  "data-slide": !0,
86
- "data-index": e,
87
- className: o(
102
+ "data-index": r,
103
+ className: l(
88
104
  "shrink-0 snap-start",
89
105
  // centeredSlides: タブレットで snap-center、PC で snap-start に戻す
90
- h && "@[768px]:snap-center @[960px]:snap-start",
91
- x ? d > 1 ? "w-[calc(100%-48px)] pr-3 @[960px]:w-[calc((100%-48px)/3)] @[960px]:pr-0" : "w-[calc(100%-48px)] pr-3 @[960px]:w-full @[960px]:pr-0" : d > 1 ? "w-full @[960px]:w-[calc((100%-48px)/3)]" : "w-full"
106
+ d && "@[768px]:snap-center @[960px]:snap-start",
107
+ // peek + centeredSlides: タブレットは centeredSlides と同じく左右の余白の内側いっぱい
108
+ c && d && "@[768px]:w-full",
109
+ // peek: 端の余白 16px のとき、カード幅は導入前(全幅に置いた場合)と同じ「全幅 - 76px」。
110
+ // スライドの間隔は scroller の gap-3
111
+ c ? u > 1 ? "w-[calc(100%-44px)] @[960px]:w-[calc((100%-48px)/3)]" : "w-[calc(100%-44px)] @[960px]:w-full" : u > 1 ? "w-full @[960px]:w-[calc((100%-48px)/3)]" : "w-full"
92
112
  ),
93
- children: r.href ? /* @__PURE__ */ t("a", { href: r.href, className: "block", children: /* @__PURE__ */ t(
113
+ children: e.href ? /* @__PURE__ */ t(O, { href: e.href, className: "block", children: /* @__PURE__ */ t(
94
114
  "img",
95
115
  {
96
- src: r.src,
97
- alt: r.alt,
98
- loading: e === 0 ? "eager" : "lazy",
99
- className: o("w-full rounded-md object-cover @[960px]:rounded-lg", b)
116
+ src: e.src,
117
+ alt: e.alt,
118
+ loading: r === 0 ? "eager" : "lazy",
119
+ className: l("w-full rounded-md object-cover @[960px]:rounded-lg", g)
100
120
  }
101
121
  ) }) : /* @__PURE__ */ t(
102
122
  "img",
103
123
  {
104
- src: r.src,
105
- alt: r.alt,
106
- loading: e === 0 ? "eager" : "lazy",
107
- className: o("w-full rounded-md object-cover @[960px]:rounded-lg", b)
124
+ src: e.src,
125
+ alt: e.alt,
126
+ loading: r === 0 ? "eager" : "lazy",
127
+ className: l("w-full rounded-md object-cover @[960px]:rounded-lg", g)
108
128
  }
109
129
  )
110
130
  },
111
- e
131
+ r
112
132
  ))
113
133
  }
114
134
  ),
115
- w && a > 1 && /* @__PURE__ */ y(T, { children: [
135
+ z && a > 1 && /* @__PURE__ */ C(M, { children: [
116
136
  /* @__PURE__ */ t(
117
137
  "button",
118
138
  {
119
139
  type: "button",
120
- onClick: I,
140
+ onClick: F,
121
141
  "aria-label": "前へ",
122
- className: "absolute left-2 top-1/2 z-10 hidden size-10 -translate-y-1/2 items-center justify-center rounded-full border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Secondary)] shadow-md transition-opacity hover:bg-[var(--Surface-Tertiary)] @md:flex @[960px]:opacity-0 @[960px]:group-hover/carousel:opacity-100",
123
- children: /* @__PURE__ */ t(k, { size: 20, className: "text-[var(--Object-High-Emphasis)]" })
142
+ className: "absolute left-2 top-1/2 z-10 hidden size-10 -translate-y-1/2 items-center justify-center rounded-full border border-[var(--Border-Control,var(--Border-Medium-Emphasis))] bg-[var(--Surface-Secondary)] shadow-md transition-opacity hover:bg-[var(--Surface-Tertiary)] @md:flex @[960px]:opacity-0 @[960px]:group-hover/carousel:opacity-100",
143
+ children: /* @__PURE__ */ t(q, { size: 20, className: "text-[var(--Object-High-Emphasis)]" })
124
144
  }
125
145
  ),
126
146
  /* @__PURE__ */ t(
127
147
  "button",
128
148
  {
129
149
  type: "button",
130
- onClick: S,
150
+ onClick: b,
131
151
  "aria-label": "次へ",
132
- className: "absolute right-2 top-1/2 z-10 hidden size-10 -translate-y-1/2 items-center justify-center rounded-full border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Secondary)] shadow-md transition-opacity hover:bg-[var(--Surface-Tertiary)] @md:flex @[960px]:opacity-0 @[960px]:group-hover/carousel:opacity-100",
133
- children: /* @__PURE__ */ t(C, { size: 20, className: "text-[var(--Object-High-Emphasis)]" })
152
+ className: "absolute right-2 top-1/2 z-10 hidden size-10 -translate-y-1/2 items-center justify-center rounded-full border border-[var(--Border-Control,var(--Border-Medium-Emphasis))] bg-[var(--Surface-Secondary)] shadow-md transition-opacity hover:bg-[var(--Surface-Tertiary)] @md:flex @[960px]:opacity-0 @[960px]:group-hover/carousel:opacity-100",
153
+ children: /* @__PURE__ */ t(B, { size: 20, className: "text-[var(--Object-High-Emphasis)]" })
134
154
  }
135
155
  )
136
156
  ] }),
137
- N && a > 1 && /* @__PURE__ */ t("div", { className: "mt-2 flex flex-wrap items-center justify-center gap-1.5 @[960px]:hidden", children: c.map((r, e) => /* @__PURE__ */ t(
157
+ E && a > 1 && /* @__PURE__ */ t("div", { className: "mt-2 flex flex-wrap items-center justify-center gap-1.5 @[960px]:hidden", children: x.map((e, r) => /* @__PURE__ */ t(
138
158
  "button",
139
159
  {
140
160
  type: "button",
141
- onClick: () => n(e),
142
- "aria-label": `スライド ${e + 1}`,
143
- className: o(
161
+ onClick: () => m(r),
162
+ "aria-label": `スライド ${r + 1}`,
163
+ className: l(
144
164
  // shrink-0 必須: 空要素なので min-content 幅が 0、既定の flex-shrink:1 だとドットが消える
145
165
  "size-2 shrink-0 rounded-full transition-colors",
146
- e === s ? "bg-[var(--Text-High-Emphasis)]" : "bg-[var(--Surface-Tertiary)]"
166
+ r === s ? "bg-[var(--Text-High-Emphasis)]" : "bg-[var(--Surface-Tertiary)]"
147
167
  )
148
168
  },
149
- e
169
+ r
150
170
  )) })
151
171
  ]
152
172
  }
153
173
  );
154
174
  }
155
175
  export {
156
- B as ImageCarousel
176
+ J as ImageCarousel
157
177
  };
@@ -1,38 +1,43 @@
1
1
  "use client";
2
- import { jsxs as n, jsx as t, Fragment as b } from "react/jsx-runtime";
3
- import * as x from "react";
4
- import y from "iconsax-reactjs/dist/esm/ArrowLeft2.js";
5
- import g from "iconsax-reactjs/dist/esm/ArrowRight2.js";
2
+ import { jsxs as n, jsx as t, Fragment as g } from "react/jsx-runtime";
3
+ import * as i from "react";
4
+ import w from "iconsax-reactjs/dist/esm/ArrowLeft2.js";
5
+ import N from "iconsax-reactjs/dist/esm/ArrowRight2.js";
6
6
  import { cn as o } from "../../lib/utils.js";
7
- function P({
7
+ import { reconcileImageIndex as k } from "../../lib/image-index.js";
8
+ function z({
8
9
  images: r,
9
10
  alts: c,
10
- aspectRatio: h = "square",
11
- showThumbnails: f = !1,
12
- showDots: m = !0,
13
- layout: v = "default",
14
- className: i,
11
+ aspectRatio: p = "square",
12
+ showThumbnails: v = !1,
13
+ showDots: b = !0,
14
+ layout: x = "default",
15
+ className: u,
15
16
  ...d
16
17
  }) {
17
- const [a, p] = x.useState(0);
18
- if (r.length === 0) return null;
19
- const s = (l) => {
18
+ const [y, h] = i.useState(0), f = i.useRef(r);
19
+ if (i.useEffect(() => {
20
+ h(
21
+ (l) => k(f.current, r, l)
22
+ ), f.current = r;
23
+ }, [r]), r.length === 0) return null;
24
+ const a = Math.min(y, r.length - 1), s = (l) => {
20
25
  const e = (l % r.length + r.length) % r.length;
21
- e !== a && p(e);
22
- }, u = {
26
+ e !== a && h(e);
27
+ }, m = {
23
28
  square: "aspect-square",
24
29
  "4:3": "aspect-[4/3]",
25
30
  "16:9": "aspect-video",
26
31
  auto: ""
27
- }[h];
28
- return v === "pc-detail" ? /* @__PURE__ */ n(
32
+ }[p];
33
+ return x === "pc-detail" ? /* @__PURE__ */ n(
29
34
  "div",
30
35
  {
31
36
  "data-slot": "image-gallery",
32
- className: o("flex flex-row-reverse gap-6", i),
37
+ className: o("flex flex-row-reverse gap-6", u),
33
38
  ...d,
34
39
  children: [
35
- /* @__PURE__ */ n("div", { className: o("relative min-w-0 grow overflow-hidden rounded-lg", u), children: [
40
+ /* @__PURE__ */ n("div", { className: o("relative min-w-0 grow overflow-hidden rounded-lg", m), children: [
36
41
  /* @__PURE__ */ t(
37
42
  "div",
38
43
  {
@@ -82,10 +87,10 @@ function P({
82
87
  "div",
83
88
  {
84
89
  "data-slot": "image-gallery",
85
- className: o("space-y-2", i),
90
+ className: o("space-y-2", u),
86
91
  ...d,
87
92
  children: [
88
- /* @__PURE__ */ n("div", { className: o("relative w-full overflow-hidden", u), children: [
93
+ /* @__PURE__ */ n("div", { className: o("relative w-full overflow-hidden", m), children: [
89
94
  /* @__PURE__ */ t(
90
95
  "div",
91
96
  {
@@ -102,7 +107,7 @@ function P({
102
107
  ))
103
108
  }
104
109
  ),
105
- r.length > 1 && /* @__PURE__ */ n(b, { children: [
110
+ r.length > 1 && /* @__PURE__ */ n(g, { children: [
106
111
  /* @__PURE__ */ t(
107
112
  "button",
108
113
  {
@@ -110,7 +115,7 @@ function P({
110
115
  className: "absolute left-2 top-1/2 flex size-10 -translate-y-1/2 items-center justify-center rounded-full bg-[var(--Surface-Primary)]/80 shadow-sm transition-colors hover:bg-[var(--Surface-Primary)]",
111
116
  onClick: () => s(a - 1),
112
117
  "aria-label": "前の画像",
113
- children: /* @__PURE__ */ t(y, { size: 20, className: "text-[var(--Text-High-Emphasis)]" })
118
+ children: /* @__PURE__ */ t(w, { size: 20, className: "text-[var(--Text-High-Emphasis)]" })
114
119
  }
115
120
  ),
116
121
  /* @__PURE__ */ t(
@@ -120,7 +125,7 @@ function P({
120
125
  className: "absolute right-2 top-1/2 flex size-10 -translate-y-1/2 items-center justify-center rounded-full bg-[var(--Surface-Primary)]/80 shadow-sm transition-colors hover:bg-[var(--Surface-Primary)]",
121
126
  onClick: () => s(a + 1),
122
127
  "aria-label": "次の画像",
123
- children: /* @__PURE__ */ t(g, { size: 20, className: "text-[var(--Text-High-Emphasis)]" })
128
+ children: /* @__PURE__ */ t(N, { size: 20, className: "text-[var(--Text-High-Emphasis)]" })
124
129
  }
125
130
  )
126
131
  ] }),
@@ -130,7 +135,7 @@ function P({
130
135
  r.length
131
136
  ] })
132
137
  ] }),
133
- m && r.length > 1 && /* @__PURE__ */ t("div", { className: "flex flex-wrap justify-center gap-0.5", children: r.map((l, e) => /* @__PURE__ */ t(
138
+ b && r.length > 1 && /* @__PURE__ */ t("div", { className: "flex flex-wrap justify-center gap-0.5", children: r.map((l, e) => /* @__PURE__ */ t(
134
139
  "button",
135
140
  {
136
141
  type: "button",
@@ -149,7 +154,7 @@ function P({
149
154
  },
150
155
  e
151
156
  )) }),
152
- f && r.length > 1 && /* @__PURE__ */ t("div", { className: "flex gap-1.5 overflow-x-auto scrollbar-hide", children: r.map((l, e) => /* @__PURE__ */ t(
157
+ v && r.length > 1 && /* @__PURE__ */ t("div", { className: "flex gap-1.5 overflow-x-auto scrollbar-hide", children: r.map((l, e) => /* @__PURE__ */ t(
153
158
  "button",
154
159
  {
155
160
  type: "button",
@@ -174,5 +179,5 @@ function P({
174
179
  );
175
180
  }
176
181
  export {
177
- P as ImageGallery
182
+ z as ImageGallery
178
183
  };
@@ -1,23 +1,25 @@
1
1
  import { jsxs as t, jsx as e } from "react/jsx-runtime";
2
2
  import "react";
3
- import { cn as m } from "../../lib/utils.js";
4
- import p from "iconsax-reactjs/dist/esm/Add.js";
5
- import u from "iconsax-reactjs/dist/esm/Trash.js";
6
- function g({
3
+ import { cn as o } from "../../lib/utils.js";
4
+ import { FOCUS_RING_INSET as p } from "../../lib/focus-ring.js";
5
+ import { Button as v } from "../foundations/button.js";
6
+ import u from "iconsax-reactjs/dist/esm/Add.js";
7
+ import h from "iconsax-reactjs/dist/esm/Trash.js";
8
+ function z({
7
9
  images: i = [],
8
10
  onAdd: s,
9
11
  onRemove: l,
10
- maxImages: o = 10,
11
- columns: c = 4,
12
- className: n
12
+ maxImages: n = 10,
13
+ columns: d = 4,
14
+ className: c
13
15
  }) {
14
- const d = i.length < o;
16
+ const m = i.length < n;
15
17
  return /* @__PURE__ */ t(
16
18
  "div",
17
19
  {
18
- className: m("grid gap-3", n),
20
+ className: o("grid gap-3", c),
19
21
  style: {
20
- gridTemplateColumns: `repeat(${Math.min(c, 4)}, minmax(0, 1fr))`
22
+ gridTemplateColumns: `repeat(${Math.min(d, 4)}, minmax(0, 1fr))`
21
23
  },
22
24
  "data-slot": "image-uploader",
23
25
  children: [
@@ -34,28 +36,47 @@ function g({
34
36
  className: "absolute inset-0 size-full object-cover"
35
37
  }
36
38
  ),
37
- /* @__PURE__ */ e("div", { className: "absolute inset-0 bg-[var(--Primitive-Black-alpha-1000)]/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center", children: /* @__PURE__ */ e(
38
- "button",
39
+ /* @__PURE__ */ e(
40
+ "div",
39
41
  {
40
- className: "size-8 rounded-full bg-[var(--Primitive-White-alpha-1000)]/80 flex items-center justify-center",
41
- "aria-label": `${r.alt}を削除`,
42
- onClick: () => l?.(a),
43
- children: /* @__PURE__ */ e(u, { size: 16, className: "text-[var(--Text-Caution)]" })
42
+ "data-slot": "image-uploader-remove-overlay",
43
+ className: o(
44
+ "absolute inset-0 flex items-center justify-center bg-[var(--Surface-Overlay-Dark)] opacity-0 transition-opacity",
45
+ "group-hover:opacity-100 group-focus-within:opacity-100",
46
+ // タッチでは hover を待たず、写真を覆わない右上の操作として表示する。
47
+ "[@media(hover:none)]:items-start [@media(hover:none)]:justify-end [@media(hover:none)]:bg-transparent [@media(hover:none)]:p-1 [@media(hover:none)]:opacity-100"
48
+ ),
49
+ children: /* @__PURE__ */ e(
50
+ v,
51
+ {
52
+ type: "button",
53
+ variant: "overlay",
54
+ size: "icon-sm",
55
+ className: "rounded-full [@media(hover:none)]:size-11",
56
+ "aria-label": `${r.alt}を削除`,
57
+ onClick: () => l?.(a),
58
+ children: /* @__PURE__ */ e(h, { size: 16 })
59
+ }
60
+ )
44
61
  }
45
- ) }),
46
- /* @__PURE__ */ e("div", { className: "absolute top-1 left-1 size-5 rounded bg-[var(--Primitive-Black-alpha-1000)]/60 text-[var(--Primitive-White-alpha-1000)] flex items-center justify-center typo-label-xs", children: a + 1 })
62
+ ),
63
+ /* @__PURE__ */ e("div", { className: "absolute top-1 left-1 size-5 rounded bg-[var(--Primitive-Gray-alpha-600)] text-[var(--Primitive-White-alpha-1000)] flex items-center justify-center typo-label-xs", children: a + 1 })
47
64
  ]
48
65
  },
49
66
  a
50
67
  )),
51
- d && /* @__PURE__ */ t(
68
+ m && /* @__PURE__ */ t(
52
69
  "button",
53
70
  {
54
- className: "aspect-square rounded-xl border-2 border-dashed border-[var(--Border-Medium-Emphasis)] flex flex-col items-center justify-center gap-1 hover:border-[var(--Border-Accent-Primary)] hover:bg-[var(--Surface-Accent-Primary-Light)] transition-colors",
71
+ type: "button",
72
+ className: o(
73
+ "aspect-square rounded-xl border-2 border-dashed border-[var(--Border-Control,var(--Border-Medium-Emphasis))] flex flex-col items-center justify-center gap-1 hover:border-[var(--Border-Accent-Primary)] hover:bg-[var(--Surface-Accent-Primary-Light)] transition-colors",
74
+ p
75
+ ),
55
76
  onClick: s,
56
77
  "aria-label": "画像を追加",
57
78
  children: [
58
- /* @__PURE__ */ e(p, { size: 24, className: "text-[var(--Text-Low-Emphasis)]" }),
79
+ /* @__PURE__ */ e(u, { size: 24, className: "text-[var(--Text-Low-Emphasis)]" }),
59
80
  /* @__PURE__ */ e("span", { className: "typo-label-xs text-[var(--Text-Low-Emphasis)]", children: "追加" })
60
81
  ]
61
82
  }
@@ -65,5 +86,5 @@ function g({
65
86
  );
66
87
  }
67
88
  export {
68
- g as ImageUploader
89
+ z as ImageUploader
69
90
  };
@@ -1,78 +1,86 @@
1
1
  "use client";
2
- import { jsxs as x, Fragment as D, jsx as e } from "react/jsx-runtime";
3
- import * as L from "react";
4
- import K from "iconsax-reactjs/dist/esm/ArrowRight2.js";
5
- import F from "iconsax-reactjs/dist/esm/ArrowDown2.js";
6
- import { Switch as O } from "../foundations/switch.js";
7
- import { cn as g } from "../../lib/utils.js";
2
+ import { jsxs as b, Fragment as H, jsx as e } from "react/jsx-runtime";
3
+ import * as I from "react";
4
+ import T from "iconsax-reactjs/dist/esm/ArrowRight2.js";
5
+ import D from "iconsax-reactjs/dist/esm/ArrowDown2.js";
6
+ import { Switch as F } from "../foundations/switch.js";
7
+ import { cn as p } from "../../lib/utils.js";
8
+ import { FOCUS_RING_ONLY as K } from "../../lib/focus-ring.js";
9
+ const R = "focus-visible:ring-inset forced-colors:focus-visible:-outline-offset-2", M = [
10
+ "group-focus-visible/list-item:ring-[3px] group-focus-visible/list-item:ring-inset group-focus-visible/list-item:ring-[color:var(--Focus-Ring-Control,color-mix(in_oklab,var(--Focus-High-Emphasis)_50%,transparent))]",
11
+ "forced-colors:group-focus-visible/list-item:outline-solid forced-colors:group-focus-visible/list-item:outline-2 forced-colors:group-focus-visible/list-item:-outline-offset-2 forced-colors:group-focus-visible/list-item:outline-[Highlight]"
12
+ ].join(" ");
8
13
  function q({
9
- title: p,
10
- caption: o,
11
- rightType: a = "arrow-right",
14
+ title: x,
15
+ caption: n,
16
+ rightType: o = "arrow-right",
12
17
  rightText: d,
13
- badgeCount: m,
18
+ badgeCount: u,
14
19
  toggleChecked: y = !1,
15
- onToggleChange: w,
20
+ onToggleChange: N,
16
21
  leftIcon: l,
17
- leftImageUrl: n,
18
- size: N = "sm",
22
+ leftImageUrl: a,
23
+ size: w = "sm",
19
24
  selected: k = !1,
20
- showBorder: h = !0,
21
- showBadgeDot: E = !1,
25
+ showBorder: f = !0,
26
+ showBadgeDot: S = !1,
22
27
  href: c,
23
- className: S,
24
- ...s
28
+ linkComponent: E,
29
+ className: C,
30
+ ...i
25
31
  }) {
26
- const u = L.useId(), t = o ? "md" : !!(l || n) ? "lg" : N, v = !!c, r = !v && typeof s.onClick == "function", j = v || r, C = r ? (i) => {
27
- s.onKeyDown?.(i), !i.defaultPrevented && (i.key === "Enter" || i.key === " ") && (i.preventDefault(), i.currentTarget.click());
28
- } : s.onKeyDown, z = t === "lg" ? "min-h-16 py-4" : t === "md" ? "min-h-14 py-2" : "min-h-11 py-2", H = t === "lg" ? "typo-body-lg text-[var(--Text-High-Emphasis)]" : "typo-body-md text-[var(--Text-High-Emphasis)]", f = g(
32
+ const L = E ?? "a", h = I.useId(), r = n ? "md" : !!(l || a) ? "lg" : w, m = !!c, s = !m && typeof i.onClick == "function", _ = m || s, j = s ? (t) => {
33
+ i.onKeyDown?.(t), !t.defaultPrevented && (t.key === "Enter" || t.key === " ") && (t.preventDefault(), t.currentTarget.click());
34
+ } : i.onKeyDown, O = r === "lg" ? "min-h-16 py-4" : r === "md" ? "min-h-14 py-2" : "min-h-11 py-2", z = r === "lg" ? "typo-body-lg text-[var(--Text-High-Emphasis)]" : "typo-body-md text-[var(--Text-High-Emphasis)]", v = p(
29
35
  "relative flex w-full items-center gap-2 bg-[var(--Surface-Primary)] px-4 rounded-lg",
30
- z,
36
+ O,
31
37
  k && "bg-[var(--Surface-Secondary)]",
32
- j && "transition-colors hover:bg-[var(--Surface-Tertiary)]",
33
- r && "cursor-pointer focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50",
34
- S
35
- ), b = /* @__PURE__ */ x(D, { children: [
36
- n && /* @__PURE__ */ e("div", { className: "relative shrink-0 size-8 overflow-hidden rounded-[var(--radius-sm,4px)]", children: /* @__PURE__ */ e("img", { src: n, alt: "", className: "size-full object-cover" }) }),
37
- l && !n && /* @__PURE__ */ e("div", { className: "shrink-0 size-5 flex items-center justify-center text-[var(--Object-High-Emphasis)]", children: l }),
38
- /* @__PURE__ */ x("div", { className: "flex flex-1 min-w-0 flex-col gap-0", children: [
39
- /* @__PURE__ */ e("span", { id: u, className: g("truncate", H), children: p }),
40
- o && /* @__PURE__ */ e("span", { className: "truncate typo-body-sm text-[var(--Text-Medium-Emphasis)]", children: o })
38
+ _ && "transition-colors hover:bg-[var(--Surface-Tertiary)]",
39
+ s && `cursor-pointer focus-visible:outline-none ${K}`,
40
+ s && R,
41
+ m && M,
42
+ C
43
+ ), g = /* @__PURE__ */ b(H, { children: [
44
+ a && /* @__PURE__ */ e("div", { className: "relative shrink-0 size-8 overflow-hidden rounded-[var(--radius-sm,4px)]", children: /* @__PURE__ */ e("img", { src: a, alt: "", className: "size-full object-cover" }) }),
45
+ l && !a && /* @__PURE__ */ e("div", { className: "shrink-0 size-5 flex items-center justify-center text-[var(--Object-High-Emphasis)]", children: l }),
46
+ /* @__PURE__ */ b("div", { className: "flex flex-1 min-w-0 flex-col gap-0", children: [
47
+ /* @__PURE__ */ e("span", { id: h, className: p("truncate", z), children: x }),
48
+ n && /* @__PURE__ */ e("span", { className: "truncate typo-body-sm text-[var(--Text-Medium-Emphasis)]", children: n })
41
49
  ] }),
42
- a === "arrow-right" && /* @__PURE__ */ e(K, { size: 20, className: "shrink-0 text-[var(--Object-Low-Emphasis)]" }),
43
- a === "arrow-down" && /* @__PURE__ */ e(F, { size: 20, className: "shrink-0 text-[var(--Object-Low-Emphasis)]" }),
44
- a === "text" && d && /* @__PURE__ */ e("span", { className: "shrink-0 typo-body-md text-[var(--Text-High-Emphasis)]", children: d }),
45
- a === "badge" && m !== void 0 && /* @__PURE__ */ e("span", { className: "flex shrink-0 h-[13px] min-w-[13px] items-center justify-center rounded-full bg-[var(--Surface-Caution,#ec0000)] px-1 typo-label-xs text-white", children: m }),
46
- a === "toggle" && /* @__PURE__ */ e(
47
- O,
50
+ o === "arrow-right" && /* @__PURE__ */ e(T, { size: 20, className: "shrink-0 text-[var(--Object-Low-Emphasis)]" }),
51
+ o === "arrow-down" && /* @__PURE__ */ e(D, { size: 20, className: "shrink-0 text-[var(--Object-Low-Emphasis)]" }),
52
+ o === "text" && d && /* @__PURE__ */ e("span", { className: "shrink-0 typo-body-md text-[var(--Text-High-Emphasis)]", children: d }),
53
+ o === "badge" && u !== void 0 && /* @__PURE__ */ e("span", { className: "flex shrink-0 h-[13px] min-w-[13px] items-center justify-center rounded-full bg-[var(--Surface-Caution,#ec0000)] px-1 typo-label-xs text-white", children: u }),
54
+ o === "toggle" && /* @__PURE__ */ e(
55
+ F,
48
56
  {
49
57
  checked: y,
50
- onCheckedChange: w,
51
- "aria-labelledby": u,
58
+ onCheckedChange: N,
59
+ "aria-labelledby": h,
52
60
  className: "shrink-0"
53
61
  }
54
62
  ),
55
- E && /* @__PURE__ */ e("span", { className: "absolute left-1 top-1/2 -translate-y-1/2 size-2 rounded-full bg-[var(--Surface-Caution,#ec0000)]", "aria-hidden": !0 }),
56
- h && t !== "lg" && /* @__PURE__ */ e("div", { className: "absolute bottom-0 left-4 right-4 h-px bg-[var(--Surface-Secondary)]", "aria-hidden": !0 }),
57
- h && t === "lg" && /* @__PURE__ */ e("div", { className: "absolute bottom-0 left-4 right-4 h-px bg-[var(--Border-Medium-Emphasis)]", "aria-hidden": !0 })
63
+ S && /* @__PURE__ */ e("span", { className: "absolute left-1 top-1/2 -translate-y-1/2 size-2 rounded-full bg-[var(--Surface-Caution,#ec0000)]", "aria-hidden": !0 }),
64
+ f && r !== "lg" && /* @__PURE__ */ e("div", { className: "absolute bottom-0 left-4 right-4 h-px bg-[var(--Surface-Secondary)]", "aria-hidden": !0 }),
65
+ f && r === "lg" && /* @__PURE__ */ e("div", { className: "absolute bottom-0 left-4 right-4 h-px bg-[var(--Border-Medium-Emphasis)]", "aria-hidden": !0 })
58
66
  ] });
59
67
  return c ? /* @__PURE__ */ e(
60
- "a",
68
+ L,
61
69
  {
62
70
  href: c,
63
- ...s,
64
- className: "block rounded-lg focus-visible:outline-none focus-visible:ring-[3px] focus-visible:ring-[var(--Focus-High-Emphasis)]/50",
65
- children: /* @__PURE__ */ e("div", { className: f, children: b })
71
+ ...i,
72
+ className: "group/list-item block rounded-lg outline-none",
73
+ children: /* @__PURE__ */ e("div", { className: v, children: g })
66
74
  }
67
75
  ) : /* @__PURE__ */ e(
68
76
  "div",
69
77
  {
70
- className: f,
71
- ...s,
72
- role: r ? "button" : s.role,
73
- tabIndex: r ? 0 : s.tabIndex,
74
- onKeyDown: C,
75
- children: b
78
+ className: v,
79
+ ...i,
80
+ role: s ? "button" : i.role,
81
+ tabIndex: s ? 0 : i.tabIndex,
82
+ onKeyDown: j,
83
+ children: g
76
84
  }
77
85
  );
78
86
  }