laif-ds 0.2.44 → 0.2.45

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 (98) hide show
  1. package/dist/_virtual/index4.js +5 -5
  2. package/dist/_virtual/index5.js +5 -5
  3. package/dist/_virtual/index6.js +2 -2
  4. package/dist/_virtual/index7.js +2 -2
  5. package/dist/agent-docs/components/Accordion.md +157 -0
  6. package/dist/agent-docs/components/Alert.md +95 -0
  7. package/dist/agent-docs/components/AlertDialog.md +126 -0
  8. package/dist/agent-docs/components/AppEditor.md +90 -0
  9. package/dist/agent-docs/components/AppForm.md +242 -0
  10. package/dist/agent-docs/components/AppMultipleSelectDropdown.md +38 -0
  11. package/dist/agent-docs/components/AppRadioGroup.md +223 -0
  12. package/dist/agent-docs/components/AppSelect.md +427 -0
  13. package/dist/agent-docs/components/AppSidebar.md +122 -0
  14. package/dist/agent-docs/components/AppStepper.md +77 -0
  15. package/dist/agent-docs/components/AspectRatio.md +87 -0
  16. package/dist/agent-docs/components/AsyncSelect.md +127 -0
  17. package/dist/agent-docs/components/AudioVisualizer.md +41 -0
  18. package/dist/agent-docs/components/Avatar.md +113 -0
  19. package/dist/agent-docs/components/Badge.md +118 -0
  20. package/dist/agent-docs/components/Breadcrumb.md +78 -0
  21. package/dist/agent-docs/components/Button.md +129 -0
  22. package/dist/agent-docs/components/Calendar.md +222 -0
  23. package/dist/agent-docs/components/Card.md +147 -0
  24. package/dist/agent-docs/components/Carousel.md +129 -0
  25. package/dist/agent-docs/components/Chart.md +75 -0
  26. package/dist/agent-docs/components/Chat.md +109 -0
  27. package/dist/agent-docs/components/ChatMessage.md +61 -0
  28. package/dist/agent-docs/components/Checkbox.md +135 -0
  29. package/dist/agent-docs/components/CircularProgress.md +49 -0
  30. package/dist/agent-docs/components/CodeHighlighter.md +31 -0
  31. package/dist/agent-docs/components/Collapsible.md +95 -0
  32. package/dist/agent-docs/components/Command.md +142 -0
  33. package/dist/agent-docs/components/Confirmer.md +175 -0
  34. package/dist/agent-docs/components/ContextMenu.md +191 -0
  35. package/dist/agent-docs/components/CopyButton.md +26 -0
  36. package/dist/agent-docs/components/DataCrossTable.md +94 -0
  37. package/dist/agent-docs/components/DataTable.md +254 -0
  38. package/dist/agent-docs/components/DatePicker.md +109 -0
  39. package/dist/agent-docs/components/Dialog.md +125 -0
  40. package/dist/agent-docs/components/Drawer.md +127 -0
  41. package/dist/agent-docs/components/DropdownMenu.md +57 -0
  42. package/dist/agent-docs/components/FilePreview.md +99 -0
  43. package/dist/agent-docs/components/FilePreviewer.md +139 -0
  44. package/dist/agent-docs/components/FileUploader.md +129 -0
  45. package/dist/agent-docs/components/Form.md +62 -0
  46. package/dist/agent-docs/components/FormComposer.md +137 -0
  47. package/dist/agent-docs/components/GanttChart.md +122 -0
  48. package/dist/agent-docs/components/HoverCard.md +37 -0
  49. package/dist/agent-docs/components/Icon.md +99 -0
  50. package/dist/agent-docs/components/Input.md +138 -0
  51. package/dist/agent-docs/components/InputOtp.md +40 -0
  52. package/dist/agent-docs/components/InputSelector.md +97 -0
  53. package/dist/agent-docs/components/InterruptPrompt.md +32 -0
  54. package/dist/agent-docs/components/Label.md +28 -0
  55. package/dist/agent-docs/components/MarkdownRenderer.md +36 -0
  56. package/dist/agent-docs/components/Menubar.md +164 -0
  57. package/dist/agent-docs/components/MessageInput.md +131 -0
  58. package/dist/agent-docs/components/MessageList.md +96 -0
  59. package/dist/agent-docs/components/MultipleSelector.md +146 -0
  60. package/dist/agent-docs/components/NavigationMenu.md +51 -0
  61. package/dist/agent-docs/components/Pagination.md +55 -0
  62. package/dist/agent-docs/components/Popover.md +103 -0
  63. package/dist/agent-docs/components/Progress.md +30 -0
  64. package/dist/agent-docs/components/PromptSuggestions.md +33 -0
  65. package/dist/agent-docs/components/RadioGroup.md +90 -0
  66. package/dist/agent-docs/components/Resizable.md +35 -0
  67. package/dist/agent-docs/components/ResizePrompt.md +13 -0
  68. package/dist/agent-docs/components/ScrollArea.md +49 -0
  69. package/dist/agent-docs/components/SecurePdfViewer.md +38 -0
  70. package/dist/agent-docs/components/Select.md +132 -0
  71. package/dist/agent-docs/components/Separator.md +32 -0
  72. package/dist/agent-docs/components/Sheet.md +40 -0
  73. package/dist/agent-docs/components/ShikiHighlighter.md +31 -0
  74. package/dist/agent-docs/components/Sidebar.md +85 -0
  75. package/dist/agent-docs/components/Skeleton.md +29 -0
  76. package/dist/agent-docs/components/Slider.md +58 -0
  77. package/dist/agent-docs/components/Sonner.md +21 -0
  78. package/dist/agent-docs/components/Spinner.md +139 -0
  79. package/dist/agent-docs/components/Stepper.md +67 -0
  80. package/dist/agent-docs/components/Switch.md +42 -0
  81. package/dist/agent-docs/components/Table.md +63 -0
  82. package/dist/agent-docs/components/TableSkeleton.md +46 -0
  83. package/dist/agent-docs/components/Tabs.md +86 -0
  84. package/dist/agent-docs/components/TextArea.md +52 -0
  85. package/dist/agent-docs/components/ThemeSwitcher.md +69 -0
  86. package/dist/agent-docs/components/Toaster.md +23 -0
  87. package/dist/agent-docs/components/Toggle.md +31 -0
  88. package/dist/agent-docs/components/ToggleGroup.md +30 -0
  89. package/dist/agent-docs/components/Tooltip.md +91 -0
  90. package/dist/agent-docs/components/TypingIndicator.md +21 -0
  91. package/dist/agent-docs/components/Typo.md +65 -0
  92. package/dist/agent-docs/components/WeeklyCalendar.md +64 -0
  93. package/dist/agent-docs/components-list.md +144 -0
  94. package/dist/node_modules/eventemitter3/index2.js +1 -1
  95. package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.js +1 -1
  96. package/dist/node_modules/style-to-object/cjs/index.js +1 -1
  97. package/dist/node_modules/unified/lib/index.js +1 -1
  98. package/package.json +3 -2
