@cloudflare/kumo 1.5.1 → 1.6.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 (150) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/ai/component-registry.json +52 -3
  3. package/ai/component-registry.md +291 -2
  4. package/ai/schemas.ts +11 -2
  5. package/dist/.build-complete +1 -1
  6. package/dist/ai/schemas.d.ts +24 -5
  7. package/dist/ai/schemas.d.ts.map +1 -1
  8. package/dist/catalog.js +1 -1
  9. package/dist/{checkbox-CWANiedi.js → checkbox-Dt8iSNOg.js} +3 -3
  10. package/dist/{checkbox-CWANiedi.js.map → checkbox-Dt8iSNOg.js.map} +1 -1
  11. package/dist/clipboard-text-Bw5rKPXz.js +185 -0
  12. package/dist/clipboard-text-Bw5rKPXz.js.map +1 -0
  13. package/dist/{combobox-C9koouxM.js → combobox-BIC-YZ2L.js} +41 -41
  14. package/dist/combobox-BIC-YZ2L.js.map +1 -0
  15. package/dist/command-line/cli.js +88 -30
  16. package/dist/command-line/commands/add.js +88 -30
  17. package/dist/{command-palette-TGXgr6Vq.js → command-palette-D3MNR7w9.js} +31 -31
  18. package/dist/{command-palette-TGXgr6Vq.js.map → command-palette-D3MNR7w9.js.map} +1 -1
  19. package/dist/components/checkbox.js +1 -1
  20. package/dist/components/clipboard-text.js +1 -1
  21. package/dist/components/combobox.js +1 -1
  22. package/dist/components/command-palette.js +1 -1
  23. package/dist/components/date-picker.js +6 -0
  24. package/dist/components/date-picker.js.map +1 -0
  25. package/dist/components/dialog.js +1 -1
  26. package/dist/components/dropdown.js +1 -1
  27. package/dist/components/field.js +1 -1
  28. package/dist/components/input.js +3 -3
  29. package/dist/components/label.js +1 -1
  30. package/dist/components/link.js +1 -1
  31. package/dist/components/menubar.js +1 -1
  32. package/dist/components/meter.js +1 -1
  33. package/dist/components/pagination.js +1 -1
  34. package/dist/components/popover.js +1 -1
  35. package/dist/components/radio.js +1 -1
  36. package/dist/components/select.js +1 -1
  37. package/dist/components/sensitive-input.js +1 -1
  38. package/dist/components/switch.js +1 -1
  39. package/dist/components/table.js +1 -1
  40. package/dist/components/tabs.js +1 -1
  41. package/dist/components/toast.js +2 -2
  42. package/dist/components/tooltip.js +1 -1
  43. package/dist/date-picker-M6uNX5Ca.js +2921 -0
  44. package/dist/date-picker-M6uNX5Ca.js.map +1 -0
  45. package/dist/{dialog-CpCeOqSZ.js → dialog-toS9krNF.js} +17 -17
  46. package/dist/dialog-toS9krNF.js.map +1 -0
  47. package/dist/{dropdown-DFeFcKfn.js → dropdown-BquiYKKC.js} +38 -38
  48. package/dist/dropdown-BquiYKKC.js.map +1 -0
  49. package/dist/{field-Dt-XuSaQ.js → field-DCq04TgZ.js} +3 -3
  50. package/dist/{field-Dt-XuSaQ.js.map → field-DCq04TgZ.js.map} +1 -1
  51. package/dist/index.js +51 -49
  52. package/dist/index.js.map +1 -1
  53. package/dist/{input-GZAWBXYX.js → input-CCR8NGG7.js} +3 -3
  54. package/dist/{input-GZAWBXYX.js.map → input-CCR8NGG7.js.map} +1 -1
  55. package/dist/{input-area-CS1-ceY4.js → input-area-DU2Yvp_t.js} +3 -3
  56. package/dist/{input-area-CS1-ceY4.js.map → input-area-DU2Yvp_t.js.map} +1 -1
  57. package/dist/{input-group-COo-wz5O.js → input-group-C365-qBq.js} +2 -2
  58. package/dist/{input-group-COo-wz5O.js.map → input-group-C365-qBq.js.map} +1 -1
  59. package/dist/{label-ChZ2Pp5p.js → label-zjtV7oXa.js} +2 -2
  60. package/dist/{label-ChZ2Pp5p.js.map → label-zjtV7oXa.js.map} +1 -1
  61. package/dist/{link-Mj2WM1AS.js → link-C8pUZ4Q-.js} +8 -8
  62. package/dist/{link-Mj2WM1AS.js.map → link-C8pUZ4Q-.js.map} +1 -1
  63. package/dist/{menubar-CbXWXQYR.js → menubar-D7WvAf6x.js} +6 -6
  64. package/dist/menubar-D7WvAf6x.js.map +1 -0
  65. package/dist/{meter-Bu5f3mAc.js → meter-jQGKS1z4.js} +4 -4
  66. package/dist/{meter-Bu5f3mAc.js.map → meter-jQGKS1z4.js.map} +1 -1
  67. package/dist/{pagination-Cf-yRO-n.js → pagination-BN80iKY6.js} +2 -2
  68. package/dist/{pagination-Cf-yRO-n.js.map → pagination-BN80iKY6.js.map} +1 -1
  69. package/dist/{popover-D7yeRosi.js → popover-syU1104E.js} +4 -4
  70. package/dist/{popover-D7yeRosi.js.map → popover-syU1104E.js.map} +1 -1
  71. package/dist/primitives/accordion.js +1 -1
  72. package/dist/primitives/alert-dialog.js +1 -1
  73. package/dist/primitives/autocomplete.js +1 -1
  74. package/dist/primitives/avatar.js +1 -1
  75. package/dist/primitives/button.js +1 -1
  76. package/dist/primitives/checkbox-group.js +1 -1
  77. package/dist/primitives/checkbox.js +1 -1
  78. package/dist/primitives/collapsible.js +1 -1
  79. package/dist/primitives/combobox.js +1 -1
  80. package/dist/primitives/context-menu.js +1 -1
  81. package/dist/primitives/dialog.js +1 -1
  82. package/dist/primitives/direction-provider.js +1 -1
  83. package/dist/primitives/field.js +1 -1
  84. package/dist/primitives/fieldset.js +1 -1
  85. package/dist/primitives/form.js +1 -1
  86. package/dist/primitives/input.js +1 -1
  87. package/dist/primitives/menu.js +1 -1
  88. package/dist/primitives/menubar.js +1 -1
  89. package/dist/primitives/meter.js +1 -1
  90. package/dist/primitives/navigation-menu.js +1 -1
  91. package/dist/primitives/number-field.js +1 -1
  92. package/dist/primitives/popover.js +1 -1
  93. package/dist/primitives/preview-card.js +1 -1
  94. package/dist/primitives/progress.js +1 -1
  95. package/dist/primitives/radio-group.js +1 -1
  96. package/dist/primitives/radio.js +1 -1
  97. package/dist/primitives/scroll-area.js +1 -1
  98. package/dist/primitives/select.js +1 -1
  99. package/dist/primitives/separator.js +1 -1
  100. package/dist/primitives/slider.js +1 -1
  101. package/dist/primitives/switch.js +1 -1
  102. package/dist/primitives/tabs.js +1 -1
  103. package/dist/primitives/toast.js +1 -1
  104. package/dist/primitives/toggle-group.js +1 -1
  105. package/dist/primitives/toggle.js +1 -1
  106. package/dist/primitives/toolbar.js +1 -1
  107. package/dist/primitives/tooltip.js +1 -1
  108. package/dist/primitives.js +1 -1
  109. package/dist/{radio-CKn09bGo.js → radio-CWMtSx65.js} +8 -8
  110. package/dist/{radio-CKn09bGo.js.map → radio-CWMtSx65.js.map} +1 -1
  111. package/dist/{schemas-H10xB2M_.js → schemas-DbIwo0ET.js} +251 -239
  112. package/dist/{schemas-H10xB2M_.js.map → schemas-DbIwo0ET.js.map} +1 -1
  113. package/dist/{select-DvpgiOau.js → select-G6JqBVkg.js} +37 -37
  114. package/dist/{select-DvpgiOau.js.map → select-G6JqBVkg.js.map} +1 -1
  115. package/dist/{sensitive-input-BuYT6U6C.js → sensitive-input-DNFpycoy.js} +4 -4
  116. package/dist/{sensitive-input-BuYT6U6C.js.map → sensitive-input-DNFpycoy.js.map} +1 -1
  117. package/dist/src/command-line/utils/transformer.d.ts +8 -4
  118. package/dist/src/command-line/utils/transformer.d.ts.map +1 -1
  119. package/dist/src/components/clipboard-text/clipboard-text.d.ts +23 -0
  120. package/dist/src/components/clipboard-text/clipboard-text.d.ts.map +1 -1
  121. package/dist/src/components/date-picker/date-picker.d.ts +65 -0
  122. package/dist/src/components/date-picker/date-picker.d.ts.map +1 -0
  123. package/dist/src/components/date-picker/index.d.ts +4 -0
  124. package/dist/src/components/date-picker/index.d.ts.map +1 -0
  125. package/dist/src/components/dropdown/dropdown.d.ts.map +1 -1
  126. package/dist/src/index.d.ts +1 -0
  127. package/dist/src/index.d.ts.map +1 -1
  128. package/dist/styles/kumo-binding.css +0 -4
  129. package/dist/styles/kumo-standalone.css +1 -1
  130. package/dist/styles/kumo.css +541 -0
  131. package/dist/{switch-Tu34uFoa.js → switch-CmsZ4z-g.js} +9 -9
  132. package/dist/{switch-Tu34uFoa.js.map → switch-CmsZ4z-g.js.map} +1 -1
  133. package/dist/{table-DtUrZ2Rj.js → table-Dc0AGcLV.js} +2 -2
  134. package/dist/{table-DtUrZ2Rj.js.map → table-Dc0AGcLV.js.map} +1 -1
  135. package/dist/{tabs-B7THfqHW.js → tabs-BpD1iUiz.js} +2 -2
  136. package/dist/{tabs-B7THfqHW.js.map → tabs-BpD1iUiz.js.map} +1 -1
  137. package/dist/{toast-Du4y8qng.js → toast-BrR0pjLE.js} +8 -8
  138. package/dist/{toast-Du4y8qng.js.map → toast-BrR0pjLE.js.map} +1 -1
  139. package/dist/{tooltip-BxV1H6AV.js → tooltip-daVJYtXY.js} +2 -2
  140. package/dist/{tooltip-BxV1H6AV.js.map → tooltip-daVJYtXY.js.map} +1 -1
  141. package/dist/{vendor-base-ui-CQ6wEonS.js → vendor-base-ui-9w7J6BvW.js} +7246 -7245
  142. package/dist/{vendor-base-ui-CQ6wEonS.js.map → vendor-base-ui-9w7J6BvW.js.map} +1 -1
  143. package/package.json +6 -1
  144. package/scripts/component-registry/discovery.ts +1 -7
  145. package/dist/clipboard-text-B32_yb2r.js +0 -108
  146. package/dist/clipboard-text-B32_yb2r.js.map +0 -1
  147. package/dist/combobox-C9koouxM.js.map +0 -1
  148. package/dist/dialog-CpCeOqSZ.js.map +0 -1
  149. package/dist/dropdown-DFeFcKfn.js.map +0 -1
  150. package/dist/menubar-CbXWXQYR.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,95 @@
