@recursica/mui-adapter 0.22.0 → 0.23.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 CHANGED
@@ -1,5 +1,28 @@
1
1
  # @recursica/mui-adapter
2
2
 
3
+ ## 0.23.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1c317a3: Implement the `FileUpload` component (drag-and-drop dropzone, browse-button fallback, removable file-chip list) in `mantine-adapter` and `mui-adapter`, replacing the "coming soon" stub, with a shared `RecursicaFileUploadProps`/`RecursicaFileUploadItem` contract in `adapter-common`. Also fixes `mui-adapter`'s `Chip` component's public type to allow `children` (a pre-existing type-only gap; the component already accepted them at runtime).
8
+
9
+ ### Patch Changes
10
+
11
+ - 1c317a3: `FileUpload` now surfaces a built-in error message ("File type not accepted", overridable via the new `invalidFileTypeMessage` prop) when a dropped/picked file doesn't match `accept`, shown through the standard assistive-text error slot instead of requiring the integrator to wire up `onFilesRejected` themselves. Also reverts `FileUpload`'s assistive/error rendering back to `FormControlWrapper` (file list renders above the assistive/error text again, matching every other form control).
12
+
13
+ Fixes `Chip` clipping the descender (e.g. the "g" in "image.png") off long labels — `overflow: hidden` was clipping vertically as well as horizontally, cutting off glyph ink whenever the line-height token was tighter than the font's natural ascent+descent.
14
+
15
+ - 1c317a3: `FileUpload` now supports a `maxFiles` prop (with an overridable `maxFilesMessage`, defaulting to "Maximum of {maxFiles} files allowed") that rejects files past a total-count cap the same way `accept`/`maxSize` already do.
16
+
17
+ Fixes `Chip` rendered without a real handler (`onRemove`/`onClick`/`onChange`) — such as `FileUpload`'s `readOnly` file list — still showing a pointer cursor on hover and picking up a phantom, un-styled keyboard Tab stop on its truncated label text. Both were general `Chip` bugs, not specific to `FileUpload`.
18
+
19
+ - 1c317a3: Fix `Button` showing the native browser focus outline instead of the recursica focus ring, and fix `Chip` losing its remove (X) icon behind an overflowing long label instead of truncating with an ellipsis. Adds optional `removeTabIndex`/`removeIconRef` props to `Chip` for building keyboard-navigable chip groups. Also fixes the remove icon's own focus ring rendering in the chip's neutral border color instead of the recursica focus-ring color, making it barely visible.
20
+ - Updated dependencies [1c317a3]
21
+ - Updated dependencies [1c317a3]
22
+ - Updated dependencies [1c317a3]
23
+ - Updated dependencies [1c317a3]
24
+ - @recursica/adapter-common@0.16.0
25
+
3
26
  ## 0.22.0
4
27
 
5
28
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -406,9 +406,13 @@ declare type CheckboxWrapperProps = Omit<CheckboxProps_2, "size" | "color"> & Re
406
406
 
407
407
  export declare const Chip: typeof rawComponents.Chip;
408
408
 