@@ -0,0 +1,125 @@
1
+ # Dialog
2
+
3
+ ## Overview
4
+
5
+ Accessible modal dialog built on Radix. Includes overlay, content with size variants, header/footer layout, title/description, trigger and close controls.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ ### Dialog (Root)
12
+
13
+ | Prop | Type | Default | Description |
14
+ | -------------- | ------------------- | ----------- | ---------------------------------------- |
15
+ | `open` | `boolean` | `undefined` | Controlled open state. |
16
+ | `defaultOpen` | `boolean` | `false` | Uncontrolled initial open state. |
17
+ | `onOpenChange` | `(open: boolean) => void` | `undefined` | Called when open state changes. |
18
+ | `modal` | `boolean` | `true` | Modal behavior (trap focus, background). |
19
+
20
+ ### DialogContent
21
+
22
+ Additional prop:
23
+
24
+ | Prop | Type | Default | Description |
25
+ | -------- | ----------------------------- | ----------- | ------------------------------------- |
26
+ | `size` | `"sm" | "default" | "lg" | "xl"` | `"default"` | Max-width preset for the content. |
27
+ | `className` | `string` | `""` | Additional classes for the panel. |
28
+
29
+ ### Subcomponents
30
+
31
+ - `DialogTrigger`: Element that opens the dialog (supports `asChild`).
32
+ - `DialogPortal` / `DialogOverlay`: Portal root and backdrop.
33
+ - `DialogContent`: Centered panel with animations and close button.
34
+ - `DialogHeader` / `DialogFooter`: Layout helpers for content.
35
+ - `DialogTitle` / `DialogDescription`: Accessible title and description.
36
+ - `DialogClose`: Close button (already included inside `DialogContent`).
37
+
38
+ ---
39
+
40
+ ## Behavior
41
+
42
+ - **Focus management**: Traps focus while open; returns on close.
43
+ - **Pointer outside exception**: Clicks inside elements marked `data-command-portal` are ignored to prevent unintended close.
44
+ - **Sizes**: `size` controls the max-width (`sm`, `default`, `lg`, `xl`).
45
+
46
+ ---
47
+
48
+ ## Examples
49
+
50
+ ### Basic
51
+
52
+ ```tsx
53
+ import { Button } from "laif-ds";
54
+ import {
55
+ Dialog,
56
+ DialogTrigger,
57
+ DialogContent,
58
+ DialogHeader,
59
+ DialogTitle,
60
+ DialogDescription,
61
+ DialogFooter,
62
+ } from "laif-ds";
63
+
64
+ export function BasicDialog() {
65
+ return (
66
+ <Dialog>
67
+ <DialogTrigger asChild>
68
+ <Button variant="outline">Open Dialog</Button>
69
+ </DialogTrigger>
70
+ <DialogContent>
71
+ <DialogHeader>
72
+ <DialogTitle>Basic Dialog</DialogTitle>
73
+ <DialogDescription>
74
+ This is a basic dialog with title and description.
75
+ </DialogDescription>
76
+ </DialogHeader>
77
+ <div className="py-4">
78
+ <p className="text-d-secondary-foreground text-sm">
79
+ Dialog content goes here.
80
+ </p>
81
+ </div>
82
+ <DialogFooter>
83
+ <Button type="submit">Save changes</Button>
84
+ </DialogFooter>
85
+ </DialogContent>
86
+ </Dialog>
87
+ );
88
+ }
89
+ ```
90
+
91
+ ### Size Variants
92
+
93
+ ```tsx
94
+ import { Button } from "laif-ds";
95
+ import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle } from "laif-ds";
96
+
97
+ export function SizeVariants() {
98
+ return (
99
+ <div className="flex flex-wrap gap-3">
100
+ {["sm", "default", "lg", "xl"].map((sz) => (
101
+ <Dialog key={sz as string}>
102
+ <DialogTrigger asChild>
103
+ <Button variant="outline">Open {String(sz)}</Button>
104
+ </DialogTrigger>
105
+ <DialogContent size={sz as any}>
106
+ <DialogHeader>
107
+ <DialogTitle>Size: {String(sz)}</DialogTitle>
108
+ </DialogHeader>
109
+ <div className="text-sm">Content for {String(sz)}</div>
110
+ </DialogContent>
111
+ </Dialog>
112
+ ))}
113
+ </div>
114
+ );
115
+ }
116
+ ```
117
+
118
+ ---
119
+
120
+ ## Notes
121
+
122
+ - **Accessibility**: Use `DialogTitle` and `DialogDescription` for screen readers.
123
+ - **Styling**: Customize panel via `className` on `DialogContent`.
124
+ - **Closing**: A close button is rendered in the top-right of `DialogContent`.
125
+
@@ -0,0 +1,127 @@
1
+ # Drawer
2
+
3
+ ## Overview
4
+
5
+ Sliding panel component (top/right/bottom/left) built on Vaul. Supports modal behavior, background scaling, snap points, and full keyboard accessibility.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ ### Drawer (Root)
12
+
13
+ | Prop | Type | Default | Description |
14
+ | -------------------- | ------------------------------------- | ----------- | ------------------------------------------------------------------ |
15
+ | `open` | `boolean` | `undefined` | Controlled open state. |
16
+ | `onOpenChange` | `(open: boolean) => void` | `undefined` | Called when open state changes. |
17
+ | `direction` | `"top" | "right" | "bottom" | "left"` | `"bottom"` | Drawer opening direction. |
18
+ | `modal` | `boolean` | `true` | Modal behavior (trap focus, block background interaction). |
19
+ | `shouldScaleBackground` | `boolean` | `true` | Scales the background when the drawer is open. |
20
+ | `snapPoints` | `number[]` | `[]` | Optional snap points (fractions of viewport: e.g., `0.4`, `0.6`). |
21
+ | `activeSnapPoint` | `number | string` | `undefined` | The active snap point index/value. |
22
+ | `closeThreshold` | `number` | `undefined` | Threshold to trigger close on drag. |
23
+
24
+ ### Subcomponents
25
+
26
+ - `DrawerTrigger`: Element that opens the drawer (supports `asChild`).
27
+ - `DrawerPortal` / `DrawerOverlay`: Portal root and backdrop.
28
+ - `DrawerContent`: Panel container; includes a grab handle in bottom direction.
29
+ - `DrawerHeader` / `DrawerFooter`: Layout helpers for content.
30
+ - `DrawerTitle` / `DrawerDescription`: Header title and description.
31
+ - `DrawerClose`: Close button helper to wrap an element.
32
+
33
+ ---
34
+
35
+ ## Behavior
36
+
37
+ - **Directions**: Open from any side via `direction` prop.
38
+ - **Snap points**: Provide a list of fractional heights; control active point via `activeSnapPoint`.
39
+ - **Modal**: When `modal` is true, interaction outside is blocked and overlay is shown.
40
+ - **Accessibility**: Focus trapping and keyboard navigation handled by the underlying library.
41
+
42
+ ---
43
+
44
+ ## Examples
45
+
46
+ ### Interactive Drawer
47
+
48
+ ```tsx
49
+ import { Button } from "laif-ds";
50
+ import {
51
+ Drawer,
52
+ DrawerTrigger,
53
+ DrawerContent,
54
+ DrawerHeader,
55
+ DrawerTitle,
56
+ DrawerDescription,
57
+ DrawerFooter,
58
+ DrawerClose,
59
+ } from "laif-ds";
60
+ import { Input } from "laif-ds";
61
+
62
+ export function InteractiveDrawer() {
63
+ return (
64
+ <Drawer direction="bottom" modal shouldScaleBackground>
65
+ <DrawerTrigger asChild>
66
+ <Button variant="outline">Apri Drawer</Button>
67
+ </DrawerTrigger>
68
+ <DrawerContent>
69
+ <DrawerHeader>
70
+ <DrawerTitle>Drawer di Esempio</DrawerTitle>
71
+ <DrawerDescription>
72
+ Personalizza contenuti e comportamento tramite le props.
73
+ </DrawerDescription>
74
+ </DrawerHeader>
75
+ <div className="space-y-4 p-4">
76
+ <Input label="Nome" placeholder="Inserisci il tuo nome" />
77
+ <Input label="Email" type="email" placeholder="Inserisci la tua email" />
78
+ </div>
79
+ <DrawerFooter>
80
+ <Button>Salva modifiche</Button>
81
+ <DrawerClose asChild>
82
+ <Button variant="outline">Annulla</Button>
83
+ </DrawerClose>
84
+ </DrawerFooter>
85
+ </DrawerContent>
86
+ </Drawer>
87
+ );
88
+ }
89
+ ```
90
+
91
+ ### With Snap Points
92
+
93
+ ```tsx
94
+ import { Button } from "laif-ds";
95
+ import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose } from "laif-ds";
96
+
97
+ export function DrawerWithSnapPoints() {
98
+ const snapPoints = [0.4, 0.6, 0.9];
99
+ return (
100
+ <Drawer snapPoints={snapPoints} activeSnapPoint={0}>
101
+ <DrawerTrigger asChild>
102
+ <Button variant="outline">Drawer con Snap Points</Button>
103
+ </DrawerTrigger>
104
+ <DrawerContent>
105
+ <DrawerHeader>
106
+ <DrawerTitle>Drawer con Snap Points</DrawerTitle>
107
+ <DrawerDescription>Snap a 40%, 60% e 90% dell'altezza.</DrawerDescription>
108
+ </DrawerHeader>
109
+ <DrawerFooter>
110
+ <DrawerClose asChild>
111
+ <Button variant="outline">Chiudi</Button>
112
+ </DrawerClose>
113
+ </DrawerFooter>
114
+ </DrawerContent>
115
+ </Drawer>
116
+ );
117
+ }
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Notes
123
+
124
+ - **Handle**: A grab handle is visible for bottom direction.
125
+ - **Layout**: Use `DrawerHeader`/`DrawerFooter` and your own content in between.
126
+ - **Styling**: Customize via `className` on `DrawerContent`.
127
+
@@ -0,0 +1,57 @@
1
+ # DropdownMenu
2
+
3
+ ## Overview
4
+
5
+ Contextual menu built on Radix Dropdown Menu with support for submenus, checkboxes, radio items, labels, separators, and shortcuts.
6
+
7
+ ---
8
+
9
+ ## Exports
10
+
11
+ - `DropdownMenu`, `DropdownMenuTrigger`, `DropdownMenuContent`
12
+ - `DropdownMenuItem`, `DropdownMenuCheckboxItem`, `DropdownMenuRadioItem`
13
+ - `DropdownMenuLabel`, `DropdownMenuSeparator`, `DropdownMenuShortcut`
14
+ - `DropdownMenuGroup`, `DropdownMenuPortal`
15
+ - `DropdownMenuSub`, `DropdownMenuSubContent`, `DropdownMenuSubTrigger`
16
+ - `DropdownMenuRadioGroup`
17
+
18
+ All components extend Radix props.
19
+
20
+ ---
21
+
22
+ ## Example
23
+
24
+ ```tsx
25
+ import {
26
+ DropdownMenu,
27
+ DropdownMenuTrigger,
28
+ DropdownMenuContent,
29
+ DropdownMenuItem,
30
+ DropdownMenuSeparator,
31
+ DropdownMenuSub,
32
+ DropdownMenuSubTrigger,
33
+ DropdownMenuSubContent,
34
+ } from "laif-ds";
35
+ import { Button } from "laif-ds";
36
+
37
+ export function UserMenu() {
38
+ return (
39
+ <DropdownMenu>
40
+ <DropdownMenuTrigger asChild>
41
+ <Button variant="outline">Open</Button>
42
+ </DropdownMenuTrigger>
43
+ <DropdownMenuContent sideOffset={4}>
44
+ <DropdownMenuItem>Profile</DropdownMenuItem>
45
+ <DropdownMenuItem>Settings</DropdownMenuItem>
46
+ <DropdownMenuSeparator />
47
+ <DropdownMenuSub>
48
+ <DropdownMenuSubTrigger>More</DropdownMenuSubTrigger>
49
+ <DropdownMenuSubContent>
50
+ <DropdownMenuItem>Theme</DropdownMenuItem>
51
+ </DropdownMenuSubContent>
52
+ </DropdownMenuSub>
53
+ </DropdownMenuContent>
54
+ </DropdownMenu>
55
+ );
56
+ }
57
+ ```
@@ -0,0 +1,99 @@
1
+ # FilePreview
2
+
3
+ ## Overview
4
+
5
+ Compact file chip with name, format/size info, optional remove button, and optional action menu (preview/download/remove). Automatically adapts its preview based on file type (image, text, generic).
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | ---------------- | -------------------------------------------------------------------- | ------------- | ---------------------------------------------------------- |
13
+ | `file` | `File \| { name: string; url: string; type?: string }` | **required** | File object or remote descriptor with `url`. |
14
+ | `onRemove` | `(url: string) => void` | `undefined` | Called when user removes the file. |
15
+ | `onPreview` | `(url: string) => void` | `undefined` | Called when user clicks Preview from the action menu. |
16
+ | `onDownload` | `(url: string) => void` | `undefined` | Called when user clicks Download from the action menu. |
17
+ | `showActionMenu` | `boolean` | `false` | Show overflow menu (Preview/Download/Delete if provided). |
18
+ | `className` | `string` | `""` | Additional classes for the wrapper. |
19
+
20
+ ---
21
+
22
+ ## Behavior
23
+
24
+ - **Automatic preview**:
25
+ - Images: thumbnail preview.
26
+ - Text: small snippet (first 100 chars).
27
+ - Generic: file-type icon and labels.
28
+ - **Format & size**: Displays file size (if available) and format label (e.g., PDF, JPG).
29
+ - **Actions**:
30
+ - Inline remove button if `onRemove` is provided and `showActionMenu` is false.
31
+ - Popover action menu when `showActionMenu` is true, using `onPreview`, `onDownload`, `onRemove`.
32
+
33
+ ---
34
+
35
+ ## Examples
36
+
37
+ ### Image
38
+
39
+ ```tsx
40
+ import { FilePreview } from "laif-ds";
41
+
42
+ export function ImagePreview() {
43
+ return (
44
+ <FilePreview
45
+ file={{ name: "photo.jpg", url: "https://picsum.photos/id/237/200/200", type: "image/jpeg" }}
46
+ onPreview={(url) => console.log("preview", url)}
47
+ onDownload={(url) => console.log("download", url)}
48
+ />
49
+ );
50
+ }
51
+ ```
52
+
53
+ ### With Remove Button
54
+
55
+ ```tsx
56
+ import { FilePreview } from "laif-ds";
57
+
58
+ export function RemovablePreview() {
59
+ return (
60
+ <FilePreview
61
+ file={{
62
+ name: "document.docx",
63
+ url: "https://example.com/document.docx",
64
+ type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
65
+ }}
66
+ onRemove={(url) => console.log("remove", url)}
67
+ onPreview={(url) => console.log("preview", url)}
68
+ onDownload={(url) => console.log("download", url)}
69
+ />
70
+ );
71
+ }
72
+ ```
73
+
74
+ ### With Action Menu
75
+
76
+ ```tsx
77
+ import { FilePreview } from "laif-ds";
78
+
79
+ export function WithMenu() {
80
+ return (
81
+ <FilePreview
82
+ file={{ name: "presentation.ppt", url: "https://example.com/presentation.ppt", type: "application/vnd.ms-powerpoint" }}
83
+ showActionMenu
84
+ onPreview={(url) => console.log("preview", url)}
85
+ onDownload={(url) => console.log("download", url)}
86
+ onRemove={(url) => console.log("remove", url)}
87
+ />
88
+ );
89
+ }
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Notes
95
+
96
+ - **Thumbnails**: Image previews use object-fit to contain within the chip.
97
+ - **Security**: For local `File` previews, temporary object URLs are created; cleanup is handled by the browser GC.
98
+ - **Internationalization**: Text labels in the action menu can be adjusted at call sites when needed.
99
+
@@ -0,0 +1,139 @@
1
+ # FilePreviewer
2
+
3
+ ## Overview
4
+
5
+ Modal file preview component with support for images, PDFs (including secure read-only mode), audio, video, text, and Office documents (via online viewers). Use helper functions to open the modal from anywhere; mount the component once.
6
+
7
+ ---
8
+
9
+ ## API
10
+
11
+ ### Functions
12
+
13
+ | Function | Signature | Description |
14
+ | ----------------------- | ------------------------------------------------------------- | --------------------------------------------------------- |
15
+ | `previewFileModal` | `(arg: string | PreviewOptions) => Promise<void>` | Opens the preview modal. Resolves when closed. |
16
+ | `safePreviewFileModal` | `(arg: string | PreviewOptions) => Promise<void | undefined>` | Safe variant that never throws on close. |
17
+
18
+ ```ts
19
+ export type PreviewOptions = {
20
+ url?: string;
21
+ filename?: string;
22
+ mimeType?: string;
23
+ title?: React.ReactNode;
24
+ readOnly?: boolean; // Enables SecurePdfViewer for PDFs
25
+ page?: number; // Initial page for PDFs (1-based)
26
+ };
27
+ ```
28
+
29
+ ### Component
30
+
31
+ - `FilePreviewer`: Mount once near the app root. Controls the dialog UI and renders the appropriate preview body.
32
+
33
+ ---
34
+
35
+ ## Behavior
36
+
37
+ - **Kind detection**: Determines preview type from `mimeType`, `filename` or `url`.
38
+ - **Image**: Responsive `<img>` with contain fit.
39
+ - **PDF**:
40
+ - `readOnly=true` uses `SecurePdfViewer` with `page` support.
41
+ - Otherwise embedded via `<iframe>` (supports `#page=` parameter).
42
+ - **Audio/Video**: Native `<audio>`/`<video>` players.
43
+ - **Text**: Rendered in an `<iframe>` for remote text URLs.
44
+ - **Office**: Uses an online viewer when `url` is HTTP(S); otherwise shows a fallback notice.
45
+ - **Dialog**: Uses `Dialog` with `size="xl"` and a heading showing `title` or `filename` with a file icon.
46
+
47
+ ---
48
+
49
+ ## Examples
50
+
51
+ ### Preview an Image (URL)
52
+
53
+ ```tsx
54
+ import { Button } from "laif-ds";
55
+ import { FilePreviewer, previewFileModal } from "laif-ds";
56
+
57
+ export function PreviewImageButton() {
58
+ return (
59
+ <>
60
+ <Button
61
+ onClick={() =>
62
+ previewFileModal({
63
+ url: "https://picsum.photos/id/1003/1200/800",
64
+ filename: "image.jpg",
65
+ title: "Random Image",
66
+ })
67
+ }
68
+ >
69
+ Preview Image
70
+ </Button>
71
+ <FilePreviewer />
72
+ </>
73
+ );
74
+ }
75
+ ```
76
+
77
+ ### PDF with Read-only Secure Viewer
78
+
79
+ ```tsx
80
+ import { Button } from "laif-ds";
81
+ import { FilePreviewer, previewFileModal } from "laif-ds";
82
+
83
+ export function PreviewPdf() {
84
+ return (
85
+ <>
86
+ <Button
87
+ onClick={() =>
88
+ previewFileModal({
89
+ url: "https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf",
90
+ filename: "dummy.pdf",
91
+ title: "PDF Document",
92
+ readOnly: true,
93
+ page: 1,
94
+ })
95
+ }
96
+ >
97
+ Preview PDF
98
+ </Button>
99
+ <FilePreviewer />
100
+ </>
101
+ );
102
+ }
103
+ ```
104
+
105
+ ### Office Document (XLSX)
106
+
107
+ ```tsx
108
+ import { Button } from "laif-ds";
109
+ import { FilePreviewer, previewFileModal } from "laif-ds";
110
+
111
+ export function PreviewSpreadsheet() {
112
+ return (
113
+ <>
114
+ <Button
115
+ onClick={() =>
116
+ previewFileModal({
117
+ url: "https://filesamples.com/samples/document/xlsx/sample3.xlsx",
118
+ filename: "spreadsheet.xlsx",
119
+ title: "Excel Spreadsheet",
120
+ readOnly: true,
121
+ })
122
+ }
123
+ >
124
+ Preview XLSX
125
+ </Button>
126
+ <FilePreviewer />
127
+ </>
128
+ );
129
+ }
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Notes
135
+
136
+ - **Mount**: Add a single `<FilePreviewer />` near app root or in Storybook decorators.
137
+ - **Filenames**: If `filename` is omitted, it is inferred from `url`.
138
+ - **Security**: For local files, prefer read-only mode for PDFs when appropriate.
139
+
@@ -0,0 +1,129 @@
1
+ # FileUploader
2
+
3
+ ## Overview
4
+
5
+ Drag-and-drop uploader with keyboard activation, file type filtering, limits (count/total size), previews via `FilePreview`, and external upload integration.
6
+
7
+ ---
8
+
9
+ ## Props
10
+
11
+ | Prop | Type | Default | Description |
12
+ | ------------------ | --------------------------------------- | --------------------------------------------------------- | ---------------------------------------------------------- |
13
+ | `extensions` | `AcceptItem[]` | `["pdf","image","video","audio"]` | Allowed extensions/categories (maps to accept attribute). |
14
+ | `multiple` | `boolean` | `false` | Enables multiple file selection. |
15
+ | `onUpload` | `(files: File[]) => void` | `undefined` | Called whenever selected files change. |
16
+ | `description` | `string` | `"Trascina un file o clicca per selezionare"` | Dropzone hint. |
17
+ | `formatDescription`| `string` | `"Formato accettato: PDF, Immagini, Video, Audio"` | Accepted formats hint. |
18
+ | `selectedLabel` | `string` | `"File selezionati"` | Title shown above selected files list. |
19
+ | `removeAllLabel` | `string` | `"rimuovi tutto"` | Label for the "remove all" button. |
20
+ | `maxTotalSize` | `number` (bytes) | `undefined` | Maximum total size of selected files. |
21
+ | `maxFiles` | `number` | `undefined` | Maximum number of files (when `multiple` is true). |
22
+
23
+ `AcceptItem` includes: `pdf | doc | docx | xls | xlsx | ppt | pptx | txt | csv | jpg | jpeg | png | gif | image | video | audio`.
24
+
25
+ ---
26
+
27
+ ## Behavior
28
+
29
+ - **Dropzone**: Click or drag files; keyboard accessible (Enter/Space opens file dialog).
30
+ - **Filtering**: `extensions` map to accept string; only matching files are added.
31
+ - **Limits**: Enforces `maxFiles` and `maxTotalSize` (with compact error caption).
32
+ - **Previews**: Renders selected files with `FilePreview`; supports remove per file and remove-all.
33
+ - **Integration**: `onUpload` provides the current `File[]`; perform the actual upload externally.
34
+
35
+ ---
36
+
37
+ ## Examples
38
+
39
+ ### Default
40
+
41
+ ```tsx
42
+ import { FileUploader } from "laif-ds";
43
+
44
+ export function DefaultUploader() {
45
+ return <FileUploader multiple={false} />;
46
+ }
47
+ ```
48
+
49
+ ### Multiple + Custom Extensions
50
+
51
+ ```tsx
52
+ import { FileUploader, type AcceptItem } from "laif-ds";
53
+
54
+ const exts: AcceptItem[] = [
55
+ "pdf","doc","docx","xls","xlsx","ppt","pptx","txt","csv","jpg","jpeg","png","gif","image","video","audio",
56
+ ];
57
+
58
+ export function MultiUploader() {
59
+ return (
60
+ <FileUploader
61
+ multiple
62
+ extensions={exts}
63
+ description="Seleziona più file"
64
+ formatDescription="Trascina o clicca per selezionare più file"
65
+ />
66
+ );
67
+ }
68
+ ```
69
+
70
+ ### With Limits
71
+
72
+ ```tsx
73
+ import { FileUploader } from "laif-ds";
74
+
75
+ export function LimitedUploader() {
76
+ return (
77
+ <FileUploader
78
+ multiple
79
+ maxFiles={3}
80
+ maxTotalSize={10 * 1024 * 1024} // 10 MB
81
+ description="Con limiti su numero e dimensione totale"
82
+ formatDescription="Esempio: max 3 file, max totale 10 MB"
83
+ />
84
+ );
85
+ }
86
+ ```
87
+
88
+ ### External Upload Flow
89
+
90
+ ```tsx
91
+ import * as React from "react";
92
+ import { Button } from "laif-ds";
93
+ import { FileUploader } from "laif-ds";
94
+
95
+ export function ExternalUploadExample() {
96
+ const [files, setFiles] = React.useState<File[]>([]);
97
+ const [loading, setLoading] = React.useState(false);
98
+
99
+ const handleSubmit = async () => {
100
+ setLoading(true);
101
+ // ...upload files
102
+ await new Promise((r) => setTimeout(r, 1500));
103
+ setLoading(false);
104
+ alert(`Upload completato: ${files.length} file`);
105
+ };
106
+
107
+ return (
108
+ <div className="space-y-4">
109
+ <FileUploader multiple onUpload={setFiles} />
110
+ {files.length > 0 && (
111
+ <div className="flex justify-end">
112
+ <Button onClick={handleSubmit} isLoading={loading} iconLeft="Upload">
113
+ {loading ? "Caricamento..." : `Carica ${files.length} file`}
114
+ </Button>
115
+ </div>
116
+ )}
117
+ </div>
118
+ );
119
+ }
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Notes
125
+
126
+ - **A11y**: Dropzone is a button-like region with `aria-describedby` hints and keyboard support.
127
+ - **Errors**: Limit violations are summarized in a compact caption.
128
+ - **Localization**: Provide localized `description`/`formatDescription`/labels when needed.
129
+