@ceed/ads 1.35.0 → 1.36.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 (124) hide show
  1. package/README.md +85 -95
  2. package/dist/components/Accordions/Accordions.d.ts +1 -0
  3. package/dist/components/Alert/Alert.d.ts +5 -5
  4. package/dist/components/Autocomplete/Autocomplete.d.ts +2 -2
  5. package/dist/components/Avatar/Avatar.d.ts +7 -17
  6. package/dist/components/Box/Box.d.ts +1 -0
  7. package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +6 -5
  8. package/dist/components/Button/Button.d.ts +3 -2
  9. package/dist/components/Calendar/Calendar.d.ts +1 -0
  10. package/dist/components/Card/Card.d.ts +1 -0
  11. package/dist/components/Checkbox/Checkbox.d.ts +1 -0
  12. package/dist/components/Chip/Chip.d.ts +1 -0
  13. package/dist/components/Container/Container.d.ts +6 -1
  14. package/dist/components/DialogActions/DialogActions.d.ts +1 -0
  15. package/dist/components/DialogContent/DialogContent.d.ts +1 -0
  16. package/dist/components/DialogFrame/DialogFrame.d.ts +1 -1
  17. package/dist/components/DialogTitle/DialogTitle.d.ts +1 -0
  18. package/dist/components/Divider/Divider.d.ts +1 -0
  19. package/dist/components/Dropdown/Dropdown.d.ts +28 -1
  20. package/dist/components/FilterMenu/components/MonthRange.d.ts +11 -0
  21. package/dist/components/FilterMenu/types.d.ts +5 -1
  22. package/dist/components/FormControl/FormControl.d.ts +1 -0
  23. package/dist/components/FormHelperText/FormHelperText.d.ts +1 -0
  24. package/dist/components/FormLabel/FormLabel.d.ts +1 -0
  25. package/dist/components/Grid/Grid.d.ts +1 -0
  26. package/dist/components/IconButton/IconButton.d.ts +3 -2
  27. package/dist/components/IconMenuButton/IconMenuButton.d.ts +7 -6
  28. package/dist/components/InfoSign/InfoSign.d.ts +3 -2
  29. package/dist/components/Input/Input.d.ts +8 -22
  30. package/dist/components/InsetDrawer/InsetDrawer.d.ts +1 -0
  31. package/dist/components/Markdown/Markdown.d.ts +9 -24
  32. package/dist/components/Menu/Menu.d.ts +2 -1
  33. package/dist/components/MenuButton/MenuButton.d.ts +10 -8
  34. package/dist/components/Modal/Modal.d.ts +4 -2
  35. package/dist/components/NavigationGroup/NavigationGroup.d.ts +3 -2
  36. package/dist/components/NavigationItem/NavigationItem.d.ts +3 -2
  37. package/dist/components/Navigator/Navigator.d.ts +5 -4
  38. package/dist/components/Pagination/Pagination.d.ts +1 -1
  39. package/dist/components/ProfileMenu/ProfileMenu.d.ts +2 -2
  40. package/dist/components/Radio/Radio.d.ts +1 -0
  41. package/dist/components/RadioList/RadioList.d.ts +3 -2
  42. package/dist/components/SearchBar/SearchBar.d.ts +6 -5
  43. package/dist/components/SearchBar/index.d.ts +3 -2
  44. package/dist/components/Select/Select.d.ts +12 -10
  45. package/dist/components/Sheet/Sheet.d.ts +1 -0
  46. package/dist/components/Stack/Stack.d.ts +1 -0
  47. package/dist/components/Stepper/Stepper.d.ts +2 -1
  48. package/dist/components/Switch/Switch.d.ts +1 -0
  49. package/dist/components/Table/Table.d.ts +7 -5
  50. package/dist/components/Tabs/Tabs.d.ts +1 -0
  51. package/dist/components/Textarea/Textarea.d.ts +8 -20
  52. package/dist/components/ThemeProvider/ThemeProvider.d.ts +4 -2
  53. package/dist/components/Tooltip/Tooltip.d.ts +1 -0
  54. package/dist/components/Typography/Typography.d.ts +1 -0
  55. package/dist/components/Uploader/Uploader.d.ts +18 -17
  56. package/dist/components/data-display/Avatar.md +60 -72
  57. package/dist/components/data-display/Badge.md +197 -181
  58. package/dist/components/data-display/Chip.md +164 -142
  59. package/dist/components/data-display/DataTable.md +843 -338
  60. package/dist/components/data-display/InfoSign.md +1 -3
  61. package/dist/components/data-display/Markdown.md +93 -125
  62. package/dist/components/data-display/Table.md +1453 -1007
  63. package/dist/components/data-display/Typography.md +101 -104
  64. package/dist/components/feedback/Alert.md +80 -86
  65. package/dist/components/feedback/CircularProgress.md +32 -36
  66. package/dist/components/feedback/Dialog.md +25 -17
  67. package/dist/components/feedback/Modal.md +296 -265
  68. package/dist/components/feedback/Skeleton.md +125 -89
  69. package/dist/components/index.d.ts +61 -3
  70. package/dist/components/inputs/Autocomplete.md +191 -95
  71. package/dist/components/inputs/Button.md +83 -83
  72. package/dist/components/inputs/ButtonGroup.md +195 -185
  73. package/dist/components/inputs/Calendar.md +25 -28
  74. package/dist/components/inputs/Checkbox.md +11 -29
  75. package/dist/components/inputs/CurrencyInput.md +4 -4
  76. package/dist/components/inputs/DatePicker.md +229 -110
  77. package/dist/components/inputs/DateRangePicker.md +248 -137
  78. package/dist/components/inputs/FilterMenu.md +138 -8
  79. package/dist/components/inputs/FilterableCheckboxGroup.md +115 -55
  80. package/dist/components/inputs/FormControl.md +75 -69
  81. package/dist/components/inputs/IconButton.md +229 -205
  82. package/dist/components/inputs/Input.md +131 -98
  83. package/dist/components/inputs/MonthPicker.md +186 -84
  84. package/dist/components/inputs/MonthRangePicker.md +73 -49
  85. package/dist/components/inputs/PercentageInput.md +15 -31
  86. package/dist/components/inputs/RadioButton.md +320 -256
  87. package/dist/components/inputs/RadioList.md +66 -50
  88. package/dist/components/inputs/RadioTileGroup.md +287 -170
  89. package/dist/components/inputs/SearchBar.md +154 -55
  90. package/dist/components/inputs/Select.md +106 -95
  91. package/dist/components/inputs/Slider.md +153 -102
  92. package/dist/components/inputs/Switch.md +193 -138
  93. package/dist/components/inputs/Textarea.md +15 -20
  94. package/dist/components/inputs/Uploader/Uploader.md +68 -39
  95. package/dist/components/layout/Box.md +841 -662
  96. package/dist/components/layout/Container.md +3 -11
  97. package/dist/components/layout/Grid.md +480 -394
  98. package/dist/components/layout/Stack.md +739 -566
  99. package/dist/components/navigation/Breadcrumbs.md +182 -116
  100. package/dist/components/navigation/Dropdown.md +732 -391
  101. package/dist/components/navigation/IconMenuButton.md +14 -6
  102. package/dist/components/navigation/InsetDrawer.md +550 -378
  103. package/dist/components/navigation/Link.md +104 -94
  104. package/dist/components/navigation/Menu.md +623 -502
  105. package/dist/components/navigation/MenuButton.md +18 -10
  106. package/dist/components/navigation/NavigationGroup.md +19 -50
  107. package/dist/components/navigation/NavigationItem.md +6 -6
  108. package/dist/components/navigation/Navigator.md +26 -28
  109. package/dist/components/navigation/Pagination.md +86 -75
  110. package/dist/components/navigation/ProfileMenu.md +65 -43
  111. package/dist/components/navigation/Stepper.md +2 -12
  112. package/dist/components/navigation/Tabs.md +209 -183
  113. package/dist/components/surfaces/Accordions.md +89 -172
  114. package/dist/components/surfaces/Card.md +1094 -709
  115. package/dist/components/surfaces/Divider.md +562 -412
  116. package/dist/components/surfaces/Sheet.md +700 -518
  117. package/dist/guides/ThemeProvider.md +65 -40
  118. package/dist/index.browser.js +4 -4
  119. package/dist/index.browser.js.map +4 -4
  120. package/dist/index.cjs +1653 -1560
  121. package/dist/index.d.ts +1 -1
  122. package/dist/index.js +1316 -1215
  123. package/framer/index.js +1 -1
  124. package/package.json +32 -35
