@cloudflare/kumo 2.0.1 → 2.0.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @cloudflare/kumo
2
2
 
3
+ ## 2.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - fbf3eef: Forward all Base UI Panel props (including `keepMounted` and `hiddenUntilFound`) through `Collapsible.DefaultPanel`. Previously these were silently dropped because `DefaultPanel` used a standalone props interface instead of extending `BasePanelProps`.
8
+ - 40491c2: Fix registry codegen to match demo examples when component export name differs from directory name (e.g. DropdownMenu vs dropdown). This restores missing examples for DropdownMenu and other affected components.
9
+ - 3427221: TooltipProvider props (`delay`, `closeDelay`, `timeout`) are now shown in the Tooltip component's API Reference on the docs site.
10
+
3
11
  ## 2.0.1
4
12
 
5
13
  ### Patch Changes
@@ -2123,7 +2123,7 @@
2123
2123
  "<div className=\"flex flex-wrap items-center gap-8\">\n <CloudflareLogo className=\"w-28\" color=\"color\" />\n <div className=\"rounded-lg bg-white p-4\">\n <CloudflareLogo className=\"w-28\" color=\"black\" />\n </div>\n <div className=\"rounded-lg bg-black p-4\">\n <CloudflareLogo className=\"w-28\" color=\"white\" />\n </div>\n </div>",
2124
2124
  "<div className=\"flex flex-wrap items-center gap-8\">\n <CloudflareLogo variant=\"glyph\" className=\"w-12\" color=\"color\" />\n <div className=\"rounded-lg bg-white p-4\">\n <CloudflareLogo variant=\"glyph\" className=\"w-12\" color=\"black\" />\n </div>\n <div className=\"rounded-lg bg-black p-4\">\n <CloudflareLogo variant=\"glyph\" className=\"w-12\" color=\"white\" />\n </div>\n </div>",
2125
2125
  "<div className=\"flex flex-wrap items-end gap-6\">\n <CloudflareLogo className=\"w-20\" />\n <CloudflareLogo className=\"w-28\" />\n <CloudflareLogo className=\"w-44\" />\n </div>",
2126
- "<div className=\"flex items-center gap-4\">\n <DropdownMenu>\n <DropdownMenu.Trigger>\n <button\n type=\"button\"\n className=\"flex items-center gap-2 rounded-lg bg-black px-4 py-3 text-white transition-opacity hover:opacity-80\"\n >\n <CloudflareLogo variant=\"glyph\" color=\"white\" className=\"w-8\" />\n <span className=\"font-medium\">Logo</span>\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Item\n icon={CloudIcon}\n onSelect={() =>\n copyToClipboard(\n generateCloudflareLogoSvg({ variant: \"glyph\" }),\n \"glyph\",\n )\n }\n >\n {copied === \"glyph\" ? \"Copied!\" : \"Copy logo as SVG\"}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n icon={CodeIcon}\n onSelect={() =>\n copyToClipboard(\n generateCloudflareLogoSvg({ variant: \"full\" }),\n \"full\",\n )\n }\n >\n {copied === \"full\" ? \"Copied!\" : \"Copy full logo as SVG\"}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n icon={DownloadSimpleIcon}\n onSelect={() =>\n window.open(\n \"https://www.cloudflare.com/press-kit/\",\n \"_blank\",\n \"noopener\",\n )\n }\n >\n Download brand assets\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n icon={ArrowSquareOutIcon}\n onSelect={() =>\n window.open(\n \"https://www.cloudflare.com/brand-assets/\",\n \"_blank\",\n \"noopener\",\n )\n }\n >\n Visit brand guidelines\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n\n <span className=\"text-sm text-kumo-subtle\">\n Click to open the brand assets menu\n </span>\n </div>",
2126
+ "<div className=\"flex items-center gap-4\">\n <DropdownMenu>\n <DropdownMenu.Trigger>\n <button\n type=\"button\"\n className=\"flex items-center gap-2 rounded-lg bg-black px-4 py-3 text-white transition-opacity hover:opacity-80\"\n >\n <CloudflareLogo variant=\"glyph\" color=\"white\" className=\"w-8\" />\n <span className=\"font-medium\">Logo</span>\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Item\n icon={CloudIcon}\n onClick={() =>\n copyToClipboard(\n generateCloudflareLogoSvg({ variant: \"glyph\" }),\n \"glyph\",\n )\n }\n >\n {copied === \"glyph\" ? \"Copied!\" : \"Copy logo as SVG\"}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n icon={CodeIcon}\n onClick={() =>\n copyToClipboard(\n generateCloudflareLogoSvg({ variant: \"full\" }),\n \"full\",\n )\n }\n >\n {copied === \"full\" ? \"Copied!\" : \"Copy full logo as SVG\"}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n icon={DownloadSimpleIcon}\n onClick={() =>\n window.open(\n \"https://www.cloudflare.com/press-kit/\",\n \"_blank\",\n \"noopener\",\n )\n }\n >\n Download brand assets\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n icon={ArrowSquareOutIcon}\n onClick={() =>\n window.open(\n \"https://www.cloudflare.com/brand-assets/\",\n \"_blank\",\n \"noopener\",\n )\n }\n >\n Visit brand guidelines\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n\n <span className=\"text-sm text-kumo-subtle\">\n Click to open the brand assets menu\n </span>\n </div>",
2127
2127
  "<PoweredByCloudflare />",
2128
2128
  "<div className=\"flex flex-wrap items-center gap-4\">\n <PoweredByCloudflare />\n <PoweredByCloudflare color=\"black\" />\n <div className=\"rounded-lg bg-black p-3\">\n <PoweredByCloudflare color=\"white\" />\n </div>\n </div>",
2129
2129
  "<footer className=\"flex w-full items-center justify-between rounded-lg border border-kumo-hairline bg-kumo-elevated px-6 py-4\">\n <span className=\"text-sm text-kumo-subtle\">\n &copy; 2026 Your Company. All rights reserved.\n </span>\n <PoweredByCloudflare />\n </footer>"
@@ -2242,6 +2242,7 @@
2242
2242
  "<div className=\"w-full\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Kumo is Cloudflare's new design system.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2243
2243
  "<div className=\"w-full space-y-2\">\n <Collapsible.Root open={open1} onOpenChange={setOpen1}>\n <Collapsible.DefaultTrigger>What is Kumo?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Kumo is Cloudflare's new design system.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n <Collapsible.Root open={open2} onOpenChange={setOpen2}>\n <Collapsible.DefaultTrigger>How do I use it?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Install the components and import them into your project.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n <Collapsible.Root open={open3} onOpenChange={setOpen3}>\n <Collapsible.DefaultTrigger>Is it open source?</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>Check the repository for license information.</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2244
2244
  "<div className=\"w-full\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.Trigger\n render={<Button variant=\"secondary\" size=\"sm\" />}\n >\n {isOpen ? \"Hide details\" : \"Show details\"}\n </Collapsible.Trigger>\n <Collapsible.Panel className=\"mt-3 rounded-lg bg-kumo-tint p-4\">\n <Text>\n This panel uses custom styling instead of the default border-left accent.\n </Text>\n </Collapsible.Panel>\n </Collapsible.Root>\n </div>",
2245
+ "<div className=\"w-full space-y-4\">\n <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>\n <Collapsible.DefaultTrigger>Edit details</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel keepMounted>\n <Text>\n Type something below, then collapse and re-open — your input is\n preserved because the panel stays mounted.\n </Text>\n <Input label=\"Name\" placeholder=\"Type here…\" />\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n </div>",
2245
2246
  "<div className=\"w-full space-y-2\">\n {items.map((item, i) => (\n <Collapsible.Root\n key={i}\n open={activeIndex === i}\n onOpenChange={(open) => setActiveIndex(open ? i : null)}\n >\n <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger>\n <Collapsible.DefaultPanel>\n <Text>{item.content}</Text>\n </Collapsible.DefaultPanel>\n </Collapsible.Root>\n ))}\n </div>"
2246
2247
  ],
2247
2248
  "colors": [
@@ -2900,7 +2901,15 @@
2900
2901
  "default": "default"
2901
2902
  }
2902
2903
  },
