Skip to content
Closed
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { CSSProperties, useMemo } from 'react';
import { observer } from 'mobx-react-lite';
import { useBlock, useBlocks } from '@/hooks';
import { BlockDef, BlockComponent } from '@/stores';
import { Slot } from '@/components/blocks';
import { Drawer, Stack, styled, Box } from '@semoss/ui';

export interface SidebarMenuBlockDef extends BlockDef<'sidebar-menu'> {
widget: 'sidebar-menu';
data: {
style: CSSProperties;
anchor: 'left' | 'top';
sidebarWidth: number;
sidebarHeight: number | string;
designMode: boolean;
open: string | boolean | number; // Changed to string to store query
};
slots: {
content: true;
};
}

const SideBarWrapper = styled(Box)<{ $visible: boolean }>(({ $visible }) => ({
visibility: $visible ? 'visible' : 'hidden',
}));

export const SidebarMenuBlock: BlockComponent = observer(({ id }) => {
const { attrs, data, slots } = useBlock<SidebarMenuBlockDef>(id);
const { state } = useBlocks();
const isStatic = state.mode === 'static';

const open = useMemo(() => {
let o = false;
// Interpret Python
if (
data.open === true ||
data.open === 'true' ||
data.open === 1 ||
data.open === '1'
) {
o = true;
}

return o;
}, [data.open]);

// Helper to determine if modal should be shown
const shouldShowSidebar = isStatic
? data.designMode // In static mode, show when design mode is on
: Boolean(open); // In interactive mode, show when query returns true

// In static mode with design mode on, show as modal but without portal
if (!shouldShowSidebar && !isStatic) {
return <></>;
}

return (
<SideBarWrapper {...attrs} $visible={shouldShowSidebar}>
<Drawer
variant="persistent"
anchor={data.anchor}
open={shouldShowSidebar}
// onClose={handleSidebarOpen}
PaperProps={{
sx: {
position: 'absolute',
height: data.sidebarHeight ?? '100%',
width: data.sidebarWidth,
zIndex: !isStatic ? 40 : 19,
...data.style,
},
}}
>
<Stack>
<Slot slot={slots.content} />
</Stack>
</Drawer>
</SideBarWrapper>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { BlockConfig } from '@/stores';
import {
ArrowBack,
ArrowDownward,
ArrowForward,
ArrowUpward,
Schema,
} from '@mui/icons-material';
import { BLOCK_TYPE_LAYOUT } from '../block-defaults.constants';
import { SidebarMenuBlock, SidebarMenuBlockDef } from './SidebarMenuBlock';
import {
ButtonGroupSettings,
SizeSettings,
SwitchSettings,
QueryInputSettings,
} from '@/components/block-settings';
import {
buildColorSection,
buildBorderSection,
} from '../block-defaults.shared';

export const config: BlockConfig<SidebarMenuBlockDef> = {
widget: 'sidebar-menu',
type: BLOCK_TYPE_LAYOUT,
data: {
style: {},
anchor: 'left',
sidebarWidth: 240,
sidebarHeight: '100%',
designMode: true, // Default to design mode when first dropped
open: '', // Default to closed
},
listeners: {},
slots: {
content: [],
},
render: SidebarMenuBlock,
icon: Schema,
contentMenu: [
{
name: 'General',
children: [
{
description: 'Design Mode',
render: ({ id }) => (
<SwitchSettings
id={id}
label="Design Mode"
path="designMode"
description="Enable to edit modal content"
/>
),
},
{
description: 'Open',
render: ({ id }) => (
<QueryInputSettings
id={id}
label="Open Modal"
path="open"
/>
),
},
{
description: 'Sidebar Width',
render: ({ id }) => (
<SizeSettings
id={id}
label="Sidebar Width"
path="sidebarWidth"
/>
),
},
{
description: 'Sidebar Height',
render: ({ id }) => (
<SizeSettings
id={id}
label="Sidebar Height"
path="sidebarHeight"
/>
),
},
{
description: 'Direction',
render: ({ id }) => (
<ButtonGroupSettings
id={id}
path="anchor"
label="Direction"
options={[
{
value: 'top',
icon: ArrowDownward,
title: 'Top',
isDefault: false,
},
{
value: 'left',
icon: ArrowForward,
title: 'Left',
isDefault: true,
},
]}
/>
),
},
],
},
],
styleMenu: [
buildColorSection(),
{
name: 'Spacing',
children: [
{
description: 'Padding',
render: ({ id }) => (
<SizeSettings
id={id}
label="Padding"
path="style.padding"
/>
),
},
],
},
buildBorderSection(),
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './config';
export * from './SidebarMenuBlock';
21 changes: 21 additions & 0 deletions packages/client/src/components/designer/menu/default-menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import HTML_BLOCK from '@/assets/img/HTML_BLOCK_SM.png';
import BLOCK_MODAL from '@/assets/img/BLOCK_MODAL.png';
import BLOCK_THEME from '@/assets/img/BLOCK_THEME.png';
import BLOCK_ACCORDION from '@/assets/img/BLOCK_ACCORDION.png';
import BLOCK_SIDEBARMENU from '@/assets/img/BLOCK_SIDEBARMENU.png';

const SECTION_ELEMENT = 'Element';
const SECTION_INPUT = 'Input';
Expand Down Expand Up @@ -187,6 +188,26 @@ export const DEFAULT_MENU: DesignerMenuItem[] = [
},
},
},
{
section: SECTION_LAYOUT,
image: BLOCK_SIDEBARMENU,
name: 'Sidebar-Menu',
json: {
widget: 'sidebar-menu',
data: {
style: {},
open: false,
anchor: 'left',
sidebarWidth: 240,
sidebarHeight: '100%',
designMode: true,
},
listeners: {},
slots: {
content: [],
},
},
},
{
section: SECTION_INPUT,
image: BLOCK_INPUT,
Expand Down