@recursica/mantine-adapter 0.42.0 → 0.43.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.
- package/CHANGELOG.md +18 -0
- package/dist/index.d.ts +93 -15
- package/dist/mantine-adapter.cjs +2 -2
- package/dist/mantine-adapter.cjs.map +1 -1
- package/dist/mantine-adapter.css +1 -1
- package/dist/mantine-adapter.js +3546 -3250
- package/dist/mantine-adapter.js.map +1 -1
- package/package.json +1 -1
- package/src/GlobalExemptions.modules.css +0 -6
- package/src/components/Accordion/Accordion.module.css +0 -8
- package/src/components/Accordion/Accordion.tsx +32 -33
- package/src/components/AssistiveElement/AssistiveElement.tsx +1 -1
- package/src/components/AutoComplete/AutoComplete.module.css +0 -7
- package/src/components/AutoComplete/AutoComplete.tsx +26 -38
- package/src/components/Avatar/Avatar.module.css +0 -8
- package/src/components/Avatar/Avatar.tsx +22 -23
- package/src/components/Badge/Badge.tsx +12 -18
- package/src/components/Breadcrumb/Breadcrumb.tsx +10 -18
- package/src/components/Button/Button.tsx +31 -30
- package/src/components/Card/Card.tsx +48 -27
- package/src/components/Checkbox/Checkbox.tsx +29 -42
- package/src/components/Checkbox/CheckboxGroup.tsx +12 -5
- package/src/components/Chip/Chip.module.css +0 -16
- package/src/components/Chip/Chip.tsx +34 -27
- package/src/components/DatePicker/DATEPICKER_IMPLEMENTATION_NOTES.md +14 -1
- package/src/components/DatePicker/DatePicker.icons.tsx +27 -0
- package/src/components/DatePicker/DatePicker.module.css +256 -7
- package/src/components/DatePicker/DatePicker.stories.tsx +0 -7
- package/src/components/DatePicker/DatePicker.tsx +68 -33
- package/src/components/DatePicker/USAGE.md +6 -2
- package/src/components/Dropdown/BareDropdown.tsx +25 -13
- package/src/components/Dropdown/Dropdown.module.css +0 -7
- package/src/components/Dropdown/Dropdown.tsx +25 -38
- package/src/components/FileInput/FileInput.module.css +0 -21
- package/src/components/FileInput/FileInput.tsx +1 -1
- package/src/components/FileUpload/FileUpload.module.css +0 -11
- package/src/components/FileUpload/FileUpload.tsx +1 -1
- package/src/components/HoverCard/HoverCard.module.css +1 -7
- package/src/components/HoverCard/HoverCard.tsx +18 -34
- package/src/components/Label/Label.module.css +0 -6
- package/src/components/Label/Label.tsx +20 -21
- package/src/components/Link/Link.module.css +1 -6
- package/src/components/Link/Link.tsx +6 -14
- package/src/components/Loader/Loader.tsx +8 -16
- package/src/components/Menu/Menu.module.css +0 -6
- package/src/components/Menu/Menu.tsx +55 -48
- package/src/components/Modal/Modal.module.css +0 -11
- package/src/components/Modal/Modal.tsx +134 -96
- package/src/components/NumberInput/NumberInput.module.css +0 -7
- package/src/components/NumberInput/NumberInput.tsx +14 -7
- package/src/components/Pagination/Pagination.module.css +0 -81
- package/src/components/Pagination/Pagination.tsx +25 -34
- package/src/components/Panel/Panel.tsx +19 -26
- package/src/components/Popover/Popover.tsx +19 -31
- package/src/components/Radio/Radio.tsx +32 -43
- package/src/components/Radio/RadioGroup.tsx +11 -4
- package/src/components/ReadOnlyField/ReadOnlyField.tsx +1 -1
- package/src/components/ReadOnlyField/ReadOnlyTextField.tsx +1 -1
- package/src/components/ReadOnlyField/WithReadOnlyWrapper.tsx +1 -1
- package/src/components/SegmentedControl/SegmentedControl.module.css +0 -1
- package/src/components/SegmentedControl/SegmentedControl.tsx +29 -33
- package/src/components/Slider/Slider.tsx +30 -43
- package/src/components/Stepper/Stepper.tsx +20 -13
- package/src/components/Switch/Switch.tsx +45 -45
- package/src/components/Switch/SwitchGroup.tsx +11 -4
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Tabs/Tabs.tsx +13 -6
- package/src/components/Text/Text.tsx +1 -1
- package/src/components/TextArea/TextArea.module.css +0 -7
- package/src/components/TextArea/TextArea.tsx +21 -25
- package/src/components/TextField/TextField.module.css +0 -7
- package/src/components/TextField/TextField.tsx +23 -30
- package/src/components/TimePicker/TimePicker.module.css +0 -16
- package/src/components/TimePicker/TimePicker.tsx +26 -12
- package/src/components/Timeline/Timeline.module.css +0 -6
- package/src/components/Timeline/Timeline.tsx +7 -21
- package/src/components/Timeline/TimelineItem.tsx +14 -26
- package/src/components/Title/Title.tsx +12 -2
- package/src/components/Toast/Toast.module.css +0 -7
- package/src/components/Toast/Toast.tsx +32 -31
- package/src/components/Tooltip/Tooltip.module.css +0 -9
- package/src/components/Tooltip/Tooltip.tsx +18 -34
- package/src/components/TransferList/TransferList.module.css +0 -8
- package/src/components/TransferList/TransferList.tsx +1 -1
- package/src/components/Tree/Tree.tsx +8 -8
- package/src/utils/filterStylingProps.ts +4 -0
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/* EXEMPTIONS:
|
|
2
|
-
- border-size variables are ignored because a uniform 1px border is applied globally to prevent
|
|
3
|
-
unexpected layout shift or flickering during focused, disabled, or error state transitions. */
|
|
4
|
-
/* recursica-ignore: --recursica_ui-kit_components_date-picker_properties_border-size */
|
|
5
|
-
/* recursica-ignore: --recursica_ui-kit_components_date-picker_variants_states_disabled_properties_border-size */
|
|
6
|
-
/* recursica-ignore: --recursica_ui-kit_components_date-picker_variants_states_error_properties_border-size */
|
|
7
|
-
|
|
8
1
|
/* LAYOUT SPACING OVERRIDES:
|
|
9
2
|
- Sets the --form-control-margin-bottom spacing hook to map component-specific layout tokens. */
|
|
10
3
|
.layoutOverride {
|
|
@@ -117,6 +110,14 @@
|
|
|
117
110
|
);
|
|
118
111
|
|
|
119
112
|
outline: none;
|
|
113
|
+
|
|
114
|
+
/* Single-line enforcement: DatePickerInput renders its value/placeholder as a <button>'s text
|
|
115
|
+
content (not a native <input>), so it wraps by default like any other block text — clip it to
|
|
116
|
+
one line with ellipsis instead, same convention as FileInput's .value. */
|
|
117
|
+
white-space: nowrap;
|
|
118
|
+
text-overflow: ellipsis;
|
|
119
|
+
overflow-x: clip;
|
|
120
|
+
overflow-y: visible;
|
|
120
121
|
}
|
|
121
122
|
|
|
122
123
|
.input::placeholder {
|
|
@@ -263,10 +264,257 @@
|
|
|
263
264
|
);
|
|
264
265
|
}
|
|
265
266
|
|
|
267
|
+
/* Month label + prev/next nav controls: styled as Recursica's own "text" button variant (small
|
|
268
|
+
size) rather than bare popover text — same border/background/color/typography tokens Button
|
|
269
|
+
uses for data-variant="text", since these are functionally buttons inside the popover. */
|
|
270
|
+
.calendarHeaderControl,
|
|
271
|
+
.calendarHeaderLevel {
|
|
272
|
+
position: relative;
|
|
273
|
+
border-style: solid;
|
|
274
|
+
border-width: var(
|
|
275
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_border-size
|
|
276
|
+
);
|
|
277
|
+
border-color: var(
|
|
278
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_border-color
|
|
279
|
+
);
|
|
280
|
+
background-color: var(
|
|
281
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_background-color
|
|
282
|
+
);
|
|
283
|
+
box-shadow: var(
|
|
284
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_elevation
|
|
285
|
+
);
|
|
286
|
+
color: var(
|
|
287
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_text-color
|
|
288
|
+
);
|
|
289
|
+
font-family: var(
|
|
290
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-family
|
|
291
|
+
);
|
|
292
|
+
font-size: var(
|
|
293
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-size
|
|
294
|
+
);
|
|
295
|
+
font-style: var(
|
|
296
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-style
|
|
297
|
+
);
|
|
298
|
+
font-weight: var(
|
|
299
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_font-weight
|
|
300
|
+
);
|
|
301
|
+
letter-spacing: var(
|
|
302
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_letter-spacing
|
|
303
|
+
);
|
|
304
|
+
text-decoration: var(
|
|
305
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_text-decoration
|
|
306
|
+
);
|
|
307
|
+
text-transform: var(
|
|
308
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_text_text-transform
|
|
309
|
+
);
|
|
310
|
+
transition: all 0.2s ease;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* Prev/next nav: icon-only button sizing (small). */
|
|
314
|
+
.calendarHeaderControl {
|
|
315
|
+
min-width: var(
|
|
316
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_min-width
|
|
317
|
+
);
|
|
318
|
+
height: var(
|
|
319
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_height
|
|
320
|
+
);
|
|
321
|
+
border-radius: var(
|
|
322
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_border-radius
|
|
323
|
+
);
|
|
324
|
+
padding: 0
|
|
325
|
+
var(
|
|
326
|
+
--recursica_ui-kit_components_button_variants_content_icon-only_variants_sizes_small_properties_horizontal-padding
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/* Month/year label: label-content button sizing (small). */
|
|
331
|
+
.calendarHeaderLevel {
|
|
332
|
+
height: var(
|
|
333
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_height
|
|
334
|
+
);
|
|
335
|
+
border-radius: var(
|
|
336
|
+
--recursica_ui-kit_components_button_variants_content_label_variants_sizes_small_properties_border-radius
|
|
337
|
+
);
|
|
338
|
+
padding: 0
|
|
339
|
+
var(
|
|
340
|
+
--recursica_ui-kit_components_button_variants_content_label_variants_sizes_small_properties_horizontal-padding
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/* Neutralize Mantine's own native :hover background-color (gray-0/dark-5) so only our
|
|
345
|
+
token-driven overlay below is visible — same reasoning as .day above. */
|
|
346
|
+
.calendarHeaderControl:hover:not(:disabled, [data-disabled]),
|
|
347
|
+
.calendarHeaderLevel:hover:not(:disabled, [data-disabled]) {
|
|
348
|
+
background-color: transparent;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.calendarHeaderControl::after,
|
|
352
|
+
.calendarHeaderLevel::after {
|
|
353
|
+
content: "";
|
|
354
|
+
position: absolute;
|
|
355
|
+
inset: 0;
|
|
356
|
+
border-radius: inherit;
|
|
357
|
+
z-index: -1;
|
|
358
|
+
pointer-events: none;
|
|
359
|
+
background-color: var(--recursica_brand_states_hover_color);
|
|
360
|
+
opacity: 0;
|
|
361
|
+
transition: opacity 150ms ease;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.calendarHeaderControl:hover:not(:disabled, [data-disabled])::after,
|
|
365
|
+
.calendarHeaderLevel:hover:not(:disabled, [data-disabled])::after {
|
|
366
|
+
opacity: var(--recursica_brand_states_hover_opacity);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
.calendarHeaderControl:disabled,
|
|
370
|
+
.calendarHeaderControl[data-disabled],
|
|
371
|
+
.calendarHeaderLevel:disabled,
|
|
372
|
+
.calendarHeaderLevel[data-disabled] {
|
|
373
|
+
opacity: var(
|
|
374
|
+
--recursica_ui-kit_components_button_variants_styles_text_variants_states_disabled_properties_opacity
|
|
375
|
+
);
|
|
376
|
+
box-shadow: var(
|
|
377
|
+
--recursica_ui-kit_components_button_variants_styles_text_variants_states_disabled_properties_elevation
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/* Focus ring, same convention as Button's own :focus-visible treatment. */
|
|
382
|
+
.calendarHeaderControl:focus-visible,
|
|
383
|
+
.calendarHeaderLevel:focus-visible {
|
|
384
|
+
outline: none;
|
|
385
|
+
box-shadow:
|
|
386
|
+
0 0 0 var(--recursica_brand_states_focus_border-size)
|
|
387
|
+
var(--recursica_brand_states_focus_color),
|
|
388
|
+
0 0 var(--recursica_brand_states_focus_blur)
|
|
389
|
+
var(--recursica_brand_states_focus_margin)
|
|
390
|
+
var(--recursica_brand_states_focus_color);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
.calendarHeaderControlIcon {
|
|
394
|
+
color: var(
|
|
395
|
+
--recursica_ui-kit_components_button_variants_styles_text_properties_colors_icon-color
|
|
396
|
+
);
|
|
397
|
+
width: var(
|
|
398
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon
|
|
399
|
+
);
|
|
400
|
+
height: var(
|
|
401
|
+
--recursica_ui-kit_components_button_variants_sizes_small_properties_icon
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/* Weekday row (Mo, Tu, We...) */
|
|
406
|
+
.weekday {
|
|
407
|
+
color: var(
|
|
408
|
+
--recursica_ui-kit_components_hover-card-popover_properties_colors_content
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
|
|
266
412
|
.day {
|
|
413
|
+
position: relative;
|
|
414
|
+
color: var(
|
|
415
|
+
--recursica_ui-kit_components_hover-card-popover_properties_colors_content
|
|
416
|
+
);
|
|
417
|
+
border-radius: var(--recursica_brand_dimensions_border-radii_default);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* Weekend days: Mantine's default colors them red; the UI Kit has no such concept, so they're
|
|
421
|
+
intentionally kept identical to any other day rather than left on Mantine's un-tokenized default. */
|
|
422
|
+
.day[data-weekend] {
|
|
267
423
|
color: var(
|
|
268
424
|
--recursica_ui-kit_components_hover-card-popover_properties_colors_content
|
|
269
425
|
);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/* Today marker: reuse the popover border-size/color tokens already used for the dropdown
|
|
429
|
+
surface itself, since the UI Kit exports no dedicated "today" indicator token. */
|
|
430
|
+
.day[data-today][data-highlight-today]:not([data-selected], [data-in-range]) {
|
|
431
|
+
border-style: solid;
|
|
432
|
+
border-width: var(
|
|
433
|
+
--recursica_ui-kit_components_hover-card-popover_properties_border-size
|
|
434
|
+
);
|
|
435
|
+
border-color: var(
|
|
436
|
+
--recursica_ui-kit_components_hover-card-popover_properties_colors_border-color
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* Outside-month & disabled days: dim with the generic disabled-opacity token used everywhere else
|
|
441
|
+
in the design system for elements with no dedicated disabled token. */
|
|
442
|
+
.day[data-outside],
|
|
443
|
+
.day[data-disabled] {
|
|
444
|
+
opacity: var(--recursica_brand_states_disabled);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
.day[data-disabled] {
|
|
448
|
+
cursor: not-allowed;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/* Unlike Button (a plain button with no built-in library hover), Mantine's Day ships its own
|
|
452
|
+
native :hover background-color (gray-0/dark-5) — neutralize it so only our token-driven
|
|
453
|
+
overlay below is visible. Same specificity as Mantine's own selector, so this relies on our
|
|
454
|
+
CSS module loading after @mantine/dates' stylesheet to win the tie (true today; see
|
|
455
|
+
DATEPICKER_IMPLEMENTATION_NOTES.md if that load order ever changes). */
|
|
456
|
+
.day:hover:not(:disabled, [data-disabled], [data-static]) {
|
|
457
|
+
background-color: transparent;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/* Hover overlay, same generic mechanism used by Button/Menu for components without a dedicated
|
|
461
|
+
hover token. Unlike Button, the day number here is a bare text node (Mantine's Day renders it
|
|
462
|
+
directly, with no wrapping span to z-index above the overlay), so this sits at z-index: -1
|
|
463
|
+
instead — still scoped to .day's own positioned box, just painted behind the digit rather than
|
|
464
|
+
in front of it. */
|
|
465
|
+
.day::after {
|
|
466
|
+
content: "";
|
|
467
|
+
position: absolute;
|
|
468
|
+
inset: 0;
|
|
469
|
+
border-radius: inherit;
|
|
470
|
+
z-index: -1;
|
|
471
|
+
pointer-events: none;
|
|
472
|
+
background-color: var(--recursica_brand_states_hover_color);
|
|
473
|
+
opacity: 0;
|
|
474
|
+
transition: opacity 150ms ease;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.day:hover:not(:disabled, [data-disabled], [data-static])::after {
|
|
478
|
+
opacity: var(--recursica_brand_states_hover_opacity);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/* Range selection (type="range"): the UI Kit exports no dedicated in-range token, so the generic
|
|
482
|
+
overlay token — meant for exactly this kind of translucent tint — fills the band between the
|
|
483
|
+
two selected endpoints. Painted via ::before (behind the day number and the ::after hover
|
|
484
|
+
overlay) so the fill's opacity never dims the text itself. */
|
|
485
|
+
.day[data-in-range] {
|
|
486
|
+
border-radius: 0;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.day[data-in-range]::before {
|
|
490
|
+
content: "";
|
|
491
|
+
position: absolute;
|
|
492
|
+
inset: 0;
|
|
493
|
+
z-index: -1;
|
|
494
|
+
pointer-events: none;
|
|
495
|
+
background-color: var(--recursica_brand_states_overlay_color);
|
|
496
|
+
opacity: var(--recursica_brand_states_overlay_opacity);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
.day[data-first-in-range] {
|
|
500
|
+
border-radius: 0;
|
|
501
|
+
border-start-start-radius: var(
|
|
502
|
+
--recursica_brand_dimensions_border-radii_default
|
|
503
|
+
);
|
|
504
|
+
border-end-start-radius: var(
|
|
505
|
+
--recursica_brand_dimensions_border-radii_default
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.day[data-last-in-range] {
|
|
510
|
+
border-radius: 0;
|
|
511
|
+
border-end-end-radius: var(--recursica_brand_dimensions_border-radii_default);
|
|
512
|
+
border-start-end-radius: var(
|
|
513
|
+
--recursica_brand_dimensions_border-radii_default
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
.day[data-first-in-range][data-last-in-range] {
|
|
270
518
|
border-radius: var(--recursica_brand_dimensions_border-radii_default);
|
|
271
519
|
}
|
|
272
520
|
|
|
@@ -278,4 +526,5 @@
|
|
|
278
526
|
color: var(
|
|
279
527
|
--recursica_ui-kit_components_button_variants_styles_solid_properties_colors_text-color
|
|
280
528
|
);
|
|
529
|
+
opacity: 1;
|
|
281
530
|
}
|
|
@@ -65,7 +65,6 @@ export const Default: Story = {
|
|
|
65
65
|
args: {
|
|
66
66
|
disabled: false,
|
|
67
67
|
label: "Project Deadline",
|
|
68
|
-
placeholder: "Select a deadline...",
|
|
69
68
|
assistiveText: "Specify the absolute cutoff for code submission.",
|
|
70
69
|
},
|
|
71
70
|
};
|
|
@@ -73,7 +72,6 @@ export const Default: Story = {
|
|
|
73
72
|
export const FormsSideBySide: Story = {
|
|
74
73
|
args: {
|
|
75
74
|
label: "Incident Start Date",
|
|
76
|
-
placeholder: "Pick date...",
|
|
77
75
|
assistiveText: "When did the incident originally occur?",
|
|
78
76
|
formLayout: "side-by-side",
|
|
79
77
|
},
|
|
@@ -82,7 +80,6 @@ export const FormsSideBySide: Story = {
|
|
|
82
80
|
export const WithLeadingIcon: Story = {
|
|
83
81
|
args: {
|
|
84
82
|
label: "Launch Date",
|
|
85
|
-
placeholder: "Select launch date...",
|
|
86
83
|
leftSection: (
|
|
87
84
|
<svg
|
|
88
85
|
width="24"
|
|
@@ -106,7 +103,6 @@ export const WithLeadingIcon: Story = {
|
|
|
106
103
|
export const Disabled: Story = {
|
|
107
104
|
args: {
|
|
108
105
|
label: "Disabled Date Range",
|
|
109
|
-
placeholder: "Disabled selection...",
|
|
110
106
|
disabled: true,
|
|
111
107
|
},
|
|
112
108
|
};
|
|
@@ -114,7 +110,6 @@ export const Disabled: Story = {
|
|
|
114
110
|
export const ErrorState: Story = {
|
|
115
111
|
args: {
|
|
116
112
|
label: "Execution Date",
|
|
117
|
-
placeholder: "Pick a valid date...",
|
|
118
113
|
error: "The chosen date conflicts with an existing deployment freeze.",
|
|
119
114
|
required: true,
|
|
120
115
|
},
|
|
@@ -123,7 +118,6 @@ export const ErrorState: Story = {
|
|
|
123
118
|
export const StaticReadOnly: Story = {
|
|
124
119
|
args: {
|
|
125
120
|
label: "Static ReadOnly Review",
|
|
126
|
-
placeholder: "Ignored...",
|
|
127
121
|
value: new Date("2026-05-21"),
|
|
128
122
|
readOnly: true,
|
|
129
123
|
},
|
|
@@ -132,7 +126,6 @@ export const StaticReadOnly: Story = {
|
|
|
132
126
|
export const EditableReadOnly: Story = {
|
|
133
127
|
args: {
|
|
134
128
|
label: "Editable ReadOnly Review",
|
|
135
|
-
placeholder: "Ignored until active...",
|
|
136
129
|
defaultValue: new Date("2026-06-01"),
|
|
137
130
|
readOnly: true,
|
|
138
131
|
labelWithEditIcon: true,
|
|
@@ -3,10 +3,14 @@ import { DatePickerInput, type DatePickerInputProps } from "@mantine/dates";
|
|
|
3
3
|
import { type ReadOnlyControlProps } from "@recursica/adapter-common";
|
|
4
4
|
import {
|
|
5
5
|
filterStylingProps,
|
|
6
|
+
omitUnsupportedProps,
|
|
7
|
+
withCallerOverride,
|
|
8
|
+
mergeClassNames,
|
|
6
9
|
type RecursicaOverStyled,
|
|
7
10
|
} from "../../utils/filterStylingProps";
|
|
8
11
|
import { type RecursicaFormControlWrapperProps } from "../FormControlWrapper/FormControlWrapper";
|
|
9
12
|
import { WithReadOnlyWrapper } from "../ReadOnlyField/WithReadOnlyWrapper";
|
|
13
|
+
import { CalendarIcon } from "./DatePicker.icons";
|
|
10
14
|
import styles from "./DatePicker.module.css";
|
|
11
15
|
|
|
12
16
|
import { type RecursicaDatePickerProps as BaseRecursicaDatePickerProps } from "@recursica/adapter-common";
|
|
@@ -38,6 +42,15 @@ export interface RecursicaDatePickerProps
|
|
|
38
42
|
|
|
39
43
|
export type DatePickerProps = RecursicaOverStyled<RecursicaDatePickerProps>;
|
|
40
44
|
|
|
45
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
46
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
47
|
+
const UNSUPPORTED_PROPS = [
|
|
48
|
+
"size", // Recursica controls sizing via the `size` variant + design tokens, not raw dimensions.
|
|
49
|
+
"variant", // Colors/variants are token-driven; the library's native palette isn't exposed.
|
|
50
|
+
"radius", // Recursica does not expose the library's native corner-radius system.
|
|
51
|
+
"description", // Managed by FormControlWrapper via assistiveText.
|
|
52
|
+
] as const satisfies readonly (keyof DatePickerInputProps)[];
|
|
53
|
+
|
|
41
54
|
export const DatePicker = forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
42
55
|
function DatePicker(props, ref) {
|
|
43
56
|
const {
|
|
@@ -66,45 +79,59 @@ export const DatePicker = forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
|
66
79
|
emptyValueComponent,
|
|
67
80
|
value,
|
|
68
81
|
defaultValue,
|
|
82
|
+
highlightToday = true, // Default on so today is visually marked; consumers can still override.
|
|
83
|
+
valueFormat = "MM/DD/YY", // Default display format; consumers can still override.
|
|
84
|
+
placeholder = "MM / DD / YY", // Default placeholder; consumers can still override.
|
|
85
|
+
leftSection, // Default leading icon computed below; consumers can still override.
|
|
69
86
|
...rest
|
|
70
87
|
} = props;
|
|
71
88
|
|
|
72
|
-
const sanitizedProps =
|
|
89
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
90
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
91
|
+
UNSUPPORTED_PROPS,
|
|
92
|
+
);
|
|
73
93
|
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
74
94
|
|
|
75
|
-
// Delete prohibited sizing hooks from bypassing variables natively
|
|
76
|
-
delete restRecord["size"];
|
|
77
|
-
delete restRecord["variant"];
|
|
78
|
-
delete restRecord["radius"];
|
|
79
|
-
delete restRecord["description"]; // Managed by FormControlWrapper via assistiveText
|
|
80
|
-
|
|
81
95
|
// Securely map core native blocks down ensuring nested CSS modules map precisely
|
|
82
|
-
const mergedClassNames
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
const mergedClassNames = mergeClassNames(
|
|
97
|
+
{
|
|
98
|
+
wrapper: styles.root, // The nested Input internal relative wrapper bounding box
|
|
99
|
+
input: styles.input,
|
|
100
|
+
section: styles.section,
|
|
101
|
+
day: styles.day,
|
|
102
|
+
weekday: styles.weekday,
|
|
103
|
+
calendarHeader: styles.calendarHeader,
|
|
104
|
+
calendarHeaderControl: styles.calendarHeaderControl,
|
|
105
|
+
calendarHeaderLevel: styles.calendarHeaderLevel,
|
|
106
|
+
calendarHeaderControlIcon: styles.calendarHeaderControlIcon,
|
|
107
|
+
},
|
|
108
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
109
|
+
);
|
|
90
110
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
?
|
|
100
|
-
:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
?
|
|
106
|
-
:
|
|
107
|
-
|
|
111
|
+
// The calendar popover surface (.dropdown) is styled by Mantine's underlying `Popover`
|
|
112
|
+
// component, not `DatePickerInput` itself — it only accepts classNames via `popoverProps`,
|
|
113
|
+
// not the top-level `classNames` map above (which only reaches the Input/Calendar parts).
|
|
114
|
+
const popoverPropsInput = restRecord.popoverProps;
|
|
115
|
+
const consumerPopoverProps =
|
|
116
|
+
popoverPropsInput &&
|
|
117
|
+
typeof popoverPropsInput === "object" &&
|
|
118
|
+
!Array.isArray(popoverPropsInput)
|
|
119
|
+
? (popoverPropsInput as Record<string, unknown>)
|
|
120
|
+
: undefined;
|
|
121
|
+
const consumerPopoverClassNames =
|
|
122
|
+
consumerPopoverProps?.classNames &&
|
|
123
|
+
typeof consumerPopoverProps.classNames === "object" &&
|
|
124
|
+
!Array.isArray(consumerPopoverProps.classNames)
|
|
125
|
+
? (consumerPopoverProps.classNames as Partial<Record<string, string>>)
|
|
126
|
+
: undefined;
|
|
127
|
+
delete restRecord["popoverProps"];
|
|
128
|
+
const mergedPopoverProps = {
|
|
129
|
+
...consumerPopoverProps,
|
|
130
|
+
classNames: mergeClassNames(
|
|
131
|
+
{ dropdown: styles.dropdown },
|
|
132
|
+
consumerPopoverClassNames,
|
|
133
|
+
),
|
|
134
|
+
};
|
|
108
135
|
|
|
109
136
|
const wrapperClass = className
|
|
110
137
|
? `${styles.layoutOverride} ${className}`
|
|
@@ -146,6 +173,7 @@ export const DatePicker = forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
|
146
173
|
/* Naked Input execution safely decoupled from Mantine's macro Input.Wrapper DOM hooks */
|
|
147
174
|
<DatePickerInput
|
|
148
175
|
ref={ref}
|
|
176
|
+
{...(sanitizedProps as unknown as DatePickerInputProps)}
|
|
149
177
|
classNames={mergedClassNames}
|
|
150
178
|
disabled={disabled}
|
|
151
179
|
value={value}
|
|
@@ -154,11 +182,18 @@ export const DatePicker = forwardRef<HTMLButtonElement, DatePickerProps>(
|
|
|
154
182
|
description={undefined} // Disable Mantine's native description
|
|
155
183
|
error={undefined} // Disable Mantine's native error text (handled by wrapper)
|
|
156
184
|
withAsterisk={false} // Handled by wrapper
|
|
185
|
+
highlightToday={highlightToday}
|
|
186
|
+
valueFormat={valueFormat}
|
|
187
|
+
placeholder={placeholder}
|
|
188
|
+
leftSection={withCallerOverride<React.ReactNode>(
|
|
189
|
+
<CalendarIcon />,
|
|
190
|
+
leftSection,
|
|
191
|
+
)}
|
|
157
192
|
wrapperProps={{
|
|
158
193
|
"data-disabled": disabled ? "true" : undefined,
|
|
159
194
|
"data-error": error ? "true" : undefined,
|
|
160
195
|
}}
|
|
161
|
-
{
|
|
196
|
+
popoverProps={mergedPopoverProps}
|
|
162
197
|
/>
|
|
163
198
|
}
|
|
164
199
|
/>
|
|
@@ -19,7 +19,7 @@ import React from "react";
|
|
|
19
19
|
import { DatePicker } from "@recursica/mantine-adapter";
|
|
20
20
|
|
|
21
21
|
export default function Demo() {
|
|
22
|
-
return <DatePicker label="Select Date"
|
|
22
|
+
return <DatePicker label="Select Date" />;
|
|
23
23
|
}
|
|
24
24
|
```
|
|
25
25
|
|
|
@@ -42,4 +42,8 @@ All Recursica components in the `@recursica/mantine-adapter` package adhere stri
|
|
|
42
42
|
## Structural Constraints
|
|
43
43
|
|
|
44
44
|
1. **Read-Only Rendering**: When rendered in read-only mode, the selected date is displayed via a plain string conversion of the value. If you need custom date formatting, pass a `readOnlyComponent` prop to control how the value is rendered.
|
|
45
|
-
2. **Calendar Popover Styling**: The calendar
|
|
45
|
+
2. **Calendar Popover Styling**: The UI Kit exports no calendar-specific tokens (surface, selected day, hover, today, weekend, in-range), so the calendar reuses the closest existing tokens — see `DATEPICKER_IMPLEMENTATION_NOTES.md` for the exact mapping. All calendar states are token-driven; none are left on Mantine's un-tokenized defaults. The header's prev/next arrows and month/year label are styled as Recursica `text`-variant buttons.
|
|
46
|
+
3. **Today Highlighting**: `highlightToday` defaults to `true` so the current day is always visually marked; pass `highlightToday={false}` to turn it off.
|
|
47
|
+
4. **Default Value Format**: Displayed values default to `MM/DD/YY` (e.g. `08/19/26`); pass your own `valueFormat` (a `dayjs` format string) to override.
|
|
48
|
+
5. **Default Leading Icon**: A calendar icon is shown in the left section by default; pass your own `leftSection` to override it.
|
|
49
|
+
6. **Default Placeholder**: Defaults to `"MM / DD / YY"` when not set; pass your own `placeholder` to override it.
|
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
} from "@mantine/core";
|
|
6
6
|
import {
|
|
7
7
|
filterStylingProps,
|
|
8
|
+
omitUnsupportedProps,
|
|
9
|
+
mergeClassNames,
|
|
8
10
|
type RecursicaOverStyled,
|
|
9
11
|
} from "../../utils/filterStylingProps";
|
|
10
12
|
import styles from "./Dropdown.module.css";
|
|
@@ -37,29 +39,40 @@ export interface BareDropdownProps
|
|
|
37
39
|
|
|
38
40
|
export type BareDropdownComponentProps = RecursicaOverStyled<BareDropdownProps>;
|
|
39
41
|
|
|
42
|
+
// Props this component intentionally doesn't support — deleted at runtime so they can't leak
|
|
43
|
+
// through even if a caller forces them via plain JavaScript, bypassing the `Omit<>` above.
|
|
44
|
+
const UNSUPPORTED_PROPS = [
|
|
45
|
+
"size", // Recursica controls sizing via the `size` variant + design tokens, not raw dimensions.
|
|
46
|
+
"variant", // Colors/variants are token-driven; the library's native palette isn't exposed.
|
|
47
|
+
"radius", // Recursica does not expose the library's native corner-radius system.
|
|
48
|
+
] as const satisfies readonly (keyof MantineSelectProps)[];
|
|
49
|
+
|
|
40
50
|
export const BareDropdown = forwardRef<
|
|
41
51
|
HTMLInputElement,
|
|
42
52
|
BareDropdownComponentProps
|
|
43
53
|
>(function BareDropdown(props, ref) {
|
|
44
54
|
const { overStyled = false, className, disabled, error, ...rest } = props;
|
|
45
|
-
const sanitizedProps =
|
|
55
|
+
const sanitizedProps = omitUnsupportedProps(
|
|
56
|
+
filterStylingProps(rest, overStyled) as Record<string, unknown>,
|
|
57
|
+
UNSUPPORTED_PROPS,
|
|
58
|
+
);
|
|
46
59
|
const restRecord = sanitizedProps as Record<string, unknown>;
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
};
|
|
61
|
+
const mergedClassNames = mergeClassNames(
|
|
62
|
+
{
|
|
63
|
+
wrapper: className ? `${styles.root} ${className}` : styles.root,
|
|
64
|
+
input: styles.input,
|
|
65
|
+
section: styles.section,
|
|
66
|
+
dropdown: styles.dropdown,
|
|
67
|
+
option: styles.option,
|
|
68
|
+
},
|
|
69
|
+
restRecord.classNames as Partial<Record<string, string>> | undefined,
|
|
70
|
+
);
|
|
59
71
|
|
|
60
72
|
return (
|
|
61
73
|
<MantineSelect
|
|
62
74
|
ref={ref}
|
|
75
|
+
{...(sanitizedProps as unknown as MantineSelectProps)}
|
|
63
76
|
classNames={mergedClassNames}
|
|
64
77
|
disabled={disabled}
|
|
65
78
|
label={undefined}
|
|
@@ -77,7 +90,6 @@ export const BareDropdown = forwardRef<
|
|
|
77
90
|
"data-error": error ? "true" : undefined,
|
|
78
91
|
},
|
|
79
92
|
}}
|
|
80
|
-
{...(sanitizedProps as unknown as MantineSelectProps)}
|
|
81
93
|
/>
|
|
82
94
|
);
|
|
83
95
|
});
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/* EXEMPTIONS:
|
|
2
|
-
- border-size variables are ignored because a uniform 1px border is applied globally to prevent
|
|
3
|
-
unexpected layout shift or flickering during focus, disabled, or error state transitions. */
|
|
4
|
-
/* recursica-ignore: --recursica_ui-kit_components_dropdown_properties_border-size */
|
|
5
|
-
/* recursica-ignore: --recursica_ui-kit_components_dropdown_variants_states_disabled_properties_border-size */
|
|
6
|
-
/* recursica-ignore: --recursica_ui-kit_components_dropdown_variants_states_error_properties_border-size */
|
|
7
|
-
|
|
8
1
|
/* LAYOUT SPACING OVERRIDES:
|
|
9
2
|
- Sets the --form-control-margin-bottom spacing hook to map component-specific layout tokens.
|
|
10
3
|
- Also sets the --dropdown-control-{max,min}-width hooks consumed inline in Dropdown.tsx, since
|