2903
- "examples": [],
2904
+ "examples": [
2905
+ "<DropdownMenu>\n <DropdownMenu.Trigger render={<Button icon={PlusIcon}>Add</Button>} />\n <DropdownMenu.Content>\n <DropdownMenu.Item>Worker</DropdownMenu.Item>\n <DropdownMenu.Item>Pages</DropdownMenu.Item>\n <DropdownMenu.Item>KV Namespace</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>",
2906
+ "<DropdownMenu>\n <DropdownMenu.Trigger render={<Button>View Options</Button>} />\n <DropdownMenu.Content>\n <DropdownMenu.Group>\n <DropdownMenu.Label>Display</DropdownMenu.Label>\n <DropdownMenu.CheckboxItem\n checked={showSidebar}\n onCheckedChange={setShowSidebar}\n >\n Show sidebar\n </DropdownMenu.CheckboxItem>\n <DropdownMenu.CheckboxItem\n checked={showLineNumbers}\n onCheckedChange={setShowLineNumbers}\n >\n Show line numbers\n </DropdownMenu.CheckboxItem>\n <DropdownMenu.CheckboxItem\n checked={wordWrap}\n onCheckedChange={setWordWrap}\n >\n Word wrap\n </DropdownMenu.CheckboxItem>\n </DropdownMenu.Group>\n </DropdownMenu.Content>\n </DropdownMenu>",
2907
+ "<DropdownMenu>\n <DropdownMenu.Trigger render={<Button icon={UserIcon}>Account</Button>} />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={UserIcon}>Profile</DropdownMenu.Item>\n <DropdownMenu.Item icon={CreditCardIcon}>Billing</DropdownMenu.Item>\n <DropdownMenu.Item icon={MoonIcon}>Dark mode</DropdownMenu.Item>\n\n {/* Language submenu with RadioGroup */}\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>Language</DropdownMenu.SubTrigger>\n <DropdownMenu.SubContent>\n <DropdownMenu.Group>\n <DropdownMenu.RadioGroup\n value={language}\n onValueChange={setLanguage}\n >\n {languages.map((lang) => (\n <DropdownMenu.RadioItem key={lang.code} value={lang.code}>\n {lang.label}\n <DropdownMenu.RadioItemIndicator />\n </DropdownMenu.RadioItem>\n ))}\n </DropdownMenu.RadioGroup>\n </DropdownMenu.Group>\n </DropdownMenu.SubContent>\n </DropdownMenu.Sub>\n\n {/* Timezone submenu with RadioGroup */}\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger>Set Timezone</DropdownMenu.SubTrigger>\n <DropdownMenu.SubContent>\n <DropdownMenu.Group>\n <DropdownMenu.RadioGroup\n value={timezone}\n onValueChange={setTimezone}\n >\n {timezones.map((tz) => (\n <DropdownMenu.RadioItem key={tz.value} value={tz.value}>\n {tz.label}\n <DropdownMenu.RadioItemIndicator />\n </DropdownMenu.RadioItem>\n ))}\n </DropdownMenu.RadioGroup>\n </DropdownMenu.Group>\n </DropdownMenu.SubContent>\n </DropdownMenu.Sub>\n\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={SignOutIcon} variant=\"danger\">\n Log out\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>",
2908
+ "<DropdownMenu>\n <DropdownMenu.Trigger render={<Button>Edit</Button>} />\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={PencilSimpleIcon}>Rename</DropdownMenu.Item>\n <DropdownMenu.Item icon={CopyIcon}>Duplicate</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item inset>Move to folder</DropdownMenu.Item>\n <DropdownMenu.Item inset>Add to favorites</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={TrashIcon} variant=\"danger\">\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>",
2909
+ "<div className=\"flex flex-col items-start gap-2\">\n <DropdownMenu>\n <DropdownMenu.Trigger render={<Button>Actions</Button>} />\n <DropdownMenu.Content>\n <DropdownMenu.Item\n icon={CopyIcon}\n onClick={() => setLastAction(\"Duplicated\")}\n >\n Duplicate\n </DropdownMenu.Item>\n <DropdownMenu.Item\n icon={PencilSimpleIcon}\n onClick={() => setLastAction(\"Renamed\")}\n >\n Rename\n </DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n icon={TrashIcon}\n variant=\"danger\"\n onClick={() => setLastAction(\"Deleted\")}\n >\n Delete\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n {lastAction && (\n <p className=\"text-sm text-kumo-subtle\">\n Last action: <span className=\"text-kumo-default\">{lastAction}</span>\n </p>\n )}\n </div>",
2910
+ "<DropdownMenu>\n <DropdownMenu.Trigger\n render={<button type=\"button\" className=\"rounded-full\" />}\n >\n <span className=\"flex h-8 w-8 items-center justify-center rounded-full bg-kumo-brand text-sm font-medium text-white\">\n MR\n </span>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content>\n <DropdownMenu.Item icon={UserIcon}>Profile</DropdownMenu.Item>\n <DropdownMenu.Item icon={GearIcon}>Settings</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item icon={SignOutIcon} variant=\"danger\">\n Log out\n </DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>",
2911
+ "<DropdownMenu>\n <DropdownMenu.Trigger render={<Button>Resources</Button>} />\n <DropdownMenu.Content>\n <DropdownMenu.LinkItem href=\"/settings\" icon={GearIcon}>\n Settings\n </DropdownMenu.LinkItem>\n <DropdownMenu.LinkItem href=\"/docs\" icon={BookOpenIcon}>\n Documentation\n </DropdownMenu.LinkItem>\n <DropdownMenu.Separator />\n <DropdownMenu.LinkItem\n href=\"https://developers.cloudflare.com\"\n target=\"_blank\"\n icon={ArrowSquareOutIcon}\n >\n Developer Docs\n </DropdownMenu.LinkItem>\n </DropdownMenu.Content>\n </DropdownMenu>"
2912
+ ],
2904
2913
  "colors": [
2905
2914
  "bg-kumo-control",
2906
2915
  "bg-kumo-danger",
@@ -2936,7 +2945,16 @@
2936
2945
  "SubTrigger": {
2937
2946
  "name": "SubTrigger",
2938
2947
  "description": "SubTrigger sub-component",
2939
- "props": {}
2948
+ "props": {
2949
+ "icon": {
2950
+ "type": "Icon",
2951
+ "description": "Icon displayed before the label."
2952
+ },
2953
+ "inset": {
2954
+ "type": "boolean",
2955
+ "description": "Adds left padding to align with items that have icons."
2956
+ }
2957
+ }
2940
2958
  },
2941
2959
  "SubContent": {
2942
2960
  "name": "SubContent",
@@ -2946,34 +2964,164 @@
2946
2964
  "Content": {
2947
2965
  "name": "Content",
2948
2966
  "description": "Content sub-component",
2949
- "props": {}
2967
+ "props": {
2968
+ "sideOffset": {
2969
+ "type": "number",
2970
+ "description": "Distance in pixels from the trigger.",
2971
+ "default": "8"
2972
+ },
2973
+ "container": {
2974
+ "type": "PortalContainer",
2975
+ "description": "Container element for the portal. Use this to render inside a Shadow DOM or custom container."
2976
+ }
2977
+ }
2950
2978
  },
2951
2979
  "Item": {
2952
2980
  "name": "Item",
2953
2981
  "description": "Item sub-component",
2954
- "props": {}
2982
+ "props": {
2983
+ "icon": {
2984
+ "type": "Icon | ReactNode",
2985
+ "description": "Icon displayed before the label."
2986
+ },
2987
+ "variant": {
2988
+ "type": "\"default\" | \"danger\"",
2989
+ "description": "Visual style of the item.",
2990
+ "default": "\"default\""
2991
+ },
2992
+ "selected": {
2993
+ "type": "boolean",
2994
+ "description": "Shows a check mark indicator when true."
2995
+ },
2996
+ "inset": {
2997
+ "type": "boolean",
2998
+ "description": "Adds left padding to align with items that have icons."
2999
+ },
3000
+ "onClick": {
3001
+ "type": "(event: React.MouseEvent) => void",
3002
+ "description": "Callback when the item is clicked."
3003
+ },
3004
+ "closeOnClick": {
3005
+ "type": "boolean",
3006
+ "description": "Whether the menu closes after clicking this item.",
3007
+ "default": "true"
3008
+ },
3009
+ "disabled": {
3010
+ "type": "boolean",
3011
+ "description": "When true, the item cannot be interacted with."
3012
+ }
3013
+ }
2955
3014
  },
2956
3015
  "LinkItem": {
2957
3016
  "name": "LinkItem",
2958
3017
  "description": "LinkItem sub-component",
2959
- "props": {}
3018
+ "props": {
3019
+ "href": {
3020
+ "type": "string",
3021
+ "description": "URL to navigate to when clicked."
3022
+ },
3023
+ "icon": {
3024
+ "type": "Icon | ReactNode",
3025
+ "description": "Icon displayed before the label."
3026
+ },
3027
+ "variant": {
3028
+ "type": "\"default\" | \"danger\"",
3029
+ "description": "Visual style of the item.",
3030
+ "default": "\"default\""
3031
+ },
3032
+ "inset": {
3033
+ "type": "boolean",
3034
+ "description": "Adds left padding to align with items that have icons."
3035
+ },
3036
+ "target": {
3037
+ "type": "string",
3038
+ "description": "Link target attribute (e.g. \"_blank\" for new tab)."
3039
+ },
3040
+ "render": {
3041
+ "type": "ReactElement | ((props, state) => ReactElement)",
3042
+ "description": "Custom element to render as the link. Use to integrate with framework routers (e.g. Next.js Link)."
3043
+ }
3044
+ }
2960
3045
  },
2961
3046
  "CheckboxItem": {
2962
3047
  "name": "CheckboxItem",
2963
3048
  "description": "CheckboxItem sub-component",
2964
- "props": {}
3049
+ "props": {
3050
+ "checked": {
3051
+ "type": "boolean",
3052
+ "description": "Whether the item is checked."
3053
+ },
3054
+ "defaultChecked": {
3055
+ "type": "boolean",
3056
+ "description": "Whether the item is initially checked (uncontrolled).",
3057
+ "default": "false"
3058
+ },
3059
+ "onCheckedChange": {
3060
+ "type": "(checked: boolean, event: ChangeEventDetails) => void",
3061
+ "description": "Callback when the checked state changes."
3062
+ },
3063
+ "closeOnClick": {
3064
+ "type": "boolean",
3065
+ "description": "Whether the menu closes after clicking this item.",
3066
+ "default": "false"
3067
+ },
3068
+ "disabled": {
3069
+ "type": "boolean",
3070
+ "description": "When true, the item cannot be interacted with."
3071
+ }
3072
+ }
2965
3073
  },
2966
3074
  "RadioGroup": {
2967
3075
  "name": "RadioGroup",
2968
3076
  "description": "RadioGroup sub-component (wraps DropdownMenuPrimitive)",
2969
- "props": {},
3077
+ "props": {
3078
+ "value": {
3079
+ "type": "any",
3080
+ "description": "The controlled value of the currently selected radio item."
3081
+ },
3082
+ "defaultValue": {
3083
+ "type": "any",
3084
+ "description": "The initially selected value (uncontrolled)."
3085
+ },
3086
+ "onValueChange": {
3087
+ "type": "(value: any, event: ChangeEventDetails) => void",
3088
+ "description": "Callback when the selected value changes."
3089
+ },
3090
+ "disabled": {
3091
+ "type": "boolean",
3092
+ "description": "When true, all radio items in the group are disabled."
3093
+ }
3094
+ },
2970
3095
  "isPassThrough": true,
2971
3096
  "baseComponent": "DropdownMenuPrimitive.RadioGroup"
2972
3097
  },
2973
3098
  "RadioItem": {
2974
3099
  "name": "RadioItem",
2975
3100
  "description": "RadioItem sub-component",
2976
- "props": {}
3101
+ "props": {
3102
+ "value": {
3103
+ "type": "any",
3104
+ "required": true,
3105
+ "description": "The value of this radio item."
3106
+ },
3107
+ "icon": {
3108
+ "type": "Icon | ReactNode",
3109
+ "description": "Icon displayed before the label."
3110
+ },
3111
+ "inset": {
3112
+ "type": "boolean",
3113
+ "description": "Adds left padding to align with items that have icons."
3114
+ },
3115
+ "closeOnClick": {
3116
+ "type": "boolean",
3117
+ "description": "Whether the menu closes after clicking this item.",
3118
+ "default": "false"
3119
+ },
3120
+ "disabled": {
3121
+ "type": "boolean",
3122
+ "description": "When true, the item cannot be interacted with."
3123
+ }
3124
+ }
2977
3125
  },
2978
3126
  "RadioItemIndicator": {
2979
3127
  "name": "RadioItemIndicator",
@@ -2983,7 +3131,12 @@
2983
3131
  "Label": {
2984
3132
  "name": "Label",
2985
3133
  "description": "Label sub-component",
2986
- "props": {}
3134
+ "props": {
3135
+ "inset": {
3136
+ "type": "boolean",
3137
+ "description": "Adds left padding to align with items that have icons."
3138
+ }
3139
+ }
2987
3140
  },
2988
3141
  "Separator": {
2989
3142
  "name": "Separator",
@@ -5897,7 +6050,19 @@
5897
6050
  "description": "Child elements"
5898
6051
  }
5899
6052
  },
5900
- "examples": [],
6053
+ "examples": [
6054
+ "<Toasty>\n <ToastTriggerButton />\n </Toasty>",
6055
+ "<Toasty>\n <ToastTitleOnlyButton />\n </Toasty>",
6056
+ "<Toasty>\n <ToastDescriptionOnlyButton />\n </Toasty>",
6057
+ "<Toasty>\n <ToastSuccessButton />\n </Toasty>",
6058
+ "<Toasty>\n <ToastMultipleButton />\n </Toasty>",
6059
+ "<Toasty>\n <ToastErrorButton />\n </Toasty>",
6060
+ "<Toasty>\n <ToastWarningButton />\n </Toasty>",
6061
+ "<Toasty>\n <ToastInfoButton />\n </Toasty>",
6062
+ "<Toasty>\n <ToastCustomContentButton />\n </Toasty>",
6063
+ "<Toasty>\n <ToastActionsButton />\n </Toasty>",
6064
+ "<Toasty>\n <ToastPromiseButton />\n </Toasty>"
6065
+ ],
5901
6066
  "colors": [
5902
6067
  "bg-kumo-base",
5903
6068
  "bg-kumo-contrast",
@@ -6003,7 +6168,35 @@
6003
6168
  "fill-kumo-tip-stroke",
6004
6169
  "outline-kumo-fill",
6005
6170
  "text-kumo-default"
6006
- ]
6171
+ ],
6172
+ "subComponents": {
6173
+ "Provider": {
6174
+ "name": "Provider",
6175
+ "description": "Groups multiple tooltips so that after the first tooltip is shown, switching to another skips the open delay. Place once at your app root or layout.",
6176
+ "props": {
6177
+ "delay": {
6178
+ "type": "number",
6179
+ "description": "How long to wait (ms) before opening a tooltip once the pointer enters the trigger.",
6180
+ "default": "600"
6181
+ },
6182
+ "closeDelay": {
6183
+ "type": "number",
6184
+ "description": "How long to wait (ms) before closing a tooltip.",
6185
+ "default": "0"
6186
+ },
6187
+ "timeout": {
6188
+ "type": "number",
6189
+ "description": "Grace period (ms) during which a just-closed tooltip's delay is skipped when another tooltip opens.",
6190
+ "default": "400"
6191
+ }
6192
+ },
6193
+ "isPassThrough": true,
6194
+ "baseComponent": "TooltipBase.Provider",
6195
+ "usageExamples": [
6196
+ "<TooltipProvider>\n <App />\n</TooltipProvider>"
6197
+ ]
6198
+ }
6199
+ }
6007
6200
  },
