panelgrid 0.1.1 → 0.1.3
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/dist/PanelGridProvider.cjs +54 -0
- package/dist/PanelGridProvider.cjs.map +1 -0
- package/dist/PanelGridProvider.d.cts +45 -0
- package/dist/PanelGridProvider.d.mts +45 -0
- package/dist/PanelGridProvider.mjs +52 -0
- package/dist/PanelGridProvider.mjs.map +1 -0
- package/dist/PanelGridRenderer.cjs +76 -0
- package/dist/PanelGridRenderer.cjs.map +1 -0
- package/dist/PanelGridRenderer.d.cts +15 -0
- package/dist/PanelGridRenderer.d.mts +15 -0
- package/dist/PanelGridRenderer.mjs +76 -0
- package/dist/PanelGridRenderer.mjs.map +1 -0
- package/dist/helpers/animation.cjs +24 -0
- package/dist/helpers/animation.cjs.map +1 -0
- package/dist/helpers/animation.mjs +23 -0
- package/dist/helpers/animation.mjs.map +1 -0
- package/dist/helpers/gridCalculations.cjs +76 -0
- package/dist/helpers/gridCalculations.cjs.map +1 -0
- package/dist/helpers/gridCalculations.mjs +71 -0
- package/dist/helpers/gridCalculations.mjs.map +1 -0
- package/dist/helpers/panelDetection.cjs +21 -0
- package/dist/helpers/panelDetection.cjs.map +1 -0
- package/dist/helpers/panelDetection.mjs +20 -0
- package/dist/helpers/panelDetection.mjs.map +1 -0
- package/dist/helpers/rearrangement.cjs +161 -0
- package/dist/helpers/rearrangement.cjs.map +1 -0
- package/dist/helpers/rearrangement.d.cts +14 -0
- package/dist/helpers/rearrangement.d.mts +14 -0
- package/dist/helpers/rearrangement.mjs +159 -0
- package/dist/helpers/rearrangement.mjs.map +1 -0
- package/dist/index.cjs +11 -665
- package/dist/index.d.cts +6 -128
- package/dist/index.d.mts +6 -128
- package/dist/index.mjs +5 -660
- package/dist/types.d.cts +26 -0
- package/dist/types.d.mts +26 -0
- package/dist/usePanel.cjs +11 -0
- package/dist/usePanel.cjs.map +1 -0
- package/dist/usePanel.d.cts +12 -0
- package/dist/usePanel.d.mts +12 -0
- package/dist/usePanel.mjs +11 -0
- package/dist/usePanel.mjs.map +1 -0
- package/dist/usePanelGrid.cjs +343 -0
- package/dist/usePanelGrid.cjs.map +1 -0
- package/dist/usePanelGrid.d.cts +53 -0
- package/dist/usePanelGrid.d.mts +53 -0
- package/dist/usePanelGrid.mjs +343 -0
- package/dist/usePanelGrid.mjs.map +1 -0
- package/package.json +17 -5
- package/dist/index.cjs.map +0 -1
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const require_usePanelGrid = require('./usePanelGrid.cjs');
|
|
2
|
+
let react = require("react");
|
|
3
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
4
|
+
|
|
5
|
+
//#region src/PanelGridProvider.tsx
|
|
6
|
+
const PanelGridStateContext = (0, react.createContext)(void 0);
|
|
7
|
+
const PanelGridControlsContext = (0, react.createContext)(void 0);
|
|
8
|
+
function PanelGridProvider({ panels: initialPanels, columnCount, gap, children, rearrangement }) {
|
|
9
|
+
const [baseSize, setBaseSize] = (0, react.useState)(null);
|
|
10
|
+
const { panels, panelMap, addPanel, removePanel, lockPanelSize, unlockPanelSize, exportState, ghostPanelRef } = require_usePanelGrid.usePanelGrid({
|
|
11
|
+
panels: initialPanels,
|
|
12
|
+
columnCount,
|
|
13
|
+
baseSize: baseSize || 256,
|
|
14
|
+
gap,
|
|
15
|
+
rearrangement
|
|
16
|
+
});
|
|
17
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PanelGridStateContext.Provider, {
|
|
18
|
+
value: {
|
|
19
|
+
panels,
|
|
20
|
+
panelMap,
|
|
21
|
+
columnCount,
|
|
22
|
+
gap,
|
|
23
|
+
baseSize,
|
|
24
|
+
ghostPanelRef
|
|
25
|
+
},
|
|
26
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PanelGridControlsContext.Provider, {
|
|
27
|
+
value: {
|
|
28
|
+
setBaseSize,
|
|
29
|
+
addPanel,
|
|
30
|
+
removePanel,
|
|
31
|
+
lockPanelSize,
|
|
32
|
+
unlockPanelSize,
|
|
33
|
+
exportState
|
|
34
|
+
},
|
|
35
|
+
children
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function usePanelGridState() {
|
|
40
|
+
const context = (0, react.useContext)(PanelGridStateContext);
|
|
41
|
+
if (!context) throw new Error("usePanelGridState must be used within a PanelGridProvider");
|
|
42
|
+
return context;
|
|
43
|
+
}
|
|
44
|
+
function usePanelGridControls() {
|
|
45
|
+
const context = (0, react.useContext)(PanelGridControlsContext);
|
|
46
|
+
if (!context) throw new Error("usePanelGridControls must be used within a PanelGridProvider");
|
|
47
|
+
return context;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
exports.PanelGridProvider = PanelGridProvider;
|
|
52
|
+
exports.usePanelGridControls = usePanelGridControls;
|
|
53
|
+
exports.usePanelGridState = usePanelGridState;
|
|
54
|
+
//# sourceMappingURL=PanelGridProvider.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PanelGridProvider.cjs","names":["usePanelGrid"],"sources":["../src/PanelGridProvider.tsx"],"sourcesContent":["import { createContext, useContext, useState } from \"react\";\nimport type { PanelCoordinate, PanelId, RearrangementFunction } from \"./types\";\nimport { usePanelGrid } from \"./usePanelGrid\";\n\ntype PanelGridState = ReturnType<typeof usePanelGrid>;\n\ninterface PanelGridContextType {\n panels: PanelGridState[\"panels\"];\n panelMap: PanelGridState[\"panelMap\"];\n baseSize: number | null;\n columnCount: number;\n gap: number;\n ghostPanelRef: React.RefObject<HTMLDivElement | null>;\n}\n\ninterface PanelGridControlsContextType {\n setBaseSize: (baseSize: number) => void;\n addPanel: (panel: Partial<PanelCoordinate>) => void;\n removePanel: (id: PanelId) => void;\n lockPanelSize: (id: PanelId) => void;\n unlockPanelSize: (id: PanelId) => void;\n exportState: () => PanelCoordinate[];\n}\n\nconst PanelGridStateContext = createContext<PanelGridContextType | undefined>(undefined);\nconst PanelGridControlsContext = createContext<PanelGridControlsContextType | undefined>(undefined);\n\ninterface PanelGridProviderProps {\n panels: PanelCoordinate[];\n columnCount: number;\n gap: number;\n children: React.ReactNode;\n /**\n * Optional custom rearrangement function to override default collision resolution logic\n * If provided, this function will be called instead of the default rearrangePanels\n */\n rearrangement?: RearrangementFunction;\n}\n\nexport function PanelGridProvider({\n panels: initialPanels,\n columnCount,\n gap,\n children,\n rearrangement,\n}: PanelGridProviderProps) {\n const [baseSize, setBaseSize] = useState<number | null>(null);\n\n const { panels, panelMap, addPanel, removePanel, lockPanelSize, unlockPanelSize, exportState, ghostPanelRef } =\n usePanelGrid({\n panels: initialPanels,\n columnCount,\n baseSize: baseSize || 256,\n gap,\n rearrangement,\n });\n\n return (\n <PanelGridStateContext.Provider value={{ panels, panelMap, columnCount, gap, baseSize, ghostPanelRef }}>\n <PanelGridControlsContext.Provider\n value={{ setBaseSize, addPanel, removePanel, lockPanelSize, unlockPanelSize, exportState }}\n >\n {children}\n </PanelGridControlsContext.Provider>\n </PanelGridStateContext.Provider>\n );\n}\n\nexport function usePanelGridState() {\n const context = useContext(PanelGridStateContext);\n if (!context) {\n throw new Error(\"usePanelGridState must be used within a PanelGridProvider\");\n }\n return context;\n}\n\nexport function usePanelGridControls() {\n const context = useContext(PanelGridControlsContext);\n if (!context) {\n throw new Error(\"usePanelGridControls must be used within a PanelGridProvider\");\n }\n return context;\n}\n"],"mappings":";;;;;AAwBA,MAAM,iDAAwE,OAAU;AACxF,MAAM,oDAAmF,OAAU;AAcnG,SAAgB,kBAAkB,EAChC,QAAQ,eACR,aACA,KACA,UACA,iBACyB;CACzB,MAAM,CAAC,UAAU,mCAAuC,KAAK;CAE7D,MAAM,EAAE,QAAQ,UAAU,UAAU,aAAa,eAAe,iBAAiB,aAAa,kBAC5FA,kCAAa;EACX,QAAQ;EACR;EACA,UAAU,YAAY;EACtB;EACA;EACD,CAAC;AAEJ,QACE,2CAAC,sBAAsB;EAAS,OAAO;GAAE;GAAQ;GAAU;GAAa;GAAK;GAAU;GAAe;YACpG,2CAAC,yBAAyB;GACxB,OAAO;IAAE;IAAa;IAAU;IAAa;IAAe;IAAiB;IAAa;GAEzF;IACiC;GACL;;AAIrC,SAAgB,oBAAoB;CAClC,MAAM,gCAAqB,sBAAsB;AACjD,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,4DAA4D;AAE9E,QAAO;;AAGT,SAAgB,uBAAuB;CACrC,MAAM,gCAAqB,yBAAyB;AACpD,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,+DAA+D;AAEjF,QAAO"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PanelCoordinate, PanelId, RearrangementFunction } from "./types.cjs";
|
|
2
|
+
import { usePanelGrid } from "./usePanelGrid.cjs";
|
|
3
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/PanelGridProvider.d.ts
|
|
6
|
+
type PanelGridState = ReturnType<typeof usePanelGrid>;
|
|
7
|
+
interface PanelGridContextType {
|
|
8
|
+
panels: PanelGridState["panels"];
|
|
9
|
+
panelMap: PanelGridState["panelMap"];
|
|
10
|
+
baseSize: number | null;
|
|
11
|
+
columnCount: number;
|
|
12
|
+
gap: number;
|
|
13
|
+
ghostPanelRef: React.RefObject<HTMLDivElement | null>;
|
|
14
|
+
}
|
|
15
|
+
interface PanelGridControlsContextType {
|
|
16
|
+
setBaseSize: (baseSize: number) => void;
|
|
17
|
+
addPanel: (panel: Partial<PanelCoordinate>) => void;
|
|
18
|
+
removePanel: (id: PanelId) => void;
|
|
19
|
+
lockPanelSize: (id: PanelId) => void;
|
|
20
|
+
unlockPanelSize: (id: PanelId) => void;
|
|
21
|
+
exportState: () => PanelCoordinate[];
|
|
22
|
+
}
|
|
23
|
+
interface PanelGridProviderProps {
|
|
24
|
+
panels: PanelCoordinate[];
|
|
25
|
+
columnCount: number;
|
|
26
|
+
gap: number;
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* Optional custom rearrangement function to override default collision resolution logic
|
|
30
|
+
* If provided, this function will be called instead of the default rearrangePanels
|
|
31
|
+
*/
|
|
32
|
+
rearrangement?: RearrangementFunction;
|
|
33
|
+
}
|
|
34
|
+
declare function PanelGridProvider({
|
|
35
|
+
panels: initialPanels,
|
|
36
|
+
columnCount,
|
|
37
|
+
gap,
|
|
38
|
+
children,
|
|
39
|
+
rearrangement
|
|
40
|
+
}: PanelGridProviderProps): react_jsx_runtime0.JSX.Element;
|
|
41
|
+
declare function usePanelGridState(): PanelGridContextType;
|
|
42
|
+
declare function usePanelGridControls(): PanelGridControlsContextType;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { PanelGridProvider, usePanelGridControls, usePanelGridState };
|
|
45
|
+
//# sourceMappingURL=PanelGridProvider.d.cts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PanelCoordinate, PanelId, RearrangementFunction } from "./types.mjs";
|
|
2
|
+
import { usePanelGrid } from "./usePanelGrid.mjs";
|
|
3
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/PanelGridProvider.d.ts
|
|
6
|
+
type PanelGridState = ReturnType<typeof usePanelGrid>;
|
|
7
|
+
interface PanelGridContextType {
|
|
8
|
+
panels: PanelGridState["panels"];
|
|
9
|
+
panelMap: PanelGridState["panelMap"];
|
|
10
|
+
baseSize: number | null;
|
|
11
|
+
columnCount: number;
|
|
12
|
+
gap: number;
|
|
13
|
+
ghostPanelRef: React.RefObject<HTMLDivElement | null>;
|
|
14
|
+
}
|
|
15
|
+
interface PanelGridControlsContextType {
|
|
16
|
+
setBaseSize: (baseSize: number) => void;
|
|
17
|
+
addPanel: (panel: Partial<PanelCoordinate>) => void;
|
|
18
|
+
removePanel: (id: PanelId) => void;
|
|
19
|
+
lockPanelSize: (id: PanelId) => void;
|
|
20
|
+
unlockPanelSize: (id: PanelId) => void;
|
|
21
|
+
exportState: () => PanelCoordinate[];
|
|
22
|
+
}
|
|
23
|
+
interface PanelGridProviderProps {
|
|
24
|
+
panels: PanelCoordinate[];
|
|
25
|
+
columnCount: number;
|
|
26
|
+
gap: number;
|
|
27
|
+
children: React.ReactNode;
|
|
28
|
+
/**
|
|
29
|
+
* Optional custom rearrangement function to override default collision resolution logic
|
|
30
|
+
* If provided, this function will be called instead of the default rearrangePanels
|
|
31
|
+
*/
|
|
32
|
+
rearrangement?: RearrangementFunction;
|
|
33
|
+
}
|
|
34
|
+
declare function PanelGridProvider({
|
|
35
|
+
panels: initialPanels,
|
|
36
|
+
columnCount,
|
|
37
|
+
gap,
|
|
38
|
+
children,
|
|
39
|
+
rearrangement
|
|
40
|
+
}: PanelGridProviderProps): react_jsx_runtime0.JSX.Element;
|
|
41
|
+
declare function usePanelGridState(): PanelGridContextType;
|
|
42
|
+
declare function usePanelGridControls(): PanelGridControlsContextType;
|
|
43
|
+
//#endregion
|
|
44
|
+
export { PanelGridProvider, usePanelGridControls, usePanelGridState };
|
|
45
|
+
//# sourceMappingURL=PanelGridProvider.d.mts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { usePanelGrid } from "./usePanelGrid.mjs";
|
|
2
|
+
import { createContext, useContext, useState } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/PanelGridProvider.tsx
|
|
6
|
+
const PanelGridStateContext = createContext(void 0);
|
|
7
|
+
const PanelGridControlsContext = createContext(void 0);
|
|
8
|
+
function PanelGridProvider({ panels: initialPanels, columnCount, gap, children, rearrangement }) {
|
|
9
|
+
const [baseSize, setBaseSize] = useState(null);
|
|
10
|
+
const { panels, panelMap, addPanel, removePanel, lockPanelSize, unlockPanelSize, exportState, ghostPanelRef } = usePanelGrid({
|
|
11
|
+
panels: initialPanels,
|
|
12
|
+
columnCount,
|
|
13
|
+
baseSize: baseSize || 256,
|
|
14
|
+
gap,
|
|
15
|
+
rearrangement
|
|
16
|
+
});
|
|
17
|
+
return /* @__PURE__ */ jsx(PanelGridStateContext.Provider, {
|
|
18
|
+
value: {
|
|
19
|
+
panels,
|
|
20
|
+
panelMap,
|
|
21
|
+
columnCount,
|
|
22
|
+
gap,
|
|
23
|
+
baseSize,
|
|
24
|
+
ghostPanelRef
|
|
25
|
+
},
|
|
26
|
+
children: /* @__PURE__ */ jsx(PanelGridControlsContext.Provider, {
|
|
27
|
+
value: {
|
|
28
|
+
setBaseSize,
|
|
29
|
+
addPanel,
|
|
30
|
+
removePanel,
|
|
31
|
+
lockPanelSize,
|
|
32
|
+
unlockPanelSize,
|
|
33
|
+
exportState
|
|
34
|
+
},
|
|
35
|
+
children
|
|
36
|
+
})
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function usePanelGridState() {
|
|
40
|
+
const context = useContext(PanelGridStateContext);
|
|
41
|
+
if (!context) throw new Error("usePanelGridState must be used within a PanelGridProvider");
|
|
42
|
+
return context;
|
|
43
|
+
}
|
|
44
|
+
function usePanelGridControls() {
|
|
45
|
+
const context = useContext(PanelGridControlsContext);
|
|
46
|
+
if (!context) throw new Error("usePanelGridControls must be used within a PanelGridProvider");
|
|
47
|
+
return context;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
export { PanelGridProvider, usePanelGridControls, usePanelGridState };
|
|
52
|
+
//# sourceMappingURL=PanelGridProvider.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PanelGridProvider.mjs","names":[],"sources":["../src/PanelGridProvider.tsx"],"sourcesContent":["import { createContext, useContext, useState } from \"react\";\nimport type { PanelCoordinate, PanelId, RearrangementFunction } from \"./types\";\nimport { usePanelGrid } from \"./usePanelGrid\";\n\ntype PanelGridState = ReturnType<typeof usePanelGrid>;\n\ninterface PanelGridContextType {\n panels: PanelGridState[\"panels\"];\n panelMap: PanelGridState[\"panelMap\"];\n baseSize: number | null;\n columnCount: number;\n gap: number;\n ghostPanelRef: React.RefObject<HTMLDivElement | null>;\n}\n\ninterface PanelGridControlsContextType {\n setBaseSize: (baseSize: number) => void;\n addPanel: (panel: Partial<PanelCoordinate>) => void;\n removePanel: (id: PanelId) => void;\n lockPanelSize: (id: PanelId) => void;\n unlockPanelSize: (id: PanelId) => void;\n exportState: () => PanelCoordinate[];\n}\n\nconst PanelGridStateContext = createContext<PanelGridContextType | undefined>(undefined);\nconst PanelGridControlsContext = createContext<PanelGridControlsContextType | undefined>(undefined);\n\ninterface PanelGridProviderProps {\n panels: PanelCoordinate[];\n columnCount: number;\n gap: number;\n children: React.ReactNode;\n /**\n * Optional custom rearrangement function to override default collision resolution logic\n * If provided, this function will be called instead of the default rearrangePanels\n */\n rearrangement?: RearrangementFunction;\n}\n\nexport function PanelGridProvider({\n panels: initialPanels,\n columnCount,\n gap,\n children,\n rearrangement,\n}: PanelGridProviderProps) {\n const [baseSize, setBaseSize] = useState<number | null>(null);\n\n const { panels, panelMap, addPanel, removePanel, lockPanelSize, unlockPanelSize, exportState, ghostPanelRef } =\n usePanelGrid({\n panels: initialPanels,\n columnCount,\n baseSize: baseSize || 256,\n gap,\n rearrangement,\n });\n\n return (\n <PanelGridStateContext.Provider value={{ panels, panelMap, columnCount, gap, baseSize, ghostPanelRef }}>\n <PanelGridControlsContext.Provider\n value={{ setBaseSize, addPanel, removePanel, lockPanelSize, unlockPanelSize, exportState }}\n >\n {children}\n </PanelGridControlsContext.Provider>\n </PanelGridStateContext.Provider>\n );\n}\n\nexport function usePanelGridState() {\n const context = useContext(PanelGridStateContext);\n if (!context) {\n throw new Error(\"usePanelGridState must be used within a PanelGridProvider\");\n }\n return context;\n}\n\nexport function usePanelGridControls() {\n const context = useContext(PanelGridControlsContext);\n if (!context) {\n throw new Error(\"usePanelGridControls must be used within a PanelGridProvider\");\n }\n return context;\n}\n"],"mappings":";;;;;AAwBA,MAAM,wBAAwB,cAAgD,OAAU;AACxF,MAAM,2BAA2B,cAAwD,OAAU;AAcnG,SAAgB,kBAAkB,EAChC,QAAQ,eACR,aACA,KACA,UACA,iBACyB;CACzB,MAAM,CAAC,UAAU,eAAe,SAAwB,KAAK;CAE7D,MAAM,EAAE,QAAQ,UAAU,UAAU,aAAa,eAAe,iBAAiB,aAAa,kBAC5F,aAAa;EACX,QAAQ;EACR;EACA,UAAU,YAAY;EACtB;EACA;EACD,CAAC;AAEJ,QACE,oBAAC,sBAAsB;EAAS,OAAO;GAAE;GAAQ;GAAU;GAAa;GAAK;GAAU;GAAe;YACpG,oBAAC,yBAAyB;GACxB,OAAO;IAAE;IAAa;IAAU;IAAa;IAAe;IAAiB;IAAa;GAEzF;IACiC;GACL;;AAIrC,SAAgB,oBAAoB;CAClC,MAAM,UAAU,WAAW,sBAAsB;AACjD,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,4DAA4D;AAE9E,QAAO;;AAGT,SAAgB,uBAAuB;CACrC,MAAM,UAAU,WAAW,yBAAyB;AACpD,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,+DAA+D;AAEjF,QAAO"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const require_gridCalculations = require('./helpers/gridCalculations.cjs');
|
|
2
|
+
const require_PanelGridProvider = require('./PanelGridProvider.cjs');
|
|
3
|
+
let react = require("react");
|
|
4
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
+
|
|
6
|
+
//#region src/PanelGridRenderer.tsx
|
|
7
|
+
function PanelGridRenderer({ itemRenderer: ItemRenderer }) {
|
|
8
|
+
const { panels, columnCount, gap, baseSize, ghostPanelRef } = require_PanelGridProvider.usePanelGridState();
|
|
9
|
+
const { setBaseSize } = require_PanelGridProvider.usePanelGridControls();
|
|
10
|
+
const containerRef = (0, react.useRef)(null);
|
|
11
|
+
const rowCount = require_gridCalculations.getGridRowCount(panels.map(({ panelProps: p }) => ({
|
|
12
|
+
id: p.key,
|
|
13
|
+
x: p.positionData.x,
|
|
14
|
+
y: p.positionData.y,
|
|
15
|
+
w: p.positionData.w,
|
|
16
|
+
h: p.positionData.h
|
|
17
|
+
})));
|
|
18
|
+
const count = Math.max(columnCount * (rowCount + 1), columnCount * columnCount);
|
|
19
|
+
(0, react.useLayoutEffect)(() => {
|
|
20
|
+
if (!containerRef.current) return;
|
|
21
|
+
const observer = new ResizeObserver((entries) => {
|
|
22
|
+
const [entry] = entries;
|
|
23
|
+
const rect = entry.contentRect;
|
|
24
|
+
setBaseSize(Math.floor((rect.width - gap * (columnCount - 1)) / columnCount));
|
|
25
|
+
});
|
|
26
|
+
observer.observe(containerRef.current);
|
|
27
|
+
return () => observer.disconnect();
|
|
28
|
+
}, [
|
|
29
|
+
columnCount,
|
|
30
|
+
gap,
|
|
31
|
+
setBaseSize
|
|
32
|
+
]);
|
|
33
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
34
|
+
className: "panelgrid-renderer",
|
|
35
|
+
style: {
|
|
36
|
+
"--column-count": `${columnCount}`,
|
|
37
|
+
"--gap": `${gap}px`,
|
|
38
|
+
opacity: baseSize ? 1 : 0
|
|
39
|
+
},
|
|
40
|
+
ref: containerRef,
|
|
41
|
+
children: [
|
|
42
|
+
Array.from({ length: count }).map((_, i) => {
|
|
43
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "panelgrid-panel-placeholder" }, i);
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
46
|
+
className: "panelgrid-panel-ghost",
|
|
47
|
+
ref: ghostPanelRef
|
|
48
|
+
}),
|
|
49
|
+
panels.map((panel) => {
|
|
50
|
+
const { panelProps, resizeHandleProps } = panel;
|
|
51
|
+
const { key, lockSize, style, positionData, ref, onMouseDown } = panelProps;
|
|
52
|
+
const className = lockSize ? "panelgrid-panel panelgrid-panel--size-locked" : "panelgrid-panel";
|
|
53
|
+
const { x, y, w, h } = positionData;
|
|
54
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
55
|
+
className,
|
|
56
|
+
style,
|
|
57
|
+
ref,
|
|
58
|
+
onMouseDown,
|
|
59
|
+
"data-panel-id": key,
|
|
60
|
+
"data-pg-x": x,
|
|
61
|
+
"data-pg-y": y,
|
|
62
|
+
"data-pg-w": w,
|
|
63
|
+
"data-pg-h": h,
|
|
64
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ItemRenderer, { id: key }), resizeHandleProps && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
65
|
+
className: "panelgrid-resize-handle",
|
|
66
|
+
...resizeHandleProps
|
|
67
|
+
})]
|
|
68
|
+
}, key);
|
|
69
|
+
})
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
exports.PanelGridRenderer = PanelGridRenderer;
|
|
76
|
+
//# sourceMappingURL=PanelGridRenderer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PanelGridRenderer.cjs","names":["usePanelGridState","usePanelGridControls","getGridRowCount"],"sources":["../src/PanelGridRenderer.tsx"],"sourcesContent":["import { useLayoutEffect, useRef } from \"react\";\nimport { getGridRowCount } from \"./helpers/gridCalculations\";\nimport { usePanelGridControls, usePanelGridState } from \"./PanelGridProvider\";\nimport type { PanelId } from \"./types\";\n\ninterface PanelGridRendererProps {\n itemRenderer: React.ComponentType<{ id: PanelId }>;\n}\n\nexport function PanelGridRenderer({ itemRenderer: ItemRenderer }: PanelGridRendererProps) {\n const { panels, columnCount, gap, baseSize, ghostPanelRef } = usePanelGridState();\n const { setBaseSize } = usePanelGridControls();\n const containerRef = useRef<HTMLDivElement | null>(null);\n const rowCount = getGridRowCount(\n panels.map(({ panelProps: p }) => ({\n id: p.key,\n x: p.positionData.x,\n y: p.positionData.y,\n w: p.positionData.w,\n h: p.positionData.h,\n }))\n );\n const count = Math.max(columnCount * (rowCount + 1), columnCount * columnCount);\n\n useLayoutEffect(() => {\n if (!containerRef.current) return;\n const observer = new ResizeObserver((entries) => {\n const [entry] = entries;\n const rect = entry.contentRect;\n const baseSize = Math.floor((rect.width - gap * (columnCount - 1)) / columnCount);\n setBaseSize(baseSize);\n });\n observer.observe(containerRef.current);\n return () => observer.disconnect();\n }, [columnCount, gap, setBaseSize]);\n\n return (\n <div\n className=\"panelgrid-renderer\"\n style={{\n \"--column-count\": `${columnCount}`,\n \"--gap\": `${gap}px`,\n opacity: baseSize ? 1 : 0,\n }}\n ref={containerRef}\n >\n {Array.from({ length: count }).map((_, i) => {\n return <div key={i} className=\"panelgrid-panel-placeholder\" />;\n })}\n\n <div className=\"panelgrid-panel-ghost\" ref={ghostPanelRef}></div>\n\n {panels.map((panel) => {\n const { panelProps, resizeHandleProps } = panel;\n const { key, lockSize, style, positionData, ref, onMouseDown } = panelProps;\n\n const className = lockSize ? \"panelgrid-panel panelgrid-panel--size-locked\" : \"panelgrid-panel\";\n const { x, y, w, h } = positionData;\n\n return (\n <div\n key={key}\n className={className}\n style={style}\n ref={ref}\n onMouseDown={onMouseDown}\n data-panel-id={key}\n data-pg-x={x}\n data-pg-y={y}\n data-pg-w={w}\n data-pg-h={h}\n >\n <ItemRenderer id={key} />\n {resizeHandleProps && <span className=\"panelgrid-resize-handle\" {...resizeHandleProps}></span>}\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;AASA,SAAgB,kBAAkB,EAAE,cAAc,gBAAwC;CACxF,MAAM,EAAE,QAAQ,aAAa,KAAK,UAAU,kBAAkBA,6CAAmB;CACjF,MAAM,EAAE,gBAAgBC,gDAAsB;CAC9C,MAAM,iCAA6C,KAAK;CACxD,MAAM,WAAWC,yCACf,OAAO,KAAK,EAAE,YAAY,SAAS;EACjC,IAAI,EAAE;EACN,GAAG,EAAE,aAAa;EAClB,GAAG,EAAE,aAAa;EAClB,GAAG,EAAE,aAAa;EAClB,GAAG,EAAE,aAAa;EACnB,EAAE,CACJ;CACD,MAAM,QAAQ,KAAK,IAAI,eAAe,WAAW,IAAI,cAAc,YAAY;AAE/E,kCAAsB;AACpB,MAAI,CAAC,aAAa,QAAS;EAC3B,MAAM,WAAW,IAAI,gBAAgB,YAAY;GAC/C,MAAM,CAAC,SAAS;GAChB,MAAM,OAAO,MAAM;AAEnB,eADiB,KAAK,OAAO,KAAK,QAAQ,OAAO,cAAc,MAAM,YAAY,CAC5D;IACrB;AACF,WAAS,QAAQ,aAAa,QAAQ;AACtC,eAAa,SAAS,YAAY;IACjC;EAAC;EAAa;EAAK;EAAY,CAAC;AAEnC,QACE,4CAAC;EACC,WAAU;EACV,OAAO;GACL,kBAAkB,GAAG;GACrB,SAAS,GAAG,IAAI;GAChB,SAAS,WAAW,IAAI;GACzB;EACD,KAAK;;GAEJ,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC,CAAC,KAAK,GAAG,MAAM;AAC3C,WAAO,2CAAC,SAAY,WAAU,iCAAb,EAA6C;KAC9D;GAEF,2CAAC;IAAI,WAAU;IAAwB,KAAK;KAAqB;GAEhE,OAAO,KAAK,UAAU;IACrB,MAAM,EAAE,YAAY,sBAAsB;IAC1C,MAAM,EAAE,KAAK,UAAU,OAAO,cAAc,KAAK,gBAAgB;IAEjE,MAAM,YAAY,WAAW,iDAAiD;IAC9E,MAAM,EAAE,GAAG,GAAG,GAAG,MAAM;AAEvB,WACE,4CAAC;KAEY;KACJ;KACF;KACQ;KACb,iBAAe;KACf,aAAW;KACX,aAAW;KACX,aAAW;KACX,aAAW;gBAEX,2CAAC,gBAAa,IAAI,MAAO,EACxB,qBAAqB,2CAAC;MAAK,WAAU;MAA0B,GAAI;OAA0B;OAZzF,IAaD;KAER;;GACE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PanelId } from "./types.cjs";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/PanelGridRenderer.d.ts
|
|
5
|
+
interface PanelGridRendererProps {
|
|
6
|
+
itemRenderer: React.ComponentType<{
|
|
7
|
+
id: PanelId;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
declare function PanelGridRenderer({
|
|
11
|
+
itemRenderer: ItemRenderer
|
|
12
|
+
}: PanelGridRendererProps): react_jsx_runtime0.JSX.Element;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { PanelGridRenderer };
|
|
15
|
+
//# sourceMappingURL=PanelGridRenderer.d.cts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PanelId } from "./types.mjs";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
|
|
4
|
+
//#region src/PanelGridRenderer.d.ts
|
|
5
|
+
interface PanelGridRendererProps {
|
|
6
|
+
itemRenderer: React.ComponentType<{
|
|
7
|
+
id: PanelId;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
declare function PanelGridRenderer({
|
|
11
|
+
itemRenderer: ItemRenderer
|
|
12
|
+
}: PanelGridRendererProps): react_jsx_runtime0.JSX.Element;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { PanelGridRenderer };
|
|
15
|
+
//# sourceMappingURL=PanelGridRenderer.d.mts.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { getGridRowCount } from "./helpers/gridCalculations.mjs";
|
|
2
|
+
import { usePanelGridControls, usePanelGridState } from "./PanelGridProvider.mjs";
|
|
3
|
+
import { useLayoutEffect, useRef } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/PanelGridRenderer.tsx
|
|
7
|
+
function PanelGridRenderer({ itemRenderer: ItemRenderer }) {
|
|
8
|
+
const { panels, columnCount, gap, baseSize, ghostPanelRef } = usePanelGridState();
|
|
9
|
+
const { setBaseSize } = usePanelGridControls();
|
|
10
|
+
const containerRef = useRef(null);
|
|
11
|
+
const rowCount = getGridRowCount(panels.map(({ panelProps: p }) => ({
|
|
12
|
+
id: p.key,
|
|
13
|
+
x: p.positionData.x,
|
|
14
|
+
y: p.positionData.y,
|
|
15
|
+
w: p.positionData.w,
|
|
16
|
+
h: p.positionData.h
|
|
17
|
+
})));
|
|
18
|
+
const count = Math.max(columnCount * (rowCount + 1), columnCount * columnCount);
|
|
19
|
+
useLayoutEffect(() => {
|
|
20
|
+
if (!containerRef.current) return;
|
|
21
|
+
const observer = new ResizeObserver((entries) => {
|
|
22
|
+
const [entry] = entries;
|
|
23
|
+
const rect = entry.contentRect;
|
|
24
|
+
setBaseSize(Math.floor((rect.width - gap * (columnCount - 1)) / columnCount));
|
|
25
|
+
});
|
|
26
|
+
observer.observe(containerRef.current);
|
|
27
|
+
return () => observer.disconnect();
|
|
28
|
+
}, [
|
|
29
|
+
columnCount,
|
|
30
|
+
gap,
|
|
31
|
+
setBaseSize
|
|
32
|
+
]);
|
|
33
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
34
|
+
className: "panelgrid-renderer",
|
|
35
|
+
style: {
|
|
36
|
+
"--column-count": `${columnCount}`,
|
|
37
|
+
"--gap": `${gap}px`,
|
|
38
|
+
opacity: baseSize ? 1 : 0
|
|
39
|
+
},
|
|
40
|
+
ref: containerRef,
|
|
41
|
+
children: [
|
|
42
|
+
Array.from({ length: count }).map((_, i) => {
|
|
43
|
+
return /* @__PURE__ */ jsx("div", { className: "panelgrid-panel-placeholder" }, i);
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ jsx("div", {
|
|
46
|
+
className: "panelgrid-panel-ghost",
|
|
47
|
+
ref: ghostPanelRef
|
|
48
|
+
}),
|
|
49
|
+
panels.map((panel) => {
|
|
50
|
+
const { panelProps, resizeHandleProps } = panel;
|
|
51
|
+
const { key, lockSize, style, positionData, ref, onMouseDown } = panelProps;
|
|
52
|
+
const className = lockSize ? "panelgrid-panel panelgrid-panel--size-locked" : "panelgrid-panel";
|
|
53
|
+
const { x, y, w, h } = positionData;
|
|
54
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
55
|
+
className,
|
|
56
|
+
style,
|
|
57
|
+
ref,
|
|
58
|
+
onMouseDown,
|
|
59
|
+
"data-panel-id": key,
|
|
60
|
+
"data-pg-x": x,
|
|
61
|
+
"data-pg-y": y,
|
|
62
|
+
"data-pg-w": w,
|
|
63
|
+
"data-pg-h": h,
|
|
64
|
+
children: [/* @__PURE__ */ jsx(ItemRenderer, { id: key }), resizeHandleProps && /* @__PURE__ */ jsx("span", {
|
|
65
|
+
className: "panelgrid-resize-handle",
|
|
66
|
+
...resizeHandleProps
|
|
67
|
+
})]
|
|
68
|
+
}, key);
|
|
69
|
+
})
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//#endregion
|
|
75
|
+
export { PanelGridRenderer };
|
|
76
|
+
//# sourceMappingURL=PanelGridRenderer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PanelGridRenderer.mjs","names":[],"sources":["../src/PanelGridRenderer.tsx"],"sourcesContent":["import { useLayoutEffect, useRef } from \"react\";\nimport { getGridRowCount } from \"./helpers/gridCalculations\";\nimport { usePanelGridControls, usePanelGridState } from \"./PanelGridProvider\";\nimport type { PanelId } from \"./types\";\n\ninterface PanelGridRendererProps {\n itemRenderer: React.ComponentType<{ id: PanelId }>;\n}\n\nexport function PanelGridRenderer({ itemRenderer: ItemRenderer }: PanelGridRendererProps) {\n const { panels, columnCount, gap, baseSize, ghostPanelRef } = usePanelGridState();\n const { setBaseSize } = usePanelGridControls();\n const containerRef = useRef<HTMLDivElement | null>(null);\n const rowCount = getGridRowCount(\n panels.map(({ panelProps: p }) => ({\n id: p.key,\n x: p.positionData.x,\n y: p.positionData.y,\n w: p.positionData.w,\n h: p.positionData.h,\n }))\n );\n const count = Math.max(columnCount * (rowCount + 1), columnCount * columnCount);\n\n useLayoutEffect(() => {\n if (!containerRef.current) return;\n const observer = new ResizeObserver((entries) => {\n const [entry] = entries;\n const rect = entry.contentRect;\n const baseSize = Math.floor((rect.width - gap * (columnCount - 1)) / columnCount);\n setBaseSize(baseSize);\n });\n observer.observe(containerRef.current);\n return () => observer.disconnect();\n }, [columnCount, gap, setBaseSize]);\n\n return (\n <div\n className=\"panelgrid-renderer\"\n style={{\n \"--column-count\": `${columnCount}`,\n \"--gap\": `${gap}px`,\n opacity: baseSize ? 1 : 0,\n }}\n ref={containerRef}\n >\n {Array.from({ length: count }).map((_, i) => {\n return <div key={i} className=\"panelgrid-panel-placeholder\" />;\n })}\n\n <div className=\"panelgrid-panel-ghost\" ref={ghostPanelRef}></div>\n\n {panels.map((panel) => {\n const { panelProps, resizeHandleProps } = panel;\n const { key, lockSize, style, positionData, ref, onMouseDown } = panelProps;\n\n const className = lockSize ? \"panelgrid-panel panelgrid-panel--size-locked\" : \"panelgrid-panel\";\n const { x, y, w, h } = positionData;\n\n return (\n <div\n key={key}\n className={className}\n style={style}\n ref={ref}\n onMouseDown={onMouseDown}\n data-panel-id={key}\n data-pg-x={x}\n data-pg-y={y}\n data-pg-w={w}\n data-pg-h={h}\n >\n <ItemRenderer id={key} />\n {resizeHandleProps && <span className=\"panelgrid-resize-handle\" {...resizeHandleProps}></span>}\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;AASA,SAAgB,kBAAkB,EAAE,cAAc,gBAAwC;CACxF,MAAM,EAAE,QAAQ,aAAa,KAAK,UAAU,kBAAkB,mBAAmB;CACjF,MAAM,EAAE,gBAAgB,sBAAsB;CAC9C,MAAM,eAAe,OAA8B,KAAK;CACxD,MAAM,WAAW,gBACf,OAAO,KAAK,EAAE,YAAY,SAAS;EACjC,IAAI,EAAE;EACN,GAAG,EAAE,aAAa;EAClB,GAAG,EAAE,aAAa;EAClB,GAAG,EAAE,aAAa;EAClB,GAAG,EAAE,aAAa;EACnB,EAAE,CACJ;CACD,MAAM,QAAQ,KAAK,IAAI,eAAe,WAAW,IAAI,cAAc,YAAY;AAE/E,uBAAsB;AACpB,MAAI,CAAC,aAAa,QAAS;EAC3B,MAAM,WAAW,IAAI,gBAAgB,YAAY;GAC/C,MAAM,CAAC,SAAS;GAChB,MAAM,OAAO,MAAM;AAEnB,eADiB,KAAK,OAAO,KAAK,QAAQ,OAAO,cAAc,MAAM,YAAY,CAC5D;IACrB;AACF,WAAS,QAAQ,aAAa,QAAQ;AACtC,eAAa,SAAS,YAAY;IACjC;EAAC;EAAa;EAAK;EAAY,CAAC;AAEnC,QACE,qBAAC;EACC,WAAU;EACV,OAAO;GACL,kBAAkB,GAAG;GACrB,SAAS,GAAG,IAAI;GAChB,SAAS,WAAW,IAAI;GACzB;EACD,KAAK;;GAEJ,MAAM,KAAK,EAAE,QAAQ,OAAO,CAAC,CAAC,KAAK,GAAG,MAAM;AAC3C,WAAO,oBAAC,SAAY,WAAU,iCAAb,EAA6C;KAC9D;GAEF,oBAAC;IAAI,WAAU;IAAwB,KAAK;KAAqB;GAEhE,OAAO,KAAK,UAAU;IACrB,MAAM,EAAE,YAAY,sBAAsB;IAC1C,MAAM,EAAE,KAAK,UAAU,OAAO,cAAc,KAAK,gBAAgB;IAEjE,MAAM,YAAY,WAAW,iDAAiD;IAC9E,MAAM,EAAE,GAAG,GAAG,GAAG,MAAM;AAEvB,WACE,qBAAC;KAEY;KACJ;KACF;KACQ;KACb,iBAAe;KACf,aAAW;KACX,aAAW;KACX,aAAW;KACX,aAAW;gBAEX,oBAAC,gBAAa,IAAI,MAAO,EACxB,qBAAqB,oBAAC;MAAK,WAAU;MAA0B,GAAI;OAA0B;OAZzF,IAaD;KAER;;GACE"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/helpers/animation.ts
|
|
3
|
+
/**
|
|
4
|
+
* Applies snap-back animation to element
|
|
5
|
+
* Smoothly animates the element from its dropped position to the snapped grid position
|
|
6
|
+
*/
|
|
7
|
+
function applySnapAnimation(options) {
|
|
8
|
+
const { element, droppedLeft, droppedTop, nextLeft, nextTop, originalTransition } = options;
|
|
9
|
+
const deltaX = droppedLeft - nextLeft;
|
|
10
|
+
const deltaY = droppedTop - nextTop;
|
|
11
|
+
element.style.transform = `translate3D(${deltaX}px, ${deltaY}px, 0)`;
|
|
12
|
+
element.style.transition = "";
|
|
13
|
+
window.requestAnimationFrame(() => {
|
|
14
|
+
element.style.transform = "translate3D(0, 0, 0)";
|
|
15
|
+
element.style.transition = "transform 0.1s ease-out";
|
|
16
|
+
});
|
|
17
|
+
element.style.left = `${nextLeft}px`;
|
|
18
|
+
element.style.top = `${nextTop}px`;
|
|
19
|
+
element.style.transition = originalTransition;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
exports.applySnapAnimation = applySnapAnimation;
|
|
24
|
+
//# sourceMappingURL=animation.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animation.cjs","names":[],"sources":["../../src/helpers/animation.ts"],"sourcesContent":["/**\n * Options for applying snap-back animation\n */\ninterface ApplySnapAnimationOptions {\n element: HTMLElement;\n droppedLeft: number;\n droppedTop: number;\n nextLeft: number;\n nextTop: number;\n originalTransition: string;\n}\n\n/**\n * Applies snap-back animation to element\n * Smoothly animates the element from its dropped position to the snapped grid position\n */\nexport function applySnapAnimation(options: ApplySnapAnimationOptions): void {\n const { element, droppedLeft, droppedTop, nextLeft, nextTop, originalTransition } = options;\n\n const deltaX = droppedLeft - nextLeft;\n const deltaY = droppedTop - nextTop;\n\n element.style.transform = `translate3D(${deltaX}px, ${deltaY}px, 0)`;\n element.style.transition = \"\";\n\n window.requestAnimationFrame(() => {\n element.style.transform = \"translate3D(0, 0, 0)\";\n element.style.transition = \"transform 0.1s ease-out\";\n });\n\n element.style.left = `${nextLeft}px`;\n element.style.top = `${nextTop}px`;\n element.style.transition = originalTransition;\n}\n"],"mappings":";;;;;;AAgBA,SAAgB,mBAAmB,SAA0C;CAC3E,MAAM,EAAE,SAAS,aAAa,YAAY,UAAU,SAAS,uBAAuB;CAEpF,MAAM,SAAS,cAAc;CAC7B,MAAM,SAAS,aAAa;AAE5B,SAAQ,MAAM,YAAY,eAAe,OAAO,MAAM,OAAO;AAC7D,SAAQ,MAAM,aAAa;AAE3B,QAAO,4BAA4B;AACjC,UAAQ,MAAM,YAAY;AAC1B,UAAQ,MAAM,aAAa;GAC3B;AAEF,SAAQ,MAAM,OAAO,GAAG,SAAS;AACjC,SAAQ,MAAM,MAAM,GAAG,QAAQ;AAC/B,SAAQ,MAAM,aAAa"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/helpers/animation.ts
|
|
2
|
+
/**
|
|
3
|
+
* Applies snap-back animation to element
|
|
4
|
+
* Smoothly animates the element from its dropped position to the snapped grid position
|
|
5
|
+
*/
|
|
6
|
+
function applySnapAnimation(options) {
|
|
7
|
+
const { element, droppedLeft, droppedTop, nextLeft, nextTop, originalTransition } = options;
|
|
8
|
+
const deltaX = droppedLeft - nextLeft;
|
|
9
|
+
const deltaY = droppedTop - nextTop;
|
|
10
|
+
element.style.transform = `translate3D(${deltaX}px, ${deltaY}px, 0)`;
|
|
11
|
+
element.style.transition = "";
|
|
12
|
+
window.requestAnimationFrame(() => {
|
|
13
|
+
element.style.transform = "translate3D(0, 0, 0)";
|
|
14
|
+
element.style.transition = "transform 0.1s ease-out";
|
|
15
|
+
});
|
|
16
|
+
element.style.left = `${nextLeft}px`;
|
|
17
|
+
element.style.top = `${nextTop}px`;
|
|
18
|
+
element.style.transition = originalTransition;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { applySnapAnimation };
|
|
23
|
+
//# sourceMappingURL=animation.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animation.mjs","names":[],"sources":["../../src/helpers/animation.ts"],"sourcesContent":["/**\n * Options for applying snap-back animation\n */\ninterface ApplySnapAnimationOptions {\n element: HTMLElement;\n droppedLeft: number;\n droppedTop: number;\n nextLeft: number;\n nextTop: number;\n originalTransition: string;\n}\n\n/**\n * Applies snap-back animation to element\n * Smoothly animates the element from its dropped position to the snapped grid position\n */\nexport function applySnapAnimation(options: ApplySnapAnimationOptions): void {\n const { element, droppedLeft, droppedTop, nextLeft, nextTop, originalTransition } = options;\n\n const deltaX = droppedLeft - nextLeft;\n const deltaY = droppedTop - nextTop;\n\n element.style.transform = `translate3D(${deltaX}px, ${deltaY}px, 0)`;\n element.style.transition = \"\";\n\n window.requestAnimationFrame(() => {\n element.style.transform = \"translate3D(0, 0, 0)\";\n element.style.transition = \"transform 0.1s ease-out\";\n });\n\n element.style.left = `${nextLeft}px`;\n element.style.top = `${nextTop}px`;\n element.style.transition = originalTransition;\n}\n"],"mappings":";;;;;AAgBA,SAAgB,mBAAmB,SAA0C;CAC3E,MAAM,EAAE,SAAS,aAAa,YAAY,UAAU,SAAS,uBAAuB;CAEpF,MAAM,SAAS,cAAc;CAC7B,MAAM,SAAS,aAAa;AAE5B,SAAQ,MAAM,YAAY,eAAe,OAAO,MAAM,OAAO;AAC7D,SAAQ,MAAM,aAAa;AAE3B,QAAO,4BAA4B;AACjC,UAAQ,MAAM,YAAY;AAC1B,UAAQ,MAAM,aAAa;GAC3B;AAEF,SAAQ,MAAM,OAAO,GAAG,SAAS;AACjC,SAAQ,MAAM,MAAM,GAAG,QAAQ;AAC/B,SAAQ,MAAM,aAAa"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/helpers/gridCalculations.ts
|
|
3
|
+
/**
|
|
4
|
+
* Converts a pixel value to grid units by dividing by the cell size (baseSize + gap)
|
|
5
|
+
* and rounding up with Math.ceil. Ensures the result is at least 1 and does not exceed available space.
|
|
6
|
+
* When columnCount and xPosition are provided, ensures x + width <= columnCount.
|
|
7
|
+
*
|
|
8
|
+
* ピクセル値をグリッド単位に変換します。セルサイズ (baseSize + gap) で割り、小数点は切り上げて整数にします。
|
|
9
|
+
* 結果は最小1で、columnCountとxPositionが指定された場合はx + width <= columnCountを満たすように制限されます。
|
|
10
|
+
*/
|
|
11
|
+
function pixelsToGridSize(pixels, baseSize, gap, columnCount, xPosition) {
|
|
12
|
+
const gridSize = Math.ceil(pixels / (baseSize + gap));
|
|
13
|
+
const constrainedSize = Math.max(1, gridSize);
|
|
14
|
+
if (columnCount !== void 0 && xPosition !== void 0) {
|
|
15
|
+
const maxWidth = Math.max(1, columnCount - xPosition);
|
|
16
|
+
return Math.min(constrainedSize, maxWidth);
|
|
17
|
+
}
|
|
18
|
+
if (columnCount !== void 0) return Math.min(constrainedSize, columnCount);
|
|
19
|
+
return constrainedSize;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Converts a pixel coordinate to grid coordinate by dividing by the cell size
|
|
23
|
+
* and rounding down with Math.floor, ensuring the result is not negative and does not cause overflow.
|
|
24
|
+
* When columnCount and width are provided, ensures x + width <= columnCount
|
|
25
|
+
*
|
|
26
|
+
* ピクセル座標をグリッド座標に変換します。セルサイズで割り、小数点は切り捨てて整数にします。
|
|
27
|
+
* 結果が負にならず、columnCountとwidthが指定された場合はx + width <= columnCountを満たすようにします。
|
|
28
|
+
*/
|
|
29
|
+
function pixelsToGridPosition(pixels, baseSize, gap, columnCount, width) {
|
|
30
|
+
const gridPosition = Math.max(0, Math.floor(pixels / (baseSize + gap)));
|
|
31
|
+
if (columnCount !== void 0 && width !== void 0) {
|
|
32
|
+
const maxPosition = Math.max(0, columnCount - width);
|
|
33
|
+
return Math.min(gridPosition, maxPosition);
|
|
34
|
+
}
|
|
35
|
+
if (columnCount !== void 0) return Math.min(gridPosition, columnCount - 1);
|
|
36
|
+
return gridPosition;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Converts grid units to pixels
|
|
40
|
+
* Formula: gridUnits * baseSize + max(0, gridUnits - 1) * gap
|
|
41
|
+
* This accounts for gaps between grid cells but not after the last cell
|
|
42
|
+
*
|
|
43
|
+
* グリッド単位をピクセルに変換します。
|
|
44
|
+
* 計算式: gridUnits * baseSize + max(0, gridUnits - 1) * gap
|
|
45
|
+
* グリッドセル間の gap を考慮しますが、最後のセルの後には gap を含めません。
|
|
46
|
+
*/
|
|
47
|
+
function gridToPixels(gridUnits, baseSize, gap) {
|
|
48
|
+
return gridUnits * baseSize + Math.max(0, gridUnits - 1) * gap;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Converts grid coordinate to pixel coordinate for positioning
|
|
52
|
+
* Formula: max(0, gridCoord * (baseSize + gap))
|
|
53
|
+
* This includes the gap after each cell for proper positioning in the grid
|
|
54
|
+
*
|
|
55
|
+
* グリッド座標をピクセル座標に変換します(位置計算用)。
|
|
56
|
+
* 計算式: max(0, gridCoord * (baseSize + gap))
|
|
57
|
+
* 各セルの後に gap を含めて、グリッド内での適切な位置決めを行います。
|
|
58
|
+
*/
|
|
59
|
+
function gridPositionToPixels(gridCoord, baseSize, gap) {
|
|
60
|
+
return Math.max(0, gridCoord * (baseSize + gap));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Gets the maximum Y coordinate of the panels
|
|
64
|
+
* パネルの最大Y座標を取得します。
|
|
65
|
+
*/
|
|
66
|
+
function getGridRowCount(panels) {
|
|
67
|
+
return Math.max(...panels.map((p) => p.y + p.h));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
exports.getGridRowCount = getGridRowCount;
|
|
72
|
+
exports.gridPositionToPixels = gridPositionToPixels;
|
|
73
|
+
exports.gridToPixels = gridToPixels;
|
|
74
|
+
exports.pixelsToGridPosition = pixelsToGridPosition;
|
|
75
|
+
exports.pixelsToGridSize = pixelsToGridSize;
|
|
76
|
+
//# sourceMappingURL=gridCalculations.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gridCalculations.cjs","names":[],"sources":["../../src/helpers/gridCalculations.ts"],"sourcesContent":["import type { PanelCoordinate } from \"../types\";\n\n/**\n * Converts a pixel value to grid units by dividing by the cell size (baseSize + gap)\n * and rounding up with Math.ceil. Ensures the result is at least 1 and does not exceed available space.\n * When columnCount and xPosition are provided, ensures x + width <= columnCount.\n *\n * ピクセル値をグリッド単位に変換します。セルサイズ (baseSize + gap) で割り、小数点は切り上げて整数にします。\n * 結果は最小1で、columnCountとxPositionが指定された場合はx + width <= columnCountを満たすように制限されます。\n */\nexport function pixelsToGridSize(\n pixels: number,\n baseSize: number,\n gap: number,\n columnCount?: number,\n xPosition?: number\n): number {\n const gridSize = Math.ceil(pixels / (baseSize + gap));\n const constrainedSize = Math.max(1, gridSize);\n\n if (columnCount !== undefined && xPosition !== undefined) {\n // Ensure x + width <= columnCount\n const maxWidth = Math.max(1, columnCount - xPosition);\n return Math.min(constrainedSize, maxWidth);\n }\n\n if (columnCount !== undefined) {\n // Legacy behavior: constrain to columnCount\n return Math.min(constrainedSize, columnCount);\n }\n\n return constrainedSize;\n}\n\n/**\n * Converts a pixel coordinate to grid coordinate by dividing by the cell size\n * and rounding down with Math.floor, ensuring the result is not negative and does not cause overflow.\n * When columnCount and width are provided, ensures x + width <= columnCount\n *\n * ピクセル座標をグリッド座標に変換します。セルサイズで割り、小数点は切り捨てて整数にします。\n * 結果が負にならず、columnCountとwidthが指定された場合はx + width <= columnCountを満たすようにします。\n */\nexport function pixelsToGridPosition(\n pixels: number,\n baseSize: number,\n gap: number,\n columnCount?: number,\n width?: number\n): number {\n const gridPosition = Math.max(0, Math.floor(pixels / (baseSize + gap)));\n\n if (columnCount !== undefined && width !== undefined) {\n // Ensure x + width <= columnCount\n const maxPosition = Math.max(0, columnCount - width);\n return Math.min(gridPosition, maxPosition);\n }\n\n if (columnCount !== undefined) {\n // Legacy behavior: constrain to columnCount - 1\n return Math.min(gridPosition, columnCount - 1);\n }\n\n return gridPosition;\n}\n\n/**\n * Converts grid units to pixels\n * Formula: gridUnits * baseSize + max(0, gridUnits - 1) * gap\n * This accounts for gaps between grid cells but not after the last cell\n *\n * グリッド単位をピクセルに変換します。\n * 計算式: gridUnits * baseSize + max(0, gridUnits - 1) * gap\n * グリッドセル間の gap を考慮しますが、最後のセルの後には gap を含めません。\n */\nexport function gridToPixels(gridUnits: number, baseSize: number, gap: number): number {\n return gridUnits * baseSize + Math.max(0, gridUnits - 1) * gap;\n}\n\n/**\n * Converts grid coordinate to pixel coordinate for positioning\n * Formula: max(0, gridCoord * (baseSize + gap))\n * This includes the gap after each cell for proper positioning in the grid\n *\n * グリッド座標をピクセル座標に変換します(位置計算用)。\n * 計算式: max(0, gridCoord * (baseSize + gap))\n * 各セルの後に gap を含めて、グリッド内での適切な位置決めを行います。\n */\nexport function gridPositionToPixels(gridCoord: number, baseSize: number, gap: number): number {\n return Math.max(0, gridCoord * (baseSize + gap));\n}\n\n/**\n * Snaps a pixel value to the nearest grid position\n * Useful for aligning elements to the grid after drag/resize operations\n *\n * ピクセル値を最も近いグリッド位置にスナップします。\n * ドラッグ・リサイズ操作後に要素をグリッドに整列させる際に利用する。\n */\nexport function snapToGrid(pixels: number, baseSize: number, gap: number): number {\n const gridPosition = pixelsToGridPosition(pixels, baseSize, gap);\n return gridPositionToPixels(gridPosition, baseSize, gap);\n}\n\n/**\n * Gets the maximum Y coordinate of the panels\n * パネルの最大Y座標を取得します。\n */\nexport function getGridRowCount(panels: PanelCoordinate[]): number {\n return Math.max(...panels.map((p) => p.y + p.h));\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,iBACd,QACA,UACA,KACA,aACA,WACQ;CACR,MAAM,WAAW,KAAK,KAAK,UAAU,WAAW,KAAK;CACrD,MAAM,kBAAkB,KAAK,IAAI,GAAG,SAAS;AAE7C,KAAI,gBAAgB,UAAa,cAAc,QAAW;EAExD,MAAM,WAAW,KAAK,IAAI,GAAG,cAAc,UAAU;AACrD,SAAO,KAAK,IAAI,iBAAiB,SAAS;;AAG5C,KAAI,gBAAgB,OAElB,QAAO,KAAK,IAAI,iBAAiB,YAAY;AAG/C,QAAO;;;;;;;;;;AAWT,SAAgB,qBACd,QACA,UACA,KACA,aACA,OACQ;CACR,MAAM,eAAe,KAAK,IAAI,GAAG,KAAK,MAAM,UAAU,WAAW,KAAK,CAAC;AAEvE,KAAI,gBAAgB,UAAa,UAAU,QAAW;EAEpD,MAAM,cAAc,KAAK,IAAI,GAAG,cAAc,MAAM;AACpD,SAAO,KAAK,IAAI,cAAc,YAAY;;AAG5C,KAAI,gBAAgB,OAElB,QAAO,KAAK,IAAI,cAAc,cAAc,EAAE;AAGhD,QAAO;;;;;;;;;;;AAYT,SAAgB,aAAa,WAAmB,UAAkB,KAAqB;AACrF,QAAO,YAAY,WAAW,KAAK,IAAI,GAAG,YAAY,EAAE,GAAG;;;;;;;;;;;AAY7D,SAAgB,qBAAqB,WAAmB,UAAkB,KAAqB;AAC7F,QAAO,KAAK,IAAI,GAAG,aAAa,WAAW,KAAK;;;;;;AAmBlD,SAAgB,gBAAgB,QAAmC;AACjE,QAAO,KAAK,IAAI,GAAG,OAAO,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//#region src/helpers/gridCalculations.ts
|
|
2
|
+
/**
|
|
3
|
+
* Converts a pixel value to grid units by dividing by the cell size (baseSize + gap)
|
|
4
|
+
* and rounding up with Math.ceil. Ensures the result is at least 1 and does not exceed available space.
|
|
5
|
+
* When columnCount and xPosition are provided, ensures x + width <= columnCount.
|
|
6
|
+
*
|
|
7
|
+
* ピクセル値をグリッド単位に変換します。セルサイズ (baseSize + gap) で割り、小数点は切り上げて整数にします。
|
|
8
|
+
* 結果は最小1で、columnCountとxPositionが指定された場合はx + width <= columnCountを満たすように制限されます。
|
|
9
|
+
*/
|
|
10
|
+
function pixelsToGridSize(pixels, baseSize, gap, columnCount, xPosition) {
|
|
11
|
+
const gridSize = Math.ceil(pixels / (baseSize + gap));
|
|
12
|
+
const constrainedSize = Math.max(1, gridSize);
|
|
13
|
+
if (columnCount !== void 0 && xPosition !== void 0) {
|
|
14
|
+
const maxWidth = Math.max(1, columnCount - xPosition);
|
|
15
|
+
return Math.min(constrainedSize, maxWidth);
|
|
16
|
+
}
|
|
17
|
+
if (columnCount !== void 0) return Math.min(constrainedSize, columnCount);
|
|
18
|
+
return constrainedSize;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Converts a pixel coordinate to grid coordinate by dividing by the cell size
|
|
22
|
+
* and rounding down with Math.floor, ensuring the result is not negative and does not cause overflow.
|
|
23
|
+
* When columnCount and width are provided, ensures x + width <= columnCount
|
|
24
|
+
*
|
|
25
|
+
* ピクセル座標をグリッド座標に変換します。セルサイズで割り、小数点は切り捨てて整数にします。
|
|
26
|
+
* 結果が負にならず、columnCountとwidthが指定された場合はx + width <= columnCountを満たすようにします。
|
|
27
|
+
*/
|
|
28
|
+
function pixelsToGridPosition(pixels, baseSize, gap, columnCount, width) {
|
|
29
|
+
const gridPosition = Math.max(0, Math.floor(pixels / (baseSize + gap)));
|
|
30
|
+
if (columnCount !== void 0 && width !== void 0) {
|
|
31
|
+
const maxPosition = Math.max(0, columnCount - width);
|
|
32
|
+
return Math.min(gridPosition, maxPosition);
|
|
33
|
+
}
|
|
34
|
+
if (columnCount !== void 0) return Math.min(gridPosition, columnCount - 1);
|
|
35
|
+
return gridPosition;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Converts grid units to pixels
|
|
39
|
+
* Formula: gridUnits * baseSize + max(0, gridUnits - 1) * gap
|
|
40
|
+
* This accounts for gaps between grid cells but not after the last cell
|
|
41
|
+
*
|
|
42
|
+
* グリッド単位をピクセルに変換します。
|
|
43
|
+
* 計算式: gridUnits * baseSize + max(0, gridUnits - 1) * gap
|
|
44
|
+
* グリッドセル間の gap を考慮しますが、最後のセルの後には gap を含めません。
|
|
45
|
+
*/
|
|
46
|
+
function gridToPixels(gridUnits, baseSize, gap) {
|
|
47
|
+
return gridUnits * baseSize + Math.max(0, gridUnits - 1) * gap;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Converts grid coordinate to pixel coordinate for positioning
|
|
51
|
+
* Formula: max(0, gridCoord * (baseSize + gap))
|
|
52
|
+
* This includes the gap after each cell for proper positioning in the grid
|
|
53
|
+
*
|
|
54
|
+
* グリッド座標をピクセル座標に変換します(位置計算用)。
|
|
55
|
+
* 計算式: max(0, gridCoord * (baseSize + gap))
|
|
56
|
+
* 各セルの後に gap を含めて、グリッド内での適切な位置決めを行います。
|
|
57
|
+
*/
|
|
58
|
+
function gridPositionToPixels(gridCoord, baseSize, gap) {
|
|
59
|
+
return Math.max(0, gridCoord * (baseSize + gap));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Gets the maximum Y coordinate of the panels
|
|
63
|
+
* パネルの最大Y座標を取得します。
|
|
64
|
+
*/
|
|
65
|
+
function getGridRowCount(panels) {
|
|
66
|
+
return Math.max(...panels.map((p) => p.y + p.h));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
export { getGridRowCount, gridPositionToPixels, gridToPixels, pixelsToGridPosition, pixelsToGridSize };
|
|
71
|
+
//# sourceMappingURL=gridCalculations.mjs.map
|