@@ -56,13 +56,7 @@ import { DateRangePicker } from '@ceed/ads';
56
56
  function DateRangeForm() {
57
57
  const [dateRange, setDateRange] = useState('');
58
58
 
59
- return (
60
- <DateRangePicker
61
- label="Select Date Range"
62
- value={dateRange}
63
- onChange={(e) => setDateRange(e.target.value)}
64
- />
65
- );
59
+ return <DateRangePicker label="Select Date Range" value={dateRange} onChange={(e) => setDateRange(e.target.value)} />;
66
60
  }
67
61
  ```
68
62
 
@@ -72,10 +66,10 @@ DateRangePicker supports three sizes (`sm`, `md`, `lg`) to fit different layouts
72
66
 
73
67
  ```tsx
74
68
  <Stack gap={2}>
75
- <DateRangePicker size="sm" />
76
- <DateRangePicker size="md" />
77
- <DateRangePicker size="lg" />
78
- </Stack>
69
+ <DateRangePicker size="sm" />
70
+ <DateRangePicker size="md" />
71
+ <DateRangePicker size="lg" />
72
+ </Stack>
79
73
  ```
80
74
 
81
75
  ## Form Features
@@ -183,25 +177,31 @@ In controlled mode, the parent component manages the date range state via `value
183
177
 
