@cakejp/design-system 0.17.1 → 0.19.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 (88) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/CLAUDE.md +15 -0
  3. package/contracts/components.json +144 -16
  4. package/contracts/composition.json +1 -1
  5. package/contracts/rules.json +5 -1
  6. package/contracts/screen-patterns.json +1 -1
  7. package/dist/components/ec/admin-shell.js +7 -6
  8. package/dist/components/ec/product-card.js +107 -102
  9. package/dist/components/ec/product-option.js +1 -0
  10. package/dist/components/ec/review-card.js +22 -20
  11. package/dist/components/ec/review-form.js +1 -0
  12. package/dist/components/foundations/accordion.js +23 -22
  13. package/dist/components/foundations/alert.js +1 -0
  14. package/dist/components/foundations/aspect-ratio.js +3 -2
  15. package/dist/components/foundations/avatar.js +1 -0
  16. package/dist/components/foundations/button.js +7 -1
  17. package/dist/components/foundations/calendar.js +1 -0
  18. package/dist/components/foundations/checkbox-group.js +1 -0
  19. package/dist/components/foundations/checkbox.js +1 -0
  20. package/dist/components/foundations/command.js +1 -0
  21. package/dist/components/foundations/context-menu.js +1 -0
  22. package/dist/components/foundations/drawer.js +1 -0
  23. package/dist/components/foundations/file-input.js +1 -0
  24. package/dist/components/foundations/form.js +26 -25
  25. package/dist/components/foundations/pagination.js +49 -46
  26. package/dist/components/foundations/popover.js +9 -8
  27. package/dist/components/foundations/radio-group.js +3 -2
  28. package/dist/components/foundations/responsive-dialog.js +1 -0
  29. package/dist/components/foundations/separator.js +7 -6
  30. package/dist/components/foundations/sheet.js +40 -33
  31. package/dist/components/foundations/slider.js +7 -6
  32. package/dist/components/foundations/social-icon.js +30 -10
  33. package/dist/components/foundations/sonner.js +5 -4
  34. package/dist/components/foundations/tabs.js +45 -25
  35. package/dist/components/foundations/toggle-group.js +6 -5
  36. package/dist/components/primitives/admin-side-nav.js +1 -0
  37. package/dist/components/primitives/chat-composer.js +1 -0
  38. package/dist/components/primitives/combobox.js +1 -0
  39. package/dist/components/primitives/content-card.js +111 -0
  40. package/dist/components/primitives/content-carousel.js +9 -8
  41. package/dist/components/primitives/date-picker.js +9 -8
  42. package/dist/components/primitives/footer.js +169 -100
  43. package/dist/components/primitives/form-field.js +1 -0
  44. package/dist/components/primitives/header.js +220 -176
  45. package/dist/components/primitives/image-carousel.js +8 -7
  46. package/dist/components/primitives/image-gallery.js +15 -14
  47. package/dist/components/primitives/image-input.js +9 -8
  48. package/dist/components/primitives/list-item.js +9 -8
  49. package/dist/components/primitives/menu-drawer.js +60 -56
  50. package/dist/components/primitives/multi-select.js +7 -6
  51. package/dist/components/primitives/number-input.js +1 -0
  52. package/dist/components/primitives/prose.js +52 -0
  53. package/dist/components/primitives/search-bar.js +81 -66
  54. package/dist/components/primitives/section-header.js +58 -55
  55. package/dist/components/primitives/share-buttons.js +93 -85
  56. package/dist/components/primitives/status-count-tabs.js +8 -7
  57. package/dist/components/primitives/sub-nav.js +52 -52
  58. package/dist/index.css +1 -1
  59. package/dist/index.js +1513 -559
  60. package/dist/lib/field-labelling.js +7 -6
  61. package/dist/lib/link-component.js +6 -0
  62. package/dist/lib/use-value-length.js +1 -0
  63. package/dist/types/components/ec/product-card.d.ts +12 -19
  64. package/dist/types/components/ec/review-card.d.ts +6 -1
  65. package/dist/types/components/foundations/button.d.ts +1 -1
  66. package/dist/types/components/foundations/chip-variants.d.ts +1 -1
  67. package/dist/types/components/foundations/data-table.d.ts +9 -1
  68. package/dist/types/components/foundations/pagination.d.ts +7 -1
  69. package/dist/types/components/foundations/sheet.d.ts +6 -1
  70. package/dist/types/components/foundations/social-icon.d.ts +1 -1
  71. package/dist/types/components/foundations/tabs.d.ts +2 -1
  72. package/dist/types/components/primitives/content-card.d.ts +67 -0
  73. package/dist/types/components/primitives/footer.d.ts +21 -1
  74. package/dist/types/components/primitives/header.d.ts +30 -2
  75. package/dist/types/components/primitives/menu-drawer.d.ts +7 -1
  76. package/dist/types/components/primitives/prose.d.ts +35 -0
  77. package/dist/types/components/primitives/search-bar.d.ts +14 -1
  78. package/dist/types/components/primitives/section-header.d.ts +2 -1
  79. package/dist/types/components/primitives/share-buttons.d.ts +26 -4
  80. package/dist/types/components/primitives/sub-nav.d.ts +16 -1
  81. package/dist/types/index.d.ts +4 -0
  82. package/dist/types/lib/link-component.d.ts +26 -0
  83. package/package.json +4 -3
  84. package/src/components/COMPONENT_LOOKUP.md +7 -5
  85. package/src/preset-standalone.css +1 -0
  86. package/src/preset.css +8 -0
  87. package/src/styles/semantic.css +1 -0
  88. package/tokens.json +8 -1
package/dist/index.js CHANGED
@@ -1,10 +1,9 @@
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
4
  import { toast as l } 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";
6
+ import { Alert as s, AlertDescription as c, AlertTitle as S } from "./components/foundations/alert.js";
8
7
  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
8
  import { AspectRatio as k } from "./components/foundations/aspect-ratio.js";
10
9
  import { Avatar as L, AvatarFallback as N, AvatarImage as G } from "./components/foundations/avatar.js";
@@ -12,33 +11,33 @@ import { Badge as H, badgeVariants as O } from "./components/foundations/badge.j
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";
14
+ import { Card as oo, CardAction as ro, CardContent as eo, CardDescription as to, CardFooter as ao, CardHeader as no, CardTitle as io, cardVariants as po } from "./components/foundations/card.js";
16
15
  import { Checkbox as lo } from "./components/foundations/checkbox.js";
17
16
  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";
17
+ import { CheckboxGroup as Co, CheckboxGroupItem as so } from "./components/foundations/checkbox-group.js";
19
18
  import { Collapsible as So, CollapsibleContent as bo, CollapsibleTrigger as Do } from "./components/foundations/collapsible.js";
20
19
  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
20
  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
21
  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";
22
+ import { Dialog as Xo, DialogClose as Yo, DialogContent as Zo, DialogDescription as $o, DialogFooter as or, DialogHeader as rr, DialogOverlay as er, DialogPortal as tr, DialogTitle as ar, DialogTrigger as nr } from "./components/foundations/dialog.js";
23
+ import { Drawer as pr, DrawerClose as mr, DrawerContent as lr, DrawerDescription as xr, DrawerFooter as ur, DrawerHeader as fr, DrawerOverlay as dr, DrawerPortal as gr, DrawerTitle as Cr, DrawerTrigger as sr } from "./components/foundations/drawer.js";
24
+ import { DropdownMenu as Sr, DropdownMenuCheckboxItem as br, DropdownMenuContent as Dr, DropdownMenuGroup as Mr, DropdownMenuItem as Tr, DropdownMenuLabel as Ir, DropdownMenuPortal as vr, DropdownMenuRadioGroup as hr, DropdownMenuRadioItem as Fr, DropdownMenuSeparator as Pr, DropdownMenuShortcut as wr, DropdownMenuSub as Ar, DropdownMenuSubContent as Br, DropdownMenuSubTrigger as Rr, DropdownMenuTrigger as kr } from "./components/foundations/dropdown-menu.js";
25
+ import { Field as Lr, FieldDescription as Nr, FieldError as Gr, FieldGroup as Vr, FieldLabel as Hr, FieldLegend as Or, FieldSeparator as Er, FieldSet as Ur, fieldVariants as _r } from "./components/foundations/field.js";
26
+ import { FileInput as Qr, formatFileNames as zr, validateFileSize as Kr } from "./components/foundations/file-input.js";
27
+ import { Form as qr, FormControl as Jr, FormDescription as Xr, FormField as Yr, FormItem as Zr, FormLabel as $r, FormMessage as oe, useFormField as re } from "./components/foundations/form.js";
28
+ import { HoverCard as te, HoverCardContent as ae, HoverCardTrigger as ne } from "./components/foundations/hover-card.js";
29
+ import { IconBadge as pe, iconBadgeVariants as me } from "./components/foundations/icon-badge.js";
30
+ import { Input as xe } from "./components/foundations/input.js";
31
+ import { Label as fe } from "./components/foundations/label.js";
32
+ import { Menubar as ge, MenubarCheckboxItem as Ce, MenubarContent as se, MenubarGroup as ce, MenubarItem as Se, MenubarLabel as be, MenubarMenu as De, MenubarPortal as Me, MenubarRadioGroup as Te, MenubarRadioItem as Ie, MenubarSeparator as ve, MenubarShortcut as he, MenubarSub as Fe, MenubarSubContent as Pe, MenubarSubTrigger as we, MenubarTrigger as Ae } from "./components/foundations/menubar.js";
33
+ import { NavigationMenu as Re, NavigationMenuContent as ke, NavigationMenuIndicator as ye, NavigationMenuItem as Le, NavigationMenuLink as Ne, NavigationMenuList as Ge, NavigationMenuTrigger as Ve, NavigationMenuViewport as He, navigationMenuTriggerStyle as Oe } from "./components/foundations/navigation-menu.js";
34
+ import { Pagination as Ue, PaginationContent as _e, PaginationEllipsis as We, PaginationItem as Qe, PaginationLink as ze, PaginationNext as Ke, PaginationPrevious as je } from "./components/foundations/pagination.js";
35
+ import { getPaginationRange as Je } from "./lib/pagination-range.js";
36
+ import { Popover as Ye, PopoverAnchor as Ze, PopoverContent as $e, PopoverTrigger as ot } from "./components/foundations/popover.js";
37
+ import { Progress as et } from "./components/foundations/progress.js";
39
38
  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
39
  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";
40
+ import { ScrollArea as ct, ScrollBar as St } from "./components/foundations/scroll-area.js";
42
41
  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
42
  import { Separator as Rt } from "./components/foundations/separator.js";
44
43
  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";
@@ -48,10 +47,10 @@ import { Slider as Kt } from "./components/foundations/slider.js";
48
47
  import { Spinner as qt } from "./components/foundations/spinner.js";
49
48
  import { SocialIcon as Xt } from "./components/foundations/social-icon.js";
50
49
  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";
50
+ import { Table as oa, TableBody as ra, TableCaption as ea, TableCell as ta, TableFooter as aa, TableHead as na, TableHeader as ia, TableRow as pa } from "./components/foundations/table.js";
52
51
  import { Tabs as la, TabsContent as xa, TabsList as ua, TabsTrigger as fa } from "./components/foundations/tabs.js";
53
52
  import { Textarea as ga } from "./components/foundations/textarea.js";
54
- import { Toaster as ca } from "./components/foundations/sonner.js";
53
+ import { Toaster as sa } from "./components/foundations/sonner.js";
55
54
  import { Toggle as Sa, toggleVariants as ba } from "./components/foundations/toggle.js";
56
55
  import { ToggleGroup as Ma, ToggleGroupItem as Ta } from "./components/foundations/toggle-group.js";
57
56
  import { Tooltip as va, TooltipContent as ha, TooltipProvider as Fa, TooltipTrigger as Pa } from "./components/foundations/tooltip.js";
@@ -68,79 +67,81 @@ import { BulkActionBar as ja } from "./components/primitives/bulk-action-bar.js"
68
67
  import { CategoryShortcuts as Ja } from "./components/primitives/category-shortcuts.js";
69
68
  import { CategoryScroll as Ya } from "./components/primitives/category-scroll.js";
70
69
  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";
70
+ import { Chip as rn } from "./components/primitives/chip.js";
71
+ import { Prose as tn } from "./components/primitives/prose.js";
72
+ import { ContentCard as nn, ContentList as pn } from "./components/primitives/content-card.js";
73
+ import { StandardPageShell as ln, StandardPageShell as xn } from "./components/primitives/standard-page-shell.js";
74
+ import { EmptyState as fn } from "./components/primitives/empty-state.js";
75
+ import { DatePicker as gn, DateTimePicker as Cn } from "./components/primitives/date-picker.js";
76
+ import { ErrorState as cn, NotFoundIllustration as Sn } from "./components/primitives/error-state.js";
77
+ import { FilterBar as Dn } from "./components/primitives/filter-bar.js";
78
+ import { Footer as Tn } from "./components/primitives/footer.js";
79
+ import { FormField as vn } from "./components/primitives/form-field.js";
80
+ import { FunnelShell as Fn } from "./components/primitives/funnel-shell.js";
81
+ import { Header as wn } from "./components/primitives/header.js";
82
+ import { ImageCarousel as Bn } from "./components/primitives/image-carousel.js";
83
+ import { ImageGallery as kn } from "./components/primitives/image-gallery.js";
84
+ import { ImageInput as Ln, imageInputPreviewVariants as Nn } from "./components/primitives/image-input.js";
85
+ import { ImageUploader as Vn } from "./components/primitives/image-uploader.js";
86
+ import { KebabMenu as On } from "./components/primitives/kebab-menu.js";
87
+ import { ListItem as Un } from "./components/primitives/list-item.js";
88
+ import { MenuDrawer as Wn } from "./components/primitives/menu-drawer.js";
89
+ import { SubNav as zn } from "./components/primitives/sub-nav.js";
90
+ import { NotificationBadge as jn, notificationBadgeVariants as qn } from "./components/primitives/notification-badge.js";
91
+ import { NotificationList as Xn } from "./components/primitives/notification-list.js";
92
+ import { PriceDisplay as Zn, priceDisplayVariants as $n } from "./components/primitives/price-display.js";
93
+ import { ProgressSteps as ri } from "./components/primitives/progress-steps.js";
94
+ import { Timeline as ti } from "./components/primitives/timeline.js";
95
+ import { NumberInput as ni, QuantitySelector as ii } from "./components/primitives/number-input.js";
96
+ import { SearchBar as mi } from "./components/primitives/search-bar.js";
97
+ import { SearchPanel as xi } from "./components/primitives/search-panel.js";
98
+ import { Container as fi, containerVariants as di } from "./components/primitives/container.js";
99
+ import { Section as Ci, sectionScrimVariants as si, sectionVariants as ci } from "./components/primitives/section.js";
100
+ import { SectionHeader as bi } from "./components/primitives/section-header.js";
101
+ import { SectionNav as Mi } from "./components/primitives/section-nav.js";
102
+ import { ShareButtons as Ii } from "./components/primitives/share-buttons.js";
103
+ import { SideNav as hi } from "./components/primitives/side-nav.js";
104
+ import { SocialLoginButton as Pi } from "./components/primitives/social-login-button.js";
105
+ import { StatusCountTabs as Ai } from "./components/primitives/status-count-tabs.js";
106
+ import { Tag as Ri, tagVariants as ki } from "./components/primitives/tag.js";
107
+ import { WorkspaceShell as Li, WorkspaceShell as Ni } from "./components/primitives/workspace-shell.js";
108
+ import { AdminShell as Vi, AdminShell as Hi, MissingComponent as Oi } from "./components/ec/admin-shell.js";
109
+ import { AnniversaryCard as Ui } from "./components/ec/anniversary-card.js";
110
+ import { CakeLogo as Wi } from "./components/ec/cake-logo.js";
111
+ import { ChartControls as zi } from "./components/ec/chart-controls.js";
112
+ import { CountdownTimer as ji } from "./components/ec/countdown-timer.js";
113
+ import { CouponCard as Ji } from "./components/ec/coupon-card.js";
114
+ import { DeliveryCalendar as Yi } from "./components/ec/delivery-calendar.js";
115
+ import { mypageMenuGroups as $i } from "./components/ec/_mypage-menu-data.js";
116
+ import { OrderSection as rp } from "./components/ec/order-section.js";
117
+ import { OrderSummary as tp } from "./components/ec/order-summary.js";
118
+ import { CreditCardIcon as np, PaymentMethodDisplay as ip } from "./components/ec/payment-method.js";
119
+ import { ProductCard as mp } from "./components/ec/product-card.js";
120
+ import { ProductCarousel as xp } from "./components/ec/product-carousel.js";
121
+ import { ProductCTA as fp } from "./components/ec/product-cta.js";
122
+ import { ProductDetailBar as gp } from "./components/ec/product-detail-bar.js";
123
+ import { ProductDetailSidebar as sp } from "./components/ec/product-detail-sidebar.js";
124
+ import { ProductListItem as Sp } from "./components/ec/product-list-item.js";
125
+ import { OptionImageUpload as Dp, OptionQuantity as Mp, OptionSelect as Tp, OptionText as Ip, ProductOption as vp } from "./components/ec/product-option.js";
126
+ import { RatingStars as Fp, SparkleIcon as Pp } from "./components/ec/rating-stars.js";
127
+ import { ReviewCard as Ap } from "./components/ec/review-card.js";
128
+ import { ReviewForm as Rp } from "./components/ec/review-form.js";
129
+ import { ReviewItem as yp, ReviewSummary as Lp } from "./components/ec/review-summary.js";
130
+ import { MypageShell as Gp } from "./components/ec/mypage-shell.js";
131
+ import { ShopCard as Hp } from "./components/ec/shop-card.js";
132
+ import { StatCard as Ep } from "./components/ec/stat-card.js";
133
+ import { chipVariants as _p } 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
139
  Ra as AdminHeader,