409
- declare const Chip_2: default_2.ForwardRefExoticComponent<(Omit<Omit<WithRecursicaSpacing<Omit<ChipProps_2, "color" | "variant" | "size" | "radius"> & RecursicaChipProps>, BlockedStylingKeys> & ForbiddenStyles & {
409
+ declare const Chip_2: default_2.ForwardRefExoticComponent<(Omit<Omit<WithRecursicaSpacing<Omit<ChipProps_2, "color" | "children" | "variant" | "size" | "radius"> & RecursicaChipProps & {
410
+ children?: default_2.ReactNode;
411
+ }>, BlockedStylingKeys> & ForbiddenStyles & {
410
412
  overStyled?: false | undefined;
411
- }, "ref"> | Omit<Omit<Omit<ChipProps_2, "color" | "variant" | "size" | "radius"> & RecursicaChipProps, "m" | "my" | "mx" | "mt" | "mb" | "ml" | "mr" | "gap" | "rowGap" | "columnGap"> & {
413
+ }, "ref"> | Omit<Omit<Omit<ChipProps_2, "color" | "children" | "variant" | "size" | "radius"> & RecursicaChipProps & {
414
+ children?: default_2.ReactNode;
415
+ }, "m" | "my" | "mx" | "mt" | "mb" | "ml" | "mr" | "gap" | "rowGap" | "columnGap"> & {
412
416
  m?: string | number | RecursicaSpacing;
413
417
  mx?: string | number | RecursicaSpacing;
414
418
  my?: string | number | RecursicaSpacing;
@@ -423,7 +427,9 @@ declare const Chip_2: default_2.ForwardRefExoticComponent<(Omit<Omit<WithRecursi
423
427
  overStyled: true;
424
428
  }, "ref">) & default_2.RefAttributes<HTMLInputElement>>;
425
429
 
426
- declare type ChipProps = RecursicaOverStyled<Omit<ChipProps_2, "variant" | "size" | "color" | "radius"> & RecursicaChipProps>;
430
+ declare type ChipProps = RecursicaOverStyled<Omit<ChipProps_2, "variant" | "size" | "color" | "radius" | "children"> & RecursicaChipProps & {
431
+ children?: default_2.ReactNode;
432
+ }>;
427
433
 
428
434
  export declare const Container: ForwardRefExoticComponent<Omit<rawComponents.ContainerProps, "ref"> & RefAttributes<HTMLDivElement>>;
429
435
 
@@ -501,11 +507,47 @@ declare const FileInput_2: default_2.FC<FileInputProps>;
501
507
 
502
508
  declare type FileInputProps = default_2.HTMLAttributes<HTMLDivElement>;
503
509
 
504
- export declare const FileUpload: FC<rawComponents.FileUploadProps>;
510
+ /**
511
+ * Mirrors the semantics of the native HTML `accept` attribute (comma-separated file extensions,
512
+ * MIME types, or MIME wildcards like `image/*`) so drag-and-drop can be validated the same way —
513
+ * the browser only applies `accept` to its own file-picker dialog, never to a `drop` event, so
514
+ * without this a dropped file bypasses the restriction entirely.
515
+ */
516
+ export declare function fileMatchesAccept(file: File, accept?: string): boolean;
517
+
518
+ export declare const FileUpload: typeof rawComponents.FileUpload;
505
519
 
506
- declare const FileUpload_2: default_2.FC<FileUploadProps>;
520
+ /**
521
+ * A dropzone for uploading files, with a native browse-button fallback and a
522
+ * removable-chip list of the currently selected files.
523
+ *
524
+ * @example
525
+ * <FileUpload
526
+ * label="Upload Files"
527
+ * assistiveText="Max file size 5MB"
528
+ * files={files}
529
+ * onFilesAdded={(added) => setFiles((f) => [...f, ...added.map((file) => ({ file }))])}
530
+ * onFileRemove={(id) => setFiles((f) => f.filter((item) => (item.id ?? item.file.name) !== id))}
531
+ * />
532
+ */
533
+ declare const FileUpload_2: default_2.ForwardRefExoticComponent<(Omit<Omit<WithRecursicaSpacing<RecursicaFileUploadProps_2>, BlockedStylingKeys> & ForbiddenStyles & {
534
+ overStyled?: false | undefined;
535
+ }, "ref"> | Omit<Omit<RecursicaFileUploadProps_2, "m" | "my" | "mx" | "mt" | "mb" | "ml" | "mr" | "gap" | "rowGap" | "columnGap"> & {
536
+ m?: string | number | RecursicaSpacing;
537
+ mx?: string | number | RecursicaSpacing;
538
+ my?: string | number | RecursicaSpacing;
539
+ mt?: string | number | RecursicaSpacing;
540
+ mb?: string | number | RecursicaSpacing;
541
+ ml?: string | number | RecursicaSpacing;
542
+ mr?: string | number | RecursicaSpacing;
543
+ gap?: string | number | RecursicaSpacing;
544
+ rowGap?: string | number | RecursicaSpacing;
545
+ columnGap?: string | number | RecursicaSpacing;
546
+ } & {
547
+ overStyled: true;
548
+ }, "ref">) & default_2.RefAttributes<HTMLDivElement>>;
507
549
 
508
- declare type FileUploadProps = default_2.HTMLAttributes<HTMLDivElement>;
550
+ declare type FileUploadProps = RecursicaOverStyled<RecursicaFileUploadProps_2>;
509
551
 
510
552
  export declare const Flex: ForwardRefExoticComponent<Omit<rawComponents.FlexProps, "ref"> & RefAttributes<HTMLDivElement>>;
511
553
 
@@ -1006,6 +1048,8 @@ declare namespace rawComponents {
1006
1048
  Dropdown_2 as Dropdown,
1007
1049
  FileInputProps,
1008
1050
  FileInput_2 as FileInput,
1051
+ RecursicaFileUploadItem,
1052
+ RecursicaFileUploadProps_2 as RecursicaFileUploadProps,
1009
1053
  FileUploadProps,
1010
1054
  FileUpload_2 as FileUpload,
1011
1055
  FlexProps,
@@ -1388,6 +1432,17 @@ export declare interface RecursicaChipProps {
1388
1432
  removeLabel?: string;
1389
1433
  /** Checked state for the chip (acts as a checkbox) */
1390
1434
  checked?: boolean;
1435
+ /**
1436
+ * Tab index for the remove (X) icon. Defaults to `0`. Lets a parent implement a roving-tabindex
1437
+ * pattern across a group of chips (e.g. FileUpload's file list) by setting this to `-1` on every
1438
+ * chip except the currently-active one.
1439
+ */
1440
+ removeTabIndex?: number;
1441
+ /**
1442
+ * Ref to the remove (X) icon element, so a parent can move focus to it imperatively — e.g.
1443
+ * arrow-key navigation across a group of chips.
1444
+ */
1445
+ removeIconRef?: default_2.Ref<HTMLSpanElement>;
1391
1446
  }
1392
1447
 
1393
1448
  /**
@@ -1438,6 +1493,102 @@ declare interface RecursicaDropdownProps_2 {
1438
1493
  placeholder?: string;
1439
1494
  }
1440
1495
 
1496
+ /**
1497
+ * A single file entry rendered as a removable chip in the FileUpload's file list.
1498
+ */
1499
+ export declare interface RecursicaFileUploadItem {
1500
+ /** The underlying browser File object. */
1501
+ file: File;
1502
+ /**
1503
+ * Stable identifier for this entry, used as the React key and passed back to
1504
+ * `onFileRemove`. Defaults to the file's `name` when not provided.
1505
+ */
1506
+ id?: string;
1507
+ }
1508
+
1509
+ /**
1510
+ * Props for the Recursica FileUpload component.
1511
+ */
1512
+ export declare interface RecursicaFileUploadProps {
1513
+ /**
1514
+ * Files currently selected, rendered as removable chips below the dropzone.
1515
+ * This is a controlled list — `onFilesAdded`/`onFileRemove` report changes, but
1516
+ * `FileUpload` never mutates this array itself; merge the reported changes into
1517
+ * your own state and pass the updated list back in.
1518
+ */
1519
+ files?: RecursicaFileUploadItem[];
1520
+ /**
1521
+ * Called with the files the user just dropped onto the dropzone or picked via
1522
+ * the browse button. Only the newly added files are passed — merge them into
1523
+ * `files` yourself (e.g. to assign an `id`, dedupe, or reject some of them).
1524
+ */
1525
+ onFilesAdded?: (files: File[]) => void;
1526
+ /**
1527
+ * Called when a file chip's remove (X) icon is activated, identified by its
1528
+ * `id` (or `file.name` when no `id` was given for that entry).
1529
+ */
1530
+ onFileRemove?: (id: string) => void;
1531
+ /**
1532
+ * Native `accept` attribute for the underlying file input (e.g. `".pdf,.png"`
1533
+ * or `"image/*"`) — constrains the browse-button file picker natively. Also
1534
+ * enforced against files dropped onto the dropzone: the browser only applies
1535
+ * `accept` to its own file-picker dialog, never to a `drop` event, so files
1536
+ * that don't match are rejected the same way (see `onFilesRejected`) rather
1537
+ * than silently bypassing the restriction.
1538
+ */
1539
+ accept?: string;
1540
+ /** Whether more than one file can be selected/dropped at once. Defaults to `true`. */
1541
+ multiple?: boolean;
1542
+ /**
1543
+ * Maximum size per file, in bytes. Files exceeding this are passed to
1544
+ * `onFilesRejected` instead of `onFilesAdded`.
1545
+ */
1546
+ maxSize?: number;
1547
+ /**
1548
+ * Maximum total number of files allowed in `files`. Once reached, further
1549
+ * dropped/picked files are passed to `onFilesRejected` instead of
1550
+ * `onFilesAdded`.
1551
+ */
1552
+ maxFiles?: number;
1553
+ /**
1554
+ * Called with any files rejected for exceeding `maxSize`/`maxFiles` or not
1555
+ * matching `accept`.
1556
+ */
1557
+ onFilesRejected?: (files: File[]) => void;
1558
+ /**
1559
+ * Error message shown (via the standard assistive-text error slot) when a
1560
+ * dropped/picked file's extension or MIME type doesn't match `accept`.
1561
+ * Defaults to `"File type not accepted"`.
1562
+ */
1563
+ invalidFileTypeMessage?: default_2.ReactNode;
1564
+ /**
1565
+ * Error message shown (via the standard assistive-text error slot) when a
1566
+ * dropped/picked file would exceed `maxFiles`. Defaults to
1567
+ * `"Maximum of {maxFiles} files allowed"`.
1568
+ */
1569
+ maxFilesMessage?: default_2.ReactNode;
1570
+ /** Icon shown above the dropzone label. Defaults to the built-in upload icon. */
1571
+ icon?: default_2.ReactNode;
1572
+ /** Text shown inside the dropzone. Defaults to `"Drag and drop files here to upload"`. */
1573
+ dropzoneLabel?: default_2.ReactNode;
1574
+ /** Label for the button that opens the native file picker. Defaults to `"Browse files"`. */
1575
+ browseButtonLabel?: default_2.ReactNode;
1576
+ /** Screen-reader label for each file chip's remove button. Defaults to `"Remove"`. */
1577
+ removeFileLabel?: string;
1578
+ /** Disables the dropzone, browse button, and every file chip's remove icon. */
1579
+ disabled?: boolean;
1580
+ /**
1581
+ * Renders `files` as a static list of chips with no remove icon, and omits
1582
+ * the dropzone/browse button entirely.
1583
+ */
1584
+ readOnly?: boolean;
1585
+ }
1586
+
1587
+ declare interface RecursicaFileUploadProps_2 extends Omit<default_2.HTMLAttributes<HTMLDivElement>, "children" | "onDrop" | "onChange">, Omit<RecursicaFormControlWrapperProps, "controlMaxWidth" | "controlMinWidth">, RecursicaFileUploadProps {
1588
+ /** Visually forces the mandatory asterisk. Accepted for API parity with other adapters; MUI's own `required` already renders the asterisk, so this has no separate effect here. */
1589
+ withAsterisk?: boolean;
1590
+ }
1591
+
1441
1592
  /**
1442
1593
  * Props for the Recursica Flex layout component.
1443
1594
  */