184
178
  ```tsx
185
179
  <Stack gap={2}>
186
- <DateRangePicker {...args} onChange={e => {
187
- args.onChange?.(e);
188
- setValue(e.target.value);
189
- }} value={value} />
190
- <Button onClick={() => {
191
- const [start, end] = value.split(' - ');
192
- function shiftMonth(dateString: string) {
193
- const currentValue = new Date(dateString);
194
- currentValue.setMonth(currentValue.getMonth() + 1);
195
- const year = currentValue.getFullYear();
196
- const month = String(currentValue.getMonth() + 1).padStart(2, '0');
197
- const day = String(currentValue.getDate()).padStart(2, '0');
198
- return `${year}/${month}/${day}`;
199
- }
200
- setValue(`${shiftMonth(start)} - ${shiftMonth(end)}`);
201
- }}>
202
- Shift Month
203
- </Button>
204
- </Stack>
180
+ <DateRangePicker
181
+ {...args}
182
+ onChange={(e) => {
183
+ args.onChange?.(e);
184
+ setValue(e.target.value);
185
+ }}
186
+ value={value}
187
+ />
188
+ <Button
189
+ onClick={() => {
190
+ const [start, end] = value.split(" - ");
191
+ function shiftMonth(dateString: string) {
192
+ const currentValue = new Date(dateString);
193
+ currentValue.setMonth(currentValue.getMonth() + 1);
194
+ const year = currentValue.getFullYear();
195
+ const month = String(currentValue.getMonth() + 1).padStart(2, "0");
196
+ const day = String(currentValue.getDate()).padStart(2, "0");
197
+ return `${year}/${month}/${day}`;
198
+ }
199
+ setValue(`${shiftMonth(start)} - ${shiftMonth(end)}`);
200
+ }}
201
+ >
202
+ Shift Month
203
+ </Button>
204
+ </Stack>
205
205
  ```
206
206
 
207
207
  ### Uncontrolled
@@ -225,31 +225,73 @@ The `format` prop controls the format of the value returned in `onChange`. The i
225
225
 
