@cakejp/design-system 0.17.1 → 0.20.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 (101) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/CLAUDE.md +16 -0
  3. package/bin/init.js +191 -28
  4. package/contracts/components.json +176 -17
  5. package/contracts/composition.json +1 -1
  6. package/contracts/rules.json +5 -1
  7. package/contracts/screen-patterns.json +1 -1
  8. package/dist/components/ec/admin-shell.js +7 -6
  9. package/dist/components/ec/order-summary.js +16 -15
  10. package/dist/components/ec/product-card.js +107 -102
  11. package/dist/components/ec/product-option.js +1 -0
  12. package/dist/components/ec/review-card.js +22 -20
  13. package/dist/components/ec/review-form.js +1 -0
  14. package/dist/components/foundations/accordion.js +23 -22
  15. package/dist/components/foundations/alert-dialog.js +7 -7
  16. package/dist/components/foundations/alert.js +1 -0
  17. package/dist/components/foundations/aspect-ratio.js +3 -2
  18. package/dist/components/foundations/avatar.js +1 -0
  19. package/dist/components/foundations/button.js +7 -1
  20. package/dist/components/foundations/calendar.js +1 -0
  21. package/dist/components/foundations/checkbox-group.js +1 -0
  22. package/dist/components/foundations/checkbox.js +1 -0
  23. package/dist/components/foundations/command.js +1 -0
  24. package/dist/components/foundations/context-menu.js +1 -0
  25. package/dist/components/foundations/data-table.js +489 -16
  26. package/dist/components/foundations/dialog.js +13 -13
  27. package/dist/components/foundations/drawer.js +6 -5
  28. package/dist/components/foundations/file-input.js +1 -0
  29. package/dist/components/foundations/form.js +26 -25
  30. package/dist/components/foundations/pagination.js +49 -46
  31. package/dist/components/foundations/popover.js +9 -8
  32. package/dist/components/foundations/radio-group.js +3 -2
  33. package/dist/components/foundations/responsive-dialog.js +1 -0
  34. package/dist/components/foundations/separator.js +7 -6
  35. package/dist/components/foundations/sheet.js +41 -34
  36. package/dist/components/foundations/slider.js +7 -6
  37. package/dist/components/foundations/social-icon.js +30 -10
  38. package/dist/components/foundations/sonner.js +5 -4
  39. package/dist/components/foundations/tabs.js +45 -25
  40. package/dist/components/foundations/toggle-group.js +6 -5
  41. package/dist/components/primitives/admin-header.js +1 -1
  42. package/dist/components/primitives/admin-side-nav.js +196 -86
  43. package/dist/components/primitives/bottom-tab-bar.js +20 -20
  44. package/dist/components/primitives/chat-composer.js +1 -0
  45. package/dist/components/primitives/combobox.js +1 -0
  46. package/dist/components/primitives/content-card.js +111 -0
  47. package/dist/components/primitives/content-carousel.js +9 -8
  48. package/dist/components/primitives/date-picker.js +9 -8
  49. package/dist/components/primitives/footer.js +169 -100
  50. package/dist/components/primitives/form-field.js +1 -0
  51. package/dist/components/primitives/header.js +226 -176
  52. package/dist/components/primitives/image-carousel.js +8 -7
  53. package/dist/components/primitives/image-gallery.js +15 -14
  54. package/dist/components/primitives/image-input.js +9 -8
  55. package/dist/components/primitives/list-item.js +9 -8
  56. package/dist/components/primitives/menu-drawer.js +60 -56
  57. package/dist/components/primitives/multi-select.js +7 -6
  58. package/dist/components/primitives/number-input.js +1 -0
  59. package/dist/components/primitives/prose.js +52 -0
  60. package/dist/components/primitives/search-bar.js +81 -66
  61. package/dist/components/primitives/section-header.js +58 -55
  62. package/dist/components/primitives/share-buttons.js +93 -85
  63. package/dist/components/primitives/status-count-tabs.js +8 -7
  64. package/dist/components/primitives/sticky-action-bar.js +2 -1
  65. package/dist/components/primitives/sub-nav.js +52 -52
  66. package/dist/index.css +1 -1
  67. package/dist/index.js +2027 -752
  68. package/dist/lib/field-labelling.js +7 -6
  69. package/dist/lib/link-component.js +6 -0
  70. package/dist/lib/use-value-length.js +1 -0
  71. package/dist/types/components/ec/product-card.d.ts +12 -19
  72. package/dist/types/components/ec/review-card.d.ts +6 -1
  73. package/dist/types/components/foundations/button.d.ts +1 -1
  74. package/dist/types/components/foundations/chip-variants.d.ts +1 -1
  75. package/dist/types/components/foundations/data-table.d.ts +9 -1
  76. package/dist/types/components/foundations/pagination.d.ts +7 -1
  77. package/dist/types/components/foundations/sheet.d.ts +6 -1
  78. package/dist/types/components/foundations/social-icon.d.ts +1 -1
  79. package/dist/types/components/foundations/tabs.d.ts +2 -1
  80. package/dist/types/components/primitives/admin-side-nav.d.ts +3 -0
  81. package/dist/types/components/primitives/content-card.d.ts +67 -0
  82. package/dist/types/components/primitives/footer.d.ts +21 -1
  83. package/dist/types/components/primitives/header.d.ts +30 -2
  84. package/dist/types/components/primitives/menu-drawer.d.ts +7 -1
  85. package/dist/types/components/primitives/prose.d.ts +35 -0
  86. package/dist/types/components/primitives/search-bar.d.ts +14 -1
  87. package/dist/types/components/primitives/section-header.d.ts +2 -1
  88. package/dist/types/components/primitives/share-buttons.d.ts +26 -4
  89. package/dist/types/components/primitives/sub-nav.d.ts +16 -1
  90. package/dist/types/index.d.ts +7 -2
  91. package/dist/types/lib/link-component.d.ts +35 -0
  92. package/package.json +5 -4
  93. package/src/components/COMPONENT_LOOKUP.md +8 -6
  94. package/src/preset-standalone.css +3 -0
  95. package/src/preset.css +21 -3
  96. package/src/styles/semantic.css +11 -0
  97. package/templates/AGENTS.md +4 -2
  98. package/templates/AGENTS.stub.md +25 -0
  99. package/templates/CLAUDE.md +4 -2
  100. package/templates/CLAUDE.stub.md +25 -0
  101. package/tokens.json +17 -1
package/dist/index.js CHANGED
@@ -1,149 +1,150 @@
1
- "use client";
2
1
  /* empty css */
3
2
  import { cn as t } from "./lib/utils.js";
4
3
  import { FOCUS_RING as n, FOCUS_RING_INSET as i, FOCUS_RING_WITHIN as p } from "./lib/focus-ring.js";
5
- import { toast as l } from "sonner";
4
+ import { toast as m } from "sonner";
6
5
  import { Accordion as u, AccordionContent as f, AccordionItem as d, AccordionTrigger as g } from "./components/foundations/accordion.js";
7
- import { Alert as c, AlertDescription as s, AlertTitle as S } from "./components/foundations/alert.js";
8
- import { AlertDialog as D, AlertDialogAction as M, AlertDialogCancel as T, AlertDialogContent as I, AlertDialogDescription as v, AlertDialogFooter as h, AlertDialogHeader as F, AlertDialogOverlay as P, AlertDialogPortal as w, AlertDialogTitle as A, AlertDialogTrigger as B } from "./components/foundations/alert-dialog.js";
9
- import { AspectRatio as k } from "./components/foundations/aspect-ratio.js";
6
+ import { Alert as c, AlertDescription as s, AlertTitle as b } from "./components/foundations/alert.js";
7
+ import { AlertDialog as D, AlertDialogAction as T, AlertDialogCancel as M, AlertDialogContent as I, AlertDialogDescription as v, AlertDialogFooter as h, AlertDialogHeader as F, AlertDialogOverlay as P, AlertDialogPortal as w, AlertDialogTitle as A, AlertDialogTrigger as k } from "./components/foundations/alert-dialog.js";
8
+ import { AspectRatio as R } from "./components/foundations/aspect-ratio.js";
10
9
  import { Avatar as L, AvatarFallback as N, AvatarImage as G } from "./components/foundations/avatar.js";
11
- import { Badge as H, badgeVariants as O } from "./components/foundations/badge.js";
10
+ import { Badge as V, badgeVariants as O } from "./components/foundations/badge.js";
12
11
  import { Breadcrumb as U, BreadcrumbEllipsis as _, BreadcrumbItem as W, BreadcrumbLink as Q, BreadcrumbList as z, BreadcrumbPage as K, BreadcrumbSeparator as j } from "./components/foundations/breadcrumb.js";
13
12
  import { Button as J, buttonVariants as X } from "./components/foundations/button.js";
14
13
  import { Calendar as Z } from "./components/foundations/calendar.js";