1
1
  # @cloudflare/kumo
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 50d4251: Add DatePicker component built on react-day-picker v9
8
+
9
+ **New Component: DatePicker**
10
+ - Three selection modes: `single`, `multiple`, and `range`
11
+ - Forwards all react-day-picker props for maximum flexibility
12
+ - Styled with Kumo tokens (no external CSS import needed)
13
+ - Supports localization via date-fns locales
14
+ - Supports timezone via `timeZone` prop
15
+ - Custom modifiers for highlighting specific dates
16
+ - Footer prop for messages/usage limits
17
+ - Accessible keyboard navigation with Kumo-styled focus rings
18
+
19
+ **Usage:**
20
+
21
+ ```tsx
22
+ // Single date
23
+ <DatePicker mode="single" selected={date} onSelect={setDate} />
24
+
25
+ // Multiple dates
26
+ <DatePicker mode="multiple" selected={dates} onSelect={setDates} max={5} />
27
+
28
+ // Date range
29
+ <DatePicker mode="range" selected={range} onSelect={setRange} numberOfMonths={2} />
30
+ ```
31
+
32
+ **Composing with Popover:**
33
+
34
+ ```tsx
35
+ <Popover>
36
+ <Popover.Trigger asChild>
37
+ <Button variant="outline" icon={CalendarDotsIcon}>
38
+ Pick a date
39
+ </Button>
40
+ </Popover.Trigger>
41
+ <Popover.Content className="p-3">
42
+ <DatePicker mode="single" selected={date} onSelect={setDate} />
43
+ </Popover.Content>
44
+ </Popover>
45
+ ```
46
+
47
+ **Note:** Consider using `DatePicker` with `mode="range"` instead of `DateRangePicker` for new projects - it offers more flexibility and a smaller bundle size.
48
+
49
+ **Internal changes:**
50
+ - Added `react-day-picker` v9 as a dependency
51
+ - Updated lint rule to allow components without KUMO\_\*\_VARIANTS exports
52
+ - Updated component registry codegen to handle variant-less components
53
+ - Disabled `jsx-a11y/no-autofocus` rule (intentional prop forwarding)
54
+
55
+ - 93361ed: feat(clipboard-text): add slide animation with tooltip on copy
56
+
57
+ ### Patch Changes
58
+
59
+ - c71bd9b: Updated the MenuBar so its child buttons align with the container’s outer corners.
60
+ - 46ecf42: Fix `kumo add` to consolidate imports from `@cloudflare/kumo` into a single statement using inline `type` syntax.
61
+
62
+ Previously, running `kumo add DeleteResource` would produce non-conformant code with duplicate imports:
63
+
64
+ ```typescript
65
+ import { Dialog, DialogRoot } from "@cloudflare/kumo";
66
+ import { Input } from "@cloudflare/kumo";
67
+ import { Button } from "@cloudflare/kumo";
68
+ ```
69
+
70
+ Now it produces a single consolidated import:
71
+
72
+ ```typescript
73
+ import {
74
+ Dialog,
75
+ DialogRoot,
76
+ Input,
77
+ Button,
78
+ type DialogProps,
79
+ } from "@cloudflare/kumo";
80
+ ```
81
+
82
+ This satisfies ESLint's `import/no-duplicates` rule with `prefer-inline: true`.
83
+
84
+ - a9167fa: Fix z-index stacking issues with nested portaled components (e.g., Select inside Dialog)
85
+ - Remove unnecessary z-index values from Dialog, Select, Combobox, and Dropdown
86
+ - Delete `.z-modal { z-index: 9999 }` - DOM order now handles stacking naturally
87
+ - Components opened later correctly appear on top without z-index wars
88
+
89
+ - f02494d: fix(dropdown): improve external link detection to handle http:// and protocol-relative urls
90
+
91
+ updated the external link check to use a regex that matches `https://`, `http://`, and protocol-relative URLs (`//`). previously only `https://` links opened in a new tab.
92
+
3
93
  ## 1.5.1