226
226
  ```tsx
227
227
  <Stack gap={2}>
228
- <DateRangePicker {...args} value={value1} label="YYYY.MM.DD" name="YYYY.MM.DD" format="YYYY.MM.DD" onChange={e => {
229
- setValue1(e.target.value);
230
- args.onChange?.(e);
231
- }} />
232
- <DateRangePicker {...args} value={value2} label="YYYY/MM/DD" name="YYYY/MM/DD" format="YYYY/MM/DD" onChange={e => {
233
- setValue2(e.target.value);
234
- args.onChange?.(e);
235
- }} />
236
- <DateRangePicker {...args} value={value3} label="MM/DD/YYYY" name="MM/DD/YYYY" format="MM/DD/YYYY" onChange={e => {
237
- setValue3(e.target.value);
238
- args.onChange?.(e);
239
- }} />
240
- <DateRangePicker {...args} value={value4} label="YYYY-MM-DD" name="YYYY-MM-DD" format="YYYY-MM-DD" onChange={e => {
241
- setValue4(e.target.value);
242
- args.onChange?.(e);
243
- }} />
244
- <DateRangePicker {...args} value={value5} label="DD/MM/YYYY" name="DD/MM/YYYY" format="DD/MM/YYYY" onChange={e => {
245
- setValue5(e.target.value);
246
- args.onChange?.(e);
247
- }} />
248
- <DateRangePicker {...args} value={value6} label="DD.MM.YYYY" name="DD.MM.YYYY" format="DD.MM.YYYY" onChange={e => {
249
- setValue6(e.target.value);
250
- args.onChange?.(e);
251
- }} />
252
- </Stack>
228
+ <DateRangePicker
229
+ {...args}
230
+ value={value1}
231
+ label="YYYY.MM.DD"
232
+ name="YYYY.MM.DD"
233
+ format="YYYY.MM.DD"
234
+ onChange={(e) => {
235
+ setValue1(e.target.value);
236
+ args.onChange?.(e);
237
+ }}
238
+ />
239
+ <DateRangePicker
240
+ {...args}
241
+ value={value2}
242
+ label="YYYY/MM/DD"
243
+ name="YYYY/MM/DD"
244
+ format="YYYY/MM/DD"
245
+ onChange={(e) => {
246
+ setValue2(e.target.value);
247
+ args.onChange?.(e);
248
+ }}
249
+ />
250
+ <DateRangePicker
251
+ {...args}
252
+ value={value3}
253
+ label="MM/DD/YYYY"
254
+ name="MM/DD/YYYY"
255
+ format="MM/DD/YYYY"
256
+ onChange={(e) => {
257
+ setValue3(e.target.value);
258
+ args.onChange?.(e);
259
+ }}
260
+ />
261
+ <DateRangePicker
262
+ {...args}
263
+ value={value4}
264
+ label="YYYY-MM-DD"
265
+ name="YYYY-MM-DD"
266
+ format="YYYY-MM-DD"
267
+ onChange={(e) => {
268
+ setValue4(e.target.value);
269
+ args.onChange?.(e);
270
+ }}
271
+ />
272
+ <DateRangePicker
273
+ {...args}
274
+ value={value5}
275
+ label="DD/MM/YYYY"
276
+ name="DD/MM/YYYY"
277
+ format="DD/MM/YYYY"
278
+ onChange={(e) => {
279
+ setValue5(e.target.value);
280
+ args.onChange?.(e);
281
+ }}
282
+ />
283
+ <DateRangePicker
284
+ {...args}
285
+ value={value6}
286
+ label="DD.MM.YYYY"
287
+ name="DD.MM.YYYY"
288
+ format="DD.MM.YYYY"
289
+ onChange={(e) => {
290
+ setValue6(e.target.value);
291
+ args.onChange?.(e);
292
+ }}
293
+ />
294
+ </Stack>
253
295
  ```
254
296
 
255
297
  ### Display Format (`displayFormat`)
@@ -258,31 +300,73 @@ The `displayFormat` prop controls what the user sees in the input field. This is
258
300
 
