dashboardity 1.1.0 → 1.2.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/dist/index.d.mts +17 -5
- package/dist/index.d.ts +17 -5
- package/dist/index.js +110 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +110 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -79,16 +79,22 @@ type BreakpointWidths = Partial<Record<Exclude<BreakpointKey, "base">, number>>;
|
|
|
79
79
|
type ColumnsByBreakpoint = Partial<Record<BreakpointKey, number>> & {
|
|
80
80
|
base: number;
|
|
81
81
|
};
|
|
82
|
+
/** 브레이크포인트별 레이아웃. 지정 시 해당 구간에서 스케일 대신 이 레이아웃 사용 */
|
|
83
|
+
type LayoutByBreakpoint = {
|
|
84
|
+
items: GridItem[];
|
|
85
|
+
};
|
|
82
86
|
/**
|
|
83
87
|
* 대시보드 공식 스펙. "대시보드 = JSON"
|
|
84
88
|
* layout.items[].id === panels[].id 1:1. panels에는 좌표 없음.
|
|
85
89
|
* breakpoints + columnsByBreakpoint 있으면 뷰포트 너비에 따라 columns 해석.
|
|
90
|
+
* layoutsByBreakpoint 있으면 해당 구간에서 layout 대신 그 레이아웃 사용(브레이크포인트별 배치).
|
|
86
91
|
*/
|
|
87
92
|
type DashboardSpec = {
|
|
88
93
|
id: string;
|
|
89
94
|
title: string;
|
|
90
95
|
/** 현재 저장된 레이아웃의 열 수. columnsByBreakpoint 사용 시에도 직렬화 시 이 값으로 저장 */
|
|
91
96
|
columns: number;
|
|
97
|
+
/** 기본/캐논칼 레이아웃. layoutsByBreakpoint 미지정 구간은 여기서 스케일 */
|
|
92
98
|
layout: {
|
|
93
99
|
items: GridItem[];
|
|
94
100
|
};
|
|
@@ -97,6 +103,8 @@ type DashboardSpec = {
|
|
|
97
103
|
breakpoints?: BreakpointWidths;
|
|
98
104
|
/** 브레이크포인트별 열 수. 지정 시 반응형 columns 적용 */
|
|
99
105
|
columnsByBreakpoint?: ColumnsByBreakpoint;
|
|
106
|
+
/** 브레이크포인트별 레이아웃. 지정한 구간은 스케일 없이 이 배치 사용 */
|
|
107
|
+
layoutsByBreakpoint?: Partial<Record<BreakpointKey, LayoutByBreakpoint>>;
|
|
100
108
|
};
|
|
101
109
|
/** 편집 / 보기 모드 (Grafana 핵심 UX) */
|
|
102
110
|
type DashboardMode = "view" | "edit";
|
|
@@ -271,22 +279,26 @@ declare const DashboardRuntime: React$1.ForwardRefExoticComponent<DashboardRunti
|
|
|
271
279
|
declare const createEmptyPanel: (type: string, defaultTitle?: string) => PanelConfig;
|
|
272
280
|
/**
|
|
273
281
|
* 라이브러리 레벨: store + panels + meta → JSON 스펙.
|
|
274
|
-
*
|
|
275
|
-
*
|
|
282
|
+
* breakpoints/columnsByBreakpoint/layoutsByBreakpoint 있으면 그대로 직렬화.
|
|
283
|
+
* layoutCache: 현재 브레이크포인트 포함 편집된 구간별 레이아웃(merge되어 출력).
|
|
276
284
|
*/
|
|
277
285
|
declare const serializeDashboard: (store: LayoutStore, panels: PanelConfig[], meta: {
|
|
278
286
|
id: string;
|
|
279
287
|
title: string;
|
|
280
|
-
}, specOverrides?: Pick<DashboardSpec, "breakpoints" | "columnsByBreakpoint">) => DashboardSpec;
|
|
288
|
+
}, specOverrides?: Pick<DashboardSpec, "breakpoints" | "columnsByBreakpoint" | "layoutsByBreakpoint">) => DashboardSpec;
|
|
281
289
|
type LoadDashboardOptions = {
|
|
282
290
|
/** 뷰포트/컨테이너 너비(px). columnsByBreakpoint 있을 때 이 너비로 열 수 해석 */
|
|
283
291
|
width?: number;
|
|
284
292
|
/** 이미 해석된 열 수. 지정 시 width 무시하고 이 값으로 스토어 생성 */
|
|
285
293
|
resolvedColumns?: number;
|
|
294
|
+
/** 현재 브레이크포인트. layoutsByBreakpoint[breakpointKey] 있으면 그 레이아웃 사용 */
|
|
295
|
+
breakpointKey?: BreakpointKey;
|
|
296
|
+
/** 런타임 캐시(구간별 레이아웃). breakpointKey에 대한 캐시가 있으면 spec보다 우선 */
|
|
297
|
+
layoutCache?: Partial<Record<BreakpointKey, GridItem[]>>;
|
|
286
298
|
};
|
|
287
299
|
/**
|
|
288
300
|
* JSON 스펙 → store + panels 복원.
|
|
289
|
-
*
|
|
301
|
+
* layoutsByBreakpoint 또는 layoutCache로 해당 구간 레이아웃 사용, 없으면 layout 스케일.
|
|
290
302
|
*/
|
|
291
303
|
declare const loadDashboard: (spec: DashboardSpec, options?: LoadDashboardOptions) => {
|
|
292
304
|
store: LayoutStore;
|
|
@@ -425,4 +437,4 @@ type WidgetContainerProps = {
|
|
|
425
437
|
*/
|
|
426
438
|
declare const WidgetContainer: React$1.FC<WidgetContainerProps>;
|
|
427
439
|
|
|
428
|
-
export { type BreakpointKey, type BreakpointWidths, type ColumnsByBreakpoint, DEFAULT_BREAKPOINT_WIDTHS, Dashboard, type DashboardGridOptions, type DashboardMode, type DashboardOption, DashboardPicker, type DashboardPickerProps, type DashboardProps, DashboardRuntime, type DashboardRuntimeHandle, type DashboardRuntimeProps, type DashboardSpec, type DataSource, FallbackWidget, type LoadDashboardOptions, Panel, type PanelAction, type PanelConfig, type PanelConfigWithLayout, PanelOptionEditor, type PanelOptionEditorProps, type PanelProps, type ResponsiveGridSize, SideNav, type SideNavItem, type SideNavProps, type Theme, TimeRangePicker, type TimeRangePickerProps, type TimeRangePreset, TopBar, type TopBarProps, type UseResponsiveGridOptions, type WidgetComponent, WidgetContainer, type WidgetContainerProps, type WidgetDefinition, type WidgetOptionSchema, type WidgetOptionSchemaField, type WidgetProps, type WidgetRegistry, buildInitialItemsFromPanelConfigs, cn, colors, createEmptyPanel, createStaticDataSource, createWidgetRegistry, defaultTheme, getBreakpointKey, loadDashboard, resolveColumns, scaleLayout, serializeDashboard, spacing, typography, useContainerWidth, useResponsiveGrid };
|
|
440
|
+
export { type BreakpointKey, type BreakpointWidths, type ColumnsByBreakpoint, DEFAULT_BREAKPOINT_WIDTHS, Dashboard, type DashboardGridOptions, type DashboardMode, type DashboardOption, DashboardPicker, type DashboardPickerProps, type DashboardProps, DashboardRuntime, type DashboardRuntimeHandle, type DashboardRuntimeProps, type DashboardSpec, type DataSource, FallbackWidget, type LayoutByBreakpoint, type LoadDashboardOptions, Panel, type PanelAction, type PanelConfig, type PanelConfigWithLayout, PanelOptionEditor, type PanelOptionEditorProps, type PanelProps, type ResponsiveGridSize, SideNav, type SideNavItem, type SideNavProps, type Theme, TimeRangePicker, type TimeRangePickerProps, type TimeRangePreset, TopBar, type TopBarProps, type UseResponsiveGridOptions, type WidgetComponent, WidgetContainer, type WidgetContainerProps, type WidgetDefinition, type WidgetOptionSchema, type WidgetOptionSchemaField, type WidgetProps, type WidgetRegistry, buildInitialItemsFromPanelConfigs, cn, colors, createEmptyPanel, createStaticDataSource, createWidgetRegistry, defaultTheme, getBreakpointKey, loadDashboard, resolveColumns, scaleLayout, serializeDashboard, spacing, typography, useContainerWidth, useResponsiveGrid };
|
package/dist/index.d.ts
CHANGED
|
@@ -79,16 +79,22 @@ type BreakpointWidths = Partial<Record<Exclude<BreakpointKey, "base">, number>>;
|
|
|
79
79
|
type ColumnsByBreakpoint = Partial<Record<BreakpointKey, number>> & {
|
|
80
80
|
base: number;
|
|
81
81
|
};
|
|
82
|
+
/** 브레이크포인트별 레이아웃. 지정 시 해당 구간에서 스케일 대신 이 레이아웃 사용 */
|
|
83
|
+
type LayoutByBreakpoint = {
|
|
84
|
+
items: GridItem[];
|
|
85
|
+
};
|
|
82
86
|
/**
|
|
83
87
|
* 대시보드 공식 스펙. "대시보드 = JSON"
|
|
84
88
|
* layout.items[].id === panels[].id 1:1. panels에는 좌표 없음.
|
|
85
89
|
* breakpoints + columnsByBreakpoint 있으면 뷰포트 너비에 따라 columns 해석.
|
|
90
|
+
* layoutsByBreakpoint 있으면 해당 구간에서 layout 대신 그 레이아웃 사용(브레이크포인트별 배치).
|
|
86
91
|
*/
|
|
87
92
|
type DashboardSpec = {
|
|
88
93
|
id: string;
|
|
89
94
|
title: string;
|
|
90
95
|
/** 현재 저장된 레이아웃의 열 수. columnsByBreakpoint 사용 시에도 직렬화 시 이 값으로 저장 */
|
|
91
96
|
columns: number;
|
|
97
|
+
/** 기본/캐논칼 레이아웃. layoutsByBreakpoint 미지정 구간은 여기서 스케일 */
|
|
92
98
|
layout: {
|
|
93
99
|
items: GridItem[];
|
|
94
100
|
};
|
|
@@ -97,6 +103,8 @@ type DashboardSpec = {
|
|
|
97
103
|
breakpoints?: BreakpointWidths;
|
|
98
104
|
/** 브레이크포인트별 열 수. 지정 시 반응형 columns 적용 */
|
|
99
105
|
columnsByBreakpoint?: ColumnsByBreakpoint;
|
|
106
|
+
/** 브레이크포인트별 레이아웃. 지정한 구간은 스케일 없이 이 배치 사용 */
|
|
107
|
+
layoutsByBreakpoint?: Partial<Record<BreakpointKey, LayoutByBreakpoint>>;
|
|
100
108
|
};
|
|
101
109
|
/** 편집 / 보기 모드 (Grafana 핵심 UX) */
|
|
102
110
|
type DashboardMode = "view" | "edit";
|
|
@@ -271,22 +279,26 @@ declare const DashboardRuntime: React$1.ForwardRefExoticComponent<DashboardRunti
|
|
|
271
279
|
declare const createEmptyPanel: (type: string, defaultTitle?: string) => PanelConfig;
|
|
272
280
|
/**
|
|
273
281
|
* 라이브러리 레벨: store + panels + meta → JSON 스펙.
|
|
274
|
-
*
|
|
275
|
-
*
|
|
282
|
+
* breakpoints/columnsByBreakpoint/layoutsByBreakpoint 있으면 그대로 직렬화.
|
|
283
|
+
* layoutCache: 현재 브레이크포인트 포함 편집된 구간별 레이아웃(merge되어 출력).
|
|
276
284
|
*/
|
|
277
285
|
declare const serializeDashboard: (store: LayoutStore, panels: PanelConfig[], meta: {
|
|
278
286
|
id: string;
|
|
279
287
|
title: string;
|
|
280
|
-
}, specOverrides?: Pick<DashboardSpec, "breakpoints" | "columnsByBreakpoint">) => DashboardSpec;
|
|
288
|
+
}, specOverrides?: Pick<DashboardSpec, "breakpoints" | "columnsByBreakpoint" | "layoutsByBreakpoint">) => DashboardSpec;
|
|
281
289
|
type LoadDashboardOptions = {
|
|
282
290
|
/** 뷰포트/컨테이너 너비(px). columnsByBreakpoint 있을 때 이 너비로 열 수 해석 */
|
|
283
291
|
width?: number;
|
|
284
292
|
/** 이미 해석된 열 수. 지정 시 width 무시하고 이 값으로 스토어 생성 */
|
|
285
293
|
resolvedColumns?: number;
|
|
294
|
+
/** 현재 브레이크포인트. layoutsByBreakpoint[breakpointKey] 있으면 그 레이아웃 사용 */
|
|
295
|
+
breakpointKey?: BreakpointKey;
|
|
296
|
+
/** 런타임 캐시(구간별 레이아웃). breakpointKey에 대한 캐시가 있으면 spec보다 우선 */
|
|
297
|
+
layoutCache?: Partial<Record<BreakpointKey, GridItem[]>>;
|
|
286
298
|
};
|
|
287
299
|
/**
|
|
288
300
|
* JSON 스펙 → store + panels 복원.
|
|
289
|
-
*
|
|
301
|
+
* layoutsByBreakpoint 또는 layoutCache로 해당 구간 레이아웃 사용, 없으면 layout 스케일.
|
|
290
302
|
*/
|
|
291
303
|
declare const loadDashboard: (spec: DashboardSpec, options?: LoadDashboardOptions) => {
|
|
292
304
|
store: LayoutStore;
|
|
@@ -425,4 +437,4 @@ type WidgetContainerProps = {
|
|
|
425
437
|
*/
|
|
426
438
|
declare const WidgetContainer: React$1.FC<WidgetContainerProps>;
|
|
427
439
|
|
|
428
|
-
export { type BreakpointKey, type BreakpointWidths, type ColumnsByBreakpoint, DEFAULT_BREAKPOINT_WIDTHS, Dashboard, type DashboardGridOptions, type DashboardMode, type DashboardOption, DashboardPicker, type DashboardPickerProps, type DashboardProps, DashboardRuntime, type DashboardRuntimeHandle, type DashboardRuntimeProps, type DashboardSpec, type DataSource, FallbackWidget, type LoadDashboardOptions, Panel, type PanelAction, type PanelConfig, type PanelConfigWithLayout, PanelOptionEditor, type PanelOptionEditorProps, type PanelProps, type ResponsiveGridSize, SideNav, type SideNavItem, type SideNavProps, type Theme, TimeRangePicker, type TimeRangePickerProps, type TimeRangePreset, TopBar, type TopBarProps, type UseResponsiveGridOptions, type WidgetComponent, WidgetContainer, type WidgetContainerProps, type WidgetDefinition, type WidgetOptionSchema, type WidgetOptionSchemaField, type WidgetProps, type WidgetRegistry, buildInitialItemsFromPanelConfigs, cn, colors, createEmptyPanel, createStaticDataSource, createWidgetRegistry, defaultTheme, getBreakpointKey, loadDashboard, resolveColumns, scaleLayout, serializeDashboard, spacing, typography, useContainerWidth, useResponsiveGrid };
|
|
440
|
+
export { type BreakpointKey, type BreakpointWidths, type ColumnsByBreakpoint, DEFAULT_BREAKPOINT_WIDTHS, Dashboard, type DashboardGridOptions, type DashboardMode, type DashboardOption, DashboardPicker, type DashboardPickerProps, type DashboardProps, DashboardRuntime, type DashboardRuntimeHandle, type DashboardRuntimeProps, type DashboardSpec, type DataSource, FallbackWidget, type LayoutByBreakpoint, type LoadDashboardOptions, Panel, type PanelAction, type PanelConfig, type PanelConfigWithLayout, PanelOptionEditor, type PanelOptionEditorProps, type PanelProps, type ResponsiveGridSize, SideNav, type SideNavItem, type SideNavProps, type Theme, TimeRangePicker, type TimeRangePickerProps, type TimeRangePreset, TopBar, type TopBarProps, type UseResponsiveGridOptions, type WidgetComponent, WidgetContainer, type WidgetContainerProps, type WidgetDefinition, type WidgetOptionSchema, type WidgetOptionSchemaField, type WidgetProps, type WidgetRegistry, buildInitialItemsFromPanelConfigs, cn, colors, createEmptyPanel, createStaticDataSource, createWidgetRegistry, defaultTheme, getBreakpointKey, loadDashboard, resolveColumns, scaleLayout, serializeDashboard, spacing, typography, useContainerWidth, useResponsiveGrid };
|
package/dist/index.js
CHANGED
|
@@ -35,7 +35,7 @@ __export(index_exports, {
|
|
|
35
35
|
cn: () => cn3,
|
|
36
36
|
colors: () => colors,
|
|
37
37
|
createEmptyPanel: () => createEmptyPanel,
|
|
38
|
-
createLayoutStore: () =>
|
|
38
|
+
createLayoutStore: () => import_layout_store2.createLayoutStore,
|
|
39
39
|
createStaticDataSource: () => createStaticDataSource,
|
|
40
40
|
createWidgetRegistry: () => createWidgetRegistry,
|
|
41
41
|
defaultTheme: () => defaultTheme,
|
|
@@ -518,7 +518,6 @@ var Dashboard = ({
|
|
|
518
518
|
|
|
519
519
|
// src/core/DashboardRuntime.tsx
|
|
520
520
|
var import_react4 = require("react");
|
|
521
|
-
var import_layout_store2 = require("@dashboardity/layout-store");
|
|
522
521
|
|
|
523
522
|
// src/core/DashboardSerializer.ts
|
|
524
523
|
var import_layout_store = require("@dashboardity/layout-store");
|
|
@@ -542,13 +541,32 @@ var serializeDashboard = (store, panels, meta, specOverrides) => {
|
|
|
542
541
|
if (specOverrides?.breakpoints) base.breakpoints = specOverrides.breakpoints;
|
|
543
542
|
if (specOverrides?.columnsByBreakpoint)
|
|
544
543
|
base.columnsByBreakpoint = specOverrides.columnsByBreakpoint;
|
|
544
|
+
if (specOverrides?.layoutsByBreakpoint != null)
|
|
545
|
+
base.layoutsByBreakpoint = specOverrides.layoutsByBreakpoint;
|
|
545
546
|
return base;
|
|
546
547
|
};
|
|
548
|
+
var getItemsForBreakpoint = (spec, breakpointKey, resolvedColumns, layoutCache) => {
|
|
549
|
+
const cached = layoutCache?.[breakpointKey];
|
|
550
|
+
if (cached != null && cached.length > 0) return [...cached];
|
|
551
|
+
const byBp = spec.layoutsByBreakpoint?.[breakpointKey]?.items;
|
|
552
|
+
if (byBp != null && byBp.length > 0) return [...byBp];
|
|
553
|
+
return scaleLayout(
|
|
554
|
+
spec.layout.items,
|
|
555
|
+
spec.columns,
|
|
556
|
+
resolvedColumns
|
|
557
|
+
);
|
|
558
|
+
};
|
|
547
559
|
var loadDashboard = (spec, options) => {
|
|
548
560
|
const savedColumns = spec.columns;
|
|
549
561
|
const colConfig = spec.columnsByBreakpoint ?? savedColumns;
|
|
550
562
|
const resolved = options?.resolvedColumns ?? (options?.width != null ? resolveColumns(options.width, colConfig, spec.breakpoints) : savedColumns);
|
|
551
|
-
const
|
|
563
|
+
const breakpointKey = options?.breakpointKey ?? "xl";
|
|
564
|
+
const items = getItemsForBreakpoint(
|
|
565
|
+
spec,
|
|
566
|
+
breakpointKey,
|
|
567
|
+
resolved,
|
|
568
|
+
options?.layoutCache
|
|
569
|
+
);
|
|
552
570
|
const store = (0, import_layout_store.createLayoutStore)({
|
|
553
571
|
items,
|
|
554
572
|
columns: resolved
|
|
@@ -749,16 +767,26 @@ var DashboardRuntime = (0, import_react4.forwardRef)((props, ref) => {
|
|
|
749
767
|
const isEdit = mode === "edit";
|
|
750
768
|
const gridWrapRef = (0, import_react4.useRef)(null);
|
|
751
769
|
const containerWidth = useContainerWidth(gridWrapRef);
|
|
770
|
+
const widthForBreakpoint = containerWidth || (typeof window !== "undefined" ? window.innerWidth : 1024);
|
|
771
|
+
const currentBreakpoint = (0, import_react4.useMemo)(
|
|
772
|
+
() => getBreakpointKey(widthForBreakpoint, initialSpec.breakpoints),
|
|
773
|
+
[widthForBreakpoint, initialSpec.breakpoints]
|
|
774
|
+
);
|
|
752
775
|
const resolvedColumns = (0, import_react4.useMemo)(() => {
|
|
753
776
|
const colConfig = initialSpec.columnsByBreakpoint ?? initialSpec.columns;
|
|
754
|
-
|
|
755
|
-
|
|
777
|
+
return resolveColumns(
|
|
778
|
+
widthForBreakpoint,
|
|
779
|
+
colConfig,
|
|
780
|
+
initialSpec.breakpoints
|
|
781
|
+
);
|
|
756
782
|
}, [
|
|
757
|
-
|
|
783
|
+
widthForBreakpoint,
|
|
758
784
|
initialSpec.columns,
|
|
759
785
|
initialSpec.columnsByBreakpoint,
|
|
760
786
|
initialSpec.breakpoints
|
|
761
787
|
]);
|
|
788
|
+
const initialSpecRef = (0, import_react4.useRef)(initialSpec);
|
|
789
|
+
initialSpecRef.current = initialSpec;
|
|
762
790
|
const [store, setStore] = (0, import_react4.useState)(() => loadDashboard(initialSpec).store);
|
|
763
791
|
const [panels, setPanels] = (0, import_react4.useState)(() => [
|
|
764
792
|
...loadDashboard(initialSpec).panels
|
|
@@ -767,29 +795,52 @@ var DashboardRuntime = (0, import_react4.forwardRef)((props, ref) => {
|
|
|
767
795
|
const specIdRef = (0, import_react4.useRef)(initialSpec.id);
|
|
768
796
|
const storeRef = (0, import_react4.useRef)(store);
|
|
769
797
|
storeRef.current = store;
|
|
798
|
+
const prevBreakpointRef = (0, import_react4.useRef)(currentBreakpoint);
|
|
799
|
+
const layoutCacheRef = (0, import_react4.useRef)({});
|
|
800
|
+
const currentBreakpointRef = (0, import_react4.useRef)(currentBreakpoint);
|
|
801
|
+
currentBreakpointRef.current = currentBreakpoint;
|
|
770
802
|
(0, import_react4.useEffect)(() => {
|
|
771
803
|
if (resolvedColumns < 1) return;
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
804
|
+
const spec = initialSpecRef.current;
|
|
805
|
+
if (specIdRef.current !== spec.id) {
|
|
806
|
+
specIdRef.current = spec.id;
|
|
807
|
+
prevBreakpointRef.current = currentBreakpoint;
|
|
808
|
+
layoutCacheRef.current = {};
|
|
809
|
+
Object.keys(spec.layoutsByBreakpoint ?? {}).forEach(
|
|
810
|
+
(k) => {
|
|
811
|
+
const items = spec.layoutsByBreakpoint?.[k]?.items;
|
|
812
|
+
if (items) layoutCacheRef.current[k] = [...items];
|
|
813
|
+
}
|
|
814
|
+
);
|
|
815
|
+
const loaded2 = loadDashboard(spec, {
|
|
816
|
+
resolvedColumns,
|
|
817
|
+
breakpointKey: currentBreakpoint,
|
|
818
|
+
layoutCache: layoutCacheRef.current
|
|
819
|
+
});
|
|
820
|
+
setStore(loaded2.store);
|
|
821
|
+
setPanels([...loaded2.panels]);
|
|
822
|
+
layoutCacheRef.current[currentBreakpoint] = loaded2.store.getState().items;
|
|
777
823
|
return;
|
|
778
824
|
}
|
|
825
|
+
const prevBp = prevBreakpointRef.current;
|
|
779
826
|
const current = storeRef.current;
|
|
780
|
-
if (
|
|
781
|
-
const loaded = loadDashboard(initialSpec, { resolvedColumns });
|
|
782
|
-
setStore(loaded.store);
|
|
783
|
-
setPanels([...loaded.panels]);
|
|
827
|
+
if (prevBp === currentBreakpoint && current?.getState().columns === resolvedColumns) {
|
|
784
828
|
return;
|
|
785
829
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
830
|
+
if (current) {
|
|
831
|
+
layoutCacheRef.current[prevBp] = [...current.getState().items];
|
|
832
|
+
}
|
|
833
|
+
prevBreakpointRef.current = currentBreakpoint;
|
|
834
|
+
const loaded = loadDashboard(spec, {
|
|
835
|
+
resolvedColumns,
|
|
836
|
+
breakpointKey: currentBreakpoint,
|
|
837
|
+
layoutCache: layoutCacheRef.current
|
|
838
|
+
});
|
|
839
|
+
const loadedItems = loaded.store.getState().items;
|
|
840
|
+
layoutCacheRef.current[currentBreakpoint] = [...loadedItems];
|
|
841
|
+
setStore(loaded.store);
|
|
842
|
+
setPanels([...loaded.panels]);
|
|
843
|
+
}, [initialSpec.id, resolvedColumns, currentBreakpoint]);
|
|
793
844
|
const meta = (0, import_react4.useMemo)(
|
|
794
845
|
() => ({ id: initialSpec.id, title: initialSpec.title }),
|
|
795
846
|
[initialSpec.id, initialSpec.title]
|
|
@@ -797,15 +848,32 @@ var DashboardRuntime = (0, import_react4.forwardRef)((props, ref) => {
|
|
|
797
848
|
const panelsRef = (0, import_react4.useRef)(panels);
|
|
798
849
|
panelsRef.current = panels;
|
|
799
850
|
const notifyChange = (0, import_react4.useCallback)(() => {
|
|
851
|
+
const cache = layoutCacheRef.current;
|
|
852
|
+
const layoutsByBreakpoint = Object.keys(cache).length > 0 ? Object.fromEntries(
|
|
853
|
+
Object.entries(cache).map(([k, v]) => [k, { items: v }])
|
|
854
|
+
) : initialSpec.layoutsByBreakpoint;
|
|
800
855
|
onChange?.(
|
|
801
856
|
serializeDashboard(store, panelsRef.current, meta, {
|
|
802
857
|
breakpoints: initialSpec.breakpoints,
|
|
803
|
-
columnsByBreakpoint: initialSpec.columnsByBreakpoint
|
|
858
|
+
columnsByBreakpoint: initialSpec.columnsByBreakpoint,
|
|
859
|
+
layoutsByBreakpoint
|
|
804
860
|
})
|
|
805
861
|
);
|
|
806
|
-
}, [
|
|
862
|
+
}, [
|
|
863
|
+
onChange,
|
|
864
|
+
store,
|
|
865
|
+
meta,
|
|
866
|
+
initialSpec.breakpoints,
|
|
867
|
+
initialSpec.columnsByBreakpoint,
|
|
868
|
+
initialSpec.layoutsByBreakpoint
|
|
869
|
+
]);
|
|
807
870
|
(0, import_react4.useEffect)(() => {
|
|
808
|
-
const unsub = store.subscribe(
|
|
871
|
+
const unsub = store.subscribe(() => {
|
|
872
|
+
layoutCacheRef.current[currentBreakpointRef.current] = [
|
|
873
|
+
...store.getState().items
|
|
874
|
+
];
|
|
875
|
+
notifyChange();
|
|
876
|
+
});
|
|
809
877
|
return unsub;
|
|
810
878
|
}, [store, notifyChange]);
|
|
811
879
|
(0, import_react4.useEffect)(() => {
|
|
@@ -873,13 +941,23 @@ var DashboardRuntime = (0, import_react4.forwardRef)((props, ref) => {
|
|
|
873
941
|
},
|
|
874
942
|
[store]
|
|
875
943
|
);
|
|
876
|
-
const exportSpec = (0, import_react4.useCallback)(
|
|
877
|
-
|
|
944
|
+
const exportSpec = (0, import_react4.useCallback)(() => {
|
|
945
|
+
const cache = layoutCacheRef.current;
|
|
946
|
+
const layoutsByBreakpoint = Object.keys(cache).length > 0 ? Object.fromEntries(
|
|
947
|
+
Object.entries(cache).map(([k, v]) => [k, { items: v }])
|
|
948
|
+
) : initialSpec.layoutsByBreakpoint;
|
|
949
|
+
return serializeDashboard(store, panelsRef.current, meta, {
|
|
878
950
|
breakpoints: initialSpec.breakpoints,
|
|
879
|
-
columnsByBreakpoint: initialSpec.columnsByBreakpoint
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
951
|
+
columnsByBreakpoint: initialSpec.columnsByBreakpoint,
|
|
952
|
+
layoutsByBreakpoint
|
|
953
|
+
});
|
|
954
|
+
}, [
|
|
955
|
+
store,
|
|
956
|
+
meta,
|
|
957
|
+
initialSpec.breakpoints,
|
|
958
|
+
initialSpec.columnsByBreakpoint,
|
|
959
|
+
initialSpec.layoutsByBreakpoint
|
|
960
|
+
]);
|
|
883
961
|
(0, import_react4.useImperativeHandle)(
|
|
884
962
|
ref,
|
|
885
963
|
() => ({
|
|
@@ -956,7 +1034,7 @@ var DashboardRuntime = (0, import_react4.forwardRef)((props, ref) => {
|
|
|
956
1034
|
DashboardRuntime.displayName = "DashboardRuntime";
|
|
957
1035
|
|
|
958
1036
|
// src/index.ts
|
|
959
|
-
var
|
|
1037
|
+
var import_layout_store2 = require("@dashboardity/layout-store");
|
|
960
1038
|
|
|
961
1039
|
// src/app-shell/TopBar.tsx
|
|
962
1040
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|