4
94
 
5
95
  ### Patch Changes
@@ -647,17 +647,30 @@
647
647
  "type": "string",
648
648
  "optional": true,
649
649
  "description": "Additional CSS classes merged via `cn()`."
650
+ },
651
+ "tooltip": {
652
+ "type": "object",
653
+ "optional": true,
654
+ "description": "Tooltip config. Shows tooltip on hover, anchored toast on click."
655
+ },
656
+ "labels": {
657
+ "type": "object",
658
+ "optional": true,
659
+ "description": "Accessible labels for i18n."
650
660
  }
651
661
  },
652
662
  "examples": [
653
663
  "<ClipboardText text=\"0c239dd2\" />",
654
664
  "<ClipboardText text=\"abc123\" />",
655
665
  "<ClipboardText text=\"sk_live_51H8...\" />",
656
- "<ClipboardText text=\"https://example.com/very/long/url/path\" />"
666
+ "<ClipboardText text=\"https://example.com/very/long/url/path\" />",
667
+ "<ClipboardText\n text=\"npx kumo add button\"\n tooltip={{ text: \"Copy\", copiedText: \"Copied!\", side: \"top\" }}\n />"
657
668
  ],
658
669
  "colors": [
659
670
  "bg-kumo-base",
660
- "border-kumo-line"
671
+ "border-kumo-line",
672
+ "outline-kumo-fill",
673
+ "text-kumo-default"
661
674
  ],
662
675
  "styling": {
663
676
  "baseTokens": [
@@ -2236,6 +2249,36 @@
2236
2249
  "text-kumo-subtle"
2237
2250
  ]
2238
2251
  },