259
301
  ```tsx
260
302
  <Stack gap={2}>
261
- <DateRangePicker {...args} value={value1} label="YYYY.MM.DD" name="YYYY.MM.DD" displayFormat="YYYY.MM.DD" onChange={e => {
262
- setValue1(e.target.value);
263
- args.onChange?.(e);
264
- }} />
265
- <DateRangePicker {...args} value={value2} label="YYYY/MM/DD" name="YYYY/MM/DD" displayFormat="YYYY/MM/DD" onChange={e => {
266
- setValue2(e.target.value);
267
- args.onChange?.(e);
268
- }} />
269
- <DateRangePicker {...args} value={value3} label="MM/DD/YYYY" name="MM/DD/YYYY" displayFormat="MM/DD/YYYY" onChange={e => {
270
- setValue3(e.target.value);
271
- args.onChange?.(e);
272
- }} />
273
- <DateRangePicker {...args} value={value4} label="YYYY-MM-DD" name="YYYY-MM-DD" displayFormat="YYYY-MM-DD" onChange={e => {
274
- setValue4(e.target.value);
275
- args.onChange?.(e);
276
- }} />
277
- <DateRangePicker {...args} value={value5} label="DD/MM/YYYY" name="DD/MM/YYYY" displayFormat="DD/MM/YYYY" onChange={e => {
278
- setValue5(e.target.value);
279
- args.onChange?.(e);
280
- }} />
281
- <DateRangePicker {...args} value={value6} label="DD.MM.YYYY" name="DD.MM.YYYY" displayFormat="DD.MM.YYYY" onChange={e => {
282
- setValue6(e.target.value);
283
- args.onChange?.(e);
284
- }} />
285
- </Stack>
303
+ <DateRangePicker
304
+ {...args}
305
+ value={value1}
306
+ label="YYYY.MM.DD"
307
+ name="YYYY.MM.DD"
308
+ displayFormat="YYYY.MM.DD"
309
+ onChange={(e) => {
310
+ setValue1(e.target.value);
311
+ args.onChange?.(e);
312
+ }}
313
+ />
314
+ <DateRangePicker
315
+ {...args}
316
+ value={value2}
317
+ label="YYYY/MM/DD"
318
+ name="YYYY/MM/DD"
319
+ displayFormat="YYYY/MM/DD"
320
+ onChange={(e) => {
321
+ setValue2(e.target.value);
322
+ args.onChange?.(e);
323
+ }}
324
+ />
325
+ <DateRangePicker
326
+ {...args}
327
+ value={value3}
328
+ label="MM/DD/YYYY"
329
+ name="MM/DD/YYYY"
330
+ displayFormat="MM/DD/YYYY"
331
+ onChange={(e) => {
332
+ setValue3(e.target.value);
333
+ args.onChange?.(e);
334
+ }}
335
+ />
336
+ <DateRangePicker
337
+ {...args}
338
+ value={value4}
339
+ label="YYYY-MM-DD"
340
+ name="YYYY-MM-DD"
341
+ displayFormat="YYYY-MM-DD"
342
+ onChange={(e) => {
343
+ setValue4(e.target.value);
344
+ args.onChange?.(e);
345
+ }}
346
+ />
347
+ <DateRangePicker
348
+ {...args}
349
+ value={value5}
350
+ label="DD/MM/YYYY"
351
+ name="DD/MM/YYYY"
352
+ displayFormat="DD/MM/YYYY"
353
+ onChange={(e) => {
354
+ setValue5(e.target.value);
355
+ args.onChange?.(e);
356
+ }}
357
+ />
358
+ <DateRangePicker
359
+ {...args}
360
+ value={value6}
361
+ label="DD.MM.YYYY"
362
+ name="DD.MM.YYYY"
363
+ displayFormat="DD.MM.YYYY"
364
+ onChange={(e) => {
365
+ setValue6(e.target.value);
366
+ args.onChange?.(e);
367
+ }}
368
+ />
369
+ </Stack>
286
370
  ```
287
371
 
288
372
  **Supported format tokens:**
@@ -296,8 +380,8 @@ The `displayFormat` prop controls what the user sees in the input field. This is
296
380
  ```tsx
297
381
  // format affects onChange value; displayFormat affects what users see
298
382
  <DateRangePicker
299
- format="YYYY-MM-DD" // onChange returns "2024-04-01 - 2024-04-15"
300
- displayFormat="MM/DD/YYYY" // Input shows "04/01/2024 - 04/15/2024"
383
+ format="YYYY-MM-DD" // onChange returns "2024-04-01 - 2024-04-15"
384
+ displayFormat="MM/DD/YYYY" // Input shows "04/01/2024 - 04/15/2024"
301
385
  />
302
386
  ```
303
387
 
@@ -353,25 +437,37 @@ Use the `numberOfMonths` prop to display two calendar months side by side in the
353
437
  When combined with `presets`, the dual calendar provides a fast, at-a-glance interface for report and analytics date filters.
354
438
 
355
439
  ```tsx
356
- <DateRangePicker {...args} value={value} onChange={e => {
357
- setValue(e.target.value);
358
- args.onChange?.(e);
359
- }} disableFuture presets={[{
360
- label: 'Today',
361
- value: `${fmt(today)} - ${fmt(today)}`
362
- }, {
363
- label: 'Last 7 days',
364
- value: range(7)
365
- }, {
366
- label: 'Last 1 month',
367
- value: range(1, 'months')
368
- }, {
369
- label: 'Last 3 months',
370
- value: range(3, 'months')
371
- }, {
372
- label: 'Last 6 months',
373
- value: range(6, 'months')
374
- }]} />
440
+ <DateRangePicker
441
+ {...args}
442
+ value={value}
443
+ onChange={(e) => {
444
+ setValue(e.target.value);
445
+ args.onChange?.(e);
446
+ }}
447
+ disableFuture
448
+ presets={[
449
+ {
450
+ label: "Today",
451
+ value: `${fmt(today)} - ${fmt(today)}`
452
+ },
453
+ {
454
+ label: "Last 7 days",
455
+ value: range(7)
456
+ },
457
+ {
458
+ label: "Last 1 month",
459
+ value: range(1, "months")
460
+ },
461
+ {
462
+ label: "Last 3 months",
463
+ value: range(3, "months")
464
+ },
465
+ {
466
+ label: "Last 6 months",
467
+ value: range(6, "months")
468
+ }
469
+ ]}
470
+ />
375
471
  ```
