@particle-academy/react-fancy 5.58.0 → 5.60.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 +84 -0
- package/dist/{PdfViewer.types-DyoUBa2g.d.cts → PdfViewer.types-BRtcZt-X.d.cts} +28 -2
- package/dist/{PdfViewer.types-BEk2Jq6p.d.ts → PdfViewer.types-sM52m3OI.d.ts} +28 -2
- package/dist/{chunk-MTTRPPHH.js → chunk-5PHPJL7Z.js} +3 -3
- package/dist/{chunk-MTTRPPHH.js.map → chunk-5PHPJL7Z.js.map} +1 -1
- package/dist/{chunk-7MDHCYEB.cjs → chunk-5QKQXM5V.cjs} +52 -5
- package/dist/chunk-5QKQXM5V.cjs.map +1 -0
- package/dist/{chunk-2GFM5WD4.cjs → chunk-AGO4AA3K.cjs} +57 -9
- package/dist/chunk-AGO4AA3K.cjs.map +1 -0
- package/dist/{chunk-SLCR7A6W.cjs → chunk-AQ4DZT4Y.cjs} +4 -4
- package/dist/{chunk-SLCR7A6W.cjs.map → chunk-AQ4DZT4Y.cjs.map} +1 -1
- package/dist/chunk-CEFK54WP.cjs +186 -0
- package/dist/chunk-CEFK54WP.cjs.map +1 -0
- package/dist/{chunk-MORXQ5UM.js → chunk-CS2ZYMYP.js} +54 -7
- package/dist/chunk-CS2ZYMYP.js.map +1 -0
- package/dist/chunk-GDF6XTHC.js +184 -0
- package/dist/chunk-GDF6XTHC.js.map +1 -0
- package/dist/{chunk-ZAX72LXL.js → chunk-JEHV7PYP.js} +58 -10
- package/dist/chunk-JEHV7PYP.js.map +1 -0
- package/dist/{chunk-6XX6OHAP.cjs → chunk-M77BB2QI.cjs} +3 -3
- package/dist/{chunk-6XX6OHAP.cjs.map → chunk-M77BB2QI.cjs.map} +1 -1
- package/dist/{chunk-YBRQTZKV.js → chunk-ZGQEKDG6.js} +3 -3
- package/dist/{chunk-YBRQTZKV.js.map → chunk-ZGQEKDG6.js.map} +1 -1
- package/dist/file-upload.cjs +3 -3
- package/dist/file-upload.d.cts +7 -1
- package/dist/file-upload.d.ts +7 -1
- package/dist/file-upload.js +1 -1
- package/dist/{index-Bwrc9ktU.d.ts → index-BiyyxWtb.d.ts} +1 -1
- package/dist/{index-Bd4br4sF.d.cts → index-WG8UdfiE.d.cts} +1 -1
- package/dist/index.cjs +47 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -1
- package/dist/inputs.cjs +7 -7
- package/dist/inputs.js +3 -3
- package/dist/json-editor.cjs +13 -13
- package/dist/json-editor.js +2 -2
- package/dist/media-viewer.cjs +3 -3
- package/dist/media-viewer.d.cts +2 -2
- package/dist/media-viewer.d.ts +2 -2
- package/dist/media-viewer.js +2 -2
- package/dist/pdf-viewer.cjs +2 -2
- package/dist/pdf-viewer.d.cts +2 -2
- package/dist/pdf-viewer.d.ts +2 -2
- package/dist/pdf-viewer.js +1 -1
- package/dist/resizable-panels.cjs +13 -0
- package/dist/resizable-panels.cjs.map +1 -0
- package/dist/resizable-panels.d.cts +68 -0
- package/dist/resizable-panels.d.ts +68 -0
- package/dist/resizable-panels.js +4 -0
- package/dist/resizable-panels.js.map +1 -0
- package/dist/time-grid.d.cts +3 -2
- package/dist/time-grid.d.ts +3 -2
- package/docs/FileUpload.md +3 -0
- package/docs/ResizablePanels.md +81 -0
- package/package.json +11 -1
- package/dist/chunk-2GFM5WD4.cjs.map +0 -1
- package/dist/chunk-7MDHCYEB.cjs.map +0 -1
- package/dist/chunk-MORXQ5UM.js.map +0 -1
- package/dist/chunk-ZAX72LXL.js.map +0 -1
package/dist/json-editor.cjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkM77BB2QI_cjs = require('./chunk-M77BB2QI.cjs');
|
|
4
|
+
require('./chunk-TLRFXSPA.cjs');
|
|
4
5
|
require('./chunk-JRRYYW3Y.cjs');
|
|
5
6
|
require('./chunk-GLGUQGAQ.cjs');
|
|
6
7
|
require('./chunk-2O5UXH5R.cjs');
|
|
7
|
-
require('./chunk-TLRFXSPA.cjs');
|
|
8
8
|
require('./chunk-MAZEX4EZ.cjs');
|
|
9
9
|
require('./chunk-MRZXTL46.cjs');
|
|
10
10
|
require('./chunk-P53432AK.cjs');
|
|
@@ -33,47 +33,47 @@ require('./chunk-ZU5Q77OT.cjs');
|
|
|
33
33
|
|
|
34
34
|
Object.defineProperty(exports, "JsonEditor", {
|
|
35
35
|
enumerable: true,
|
|
36
|
-
get: function () { return
|
|
36
|
+
get: function () { return chunkM77BB2QI_cjs.JsonEditor; }
|
|
37
37
|
});
|
|
38
38
|
Object.defineProperty(exports, "applyJsonEdit", {
|
|
39
39
|
enumerable: true,
|
|
40
|
-
get: function () { return
|
|
40
|
+
get: function () { return chunkM77BB2QI_cjs.applyJsonEdit; }
|
|
41
41
|
});
|
|
42
42
|
Object.defineProperty(exports, "describeEdit", {
|
|
43
43
|
enumerable: true,
|
|
44
|
-
get: function () { return
|
|
44
|
+
get: function () { return chunkM77BB2QI_cjs.describeEdit; }
|
|
45
45
|
});
|
|
46
46
|
Object.defineProperty(exports, "findJsonConflicts", {
|
|
47
47
|
enumerable: true,
|
|
48
|
-
get: function () { return
|
|
48
|
+
get: function () { return chunkM77BB2QI_cjs.findJsonConflicts; }
|
|
49
49
|
});
|
|
50
50
|
Object.defineProperty(exports, "getAtPath", {
|
|
51
51
|
enumerable: true,
|
|
52
|
-
get: function () { return
|
|
52
|
+
get: function () { return chunkM77BB2QI_cjs.getAtPath; }
|
|
53
53
|
});
|
|
54
54
|
Object.defineProperty(exports, "inferType", {
|
|
55
55
|
enumerable: true,
|
|
56
|
-
get: function () { return
|
|
56
|
+
get: function () { return chunkM77BB2QI_cjs.inferType; }
|
|
57
57
|
});
|
|
58
58
|
Object.defineProperty(exports, "parseKeyMap", {
|
|
59
59
|
enumerable: true,
|
|
60
|
-
get: function () { return
|
|
60
|
+
get: function () { return chunkM77BB2QI_cjs.parseKeyMap; }
|
|
61
61
|
});
|
|
62
62
|
Object.defineProperty(exports, "parsePath", {
|
|
63
63
|
enumerable: true,
|
|
64
|
-
get: function () { return
|
|
64
|
+
get: function () { return chunkM77BB2QI_cjs.parsePath; }
|
|
65
65
|
});
|
|
66
66
|
Object.defineProperty(exports, "pathToString", {
|
|
67
67
|
enumerable: true,
|
|
68
|
-
get: function () { return
|
|
68
|
+
get: function () { return chunkM77BB2QI_cjs.pathToString; }
|
|
69
69
|
});
|
|
70
70
|
Object.defineProperty(exports, "resolveKeyRule", {
|
|
71
71
|
enumerable: true,
|
|
72
|
-
get: function () { return
|
|
72
|
+
get: function () { return chunkM77BB2QI_cjs.resolveKeyRule; }
|
|
73
73
|
});
|
|
74
74
|
Object.defineProperty(exports, "typeMatches", {
|
|
75
75
|
enumerable: true,
|
|
76
|
-
get: function () { return
|
|
76
|
+
get: function () { return chunkM77BB2QI_cjs.typeMatches; }
|
|
77
77
|
});
|
|
78
78
|
//# sourceMappingURL=json-editor.cjs.map
|
|
79
79
|
//# sourceMappingURL=json-editor.cjs.map
|
package/dist/json-editor.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { JsonEditor, applyJsonEdit, describeEdit, findJsonConflicts, getAtPath, inferType, parseKeyMap, parsePath, pathToString, resolveKeyRule, typeMatches } from './chunk-
|
|
1
|
+
export { JsonEditor, applyJsonEdit, describeEdit, findJsonConflicts, getAtPath, inferType, parseKeyMap, parsePath, pathToString, resolveKeyRule, typeMatches } from './chunk-ZGQEKDG6.js';
|
|
2
|
+
import './chunk-2UTN3EFK.js';
|
|
2
3
|
import './chunk-XQDGUXMS.js';
|
|
3
4
|
import './chunk-T45LBTXH.js';
|
|
4
5
|
import './chunk-DXZCKDYS.js';
|
|
5
|
-
import './chunk-2UTN3EFK.js';
|
|
6
6
|
import './chunk-UVUBV4VZ.js';
|
|
7
7
|
import './chunk-KXYMMNNV.js';
|
|
8
8
|
import './chunk-WX5XYDVN.js';
|
package/dist/media-viewer.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkAQ4DZT4Y_cjs = require('./chunk-AQ4DZT4Y.cjs');
|
|
4
4
|
require('./chunk-TH7VP4CL.cjs');
|
|
5
|
-
require('./chunk-
|
|
5
|
+
require('./chunk-5QKQXM5V.cjs');
|
|
6
6
|
require('./chunk-7QENPLOP.cjs');
|
|
7
7
|
require('./chunk-M5SEYDSS.cjs');
|
|
8
8
|
require('./chunk-T6YELZPJ.cjs');
|
|
@@ -14,7 +14,7 @@ require('./chunk-ZU5Q77OT.cjs');
|
|
|
14
14
|
|
|
15
15
|
Object.defineProperty(exports, "MediaViewer", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkAQ4DZT4Y_cjs.MediaViewer; }
|
|
18
18
|
});
|
|
19
19
|
//# sourceMappingURL=media-viewer.cjs.map
|
|
20
20
|
//# sourceMappingURL=media-viewer.cjs.map
|
package/dist/media-viewer.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { a as MediaViewer, b as MediaViewerProps } from './index-
|
|
1
|
+
export { a as MediaViewer, b as MediaViewerProps } from './index-WG8UdfiE.cjs';
|
|
2
2
|
import 'react';
|
|
3
3
|
import './ImageViewer.types-CtqaA6KV.cjs';
|
|
4
4
|
import './FauxClient.types-Dtk9aRs6.cjs';
|
|
5
5
|
import './VideoViewer.types-_AwQ8DQr.cjs';
|
|
6
6
|
import './AudioViewer.types-CyhmQVQd.cjs';
|
|
7
|
-
import './PdfViewer.types-
|
|
7
|
+
import './PdfViewer.types-BRtcZt-X.cjs';
|
package/dist/media-viewer.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { a as MediaViewer, b as MediaViewerProps } from './index-
|
|
1
|
+
export { a as MediaViewer, b as MediaViewerProps } from './index-BiyyxWtb.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
import './ImageViewer.types-BDTxBYEN.js';
|
|
4
4
|
import './FauxClient.types-Dtk9aRs6.js';
|
|
5
5
|
import './VideoViewer.types-_AwQ8DQr.js';
|
|
6
6
|
import './AudioViewer.types-CyhmQVQd.js';
|
|
7
|
-
import './PdfViewer.types-
|
|
7
|
+
import './PdfViewer.types-sM52m3OI.js';
|
package/dist/media-viewer.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { MediaViewer } from './chunk-
|
|
1
|
+
export { MediaViewer } from './chunk-5PHPJL7Z.js';
|
|
2
2
|
import './chunk-VOGI7GX3.js';
|
|
3
|
-
import './chunk-
|
|
3
|
+
import './chunk-CS2ZYMYP.js';
|
|
4
4
|
import './chunk-ICMLLZKZ.js';
|
|
5
5
|
import './chunk-GVMWJ4NI.js';
|
|
6
6
|
import './chunk-CPY7NHXM.js';
|
package/dist/pdf-viewer.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunk5QKQXM5V_cjs = require('./chunk-5QKQXM5V.cjs');
|
|
4
4
|
require('./chunk-M5SEYDSS.cjs');
|
|
5
5
|
require('./chunk-SNHU2AI4.cjs');
|
|
6
6
|
require('./chunk-ZU5Q77OT.cjs');
|
|
@@ -9,7 +9,7 @@ require('./chunk-ZU5Q77OT.cjs');
|
|
|
9
9
|
|
|
10
10
|
Object.defineProperty(exports, "PdfViewer", {
|
|
11
11
|
enumerable: true,
|
|
12
|
-
get: function () { return
|
|
12
|
+
get: function () { return chunk5QKQXM5V_cjs.PdfViewer; }
|
|
13
13
|
});
|
|
14
14
|
//# sourceMappingURL=pdf-viewer.cjs.map
|
|
15
15
|
//# sourceMappingURL=pdf-viewer.cjs.map
|
package/dist/pdf-viewer.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import {
|
|
3
|
-
export { P as
|
|
2
|
+
import { c as PdfViewerProps } from './PdfViewer.types-BRtcZt-X.cjs';
|
|
3
|
+
export { P as PdfPageErrorContext, a as PdfPageSource, b as PdfViewerPolicy, d as PdfViewerWatermark } from './PdfViewer.types-BRtcZt-X.cjs';
|
|
4
4
|
import './FauxClient.types-Dtk9aRs6.cjs';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/pdf-viewer.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import {
|
|
3
|
-
export { P as
|
|
2
|
+
import { c as PdfViewerProps } from './PdfViewer.types-sM52m3OI.js';
|
|
3
|
+
export { P as PdfPageErrorContext, a as PdfPageSource, b as PdfViewerPolicy, d as PdfViewerWatermark } from './PdfViewer.types-sM52m3OI.js';
|
|
4
4
|
import './FauxClient.types-Dtk9aRs6.js';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/pdf-viewer.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkCEFK54WP_cjs = require('./chunk-CEFK54WP.cjs');
|
|
4
|
+
require('./chunk-ZU5Q77OT.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, "ResizablePanels", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function () { return chunkCEFK54WP_cjs.ResizablePanels; }
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=resizable-panels.cjs.map
|
|
13
|
+
//# sourceMappingURL=resizable-panels.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"resizable-panels.cjs"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* How the two PANELS are laid out.
|
|
6
|
+
*
|
|
7
|
+
* - `"horizontal"`: side by side. The separator is a vertical bar
|
|
8
|
+
* (`aria-orientation="vertical"`), moved with ArrowLeft / ArrowRight.
|
|
9
|
+
* - `"vertical"`: stacked. The separator is a horizontal bar
|
|
10
|
+
* (`aria-orientation="horizontal"`), moved with ArrowUp / ArrowDown.
|
|
11
|
+
*/
|
|
12
|
+
type ResizablePanelsOrientation = "horizontal" | "vertical";
|
|
13
|
+
interface ResizablePanelsProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "defaultValue" | "onChange"> {
|
|
14
|
+
/**
|
|
15
|
+
* Exactly two children: the PRIMARY panel (first, left / top) and the
|
|
16
|
+
* secondary panel (second, right / bottom). Further children are ignored.
|
|
17
|
+
*/
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Controlled size of the primary panel, as a PERCENTAGE (0-100) of the
|
|
21
|
+
* container. Clamped to `min` / `max`.
|
|
22
|
+
*/
|
|
23
|
+
value?: number;
|
|
24
|
+
/** Uncontrolled starting size, a percentage. Default `50`. */
|
|
25
|
+
defaultValue?: number;
|
|
26
|
+
/** Fires on every change while dragging or pressing keys. */
|
|
27
|
+
onValueChange?: (value: number) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Fires ONCE when a gesture ends: at pointer release (or cancel) and at key
|
|
30
|
+
* release, and only if the value changed. This is the moment to persist a
|
|
31
|
+
* per-user size; the host owns persistence.
|
|
32
|
+
*/
|
|
33
|
+
onValueCommit?: (value: number) => void;
|
|
34
|
+
/** Smallest primary size, a percentage. Default `10`. */
|
|
35
|
+
min?: number;
|
|
36
|
+
/** Largest primary size, a percentage. Default `90`. */
|
|
37
|
+
max?: number;
|
|
38
|
+
/** Panel layout. Default `"horizontal"` (side by side). */
|
|
39
|
+
orientation?: ResizablePanelsOrientation;
|
|
40
|
+
/** Arrow-key step, in percentage points. Default `5`. */
|
|
41
|
+
step?: number;
|
|
42
|
+
/** Shift + Arrow step, in percentage points. Default `20`. */
|
|
43
|
+
largeStep?: number;
|
|
44
|
+
/** Accessible name of the separator. Default `"Resize panels"`. */
|
|
45
|
+
label?: string;
|
|
46
|
+
/** Freezes the split: the separator is not focusable and ignores input. */
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Two panels and a draggable, keyboard-operable separator between them — the
|
|
52
|
+
* W3C window-splitter pattern
|
|
53
|
+
* (https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/).
|
|
54
|
+
*
|
|
55
|
+
* `value` is the PRIMARY (first) panel's share of the container, as a
|
|
56
|
+
* percentage. The separator is `role="separator"` with `aria-valuenow/min/max`,
|
|
57
|
+
* `aria-controls` pointing at the primary panel, and a tab stop. Arrow keys
|
|
58
|
+
* along the drag axis move it by `step`, Shift + Arrow by `largeStep`, Home /
|
|
59
|
+
* End jump to `min` / `max`. Pointer and touch drags use pointer capture, so a
|
|
60
|
+
* fast drag that leaves the bar keeps resizing.
|
|
61
|
+
*
|
|
62
|
+
* `onValueChange` fires continuously; `onValueCommit` fires once per gesture
|
|
63
|
+
* (pointer release, key release) so a host can persist a per-user size without
|
|
64
|
+
* writing on every frame. The host owns persistence.
|
|
65
|
+
*/
|
|
66
|
+
declare const ResizablePanels: react.ForwardRefExoticComponent<ResizablePanelsProps & react.RefAttributes<HTMLDivElement>>;
|
|
67
|
+
|
|
68
|
+
export { ResizablePanels, type ResizablePanelsOrientation, type ResizablePanelsProps };
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* How the two PANELS are laid out.
|
|
6
|
+
*
|
|
7
|
+
* - `"horizontal"`: side by side. The separator is a vertical bar
|
|
8
|
+
* (`aria-orientation="vertical"`), moved with ArrowLeft / ArrowRight.
|
|
9
|
+
* - `"vertical"`: stacked. The separator is a horizontal bar
|
|
10
|
+
* (`aria-orientation="horizontal"`), moved with ArrowUp / ArrowDown.
|
|
11
|
+
*/
|
|
12
|
+
type ResizablePanelsOrientation = "horizontal" | "vertical";
|
|
13
|
+
interface ResizablePanelsProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "defaultValue" | "onChange"> {
|
|
14
|
+
/**
|
|
15
|
+
* Exactly two children: the PRIMARY panel (first, left / top) and the
|
|
16
|
+
* secondary panel (second, right / bottom). Further children are ignored.
|
|
17
|
+
*/
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
/**
|
|
20
|
+
* Controlled size of the primary panel, as a PERCENTAGE (0-100) of the
|
|
21
|
+
* container. Clamped to `min` / `max`.
|
|
22
|
+
*/
|
|
23
|
+
value?: number;
|
|
24
|
+
/** Uncontrolled starting size, a percentage. Default `50`. */
|
|
25
|
+
defaultValue?: number;
|
|
26
|
+
/** Fires on every change while dragging or pressing keys. */
|
|
27
|
+
onValueChange?: (value: number) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Fires ONCE when a gesture ends: at pointer release (or cancel) and at key
|
|
30
|
+
* release, and only if the value changed. This is the moment to persist a
|
|
31
|
+
* per-user size; the host owns persistence.
|
|
32
|
+
*/
|
|
33
|
+
onValueCommit?: (value: number) => void;
|
|
34
|
+
/** Smallest primary size, a percentage. Default `10`. */
|
|
35
|
+
min?: number;
|
|
36
|
+
/** Largest primary size, a percentage. Default `90`. */
|
|
37
|
+
max?: number;
|
|
38
|
+
/** Panel layout. Default `"horizontal"` (side by side). */
|
|
39
|
+
orientation?: ResizablePanelsOrientation;
|
|
40
|
+
/** Arrow-key step, in percentage points. Default `5`. */
|
|
41
|
+
step?: number;
|
|
42
|
+
/** Shift + Arrow step, in percentage points. Default `20`. */
|
|
43
|
+
largeStep?: number;
|
|
44
|
+
/** Accessible name of the separator. Default `"Resize panels"`. */
|
|
45
|
+
label?: string;
|
|
46
|
+
/** Freezes the split: the separator is not focusable and ignores input. */
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Two panels and a draggable, keyboard-operable separator between them — the
|
|
52
|
+
* W3C window-splitter pattern
|
|
53
|
+
* (https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/).
|
|
54
|
+
*
|
|
55
|
+
* `value` is the PRIMARY (first) panel's share of the container, as a
|
|
56
|
+
* percentage. The separator is `role="separator"` with `aria-valuenow/min/max`,
|
|
57
|
+
* `aria-controls` pointing at the primary panel, and a tab stop. Arrow keys
|
|
58
|
+
* along the drag axis move it by `step`, Shift + Arrow by `largeStep`, Home /
|
|
59
|
+
* End jump to `min` / `max`. Pointer and touch drags use pointer capture, so a
|
|
60
|
+
* fast drag that leaves the bar keeps resizing.
|
|
61
|
+
*
|
|
62
|
+
* `onValueChange` fires continuously; `onValueCommit` fires once per gesture
|
|
63
|
+
* (pointer release, key release) so a host can persist a per-user size without
|
|
64
|
+
* writing on every frame. The host owns persistence.
|
|
65
|
+
*/
|
|
66
|
+
declare const ResizablePanels: react.ForwardRefExoticComponent<ResizablePanelsProps & react.RefAttributes<HTMLDivElement>>;
|
|
67
|
+
|
|
68
|
+
export { ResizablePanels, type ResizablePanelsOrientation, type ResizablePanelsProps };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"resizable-panels.js"}
|
package/dist/time-grid.d.cts
CHANGED
|
@@ -143,8 +143,9 @@ interface TimeGridProps {
|
|
|
143
143
|
/** Hover, for a host-owned detail panel. `null, null` when the pointer leaves. */
|
|
144
144
|
onCellHover?: (cell: TimeGridCell | null, at: TimeGridCoord | null) => void;
|
|
145
145
|
/**
|
|
146
|
-
* Typed grid: render only the columns in view (plus overscan)
|
|
147
|
-
*
|
|
146
|
+
* Typed grid: render only the columns in view (plus overscan). The column
|
|
147
|
+
* tracks stay the full grid, so the scroll width never changes; each row's
|
|
148
|
+
* first rendered cell is placed explicitly. Default: on above 500 columns. Cell ids,
|
|
148
149
|
* selection and callbacks still cover every cell — they come from `cells`,
|
|
149
150
|
* not the DOM — and keyboard focus or an out-of-view `selection` scrolls the
|
|
150
151
|
* window to it.
|
package/dist/time-grid.d.ts
CHANGED
|
@@ -143,8 +143,9 @@ interface TimeGridProps {
|
|
|
143
143
|
/** Hover, for a host-owned detail panel. `null, null` when the pointer leaves. */
|
|
144
144
|
onCellHover?: (cell: TimeGridCell | null, at: TimeGridCoord | null) => void;
|
|
145
145
|
/**
|
|
146
|
-
* Typed grid: render only the columns in view (plus overscan)
|
|
147
|
-
*
|
|
146
|
+
* Typed grid: render only the columns in view (plus overscan). The column
|
|
147
|
+
* tracks stay the full grid, so the scroll width never changes; each row's
|
|
148
|
+
* first rendered cell is placed explicitly. Default: on above 500 columns. Cell ids,
|
|
148
149
|
* selection and callbacks still cover every cell — they come from `cells`,
|
|
149
150
|
* not the DOM — and keyboard focus or an out-of-view `selection` scrolls the
|
|
150
151
|
* window to it.
|
package/docs/FileUpload.md
CHANGED
|
@@ -39,9 +39,12 @@ Provides file state context to its children.
|
|
|
39
39
|
|
|
40
40
|
Drag-and-drop area that also opens a file picker on click.
|
|
41
41
|
|
|
42
|
+
It contains a native browse `<button type="button">` (`data-react-fancy-file-upload-browse`), so keyboard users can Tab to it and open the picker with Enter or Space. On the default zone the button wraps the icon and copy; with custom `children` it is visually hidden beside them and the zone draws the focus ring. When `disabled`, the button is disabled and the zone carries `aria-disabled="true"`.
|
|
43
|
+
|
|
42
44
|
| Prop | Type | Default | Description |
|
|
43
45
|
|------|------|---------|-------------|
|
|
44
46
|
| `children` | `ReactNode` | Default upload icon + text | Custom dropzone content |
|
|
47
|
+
| `browseLabel` | `string` | The visible copy, or `"Browse files"` with custom children | Accessible name of the browse button |
|
|
45
48
|
| `className` | `string` | - | Additional CSS classes |
|
|
46
49
|
|
|
47
50
|
### `FileUpload.List`
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# ResizablePanels
|
|
2
|
+
|
|
3
|
+
Two panels with a draggable, keyboard-operable separator between them. Follows the W3C [window splitter pattern](https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/).
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { ResizablePanels } from "@particle-academy/react-fancy";
|
|
9
|
+
// or the subpath
|
|
10
|
+
import { ResizablePanels } from "@particle-academy/react-fancy/resizable-panels";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Basic Usage
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
const [size, setSize] = useState(30);
|
|
17
|
+
|
|
18
|
+
<div className="h-96">
|
|
19
|
+
<ResizablePanels
|
|
20
|
+
value={size}
|
|
21
|
+
onValueChange={setSize}
|
|
22
|
+
onValueCommit={(v) => savePreference("sidebar", v)}
|
|
23
|
+
min={15}
|
|
24
|
+
max={60}
|
|
25
|
+
label="Resize sidebar"
|
|
26
|
+
>
|
|
27
|
+
<nav>Sidebar</nav>
|
|
28
|
+
<main>Content</main>
|
|
29
|
+
</ResizablePanels>
|
|
30
|
+
</div>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The component fills its parent (`h-full w-full`); give the parent a size.
|
|
34
|
+
|
|
35
|
+
## Value
|
|
36
|
+
|
|
37
|
+
`value` is the **primary (first) panel's size as a percentage (0-100)** of the container. It is clamped to `min` / `max`, and `min` / `max` are themselves clamped to 0-100, so a panel can never be sized past the container.
|
|
38
|
+
|
|
39
|
+
## Props
|
|
40
|
+
|
|
41
|
+
| Prop | Type | Default | Description |
|
|
42
|
+
|------|------|---------|-------------|
|
|
43
|
+
| `children` | `ReactNode` | **required** | Two children: the primary panel, then the secondary |
|
|
44
|
+
| `value` | `number` | - | Controlled primary size, a percentage |
|
|
45
|
+
| `defaultValue` | `number` | `50` | Uncontrolled starting size |
|
|
46
|
+
| `onValueChange` | `(value: number) => void` | - | Every change while dragging or pressing keys |
|
|
47
|
+
| `onValueCommit` | `(value: number) => void` | - | Once per gesture (pointer release / cancel, key release), only if the value changed. Persist here; the host owns persistence |
|
|
48
|
+
| `min` | `number` | `10` | Smallest primary size |
|
|
49
|
+
| `max` | `number` | `90` | Largest primary size |
|
|
50
|
+
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Panel layout: side by side, or stacked |
|
|
51
|
+
| `step` | `number` | `5` | Arrow-key step, in percentage points |
|
|
52
|
+
| `largeStep` | `number` | `20` | Shift + Arrow step |
|
|
53
|
+
| `label` | `string` | `"Resize panels"` | Accessible name of the separator |
|
|
54
|
+
| `disabled` | `boolean` | `false` | Separator not focusable, ignores input |
|
|
55
|
+
| `className` | `string` | - | Classes on the root |
|
|
56
|
+
|
|
57
|
+
Other HTML attributes (including `data-*` handles) pass through to the root.
|
|
58
|
+
|
|
59
|
+
## Orientation and keys
|
|
60
|
+
|
|
61
|
+
`orientation` names how the **panels** are laid out:
|
|
62
|
+
|
|
63
|
+
| `orientation` | Panels | Separator `aria-orientation` | Keys |
|
|
64
|
+
|---|---|---|---|
|
|
65
|
+
| `"horizontal"` | side by side | `vertical` | ArrowLeft / ArrowRight |
|
|
66
|
+
| `"vertical"` | stacked | `horizontal` | ArrowUp / ArrowDown |
|
|
67
|
+
|
|
68
|
+
Shift + Arrow moves by `largeStep`. Home / End jump to `min` / `max`.
|
|
69
|
+
|
|
70
|
+
## Accessibility
|
|
71
|
+
|
|
72
|
+
The separator is `role="separator"`, `tabIndex=0`, with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`, `aria-orientation`, `aria-label` and `aria-controls` pointing at the primary panel. It shows a focus ring from the `--fancy-focus` token. Pointer and touch drags use pointer capture (`touch-action: none` on the separator), and the separator has a 12px hit area around its 1px line.
|
|
73
|
+
|
|
74
|
+
## Data attributes
|
|
75
|
+
|
|
76
|
+
| Selector | Element |
|
|
77
|
+
|---|---|
|
|
78
|
+
| `[data-react-fancy-resizable-panels]` | Root; carries `data-orientation`, `data-dragging` while dragging, `data-disabled` |
|
|
79
|
+
| `[data-react-fancy-resizable-panels-panel="first"]` | Primary panel |
|
|
80
|
+
| `[data-react-fancy-resizable-panels-panel="second"]` | Secondary panel |
|
|
81
|
+
| `[data-react-fancy-resizable-panels-separator]` | The separator |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@particle-academy/react-fancy",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.60.0",
|
|
4
4
|
"description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -753,6 +753,16 @@
|
|
|
753
753
|
"default": "./dist/reason-tag.cjs"
|
|
754
754
|
}
|
|
755
755
|
},
|
|
756
|
+
"./resizable-panels": {
|
|
757
|
+
"import": {
|
|
758
|
+
"types": "./dist/resizable-panels.d.ts",
|
|
759
|
+
"default": "./dist/resizable-panels.js"
|
|
760
|
+
},
|
|
761
|
+
"require": {
|
|
762
|
+
"types": "./dist/resizable-panels.d.cts",
|
|
763
|
+
"default": "./dist/resizable-panels.cjs"
|
|
764
|
+
}
|
|
765
|
+
},
|
|
756
766
|
"./section": {
|
|
757
767
|
"import": {
|
|
758
768
|
"types": "./dist/section.d.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/FileUpload/FileUpload.context.ts","../src/components/FileUpload/FileUploadDropzone.tsx","../src/components/FileUpload/FileUploadList.tsx","../src/components/FileUpload/matchesAccept.ts","../src/components/FileUpload/FileUpload.tsx"],"names":["createContext","useContext","useState","useRef","useCallback","jsxs","cn","jsx","Fragment","Upload","useMemo","useEffect","File","X"],"mappings":";;;;;;;AAGO,IAAM,iBAAA,GACXA,oBAA6C,IAAI,CAAA;AAE5C,SAAS,aAAA,GAAwC;AACtD,EAAA,MAAM,GAAA,GAAMC,iBAAW,iBAAiB,CAAA;AACxC,EAAA,IAAI,CAAC,GAAA,EAAK;AACR,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,GAAA;AACT;ACRO,SAAS,kBAAA,CAAmB;AAAA,EACjC,QAAA;AAAA,EACA;AACF,CAAA,EAA4B;AAC1B,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,MAAA,EAAQ,QAAA,KAAa,aAAA,EAAc;AAC/D,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIC,eAAS,KAAK,CAAA;AAC9C,EAAA,MAAM,QAAA,GAAWC,aAAyB,IAAI,CAAA;AAE9C,EAAA,MAAM,UAAA,GAAaC,iBAAA;AAAA,IACjB,CAAC,CAAA,KAAuB;AACtB,MAAA,CAAA,CAAE,cAAA,EAAe;AACjB,MAAA,WAAA,CAAY,KAAK,CAAA;AACjB,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,QAAA,CAAS,CAAA,CAAE,aAAa,KAAK,CAAA;AAAA,IAC/B,CAAA;AAAA,IACA,CAAC,UAAU,QAAQ;AAAA,GACrB;AAEA,EAAA,MAAM,cAAA,GAAiBA,iBAAA,CAAY,CAAC,CAAA,KAAuB;AACzD,IAAA,CAAA,CAAE,cAAA,EAAe;AACjB,IAAA,WAAA,CAAY,IAAI,CAAA;AAAA,EAClB,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,kBAAkBA,iBAAA,CAAY,MAAM,YAAY,KAAK,CAAA,EAAG,EAAE,CAAA;AAEhE,EAAA,uBACEC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,uCAAA,EAAsC,EAAA;AAAA,MACtC,MAAA,EAAQ,UAAA;AAAA,MACR,UAAA,EAAY,cAAA;AAAA,MACZ,WAAA,EAAa,eAAA;AAAA,MACb,SAAS,MAAM,CAAC,QAAA,IAAY,QAAA,CAAS,SAAS,KAAA,EAAM;AAAA,MACpD,SAAA,EAAWC,oBAAA;AAAA,QACT,8HAAA;AAAA,QACA,WACI,kEAAA,GACA,4LAAA;AAAA,QACJ,QAAA,IAAY,+BAAA;AAAA,QACZ;AAAA,OACF;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAC,cAAA;AAAA,UAAC,OAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,QAAA;AAAA,YACL,IAAA,EAAK,MAAA;AAAA,YACL,SAAA,EAAU,QAAA;AAAA,YACV,QAAA,EAAU,CAAC,CAAA,KAAM;AACf,cAAA,IAAI,EAAE,MAAA,CAAO,KAAA,EAAO,QAAA,CAAS,CAAA,CAAE,OAAO,KAAK,CAAA;AAM3C,cAAA,CAAA,CAAE,OAAO,KAAA,GAAQ,EAAA;AAAA,YACnB,CAAA;AAAA,YACA,MAAA;AAAA,YACA,QAAA;AAAA,YACA;AAAA;AAAA,SACF;AAAA,QACC,4BACCF,eAAA,CAAAG,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,0BAAAD,cAAA,CAACE,sBAAO,IAAA,EAAM,EAAA,EAAI,WAAA,EAAa,GAAA,EAAK,WAAU,oBAAA,EAAqB,CAAA;AAAA,0BACnEF,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,uBAAA,EAAwB,QAAA,EAAA,oCAAA,EAErC;AAAA,SAAA,EACF;AAAA;AAAA;AAAA,GAEJ;AAEJ;AAEA,kBAAA,CAAmB,WAAA,GAAc,oBAAA;ACtEjC,SAAS,WAAW,KAAA,EAAuB;AACzC,EAAA,IAAI,KAAA,GAAQ,IAAA,EAAM,OAAO,CAAA,EAAG,KAAK,CAAA,EAAA,CAAA;AACjC,EAAA,IAAI,KAAA,GAAQ,OAAO,IAAA,EAAM,OAAO,IAAI,KAAA,GAAQ,IAAA,EAAM,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,CAAA;AAC5D,EAAA,OAAO,IAAI,KAAA,IAAS,IAAA,GAAO,IAAA,CAAA,EAAO,OAAA,CAAQ,CAAC,CAAC,CAAA,GAAA,CAAA;AAC9C;AAEA,SAAS,aAAa,IAAA,EAAsB;AAC1C,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC5B,EAAA,OAAO,MAAM,MAAA,GAAS,CAAA,GAAI,MAAM,GAAA,EAAI,CAAG,aAAY,GAAI,EAAA;AACzD;AAEA,SAAS,aAAA,CAAc,EAAE,IAAA,EAAM,KAAA,EAAO,UAAS,EAAiE;AAC9G,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,UAAA,CAAW,QAAQ,CAAA;AAC7C,EAAA,MAAM,SAAA,GAAYG,aAAA,CAAQ,MAAO,OAAA,GAAU,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA,GAAI,IAAA,EAAO,CAAC,IAAA,EAAM,OAAO,CAAC,CAAA;AAE7F,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,OAAO,MAAM;AACX,MAAA,IAAI,SAAA,EAAW,GAAA,CAAI,eAAA,CAAgB,SAAS,CAAA;AAAA,IAC9C,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEd,EAAA,uBACEN,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sDAAA,EACb,QAAA,EAAA;AAAA,oBAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8MAAA,EACZ,QAAA,EAAA;AAAA,MAAA,OAAA,IAAW,4BACVE,cAAAA,CAAC,KAAA,EAAA,EAAI,GAAA,EAAK,WAAW,GAAA,EAAK,IAAA,CAAK,IAAA,EAAM,SAAA,EAAU,8BAA6B,CAAA,mBAE5EF,eAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,+DAAA,EACb,QAAA,EAAA;AAAA,wBAAAE,cAAAA,CAACK,gBAAA,EAAA,EAAK,IAAA,EAAM,EAAA,EAAI,WAAU,eAAA,EAAgB,CAAA;AAAA,wBAC1CL,eAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yCAAyC,QAAA,EAAA,YAAA,CAAa,IAAA,CAAK,IAAI,CAAA,EAAE;AAAA,OAAA,EACnF,CAAA;AAAA,sBAEFA,cAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,OAAA,EAAS,MAAM,QAAA,CAAS,KAAK,CAAA;AAAA,UAC7B,SAAA,EAAU,4KAAA;AAAA,UACV,YAAA,EAAY,CAAA,OAAA,EAAU,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,UAE/B,QAAA,kBAAAA,cAAAA,CAACM,aAAA,EAAA,EAAE,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA;AACf,KAAA,EACF,CAAA;AAAA,oBACAN,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,mDAAA,EAAqD,eAAK,IAAA,EAAK;AAAA,GAAA,EACjF,CAAA;AAEJ;AAEO,SAAS,cAAA,CAAe,EAAE,SAAA,EAAW,SAAA,EAAU,EAAwB;AAC5E,EAAA,MAAM,EAAE,KAAA,EAAO,UAAA,EAAW,GAAI,aAAA,EAAc;AAE5C,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE/B,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,uBACEA,cAAAA,CAAC,KAAA,EAAA,EAAI,mCAAA,EAAkC,EAAA,EAAG,SAAA,EAAWD,oBAAA,CAAG,2BAAA,EAA6B,SAAS,CAAA,EAC3F,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,CAAA,qBAChBC,cAAAA,CAAC,aAAA,EAAA,EAAwC,IAAA,EAAY,KAAA,EAAO,CAAA,EAAG,QAAA,EAAU,UAAA,EAAA,EAArD,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,CAAA,EAAI,CAAC,CAAA,CAAgD,CACtF,CAAA,EACH,CAAA;AAAA,EAEJ;AAEA,EAAA,uBACEA,cAAAA,CAAC,IAAA,EAAA,EAAG,mCAAA,EAAkC,IAAG,SAAA,EAAWD,oBAAA,CAAG,gBAAA,EAAkB,SAAS,GAC/E,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,EAAM,sBAChBD,eAAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MAEC,SAAA,EAAU,yLAAA;AAAA,MAEV,QAAA,EAAA;AAAA,wBAAAE,cAAAA,CAACK,gBAAA,EAAA,EAAK,IAAA,EAAM,EAAA,EAAI,WAAU,wBAAA,EAAyB,CAAA;AAAA,wBACnDL,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iBAAA,EAAmB,eAAK,IAAA,EAAK,CAAA;AAAA,wBAC7CA,eAAC,MAAA,EAAA,EAAK,SAAA,EAAU,kCACb,QAAA,EAAA,UAAA,CAAW,IAAA,CAAK,IAAI,CAAA,EACvB,CAAA;AAAA,wBACAA,cAAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,OAAA,EAAS,MAAM,UAAA,CAAW,CAAC,CAAA;AAAA,YAC3B,SAAA,EAAU,qEAAA;AAAA,YACV,YAAA,EAAY,CAAA,OAAA,EAAU,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,YAE/B,QAAA,kBAAAA,cAAAA,CAACM,aAAA,EAAA,EAAE,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA;AACf;AAAA,KAAA;AAAA,IAfK,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,CAAA,EAAI,CAAC,CAAA;AAAA,GAiBzB,CAAA,EACH,CAAA;AAEJ;AAEA,cAAA,CAAe,WAAA,GAAc,gBAAA;;;AC3EtB,SAAS,aAAA,CAAc,MAAY,MAAA,EAAyB;AACjE,EAAA,MAAM,KAAA,GAAQ,MAAA,CACX,KAAA,CAAM,GAAG,EACT,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,MAAK,CAAE,WAAA,EAAa,CAAA,CACvC,OAAO,OAAO,CAAA;AAIjB,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE/B,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,WAAA,EAAY;AACnC,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,WAAA,EAAY;AAEnC,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,IAAA,KAAS;AAC1B,IAAA,IAAI,KAAK,UAAA,CAAW,GAAG,GAAG,OAAO,IAAA,CAAK,SAAS,IAAI,CAAA;AACnD,IAAA,IAAI,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG,OAAO,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA;AACjE,IAAA,OAAO,IAAA,KAAS,IAAA;AAAA,EAClB,CAAC,CAAA;AACH;AC5BA,SAAS,cAAA,CAAe;AAAA,EACtB,QAAA;AAAA,EACA,KAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,QAAA,GAAW,IAAA;AAAA,EACX,QAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA,GAAW,KAAA;AAAA,EACX;AACF,CAAA,EAAoB;AAClB,EAAA,MAAM,CAAC,aAAA,EAAe,gBAAgB,CAAA,GAAIX,cAAAA,CAAiB,EAAE,CAAA;AAC7D,EAAA,MAAM,QAAQ,KAAA,IAAS,aAAA;AAEvB,EAAA,MAAM,QAAA,GAAWE,iBAAAA;AAAA,IACf,CAAC,QAAA,KAAgC;AAC/B,MAAA,IAAI,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA;AAI/B,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,KAAA,GAAQ,MAAM,MAAA,CAAO,CAAC,MAAM,aAAA,CAAc,CAAA,EAAG,MAAM,CAAC,CAAA;AAAA,MACtD;AAEA,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,KAAA,GAAQ,MAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,OAAO,CAAA;AAAA,MAC/C;AAoBA,MAAA,IAAI,aAAa,KAAA,EAAO;AAgBtB,QAAA,MAAM,WAAA,GAAc,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAGpC,QAAA,MAAM,IAAA,GAAO,WAAA,CAAY,MAAA,GAAS,CAAA,GAAI,WAAA,GAAc,KAAA;AAEpD,QAAA,IAAI,KAAA,KAAU,MAAA,EAAW,gBAAA,CAAiB,IAAI,CAAA;AAC9C,QAAA,QAAA,GAAW,IAAI,CAAA;AAEf,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,OAAA,GAAU,CAAC,GAAG,KAAA,EAAO,GAAG,KAAK,CAAA;AACnC,MAAA,MAAM,UAAU,QAAA,GAAW,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,QAAQ,CAAA,GAAI,OAAA;AAExD,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,gBAAA,CAAiB,OAAO,CAAA;AACjD,MAAA,QAAA,GAAW,OAAO,CAAA;AAAA,IACpB,CAAA;AAAA,IACA,CAAC,MAAA,EAAQ,KAAA,EAAO,UAAU,OAAA,EAAS,QAAA,EAAU,UAAU,KAAK;AAAA,GAC9D;AAEA,EAAA,MAAM,UAAA,GAAaA,iBAAAA;AAAA,IACjB,CAAC,KAAA,KAAkB;AACjB,MAAA,MAAM,UAAU,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,EAAG,CAAA,KAAM,MAAM,KAAK,CAAA;AAClD,MAAA,IAAI,KAAA,KAAU,MAAA,EAAW,gBAAA,CAAiB,OAAO,CAAA;AACjD,MAAA,QAAA,GAAW,OAAO,CAAA;AAAA,IACpB,CAAA;AAAA,IACA,CAAC,KAAA,EAAO,QAAA,EAAU,KAAK;AAAA,GACzB;AAEA,EAAA,MAAM,GAAA,GAAMM,aAAAA;AAAA,IACV,OAAO,EAAE,KAAA,EAAO,UAAU,UAAA,EAAY,QAAA,EAAU,QAAQ,QAAA,EAAS,CAAA;AAAA,IACjE,CAAC,KAAA,EAAO,QAAA,EAAU,UAAA,EAAY,QAAA,EAAU,QAAQ,QAAQ;AAAA,GAC1D;AAEA,EAAA,uBACEH,cAAAA,CAAC,iBAAA,CAAkB,QAAA,EAAlB,EAA2B,OAAO,GAAA,EACjC,QAAA,kBAAAA,cAAAA,CAAC,KAAA,EAAA,EAAI,gCAA6B,EAAA,EAAG,SAAA,EAAWD,qBAAG,SAAS,CAAA,EAAI,UAAS,CAAA,EAC3E,CAAA;AAEJ;AAEO,IAAM,UAAA,GAAa,MAAA,CAAO,MAAA,CAAO,cAAA,EAAgB;AAAA,EACtD,QAAA,EAAU,kBAAA;AAAA,EACV,IAAA,EAAM;AACR,CAAC","file":"chunk-2GFM5WD4.cjs","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { FileUploadContextValue } from \"./FileUpload.types\";\n\nexport const FileUploadContext =\n createContext<FileUploadContextValue | null>(null);\n\nexport function useFileUpload(): FileUploadContextValue {\n const ctx = useContext(FileUploadContext);\n if (!ctx) {\n throw new Error(\n \"FileUpload compound components must be used within <FileUpload>\",\n );\n }\n return ctx;\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport { Upload } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useFileUpload } from \"./FileUpload.context\";\nimport type { FileUploadDropzoneProps } from \"./FileUpload.types\";\n\nexport function FileUploadDropzone({\n children,\n className,\n}: FileUploadDropzoneProps) {\n const { addFiles, disabled, accept, multiple } = useFileUpload();\n const [dragOver, setDragOver] = useState(false);\n const inputRef = useRef<HTMLInputElement>(null);\n\n const handleDrop = useCallback(\n (e: React.DragEvent) => {\n e.preventDefault();\n setDragOver(false);\n if (disabled) return;\n addFiles(e.dataTransfer.files);\n },\n [addFiles, disabled],\n );\n\n const handleDragOver = useCallback((e: React.DragEvent) => {\n e.preventDefault();\n setDragOver(true);\n }, []);\n\n const handleDragLeave = useCallback(() => setDragOver(false), []);\n\n return (\n <div\n data-react-fancy-file-upload-dropzone=\"\"\n onDrop={handleDrop}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onClick={() => !disabled && inputRef.current?.click()}\n className={cn(\n \"flex cursor-pointer flex-col items-center justify-center rounded-xl border-2 border-dashed p-8 text-center transition-colors\",\n dragOver\n ? \"border-blue-400 bg-blue-50 dark:border-blue-500 dark:bg-blue-950\"\n : \"border-[color:var(--fancy-border-strong,var(--color-zinc-300))] hover:border-zinc-400 dark:border-[color:var(--fancy-border-strong-dark,var(--color-zinc-700))] dark:hover:border-zinc-500\",\n disabled && \"cursor-not-allowed opacity-50\",\n className,\n )}\n >\n <input\n ref={inputRef}\n type=\"file\"\n className=\"hidden\"\n onChange={(e) => {\n if (e.target.files) addFiles(e.target.files);\n\n // Reset, or choosing the SAME file again fires no `change` event at\n // all and the gesture is simply dead — \"remove it, then re-add it\"\n // and \"retry the import that just failed\" both stop working. The\n // component never sees those files to reject them; it is not asked.\n e.target.value = \"\";\n }}\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n />\n {children ?? (\n <>\n <Upload size={32} strokeWidth={1.5} className=\"mb-2 text-zinc-400\" />\n <p className=\"text-sm text-zinc-500\">\n Drop files here or click to browse\n </p>\n </>\n )}\n </div>\n );\n}\n\nFileUploadDropzone.displayName = \"FileUploadDropzone\";\n","import { useEffect, useMemo } from \"react\";\nimport { File, X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useFileUpload } from \"./FileUpload.context\";\nimport type { FileUploadListProps } from \"./FileUpload.types\";\n\nfunction formatSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nfunction getExtension(name: string): string {\n const parts = name.split(\".\");\n return parts.length > 1 ? parts.pop()!.toUpperCase() : \"\";\n}\n\nfunction ThumbnailItem({ file, index, onRemove }: { file: File; index: number; onRemove: (i: number) => void }) {\n const isImage = file.type.startsWith(\"image/\");\n const objectUrl = useMemo(() => (isImage ? URL.createObjectURL(file) : null), [file, isImage]);\n\n useEffect(() => {\n return () => {\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n };\n }, [objectUrl]);\n\n return (\n <div className=\"group relative flex w-20 flex-col items-center gap-1\">\n <div className=\"relative h-20 w-20 overflow-hidden rounded-lg border border-[color:var(--fancy-border,var(--color-zinc-200))] bg-zinc-50 dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))] dark:bg-zinc-800\">\n {isImage && objectUrl ? (\n <img src={objectUrl} alt={file.name} className=\"h-full w-full object-cover\" />\n ) : (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-1\">\n <File size={20} className=\"text-zinc-400\" />\n <span className=\"text-[10px] font-medium text-zinc-500\">{getExtension(file.name)}</span>\n </div>\n )}\n <button\n type=\"button\"\n onClick={() => onRemove(index)}\n className=\"absolute top-1 right-1 flex h-5 w-5 items-center justify-center rounded-full bg-black/60 text-white opacity-0 transition-opacity hover:bg-black/80 group-hover:opacity-100\"\n aria-label={`Remove ${file.name}`}\n >\n <X size={10} />\n </button>\n </div>\n <span className=\"w-full truncate text-center text-xs text-zinc-500\">{file.name}</span>\n </div>\n );\n}\n\nexport function FileUploadList({ thumbnail, className }: FileUploadListProps) {\n const { files, removeFile } = useFileUpload();\n\n if (files.length === 0) return null;\n\n if (thumbnail) {\n return (\n <div data-react-fancy-file-upload-list=\"\" className={cn(\"mt-3 flex flex-wrap gap-3\", className)}>\n {files.map((file, i) => (\n <ThumbnailItem key={`${file.name}-${i}`} file={file} index={i} onRemove={removeFile} />\n ))}\n </div>\n );\n }\n\n return (\n <ul data-react-fancy-file-upload-list=\"\" className={cn(\"mt-3 space-y-2\", className)}>\n {files.map((file, i) => (\n <li\n key={`${file.name}-${i}`}\n className=\"flex items-center gap-3 rounded-lg border border-[color:var(--fancy-border,var(--color-zinc-200))] px-3 py-2 text-sm dark:border-[color:var(--fancy-border-dark,var(--color-zinc-700))]\"\n >\n <File size={16} className=\"shrink-0 text-zinc-400\" />\n <span className=\"flex-1 truncate\">{file.name}</span>\n <span className=\"shrink-0 text-xs text-zinc-400\">\n {formatSize(file.size)}\n </span>\n <button\n type=\"button\"\n onClick={() => removeFile(i)}\n className=\"shrink-0 text-zinc-400 hover:text-zinc-600 dark:hover:text-zinc-300\"\n aria-label={`Remove ${file.name}`}\n >\n <X size={14} />\n </button>\n </li>\n ))}\n </ul>\n );\n}\n\nFileUploadList.displayName = \"FileUploadList\";\n","/**\n * Does a file satisfy an `accept` string?\n *\n * The browser enforces `accept` in the FILE PICKER only. A drag-and-drop never\n * opens a picker, so on the drop path this is the only thing standing between an\n * image-only dropzone and a dropped executable. Forwarding the attribute to the\n * hidden input is half the job; this is the other half.\n *\n * Follows the HTML `accept` grammar: a comma-separated list of extensions\n * (`.csv`), exact MIME types (`text/plain`) and type wildcards (`image/*`).\n * Matching is case-insensitive, because a drop reports whatever the OS says and\n * `TEXT/PLAIN` is a real thing to receive.\n *\n * A dropped file often carries an EMPTY `type` — the OS may not know it and\n * `File.type` is a hint, never a guarantee. That is why extension rules are\n * checked against the name and not the type: an `accept=\".csv\"` zone has to work\n * for a .csv whose type is `\"\"`, which is the common case rather than the edge.\n */\nexport function matchesAccept(file: File, accept: string): boolean {\n const rules = accept\n .split(\",\")\n .map((rule) => rule.trim().toLowerCase())\n .filter(Boolean);\n\n // An accept string that lists nothing constrains nothing. Failing closed here\n // would turn `accept=\"\"` into a dropzone that silently swallows every file.\n if (rules.length === 0) return true;\n\n const type = file.type.toLowerCase();\n const name = file.name.toLowerCase();\n\n return rules.some((rule) => {\n if (rule.startsWith(\".\")) return name.endsWith(rule);\n if (rule.endsWith(\"/*\")) return type.startsWith(rule.slice(0, -1));\n return type === rule;\n });\n}\n","import { useCallback, useMemo, useState } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { FileUploadContext } from \"./FileUpload.context\";\nimport { FileUploadDropzone } from \"./FileUploadDropzone\";\nimport { FileUploadList } from \"./FileUploadList\";\nimport { matchesAccept } from \"./matchesAccept\";\nimport type { FileUploadProps } from \"./FileUpload.types\";\n\nfunction FileUploadRoot({\n children,\n value,\n onChange,\n accept,\n multiple = true,\n maxFiles,\n maxSize,\n disabled = false,\n className,\n}: FileUploadProps) {\n const [internalFiles, setInternalFiles] = useState<File[]>([]);\n const files = value ?? internalFiles;\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n let toAdd = Array.from(newFiles);\n\n // `accept` is enforced HERE, not only on the input: the input's attribute\n // governs the picker, and a drop never opens one.\n if (accept) {\n toAdd = toAdd.filter((f) => matchesAccept(f, accept));\n }\n\n if (maxSize) {\n toAdd = toAdd.filter((f) => f.size <= maxSize);\n }\n\n /*\n * `multiple={false}` REPLACES; `maxFiles` refuses the overflow.\n *\n * These used to be the same rule — a cap of one, first-wins — on the\n * reasoning that the two props must not disagree about what a single-file\n * upload means. But they are different statements:\n *\n * - `maxFiles={n}` is a QUOTA. Dropping five files into a three-file\n * field should keep three, not the last three.\n * - `multiple={false}` is a FIELD SHAPE: this input holds one file. Its\n * analogue is a radio group, where choosing again MOVES the selection.\n *\n * Under the old rule a single-file field could never change its mind: the\n * second choice computed `[old, new].slice(0, 1)` and discarded the new\n * file in silence. The YouGene estate worked around it by remounting the\n * component with a `key`, which is the shape of a bug rather than a\n * preference.\n */\n if (multiple === false) {\n /*\n * The FIRST of the incoming batch, not the last.\n *\n * Two separate questions hide here, and only one of them was the bug:\n *\n * - ACROSS gestures — choose a file, then choose another. The second\n * must win, or the field cannot change its mind. That is the fix.\n * - WITHIN one gesture — drop two files at once onto a single-file\n * field. Which one wins is arbitrary, and taking the first is what\n * has always shipped; there is no replacement intent in a single\n * ambiguous drop.\n *\n * Taking `slice(-1)` would have answered both with \"the last\", quietly\n * changing the second. The existing drop test caught it.\n */\n const replacement = toAdd.slice(0, 1);\n // Nothing survived the accept/size filters — leave the field alone\n // rather than clearing a file the user never asked to remove.\n const next = replacement.length > 0 ? replacement : files;\n\n if (value === undefined) setInternalFiles(next);\n onChange?.(next);\n\n return;\n }\n\n const updated = [...files, ...toAdd];\n const limited = maxFiles ? updated.slice(0, maxFiles) : updated;\n\n if (value === undefined) setInternalFiles(limited);\n onChange?.(limited);\n },\n [accept, files, maxFiles, maxSize, multiple, onChange, value],\n );\n\n const removeFile = useCallback(\n (index: number) => {\n const updated = files.filter((_, i) => i !== index);\n if (value === undefined) setInternalFiles(updated);\n onChange?.(updated);\n },\n [files, onChange, value],\n );\n\n const ctx = useMemo(\n () => ({ files, addFiles, removeFile, disabled, accept, multiple }),\n [files, addFiles, removeFile, disabled, accept, multiple],\n );\n\n return (\n <FileUploadContext.Provider value={ctx}>\n <div data-react-fancy-file-upload=\"\" className={cn(className)}>{children}</div>\n </FileUploadContext.Provider>\n );\n}\n\nexport const FileUpload = Object.assign(FileUploadRoot, {\n Dropzone: FileUploadDropzone,\n List: FileUploadList,\n});\n"]}
|