2252
+ "DatePicker": {
2253
+ "name": "DatePicker",
2254
+ "type": "component",
2255
+ "description": "DatePicker — a date selection calendar. Built on [react-day-picker](https://daypicker.dev) with Kumo styling. Supports three selection modes: single, multiple, and range.",
2256
+ "importPath": "@cloudflare/kumo",
2257
+ "category": "Other",
2258
+ "props": {
2259
+ "className": {
2260
+ "type": "string",
2261
+ "description": "Additional CSS classes"
2262
+ },
2263
+ "children": {
2264
+ "type": "ReactNode",
2265
+ "description": "Child elements"
2266
+ }
2267
+ },
2268
+ "examples": [
2269
+ "<div className=\"flex flex-col gap-4\">\n <DatePicker mode=\"single\" selected={date} onChange={d => {\n if (d) {\n setDate(d);\n }\n }} />\n <p className=\"text-sm text-kumo-subtle\">\n Selected: {date ? date.toLocaleDateString() : \"None\"}\n </p>\n </div>",
2270
+ "<div className=\"flex flex-col gap-4\">\n <DatePicker\n mode=\"multiple\"\n selected={dates}\n onChange={setDates}\n max={5}\n />\n <p className=\"text-sm text-kumo-subtle\">\n Selected: {dates?.length ?? 0} date(s)\n </p>\n </div>",
2271
+ "<div className=\"flex flex-col gap-4\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n numberOfMonths={2}\n />\n <p className=\"text-sm text-kumo-subtle\">\n Range:{\" \"}\n {range?.from\n ? `${range.from.toLocaleDateString()} - ${range.to?.toLocaleDateString() ?? \"...\"}`\n : \"None\"}\n </p>\n </div>",
2272
+ "<div className=\"flex flex-col gap-4\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n min={3}\n max={7}\n footer={\n <span className=\"text-xs text-kumo-subtle\">Select 3-7 nights</span>\n }\n />\n </div>",
2273
+ "<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"outline\" icon={CalendarDotsIcon}>\n {date ? date.toLocaleDateString() : \"Pick a date\"}\n </Button>\n </Popover.Trigger>\n <Popover.Content className=\"p-3\">\n <DatePicker mode=\"single\" selected={date} onChange={setDate} />\n </Popover.Content>\n </Popover>",
2274
+ "<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"outline\" icon={CalendarDotsIcon}>\n {formatRange()}\n </Button>\n </Popover.Trigger>\n <Popover.Content className=\"p-3\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n numberOfMonths={2}\n />\n </Popover.Content>\n </Popover>",
2275
+ "<Popover>\n <Popover.Trigger asChild>\n <Button variant=\"outline\" icon={CalendarDotsIcon}>\n {formatRange()}\n </Button>\n </Popover.Trigger>\n <Popover.Content className=\"p-0\">\n <div className=\"flex\">\n <div className=\"flex flex-col gap-1 border-r border-kumo-line p-2 text-sm\">\n {presets.map((preset) => {\n const isActive = isPresetActive(preset);\n return (\n <button\n key={preset.label}\n type=\"button\"\n onClick={() => handlePresetClick(preset)}\n className={`rounded-md px-3 py-1.5 text-left whitespace-nowrap ${isActive\n ? \"bg-kumo-bg-inverse text-kumo-text-inverse\"\n : \"text-kumo-strong hover:bg-kumo-control\"\n }`}\n >\n {preset.label}\n </button>\n );\n })}\n </div>\n <div className=\"p-3\">\n <DatePicker\n mode=\"range\"\n selected={range}\n onChange={setRange}\n month={month}\n onMonthChange={setMonth}\n numberOfMonths={2}\n />\n </div>\n </div>\n </Popover.Content>\n </Popover>",
2276
+ "<DatePicker\n mode=\"multiple\"\n selected={dates}\n onChange={setDates}\n max={maxDays}\n disabled={unavailableDates}\n fixedWeeks\n footer={\n <p className=\"text-xs text-kumo-subtle pt-2 w-full\">\n {selectedCount}/{maxDays} days selected. Grayed dates are unavailable.\n </p>\n }\n />"
2277
+ ],
2278
+ "colors": [
2279
+ "bg-kumo-base"
2280
+ ]
2281
+ },
2239
2282
  "DateRangePicker": {
2240
2283
  "name": "DateRangePicker",
2241
2284
  "type": "component",
@@ -2408,7 +2451,10 @@
2408
2451
  "examples": [
2409
2452
  "<Dialog.Root>\n <Dialog.Trigger render={(p) => <Button {...p}>Click me</Button>} />\n <Dialog className=\"p-8\">\n <div className=\"mb-4 flex items-start justify-between gap-4\">\n <Dialog.Title className=\"text-2xl font-semibold\">\n Modal Title\n </Dialog.Title>\n <Dialog.Close\n aria-label=\"Close\"\n render={(props) => (\n <Button\n {...props}\n variant=\"secondary\"\n shape=\"square\"\n icon={<X />}\n aria-label=\"Close\"\n />\n )}\n />\n </div>\n <Dialog.Description className=\"text-kumo-subtle\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\n eiusmod tempor incididunt ut labore et dolore magna aliqua.\n </Dialog.Description>\n </Dialog>\n </Dialog.Root>",
2410
2453
  "<Dialog.Root>\n <Dialog.Trigger render={(p) => <Button {...p}>Delete</Button>} />\n <Dialog className=\"p-8\">\n <div className=\"mb-4 flex items-start justify-between gap-4\">\n <Dialog.Title className=\"text-2xl font-semibold\">\n Modal Title\n </Dialog.Title>\n <Dialog.Close\n aria-label=\"Close\"\n render={(props) => (\n <Button\n {...props}\n variant=\"secondary\"\n shape=\"square\"\n icon={<X />}\n aria-label=\"Close\"\n />\n )}\n />\n </div>\n <Dialog.Description className=\"text-kumo-subtle\">\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do\n eiusmod tempor incididunt ut labore et dolore magna aliqua.\n </Dialog.Description>\n <div className=\"mt-8 flex justify-end gap-2\">\n <Dialog.Close\n render={(props) => (\n <Button variant=\"secondary\" {...props}>\n Cancel\n </Button>\n )}\n />\n <Dialog.Close\n render={(props) => (\n <Button variant=\"destructive\" {...props}>\n Delete\n </Button>\n )}\n />\n </div>\n </Dialog>\n </Dialog.Root>",
2411
- "<Dialog.Root disablePointerDismissal>\n <Dialog.Trigger\n render={(p) => (\n <Button {...p} variant=\"destructive\">\n Delete Project\n </Button>\n )}\n />\n <Dialog className=\"p-8\">\n <div className=\"mb-4 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-kumo-danger/20\">\n <Warning size={20} className=\"text-kumo-danger\" />\n </div>\n <Dialog.Title className=\"text-xl font-semibold\">\n Delete Project?\n </Dialog.Title>\n </div>\n <Dialog.Description className=\"text-kumo-subtle\">\n This action cannot be undone. This will permanently delete the project\n and all associated data.\n </Dialog.Description>\n <div className=\"mt-8 flex justify-end gap-2\">\n <Dialog.Close\n render={(props) => (\n <Button variant=\"secondary\" {...props}>\n Cancel\n </Button>\n )}\n />\n <Dialog.Close\n render={(props) => (\n <Button variant=\"destructive\" {...props}>\n Delete\n </Button>\n )}\n />\n </div>\n </Dialog>\n </Dialog.Root>"
2454
+ "<Dialog.Root disablePointerDismissal>\n <Dialog.Trigger\n render={(p) => (\n <Button {...p} variant=\"destructive\">\n Delete Project\n </Button>\n )}\n />\n <Dialog className=\"p-8\">\n <div className=\"mb-4 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-full bg-kumo-danger/20\">\n <Warning size={20} className=\"text-kumo-danger\" />\n </div>\n <Dialog.Title className=\"text-xl font-semibold\">\n Delete Project?\n </Dialog.Title>\n </div>\n <Dialog.Description className=\"text-kumo-subtle\">\n This action cannot be undone. This will permanently delete the project\n and all associated data.\n </Dialog.Description>\n <div className=\"mt-8 flex justify-end gap-2\">\n <Dialog.Close\n render={(props) => (\n <Button variant=\"secondary\" {...props}>\n Cancel\n </Button>\n )}\n />\n <Dialog.Close\n render={(props) => (\n <Button variant=\"destructive\" {...props}>\n Delete\n </Button>\n )}\n />\n </div>\n </Dialog>\n </Dialog.Root>",
2455
+ "<Dialog.Root>\n <Dialog.Trigger render={(p) => <Button {...p}>Open Form</Button>} />\n <Dialog className=\"p-8\">\n <div className=\"mb-4 flex items-start justify-between gap-4\">\n <Dialog.Title className=\"text-2xl font-semibold\">\n Create Resource\n </Dialog.Title>\n <Dialog.Close\n aria-label=\"Close\"\n render={(props) => (\n <Button\n {...props}\n variant=\"secondary\"\n shape=\"square\"\n icon={<X />}\n aria-label=\"Close\"\n />\n )}\n />\n </div>\n <Dialog.Description className=\"mb-4 text-kumo-subtle\">\n Select a region for your new resource.\n </Dialog.Description>\n <Select\n className=\"w-full\"\n renderValue={(v) =>\n regions.find((r) => r.value === v)?.label ?? \"Select region...\"\n }\n >\n {regions.map((region) => (\n <Select.Option key={region.value} value={region.value}>\n {region.label}\n </Select.Option>\n ))}\n </Select>\n <div className=\"mt-8 flex justify-end gap-2\">\n <Dialog.Close\n render={(props) => (\n <Button variant=\"secondary\" {...props}>\n Cancel\n </Button>\n )}\n />\n <Button variant=\"primary\">Create</Button>\n </div>\n </Dialog>\n </Dialog.Root>",
2456
+ "<Dialog.Root>\n <Dialog.Trigger render={(p) => <Button {...p}>Open Form</Button>} />\n <Dialog className=\"p-8\">\n <div className=\"mb-4 flex items-start justify-between gap-4\">\n <Dialog.Title className=\"text-2xl font-semibold\">\n Create Resource\n </Dialog.Title>\n <Dialog.Close\n aria-label=\"Close\"\n render={(props) => (\n <Button\n {...props}\n variant=\"secondary\"\n shape=\"square\"\n icon={<X />}\n aria-label=\"Close\"\n />\n )}\n />\n </div>\n <Dialog.Description className=\"mb-4 text-kumo-subtle\">\n Search and select a region for your new resource.\n </Dialog.Description>\n <Combobox value={value} onValueChange={setValue} items={regions}>\n <Combobox.TriggerInput\n className=\"w-full\"\n placeholder=\"Search regions...\"\n />\n <Combobox.Content>\n <Combobox.Empty>No regions found</Combobox.Empty>\n <Combobox.List>\n {(item: { value: string; label: string }) => (\n <Combobox.Item key={item.value} value={item}>\n {item.label}\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Content>\n </Combobox>\n <div className=\"mt-8 flex justify-end gap-2\">\n <Dialog.Close\n render={(props) => (\n <Button variant=\"secondary\" {...props}>\n Cancel\n </Button>\n )}\n />\n <Button variant=\"primary\">Create</Button>\n </div>\n </Dialog>\n </Dialog.Root>",
2457
+ "<Dialog.Root>\n <Dialog.Trigger render={(p) => <Button {...p}>Open Form</Button>} />\n <Dialog className=\"p-8\">\n <div className=\"mb-4 flex items-start justify-between gap-4\">\n <Dialog.Title className=\"text-2xl font-semibold\">\n Resource Actions\n </Dialog.Title>\n <Dialog.Close\n aria-label=\"Close\"\n render={(props) => (\n <Button\n {...props}\n variant=\"secondary\"\n shape=\"square\"\n icon={<X />}\n aria-label=\"Close\"\n />\n )}\n />\n </div>\n <Dialog.Description className=\"mb-4 text-kumo-subtle\">\n Choose an action for the selected resource.\n </Dialog.Description>\n <DropdownMenu>\n <DropdownMenu.Trigger render={<Button>Actions</Button>} />\n <DropdownMenu.Content>\n <DropdownMenu.Item>Edit</DropdownMenu.Item>\n <DropdownMenu.Item>Duplicate</DropdownMenu.Item>\n <DropdownMenu.Separator />\n <DropdownMenu.Item variant=\"danger\">Delete</DropdownMenu.Item>\n </DropdownMenu.Content>\n </DropdownMenu>\n <div className=\"mt-8 flex justify-end\">\n <Dialog.Close\n render={(props) => (\n <Button variant=\"secondary\" {...props}>\n Close\n </Button>\n )}\n />\n </div>\n </Dialog>\n </Dialog.Root>"
2412
2458
  ],
2413
2459
  "colors": [
2414
2460
  "bg-kumo-base",
@@ -4859,6 +4905,7 @@
4859
4905
  ],
4860
4906
  "Other": [
4861
4907
  "CloudflareLogo",
4908
+ "DatePicker",
4862
4909
  "Label",
4863
4910
  "Link",
4864
4911
  "SensitiveInput",
@@ -4896,6 +4943,7 @@
4896
4943
  "Collapsible",
4897
4944
  "Combobox",
4898
4945
  "CommandPalette",
4946
+ "DatePicker",
4899
4947
  "DateRangePicker",
4900
4948
  "DeleteResource",
4901
4949
  "Dialog",
@@ -4938,6 +4986,7 @@
4938
4986
  "Collapsible",
4939
4987
  "Combobox",
4940
4988
  "CommandPalette",
4989
+ "DatePicker",
4941
4990
  "DateRangePicker",
4942
4991
  "Dialog",
4943
4992
  "DropdownMenu",
@@ -512,10 +512,14 @@ Read-only text field with a one-click copy-to-clipboard button.
512
512
  The text to display and copy to clipboard.
513
513
  - `className`: string
514
514
  Additional CSS classes merged via `cn()`.
515
+ - `tooltip`: object
516
+ Tooltip config. Shows tooltip on hover, anchored toast on click.
517
+ - `labels`: object
518
+ Accessible labels for i18n.
515
519
 
516
520
  **Colors (kumo tokens used):**
517
521
 
518
- `bg-kumo-base`, `border-kumo-line`
522
+ `bg-kumo-base`, `border-kumo-line`, `outline-kumo-fill`, `text-kumo-default`
519
523
 
520
524
  **Styling:**
521
525
 
@@ -569,6 +573,13 @@ Read-only text field with a one-click copy-to-clipboard button.
569
573
  <ClipboardText text="0c239dd2" />
570
574
  ```
571
575
 
576
+ ```tsx
577
+ <ClipboardText
578
+ text="npx kumo add button"
579
+ tooltip={{ text: "Copy", copiedText: "Copied!", side: "top" }}
580
+ />
581
+ ```
582
+
572
583
 
573
584
  ---
574
585
 
@@ -1639,6 +1650,180 @@ CommandPalette — accessible command palette / spotlight search overlay. Compo
1639
1650
  ```
1640
1651
 
1641
1652
 
1653
+ ---
1654
+
1655
+ ### DatePicker
1656
+
1657
+ DatePicker — a date selection calendar. Built on [react-day-picker](https://daypicker.dev) with Kumo styling. Supports three selection modes: single, multiple, and range.
1658
+
1659
+ **Type:** component
1660
+
1661
+ **Import:** `import { DatePicker } from "@cloudflare/kumo";`
1662
+
1663
+ **Category:** Other
1664
+
1665
+ **Props:**
1666
+
1667
+ - `className`: string
1668
+ Additional CSS classes
1669
+ - `children`: ReactNode
1670
+ Child elements
1671
+
1672
+ **Colors (kumo tokens used):**
1673
+
1674
+ `bg-kumo-base`
1675
+
1676
+ **Examples:**
1677
+
1678
+ ```tsx
1679
+ <div className="flex flex-col gap-4">
1680
+ <DatePicker mode="single" selected={date} onChange={d => {
1681
+ if (d) {
1682
+ setDate(d);
1683
+ }
1684
+ }} />
1685
+ <p className="text-sm text-kumo-subtle">
1686
+ Selected: {date ? date.toLocaleDateString() : "None"}
1687
+ </p>
1688
+ </div>
1689
+ ```
1690
+
1691
+ ```tsx
1692
+ <div className="flex flex-col gap-4">
1693
+ <DatePicker
1694
+ mode="multiple"
1695
+ selected={dates}
1696
+ onChange={setDates}
1697
+ max={5}
1698
+ />
1699
+ <p className="text-sm text-kumo-subtle">
1700
+ Selected: {dates?.length ?? 0} date(s)
1701
+ </p>
1702
+ </div>
1703
+ ```
1704
+
1705
+ ```tsx
1706
+ <div className="flex flex-col gap-4">
1707
+ <DatePicker
1708
+ mode="range"
1709
+ selected={range}
1710
+ onChange={setRange}
1711
+ numberOfMonths={2}
1712
+ />
1713
+ <p className="text-sm text-kumo-subtle">
1714
+ Range:{" "}
1715
+ {range?.from
1716
+ ? `${range.from.toLocaleDateString()} - ${range.to?.toLocaleDateString() ?? "..."}`
1717
+ : "None"}
1718
+ </p>
1719
+ </div>
1720
+ ```
1721
+
1722
+ ```tsx
1723
+ <div className="flex flex-col gap-4">
1724
+ <DatePicker
1725
+ mode="range"
1726
+ selected={range}
1727
+ onChange={setRange}
1728
+ min={3}
1729
+ max={7}
1730
+ footer={
1731
+ <span className="text-xs text-kumo-subtle">Select 3-7 nights</span>
1732
+ }
1733
+ />
1734
+ </div>
1735
+ ```
1736
+
1737
+ ```tsx
1738
+ <Popover>
1739
+ <Popover.Trigger asChild>
1740
+ <Button variant="outline" icon={CalendarDotsIcon}>
1741
+ {date ? date.toLocaleDateString() : "Pick a date"}
1742
+ </Button>
1743
+ </Popover.Trigger>
1744
+ <Popover.Content className="p-3">
1745
+ <DatePicker mode="single" selected={date} onChange={setDate} />
1746
+ </Popover.Content>
1747
+ </Popover>
1748
+ ```
1749
+
1750
+ ```tsx
1751
+ <Popover>
1752
+ <Popover.Trigger asChild>
1753
+ <Button variant="outline" icon={CalendarDotsIcon}>
1754
+ {formatRange()}
1755
+ </Button>
1756
+ </Popover.Trigger>
1757
+ <Popover.Content className="p-3">
1758
+ <DatePicker
1759
+ mode="range"
1760
+ selected={range}
1761
+ onChange={setRange}
1762
+ numberOfMonths={2}
1763
+ />
1764
+ </Popover.Content>
1765
+ </Popover>
1766
+ ```
1767
+
1768
+ ```tsx
1769
+ <Popover>
1770
+ <Popover.Trigger asChild>
1771
+ <Button variant="outline" icon={CalendarDotsIcon}>
1772
+ {formatRange()}
1773
+ </Button>
1774
+ </Popover.Trigger>
1775
+ <Popover.Content className="p-0">
1776
+ <div className="flex">
1777
+ <div className="flex flex-col gap-1 border-r border-kumo-line p-2 text-sm">
1778
+ {presets.map((preset) => {
1779
+ const isActive = isPresetActive(preset);
1780
+ return (
1781
+ <button
1782
+ key={preset.label}
1783
+ type="button"
1784
+ onClick={() => handlePresetClick(preset)}
1785
+ className={`rounded-md px-3 py-1.5 text-left whitespace-nowrap ${isActive
1786
+ ? "bg-kumo-bg-inverse text-kumo-text-inverse"
1787
+ : "text-kumo-strong hover:bg-kumo-control"
1788
+ }`}
1789
+ >
1790
+ {preset.label}
1791
+ </button>
1792
+ );
1793
+ })}
1794
+ </div>
1795
+ <div className="p-3">
1796
+ <DatePicker
1797
+ mode="range"
1798
+ selected={range}
1799
+ onChange={setRange}
1800
+ month={month}
1801
+ onMonthChange={setMonth}
1802
+ numberOfMonths={2}
1803
+ />
1804
+ </div>
1805
+ </div>
1806
+ </Popover.Content>
1807
+ </Popover>
1808
+ ```
1809
+
1810
+ ```tsx
1811
+ <DatePicker
1812
+ mode="multiple"
1813
+ selected={dates}
1814
+ onChange={setDates}
1815
+ max={maxDays}
1816
+ disabled={unavailableDates}
1817
+ fixedWeeks
1818
+ footer={
1819
+ <p className="text-xs text-kumo-subtle pt-2 w-full">
1820
+ {selectedCount}/{maxDays} days selected. Grayed dates are unavailable.
1821
+ </p>
1822
+ }
1823
+ />
1824
+ ```
1825
+
1826
+
1642
1827
  ---
1643
1828
 
1644
1829
  ### DateRangePicker
@@ -1970,6 +2155,110 @@ Close sub-component
1970
2155
  </Dialog.Root>
1971
2156
  ```
1972
2157
 
2158
+ ```tsx
2159
+ <Dialog.Root>
2160
+ <Dialog.Trigger render={(p) => <Button {...p}>Open Form</Button>} />
2161
+ <Dialog className="p-8">
2162
+ <div className="mb-4 flex items-start justify-between gap-4">
2163
+ <Dialog.Title className="text-2xl font-semibold">
2164
+ Create Resource
2165
+ </Dialog.Title>
2166
+ <Dialog.Close
2167
+ aria-label="Close"
2168
+ render={(props) => (
2169
+ <Button
2170
+ {...props}
2171
+ variant="secondary"
2172
+ shape="square"
2173
+ icon={<X />}
2174
+ aria-label="Close"
2175
+ />
2176
+ )}
2177
+ />
2178
+ </div>
2179
+ <Dialog.Description className="mb-4 text-kumo-subtle">
2180
+ Select a region for your new resource.
2181
+ </Dialog.Description>
2182
+ <Select
2183
+ className="w-full"
2184
+ renderValue={(v) =>
2185
+ regions.find((r) => r.value === v)?.label ?? "Select region..."
2186
+ }
2187
+ >
2188
+ {regions.map((region) => (
2189
+ <Select.Option key={region.value} value={region.value}>
2190
+ {region.label}
2191
+ </Select.Option>
2192
+ ))}
2193
+ </Select>
2194
+ <div className="mt-8 flex justify-end gap-2">
2195
+ <Dialog.Close
2196
+ render={(props) => (
2197
+ <Button variant="secondary" {...props}>
2198
+ Cancel
2199
+ </Button>
2200
+ )}
2201
+ />
2202
+ <Button variant="primary">Create</Button>
2203
+ </div>
2204
+ </Dialog>
2205
+ </Dialog.Root>
2206
+ ```
2207
+
2208
+ ```tsx
2209
+ <Dialog.Root>
2210
+ <Dialog.Trigger render={(p) => <Button {...p}>Open Form</Button>} />
2211
+ <Dialog className="p-8">
2212
+ <div className="mb-4 flex items-start justify-between gap-4">
2213
+ <Dialog.Title className="text-2xl font-semibold">
2214
+ Create Resource
2215
+ </Dialog.Title>
2216
+ <Dialog.Close
2217
+ aria-label="Close"
2218
+ render={(props) => (
2219
+ <Button
2220
+ {...props}
2221
+ variant="secondary"
2222
+ shape="square"
2223
+ icon={<X />}
2224
+ aria-label="Close"
2225
+ />
2226
+ )}
2227
+ />
2228
+ </div>
2229
+ <Dialog.Description className="mb-4 text-kumo-subtle">
2230
+ Search and select a region for your new resource.
2231
+ </Dialog.Description>
2232
+ <Combobox value={value} onValueChange={setValue} items={regions}>
2233
+ <Combobox.TriggerInput
2234
+ className="w-full"
2235
+ placeholder="Search regions..."
2236
+ />
2237
+ <Combobox.Content>
2238
+ <Combobox.Empty>No regions found</Combobox.Empty>
2239
+ <Combobox.List>
2240
+ {(item: { value: string; label: string }) => (
2241
+ <Combobox.Item key={item.value} value={item}>
2242
+ {item.label}
2243
+ </Combobox.Item>
2244
+ )}
2245
+ </Combobox.List>
2246
+ </Combobox.Content>
2247
+ </Combobox>
2248
+ <div className="mt-8 flex justify-end gap-2">
2249
+ <Dialog.Close
2250
+ render={(props) => (
2251
+ <Button variant="secondary" {...props}>
2252
+ Cancel
2253
+ </Button>
2254
+ )}
2255
+ />
2256
+ <Button variant="primary">Create</Button>
2257
+ </div>
2258
+ </Dialog>
2259
+ </Dialog.Root>
2260
+ ```
2261
+
1973
2262
 
1974
2263
  ---
1975
2264
 
@@ -4534,7 +4823,7 @@ Multi-line textarea input with Input variants and InputArea-specific dimensions
4534
4823
  - **Feedback:** Banner, Loader, Toasty
4535
4824
  - **Action:** Button, ClipboardText
4536
4825
  - **Input:** Checkbox, Combobox, DateRangePicker, Field, Input, Radio, Select, Switch
4537
- - **Other:** CloudflareLogo, Label, Link, SensitiveInput, Table, DeleteResource
4826
+ - **Other:** CloudflareLogo, DatePicker, Label, Link, SensitiveInput, Table, DeleteResource
4538
4827
  - **Navigation:** CommandPalette, MenuBar, Pagination, Tabs
4539
4828
  - **Overlay:** Dialog, DropdownMenu, Popover, Tooltip
4540
4829
  - **Layout:** Grid, Surface, PageHeader, ResourceListPage
package/ai/schemas.ts CHANGED
@@ -165,6 +165,8 @@ export const ClipboardTextPropsSchema = z.object({
165
165
  size: z.enum(["sm", "base", "lg"]).optional(), // Size of the clipboard text field. - `"sm"` — Small clipboard text for compact UIs - `"base"` — Default clipboard text size - `"lg"` — Large clipboard text for prominent display
166
166
  text: z.string(), // The text to display and copy to clipboard.
167
167
  className: z.string().optional(), // Additional CSS classes merged via `cn()`.
168
+ tooltip: z.unknown().optional(), // Tooltip config. Shows tooltip on hover, anchored toast on click.
169
+ labels: z.unknown().optional(), // Accessible labels for i18n.
168
170
  });
169
171
 
170
172
  export const CloudflareLogoPropsSchema = z.object({
@@ -460,6 +462,11 @@ export const CommandPalettePropsSchema = z.object({
460
462
  children: z.union([z.string(), z.number(), z.boolean(), z.null(), DynamicValueSchema]).optional(), // Child content - typically one or more Panel components
461
463
  });
462
464
 
465
+ export const DatePickerPropsSchema = z.object({
466
+ className: z.string().optional(), // Additional CSS classes
467
+ children: z.union([z.string(), z.number(), z.boolean(), z.null(), DynamicValueSchema]).optional(), // Child elements
468
+ });
469
+
463
470
  export const DateRangePickerPropsSchema = z.object({
464
471
  size: z.enum(["sm", "base", "lg"]).optional(), // Calendar size. - `"sm"` — Compact calendar for tight spaces - `"base"` — Default calendar size - `"lg"` — Large calendar for prominent date selection
465
472
  variant: z.enum(["default", "subtle"]).optional(), // Visual variant. - `"default"` — Standard appearance with overlay background - `"subtle"` — Minimal background
@@ -720,7 +727,7 @@ export const TooltipPropsSchema = z.object({
720
727
  /**
721
728
  * All valid component type names
722
729
  */
723
- export type KumoComponentType = "Badge" | "Banner" | "Breadcrumbs" | "Button" | "Checkbox" | "ClipboardText" | "CloudflareLogo" | "Code" | "Collapsible" | "Combobox" | "CommandPalette" | "DateRangePicker" | "Dialog" | "DropdownMenu" | "Empty" | "Field" | "Grid" | "Input" | "InputArea" | "Label" | "LayerCard" | "Link" | "Loader" | "MenuBar" | "Meter" | "Pagination" | "Popover" | "Radio" | "Select" | "SensitiveInput" | "Surface" | "Switch" | "Table" | "Tabs" | "Text" | "Toasty" | "Tooltip";
730
+ export type KumoComponentType = "Badge" | "Banner" | "Breadcrumbs" | "Button" | "Checkbox" | "ClipboardText" | "CloudflareLogo" | "Code" | "Collapsible" | "Combobox" | "CommandPalette" | "DatePicker" | "DateRangePicker" | "Dialog" | "DropdownMenu" | "Empty" | "Field" | "Grid" | "Input" | "InputArea" | "Label" | "LayerCard" | "Link" | "Loader" | "MenuBar" | "Meter" | "Pagination" | "Popover" | "Radio" | "Select" | "SensitiveInput" | "Surface" | "Switch" | "Table" | "Tabs" | "Text" | "Toasty" | "Tooltip";
724
731
 
725
732
  export const KumoComponentTypeSchema = z.enum([
726
733
  "Badge",
@@ -734,6 +741,7 @@ export const KumoComponentTypeSchema = z.enum([
734
741
  "Collapsible",
735
742
  "Combobox",
736
743
  "CommandPalette",
744
+ "DatePicker",
737
745
  "DateRangePicker",
738
746
  "Dialog",
739
747
  "DropdownMenu",
@@ -777,6 +785,7 @@ export const ComponentPropsSchemas = {
777
785
  Collapsible: CollapsiblePropsSchema,
778
786
  Combobox: ComboboxPropsSchema,
779
787
  CommandPalette: CommandPalettePropsSchema,
788
+ DatePicker: DatePickerPropsSchema,
780
789
  DateRangePicker: DateRangePickerPropsSchema,
781
790
  Dialog: DialogPropsSchema,
782
791
  DropdownMenu: DropdownMenuPropsSchema,
@@ -859,4 +868,4 @@ export function validateUITree(tree: unknown): SafeParseResult<UITree> {
859
868
  /**
860
869
  * List of all component names (for catalog generation)
861
870
  */
862
- export const KUMO_COMPONENT_NAMES = ["Badge", "Banner", "Breadcrumbs", "Button", "Checkbox", "ClipboardText", "CloudflareLogo", "Code", "Collapsible", "Combobox", "CommandPalette", "DateRangePicker", "Dialog", "DropdownMenu", "Empty", "Field", "Grid", "Input", "InputArea", "Label", "LayerCard", "Link", "Loader", "MenuBar", "Meter", "Pagination", "Popover", "Radio", "Select", "SensitiveInput", "Surface", "Switch", "Table", "Tabs", "Text", "Toasty", "Tooltip"] as const;
871
+ export const KUMO_COMPONENT_NAMES = ["Badge", "Banner", "Breadcrumbs", "Button", "Checkbox", "ClipboardText", "CloudflareLogo", "Code", "Collapsible", "Combobox", "CommandPalette", "DatePicker", "DateRangePicker", "Dialog", "DropdownMenu", "Empty", "Field", "Grid", "Input", "InputArea", "Label", "LayerCard", "Link", "Loader", "MenuBar", "Meter", "Pagination", "Popover", "Radio", "Select", "SensitiveInput", "Surface", "Switch", "Table", "Tabs", "Text", "Toasty", "Tooltip"] as const;
@@ -1 +1 @@
1
- 1771248145491
1
+ 1771426000663