376
472
 
377
473
  ```tsx
@@ -394,28 +490,40 @@ Use the `presets` prop to display quick-select options alongside the calendar, s
394
490
  Each preset's `value` must match the component's `format` prop and use the `-` separator (e.g., `"2026/03/01 - 2026/04/03"`). When the current value matches a preset, that preset is automatically highlighted -- regardless of whether the value was set via the preset button or by selecting the same range on the calendar.
395
491
 
396
492
  ```tsx
397
- <DateRangePicker {...args} value={value} onChange={e => {
398
- setValue(e.target.value);
399
- args.onChange?.(e);
400
- }} presets={[{
401
- label: 'Today',
402
- value: `${fmt(today)} - ${fmt(today)}`
403
- }, {
404
- label: 'Last 3 days',
405
- value: range(3)
406
- }, {
407
- label: 'Last 7 days',
408
- value: range(7)
409
- }, {
410
- label: 'Last 1 month',
411
- value: range(1, 'months')
412
- }, {
413
- label: 'Last 3 months',
414
- value: range(3, 'months')
415
- }, {
416
- label: 'Last 6 months',
417
- value: range(6, 'months')
418
- }]} />
493
+ <DateRangePicker
494
+ {...args}
495
+ value={value}
496
+ onChange={(e) => {
497
+ setValue(e.target.value);
498
+ args.onChange?.(e);
499
+ }}
500
+ presets={[
501
+ {
502
+ label: "Today",
503
+ value: `${fmt(today)} - ${fmt(today)}`
504
+ },
505
+ {
506
+ label: "Last 3 days",
507
+ value: range(3)
508
+ },
509
+ {
510
+ label: "Last 7 days",
511
+ value: range(7)
512
+ },
513
+ {
514
+ label: "Last 1 month",
515
+ value: range(1, "months")
516
+ },
517
+ {
518
+ label: "Last 3 months",
519
+ value: range(3, "months")
520
+ },
521
+ {
522
+ label: "Last 6 months",
523
+ value: range(6, "months")
524
+ }
525
+ ]}
526
+ />
419
527
  ```
420
528
 
421
529
  ```tsx
@@ -466,15 +574,21 @@ Remove the clear button from the calendar popup using `hideClearButton`.
466
574
  Example of integrating an external reset button to clear the selected date range programmatically.
467
575
 
468
576
  ```tsx
469
- <div style={{
470
- display: 'flex',
471
- gap: '10px'
472
- }}>
473
- <DateRangePicker {...props} value={value} onChange={event => {
474
- setValue(event.target.value);
475
- }} />
476
- <Button onClick={() => setValue('')}>Reset</Button>
477
- </div>
577
+ <div
578
+ style={{
579
+ display: "flex",
580
+ gap: "10px"
581
+ }}
582
+ >
583
+ <DateRangePicker
584
+ {...props}
585
+ value={value}
586
+ onChange={(event) => {
587
+ setValue(event.target.value);
588
+ }}
589
+ />
590
+ <Button onClick={() => setValue("")}>Reset</Button>
591
+ </div>
478
592
  ```
479
593
 
480
594
  ## Booking Form