139
- ki as AdminLayout,
140
- yi as AdminShell,
140
+ Vi as AdminLayout,
141
+ Hi as AdminShell,
141
142
  Aa as AdminSideNav,
142
- c as Alert,
143
- s as AlertDescription,
143
+ s as Alert,
144
+ c as AlertDescription,
144
145
  D as AlertDialog,
145
146
  M as AlertDialogAction,
146
147
  T as AlertDialogCancel,
@@ -153,7 +154,7 @@ export {
153
154
  A as AlertDialogTitle,
154
155
  B as AlertDialogTrigger,
155
156
  S as AlertTitle,
156
- Gi as AnniversaryCard,
157
+ Ui as AnniversaryCard,
157
158
  k as AspectRatio,
158
159
  L as Avatar,
159
160
  N as AvatarFallback,
@@ -170,26 +171,26 @@ export {
170
171
  j as BreadcrumbSeparator,
171
172
  ja as BulkActionBar,
172
173
  J as Button,
173
- bn as CakeFormField,
174
- Hi as CakeLogo,
174
+ vn as CakeFormField,
175
+ Wi as CakeLogo,
175
176
  Z as Calendar,
176
177
  oo as Card,
177
- eo as CardAction,
178
- ro as CardContent,
178
+ ro as CardAction,
179
+ eo as CardContent,
179
180
  to as CardDescription,
180
181
  ao as CardFooter,
181
182
  no as CardHeader,
182
183
  io as CardTitle,
183
184
  Ya as CategoryScroll,
184
185
  Ja as CategoryShortcuts,
185
- Ei as ChartControls,
186
+ zi as ChartControls,
186
187
  $a as ChatComposer,
187
188
  lo as Checkbox,
188
189
  uo as CheckboxCardGroup,
189
190
  fo as CheckboxCardItem,
190
191
  Co as CheckboxGroup,
191
- co as CheckboxGroupItem,
192
- en as Chip,
192
+ so as CheckboxGroupItem,
193
+ rn as Chip,
193
194
  ya as CoachMark,
194
195
  So as Collapsible,
195
196
  bo as CollapsibleContent,
@@ -204,8 +205,10 @@ export {
204
205
  wo as CommandList,
205
206
  Ao as CommandSeparator,
206
207
  Bo as CommandShortcut,
207
- pi as Container,
208
+ fi as Container,
209
+ nn as ContentCard,
208
210
  Oa as ContentCarousel,
211
+ pn as ContentList,
209
212
  ko as ContextMenu,
210
213
  yo as ContextMenuCheckboxItem,
211
214
  Lo as ContextMenuContent,
@@ -221,150 +224,151 @@ export {
221
224
  Qo as ContextMenuSubContent,
222
225
  zo as ContextMenuSubTrigger,
223
226
  Ko as ContextMenuTrigger,
224
- _i as CountdownTimer,
225
- Qi as CouponCard,
226
- op as CreditCardIcon,
227
+ ji as CountdownTimer,
228
+ Ji as CouponCard,
229
+ np as CreditCardIcon,
227
230
  qo as DataTable,
228
- ln as DatePicker,
229
- xn as DateTimePicker,
230
- Ki as DeliveryCalendar,
231
+ gn as DatePicker,
232
+ Cn as DateTimePicker,
233
+ Yi as DeliveryCalendar,
231
234
  Xo as Dialog,
232
235
  Yo as DialogClose,
233
236
  Zo as DialogContent,
234
237
  $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,
238
+ or as DialogFooter,
239
+ rr as DialogHeader,
240
+ er as DialogOverlay,
241
+ tr as DialogPortal,
242
+ ar as DialogTitle,
243
+ nr as DialogTrigger,
244
+ pr as Drawer,
245
+ mr as DrawerClose,
246
+ lr as DrawerContent,
247
+ xr as DrawerDescription,
248
+ ur as DrawerFooter,
249
+ fr as DrawerHeader,
250
+ dr as DrawerOverlay,
251
+ gr as DrawerPortal,
252
+ Cr as DrawerTitle,
253
+ sr as DrawerTrigger,
254
+ Sr as DropdownMenu,
255
+ br as DropdownMenuCheckboxItem,
256
+ Dr as DropdownMenuContent,
257
+ Mr as DropdownMenuGroup,
258
+ Tr as DropdownMenuItem,
259
+ Ir as DropdownMenuLabel,
260
+ vr as DropdownMenuPortal,
261
+ hr as DropdownMenuRadioGroup,
262
+ Fr as DropdownMenuRadioItem,
263
+ Pr as DropdownMenuSeparator,
264
+ wr as DropdownMenuShortcut,
265
+ Ar as DropdownMenuSub,
266
+ Br as DropdownMenuSubContent,
267
+ Rr as DropdownMenuSubTrigger,
268
+ kr as DropdownMenuTrigger,
269
+ ln as EcPageShell,
270
+ fn as EmptyState,
271
+ cn as ErrorState,
269
272
  n as FOCUS_RING,
270
273
  i as FOCUS_RING_INSET,
271
274
  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,
275
+ Lr as Field,
276
+ Nr as FieldDescription,
277
+ Gr as FieldError,
278
+ Vr as FieldGroup,
279
+ Hr as FieldLabel,
280
+ Or as FieldLegend,
281
+ Er as FieldSeparator,
282
+ Ur as FieldSet,
283
+ Qr as FileInput,
284
+ Dn as FilterBar,
285
+ Tn as Footer,
286
+ qr as Form,
287
+ Jr as FormControl,
288
+ Xr as FormDescription,
289
+ Yr as FormField,
290
+ Zr as FormItem,
291
+ $r as FormLabel,
292
+ oe as FormMessage,
293
+ Fn as FunnelShell,
294
+ wn as Header,
295
+ te as HoverCard,
296
+ ae as HoverCardContent,
297
+ ne as HoverCardTrigger,
298
+ pe as IconBadge,
299
+ Bn as ImageCarousel,
300
+ kn as ImageGallery,
301
+ Ln as ImageInput,
302
+ Vn as ImageUploader,
303
+ xe as Input,
304
+ On as KebabMenu,
305
+ fe as Label,
306
+ Un as ListItem,
307
+ Wn as MenuDrawer,
308
+ ge as Menubar,
309
+ Ce as MenubarCheckboxItem,
310
+ se as MenubarContent,
311
+ ce as MenubarGroup,
312
+ Se as MenubarItem,
313
+ be as MenubarLabel,
314
+ De as MenubarMenu,
315
+ Me as MenubarPortal,
316
+ Te as MenubarRadioGroup,
317
+ Ie as MenubarRadioItem,
318
+ ve as MenubarSeparator,
319
+ he as MenubarShortcut,
320
+ Fe as MenubarSub,
321
+ Pe as MenubarSubContent,
322
+ we as MenubarSubTrigger,
323
+ Ae as MenubarTrigger,
324
+ Oi as MissingComponent,
322
325
  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,
326
+ Gp as MypageShell,
327
+ Re as NavigationMenu,
328
+ ke as NavigationMenuContent,
329
+ ye as NavigationMenuIndicator,
330
+ Le as NavigationMenuItem,
331
+ Ne as NavigationMenuLink,
332
+ Ge as NavigationMenuList,
333
+ Ve as NavigationMenuTrigger,
334
+ He as NavigationMenuViewport,
335
+ Sn as NotFoundIllustration,
336
+ jn as NotificationBadge,
337
+ Xn as NotificationList,
338
+ ni as NumberInput,
339
+ Dp as OptionImageUpload,
340
+ Mp as OptionQuantity,
341
+ Tp as OptionSelect,
342
+ Ip as OptionText,
343
+ rp as OrderSection,
344
+ tp as OrderSummary,
345
+ Ue as Pagination,
346
+ _e as PaginationContent,
347
+ We as PaginationEllipsis,
348
+ Qe as PaginationItem,
349
+ ze as PaginationLink,
350
+ Ke as PaginationNext,
351
+ je as PaginationPrevious,
352
+ ip as PaymentMethodDisplay,
353
+ Ye as Popover,
354
+ Ze as PopoverAnchor,
355
+ $e as PopoverContent,
353
356
  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,
357
+ Zn as PriceDisplay,
358
+ fp as ProductCTA,
359
+ mp as ProductCard,
360
+ xp as ProductCarousel,
361
+ gp as ProductDetailBar,
362
+ sp as ProductDetailSidebar,
363
+ Sp as ProductListItem,
364
+ vp as ProductOption,
365
+ et as Progress,
366
+ ri as ProgressSteps,
367
+ tn as Prose,
368
+ ii as QuantitySelector,
365
369
  gt as RadioGroup,
366
370
  Ct as RadioGroupItem,
367
- Mp as RatingStars,
371
+ Fp as RatingStars,
368
372
  at as ResponsiveDialog,
369
373
  nt as ResponsiveDialogClose,
370
374
  it as ResponsiveDialogContent,
@@ -373,17 +377,17 @@ export {
373
377
  lt as ResponsiveDialogHeader,
374
378
  xt as ResponsiveDialogTitle,
375
379
  ut as ResponsiveDialogTrigger,
376
- vp as ReviewCard,
377
- Fp as ReviewForm,
378
- wp as ReviewItem,
379
- Ap as ReviewSummary,
380
- st as ScrollArea,
380
+ Ap as ReviewCard,
381
+ Rp as ReviewForm,
382
+ yp as ReviewItem,
383
+ Lp as ReviewSummary,
384
+ ct as ScrollArea,
381
385
  St as ScrollBar,
382
- ti as SearchBar,
383
- ni as SearchPanel,
384
- xi as Section,
385
- gi as SectionHeader,
386
- ci as SectionNav,
386
+ mi as SearchBar,
387
+ xi as SearchPanel,
388
+ Ci as Section,
389
+ bi as SectionHeader,
390
+ Mi as SectionNav,
387
391
  Dt as Select,
388
392
  Mt as SelectContent,
389
393
  Tt as SelectGroup,
@@ -395,7 +399,7 @@ export {
395
399
  wt as SelectTrigger,
396
400
  At as SelectValue,
397
401
  Rt as Separator,
398
- Si as ShareButtons,
402
+ Ii as ShareButtons,
399
403
  yt as Sheet,
400
404
  Lt as SheetClose,
401
405
  Nt as SheetContent,
@@ -404,24 +408,24 @@ export {
404
408
  Ht as SheetHeader,
405
409
  Ot as SheetTitle,
406
410
  Et as SheetTrigger,
407
- yp as ShopCard,
408
- Di as SideNav,
411
+ Hp as ShopCard,
412
+ hi as SideNav,
409
413
  _t as Skeleton,
410
414
  Qt as SkipLink,
411
415
  Kt as Slider,
412
416
  Xt as SocialIcon,
413
- Ti as SocialLoginButton,
414
- Tp as SparkleIcon,
417
+ Pi as SocialLoginButton,
418
+ Pp as SparkleIcon,
415
419
  qt as Spinner,
416
- an as StandardPageShell,
417
- Np as StatCard,
418
- vi as StatusCountTabs,
420
+ xn as StandardPageShell,
421
+ Ep as StatCard,
422
+ Ai as StatusCountTabs,
419
423
  Wa as StickyActionBar,
420
- En as SubNav,
424
+ zn as SubNav,
421
425
  Zt as Switch,
422
426
  oa as Table,
423
- ea as TableBody,
424
- ra as TableCaption,
427
+ ra as TableBody,
428
+ ea as TableCaption,
425
429
  ta as TableCell,
426
430
  aa as TableFooter,
427
431
  na as TableHead,
@@ -431,10 +435,10 @@ export {
431
435
  xa as TabsContent,
432
436
  ua as TabsList,
433
437
  fa as TabsTrigger,
434
- Fi as Tag,
438
+ Ri as Tag,
435
439
  ga as Textarea,
436
- Zn as Timeline,
437
- ca as Toaster,
440
+ ti as Timeline,
441
+ sa as Toaster,
438
442
  Sa as Toggle,
439
443
  Ma as ToggleGroup,
440
444
  Ta as ToggleGroupItem,
@@ -442,31 +446,31 @@ export {
442
446
  ha as TooltipContent,
443
447
  Fa as TooltipProvider,
444
448
  Pa as TooltipTrigger,
445
- Ai as WorkspaceLayout,
446
- Bi as WorkspaceShell,
449
+ Li as WorkspaceLayout,
450
+ Ni as WorkspaceShell,
447
451
  O as badgeVariants,
448
452
  X as buttonVariants,
449
453
  po as cardVariants,
450
- Vp as chipVariants,
454
+ _p as chipVariants,
451
455
  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,
456
+ di as containerVariants,
457
+ _r as fieldVariants,
458
+ zr as formatFileNames,
459
+ Je as getPaginationRange,
460
+ me as iconBadgeVariants,
461
+ Nn as imageInputPreviewVariants,
462
+ $i as mypageMenuGroups,
463
+ Oe as navigationMenuTriggerStyle,
464
+ qn as notificationBadgeVariants,
465
+ $n as priceDisplayVariants,
466
+ si as sectionScrimVariants,
467
+ ci as sectionVariants,
468
+ ki as tagVariants,
465
469
  l as toast,
466
470
  ba as toggleVariants,
467
- er as useFormField,
471
+ re as useFormField,
468
472
  ft as useIsMobile,
469
- Ke as validateFileSize
473
+ Kr as validateFileSize
470
474
  };
471
475
 
472
476
 
@@ -656,6 +660,8 @@ export {
656
660
  // ]
657
661
  //
658
662
  // src/components/ec/admin-shell.tsx
663
+ // "use client"
664
+ //
659
665
  // /**
660
666
  // * AdminShell — 管理画面の共通レイアウト
661
667
  // *
@@ -2557,6 +2563,17 @@ export {
2557
2563
  // reviewCount?: number
2558
2564
  // /** ショップ名 */
2559
2565
  // shopName?: string
2566
+ // /**
2567
+ // * ホバー時の画像演出。
2568
+ // * - `zoom` : 画像をわずかに拡大
2569
+ // * - `fade` : 拡大せず画像をわずかに明るくする(本番 EC 準拠)
2570
+ // * - `none` : 演出なし
2571
+ // *
2572
+ // * 未指定時の既定は orientation で変わる(従来の見た目を維持するため):
2573
+ // * `vertical` = `zoom` / `horizontal` = `none`。明示指定すればどちらの
2574
+ // * orientation でも同じように効く。
2575
+ // */
2576
+ // hoverEffect?: "zoom" | "fade" | "none"
2560
2577
  // /** ショップページURL(指定するとショップ名がリンク化、hover時アンダーライン) */
2561
2578
  // shopHref?: string
2562
2579
  // /** タグリスト(配送方法・キャンペーンなど) */
@@ -2753,6 +2770,18 @@ export {
2753
2770
  // * - `showCartButton` で「カートに追加」ボタン表示(verticalのみ)
2754
2771
  // * - ランキングバッジ、お気に入り、割引バッジなどEC必須要素を統合提供
2755
2772
  // */
2773
+ // /**
2774
+ // * hoverEffect ごとの画像クラス(拡大 / 明るく / なし)
2775
+ // *
2776
+ // * fade は opacity ではなく brightness を使う。opacity は背景(--Surface-Primary)と
2777
+ // * 合成されるだけなので、暗テーマでは「明るく」ではなく暗くなってしまう。
2778
+ // */
2779
+ // function hoverEffectImageClass(effect: "zoom" | "fade" | "none") {
2780
+ // if (effect === "none") return undefined
2781
+ // if (effect === "fade") return "transition-[filter] group-hover:brightness-110"
2782
+ // return "transition-transform group-hover:scale-105"
2783
+ // }
2784
+ //
2756
2785
  // function ProductCard({
2757
2786
  // className,
2758
2787
  // name,
@@ -2765,6 +2794,7 @@ export {
2765
2794
  // reviewCount,
2766
2795
  // shopName,
2767
2796
  // shopHref,
2797
+ // hoverEffect,
2768
2798
  // tags = [],
2769
2799
  // isFavorite = false,
2770
2800
  // onFavoriteToggle,
@@ -2779,6 +2809,9 @@ export {
2779
2809
  // cartButtonLabel = "カートに追加",
2780
2810
  // ...props
2781
2811
  // }: ProductCardProps) {
2812
+ // // 既定は orientation ごと(vertical=zoom / horizontal=none)。従来の見た目を変えない。
2813
+ // const resolvedHoverEffect =
2814
+ // hoverEffect ?? (orientation === "horizontal" ? "none" : "zoom")
2782
2815
  // const discountText = showDiscountBadge ? calcDiscountPercent(price, originalPrice) : null
2783
2816
  //
2784
2817
  // if (orientation === "horizontal") {
@@ -2799,7 +2832,7 @@ export {
2799
2832
  // {/* ランキングバッジ: カードレベルに配置(画像の overflow-hidden の外) */}
2800
2833
  // {ranking != null && <RankingBadge rank={ranking} />}
2801
2834
  // <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" />
2835
+ // <img src={imageUrl} alt={imageAlt ?? name} className={cn("h-full w-full object-cover duration-[var(--Motion-Duration-Base)]", hoverEffectImageClass(resolvedHoverEffect))} loading="lazy" />
2803
2836
  // {discountText && (
2804
2837
  // <Tag variant="sale" size="sm" className="absolute bottom-1.5 left-1.5 z-[var(--Z-Local-2)]">{discountText}</Tag>
2805
2838
  // )}
@@ -2861,7 +2894,7 @@ export {
2861
2894
  // {/* 画像エリア: Figma — aspect-square, rounded-lg, p-1, 内部にタグ+ブックマーク */}
2862
2895
  // <div className="relative">
2863
2896
  // <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" />
2897
+ // <img src={imageUrl} alt={imageAlt ?? name} className={cn("h-full w-full object-cover duration-[var(--Motion-Duration-Base)]", hoverEffectImageClass(resolvedHoverEffect))} loading="lazy" />
2865
2898
  //
2866
2899
  // {/* 画像内オーバーレイ: 左下にタグ・割引 */}
2867
2900
  // <div className="absolute inset-x-1 bottom-1 z-[var(--Z-Local-3)] flex items-end">
@@ -4375,6 +4408,8 @@ export {
4375
4408
  // export { ProductListItem }
4376
4409
  //
4377
4410
  // src/components/ec/product-option.tsx
4411
+ // "use client"
4412
+ //
4378
4413
  // import * as React from "react"
4379
4414
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
4380
4415
  // import Add from "iconsax-reactjs/dist/esm/Add.js"
@@ -4757,6 +4792,11 @@ export {
4757
4792
  // export interface ReviewCardProps extends React.HTMLAttributes<HTMLDivElement> {
4758
4793
  // /** レビューバリアント */
4759
4794
  // variant?: "list" | "card" | "pc"
4795
+ // /**
4796
+ // * 枠線を出すか(既定 true)。
4797
+ // * 商品詳細などページ全体をフラットに統一する画面では false にする。
4798
+ // */
4799
+ // bordered?: boolean
4760
4800
  // /** 星評価(1〜5) */
4761
4801
  // rating: number
4762
4802
  // /** 投稿日 */
@@ -4799,6 +4839,7 @@ export {
4799
4839
  // function ReviewCard({
4800
4840
  // className,
4801
4841
  // variant = "list",
4842
+ // bordered = true,
4802
4843
  // rating,
4803
4844
  // date,
4804
4845
  // text,
@@ -4825,7 +4866,8 @@ export {
4825
4866
  // <div
4826
4867
  // data-slot="review-card"
4827
4868
  // className={cn(
4828
- // "flex flex-col rounded-lg border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Primary)]",
4869
+ // "flex flex-col rounded-lg bg-[var(--Surface-Primary)]",
4870
+ // bordered && "border border-[var(--Border-Medium-Emphasis)]",
4829
4871
  // isPc ? "w-full max-w-[680px] gap-4 p-6" : "min-w-[240px] w-full gap-2 p-4",
4830
4872
  // isCard && "items-center",
4831
4873
  // className
@@ -4935,6 +4977,8 @@ export {
4935
4977
  // export { ReviewCard }
4936
4978
  //
4937
4979
  // src/components/ec/review-form.tsx
4980
+ // "use client"
4981
+ //
4938
4982
  // import * as React from "react"
4939
4983
  // import Camera from "iconsax-reactjs/dist/esm/Camera.js"
4940
4984
  // import { X } from "lucide-react"
@@ -6024,6 +6068,8 @@ export {
6024
6068
  // }
6025
6069
  //
6026
6070
  // src/components/foundations/alert.tsx
6071
+ // "use client"
6072
+ //
6027
6073
  // import * as React from "react"
6028
6074
  // import { cva, type VariantProps } from "class-variance-authority"
6029
6075
  // import Warning2 from "iconsax-reactjs/dist/esm/Warning2.js"
@@ -6741,6 +6787,12 @@ export {
6741
6787
  // "icon-xs": "size-6 rounded [&_svg:not([class*='size-'])]:size-3",
6742
6788
  // "icon-sm": "size-8 rounded-lg",
6743
6789
  // "icon-lg": "size-10 rounded-lg",
6790
+ // /**
6791
+ // * icon-xl — 44px(size-11)。size="default" と同じ高さなので、
6792
+ // * 入力行(Input / SearchBar / SelectTrigger)の横にアイコンボタンを並置しても揃う。
6793
+ // * tokens.json の touchTarget["text-input"].min = 44px も満たす唯一の icon サイズ。
6794
+ // */
6795
+ // "icon-xl": "size-11 rounded-lg",
6744
6796
  // },
6745
6797
  // },
6746
6798
  // defaultVariants: {
@@ -6777,6 +6829,8 @@ export {
6777
6829
  // export { Button, buttonVariants }
6778
6830
  //
6779
6831
  // src/components/foundations/calendar.tsx
6832
+ // "use client"
6833
+ //
6780
6834
  // import * as React from "react"
6781
6835
  // import {
6782
6836
  // ChevronDownIcon,
@@ -7284,6 +7338,8 @@ export {
7284
7338
  // export { CheckboxCardGroup, CheckboxCardItem }
7285
7339
  //
7286
7340
  // src/components/foundations/checkbox-group.tsx
7341
+ // "use client"
7342
+ //
7287
7343
  // /**
7288
7344
  // * ## CheckboxGroup / チェックボックスグループ
7289
7345
  // *
@@ -7456,6 +7512,8 @@ export {
7456
7512
  // export { CheckboxGroup, CheckboxGroupItem }
7457
7513
  //
7458
7514
  // src/components/foundations/checkbox.tsx
7515
+ // "use client"
7516
+ //
7459
7517
  // import * as React from "react"
7460
7518
  // import TickSquare from "iconsax-reactjs/dist/esm/TickSquare.js"
7461
7519
  // import MinusSquare from "iconsax-reactjs/dist/esm/MinusSquare.js"
@@ -8154,6 +8212,7 @@ export {
8154
8212
  // import ExportSquare from "iconsax-reactjs/dist/esm/ExportSquare.js"
8155
8213
  //
8156
8214
  // import { cn } from "@/lib/utils"
8215
+ // import { FOCUS_RING } from "@/lib/focus-ring"
8157
8216
  // import { Checkbox } from "@/components/foundations/checkbox"
8158
8217
  // import { Button } from "@/components/foundations/button"
8159
8218
  // import { Avatar, AvatarImage, AvatarFallback } from "@/components/foundations/avatar"
@@ -8263,6 +8322,7 @@ export {
8263
8322
  // sortDirection,
8264
8323
  // onSort,
8265
8324
  // width,
8325
+ // srLabel,
8266
8326
  // children,
8267
8327
  // ...props
8268
8328
  // }: React.ComponentProps<"th"> & {
@@ -8271,8 +8331,19 @@ export {
8271
8331
  // onSort?: () => void
8272
8332
  // /** セル幅バリアント: max=320-360px, hug=最小 */
8273
8333
  // width?: "auto" | "max" | "hug"
8334
+ // /**
8335
+ // * 見出し文字を出さない列(チェックボックス選択列・操作列など)の読み上げ用ラベル。
8336
+ // * 画面には出さず、スクリーンリーダーにだけ列の意味を伝える。
8337
+ // *
8338
+ // * 空の `<th>` は「この列が何か」が支援技術に伝わらない(axe: empty-table-header)。
8339
+ // * 見出しを出したくない列には必ず指定する。
8340
+ // */
8341
+ // srLabel?: string
8274
8342
  // }) {
8275
8343
  // const SortIcon = sortDirection === "asc" ? ArrowUp : sortDirection === "desc" ? ArrowDown : ArrowSwapVertical
8344
+ // /** 未ソート列も "none" を明示する(列が並び替え可能であること自体を読み上げる) */
8345
+ // const ariaSort: React.AriaAttributes["aria-sort"] =
8346
+ // sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none"
8276
8347
  //
8277
8348
  // return (
8278
8349
  // <th
@@ -8280,22 +8351,40 @@ export {
8280
8351
  // className={cn(
8281
8352
  // "h-16 px-4 text-left align-middle typo-label-sm whitespace-nowrap text-[var(--Text-Medium-Emphasis)]",
8282
8353
  // "[&:has([role=checkbox])]:w-12 [&:has([role=checkbox])]:pr-0",
8283
- // sortable && "cursor-pointer select-none hover:bg-[var(--Surface-Tertiary)]",
8354
+ // sortable && "hover:bg-[var(--Surface-Tertiary)]",
8284
8355
  // width === "max" && "min-w-[320px] max-w-[360px]",
8285
8356
  // width === "hug" && "min-w-0 w-0",
8286
8357
  // className
8287
8358
  // )}
8288
- // onClick={sortable ? onSort : undefined}
8359
+ // // 並び替えの状態は aria-sort で読み上げる。押下は下の <button> が担う
8360
+ // aria-sort={sortable ? ariaSort : undefined}
8289
8361
  // {...props}
8290
8362
  // >
8291
8363
  // {sortable ? (
8292
- // <span className={cn("inline-flex items-center gap-1", sortDirection && "typo-label-sm font-bold text-[var(--Text-High-Emphasis)]")}>
8364
+ // // th の onClick はマウスにしか届かない(キーボードで到達できず role も無い)。
8365
+ // // 本物の <button> にして Tab / Enter / Space で並び替えられるようにする。
8366
+ // <button
8367
+ // type="button"
8368
+ // onClick={onSort}
8369
+ // className={cn(
8370
+ // "inline-flex items-center gap-1 rounded-sm outline-none",
8371
+ // "cursor-pointer select-none",
8372
+ // FOCUS_RING,
8373
+ // sortDirection && "typo-label-sm font-bold text-[var(--Text-High-Emphasis)]"
8374
+ // )}
8375
+ // >
8293
8376
  // {children}
8294
- // <SortIcon size={14} className={cn(sortDirection ? "text-[var(--Text-High-Emphasis)]" : "text-[var(--Text-Low-Emphasis)]")} />
8295
- // </span>
8377
+ // <SortIcon
8378
+ // size={14}
8379
+ // aria-hidden="true"
8380
+ // className={cn(sortDirection ? "text-[var(--Text-High-Emphasis)]" : "text-[var(--Text-Low-Emphasis)]")}
8381
+ // />
8382
+ // </button>
8296
8383
  // ) : (
8297
8384
  // children
8298
8385
  // )}
8386
+ // {/* 見出し文字を出さない列は、読み上げ用のラベルだけ置く */}
8387
+ // {srLabel && <span className="sr-only">{srLabel}</span>}
8299
8388
  // </th>
8300
8389
  // )
8301
8390
  // }
@@ -9624,6 +9713,8 @@ export {
9624
9713
  // VariantProps<typeof fieldVariants>
9625
9714
  //
9626
9715
  // src/components/foundations/file-input.tsx
9716
+ // "use client"
9717
+ //
9627
9718
  // import * as React from "react"
9628
9719
  // import { Paperclip, X } from "lucide-react"
9629
9720
  //
@@ -10697,6 +10788,7 @@ export {
10697
10788
  // } from "lucide-react"
10698
10789
  //
10699
10790
  // import { cn } from "@/lib/utils"
10791
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
10700
10792
  // import { buttonVariants, type Button } from "@/components/foundations/button"
10701
10793
  //
10702
10794
  // function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
@@ -10730,6 +10822,11 @@ export {
10730
10822
  //
10731
10823
  // type PaginationLinkProps = {
10732
10824
  // isActive?: boolean
10825
+ // /**
10826
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
10827
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
10828
+ // */
10829
+ // linkComponent?: LinkComponent
10733
10830
  // } & Pick<React.ComponentProps<typeof Button>, "size"> &
10734
10831
  // React.ComponentProps<"a">
10735
10832
  //
@@ -10737,10 +10834,12 @@ export {
10737
10834
  // className,
10738
10835
  // isActive,
10739
10836
  // size = "icon",
10837
+ // linkComponent,
10740
10838
  // ...props
10741
10839
  // }: PaginationLinkProps) {
10840
+ // const LinkTag = resolveLinkComponent(linkComponent)
10742
10841
  // return (
10743
- // <a
10842
+ // <LinkTag
10744
10843
  // aria-current={isActive ? "page" : undefined}
10745
10844
  // data-slot="pagination-link"
10746
10845
  // data-active={isActive}
@@ -10948,6 +11047,8 @@ export {
10948
11047
  // export { Progress }
10949
11048
  //
10950
11049
  // src/components/foundations/radio-group.tsx
11050
+ // "use client"
11051
+ //
10951
11052
  // import * as React from "react"
10952
11053
  // import { RadioGroup as RadioGroupPrimitive } from "radix-ui"
10953
11054
  //
@@ -11111,6 +11212,8 @@ export {
11111
11212
  // export { RadioGroup, RadioGroupItem }
11112
11213
  //
11113
11214
  // src/components/foundations/responsive-dialog.tsx
11215
+ // "use client"
11216
+ //
11114
11217
  // import * as React from "react"
11115
11218
  //
11116
11219
  // import { cn } from "@/lib/utils"
@@ -11671,18 +11774,32 @@ export {
11671
11774
  // children,
11672
11775
  // side = "right",
11673
11776
  // showCloseButton = true,
11777
+ // autoFocus = true,
11778
+ // onOpenAutoFocus,
11779
+ // onCloseAutoFocus,
11674
11780
  // ...props
11675
11781
  // }: React.ComponentProps<typeof SheetPrimitive.Content> & {
11676
11782
  // side?: "top" | "right" | "bottom" | "left"
11677
11783
  // showCloseButton?: boolean
11784
+ // /**
11785
+ // * 開閉時のフォーカス自動移動。既定 true(Radix 既定=開いたら中へ入り、閉じたらトリガーへ戻る)。
11786
+ // * WCAG 2.4.3 を満たすため、止めたい特別な事情があるときだけ false にする。
11787
+ // */
11788
+ // autoFocus?: boolean
11678
11789
  // }) {
11679
11790
  // return (
11680
11791
  // <SheetPortal>
11681
11792
  // <SheetOverlay />
11682
11793
  // <SheetPrimitive.Content
11683
11794
  // data-slot="sheet-content"
11684
- // onOpenAutoFocus={(e) => e.preventDefault()}
11685
- // onCloseAutoFocus={(e) => e.preventDefault()}
11795
+ // onOpenAutoFocus={(e) => {
11796
+ // if (!autoFocus) e.preventDefault()
11797
+ // onOpenAutoFocus?.(e)
11798
+ // }}
11799
+ // onCloseAutoFocus={(e) => {
11800
+ // if (!autoFocus) e.preventDefault()
11801
+ // onCloseAutoFocus?.(e)
11802
+ // }}
11686
11803
  // className={cn(
11687
11804
  // "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)]",
11688
11805
  // side === "right" &&
@@ -11964,10 +12081,20 @@ export {
11964
12081
  //
11965
12082
  // import { cn } from "@/lib/utils"
11966
12083
  //
11967
- // export type SocialPlatform = "line" | "x" | "facebook" | "amazon" | "google" | "apple"
12084
+ // export type SocialPlatform =
12085
+ // | "line"
12086
+ // | "x"
12087
+ // | "facebook"
12088
+ // | "amazon"
12089
+ // | "google"
12090
+ // | "apple"
12091
+ // | "hatena"
11968
12092
  //
11969
- // /** 単色で描くブランド。多色ロゴ(google / amazon)は個別に塗り分けるため除外 */
11970
- // type MonoPlatform = Exclude<SocialPlatform, "google" | "amazon">
12093
+ // /**
12094
+ // * 単色で描くブランド。
12095
+ // * 多色ロゴ(google / amazon)と、地+白抜きで描くもの(hatena)は個別に塗り分けるため除外
12096
+ // */
12097
+ // type MonoPlatform = Exclude<SocialPlatform, "google" | "amazon" | "hatena">
11971
12098
  //
11972
12099
  // export interface SocialIconProps extends Omit<React.ComponentProps<"svg">, "children"> {
11973
12100
  // platform: SocialPlatform
@@ -12055,6 +12182,33 @@ export {
12055
12182
  // )
12056
12183
  // }
12057
12184
  //
12185
+ // if (platform === "hatena") {
12186
+ // // はてなブックマークの「B!」マーク。角丸の地(--Third-Party-Hatena = #00A4DE)に白抜き。
12187
+ // // 字形は公式アートワークのトレースではなく幾何的に再構成したもの。公式 SVG が入手できたら
12188
+ // // この 2 つの path を差し替えれば足りる(公開 API は変わらない)。
12189
+ // // tone="mono" では地を描かず currentColor の字だけにする(ブランド色の地に載せる用)。
12190
+ // return (
12191
+ // <svg {...common} fill="none">
12192
+ // {!mono && (
12193
+ // <rect
12194
+ // x="1"
12195
+ // y="1"
12196
+ // width="22"
12197
+ // height="22"
12198
+ // rx="4"
12199
+ // fill="var(--Third-Party-Hatena)"
12200
+ // />
12201
+ // )}
12202
+ // <path
12203
+ // fillRule="evenodd"
12204
+ // /* 出典: はてなブックマークのブランド表記「B!」。白抜き(地の上)または currentColor */
12205
+ // fill={mono ? "currentColor" : "#FFFFFF"}
12206
+ // 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"
12207
+ // />
12208
+ // </svg>
12209
+ // )
12210
+ // }
12211
+ //
12058
12212
  // return (
12059
12213
  // <svg {...common} fill={mono ? "currentColor" : brandColors[platform]}>
12060
12214
  // <path d={monoPaths[platform]} />
@@ -12380,10 +12534,22 @@ export {
12380
12534
  // scrollable: {
12381
12535
  // true: "gap-4",
12382
12536
  // },
12537
+ // /**
12538
+ // * 狭い置き場所(サイドバー等)向けの詰め設定。
12539
+ // * segment の 1 項目あたりの最小幅(100px)を外し、左右の padding を詰める(issue #235)。
12540
+ // */
12541
+ // size: {
12542
+ // md: "",
12543
+ // sm: "",
12544
+ // },
12383
12545
  // },
12546
+ // compoundVariants: [
12547
+ // { variant: "segment", size: "sm", class: "p-1" },
12548
+ // ],
12384
12549
  // defaultVariants: {
12385
12550
  // variant: "underbar",
12386
12551
  // scrollable: false,
12552
+ // size: "md",
12387
12553
  // },
12388
12554
  // }
12389
12555
  // )
@@ -12392,6 +12558,7 @@ export {
12392
12558
  // className,
12393
12559
  // variant = "underbar",
12394
12560
  // scrollable = false,
12561
+ // size = "md",
12395
12562
  // ...props
12396
12563
  // }: React.ComponentProps<typeof TabsPrimitive.List> &
12397
12564
  // VariantProps<typeof tabsListVariants>) {
@@ -12400,7 +12567,8 @@ export {
12400
12567
  // data-slot="tabs-list"
12401
12568
  // data-variant={variant}
12402
12569
  // data-scrollable={scrollable || undefined}
12403
- // className={cn(tabsListVariants({ variant, scrollable }), className)}
12570
+ // data-size={size}
12571
+ // className={cn(tabsListVariants({ variant, scrollable, size }), className)}
12404
12572
  // {...props}
12405
12573
  // />
12406
12574
  // )
@@ -12418,13 +12586,19 @@ export {
12418
12586
  // // Base
12419
12587
  // "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
12588
  // // 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)]",
12589
+ // // px-2: 均等割りで幅が詰まったとき、隣のラベルと文字が接触しないための最小余白(issue #235)
12590
+ // "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
12591
  // // Underbar active
12423
12592
  // "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
12593
  // // 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",
12594
+ // // gap-4 で間隔を取っているので左右 padding は戻す(従来の間隔を保つ)
12595
+ // "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
12596
  // // Segment variant
12427
12597
  // "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)]",
12598
+ // // size="sm": 狭い置き場所(サイドバー等)向け。1 項目あたりの最小幅を外し、
12599
+ // // 左右の padding を詰める。min-w を持つのは segment だけ、underbar の px-2 は同値なので
12600
+ // // 実際に効くのは segment。variant 側の group-data と具体度が並ぶため ! で順序依存を断つ(issue #235)
12601
+ // "group-data-[size=sm]/tabs-list:!min-w-0 group-data-[size=sm]/tabs-list:!px-2",
12428
12602
  // // Segment active
12429
12603
  // "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
12604
  // className
@@ -12546,6 +12720,8 @@ export {
12546
12720
  // export { Textarea }
12547
12721
  //
12548
12722
  // src/components/foundations/toggle-group.tsx
12723
+ // "use client"
12724
+ //
12549
12725
  // import * as React from "react"
12550
12726
  // import { cva, type VariantProps } from "class-variance-authority"
12551
12727
  // import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"
@@ -12869,6 +13045,8 @@ export {
12869
13045
  // export { AdminHeader }
12870
13046
  //
12871
13047
  // src/components/primitives/admin-side-nav.tsx
13048
+ // "use client"
13049
+ //
12872
13050
  // import * as React from "react"
12873
13051
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
12874
13052
  // import { XIcon } from "lucide-react"
@@ -13802,6 +13980,8 @@ export {
13802
13980
  // export { CategoryShortcuts }
13803
13981
  //
13804
13982
  // src/components/primitives/chat-composer.tsx
13983
+ // "use client"
13984
+ //
13805
13985
  // import * as React from "react"
13806
13986
  // import { SendHorizontal } from "lucide-react"
13807
13987
  //
@@ -14396,6 +14576,8 @@ export {
14396
14576
  // export { CoachMark }
14397
14577
  //
14398
14578
  // src/components/primitives/combobox.tsx
14579
+ // "use client"
14580
+ //
14399
14581
  // import * as React from "react"
14400
14582
  // import { Check, ChevronsUpDown } from "lucide-react"
14401
14583
  //
@@ -14583,7 +14765,186 @@ export {
14583
14765
  // // eslint-disable-next-line react-refresh/only-export-components -- shadcn 慣習: variants はコンポーネントと同居 export(分割は公開 API の破壊変更)
14584
14766
  // export { Container, containerVariants }
14585
14767
  //
14768
+ // src/components/primitives/content-card.tsx
14769
+ // import * as React from "react"
14770
+ //
14771
+ // import { cn } from "@/lib/utils"
14772
+ // import { FOCUS_RING } from "@/lib/focus-ring"
14773
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
14774
+ // import { Tag, type TagProps } from "@/components/primitives/tag"
14775
+ //
14776
+ // export type ContentCardOrientation = "vertical" | "horizontal" | "list"
14777
+ // export type ContentCardAspect = "16/10" | "16/9" | "1/1"
14778
+ //
14779
+ // export interface ContentCardProps
14780
+ // extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
14781
+ // /** 記事タイトル。一覧で高さが割れないよう常に 2 行ぶんの高さを取る */
14782
+ // title: string
14783
+ // /** 遷移先。カード全体がリンクになる */
14784
+ // href: string
14785
+ // /**
14786
+ // * 画像。`next/image` や CMS の img、図版をそのまま渡す。
14787
+ // * 縦横比とクリップはカード側が持つので、中身は `h-full w-full object-cover` を想定。
14788
+ // */
14789
+ // imageSlot?: React.ReactNode
14790
+ // /** 画像左下に重ねるラベル(カテゴリ等)。長いラベルは省略記号で切る */
14791
+ // tag?: { label: string; variant?: TagProps["variant"] }
14792
+ // /** 日付・著者などの補足。**必ず 1 行**に収まる内容にする(複数行だと一覧で高さが割れる) */
14793
+ // meta?: React.ReactNode
14794
+ // /**
14795
+ // * カードの向き。
14796
+ // * - `vertical`(既定): 画像が上、本文が下。グリッド一覧向け
14797
+ // * - `horizontal` : 画像が左、本文が右
14798
+ // * - `list` : 本文が左、サムネイルが右(記事一覧の Medium 型)
14799
+ // */
14800
+ // orientation?: ContentCardOrientation
14801
+ // /** 画像の縦横比(既定 `16/10`。記事のアイキャッチは横長素材が前提) */
14802
+ // aspect?: ContentCardAspect
14803
+ // /**
14804
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
14805
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
14806
+ // */
14807
+ // linkComponent?: LinkComponent
14808
+ // }
14809
+ //
14810
+ // const aspectClass: Record<ContentCardAspect, string> = {
14811
+ // "16/10": "aspect-[16/10]",
14812
+ // "16/9": "aspect-[16/9]",
14813
+ // "1/1": "aspect-[1/1]",
14814
+ // }
14815
+ //
14816
+ // /** orientation ごとの外枠レイアウト */
14817
+ // const rootLayout: Record<ContentCardOrientation, string> = {
14818
+ // vertical: "flex-col gap-2",
14819
+ // horizontal: "flex-row items-start gap-3",
14820
+ // list: "flex-row-reverse items-start gap-3",
14821
+ // }
14822
+ //
14823
+ // /** orientation ごとの画像枠の幅 */
14824
+ // const mediaLayout: Record<ContentCardOrientation, string> = {
14825
+ // vertical: "w-full",
14826
+ // horizontal: "w-28 shrink-0",
14827
+ // list: "w-24 shrink-0",
14828
+ // }
14829
+ //
14830
+ // /**
14831
+ // * 記事・特集・お知らせなど「画像 + タイトル + メタ」のカード。
14832
+ // *
14833
+ // * `ProductCard`(商品)/ `ShopCard`(店舗)の兄弟で、記事メディア向け。
14834
+ // * 汎用の `Card` に載せて組むと、枠線・タイトル行数・カード高さが揃わない
14835
+ // * (実測で高さ 268 と 312 に割れる事例あり)ため、この部品を使う。
14836
+ // *
14837
+ // * ### 作法
14838
+ // *
14839
+ // * - 枠線なし・`rounded-lg`・サーフェスは親から伝播(`Section background="subtle"` 配下では白)
14840
+ // * - タイトルは 2 行で省略し、常に 2 行ぶんの高さを取る(一覧で下端が揃う)
14841
+ // * - `meta` は 1 行固定でカード下端へ寄る
14842
+ // * - 画像は `imageSlot` で consumer が用意する(`next/image` / CMS / 図版を吸収する)
14843
+ // *
14844
+ // * ### AI 向け使用ルール
14845
+ // *
14846
+ // * - 記事一覧・関連記事・注目記事は `Card` + `CardContent` で組まずこれを使う
14847
+ // * - グリッド一覧は `orientation="vertical"`、Medium 型の縦リストは `orientation="list"` +
14848
+ // * `ContentList`(区切り線つき)
14849
+ // * - タイトルの文字装飾を利用側で足さない(`font-bold` にしない。既定は `font-medium`)
14850
+ // */
14851
+ // function ContentCard({
14852
+ // className,
14853
+ // title,
14854
+ // href,
14855
+ // imageSlot,
14856
+ // tag,
14857
+ // meta,
14858
+ // orientation = "vertical",
14859
+ // aspect = "16/10",
14860
+ // linkComponent,
14861
+ // ...props
14862
+ // }: ContentCardProps) {
14863
+ // const Comp = resolveLinkComponent(linkComponent)
14864
+ //
14865
+ // return (
14866
+ // <Comp
14867
+ // data-slot="content-card"
14868
+ // data-orientation={orientation}
14869
+ // href={href}
14870
+ // className={cn(
14871
+ // "group flex rounded-lg bg-[var(--card-surface,var(--Surface-Primary))]",
14872
+ // rootLayout[orientation],
14873
+ // FOCUS_RING,
14874
+ // className
14875
+ // )}
14876
+ // {...props}
14877
+ // >
14878
+ // {imageSlot && (
14879
+ // <div
14880
+ // data-slot="content-card-media"
14881
+ // className={cn(
14882
+ // "relative overflow-hidden rounded-lg",
14883
+ // aspectClass[aspect],
14884
+ // mediaLayout[orientation]
14885
+ // )}
14886
+ // >
14887
+ // <div className="h-full w-full transition-transform duration-[var(--Motion-Duration-Base)] ease-[var(--Motion-Easing-Standard)] group-hover:scale-[1.02]">
14888
+ // {imageSlot}
14889
+ // </div>
14890
+ // {tag && (
14891
+ // <Tag
14892
+ // variant={tag.variant}
14893
+ // className="absolute bottom-2 left-2 max-w-[calc(100%-1rem)] overflow-hidden text-ellipsis"
14894
+ // >
14895
+ // {tag.label}
14896
+ // </Tag>
14897
+ // )}
14898
+ // </div>
14899
+ // )}
14900
+ // <div className="flex min-w-0 flex-1 flex-col gap-0.5">
14901
+ // <span
14902
+ // data-slot="content-card-title"
14903
+ // className="line-clamp-2 min-h-[2lh] typo-body-md font-medium text-[var(--Text-High-Emphasis)]"
14904
+ // >
14905
+ // {title}
14906
+ // </span>
14907
+ // {meta && (
14908
+ // <span
14909
+ // data-slot="content-card-meta"
14910
+ // className="mt-auto truncate typo-body-sm text-[var(--Text-Medium-Emphasis)]"
14911
+ // >
14912
+ // {meta}
14913
+ // </span>
14914
+ // )}
14915
+ // </div>
14916
+ // </Comp>
14917
+ // )
14918
+ // }
14919
+ //
14920
+ // /**
14921
+ // * `ContentCard` を区切り線つきで縦に並べるリスト(記事一覧の Medium 型)。
14922
+ // *
14923
+ // * 一覧ページで `orientation="list"` の `ContentCard` を並べるときに使う。
14924
+ // * 区切り線と項目間の余白だけを持ち、幅・背景は持たない。
14925
+ // */
14926
+ // function ContentList({
14927
+ // className,
14928
+ // ...props
14929
+ // }: React.HTMLAttributes<HTMLDivElement>) {
14930
+ // return (
14931
+ // <div
14932
+ // data-slot="content-list"
14933
+ // className={cn(
14934
+ // "flex flex-col divide-y divide-[var(--Border-Low-Emphasis)]",
14935
+ // "[&>*]:py-4 [&>*:first-child]:pt-0 [&>*:last-child]:pb-0",
14936
+ // className
14937
+ // )}
14938
+ // {...props}
14939
+ // />
14940
+ // )
14941
+ // }
14942
+ //
14943
+ // export { ContentCard, ContentList }
14944
+ //
14586
14945
  // src/components/primitives/content-carousel.tsx
14946
+ // "use client"
14947
+ //
14587
14948
  // import * as React from "react"
14588
14949
  // import ArrowLeft2 from "iconsax-reactjs/dist/esm/ArrowLeft2.js"
14589
14950
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
@@ -14825,6 +15186,8 @@ export {
14825
15186
  // export { ContentCarousel }
14826
15187
  //
14827
15188
  // src/components/primitives/date-picker.tsx
15189
+ // "use client"
15190
+ //
14828
15191
  // /**
14829
15192
  // * ## DatePicker / DateTimePicker — Popover + Calendar 組合せ済みの日付・日時入力
14830
15193
  // *
@@ -15620,9 +15983,12 @@ export {
15620
15983
  // export { FilterBar }
15621
15984
  //
15622
15985
  // src/components/primitives/footer.tsx
15986
+ // "use client"
15987
+ //
15623
15988
  // import * as React from "react"
15624
15989
  //
15625
15990
  // import { cn } from "@/lib/utils"
15991
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
15626
15992
  //
15627
15993
  // export interface FooterLink {
15628
15994
  // label: string
@@ -15682,6 +16048,25 @@ export {
15682
16048
  // trustBadge?: FooterTrustBadge
15683
16049
  // /** フッター下部の補助リンク(特定商取引法、プライバシーポリシー等) */
15684
16050
  // bottomLinks?: FooterLink[]
16051
+ // /**
16052
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
16053
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
16054
+ // * `external: true` のリンクは常に素の `<a target="_blank">` で描く。
16055
+ // */
16056
+ // linkComponent?: LinkComponent
16057
+ // /**
16058
+ // * レイアウト(既定 `default`)。
16059
+ // * - `default` : ロゴ・説明文を最下部に中央寄せ(本番 Cake.jp 準拠)
16060
+ // * - `brand-first` : ロゴ・説明文を先頭カラムに置き、その右にリンク群を並べる。
16061
+ // * 下部バーはコピーライト左・`bottomRightSlot` 右の左右振り分けになる
16062
+ // * (求人ケーキ屋さん.jp / 仕入れケーキ屋さん.JP のフッター構成)
16063
+ // */
16064
+ // variant?: "default" | "brand-first"
16065
+ // /**
16066
+ // * 下部バーの右側に置く要素(`Powered by` 等)。
16067
+ // * `variant="brand-first"` でのみ配置され、既定レイアウトでは無視される。
16068
+ // */
16069
+ // bottomRightSlot?: React.ReactNode
15685
16070
  // }
15686
16071
  //
15687
16072
  // /**
@@ -15757,7 +16142,7 @@ export {
15757
16142
  // * 本番CSS: `.p-footer-item__area { display: flex; justify-content: space-between; }`
15758
16143
  // * 本番CSS: `.p-footer-item__title { pointer-events: none; }` (PCではアコーディオン無効)
15759
16144
  // */
15760
- // function FooterColumnNav({ groups }: { groups: FooterLinkGroup[] }) {
16145
+ // function FooterColumnNav({ groups, linkComponent }: { groups: FooterLinkGroup[]; linkComponent?: LinkComponent }) {
15761
16146
  // const colClass =
15762
16147
  // groups.length <= 4 ? "@lg:grid-cols-4" :
15763
16148
  // groups.length === 5 ? "@lg:grid-cols-5" :
@@ -15773,13 +16158,13 @@ export {
15773
16158
  // <ul className="space-y-1.5">
15774
16159
  // {group.links.map((link) => (
15775
16160
  // <li key={link.label}>
15776
- // <a
15777
- // href={link.href}
16161
+ // <FooterAnchor
16162
+ // link={link}
16163
+ // linkComponent={linkComponent}
15778
16164
  // 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
16165
  // >
15781
16166
  // {link.label}
15782
- // </a>
16167
+ // </FooterAnchor>
15783
16168
  // </li>
15784
16169
  // ))}
15785
16170
  // </ul>
@@ -15792,13 +16177,13 @@ export {
15792
16177
  // <ul className="space-y-1.5">
15793
16178
  // {sub.links.map((link) => (
15794
16179
  // <li key={link.label}>
15795
- // <a
15796
- // href={link.href}
16180
+ // <FooterAnchor
16181
+ // link={link}
16182
+ // linkComponent={linkComponent}
15797
16183
  // 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
16184
  // >
15800
16185
  // {link.label}
15801
- // </a>
16186
+ // </FooterAnchor>
15802
16187
  // </li>
15803
16188
  // ))}
15804
16189
  // </ul>
@@ -15813,19 +16198,46 @@ export {
15813
16198
  // /**
15814
16199
  // * フッターリンクリスト
15815
16200
  // */
15816
- // function FooterLinkList({ links }: { links: FooterLink[] }) {
16201
+ // /**
16202
+ // * フッター内のリンク 1 本。linkComponent が渡されていればそれで描く(#236)。
16203
+ // * 外部リンクは常に素の `<a target="_blank">`。
16204
+ // */
16205
+ // function FooterAnchor({
16206
+ // link,
16207
+ // linkComponent,
16208
+ // className,
16209
+ // children,
16210
+ // }: {
16211
+ // link: FooterLink
16212
+ // linkComponent?: LinkComponent
16213
+ // className?: string
16214
+ // children: React.ReactNode
16215
+ // }) {
16216
+ // const LinkTag = resolveLinkComponent(linkComponent, link.external)
16217
+ // return (
16218
+ // <LinkTag
16219
+ // href={link.href}
16220
+ // className={className}
16221
+ // {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
16222
+ // >
16223
+ // {children}
16224
+ // </LinkTag>
16225
+ // )
16226
+ // }
16227
+ //
16228
+ // function FooterLinkList({ links, linkComponent }: { links: FooterLink[]; linkComponent?: LinkComponent }) {
15817
16229
  // return (
15818
16230
  // <ul>
15819
16231
  // {links.map((link) => (
15820
16232
  // <li key={link.label} className="border-b border-[var(--Border-Low-Emphasis)] last:border-b-0">
15821
- // <a
15822
- // href={link.href}
16233
+ // <FooterAnchor
16234
+ // link={link}
16235
+ // linkComponent={linkComponent}
15823
16236
  // className={cn(
15824
16237
  // "flex items-center justify-between px-5 py-5",
15825
16238
  // "typo-body-sm text-[var(--Text-Medium-Emphasis)]",
15826
16239
  // "hover:text-[var(--Text-High-Emphasis)] transition-colors duration-[var(--Motion-Duration-Fast)]"
15827
16240
  // )}
15828
- // {...(link.external ? { target: "_blank", rel: "noopener noreferrer" } : {})}
15829
16241
  // >
15830
16242
  // <span>{link.label}</span>
15831
16243
  // {/* 右矢印アイコン(本番の icon-arrow と同等) */}
@@ -15838,7 +16250,7 @@ export {
15838
16250
  // >
15839
16251
  // <path d="M3.5 1.5L7 5L3.5 8.5" />
15840
16252
  // </svg>
15841
- // </a>
16253
+ // </FooterAnchor>
15842
16254
  // </li>
15843
16255
  // ))}
15844
16256
  // </ul>
@@ -15879,8 +16291,27 @@ export {
15879
16291
  // paymentMethods = [],
15880
16292
  // trustBadge,
15881
16293
  // bottomLinks = [],
16294
+ // variant = "default",
16295
+ // bottomRightSlot,
16296
+ // linkComponent,
15882
16297
  // ...props
15883
16298
  // }: FooterProps) {
16299
+ // const isBrandFirst = variant === "brand-first"
16300
+ // // ロゴはサイト内トップへの内部遷移なので linkComponent の対象にする(#236)
16301
+ // const LogoLinkTag = resolveLinkComponent(linkComponent)
16302
+ // const brandBlock = (logo || description) && (
16303
+ // <div data-slot="footer-brand" className="grid content-start gap-4">
16304
+ // {logo && (
16305
+ // <LogoLinkTag href={logoHref} className="block w-fit text-[var(--Text-High-Emphasis)]">
16306
+ // {logo}
16307
+ // </LogoLinkTag>
16308
+ // )}
16309
+ // {description && (
16310
+ // <p className="typo-body-sm text-[var(--Text-Low-Emphasis)]">{description}</p>
16311
+ // )}
16312
+ // </div>
16313
+ // )
16314
+ //
15884
16315
  // return (
15885
16316
  // <footer
15886
16317
  // data-slot="footer"
@@ -15898,18 +16329,24 @@ export {
15898
16329
  // */}
15899
16330
  // {linkGroups.length > 0 && (
15900
16331
  // <>
16332
+ // {/* SP: brand-first はブランドブロックを先頭に出す */}
16333
+ // {isBrandFirst && brandBlock && (
16334
+ // <div className="border-t border-[var(--Border-Medium-Emphasis)] px-5 py-8 @lg:hidden">
16335
+ // {brandBlock}
16336
+ // </div>
16337
+ // )}
15901
16338
  // {/* SP: アコーディオン形式(md未満で表示) */}
15902
- // <nav aria-label="フッターナビゲーション" data-slot="footer-links" className="border-t border-[var(--Border-Medium-Emphasis)] @lg:hidden">
16339
+ // <nav aria-label="フッターナビゲーション" data-slot="footer-links" className={cn("border-t border-[var(--Border-Medium-Emphasis)] @lg:hidden", isBrandFirst && "border-t-0")}>
15903
16340
  // {linkGroups.map((group) => (
15904
16341
  // <FooterAccordion key={group.title} title={group.title}>
15905
- // <FooterLinkList links={group.links} />
16342
+ // <FooterLinkList links={group.links} linkComponent={linkComponent} />
15906
16343
  // {/* サブグループ(法人セクション内の催事・マガジン等) */}
15907
16344
  // {group.subGroups?.map((sub) => (
15908
16345
  // <div key={sub.title}>
15909
16346
  // <div className="border-t border-[var(--Border-Low-Emphasis)] px-5 py-5 typo-body-md text-[var(--Text-High-Emphasis)]">
15910
16347
  // {sub.title}
15911
16348
  // </div>
15912
- // <FooterLinkList links={sub.links} />
16349
+ // <FooterLinkList links={sub.links} linkComponent={linkComponent} />
15913
16350
  // </div>
15914
16351
  // ))}
15915
16352
  // </FooterAccordion>
@@ -15924,12 +16361,41 @@ export {
15924
16361
  // className="hidden @lg:block border-t border-[var(--Border-Medium-Emphasis)]"
15925
16362
  // >
15926
16363
  // <div className="mx-auto max-w-[1065px] px-5 py-16">
15927
- // <FooterColumnNav groups={linkGroups} />
16364
+ // {isBrandFirst ? (
16365
+ // // FooterColumnNav は 1 つの grid 子としてリンク群をまとめて持つ。
16366
+ // // auto-fit だと nav 全体が 1 トラックに潰れて中で再分割されるため、
16367
+ // // ブランド列と nav 領域の比率を明示する(求人サイトの 1.6 : 3.4 相当)。
16368
+ // // brandBlock が無い(logo も description も未指定)ときに 2 カラムへ
16369
+ // // すると nav が 1.6fr のブランド側トラックへ入って左に寄るため、
16370
+ // // その場合は nav 単独レイアウトにする。
16371
+ // <div
16372
+ // className={cn(
16373
+ // "grid gap-8",
16374
+ // brandBlock && "@lg:grid-cols-[minmax(0,1.6fr)_minmax(0,3.4fr)]"
16375
+ // )}
16376
+ // >
16377
+ // {brandBlock}
16378
+ // <FooterColumnNav groups={linkGroups} linkComponent={linkComponent} />
16379
+ // </div>
16380
+ // ) : (
16381
+ // <FooterColumnNav groups={linkGroups} linkComponent={linkComponent} />
16382
+ // )}
15928
16383
  // </div>
15929
16384
  // </nav>
15930
16385
  // </>
15931
16386
  // )}
15932
16387
  //
16388
+ // {/* brand-first でリンク群が無いとき、ロゴ・説明文が消えないよう単独で出す
16389
+ // (既定レイアウトは下部バーで出すのでここは通らない) */}
16390
+ // {isBrandFirst && linkGroups.length === 0 && brandBlock && (
16391
+ // <div
16392
+ // data-slot="footer-brand-only"
16393
+ // className="border-t border-[var(--Border-Medium-Emphasis)] px-5 py-8 @lg:py-16"
16394
+ // >
16395
+ // <div className="mx-auto max-w-[1065px]">{brandBlock}</div>
16396
+ // </div>
16397
+ // )}
16398
+ //
15933
16399
  // {/* Social Links (p-footer-item__sns) */}
15934
16400
  // {socialLinks.length > 0 && (
15935
16401
  // <div
@@ -16013,45 +16479,59 @@ export {
16013
16479
  // >
16014
16480
  // <div className="flex flex-wrap items-center justify-center gap-x-3 gap-y-2 @sm:gap-x-4">
16015
16481
  // {bottomLinks.map((link) => (
16016
- // <a
16482
+ // <FooterAnchor
16017
16483
  // key={link.label}
16018
- // href={link.href}
16484
+ // link={link}
16485
+ // linkComponent={linkComponent}
16019
16486
  // 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
16487
  // >
16022
16488
  // {link.label}
16023
- // </a>
16489
+ // </FooterAnchor>
16024
16490
  // ))}
16025
16491
  // </div>
16026
16492
  // </div>
16027
16493
  // )}
16028
16494
  //
16029
16495
  // {/* 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>
16496
+ // {isBrandFirst ? (
16497
+ // // ロゴ・説明文はブランド列で出し済みなので、ここはコピーライトと
16498
+ // // bottomRightSlot(Powered by 等)を左右に振り分けるだけにする。
16499
+ // <div
16500
+ // data-slot="footer-bottom"
16501
+ // className="border-t border-[var(--Border-Medium-Emphasis)] px-5 py-5"
16502
+ // >
16503
+ // <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">
16504
+ // <p>{copyright}</p>
16505
+ // {bottomRightSlot}
16040
16506
  // </div>
16041
- // )}
16507
+ // </div>
16508
+ // ) : (
16509
+ // <div
16510
+ // data-slot="footer-bottom"
16511
+ // className="border-t border-[var(--Border-Medium-Emphasis)] px-5 pt-8 pb-9 text-center"
16512
+ // >
16513
+ // {/* Logo */}
16514
+ // {logo && (
16515
+ // <div className="mx-auto w-fit max-w-[160px]">
16516
+ // <LogoLinkTag href={logoHref} className="block text-[var(--Text-High-Emphasis)]">
16517
+ // {logo}
16518
+ // </LogoLinkTag>
16519
+ // </div>
16520
+ // )}
16042
16521
  //
16043
- // {/* Description */}
16044
- // {description && (
16045
- // <p className="mt-6 typo-body-sm text-[var(--Text-Low-Emphasis)]">
16046
- // {description}
16047
- // </p>
16048
- // )}
16522
+ // {/* Description */}
16523
+ // {description && (
16524
+ // <p className="mt-6 typo-body-sm text-[var(--Text-Low-Emphasis)]">
16525
+ // {description}
16526
+ // </p>
16527
+ // )}
16049
16528
  //
16050
- // {/* Copyright */}
16051
- // <p className="mt-5 typo-body-sm text-[var(--Text-Low-Emphasis)]">
16052
- // {copyright}
16053
- // </p>
16054
- // </div>
16529
+ // {/* Copyright */}
16530
+ // <p className="mt-5 typo-body-sm text-[var(--Text-Low-Emphasis)]">
16531
+ // {copyright}
16532
+ // </p>
16533
+ // </div>
16534
+ // )}
16055
16535
  // </footer>
16056
16536
  // )
16057
16537
  // }
@@ -16059,6 +16539,8 @@ export {
16059
16539
  // export { Footer }
16060
16540
  //
16061
16541
  // src/components/primitives/form-field.tsx
16542
+ // "use client"
16543
+ //
16062
16544
  // /**
16063
16545
  // * ## FormField / フォームフィールド
16064
16546
  // *
@@ -16394,6 +16876,8 @@ export {
16394
16876
  // export { FunnelShell }
16395
16877
  //
16396
16878
  // src/components/primitives/header.tsx
16879
+ // "use client"
16880
+ //
16397
16881
  // import * as React from "react"
16398
16882
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
16399
16883
  // import ArrowLeft from "iconsax-reactjs/dist/esm/ArrowLeft.js"
@@ -16406,8 +16890,15 @@ export {
16406
16890
  // DropdownMenuItem,
16407
16891
  // DropdownMenuTrigger,
16408
16892
  // } from "@/components/foundations/dropdown-menu"
16893
+ // import { containerVariants } from "@/components/primitives/container"
16409
16894
  //
16410
- // export interface HeaderAction {
16895
+ // /**
16896
+ // * ヘッダー内側の最大幅。`Container` の同名 size と同じ値を使う(値の正本は Container)。
16897
+ // * 本文を `Container size="page"` で中央寄せしているサイトで、ロゴ・ナビの左端を本文に揃える。
16898
+ // */
16899
+ // export type HeaderContainerSize = "page" | "wide" | "fluid"
16900
+ //
16901
+ // export interface HeaderAction {
16411
16902
  // /** アイコン要素 */
16412
16903
  // icon: React.ReactNode
16413
16904
  // /** アクセシビリティラベル */
@@ -16422,6 +16913,12 @@ export {
16422
16913
  // href?: string
16423
16914
  // /** バッジ数(通知やカート件数) */
16424
16915
  // badge?: React.ReactNode
16916
+ // /**
16917
+ // * `label` をアイコンの右に可視テキストとして出す(既定 false = アイコンのみ)。
16918
+ // * 「ログイン」等、文字が無いと意味が伝わりにくい導線に使う。
16919
+ // * true のときは正方形のアイコンボタンではなく、枠線付きのピル型で描画する。
16920
+ // */
16921
+ // showLabel?: boolean
16425
16922
  // }
16426
16923
  //
16427
16924
  // export interface HeaderNavItem {
@@ -16466,7 +16963,7 @@ export {
16466
16963
  // /**
16467
16964
  // * インラインナビ(navItems / searchSlot 行)を出し始めるコンテナ幅。
16468
16965
  // * - `md`(既定): `@[768px]`+
16469
- // * - `lg` : `@[1024px]`+(ロゴが多段で横幅を食う等、中幅での同居を避けたいとき)
16966
+ // * - `lg` : `@[960px]`+(ロゴが多段で横幅を食う等、中幅での同居を避けたいとき)
16470
16967
  // * 未満の幅では SP 行(ロゴ + actions)になる。
16471
16968
  // */
16472
16969
  // navBreakpoint?: "md" | "lg"
@@ -16480,6 +16977,16 @@ export {
16480
16977
  // * navItems が無く searchSlot だけを渡した場合も PC 行を描画する。
16481
16978
  // */
16482
16979
  // searchSlot?: React.ReactNode
16980
+ // /**
16981
+ // * `searchSlot` を出し始めるコンテナ幅(既定はインラインナビ行と同じ)。
16982
+ // * tokens.json の切替段に一致する `md`(768px)/ `lg`(960px)のみ。
16983
+ // * `xl`(1280) はコンテンツ上限段でレイアウトの切替段ではないため受け付けない。
16984
+ // *
16985
+ // * 中身を consumer 側の CSS で隠しても、このスロットの器は `flex-1` の幅を
16986
+ // * 確保し続けてインラインナビを潰す(#243)。狭い帯で検索を出さない場合は
16987
+ // * CSS ではなくこの prop で器ごと畳むこと。
16988
+ // */
16989
+ // searchBreakpoint?: "md" | "lg"
16483
16990
  // /** 右側に配置するカスタム要素(variant="back"で使用) */
16484
16991
  // rightSlot?: React.ReactNode
16485
16992
  // /** 検索バーなど中央に配置するカスタム要素(variant="back-search"で使用) */
@@ -16492,6 +16999,65 @@ export {
16492
16999
  // bottomSlot?: React.ReactNode
16493
17000
  // /** sticky 配置を無効化 */
16494
17001
  // disableSticky?: boolean
17002
+ // /**
17003
+ // * ヘッダー内側の最大幅(`Container` と同じ段)。
17004
+ // * 指定すると背景・border・sticky は全幅のまま、**中身だけ**を中央寄せする。
17005
+ // * 本文を `Container size="page"` で組んでいるサイトで、ロゴ・ナビの左端が本文と揃う。
17006
+ // * 未指定なら従来どおり全幅(DOM も従来どおりで内側ラッパーを足さない)。
17007
+ // */
17008
+ // containerSize?: HeaderContainerSize
17009
+ // }
17010
+ //
17011
+ // /**
17012
+ // * ヘッダーの外枠。
17013
+ // *
17014
+ // * `containerSize` 指定時は、背景・border・sticky を `<header>` に残したまま、
17015
+ // * 内側だけ `Container` 相当(max-width + mx-auto)で中央寄せする。
17016
+ // * 未指定時はラッパーを足さず、従来の DOM 構造をそのまま保つ。
17017
+ // */
17018
+ // function HeaderShell({
17019
+ // containerSize,
17020
+ // shellClass,
17021
+ // layoutClass,
17022
+ // containerQuery = false,
17023
+ // children,
17024
+ // ...props
17025
+ // }: React.ComponentProps<"header"> & {
17026
+ // containerSize?: HeaderContainerSize
17027
+ // /** sticky / 背景 / border / 利用側 className をまとめたもの(常に全幅側) */
17028
+ // shellClass?: string
17029
+ // /** その variant の行レイアウト(padding 含む)。containerSize 指定時は内側へ移す */
17030
+ // layoutClass?: string
17031
+ // /** @container を張るか(variant="logo" のインラインナビ判定用) */
17032
+ // containerQuery?: boolean
17033
+ // }) {
17034
+ // if (!containerSize) {
17035
+ // return (
17036
+ // <header
17037
+ // data-slot="header"
17038
+ // className={cn(containerQuery && "@container", layoutClass, shellClass)}
17039
+ // {...props}
17040
+ // >
17041
+ // {children}
17042
+ // </header>
17043
+ // )
17044
+ // }
17045
+ //
17046
+ // return (
17047
+ // <header data-slot="header" className={shellClass} {...props}>
17048
+ // <div
17049
+ // data-slot="header-container"
17050
+ // data-container-size={containerSize}
17051
+ // className={cn(
17052
+ // containerQuery && "@container",
17053
+ // containerVariants({ size: containerSize, gutter: "none" }),
17054
+ // layoutClass
17055
+ // )}
17056
+ // >
17057
+ // {children}
17058
+ // </div>
17059
+ // </header>
17060
+ // )
16495
17061
  // }
16496
17062
  //
16497
17063
  // /** ナビ項目の共通クラス(表示用・計測用で同一にしないと退避判定がずれる) */
@@ -16581,21 +17147,30 @@ export {
16581
17147
  //
16582
17148
  // return (
16583
17149
  // <div ref={wrapRef} className="relative min-w-0 flex-1">
16584
- // {/* 計測用の複製(visibility:hidden・absolute なのでレイアウトに影響しない) */}
17150
+ // {/*
17151
+ // 計測用の複製。absolute + invisible は通常フローには影響しないが、絶対配置
17152
+ // 要素も祖先のスクロール可能領域には寄与するため、そのままではページ全体が
17153
+ // 横スクロールする(#243)。0 幅 0 高 + overflow:hidden の器で包んで寄与を
17154
+ // 断つ。クリップは描画時のみでレイアウトは保たれるため計測結果は変わらない。
17155
+ // */}
16585
17156
  // <div
16586
- // ref={measureRef}
16587
17157
  // aria-hidden="true"
16588
- // className="invisible pointer-events-none absolute top-0 left-0 flex w-max items-center gap-0.5"
17158
+ // className="pointer-events-none absolute top-0 left-0 h-0 w-0 overflow-hidden"
16589
17159
  // >
16590
- // {items.map((item) => (
16591
- // <span key={item.label} className={navItemClass(item.isActive)}>
16592
- // {item.label}
17160
+ // <div
17161
+ // ref={measureRef}
17162
+ // className="invisible flex w-max items-center gap-0.5"
17163
+ // >
17164
+ // {items.map((item) => (
17165
+ // <span key={item.label} className={navItemClass(item.isActive)}>
17166
+ // {item.label}
17167
+ // </span>
17168
+ // ))}
17169
+ // <span className={cn(navItemClass(false), "inline-flex items-center gap-1")}>
17170
+ // {overflowLabel}
17171
+ // <ArrowDown2 size={16} />
16593
17172
  // </span>
16594
- // ))}
16595
- // <span className={cn(navItemClass(false), "inline-flex items-center gap-1")}>
16596
- // {overflowLabel}
16597
- // <ArrowDown2 size={16} />
16598
- // </span>
17173
+ // </div>
16599
17174
  // </div>
16600
17175
  //
16601
17176
  // <nav className="flex items-center gap-0.5">
@@ -16672,10 +17247,12 @@ export {
16672
17247
  // navBreakpoint = "md",
16673
17248
  // navOverflowLabel,
16674
17249
  // searchSlot,
17250
+ // searchBreakpoint,
16675
17251
  // rightSlot,
16676
17252
  // centerSlot,
16677
17253
  // bottomSlot,
16678
17254
  // disableSticky = false,
17255
+ // containerSize,
16679
17256
  // ...props
16680
17257
  // }: HeaderProps) {
16681
17258
  // const stickyClass = disableSticky
@@ -16685,11 +17262,21 @@ export {
16685
17262
  // const baseClass =
16686
17263
  // "border-b border-[var(--Border-Low-Emphasis)] bg-[var(--Surface-Primary)]"
16687
17264
  //
17265
+ // const shellClass = cn(stickyClass, baseClass, className)
17266
+ //
16688
17267
  // // navBreakpoint → コンテナクエリのクラス(Tailwind の静的解析を保つため即値で持つ)
17268
+ // // 切替段は tokens.json の md=768 / lg=960 のみ(1024 は DS に存在しない段)
16689
17269
  // const spRowHiddenClass =
16690
- // navBreakpoint === "lg" ? "@[1024px]:hidden" : "@[768px]:hidden"
17270
+ // navBreakpoint === "lg" ? "@[960px]:hidden" : "@[768px]:hidden"
16691
17271
  // const pcRowVisibleClass =
16692
- // navBreakpoint === "lg" ? "hidden @[1024px]:flex" : "hidden @[768px]:flex"
17272
+ // navBreakpoint === "lg" ? "hidden @[960px]:flex" : "hidden @[768px]:flex"
17273
+ // // searchSlot の器を出す幅。未指定ならナビ行と同じ(=常に描画)。
17274
+ // const searchSlotVisibleClass =
17275
+ // searchBreakpoint === "lg"
17276
+ // ? "hidden @[960px]:block"
17277
+ // : searchBreakpoint === "md"
17278
+ // ? "hidden @[768px]:block"
17279
+ // : undefined
16693
17280
  //
16694
17281
  // /* ── variant: logo ─────────────────────────────── */
16695
17282
  // if (variant === "logo") {
@@ -16701,38 +17288,56 @@ export {
16701
17288
  //
16702
17289
  // const actionsEl = actions && actions.length > 0 && (
16703
17290
  // <div className="flex shrink-0 items-center gap-1">
16704
- // {actions.map((action) =>
16705
- // action.href ? (
17291
+ // {actions.map((action) => {
17292
+ // // showLabel はアイコン+可視テキストのピル。タップターゲット確保のため
17293
+ // // 高さは 40px(h-10)で、正方形の icon-sm とは別サイズにする。
17294
+ // const buttonProps = action.showLabel
17295
+ // ? {
17296
+ // variant: "ghost" as const,
17297
+ // size: "sm" as const,
17298
+ // className:
17299
+ // "h-10 gap-1.5 rounded-full border border-[var(--Border-Medium-Emphasis)] px-4",
17300
+ // }
17301
+ // : { variant: "ghost" as const, size: "icon-sm" as const }
17302
+ // const content = (
17303
+ // <>
17304
+ // {action.badge ? action.badge : action.icon}
17305
+ // {action.showLabel && (
17306
+ // <span className="typo-label-sm">{action.label}</span>
17307
+ // )}
17308
+ // </>
17309
+ // )
17310
+ //
17311
+ // return action.href ? (
16706
17312
  // <Button
16707
17313
  // key={action.label}
16708
17314
  // asChild
16709
- // variant="ghost"
16710
- // size="icon-sm"
16711
- // aria-label={action.label}
17315
+ // {...buttonProps}
17316
+ // aria-label={action.showLabel ? undefined : action.label}
16712
17317
  // >
16713
17318
  // <a href={action.href} onClick={action.onClick}>
16714
- // {action.badge ? action.badge : action.icon}
17319
+ // {content}
16715
17320
  // </a>
16716
17321
  // </Button>
16717
17322
  // ) : (
16718
17323
  // <Button
16719
17324
  // key={action.label}
16720
- // variant="ghost"
16721
- // size="icon-sm"
16722
- // aria-label={action.label}
17325
+ // {...buttonProps}
17326
+ // aria-label={action.showLabel ? undefined : action.label}
16723
17327
  // onClick={action.onClick}
16724
17328
  // >
16725
- // {action.badge ? action.badge : action.icon}
17329
+ // {content}
16726
17330
  // </Button>
16727
17331
  // )
16728
- // )}
17332
+ // })}
16729
17333
  // </div>
16730
17334
  // )
16731
17335
  //
16732
17336
  // return (
16733
- // <header
16734
- // data-slot="header"
16735
- // className={cn(stickyClass, baseClass, "@container", className)}
17337
+ // <HeaderShell
17338
+ // containerSize={containerSize}
17339
+ // shellClass={shellClass}
17340
+ // containerQuery
16736
17341
  // {...props}
16737
17342
  // >
16738
17343
  // {/* SP: ロゴ + アクション(navItems / searchSlot は非表示。SP 検索は bottomSlot で運用) */}
@@ -16744,7 +17349,7 @@ export {
16744
17349
  // {actionsEl}
16745
17350
  // </div>
16746
17351
  //
16747
- // {/* PC(既定 @[768px]+ / navBreakpoint="lg" なら @[1024px]+):
17352
+ // {/* PC(既定 @[768px]+ / navBreakpoint="lg" なら @[960px]+):
16748
17353
  // ロゴ + グローバルナビ + 検索 + アクション(1行)。
16749
17354
  // navItems / searchSlot のどちらかがあれば描画する。 */}
16750
17355
  // {(navItems || searchSlot) && (
@@ -16760,28 +17365,31 @@ export {
16760
17365
  // </div>
16761
17366
  // {/* 検索スロット(navItems と actions の間・伸縮。既存要素を潰さない) */}
16762
17367
  // {searchSlot && (
16763
- // <div className="min-w-0 flex-1 max-w-[400px]">{searchSlot}</div>
17368
+ // <div
17369
+ // className={cn(
17370
+ // "min-w-0 flex-1 max-w-[400px]",
17371
+ // searchSlotVisibleClass
17372
+ // )}
17373
+ // >
17374
+ // {searchSlot}
17375
+ // </div>
16764
17376
  // )}
16765
17377
  // {actionsEl}
16766
17378
  // </div>
16767
17379
  // )}
16768
17380
  //
16769
17381
  // {bottomSlot}
16770
- // </header>
17382
+ // </HeaderShell>
16771
17383
  // )
16772
17384
  // }
16773
17385
  //
16774
17386
  // /* ── variant: logo-center ────────────────────────── */
16775
17387
  // if (variant === "logo-center") {
16776
17388
  // 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
- // )}
17389
+ // <HeaderShell
17390
+ // containerSize={containerSize}
17391
+ // shellClass={shellClass}
17392
+ // layoutClass="flex items-center justify-center px-4 py-3"
16785
17393
  // {...props}
16786
17394
  // >
16787
17395
  // {typeof logo === "string" ? (
@@ -16791,27 +17399,25 @@ export {
16791
17399
  // ) : (
16792
17400
  // logo ?? null
16793
17401
  // )}
16794
- // </header>
17402
+ // </HeaderShell>
16795
17403
  // )
16796
17404
  // }
16797
17405
  //
16798
17406
  // /* ── variant: back-search ──────────────────────── */
16799
17407
  // if (variant === "back-search") {
16800
17408
  // return (
16801
- // <header
16802
- // data-slot="header"
16803
- // className={cn(
16804
- // stickyClass,
16805
- // baseClass,
16806
- // "px-4 py-3",
16807
- // className
16808
- // )}
17409
+ // <HeaderShell
17410
+ // containerSize={containerSize}
17411
+ // shellClass={shellClass}
17412
+ // layoutClass="px-4 py-3"
16809
17413
  // {...props}
16810
17414
  // >
16811
17415
  // <div className="flex items-center gap-2">
17416
+ // {/* centerSlot は SearchBar 等の入力コントロール(44px)が入るので、
17417
+ // 戻るボタンも同じ 44px にして高さを揃える(icon-sm=32px だと 12px ずれる) */}
16812
17418
  // <Button
16813
17419
  // variant="ghost"
16814
- // size="icon-sm"
17420
+ // size="icon-xl"
16815
17421
  // aria-label={backLabel}
16816
17422
  // onClick={onBack}
16817
17423
  // >
@@ -16819,7 +17425,7 @@ export {
16819
17425
  // </Button>
16820
17426
  // {centerSlot && <div className="flex-1">{centerSlot}</div>}
16821
17427
  // </div>
16822
- // </header>
17428
+ // </HeaderShell>
16823
17429
  // )
16824
17430
  // }
16825
17431
  //
@@ -16828,14 +17434,10 @@ export {
16828
17434
  // // 左右カラムを等幅にすることで、rightSlot の幅に関わらずタイトルがヘッダー中央に
16829
17435
  // // 正しく揃う(旧 flex-1 text-center は rightSlot が広いとタイトルが左へずれた)。
16830
17436
  // 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
- // )}
17437
+ // <HeaderShell
17438
+ // containerSize={containerSize}
17439
+ // shellClass={shellClass}
17440
+ // layoutClass="grid grid-cols-[1fr_auto_1fr] items-center gap-2 px-2 py-3"
16839
17441
  // {...props}
16840
17442
  // >
16841
17443
  // <div className="justify-self-start">
@@ -16852,13 +17454,15 @@ export {
16852
17454
  // {title}
16853
17455
  // </h1>
16854
17456
  // <div className="justify-self-end">{rightSlot}</div>
16855
- // </header>
17457
+ // </HeaderShell>
16856
17458
  // )
16857
17459
  // }
16858
17460
  //
16859
17461
  // export { Header }
16860
17462
  //
16861
17463
  // src/components/primitives/image-carousel.tsx
17464
+ // "use client"
17465
+ //
16862
17466
  // import * as React from "react"
16863
17467
  // import ArrowLeft2 from "iconsax-reactjs/dist/esm/ArrowLeft2.js"
16864
17468
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
@@ -17111,6 +17715,8 @@ export {
17111
17715
  // export { ImageCarousel }
17112
17716
  //
17113
17717
  // src/components/primitives/image-gallery.tsx
17718
+ // "use client"
17719
+ //
17114
17720
  // import * as React from "react"
17115
17721
  // import ArrowLeft2 from "iconsax-reactjs/dist/esm/ArrowLeft2.js"
17116
17722
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
@@ -17350,6 +17956,8 @@ export {
17350
17956
  // export { ImageGallery }
17351
17957
  //
17352
17958
  // src/components/primitives/image-input.tsx
17959
+ // "use client"
17960
+ //
17353
17961
  // import * as React from "react"
17354
17962
  // import { cva, type VariantProps } from "class-variance-authority"
17355
17963
  // import { Image as ImageIcon, X } from "lucide-react"
@@ -17917,6 +18525,8 @@ export {
17917
18525
  // }
17918
18526
  //
17919
18527
  // src/components/primitives/list-item.tsx
18528
+ // "use client"
18529
+ //
17920
18530
  // import * as React from "react"
17921
18531
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
17922
18532
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
@@ -18139,6 +18749,8 @@ export {
18139
18749
  // export { ListItem }
18140
18750
  //
18141
18751
  // src/components/primitives/menu-drawer.tsx
18752
+ // "use client"
18753
+ //
18142
18754
  // import * as React from "react"
18143
18755
  // import ArrowDown2 from "iconsax-reactjs/dist/esm/ArrowDown2.js"
18144
18756
  // import ArrowRight2 from "iconsax-reactjs/dist/esm/ArrowRight2.js"
@@ -18147,6 +18759,7 @@ export {
18147
18759
  // import { X } from "lucide-react"
18148
18760
  //
18149
18761
  // import { cn } from "@/lib/utils"
18762
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
18150
18763
  // import { Button } from "@/components/foundations/button"
18151
18764
  //
18152
18765
  // export interface MenuSection {
@@ -18191,6 +18804,12 @@ export {
18191
18804
  // }
18192
18805
  //
18193
18806
  // export interface MenuDrawerProps extends React.HTMLAttributes<HTMLDivElement> {
18807
+ // /**
18808
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
18809
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
18810
+ // */
18811
+ // linkComponent?: LinkComponent
18812
+ //
18194
18813
  // /** ユーザー名(ログイン時) */
18195
18814
  // userName?: string
18196
18815
  // /** ログイン状態 */
@@ -18247,8 +18866,12 @@ export {
18247
18866
  // onLogin,
18248
18867
  // loginHref = "/security/login_link/",
18249
18868
  // className,
18869
+ // linkComponent,
18250
18870
  // ...props
18251
18871
  // }: MenuDrawerProps) {
18872
+ // // ログイン導線・バナーも内部遷移なので linkComponent の対象にする(#236)
18873
+ // const LoginLinkTag = resolveLinkComponent(linkComponent)
18874
+ // const BannerLinkTag = resolveLinkComponent(linkComponent)
18252
18875
  // const [expandedSections, setExpandedSections] = React.useState<Set<number>>(
18253
18876
  // new Set()
18254
18877
  // )
@@ -18305,7 +18928,7 @@ export {
18305
18928
  // <div className="py-2">
18306
18929
  // <ul>
18307
18930
  // <li>
18308
- // <a
18931
+ // <LoginLinkTag
18309
18932
  // href={loginHref}
18310
18933
  // onClick={
18311
18934
  // onLogin
@@ -18321,7 +18944,7 @@ export {
18321
18944
  // <Add size={16} />
18322
18945
  // </span>
18323
18946
  // <span className="flex-1">ログイン・新規会員登録</span>
18324
- // </a>
18947
+ // </LoginLinkTag>
18325
18948
  // </li>
18326
18949
  // </ul>
18327
18950
  // </div>
@@ -18355,7 +18978,7 @@ export {
18355
18978
  // <ul>
18356
18979
  // {section.items.map((item) => (
18357
18980
  // <li key={item.label}>
18358
- // <MenuItemLink item={item} />
18981
+ // <MenuItemLink linkComponent={linkComponent} item={item} />
18359
18982
  // </li>
18360
18983
  // ))}
18361
18984
  // </ul>
@@ -18367,7 +18990,7 @@ export {
18367
18990
  // <ul>
18368
18991
  // {section.itemsExtra.map((item) => (
18369
18992
  // <li key={item.label}>
18370
- // <MenuItemLink item={item} />
18993
+ // <MenuItemLink linkComponent={linkComponent} item={item} />
18371
18994
  // </li>
18372
18995
  // ))}
18373
18996
  // </ul>
@@ -18401,7 +19024,7 @@ export {
18401
19024
  // <ul className="flex justify-center">
18402
19025
  // {banners.map((banner, i) => (
18403
19026
  // <li key={i} className="w-1/2 max-w-28 px-2">
18404
- // <a
19027
+ // <BannerLinkTag
18405
19028
  // href={banner.href ?? "#"}
18406
19029
  // className="block overflow-hidden rounded"
18407
19030
  // >
@@ -18411,7 +19034,7 @@ export {
18411
19034
  // alt={banner.alt}
18412
19035
  // className="h-auto w-full object-cover"
18413
19036
  // />
18414
- // </a>
19037
+ // </BannerLinkTag>
18415
19038
  // </li>
18416
19039
  // ))}
18417
19040
  // </ul>
@@ -18423,9 +19046,10 @@ export {
18423
19046
  // }
18424
19047
  //
18425
19048
  // /** 個別メニューアイテムのリンク表示 */
18426
- // function MenuItemLink({ item }: { item: MenuItem }) {
19049
+ // function MenuItemLink({ item, linkComponent }: { item: MenuItem; linkComponent?: LinkComponent }) {
19050
+ // const LinkTag = resolveLinkComponent(linkComponent)
18427
19051
  // return (
18428
- // <a
19052
+ // <LinkTag
18429
19053
  // href={item.href ?? "#"}
18430
19054
  // onClick={item.onClick}
18431
19055
  // className={menuRowClass}
@@ -18466,13 +19090,15 @@ export {
18466
19090
  // {item.hasChildren && (
18467
19091
  // <ArrowRight2 size={16} className="shrink-0 text-[var(--Object-High-Emphasis)]" />
18468
19092
  // )}
18469
- // </a>
19093
+ // </LinkTag>
18470
19094
  // )
18471
19095
  // }
18472
19096
  //
18473
19097
  // export { MenuDrawer }
18474
19098
  //
18475
19099
  // src/components/primitives/multi-select.tsx
19100
+ // "use client"
19101
+ //
18476
19102
  // import * as React from "react"
18477
19103
  // import { Check, ChevronsUpDown } from "lucide-react"
18478
19104
  //
@@ -18871,6 +19497,8 @@ export {
18871
19497
  // export { NotificationList }
18872
19498
  //
18873
19499
  // src/components/primitives/number-input.tsx
19500
+ // "use client"
19501
+ //
18874
19502
  // import * as React from "react"
18875
19503
  // import Add from "iconsax-reactjs/dist/esm/Add.js"
18876
19504
  // import Minus from "iconsax-reactjs/dist/esm/Minus.js"
@@ -19511,7 +20139,104 @@ export {
19511
20139
  //
19512
20140
  // export { ProgressSteps }
19513
20141
  //
20142
+ // src/components/primitives/prose.tsx
20143
+ // import * as React from "react"
20144
+ //
20145
+ // import { cn } from "@/lib/utils"
20146
+ //
20147
+ // export interface ProseProps extends React.HTMLAttributes<HTMLElement> {
20148
+ // /**
20149
+ // * CMS(microCMS 等)のリッチテキスト HTML。
20150
+ // *
20151
+ // * **サニタイズ済みの HTML だけを渡すこと。** この部品は体裁を当てるだけで、
20152
+ // * 中身の無害化は行わない(`dangerouslySetInnerHTML` に素通しする)。
20153
+ // * 未指定なら `children` をそのまま包む。
20154
+ // */
20155
+ // html?: string
20156
+ // /** ラップする要素(既定 `div`。記事本文なら `article`) */
20157
+ // as?: "div" | "article" | "section"
20158
+ // }
20159
+ //
20160
+ // /**
20161
+ // * 記事本文の体裁(見出し・段落・リスト・引用・表・画像・リンク)をトークンで揃える。
20162
+ // *
20163
+ // * 各要素の余白・サイズ・線・色を 1 箇所に集約し、記事メディアごとに CSS Modules を
20164
+ // * 書き分けて見た目がばらつくのを防ぐ。`Container size="narrow"`(760px)と
20165
+ // * 組み合わせて使う前提の行長になっている。
20166
+ // *
20167
+ // * ### AI 向け使用ルール
20168
+ // *
20169
+ // * - CMS のリッチテキストを描くときは、consumer 側で `h2` / `p` / `ul` の CSS を書かず
20170
+ // * これを使う(`ArticleBody.module.css` のような独自 CSS を作らない)
20171
+ // * - `html` に渡す HTML は **利用側でサニタイズ済み**であること
20172
+ // * - 記事幅は `Container size="narrow"` で決める。この部品は幅を持たない
20173
+ // * - 見出しレベルは CMS の出力に従う(この部品は体裁だけを当て、階層は変えない)
20174
+ // *
20175
+ // * @example
20176
+ // * <Container size="narrow">
20177
+ // * <Prose as="article" html={sanitizedHtml} />
20178
+ // * </Container>
20179
+ // */
20180
+ // function Prose({ className, html, as: Comp = "div", children, ...props }: ProseProps) {
20181
+ // const proseClass = cn(
20182
+ // // 基本の本文
20183
+ // "typo-body-md text-[var(--Text-High-Emphasis)]",
20184
+ // // 見出し
20185
+ // "[&_h2]:mt-10 [&_h2]:mb-4 [&_h2]:typo-heading-2xl",
20186
+ // "[&_h3]:mt-8 [&_h3]:mb-3 [&_h3]:typo-heading-xl",
20187
+ // "[&_h4]:mt-6 [&_h4]:mb-2 [&_h4]:typo-heading-lg",
20188
+ // "[&_h5]:mt-6 [&_h5]:mb-2 [&_h5]:typo-heading-md",
20189
+ // // 段落・リスト
20190
+ // "[&_p]:my-4",
20191
+ // "[&_ul]:my-4 [&_ul]:list-disc [&_ul]:pl-6",
20192
+ // "[&_ol]:my-4 [&_ol]:list-decimal [&_ol]:pl-6",
20193
+ // "[&_li]:my-1",
20194
+ // // 引用
20195
+ // "[&_blockquote]:my-6 [&_blockquote]:border-l-4 [&_blockquote]:border-[var(--Border-Medium-Emphasis)] [&_blockquote]:pl-4 [&_blockquote]:text-[var(--Text-Medium-Emphasis)]",
20196
+ // // リンク
20197
+ // "[&_a]:text-[var(--Text-Accent-Primary)] [&_a]:underline [&_a]:underline-offset-2 [&_a:hover]:no-underline",
20198
+ // // 画像・図版
20199
+ // "[&_img]:my-6 [&_img]:h-auto [&_img]:w-full [&_img]:rounded-lg",
20200
+ // "[&_figure]:my-6 [&_figcaption]:mt-2 [&_figcaption]:typo-body-sm [&_figcaption]:text-[var(--Text-Medium-Emphasis)]",
20201
+ // // 表。block + w-max + max-w-full で、枠に収まるまで縮み、縮みきれなければ
20202
+ // // 表自身が横スクロールする。どちらの場合もページを横に伸ばさない
20203
+ // "[&_table]:my-6 [&_table]:block [&_table]:w-max [&_table]:max-w-full [&_table]:overflow-x-auto [&_table]:border-collapse",
20204
+ // "[&_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",
20205
+ // "[&_td]:border [&_td]:border-[var(--Border-Low-Emphasis)] [&_td]:px-3 [&_td]:py-2",
20206
+ // // コード
20207
+ // "[&_code]:rounded-xs [&_code]:bg-[var(--Surface-Secondary)] [&_code]:px-1 [&_code]:py-0.5",
20208
+ // "[&_pre]:my-6 [&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:bg-[var(--Surface-Secondary)] [&_pre]:p-4",
20209
+ // "[&_pre_code]:bg-transparent [&_pre_code]:p-0",
20210
+ // // 区切り線
20211
+ // "[&_hr]:my-8 [&_hr]:border-t [&_hr]:border-[var(--Border-Low-Emphasis)]",
20212
+ // // 先頭・末尾は外側の余白と二重にしない
20213
+ // "[&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
20214
+ // className
20215
+ // )
20216
+ //
20217
+ // if (html !== undefined) {
20218
+ // return (
20219
+ // <Comp
20220
+ // data-slot="prose"
20221
+ // className={proseClass}
20222
+ // dangerouslySetInnerHTML={{ __html: html }}
20223
+ // {...props}
20224
+ // />
20225
+ // )
20226
+ // }
20227
+ //
20228
+ // return (
20229
+ // <Comp data-slot="prose" className={proseClass} {...props}>
20230
+ // {children}
20231
+ // </Comp>
20232
+ // )
20233
+ // }
20234
+ //
20235
+ // export { Prose }
20236
+ //
19514
20237
  // src/components/primitives/search-bar.tsx
20238
+ // "use client"
20239
+ //
19515
20240
  // import * as React from "react"
19516
20241
  // import SearchNormal1 from "iconsax-reactjs/dist/esm/SearchNormal1.js"
19517
20242
  //
@@ -19526,6 +20251,17 @@ export {
19526
20251
  // size?: "sm" | "md"
19527
20252
  // /** 検索リンクURL({query} はクエリに置換) */
19528
20253
  // searchHref?: string
20254
+ // /**
20255
+ // * 指定すると `<form method="get" action={action}>` として描画し、素のフォーム送信で遷移する。
20256
+ // * JS を必要としないので、スクリプト無効環境やクローラでも検索が成立する(SEO 重視のサイト向け)。
20257
+ // * 送信するクエリのキーは `name`(既定 `"q"`)。`searchHref` とは併用しない(`action` が優先)。
20258
+ // */
20259
+ // action?: string
20260
+ // /**
20261
+ // * 送信するクエリのキー(`action` 指定時の既定 `"q"`)。
20262
+ // * そのまま input の `name` 属性になる。
20263
+ // */
20264
+ // name?: string
19529
20265
  // }
19530
20266
  //
19531
20267
  // /**
@@ -19546,7 +20282,9 @@ export {
19546
20282
  // * - `size="sm"` はコンパクトなヘッダー向け
19547
20283
  // * - `size="md"` は検索専用ページ向け
19548
20284
  // * - `onSearch` で検索クエリを受け取る
19549
- // * - `searchHref` で検索結果ページへの遷移リンクを生成
20285
+ // * - `searchHref` で検索結果ページへの遷移リンクを生成(JS が必要)
20286
+ // * - **JS 無効環境・SEO を考慮するサイトは `action` を使う**。`<form method="get">` として
20287
+ // * 描画され、素のフォーム送信で遷移する(`Input` + `Button` で `<form>` を手組みしない)
19550
20288
  // */
19551
20289
  // const SearchBar = React.forwardRef<HTMLInputElement, SearchBarProps>(
19552
20290
  // (
@@ -19556,10 +20294,14 @@ export {
19556
20294
  // onSearch,
19557
20295
  // size = "md",
19558
20296
  // searchHref,
20297
+ // action,
20298
+ // name,
19559
20299
  // ...props
19560
20300
  // },
19561
20301
  // ref
19562
20302
  // ) => {
20303
+ // /** action があれば素の GET フォームとして描く(JS 不要で遷移する) */
20304
+ // const isFormMode = !!action
19563
20305
  // const inputRef = React.useRef<HTMLInputElement | null>(null)
19564
20306
  //
19565
20307
  // const setRefs = React.useCallback(
@@ -19584,29 +20326,40 @@ export {
19584
20326
  // }
19585
20327
  //
19586
20328
  // const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
19587
- // if (e.key === "Enter") {
20329
+ // // form モードでは Enter は素のフォーム送信が処理する(ここで遷移すると二重になる)
20330
+ // if (e.key === "Enter" && !isFormMode) {
19588
20331
  // triggerSearch()
19589
20332
  // }
19590
20333
  // props.onKeyDown?.(e)
19591
20334
  // }
19592
20335
  //
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
- // >
20336
+ // /** form モードの送信。空クエリは従来どおり無視する */
20337
+ // const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
20338
+ // const query = inputRef.current?.value ?? ""
20339
+ // if (!query.trim()) {
20340
+ // e.preventDefault()
20341
+ // return
20342
+ // }
20343
+ // onSearch?.(query)
20344
+ // }
20345
+ //
20346
+ // const rootClassName = cn(
20347
+ // "group flex items-center overflow-hidden rounded-lg border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Secondary)] transition-colors",
20348
+ // // Tailwind の variant 順では focus-within が hover より先に出力される
20349
+ // // = hover が後勝ちしてフォーカス枠を潰すため、hover 側を明示的に抑制する。
20350
+ // "hover:not-focus-within:border-[var(--Border-High-Emphasis)]",
20351
+ // FOCUS_RING_WITHIN,
20352
+ // size === "sm" ? "h-9" : "h-11",
20353
+ // className
20354
+ // )
20355
+ //
20356
+ // const content = (
20357
+ // <>
19606
20358
  // <input
19607
20359
  // ref={setRefs}
19608
20360
  // type="search"
19609
20361
  // aria-label="キーワード検索"
20362
+ // name={isFormMode ? (name ?? "q") : name}
19610
20363
  // placeholder={placeholder}
19611
20364
  // className={cn(
19612
20365
  // "min-w-0 flex-1 bg-transparent px-3 text-[var(--Text-High-Emphasis)] outline-none placeholder:text-[var(--Text-Low-Emphasis)]",
@@ -19616,18 +20369,40 @@ export {
19616
20369
  // {...props}
19617
20370
  // />
19618
20371
  // <button
19619
- // type="button"
20372
+ // type={isFormMode ? "submit" : "button"}
19620
20373
  // className={cn(
19621
20374
  // "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
20375
  // // 親が overflow-hidden なので外向きリングは切れる。内側に描く。
19623
20376
  // FOCUS_RING_INSET,
19624
20377
  // size === "sm" ? "size-9" : "h-11 w-11"
19625
20378
  // )}
19626
- // onClick={triggerSearch}
20379
+ // onClick={isFormMode ? undefined : triggerSearch}
19627
20380
  // aria-label="検索"
19628
20381
  // >
19629
20382
  // <SearchNormal1 size={size === "sm" ? 14 : 16} />
19630
20383
  // </button>
20384
+ // </>
20385
+ // )
20386
+ //
20387
+ // if (isFormMode) {
20388
+ // return (
20389
+ // <form
20390
+ // data-slot="search-bar"
20391
+ // action={action}
20392
+ // method="get"
20393
+ // // 検索フォームであることを支援技術に伝える標準パターン
20394
+ // role="search"
20395
+ // onSubmit={handleSubmit}
20396
+ // className={rootClassName}
20397
+ // >
20398
+ // {content}
20399
+ // </form>
20400
+ // )
20401
+ // }
20402
+ //
20403
+ // return (
20404
+ // <div data-slot="search-bar" className={rootClassName}>
20405
+ // {content}
19631
20406
  // </div>
19632
20407
  // )
19633
20408
  // }
@@ -19832,7 +20607,8 @@ export {
19832
20607
  // * - セクション見出し(ランキング等): `size="xl"` or `size="lg"`(デフォルト)
19833
20608
  // * - 小見出し・グループラベル: `size="md"` or `size="sm"`
19834
20609
  // * - `as` で見出しレベルを上書き可能(同一ページに h1 が複数必要な場合など)
19835
- // * - `moreHref` 指定時はタイトル+サブタイトル全体がリンクになる(クリック領域拡大)
20610
+ // * - `moreHref` 指定時はタイトル行がリンクになる(クリック領域拡大)。`subtitle` は
20611
+ // * 右側アクションの下も含めた全幅で折り返すため、リンクの外に置く(issue #232)
19836
20612
  // * - `action` に任意の ReactNode(Button 等)を渡して右側にアクションを配置可能
19837
20613
  // * - `align="center"` でランディング/ガイド系の中央寄せ大見出しに切替(`eyebrow` に Badge 等を載せられる)
19838
20614
  // */
@@ -19914,29 +20690,33 @@ export {
19914
20690
  // </div>
19915
20691
  // )
19916
20692
  //
20693
+ // const headingNode = (
20694
+ // <HeadingTag
20695
+ // className={cn(
20696
+ // "text-[var(--Text-High-Emphasis)]",
20697
+ // titleSizeClasses[size],
20698
+ // desktopSize && desktopTitleSizeClasses[desktopSize]
20699
+ // )}
20700
+ // >
20701
+ // {title}
20702
+ // </HeadingTag>
20703
+ // )
20704
+ //
20705
+ // const subtitleNode = subtitle && (
20706
+ // <p
20707
+ // className={cn(
20708
+ // "text-[var(--Text-High-Emphasis)]",
20709
+ // isLargeCaption ? "typo-body-lg" : "typo-body-md"
20710
+ // )}
20711
+ // >
20712
+ // {subtitle}
20713
+ // </p>
20714
+ // )
20715
+ //
19917
20716
  // const titleContent = (
19918
20717
  // <>
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
- // )}
20718
+ // {headingNode}
20719
+ // {subtitleNode}
19940
20720
  // </>
19941
20721
  // )
19942
20722
  //
@@ -19967,17 +20747,23 @@ export {
19967
20747
  // {...props}
19968
20748
  // >
19969
20749
  // {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}
20750
+ // {/*
20751
+ // タイトル行(タイトル + もっと見る/action)と subtitle を別の行に分ける。
20752
+ // 同じ Flex 行に入れると subtitle まで action の幅ぶん狭まり、右側に空きが
20753
+ // あるのに早い位置で折り返していた(issue #232)。
20754
+ // */}
20755
+ // <div className="flex flex-col gap-1">
20756
+ // <div className="flex items-baseline justify-between gap-2 min-w-0">
20757
+ // {wrapTitleWithLink ? (
20758
+ // <a href={moreHref} className="min-w-0 flex-1">
20759
+ // {headingNode}
20760
+ // </a>
20761
+ // ) : (
20762
+ // <div className="min-w-0 flex-1">{headingNode}</div>
20763
+ // )}
20764
+ // {trailingControls}
20765
+ // </div>
20766
+ // {subtitleNode}
19981
20767
  // </div>
19982
20768
  // </div>
19983
20769
  // )
@@ -20318,6 +21104,8 @@ export {
20318
21104
  // export { Section, sectionVariants, sectionScrimVariants }
20319
21105
  //
20320
21106
  // src/components/primitives/share-buttons.tsx
21107
+ // "use client"
21108
+ //
20321
21109
  // import * as React from "react"
20322
21110
  // import Link2 from "iconsax-reactjs/dist/esm/Link2.js"
20323
21111
  //
@@ -20325,12 +21113,34 @@ export {
20325
21113
  // import { Button } from "@/components/foundations/button"
20326
21114
  // import { SocialIcon } from "@/components/foundations/social-icon"
20327
21115
  //
21116
+ // /** 組み込みの共有先 */
21117
+ // export type ShareService = "line" | "x" | "facebook" | "hatena" | "copy"
21118
+ //
21119
+ // /** 組み込みに無い共有先を足すための指定 */
21120
+ // export interface ShareCustomService {
21121
+ // /** 一意なキー(React の key に使う) */
21122
+ // key: string
21123
+ // /** ボタンの可視ラベル */
21124
+ // label: string
21125
+ // /** 共有先 URL。`{url}` / `{text}` は共有対象に置換される(どちらも URL エンコード済み) */
21126
+ // href: string
21127
+ // /** ラベル左のアイコン */
21128
+ // icon?: React.ReactNode
21129
+ // /** 読み上げ名(未指定ならラベルをそのまま使う) */
21130
+ // ariaLabel?: string
21131
+ // }
21132
+ //
20328
21133
  // export interface ShareButtonsProps
20329
21134
  // extends Omit<React.HTMLAttributes<HTMLDivElement>, "onCopy"> {
20330
21135
  // /** シェアURL */
20331
21136
  // url?: string
20332
21137
  // /** シェアテキスト */
20333
21138
  // text?: string
21139
+ // /**
21140
+ // * 表示する共有先と並び順(既定 `["line", "x", "copy"]`)。
21141
+ // * 組み込みに無い共有先は `ShareCustomService` を混ぜて足す。
21142
+ // */
21143
+ // services?: Array<ShareService | ShareCustomService>
20334
21144
  // /** コピーボタンのラベル */
20335
21145
  // copyLabel?: string
20336
21146
  // /** コピー成功時に一時表示するラベル(約2秒) */
@@ -20341,22 +21151,68 @@ export {
20341
21151
  // onCopy?: (result: "success" | "error") => void
20342
21152
  // }
20343
21153
  //
21154
+ // const DEFAULT_SERVICES: ShareService[] = ["line", "x", "copy"]
21155
+ //
21156
+ // /** 組み込み共有先の共有 URL・ラベル・アイコン */
21157
+ // const SHARE_TARGETS: Record<
21158
+ // Exclude<ShareService, "copy">,
21159
+ // {
21160
+ // label: string
21161
+ // ariaLabel: string
21162
+ // href: (url: string, text: string) => string
21163
+ // icon: React.ReactNode
21164
+ // }
21165
+ // > = {
21166
+ // line: {
21167
+ // label: "LINE",
21168
+ // ariaLabel: "LINEでシェア",
21169
+ // href: (url) =>
21170
+ // `https://social-plugins.line.me/lineit/share?url=${encodeURIComponent(url)}`,
21171
+ // icon: <SocialIcon platform="line" size={16} />,
21172
+ // },
21173
+ // x: {
21174
+ // label: "X",
21175
+ // ariaLabel: "Xでシェア",
21176
+ // href: (url, text) =>
21177
+ // `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`,
21178
+ // // X のブランド色は黒固定でダーク地に溶けるため、地の文字色に追従させる
21179
+ // icon: <SocialIcon platform="x" size={14} tone="mono" />,
21180
+ // },
21181
+ // facebook: {
21182
+ // label: "Facebook",
21183
+ // ariaLabel: "Facebookでシェア",
21184
+ // href: (url) =>
21185
+ // `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`,
21186
+ // icon: <SocialIcon platform="facebook" size={16} />,
21187
+ // },
21188
+ // hatena: {
21189
+ // label: "はてブ",
21190
+ // ariaLabel: "はてなブックマークに追加",
21191
+ // href: (url, text) =>
21192
+ // `https://b.hatena.ne.jp/entry/panel/?url=${encodeURIComponent(url)}&title=${encodeURIComponent(text)}`,
21193
+ // icon: <SocialIcon platform="hatena" size={16} />,
21194
+ // },
21195
+ // }
21196
+ //
20344
21197
  // /**
20345
21198
  // * シェアボタンコンポーネント
20346
21199
  // *
20347
- // * 商品をSNSやURLでシェアするためのボタン群。
20348
- // * LINE、X(Twitter)、URLコピーに対応。
21200
+ // * 記事や商品を SNS・URL コピーで共有するためのボタン群。
20349
21201
  // *
20350
21202
  // * ### AI 向け使用ルール
20351
21203
  // *
20352
- // * - 商品詳細ページの共有セクションに使用
21204
+ // * - 商品詳細ページ・記事ページの共有セクションに使用
20353
21205
  // * - `url` と `text` でシェア内容を指定
21206
+ // * - 共有先は `services` で選ぶ(既定は LINE / X / コピー)。
21207
+ // * **同じ意匠を `Button asChild` で組み直さない**
21208
+ // * - 組み込みに無い共有先は `services` に `{ key, label, href, icon }` を混ぜて足す
20354
21209
  // * - ボタンは横並び、等幅表示
20355
21210
  // */
20356
21211
  // function ShareButtons({
20357
21212
  // className,
20358
21213
  // url = "",
20359
21214
  // text = "",
21215
+ // services = DEFAULT_SERVICES,
20360
21216
  // copyLabel = "URLをコピー",
20361
21217
  // copiedLabel = "コピーしました",
20362
21218
  // copyErrorLabel = "コピーできませんでした",
@@ -20398,59 +21254,70 @@ export {
20398
21254
  // ? copyErrorLabel
20399
21255
  // : copyLabel
20400
21256
  //
21257
+ // const renderLink = (
21258
+ // key: string,
21259
+ // href: string,
21260
+ // ariaLabel: string,
21261
+ // icon: React.ReactNode,
21262
+ // label: string
21263
+ // ) => (
21264
+ // <Button key={key} variant="tertiary" size="sm" className="flex-1 gap-1.5" asChild>
21265
+ // <a href={href} target="_blank" rel="noopener noreferrer" aria-label={ariaLabel}>
21266
+ // {icon}
21267
+ // <span className="typo-body-sm">{label}</span>
21268
+ // </a>
21269
+ // </Button>
21270
+ // )
21271
+ //
20401
21272
  // return (
20402
21273
  // <div
20403
21274
  // data-slot="share-buttons"
20404
21275
  // className={cn("flex items-center gap-2", className)}
20405
21276
  // {...props}
20406
21277
  // >
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>
21278
+ // {services.map((service) => {
21279
+ // if (typeof service !== "string") {
21280
+ // const href = service.href
21281
+ // .replace("{url}", encodeURIComponent(url))
21282
+ // .replace("{text}", encodeURIComponent(text))
21283
+ // return renderLink(
21284
+ // service.key,
21285
+ // href,
21286
+ // service.ariaLabel ?? service.label,
21287
+ // service.icon,
21288
+ // service.label
21289
+ // )
21290
+ // }
21291
+ //
21292
+ // if (service === "copy") {
21293
+ // // aria-label は付けない: 可視ラベルが「コピーしました/できませんでした」に変わるため、
21294
+ // // 固定 aria-label だとアクセシブル名と可視名が食い違う(WCAG 2.5.3 Label in Name)。
21295
+ // // アクセシブル名は可視テキスト(aria-live で読み上げ更新)に委ねる。
21296
+ // return (
21297
+ // <Button
21298
+ // key="copy"
21299
+ // variant="tertiary"
21300
+ // size="sm"
21301
+ // className="flex-1 gap-1.5"
21302
+ // onClick={handleCopy}
21303
+ // >
21304
+ // <Link2 size={14} aria-hidden="true" />
21305
+ // <span className="typo-body-sm" aria-live="polite">
21306
+ // {copyButtonLabel}
21307
+ // </span>
21308
+ // </Button>
21309
+ // )
21310
+ // }
21311
+ //
21312
+ // const target = SHARE_TARGETS[service]
21313
+ // return renderLink(
21314
+ // service,
21315
+ // target.href(url, text),
21316
+ // target.ariaLabel,
21317
+ // target.icon,
21318
+ // target.label
21319
+ // )
21320
+ // })}
20454
21321
  // </div>
20455
21322
  // )
20456
21323
  // }
@@ -20895,6 +21762,8 @@ export {
20895
21762
  // export { StandardPageShell }
20896
21763
  //
20897
21764
  // src/components/primitives/status-count-tabs.tsx
21765
+ // "use client"
21766
+ //
20898
21767
  // /**
20899
21768
  // * ## StatusCountTabs / ステータスカウントタブ
20900
21769
  // *
@@ -21010,6 +21879,11 @@ export {
21010
21879
  // import * as React from "react"
21011
21880
  //
21012
21881
  // import { cn } from "@/lib/utils"
21882
+ // import { resolveLinkComponent, type LinkComponent } from "@/lib/link-component"
21883
+ // import { containerVariants } from "@/components/primitives/container"
21884
+ //
21885
+ // /** `Container` の gutter(SP 16 / PC 24)。本文の左端と揃えるための正本 */
21886
+ // const GUTTER_CLASS = "px-4 md:px-6"
21013
21887
  //
21014
21888
  // export interface SubNavItem {
21015
21889
  // /** 表示ラベル */
@@ -21024,10 +21898,23 @@ export {
21024
21898
  //
21025
21899
  // export interface SubNavProps
21026
21900
  // extends React.HTMLAttributes<HTMLDivElement> {
21901
+ // /**
21902
+ // * リンクの描画に使うコンポーネント(既定 `a`)。
21903
+ // * `next/link` 等を渡すとクライアント遷移になる(#236)。
21904
+ // */
21905
+ // linkComponent?: LinkComponent
21906
+ //
21027
21907
  // /** ナビゲーション項目 */
21028
21908
  // items: SubNavItem[]
21029
21909
  // /** スタイルバリアント */
21030
21910
  // variant?: "text" | "chip"
21911
+ // /**
21912
+ // * ナビ内側の最大幅(`Container` と同じ段)。
21913
+ // * 指定すると下線(border)は全幅のまま、**中身だけ**を中央寄せする。
21914
+ // * 本文を `Container size="page"` で組んでいるサイトで、項目の左端が本文と揃う。
21915
+ // * 未指定なら従来どおり全幅(DOM も従来どおりで内側ラッパーを足さない)。
21916
+ // */
21917
+ // containerSize?: "page" | "wide" | "fluid"
21031
21918
  // }
21032
21919
  //
21033
21920
  // /**
@@ -21044,81 +21931,100 @@ export {
21044
21931
  // * - アクティブ項目は `isActive: true` で下線を強調
21045
21932
  // * - テキスト色: アクティブ = 黒(High-Emphasis)、非アクティブ = グレー(Medium-Emphasis)
21046
21933
  // * - 必ず `overflow-x-auto` + `scrollbar-hide` で横スクロール対応
21934
+ // * - 左右の余白は `Container` と同じ(SP 16 / PC 24)。本文を `Container` で中央寄せしている
21935
+ // * サイトでは `containerSize="page"` を指定すると項目の左端が本文と揃う
21047
21936
  // */
21048
21937
  // function SubNav({
21049
21938
  // className,
21050
21939
  // items,
21051
21940
  // variant = "text",
21941
+ // linkComponent,
21942
+ // containerSize,
21052
21943
  // ...props
21053
21944
  // }: 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 }
21945
+ // const renderItems = () =>
21946
+ // items.map((item) => {
21947
+ // const Comp = item.href ? resolveLinkComponent(linkComponent) : "button"
21948
+ // const compProps = item.href
21949
+ // ? { href: item.href }
21950
+ // : { type: "button" as const, onClick: item.onClick }
21951
+ //
21952
+ // if (variant === "chip") {
21103
21953
  // return (
21104
21954
  // <Comp
21105
21955
  // key={item.label}
21106
21956
  // className={cn(
21107
- // "relative shrink-0 py-2.5 typo-label-md transition-colors",
21957
+ // "shrink-0 rounded-full px-3 typo-label-sm transition-colors h-8 inline-flex items-center justify-center",
21108
21958
  // item.isActive
21109
- // ? "text-[var(--Text-High-Emphasis)]"
21110
- // : "text-[var(--Text-Medium-Emphasis)] hover:text-[var(--Text-High-Emphasis)]"
21959
+ // ? "bg-[var(--Brand-Cake-Orange)] text-[var(--Text-on-Inverse)]"
21960
+ // : "bg-[var(--Surface-Secondary)] text-[var(--Text-Medium-Emphasis)] hover:bg-[var(--Surface-Tertiary)]"
21111
21961
  // )}
21112
21962
  // {...compProps}
21113
21963
  // >
21114
21964
  // {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
21965
  // </Comp>
21119
21966
  // )
21120
- // })}
21121
- // </nav>
21967
+ // }
21968
+ //
21969
+ // return (
21970
+ // <Comp
21971
+ // key={item.label}
21972
+ // className={cn(
21973
+ // "relative shrink-0 py-2.5 typo-label-md transition-colors",
21974
+ // item.isActive
21975
+ // ? "text-[var(--Text-High-Emphasis)]"
21976
+ // : "text-[var(--Text-Medium-Emphasis)] hover:text-[var(--Text-High-Emphasis)]"
21977
+ // )}
21978
+ // {...compProps}
21979
+ // >
21980
+ // {item.label}
21981
+ // {item.isActive && (
21982
+ // <span className="absolute inset-x-0 bottom-0 h-0.5 rounded-full bg-[var(--Text-High-Emphasis)]" />
21983
+ // )}
21984
+ // </Comp>
21985
+ // )
21986
+ // })
21987
+ //
21988
+ // const isChip = variant === "chip"
21989
+ // const Root = isChip ? "div" : "nav"
21990
+ //
21991
+ // /** 項目を並べる行(横スクロール・左右 gutter を持つ) */
21992
+ // const rowClass = isChip
21993
+ // ? cn("flex gap-2 overflow-x-auto py-2 scrollbar-hide", GUTTER_CLASS)
21994
+ // : cn("flex gap-4 overflow-x-auto scrollbar-hide", GUTTER_CLASS)
21995
+ //
21996
+ // /** 外枠が常に持つ装飾(全幅で描く) */
21997
+ // const decorationClass = isChip
21998
+ // ? undefined
21999
+ // : "border-b border-[var(--Border-Low-Emphasis)]"
22000
+ //
22001
+ // // containerSize 指定時は、下線を外枠に残したまま内側だけ Container 相当で中央寄せする。
22002
+ // // 未指定時はラッパーを足さず従来の DOM 構造をそのまま保つ(#234)。
22003
+ // if (containerSize) {
22004
+ // return (
22005
+ // <Root data-slot="sub-nav" className={cn(decorationClass, className)} {...props}>
22006
+ // <div
22007
+ // data-slot="sub-nav-container"
22008
+ // data-container-size={containerSize}
22009
+ // className={cn(
22010
+ // containerVariants({ size: containerSize, gutter: "none" }),
22011
+ // rowClass
22012
+ // )}
22013
+ // >
22014
+ // {renderItems()}
22015
+ // </div>
22016
+ // </Root>
22017
+ // )
22018
+ // }
22019
+ //
22020
+ // return (
22021
+ // <Root
22022
+ // data-slot="sub-nav"
22023
+ // className={cn(decorationClass, rowClass, className)}
22024
+ // {...props}
22025
+ // >
22026
+ // {renderItems()}
22027
+ // </Root>
21122
22028
  // )
21123
22029
  // }
21124
22030
  //
@@ -22322,6 +23228,14 @@ export {
22322
23228
  // export type { ChatComposerProps, ChatComposerAttachmentError } from "./components/primitives/chat-composer"
22323
23229
  // export { Chip, chipVariants } from "./components/primitives/chip"
22324
23230
  // export type { ChipProps } from "./components/primitives/chip"
23231
+ // export { Prose } from "./components/primitives/prose"
23232
+ // export type { ProseProps } from "./components/primitives/prose"
23233
+ // export { ContentCard, ContentList } from "./components/primitives/content-card"
23234
+ // export type {
23235
+ // ContentCardProps,
23236
+ // ContentCardOrientation,
23237
+ // ContentCardAspect,
23238
+ // } from "./components/primitives/content-card"
22325
23239
  // export { StandardPageShell } from "./components/primitives/standard-page-shell"
22326
23240
  // export type { StandardPageShellProps } from "./components/primitives/standard-page-shell"
22327
23241
  // /**
@@ -22475,6 +23389,8 @@ export {
22475
23389
  // export type { StatCardProps } from "./components/ec/stat-card"
22476
23390
  //
22477
23391
  // src/lib/field-labelling.ts
23392
+ // "use client"
23393
+ //
22478
23394
  // /**
22479
23395
  // * ## フィールドのラベル関連付け(DS 全体の方針 / issue #202)
22480
23396
  // *
@@ -22624,6 +23540,42 @@ export {
22624
23540
  // export const FOCUS_RING_INSET =
22625
23541
  // "focus-visible:ring-[3px] focus-visible:ring-inset focus-visible:ring-[var(--Focus-High-Emphasis)]/50"
22626
23542
  //
23543
+ // src/lib/link-component.ts
23544
+ // import type * as React from "react"
23545
+ //
23546
+ // /**
23547
+ // * リンクの描画に使うコンポーネント(#236)
23548
+ // *
23549
+ // * DS 内でリンクを複数描く部品(Footer / MenuDrawer / SubNav / Pagination)は
23550
+ // * 素の `<a>` を描くため、Next.js の `next/link` 等を差し込めずクライアント遷移に
23551
+ // * ならない。`asChild` は複数リンクを内部で描く部品には向かないため、
23552
+ // * 「リンク実装そのもの」を差し替える prop を共通の型で用意する。
23553
+ // *
23554
+ // * 例: `<Footer linkComponent={Link} … />`(next/link をそのまま渡せる)
23555
+ // */
23556
+ // export type LinkComponent = React.ComponentType<
23557
+ // React.AnchorHTMLAttributes<HTMLAnchorElement> & { href: string }
23558
+ // >
23559
+ //
23560
+ // /**
23561
+ // * 実際に使うリンク実装を決める。
23562
+ // *
23563
+ // * 外部リンク(`target="_blank"` を付けるもの)は framework のリンク部品に通す
23564
+ // * 意味が無いため、常に素の `<a>` にフォールバックする。
23565
+ // *
23566
+ // * `isExternal` を渡せるのは、項目に `external` フラグを持つ `Footer` だけ。
23567
+ // * MenuDrawer / SubNav / Pagination の項目に `external` は無く、渡した href は
23568
+ // * すべて `linkComponent` で描かれる(外部 URL を出し分けたい場合は consumer 側で
23569
+ // * ラップする)。
23570
+ // */
23571
+ // export function resolveLinkComponent(
23572
+ // linkComponent: LinkComponent | undefined,
23573
+ // isExternal?: boolean
23574
+ // ): React.ElementType {
23575
+ // if (isExternal || !linkComponent) return "a"
23576
+ // return linkComponent
23577
+ // }
23578
+ //
22627
23579
  // src/lib/pagination-range.ts
22628
23580
  // export type PaginationRangeItem = number | "ellipsis"
22629
23581
  //
@@ -22755,6 +23707,8 @@ export {
22755
23707
  // } as const
22756
23708
  //
22757
23709
  // src/lib/use-value-length.ts
23710
+ // "use client"
23711
+ //
22758
23712
  // import * as React from "react"
22759
23713
  //
22760
23714
  // type CountableElement = HTMLInputElement | HTMLTextAreaElement