6008
6201
  "InputArea": {
6009
6202
  "name": "InputArea",
@@ -6237,7 +6430,11 @@
6237
6430
  "optional": true
6238
6431
  }
6239
6432
  },
6240
- "examples": [],
6433
+ "examples": [
6434
+ "<ResourceListPage\n title=\"Databases\"\n description=\"Manage your database instances and configurations\"\n icon={<DatabaseIcon size={32} className=\"text-kumo-subtle\" />}\n >\n <Surface className=\"p-6\">\n <p>Main content area - your resource list would go here</p>\n </Surface>\n </ResourceListPage>",
6435
+ "<ResourceListPage\n title=\"API Keys\"\n description=\"Create and manage API keys for your applications\"\n usage={\n <Surface className=\"p-4\">\n <h3 className=\"mb-2 font-semibold\">Quick Start</h3>\n <p className=\"mb-3 text-sm text-kumo-subtle\">\n Generate an API key to authenticate your requests\n </p>\n <Code\n lang=\"bash\"\n code='curl -H \"Authorization: Bearer YOUR_API_KEY\" https://api.example.com'\n />\n </Surface>\n }\n >\n <Surface className=\"p-6\">\n <p>API keys list would appear here</p>\n </Surface>\n </ResourceListPage>",
6436
+ "<ResourceListPage\n title=\"KV Namespaces\"\n description=\"Store key-value data globally with low-latency access\"\n icon={<DatabaseIcon size={32} className=\"text-kumo-subtle\" />}\n usage={\n <Surface className=\"p-4\">\n <h3 className=\"mb-2 font-semibold\">Usage Example</h3>\n <Code\n lang=\"ts\"\n code={`// Read from KV\nconst value = await KV.get('key');\n\n// Write to KV\nawait KV.put('key', 'value');`}\n />\n </Surface>\n }\n additionalContent={\n <Surface className=\"p-4\">\n <h3 className=\"mb-2 font-semibold\">Learn More</h3>\n <p className=\"text-sm text-kumo-subtle\">\n Check out our documentation to learn more about KV storage.\n </p>\n </Surface>\n }\n >\n <div className=\"space-y-4\">\n <Surface className=\"p-6\">\n <h4 className=\"mb-2 font-semibold\">production-kv</h4>\n <p className=\"text-sm text-kumo-subtle\">Created 2 days ago</p>\n </Surface>\n <Surface className=\"p-6\">\n <h4 className=\"mb-2 font-semibold\">staging-kv</h4>\n <p className=\"text-sm text-kumo-subtle\">Created 1 week ago</p>\n </Surface>\n </div>\n </ResourceListPage>"
6437
+ ],
6241
6438
  "colors": [
6242
6439
  "bg-kumo-overlay",
6243
6440
  "text-kumo-subtle"
@@ -1315,7 +1315,7 @@ Cloudflare logo component.
1315
1315
  <DropdownMenu.Content>
1316
1316
  <DropdownMenu.Item
1317
1317
  icon={CloudIcon}
1318
- onSelect={() =>
1318
+ onClick={() =>
1319
1319
  copyToClipboard(
1320
1320
  generateCloudflareLogoSvg({ variant: "glyph" }),
1321
1321
  "glyph",
@@ -1326,7 +1326,7 @@ Cloudflare logo component.
1326
1326
  </DropdownMenu.Item>
1327
1327
  <DropdownMenu.Item
1328
1328
  icon={CodeIcon}
1329
- onSelect={() =>
1329
+ onClick={() =>
1330
1330
  copyToClipboard(
1331
1331
  generateCloudflareLogoSvg({ variant: "full" }),
1332
1332
  "full",
@@ -1337,7 +1337,7 @@ Cloudflare logo component.
1337
1337
  </DropdownMenu.Item>
1338
1338
  <DropdownMenu.Item
1339
1339
  icon={DownloadSimpleIcon}
1340
- onSelect={() =>
1340
+ onClick={() =>
1341
1341
  window.open(
1342
1342
  "https://www.cloudflare.com/press-kit/",
1343
1343
  "_blank",
@@ -1350,7 +1350,7 @@ Cloudflare logo component.
1350
1350
  <DropdownMenu.Separator />
1351
1351
  <DropdownMenu.Item
1352
1352
  icon={ArrowSquareOutIcon}
1353
- onSelect={() =>
1353
+ onClick={() =>
1354
1354
  window.open(
1355
1355
  "https://www.cloudflare.com/brand-assets/",
1356
1356
  "_blank",
@@ -1560,6 +1560,21 @@ Props:
1560
1560
  </div>
1561
1561
  ```
1562
1562
 
1563
+ ```tsx
1564
+ <div className="w-full space-y-4">
1565
+ <Collapsible.Root open={isOpen} onOpenChange={setIsOpen}>
1566
+ <Collapsible.DefaultTrigger>Edit details</Collapsible.DefaultTrigger>
1567
+ <Collapsible.DefaultPanel keepMounted>
1568
+ <Text>
1569
+ Type something below, then collapse and re-open — your input is
1570
+ preserved because the panel stays mounted.
1571
+ </Text>
1572
+ <Input label="Name" placeholder="Type here…" />
1573
+ </Collapsible.DefaultPanel>
1574
+ </Collapsible.Root>
1575
+ </div>
1576
+ ```
1577
+
1563
1578
  ```tsx
1564
1579
  <div className="w-full space-y-2">
1565
1580
  {items.map((item, i) => (
@@ -2932,6 +2947,10 @@ Sub sub-component (wraps DropdownMenuPrimitive)
2932
2947
 
2933
2948
  SubTrigger sub-component
2934
2949
 
2950
+ Props:
2951
+ - `icon`: Icon - Icon displayed before the label.
2952
+ - `inset`: boolean - Adds left padding to align with items that have icons.
2953
+
2935
2954
  #### DropdownMenu.SubContent
2936
2955
 
2937
2956
  SubContent sub-component
@@ -2940,26 +2959,67 @@ SubContent sub-component
2940
2959
 
2941
2960
  Content sub-component
2942
2961
 
2962
+ Props:
2963
+ - `sideOffset`: number [default: 8] - Distance in pixels from the trigger.
2964
+ - `container`: PortalContainer - Container element for the portal. Use this to render inside a Shadow DOM or custom container.
2965
+
2943
2966
  #### DropdownMenu.Item
2944
2967
 
2945
2968
  Item sub-component
2946
2969
 
2970
+ Props:
2971
+ - `icon`: Icon | ReactNode - Icon displayed before the label.
2972
+ - `variant`: "default" | "danger" [default: "default"] - Visual style of the item.
2973
+ - `selected`: boolean - Shows a check mark indicator when true.
2974
+ - `inset`: boolean - Adds left padding to align with items that have icons.
2975
+ - `onClick`: (event: React.MouseEvent) => void - Callback when the item is clicked.
2976
+ - `closeOnClick`: boolean [default: true] - Whether the menu closes after clicking this item.
2977
+ - `disabled`: boolean - When true, the item cannot be interacted with.
2978
+
2947
2979
  #### DropdownMenu.LinkItem
2948
2980
 
2949
2981
  LinkItem sub-component
2950
2982
 
2983
+ Props:
2984
+ - `href`: string - URL to navigate to when clicked.
2985
+ - `icon`: Icon | ReactNode - Icon displayed before the label.
2986
+ - `variant`: "default" | "danger" [default: "default"] - Visual style of the item.
2987
+ - `inset`: boolean - Adds left padding to align with items that have icons.
2988
+ - `target`: string - Link target attribute (e.g. "_blank" for new tab).
2989
+ - `render`: ReactElement | ((props, state) => ReactElement) - Custom element to render as the link. Use to integrate with framework routers (e.g. Next.js Link).
2990
+
2951
2991
  #### DropdownMenu.CheckboxItem
2952
2992
 
2953
2993
  CheckboxItem sub-component
2954
2994
 
2995
+ Props:
2996
+ - `checked`: boolean - Whether the item is checked.
2997
+ - `defaultChecked`: boolean [default: false] - Whether the item is initially checked (uncontrolled).
2998
+ - `onCheckedChange`: (checked: boolean, event: ChangeEventDetails) => void - Callback when the checked state changes.
2999
+ - `closeOnClick`: boolean [default: false] - Whether the menu closes after clicking this item.
3000
+ - `disabled`: boolean - When true, the item cannot be interacted with.
3001
+
2955
3002
  #### DropdownMenu.RadioGroup
2956
3003
 
2957
3004
  RadioGroup sub-component (wraps DropdownMenuPrimitive)
2958
3005
 
3006
+ Props:
3007
+ - `value`: any - The controlled value of the currently selected radio item.
3008
+ - `defaultValue`: any - The initially selected value (uncontrolled).
3009
+ - `onValueChange`: (value: any, event: ChangeEventDetails) => void - Callback when the selected value changes.
3010
+ - `disabled`: boolean - When true, all radio items in the group are disabled.
3011
+
2959
3012
  #### DropdownMenu.RadioItem
2960
3013
 
2961
3014
  RadioItem sub-component
2962
3015
 
3016
+ Props:
3017
+ - `value`: any (required) - The value of this radio item.
3018
+ - `icon`: Icon | ReactNode - Icon displayed before the label.
3019
+ - `inset`: boolean - Adds left padding to align with items that have icons.
3020
+ - `closeOnClick`: boolean [default: false] - Whether the menu closes after clicking this item.
3021
+ - `disabled`: boolean - When true, the item cannot be interacted with.
3022
+
2963
3023
  #### DropdownMenu.RadioItemIndicator
2964
3024
 
2965
3025
  RadioItemIndicator sub-component
@@ -2968,6 +3028,9 @@ RadioItemIndicator sub-component
2968
3028
 
2969
3029
  Label sub-component
2970
3030
 
3031
+ Props:
3032
+ - `inset`: boolean - Adds left padding to align with items that have icons.
3033
+
2971
3034
  #### DropdownMenu.Separator
2972
3035
 
2973
3036
  Separator sub-component
@@ -2981,6 +3044,199 @@ Shortcut sub-component
2981
3044
  Group sub-component (wraps DropdownMenuPrimitive)
2982
3045
 
2983
3046
 
3047
+ **Examples:**
3048
+
3049
+ ```tsx
3050
+ <DropdownMenu>
3051
+ <DropdownMenu.Trigger render={<Button icon={PlusIcon}>Add</Button>} />
3052
+ <DropdownMenu.Content>
3053
+ <DropdownMenu.Item>Worker</DropdownMenu.Item>
3054
+ <DropdownMenu.Item>Pages</DropdownMenu.Item>
3055
+ <DropdownMenu.Item>KV Namespace</DropdownMenu.Item>
3056
+ </DropdownMenu.Content>
3057
+ </DropdownMenu>
3058
+ ```
3059
+
3060
+ ```tsx
3061
+ <DropdownMenu>
3062
+ <DropdownMenu.Trigger render={<Button>View Options</Button>} />
3063
+ <DropdownMenu.Content>
3064
+ <DropdownMenu.Group>
3065
+ <DropdownMenu.Label>Display</DropdownMenu.Label>
3066
+ <DropdownMenu.CheckboxItem
3067
+ checked={showSidebar}
3068
+ onCheckedChange={setShowSidebar}
3069
+ >
3070
+ Show sidebar
3071
+ </DropdownMenu.CheckboxItem>
3072
+ <DropdownMenu.CheckboxItem
3073
+ checked={showLineNumbers}
3074
+ onCheckedChange={setShowLineNumbers}
3075
+ >
3076
+ Show line numbers
3077
+ </DropdownMenu.CheckboxItem>
3078
+ <DropdownMenu.CheckboxItem
3079
+ checked={wordWrap}
3080
+ onCheckedChange={setWordWrap}
3081
+ >
3082
+ Word wrap
3083
+ </DropdownMenu.CheckboxItem>
3084
+ </DropdownMenu.Group>
3085
+ </DropdownMenu.Content>
3086
+ </DropdownMenu>
3087
+ ```
3088
+
3089
+ ```tsx
3090
+ <DropdownMenu>
3091
+ <DropdownMenu.Trigger render={<Button icon={UserIcon}>Account</Button>} />
3092
+ <DropdownMenu.Content>
3093
+ <DropdownMenu.Item icon={UserIcon}>Profile</DropdownMenu.Item>
3094
+ <DropdownMenu.Item icon={CreditCardIcon}>Billing</DropdownMenu.Item>
3095
+ <DropdownMenu.Item icon={MoonIcon}>Dark mode</DropdownMenu.Item>
3096
+
3097
+ {/* Language submenu with RadioGroup */}
3098
+ <DropdownMenu.Sub>
3099
+ <DropdownMenu.SubTrigger>Language</DropdownMenu.SubTrigger>
3100
+ <DropdownMenu.SubContent>
3101
+ <DropdownMenu.Group>
3102
+ <DropdownMenu.RadioGroup
3103
+ value={language}
3104
+ onValueChange={setLanguage}
3105
+ >
3106
+ {languages.map((lang) => (
3107
+ <DropdownMenu.RadioItem key={lang.code} value={lang.code}>
3108
+ {lang.label}
3109
+ <DropdownMenu.RadioItemIndicator />
3110
+ </DropdownMenu.RadioItem>
3111
+ ))}
3112
+ </DropdownMenu.RadioGroup>
3113
+ </DropdownMenu.Group>
3114
+ </DropdownMenu.SubContent>
3115
+ </DropdownMenu.Sub>
3116
+
3117
+ {/* Timezone submenu with RadioGroup */}
3118
+ <DropdownMenu.Sub>
3119
+ <DropdownMenu.SubTrigger>Set Timezone</DropdownMenu.SubTrigger>
3120
+ <DropdownMenu.SubContent>
3121
+ <DropdownMenu.Group>
3122
+ <DropdownMenu.RadioGroup
3123
+ value={timezone}
3124
+ onValueChange={setTimezone}
3125
+ >
3126
+ {timezones.map((tz) => (
3127
+ <DropdownMenu.RadioItem key={tz.value} value={tz.value}>
3128
+ {tz.label}
3129
+ <DropdownMenu.RadioItemIndicator />
3130
+ </DropdownMenu.RadioItem>
3131
+ ))}
3132
+ </DropdownMenu.RadioGroup>
3133
+ </DropdownMenu.Group>
3134
+ </DropdownMenu.SubContent>
3135
+ </DropdownMenu.Sub>
3136
+
3137
+ <DropdownMenu.Separator />
3138
+ <DropdownMenu.Item icon={SignOutIcon} variant="danger">
3139
+ Log out
3140
+ </DropdownMenu.Item>
3141
+ </DropdownMenu.Content>
3142
+ </DropdownMenu>
3143
+ ```
3144
+
3145
+ ```tsx
3146
+ <DropdownMenu>
3147
+ <DropdownMenu.Trigger render={<Button>Edit</Button>} />
3148
+ <DropdownMenu.Content>
3149
+ <DropdownMenu.Item icon={PencilSimpleIcon}>Rename</DropdownMenu.Item>
3150
+ <DropdownMenu.Item icon={CopyIcon}>Duplicate</DropdownMenu.Item>
3151
+ <DropdownMenu.Separator />
3152
+ <DropdownMenu.Item inset>Move to folder</DropdownMenu.Item>
3153
+ <DropdownMenu.Item inset>Add to favorites</DropdownMenu.Item>
3154
+ <DropdownMenu.Separator />
3155
+ <DropdownMenu.Item icon={TrashIcon} variant="danger">
3156
+ Delete
3157
+ </DropdownMenu.Item>
3158
+ </DropdownMenu.Content>
3159
+ </DropdownMenu>
3160
+ ```
3161
+
3162
+ ```tsx
3163
+ <div className="flex flex-col items-start gap-2">
3164
+ <DropdownMenu>
3165
+ <DropdownMenu.Trigger render={<Button>Actions</Button>} />
3166
+ <DropdownMenu.Content>
3167
+ <DropdownMenu.Item
3168
+ icon={CopyIcon}
3169
+ onClick={() => setLastAction("Duplicated")}
3170
+ >
3171
+ Duplicate
3172
+ </DropdownMenu.Item>
3173
+ <DropdownMenu.Item
3174
+ icon={PencilSimpleIcon}
3175
+ onClick={() => setLastAction("Renamed")}
3176
+ >
3177
+ Rename
3178
+ </DropdownMenu.Item>
3179
+ <DropdownMenu.Separator />
3180
+ <DropdownMenu.Item
3181
+ icon={TrashIcon}
3182
+ variant="danger"
3183
+ onClick={() => setLastAction("Deleted")}
3184
+ >
3185
+ Delete
3186
+ </DropdownMenu.Item>
3187
+ </DropdownMenu.Content>
3188
+ </DropdownMenu>
3189
+ {lastAction && (
3190
+ <p className="text-sm text-kumo-subtle">
3191
+ Last action: <span className="text-kumo-default">{lastAction}</span>
3192
+ </p>
3193
+ )}
3194
+ </div>
3195
+ ```
3196
+
3197
+ ```tsx
3198
+ <DropdownMenu>
3199
+ <DropdownMenu.Trigger
3200
+ render={<button type="button" className="rounded-full" />}
3201
+ >
3202
+ <span className="flex h-8 w-8 items-center justify-center rounded-full bg-kumo-brand text-sm font-medium text-white">
3203
+ MR
3204
+ </span>
3205
+ </DropdownMenu.Trigger>
3206
+ <DropdownMenu.Content>
3207
+ <DropdownMenu.Item icon={UserIcon}>Profile</DropdownMenu.Item>
3208
+ <DropdownMenu.Item icon={GearIcon}>Settings</DropdownMenu.Item>
3209
+ <DropdownMenu.Separator />
3210
+ <DropdownMenu.Item icon={SignOutIcon} variant="danger">
3211
+ Log out
3212
+ </DropdownMenu.Item>
3213
+ </DropdownMenu.Content>
3214
+ </DropdownMenu>
3215
+ ```
3216
+
3217
+ ```tsx
3218
+ <DropdownMenu>
3219
+ <DropdownMenu.Trigger render={<Button>Resources</Button>} />
3220
+ <DropdownMenu.Content>
3221
+ <DropdownMenu.LinkItem href="/settings" icon={GearIcon}>
3222
+ Settings
3223
+ </DropdownMenu.LinkItem>
3224
+ <DropdownMenu.LinkItem href="/docs" icon={BookOpenIcon}>
3225
+ Documentation
3226
+ </DropdownMenu.LinkItem>
3227
+ <DropdownMenu.Separator />
3228
+ <DropdownMenu.LinkItem
3229
+ href="https://developers.cloudflare.com"
3230
+ target="_blank"
3231
+ icon={ArrowSquareOutIcon}
3232
+ >
3233
+ Developer Docs
3234
+ </DropdownMenu.LinkItem>
3235
+ </DropdownMenu.Content>
3236
+ </DropdownMenu>
3237
+ ```
3238
+
3239
+
2984
3240
  ---
2985
3241
 
2986
3242
  ### Empty
@@ -7382,6 +7638,15 @@ Toasty — toast notification provider and viewport. Renders a `Toast.Provider`
7382
7638
  **Styling:**
7383
7639
 
7384
7640
 
7641
+ **Examples:**
7642
+
7643
+ ```tsx
7644
+ <Toasty>
7645
+ <ToastTitleOnlyButton />
7646
+ </Toasty>
7647
+ ```
7648
+
7649
+
7385
7650
  ---
7386
7651
 
7387
7652
  ### Tooltip
@@ -7412,6 +7677,27 @@ Accessible popup that shows additional information on hover/focus. Wrap your app
7412
7677
 
7413
7678
  `bg-kumo-base`, `fill-kumo-base`, `fill-kumo-tip-shadow`, `fill-kumo-tip-stroke`, `outline-kumo-fill`, `text-kumo-default`
7414
7679
 
7680
+ **Sub-Components:**
7681
+
7682
+ This is a compound component. Use these sub-components:
7683
+
7684
+ #### Tooltip.Provider
7685
+
7686
+ Groups multiple tooltips so that after the first tooltip is shown, switching to another skips the open delay. Place once at your app root or layout.
7687
+
7688
+ Props:
7689
+ - `delay`: number [default: 600] - How long to wait (ms) before opening a tooltip once the pointer enters the trigger.
7690
+ - `closeDelay`: number [default: 0] - How long to wait (ms) before closing a tooltip.
7691
+ - `timeout`: number [default: 400] - Grace period (ms) during which a just-closed tooltip's delay is skipped when another tooltip opens.
7692
+
7693
+ Usage:
7694
+ ```tsx
7695
+ <TooltipProvider>
7696
+ <App />
7697
+ </TooltipProvider>
7698
+ ```
7699
+
7700
+
7415
7701
  **Examples:**
7416
7702
 
7417
7703
  ```tsx
@@ -1 +1 @@
1
- 1777571062774
1
+ 1777656981695
@@ -1,11 +1,11 @@
1
1
  "use client";
2
- import { jsx as o, jsxs as f } from "react/jsx-runtime";
3
- import { CaretDownIcon as g } from "@phosphor-icons/react";
2
+ import { jsx as o, jsxs as g } from "react/jsx-runtime";
3
+ import { CaretDownIcon as u } from "@phosphor-icons/react";
4
4
  import { forwardRef as r } from "react";
5
5
  import { c as t } from "./cn-ct4n7r74mh8y0f48.js";
6
- import { aO as u, aP as i, aQ as n } from "./vendor-base-ui-ie71jahf0czyf58j.js";
6
+ import { aO as C, aP as i, aQ as n } from "./vendor-base-ui-ie71jahf0czyf58j.js";
7
7
  function s({ className: e, ...l }) {
8
- return /* @__PURE__ */ o(u, { className: e, ...l });
8
+ return /* @__PURE__ */ o(C, { className: e, ...l });
9
9
  }
10
10
  s.displayName = "Collapsible.Root";
11
11
  const p = r(
@@ -30,7 +30,7 @@ const m = r(
30
30
  )
31
31
  );
32
32
  m.displayName = "Collapsible.Panel";
33
- const c = r(({ children: e, className: l }, a) => /* @__PURE__ */ f(
33
+ const c = r(({ children: e, className: l }, a) => /* @__PURE__ */ g(
34
34
  n,
35
35
  {
36
36
  ref: a,
@@ -44,21 +44,22 @@ const c = r(({ children: e, className: l }, a) => /* @__PURE__ */ f(
44
44
  children: [
45
45
  e,
46
46
  " ",
47
- /* @__PURE__ */ o(g, { className: "h-4 w-4 transition-transform [[data-panel-open]_&]:rotate-180" })
47
+ /* @__PURE__ */ o(u, { className: "h-4 w-4 transition-transform [[data-panel-open]_&]:rotate-180" })
48
48
  ]
49
49
  }
50
50
  ));
51
51
  c.displayName = "Collapsible.DefaultTrigger";
52
- const b = r(({ children: e, className: l }, a) => /* @__PURE__ */ o(
52
+ const b = r(({ children: e, className: l, ...a }, f) => /* @__PURE__ */ o(
53
53
  i,
54
54
  {
55
- ref: a,
55
+ ref: f,
56
56
  className: t("my-2 space-y-4 border-l-2 border-kumo-fill pl-4", l),
57
+ ...a,
57
58
  children: e
58
59
  }
59
60
  ));
60
61
  b.displayName = "Collapsible.DefaultPanel";
61
- const D = Object.assign(s, {
62
+ const T = Object.assign(s, {
62
63
  Root: s,
63
64
  Trigger: p,
64
65
  Panel: m,
@@ -66,6 +67,6 @@ const D = Object.assign(s, {
66
67
  DefaultPanel: b
67
68
  });
68
69
  export {
69
- D as C
70
+ T as C
70
71
  };
71
- //# sourceMappingURL=collapsible-k8urhi16pg90jvxa.js.map
72
+ //# sourceMappingURL=collapsible-nlp2jvcyuzxmq28o.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible-k8urhi16pg90jvxa.js","sources":["../../src/components/collapsible/collapsible.tsx"],"sourcesContent":["import { Collapsible as CollapsibleBase } from \"@base-ui/react/collapsible\";\nimport { CaretDownIcon } from \"@phosphor-icons/react\";\nimport {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nexport const KUMO_COLLAPSIBLE_VARIANTS = {} as const;\n\nexport const KUMO_COLLAPSIBLE_DEFAULT_VARIANTS = {} as const;\n\nexport interface KumoCollapsibleVariantsProps {}\n\nexport function collapsibleVariants(_props: KumoCollapsibleVariantsProps = {}) {\n return cn();\n}\n\n// =============================================================================\n// Collapsible Root\n// =============================================================================\n\ntype BaseRootProps = ComponentPropsWithoutRef<typeof CollapsibleBase.Root>;\n\nexport interface CollapsibleRootProps extends BaseRootProps {\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Root component that manages collapsible state.\n *\n * @example\n * ```tsx\n * <Collapsible.Root open={open} onOpenChange={setOpen}>\n * <Collapsible.Trigger>Toggle</Collapsible.Trigger>\n * <Collapsible.Panel>Content</Collapsible.Panel>\n * </Collapsible.Root>\n * ```\n */\nfunction CollapsibleRoot({ className, ...props }: CollapsibleRootProps) {\n return <CollapsibleBase.Root className={className} {...props} />;\n}\n\nCollapsibleRoot.displayName = \"Collapsible.Root\";\n\n// =============================================================================\n// Collapsible Trigger\n// =============================================================================\n\ntype BaseTriggerProps = ComponentPropsWithoutRef<\n typeof CollapsibleBase.Trigger\n>;\n\nexport interface CollapsibleTriggerProps extends BaseTriggerProps {\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Button that toggles the collapsible panel visibility.\n * Use the `render` prop to customize the trigger element.\n *\n * @example\n * ```tsx\n * // Default button\n * <Collapsible.Trigger>Show more</Collapsible.Trigger>\n *\n * // Custom trigger element\n * <Collapsible.Trigger render={<Button variant=\"ghost\" />}>\n * Toggle details\n * </Collapsible.Trigger>\n * ```\n */\nconst CollapsibleTrigger = forwardRef<HTMLButtonElement, CollapsibleTriggerProps>(\n ({ className, ...props }, ref) => {\n return (\n <CollapsibleBase.Trigger\n ref={ref}\n className={cn(\"cursor-pointer\", className)}\n {...props}\n />\n );\n },\n);\n\nCollapsibleTrigger.displayName = \"Collapsible.Trigger\";\n\n// =============================================================================\n// Collapsible Panel\n// =============================================================================\n\ntype BasePanelProps = ComponentPropsWithoutRef<typeof CollapsibleBase.Panel>;\n\nexport interface CollapsiblePanelProps extends BasePanelProps {\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Container for collapsible content. Renders when the collapsible is open.\n *\n * @example\n * ```tsx\n * <Collapsible.Panel className=\"mt-2 space-y-4\">\n * <Text>Revealed content here</Text>\n * </Collapsible.Panel>\n * ```\n */\nconst CollapsiblePanel = forwardRef<HTMLDivElement, CollapsiblePanelProps>(\n ({ className, ...props }, ref) => {\n return (\n <CollapsibleBase.Panel\n ref={ref}\n className={className}\n {...props}\n />\n );\n },\n);\n\nCollapsiblePanel.displayName = \"Collapsible.Panel\";\n\n// =============================================================================\n// Default Trigger (Migration Affordance)\n// =============================================================================\n\nexport interface CollapsibleDefaultTriggerProps {\n /** Label text displayed in the trigger */\n children: ReactNode;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Pre-styled trigger with text label and animated caret icon.\n * Provides the same visual style as the previous Collapsible API.\n *\n * Use this for quick migration or when you want the default Kumo style.\n *\n * @example\n * ```tsx\n * <Collapsible.Root>\n * <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>\n * <Collapsible.Panel>Content</Collapsible.Panel>\n * </Collapsible.Root>\n * ```\n */\nconst CollapsibleDefaultTrigger = forwardRef<\n HTMLButtonElement,\n CollapsibleDefaultTriggerProps\n>(({ children, className }, ref) => {\n return (\n <CollapsibleBase.Trigger\n ref={ref}\n className={cn(\n // Defensive resets to prevent global button styles from polluting the trigger\n \"bg-transparent border-none shadow-none p-0 m-0\",\n // Base styles for the trigger\n \"flex cursor-pointer items-center gap-1 text-sm text-kumo-link select-none\",\n className,\n )}\n >\n {children}{\" \"}\n <CaretDownIcon className=\"h-4 w-4 transition-transform [[data-panel-open]_&]:rotate-180\" />\n </CollapsibleBase.Trigger>\n );\n});\n\nCollapsibleDefaultTrigger.displayName = \"Collapsible.DefaultTrigger\";\n\n// =============================================================================\n// Default Panel (Migration Affordance)\n// =============================================================================\n\nexport interface CollapsibleDefaultPanelProps {\n /** Panel content */\n children: ReactNode;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Pre-styled panel with left border accent and standard spacing.\n * Provides the same visual style as the previous Collapsible API.\n *\n * @example\n * ```tsx\n * <Collapsible.Root>\n * <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>\n * <Collapsible.DefaultPanel>\n * <Text>Content with default styling</Text>\n * </Collapsible.DefaultPanel>\n * </Collapsible.Root>\n * ```\n */\nconst CollapsibleDefaultPanel = forwardRef<\n HTMLDivElement,\n CollapsibleDefaultPanelProps\n>(({ children, className }, ref) => {\n return (\n <CollapsibleBase.Panel\n ref={ref}\n className={cn(\"my-2 space-y-4 border-l-2 border-kumo-fill pl-4\", className)}\n >\n {children}\n </CollapsibleBase.Panel>\n );\n});\n\nCollapsibleDefaultPanel.displayName = \"Collapsible.DefaultPanel\";\n\n// =============================================================================\n// Compound Component Export\n// =============================================================================\n\n/**\n * Collapsible — a composable disclosure component for showing/hiding content.\n *\n * Built on Base UI's Collapsible with full composition support.\n *\n * ## Basic Usage\n *\n * ```tsx\n * const [open, setOpen] = useState(false);\n *\n * <Collapsible.Root open={open} onOpenChange={setOpen}>\n * <Collapsible.Trigger render={<Button variant=\"ghost\" />}>\n * Show details\n * </Collapsible.Trigger>\n * <Collapsible.Panel className=\"mt-2\">\n * <Text>Hidden content revealed when expanded.</Text>\n * </Collapsible.Panel>\n * </Collapsible.Root>\n * ```\n *\n * ## With Default Styling\n *\n * Use `DefaultTrigger` and `DefaultPanel` for the classic Kumo style:\n *\n * ```tsx\n * <Collapsible.Root>\n * <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>\n * <Collapsible.DefaultPanel>\n * <Text>Content with border-left accent</Text>\n * </Collapsible.DefaultPanel>\n * </Collapsible.Root>\n * ```\n *\n * ## Controlled Accordion Pattern\n *\n * ```tsx\n * const [activeIndex, setActiveIndex] = useState<number | null>(null);\n *\n * {items.map((item, i) => (\n * <Collapsible.Root\n * key={i}\n * open={activeIndex === i}\n * onOpenChange={(open) => setActiveIndex(open ? i : null)}\n * >\n * <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger>\n * <Collapsible.DefaultPanel>{item.content}</Collapsible.DefaultPanel>\n * </Collapsible.Root>\n * ))}\n * ```\n */\nexport const Collapsible = Object.assign(CollapsibleRoot, {\n Root: CollapsibleRoot,\n Trigger: CollapsibleTrigger,\n Panel: CollapsiblePanel,\n DefaultTrigger: CollapsibleDefaultTrigger,\n DefaultPanel: CollapsibleDefaultPanel,\n});\n\n// =============================================================================\n// Type Exports\n// =============================================================================\n\nexport type CollapsibleProps = CollapsibleRootProps;\n"],"names":["CollapsibleRoot","className","props","CollapsibleBase.Root","CollapsibleTrigger","forwardRef","ref","jsx","CollapsibleBase.Trigger","cn","CollapsiblePanel","CollapsibleBase.Panel","CollapsibleDefaultTrigger","children","jsxs","CaretDownIcon","CollapsibleDefaultPanel","Collapsible"],"mappings":";;;;;;AA6CA,SAASA,EAAgB,EAAE,WAAAC,GAAW,GAAGC,KAA+B;AACtE,2BAAQC,GAAA,EAAqB,WAAAF,GAAuB,GAAGC,EAAA,CAAO;AAChE;AAEAF,EAAgB,cAAc;AA8B9B,MAAMI,IAAqBC;AAAA,EACzB,CAAC,EAAE,WAAAJ,GAAW,GAAGC,EAAA,GAASI,MAEtB,gBAAAC;AAAA,IAACC;AAAAA,IAAA;AAAA,MACC,KAAAF;AAAA,MACA,WAAWG,EAAG,kBAAkBR,CAAS;AAAA,MACxC,GAAGC;AAAA,IAAA;AAAA,EAAA;AAIZ;AAEAE,EAAmB,cAAc;AAuBjC,MAAMM,IAAmBL;AAAA,EACvB,CAAC,EAAE,WAAAJ,GAAW,GAAGC,EAAA,GAASI,MAEtB,gBAAAC;AAAA,IAACI;AAAAA,IAAA;AAAA,MACC,KAAAL;AAAA,MACA,WAAAL;AAAA,MACC,GAAGC;AAAA,IAAA;AAAA,EAAA;AAIZ;AAEAQ,EAAiB,cAAc;AA2B/B,MAAME,IAA4BP,EAGhC,CAAC,EAAE,UAAAQ,GAAU,WAAAZ,EAAA,GAAaK,MAExB,gBAAAQ;AAAA,EAACN;AAAAA,EAAA;AAAA,IACC,KAAAF;AAAA,IACA,WAAWG;AAAA;AAAA,MAET;AAAA;AAAA,MAEA;AAAA,MACAR;AAAA,IAAA;AAAA,IAGD,UAAA;AAAA,MAAAY;AAAA,MAAU;AAAA,MACX,gBAAAN,EAACQ,GAAA,EAAc,WAAU,gEAAA,CAAgE;AAAA,IAAA;AAAA,EAAA;AAAA,CAG9F;AAEDH,EAA0B,cAAc;AA2BxC,MAAMI,IAA0BX,EAG9B,CAAC,EAAE,UAAAQ,GAAU,WAAAZ,EAAA,GAAaK,MAExB,gBAAAC;AAAA,EAACI;AAAAA,EAAA;AAAA,IACC,KAAAL;AAAA,IACA,WAAWG,EAAG,mDAAmDR,CAAS;AAAA,IAEzE,UAAAY;AAAA,EAAA;AAAA,CAGN;AAEDG,EAAwB,cAAc;AAwD/B,MAAMC,IAAc,OAAO,OAAOjB,GAAiB;AAAA,EACxD,MAAMA;AAAA,EACN,SAASI;AAAA,EACT,OAAOM;AAAA,EACP,gBAAgBE;AAAA,EAChB,cAAcI;AAChB,CAAC;"}
1
+ {"version":3,"file":"collapsible-nlp2jvcyuzxmq28o.js","sources":["../../src/components/collapsible/collapsible.tsx"],"sourcesContent":["import { Collapsible as CollapsibleBase } from \"@base-ui/react/collapsible\";\nimport { CaretDownIcon } from \"@phosphor-icons/react\";\nimport {\n forwardRef,\n type ComponentPropsWithoutRef,\n type ReactNode,\n} from \"react\";\nimport { cn } from \"../../utils/cn\";\n\n// =============================================================================\n// Variants\n// =============================================================================\n\nexport const KUMO_COLLAPSIBLE_VARIANTS = {} as const;\n\nexport const KUMO_COLLAPSIBLE_DEFAULT_VARIANTS = {} as const;\n\nexport interface KumoCollapsibleVariantsProps {}\n\nexport function collapsibleVariants(_props: KumoCollapsibleVariantsProps = {}) {\n return cn();\n}\n\n// =============================================================================\n// Collapsible Root\n// =============================================================================\n\ntype BaseRootProps = ComponentPropsWithoutRef<typeof CollapsibleBase.Root>;\n\nexport interface CollapsibleRootProps extends BaseRootProps {\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Root component that manages collapsible state.\n *\n * @example\n * ```tsx\n * <Collapsible.Root open={open} onOpenChange={setOpen}>\n * <Collapsible.Trigger>Toggle</Collapsible.Trigger>\n * <Collapsible.Panel>Content</Collapsible.Panel>\n * </Collapsible.Root>\n * ```\n */\nfunction CollapsibleRoot({ className, ...props }: CollapsibleRootProps) {\n return <CollapsibleBase.Root className={className} {...props} />;\n}\n\nCollapsibleRoot.displayName = \"Collapsible.Root\";\n\n// =============================================================================\n// Collapsible Trigger\n// =============================================================================\n\ntype BaseTriggerProps = ComponentPropsWithoutRef<\n typeof CollapsibleBase.Trigger\n>;\n\nexport interface CollapsibleTriggerProps extends BaseTriggerProps {\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Button that toggles the collapsible panel visibility.\n * Use the `render` prop to customize the trigger element.\n *\n * @example\n * ```tsx\n * // Default button\n * <Collapsible.Trigger>Show more</Collapsible.Trigger>\n *\n * // Custom trigger element\n * <Collapsible.Trigger render={<Button variant=\"ghost\" />}>\n * Toggle details\n * </Collapsible.Trigger>\n * ```\n */\nconst CollapsibleTrigger = forwardRef<HTMLButtonElement, CollapsibleTriggerProps>(\n ({ className, ...props }, ref) => {\n return (\n <CollapsibleBase.Trigger\n ref={ref}\n className={cn(\"cursor-pointer\", className)}\n {...props}\n />\n );\n },\n);\n\nCollapsibleTrigger.displayName = \"Collapsible.Trigger\";\n\n// =============================================================================\n// Collapsible Panel\n// =============================================================================\n\ntype BasePanelProps = ComponentPropsWithoutRef<typeof CollapsibleBase.Panel>;\n\nexport interface CollapsiblePanelProps extends BasePanelProps {\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Container for collapsible content. Renders when the collapsible is open.\n *\n * @example\n * ```tsx\n * <Collapsible.Panel className=\"mt-2 space-y-4\">\n * <Text>Revealed content here</Text>\n * </Collapsible.Panel>\n * ```\n */\nconst CollapsiblePanel = forwardRef<HTMLDivElement, CollapsiblePanelProps>(\n ({ className, ...props }, ref) => {\n return (\n <CollapsibleBase.Panel\n ref={ref}\n className={className}\n {...props}\n />\n );\n },\n);\n\nCollapsiblePanel.displayName = \"Collapsible.Panel\";\n\n// =============================================================================\n// Default Trigger (Migration Affordance)\n// =============================================================================\n\nexport interface CollapsibleDefaultTriggerProps {\n /** Label text displayed in the trigger */\n children: ReactNode;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Pre-styled trigger with text label and animated caret icon.\n * Provides the same visual style as the previous Collapsible API.\n *\n * Use this for quick migration or when you want the default Kumo style.\n *\n * @example\n * ```tsx\n * <Collapsible.Root>\n * <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>\n * <Collapsible.Panel>Content</Collapsible.Panel>\n * </Collapsible.Root>\n * ```\n */\nconst CollapsibleDefaultTrigger = forwardRef<\n HTMLButtonElement,\n CollapsibleDefaultTriggerProps\n>(({ children, className }, ref) => {\n return (\n <CollapsibleBase.Trigger\n ref={ref}\n className={cn(\n // Defensive resets to prevent global button styles from polluting the trigger\n \"bg-transparent border-none shadow-none p-0 m-0\",\n // Base styles for the trigger\n \"flex cursor-pointer items-center gap-1 text-sm text-kumo-link select-none\",\n className,\n )}\n >\n {children}{\" \"}\n <CaretDownIcon className=\"h-4 w-4 transition-transform [[data-panel-open]_&]:rotate-180\" />\n </CollapsibleBase.Trigger>\n );\n});\n\nCollapsibleDefaultTrigger.displayName = \"Collapsible.DefaultTrigger\";\n\n// =============================================================================\n// Default Panel (Migration Affordance)\n// =============================================================================\n\nexport interface CollapsibleDefaultPanelProps extends BasePanelProps {\n /** Panel content */\n children: ReactNode;\n /** Additional CSS classes */\n className?: string;\n}\n\n/**\n * Pre-styled panel with left border accent and standard spacing.\n * Provides the same visual style as the previous Collapsible API.\n *\n * @example\n * ```tsx\n * <Collapsible.Root>\n * <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>\n * <Collapsible.DefaultPanel>\n * <Text>Content with default styling</Text>\n * </Collapsible.DefaultPanel>\n * </Collapsible.Root>\n * ```\n */\nconst CollapsibleDefaultPanel = forwardRef<\n HTMLDivElement,\n CollapsibleDefaultPanelProps\n>(({ children, className, ...props }, ref) => {\n return (\n <CollapsibleBase.Panel\n ref={ref}\n className={cn(\"my-2 space-y-4 border-l-2 border-kumo-fill pl-4\", className)}\n {...props}\n >\n {children}\n </CollapsibleBase.Panel>\n );\n});\n\nCollapsibleDefaultPanel.displayName = \"Collapsible.DefaultPanel\";\n\n// =============================================================================\n// Compound Component Export\n// =============================================================================\n\n/**\n * Collapsible — a composable disclosure component for showing/hiding content.\n *\n * Built on Base UI's Collapsible with full composition support.\n *\n * ## Basic Usage\n *\n * ```tsx\n * const [open, setOpen] = useState(false);\n *\n * <Collapsible.Root open={open} onOpenChange={setOpen}>\n * <Collapsible.Trigger render={<Button variant=\"ghost\" />}>\n * Show details\n * </Collapsible.Trigger>\n * <Collapsible.Panel className=\"mt-2\">\n * <Text>Hidden content revealed when expanded.</Text>\n * </Collapsible.Panel>\n * </Collapsible.Root>\n * ```\n *\n * ## With Default Styling\n *\n * Use `DefaultTrigger` and `DefaultPanel` for the classic Kumo style:\n *\n * ```tsx\n * <Collapsible.Root>\n * <Collapsible.DefaultTrigger>Show details</Collapsible.DefaultTrigger>\n * <Collapsible.DefaultPanel>\n * <Text>Content with border-left accent</Text>\n * </Collapsible.DefaultPanel>\n * </Collapsible.Root>\n * ```\n *\n * ## Controlled Accordion Pattern\n *\n * ```tsx\n * const [activeIndex, setActiveIndex] = useState<number | null>(null);\n *\n * {items.map((item, i) => (\n * <Collapsible.Root\n * key={i}\n * open={activeIndex === i}\n * onOpenChange={(open) => setActiveIndex(open ? i : null)}\n * >\n * <Collapsible.DefaultTrigger>{item.title}</Collapsible.DefaultTrigger>\n * <Collapsible.DefaultPanel>{item.content}</Collapsible.DefaultPanel>\n * </Collapsible.Root>\n * ))}\n * ```\n */\nexport const Collapsible = Object.assign(CollapsibleRoot, {\n Root: CollapsibleRoot,\n Trigger: CollapsibleTrigger,\n Panel: CollapsiblePanel,\n DefaultTrigger: CollapsibleDefaultTrigger,\n DefaultPanel: CollapsibleDefaultPanel,\n});\n\n// =============================================================================\n// Type Exports\n// =============================================================================\n\nexport type CollapsibleProps = CollapsibleRootProps;\n"],"names":["CollapsibleRoot","className","props","CollapsibleBase.Root","CollapsibleTrigger","forwardRef","ref","jsx","CollapsibleBase.Trigger","cn","CollapsiblePanel","CollapsibleBase.Panel","CollapsibleDefaultTrigger","children","jsxs","CaretDownIcon","CollapsibleDefaultPanel","Collapsible"],"mappings":";;;;;;AA6CA,SAASA,EAAgB,EAAE,WAAAC,GAAW,GAAGC,KAA+B;AACtE,2BAAQC,GAAA,EAAqB,WAAAF,GAAuB,GAAGC,EAAA,CAAO;AAChE;AAEAF,EAAgB,cAAc;AA8B9B,MAAMI,IAAqBC;AAAA,EACzB,CAAC,EAAE,WAAAJ,GAAW,GAAGC,EAAA,GAASI,MAEtB,gBAAAC;AAAA,IAACC;AAAAA,IAAA;AAAA,MACC,KAAAF;AAAA,MACA,WAAWG,EAAG,kBAAkBR,CAAS;AAAA,MACxC,GAAGC;AAAA,IAAA;AAAA,EAAA;AAIZ;AAEAE,EAAmB,cAAc;AAuBjC,MAAMM,IAAmBL;AAAA,EACvB,CAAC,EAAE,WAAAJ,GAAW,GAAGC,EAAA,GAASI,MAEtB,gBAAAC;AAAA,IAACI;AAAAA,IAAA;AAAA,MACC,KAAAL;AAAA,MACA,WAAAL;AAAA,MACC,GAAGC;AAAA,IAAA;AAAA,EAAA;AAIZ;AAEAQ,EAAiB,cAAc;AA2B/B,MAAME,IAA4BP,EAGhC,CAAC,EAAE,UAAAQ,GAAU,WAAAZ,EAAA,GAAaK,MAExB,gBAAAQ;AAAA,EAACN;AAAAA,EAAA;AAAA,IACC,KAAAF;AAAA,IACA,WAAWG;AAAA;AAAA,MAET;AAAA;AAAA,MAEA;AAAA,MACAR;AAAA,IAAA;AAAA,IAGD,UAAA;AAAA,MAAAY;AAAA,MAAU;AAAA,MACX,gBAAAN,EAACQ,GAAA,EAAc,WAAU,gEAAA,CAAgE;AAAA,IAAA;AAAA,EAAA;AAAA,CAG9F;AAEDH,EAA0B,cAAc;AA2BxC,MAAMI,IAA0BX,EAG9B,CAAC,EAAE,UAAAQ,GAAU,WAAAZ,GAAW,GAAGC,EAAA,GAASI,MAElC,gBAAAC;AAAA,EAACI;AAAAA,EAAA;AAAA,IACC,KAAAL;AAAA,IACA,WAAWG,EAAG,mDAAmDR,CAAS;AAAA,IACzE,GAAGC;AAAA,IAEH,UAAAW;AAAA,EAAA;AAAA,CAGN;AAEDG,EAAwB,cAAc;AAwD/B,MAAMC,IAAc,OAAO,OAAOjB,GAAiB;AAAA,EACxD,MAAMA;AAAA,EACN,SAASI;AAAA,EACT,OAAOM;AAAA,EACP,gBAAgBE;AAAA,EAChB,cAAcI;AAChB,CAAC;"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { C as o } from "../chunks/collapsible-k8urhi16pg90jvxa.js";
2
+ import { C as o } from "../chunks/collapsible-nlp2jvcyuzxmq28o.js";
3
3
  export {
4
4
  o as Collapsible
5
5
  };
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import { C as Ta } from "./chunks/combobox-fq36ye0hstote16x.js";
12
12
  import { a as M, D as U, c as N, e as u } from "./chunks/dialog-k3f1fbam6nt96k8x.js";
13
13
  import { d as Aa, b as ba } from "./chunks/dialog-k3f1fbam6nt96k8x.js";
14
14
  import { D as Sa } from "./chunks/dropdown-zbax0zowy6m9zhmt.js";
15
- import { C as _a } from "./chunks/collapsible-k8urhi16pg90jvxa.js";
15
+ import { C as _a } from "./chunks/collapsible-nlp2jvcyuzxmq28o.js";
16
16
  import { F as Ia, a as La, K as Ra, f as Ea } from "./chunks/field-c0wf94plit2gci59.js";
17
17
  import { b as Ma, K as Ua, L as Na, a as Ka, l as ga } from "./chunks/label-c3h9i3y4wiccelt7.js";
18
18
  import { I as K } from "./chunks/input-ncfowphv81yq7fyy.js";
@@ -41,7 +41,7 @@ export interface CollapsibleDefaultTriggerProps {
41
41
  /** Additional CSS classes */
42
42
  className?: string;
43
43
  }
44
- export interface CollapsibleDefaultPanelProps {
44
+ export interface CollapsibleDefaultPanelProps extends BasePanelProps {
45
45
  /** Panel content */
46
46
  children: ReactNode;
47
47
  /** Additional CSS classes */
@@ -1 +1 @@
1
- {"version":3,"file":"collapsible.d.ts","sourceRoot":"","sources":["../../../../src/components/collapsible/collapsible.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE5E,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAOf,eAAO,MAAM,yBAAyB,IAAc,CAAC;AAErD,eAAO,MAAM,iCAAiC,IAAc,CAAC;AAE7D,MAAM,WAAW,4BAA4B;CAAG;AAEhD,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,4BAAiC,UAE5E;AAMD,KAAK,aAAa,GAAG,wBAAwB,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAE3E,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACzD,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,2CAErE;kBAFQ,eAAe;;;AAUxB,KAAK,gBAAgB,GAAG,wBAAwB,CAC9C,OAAO,eAAe,CAAC,OAAO,CAC/B,CAAC;AAEF,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmCD,KAAK,cAAc,GAAG,wBAAwB,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;AAE7E,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8BD,MAAM,WAAW,8BAA8B;IAC7C,0CAA0C;IAC1C,QAAQ,EAAE,SAAS,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2CD,MAAM,WAAW,4BAA4B;IAC3C,oBAAoB;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,WAAW;;;;;;CAMtB,CAAC;AAMH,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC"}
1
+ {"version":3,"file":"collapsible.d.ts","sourceRoot":"","sources":["../../../../src/components/collapsible/collapsible.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE5E,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAOf,eAAO,MAAM,yBAAyB,IAAc,CAAC;AAErD,eAAO,MAAM,iCAAiC,IAAc,CAAC;AAE7D,MAAM,WAAW,4BAA4B;CAAG;AAEhD,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,4BAAiC,UAE5E;AAMD,KAAK,aAAa,GAAG,wBAAwB,CAAC,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAE3E,MAAM,WAAW,oBAAqB,SAAQ,aAAa;IACzD,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,iBAAS,eAAe,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,oBAAoB,2CAErE;kBAFQ,eAAe;;;AAUxB,KAAK,gBAAgB,GAAG,wBAAwB,CAC9C,OAAO,eAAe,CAAC,OAAO,CAC/B,CAAC;AAEF,MAAM,WAAW,uBAAwB,SAAQ,gBAAgB;IAC/D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAmCD,KAAK,cAAc,GAAG,wBAAwB,CAAC,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;AAE7E,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IAC3D,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8BD,MAAM,WAAW,8BAA8B;IAC7C,0CAA0C;IAC1C,QAAQ,EAAE,SAAS,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2CD,MAAM,WAAW,4BAA6B,SAAQ,cAAc;IAClE,oBAAoB;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,WAAW;;;;;;CAMtB,CAAC;AAMH,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudflare/kumo",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Kumo - Cloudflare's component library for building modern web applications",
@@ -943,3 +943,45 @@ interface GroupProps extends BaseProps {
943
943
  expect(props).toEqual({});
944
944
  });
945
945
  });
946
+
947
+ describe("SUB_COMPONENT_OVERRIDES", () => {
948
+ it("declares a Tooltip.Provider entry that passes through to TooltipBase.Provider", async () => {
949
+ const { SUB_COMPONENT_OVERRIDES, PASSTHROUGH_COMPONENT_DOCS } =
950
+ await import("./metadata.js");
951
+
952
+ expect(SUB_COMPONENT_OVERRIDES.Tooltip).toBeDefined();
953
+ const tooltipOverrides = SUB_COMPONENT_OVERRIDES.Tooltip;
954
+ expect(tooltipOverrides).toHaveLength(1);
955
+
956
+ const provider = tooltipOverrides[0];
957
+ expect(provider.name).toBe("Provider");
958
+ expect(provider.valueName).toBe("TooltipProvider");
959
+ expect(provider.isPassThrough).toBe(true);
960
+ expect(provider.baseComponent).toBe("TooltipBase.Provider");
961
+ expect(provider.propsType).toBeNull();
962
+
963
+ // The baseComponent must resolve to a documented passthrough entry so the
964
+ // merge + lookup path in index.ts produces real docs, not an empty stub.
965
+ expect(
966
+ PASSTHROUGH_COMPONENT_DOCS[provider.baseComponent as string],
967
+ ).toBeDefined();
968
+ });
969
+
970
+ it("entries have the same shape as detectSubComponents() results", async () => {
971
+ const { SUB_COMPONENT_OVERRIDES } = await import("./metadata.js");
972
+
973
+ for (const overrides of Object.values(SUB_COMPONENT_OVERRIDES)) {
974
+ for (const entry of overrides) {
975
+ // Required fields of SubComponentConfig.
976
+ expect(typeof entry.name).toBe("string");
977
+ expect(typeof entry.valueName).toBe("string");
978
+ expect(typeof entry.description).toBe("string");
979
+ expect(typeof entry.isPassThrough).toBe("boolean");
980
+ // propsType may be a string or null.
981
+ expect(
982
+ entry.propsType === null || typeof entry.propsType === "string",
983
+ ).toBe(true);
984
+ }
985
+ }
986
+ });
987
+ });
@@ -44,6 +44,7 @@ import {
44
44
  createCacheEntry,
45
45
  } from "./cache.js";
46
46
  import {
47
+ toPascalCase,
47
48
  toScreamingSnakeCase,
48
49
  extractSemanticColors,
49
50
  extractBlockDependencies,
@@ -62,6 +63,7 @@ import {
62
63
  ADDITIONAL_COMPONENT_PROPS,
63
64
  PROP_TYPE_OVERRIDES,
64
65
  COMPONENT_STYLING_METADATA,
66
+ SUB_COMPONENT_OVERRIDES,
65
67
  } from "./metadata.js";
66
68
 
67
69
  // External imports - demo examples from kumo-docs-astro
@@ -585,11 +587,16 @@ async function processComponent(
585
587
  const colors = extractSemanticColors(sourcePath);
586
588
 
587
589
  // Determine examples
590
+ // Demo metadata keys are derived from file names (e.g. DropdownDemo.tsx → "Dropdown")
591
+ // which may differ from the component's export name (e.g. "DropdownMenu").
592
+ // Try the component name first, then fall back to the PascalCase directory name.
588
593
  let examples: readonly string[];
589
594
  if (config.examples !== undefined) {
590
595
  examples = config.examples;
591
596
  } else {
592
- const extracted = input.storyExamples.get(config.name);
597
+ const extracted =
598
+ input.storyExamples.get(config.name) ??
599
+ input.storyExamples.get(toPascalCase(config.dirName));
593
600
  examples = extracted?.aiExamples ?? [];
594
601
  if (examples.length > 0 && CLI_FLAGS.verbose) {
595
602
  console.log(
@@ -598,14 +605,21 @@ async function processComponent(
598
605
  }
599
606
  }
600
607
 
601
- // Detect and process sub-components
608
+ // Merge SUB_COMPONENT_OVERRIDES after source detection.
609
+ // Detected entries win on name conflict so source-level patterns aren't masked.
602
610
  const detectedSubComponents = detectSubComponents(sourcePath);
611
+ const subComponentOverrides = SUB_COMPONENT_OVERRIDES[config.name] ?? [];
612
+ const detectedNames = new Set(detectedSubComponents.map((sc) => sc.name));
613
+ const mergedSubComponents = [
614
+ ...detectedSubComponents,
615
+ ...subComponentOverrides.filter((o) => !detectedNames.has(o.name)),
616
+ ];
603
617
  let subComponentSchemas: Record<string, SubComponentSchema> | undefined;
604
618
 
605
- if (detectedSubComponents.length > 0) {
619
+ if (mergedSubComponents.length > 0) {
606
620
  subComponentSchemas = {};
607
621
 
608
- for (const subComp of detectedSubComponents) {
622
+ for (const subComp of mergedSubComponents) {
609
623
  let subProps = extractSubComponentProps(sourcePath, subComp, CLI_FLAGS);
610
624
  let description = subComp.description;
611
625
  let usageExamples: string[] | undefined;
@@ -8,7 +8,12 @@
8
8
  * - Styling metadata for Figma plugin
9
9
  */
10
10
 
11
- import type { PropSchema, PassthroughDoc, ComponentStyling } from "./types.js";
11
+ import type {
12
+ PropSchema,
13
+ PassthroughDoc,
14
+ ComponentStyling,
15
+ SubComponentConfig,
16
+ } from "./types.js";
12
17
 
13
18
  // =============================================================================
14
19
  // Pass-through Component Documentation
@@ -158,6 +163,66 @@ export const PASSTHROUGH_COMPONENT_DOCS: Record<string, PassthroughDoc> = {
158
163
  </Combobox.Collection>`,
159
164
  ],
160
165
  },
166
+
167
+ // Tooltip sub-components
168
+ "TooltipBase.Provider": {
169
+ description:
170
+ "Groups multiple tooltips so that after the first tooltip is shown, switching to another skips the open delay. Place once at your app root or layout.",
171
+ props: {
172
+ delay: {
173
+ type: "number",
174
+ description:
175
+ "How long to wait (ms) before opening a tooltip once the pointer enters the trigger.",
176
+ default: "600",
177
+ },
178
+ closeDelay: {
179
+ type: "number",
180
+ description: "How long to wait (ms) before closing a tooltip.",
181
+ default: "0",
182
+ },
183
+ timeout: {
184
+ type: "number",
185
+ description:
186
+ "Grace period (ms) during which a just-closed tooltip's delay is skipped when another tooltip opens.",
187
+ default: "400",
188
+ },
189
+ },
190
+ usageExamples: ["<TooltipProvider>\n <App />\n</TooltipProvider>"],
191
+ },
192
+ };
193
+
194
+ // =============================================================================
195
+ // Sub-Component Overrides
196
+ // =============================================================================
197
+
198
+ /**
199
+ * Manual sub-component entries that are merged into the registry alongside
200
+ * entries detected by `detectSubComponents()` in `sub-components.ts`.
201
+ *
202
+ * Use this when a component exposes a related API (e.g., a sibling named
203
+ * export like `TooltipProvider`) that we want documented as a sub-component
204
+ * (e.g., `Tooltip.Provider`) for the registry / docs, *without* changing the
205
+ * component's runtime shape (no `Object.assign`, no attached property).
206
+ *
207
+ * Detected sub-components take precedence over overrides with the same
208
+ * `name`, so a real source-level compound pattern will always win and
209
+ * prevent silent masking of detector regressions.
210
+ *
211
+ * Keyed by the parent component name (e.g., "Tooltip"). Values have the same
212
+ * shape as `detectSubComponents()` entries so they feed directly into the
213
+ * existing processing loop in `index.ts`.
214
+ */
215
+ export const SUB_COMPONENT_OVERRIDES: Record<string, SubComponentConfig[]> = {
216
+ Tooltip: [
217
+ {
218
+ name: "Provider",
219
+ valueName: "TooltipProvider",
220
+ propsType: null,
221
+ description: "Provider sub-component (wraps TooltipBase)",
222
+ isPassThrough: true,
223
+ baseComponent: "TooltipBase.Provider",
224
+ },
225
+ ],
161
226
  };
162
227
 
163
228
  // =============================================================================
@@ -254,6 +319,161 @@ export const ADDITIONAL_COMPONENT_PROPS: Record<
254
319
  description: "Callback when collapsed state changes",
255
320
  },
256
321
  },
322
+ "DropdownMenu.Item": {
323
+ icon: {
324
+ type: "Icon | ReactNode",
325
+ description: "Icon displayed before the label.",
326
+ },
327
+ variant: {
328
+ type: '"default" | "danger"',
329
+ description: "Visual style of the item.",
330
+ default: '"default"',
331
+ },
332
+ selected: {
333
+ type: "boolean",
334
+ description: "Shows a check mark indicator when true.",
335
+ },
336
+ inset: {
337
+ type: "boolean",
338
+ description: "Adds left padding to align with items that have icons.",
339
+ },
340
+ onClick: {
341
+ type: "(event: React.MouseEvent) => void",
342
+ description: "Callback when the item is clicked.",
343
+ },
344
+ closeOnClick: {
345
+ type: "boolean",
346
+ description: "Whether the menu closes after clicking this item.",
347
+ default: "true",
348
+ },
349
+ disabled: {
350
+ type: "boolean",
351
+ description: "When true, the item cannot be interacted with.",
352
+ },
353
+ },
354
+ "DropdownMenu.LinkItem": {
355
+ href: {
356
+ type: "string",
357
+ description: "URL to navigate to when clicked.",
358
+ },
359
+ icon: {
360
+ type: "Icon | ReactNode",
361
+ description: "Icon displayed before the label.",
362
+ },
363
+ variant: {
364
+ type: '"default" | "danger"',
365
+ description: "Visual style of the item.",
366
+ default: '"default"',
367
+ },
368
+ inset: {
369
+ type: "boolean",
370
+ description: "Adds left padding to align with items that have icons.",
371
+ },
372
+ target: {
373
+ type: "string",
374
+ description: 'Link target attribute (e.g. "_blank" for new tab).',
375
+ },
376
+ render: {
377
+ type: "ReactElement | ((props, state) => ReactElement)",
378
+ description:
379
+ "Custom element to render as the link. Use to integrate with framework routers (e.g. Next.js Link).",
380
+ },
381
+ },
382
+ "DropdownMenu.Content": {
383
+ sideOffset: {
384
+ type: "number",
385
+ description: "Distance in pixels from the trigger.",
386
+ default: "8",
387
+ },
388
+ container: {
389
+ type: "PortalContainer",
390
+ description:
391
+ "Container element for the portal. Use this to render inside a Shadow DOM or custom container.",
392
+ },
393
+ },
394
+ "DropdownMenu.SubTrigger": {
395
+ icon: {
396
+ type: "Icon",
397
+ description: "Icon displayed before the label.",
398
+ },
399
+ inset: {
400
+ type: "boolean",
401
+ description: "Adds left padding to align with items that have icons.",
402
+ },
403
+ },
404
+ "DropdownMenu.CheckboxItem": {
405
+ checked: {
406
+ type: "boolean",
407
+ description: "Whether the item is checked.",
408
+ },
409
+ defaultChecked: {
410
+ type: "boolean",
411
+ description: "Whether the item is initially checked (uncontrolled).",
412
+ default: "false",
413
+ },
414
+ onCheckedChange: {
415
+ type: "(checked: boolean, event: ChangeEventDetails) => void",
416
+ description: "Callback when the checked state changes.",
417
+ },
418
+ closeOnClick: {
419
+ type: "boolean",
420
+ description: "Whether the menu closes after clicking this item.",
421
+ default: "false",
422
+ },
423
+ disabled: {
424
+ type: "boolean",
425
+ description: "When true, the item cannot be interacted with.",
426
+ },
427
+ },
428
+ "DropdownMenu.RadioGroup": {
429
+ value: {
430
+ type: "any",
431
+ description:
432
+ "The controlled value of the currently selected radio item.",
433
+ },
434
+ defaultValue: {
435
+ type: "any",
436
+ description: "The initially selected value (uncontrolled).",
437
+ },
438
+ onValueChange: {
439
+ type: "(value: any, event: ChangeEventDetails) => void",
440
+ description: "Callback when the selected value changes.",
441
+ },
442
+ disabled: {
443
+ type: "boolean",
444
+ description: "When true, all radio items in the group are disabled.",
445
+ },
446
+ },
447
+ "DropdownMenu.RadioItem": {
448
+ value: {
449
+ type: "any",
450
+ required: true,
451
+ description: "The value of this radio item.",
452
+ },
453
+ icon: {
454
+ type: "Icon | ReactNode",
455
+ description: "Icon displayed before the label.",
456
+ },
457
+ inset: {
458
+ type: "boolean",
459
+ description: "Adds left padding to align with items that have icons.",
460
+ },
461
+ closeOnClick: {
462
+ type: "boolean",
463
+ description: "Whether the menu closes after clicking this item.",
464
+ default: "false",
465
+ },
466
+ disabled: {
467
+ type: "boolean",
468
+ description: "When true, the item cannot be interacted with.",
469
+ },
470
+ },
471
+ "DropdownMenu.Label": {
472
+ inset: {
473
+ type: "boolean",
474
+ description: "Adds left padding to align with items that have icons.",
475
+ },
476
+ },
257
477
  "InputGroup.Addon": {
258
478
  align: {
259
479
  type: '"start" | "end"',