@@ -575,10 +689,7 @@ function DataExport() {
575
689
 
576
690
  ```tsx
577
691
  // Store ISO format, display locale format
578
- <DateRangePicker
579
- format="YYYY-MM-DD"
580
- displayFormat="MM/DD/YYYY"
581
- />
692
+ <DateRangePicker format="YYYY-MM-DD" displayFormat="MM/DD/YYYY" />
582
693
  ```
583
694
 
584
695
  3. **Use `inputReadOnly` on mobile**: On touch devices, keyboard input for date ranges is error-prone. Use `inputReadOnly` to force calendar selection.
@@ -605,7 +716,7 @@ const getDuration = (value) => {
605
716
  return `${days} day${days !== 1 ? 's' : ''} selected`;
606
717
  };
607
718
 
608
- <DateRangePicker helperText={getDuration(dateRange)} />
719
+ <DateRangePicker helperText={getDuration(dateRange)} />;
609
720
  ```
610
721
 
611
722
  ## Props and Customization
@@ -7,10 +7,14 @@ FilterMenu is a comprehensive filtering component that supports multiple filter
7
7
  FilterMenu is ideal for data-heavy admin interfaces such as tables, lists, and dashboards where users need to narrow down results based on multiple criteria. It supports both controlled and uncontrolled state management, allowing flexible integration with different state architectures.
8
8
 
9
9
  ```tsx
10
- <FilterMenu {...args} defaultValues={values} onChange={newValues => {
11
- setValues(newValues);
12
- args.onChange!(newValues);
13
- }} />
10
+ <FilterMenu
11
+ {...args}
12
+ defaultValues={values}
13
+ onChange={(newValues) => {
14
+ setValues(newValues);
15
+ args.onChange!(newValues);
16
+ }}
17
+ />
14
18
  ```
15
19
 
16
20
  | Field | Description | Default |
@@ -128,6 +132,21 @@ A date range picker filter. The value is stored as a two-element array of date s
128
132
  }
129
133
  ```
130
134
 
135
+ ### Month Range
136
+
137
+ A month range picker filter, built on `MonthRangePicker`. The value is stored as a two-element array of month strings. Both ends follow the `format` you provide (default `YYYY/MM`), so the value tuple format is fully controlled by the consumer.
138
+
139
+ ```tsx
140
+ {
141
+ id: 'monthRange',
142
+ type: 'month-range',
143
+ label: 'Month Range',
144
+ format: 'YYYY-MM',
145
+ displayFormat: 'MMM YYYY',
146
+ }
147
+ // value → ['2025-01', '2025-06']
148
+ ```
149
+
131
150
  ### Currency Input
132
151
 
133
152
  A single currency value input field.
@@ -204,10 +223,14 @@ A searchable single-select filter with autocomplete support.
204
223
  In controlled mode, you manage the filter state externally using `values` (or `defaultValues` with an `onChange` handler).
205
224
 
206
225
  ```tsx
207
- <FilterMenu {...args} defaultValues={values} onChange={newValues => {
208
- setValues(newValues);
209
- args.onChange!(newValues);
210
- }} />
226
+ <FilterMenu
227
+ {...args}
228
+ defaultValues={values}
229
+ onChange={(newValues) => {
230
+ setValues(newValues);
231
+ args.onChange!(newValues);
232
+ }}
233
+ />
211
234
  ```
212
235
 
213
236
  ## Uncontrolled FilterMenu
@@ -218,6 +241,111 @@ In uncontrolled mode, FilterMenu manages its own internal state. This is useful
218
241
  <FilterMenu />
219
242
  ```
220
243
 
244
+ ## Filter Button with Dropdown Trigger
245
+
246
+ In real applications, FilterMenu is opened from a toolbar "Filter" button rather than rendered inline. Compose it with `Dropdown` and `MenuButtonTrigger`: FilterMenu renders with `position: relative` (it is not a centered modal), so it sits naturally inside the dropdown popover. Control the `Dropdown` `open` state so the panel's **Apply** / **Reset** buttons can close the popover through `onClose`.
247
+
248
+ ```tsx
249
+ <Dropdown open={open} onOpenChange={(_event, isOpen) => setOpen(isOpen)}>
250
+ <MenuButtonTrigger
251
+ variant="outlined"
252
+ startDecorator={<FilterListIcon />}
253
+ endDecorator={<ExpandMoreIcon />}
254
+ >
255
+ Filters
256
+ </MenuButtonTrigger>
257
+ <Menu
258
+ placement="bottom-start"
259
+ sx={{
260
+ p: 0,
261
+ border: "none",
262
+ boxShadow: "none",
263
+ bgcolor: "transparent"
264
+ }}
265
+ >
266
+ <FilterMenu
267
+ filters={[
268
+ {
269
+ id: "status",
270
+ type: "checkbox-group",
271
+ label: "Status",
272
+ options: [
273
+ {
274
+ label: "Active",
275
+ value: "active"
276
+ },
277
+ {
278
+ label: "Inactive",
279
+ value: "inactive"
280
+ }
281
+ ]
282
+ },
283
+ {
284
+ id: "priority",
285
+ type: "radio-group",
286
+ label: "Priority",
287
+ options: [
288
+ {
289
+ label: "High",
290
+ value: "high"
291
+ },
292
+ {
293
+ label: "Medium",
294
+ value: "medium"
295
+ },
296
+ {
297
+ label: "Low",
298
+ value: "low"
299
+ }
300
+ ]
301
+ },
302
+ {
303
+ id: "amountRange",
304
+ type: "currency-range",
305
+ label: "Amount Range",
306
+ currency: "USD"
307
+ },
308
+ {
309
+ id: "monthRange",
310
+ type: "month-range",
311
+ label: "Month Range",
312
+ format: "YYYY-MM",
313
+ displayFormat: "MMM YYYY"
314
+ }
315
+ ]}
316
+ values={values}
317
+ onChange={(newValues) => setValues(newValues)}
318
+ onClose={() => setOpen(false)}
319
+ useReset
320
+ />
321
+ </Menu>
322
+ </Dropdown>
323
+ ```
324
+
325
+ ```tsx
326
+ import { Dropdown, MenuButtonTrigger, Menu, FilterMenu } from '@ceed/ads';
327
+ import FilterListIcon from '@mui/icons-material/FilterList';
328
+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
329
+
330
+ function ToolbarFilter() {
331
+ const [open, setOpen] = useState(false);
332
+ const [values, setValues] = useState({ status: ['active'] });
333
+
334
+ return (
335
+ <Dropdown open={open} onOpenChange={(_event, isOpen) => setOpen(isOpen)}>
336
+ <MenuButtonTrigger variant="outlined" startDecorator={<FilterListIcon />} endDecorator={<ExpandMoreIcon />}>
337
+ Filters
338
+ </MenuButtonTrigger>
339
+ <Menu placement="bottom-start" sx={{ p: 0, border: 'none', boxShadow: 'none', bgcolor: 'transparent' }}>
340
+ <FilterMenu filters={filters} values={values} onChange={setValues} onClose={() => setOpen(false)} useReset />
341
+ </Menu>
342
+ </Dropdown>
343
+ );
344
+ }
345
+ ```
346
+
347
+ > **Note**: Use `MenuButtonTrigger` (the low-level composition trigger), not the high-level `MenuButton` -- the latter renders its own item list and cannot host a FilterMenu. Strip the `Menu` surface styling (`p: 0`, transparent background, no border/shadow) so only FilterMenu's own panel surface is visible inside the popover. When FilterMenu is mounted inside `Dropdown`, the dropdown automatically keeps itself open while a picker filter's calendar (e.g. `date-range`, `month-range`) takes focus, so the panel survives nested popover interaction without any custom `onOpenChange` handling.
348
+
221
349
  ## Table Filters
222
350
 
223
351
  ```tsx
@@ -393,6 +521,7 @@ type FilterItem =
393
521
  | FilterableCheckboxGroupItem
394
522
  | FilterRadioGroupItem
395
523
  | FilterDateRangeItem
524
+ | FilterMonthRangeItem
396
525
  | FilterCurrencyInputItem
397
526
  | FilterCurrencyRangeItem
398
527
  | FilterPercentageInputItem
@@ -408,6 +537,7 @@ type FilterItem =
408
537
  | `'filterable-checkbox-group'` | `string[]` | Searchable multi-select with checkboxes. Supports `placeholder` and `maxHeight` |
409
538
  | `'radio-group'` | `string \| number` | Single-select with radio buttons |
410
539
  | `'date-range'` | `[string, string]` | Date range picker. Supports `displayFormat`, `inputReadOnly`, `hideClearButton`, `minDate`, `maxDate`, `disableFuture`, `disablePast` |
540
+ | `'month-range'` | `[string, string]` | Month range picker. Supports `format`, `displayFormat`, `locale`, `minDate`, `maxDate`, `disableFuture`, `disablePast` |
411
541
  | `'currency-input'` | `number` | Single currency value. Supports `currency`, `useMinorUnit`, `max`, `placeholder` |
412
542
  | `'currency-range'` | `[number, number]` | Currency range (min/max). Supports same props as currency-input |
413
543
  | `'percentage-input'` | `number` | Single percentage value. Supports `useMinorUnit`, `maxDecimalScale`, `min`, `max`, `placeholder` |