@psnext/design-system 2.4.0 → 2.6.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/DESIGN.md +32 -4
- package/SKILL.md +1 -1
- package/dist/Header.cjs +3 -3
- package/dist/Header.cjs.map +1 -1
- package/dist/Header.js +3 -3
- package/dist/Header.js.map +1 -1
- package/dist/Mosaic.cjs +472 -0
- package/dist/Mosaic.cjs.map +1 -0
- package/dist/Mosaic.js +459 -0
- package/dist/Mosaic.js.map +1 -0
- package/dist/index.cjs +25 -4
- package/dist/index.d.cts +5 -5
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +10 -5
- package/dist/index10.d.cts +5 -5
- package/dist/index10.d.ts +6 -6
- package/dist/index11.d.cts +3 -3
- package/dist/index11.d.ts +3 -3
- package/dist/index12.d.cts +12 -12
- package/dist/index12.d.cts.map +1 -1
- package/dist/index12.d.ts +12 -12
- package/dist/index12.d.ts.map +1 -1
- package/dist/index13.d.cts +6 -6
- package/dist/index13.d.cts.map +1 -1
- package/dist/index13.d.ts +6 -6
- package/dist/index13.d.ts.map +1 -1
- package/dist/index14.d.cts +5 -5
- package/dist/index14.d.ts +5 -5
- package/dist/index15.d.cts +58 -23
- package/dist/index15.d.cts.map +1 -1
- package/dist/index15.d.ts +58 -23
- package/dist/index15.d.ts.map +1 -1
- package/dist/index16.d.cts +23 -32
- package/dist/index16.d.cts.map +1 -1
- package/dist/index16.d.ts +23 -32
- package/dist/index16.d.ts.map +1 -1
- package/dist/index17.d.cts +34 -15
- package/dist/index17.d.cts.map +1 -1
- package/dist/index17.d.ts +34 -15
- package/dist/index17.d.ts.map +1 -1
- package/dist/index18.d.cts +13 -67
- package/dist/index18.d.cts.map +1 -1
- package/dist/index18.d.ts +13 -67
- package/dist/index18.d.ts.map +1 -1
- package/dist/index19.d.cts +55 -48
- package/dist/index19.d.cts.map +1 -1
- package/dist/index19.d.ts +55 -48
- package/dist/index19.d.ts.map +1 -1
- package/dist/index2.d.cts +8 -8
- package/dist/index2.d.cts.map +1 -1
- package/dist/index2.d.ts +8 -8
- package/dist/index2.d.ts.map +1 -1
- package/dist/index20.d.cts +45 -75
- package/dist/index20.d.cts.map +1 -1
- package/dist/index20.d.ts +45 -75
- package/dist/index20.d.ts.map +1 -1
- package/dist/index21.d.cts +39 -28
- package/dist/index21.d.cts.map +1 -1
- package/dist/index21.d.ts +39 -28
- package/dist/index21.d.ts.map +1 -1
- package/dist/index22.d.cts +98 -44
- package/dist/index22.d.cts.map +1 -1
- package/dist/index22.d.ts +98 -44
- package/dist/index22.d.ts.map +1 -1
- package/dist/index23.d.cts +65 -68
- package/dist/index23.d.cts.map +1 -1
- package/dist/index23.d.ts +65 -68
- package/dist/index23.d.ts.map +1 -1
- package/dist/index24.d.cts +27 -42
- package/dist/index24.d.cts.map +1 -1
- package/dist/index24.d.ts +27 -42
- package/dist/index24.d.ts.map +1 -1
- package/dist/index25.d.cts +68 -11
- package/dist/index25.d.cts.map +1 -1
- package/dist/index25.d.ts +68 -11
- package/dist/index25.d.ts.map +1 -1
- package/dist/index26.d.cts +75 -56
- package/dist/index26.d.cts.map +1 -1
- package/dist/index26.d.ts +75 -56
- package/dist/index26.d.ts.map +1 -1
- package/dist/index27.d.cts +38 -60
- package/dist/index27.d.cts.map +1 -1
- package/dist/index27.d.ts +38 -60
- package/dist/index27.d.ts.map +1 -1
- package/dist/index28.d.cts +10 -30
- package/dist/index28.d.cts.map +1 -1
- package/dist/index28.d.ts +10 -30
- package/dist/index28.d.ts.map +1 -1
- package/dist/index29.d.cts +72 -17
- package/dist/index29.d.cts.map +1 -1
- package/dist/index29.d.ts +72 -17
- package/dist/index29.d.ts.map +1 -1
- package/dist/index3.d.cts +13 -13
- package/dist/index3.d.cts.map +1 -1
- package/dist/index3.d.ts +13 -13
- package/dist/index30.d.cts +46 -80
- package/dist/index30.d.cts.map +1 -1
- package/dist/index30.d.ts +46 -80
- package/dist/index30.d.ts.map +1 -1
- package/dist/index31.d.cts +64 -33
- package/dist/index31.d.cts.map +1 -1
- package/dist/index31.d.ts +64 -33
- package/dist/index31.d.ts.map +1 -1
- package/dist/index32.d.cts +29 -18
- package/dist/index32.d.cts.map +1 -1
- package/dist/index32.d.ts +29 -18
- package/dist/index32.d.ts.map +1 -1
- package/dist/index33.d.cts +17 -51
- package/dist/index33.d.cts.map +1 -1
- package/dist/index33.d.ts +17 -51
- package/dist/index33.d.ts.map +1 -1
- package/dist/index34.d.cts +81 -36
- package/dist/index34.d.cts.map +1 -1
- package/dist/index34.d.ts +81 -36
- package/dist/index34.d.ts.map +1 -1
- package/dist/index35.d.cts +32 -69
- package/dist/index35.d.cts.map +1 -1
- package/dist/index35.d.ts +32 -69
- package/dist/index35.d.ts.map +1 -1
- package/dist/index36.d.cts +20 -13
- package/dist/index36.d.cts.map +1 -1
- package/dist/index36.d.ts +20 -13
- package/dist/index36.d.ts.map +1 -1
- package/dist/index37.d.cts +51 -21
- package/dist/index37.d.cts.map +1 -1
- package/dist/index37.d.ts +51 -21
- package/dist/index37.d.ts.map +1 -1
- package/dist/index38.d.cts +38 -15
- package/dist/index38.d.cts.map +1 -1
- package/dist/index38.d.ts +38 -15
- package/dist/index38.d.ts.map +1 -1
- package/dist/index39.d.cts +53 -81
- package/dist/index39.d.cts.map +1 -1
- package/dist/index39.d.ts +53 -81
- package/dist/index39.d.ts.map +1 -1
- package/dist/index4.d.cts +2 -2
- package/dist/index4.d.ts +2 -2
- package/dist/index4.d.ts.map +1 -1
- package/dist/index40.d.cts +13 -16
- package/dist/index40.d.cts.map +1 -1
- package/dist/index40.d.ts +13 -16
- package/dist/index40.d.ts.map +1 -1
- package/dist/index41.d.cts +25 -52
- package/dist/index41.d.cts.map +1 -1
- package/dist/index41.d.ts +24 -51
- package/dist/index41.d.ts.map +1 -1
- package/dist/index42.d.cts +15 -40
- package/dist/index42.d.cts.map +1 -1
- package/dist/index42.d.ts +15 -40
- package/dist/index42.d.ts.map +1 -1
- package/dist/index43.d.cts +86 -77
- package/dist/index43.d.cts.map +1 -1
- package/dist/index43.d.ts +86 -77
- package/dist/index43.d.ts.map +1 -1
- package/dist/index44.d.cts +125 -1
- package/dist/index44.d.cts.map +1 -0
- package/dist/index44.d.ts +125 -1
- package/dist/index44.d.ts.map +1 -0
- package/dist/index45.d.cts +15 -41
- package/dist/index45.d.cts.map +1 -1
- package/dist/index45.d.ts +15 -41
- package/dist/index45.d.ts.map +1 -1
- package/dist/index46.d.cts +52 -24
- package/dist/index46.d.cts.map +1 -1
- package/dist/index46.d.ts +52 -24
- package/dist/index46.d.ts.map +1 -1
- package/dist/index47.d.cts +86 -31
- package/dist/index47.d.cts.map +1 -1
- package/dist/index47.d.ts +86 -31
- package/dist/index47.d.ts.map +1 -1
- package/dist/index48.d.cts +1 -25
- package/dist/index48.d.ts +1 -25
- package/dist/index49.d.cts +120 -14
- package/dist/index49.d.cts.map +1 -1
- package/dist/index49.d.ts +120 -14
- package/dist/index49.d.ts.map +1 -1
- package/dist/index5.d.cts +7 -7
- package/dist/index5.d.ts +7 -7
- package/dist/index50.d.cts +32 -53
- package/dist/index50.d.cts.map +1 -1
- package/dist/index50.d.ts +32 -53
- package/dist/index50.d.ts.map +1 -1
- package/dist/index51.d.cts +21 -56
- package/dist/index51.d.cts.map +1 -1
- package/dist/index51.d.ts +21 -56
- package/dist/index51.d.ts.map +1 -1
- package/dist/index52.d.cts +33 -23
- package/dist/index52.d.cts.map +1 -1
- package/dist/index52.d.ts +33 -23
- package/dist/index52.d.ts.map +1 -1
- package/dist/index53.d.cts +17 -201
- package/dist/index53.d.cts.map +1 -1
- package/dist/index53.d.ts +17 -201
- package/dist/index53.d.ts.map +1 -1
- package/dist/index54.d.cts +14 -19
- package/dist/index54.d.cts.map +1 -1
- package/dist/index54.d.ts +14 -19
- package/dist/index54.d.ts.map +1 -1
- package/dist/index55.d.cts +64 -23
- package/dist/index55.d.cts.map +1 -1
- package/dist/index55.d.ts +64 -23
- package/dist/index55.d.ts.map +1 -1
- package/dist/index56.d.cts +95 -22
- package/dist/index56.d.cts.map +1 -1
- package/dist/index56.d.ts +95 -22
- package/dist/index56.d.ts.map +1 -1
- package/dist/index57.d.cts +25 -6
- package/dist/index57.d.cts.map +1 -1
- package/dist/index57.d.ts +25 -6
- package/dist/index57.d.ts.map +1 -1
- package/dist/index58.d.cts +202 -43
- package/dist/index58.d.cts.map +1 -1
- package/dist/index58.d.ts +202 -43
- package/dist/index58.d.ts.map +1 -1
- package/dist/index59.d.cts +15 -40
- package/dist/index59.d.cts.map +1 -1
- package/dist/index59.d.ts +15 -40
- package/dist/index59.d.ts.map +1 -1
- package/dist/index6.d.cts +5 -5
- package/dist/index6.d.cts.map +1 -1
- package/dist/index6.d.ts +5 -5
- package/dist/index6.d.ts.map +1 -1
- package/dist/index60.d.cts +20 -55
- package/dist/index60.d.cts.map +1 -1
- package/dist/index60.d.ts +20 -55
- package/dist/index60.d.ts.map +1 -1
- package/dist/index61.d.cts +21 -41
- package/dist/index61.d.cts.map +1 -1
- package/dist/index61.d.ts +21 -41
- package/dist/index61.d.ts.map +1 -1
- package/dist/index62.d.cts +6 -18
- package/dist/index62.d.cts.map +1 -1
- package/dist/index62.d.ts +6 -18
- package/dist/index62.d.ts.map +1 -1
- package/dist/index63.d.cts +46 -41
- package/dist/index63.d.cts.map +1 -1
- package/dist/index63.d.ts +46 -41
- package/dist/index63.d.ts.map +1 -1
- package/dist/index64.d.cts +47 -19
- package/dist/index64.d.cts.map +1 -1
- package/dist/index64.d.ts +47 -19
- package/dist/index64.d.ts.map +1 -1
- package/dist/index65.d.cts +50 -35
- package/dist/index65.d.cts.map +1 -1
- package/dist/index65.d.ts +50 -35
- package/dist/index65.d.ts.map +1 -1
- package/dist/index66.d.cts +33 -13
- package/dist/index66.d.cts.map +1 -1
- package/dist/index66.d.ts +33 -13
- package/dist/index66.d.ts.map +1 -1
- package/dist/index67.d.cts +17 -84
- package/dist/index67.d.cts.map +1 -1
- package/dist/index67.d.ts +17 -84
- package/dist/index67.d.ts.map +1 -1
- package/dist/index68.d.cts +40 -14
- package/dist/index68.d.cts.map +1 -1
- package/dist/index68.d.ts +40 -14
- package/dist/index68.d.ts.map +1 -1
- package/dist/index69.d.cts +16 -30
- package/dist/index69.d.cts.map +1 -1
- package/dist/index69.d.ts +16 -30
- package/dist/index69.d.ts.map +1 -1
- package/dist/index7.d.cts +8 -8
- package/dist/index7.d.ts +8 -8
- package/dist/index70.d.cts +39 -27
- package/dist/index70.d.cts.map +1 -1
- package/dist/index70.d.ts +39 -27
- package/dist/index70.d.ts.map +1 -1
- package/dist/index71.d.cts +22 -79
- package/dist/index71.d.cts.map +1 -1
- package/dist/index71.d.ts +22 -79
- package/dist/index71.d.ts.map +1 -1
- package/dist/index72.d.cts +77 -264
- package/dist/index72.d.cts.map +1 -1
- package/dist/index72.d.ts +77 -264
- package/dist/index72.d.ts.map +1 -1
- package/dist/index73.d.cts +19 -0
- package/dist/index73.d.cts.map +1 -0
- package/dist/index73.d.ts +19 -0
- package/dist/index73.d.ts.map +1 -0
- package/dist/index74.d.cts +37 -0
- package/dist/index74.d.cts.map +1 -0
- package/dist/index74.d.ts +37 -0
- package/dist/index74.d.ts.map +1 -0
- package/dist/index75.d.cts +36 -0
- package/dist/index75.d.cts.map +1 -0
- package/dist/index75.d.ts +36 -0
- package/dist/index75.d.ts.map +1 -0
- package/dist/index76.d.cts +87 -0
- package/dist/index76.d.cts.map +1 -0
- package/dist/index76.d.ts +87 -0
- package/dist/index76.d.ts.map +1 -0
- package/dist/index77.d.cts +278 -0
- package/dist/index77.d.cts.map +1 -0
- package/dist/index77.d.ts +278 -0
- package/dist/index77.d.ts.map +1 -0
- package/dist/index8.d.cts +4 -4
- package/dist/index8.d.cts.map +1 -1
- package/dist/index8.d.ts +4 -4
- package/dist/index9.d.cts +2 -2
- package/dist/index9.d.ts +2 -2
- package/dist/index9.d.ts.map +1 -1
- package/dist/layouts/Container/index.d.cts +1 -1
- package/dist/layouts/Container/index.d.ts +1 -1
- package/dist/layouts/MultiColumn/index.d.cts +1 -1
- package/dist/layouts/MultiColumn/index.d.ts +1 -1
- package/dist/layouts/PageBackground/index.d.cts +1 -1
- package/dist/layouts/PageBackground/index.d.ts +1 -1
- package/dist/layouts/Stack/index.d.cts +1 -1
- package/dist/layouts/Stack/index.d.ts +1 -1
- package/dist/layouts/TwoColumn/index.d.cts +1 -1
- package/dist/layouts/TwoColumn/index.d.ts +1 -1
- package/dist/layouts/index.d.cts +5 -5
- package/dist/layouts/index.d.ts +5 -5
- package/dist/patterns/DataTable/index.d.cts +3 -3
- package/dist/patterns/DataTable/index.d.cts.map +1 -1
- package/dist/patterns/DataTable/index.d.ts +3 -3
- package/dist/patterns/DataTable/index.d.ts.map +1 -1
- package/dist/patterns/Footer/index.d.cts +7 -7
- package/dist/patterns/Footer/index.d.ts +7 -7
- package/dist/patterns/Footer/index.d.ts.map +1 -1
- package/dist/patterns/Header/index.d.cts +1 -1
- package/dist/patterns/Header/index.d.ts +1 -1
- package/dist/patterns/MediaObject/index.d.cts +14 -14
- package/dist/patterns/MediaObject/index.d.cts.map +1 -1
- package/dist/patterns/MediaObject/index.d.ts +14 -14
- package/dist/patterns/NavRail/index.d.cts +1 -1
- package/dist/patterns/NavRail/index.d.ts +1 -1
- package/dist/patterns/SectionCard/index.d.cts +2 -2
- package/dist/patterns/SectionCard/index.d.ts +2 -2
- package/dist/patterns/SectionCard/index.d.ts.map +1 -1
- package/dist/patterns/SectionHeading/index.d.cts +3 -3
- package/dist/patterns/SectionHeading/index.d.ts +3 -3
- package/dist/patterns/SectionHeading/index.d.ts.map +1 -1
- package/dist/patterns/index.d.cts +2 -2
- package/dist/patterns/index.d.ts +2 -2
- package/dist/primitives/Checkbox/index.cjs +1 -1
- package/dist/primitives/Checkbox/index.cjs.map +1 -1
- package/dist/primitives/Checkbox/index.d.cts +1 -1
- package/dist/primitives/Checkbox/index.d.ts +1 -1
- package/dist/primitives/Checkbox/index.js +1 -1
- package/dist/primitives/Checkbox/index.js.map +1 -1
- package/dist/primitives/CheckboxTree/index.d.cts +1 -1
- package/dist/primitives/CheckboxTree/index.d.ts +1 -1
- package/dist/primitives/CircularProgress/index.cjs +106 -0
- package/dist/primitives/CircularProgress/index.cjs.map +1 -0
- package/dist/primitives/CircularProgress/index.d.cts +2 -0
- package/dist/primitives/CircularProgress/index.d.ts +2 -0
- package/dist/primitives/CircularProgress/index.js +105 -0
- package/dist/primitives/CircularProgress/index.js.map +1 -0
- package/dist/primitives/Collapsible/index.d.cts +1 -1
- package/dist/primitives/Collapsible/index.d.ts +1 -1
- package/dist/primitives/Combobox/index.cjs +210 -0
- package/dist/primitives/Combobox/index.cjs.map +1 -0
- package/dist/primitives/Combobox/index.d.cts +2 -0
- package/dist/primitives/Combobox/index.d.ts +2 -0
- package/dist/primitives/Combobox/index.js +199 -0
- package/dist/primitives/Combobox/index.js.map +1 -0
- package/dist/primitives/Command/index.d.cts +1 -1
- package/dist/primitives/Command/index.d.ts +1 -1
- package/dist/primitives/ContextMenu/index.d.cts +1 -1
- package/dist/primitives/ContextMenu/index.d.ts +1 -1
- package/dist/primitives/Credits/index.d.cts +1 -1
- package/dist/primitives/Credits/index.d.ts +1 -1
- package/dist/primitives/Dialog/index.d.cts +1 -1
- package/dist/primitives/Dialog/index.d.ts +1 -1
- package/dist/primitives/Drawer/index.cjs +34 -2
- package/dist/primitives/Drawer/index.cjs.map +1 -1
- package/dist/primitives/Drawer/index.d.cts +1 -1
- package/dist/primitives/Drawer/index.d.ts +1 -1
- package/dist/primitives/Drawer/index.js +34 -2
- package/dist/primitives/Drawer/index.js.map +1 -1
- package/dist/primitives/DropdownMenu/index.d.cts +1 -1
- package/dist/primitives/DropdownMenu/index.d.ts +1 -1
- package/dist/primitives/Empty/index.d.cts +1 -1
- package/dist/primitives/Empty/index.d.ts +1 -1
- package/dist/primitives/Field/index.d.cts +1 -1
- package/dist/primitives/Field/index.d.ts +1 -1
- package/dist/primitives/FileUpload/index.cjs +354 -0
- package/dist/primitives/FileUpload/index.cjs.map +1 -0
- package/dist/primitives/FileUpload/index.d.cts +2 -0
- package/dist/primitives/FileUpload/index.d.ts +2 -0
- package/dist/primitives/FileUpload/index.js +351 -0
- package/dist/primitives/FileUpload/index.js.map +1 -0
- package/dist/primitives/Form/index.d.cts +1 -1
- package/dist/primitives/Form/index.d.ts +1 -1
- package/dist/primitives/Heading/index.d.cts +1 -1
- package/dist/primitives/Heading/index.d.ts +1 -1
- package/dist/primitives/HoverCard/index.d.cts +1 -1
- package/dist/primitives/HoverCard/index.d.ts +1 -1
- package/dist/primitives/Icon/index.d.cts +1 -1
- package/dist/primitives/Icon/index.d.ts +1 -1
- package/dist/primitives/InfoBanner/index.d.cts +1 -1
- package/dist/primitives/InfoBanner/index.d.ts +1 -1
- package/dist/primitives/Input/index.d.cts +1 -1
- package/dist/primitives/Input/index.d.ts +1 -1
- package/dist/primitives/InputGroup/index.d.cts +1 -1
- package/dist/primitives/InputGroup/index.d.ts +1 -1
- package/dist/primitives/InputOtp/index.d.cts +1 -1
- package/dist/primitives/InputOtp/index.d.ts +1 -1
- package/dist/primitives/Item/index.d.cts +1 -1
- package/dist/primitives/Item/index.d.ts +1 -1
- package/dist/primitives/Kbd/index.d.cts +1 -1
- package/dist/primitives/Kbd/index.d.ts +1 -1
- package/dist/primitives/Label/index.d.cts +1 -1
- package/dist/primitives/Label/index.d.ts +1 -1
- package/dist/primitives/Link/index.d.cts +1 -1
- package/dist/primitives/Link/index.d.ts +1 -1
- package/dist/primitives/Logo/index.d.cts +1 -1
- package/dist/primitives/Logo/index.d.ts +1 -1
- package/dist/primitives/Menubar/index.d.cts +1 -1
- package/dist/primitives/Menubar/index.d.ts +1 -1
- package/dist/primitives/Mosaic/index.cjs +4 -0
- package/dist/primitives/Mosaic/index.d.cts +2 -0
- package/dist/primitives/Mosaic/index.d.ts +2 -0
- package/dist/primitives/Mosaic/index.js +2 -0
- package/dist/primitives/NativeSelect/index.d.cts +1 -1
- package/dist/primitives/NativeSelect/index.d.ts +1 -1
- package/dist/primitives/NavRail/index.d.cts +2 -2
- package/dist/primitives/NavRail/index.d.ts +2 -2
- package/dist/primitives/NavigationMenu/index.d.cts +1 -1
- package/dist/primitives/NavigationMenu/index.d.ts +1 -1
- package/dist/primitives/NotchedCard/index.cjs +390 -0
- package/dist/primitives/NotchedCard/index.cjs.map +1 -0
- package/dist/primitives/NotchedCard/index.d.cts +2 -0
- package/dist/primitives/NotchedCard/index.d.ts +2 -0
- package/dist/primitives/NotchedCard/index.js +385 -0
- package/dist/primitives/NotchedCard/index.js.map +1 -0
- package/dist/primitives/Pagination/index.d.cts +1 -1
- package/dist/primitives/Pagination/index.d.ts +1 -1
- package/dist/primitives/Popover/index.d.cts +1 -1
- package/dist/primitives/Popover/index.d.ts +1 -1
- package/dist/primitives/Progress/index.d.cts +1 -1
- package/dist/primitives/Progress/index.d.ts +1 -1
- package/dist/primitives/RadioGroup/index.cjs +1 -1
- package/dist/primitives/RadioGroup/index.cjs.map +1 -1
- package/dist/primitives/RadioGroup/index.d.cts +1 -1
- package/dist/primitives/RadioGroup/index.d.ts +1 -1
- package/dist/primitives/RadioGroup/index.js +1 -1
- package/dist/primitives/RadioGroup/index.js.map +1 -1
- package/dist/primitives/Resizable/index.d.cts +1 -1
- package/dist/primitives/Resizable/index.d.ts +1 -1
- package/dist/primitives/ScrollArea/index.d.cts +1 -1
- package/dist/primitives/ScrollArea/index.d.ts +1 -1
- package/dist/primitives/Select/index.d.cts +1 -1
- package/dist/primitives/Select/index.d.ts +1 -1
- package/dist/primitives/Sheet/index.cjs +34 -2
- package/dist/primitives/Sheet/index.cjs.map +1 -1
- package/dist/primitives/Sheet/index.d.cts +1 -1
- package/dist/primitives/Sheet/index.d.ts +1 -1
- package/dist/primitives/Sheet/index.js +34 -2
- package/dist/primitives/Sheet/index.js.map +1 -1
- package/dist/primitives/Sidebar/index.d.cts +1 -1
- package/dist/primitives/Sidebar/index.d.ts +1 -1
- package/dist/primitives/Skeleton/index.d.cts +1 -1
- package/dist/primitives/Skeleton/index.d.ts +1 -1
- package/dist/primitives/Slider/index.d.cts +1 -1
- package/dist/primitives/Slider/index.d.ts +1 -1
- package/dist/primitives/Sonner/index.d.cts +1 -1
- package/dist/primitives/Sonner/index.d.ts +1 -1
- package/dist/primitives/Spinner/index.d.cts +1 -1
- package/dist/primitives/Spinner/index.d.ts +1 -1
- package/dist/primitives/Switch/index.d.cts +1 -1
- package/dist/primitives/Switch/index.d.ts +1 -1
- package/dist/primitives/Table/index.d.cts +1 -1
- package/dist/primitives/Table/index.d.ts +1 -1
- package/dist/primitives/Tabs/index.cjs +153 -10
- package/dist/primitives/Tabs/index.cjs.map +1 -1
- package/dist/primitives/Tabs/index.d.cts +1 -1
- package/dist/primitives/Tabs/index.d.ts +1 -1
- package/dist/primitives/Tabs/index.js +153 -10
- package/dist/primitives/Tabs/index.js.map +1 -1
- package/dist/primitives/Text/index.d.cts +1 -1
- package/dist/primitives/Text/index.d.ts +1 -1
- package/dist/primitives/Textarea/index.d.cts +1 -1
- package/dist/primitives/Textarea/index.d.ts +1 -1
- package/dist/primitives/ThemeProvider/index.d.cts +1 -1
- package/dist/primitives/ThemeProvider/index.d.ts +1 -1
- package/dist/primitives/Toggle/index.d.cts +1 -1
- package/dist/primitives/Toggle/index.d.ts +1 -1
- package/dist/primitives/ToggleGroup/index.d.cts +1 -1
- package/dist/primitives/ToggleGroup/index.d.ts +1 -1
- package/dist/primitives/Tooltip/index.d.cts +1 -1
- package/dist/primitives/Tooltip/index.d.ts +1 -1
- package/dist/primitives/index.cjs +25 -4
- package/dist/primitives/index.d.cts +56 -51
- package/dist/primitives/index.d.ts +56 -51
- package/dist/primitives/index.js +10 -5
- package/dist/styles/tokens/mode-dark.css +1 -1
- package/package.json +1 -1
- package/dist/index48.d.cts.map +0 -1
- package/dist/index48.d.ts.map +0 -1
package/dist/Mosaic.js
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import { t as cn } from "./cn.js";
|
|
2
|
+
import { Button } from "./primitives/Button/index.js";
|
|
3
|
+
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "./primitives/Resizable/index.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { GripVerticalIcon, PanelLeftIcon, PanelTopIcon, PencilIcon, XIcon } from "lucide-react";
|
|
7
|
+
//#region src/primitives/Mosaic/Mosaic.utils.ts
|
|
8
|
+
/** Every recursive walk depends on this being correct — `T` is constrained to non-object keys precisely so this check can't be fooled by a leaf that happens to be an object. */
|
|
9
|
+
function isParent(node) {
|
|
10
|
+
return typeof node === "object" && node !== null && "direction" in node;
|
|
11
|
+
}
|
|
12
|
+
/** All leaf ids under `root`, in first-then-second (left-to-right / top-to-bottom) order. */
|
|
13
|
+
function getLeaves(root) {
|
|
14
|
+
if (root === null) return [];
|
|
15
|
+
if (!isParent(root)) return [root];
|
|
16
|
+
return [...getLeaves(root.first), ...getLeaves(root.second)];
|
|
17
|
+
}
|
|
18
|
+
/** Walks `path` from `root`; `null` if the path runs off a leaf or is otherwise invalid. `path: []` returns `root` itself. */
|
|
19
|
+
function getNodeAtPath(root, path) {
|
|
20
|
+
let node = root;
|
|
21
|
+
for (const step of path) {
|
|
22
|
+
if (node === null || !isParent(node)) return null;
|
|
23
|
+
node = node[step];
|
|
24
|
+
}
|
|
25
|
+
return node;
|
|
26
|
+
}
|
|
27
|
+
/** First DFS path whose leaf `===` matches `leaf`; `null` if not found. Assumes leaf ids are unique across the tree — `Mosaic` warns in dev mode when they aren't. */
|
|
28
|
+
function getPathToLeaf(root, leaf) {
|
|
29
|
+
if (root === null) return null;
|
|
30
|
+
function search(node, path) {
|
|
31
|
+
if (!isParent(node)) return node === leaf ? path : null;
|
|
32
|
+
return search(node.first, [...path, "first"]) ?? search(node.second, [...path, "second"]);
|
|
33
|
+
}
|
|
34
|
+
return search(root, []);
|
|
35
|
+
}
|
|
36
|
+
/** Immutable path-copy replace: only nodes along `path` are cloned, siblings off the path are referentially reused. `path: []` replaces the whole tree. */
|
|
37
|
+
function replaceNodeAtPath(root, path, next) {
|
|
38
|
+
if (path.length === 0) return next;
|
|
39
|
+
if (!isParent(root)) return root;
|
|
40
|
+
const [step, ...rest] = path;
|
|
41
|
+
if (step === "first") return {
|
|
42
|
+
...root,
|
|
43
|
+
first: replaceNodeAtPath(root.first, rest, next)
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
...root,
|
|
47
|
+
second: replaceNodeAtPath(root.second, rest, next)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Patches `splitPercentage` on the parent at `path`, used by the resize-commit callback. No-ops (dev-mode warns) if `path` doesn't resolve to a parent. */
|
|
51
|
+
function updateSplitPercentageAtPath(root, path, splitPercentage) {
|
|
52
|
+
const node = getNodeAtPath(root, path);
|
|
53
|
+
if (node === null || !isParent(node)) {
|
|
54
|
+
if (process.env.NODE_ENV !== "production") console.warn("Mosaic: updateSplitPercentageAtPath was called with a path that doesn't resolve to a parent node.");
|
|
55
|
+
return root;
|
|
56
|
+
}
|
|
57
|
+
return replaceNodeAtPath(root, path, {
|
|
58
|
+
...node,
|
|
59
|
+
splitPercentage
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Removes the leaf at `path`, collapsing its parent so the sibling takes the
|
|
64
|
+
* parent's position. Returns `null` only when `path` is `[]` (the sole
|
|
65
|
+
* remaining leaf — the root itself — is removed).
|
|
66
|
+
*/
|
|
67
|
+
function removeLeaf(root, path) {
|
|
68
|
+
if (path.length === 0) return null;
|
|
69
|
+
const parentPath = path.slice(0, -1);
|
|
70
|
+
const lastStep = path[path.length - 1];
|
|
71
|
+
const parent = getNodeAtPath(root, parentPath);
|
|
72
|
+
if (parent === null || !isParent(parent)) return root;
|
|
73
|
+
const sibling = lastStep === "first" ? parent.second : parent.first;
|
|
74
|
+
if (parentPath.length === 0) return sibling;
|
|
75
|
+
return replaceNodeAtPath(root, parentPath, sibling);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Replaces the node at `path` with a new `MosaicParent` split 50/50 between
|
|
79
|
+
* `newLeaf` and the existing node there. `"before"` (top/left drops) makes
|
|
80
|
+
* `newLeaf` the `first` child; `"after"` (bottom/right drops) makes it `second`.
|
|
81
|
+
*/
|
|
82
|
+
function splitLeaf(root, path, newLeaf, direction, position) {
|
|
83
|
+
const existing = getNodeAtPath(root, path);
|
|
84
|
+
if (existing === null) return root;
|
|
85
|
+
return replaceNodeAtPath(root, path, position === "before" ? {
|
|
86
|
+
direction,
|
|
87
|
+
first: newLeaf,
|
|
88
|
+
second: existing,
|
|
89
|
+
splitPercentage: 50
|
|
90
|
+
} : {
|
|
91
|
+
direction,
|
|
92
|
+
first: existing,
|
|
93
|
+
second: newLeaf,
|
|
94
|
+
splitPercentage: 50
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/** Swaps the two leaves at `pathA`/`pathB` in place, no restructuring. No-op if the paths are equal or either is invalid. Used for center-zone drops. */
|
|
98
|
+
function swapLeaves(root, pathA, pathB) {
|
|
99
|
+
if (pathA.length === pathB.length && pathA.every((step, i) => step === pathB[i])) return root;
|
|
100
|
+
const nodeA = getNodeAtPath(root, pathA);
|
|
101
|
+
const nodeB = getNodeAtPath(root, pathB);
|
|
102
|
+
if (nodeA === null || nodeB === null) return root;
|
|
103
|
+
return replaceNodeAtPath(replaceNodeAtPath(root, pathA, nodeB), pathB, nodeA);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The drag-drop commit entry point. No-op on a self-drop. `zone: "center"`
|
|
107
|
+
* swaps the two leaves; otherwise removes the source leaf and re-resolves the
|
|
108
|
+
* target's path against the POST-REMOVAL tree (removal can shift paths on the
|
|
109
|
+
* way to the target, e.g. when an ancestor collapses away) before splitting
|
|
110
|
+
* at that re-resolved path — never adjusting the original path by arithmetic.
|
|
111
|
+
*/
|
|
112
|
+
function moveLeaf(root, sourceLeaf, targetLeaf, zone) {
|
|
113
|
+
if (sourceLeaf === targetLeaf) return root;
|
|
114
|
+
const sourcePath = getPathToLeaf(root, sourceLeaf);
|
|
115
|
+
const targetPath = getPathToLeaf(root, targetLeaf);
|
|
116
|
+
if (sourcePath === null || targetPath === null) return root;
|
|
117
|
+
if (zone === "center") return swapLeaves(root, sourcePath, targetPath);
|
|
118
|
+
const afterRemoval = removeLeaf(root, sourcePath);
|
|
119
|
+
if (afterRemoval === null) return root;
|
|
120
|
+
const resolvedTargetPath = getPathToLeaf(afterRemoval, targetLeaf);
|
|
121
|
+
if (resolvedTargetPath === null) return afterRemoval;
|
|
122
|
+
return splitLeaf(afterRemoval, resolvedTargetPath, sourceLeaf, zone === "top" || zone === "bottom" ? "column" : "row", zone === "top" || zone === "left" ? "before" : "after");
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Classifies a pointer position within a pane into one of 5 drop zones.
|
|
126
|
+
* Within `dropZoneFraction` of an edge (0-1, fraction of that axis's size)
|
|
127
|
+
* counts as that edge; otherwise center. At corners, where both axes are
|
|
128
|
+
* within range, the axis whose edge distance is smaller wins, so corners
|
|
129
|
+
* resolve deterministically instead of arbitrarily favoring x or y.
|
|
130
|
+
*/
|
|
131
|
+
function classifyDropZone(rect, clientX, clientY, dropZoneFraction) {
|
|
132
|
+
const xFraction = rect.width === 0 ? .5 : (clientX - rect.left) / rect.width;
|
|
133
|
+
const yFraction = rect.height === 0 ? .5 : (clientY - rect.top) / rect.height;
|
|
134
|
+
const xEdgeDistance = Math.min(xFraction, 1 - xFraction);
|
|
135
|
+
const yEdgeDistance = Math.min(yFraction, 1 - yFraction);
|
|
136
|
+
if (xEdgeDistance >= dropZoneFraction && yEdgeDistance >= dropZoneFraction) return "center";
|
|
137
|
+
if (xEdgeDistance < yEdgeDistance) return xFraction < .5 ? "left" : "right";
|
|
138
|
+
return yFraction < .5 ? "top" : "bottom";
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region src/primitives/Mosaic/Mosaic.tsx
|
|
142
|
+
const DEFAULT_DROP_ZONE_FRACTION = .25;
|
|
143
|
+
const DEFAULT_MIN_PANE_SIZE_PERCENTAGE = 10;
|
|
144
|
+
const MosaicContext = React.createContext(null);
|
|
145
|
+
/** Hook giving `MosaicWindow` access to shared drag/split/remove actions; must be used inside a `Mosaic`. */
|
|
146
|
+
function useMosaic() {
|
|
147
|
+
const context = React.useContext(MosaicContext);
|
|
148
|
+
if (!context) throw new Error("useMosaic must be used within a Mosaic.");
|
|
149
|
+
return context;
|
|
150
|
+
}
|
|
151
|
+
/** Recursive tiling layout: panes split into rows/columns, resized via draggable dividers, and rearranged by dragging a pane's title bar onto another pane's edge or center. */
|
|
152
|
+
function Mosaic({ className, style, value, defaultValue, onChange, renderTile, renderTitle, renderControls, renamable = false, paneNames, defaultPaneNames, onPaneNamesChange, createNode, dragToRearrange = true, dropZoneFraction = DEFAULT_DROP_ZONE_FRACTION, minPaneSizePercentage = DEFAULT_MIN_PANE_SIZE_PERCENTAGE, emptyPlaceholder, ...props }) {
|
|
153
|
+
const valueKey = React.useMemo(() => JSON.stringify(value ?? null), [value]);
|
|
154
|
+
const [liveTree, setLiveTree] = React.useState(value !== void 0 ? value : defaultValue ?? null);
|
|
155
|
+
const [syncedValueKey, setSyncedValueKey] = React.useState(valueKey);
|
|
156
|
+
if (value !== void 0 && valueKey !== syncedValueKey) {
|
|
157
|
+
setSyncedValueKey(valueKey);
|
|
158
|
+
setLiveTree(value);
|
|
159
|
+
}
|
|
160
|
+
const liveTreeRef = React.useRef(liveTree);
|
|
161
|
+
liveTreeRef.current = liveTree;
|
|
162
|
+
function commitTree(next) {
|
|
163
|
+
setLiveTree(next);
|
|
164
|
+
onChange?.(next);
|
|
165
|
+
}
|
|
166
|
+
const paneNamesKey = React.useMemo(() => JSON.stringify(paneNames ?? {}), [paneNames]);
|
|
167
|
+
const [livePaneNames, setLivePaneNames] = React.useState(paneNames !== void 0 ? paneNames : defaultPaneNames ?? {});
|
|
168
|
+
const [syncedPaneNamesKey, setSyncedPaneNamesKey] = React.useState(paneNamesKey);
|
|
169
|
+
if (paneNames !== void 0 && paneNamesKey !== syncedPaneNamesKey) {
|
|
170
|
+
setSyncedPaneNamesKey(paneNamesKey);
|
|
171
|
+
setLivePaneNames(paneNames);
|
|
172
|
+
}
|
|
173
|
+
function onRenamePane(id, name) {
|
|
174
|
+
const trimmed = name.trim();
|
|
175
|
+
const next = { ...livePaneNames };
|
|
176
|
+
if (trimmed.length === 0) delete next[id];
|
|
177
|
+
else next[id] = trimmed;
|
|
178
|
+
setLivePaneNames(next);
|
|
179
|
+
onPaneNamesChange?.(next);
|
|
180
|
+
}
|
|
181
|
+
if (process.env.NODE_ENV !== "production") {
|
|
182
|
+
const leaves = getLeaves(liveTree);
|
|
183
|
+
if (new Set(leaves).size !== leaves.length) console.warn("Mosaic: duplicate leaf ids detected in the tree. Every pane needs a unique id, or drag/split/remove operations may target the wrong pane.");
|
|
184
|
+
}
|
|
185
|
+
function onSplitLeaf(path, direction) {
|
|
186
|
+
if (liveTreeRef.current === null) return;
|
|
187
|
+
Promise.resolve(createNode(path)).then((newLeaf) => {
|
|
188
|
+
const current = liveTreeRef.current;
|
|
189
|
+
if (current === null) return;
|
|
190
|
+
commitTree(splitLeaf(current, path, newLeaf, direction, "after"));
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
function onRemoveLeaf(path) {
|
|
194
|
+
const current = liveTreeRef.current;
|
|
195
|
+
if (current === null) return;
|
|
196
|
+
commitTree(removeLeaf(current, path));
|
|
197
|
+
}
|
|
198
|
+
function onGroupLayoutChanged(path, layout, firstPanelId) {
|
|
199
|
+
const current = liveTreeRef.current;
|
|
200
|
+
if (current === null) return;
|
|
201
|
+
const percentage = layout[firstPanelId];
|
|
202
|
+
if (percentage === void 0) return;
|
|
203
|
+
commitTree(updateSplitPercentageAtPath(current, path, percentage));
|
|
204
|
+
}
|
|
205
|
+
const [draggingPath, setDraggingPath] = React.useState(null);
|
|
206
|
+
const [dropTarget, setDropTarget] = React.useState(null);
|
|
207
|
+
function onDragStart(path) {
|
|
208
|
+
setDraggingPath(path);
|
|
209
|
+
}
|
|
210
|
+
function onDragMove(targetPath, zone) {
|
|
211
|
+
setDropTarget(targetPath && zone ? {
|
|
212
|
+
path: targetPath,
|
|
213
|
+
zone
|
|
214
|
+
} : null);
|
|
215
|
+
}
|
|
216
|
+
function onDragEnd(sourceId, targetPath, zone) {
|
|
217
|
+
const current = liveTreeRef.current;
|
|
218
|
+
if (targetPath && zone && current !== null) {
|
|
219
|
+
const targetNode = getNodeAtPath(current, targetPath);
|
|
220
|
+
if (targetNode !== null && !isParent(targetNode)) commitTree(moveLeaf(current, sourceId, targetNode, zone));
|
|
221
|
+
}
|
|
222
|
+
setDraggingPath(null);
|
|
223
|
+
setDropTarget(null);
|
|
224
|
+
}
|
|
225
|
+
function onDragCancel() {
|
|
226
|
+
setDraggingPath(null);
|
|
227
|
+
setDropTarget(null);
|
|
228
|
+
}
|
|
229
|
+
const contextValue = {
|
|
230
|
+
renderTile,
|
|
231
|
+
renderTitle,
|
|
232
|
+
onSplitLeaf,
|
|
233
|
+
onRemoveLeaf,
|
|
234
|
+
onDragStart,
|
|
235
|
+
onDragMove,
|
|
236
|
+
onDragEnd: (sourceId, targetPath, zone) => onDragEnd(sourceId, targetPath, zone),
|
|
237
|
+
onDragCancel,
|
|
238
|
+
draggingPath,
|
|
239
|
+
dropTarget,
|
|
240
|
+
dragToRearrange,
|
|
241
|
+
dropZoneFraction,
|
|
242
|
+
renamable,
|
|
243
|
+
getPaneName: (id) => livePaneNames[id],
|
|
244
|
+
onRenamePane: (id, name) => onRenamePane(id, name)
|
|
245
|
+
};
|
|
246
|
+
function renderNode(node, path) {
|
|
247
|
+
if (!isParent(node)) return /* @__PURE__ */ jsx(MosaicWindow, {
|
|
248
|
+
id: node,
|
|
249
|
+
path,
|
|
250
|
+
controls: renderControls?.(node, path)
|
|
251
|
+
}, String(node));
|
|
252
|
+
const groupId = path.length === 0 ? "mosaic-root" : path.join(".");
|
|
253
|
+
const firstPanelId = `${groupId}.first`;
|
|
254
|
+
const secondPanelId = `${groupId}.second`;
|
|
255
|
+
const firstLabel = String(getLeaves(node.first)[0] ?? "pane");
|
|
256
|
+
const secondLabel = String(getLeaves(node.second)[0] ?? "pane");
|
|
257
|
+
return /* @__PURE__ */ jsxs(ResizablePanelGroup, {
|
|
258
|
+
id: groupId,
|
|
259
|
+
orientation: node.direction === "row" ? "horizontal" : "vertical",
|
|
260
|
+
onLayoutChanged: (layout) => onGroupLayoutChanged(path, layout, firstPanelId),
|
|
261
|
+
children: [
|
|
262
|
+
/* @__PURE__ */ jsx(ResizablePanel, {
|
|
263
|
+
id: firstPanelId,
|
|
264
|
+
defaultSize: node.splitPercentage ?? 50,
|
|
265
|
+
minSize: minPaneSizePercentage,
|
|
266
|
+
children: renderNode(node.first, [...path, "first"])
|
|
267
|
+
}),
|
|
268
|
+
/* @__PURE__ */ jsx(ResizableHandle, { "aria-label": `Resize between pane ${firstLabel} and pane ${secondLabel}` }),
|
|
269
|
+
/* @__PURE__ */ jsx(ResizablePanel, {
|
|
270
|
+
id: secondPanelId,
|
|
271
|
+
defaultSize: 100 - (node.splitPercentage ?? 50),
|
|
272
|
+
minSize: minPaneSizePercentage,
|
|
273
|
+
children: renderNode(node.second, [...path, "second"])
|
|
274
|
+
})
|
|
275
|
+
]
|
|
276
|
+
}, groupId);
|
|
277
|
+
}
|
|
278
|
+
return /* @__PURE__ */ jsx(MosaicContext.Provider, {
|
|
279
|
+
value: contextValue,
|
|
280
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
281
|
+
"data-slot": "mosaic",
|
|
282
|
+
className: cn("relative h-full w-full overflow-hidden", className),
|
|
283
|
+
style,
|
|
284
|
+
...props,
|
|
285
|
+
children: liveTree === null ? emptyPlaceholder ?? null : renderNode(liveTree, [])
|
|
286
|
+
})
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
const dropZoneOverlayClass = {
|
|
290
|
+
top: "inset-x-0 top-0 h-1/2",
|
|
291
|
+
bottom: "inset-x-0 bottom-0 h-1/2",
|
|
292
|
+
left: "inset-y-0 left-0 w-1/2",
|
|
293
|
+
right: "inset-y-0 right-0 w-1/2",
|
|
294
|
+
center: "inset-0"
|
|
295
|
+
};
|
|
296
|
+
/**
|
|
297
|
+
* A single pane's chrome: drag handle, title, split/remove buttons, and its
|
|
298
|
+
* `renderTile` content. Rendered internally by `Mosaic` for every leaf,
|
|
299
|
+
* and also exported for a consumer already inside a `<Mosaic>` tree who
|
|
300
|
+
* wants to add a fixed, non-tile element reusing the same toolbar chrome —
|
|
301
|
+
* it calls `useMosaic()` internally, so it can't be used to build an
|
|
302
|
+
* independent custom recursive renderer outside a `Mosaic`.
|
|
303
|
+
*
|
|
304
|
+
* The `path` you supply for such a fixed element must not collide with any
|
|
305
|
+
* real leaf's path in the current tree — its split/remove/rename actions
|
|
306
|
+
* operate on whatever the tree resolves at that path, so a colliding path
|
|
307
|
+
* would silently act on that real pane instead of a no-op.
|
|
308
|
+
*/
|
|
309
|
+
function MosaicWindow({ id, path, className, controls }) {
|
|
310
|
+
const { renderTile, renderTitle, onSplitLeaf, onRemoveLeaf, onDragStart, onDragMove, onDragEnd, onDragCancel, draggingPath, dropTarget, dragToRearrange, dropZoneFraction, renamable, getPaneName, onRenamePane } = useMosaic();
|
|
311
|
+
const pathKey = path.join(".");
|
|
312
|
+
const isDragging = draggingPath !== null && draggingPath.join(".") === pathKey;
|
|
313
|
+
const isDropTarget = dropTarget !== null && dropTarget.path.join(".") === pathKey;
|
|
314
|
+
const accessibleName = getPaneName(id) ?? String(id);
|
|
315
|
+
const [isEditingName, setIsEditingName] = React.useState(false);
|
|
316
|
+
const [draftName, setDraftName] = React.useState("");
|
|
317
|
+
const editResolvedRef = React.useRef(false);
|
|
318
|
+
function startEditingName() {
|
|
319
|
+
editResolvedRef.current = false;
|
|
320
|
+
setDraftName(getPaneName(id) ?? String(id));
|
|
321
|
+
setIsEditingName(true);
|
|
322
|
+
}
|
|
323
|
+
function commitEditingName(name) {
|
|
324
|
+
if (editResolvedRef.current) return;
|
|
325
|
+
editResolvedRef.current = true;
|
|
326
|
+
setIsEditingName(false);
|
|
327
|
+
onRenamePane(id, name);
|
|
328
|
+
}
|
|
329
|
+
function cancelEditingName() {
|
|
330
|
+
editResolvedRef.current = true;
|
|
331
|
+
setIsEditingName(false);
|
|
332
|
+
}
|
|
333
|
+
function resolveHover(clientX, clientY) {
|
|
334
|
+
const hoveredEl = document.elementFromPoint(clientX, clientY)?.closest("[data-slot=\"mosaic-window\"]");
|
|
335
|
+
const hoveredPathKey = hoveredEl?.dataset.mosaicPath;
|
|
336
|
+
if (!hoveredEl || hoveredPathKey === void 0 || hoveredPathKey === pathKey) return null;
|
|
337
|
+
return {
|
|
338
|
+
targetPath: hoveredPathKey === "" ? [] : hoveredPathKey.split("."),
|
|
339
|
+
zone: classifyDropZone(hoveredEl.getBoundingClientRect(), clientX, clientY, dropZoneFraction)
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
function handleGripPointerDown(event) {
|
|
343
|
+
if (event.button !== 0 && event.pointerType === "mouse") return;
|
|
344
|
+
event.preventDefault();
|
|
345
|
+
onDragStart(path);
|
|
346
|
+
document.body.style.cursor = "grabbing";
|
|
347
|
+
function removeListeners() {
|
|
348
|
+
window.removeEventListener("pointermove", onMove);
|
|
349
|
+
window.removeEventListener("pointerup", onUp);
|
|
350
|
+
window.removeEventListener("pointercancel", onCancel);
|
|
351
|
+
}
|
|
352
|
+
const onMove = (moveEvent) => {
|
|
353
|
+
const hover = resolveHover(moveEvent.clientX, moveEvent.clientY);
|
|
354
|
+
onDragMove(hover?.targetPath ?? null, hover?.zone ?? null);
|
|
355
|
+
};
|
|
356
|
+
const onUp = (upEvent) => {
|
|
357
|
+
removeListeners();
|
|
358
|
+
document.body.style.cursor = "";
|
|
359
|
+
const hover = resolveHover(upEvent.clientX, upEvent.clientY);
|
|
360
|
+
onDragEnd(id, hover?.targetPath ?? null, hover?.zone ?? null);
|
|
361
|
+
};
|
|
362
|
+
const onCancel = () => {
|
|
363
|
+
removeListeners();
|
|
364
|
+
document.body.style.cursor = "";
|
|
365
|
+
onDragCancel();
|
|
366
|
+
};
|
|
367
|
+
window.addEventListener("pointermove", onMove);
|
|
368
|
+
window.addEventListener("pointerup", onUp);
|
|
369
|
+
window.addEventListener("pointercancel", onCancel);
|
|
370
|
+
}
|
|
371
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
372
|
+
"data-slot": "mosaic-window",
|
|
373
|
+
"data-mosaic-path": pathKey,
|
|
374
|
+
className: cn("relative flex h-full w-full flex-col overflow-hidden", isDragging && "opacity-50", className),
|
|
375
|
+
children: [
|
|
376
|
+
/* @__PURE__ */ jsxs("div", {
|
|
377
|
+
"data-slot": "mosaic-window-toolbar",
|
|
378
|
+
className: "flex shrink-0 items-center gap-1 border-primary-border border-b bg-primary-bg px-1.5 py-1",
|
|
379
|
+
children: [
|
|
380
|
+
dragToRearrange && /* @__PURE__ */ jsx("button", {
|
|
381
|
+
type: "button",
|
|
382
|
+
"data-slot": "mosaic-window-grip",
|
|
383
|
+
"aria-label": `Drag to move pane "${accessibleName}". Use the split and close buttons for keyboard-accessible rearranging.`,
|
|
384
|
+
draggable: false,
|
|
385
|
+
className: "flex size-6 shrink-0 cursor-grab touch-none items-center justify-center rounded-6 text-muted-txt focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-focus active:cursor-grabbing",
|
|
386
|
+
onPointerDown: handleGripPointerDown,
|
|
387
|
+
children: /* @__PURE__ */ jsx(GripVerticalIcon, { className: "size-3.5" })
|
|
388
|
+
}),
|
|
389
|
+
isEditingName ? /* @__PURE__ */ jsx("input", {
|
|
390
|
+
type: "text",
|
|
391
|
+
"data-slot": "mosaic-window-name-input",
|
|
392
|
+
"aria-label": `Pane name for "${accessibleName}"`,
|
|
393
|
+
value: draftName,
|
|
394
|
+
autoFocus: true,
|
|
395
|
+
className: "h-6 min-w-0 flex-1 rounded-4 border border-primary-border bg-primary-bg px-1 text-primary-txt text-sm outline-hidden focus-visible:ring-1 focus-visible:ring-focus",
|
|
396
|
+
onChange: (event) => setDraftName(event.target.value),
|
|
397
|
+
onFocus: (event) => event.currentTarget.select(),
|
|
398
|
+
onBlur: (event) => commitEditingName(event.currentTarget.value),
|
|
399
|
+
onKeyDown: (event) => {
|
|
400
|
+
if (event.key === "Enter") {
|
|
401
|
+
event.preventDefault();
|
|
402
|
+
commitEditingName(event.currentTarget.value);
|
|
403
|
+
} else if (event.key === "Escape") {
|
|
404
|
+
event.preventDefault();
|
|
405
|
+
cancelEditingName();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}) : /* @__PURE__ */ jsx("span", {
|
|
409
|
+
className: "min-w-0 flex-1 truncate text-primary-txt text-sm",
|
|
410
|
+
onDoubleClick: renamable ? startEditingName : void 0,
|
|
411
|
+
children: getPaneName(id) ?? (renderTitle ? renderTitle(id, path) : String(id))
|
|
412
|
+
}),
|
|
413
|
+
renamable && !isEditingName && /* @__PURE__ */ jsx(Button, {
|
|
414
|
+
variant: "ghost",
|
|
415
|
+
size: "icon-xs",
|
|
416
|
+
"aria-label": `Rename pane "${accessibleName}"`,
|
|
417
|
+
onClick: startEditingName,
|
|
418
|
+
children: /* @__PURE__ */ jsx(PencilIcon, {})
|
|
419
|
+
}),
|
|
420
|
+
controls,
|
|
421
|
+
/* @__PURE__ */ jsx(Button, {
|
|
422
|
+
variant: "ghost",
|
|
423
|
+
size: "icon-xs",
|
|
424
|
+
"aria-label": `Split pane "${accessibleName}", side by side`,
|
|
425
|
+
onClick: () => onSplitLeaf(path, "row"),
|
|
426
|
+
children: /* @__PURE__ */ jsx(PanelLeftIcon, {})
|
|
427
|
+
}),
|
|
428
|
+
/* @__PURE__ */ jsx(Button, {
|
|
429
|
+
variant: "ghost",
|
|
430
|
+
size: "icon-xs",
|
|
431
|
+
"aria-label": `Split pane "${accessibleName}", stacked`,
|
|
432
|
+
onClick: () => onSplitLeaf(path, "column"),
|
|
433
|
+
children: /* @__PURE__ */ jsx(PanelTopIcon, {})
|
|
434
|
+
}),
|
|
435
|
+
/* @__PURE__ */ jsx(Button, {
|
|
436
|
+
variant: "ghost",
|
|
437
|
+
size: "icon-xs",
|
|
438
|
+
"aria-label": `Remove pane "${accessibleName}"`,
|
|
439
|
+
onClick: () => onRemoveLeaf(path),
|
|
440
|
+
children: /* @__PURE__ */ jsx(XIcon, {})
|
|
441
|
+
})
|
|
442
|
+
]
|
|
443
|
+
}),
|
|
444
|
+
/* @__PURE__ */ jsx("div", {
|
|
445
|
+
"data-slot": "mosaic-window-content",
|
|
446
|
+
className: "min-h-0 flex-1 overflow-auto",
|
|
447
|
+
children: renderTile(id, path)
|
|
448
|
+
}),
|
|
449
|
+
isDropTarget && dropTarget && /* @__PURE__ */ jsx("div", {
|
|
450
|
+
"data-slot": "mosaic-drop-overlay",
|
|
451
|
+
className: cn("pointer-events-none absolute z-20 bg-focus/20 ring-2 ring-focus ring-inset", dropZoneOverlayClass[dropTarget.zone])
|
|
452
|
+
})
|
|
453
|
+
]
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
//#endregion
|
|
457
|
+
export { MosaicWindow as n, Mosaic as t };
|
|
458
|
+
|
|
459
|
+
//# sourceMappingURL=Mosaic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Mosaic.js","names":[],"sources":["../src/primitives/Mosaic/Mosaic.utils.ts","../src/primitives/Mosaic/Mosaic.tsx"],"sourcesContent":["// Pure tree/geometry helpers for Mosaic, kept separate from the component so\n// the tree algorithm and drop-zone math are unit-testable without a real\n// browser — matching MultiColumn.utils.ts's split between pure logic and DOM\n// wiring.\n\n/** A pane's identity. Compared with `===`, so no object identities. */\ntype MosaicKey = string | number;\n\n/** \"row\" places children side by side (horizontal split); \"column\" stacks them (vertical split). */\ntype MosaicDirection = \"row\" | \"column\";\n\n/** Sequence of \"first\"/\"second\" steps from the tree root down to a node. */\ntype MosaicPath = (\"first\" | \"second\")[];\n\ntype MosaicParent<T extends MosaicKey = MosaicKey> = {\n direction: MosaicDirection;\n first: MosaicNode<T>;\n second: MosaicNode<T>;\n /** Percentage (0-100) of the group's size given to `first`. Defaults to 50 when omitted. */\n splitPercentage?: number;\n};\n\n/** A leaf pane id, or a parent split of two further nodes. */\ntype MosaicNode<T extends MosaicKey = MosaicKey> = T | MosaicParent<T>;\n\n/** Which edge (or center) of a pane a drag is hovering over. */\ntype DropZone = \"top\" | \"bottom\" | \"left\" | \"right\" | \"center\";\n\n/** Every recursive walk depends on this being correct — `T` is constrained to non-object keys precisely so this check can't be fooled by a leaf that happens to be an object. */\nfunction isParent<T extends MosaicKey>(node: MosaicNode<T>): node is MosaicParent<T> {\n return typeof node === \"object\" && node !== null && \"direction\" in node;\n}\n\n/** All leaf ids under `root`, in first-then-second (left-to-right / top-to-bottom) order. */\nfunction getLeaves<T extends MosaicKey>(root: MosaicNode<T> | null): T[] {\n if (root === null) return [];\n if (!isParent(root)) return [root];\n return [...getLeaves(root.first), ...getLeaves(root.second)];\n}\n\n/** Walks `path` from `root`; `null` if the path runs off a leaf or is otherwise invalid. `path: []` returns `root` itself. */\nfunction getNodeAtPath<T extends MosaicKey>(\n root: MosaicNode<T> | null,\n path: MosaicPath,\n): MosaicNode<T> | null {\n let node = root;\n for (const step of path) {\n if (node === null || !isParent(node)) return null;\n node = node[step];\n }\n return node;\n}\n\n/** First DFS path whose leaf `===` matches `leaf`; `null` if not found. Assumes leaf ids are unique across the tree — `Mosaic` warns in dev mode when they aren't. */\nfunction getPathToLeaf<T extends MosaicKey>(\n root: MosaicNode<T> | null,\n leaf: T,\n): MosaicPath | null {\n if (root === null) return null;\n function search(node: MosaicNode<T>, path: MosaicPath): MosaicPath | null {\n if (!isParent(node)) {\n return node === leaf ? path : null;\n }\n return search(node.first, [...path, \"first\"]) ?? search(node.second, [...path, \"second\"]);\n }\n return search(root, []);\n}\n\n/** Immutable path-copy replace: only nodes along `path` are cloned, siblings off the path are referentially reused. `path: []` replaces the whole tree. */\nfunction replaceNodeAtPath<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n next: MosaicNode<T>,\n): MosaicNode<T> {\n if (path.length === 0) return next;\n if (!isParent(root)) return root;\n const [step, ...rest] = path;\n if (step === \"first\") {\n return { ...root, first: replaceNodeAtPath(root.first, rest, next) };\n }\n return { ...root, second: replaceNodeAtPath(root.second, rest, next) };\n}\n\n/** Patches `splitPercentage` on the parent at `path`, used by the resize-commit callback. No-ops (dev-mode warns) if `path` doesn't resolve to a parent. */\nfunction updateSplitPercentageAtPath<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n splitPercentage: number,\n): MosaicNode<T> {\n const node = getNodeAtPath(root, path);\n if (node === null || !isParent(node)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"Mosaic: updateSplitPercentageAtPath was called with a path that doesn't resolve to a parent node.\",\n );\n }\n return root;\n }\n return replaceNodeAtPath(root, path, { ...node, splitPercentage });\n}\n\n/**\n * Removes the leaf at `path`, collapsing its parent so the sibling takes the\n * parent's position. Returns `null` only when `path` is `[]` (the sole\n * remaining leaf — the root itself — is removed).\n */\nfunction removeLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n): MosaicNode<T> | null {\n if (path.length === 0) return null;\n const parentPath = path.slice(0, -1);\n const lastStep = path[path.length - 1];\n const parent = getNodeAtPath(root, parentPath);\n if (parent === null || !isParent(parent)) return root;\n const sibling = lastStep === \"first\" ? parent.second : parent.first;\n if (parentPath.length === 0) return sibling;\n return replaceNodeAtPath(root, parentPath, sibling);\n}\n\n/**\n * Replaces the node at `path` with a new `MosaicParent` split 50/50 between\n * `newLeaf` and the existing node there. `\"before\"` (top/left drops) makes\n * `newLeaf` the `first` child; `\"after\"` (bottom/right drops) makes it `second`.\n */\nfunction splitLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n path: MosaicPath,\n newLeaf: T,\n direction: MosaicDirection,\n position: \"before\" | \"after\",\n): MosaicNode<T> {\n const existing = getNodeAtPath(root, path);\n if (existing === null) return root;\n const parent: MosaicParent<T> =\n position === \"before\"\n ? { direction, first: newLeaf, second: existing, splitPercentage: 50 }\n : { direction, first: existing, second: newLeaf, splitPercentage: 50 };\n return replaceNodeAtPath(root, path, parent);\n}\n\n/** Swaps the two leaves at `pathA`/`pathB` in place, no restructuring. No-op if the paths are equal or either is invalid. Used for center-zone drops. */\nfunction swapLeaves<T extends MosaicKey>(\n root: MosaicNode<T>,\n pathA: MosaicPath,\n pathB: MosaicPath,\n): MosaicNode<T> {\n if (pathA.length === pathB.length && pathA.every((step, i) => step === pathB[i])) return root;\n const nodeA = getNodeAtPath(root, pathA);\n const nodeB = getNodeAtPath(root, pathB);\n if (nodeA === null || nodeB === null) return root;\n const afterA = replaceNodeAtPath(root, pathA, nodeB);\n return replaceNodeAtPath(afterA, pathB, nodeA);\n}\n\n/**\n * The drag-drop commit entry point. No-op on a self-drop. `zone: \"center\"`\n * swaps the two leaves; otherwise removes the source leaf and re-resolves the\n * target's path against the POST-REMOVAL tree (removal can shift paths on the\n * way to the target, e.g. when an ancestor collapses away) before splitting\n * at that re-resolved path — never adjusting the original path by arithmetic.\n */\nfunction moveLeaf<T extends MosaicKey>(\n root: MosaicNode<T>,\n sourceLeaf: T,\n targetLeaf: T,\n zone: DropZone,\n): MosaicNode<T> | null {\n if (sourceLeaf === targetLeaf) return root;\n const sourcePath = getPathToLeaf(root, sourceLeaf);\n const targetPath = getPathToLeaf(root, targetLeaf);\n if (sourcePath === null || targetPath === null) return root;\n\n if (zone === \"center\") {\n return swapLeaves(root, sourcePath, targetPath);\n }\n\n const afterRemoval = removeLeaf(root, sourcePath);\n if (afterRemoval === null) {\n // Unreachable: root having only sourceLeaf means targetLeaf couldn't have\n // been found above (sourceLeaf === targetLeaf is already handled). Kept\n // as a defensive no-op rather than assuming it can never fire.\n return root;\n }\n const resolvedTargetPath = getPathToLeaf(afterRemoval, targetLeaf);\n if (resolvedTargetPath === null) return afterRemoval;\n\n const direction: MosaicDirection = zone === \"top\" || zone === \"bottom\" ? \"column\" : \"row\";\n const position: \"before\" | \"after\" = zone === \"top\" || zone === \"left\" ? \"before\" : \"after\";\n return splitLeaf(afterRemoval, resolvedTargetPath, sourceLeaf, direction, position);\n}\n\n/** A pane's rect in the same coordinate space as pointer `clientX`/`clientY` (i.e. `getBoundingClientRect()`). */\ntype PaneRect = { left: number; top: number; width: number; height: number };\n\n/**\n * Classifies a pointer position within a pane into one of 5 drop zones.\n * Within `dropZoneFraction` of an edge (0-1, fraction of that axis's size)\n * counts as that edge; otherwise center. At corners, where both axes are\n * within range, the axis whose edge distance is smaller wins, so corners\n * resolve deterministically instead of arbitrarily favoring x or y.\n */\nfunction classifyDropZone(\n rect: PaneRect,\n clientX: number,\n clientY: number,\n dropZoneFraction: number,\n): DropZone {\n const xFraction = rect.width === 0 ? 0.5 : (clientX - rect.left) / rect.width;\n const yFraction = rect.height === 0 ? 0.5 : (clientY - rect.top) / rect.height;\n const xEdgeDistance = Math.min(xFraction, 1 - xFraction);\n const yEdgeDistance = Math.min(yFraction, 1 - yFraction);\n\n if (xEdgeDistance >= dropZoneFraction && yEdgeDistance >= dropZoneFraction) return \"center\";\n if (xEdgeDistance < yEdgeDistance) {\n return xFraction < 0.5 ? \"left\" : \"right\";\n }\n return yFraction < 0.5 ? \"top\" : \"bottom\";\n}\n\nexport {\n isParent,\n getLeaves,\n getNodeAtPath,\n getPathToLeaf,\n replaceNodeAtPath,\n updateSplitPercentageAtPath,\n removeLeaf,\n splitLeaf,\n swapLeaves,\n moveLeaf,\n classifyDropZone,\n type MosaicKey,\n type MosaicDirection,\n type MosaicPath,\n type MosaicParent,\n type MosaicNode,\n type DropZone,\n type PaneRect,\n};\n","\"use client\";\n\nimport { GripVerticalIcon, PanelLeftIcon, PanelTopIcon, PencilIcon, XIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/primitives/Button\";\nimport { ResizableHandle, ResizablePanel, ResizablePanelGroup } from \"@/primitives/Resizable\";\nimport { cn } from \"@/utils\";\nimport {\n type DropZone,\n type MosaicDirection,\n type MosaicKey,\n type MosaicNode,\n type MosaicPath,\n classifyDropZone,\n getLeaves,\n getNodeAtPath,\n isParent,\n moveLeaf,\n removeLeaf,\n splitLeaf,\n updateSplitPercentageAtPath,\n} from \"./Mosaic.utils\";\n\nconst DEFAULT_DROP_ZONE_FRACTION = 0.25;\nconst DEFAULT_MIN_PANE_SIZE_PERCENTAGE = 10;\n\n// The context is intentionally widened to MosaicKey rather than parameterized\n// by the consumer's T — React context can't itself be generic. This is safe\n// at runtime because every id flowing through a given <Mosaic> instance's\n// context originates from that same instance's T-typed tree; MosaicWindow\n// narrows back to T at its own boundary.\ntype MosaicContextValue = {\n renderTile: (id: MosaicKey, path: MosaicPath) => React.ReactNode;\n renderTitle: ((id: MosaicKey, path: MosaicPath) => React.ReactNode) | undefined;\n onSplitLeaf: (path: MosaicPath, direction: MosaicDirection) => void;\n onRemoveLeaf: (path: MosaicPath) => void;\n onDragStart: (path: MosaicPath) => void;\n onDragMove: (targetPath: MosaicPath | null, zone: DropZone | null) => void;\n onDragEnd: (sourceId: MosaicKey, targetPath: MosaicPath | null, zone: DropZone | null) => void;\n onDragCancel: () => void;\n draggingPath: MosaicPath | null;\n dropTarget: { path: MosaicPath; zone: DropZone } | null;\n dragToRearrange: boolean;\n dropZoneFraction: number;\n renamable: boolean;\n getPaneName: (id: MosaicKey) => string | undefined;\n onRenamePane: (id: MosaicKey, name: string) => void;\n};\n\nconst MosaicContext = React.createContext<MosaicContextValue | null>(null);\n\n/** Hook giving `MosaicWindow` access to shared drag/split/remove actions; must be used inside a `Mosaic`. */\nfunction useMosaic(): MosaicContextValue {\n const context = React.useContext(MosaicContext);\n if (!context) {\n throw new Error(\"useMosaic must be used within a Mosaic.\");\n }\n return context;\n}\n\ntype MosaicProps<T extends MosaicKey = string> = Omit<\n React.ComponentProps<\"div\">,\n \"onChange\" | \"value\" | \"defaultValue\"\n> & {\n /** The tree of panes to render. `null` (or an empty tree via `emptyPlaceholder`) renders nothing tile-related. */\n value?: MosaicNode<T> | null;\n /** Initial tree when uncontrolled. */\n defaultValue?: MosaicNode<T> | null;\n /**\n * Fires with the updated tree after a resize, toolbar split/remove, or\n * drag-drop rearrange. Pass `value` back to fully control; omit for\n * internal (uncontrolled) tracking — mirrors MultiColumn's\n * `columns`/`onColumnsChange`.\n *\n * Note: there is no strict controlled veto. If a controlled consumer's\n * `onChange` doesn't feed back an updated `value` (e.g. to reject a\n * drag/split), the optimistic change still applies locally and persists —\n * the same behavior MultiColumn already ships for resize/reorder. A true\n * veto would need a different API shape (e.g. an `onBeforeChange` returning\n * `boolean`), which is out of scope here.\n */\n onChange?: (next: MosaicNode<T> | null) => void;\n /** Renders the content for a leaf pane; required — Mosaic has no default tile content. */\n renderTile: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders the title shown in a pane's toolbar. Defaults to `String(id)`. */\n renderTitle?: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders extra toolbar actions for a pane, after the built-in split/remove buttons. */\n renderControls?: (id: T, path: MosaicPath) => React.ReactNode;\n /** Renders a rename (pencil) button in each pane's toolbar; double-clicking the title also starts editing. Renaming sets a plain-text name that overrides `renderTitle`/`String(id)` for that pane. Default off. */\n renamable?: boolean;\n /** Custom pane names, keyed by leaf id (controlled). Only panes that have been renamed need an entry. */\n paneNames?: Partial<Record<T, string>>;\n /** Initial pane names when uncontrolled. */\n defaultPaneNames?: Partial<Record<T, string>>;\n /** Fires with the updated name map after a rename commits (Enter, blur, or the confirm affordance). Clearing a pane's name back to empty removes its entry, falling back to `renderTitle`/`String(id)` again. Pass `paneNames` back to fully control; omit for internal (uncontrolled) tracking. */\n onPaneNamesChange?: (names: Partial<Record<T, string>>) => void;\n /**\n * Creates the id for a new pane when a toolbar split button is used\n * (drag-triggered splits reuse the dragged pane's existing id instead).\n * May return a Promise. `renderTile` must be able to render whatever this\n * returns.\n */\n createNode: (path: MosaicPath) => T | Promise<T>;\n /** Renders a drag handle in each pane's toolbar for drag-to-split/rearrange. Toolbar split/remove buttons remain active either way. Default enabled. */\n dragToRearrange?: boolean;\n /** Fraction (0-1) of a pane's width/height, measured from each edge, that counts as an edge drop zone rather than the center. Defaults to `0.25`. */\n dropZoneFraction?: number;\n /** Minimum size (percentage, 0-100) a pane can be resized down to. Defaults to `10`. */\n minPaneSizePercentage?: number;\n /** Rendered instead of the tree when `value`/the live tree is `null` (e.g. every pane has been removed). */\n emptyPlaceholder?: React.ReactNode;\n};\n\n/** Recursive tiling layout: panes split into rows/columns, resized via draggable dividers, and rearranged by dragging a pane's title bar onto another pane's edge or center. */\nfunction Mosaic<T extends MosaicKey = string>({\n className,\n style,\n value,\n defaultValue,\n onChange,\n renderTile,\n renderTitle,\n renderControls,\n renamable = false,\n paneNames,\n defaultPaneNames,\n onPaneNamesChange,\n createNode,\n dragToRearrange = true,\n dropZoneFraction = DEFAULT_DROP_ZONE_FRACTION,\n minPaneSizePercentage = DEFAULT_MIN_PANE_SIZE_PERCENTAGE,\n emptyPlaceholder,\n ...props\n}: MosaicProps<T>) {\n // ---- Controlled/uncontrolled sync — generalizes MultiColumn's\n // columnsKey/syncedColumnsKey render-time-sync idiom to a tree. Unlike\n // MultiColumn, `value` is genuinely optional (the tree is stateful\n // regardless of controlled mode), so the resync only fires when `value` is\n // actually passed and has changed.\n const valueKey = React.useMemo(() => JSON.stringify(value ?? null), [value]);\n const [liveTree, setLiveTree] = React.useState<MosaicNode<T> | null>(\n value !== undefined ? value : (defaultValue ?? null),\n );\n const [syncedValueKey, setSyncedValueKey] = React.useState(valueKey);\n if (value !== undefined && valueKey !== syncedValueKey) {\n setSyncedValueKey(valueKey);\n setLiveTree(value);\n }\n\n // Mirrors `liveTree` for reads inside callbacks that resume after a gap\n // (an awaited `createNode`, or a pointerdown-to-pointerup drag session) —\n // those callbacks close over whatever `liveTree` was at the time they were\n // created, which can be stale if something else committed a change during\n // the gap. Reading `liveTreeRef.current` instead always reflects the tree\n // at the moment the callback actually runs, not the moment it was defined.\n const liveTreeRef = React.useRef(liveTree);\n liveTreeRef.current = liveTree;\n\n function commitTree(next: MosaicNode<T> | null) {\n setLiveTree(next);\n onChange?.(next);\n }\n\n // ---- Pane rename state — same render-time-sync idiom as the tree above,\n // but a separate controlled pair (not folded into `value`) since a pane's\n // display name and its position in the tree are independent concerns.\n const paneNamesKey = React.useMemo(() => JSON.stringify(paneNames ?? {}), [paneNames]);\n const [livePaneNames, setLivePaneNames] = React.useState<Partial<Record<T, string>>>(\n paneNames !== undefined ? paneNames : (defaultPaneNames ?? {}),\n );\n const [syncedPaneNamesKey, setSyncedPaneNamesKey] = React.useState(paneNamesKey);\n if (paneNames !== undefined && paneNamesKey !== syncedPaneNamesKey) {\n setSyncedPaneNamesKey(paneNamesKey);\n setLivePaneNames(paneNames);\n }\n\n function onRenamePane(id: T, name: string) {\n const trimmed = name.trim();\n const next = { ...livePaneNames };\n if (trimmed.length === 0) {\n delete next[id];\n } else {\n next[id] = trimmed;\n }\n setLivePaneNames(next);\n onPaneNamesChange?.(next);\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n const leaves = getLeaves(liveTree);\n if (new Set(leaves).size !== leaves.length) {\n console.warn(\n \"Mosaic: duplicate leaf ids detected in the tree. Every pane needs a unique id, or drag/split/remove operations may target the wrong pane.\",\n );\n }\n }\n\n // ---- Split/remove ----\n function onSplitLeaf(path: MosaicPath, direction: MosaicDirection) {\n if (liveTreeRef.current === null) return;\n // `createNode` may be async — read `liveTreeRef.current` again once it\n // resolves rather than the `liveTree` closed over above, in case a\n // resize/remove/drag committed a change while the promise was in flight.\n Promise.resolve(createNode(path)).then((newLeaf) => {\n const current = liveTreeRef.current;\n if (current === null) return;\n commitTree(splitLeaf(current, path, newLeaf, direction, \"after\"));\n });\n }\n\n function onRemoveLeaf(path: MosaicPath) {\n const current = liveTreeRef.current;\n if (current === null) return;\n commitTree(removeLeaf(current, path));\n }\n\n // ---- Resize commit — wired to each Group's onLayoutChanged (fires once,\n // after the pointer is released), not Panel.onResize (fires every pointer\n // move tick) — see Mosaic.tsx rendering below.\n function onGroupLayoutChanged(\n path: MosaicPath,\n layout: Record<string, number>,\n firstPanelId: string,\n ) {\n const current = liveTreeRef.current;\n if (current === null) return;\n const percentage = layout[firstPanelId];\n if (percentage === undefined) return;\n commitTree(updateSplitPercentageAtPath(current, path, percentage));\n }\n\n // ---- Drag-to-rearrange state — shared via context so every MosaicWindow\n // can render its own drag/drop-target feedback without prop-drilling.\n const [draggingPath, setDraggingPath] = React.useState<MosaicPath | null>(null);\n const [dropTarget, setDropTarget] = React.useState<{ path: MosaicPath; zone: DropZone } | null>(\n null,\n );\n\n function onDragStart(path: MosaicPath) {\n setDraggingPath(path);\n }\n\n function onDragMove(targetPath: MosaicPath | null, zone: DropZone | null) {\n setDropTarget(targetPath && zone ? { path: targetPath, zone } : null);\n }\n\n // `sourceId` — the dragged pane's own leaf id — is passed in directly by\n // the caller (`MosaicWindow` already knows its own `id` prop) rather than\n // re-derived here via `getNodeAtPath(tree, sourcePath)`. Two reasons:\n // 1. This fires synchronously from the same pointerup handler registered\n // at pointerdown time, before React has necessarily flushed the state\n // update `onDragStart` queued — reading `draggingPath` state here would\n // close over that pre-drag (still `null`) render.\n // 2. If the tree was restructured elsewhere while this drag was in\n // progress (another split/remove, or a controlled `value` update),\n // `sourcePath` could now resolve to a different leaf than the one the\n // user actually grabbed. `moveLeaf` re-derives the source's current\n // path from its id fresh against `liveTreeRef.current`, so passing the\n // id directly can't silently move the wrong pane.\n function onDragEnd(sourceId: T, targetPath: MosaicPath | null, zone: DropZone | null) {\n const current = liveTreeRef.current;\n if (targetPath && zone && current !== null) {\n const targetNode = getNodeAtPath(current, targetPath);\n if (targetNode !== null && !isParent(targetNode)) {\n commitTree(moveLeaf(current, sourceId, targetNode, zone));\n }\n }\n setDraggingPath(null);\n setDropTarget(null);\n }\n\n function onDragCancel() {\n setDraggingPath(null);\n setDropTarget(null);\n }\n\n const contextValue: MosaicContextValue = {\n renderTile: renderTile as (id: MosaicKey, path: MosaicPath) => React.ReactNode,\n renderTitle: renderTitle as ((id: MosaicKey, path: MosaicPath) => React.ReactNode) | undefined,\n onSplitLeaf,\n onRemoveLeaf,\n onDragStart,\n onDragMove,\n onDragEnd: (sourceId, targetPath, zone) => onDragEnd(sourceId as T, targetPath, zone),\n onDragCancel,\n draggingPath,\n dropTarget,\n dragToRearrange,\n dropZoneFraction,\n renamable,\n getPaneName: (id) => livePaneNames[id as T],\n onRenamePane: (id, name) => onRenamePane(id as T, name),\n };\n\n // ---- Recursive rendering ----\n function renderNode(node: MosaicNode<T>, path: MosaicPath): React.ReactNode {\n if (!isParent(node)) {\n return (\n <MosaicWindow\n key={String(node)}\n id={node}\n path={path}\n controls={renderControls?.(node, path)}\n />\n );\n }\n\n const groupId = path.length === 0 ? \"mosaic-root\" : path.join(\".\");\n const firstPanelId = `${groupId}.first`;\n const secondPanelId = `${groupId}.second`;\n const firstLabel = String(getLeaves(node.first)[0] ?? \"pane\");\n const secondLabel = String(getLeaves(node.second)[0] ?? \"pane\");\n\n return (\n <ResizablePanelGroup\n key={groupId}\n id={groupId}\n orientation={node.direction === \"row\" ? \"horizontal\" : \"vertical\"}\n onLayoutChanged={(layout) => onGroupLayoutChanged(path, layout, firstPanelId)}\n >\n <ResizablePanel\n id={firstPanelId}\n defaultSize={node.splitPercentage ?? 50}\n minSize={minPaneSizePercentage}\n >\n {renderNode(node.first, [...path, \"first\"])}\n </ResizablePanel>\n <ResizableHandle aria-label={`Resize between pane ${firstLabel} and pane ${secondLabel}`} />\n <ResizablePanel\n id={secondPanelId}\n defaultSize={100 - (node.splitPercentage ?? 50)}\n minSize={minPaneSizePercentage}\n >\n {renderNode(node.second, [...path, \"second\"])}\n </ResizablePanel>\n </ResizablePanelGroup>\n );\n }\n\n return (\n <MosaicContext.Provider value={contextValue}>\n <div\n data-slot=\"mosaic\"\n className={cn(\"relative h-full w-full overflow-hidden\", className)}\n style={style}\n {...props}\n >\n {liveTree === null ? (emptyPlaceholder ?? null) : renderNode(liveTree, [])}\n </div>\n </MosaicContext.Provider>\n );\n}\n\nconst dropZoneOverlayClass: Record<DropZone, string> = {\n top: \"inset-x-0 top-0 h-1/2\",\n bottom: \"inset-x-0 bottom-0 h-1/2\",\n left: \"inset-y-0 left-0 w-1/2\",\n right: \"inset-y-0 right-0 w-1/2\",\n center: \"inset-0\",\n};\n\ntype MosaicWindowProps<T extends MosaicKey = string> = {\n /** This pane's leaf id. */\n id: T;\n /** This pane's path from the tree root — supplied automatically when rendered by `Mosaic`. */\n path: MosaicPath;\n className?: string;\n /** Extra toolbar actions rendered after the built-in split/remove buttons. */\n controls?: React.ReactNode;\n};\n\n/**\n * A single pane's chrome: drag handle, title, split/remove buttons, and its\n * `renderTile` content. Rendered internally by `Mosaic` for every leaf,\n * and also exported for a consumer already inside a `<Mosaic>` tree who\n * wants to add a fixed, non-tile element reusing the same toolbar chrome —\n * it calls `useMosaic()` internally, so it can't be used to build an\n * independent custom recursive renderer outside a `Mosaic`.\n *\n * The `path` you supply for such a fixed element must not collide with any\n * real leaf's path in the current tree — its split/remove/rename actions\n * operate on whatever the tree resolves at that path, so a colliding path\n * would silently act on that real pane instead of a no-op.\n */\nfunction MosaicWindow<T extends MosaicKey = string>({\n id,\n path,\n className,\n controls,\n}: MosaicWindowProps<T>) {\n const {\n renderTile,\n renderTitle,\n onSplitLeaf,\n onRemoveLeaf,\n onDragStart,\n onDragMove,\n onDragEnd,\n onDragCancel,\n draggingPath,\n dropTarget,\n dragToRearrange,\n dropZoneFraction,\n renamable,\n getPaneName,\n onRenamePane,\n } = useMosaic();\n\n const pathKey = path.join(\".\");\n const isDragging = draggingPath !== null && draggingPath.join(\".\") === pathKey;\n const isDropTarget = dropTarget !== null && dropTarget.path.join(\".\") === pathKey;\n // A plain-text identifier for this pane's toolbar aria-labels — every pane\n // otherwise shares identical button names (\"Remove pane\", etc.), which is\n // indistinguishable when tabbing through a multi-pane layout with a screen\n // reader. Falls back to the raw id rather than `renderTitle`'s output,\n // since that can be arbitrary JSX with no plain-text form.\n const accessibleName = getPaneName(id) ?? String(id);\n\n // ---- Rename editing ----\n const [isEditingName, setIsEditingName] = React.useState(false);\n const [draftName, setDraftName] = React.useState(\"\");\n // Guards against a rename being applied twice: pressing Escape unmounts the\n // input, which itself fires a native blur — without this, that blur's\n // commit would silently undo the cancel and re-apply the (unchanged) draft.\n const editResolvedRef = React.useRef(false);\n\n function startEditingName() {\n editResolvedRef.current = false;\n setDraftName(getPaneName(id) ?? String(id));\n setIsEditingName(true);\n }\n\n function commitEditingName(name: string) {\n if (editResolvedRef.current) return;\n editResolvedRef.current = true;\n setIsEditingName(false);\n onRenamePane(id, name);\n }\n\n function cancelEditingName() {\n editResolvedRef.current = true;\n setIsEditingName(false);\n }\n\n function resolveHover(clientX: number, clientY: number) {\n const hoveredEl = document\n .elementFromPoint(clientX, clientY)\n ?.closest<HTMLElement>('[data-slot=\"mosaic-window\"]');\n const hoveredPathKey = hoveredEl?.dataset.mosaicPath;\n if (!hoveredEl || hoveredPathKey === undefined || hoveredPathKey === pathKey) return null;\n const targetPath = (hoveredPathKey === \"\" ? [] : hoveredPathKey.split(\".\")) as MosaicPath;\n const rect = hoveredEl.getBoundingClientRect();\n const zone = classifyDropZone(rect, clientX, clientY, dropZoneFraction);\n return { targetPath, zone };\n }\n\n function handleGripPointerDown(event: React.PointerEvent<HTMLButtonElement>) {\n if (event.button !== 0 && event.pointerType === \"mouse\") return;\n event.preventDefault();\n onDragStart(path);\n // A body-level cursor override, since without pointer capture the cursor\n // would otherwise flicker to whatever's under the pointer during the drag.\n document.body.style.cursor = \"grabbing\";\n\n function removeListeners() {\n window.removeEventListener(\"pointermove\", onMove);\n window.removeEventListener(\"pointerup\", onUp);\n window.removeEventListener(\"pointercancel\", onCancel);\n }\n const onMove = (moveEvent: PointerEvent) => {\n const hover = resolveHover(moveEvent.clientX, moveEvent.clientY);\n onDragMove(hover?.targetPath ?? null, hover?.zone ?? null);\n };\n const onUp = (upEvent: PointerEvent) => {\n removeListeners();\n document.body.style.cursor = \"\";\n const hover = resolveHover(upEvent.clientX, upEvent.clientY);\n onDragEnd(id, hover?.targetPath ?? null, hover?.zone ?? null);\n };\n // A trackpad/touch gesture the browser reinterprets as scroll/pan fires\n // `pointercancel` instead of `pointerup` — clean up, no drop.\n const onCancel = () => {\n removeListeners();\n document.body.style.cursor = \"\";\n onDragCancel();\n };\n window.addEventListener(\"pointermove\", onMove);\n window.addEventListener(\"pointerup\", onUp);\n window.addEventListener(\"pointercancel\", onCancel);\n }\n\n return (\n <div\n data-slot=\"mosaic-window\"\n data-mosaic-path={pathKey}\n className={cn(\n \"relative flex h-full w-full flex-col overflow-hidden\",\n isDragging && \"opacity-50\",\n className,\n )}\n >\n <div\n data-slot=\"mosaic-window-toolbar\"\n className=\"flex shrink-0 items-center gap-1 border-primary-border border-b bg-primary-bg px-1.5 py-1\"\n >\n {dragToRearrange && (\n <button\n type=\"button\"\n data-slot=\"mosaic-window-grip\"\n aria-label={`Drag to move pane \"${accessibleName}\". Use the split and close buttons for keyboard-accessible rearranging.`}\n draggable={false}\n className=\"flex size-6 shrink-0 cursor-grab touch-none items-center justify-center rounded-6 text-muted-txt focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-focus active:cursor-grabbing\"\n onPointerDown={handleGripPointerDown}\n >\n <GripVerticalIcon className=\"size-3.5\" />\n </button>\n )}\n {isEditingName ? (\n <input\n type=\"text\"\n data-slot=\"mosaic-window-name-input\"\n aria-label={`Pane name for \"${accessibleName}\"`}\n value={draftName}\n autoFocus\n className=\"h-6 min-w-0 flex-1 rounded-4 border border-primary-border bg-primary-bg px-1 text-primary-txt text-sm outline-hidden focus-visible:ring-1 focus-visible:ring-focus\"\n onChange={(event) => setDraftName(event.target.value)}\n onFocus={(event) => event.currentTarget.select()}\n onBlur={(event) => commitEditingName(event.currentTarget.value)}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n event.preventDefault();\n commitEditingName(event.currentTarget.value);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n cancelEditingName();\n }\n }}\n />\n ) : (\n <span\n className=\"min-w-0 flex-1 truncate text-primary-txt text-sm\"\n onDoubleClick={renamable ? startEditingName : undefined}\n >\n {getPaneName(id) ?? (renderTitle ? renderTitle(id, path) : String(id))}\n </span>\n )}\n {renamable && !isEditingName && (\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Rename pane \"${accessibleName}\"`}\n onClick={startEditingName}\n >\n <PencilIcon />\n </Button>\n )}\n {controls}\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Split pane \"${accessibleName}\", side by side`}\n onClick={() => onSplitLeaf(path, \"row\")}\n >\n <PanelLeftIcon />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Split pane \"${accessibleName}\", stacked`}\n onClick={() => onSplitLeaf(path, \"column\")}\n >\n <PanelTopIcon />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`Remove pane \"${accessibleName}\"`}\n onClick={() => onRemoveLeaf(path)}\n >\n <XIcon />\n </Button>\n </div>\n <div data-slot=\"mosaic-window-content\" className=\"min-h-0 flex-1 overflow-auto\">\n {renderTile(id, path)}\n </div>\n {isDropTarget && dropTarget && (\n <div\n data-slot=\"mosaic-drop-overlay\"\n className={cn(\n \"pointer-events-none absolute z-20 bg-focus/20 ring-2 ring-focus ring-inset\",\n dropZoneOverlayClass[dropTarget.zone],\n )}\n />\n )}\n </div>\n );\n}\n\n// `useMosaic` is intentionally not exported: its context value is typed\n// against the widened `MosaicKey` union (React context can't itself be\n// generic), so a consumer calling it directly on a `Mosaic<T>` instance could\n// pass a mismatched id with no compile-time error. `MosaicWindow` is the\n// supported extension point and narrows back to `T` at its own boundary.\nexport { Mosaic, MosaicWindow, type MosaicProps, type MosaicWindowProps };\nexport type {\n DropZone,\n MosaicDirection,\n MosaicKey,\n MosaicNode,\n MosaicParent,\n MosaicPath,\n} from \"./Mosaic.utils\";\n"],"mappings":"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"}
|