15
- import { Card as oo, CardAction as eo, CardContent as ro, CardDescription as to, CardFooter as ao, CardHeader as no, CardTitle as io, cardVariants as po } from "./components/foundations/card.js";
16
- import { Checkbox as lo } from "./components/foundations/checkbox.js";
17
- import { CheckboxCardGroup as uo, CheckboxCardItem as fo } from "./components/foundations/checkbox-card.js";
18
- import { CheckboxGroup as Co, CheckboxGroupItem as co } from "./components/foundations/checkbox-group.js";
19
- import { Collapsible as So, CollapsibleContent as bo, CollapsibleTrigger as Do } from "./components/foundations/collapsible.js";
20
- import { Command as To, CommandDialog as Io, CommandEmpty as vo, CommandGroup as ho, CommandInput as Fo, CommandItem as Po, CommandList as wo, CommandSeparator as Ao, CommandShortcut as Bo } from "./components/foundations/command.js";
21
- import { ContextMenu as ko, ContextMenuCheckboxItem as yo, ContextMenuContent as Lo, ContextMenuGroup as No, ContextMenuItem as Go, ContextMenuLabel as Vo, ContextMenuPortal as Ho, ContextMenuRadioGroup as Oo, ContextMenuRadioItem as Eo, ContextMenuSeparator as Uo, ContextMenuShortcut as _o, ContextMenuSub as Wo, ContextMenuSubContent as Qo, ContextMenuSubTrigger as zo, ContextMenuTrigger as Ko } from "./components/foundations/context-menu.js";
22
- import { DataTable as qo } from "./components/foundations/data-table.js";
23
- import { Dialog as Xo, DialogClose as Yo, DialogContent as Zo, DialogDescription as $o, DialogFooter as oe, DialogHeader as ee, DialogOverlay as re, DialogPortal as te, DialogTitle as ae, DialogTrigger as ne } from "./components/foundations/dialog.js";
24
- import { Drawer as pe, DrawerClose as me, DrawerContent as le, DrawerDescription as xe, DrawerFooter as ue, DrawerHeader as fe, DrawerOverlay as de, DrawerPortal as ge, DrawerTitle as Ce, DrawerTrigger as ce } from "./components/foundations/drawer.js";
25
- import { DropdownMenu as Se, DropdownMenuCheckboxItem as be, DropdownMenuContent as De, DropdownMenuGroup as Me, DropdownMenuItem as Te, DropdownMenuLabel as Ie, DropdownMenuPortal as ve, DropdownMenuRadioGroup as he, DropdownMenuRadioItem as Fe, DropdownMenuSeparator as Pe, DropdownMenuShortcut as we, DropdownMenuSub as Ae, DropdownMenuSubContent as Be, DropdownMenuSubTrigger as Re, DropdownMenuTrigger as ke } from "./components/foundations/dropdown-menu.js";
26
- import { Field as Le, FieldDescription as Ne, FieldError as Ge, FieldGroup as Ve, FieldLabel as He, FieldLegend as Oe, FieldSeparator as Ee, FieldSet as Ue, fieldVariants as _e } from "./components/foundations/field.js";
27
- import { FileInput as Qe, formatFileNames as ze, validateFileSize as Ke } from "./components/foundations/file-input.js";
28
- import { Form as qe, FormControl as Je, FormDescription as Xe, FormField as Ye, FormItem as Ze, FormLabel as $e, FormMessage as or, useFormField as er } from "./components/foundations/form.js";
29
- import { HoverCard as tr, HoverCardContent as ar, HoverCardTrigger as nr } from "./components/foundations/hover-card.js";
30
- import { IconBadge as pr, iconBadgeVariants as mr } from "./components/foundations/icon-badge.js";
31
- import { Input as xr } from "./components/foundations/input.js";
32
- import { Label as fr } from "./components/foundations/label.js";
33
- import { Menubar as gr, MenubarCheckboxItem as Cr, MenubarContent as cr, MenubarGroup as sr, MenubarItem as Sr, MenubarLabel as br, MenubarMenu as Dr, MenubarPortal as Mr, MenubarRadioGroup as Tr, MenubarRadioItem as Ir, MenubarSeparator as vr, MenubarShortcut as hr, MenubarSub as Fr, MenubarSubContent as Pr, MenubarSubTrigger as wr, MenubarTrigger as Ar } from "./components/foundations/menubar.js";
34
- import { NavigationMenu as Rr, NavigationMenuContent as kr, NavigationMenuIndicator as yr, NavigationMenuItem as Lr, NavigationMenuLink as Nr, NavigationMenuList as Gr, NavigationMenuTrigger as Vr, NavigationMenuViewport as Hr, navigationMenuTriggerStyle as Or } from "./components/foundations/navigation-menu.js";
35
- import { Pagination as Ur, PaginationContent as _r, PaginationEllipsis as Wr, PaginationItem as Qr, PaginationLink as zr, PaginationNext as Kr, PaginationPrevious as jr } from "./components/foundations/pagination.js";
36
- import { getPaginationRange as Jr } from "./lib/pagination-range.js";
37
- import { Popover as Yr, PopoverAnchor as Zr, PopoverContent as $r, PopoverTrigger as ot } from "./components/foundations/popover.js";
38
- import { Progress as rt } from "./components/foundations/progress.js";
39
- import { ResponsiveDialog as at, ResponsiveDialogClose as nt, ResponsiveDialogContent as it, ResponsiveDialogDescription as pt, ResponsiveDialogFooter as mt, ResponsiveDialogHeader as lt, ResponsiveDialogTitle as xt, ResponsiveDialogTrigger as ut, useIsMobile as ft } from "./components/foundations/responsive-dialog.js";
40
- import { RadioGroup as gt, RadioGroupItem as Ct } from "./components/foundations/radio-group.js";
41
- import { ScrollArea as st, ScrollBar as St } from "./components/foundations/scroll-area.js";
42
- import { Select as Dt, SelectContent as Mt, SelectGroup as Tt, SelectItem as It, SelectLabel as vt, SelectScrollDownButton as ht, SelectScrollUpButton as Ft, SelectSeparator as Pt, SelectTrigger as wt, SelectValue as At } from "./components/foundations/select.js";
43
- import { Separator as Rt } from "./components/foundations/separator.js";
44
- import { Sheet as yt, SheetClose as Lt, SheetContent as Nt, SheetDescription as Gt, SheetFooter as Vt, SheetHeader as Ht, SheetTitle as Ot, SheetTrigger as Et } from "./components/foundations/sheet.js";
45
- import { Skeleton as _t } from "./components/foundations/skeleton.js";
46
- import { SkipLink as Qt } from "./components/foundations/skip-link.js";
47
- import { Slider as Kt } from "./components/foundations/slider.js";
48
- import { Spinner as qt } from "./components/foundations/spinner.js";
49
- import { SocialIcon as Xt } from "./components/foundations/social-icon.js";
50
- import { Switch as Zt } from "./components/foundations/switch.js";
51
- import { Table as oa, TableBody as ea, TableCaption as ra, TableCell as ta, TableFooter as aa, TableHead as na, TableHeader as ia, TableRow as pa } from "./components/foundations/table.js";
52
- import { Tabs as la, TabsContent as xa, TabsList as ua, TabsTrigger as fa } from "./components/foundations/tabs.js";
53
- import { Textarea as ga } from "./components/foundations/textarea.js";
54
- import { Toaster as ca } from "./components/foundations/sonner.js";
55
- import { Toggle as Sa, toggleVariants as ba } from "./components/foundations/toggle.js";
56
- import { ToggleGroup as Ma, ToggleGroupItem as Ta } from "./components/foundations/toggle-group.js";
57
- import { Tooltip as va, TooltipContent as ha, TooltipProvider as Fa, TooltipTrigger as Pa } from "./components/foundations/tooltip.js";
58
- import { AdminSideNav as Aa } from "./components/primitives/admin-side-nav.js";
59
- import { AdminHeader as Ra } from "./components/primitives/admin-header.js";
60
- import { CoachMark as ya } from "./components/primitives/coach-mark.js";
61
- import { Combobox as Na } from "./components/primitives/combobox.js";
62
- import { BannerCarousel as Va } from "./components/primitives/banner-carousel.js";
63
- import { ContentCarousel as Oa } from "./components/primitives/content-carousel.js";
64
- import { MultiSelect as Ua } from "./components/primitives/multi-select.js";
65
- import { StickyActionBar as Wa } from "./components/primitives/sticky-action-bar.js";
66
- import { BottomTabBar as za } from "./components/primitives/bottom-tab-bar.js";
67
- import { BulkActionBar as ja } from "./components/primitives/bulk-action-bar.js";
68
- import { CategoryShortcuts as Ja } from "./components/primitives/category-shortcuts.js";
69
- import { CategoryScroll as Ya } from "./components/primitives/category-scroll.js";
70
- import { ChatComposer as $a } from "./components/primitives/chat-composer.js";
71
- import { Chip as en } from "./components/primitives/chip.js";
72
- import { StandardPageShell as tn, StandardPageShell as an } from "./components/primitives/standard-page-shell.js";
73
- import { EmptyState as pn } from "./components/primitives/empty-state.js";
74
- import { DatePicker as ln, DateTimePicker as xn } from "./components/primitives/date-picker.js";
75
- import { ErrorState as fn, NotFoundIllustration as dn } from "./components/primitives/error-state.js";
76
- import { FilterBar as Cn } from "./components/primitives/filter-bar.js";
77
- import { Footer as sn } from "./components/primitives/footer.js";
78
- import { FormField as bn } from "./components/primitives/form-field.js";
79
- import { FunnelShell as Mn } from "./components/primitives/funnel-shell.js";
80
- import { Header as In } from "./components/primitives/header.js";
81
- import { ImageCarousel as hn } from "./components/primitives/image-carousel.js";
82
- import { ImageGallery as Pn } from "./components/primitives/image-gallery.js";
83
- import { ImageInput as An, imageInputPreviewVariants as Bn } from "./components/primitives/image-input.js";
84
- import { ImageUploader as kn } from "./components/primitives/image-uploader.js";
85
- import { KebabMenu as Ln } from "./components/primitives/kebab-menu.js";
86
- import { ListItem as Gn } from "./components/primitives/list-item.js";
87
- import { MenuDrawer as Hn } from "./components/primitives/menu-drawer.js";
88
- import { SubNav as En } from "./components/primitives/sub-nav.js";
89
- import { NotificationBadge as _n, notificationBadgeVariants as Wn } from "./components/primitives/notification-badge.js";
90
- import { NotificationList as zn } from "./components/primitives/notification-list.js";
91
- import { PriceDisplay as jn, priceDisplayVariants as qn } from "./components/primitives/price-display.js";
92
- import { ProgressSteps as Xn } from "./components/primitives/progress-steps.js";
93
- import { Timeline as Zn } from "./components/primitives/timeline.js";
94
- import { NumberInput as oi, QuantitySelector as ei } from "./components/primitives/number-input.js";
95
- import { SearchBar as ti } from "./components/primitives/search-bar.js";
96
- import { SearchPanel as ni } from "./components/primitives/search-panel.js";
97
- import { Container as pi, containerVariants as mi } from "./components/primitives/container.js";
98
- import { Section as xi, sectionScrimVariants as ui, sectionVariants as fi } from "./components/primitives/section.js";
99
- import { SectionHeader as gi } from "./components/primitives/section-header.js";
100
- import { SectionNav as ci } from "./components/primitives/section-nav.js";
101
- import { ShareButtons as Si } from "./components/primitives/share-buttons.js";
102
- import { SideNav as Di } from "./components/primitives/side-nav.js";
103
- import { SocialLoginButton as Ti } from "./components/primitives/social-login-button.js";
104
- import { StatusCountTabs as vi } from "./components/primitives/status-count-tabs.js";
105
- import { Tag as Fi, tagVariants as Pi } from "./components/primitives/tag.js";
106
- import { WorkspaceShell as Ai, WorkspaceShell as Bi } from "./components/primitives/workspace-shell.js";
107
- import { AdminShell as ki, AdminShell as yi, MissingComponent as Li } from "./components/ec/admin-shell.js";
108
- import { AnniversaryCard as Gi } from "./components/ec/anniversary-card.js";
109
- import { CakeLogo as Hi } from "./components/ec/cake-logo.js";
110
- import { ChartControls as Ei } from "./components/ec/chart-controls.js";
111
- import { CountdownTimer as _i } from "./components/ec/countdown-timer.js";
112
- import { CouponCard as Qi } from "./components/ec/coupon-card.js";
113
- import { DeliveryCalendar as Ki } from "./components/ec/delivery-calendar.js";
114
- import { mypageMenuGroups as qi } from "./components/ec/_mypage-menu-data.js";
115
- import { OrderSection as Xi } from "./components/ec/order-section.js";
116
- import { OrderSummary as Zi } from "./components/ec/order-summary.js";
117
- import { CreditCardIcon as op, PaymentMethodDisplay as ep } from "./components/ec/payment-method.js";
118
- import { ProductCard as tp } from "./components/ec/product-card.js";
119
- import { ProductCarousel as np } from "./components/ec/product-carousel.js";
120
- import { ProductCTA as pp } from "./components/ec/product-cta.js";
121
- import { ProductDetailBar as lp } from "./components/ec/product-detail-bar.js";
122
- import { ProductDetailSidebar as up } from "./components/ec/product-detail-sidebar.js";
123
- import { ProductListItem as dp } from "./components/ec/product-list-item.js";
124
- import { OptionImageUpload as Cp, OptionQuantity as cp, OptionSelect as sp, OptionText as Sp, ProductOption as bp } from "./components/ec/product-option.js";
125
- import { RatingStars as Mp, SparkleIcon as Tp } from "./components/ec/rating-stars.js";
126
- import { ReviewCard as vp } from "./components/ec/review-card.js";
127
- import { ReviewForm as Fp } from "./components/ec/review-form.js";
128
- import { ReviewItem as wp, ReviewSummary as Ap } from "./components/ec/review-summary.js";
129
- import { MypageShell as Rp } from "./components/ec/mypage-shell.js";
130
- import { ShopCard as yp } from "./components/ec/shop-card.js";
131
- import { StatCard as Np } from "./components/ec/stat-card.js";
132
- import { chipVariants as Vp } from "./components/foundations/chip-variants.js";
14
+ import { Card as ee, CardAction as oe, CardContent as re, CardDescription as te, CardFooter as ae, CardHeader as ne, CardTitle as ie, cardVariants as pe } from "./components/foundations/card.js";
15
+ import { Checkbox as me } from "./components/foundations/checkbox.js";
16
+ import { CheckboxCardGroup as ue, CheckboxCardItem as fe } from "./components/foundations/checkbox-card.js";
17
+ import { CheckboxGroup as ge, CheckboxGroupItem as Ce } from "./components/foundations/checkbox-group.js";
18
+ import { Collapsible as se, CollapsibleContent as be, CollapsibleTrigger as Se } from "./components/foundations/collapsible.js";
19
+ import { Command as Te, CommandDialog as Me, CommandEmpty as Ie, CommandGroup as ve, CommandInput as he, CommandItem as Fe, CommandList as Pe, CommandSeparator as we, CommandShortcut as Ae } from "./components/foundations/command.js";
20
+ import { ContextMenu as Be, ContextMenuCheckboxItem as Re, ContextMenuContent as ye, ContextMenuGroup as Le, ContextMenuItem as Ne, ContextMenuLabel as Ge, ContextMenuPortal as He, ContextMenuRadioGroup as Ve, ContextMenuRadioItem as Oe, ContextMenuSeparator as Ee, ContextMenuShortcut as Ue, ContextMenuSub as _e, ContextMenuSubContent as We, ContextMenuSubTrigger as Qe, ContextMenuTrigger as ze } from "./components/foundations/context-menu.js";
21
+ import { DataTable as je, DataTableActionCell as qe, DataTableAddRow as Je, DataTableAvatarCell as Xe, DataTableBody as Ye, DataTableBulkActions as Ze, DataTableCell as $e, DataTableCheckboxCell as eo, DataTableDragHandleCell as oo, DataTableEmptyState as ro, DataTableHead as to, DataTableHeader as ao, DataTableImageCell as no, DataTableInputCell as io, DataTableLinkCell as po, DataTableNumberCell as lo, DataTableRow as mo, DataTableSectionRow as xo, DataTableSelectCell as uo, DataTableTable as fo } from "./components/foundations/data-table.js";
22
+ import { Dialog as Co, DialogClose as co, DialogContent as so, DialogDescription as bo, DialogFooter as So, DialogHeader as Do, DialogOverlay as To, DialogPortal as Mo, DialogTitle as Io, DialogTrigger as vo } from "./components/foundations/dialog.js";
23
+ import { Drawer as Fo, DrawerClose as Po, DrawerContent as wo, DrawerDescription as Ao, DrawerFooter as ko, DrawerHeader as Bo, DrawerOverlay as Ro, DrawerPortal as yo, DrawerTitle as Lo, DrawerTrigger as No } from "./components/foundations/drawer.js";
24
+ import { DropdownMenu as Ho, DropdownMenuCheckboxItem as Vo, DropdownMenuContent as Oo, DropdownMenuGroup as Eo, DropdownMenuItem as Uo, DropdownMenuLabel as _o, DropdownMenuPortal as Wo, DropdownMenuRadioGroup as Qo, DropdownMenuRadioItem as zo, DropdownMenuSeparator as Ko, DropdownMenuShortcut as jo, DropdownMenuSub as qo, DropdownMenuSubContent as Jo, DropdownMenuSubTrigger as Xo, DropdownMenuTrigger as Yo } from "./components/foundations/dropdown-menu.js";
25
+ import { Field as $o, FieldDescription as er, FieldError as or, FieldGroup as rr, FieldLabel as tr, FieldLegend as ar, FieldSeparator as nr, FieldSet as ir, fieldVariants as pr } from "./components/foundations/field.js";
26
+ import { FileInput as mr, formatFileNames as xr, validateFileSize as ur } from "./components/foundations/file-input.js";
27
+ import { Form as dr, FormControl as gr, FormDescription as Cr, FormField as cr, FormItem as sr, FormLabel as br, FormMessage as Sr, useFormField as Dr } from "./components/foundations/form.js";
28
+ import { HoverCard as Mr, HoverCardContent as Ir, HoverCardTrigger as vr } from "./components/foundations/hover-card.js";
29
+ import { IconBadge as Fr, iconBadgeVariants as Pr } from "./components/foundations/icon-badge.js";
30
+ import { Input as Ar } from "./components/foundations/input.js";
31
+ import { Label as Br } from "./components/foundations/label.js";
32
+ import { Menubar as yr, MenubarCheckboxItem as Lr, MenubarContent as Nr, MenubarGroup as Gr, MenubarItem as Hr, MenubarLabel as Vr, MenubarMenu as Or, MenubarPortal as Er, MenubarRadioGroup as Ur, MenubarRadioItem as _r, MenubarSeparator as Wr, MenubarShortcut as Qr, MenubarSub as zr, MenubarSubContent as Kr, MenubarSubTrigger as jr, MenubarTrigger as qr } from "./components/foundations/menubar.js";
33
+ import { NavigationMenu as Xr, NavigationMenuContent as Yr, NavigationMenuIndicator as Zr, NavigationMenuItem as $r, NavigationMenuLink as et, NavigationMenuList as ot, NavigationMenuTrigger as rt, NavigationMenuViewport as tt, navigationMenuTriggerStyle as at } from "./components/foundations/navigation-menu.js";
34
+ import { Pagination as it, PaginationContent as pt, PaginationEllipsis as lt, PaginationItem as mt, PaginationLink as xt, PaginationNext as ut, PaginationPrevious as ft } from "./components/foundations/pagination.js";
35
+ import { getPaginationRange as gt } from "./lib/pagination-range.js";
36
+ import { Popover as ct, PopoverAnchor as st, PopoverContent as bt, PopoverTrigger as St } from "./components/foundations/popover.js";
37
+ import { Progress as Tt } from "./components/foundations/progress.js";
38
+ import { ResponsiveDialog as It, ResponsiveDialogClose as vt, ResponsiveDialogContent as ht, ResponsiveDialogDescription as Ft, ResponsiveDialogFooter as Pt, ResponsiveDialogHeader as wt, ResponsiveDialogTitle as At, ResponsiveDialogTrigger as kt, useIsMobile as Bt } from "./components/foundations/responsive-dialog.js";
39
+ import { RadioGroup as yt, RadioGroupItem as Lt } from "./components/foundations/radio-group.js";
40
+ import { ScrollArea as Gt, ScrollBar as Ht } from "./components/foundations/scroll-area.js";
41
+ import { Select as Ot, SelectContent as Et, SelectGroup as Ut, SelectItem as _t, SelectLabel as Wt, SelectScrollDownButton as Qt, SelectScrollUpButton as zt, SelectSeparator as Kt, SelectTrigger as jt, SelectValue as qt } from "./components/foundations/select.js";
42
+ import { Separator as Xt } from "./components/foundations/separator.js";
43
+ import { Sheet as Zt, SheetClose as $t, SheetContent as ea, SheetDescription as oa, SheetFooter as ra, SheetHeader as ta, SheetTitle as aa, SheetTrigger as na } from "./components/foundations/sheet.js";
44
+ import { Skeleton as pa } from "./components/foundations/skeleton.js";
45
+ import { SkipLink as ma } from "./components/foundations/skip-link.js";
46
+ import { Slider as ua } from "./components/foundations/slider.js";
47
+ import { Spinner as da } from "./components/foundations/spinner.js";
48
+ import { SocialIcon as Ca } from "./components/foundations/social-icon.js";
49
+ import { Switch as sa } from "./components/foundations/switch.js";
50
+ import { Table as Sa, TableBody as Da, TableCaption as Ta, TableCell as Ma, TableFooter as Ia, TableHead as va, TableHeader as ha, TableRow as Fa } from "./components/foundations/table.js";
51
+ import { Tabs as wa, TabsContent as Aa, TabsList as ka, TabsTrigger as Ba } from "./components/foundations/tabs.js";
52
+ import { Textarea as ya } from "./components/foundations/textarea.js";
53
+ import { Toaster as Na } from "./components/foundations/sonner.js";
54
+ import { Toggle as Ha, toggleVariants as Va } from "./components/foundations/toggle.js";
55
+ import { ToggleGroup as Ea, ToggleGroupItem as Ua } from "./components/foundations/toggle-group.js";
56
+ import { Tooltip as Wa, TooltipContent as Qa, TooltipProvider as za, TooltipTrigger as Ka } from "./components/foundations/tooltip.js";
57
+ import { AdminSideNav as qa } from "./components/primitives/admin-side-nav.js";
58
+ import { AdminHeader as Xa } from "./components/primitives/admin-header.js";
59
+ import { CoachMark as Za } from "./components/primitives/coach-mark.js";
60
+ import { Combobox as en } from "./components/primitives/combobox.js";
61
+ import { BannerCarousel as rn } from "./components/primitives/banner-carousel.js";
62
+ import { ContentCarousel as an } from "./components/primitives/content-carousel.js";
63
+ import { MultiSelect as pn } from "./components/primitives/multi-select.js";
64
+ import { StickyActionBar as mn } from "./components/primitives/sticky-action-bar.js";
65
+ import { BottomTabBar as un } from "./components/primitives/bottom-tab-bar.js";
66
+ import { BulkActionBar as dn } from "./components/primitives/bulk-action-bar.js";
67
+ import { CategoryShortcuts as Cn } from "./components/primitives/category-shortcuts.js";
68
+ import { CategoryScroll as sn } from "./components/primitives/category-scroll.js";
69
+ import { ChatComposer as Sn } from "./components/primitives/chat-composer.js";
70
+ import { Chip as Tn } from "./components/primitives/chip.js";
71
+ import { Prose as In } from "./components/primitives/prose.js";
72
+ import { ContentCard as hn, ContentList as Fn } from "./components/primitives/content-card.js";
73
+ import { StandardPageShell as wn, StandardPageShell as An } from "./components/primitives/standard-page-shell.js";
74
+ import { EmptyState as Bn } from "./components/primitives/empty-state.js";
75
+ import { DatePicker as yn, DateTimePicker as Ln } from "./components/primitives/date-picker.js";
76
+ import { ErrorState as Gn, NotFoundIllustration as Hn } from "./components/primitives/error-state.js";
77
+ import { FilterBar as On } from "./components/primitives/filter-bar.js";
78
+ import { Footer as Un } from "./components/primitives/footer.js";
79
+ import { FormField as Wn } from "./components/primitives/form-field.js";
80
+ import { FunnelShell as zn } from "./components/primitives/funnel-shell.js";
81
+ import { Header as jn } from "./components/primitives/header.js";
82
+ import { ImageCarousel as Jn } from "./components/primitives/image-carousel.js";
83
+ import { ImageGallery as Yn } from "./components/primitives/image-gallery.js";
84
+ import { ImageInput as $n, imageInputPreviewVariants as ei } from "./components/primitives/image-input.js";
85
+ import { ImageUploader as ri } from "./components/primitives/image-uploader.js";
86
+ import { KebabMenu as ai } from "./components/primitives/kebab-menu.js";
87
+ import { ListItem as ii } from "./components/primitives/list-item.js";
88
+ import { MenuDrawer as li } from "./components/primitives/menu-drawer.js";
89
+ import { SubNav as xi } from "./components/primitives/sub-nav.js";
90
+ import { NotificationBadge as fi, notificationBadgeVariants as di } from "./components/primitives/notification-badge.js";
91
+ import { NotificationList as Ci } from "./components/primitives/notification-list.js";
92
+ import { PriceDisplay as si, priceDisplayVariants as bi } from "./components/primitives/price-display.js";
93
+ import { ProgressSteps as Di } from "./components/primitives/progress-steps.js";
94
+ import { Timeline as Mi } from "./components/primitives/timeline.js";
95
+ import { NumberInput as vi, QuantitySelector as hi } from "./components/primitives/number-input.js";
96
+ import { SearchBar as Pi } from "./components/primitives/search-bar.js";
97
+ import { SearchPanel as Ai } from "./components/primitives/search-panel.js";
98
+ import { Container as Bi, containerVariants as Ri } from "./components/primitives/container.js";
99
+ import { Section as Li, sectionScrimVariants as Ni, sectionVariants as Gi } from "./components/primitives/section.js";
100
+ import { SectionHeader as Vi } from "./components/primitives/section-header.js";
101
+ import { SectionNav as Ei } from "./components/primitives/section-nav.js";
102
+ import { ShareButtons as _i } from "./components/primitives/share-buttons.js";
103
+ import { SideNav as Qi } from "./components/primitives/side-nav.js";
104
+ import { SocialLoginButton as Ki } from "./components/primitives/social-login-button.js";
105
+ import { StatusCountTabs as qi } from "./components/primitives/status-count-tabs.js";
106
+ import { Tag as Xi, tagVariants as Yi } from "./components/primitives/tag.js";
107
+ import { WorkspaceShell as $i, WorkspaceShell as ep } from "./components/primitives/workspace-shell.js";
108
+ import { AdminShell as rp, AdminShell as tp, MissingComponent as ap } from "./components/ec/admin-shell.js";
109
+ import { AnniversaryCard as ip } from "./components/ec/anniversary-card.js";
110
+ import { CakeLogo as lp } from "./components/ec/cake-logo.js";
111
+ import { ChartControls as xp } from "./components/ec/chart-controls.js";
112
+ import { CountdownTimer as fp } from "./components/ec/countdown-timer.js";
113
+ import { CouponCard as gp } from "./components/ec/coupon-card.js";
114
+ import { DeliveryCalendar as cp } from "./components/ec/delivery-calendar.js";
115
+ import { mypageMenuGroups as bp } from "./components/ec/_mypage-menu-data.js";
116
+ import { OrderSection as Dp } from "./components/ec/order-section.js";
117
+ import { OrderSummary as Mp } from "./components/ec/order-summary.js";
118
+ import { CreditCardIcon as vp, PaymentMethodDisplay as hp } from "./components/ec/payment-method.js";
119
+ import { BookmarkRibbonIcon as Pp, ProductCard as wp } from "./components/ec/product-card.js";
120
+ import { ProductCarousel as kp } from "./components/ec/product-carousel.js";
121
+ import { ProductCTA as Rp } from "./components/ec/product-cta.js";
122
+ import { ProductDetailBar as Lp } from "./components/ec/product-detail-bar.js";
123
+ import { ProductDetailSidebar as Gp } from "./components/ec/product-detail-sidebar.js";
124
+ import { ProductListItem as Vp } from "./components/ec/product-list-item.js";
125
+ import { OptionImageUpload as Ep, OptionQuantity as Up, OptionSelect as _p, OptionText as Wp, ProductOption as Qp } from "./components/ec/product-option.js";
126
+ import { RatingStars as Kp, SparkleIcon as jp } from "./components/ec/rating-stars.js";
127
+ import { ReviewCard as Jp } from "./components/ec/review-card.js";
128
+ import { ReviewForm as Yp } from "./components/ec/review-form.js";
129
+ import { ReviewItem as $p, ReviewSummary as el } from "./components/ec/review-summary.js";
130
+ import { MypageShell as rl } from "./components/ec/mypage-shell.js";
131
+ import { ShopCard as al } from "./components/ec/shop-card.js";
132
+ import { StatCard as il } from "./components/ec/stat-card.js";
133
+ import { chipVariants as ll } from "./components/foundations/chip-variants.js";
133
134
  export {
134
135
  u as Accordion,
135
136
  f as AccordionContent,
136
137
  d as AccordionItem,
137
138
  g as AccordionTrigger,
138
- Ra as AdminHeader,
139
- ki as AdminLayout,
140
- yi as AdminShell,
141
- Aa as AdminSideNav,
139
+ Xa as AdminHeader,
140
+ rp as AdminLayout,
141
+ tp as AdminShell,
142
+ qa as AdminSideNav,
142
143
  c as Alert,
143
144
  s as AlertDescription,
144
145
  D as AlertDialog,
145
- M as AlertDialogAction,
146
- T as AlertDialogCancel,
146
+ T as AlertDialogAction,
147
+ M as AlertDialogCancel,
147
148
  I as AlertDialogContent,
148
149
  v as AlertDialogDescription,
149
150
  h as AlertDialogFooter,
@@ -151,16 +152,17 @@ export {
151
152
  P as AlertDialogOverlay,
152
153
  w as AlertDialogPortal,
153
154
  A as AlertDialogTitle,
154
- B as AlertDialogTrigger,
155
- S as AlertTitle,
156
- Gi as AnniversaryCard,
157
- k as AspectRatio,
155
+ k as AlertDialogTrigger,
156
+ b as AlertTitle,
157
+ ip as AnniversaryCard,
158
+ R as AspectRatio,
158
159
  L as Avatar,
159
160
  N as AvatarFallback,
160
161
  G as AvatarImage,
161
- H as Badge,
162
- Va as BannerCarousel,
163
- za as BottomTabBar,
162
+ V as Badge,
163
+ rn as BannerCarousel,
164
+ Pp as BookmarkRibbonIcon,
165
+ un as BottomTabBar,
164
166
  U as Breadcrumb,
165
167
  _ as BreadcrumbEllipsis,
166
168
  W as BreadcrumbItem,
@@ -168,305 +170,327 @@ export {
168
170
  z as BreadcrumbList,
169
171
  K as BreadcrumbPage,
170
172
  j as BreadcrumbSeparator,
171
- ja as BulkActionBar,
173
+ dn as BulkActionBar,
172
174
  J as Button,
173
- bn as CakeFormField,
174
- Hi as CakeLogo,
175
+ Wn as CakeFormField,
176
+ lp as CakeLogo,
175
177
  Z as Calendar,
176
- oo as Card,
177
- eo as CardAction,
178
- ro as CardContent,
179
- to as CardDescription,
180
- ao as CardFooter,
181
- no as CardHeader,
182
- io as CardTitle,
183
- Ya as CategoryScroll,
184
- Ja as CategoryShortcuts,
185
- Ei as ChartControls,
186
- $a as ChatComposer,
187
- lo as Checkbox,
188
- uo as CheckboxCardGroup,
189
- fo as CheckboxCardItem,
190
- Co as CheckboxGroup,
191
- co as CheckboxGroupItem,
192
- en as Chip,
193
- ya as CoachMark,
194
- So as Collapsible,
195
- bo as CollapsibleContent,
196
- Do as CollapsibleTrigger,
197
- Na as Combobox,
198
- To as Command,
199
- Io as CommandDialog,
200
- vo as CommandEmpty,
201
- ho as CommandGroup,
202
- Fo as CommandInput,
203
- Po as CommandItem,
204
- wo as CommandList,
205
- Ao as CommandSeparator,
206
- Bo as CommandShortcut,
207
- pi as Container,
208
- Oa as ContentCarousel,
209
- ko as ContextMenu,
210
- yo as ContextMenuCheckboxItem,
211
- Lo as ContextMenuContent,
212
- No as ContextMenuGroup,
213
- Go as ContextMenuItem,
214
- Vo as ContextMenuLabel,
215
- Ho as ContextMenuPortal,
216
- Oo as ContextMenuRadioGroup,
217
- Eo as ContextMenuRadioItem,
218
- Uo as ContextMenuSeparator,
219
- _o as ContextMenuShortcut,
220
- Wo as ContextMenuSub,
221
- Qo as ContextMenuSubContent,
222
- zo as ContextMenuSubTrigger,
223
- Ko as ContextMenuTrigger,
224
- _i as CountdownTimer,
225
- Qi as CouponCard,
226
- op as CreditCardIcon,
227
- qo as DataTable,
228
- ln as DatePicker,
229
- xn as DateTimePicker,
230
- Ki as DeliveryCalendar,
231
- Xo as Dialog,
232
- Yo as DialogClose,
233
- Zo as DialogContent,
234
- $o as DialogDescription,
235
- oe as DialogFooter,
236
- ee as DialogHeader,
237
- re as DialogOverlay,
238
- te as DialogPortal,
239
- ae as DialogTitle,
240
- ne as DialogTrigger,
241
- pe as Drawer,
242
- me as DrawerClose,
243
- le as DrawerContent,
244
- xe as DrawerDescription,
245
- ue as DrawerFooter,
246
- fe as DrawerHeader,
247
- de as DrawerOverlay,
248
- ge as DrawerPortal,
249
- Ce as DrawerTitle,
250
- ce as DrawerTrigger,
251
- Se as DropdownMenu,
252
- be as DropdownMenuCheckboxItem,
253
- De as DropdownMenuContent,
254
- Me as DropdownMenuGroup,
255
- Te as DropdownMenuItem,
256
- Ie as DropdownMenuLabel,
257
- ve as DropdownMenuPortal,
258
- he as DropdownMenuRadioGroup,
259
- Fe as DropdownMenuRadioItem,
260
- Pe as DropdownMenuSeparator,
261
- we as DropdownMenuShortcut,
262
- Ae as DropdownMenuSub,
263
- Be as DropdownMenuSubContent,
264
- Re as DropdownMenuSubTrigger,
265
- ke as DropdownMenuTrigger,
266
- tn as EcPageShell,
267
- pn as EmptyState,
268
- fn as ErrorState,
178
+ ee as Card,
179
+ oe as CardAction,
180
+ re as CardContent,
181
+ te as CardDescription,
182
+ ae as CardFooter,
183
+ ne as CardHeader,
184
+ ie as CardTitle,
185
+ sn as CategoryScroll,
186
+ Cn as CategoryShortcuts,
187
+ xp as ChartControls,
188
+ Sn as ChatComposer,
189
+ me as Checkbox,
190
+ ue as CheckboxCardGroup,
191
+ fe as CheckboxCardItem,
192
+ ge as CheckboxGroup,
193
+ Ce as CheckboxGroupItem,
194
+ Tn as Chip,
195
+ Za as CoachMark,
196
+ se as Collapsible,
197
+ be as CollapsibleContent,
198
+ Se as CollapsibleTrigger,
199
+ en as Combobox,
200
+ Te as Command,
201
+ Me as CommandDialog,
202
+ Ie as CommandEmpty,
203
+ ve as CommandGroup,
204
+ he as CommandInput,
205
+ Fe as CommandItem,
206
+ Pe as CommandList,
207
+ we as CommandSeparator,
208
+ Ae as CommandShortcut,
209
+ Bi as Container,
210
+ hn as ContentCard,
211
+ an as ContentCarousel,
212
+ Fn as ContentList,
213
+ Be as ContextMenu,
214
+ Re as ContextMenuCheckboxItem,
215
+ ye as ContextMenuContent,
216
+ Le as ContextMenuGroup,
217
+ Ne as ContextMenuItem,
218
+ Ge as ContextMenuLabel,
219
+ He as ContextMenuPortal,
220
+ Ve as ContextMenuRadioGroup,
221
+ Oe as ContextMenuRadioItem,
222
+ Ee as ContextMenuSeparator,
223
+ Ue as ContextMenuShortcut,
224
+ _e as ContextMenuSub,
225
+ We as ContextMenuSubContent,
226
+ Qe as ContextMenuSubTrigger,
227
+ ze as ContextMenuTrigger,
228
+ fp as CountdownTimer,
229
+ gp as CouponCard,
230
+ vp as CreditCardIcon,
231
+ je as DataTable,
232
+ qe as DataTableActionCell,
233
+ Je as DataTableAddRow,
234
+ Xe as DataTableAvatarCell,
235
+ Ye as DataTableBody,
236
+ Ze as DataTableBulkActions,
237
+ $e as DataTableCell,
238
+ eo as DataTableCheckboxCell,
239
+ oo as DataTableDragHandleCell,
240
+ ro as DataTableEmptyState,
241
+ to as DataTableHead,
242
+ ao as DataTableHeader,
243
+ no as DataTableImageCell,
244
+ io as DataTableInputCell,
245
+ po as DataTableLinkCell,
246
+ lo as DataTableNumberCell,
247
+ mo as DataTableRow,
248
+ xo as DataTableSectionRow,
249
+ uo as DataTableSelectCell,
250
+ fo as DataTableTable,
251
+ yn as DatePicker,
252
+ Ln as DateTimePicker,
253
+ cp as DeliveryCalendar,
254
+ Co as Dialog,
255
+ co as DialogClose,
256
+ so as DialogContent,
257
+ bo as DialogDescription,
258
+ So as DialogFooter,
259
+ Do as DialogHeader,
260
+ To as DialogOverlay,
261
+ Mo as DialogPortal,
262
+ Io as DialogTitle,
263
+ vo as DialogTrigger,
264
+ Fo as Drawer,
265
+ Po as DrawerClose,
266
+ wo as DrawerContent,
267
+ Ao as DrawerDescription,
268
+ ko as DrawerFooter,
269
+ Bo as DrawerHeader,
270
+ Ro as DrawerOverlay,
271
+ yo as DrawerPortal,
272
+ Lo as DrawerTitle,
273
+ No as DrawerTrigger,
274
+ Ho as DropdownMenu,
275
+ Vo as DropdownMenuCheckboxItem,
276
+ Oo as DropdownMenuContent,
277
+ Eo as DropdownMenuGroup,
278
+ Uo as DropdownMenuItem,
279
+ _o as DropdownMenuLabel,
280
+ Wo as DropdownMenuPortal,
281
+ Qo as DropdownMenuRadioGroup,
282
+ zo as DropdownMenuRadioItem,
283
+ Ko as DropdownMenuSeparator,
284
+ jo as DropdownMenuShortcut,
285
+ qo as DropdownMenuSub,
286
+ Jo as DropdownMenuSubContent,
287
+ Xo as DropdownMenuSubTrigger,
288
+ Yo as DropdownMenuTrigger,
289
+ wn as EcPageShell,
290
+ Bn as EmptyState,
291
+ Gn as ErrorState,
269
292
  n as FOCUS_RING,
270
293
  i as FOCUS_RING_INSET,
271
294
  p as FOCUS_RING_WITHIN,
272
- Le as Field,
273
- Ne as FieldDescription,
274
- Ge as FieldError,
275
- Ve as FieldGroup,
276
- He as FieldLabel,
277
- Oe as FieldLegend,
278
- Ee as FieldSeparator,
279
- Ue as FieldSet,
280
- Qe as FileInput,
281
- Cn as FilterBar,
282
- sn as Footer,
283
- qe as Form,
284
- Je as FormControl,
285
- Xe as FormDescription,
286
- Ye as FormField,
287
- Ze as FormItem,
288
- $e as FormLabel,
289
- or as FormMessage,
290
- Mn as FunnelShell,
291
- In as Header,
292
- tr as HoverCard,
293
- ar as HoverCardContent,
294
- nr as HoverCardTrigger,
295
- pr as IconBadge,
296
- hn as ImageCarousel,
297
- Pn as ImageGallery,
298
- An as ImageInput,
299
- kn as ImageUploader,
300
- xr as Input,
301
- Ln as KebabMenu,
302
- fr as Label,
303
- Gn as ListItem,
304
- Hn as MenuDrawer,
305
- gr as Menubar,
306
- Cr as MenubarCheckboxItem,
307
- cr as MenubarContent,
308
- sr as MenubarGroup,
309
- Sr as MenubarItem,
310
- br as MenubarLabel,
311
- Dr as MenubarMenu,
312
- Mr as MenubarPortal,
313
- Tr as MenubarRadioGroup,
314
- Ir as MenubarRadioItem,
315
- vr as MenubarSeparator,
316
- hr as MenubarShortcut,
317
- Fr as MenubarSub,
318
- Pr as MenubarSubContent,
319
- wr as MenubarSubTrigger,
320
- Ar as MenubarTrigger,
321
- Li as MissingComponent,
322
- Ua as MultiSelect,
323
- Rp as MypageShell,
324
- Rr as NavigationMenu,
325
- kr as NavigationMenuContent,
326
- yr as NavigationMenuIndicator,
327
- Lr as NavigationMenuItem,
328
- Nr as NavigationMenuLink,
329
- Gr as NavigationMenuList,
330
- Vr as NavigationMenuTrigger,
331
- Hr as NavigationMenuViewport,
332
- dn as NotFoundIllustration,
333
- _n as NotificationBadge,
334
- zn as NotificationList,
335
- oi as NumberInput,
336
- Cp as OptionImageUpload,
337
- cp as OptionQuantity,
338
- sp as OptionSelect,
339
- Sp as OptionText,
340
- Xi as OrderSection,
341
- Zi as OrderSummary,
342
- Ur as Pagination,
343
- _r as PaginationContent,
344
- Wr as PaginationEllipsis,
345
- Qr as PaginationItem,
346
- zr as PaginationLink,
347
- Kr as PaginationNext,
348
- jr as PaginationPrevious,
349
- ep as PaymentMethodDisplay,
350
- Yr as Popover,
351
- Zr as PopoverAnchor,
352
- $r as PopoverContent,
353
- ot as PopoverTrigger,
354
- jn as PriceDisplay,
355
- pp as ProductCTA,
356
- tp as ProductCard,
357
- np as ProductCarousel,
358
- lp as ProductDetailBar,
359
- up as ProductDetailSidebar,
360
- dp as ProductListItem,
361
- bp as ProductOption,
362
- rt as Progress,
363
- Xn as ProgressSteps,
364
- ei as QuantitySelector,
365
- gt as RadioGroup,
366
- Ct as RadioGroupItem,
367
- Mp as RatingStars,
368
- at as ResponsiveDialog,
369
- nt as ResponsiveDialogClose,
370
- it as ResponsiveDialogContent,
371
- pt as ResponsiveDialogDescription,
372
- mt as ResponsiveDialogFooter,
373
- lt as ResponsiveDialogHeader,
374
- xt as ResponsiveDialogTitle,
375
- ut as ResponsiveDialogTrigger,
376
- vp as ReviewCard,
377
- Fp as ReviewForm,
378
- wp as ReviewItem,
379
- Ap as ReviewSummary,
380
- st as ScrollArea,
381
- St as ScrollBar,
382
- ti as SearchBar,
383
- ni as SearchPanel,
384
- xi as Section,
385
- gi as SectionHeader,
386
- ci as SectionNav,
387
- Dt as Select,
388
- Mt as SelectContent,
389
- Tt as SelectGroup,
390
- It as SelectItem,
391
- vt as SelectLabel,
392
- ht as SelectScrollDownButton,
393
- Ft as SelectScrollUpButton,
394
- Pt as SelectSeparator,
395
- wt as SelectTrigger,
396
- At as SelectValue,
397
- Rt as Separator,
398
- Si as ShareButtons,
399
- yt as Sheet,
400
- Lt as SheetClose,
401
- Nt as SheetContent,
402
- Gt as SheetDescription,
403
- Vt as SheetFooter,
404
- Ht as SheetHeader,
405
- Ot as SheetTitle,
406
- Et as SheetTrigger,
407
- yp as ShopCard,
408
- Di as SideNav,
409
- _t as Skeleton,
410
- Qt as SkipLink,
411
- Kt as Slider,
412
- Xt as SocialIcon,
413
- Ti as SocialLoginButton,
414
- Tp as SparkleIcon,
415
- qt as Spinner,
416
- an as StandardPageShell,
417
- Np as StatCard,
418
- vi as StatusCountTabs,
419
- Wa as StickyActionBar,
420
- En as SubNav,
421
- Zt as Switch,
422
- oa as Table,
423
- ea as TableBody,
424
- ra as TableCaption,
425
- ta as TableCell,
426
- aa as TableFooter,
427
- na as TableHead,
428
- ia as TableHeader,
429
- pa as TableRow,
430
- la as Tabs,
431
- xa as TabsContent,
432
- ua as TabsList,
433
- fa as TabsTrigger,
434
- Fi as Tag,
435
- ga as Textarea,
436
- Zn as Timeline,
437
- ca as Toaster,
438
- Sa as Toggle,
439
- Ma as ToggleGroup,
440
- Ta as ToggleGroupItem,
441
- va as Tooltip,
442
- ha as TooltipContent,
443
- Fa as TooltipProvider,
444
- Pa as TooltipTrigger,
445
- Ai as WorkspaceLayout,
446
- Bi as WorkspaceShell,
295
+ $o as Field,
296
+ er as FieldDescription,
297
+ or as FieldError,
298
+ rr as FieldGroup,
299
+ tr as FieldLabel,
300
+ ar as FieldLegend,
301
+ nr as FieldSeparator,
302
+ ir as FieldSet,
303
+ mr as FileInput,
304
+ On as FilterBar,
305
+ Un as Footer,
306
+ dr as Form,
307
+ gr as FormControl,
308
+ Cr as FormDescription,
309
+ cr as FormField,
310
+ sr as FormItem,
311
+ br as FormLabel,
312
+ Sr as FormMessage,
313
+ zn as FunnelShell,
314
+ jn as Header,
315
+ Mr as HoverCard,
316
+ Ir as HoverCardContent,
317
+ vr as HoverCardTrigger,
318
+ Fr as IconBadge,
319
+ Jn as ImageCarousel,
320
+ Yn as ImageGallery,
321
+ $n as ImageInput,
322
+ ri as ImageUploader,
323
+ Ar as Input,
324
+ ai as KebabMenu,
325
+ Br as Label,
326
+ ii as ListItem,
327
+ li as MenuDrawer,
328
+ yr as Menubar,
329
+ Lr as MenubarCheckboxItem,
330
+ Nr as MenubarContent,
331
+ Gr as MenubarGroup,
332
+ Hr as MenubarItem,
333
+ Vr as MenubarLabel,
334
+ Or as MenubarMenu,
335
+ Er as MenubarPortal,
336
+ Ur as MenubarRadioGroup,
337
+ _r as MenubarRadioItem,
338
+ Wr as MenubarSeparator,
339
+ Qr as MenubarShortcut,
340
+ zr as MenubarSub,
341
+ Kr as MenubarSubContent,
342
+ jr as MenubarSubTrigger,
343
+ qr as MenubarTrigger,
344
+ ap as MissingComponent,
345
+ pn as MultiSelect,
346
+ rl as MypageShell,
347
+ Xr as NavigationMenu,
348
+ Yr as NavigationMenuContent,
349
+ Zr as NavigationMenuIndicator,
350
+ $r as NavigationMenuItem,
351
+ et as NavigationMenuLink,
352
+ ot as NavigationMenuList,
353
+ rt as NavigationMenuTrigger,
354
+ tt as NavigationMenuViewport,
355
+ Hn as NotFoundIllustration,
356
+ fi as NotificationBadge,
357
+ Ci as NotificationList,
358
+ vi as NumberInput,
359
+ Ep as OptionImageUpload,
360
+ Up as OptionQuantity,
361
+ _p as OptionSelect,
362
+ Wp as OptionText,
363
+ Dp as OrderSection,
364
+ Mp as OrderSummary,
365
+ it as Pagination,
366
+ pt as PaginationContent,
367
+ lt as PaginationEllipsis,
368
+ mt as PaginationItem,
369
+ xt as PaginationLink,
370
+ ut as PaginationNext,
371
+ ft as PaginationPrevious,
372
+ hp as PaymentMethodDisplay,
373
+ ct as Popover,
374
+ st as PopoverAnchor,
375
+ bt as PopoverContent,
376
+ St as PopoverTrigger,
377
+ si as PriceDisplay,
378
+ Rp as ProductCTA,
379
+ wp as ProductCard,
380
+ kp as ProductCarousel,
381
+ Lp as ProductDetailBar,
382
+ Gp as ProductDetailSidebar,
383
+ Vp as ProductListItem,
384
+ Qp as ProductOption,
385
+ Tt as Progress,
386
+ Di as ProgressSteps,
387
+ In as Prose,
388
+ hi as QuantitySelector,
389
+ yt as RadioGroup,
390
+ Lt as RadioGroupItem,
391
+ Kp as RatingStars,
392
+ It as ResponsiveDialog,
393
+ vt as ResponsiveDialogClose,
394
+ ht as ResponsiveDialogContent,
395
+ Ft as ResponsiveDialogDescription,
396
+ Pt as ResponsiveDialogFooter,
397
+ wt as ResponsiveDialogHeader,
398
+ At as ResponsiveDialogTitle,
399
+ kt as ResponsiveDialogTrigger,
400
+ Jp as ReviewCard,
401
+ Yp as ReviewForm,
402
+ $p as ReviewItem,
403
+ el as ReviewSummary,
404
+ Gt as ScrollArea,
405
+ Ht as ScrollBar,
406
+ Pi as SearchBar,
407
+ Ai as SearchPanel,
408
+ Li as Section,
409
+ Vi as SectionHeader,
410
+ Ei as SectionNav,
411
+ Ot as Select,
412
+ Et as SelectContent,
413
+ Ut as SelectGroup,
414
+ _t as SelectItem,
415
+ Wt as SelectLabel,
416
+ Qt as SelectScrollDownButton,
417
+ zt as SelectScrollUpButton,
418
+ Kt as SelectSeparator,
419
+ jt as SelectTrigger,
420
+ qt as SelectValue,
421
+ Xt as Separator,
422
+ _i as ShareButtons,
423
+ Zt as Sheet,
424
+ $t as SheetClose,
425
+ ea as SheetContent,
426
+ oa as SheetDescription,
427
+ ra as SheetFooter,
428
+ ta as SheetHeader,
429
+ aa as SheetTitle,
430
+ na as SheetTrigger,
431
+ al as ShopCard,
432
+ Qi as SideNav,
433
+ pa as Skeleton,
434
+ ma as SkipLink,
435
+ ua as Slider,
436
+ Ca as SocialIcon,
437
+ Ki as SocialLoginButton,
438
+ jp as SparkleIcon,
439
+ da as Spinner,
440
+ An as StandardPageShell,
441
+ il as StatCard,
442
+ qi as StatusCountTabs,
443
+ mn as StickyActionBar,
444
+ xi as SubNav,
445
+ sa as Switch,
446
+ Sa as Table,
447
+ Da as TableBody,
448
+ Ta as TableCaption,
449
+ Ma as TableCell,
450
+ Ia as TableFooter,
451
+ va as TableHead,
452
+ ha as TableHeader,
453
+ Fa as TableRow,
454
+ wa as Tabs,
455
+ Aa as TabsContent,
456
+ ka as TabsList,
457
+ Ba as TabsTrigger,
458
+ Xi as Tag,
459
+ ya as Textarea,
460
+ Mi as Timeline,
461
+ Na as Toaster,
462
+ Ha as Toggle,
463
+ Ea as ToggleGroup,
464
+ Ua as ToggleGroupItem,
465
+ Wa as Tooltip,
466
+ Qa as TooltipContent,
467
+ za as TooltipProvider,
468
+ Ka as TooltipTrigger,
469
+ $i as WorkspaceLayout,
470
+ ep as WorkspaceShell,
447
471
  O as badgeVariants,
448
472
  X as buttonVariants,
449
- po as cardVariants,
450
- Vp as chipVariants,
473
+ pe as cardVariants,
474
+ ll as chipVariants,
451
475
  t as cn,
452
- mi as containerVariants,
453
- _e as fieldVariants,
454
- ze as formatFileNames,
455
- Jr as getPaginationRange,
456
- mr as iconBadgeVariants,
457
- Bn as imageInputPreviewVariants,
458
- qi as mypageMenuGroups,
459
- Or as navigationMenuTriggerStyle,
460
- Wn as notificationBadgeVariants,
461
- qn as priceDisplayVariants,
462
- ui as sectionScrimVariants,
463
- fi as sectionVariants,
464
- Pi as tagVariants,
465
- l as toast,
466
- ba as toggleVariants,
467
- er as useFormField,
468
- ft as useIsMobile,
469
- Ke as validateFileSize
476
+ Ri as containerVariants,
477
+ pr as fieldVariants,
478
+ xr as formatFileNames,
479
+ gt as getPaginationRange,
480
+ Pr as iconBadgeVariants,
481
+ ei as imageInputPreviewVariants,
482
+ bp as mypageMenuGroups,
483
+ at as navigationMenuTriggerStyle,
484
+ di as notificationBadgeVariants,
485
+ bi as priceDisplayVariants,
486
+ Ni as sectionScrimVariants,
487
+ Gi as sectionVariants,
488
+ Yi as tagVariants,
489
+ m as toast,
490
+ Va as toggleVariants,
491
+ Dr as useFormField,
492
+ Bt as useIsMobile,
493
+ ur as validateFileSize
470
494
  };
471
495
 
472
496
 
@@ -656,6 +680,8 @@ export {
656
680
  // ]
657
681
  //
658
682
  // src/components/ec/admin-shell.tsx
683
+ // "use client"
684
+ //
659
685
  // /**
660
686
  // * AdminShell — 管理画面の共通レイアウト
661
687
  // *
@@ -2359,7 +2385,8 @@ export {
2359
2385
  // <div
2360
2386
  // data-slot="order-summary"
2361
2387
  // className={cn(
2362
- // "fixed inset-x-0 bottom-[52px] z-[var(--Z-Sticky)] mx-auto max-w-[430px] border-t border-[var(--Border-Low-Emphasis)] bg-[var(--Surface-Primary)]",
2388
+ // // fixed 表示はスクロール内容の上に重なるため地は Surface-Elevated(disableFixed 側はページ内フローなので Surface-Primary のまま)
2389
+ // "fixed inset-x-0 bottom-[52px] z-[var(--Z-Sticky)] mx-auto max-w-[430px] border-t border-[var(--Border-Low-Emphasis)] bg-[var(--Surface-Elevated)]",
2363
2390
  // className
2364
2391
  // )}
2365
2392
  // {...props}
@@ -2557,6 +2584,17 @@ export {
2557
2584
  // reviewCount?: number
2558
2585
  // /** ショップ名 */
2559
2586
  // shopName?: string
2587
+ // /**
2588
+ // * ホバー時の画像演出。
2589
+ // * - `zoom` : 画像をわずかに拡大
2590
+ // * - `fade` : 拡大せず画像をわずかに明るくする(本番 EC 準拠)
2591
+ // * - `none` : 演出なし
2592
+ // *
2593
+ // * 未指定時の既定は orientation で変わる(従来の見た目を維持するため):
2594
+ // * `vertical` = `zoom` / `horizontal` = `none`。明示指定すればどちらの
2595
+ // * orientation でも同じように効く。
2596
+ // */
2597
+ // hoverEffect?: "zoom" | "fade" | "none"
2560
2598
  // /** ショップページURL(指定するとショップ名がリンク化、hover時アンダーライン) */
2561
2599
  // shopHref?: string
2562
2600
  // /** タグリスト(配送方法・キャンペーンなど) */
@@ -2753,6 +2791,18 @@ export {
2753
2791
  // * - `showCartButton` で「カートに追加」ボタン表示(verticalのみ)
2754
2792
  // * - ランキングバッジ、お気に入り、割引バッジなどEC必須要素を統合提供
2755
2793
  // */
2794
+ // /**
2795
+ // * hoverEffect ごとの画像クラス(拡大 / 明るく / なし)
2796
+ // *
2797
+ // * fade は opacity ではなく brightness を使う。opacity は背景(--Surface-Primary)と
2798
+ // * 合成されるだけなので、暗テーマでは「明るく」ではなく暗くなってしまう。
2799
+ // */
2800
+ // function hoverEffectImageClass(effect: "zoom" | "fade" | "none") {
2801
+ // if (effect === "none") return undefined
2802
+ // if (effect === "fade") return "transition-[filter] group-hover:brightness-110"
2803
+ // return "transition-transform group-hover:scale-105"
2804
+ // }
2805
+ //
2756
2806
  // function ProductCard({
2757
2807
  // className,
2758
2808
  // name,
@@ -2765,6 +2815,7 @@ export {
2765
2815
  // reviewCount,
2766
2816
  // shopName,
2767
2817
  // shopHref,
2818
+ // hoverEffect,
2768
2819
  // tags = [],
2769
2820
  // isFavorite = false,
2770
2821
  // onFavoriteToggle,
@@ -2779,6 +2830,9 @@ export {
2779
2830
  // cartButtonLabel = "カートに追加",
2780
2831
  // ...props
2781
2832
  // }: ProductCardProps) {
2833
+ // // 既定は orientation ごと(vertical=zoom / horizontal=none)。従来の見た目を変えない。
2834
+ // const resolvedHoverEffect =
2835
+ // hoverEffect ?? (orientation === "horizontal" ? "none" : "zoom")
2782
2836
  // const discountText = showDiscountBadge ? calcDiscountPercent(price, originalPrice) : null
2783
2837
  //
2784
2838
  // if (orientation === "horizontal") {
@@ -2799,7 +2853,7 @@ export {
2799
2853
  // {/* ランキングバッジ: カードレベルに配置(画像の overflow-hidden の外) */}
2800
2854
  // {ranking != null && <RankingBadge rank={ranking} />}
2801
2855
  // <div className="relative h-auto w-28 shrink-0 overflow-hidden rounded-lg @sm:w-36">
2802
- // <img src={imageUrl} alt={imageAlt ?? name} className="h-full w-full object-cover" loading="lazy" />
2856
+ // <img src={imageUrl} alt={imageAlt ?? name} className={cn("h-full w-full object-cover duration-[var(--Motion-Duration-Base)]", hoverEffectImageClass(resolvedHoverEffect))} loading="lazy" />
2803
2857
  // {discountText && (
2804
2858
  // <Tag variant="sale" size="sm" className="absolute bottom-1.5 left-1.5 z-[var(--Z-Local-2)]">{discountText}</Tag>
2805
2859
  // )}
@@ -2861,7 +2915,7 @@ export {
2861
2915
  // {/* 画像エリア: Figma — aspect-square, rounded-lg, p-1, 内部にタグ+ブックマーク */}
2862
2916
  // <div className="relative">
2863
2917
  // <div className="aspect-square overflow-hidden rounded-lg">
2864
- // <img src={imageUrl} alt={imageAlt ?? name} className="h-full w-full object-cover transition-transform duration-[var(--Motion-Duration-Base)] group-hover:scale-105" loading="lazy" />
2918
+ // <img src={imageUrl} alt={imageAlt ?? name} className={cn("h-full w-full object-cover duration-[var(--Motion-Duration-Base)]", hoverEffectImageClass(resolvedHoverEffect))} loading="lazy" />
2865
2919
  //
2866
2920
  // {/* 画像内オーバーレイ: 左下にタグ・割引 */}
2867
2921
  // <div className="absolute inset-x-1 bottom-1 z-[var(--Z-Local-3)] flex items-end">
@@ -4375,6 +4429,8 @@ export {
4375
4429
  // export { ProductListItem }
4376
4430
  //
4377
4431
  // src/components/ec/product-option.tsx
4432
+ // "use client"
4433
+ //
4378
4434
  // import * as React from "react"
4379
4435
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
4380
4436
  // import Add from "iconsax-reactjs/dist/esm/Add.js"
@@ -4757,6 +4813,11 @@ export {
4757
4813
  // export interface ReviewCardProps extends React.HTMLAttributes<HTMLDivElement> {
4758
4814
  // /** レビューバリアント */
4759
4815
  // variant?: "list" | "card" | "pc"
4816
+ // /**
4817
+ // * 枠線を出すか(既定 true)。
4818
+ // * 商品詳細などページ全体をフラットに統一する画面では false にする。
4819
+ // */
4820
+ // bordered?: boolean
4760
4821
  // /** 星評価(1〜5) */
4761
4822
  // rating: number
4762
4823
  // /** 投稿日 */
@@ -4799,6 +4860,7 @@ export {
4799
4860
  // function ReviewCard({
4800
4861
  // className,
4801
4862
  // variant = "list",
4863
+ // bordered = true,
4802
4864
  // rating,
4803
4865
  // date,
4804
4866
  // text,
@@ -4825,7 +4887,8 @@ export {
4825
4887
  // <div
4826
4888
  // data-slot="review-card"
4827
4889
  // className={cn(
4828
- // "flex flex-col rounded-lg border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Primary)]",
4890
+ // "flex flex-col rounded-lg bg-[var(--Surface-Primary)]",
4891
+ // bordered && "border border-[var(--Border-Medium-Emphasis)]",
4829
4892
  // isPc ? "w-full max-w-[680px] gap-4 p-6" : "min-w-[240px] w-full gap-2 p-4",
4830
4893
  // isCard && "items-center",
4831
4894
  // className
@@ -4935,6 +4998,8 @@ export {
4935
4998
  // export { ReviewCard }
4936
4999
  //
4937
5000
  // src/components/ec/review-form.tsx
5001
+ // "use client"
5002
+ //
4938
5003
  // import * as React from "react"
4939
5004
  // import Camera from "iconsax-reactjs/dist/esm/Camera.js"
4940
5005
  // import { X } from "lucide-react"
@@ -5884,7 +5949,7 @@ export {
5884
5949
  // // 画面端との余白は上下左右 40px(calc(100%-5rem))。
5885
5950
  // // 幅上限は端末幅に応じて: SP は端末幅-80px に追従 / sm 以上は
5886
5951
  // // default=480px(テキスト確認が間延びしない幅)・sm=320px
5887
- // "group/alert-dialog-content fixed top-[50%] left-[50%] z-[var(--Z-Modal)] grid w-full max-w-[calc(100%-5rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border border-[var(--Border-Medium-Emphasis)] bg-background p-6 shadow-lg duration-[var(--Motion-Duration-Base)] data-[size=sm]:max-w-xs data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[size=default]:sm:max-w-[480px]",
5952
+ // "group/alert-dialog-content fixed top-[50%] left-[50%] z-[var(--Z-Modal)] grid w-full max-w-[calc(100%-5rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Elevated)] p-6 shadow-lg duration-[var(--Motion-Duration-Base)] data-[size=sm]:max-w-xs data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[size=default]:sm:max-w-[480px]",
5888
5953
  // className
5889
5954
  // )}
5890
5955
  // {...props}
@@ -6024,6 +6089,8 @@ export {
6024
6089
  // }
6025
6090
  //
6026
6091
  // src/components/foundations/alert.tsx
6092
+ // "use client"
6093
+ //
6027
6094
  // import * as React from "react"
6028
6095
  // import { cva, type VariantProps } from "class-variance-authority"
6029
6096
  // import Warning2 from "iconsax-reactjs/dist/esm/Warning2.js"
@@ -6741,6 +6808,12 @@ export {
6741
6808
  // "icon-xs": "size-6 rounded [&_svg:not([class*='size-'])]:size-3",
6742
6809
  // "icon-sm": "size-8 rounded-lg",
6743
6810
  // "icon-lg": "size-10 rounded-lg",
6811
+ // /**
6812
+ // * icon-xl — 44px(size-11)。size="default" と同じ高さなので、
6813
+ // * 入力行(Input / SearchBar / SelectTrigger)の横にアイコンボタンを並置しても揃う。
6814
+ // * tokens.json の touchTarget["text-input"].min = 44px も満たす唯一の icon サイズ。
6815
+ // */
6816
+ // "icon-xl": "size-11 rounded-lg",
6744
6817
  // },
6745
6818
  // },
6746
6819
  // defaultVariants: {
@@ -6777,6 +6850,8 @@ export {
6777
6850
  // export { Button, buttonVariants }
6778
6851
  //
6779
6852
  // src/components/foundations/calendar.tsx
6853
+ // "use client"
6854
+ //
6780
6855
  // import * as React from "react"
6781
6856
  // import {
6782
6857
  // ChevronDownIcon,
@@ -7284,6 +7359,8 @@ export {
7284
7359
  // export { CheckboxCardGroup, CheckboxCardItem }
7285
7360
  //
7286
7361
  // src/components/foundations/checkbox-group.tsx
7362
+ // "use client"
7363
+ //
7287
7364
  // /**
7288
7365
  // * ## CheckboxGroup / チェックボックスグループ
7289
7366
  // *
@@ -7456,6 +7533,8 @@ export {
7456
7533
  // export { CheckboxGroup, CheckboxGroupItem }
7457
7534
  //
7458
7535
  // src/components/foundations/checkbox.tsx
7536
+ // "use client"
7537
+ //
7459
7538
  // import * as React from "react"
7460
7539
  // import TickSquare from "iconsax-reactjs/dist/esm/TickSquare.js"
7461
7540
  // import MinusSquare from "iconsax-reactjs/dist/esm/MinusSquare.js"
@@ -8154,6 +8233,7 @@ export {
8154
8233
  // import ExportSquare from "iconsax-reactjs/dist/esm/ExportSquare.js"
8155
8234
  //
8156
8235
  // import { cn } from "@/lib/utils"
8236
+ // import { FOCUS_RING } from "@/lib/focus-ring"
8157
8237
  // import { Checkbox } from "@/components/foundations/checkbox"
8158
8238
  // import { Button } from "@/components/foundations/button"
8159
8239
  // import { Avatar, AvatarImage, AvatarFallback } from "@/components/foundations/avatar"
@@ -8263,6 +8343,7 @@ export {
8263
8343
  // sortDirection,
8264
8344
  // onSort,
8265
8345
  // width,
8346
+ // srLabel,
8266
8347
  // children,
8267
8348
  // ...props
8268
8349
  // }: React.ComponentProps<"th"> & {
@@ -8271,8 +8352,19 @@ export {
8271
8352
  // onSort?: () => void
8272
8353
  // /** セル幅バリアント: max=320-360px, hug=最小 */
8273
8354
  // width?: "auto" | "max" | "hug"
8355
+ // /**
8356
+ // * 見出し文字を出さない列(チェックボックス選択列・操作列など)の読み上げ用ラベル。
8357
+ // * 画面には出さず、スクリーンリーダーにだけ列の意味を伝える。
8358
+ // *
8359
+ // * 空の `<th>` は「この列が何か」が支援技術に伝わらない(axe: empty-table-header)。
8360
+ // * 見出しを出したくない列には必ず指定する。
8361
+ // */
8362
+ // srLabel?: string
8274
8363
  // }) {
8275
8364
  // const SortIcon = sortDirection === "asc" ? ArrowUp : sortDirection === "desc" ? ArrowDown : ArrowSwapVertical
8365
+ // /** 未ソート列も "none" を明示する(列が並び替え可能であること自体を読み上げる) */
8366
+ // const ariaSort: React.AriaAttributes["aria-sort"] =
8367
+ // sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none"
8276
8368
  //
8277
8369
  // return (
8278
8370
  // <th
@@ -8280,22 +8372,40 @@ export {
8280
8372
  // className={cn(
8281
8373
  // "h-16 px-4 text-left align-middle typo-label-sm whitespace-nowrap text-[var(--Text-Medium-Emphasis)]",
8282
8374
  // "[&:has([role=checkbox])]:w-12 [&:has([role=checkbox])]:pr-0",
8283
- // sortable && "cursor-pointer select-none hover:bg-[var(--Surface-Tertiary)]",
8375
+ // sortable && "hover:bg-[var(--Surface-Tertiary)]",
8284
8376
  // width === "max" && "min-w-[320px] max-w-[360px]",
8285
8377
  // width === "hug" && "min-w-0 w-0",
8286
8378
  // className
8287
8379
  // )}
8288
- // onClick={sortable ? onSort : undefined}
8380
+ // // 並び替えの状態は aria-sort で読み上げる。押下は下の <button> が担う
8381
+ // aria-sort={sortable ? ariaSort : undefined}
8289
8382
  // {...props}
8290
8383
  // >
8291
8384
  // {sortable ? (
8292
- // <span className={cn("inline-flex items-center gap-1", sortDirection && "typo-label-sm font-bold text-[var(--Text-High-Emphasis)]")}>
8385
+ // // th の onClick はマウスにしか届かない(キーボードで到達できず role も無い)。
8386
+ // // 本物の <button> にして Tab / Enter / Space で並び替えられるようにする。
8387
+ // <button
8388
+ // type="button"
8389
+ // onClick={onSort}
8390
+ // className={cn(
8391
+ // "inline-flex items-center gap-1 rounded-sm outline-none",
8392
+ // "cursor-pointer select-none",
8393
+ // FOCUS_RING,
8394
+ // sortDirection && "typo-label-sm font-bold text-[var(--Text-High-Emphasis)]"
8395
+ // )}
8396
+ // >
8293
8397
  // {children}
8294
- // <SortIcon size={14} className={cn(sortDirection ? "text-[var(--Text-High-Emphasis)]" : "text-[var(--Text-Low-Emphasis)]")} />
8295
- // </span>
8398
+ // <SortIcon
8399
+ // size={14}
8400
+ // aria-hidden="true"
8401
+ // className={cn(sortDirection ? "text-[var(--Text-High-Emphasis)]" : "text-[var(--Text-Low-Emphasis)]")}
8402
+ // />
8403
+ // </button>
8296
8404
  // ) : (
8297
8405
  // children
8298
8406
  // )}
8407
+ // {/* 見出し文字を出さない列は、読み上げ用のラベルだけ置く */}
8408
+ // {srLabel && <span className="sr-only">{srLabel}</span>}
8299
8409
  // </th>
8300
8410
  // )
8301
8411
  // }
@@ -8904,7 +9014,7 @@ export {
8904
9014
  // data-slot="dialog-content"
8905
9015
  // onOpenAutoFocus={(e) => e.preventDefault()}
8906
9016
  // className={cn(
8907
- // "fixed top-[50%] left-[50%] z-[var(--Z-Modal)] grid w-[calc(100%_-_32px)] max-w-[calc(100%_-_32px)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl bg-background dark:bg-[var(--Primitive-Gray-800)] p-6 shadow-lg duration-[var(--Motion-Duration-Base)] outline-none focus-visible:ring-2 focus-visible:ring-[var(--Focus-High-Emphasis)] data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
9017
+ // "fixed top-[50%] left-[50%] z-[var(--Z-Modal)] grid w-[calc(100%_-_32px)] max-w-[calc(100%_-_32px)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl bg-[var(--Surface-Elevated)] p-6 shadow-lg duration-[var(--Motion-Duration-Base)] outline-none focus-visible:ring-2 focus-visible:ring-[var(--Focus-High-Emphasis)] data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
8908
9018
  // className
8909
9019
  // )}
8910
9020
  // {...props}
@@ -9059,7 +9169,7 @@ export {
9059
9169
  // <DrawerPrimitive.Content
9060
9170
  // data-slot="drawer-content"
9061
9171
  // className={cn(
9062
- // "group/drawer-content fixed z-[var(--Z-Modal)] flex h-auto flex-col border-[var(--Border-Medium-Emphasis)] bg-background",
9172
+ // "group/drawer-content fixed z-[var(--Z-Modal)] flex h-auto flex-col border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Elevated)]",
9063
9173
  // "data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-lg data-[vaul-drawer-direction=top]:border-b",
9064
9174
  // "data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-lg data-[vaul-drawer-direction=bottom]:border-t",
9065
9175
  // "data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=right]:sm:max-w-sm",
@@ -9624,6 +9734,8 @@ export {
9624
9734
  // VariantProps<typeof fieldVariants>
9625
9735
  //
9626
9736
  // src/components/foundations/file-input.tsx
9737
+ // "use client"
9738
+ //
9627
9739
  // import * as React from "react"
9628
9740
  // import { Paperclip, X } from "lucide-react"
9629
9741
  //
@@ -10697,6 +10809,7 @@ export {
10697
10809
  // } from "lucide-react"
10698
10810
  //
10699
10811
  // import { cn } from "@/lib/utils"
10812
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
10700
10813
  // import { buttonVariants, type Button } from "@/components/foundations/button"
10701
10814
  //
10702
10815
  // function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
@@ -10730,6 +10843,11 @@ export {
10730
10843
  //
10731
10844
  // type PaginationLinkProps = {
10732
10845
  // isActive?: boolean
10846
+ // /**
10847
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
10848
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
10849
+ // */
10850
+ // linkComponent?: LinkComponent
10733
10851
  // } & Pick<React.ComponentProps<typeof Button>, "size"> &
10734
10852
  // React.ComponentProps<"a">
10735
10853
  //
@@ -10737,10 +10855,12 @@ export {
10737
10855
  // className,
10738
10856
  // isActive,
10739
10857
  // size = "icon",
10858
+ // linkComponent,
10740
10859
  // ...props
10741
10860
  // }: PaginationLinkProps) {
10861
+ // const LinkTag = resolveLinkComponent(linkComponent)
10742
10862
  // return (
10743
- // <a
10863
+ // <LinkTag
10744
10864
  // aria-current={isActive ? "page" : undefined}
10745
10865
  // data-slot="pagination-link"
10746
10866
  // data-active={isActive}
@@ -10948,6 +11068,8 @@ export {
10948
11068
  // export { Progress }
10949
11069
  //
10950
11070
  // src/components/foundations/radio-group.tsx
11071
+ // "use client"
11072
+ //
10951
11073
  // import * as React from "react"
10952
11074
  // import { RadioGroup as RadioGroupPrimitive } from "radix-ui"
10953
11075
  //
@@ -11111,6 +11233,8 @@ export {
11111
11233
  // export { RadioGroup, RadioGroupItem }
11112
11234
  //
11113
11235
  // src/components/foundations/responsive-dialog.tsx
11236
+ // "use client"
11237
+ //
11114
11238
  // import * as React from "react"
11115
11239
  //
11116
11240
  // import { cn } from "@/lib/utils"
@@ -11671,20 +11795,34 @@ export {
11671
11795
  // children,
11672
11796
  // side = "right",
11673
11797
  // showCloseButton = true,
11798
+ // autoFocus = true,
11799
+ // onOpenAutoFocus,
11800
+ // onCloseAutoFocus,
11674
11801
  // ...props
11675
11802
  // }: React.ComponentProps<typeof SheetPrimitive.Content> & {
11676
11803
  // side?: "top" | "right" | "bottom" | "left"
11677
11804
  // showCloseButton?: boolean
11805
+ // /**
11806
+ // * 開閉時のフォーカス自動移動。既定 true(Radix 既定=開いたら中へ入り、閉じたらトリガーへ戻る)。
11807
+ // * WCAG 2.4.3 を満たすため、止めたい特別な事情があるときだけ false にする。
11808
+ // */
11809
+ // autoFocus?: boolean
11678
11810
  // }) {
11679
11811
  // return (
11680
11812
  // <SheetPortal>
11681
11813
  // <SheetOverlay />
11682
11814
  // <SheetPrimitive.Content
11683
11815
  // data-slot="sheet-content"
11684
- // onOpenAutoFocus={(e) => e.preventDefault()}
11685
- // onCloseAutoFocus={(e) => e.preventDefault()}
11816
+ // onOpenAutoFocus={(e) => {
11817
+ // if (!autoFocus) e.preventDefault()
11818
+ // onOpenAutoFocus?.(e)
11819
+ // }}
11820
+ // onCloseAutoFocus={(e) => {
11821
+ // if (!autoFocus) e.preventDefault()
11822
+ // onCloseAutoFocus?.(e)
11823
+ // }}
11686
11824
  // className={cn(
11687
- // "fixed z-[var(--Z-Modal)] flex flex-col gap-4 border-[var(--Border-Medium-Emphasis)] bg-background shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-[var(--Motion-Duration-Slow)] data-[state=open]:animate-in data-[state=open]:duration-[var(--Motion-Duration-Slower)]",
11825
+ // "fixed z-[var(--Z-Modal)] flex flex-col gap-4 border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Elevated)] shadow-lg transition ease-in-out data-[state=closed]:animate-out data-[state=closed]:duration-[var(--Motion-Duration-Slow)] data-[state=open]:animate-in data-[state=open]:duration-[var(--Motion-Duration-Slower)]",
11688
11826
  // side === "right" &&
11689
11827
  // "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
11690
11828
  // side === "left" &&
@@ -11964,10 +12102,20 @@ export {
11964
12102
  //
11965
12103
  // import { cn } from "@/lib/utils"
11966
12104
  //
11967
- // export type SocialPlatform = "line" | "x" | "facebook" | "amazon" | "google" | "apple"
12105
+ // export type SocialPlatform =
12106
+ // | "line"
12107
+ // | "x"
12108
+ // | "facebook"
12109
+ // | "amazon"
12110
+ // | "google"
12111
+ // | "apple"
12112
+ // | "hatena"
11968
12113
  //
11969
- // /** 単色で描くブランド。多色ロゴ(google / amazon)は個別に塗り分けるため除外 */
11970
- // type MonoPlatform = Exclude<SocialPlatform, "google" | "amazon">
12114
+ // /**
12115
+ // * 単色で描くブランド。
12116
+ // * 多色ロゴ(google / amazon)と、地+白抜きで描くもの(hatena)は個別に塗り分けるため除外
12117
+ // */
12118
+ // type MonoPlatform = Exclude<SocialPlatform, "google" | "amazon" | "hatena">
11971
12119
  //
11972
12120
  // export interface SocialIconProps extends Omit<React.ComponentProps<"svg">, "children"> {
11973
12121
  // platform: SocialPlatform
@@ -12055,6 +12203,33 @@ export {
12055
12203
  // )
12056
12204
  // }
12057
12205
  //
12206
+ // if (platform === "hatena") {
12207
+ // // はてなブックマークの「B!」マーク。角丸の地(--Third-Party-Hatena = #00A4DE)に白抜き。
12208
+ // // 字形は公式アートワークのトレースではなく幾何的に再構成したもの。公式 SVG が入手できたら
12209
+ // // この 2 つの path を差し替えれば足りる(公開 API は変わらない)。
12210
+ // // tone="mono" では地を描かず currentColor の字だけにする(ブランド色の地に載せる用)。
12211
+ // return (
12212
+ // <svg {...common} fill="none">
12213
+ // {!mono && (
12214
+ // <rect
12215
+ // x="1"
12216
+ // y="1"
12217
+ // width="22"
12218
+ // height="22"
12219
+ // rx="4"
12220
+ // fill="var(--Third-Party-Hatena)"
12221
+ // />
12222
+ // )}
12223
+ // <path
12224
+ // fillRule="evenodd"
12225
+ // /* 出典: はてなブックマークのブランド表記「B!」。白抜き(地の上)または currentColor */
12226
+ // fill={mono ? "currentColor" : "#FFFFFF"}
12227
+ // d="M6 6h4.4c2 0 3.2 1 3.2 2.7 0 1.1-.6 1.9-1.6 2.3 1.3.4 2.1 1.4 2.1 2.8 0 2-1.4 3.2-3.7 3.2H6V6Zm2.4 4.4h1.7c.85 0 1.3-.38 1.3-1.05s-.45-1.05-1.3-1.05H8.4v2.1Zm0 4.5h2c.95 0 1.45-.42 1.45-1.15s-.5-1.15-1.45-1.15h-2v2.3ZM16.2 6h2.4v6.6h-2.4V6Zm0 8.2h2.4V17h-2.4v-2.8Z"
12228
+ // />
12229
+ // </svg>
12230
+ // )
12231
+ // }
12232
+ //
12058
12233
  // return (
12059
12234
  // <svg {...common} fill={mono ? "currentColor" : brandColors[platform]}>
12060
12235
  // <path d={monoPaths[platform]} />
@@ -12380,10 +12555,22 @@ export {
12380
12555
  // scrollable: {
12381
12556
  // true: "gap-4",
12382
12557
  // },
12558
+ // /**
12559
+ // * 狭い置き場所(サイドバー等)向けの詰め設定。
12560
+ // * segment の 1 項目あたりの最小幅(100px)を外し、左右の padding を詰める(issue #235)。
12561
+ // */
12562
+ // size: {
12563
+ // md: "",
12564
+ // sm: "",
12565
+ // },
12383
12566
  // },
12567
+ // compoundVariants: [
12568
+ // { variant: "segment", size: "sm", class: "p-1" },
12569
+ // ],
12384
12570
  // defaultVariants: {
12385
12571
  // variant: "underbar",
12386
12572
  // scrollable: false,
12573
+ // size: "md",
12387
12574
  // },
12388
12575
  // }
12389
12576
  // )
@@ -12392,6 +12579,7 @@ export {
12392
12579
  // className,
12393
12580
  // variant = "underbar",
12394
12581
  // scrollable = false,
12582
+ // size = "md",
12395
12583
  // ...props
12396
12584
  // }: React.ComponentProps<typeof TabsPrimitive.List> &
12397
12585
  // VariantProps<typeof tabsListVariants>) {
@@ -12400,7 +12588,8 @@ export {
12400
12588
  // data-slot="tabs-list"
12401
12589
  // data-variant={variant}
12402
12590
  // data-scrollable={scrollable || undefined}
12403
- // className={cn(tabsListVariants({ variant, scrollable }), className)}
12591
+ // data-size={size}
12592
+ // className={cn(tabsListVariants({ variant, scrollable, size }), className)}
12404
12593
  // {...props}
12405
12594
  // />
12406
12595
  // )
@@ -12418,13 +12607,19 @@ export {
12418
12607
  // // Base
12419
12608
  // "group/trigger relative inline-flex items-center justify-center whitespace-nowrap transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring/70 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
12420
12609
  // // Underbar variant (default: equal-width tabs with full-width underline)
12421
- // "group-data-[variant=underbar]/tabs-list:h-12 group-data-[variant=underbar]/tabs-list:flex-1 group-data-[variant=underbar]/tabs-list:border-b-2 group-data-[variant=underbar]/tabs-list:border-transparent group-data-[variant=underbar]/tabs-list:typo-label-md group-data-[variant=underbar]/tabs-list:text-[var(--Text-Low-Emphasis)]",
12610
+ // // px-2: 均等割りで幅が詰まったとき、隣のラベルと文字が接触しないための最小余白(issue #235)
12611
+ // "group-data-[variant=underbar]/tabs-list:h-12 group-data-[variant=underbar]/tabs-list:flex-1 group-data-[variant=underbar]/tabs-list:border-b-2 group-data-[variant=underbar]/tabs-list:border-transparent group-data-[variant=underbar]/tabs-list:px-2 group-data-[variant=underbar]/tabs-list:typo-label-md group-data-[variant=underbar]/tabs-list:text-[var(--Text-Low-Emphasis)]",
12422
12612
  // // Underbar active
12423
12613
  // "group-data-[variant=underbar]/tabs-list:data-[state=active]:border-[var(--Text-High-Emphasis)] group-data-[variant=underbar]/tabs-list:data-[state=active]:text-[var(--Text-High-Emphasis)]",
12424
12614
  // // Scrollable underbar: shrink to text width, bold text, remove trigger border (underline moves to inner span)
12425
- // "group-data-[scrollable]/tabs-list:!flex-initial group-data-[scrollable]/tabs-list:!shrink-0 group-data-[scrollable]/tabs-list:!border-b-0 group-data-[scrollable]/tabs-list:data-[state=active]:!border-b-0 group-data-[scrollable]/tabs-list:typo-label-md",
12615
+ // // gap-4 で間隔を取っているので左右 padding は戻す(従来の間隔を保つ)
12616
+ // "group-data-[scrollable]/tabs-list:!flex-initial group-data-[scrollable]/tabs-list:!shrink-0 group-data-[scrollable]/tabs-list:!border-b-0 group-data-[scrollable]/tabs-list:!px-0 group-data-[scrollable]/tabs-list:data-[state=active]:!border-b-0 group-data-[scrollable]/tabs-list:typo-label-md",
12426
12617
  // // Segment variant
12427
12618
  // "group-data-[variant=segment]/tabs-list:h-[37px] group-data-[variant=segment]/tabs-list:min-w-[100px] group-data-[variant=segment]/tabs-list:rounded-full group-data-[variant=segment]/tabs-list:px-3 group-data-[variant=segment]/tabs-list:typo-body-md group-data-[variant=segment]/tabs-list:text-[var(--Text-High-Emphasis)]",
12619
+ // // size="sm": 狭い置き場所(サイドバー等)向け。1 項目あたりの最小幅を外し、
12620
+ // // 左右の padding を詰める。min-w を持つのは segment だけ、underbar の px-2 は同値なので
12621
+ // // 実際に効くのは segment。variant 側の group-data と具体度が並ぶため ! で順序依存を断つ(issue #235)
12622
+ // "group-data-[size=sm]/tabs-list:!min-w-0 group-data-[size=sm]/tabs-list:!px-2",
12428
12623
  // // Segment active
12429
12624
  // "group-data-[variant=segment]/tabs-list:data-[state=active]:bg-[var(--Surface-Primary)] group-data-[variant=segment]/tabs-list:data-[state=active]:shadow-[0px_4px_6px_-4px_rgba(24,39,75,0.12),0px_8px_8px_-4px_rgba(24,39,75,0.08)]",
12430
12625
  // className
@@ -12546,6 +12741,8 @@ export {
12546
12741
  // export { Textarea }
12547
12742
  //
12548
12743
  // src/components/foundations/toggle-group.tsx
12744
+ // "use client"
12745
+ //
12549
12746
  // import * as React from "react"
12550
12747
  // import { cva, type VariantProps } from "class-variance-authority"
12551
12748
  // import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"
@@ -12838,7 +13035,7 @@ export {
12838
13035
  // return (
12839
13036
  // <header
12840
13037
  // data-slot="admin-header"
12841
- // className="fixed top-0 left-0 right-0 z-[var(--Z-Nav)] flex h-14 @md:h-16 items-center justify-between bg-[var(--Surface-Primary)] border-b border-[var(--Border-Low-Emphasis)] px-4 @md:px-6"
13038
+ // className="fixed top-0 left-0 right-0 z-[var(--Z-Nav)] flex h-14 @md:h-16 items-center justify-between bg-[var(--Surface-Elevated)] border-b border-[var(--Border-Low-Emphasis)] px-4 @md:px-6"
12842
13039
  // >
12843
13040
  // <div className="flex items-center gap-2 @md:gap-3">
12844
13041
  // {onMenuClick && (
@@ -12869,10 +13066,19 @@ export {
12869
13066
  // export { AdminHeader }
12870
13067
  //
12871
13068
  // src/components/primitives/admin-side-nav.tsx
13069
+ // "use client"
13070
+ //
12872
13071
  // import * as React from "react"
12873
13072
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
12874
13073
  // import { XIcon } from "lucide-react"
12875
13074
  //
13075
+ // import {
13076
+ // DropdownMenu,
13077
+ // DropdownMenuContent,
13078
+ // DropdownMenuItem,
13079
+ // DropdownMenuTrigger,
13080
+ // } from "@/components/foundations/dropdown-menu"
13081
+ // import { FOCUS_RING } from "@/lib/focus-ring"
12876
13082
  // import { cn } from "@/lib/utils"
12877
13083
  //
12878
13084
  // // ============================================================
@@ -12961,6 +13167,9 @@ export {
12961
13167
  // *
12962
13168
  // * メイン項目・サブメニュー項目とも 44px(WCAG 2.5.5 の最小ターゲット)以上にする。
12963
13169
  // * 行高が小さいテキストで縦 padding だけに頼ると割り込むため、`min-h-11` で下限を固定する。
13170
+ // * PC のサブメニューは `DropdownMenu` の Portal / collision handling を利用し、
13171
+ // * viewport 端では位置と最大高を自動調整する。hover ではフォーカスを奪わず、
13172
+ // * Enter / Space / ArrowDown / Escape では標準のメニュー操作に従う。
12964
13173
  // *
12965
13174
  // * ### インポート
12966
13175
  // * ```tsx
@@ -12986,6 +13195,113 @@ export {
12986
13195
  // ariaLabel = "管理メニュー",
12987
13196
  // }: AdminSideNavProps) {
12988
13197
  // const [openMenu, setOpenMenu] = React.useState<string | null>(null)
13198
+ // const hoverOpenedMenuRef = React.useRef<string | null>(null)
13199
+ // const hoverOpenedMenusRef = React.useRef(new Set<string>())
13200
+ // const focusedMenuTriggerRef = React.useRef<string | null>(null)
13201
+ // const pointerOpenedMenuRef = React.useRef<string | null>(null)
13202
+ // const pointerHoverBlockedMenuRef = React.useRef<string | null>(null)
13203
+ // const outsideDismissedMenuRef = React.useRef<string | null>(null)
13204
+ // const menuTriggerRefs = React.useRef(new Map<string, HTMLButtonElement>())
13205
+ // const firstMenuItemRefs = React.useRef(new Map<string, HTMLAnchorElement>())
13206
+ // const openTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)
13207
+ // const closeTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null)
13208
+ // const desktopNavRef = React.useRef<HTMLElement | null>(null)
13209
+ //
13210
+ // const cancelScheduledClose = React.useCallback(() => {
13211
+ // if (closeTimerRef.current !== null) {
13212
+ // clearTimeout(closeTimerRef.current)
13213
+ // closeTimerRef.current = null
13214
+ // }
13215
+ // }, [])
13216
+ //
13217
+ // const cancelScheduledOpen = React.useCallback(() => {
13218
+ // if (openTimerRef.current !== null) {
13219
+ // clearTimeout(openTimerRef.current)
13220
+ // openTimerRef.current = null
13221
+ // }
13222
+ // }, [])
13223
+ //
13224
+ // const openMenuFromPointer = React.useCallback(
13225
+ // (key: string, pointerType: string) => {
13226
+ // if (pointerType === "touch") return
13227
+ // cancelScheduledOpen()
13228
+ // cancelScheduledClose()
13229
+ // openTimerRef.current = setTimeout(() => {
13230
+ // if (
13231
+ // pointerOpenedMenuRef.current !== null &&
13232
+ // pointerOpenedMenuRef.current !== key
13233
+ // ) {
13234
+ // pointerOpenedMenuRef.current = null
13235
+ // menuTriggerRefs.current.get(key)?.focus({ preventScroll: true })
13236
+ // }
13237
+ // hoverOpenedMenuRef.current = key
13238
+ // hoverOpenedMenusRef.current.add(key)
13239
+ // setOpenMenu(key)
13240
+ // openTimerRef.current = null
13241
+ // }, 80)
13242
+ // },
13243
+ // [cancelScheduledClose, cancelScheduledOpen],
13244
+ // )
13245
+ //
13246
+ // const schedulePointerClose = React.useCallback(
13247
+ // (key: string) => {
13248
+ // cancelScheduledOpen()
13249
+ // cancelScheduledClose()
13250
+ // closeTimerRef.current = setTimeout(() => {
13251
+ // setOpenMenu((current) => (current === key ? null : current))
13252
+ // closeTimerRef.current = null
13253
+ // }, 120)
13254
+ // },
13255
+ // [cancelScheduledClose, cancelScheduledOpen],
13256
+ // )
13257
+ //
13258
+ // const closeDesktopMenus = React.useCallback(() => {
13259
+ // cancelScheduledOpen()
13260
+ // cancelScheduledClose()
13261
+ // hoverOpenedMenuRef.current = null
13262
+ // hoverOpenedMenusRef.current.clear()
13263
+ // focusedMenuTriggerRef.current = null
13264
+ // pointerOpenedMenuRef.current = null
13265
+ // pointerHoverBlockedMenuRef.current = null
13266
+ // outsideDismissedMenuRef.current = null
13267
+ // setOpenMenu(null)
13268
+ // }, [cancelScheduledClose, cancelScheduledOpen])
13269
+ //
13270
+ // React.useEffect(
13271
+ // () => () => {
13272
+ // if (openTimerRef.current !== null) clearTimeout(openTimerRef.current)
13273
+ // if (closeTimerRef.current !== null) clearTimeout(closeTimerRef.current)
13274
+ // focusedMenuTriggerRef.current = null
13275
+ // pointerOpenedMenuRef.current = null
13276
+ // pointerHoverBlockedMenuRef.current = null
13277
+ // outsideDismissedMenuRef.current = null
13278
+ // menuTriggerRefs.current.clear()
13279
+ // firstMenuItemRefs.current.clear()
13280
+ // },
13281
+ // [],
13282
+ // )
13283
+ //
13284
+ // React.useEffect(() => {
13285
+ // const nav = desktopNavRef.current
13286
+ // if (!nav || typeof ResizeObserver === "undefined") return
13287
+ //
13288
+ // const closeWhenHidden = () => {
13289
+ // const bounds = nav.getBoundingClientRect()
13290
+ // if (
13291
+ // getComputedStyle(nav).display === "none" ||
13292
+ // bounds.width === 0 ||
13293
+ // bounds.height === 0
13294
+ // ) {
13295
+ // closeDesktopMenus()
13296
+ // }
13297
+ // }
13298
+ //
13299
+ // const observer = new ResizeObserver(closeWhenHidden)
13300
+ // observer.observe(nav)
13301
+ // closeWhenHidden()
13302
+ //
13303
+ // return () => observer.disconnect()
13304
+ // }, [closeDesktopMenus])
12989
13305
  //
12990
13306
  // return (
12991
13307
  // <>
@@ -12995,26 +13311,23 @@ export {
12995
13311
  // (h-full だとヘッダー帯に重なるため使わない)。--Z-Sticky = 30 でヘッダーより背面。
12996
13312
  // レールは @md 限定表示なので SP のヘッダー高さ h-14 は考慮しない。 */}
12997
13313
  // <nav
13314
+ // ref={desktopNavRef}
12998
13315
  // data-slot="admin-side-nav"
12999
13316
  // aria-label={ariaLabel}
13000
- // className="hidden @md:flex fixed left-0 top-16 bottom-0 z-[var(--Z-Sticky)] w-[72px] flex-col items-center bg-[var(--Surface-Primary)] border-r border-[var(--Border-Low-Emphasis)]"
13317
+ // className="hidden @md:flex fixed left-0 top-16 bottom-0 z-[var(--Z-Sticky)] w-[72px] flex-col items-center bg-[var(--Surface-Elevated)] border-r border-[var(--Border-Low-Emphasis)]"
13001
13318
  // >
13002
13319
  // {items.map((item) => {
13003
13320
  // const isActive = activeKey === item.key
13004
13321
  // const hasSubMenu = !!item.subMenus && item.subMenus.length > 0
13005
13322
  // return (
13006
- // <div
13007
- // key={item.key}
13008
- // className="relative"
13009
- // onMouseEnter={() => setOpenMenu(hasSubMenu ? item.key : null)}
13010
- // onMouseLeave={() => setOpenMenu(null)}
13011
- // >
13323
+ // <div key={item.key} className="relative">
13012
13324
  // {(() => {
13013
13325
  // const triggerClass = cn(
13014
- // "flex h-16 w-16 flex-col items-center justify-center gap-1 transition-colors",
13326
+ // "flex h-16 w-16 flex-col items-center justify-center gap-1 rounded-md transition-colors",
13015
13327
  // isActive
13016
13328
  // ? "text-[var(--Text-Accent-Primary)]"
13017
13329
  // : "text-[var(--Text-Medium-Emphasis)] hover:text-[var(--Text-High-Emphasis)]",
13330
+ // FOCUS_RING,
13018
13331
  // )
13019
13332
  // const triggerContent = (
13020
13333
  // <>
@@ -13024,6 +13337,175 @@ export {
13024
13337
  // </span>
13025
13338
  // </>
13026
13339
  // )
13340
+ // if (hasSubMenu) {
13341
+ // return (
13342
+ // <DropdownMenu
13343
+ // modal={false}
13344
+ // open={openMenu === item.key}
13345
+ // onOpenChange={(nextOpen) => {
13346
+ // cancelScheduledClose()
13347
+ // if (nextOpen) {
13348
+ // if (outsideDismissedMenuRef.current === item.key) {
13349
+ // outsideDismissedMenuRef.current = null
13350
+ // }
13351
+ // hoverOpenedMenuRef.current = null
13352
+ // hoverOpenedMenusRef.current.delete(item.key)
13353
+ // setOpenMenu(item.key)
13354
+ // } else {
13355
+ // setOpenMenu((current) =>
13356
+ // current === item.key ? null : current,
13357
+ // )
13358
+ // }
13359
+ // }}
13360
+ // >
13361
+ // <DropdownMenuTrigger asChild>
13362
+ // <button
13363
+ // ref={(node) => {
13364
+ // if (node) {
13365
+ // menuTriggerRefs.current.set(item.key, node)
13366
+ // } else {
13367
+ // menuTriggerRefs.current.delete(item.key)
13368
+ // }
13369
+ // }}
13370
+ // type="button"
13371
+ // className={triggerClass}
13372
+ // onFocus={() => {
13373
+ // cancelScheduledOpen()
13374
+ // focusedMenuTriggerRef.current = item.key
13375
+ // if (hoverOpenedMenuRef.current === item.key) {
13376
+ // hoverOpenedMenuRef.current = null
13377
+ // }
13378
+ // hoverOpenedMenusRef.current.delete(item.key)
13379
+ // }}
13380
+ // onBlur={() => {
13381
+ // if (focusedMenuTriggerRef.current === item.key) {
13382
+ // focusedMenuTriggerRef.current = null
13383
+ // }
13384
+ // }}
13385
+ // onPointerEnter={(event) => {
13386
+ // if (
13387
+ // focusedMenuTriggerRef.current === item.key ||
13388
+ // pointerHoverBlockedMenuRef.current === item.key
13389
+ // ) {
13390
+ // return
13391
+ // }
13392
+ // openMenuFromPointer(item.key, event.pointerType)
13393
+ // }}
13394
+ // onPointerDownCapture={() => {
13395
+ // cancelScheduledOpen()
13396
+ // if (openMenu !== item.key) {
13397
+ // pointerOpenedMenuRef.current = item.key
13398
+ // }
13399
+ // }}
13400
+ // onPointerLeave={() => {
13401
+ // if (
13402
+ // pointerHoverBlockedMenuRef.current === item.key
13403
+ // ) {
13404
+ // pointerHoverBlockedMenuRef.current = null
13405
+ // }
13406
+ // schedulePointerClose(item.key)
13407
+ // }}
13408
+ // >
13409
+ // {triggerContent}
13410
+ // </button>
13411
+ // </DropdownMenuTrigger>
13412
+ // <DropdownMenuContent
13413
+ // side="right"
13414
+ // align="start"
13415
+ // sideOffset={0}
13416
+ // collisionPadding={8}
13417
+ // className="w-[240px] rounded-2xl p-2 shadow-menu"
13418
+ // onPointerEnter={cancelScheduledClose}
13419
+ // onPointerLeave={() => schedulePointerClose(item.key)}
13420
+ // onPointerMoveCapture={(event) => {
13421
+ // if (hoverOpenedMenuRef.current === item.key) {
13422
+ // event.preventDefault()
13423
+ // }
13424
+ // }}
13425
+ // onInteractOutside={(event) => {
13426
+ // const trigger = menuTriggerRefs.current.get(item.key)
13427
+ // if (
13428
+ // pointerOpenedMenuRef.current === item.key &&
13429
+ // event.target instanceof Node &&
13430
+ // !trigger?.contains(event.target)
13431
+ // ) {
13432
+ // outsideDismissedMenuRef.current = item.key
13433
+ // }
13434
+ // }}
13435
+ // {...{
13436
+ // onOpenAutoFocus: (event: Event) => {
13437
+ // if (hoverOpenedMenuRef.current === item.key) {
13438
+ // event.preventDefault()
13439
+ // } else if (
13440
+ // pointerOpenedMenuRef.current === item.key
13441
+ // ) {
13442
+ // event.preventDefault()
13443
+ // requestAnimationFrame(() => {
13444
+ // firstMenuItemRefs.current.get(item.key)?.focus()
13445
+ // })
13446
+ // }
13447
+ // },
13448
+ // }}
13449
+ // onCloseAutoFocus={(event) => {
13450
+ // if (hoverOpenedMenusRef.current.has(item.key)) {
13451
+ // event.preventDefault()
13452
+ // hoverOpenedMenusRef.current.delete(item.key)
13453
+ // if (hoverOpenedMenuRef.current === item.key) {
13454
+ // hoverOpenedMenuRef.current = null
13455
+ // }
13456
+ // }
13457
+ // if (pointerOpenedMenuRef.current === item.key) {
13458
+ // event.preventDefault()
13459
+ // pointerOpenedMenuRef.current = null
13460
+ // if (outsideDismissedMenuRef.current !== item.key) {
13461
+ // pointerHoverBlockedMenuRef.current = item.key
13462
+ // requestAnimationFrame(() => {
13463
+ // menuTriggerRefs.current.get(item.key)?.focus()
13464
+ // })
13465
+ // }
13466
+ // }
13467
+ // if (outsideDismissedMenuRef.current === item.key) {
13468
+ // outsideDismissedMenuRef.current = null
13469
+ // }
13470
+ // }}
13471
+ // >
13472
+ // {item.subMenus!.map((sub, index) => (
13473
+ // <DropdownMenuItem
13474
+ // key={sub.label}
13475
+ // asChild
13476
+ // className="min-h-11 px-4"
13477
+ // onPointerLeave={(event) => {
13478
+ // if (hoverOpenedMenuRef.current === item.key) {
13479
+ // event.preventDefault()
13480
+ // }
13481
+ // }}
13482
+ // >
13483
+ // <a
13484
+ // ref={
13485
+ // index === 0
13486
+ // ? (node) => {
13487
+ // if (node) {
13488
+ // firstMenuItemRefs.current.set(
13489
+ // item.key,
13490
+ // node,
13491
+ // )
13492
+ // } else {
13493
+ // firstMenuItemRefs.current.delete(item.key)
13494
+ // }
13495
+ // }
13496
+ // : undefined
13497
+ // }
13498
+ // href={sub.href}
13499
+ // >
13500
+ // {sub.label}
13501
+ // </a>
13502
+ // </DropdownMenuItem>
13503
+ // ))}
13504
+ // </DropdownMenuContent>
13505
+ // </DropdownMenu>
13506
+ // )
13507
+ // }
13508
+ //
13027
13509
  // return item.href ? (
13028
13510
  // <a
13029
13511
  // href={item.href}
@@ -13038,23 +13520,6 @@ export {
13038
13520
  // </button>
13039
13521
  // )
13040
13522
  // })()}
13041
- // {/* Sub-menu popup */}
13042
- // {hasSubMenu && openMenu === item.key && (
13043
- // <div className="absolute left-full top-0 z-[var(--Z-Popover)] ml-0 w-[240px] rounded-2xl bg-[var(--Surface-Primary)] shadow-menu border border-[var(--Border-Low-Emphasis)] py-2">
13044
- // {item.subMenus!.map((sub) => (
13045
- // <a
13046
- // key={sub.label}
13047
- // href={sub.href}
13048
- // // min-h-11 = 44px(WCAG 2.5.5 最小ターゲット)。
13049
- // // py-2.5(10px×2) + typo-body-sm の行高 18px = 38px で 44px を割るため、
13050
- // // 高さを min-h-11 で確保し flex で中央寄せする。
13051
- // className="flex min-h-11 items-center px-4 py-2.5 typo-body-sm text-[var(--Text-High-Emphasis)] hover:bg-[var(--Surface-Secondary)] transition-colors"
13052
- // >
13053
- // {sub.label}
13054
- // </a>
13055
- // ))}
13056
- // </div>
13057
- // )}
13058
13523
  // </div>
13059
13524
  // )
13060
13525
  // })}
@@ -13366,7 +13831,7 @@ export {
13366
13831
  // data-slot="bottom-tab-bar"
13367
13832
  // aria-label="メインナビゲーション"
13368
13833
  // className={cn(
13369
- // "fixed inset-x-0 bottom-0 z-[var(--Z-Floating)] border-t border-[var(--Border-Low-Emphasis)] bg-[var(--Surface-Primary)] pb-[env(safe-area-inset-bottom)] @md:hidden",
13834
+ // "fixed inset-x-0 bottom-0 z-[var(--Z-Floating)] border-t border-[var(--Border-Low-Emphasis)] bg-[var(--Surface-Elevated)] pb-[env(safe-area-inset-bottom)] @md:hidden",
13370
13835
  // className
13371
13836
  // )}
13372
13837
  // {...props}
@@ -13802,6 +14267,8 @@ export {
13802
14267
  // export { CategoryShortcuts }
13803
14268
  //
13804
14269
  // src/components/primitives/chat-composer.tsx
14270
+ // "use client"
14271
+ //
13805
14272
  // import * as React from "react"
13806
14273
  // import { SendHorizontal } from "lucide-react"
13807
14274
  //
@@ -14396,6 +14863,8 @@ export {
14396
14863
  // export { CoachMark }
14397
14864
  //
14398
14865
  // src/components/primitives/combobox.tsx
14866
+ // "use client"
14867
+ //
14399
14868
  // import * as React from "react"
14400
14869
  // import { Check, ChevronsUpDown } from "lucide-react"
14401
14870
  //
@@ -14583,7 +15052,186 @@ export {
14583
15052
  // // eslint-disable-next-line react-refresh/only-export-components -- shadcn 慣習: variants はコンポーネントと同居 export(分割は公開 API の破壊変更)
14584
15053
  // export { Container, containerVariants }
14585
15054
  //
15055
+ // src/components/primitives/content-card.tsx
15056
+ // import * as React from "react"
15057
+ //
15058
+ // import { cn } from "@/lib/utils"
15059
+ // import { FOCUS_RING } from "@/lib/focus-ring"
15060
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
15061
+ // import { Tag, type TagProps } from "@/components/primitives/tag"
15062
+ //
15063
+ // export type ContentCardOrientation = "vertical" | "horizontal" | "list"
15064
+ // export type ContentCardAspect = "16/10" | "16/9" | "1/1"
15065
+ //
15066
+ // export interface ContentCardProps
15067
+ // extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
15068
+ // /** 記事タイトル。一覧で高さが割れないよう常に 2 行ぶんの高さを取る */
15069
+ // title: string
15070
+ // /** 遷移先。カード全体がリンクになる */
15071
+ // href: string
15072
+ // /**
15073
+ // * 画像。`next/image` や CMS の img、図版をそのまま渡す。
15074
+ // * 縦横比とクリップはカード側が持つので、中身は `h-full w-full object-cover` を想定。
15075
+ // */
15076
+ // imageSlot?: React.ReactNode
15077
+ // /** 画像左下に重ねるラベル(カテゴリ等)。長いラベルは省略記号で切る */
15078
+ // tag?: { label: string; variant?: TagProps["variant"] }
15079
+ // /** 日付・著者などの補足。**必ず 1 行**に収まる内容にする(複数行だと一覧で高さが割れる) */
15080
+ // meta?: React.ReactNode
15081
+ // /**
15082
+ // * カードの向き。
15083
+ // * - `vertical`(既定): 画像が上、本文が下。グリッド一覧向け
15084
+ // * - `horizontal` : 画像が左、本文が右
15085
+ // * - `list` : 本文が左、サムネイルが右(記事一覧の Medium 型)
15086
+ // */
15087
+ // orientation?: ContentCardOrientation
15088
+ // /** 画像の縦横比(既定 `16/10`。記事のアイキャッチは横長素材が前提) */
15089
+ // aspect?: ContentCardAspect
15090
+ // /**
15091
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
15092
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
15093
+ // */
15094
+ // linkComponent?: LinkComponent
15095
+ // }
15096
+ //
15097
+ // const aspectClass: Record<ContentCardAspect, string> = {
15098
+ // "16/10": "aspect-[16/10]",
15099
+ // "16/9": "aspect-[16/9]",
15100
+ // "1/1": "aspect-[1/1]",
15101
+ // }
15102
+ //
15103
+ // /** orientation ごとの外枠レイアウト */
15104
+ // const rootLayout: Record<ContentCardOrientation, string> = {
15105
+ // vertical: "flex-col gap-2",
15106
+ // horizontal: "flex-row items-start gap-3",
15107
+ // list: "flex-row-reverse items-start gap-3",
15108
+ // }
15109
+ //
15110
+ // /** orientation ごとの画像枠の幅 */
15111
+ // const mediaLayout: Record<ContentCardOrientation, string> = {
15112
+ // vertical: "w-full",
15113
+ // horizontal: "w-28 shrink-0",
15114
+ // list: "w-24 shrink-0",
15115
+ // }
15116
+ //
15117
+ // /**
15118
+ // * 記事・特集・お知らせなど「画像 + タイトル + メタ」のカード。
15119
+ // *
15120
+ // * `ProductCard`(商品)/ `ShopCard`(店舗)の兄弟で、記事メディア向け。
15121
+ // * 汎用の `Card` に載せて組むと、枠線・タイトル行数・カード高さが揃わない
15122
+ // * (実測で高さ 268 と 312 に割れる事例あり)ため、この部品を使う。
15123
+ // *
15124
+ // * ### 作法
15125
+ // *
15126
+ // * - 枠線なし・`rounded-lg`・サーフェスは親から伝播(`Section background="subtle"` 配下では白)
15127
+ // * - タイトルは 2 行で省略し、常に 2 行ぶんの高さを取る(一覧で下端が揃う)
15128
+ // * - `meta` は 1 行固定でカード下端へ寄る
15129
+ // * - 画像は `imageSlot` で consumer が用意する(`next/image` / CMS / 図版を吸収する)
15130
+ // *
15131
+ // * ### AI 向け使用ルール
15132
+ // *
15133
+ // * - 記事一覧・関連記事・注目記事は `Card` + `CardContent` で組まずこれを使う
15134
+ // * - グリッド一覧は `orientation="vertical"`、Medium 型の縦リストは `orientation="list"` +
15135
+ // * `ContentList`(区切り線つき)
15136
+ // * - タイトルの文字装飾を利用側で足さない(`font-bold` にしない。既定は `font-medium`)
15137
+ // */
15138
+ // function ContentCard({
15139
+ // className,
15140
+ // title,
15141
+ // href,
15142
+ // imageSlot,
15143
+ // tag,
15144
+ // meta,
15145
+ // orientation = "vertical",
15146
+ // aspect = "16/10",
15147
+ // linkComponent,
15148
+ // ...props
15149
+ // }: ContentCardProps) {
15150
+ // const Comp = resolveLinkComponent(linkComponent)
15151
+ //
15152
+ // return (
15153
+ // <Comp
15154
+ // data-slot="content-card"
15155
+ // data-orientation={orientation}
15156
+ // href={href}
15157
+ // className={cn(
15158
+ // "group flex rounded-lg bg-[var(--card-surface,var(--Surface-Primary))]",
15159
+ // rootLayout[orientation],
15160
+ // FOCUS_RING,
15161
+ // className
15162
+ // )}
15163
+ // {...props}
15164
+ // >
15165
+ // {imageSlot && (
15166
+ // <div
15167
+ // data-slot="content-card-media"
15168
+ // className={cn(
15169
+ // "relative overflow-hidden rounded-lg",
15170
+ // aspectClass[aspect],
15171
+ // mediaLayout[orientation]
15172
+ // )}
15173
+ // >
15174
+ // <div className="h-full w-full transition-transform duration-[var(--Motion-Duration-Base)] ease-[var(--Motion-Easing-Standard)] group-hover:scale-[1.02]">
15175
+ // {imageSlot}
15176
+ // </div>
15177
+ // {tag && (
15178
+ // <Tag
15179
+ // variant={tag.variant}
15180
+ // className="absolute bottom-2 left-2 max-w-[calc(100%-1rem)] overflow-hidden text-ellipsis"
15181
+ // >
15182
+ // {tag.label}
15183
+ // </Tag>
15184
+ // )}
15185
+ // </div>
15186
+ // )}
15187
+ // <div className="flex min-w-0 flex-1 flex-col gap-0.5">
15188
+ // <span
15189
+ // data-slot="content-card-title"
15190
+ // className="line-clamp-2 min-h-[2lh] typo-body-md font-medium text-[var(--Text-High-Emphasis)]"
15191
+ // >
15192
+ // {title}
15193
+ // </span>
15194
+ // {meta && (
15195
+ // <span
15196
+ // data-slot="content-card-meta"
15197
+ // className="mt-auto truncate typo-body-sm text-[var(--Text-Medium-Emphasis)]"
15198
+ // >
15199
+ // {meta}
15200
+ // </span>
15201
+ // )}
15202
+ // </div>
15203
+ // </Comp>
15204
+ // )
15205
+ // }
15206
+ //
15207
+ // /**
15208
+ // * `ContentCard` を区切り線つきで縦に並べるリスト(記事一覧の Medium 型)。
15209
+ // *
15210
+ // * 一覧ページで `orientation="list"` の `ContentCard` を並べるときに使う。
15211
+ // * 区切り線と項目間の余白だけを持ち、幅・背景は持たない。
15212
+ // */
15213
+ // function ContentList({
15214
+ // className,
15215
+ // ...props
15216
+ // }: React.HTMLAttributes<HTMLDivElement>) {
15217
+ // return (
15218
+ // <div
15219
+ // data-slot="content-list"
15220
+ // className={cn(
15221
+ // "flex flex-col divide-y divide-[var(--Border-Low-Emphasis)]",
15222
+ // "[&>*]:py-4 [&>*:first-child]:pt-0 [&>*:last-child]:pb-0",
15223
+ // className
15224
+ // )}
15225
+ // {...props}
15226
+ // />
15227
+ // )
15228
+ // }
15229
+ //
15230
+ // export { ContentCard, ContentList }
15231
+ //
14586
15232
  // src/components/primitives/content-carousel.tsx
15233
+ // "use client"
15234
+ //
14587
15235
  // import * as React from "react"
14588
15236
  // import ArrowLeft2 from "iconsax-reactjs/dist/esm/ArrowLeft2.js"
14589
15237
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
@@ -14825,6 +15473,8 @@ export {
14825
15473
  // export { ContentCarousel }
14826
15474
  //
14827
15475
  // src/components/primitives/date-picker.tsx
15476
+ // "use client"
15477
+ //
14828
15478
  // /**
14829
15479
  // * ## DatePicker / DateTimePicker — Popover + Calendar 組合せ済みの日付・日時入力
14830
15480
  // *
@@ -15620,9 +16270,12 @@ export {
15620
16270
  // export { FilterBar }
15621
16271
  //
15622
16272
  // src/components/primitives/footer.tsx
16273
+ // "use client"
16274
+ //
15623
16275
  // import * as React from "react"
15624
16276
  //
15625
16277
  // import { cn } from "@/lib/utils"
16278
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
15626
16279
  //
15627
16280
  // export interface FooterLink {
15628
16281
  // label: string
@@ -15682,6 +16335,25 @@ export {
15682
16335
  // trustBadge?: FooterTrustBadge
15683
16336
  // /** フッター下部の補助リンク(特定商取引法、プライバシーポリシー等) */
15684
16337
  // bottomLinks?: FooterLink[]
16338
+ // /**
16339
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
16340
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
16341
+ // * `external: true` のリンクは常に素の `<a target="_blank">` で描く。
16342
+ // */
16343
+ // linkComponent?: LinkComponent
16344
+ // /**
16345
+ // * レイアウト(既定 `default`)。
16346
+ // * - `default` : ロゴ・説明文を最下部に中央寄せ(本番 Cake.jp 準拠)
16347
+ // * - `brand-first` : ロゴ・説明文を先頭カラムに置き、その右にリンク群を並べる。
16348
+ // * 下部バーはコピーライト左・`bottomRightSlot` 右の左右振り分けになる
16349
+ // * (求人ケーキ屋さん.jp / 仕入れケーキ屋さん.JP のフッター構成)
16350
+ // */
16351
+ // variant?: "default" | "brand-first"
16352
+ // /**
16353
+ // * 下部バーの右側に置く要素(`Powered by` 等)。
16354
+ // * `variant="brand-first"` でのみ配置され、既定レイアウトでは無視される。
16355
+ // */
16356
+ // bottomRightSlot?: React.ReactNode
15685
16357
  // }
15686
16358
  //
15687
16359
  // /**
@@ -15757,7 +16429,7 @@ export {
15757
16429
  // * 本番CSS: `.p-footer-item__area { display: flex; justify-content: space-between; }`
15758
16430
  // * 本番CSS: `.p-footer-item__title { pointer-events: none; }` (PCではアコーディオン無効)
15759
16431
  // */
15760
- // function FooterColumnNav({ groups }: { groups: FooterLinkGroup[] }) {
16432
+ // function FooterColumnNav({ groups, linkComponent }: { groups: FooterLinkGroup[]; linkComponent?: LinkComponent }) {
15761
16433
  // const colClass =
15762
16434
  // groups.length <= 4 ? "@lg:grid-cols-4" :
15763
16435
  // groups.length === 5 ? "@lg:grid-cols-5" :
@@ -15773,13 +16445,13 @@ export {
15773
16445
  // <ul className="space-y-1.5">
15774
16446
  // {group.links.map((link) => (
15775
16447
  // <li key={link.label}>
15776
- // <a
15777
- // href={link.href}
16448
+ // <FooterAnchor
16449
+ // link={link}
16450
+ // linkComponent={linkComponent}
15778
16451
  // className="typo-body-sm text-[var(--Text-Medium-Emphasis)] hover:text-[var(--Text-High-Emphasis)] transition-colors duration-[var(--Motion-Duration-Fast)]"
15779
- // {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
15780
16452
  // >
15781
16453
  // {link.label}
15782
- // </a>
16454
+ // </FooterAnchor>
15783
16455
  // </li>
15784
16456
  // ))}
15785
16457
  // </ul>
@@ -15792,13 +16464,13 @@ export {
15792
16464
  // <ul className="space-y-1.5">
15793
16465
  // {sub.links.map((link) => (
15794
16466
  // <li key={link.label}>
15795
- // <a
15796
- // href={link.href}
16467
+ // <FooterAnchor
16468
+ // link={link}
16469
+ // linkComponent={linkComponent}
15797
16470
  // className="typo-body-sm text-[var(--Text-Medium-Emphasis)] hover:text-[var(--Text-High-Emphasis)] transition-colors duration-[var(--Motion-Duration-Fast)]"
15798
- // {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
15799
16471
  // >
15800
16472
  // {link.label}
15801
- // </a>
16473
+ // </FooterAnchor>
15802
16474
  // </li>
15803
16475
  // ))}
15804
16476
  // </ul>
@@ -15813,19 +16485,46 @@ export {
15813
16485
  // /**
15814
16486
  // * フッターリンクリスト
15815
16487
  // */
15816
- // function FooterLinkList({ links }: { links: FooterLink[] }) {
16488
+ // /**
16489
+ // * フッター内のリンク 1 本。linkComponent が渡されていればそれで描く(#236)。
16490
+ // * 外部リンクは常に素の `<a target="_blank">`。
16491
+ // */
16492
+ // function FooterAnchor({
16493
+ // link,
16494
+ // linkComponent,
16495
+ // className,
16496
+ // children,
16497
+ // }: {
16498
+ // link: FooterLink
16499
+ // linkComponent?: LinkComponent
16500
+ // className?: string
16501
+ // children: React.ReactNode
16502
+ // }) {
16503
+ // const LinkTag = resolveLinkComponent(linkComponent, link.external)
16504
+ // return (
16505
+ // <LinkTag
16506
+ // href={link.href}
16507
+ // className={className}
16508
+ // {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
16509
+ // >
16510
+ // {children}
16511
+ // </LinkTag>
16512
+ // )
16513
+ // }
16514
+ //
16515
+ // function FooterLinkList({ links, linkComponent }: { links: FooterLink[]; linkComponent?: LinkComponent }) {
15817
16516
  // return (
15818
16517
  // <ul>
15819
16518
  // {links.map((link) => (
15820
16519
  // <li key={link.label} className="border-b border-[var(--Border-Low-Emphasis)] last:border-b-0">
15821
- // <a
15822
- // href={link.href}
16520
+ // <FooterAnchor
16521
+ // link={link}
16522
+ // linkComponent={linkComponent}
15823
16523
  // className={cn(
15824
16524
  // "flex items-center justify-between px-5 py-5",
15825
16525
  // "typo-body-sm text-[var(--Text-Medium-Emphasis)]",
15826
16526
  // "hover:text-[var(--Text-High-Emphasis)] transition-colors duration-[var(--Motion-Duration-Fast)]"
15827
16527
  // )}
15828
- // {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
15829
16528
  // >
15830
16529
  // <span>{link.label}</span>
15831
16530
  // {/* 右矢印アイコン(本番の icon-arrow と同等) */}
@@ -15838,7 +16537,7 @@ export {
15838
16537
  // >
15839
16538
  // <path d="M3.5 1.5L7 5L3.5 8.5" />
15840
16539
  // </svg>
15841
- // </a>
16540
+ // </FooterAnchor>
15842
16541
  // </li>
15843
16542
  // ))}
15844
16543
  // </ul>
@@ -15879,8 +16578,27 @@ export {
15879
16578
  // paymentMethods = [],
15880
16579
  // trustBadge,
15881
16580
  // bottomLinks = [],
16581
+ // variant = "default",
16582
+ // bottomRightSlot,
16583
+ // linkComponent,
15882
16584
  // ...props
15883
16585
  // }: FooterProps) {
16586
+ // const isBrandFirst = variant === "brand-first"
16587
+ // // ロゴはサイト内トップへの内部遷移なので linkComponent の対象にする(#236)
16588
+ // const LogoLinkTag = resolveLinkComponent(linkComponent)
16589
+ // const brandBlock = (logo || description) && (
16590
+ // <div data-slot="footer-brand" className="grid content-start gap-4">
16591
+ // {logo && (
16592
+ // <LogoLinkTag href={logoHref} className="block w-fit text-[var(--Text-High-Emphasis)]">
16593
+ // {logo}
16594
+ // </LogoLinkTag>
16595
+ // )}
16596
+ // {description && (
16597
+ // <p className="typo-body-sm text-[var(--Text-Low-Emphasis)]">{description}</p>
16598
+ // )}
16599
+ // </div>
16600
+ // )
16601
+ //
15884
16602
  // return (
15885
16603
  // <footer
15886
16604
  // data-slot="footer"
@@ -15898,18 +16616,24 @@ export {
15898
16616
  // */}
15899
16617
  // {linkGroups.length > 0 && (
15900
16618
  // <>
16619
+ // {/* SP: brand-first はブランドブロックを先頭に出す */}
16620
+ // {isBrandFirst && brandBlock && (
16621
+ // <div className="border-t border-[var(--Border-Medium-Emphasis)] px-5 py-8 @lg:hidden">
16622
+ // {brandBlock}
16623
+ // </div>
16624
+ // )}
15901
16625
  // {/* SP: アコーディオン形式(md未満で表示) */}
15902
- // <nav aria-label="フッターナビゲーション" data-slot="footer-links" className="border-t border-[var(--Border-Medium-Emphasis)] @lg:hidden">
16626
+ // <nav aria-label="フッターナビゲーション" data-slot="footer-links" className={cn("border-t border-[var(--Border-Medium-Emphasis)] @lg:hidden", isBrandFirst && "border-t-0")}>
15903
16627
  // {linkGroups.map((group) => (
15904
16628
  // <FooterAccordion key={group.title} title={group.title}>
15905
- // <FooterLinkList links={group.links} />
16629
+ // <FooterLinkList links={group.links} linkComponent={linkComponent} />
15906
16630
  // {/* サブグループ(法人セクション内の催事・マガジン等) */}
15907
16631
  // {group.subGroups?.map((sub) => (
15908
16632
  // <div key={sub.title}>
15909
16633
  // <div className="border-t border-[var(--Border-Low-Emphasis)] px-5 py-5 typo-body-md text-[var(--Text-High-Emphasis)]">
15910
16634
  // {sub.title}
15911
16635
  // </div>
15912
- // <FooterLinkList links={sub.links} />
16636
+ // <FooterLinkList links={sub.links} linkComponent={linkComponent} />
15913
16637
  // </div>
15914
16638
  // ))}
15915
16639
  // </FooterAccordion>
@@ -15924,12 +16648,41 @@ export {
15924
16648
  // className="hidden @lg:block border-t border-[var(--Border-Medium-Emphasis)]"
15925
16649
  // >
15926
16650
  // <div className="mx-auto max-w-[1065px] px-5 py-16">
15927
- // <FooterColumnNav groups={linkGroups} />
15928
- // </div>
15929
- // </nav>
16651
+ // {isBrandFirst ? (
16652
+ // // FooterColumnNav は 1 つの grid 子としてリンク群をまとめて持つ。
16653
+ // // auto-fit だと nav 全体が 1 トラックに潰れて中で再分割されるため、
16654
+ // // ブランド列と nav 領域の比率を明示する(求人サイトの 1.6 : 3.4 相当)。
16655
+ // // brandBlock が無い(logo も description も未指定)ときに 2 カラムへ
16656
+ // // すると nav が 1.6fr のブランド側トラックへ入って左に寄るため、
16657
+ // // その場合は nav 単独レイアウトにする。
16658
+ // <div
16659
+ // className={cn(
16660
+ // "grid gap-8",
16661
+ // brandBlock && "@lg:grid-cols-[minmax(0,1.6fr)_minmax(0,3.4fr)]"
16662
+ // )}
16663
+ // >
16664
+ // {brandBlock}
16665
+ // <FooterColumnNav groups={linkGroups} linkComponent={linkComponent} />
16666
+ // </div>
16667
+ // ) : (
16668
+ // <FooterColumnNav groups={linkGroups} linkComponent={linkComponent} />
16669
+ // )}
16670
+ // </div>
16671
+ // </nav>
15930
16672
  // </>
15931
16673
  // )}
15932
16674
  //
16675
+ // {/* brand-first でリンク群が無いとき、ロゴ・説明文が消えないよう単独で出す
16676
+ // (既定レイアウトは下部バーで出すのでここは通らない) */}
16677
+ // {isBrandFirst && linkGroups.length === 0 && brandBlock && (
16678
+ // <div
16679
+ // data-slot="footer-brand-only"
16680
+ // className="border-t border-[var(--Border-Medium-Emphasis)] px-5 py-8 @lg:py-16"
16681
+ // >
16682
+ // <div className="mx-auto max-w-[1065px]">{brandBlock}</div>
16683
+ // </div>
16684
+ // )}
16685
+ //
15933
16686
  // {/* Social Links (p-footer-item__sns) */}
15934
16687
  // {socialLinks.length > 0 && (
15935
16688
  // <div
@@ -16013,45 +16766,59 @@ export {
16013
16766
  // >
16014
16767
  // <div className="flex flex-wrap items-center justify-center gap-x-3 gap-y-2 @sm:gap-x-4">
16015
16768
  // {bottomLinks.map((link) => (
16016
- // <a
16769
+ // <FooterAnchor
16017
16770
  // key={link.label}
16018
- // href={link.href}
16771
+ // link={link}
16772
+ // linkComponent={linkComponent}
16019
16773
  // className="typo-body-xs text-[var(--Text-Low-Emphasis)] hover:text-[var(--Text-Medium-Emphasis)] transition-colors duration-[var(--Motion-Duration-Fast)]"
16020
- // {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
16021
16774
  // >
16022
16775
  // {link.label}
16023
- // </a>
16776
+ // </FooterAnchor>
16024
16777
  // ))}
16025
16778
  // </div>
16026
16779
  // </div>
16027
16780
  // )}
16028
16781
  //
16029
16782
  // {/* Footer Bottom (p-footer-bottom) */}
16030
- // <div
16031
- // data-slot="footer-bottom"
16032
- // className="border-t border-[var(--Border-Medium-Emphasis)] px-5 pt-8 pb-9 text-center"
16033
- // >
16034
- // {/* Logo */}
16035
- // {logo && (
16036
- // <div className="mx-auto w-fit max-w-[160px]">
16037
- // <a href={logoHref} className="block text-[var(--Text-High-Emphasis)]">
16038
- // {logo}
16039
- // </a>
16783
+ // {isBrandFirst ? (
16784
+ // // ロゴ・説明文はブランド列で出し済みなので、ここはコピーライトと
16785
+ // // bottomRightSlot(Powered by 等)を左右に振り分けるだけにする。
16786
+ // <div
16787
+ // data-slot="footer-bottom"
16788
+ // className="border-t border-[var(--Border-Medium-Emphasis)] px-5 py-5"
16789
+ // >
16790
+ // <div className="mx-auto flex max-w-[1065px] flex-col gap-3 typo-body-sm text-[var(--Text-Low-Emphasis)] @lg:flex-row @lg:items-center @lg:justify-between">
16791
+ // <p>{copyright}</p>
16792
+ // {bottomRightSlot}
16040
16793
  // </div>
16041
- // )}
16794
+ // </div>
16795
+ // ) : (
16796
+ // <div
16797
+ // data-slot="footer-bottom"
16798
+ // className="border-t border-[var(--Border-Medium-Emphasis)] px-5 pt-8 pb-9 text-center"
16799
+ // >
16800
+ // {/* Logo */}
16801
+ // {logo && (
16802
+ // <div className="mx-auto w-fit max-w-[160px]">
16803
+ // <LogoLinkTag href={logoHref} className="block text-[var(--Text-High-Emphasis)]">
16804
+ // {logo}
16805
+ // </LogoLinkTag>
16806
+ // </div>
16807
+ // )}
16042
16808
  //
16043
- // {/* Description */}
16044
- // {description && (
16045
- // <p className="mt-6 typo-body-sm text-[var(--Text-Low-Emphasis)]">
16046
- // {description}
16047
- // </p>
16048
- // )}
16809
+ // {/* Description */}
16810
+ // {description && (
16811
+ // <p className="mt-6 typo-body-sm text-[var(--Text-Low-Emphasis)]">
16812
+ // {description}
16813
+ // </p>
16814
+ // )}
16049
16815
  //
16050
- // {/* Copyright */}
16051
- // <p className="mt-5 typo-body-sm text-[var(--Text-Low-Emphasis)]">
16052
- // {copyright}
16053
- // </p>
16054
- // </div>
16816
+ // {/* Copyright */}
16817
+ // <p className="mt-5 typo-body-sm text-[var(--Text-Low-Emphasis)]">
16818
+ // {copyright}
16819
+ // </p>
16820
+ // </div>
16821
+ // )}
16055
16822
  // </footer>
16056
16823
  // )
16057
16824
  // }
@@ -16059,6 +16826,8 @@ export {
16059
16826
  // export { Footer }
16060
16827
  //
16061
16828
  // src/components/primitives/form-field.tsx
16829
+ // "use client"
16830
+ //
16062
16831
  // /**
16063
16832
  // * ## FormField / フォームフィールド
16064
16833
  // *
@@ -16394,6 +17163,8 @@ export {
16394
17163
  // export { FunnelShell }
16395
17164
  //
16396
17165
  // src/components/primitives/header.tsx
17166
+ // "use client"
17167
+ //
16397
17168
  // import * as React from "react"
16398
17169
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
16399
17170
  // import ArrowLeft from "iconsax-reactjs/dist/esm/ArrowLeft.js"
@@ -16406,6 +17177,13 @@ export {
16406
17177
  // DropdownMenuItem,
16407
17178
  // DropdownMenuTrigger,
16408
17179
  // } from "@/components/foundations/dropdown-menu"
17180
+ // import { containerVariants } from "@/components/primitives/container"
17181
+ //
17182
+ // /**
17183
+ // * ヘッダー内側の最大幅。`Container` の同名 size と同じ値を使う(値の正本は Container)。
17184
+ // * 本文を `Container size="page"` で中央寄せしているサイトで、ロゴ・ナビの左端を本文に揃える。
17185
+ // */
17186
+ // export type HeaderContainerSize = "page" | "wide" | "fluid"
16409
17187
  //
16410
17188
  // export interface HeaderAction {
16411
17189
  // /** アイコン要素 */
@@ -16422,6 +17200,12 @@ export {
16422
17200
  // href?: string
16423
17201
  // /** バッジ数(通知やカート件数) */
16424
17202
  // badge?: React.ReactNode
17203
+ // /**
17204
+ // * `label` をアイコンの右に可視テキストとして出す(既定 false = アイコンのみ)。
17205
+ // * 「ログイン」等、文字が無いと意味が伝わりにくい導線に使う。
17206
+ // * true のときは正方形のアイコンボタンではなく、枠線付きのピル型で描画する。
17207
+ // */
17208
+ // showLabel?: boolean
16425
17209
  // }
16426
17210
  //
16427
17211
  // export interface HeaderNavItem {
@@ -16466,7 +17250,7 @@ export {
16466
17250
  // /**
16467
17251
  // * インラインナビ(navItems / searchSlot 行)を出し始めるコンテナ幅。
16468
17252
  // * - `md`(既定): `@[768px]`+
16469
- // * - `lg` : `@[1024px]`+(ロゴが多段で横幅を食う等、中幅での同居を避けたいとき)
17253
+ // * - `lg` : `@[960px]`+(ロゴが多段で横幅を食う等、中幅での同居を避けたいとき)
16470
17254
  // * 未満の幅では SP 行(ロゴ + actions)になる。
16471
17255
  // */
16472
17256
  // navBreakpoint?: "md" | "lg"
@@ -16480,6 +17264,16 @@ export {
16480
17264
  // * navItems が無く searchSlot だけを渡した場合も PC 行を描画する。
16481
17265
  // */
16482
17266
  // searchSlot?: React.ReactNode
17267
+ // /**
17268
+ // * `searchSlot` を出し始めるコンテナ幅(既定はインラインナビ行と同じ)。
17269
+ // * tokens.json の切替段に一致する `md`(768px)/ `lg`(960px)のみ。
17270
+ // * `xl`(1280) はコンテンツ上限段でレイアウトの切替段ではないため受け付けない。
17271
+ // *
17272
+ // * 中身を consumer 側の CSS で隠しても、このスロットの器は `flex-1` の幅を
17273
+ // * 確保し続けてインラインナビを潰す(#243)。狭い帯で検索を出さない場合は
17274
+ // * CSS ではなくこの prop で器ごと畳むこと。
17275
+ // */
17276
+ // searchBreakpoint?: "md" | "lg"
16483
17277
  // /** 右側に配置するカスタム要素(variant="back"で使用) */
16484
17278
  // rightSlot?: React.ReactNode
16485
17279
  // /** 検索バーなど中央に配置するカスタム要素(variant="back-search"で使用) */
@@ -16492,6 +17286,65 @@ export {
16492
17286
  // bottomSlot?: React.ReactNode
16493
17287
  // /** sticky 配置を無効化 */
16494
17288
  // disableSticky?: boolean
17289
+ // /**
17290
+ // * ヘッダー内側の最大幅(`Container` と同じ段)。
17291
+ // * 指定すると背景・border・sticky は全幅のまま、**中身だけ**を中央寄せする。
17292
+ // * 本文を `Container size="page"` で組んでいるサイトで、ロゴ・ナビの左端が本文と揃う。
17293
+ // * 未指定なら従来どおり全幅(DOM も従来どおりで内側ラッパーを足さない)。
17294
+ // */
17295
+ // containerSize?: HeaderContainerSize
17296
+ // }
17297
+ //
17298
+ // /**
17299
+ // * ヘッダーの外枠。
17300
+ // *
17301
+ // * `containerSize` 指定時は、背景・border・sticky を `<header>` に残したまま、
17302
+ // * 内側だけ `Container` 相当(max-width + mx-auto)で中央寄せする。
17303
+ // * 未指定時はラッパーを足さず、従来の DOM 構造をそのまま保つ。
17304
+ // */
17305
+ // function HeaderShell({
17306
+ // containerSize,
17307
+ // shellClass,
17308
+ // layoutClass,
17309
+ // containerQuery = false,
17310
+ // children,
17311
+ // ...props
17312
+ // }: React.ComponentProps<"header"> & {
17313
+ // containerSize?: HeaderContainerSize
17314
+ // /** sticky / 背景 / border / 利用側 className をまとめたもの(常に全幅側) */
17315
+ // shellClass?: string
17316
+ // /** その variant の行レイアウト(padding 含む)。containerSize 指定時は内側へ移す */
17317
+ // layoutClass?: string
17318
+ // /** @container を張るか(variant="logo" のインラインナビ判定用) */
17319
+ // containerQuery?: boolean
17320
+ // }) {
17321
+ // if (!containerSize) {
17322
+ // return (
17323
+ // <header
17324
+ // data-slot="header"
17325
+ // className={cn(containerQuery && "@container", layoutClass, shellClass)}
17326
+ // {...props}
17327
+ // >
17328
+ // {children}
17329
+ // </header>
17330
+ // )
17331
+ // }
17332
+ //
17333
+ // return (
17334
+ // <header data-slot="header" className={shellClass} {...props}>
17335
+ // <div
17336
+ // data-slot="header-container"
17337
+ // data-container-size={containerSize}
17338
+ // className={cn(
17339
+ // containerQuery && "@container",
17340
+ // containerVariants({ size: containerSize, gutter: "none" }),
17341
+ // layoutClass
17342
+ // )}
17343
+ // >
17344
+ // {children}
17345
+ // </div>
17346
+ // </header>
17347
+ // )
16495
17348
  // }
16496
17349
  //
16497
17350
  // /** ナビ項目の共通クラス(表示用・計測用で同一にしないと退避判定がずれる) */
@@ -16581,21 +17434,30 @@ export {
16581
17434
  //
16582
17435
  // return (
16583
17436
  // <div ref={wrapRef} className="relative min-w-0 flex-1">
16584
- // {/* 計測用の複製(visibility:hidden・absolute なのでレイアウトに影響しない) */}
17437
+ // {/*
17438
+ // 計測用の複製。absolute + invisible は通常フローには影響しないが、絶対配置
17439
+ // 要素も祖先のスクロール可能領域には寄与するため、そのままではページ全体が
17440
+ // 横スクロールする(#243)。0 幅 0 高 + overflow:hidden の器で包んで寄与を
17441
+ // 断つ。クリップは描画時のみでレイアウトは保たれるため計測結果は変わらない。
17442
+ // */}
16585
17443
  // <div
16586
- // ref={measureRef}
16587
17444
  // aria-hidden="true"
16588
- // className="invisible pointer-events-none absolute top-0 left-0 flex w-max items-center gap-0.5"
17445
+ // className="pointer-events-none absolute top-0 left-0 h-0 w-0 overflow-hidden"
16589
17446
  // >
16590
- // {items.map((item) => (
16591
- // <span key={item.label} className={navItemClass(item.isActive)}>
16592
- // {item.label}
17447
+ // <div
17448
+ // ref={measureRef}
17449
+ // className="invisible flex w-max items-center gap-0.5"
17450
+ // >
17451
+ // {items.map((item) => (
17452
+ // <span key={item.label} className={navItemClass(item.isActive)}>
17453
+ // {item.label}
17454
+ // </span>
17455
+ // ))}
17456
+ // <span className={cn(navItemClass(false), "inline-flex items-center gap-1")}>
17457
+ // {overflowLabel}
17458
+ // <ArrowDown2 size={16} />
16593
17459
  // </span>
16594
- // ))}
16595
- // <span className={cn(navItemClass(false), "inline-flex items-center gap-1")}>
16596
- // {overflowLabel}
16597
- // <ArrowDown2 size={16} />
16598
- // </span>
17460
+ // </div>
16599
17461
  // </div>
16600
17462
  //
16601
17463
  // <nav className="flex items-center gap-0.5">
@@ -16672,10 +17534,12 @@ export {
16672
17534
  // navBreakpoint = "md",
16673
17535
  // navOverflowLabel,
16674
17536
  // searchSlot,
17537
+ // searchBreakpoint,
16675
17538
  // rightSlot,
16676
17539
  // centerSlot,
16677
17540
  // bottomSlot,
16678
17541
  // disableSticky = false,
17542
+ // containerSize,
16679
17543
  // ...props
16680
17544
  // }: HeaderProps) {
16681
17545
  // const stickyClass = disableSticky
@@ -16683,13 +17547,25 @@ export {
16683
17547
  // : "sticky top-0 z-[var(--Z-Nav)]"
16684
17548
  //
16685
17549
  // const baseClass =
16686
- // "border-b border-[var(--Border-Low-Emphasis)] bg-[var(--Surface-Primary)]"
17550
+ // // 地は Surface-Elevated: sticky バーはスクロールするコンテンツの上に重なるため
17551
+ // // 不透明が必須(dark の Surface-Primary は 10% 透過で下の文字が透ける)。light は同値
17552
+ // "border-b border-[var(--Border-Low-Emphasis)] bg-[var(--Surface-Elevated)]"
17553
+ //
17554
+ // const shellClass = cn(stickyClass, baseClass, className)
16687
17555
  //
16688
17556
  // // navBreakpoint → コンテナクエリのクラス(Tailwind の静的解析を保つため即値で持つ)
17557
+ // // 切替段は tokens.json の md=768 / lg=960 のみ(1024 は DS に存在しない段)
16689
17558
  // const spRowHiddenClass =
16690
- // navBreakpoint === "lg" ? "@[1024px]:hidden" : "@[768px]:hidden"
17559
+ // navBreakpoint === "lg" ? "@[960px]:hidden" : "@[768px]:hidden"
16691
17560
  // const pcRowVisibleClass =
16692
- // navBreakpoint === "lg" ? "hidden @[1024px]:flex" : "hidden @[768px]:flex"
17561
+ // navBreakpoint === "lg" ? "hidden @[960px]:flex" : "hidden @[768px]:flex"
17562
+ // // searchSlot の器を出す幅。未指定ならナビ行と同じ(=常に描画)。
17563
+ // const searchSlotVisibleClass =
17564
+ // searchBreakpoint === "lg"
17565
+ // ? "hidden @[960px]:block"
17566
+ // : searchBreakpoint === "md"
17567
+ // ? "hidden @[768px]:block"
17568
+ // : undefined
16693
17569
  //
16694
17570
  // /* ── variant: logo ─────────────────────────────── */
16695
17571
  // if (variant === "logo") {
@@ -16701,38 +17577,56 @@ export {
16701
17577
  //
16702
17578
  // const actionsEl = actions && actions.length > 0 && (
16703
17579
  // <div className="flex shrink-0 items-center gap-1">
16704
- // {actions.map((action) =>
16705
- // action.href ? (
17580
+ // {actions.map((action) => {
17581
+ // // showLabel はアイコン+可視テキストのピル。タップターゲット確保のため
17582
+ // // 高さは 40px(h-10)で、正方形の icon-sm とは別サイズにする。
17583
+ // const buttonProps = action.showLabel
17584
+ // ? {
17585
+ // variant: "ghost" as const,
17586
+ // size: "sm" as const,
17587
+ // className:
17588
+ // "h-10 gap-1.5 rounded-full border border-[var(--Border-Medium-Emphasis)] px-4",
17589
+ // }
17590
+ // : { variant: "ghost" as const, size: "icon-sm" as const }
17591
+ // const content = (
17592
+ // <>
17593
+ // {action.badge ? action.badge : action.icon}
17594
+ // {action.showLabel && (
17595
+ // <span className="typo-label-sm">{action.label}</span>
17596
+ // )}
17597
+ // </>
17598
+ // )
17599
+ //
17600
+ // return action.href ? (
16706
17601
  // <Button
16707
17602
  // key={action.label}
16708
17603
  // asChild
16709
- // variant="ghost"
16710
- // size="icon-sm"
16711
- // aria-label={action.label}
17604
+ // {...buttonProps}
17605
+ // aria-label={action.showLabel ? undefined : action.label}
16712
17606
  // >
16713
17607
  // <a href={action.href} onClick={action.onClick}>
16714
- // {action.badge ? action.badge : action.icon}
17608
+ // {content}
16715
17609
  // </a>
16716
17610
  // </Button>
16717
17611
  // ) : (
16718
17612
  // <Button
16719
17613
  // key={action.label}
16720
- // variant="ghost"
16721
- // size="icon-sm"
16722
- // aria-label={action.label}
17614
+ // {...buttonProps}
17615
+ // aria-label={action.showLabel ? undefined : action.label}
16723
17616
  // onClick={action.onClick}
16724
17617
  // >
16725
- // {action.badge ? action.badge : action.icon}
17618
+ // {content}
16726
17619
  // </Button>
16727
17620
  // )
16728
- // )}
17621
+ // })}
16729
17622
  // </div>
16730
17623
  // )
16731
17624
  //
16732
17625
  // return (
16733
- // <header
16734
- // data-slot="header"
16735
- // className={cn(stickyClass, baseClass, "@container", className)}
17626
+ // <HeaderShell
17627
+ // containerSize={containerSize}
17628
+ // shellClass={shellClass}
17629
+ // containerQuery
16736
17630
  // {...props}
16737
17631
  // >
16738
17632
  // {/* SP: ロゴ + アクション(navItems / searchSlot は非表示。SP 検索は bottomSlot で運用) */}
@@ -16744,7 +17638,7 @@ export {
16744
17638
  // {actionsEl}
16745
17639
  // </div>
16746
17640
  //
16747
- // {/* PC(既定 @[768px]+ / navBreakpoint="lg" なら @[1024px]+):
17641
+ // {/* PC(既定 @[768px]+ / navBreakpoint="lg" なら @[960px]+):
16748
17642
  // ロゴ + グローバルナビ + 検索 + アクション(1行)。
16749
17643
  // navItems / searchSlot のどちらかがあれば描画する。 */}
16750
17644
  // {(navItems || searchSlot) && (
@@ -16760,28 +17654,31 @@ export {
16760
17654
  // </div>
16761
17655
  // {/* 検索スロット(navItems と actions の間・伸縮。既存要素を潰さない) */}
16762
17656
  // {searchSlot && (
16763
- // <div className="min-w-0 flex-1 max-w-[400px]">{searchSlot}</div>
17657
+ // <div
17658
+ // className={cn(
17659
+ // "min-w-0 flex-1 max-w-[400px]",
17660
+ // searchSlotVisibleClass
17661
+ // )}
17662
+ // >
17663
+ // {searchSlot}
17664
+ // </div>
16764
17665
  // )}
16765
17666
  // {actionsEl}
16766
17667
  // </div>
16767
17668
  // )}
16768
17669
  //
16769
17670
  // {bottomSlot}
16770
- // </header>
17671
+ // </HeaderShell>
16771
17672
  // )
16772
17673
  // }
16773
17674
  //
16774
17675
  // /* ── variant: logo-center ────────────────────────── */
16775
17676
  // if (variant === "logo-center") {
16776
17677
  // return (
16777
- // <header
16778
- // data-slot="header"
16779
- // className={cn(
16780
- // stickyClass,
16781
- // baseClass,
16782
- // "flex items-center justify-center px-4 py-3",
16783
- // className
16784
- // )}
17678
+ // <HeaderShell
17679
+ // containerSize={containerSize}
17680
+ // shellClass={shellClass}
17681
+ // layoutClass="flex items-center justify-center px-4 py-3"
16785
17682
  // {...props}
16786
17683
  // >
16787
17684
  // {typeof logo === "string" ? (
@@ -16791,27 +17688,25 @@ export {
16791
17688
  // ) : (
16792
17689
  // logo ?? null
16793
17690
  // )}
16794
- // </header>
17691
+ // </HeaderShell>
16795
17692
  // )
16796
17693
  // }
16797
17694
  //
16798
17695
  // /* ── variant: back-search ──────────────────────── */
16799
17696
  // if (variant === "back-search") {
16800
17697
  // return (
16801
- // <header
16802
- // data-slot="header"
16803
- // className={cn(
16804
- // stickyClass,
16805
- // baseClass,
16806
- // "px-4 py-3",
16807
- // className
16808
- // )}
17698
+ // <HeaderShell
17699
+ // containerSize={containerSize}
17700
+ // shellClass={shellClass}
17701
+ // layoutClass="px-4 py-3"
16809
17702
  // {...props}
16810
17703
  // >
16811
17704
  // <div className="flex items-center gap-2">
17705
+ // {/* centerSlot は SearchBar 等の入力コントロール(44px)が入るので、
17706
+ // 戻るボタンも同じ 44px にして高さを揃える(icon-sm=32px だと 12px ずれる) */}
16812
17707
  // <Button
16813
17708
  // variant="ghost"
16814
- // size="icon-sm"
17709
+ // size="icon-xl"
16815
17710
  // aria-label={backLabel}
16816
17711
  // onClick={onBack}
16817
17712
  // >
@@ -16819,7 +17714,7 @@ export {
16819
17714
  // </Button>
16820
17715
  // {centerSlot && <div className="flex-1">{centerSlot}</div>}
16821
17716
  // </div>
16822
- // </header>
17717
+ // </HeaderShell>
16823
17718
  // )
16824
17719
  // }
16825
17720
  //
@@ -16828,14 +17723,10 @@ export {
16828
17723
  // // 左右カラムを等幅にすることで、rightSlot の幅に関わらずタイトルがヘッダー中央に
16829
17724
  // // 正しく揃う(旧 flex-1 text-center は rightSlot が広いとタイトルが左へずれた)。
16830
17725
  // return (
16831
- // <header
16832
- // data-slot="header"
16833
- // className={cn(
16834
- // stickyClass,
16835
- // baseClass,
16836
- // "grid grid-cols-[1fr_auto_1fr] items-center gap-2 px-2 py-3",
16837
- // className
16838
- // )}
17726
+ // <HeaderShell
17727
+ // containerSize={containerSize}
17728
+ // shellClass={shellClass}
17729
+ // layoutClass="grid grid-cols-[1fr_auto_1fr] items-center gap-2 px-2 py-3"
16839
17730
  // {...props}
16840
17731
  // >
16841
17732
  // <div className="justify-self-start">
@@ -16852,13 +17743,15 @@ export {
16852
17743
  // {title}
16853
17744
  // </h1>
16854
17745
  // <div className="justify-self-end">{rightSlot}</div>
16855
- // </header>
17746
+ // </HeaderShell>
16856
17747
  // )
16857
17748
  // }
16858
17749
  //
16859
17750
  // export { Header }
16860
17751
  //
16861
17752
  // src/components/primitives/image-carousel.tsx
17753
+ // "use client"
17754
+ //
16862
17755
  // import * as React from "react"
16863
17756
  // import ArrowLeft2 from "iconsax-reactjs/dist/esm/ArrowLeft2.js"
16864
17757
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
@@ -17111,6 +18004,8 @@ export {
17111
18004
  // export { ImageCarousel }
17112
18005
  //
17113
18006
  // src/components/primitives/image-gallery.tsx
18007
+ // "use client"
18008
+ //
17114
18009
  // import * as React from "react"
17115
18010
  // import ArrowLeft2 from "iconsax-reactjs/dist/esm/ArrowLeft2.js"
17116
18011
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
@@ -17350,6 +18245,8 @@ export {
17350
18245
  // export { ImageGallery }
17351
18246
  //
17352
18247
  // src/components/primitives/image-input.tsx
18248
+ // "use client"
18249
+ //
17353
18250
  // import * as React from "react"
17354
18251
  // import { cva, type VariantProps } from "class-variance-authority"
17355
18252
  // import { Image as ImageIcon, X } from "lucide-react"
@@ -17917,6 +18814,8 @@ export {
17917
18814
  // }
17918
18815
  //
17919
18816
  // src/components/primitives/list-item.tsx
18817
+ // "use client"
18818
+ //
17920
18819
  // import * as React from "react"
17921
18820
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
17922
18821
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
@@ -18139,6 +19038,8 @@ export {
18139
19038
  // export { ListItem }
18140
19039
  //
18141
19040
  // src/components/primitives/menu-drawer.tsx
19041
+ // "use client"
19042
+ //
18142
19043
  // import * as React from "react"
18143
19044
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
18144
19045
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
@@ -18147,6 +19048,7 @@ export {
18147
19048
  // import { X } from "lucide-react"
18148
19049
  //
18149
19050
  // import { cn } from "@/lib/utils"
19051
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
18150
19052
  // import { Button } from "@/components/foundations/button"
18151
19053
  //
18152
19054
  // export interface MenuSection {
@@ -18191,6 +19093,12 @@ export {
18191
19093
  // }
18192
19094
  //
18193
19095
  // export interface MenuDrawerProps extends React.HTMLAttributes<HTMLDivElement> {
19096
+ // /**
19097
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
19098
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
19099
+ // */
19100
+ // linkComponent?: LinkComponent
19101
+ //
18194
19102
  // /** ユーザー名(ログイン時) */
18195
19103
  // userName?: string
18196
19104
  // /** ログイン状態 */
@@ -18247,8 +19155,12 @@ export {
18247
19155
  // onLogin,
18248
19156
  // loginHref = "/security/login_link/",
18249
19157
  // className,
19158
+ // linkComponent,
18250
19159
  // ...props
18251
19160
  // }: MenuDrawerProps) {
19161
+ // // ログイン導線・バナーも内部遷移なので linkComponent の対象にする(#236)
19162
+ // const LoginLinkTag = resolveLinkComponent(linkComponent)
19163
+ // const BannerLinkTag = resolveLinkComponent(linkComponent)
18252
19164
  // const [expandedSections, setExpandedSections] = React.useState<Set<number>>(
18253
19165
  // new Set()
18254
19166
  // )
@@ -18305,7 +19217,7 @@ export {
18305
19217
  // <div className="py-2">
18306
19218
  // <ul>
18307
19219
  // <li>
18308
- // <a
19220
+ // <LoginLinkTag
18309
19221
  // href={loginHref}
18310
19222
  // onClick={
18311
19223
  // onLogin
@@ -18321,7 +19233,7 @@ export {
18321
19233
  // <Add size={16} />
18322
19234
  // </span>
18323
19235
  // <span className="flex-1">ログイン・新規会員登録</span>
18324
- // </a>
19236
+ // </LoginLinkTag>
18325
19237
  // </li>
18326
19238
  // </ul>
18327
19239
  // </div>
@@ -18355,7 +19267,7 @@ export {
18355
19267
  // <ul>
18356
19268
  // {section.items.map((item) => (
18357
19269
  // <li key={item.label}>
18358
- // <MenuItemLink item={item} />
19270
+ // <MenuItemLink linkComponent={linkComponent} item={item} />
18359
19271
  // </li>
18360
19272
  // ))}
18361
19273
  // </ul>
@@ -18367,7 +19279,7 @@ export {
18367
19279
  // <ul>
18368
19280
  // {section.itemsExtra.map((item) => (
18369
19281
  // <li key={item.label}>
18370
- // <MenuItemLink item={item} />
19282
+ // <MenuItemLink linkComponent={linkComponent} item={item} />
18371
19283
  // </li>
18372
19284
  // ))}
18373
19285
  // </ul>
@@ -18401,7 +19313,7 @@ export {
18401
19313
  // <ul className="flex justify-center">
18402
19314
  // {banners.map((banner, i) => (
18403
19315
  // <li key={i} className="w-1/2 max-w-28 px-2">
18404
- // <a
19316
+ // <BannerLinkTag
18405
19317
  // href={banner.href ?? "#"}
18406
19318
  // className="block overflow-hidden rounded"
18407
19319
  // >
@@ -18411,7 +19323,7 @@ export {
18411
19323
  // alt={banner.alt}
18412
19324
  // className="h-auto w-full object-cover"
18413
19325
  // />
18414
- // </a>
19326
+ // </BannerLinkTag>
18415
19327
  // </li>
18416
19328
  // ))}
18417
19329
  // </ul>
@@ -18423,9 +19335,10 @@ export {
18423
19335
  // }
18424
19336
  //
18425
19337
  // /** 個別メニューアイテムのリンク表示 */
18426
- // function MenuItemLink({ item }: { item: MenuItem }) {
19338
+ // function MenuItemLink({ item, linkComponent }: { item: MenuItem; linkComponent?: LinkComponent }) {
19339
+ // const LinkTag = resolveLinkComponent(linkComponent)
18427
19340
  // return (
18428
- // <a
19341
+ // <LinkTag
18429
19342
  // href={item.href ?? "#"}
18430
19343
  // onClick={item.onClick}
18431
19344
  // className={menuRowClass}
@@ -18466,13 +19379,15 @@ export {
18466
19379
  // {item.hasChildren && (
18467
19380
  // <ArrowRight2 size={16} className="shrink-0 text-[var(--Object-High-Emphasis)]" />
18468
19381
  // )}
18469
- // </a>
19382
+ // </LinkTag>
18470
19383
  // )
18471
19384
  // }
18472
19385
  //
18473
19386
  // export { MenuDrawer }
18474
19387
  //
18475
19388
  // src/components/primitives/multi-select.tsx
19389
+ // "use client"
19390
+ //
18476
19391
  // import * as React from "react"
18477
19392
  // import { Check, ChevronsUpDown } from "lucide-react"
18478
19393
  //
@@ -18871,6 +19786,8 @@ export {
18871
19786
  // export { NotificationList }
18872
19787
  //
18873
19788
  // src/components/primitives/number-input.tsx
19789
+ // "use client"
19790
+ //
18874
19791
  // import * as React from "react"
18875
19792
  // import Add from "iconsax-reactjs/dist/esm/Add.js"
18876
19793
  // import Minus from "iconsax-reactjs/dist/esm/Minus.js"
@@ -19511,7 +20428,104 @@ export {
19511
20428
  //
19512
20429
  // export { ProgressSteps }
19513
20430
  //
20431
+ // src/components/primitives/prose.tsx
20432
+ // import * as React from "react"
20433
+ //
20434
+ // import { cn } from "@/lib/utils"
20435
+ //
20436
+ // export interface ProseProps extends React.HTMLAttributes<HTMLElement> {
20437
+ // /**
20438
+ // * CMS(microCMS 等)のリッチテキスト HTML。
20439
+ // *
20440
+ // * **サニタイズ済みの HTML だけを渡すこと。** この部品は体裁を当てるだけで、
20441
+ // * 中身の無害化は行わない(`dangerouslySetInnerHTML` に素通しする)。
20442
+ // * 未指定なら `children` をそのまま包む。
20443
+ // */
20444
+ // html?: string
20445
+ // /** ラップする要素(既定 `div`。記事本文なら `article`) */
20446
+ // as?: "div" | "article" | "section"
20447
+ // }
20448
+ //
20449
+ // /**
20450
+ // * 記事本文の体裁(見出し・段落・リスト・引用・表・画像・リンク)をトークンで揃える。
20451
+ // *
20452
+ // * 各要素の余白・サイズ・線・色を 1 箇所に集約し、記事メディアごとに CSS Modules を
20453
+ // * 書き分けて見た目がばらつくのを防ぐ。`Container size="narrow"`(760px)と
20454
+ // * 組み合わせて使う前提の行長になっている。
20455
+ // *
20456
+ // * ### AI 向け使用ルール
20457
+ // *
20458
+ // * - CMS のリッチテキストを描くときは、consumer 側で `h2` / `p` / `ul` の CSS を書かず
20459
+ // * これを使う(`ArticleBody.module.css` のような独自 CSS を作らない)
20460
+ // * - `html` に渡す HTML は **利用側でサニタイズ済み**であること
20461
+ // * - 記事幅は `Container size="narrow"` で決める。この部品は幅を持たない
20462
+ // * - 見出しレベルは CMS の出力に従う(この部品は体裁だけを当て、階層は変えない)
20463
+ // *
20464
+ // * @example
20465
+ // * <Container size="narrow">
20466
+ // * <Prose as="article" html={sanitizedHtml} />
20467
+ // * </Container>
20468
+ // */
20469
+ // function Prose({ className, html, as: Comp = "div", children, ...props }: ProseProps) {
20470
+ // const proseClass = cn(
20471
+ // // 基本の本文
20472
+ // "typo-body-md text-[var(--Text-High-Emphasis)]",
20473
+ // // 見出し
20474
+ // "[&_h2]:mt-10 [&_h2]:mb-4 [&_h2]:typo-heading-2xl",
20475
+ // "[&_h3]:mt-8 [&_h3]:mb-3 [&_h3]:typo-heading-xl",
20476
+ // "[&_h4]:mt-6 [&_h4]:mb-2 [&_h4]:typo-heading-lg",
20477
+ // "[&_h5]:mt-6 [&_h5]:mb-2 [&_h5]:typo-heading-md",
20478
+ // // 段落・リスト
20479
+ // "[&_p]:my-4",
20480
+ // "[&_ul]:my-4 [&_ul]:list-disc [&_ul]:pl-6",
20481
+ // "[&_ol]:my-4 [&_ol]:list-decimal [&_ol]:pl-6",
20482
+ // "[&_li]:my-1",
20483
+ // // 引用
20484
+ // "[&_blockquote]:my-6 [&_blockquote]:border-l-4 [&_blockquote]:border-[var(--Border-Medium-Emphasis)] [&_blockquote]:pl-4 [&_blockquote]:text-[var(--Text-Medium-Emphasis)]",
20485
+ // // リンク
20486
+ // "[&_a]:text-[var(--Text-Accent-Primary)] [&_a]:underline [&_a]:underline-offset-2 [&_a:hover]:no-underline",
20487
+ // // 画像・図版
20488
+ // "[&_img]:my-6 [&_img]:h-auto [&_img]:w-full [&_img]:rounded-lg",
20489
+ // "[&_figure]:my-6 [&_figcaption]:mt-2 [&_figcaption]:typo-body-sm [&_figcaption]:text-[var(--Text-Medium-Emphasis)]",
20490
+ // // 表。block + w-max + max-w-full で、枠に収まるまで縮み、縮みきれなければ
20491
+ // // 表自身が横スクロールする。どちらの場合もページを横に伸ばさない
20492
+ // "[&_table]:my-6 [&_table]:block [&_table]:w-max [&_table]:max-w-full [&_table]:overflow-x-auto [&_table]:border-collapse",
20493
+ // "[&_th]:border [&_th]:border-[var(--Border-Low-Emphasis)] [&_th]:bg-[var(--Surface-Secondary)] [&_th]:px-3 [&_th]:py-2 [&_th]:text-left [&_th]:typo-label-sm",
20494
+ // "[&_td]:border [&_td]:border-[var(--Border-Low-Emphasis)] [&_td]:px-3 [&_td]:py-2",
20495
+ // // コード
20496
+ // "[&_code]:rounded-xs [&_code]:bg-[var(--Surface-Secondary)] [&_code]:px-1 [&_code]:py-0.5",
20497
+ // "[&_pre]:my-6 [&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:bg-[var(--Surface-Secondary)] [&_pre]:p-4",
20498
+ // "[&_pre_code]:bg-transparent [&_pre_code]:p-0",
20499
+ // // 区切り線
20500
+ // "[&_hr]:my-8 [&_hr]:border-t [&_hr]:border-[var(--Border-Low-Emphasis)]",
20501
+ // // 先頭・末尾は外側の余白と二重にしない
20502
+ // "[&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
20503
+ // className
20504
+ // )
20505
+ //
20506
+ // if (html !== undefined) {
20507
+ // return (
20508
+ // <Comp
20509
+ // data-slot="prose"
20510
+ // className={proseClass}
20511
+ // dangerouslySetInnerHTML={{ __html: html }}
20512
+ // {...props}
20513
+ // />
20514
+ // )
20515
+ // }
20516
+ //
20517
+ // return (
20518
+ // <Comp data-slot="prose" className={proseClass} {...props}>
20519
+ // {children}
20520
+ // </Comp>
20521
+ // )
20522
+ // }
20523
+ //
20524
+ // export { Prose }
20525
+ //
19514
20526
  // src/components/primitives/search-bar.tsx
20527
+ // "use client"
20528
+ //
19515
20529
  // import * as React from "react"
19516
20530
  // import SearchNormal1 from "iconsax-reactjs/dist/esm/SearchNormal1.js"
19517
20531
  //
@@ -19526,6 +20540,17 @@ export {
19526
20540
  // size?: "sm" | "md"
19527
20541
  // /** 検索リンクURL({query} はクエリに置換) */
19528
20542
  // searchHref?: string
20543
+ // /**
20544
+ // * 指定すると `<form method="get" action={action}>` として描画し、素のフォーム送信で遷移する。
20545
+ // * JS を必要としないので、スクリプト無効環境やクローラでも検索が成立する(SEO 重視のサイト向け)。
20546
+ // * 送信するクエリのキーは `name`(既定 `"q"`)。`searchHref` とは併用しない(`action` が優先)。
20547
+ // */
20548
+ // action?: string
20549
+ // /**
20550
+ // * 送信するクエリのキー(`action` 指定時の既定 `"q"`)。
20551
+ // * そのまま input の `name` 属性になる。
20552
+ // */
20553
+ // name?: string
19529
20554
  // }
19530
20555
  //
19531
20556
  // /**
@@ -19546,7 +20571,9 @@ export {
19546
20571
  // * - `size="sm"` はコンパクトなヘッダー向け
19547
20572
  // * - `size="md"` は検索専用ページ向け
19548
20573
  // * - `onSearch` で検索クエリを受け取る
19549
- // * - `searchHref` で検索結果ページへの遷移リンクを生成
20574
+ // * - `searchHref` で検索結果ページへの遷移リンクを生成(JS が必要)
20575
+ // * - **JS 無効環境・SEO を考慮するサイトは `action` を使う**。`<form method="get">` として
20576
+ // * 描画され、素のフォーム送信で遷移する(`Input` + `Button` で `<form>` を手組みしない)
19550
20577
  // */
19551
20578
  // const SearchBar = React.forwardRef<HTMLInputElement, SearchBarProps>(
19552
20579
  // (
@@ -19556,10 +20583,14 @@ export {
19556
20583
  // onSearch,
19557
20584
  // size = "md",
19558
20585
  // searchHref,
20586
+ // action,
20587
+ // name,
19559
20588
  // ...props
19560
20589
  // },
19561
20590
  // ref
19562
20591
  // ) => {
20592
+ // /** action があれば素の GET フォームとして描く(JS 不要で遷移する) */
20593
+ // const isFormMode = !!action
19563
20594
  // const inputRef = React.useRef<HTMLInputElement | null>(null)
19564
20595
  //
19565
20596
  // const setRefs = React.useCallback(
@@ -19584,29 +20615,40 @@ export {
19584
20615
  // }
19585
20616
  //
19586
20617
  // const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
19587
- // if (e.key === "Enter") {
20618
+ // // form モードでは Enter は素のフォーム送信が処理する(ここで遷移すると二重になる)
20619
+ // if (e.key === "Enter" && !isFormMode) {
19588
20620
  // triggerSearch()
19589
20621
  // }
19590
20622
  // props.onKeyDown?.(e)
19591
20623
  // }
19592
20624
  //
19593
- // return (
19594
- // <div
19595
- // data-slot="search-bar"
19596
- // className={cn(
19597
- // "group flex items-center overflow-hidden rounded-lg border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Secondary)] transition-colors",
19598
- // // Tailwind の variant 順では focus-within が hover より先に出力される
19599
- // // = hover が後勝ちしてフォーカス枠を潰すため、hover 側を明示的に抑制する。
19600
- // "hover:not-focus-within:border-[var(--Border-High-Emphasis)]",
19601
- // FOCUS_RING_WITHIN,
19602
- // size === "sm" ? "h-9" : "h-11",
19603
- // className
19604
- // )}
19605
- // >
20625
+ // /** form モードの送信。空クエリは従来どおり無視する */
20626
+ // const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
20627
+ // const query = inputRef.current?.value ?? ""
20628
+ // if (!query.trim()) {
20629
+ // e.preventDefault()
20630
+ // return
20631
+ // }
20632
+ // onSearch?.(query)
20633
+ // }
20634
+ //
20635
+ // const rootClassName = cn(
20636
+ // "group flex items-center overflow-hidden rounded-lg border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Secondary)] transition-colors",
20637
+ // // Tailwind の variant 順では focus-within が hover より先に出力される
20638
+ // // = hover が後勝ちしてフォーカス枠を潰すため、hover 側を明示的に抑制する。
20639
+ // "hover:not-focus-within:border-[var(--Border-High-Emphasis)]",
20640
+ // FOCUS_RING_WITHIN,
20641
+ // size === "sm" ? "h-9" : "h-11",
20642
+ // className
20643
+ // )
20644
+ //
20645
+ // const content = (
20646
+ // <>
19606
20647
  // <input
19607
20648
  // ref={setRefs}
19608
20649
  // type="search"
19609
20650
  // aria-label="キーワード検索"
20651
+ // name={isFormMode ? (name ?? "q") : name}
19610
20652
  // placeholder={placeholder}
19611
20653
  // className={cn(
19612
20654
  // "min-w-0 flex-1 bg-transparent px-3 text-[var(--Text-High-Emphasis)] outline-none placeholder:text-[var(--Text-Low-Emphasis)]",
@@ -19616,18 +20658,40 @@ export {
19616
20658
  // {...props}
19617
20659
  // />
19618
20660
  // <button
19619
- // type="button"
20661
+ // type={isFormMode ? "submit" : "button"}
19620
20662
  // className={cn(
19621
20663
  // "flex shrink-0 items-center justify-center border-l border-[var(--Border-Medium-Emphasis)] text-[var(--Text-Low-Emphasis)] transition-colors outline-none hover:bg-[var(--Surface-Tertiary)] hover:text-[var(--Text-High-Emphasis)]",
19622
20664
  // // 親が overflow-hidden なので外向きリングは切れる。内側に描く。
19623
20665
  // FOCUS_RING_INSET,
19624
20666
  // size === "sm" ? "size-9" : "h-11 w-11"
19625
20667
  // )}
19626
- // onClick={triggerSearch}
20668
+ // onClick={isFormMode ? undefined : triggerSearch}
19627
20669
  // aria-label="検索"
19628
20670
  // >
19629
20671
  // <SearchNormal1 size={size === "sm" ? 14 : 16} />
19630
20672
  // </button>
20673
+ // </>
20674
+ // )
20675
+ //
20676
+ // if (isFormMode) {
20677
+ // return (
20678
+ // <form
20679
+ // data-slot="search-bar"
20680
+ // action={action}
20681
+ // method="get"
20682
+ // // 検索フォームであることを支援技術に伝える標準パターン
20683
+ // role="search"
20684
+ // onSubmit={handleSubmit}
20685
+ // className={rootClassName}
20686
+ // >
20687
+ // {content}
20688
+ // </form>
20689
+ // )
20690
+ // }
20691
+ //
20692
+ // return (
20693
+ // <div data-slot="search-bar" className={rootClassName}>
20694
+ // {content}
19631
20695
  // </div>
19632
20696
  // )
19633
20697
  // }
@@ -19832,7 +20896,8 @@ export {
19832
20896
  // * - セクション見出し(ランキング等): `size="xl"` or `size="lg"`(デフォルト)
19833
20897
  // * - 小見出し・グループラベル: `size="md"` or `size="sm"`
19834
20898
  // * - `as` で見出しレベルを上書き可能(同一ページに h1 が複数必要な場合など)
19835
- // * - `moreHref` 指定時はタイトル+サブタイトル全体がリンクになる(クリック領域拡大)
20899
+ // * - `moreHref` 指定時はタイトル行がリンクになる(クリック領域拡大)。`subtitle` は
20900
+ // * 右側アクションの下も含めた全幅で折り返すため、リンクの外に置く(issue #232)
19836
20901
  // * - `action` に任意の ReactNode(Button 等)を渡して右側にアクションを配置可能
19837
20902
  // * - `align="center"` でランディング/ガイド系の中央寄せ大見出しに切替(`eyebrow` に Badge 等を載せられる)
19838
20903
  // */
@@ -19914,29 +20979,33 @@ export {
19914
20979
  // </div>
19915
20980
  // )
19916
20981
  //
20982
+ // const headingNode = (
20983
+ // <HeadingTag
20984
+ // className={cn(
20985
+ // "text-[var(--Text-High-Emphasis)]",
20986
+ // titleSizeClasses[size],
20987
+ // desktopSize && desktopTitleSizeClasses[desktopSize]
20988
+ // )}
20989
+ // >
20990
+ // {title}
20991
+ // </HeadingTag>
20992
+ // )
20993
+ //
20994
+ // const subtitleNode = subtitle && (
20995
+ // <p
20996
+ // className={cn(
20997
+ // "text-[var(--Text-High-Emphasis)]",
20998
+ // isLargeCaption ? "typo-body-lg" : "typo-body-md"
20999
+ // )}
21000
+ // >
21001
+ // {subtitle}
21002
+ // </p>
21003
+ // )
21004
+ //
19917
21005
  // const titleContent = (
19918
21006
  // <>
19919
- // <HeadingTag
19920
- // className={cn(
19921
- // "text-[var(--Text-High-Emphasis)]",
19922
- // titleSizeClasses[size],
19923
- // desktopSize && desktopTitleSizeClasses[desktopSize]
19924
- // )}
19925
- // >
19926
- // {title}
19927
- // </HeadingTag>
19928
- // {subtitle && (
19929
- // <p
19930
- // className={cn(
19931
- // "text-[var(--Text-High-Emphasis)]",
19932
- // isLargeCaption
19933
- // ? "typo-body-lg"
19934
- // : "typo-body-md"
19935
- // )}
19936
- // >
19937
- // {subtitle}
19938
- // </p>
19939
- // )}
21007
+ // {headingNode}
21008
+ // {subtitleNode}
19940
21009
  // </>
19941
21010
  // )
19942
21011
  //
@@ -19967,17 +21036,23 @@ export {
19967
21036
  // {...props}
19968
21037
  // >
19969
21038
  // {eyebrow}
19970
- // <div className="flex items-baseline justify-between gap-2 min-w-0">
19971
- // {wrapTitleWithLink ? (
19972
- // <a href={moreHref} className="flex min-w-0 flex-1 flex-col gap-1">
19973
- // {titleContent}
19974
- // </a>
19975
- // ) : (
19976
- // <div className="flex min-w-0 flex-1 flex-col gap-1">
19977
- // {titleContent}
19978
- // </div>
19979
- // )}
19980
- // {trailingControls}
21039
+ // {/*
21040
+ // タイトル行(タイトル + もっと見る/action)と subtitle を別の行に分ける。
21041
+ // 同じ Flex 行に入れると subtitle まで action の幅ぶん狭まり、右側に空きが
21042
+ // あるのに早い位置で折り返していた(issue #232)。
21043
+ // */}
21044
+ // <div className="flex flex-col gap-1">
21045
+ // <div className="flex items-baseline justify-between gap-2 min-w-0">
21046
+ // {wrapTitleWithLink ? (
21047
+ // <a href={moreHref} className="min-w-0 flex-1">
21048
+ // {headingNode}
21049
+ // </a>
21050
+ // ) : (
21051
+ // <div className="min-w-0 flex-1">{headingNode}</div>
21052
+ // )}
21053
+ // {trailingControls}
21054
+ // </div>
21055
+ // {subtitleNode}
19981
21056
  // </div>
19982
21057
  // </div>
19983
21058
  // )
@@ -20318,6 +21393,8 @@ export {
20318
21393
  // export { Section, sectionVariants, sectionScrimVariants }
20319
21394
  //
20320
21395
  // src/components/primitives/share-buttons.tsx
21396
+ // "use client"
21397
+ //
20321
21398
  // import * as React from "react"
20322
21399
  // import Link2 from "iconsax-reactjs/dist/esm/Link2.js"
20323
21400
  //
@@ -20325,12 +21402,34 @@ export {
20325
21402
  // import { Button } from "@/components/foundations/button"
20326
21403
  // import { SocialIcon } from "@/components/foundations/social-icon"
20327
21404
  //
21405
+ // /** 組み込みの共有先 */
21406
+ // export type ShareService = "line" | "x" | "facebook" | "hatena" | "copy"
21407
+ //
21408
+ // /** 組み込みに無い共有先を足すための指定 */
21409
+ // export interface ShareCustomService {
21410
+ // /** 一意なキー(React の key に使う) */
21411
+ // key: string
21412
+ // /** ボタンの可視ラベル */
21413
+ // label: string
21414
+ // /** 共有先 URL。`{url}` / `{text}` は共有対象に置換される(どちらも URL エンコード済み) */
21415
+ // href: string
21416
+ // /** ラベル左のアイコン */
21417
+ // icon?: React.ReactNode
21418
+ // /** 読み上げ名(未指定ならラベルをそのまま使う) */
21419
+ // ariaLabel?: string
21420
+ // }
21421
+ //
20328
21422
  // export interface ShareButtonsProps
20329
21423
  // extends Omit<React.HTMLAttributes<HTMLDivElement>, "onCopy"> {
20330
21424
  // /** シェアURL */
20331
21425
  // url?: string
20332
21426
  // /** シェアテキスト */
20333
21427
  // text?: string
21428
+ // /**
21429
+ // * 表示する共有先と並び順(既定 `["line", "x", "copy"]`)。
21430
+ // * 組み込みに無い共有先は `ShareCustomService` を混ぜて足す。
21431
+ // */
21432
+ // services?: Array<ShareService | ShareCustomService>
20334
21433
  // /** コピーボタンのラベル */
20335
21434
  // copyLabel?: string
20336
21435
  // /** コピー成功時に一時表示するラベル(約2秒) */
@@ -20341,22 +21440,68 @@ export {
20341
21440
  // onCopy?: (result: "success" | "error") => void
20342
21441
  // }
20343
21442
  //
21443
+ // const DEFAULT_SERVICES: ShareService[] = ["line", "x", "copy"]
21444
+ //
21445
+ // /** 組み込み共有先の共有 URL・ラベル・アイコン */
21446
+ // const SHARE_TARGETS: Record<
21447
+ // Exclude<ShareService, "copy">,
21448
+ // {
21449
+ // label: string
21450
+ // ariaLabel: string
21451
+ // href: (url: string, text: string) => string
21452
+ // icon: React.ReactNode
21453
+ // }
21454
+ // > = {
21455
+ // line: {
21456
+ // label: "LINE",
21457
+ // ariaLabel: "LINEでシェア",
21458
+ // href: (url) =>
21459
+ // `https://social-plugins.line.me/lineit/share?url=${encodeURIComponent(url)}`,
21460
+ // icon: <SocialIcon platform="line" size={16} />,
21461
+ // },
21462
+ // x: {
21463
+ // label: "X",
21464
+ // ariaLabel: "Xでシェア",
21465
+ // href: (url, text) =>
21466
+ // `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`,
21467
+ // // X のブランド色は黒固定でダーク地に溶けるため、地の文字色に追従させる
21468
+ // icon: <SocialIcon platform="x" size={14} tone="mono" />,
21469
+ // },
21470
+ // facebook: {
21471
+ // label: "Facebook",
21472
+ // ariaLabel: "Facebookでシェア",
21473
+ // href: (url) =>
21474
+ // `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`,
21475
+ // icon: <SocialIcon platform="facebook" size={16} />,
21476
+ // },
21477
+ // hatena: {
21478
+ // label: "はてブ",
21479
+ // ariaLabel: "はてなブックマークに追加",
21480
+ // href: (url, text) =>
21481
+ // `https://b.hatena.ne.jp/entry/panel/?url=${encodeURIComponent(url)}&title=${encodeURIComponent(text)}`,
21482
+ // icon: <SocialIcon platform="hatena" size={16} />,
21483
+ // },
21484
+ // }
21485
+ //
20344
21486
  // /**
20345
21487
  // * シェアボタンコンポーネント
20346
21488
  // *
20347
- // * 商品をSNSやURLでシェアするためのボタン群。
20348
- // * LINE、X(Twitter)、URLコピーに対応。
21489
+ // * 記事や商品を SNS・URL コピーで共有するためのボタン群。
20349
21490
  // *
20350
21491
  // * ### AI 向け使用ルール
20351
21492
  // *
20352
- // * - 商品詳細ページの共有セクションに使用
21493
+ // * - 商品詳細ページ・記事ページの共有セクションに使用
20353
21494
  // * - `url` と `text` でシェア内容を指定
21495
+ // * - 共有先は `services` で選ぶ(既定は LINE / X / コピー)。
21496
+ // * **同じ意匠を `Button asChild` で組み直さない**
21497
+ // * - 組み込みに無い共有先は `services` に `{ key, label, href, icon }` を混ぜて足す
20354
21498
  // * - ボタンは横並び、等幅表示
20355
21499
  // */
20356
21500
  // function ShareButtons({
20357
21501
  // className,
20358
21502
  // url = "",
20359
21503
  // text = "",
21504
+ // services = DEFAULT_SERVICES,
20360
21505
  // copyLabel = "URLをコピー",
20361
21506
  // copiedLabel = "コピーしました",
20362
21507
  // copyErrorLabel = "コピーできませんでした",
@@ -20398,59 +21543,70 @@ export {
20398
21543
  // ? copyErrorLabel
20399
21544
  // : copyLabel
20400
21545
  //
21546
+ // const renderLink = (
21547
+ // key: string,
21548
+ // href: string,
21549
+ // ariaLabel: string,
21550
+ // icon: React.ReactNode,
21551
+ // label: string
21552
+ // ) => (
21553
+ // <Button key={key} variant="tertiary" size="sm" className="flex-1 gap-1.5" asChild>
21554
+ // <a href={href} target="_blank" rel="noopener noreferrer" aria-label={ariaLabel}>
21555
+ // {icon}
21556
+ // <span className="typo-body-sm">{label}</span>
21557
+ // </a>
21558
+ // </Button>
21559
+ // )
21560
+ //
20401
21561
  // return (
20402
21562
  // <div
20403
21563
  // data-slot="share-buttons"
20404
21564
  // className={cn("flex items-center gap-2", className)}
20405
21565
  // {...props}
20406
21566
  // >
20407
- // <Button
20408
- // variant="tertiary"
20409
- // size="sm"
20410
- // className="flex-1 gap-1.5"
20411
- // asChild
20412
- // >
20413
- // <a
20414
- // href={`https://social-plugins.line.me/lineit/share?url=${encodeURIComponent(url)}`}
20415
- // target="_blank"
20416
- // rel="noopener noreferrer"
20417
- // aria-label="LINEでシェア"
20418
- // >
20419
- // <SocialIcon platform="line" size={16} />
20420
- // <span className="typo-body-sm">LINE</span>
20421
- // </a>
20422
- // </Button>
20423
- // <Button
20424
- // variant="tertiary"
20425
- // size="sm"
20426
- // className="flex-1 gap-1.5"
20427
- // asChild
20428
- // >
20429
- // <a
20430
- // href={`https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`}
20431
- // target="_blank"
20432
- // rel="noopener noreferrer"
20433
- // aria-label="Xでシェア"
20434
- // >
20435
- // {/* X のブランド色は黒固定でダーク地に溶けるため、地の文字色に追従させる */}
20436
- // <SocialIcon platform="x" size={14} tone="mono" />
20437
- // <span className="typo-body-sm">X</span>
20438
- // </a>
20439
- // </Button>
20440
- // {/* aria-label は付けない: 可視ラベルが「コピーしました/できませんでした」に変わるため、
20441
- // 固定 aria-label だとアクセシブル名と可視名が食い違う(WCAG 2.5.3 Label in Name)。
20442
- // アクセシブル名は可視テキスト(aria-live で読み上げ更新)に委ねる。 */}
20443
- // <Button
20444
- // variant="tertiary"
20445
- // size="sm"
20446
- // className="flex-1 gap-1.5"
20447
- // onClick={handleCopy}
20448
- // >
20449
- // <Link2 size={14} aria-hidden="true" />
20450
- // <span className="typo-body-sm" aria-live="polite">
20451
- // {copyButtonLabel}
20452
- // </span>
20453
- // </Button>
21567
+ // {services.map((service) => {
21568
+ // if (typeof service !== "string") {
21569
+ // const href = service.href
21570
+ // .replace("{url}", encodeURIComponent(url))
21571
+ // .replace("{text}", encodeURIComponent(text))
21572
+ // return renderLink(
21573
+ // service.key,
21574
+ // href,
21575
+ // service.ariaLabel ?? service.label,
21576
+ // service.icon,
21577
+ // service.label
21578
+ // )
21579
+ // }
21580
+ //
21581
+ // if (service === "copy") {
21582
+ // // aria-label は付けない: 可視ラベルが「コピーしました/できませんでした」に変わるため、
21583
+ // // 固定 aria-label だとアクセシブル名と可視名が食い違う(WCAG 2.5.3 Label in Name)。
21584
+ // // アクセシブル名は可視テキスト(aria-live で読み上げ更新)に委ねる。
21585
+ // return (
21586
+ // <Button
21587
+ // key="copy"
21588
+ // variant="tertiary"
21589
+ // size="sm"
21590
+ // className="flex-1 gap-1.5"
21591
+ // onClick={handleCopy}
21592
+ // >
21593
+ // <Link2 size={14} aria-hidden="true" />
21594
+ // <span className="typo-body-sm" aria-live="polite">
21595
+ // {copyButtonLabel}
21596
+ // </span>
21597
+ // </Button>
21598
+ // )
21599
+ // }
21600
+ //
21601
+ // const target = SHARE_TARGETS[service]
21602
+ // return renderLink(
21603
+ // service,
21604
+ // target.href(url, text),
21605
+ // target.ariaLabel,
21606
+ // target.icon,
21607
+ // target.label
21608
+ // )
21609
+ // })}
20454
21610
  // </div>
20455
21611
  // )
20456
21612
  // }
@@ -20895,6 +22051,8 @@ export {
20895
22051
  // export { StandardPageShell }
20896
22052
  //
20897
22053
  // src/components/primitives/status-count-tabs.tsx
22054
+ // "use client"
22055
+ //
20898
22056
  // /**
20899
22057
  // * ## StatusCountTabs / ステータスカウントタブ
20900
22058
  // *
@@ -20993,7 +22151,8 @@ export {
20993
22151
  // <div
20994
22152
  // data-slot="sticky-action-bar"
20995
22153
  // className={cn(
20996
- // "sticky bottom-0 z-[var(--Z-Nav)] bg-[var(--Surface-Primary)] px-4 py-3 pb-[max(0.75rem,env(safe-area-inset-bottom))]",
22154
+ // // Surface-Elevated: スクロール内容の上に重なる固定バーは不透明が必須(dark で透けない)
22155
+ // "sticky bottom-0 z-[var(--Z-Nav)] bg-[var(--Surface-Elevated)] px-4 py-3 pb-[max(0.75rem,env(safe-area-inset-bottom))]",
20997
22156
  // bordered && "border-t border-[var(--Border-Low-Emphasis)]",
20998
22157
  // className
20999
22158
  // )}
@@ -21010,6 +22169,11 @@ export {
21010
22169
  // import * as React from "react"
21011
22170
  //
21012
22171
  // import { cn } from "@/lib/utils"
22172
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
22173
+ // import { containerVariants } from "@/components/primitives/container"
22174
+ //
22175
+ // /** `Container` の gutter(SP 16 / PC 24)。本文の左端と揃えるための正本 */
22176
+ // const GUTTER_CLASS = "px-4 md:px-6"
21013
22177
  //
21014
22178
  // export interface SubNavItem {
21015
22179
  // /** 表示ラベル */
@@ -21024,10 +22188,23 @@ export {
21024
22188
  //
21025
22189
  // export interface SubNavProps
21026
22190
  // extends React.HTMLAttributes<HTMLDivElement> {
22191
+ // /**
22192
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
22193
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
22194
+ // */
22195
+ // linkComponent?: LinkComponent
22196
+ //
21027
22197
  // /** ナビゲーション項目 */
21028
22198
  // items: SubNavItem[]
21029
22199
  // /** スタイルバリアント */
21030
22200
  // variant?: "text" | "chip"
22201
+ // /**
22202
+ // * ナビ内側の最大幅(`Container` と同じ段)。
22203
+ // * 指定すると下線(border)は全幅のまま、**中身だけ**を中央寄せする。
22204
+ // * 本文を `Container size="page"` で組んでいるサイトで、項目の左端が本文と揃う。
22205
+ // * 未指定なら従来どおり全幅(DOM も従来どおりで内側ラッパーを足さない)。
22206
+ // */
22207
+ // containerSize?: "page" | "wide" | "fluid"
21031
22208
  // }
21032
22209
  //
21033
22210
  // /**
@@ -21044,81 +22221,100 @@ export {
21044
22221
  // * - アクティブ項目は `isActive: true` で下線を強調
21045
22222
  // * - テキスト色: アクティブ = 黒(High-Emphasis)、非アクティブ = グレー(Medium-Emphasis)
21046
22223
  // * - 必ず `overflow-x-auto` + `scrollbar-hide` で横スクロール対応
22224
+ // * - 左右の余白は `Container` と同じ(SP 16 / PC 24)。本文を `Container` で中央寄せしている
22225
+ // * サイトでは `containerSize="page"` を指定すると項目の左端が本文と揃う
21047
22226
  // */
21048
22227
  // function SubNav({
21049
22228
  // className,
21050
22229
  // items,
21051
22230
  // variant = "text",
22231
+ // linkComponent,
22232
+ // containerSize,
21052
22233
  // ...props
21053
22234
  // }: SubNavProps) {
21054
- // if (variant === "chip") {
21055
- // return (
21056
- // <div
21057
- // data-slot="sub-nav"
21058
- // className={cn(
21059
- // "flex gap-2 overflow-x-auto px-4 py-2 scrollbar-hide",
21060
- // className
21061
- // )}
21062
- // {...props}
21063
- // >
21064
- // {items.map((item) => {
21065
- // const Comp = item.href ? "a" : "button"
21066
- // const compProps = item.href
21067
- // ? { href: item.href }
21068
- // : { type: "button" as const, onClick: item.onClick }
21069
- // return (
21070
- // <Comp
21071
- // key={item.label}
21072
- // className={cn(
21073
- // "shrink-0 rounded-full px-3 typo-label-sm transition-colors h-8 inline-flex items-center justify-center",
21074
- // item.isActive
21075
- // ? "bg-[var(--Brand-Cake-Orange)] text-[var(--Text-on-Inverse)]"
21076
- // : "bg-[var(--Surface-Secondary)] text-[var(--Text-Medium-Emphasis)] hover:bg-[var(--Surface-Tertiary)]"
21077
- // )}
21078
- // {...compProps}
21079
- // >
21080
- // {item.label}
21081
- // </Comp>
21082
- // )
21083
- // })}
21084
- // </div>
21085
- // )
21086
- // }
21087
- //
21088
- // // text variant (production default)
21089
- // return (
21090
- // <nav
21091
- // data-slot="sub-nav"
21092
- // className={cn(
21093
- // "flex gap-4 overflow-x-auto border-b border-[var(--Border-Low-Emphasis)] px-4 scrollbar-hide",
21094
- // className
21095
- // )}
21096
- // {...props}
21097
- // >
21098
- // {items.map((item) => {
21099
- // const Comp = item.href ? "a" : "button"
21100
- // const compProps = item.href
21101
- // ? { href: item.href }
21102
- // : { type: "button" as const, onClick: item.onClick }
22235
+ // const renderItems = () =>
22236
+ // items.map((item) => {
22237
+ // const Comp = item.href ? resolveLinkComponent(linkComponent) : "button"
22238
+ // const compProps = item.href
22239
+ // ? { href: item.href }
22240
+ // : { type: "button" as const, onClick: item.onClick }
22241
+ //
22242
+ // if (variant === "chip") {
21103
22243
  // return (
21104
22244
  // <Comp
21105
22245
  // key={item.label}
21106
22246
  // className={cn(
21107
- // "relative shrink-0 py-2.5 typo-label-md transition-colors",
22247
+ // "shrink-0 rounded-full px-3 typo-label-sm transition-colors h-8 inline-flex items-center justify-center",
21108
22248
  // item.isActive
21109
- // ? "text-[var(--Text-High-Emphasis)]"
21110
- // : "text-[var(--Text-Medium-Emphasis)] hover:text-[var(--Text-High-Emphasis)]"
22249
+ // ? "bg-[var(--Brand-Cake-Orange)] text-[var(--Text-on-Inverse)]"
22250
+ // : "bg-[var(--Surface-Secondary)] text-[var(--Text-Medium-Emphasis)] hover:bg-[var(--Surface-Tertiary)]"
21111
22251
  // )}
21112
22252
  // {...compProps}
21113
22253
  // >
21114
22254
  // {item.label}
21115
- // {item.isActive && (
21116
- // <span className="absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-[var(--Text-High-Emphasis)]" />
21117
- // )}
21118
22255
  // </Comp>
21119
22256
  // )
21120
- // })}
21121
- // </nav>
22257
+ // }
22258
+ //
22259
+ // return (
22260
+ // <Comp
22261
+ // key={item.label}
22262
+ // className={cn(
22263
+ // "relative shrink-0 py-2.5 typo-label-md transition-colors",
22264
+ // item.isActive
22265
+ // ? "text-[var(--Text-High-Emphasis)]"
22266
+ // : "text-[var(--Text-Medium-Emphasis)] hover:text-[var(--Text-High-Emphasis)]"
22267
+ // )}
22268
+ // {...compProps}
22269
+ // >
22270
+ // {item.label}
22271
+ // {item.isActive && (
22272
+ // <span className="absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-[var(--Text-High-Emphasis)]" />
22273
+ // )}
22274
+ // </Comp>
22275
+ // )
22276
+ // })
22277
+ //
22278
+ // const isChip = variant === "chip"
22279
+ // const Root = isChip ? "div" : "nav"
22280
+ //
22281
+ // /** 項目を並べる行(横スクロール・左右 gutter を持つ) */
22282
+ // const rowClass = isChip
22283
+ // ? cn("flex gap-2 overflow-x-auto py-2 scrollbar-hide", GUTTER_CLASS)
22284
+ // : cn("flex gap-4 overflow-x-auto scrollbar-hide", GUTTER_CLASS)
22285
+ //
22286
+ // /** 外枠が常に持つ装飾(全幅で描く) */
22287
+ // const decorationClass = isChip
22288
+ // ? undefined
22289
+ // : "border-b border-[var(--Border-Low-Emphasis)]"
22290
+ //
22291
+ // // containerSize 指定時は、下線を外枠に残したまま内側だけ Container 相当で中央寄せする。
22292
+ // // 未指定時はラッパーを足さず従来の DOM 構造をそのまま保つ(#234)。
22293
+ // if (containerSize) {
22294
+ // return (
22295
+ // <Root data-slot="sub-nav" className={cn(decorationClass, className)} {...props}>
22296
+ // <div
22297
+ // data-slot="sub-nav-container"
22298
+ // data-container-size={containerSize}
22299
+ // className={cn(
22300
+ // containerVariants({ size: containerSize, gutter: "none" }),
22301
+ // rowClass
22302
+ // )}
22303
+ // >
22304
+ // {renderItems()}
22305
+ // </div>
22306
+ // </Root>
22307
+ // )
22308
+ // }
22309
+ //
22310
+ // return (
22311
+ // <Root
22312
+ // data-slot="sub-nav"
22313
+ // className={cn(decorationClass, rowClass, className)}
22314
+ // {...props}
22315
+ // >
22316
+ // {renderItems()}
22317
+ // </Root>
21122
22318
  // )
21123
22319
  // }
21124
22320
  //
@@ -22247,7 +23443,29 @@ export {
22247
23443
  // export { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./components/foundations/collapsible"
22248
23444
  // export { Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut } from "./components/foundations/command"
22249
23445
  // export { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger } from "./components/foundations/context-menu"
22250
- // export { DataTable } from "./components/foundations/data-table"
23446
+ // export {
23447
+ // DataTable,
23448
+ // DataTableTable,
23449
+ // DataTableHeader,
23450
+ // DataTableBody,
23451
+ // DataTableRow,
23452
+ // DataTableHead,
23453
+ // DataTableCell,
23454
+ // DataTableAvatarCell,
23455
+ // DataTableImageCell,
23456
+ // DataTableLinkCell,
23457
+ // DataTableCheckboxCell,
23458
+ // DataTableActionCell,
23459
+ // DataTableInputCell,
23460
+ // DataTableSelectCell,
23461
+ // DataTableNumberCell,
23462
+ // DataTableDragHandleCell,
23463
+ // DataTableBulkActions,
23464
+ // DataTableSectionRow,
23465
+ // DataTableAddRow,
23466
+ // DataTableEmptyState,
23467
+ // } from "./components/foundations/data-table"
23468
+ // export type { SortDirection } from "./components/foundations/data-table"
22251
23469
  // export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from "./components/foundations/dialog"
22252
23470
  // export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger } from "./components/foundations/drawer"
22253
23471
  // export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from "./components/foundations/dropdown-menu"
@@ -22322,6 +23540,14 @@ export {
22322
23540
  // export type { ChatComposerProps, ChatComposerAttachmentError } from "./components/primitives/chat-composer"
22323
23541
  // export { Chip, chipVariants } from "./components/primitives/chip"
22324
23542
  // export type { ChipProps } from "./components/primitives/chip"
23543
+ // export { Prose } from "./components/primitives/prose"
23544
+ // export type { ProseProps } from "./components/primitives/prose"
23545
+ // export { ContentCard, ContentList } from "./components/primitives/content-card"
23546
+ // export type {
23547
+ // ContentCardProps,
23548
+ // ContentCardOrientation,
23549
+ // ContentCardAspect,
23550
+ // } from "./components/primitives/content-card"
22325
23551
  // export { StandardPageShell } from "./components/primitives/standard-page-shell"
22326
23552
  // export type { StandardPageShellProps } from "./components/primitives/standard-page-shell"
22327
23553
  // /**
@@ -22444,7 +23670,7 @@ export {
22444
23670
  // export type { OrderSummaryProps, OrderSummaryLineItem } from "./components/ec/order-summary"
22445
23671
  // export { PaymentMethodDisplay, CreditCardIcon } from "./components/ec/payment-method"
22446
23672
  // export type { PaymentMethodDisplayProps, CreditCardIconProps, CreditCardBrand } from "./components/ec/payment-method"
22447
- // export { ProductCard } from "./components/ec/product-card"
23673
+ // export { ProductCard, BookmarkRibbonIcon } from "./components/ec/product-card"
22448
23674
  // export type { ProductCardProps } from "./components/ec/product-card"
22449
23675
  // export { ProductCarousel } from "./components/ec/product-carousel"
22450
23676
  // export type { ProductCarouselProps } from "./components/ec/product-carousel"
@@ -22475,6 +23701,8 @@ export {
22475
23701
  // export type { StatCardProps } from "./components/ec/stat-card"
22476
23702
  //
22477
23703
  // src/lib/field-labelling.ts
23704
+ // "use client"
23705
+ //
22478
23706
  // /**
22479
23707
  // * ## フィールドのラベル関連付け(DS 全体の方針 / issue #202)
22480
23708
  // *
@@ -22624,6 +23852,51 @@ export {
22624
23852
  // export const FOCUS_RING_INSET =
22625
23853
  // "focus-visible:ring-[3px] focus-visible:ring-inset focus-visible:ring-[var(--Focus-High-Emphasis)]/50"
22626
23854
  //
23855
+ // src/lib/link-component.ts
23856
+ // import type * as React from "react"
23857
+ //
23858
+ // /**
23859
+ // * リンクの描画に使うコンポーネント(#236)
23860
+ // *
23861
+ // * DS 内でリンクを複数描く部品(Footer / MenuDrawer / SubNav / Pagination)は
23862
+ // * 素の `<a>` を描くため、Next.js の `next/link` 等を差し込めずクライアント遷移に
23863
+ // * ならない。`asChild` は複数リンクを内部で描く部品には向かないため、
23864
+ // * 「リンク実装そのもの」を差し替える prop を共通の型で用意する。
23865
+ // *
23866
+ // * 例: `<Footer linkComponent={Link} … />`(next/link をそのまま渡せる)
23867
+ // *
23868
+ // * ⚠️ `Footer` / `MenuDrawer` は Client Component。React Server Components では
23869
+ // * Server Component からこの prop を渡すと client 境界を越えて関数を渡すことに
23870
+ // * なり、`Functions cannot be passed directly to Client Components` で落ちる。
23871
+ // * Next.js App Router では、この prop を使う呼び出し側を `"use client"` にする
23872
+ // * (エラーメッセージは `"use server"` を示唆するが、正解は逆)。
23873
+ // *
23874
+ // * `Pagination` / `SubNav` / `ContentCard` は Server Component のまま使えるため、
23875
+ // * この prop を使うだけで呼び出し側を `"use client"` にする必要はない。
23876
+ // */
23877
+ // export type LinkComponent = React.ComponentType<
23878
+ // React.AnchorHTMLAttributes<HTMLAnchorElement> & { href: string }
23879
+ // >
23880
+ //
23881
+ // /**
23882
+ // * 実際に使うリンク実装を決める。
23883
+ // *
23884
+ // * 外部リンク(`target="_blank"` を付けるもの)は framework のリンク部品に通す
23885
+ // * 意味が無いため、常に素の `<a>` にフォールバックする。
23886
+ // *
23887
+ // * `isExternal` を渡せるのは、項目に `external` フラグを持つ `Footer` だけ。
23888
+ // * MenuDrawer / SubNav / Pagination の項目に `external` は無く、渡した href は
23889
+ // * すべて `linkComponent` で描かれる(外部 URL を出し分けたい場合は consumer 側で
23890
+ // * ラップする)。
23891
+ // */
23892
+ // export function resolveLinkComponent(
23893
+ // linkComponent: LinkComponent | undefined,
23894
+ // isExternal?: boolean
23895
+ // ): React.ElementType {
23896
+ // if (isExternal || !linkComponent) return "a"
23897
+ // return linkComponent
23898
+ // }
23899
+ //
22627
23900
  // src/lib/pagination-range.ts
22628
23901
  // export type PaginationRangeItem = number | "ellipsis"
22629
23902
  //
@@ -22755,6 +24028,8 @@ export {
22755
24028
  // } as const
22756
24029
  //
22757
24030
  // src/lib/use-value-length.ts
24031
+ // "use client"
24032
+ //
22758
24033
  // import * as React from "react"
22759
24034
  //
22760
24035
  // type CountableElement = HTMLInputElement | HTMLTextAreaElement